]> scripts.mit.edu Git - autoinstalls/mediawiki.git/commitdiff
MediaWiki 1.5.8 (initial commit) mediawiki-1.5.8
authorEdward Z. Yang <ezyang@mit.edu>
Tue, 16 Jun 2009 00:08:46 +0000 (20:08 -0400)
committerEdward Z. Yang <ezyang@mit.edu>
Tue, 16 Jun 2009 00:08:46 +0000 (20:08 -0400)
Signed-off-by: Edward Z. Yang <ezyang@mit.edu>
628 files changed:
.cvsignore [new file with mode: 0644]
AdminSettings.sample [new file with mode: 0644]
COPYING [new file with mode: 0644]
FAQ [new file with mode: 0644]
HISTORY [new file with mode: 0644]
INSTALL [new file with mode: 0644]
README [new file with mode: 0644]
RELEASE-NOTES [new file with mode: 0644]
UPGRADE [new file with mode: 0644]
config/index.php [new file with mode: 0644]
docs/README [new file with mode: 0644]
docs/deferred.txt [new file with mode: 0644]
docs/design.txt [new file with mode: 0644]
docs/export-0.1.xsd [new file with mode: 0644]
docs/export-0.2.xsd [new file with mode: 0644]
docs/export-0.3.xsd [new file with mode: 0644]
docs/export-demo.xml [new file with mode: 0644]
docs/globals.txt [new file with mode: 0644]
docs/hooks.txt [new file with mode: 0644]
docs/html/.cvsignore [new file with mode: 0644]
docs/html/README [new file with mode: 0644]
docs/language.txt [new file with mode: 0644]
docs/linkcache.txt [new file with mode: 0644]
docs/memcached.txt [new file with mode: 0644]
docs/php-memcached/ChangeLog [new file with mode: 0644]
docs/php-memcached/Documentation [new file with mode: 0644]
docs/schema.txt [new file with mode: 0644]
docs/skin.txt [new file with mode: 0644]
docs/title.txt [new file with mode: 0644]
docs/user.txt [new file with mode: 0644]
extensions/README [new file with mode: 0644]
images/.cvsignore [new file with mode: 0644]
images/README [new file with mode: 0644]
img_auth.php [new file with mode: 0644]
includes/.htaccess [new file with mode: 0644]
includes/Article.php [new file with mode: 0644]
includes/AuthPlugin.php [new file with mode: 0644]
includes/BagOStuff.php [new file with mode: 0644]
includes/Block.php [new file with mode: 0644]
includes/BlockCache.php [new file with mode: 0644]
includes/CacheManager.php [new file with mode: 0644]
includes/CategoryPage.php [new file with mode: 0644]
includes/ChangesList.php [new file with mode: 0644]
includes/Credits.php [new file with mode: 0644]
includes/Database.php [new file with mode: 0644]
includes/DatabaseFunctions.php [new file with mode: 0644]
includes/DatabasePostgreSQL.php [new file with mode: 0644]
includes/DateFormatter.php [new file with mode: 0644]
includes/DefaultSettings.php [new file with mode: 0644]
includes/Defines.php [new file with mode: 0644]
includes/DifferenceEngine.php [new file with mode: 0644]
includes/EditPage.php [new file with mode: 0644]
includes/Exif.php [new file with mode: 0644]
includes/ExternalEdit.php [new file with mode: 0644]
includes/ExternalStore.php [new file with mode: 0644]
includes/ExternalStoreDB.php [new file with mode: 0644]
includes/ExternalStoreHttp.php [new file with mode: 0644]
includes/Feed.php [new file with mode: 0644]
includes/FulltextStoplist.php [new file with mode: 0644]
includes/GlobalFunctions.php [new file with mode: 0644]
includes/Group.php [new file with mode: 0644]
includes/HTMLForm.php [new file with mode: 0644]
includes/HistoryBlob.php [new file with mode: 0644]
includes/Hooks.php [new file with mode: 0644]
includes/HttpFunctions.php [new file with mode: 0644]
includes/Image.php [new file with mode: 0644]
includes/ImageGallery.php [new file with mode: 0644]
includes/ImagePage.php [new file with mode: 0644]
includes/LinkCache.php [new file with mode: 0644]
includes/Linker.php [new file with mode: 0644]
includes/LinksUpdate.php [new file with mode: 0644]
includes/LoadBalancer.php [new file with mode: 0644]
includes/LogPage.php [new file with mode: 0644]
includes/MagicWord.php [new file with mode: 0644]
includes/Math.php [new file with mode: 0644]
includes/MemcachedSessions.php [new file with mode: 0644]
includes/MessageCache.php [new file with mode: 0644]
includes/Metadata.php [new file with mode: 0644]
includes/MimeMagic.php [new file with mode: 0644]
includes/Namespace.php [new file with mode: 0644]
includes/ObjectCache.php [new file with mode: 0644]
includes/OutputPage.php [new file with mode: 0644]
includes/PageHistory.php [new file with mode: 0644]
includes/Parser.php [new file with mode: 0644]
includes/ParserCache.php [new file with mode: 0644]
includes/ParserXML.php [new file with mode: 0644]
includes/Profiling.php [new file with mode: 0644]
includes/ProxyTools.php [new file with mode: 0644]
includes/QueryPage.php [new file with mode: 0644]
includes/RawPage.php [new file with mode: 0644]
includes/RecentChange.php [new file with mode: 0644]
includes/Revision.php [new file with mode: 0644]
includes/Sanitizer.php [new file with mode: 0644]
includes/SearchEngine.php [new file with mode: 0644]
includes/SearchMySQL.php [new file with mode: 0644]
includes/SearchMySQL3.php [new file with mode: 0644]
includes/SearchMySQL4.php [new file with mode: 0644]
includes/SearchTsearch2.php [new file with mode: 0644]
includes/SearchUpdate.php [new file with mode: 0644]
includes/Setup.php [new file with mode: 0644]
includes/SiteConfiguration.php [new file with mode: 0644]
includes/SiteStatsUpdate.php [new file with mode: 0644]
includes/Skin.php [new file with mode: 0644]
includes/SkinPHPTal.php [new file with mode: 0644]
includes/SkinTemplate.php [new file with mode: 0644]
includes/SpecialAllmessages.php [new file with mode: 0644]
includes/SpecialAllpages.php [new file with mode: 0644]
includes/SpecialAncientpages.php [new file with mode: 0644]
includes/SpecialBlockip.php [new file with mode: 0644]
includes/SpecialBlockme.php [new file with mode: 0644]
includes/SpecialBooksources.php [new file with mode: 0644]
includes/SpecialBrokenRedirects.php [new file with mode: 0644]
includes/SpecialCategories.php [new file with mode: 0644]
includes/SpecialConfirmemail.php [new file with mode: 0644]
includes/SpecialContributions.php [new file with mode: 0644]
includes/SpecialDeadendpages.php [new file with mode: 0644]
includes/SpecialDisambiguations.php [new file with mode: 0644]
includes/SpecialDoubleRedirects.php [new file with mode: 0644]
includes/SpecialEmailuser.php [new file with mode: 0644]
includes/SpecialExport.php [new file with mode: 0644]
includes/SpecialGroups.php [new file with mode: 0644]
includes/SpecialImagelist.php [new file with mode: 0644]
includes/SpecialImport.php [new file with mode: 0644]
includes/SpecialIpblocklist.php [new file with mode: 0644]
includes/SpecialListusers.php [new file with mode: 0644]
includes/SpecialLockdb.php [new file with mode: 0644]
includes/SpecialLog.php [new file with mode: 0644]
includes/SpecialLonelypages.php [new file with mode: 0644]
includes/SpecialLongpages.php [new file with mode: 0644]
includes/SpecialMaintenance.php [new file with mode: 0644]
includes/SpecialMostlinked.php [new file with mode: 0644]
includes/SpecialMovepage.php [new file with mode: 0644]
includes/SpecialNewimages.php [new file with mode: 0644]
includes/SpecialNewpages.php [new file with mode: 0644]
includes/SpecialPage.php [new file with mode: 0644]
includes/SpecialPopularpages.php [new file with mode: 0644]
includes/SpecialPreferences.php [new file with mode: 0644]
includes/SpecialRandompage.php [new file with mode: 0644]
includes/SpecialRecentchanges.php [new file with mode: 0644]
includes/SpecialRecentchangeslinked.php [new file with mode: 0644]
includes/SpecialSearch.php [new file with mode: 0644]
includes/SpecialShortpages.php [new file with mode: 0644]
includes/SpecialSpecialpages.php [new file with mode: 0644]
includes/SpecialStatistics.php [new file with mode: 0644]
includes/SpecialUncategorizedcategories.php [new file with mode: 0644]
includes/SpecialUncategorizedpages.php [new file with mode: 0644]
includes/SpecialUndelete.php [new file with mode: 0644]
includes/SpecialUnlockdb.php [new file with mode: 0644]
includes/SpecialUnusedcategories.php [new file with mode: 0644]
includes/SpecialUnusedimages.php [new file with mode: 0644]
includes/SpecialUpload.php [new file with mode: 0644]
includes/SpecialUploadMogile.php [new file with mode: 0644]
includes/SpecialUserlogin.php [new file with mode: 0644]
includes/SpecialUserlogout.php [new file with mode: 0644]
includes/SpecialUserrights.php [new file with mode: 0644]
includes/SpecialValidate.php [new file with mode: 0644]
includes/SpecialVersion.php [new file with mode: 0644]
includes/SpecialWantedpages.php [new file with mode: 0644]
includes/SpecialWatchlist.php [new file with mode: 0644]
includes/SpecialWhatlinkshere.php [new file with mode: 0644]
includes/SquidUpdate.php [new file with mode: 0644]
includes/StreamFile.php [new file with mode: 0644]
includes/Title.php [new file with mode: 0644]
includes/UpdateClasses.php [new file with mode: 0644]
includes/User.php [new file with mode: 0644]
includes/UserMailer.php [new file with mode: 0644]
includes/UserTalkUpdate.php [new file with mode: 0644]
includes/Utf8Case.php [new file with mode: 0644]
includes/WatchedItem.php [new file with mode: 0644]
includes/WebRequest.php [new file with mode: 0644]
includes/WikiError.php [new file with mode: 0644]
includes/ZhClient.php [new file with mode: 0644]
includes/ZhConversion.php [new file with mode: 0644]
includes/killthread.php [new file with mode: 0644]
includes/memcached-client.php [new file with mode: 0644]
includes/mime.info [new file with mode: 0644]
includes/mime.types [new file with mode: 0644]
includes/normal/.cvsignore [new file with mode: 0644]
includes/normal/CleanUpTest.php [new file with mode: 0644]
includes/normal/Makefile [new file with mode: 0644]
includes/normal/README [new file with mode: 0644]
includes/normal/RandomTest.php [new file with mode: 0644]
includes/normal/Utf8Test.php [new file with mode: 0644]
includes/normal/UtfNormal.php [new file with mode: 0644]
includes/normal/UtfNormalBench.php [new file with mode: 0644]
includes/normal/UtfNormalData.inc [new file with mode: 0644]
includes/normal/UtfNormalDataK.inc [new file with mode: 0644]
includes/normal/UtfNormalGenerate.php [new file with mode: 0644]
includes/normal/UtfNormalTest.php [new file with mode: 0644]
includes/normal/UtfNormalUtil.php [new file with mode: 0644]
includes/proxy_check.php [new file with mode: 0644]
includes/templates/Confirmemail.php [new file with mode: 0644]
includes/templates/Userlogin.php [new file with mode: 0644]
includes/zhtable/Makefile [new file with mode: 0644]
includes/zhtable/README [new file with mode: 0644]
includes/zhtable/printutf8.c [new file with mode: 0644]
includes/zhtable/simp2trad.manual [new file with mode: 0644]
includes/zhtable/toCN.manual [new file with mode: 0644]
includes/zhtable/toHK.manual [new file with mode: 0644]
includes/zhtable/toSG.manual [new file with mode: 0644]
includes/zhtable/toTW.manual [new file with mode: 0644]
includes/zhtable/trad2simp.manual [new file with mode: 0644]
includes/zhtable/tradphrases.manual [new file with mode: 0644]
index.php [new file with mode: 0644]
install-utils.inc [new file with mode: 0644]
languages/.htaccess [new file with mode: 0644]
languages/Language.php [new file with mode: 0644]
languages/LanguageAf.php [new file with mode: 0644]
languages/LanguageAr.php [new file with mode: 0644]
languages/LanguageArc.php [new file with mode: 0644]
languages/LanguageAs.php [new file with mode: 0644]
languages/LanguageAst.php [new file with mode: 0644]
languages/LanguageBe.php [new file with mode: 0644]
languages/LanguageBg.php [new file with mode: 0644]
languages/LanguageBm.php [new file with mode: 0644]
languages/LanguageBn.php [new file with mode: 0644]
languages/LanguageBo.php [new file with mode: 0644]
languages/LanguageCa.php [new file with mode: 0644]
languages/LanguageConverter.php [new file with mode: 0644]
languages/LanguageCs.php [new file with mode: 0644]
languages/LanguageCsb.php [new file with mode: 0644]
languages/LanguageCy.php [new file with mode: 0644]
languages/LanguageDa.php [new file with mode: 0644]
languages/LanguageDe.php [new file with mode: 0644]
languages/LanguageDv.php [new file with mode: 0644]
languages/LanguageDz.php [new file with mode: 0644]
languages/LanguageEl.php [new file with mode: 0644]
languages/LanguageEn.php [new file with mode: 0644]
languages/LanguageEo.php [new file with mode: 0644]
languages/LanguageEs.php [new file with mode: 0644]
languages/LanguageEt.php [new file with mode: 0644]
languages/LanguageFa.php [new file with mode: 0644]
languages/LanguageFi.php [new file with mode: 0644]
languages/LanguageFo.php [new file with mode: 0644]
languages/LanguageFr.php [new file with mode: 0644]
languages/LanguageFur.php [new file with mode: 0644]
languages/LanguageFy.php [new file with mode: 0644]
languages/LanguageGa.php [new file with mode: 0644]
languages/LanguageGem_alsatian.php [new file with mode: 0644]
languages/LanguageGu.php [new file with mode: 0644]
languages/LanguageHe.php [new file with mode: 0644]
languages/LanguageHi.php [new file with mode: 0644]
languages/LanguageHu.php [new file with mode: 0644]
languages/LanguageIa.php [new file with mode: 0644]
languages/LanguageId.php [new file with mode: 0644]
languages/LanguageIs.php [new file with mode: 0644]
languages/LanguageIt.php [new file with mode: 0644]
languages/LanguageJa.php [new file with mode: 0644]
languages/LanguageKa.php [new file with mode: 0644]
languages/LanguageKm.php [new file with mode: 0644]
languages/LanguageKn.php [new file with mode: 0644]
languages/LanguageKo.php [new file with mode: 0644]
languages/LanguageKs.php [new file with mode: 0644]
languages/LanguageKu.php [new file with mode: 0644]
languages/LanguageLa.php [new file with mode: 0644]
languages/LanguageLi.php [new file with mode: 0644]
languages/LanguageLo.php [new file with mode: 0644]
languages/LanguageLt.php [new file with mode: 0644]
languages/LanguageMk.php [new file with mode: 0644]
languages/LanguageMl.php [new file with mode: 0644]
languages/LanguageMs.php [new file with mode: 0644]
languages/LanguageNds.php [new file with mode: 0644]
languages/LanguageNl.php [new file with mode: 0644]
languages/LanguageNn.php [new file with mode: 0644]
languages/LanguageNo.php [new file with mode: 0644]
languages/LanguageNon.php [new file with mode: 0644]
languages/LanguageNv.php [new file with mode: 0644]
languages/LanguageOc.php [new file with mode: 0644]
languages/LanguageOr.php [new file with mode: 0644]
languages/LanguageOs.php [new file with mode: 0644]
languages/LanguagePa.php [new file with mode: 0644]
languages/LanguagePl.php [new file with mode: 0644]
languages/LanguagePs.php [new file with mode: 0644]
languages/LanguagePt.php [new file with mode: 0644]
languages/LanguageRo.php [new file with mode: 0644]
languages/LanguageRu.php [new file with mode: 0644]
languages/LanguageSc.php [new file with mode: 0644]
languages/LanguageSd.php [new file with mode: 0644]
languages/LanguageSk.php [new file with mode: 0644]
languages/LanguageSl.php [new file with mode: 0644]
languages/LanguageSq.php [new file with mode: 0644]
languages/LanguageSr.php [new file with mode: 0644]
languages/LanguageSv.php [new file with mode: 0644]
languages/LanguageTa.php [new file with mode: 0644]
languages/LanguageTe.php [new file with mode: 0644]
languages/LanguageTh.php [new file with mode: 0644]
languages/LanguageTlh.php [new file with mode: 0644]
languages/LanguageTr.php [new file with mode: 0644]
languages/LanguageTt.php [new file with mode: 0644]
languages/LanguageUg.php [new file with mode: 0644]
languages/LanguageUk.php [new file with mode: 0644]
languages/LanguageUr.php [new file with mode: 0644]
languages/LanguageUtf8.php [new file with mode: 0644]
languages/LanguageVi.php [new file with mode: 0644]
languages/LanguageWa.php [new file with mode: 0644]
languages/LanguageYi.php [new file with mode: 0644]
languages/LanguageZh.php [new file with mode: 0644]
languages/LanguageZh_cn.php [new file with mode: 0644]
languages/LanguageZh_hk.php [new file with mode: 0644]
languages/LanguageZh_sg.php [new file with mode: 0644]
languages/LanguageZh_tw.php [new file with mode: 0644]
languages/Names.php [new file with mode: 0644]
maintenance/.htaccess [new file with mode: 0644]
maintenance/FiveUpgrade.inc [new file with mode: 0644]
maintenance/InitialiseMessages.inc [new file with mode: 0644]
maintenance/Makefile [new file with mode: 0644]
maintenance/README [new file with mode: 0644]
maintenance/alltrans.php [new file with mode: 0644]
maintenance/apache-ampersand.diff [new file with mode: 0644]
maintenance/archives/.htaccess [new file with mode: 0644]
maintenance/archives/patch-archive-rev_id.sql [new file with mode: 0644]
maintenance/archives/patch-archive-text_id.sql [new file with mode: 0644]
maintenance/archives/patch-bot.sql [new file with mode: 0644]
maintenance/archives/patch-cache.sql [new file with mode: 0644]
maintenance/archives/patch-categorylinks.sql [new file with mode: 0644]
maintenance/archives/patch-drop-user_newtalk.sql [new file with mode: 0644]
maintenance/archives/patch-drop_img_type.sql [new file with mode: 0644]
maintenance/archives/patch-email-authentication.sql [new file with mode: 0644]
maintenance/archives/patch-email-notification.sql [new file with mode: 0644]
maintenance/archives/patch-hitcounter.sql [new file with mode: 0644]
maintenance/archives/patch-image_name_primary.sql [new file with mode: 0644]
maintenance/archives/patch-image_name_unique.sql [new file with mode: 0644]
maintenance/archives/patch-img_exif.sql [new file with mode: 0644]
maintenance/archives/patch-img_media_type.sql [new file with mode: 0644]
maintenance/archives/patch-img_metadata.sql [new file with mode: 0644]
maintenance/archives/patch-img_width.sql [new file with mode: 0644]
maintenance/archives/patch-indexes.sql [new file with mode: 0644]
maintenance/archives/patch-interwiki-trans.sql [new file with mode: 0644]
maintenance/archives/patch-interwiki.sql [new file with mode: 0644]
maintenance/archives/patch-inverse_timestamp.sql [new file with mode: 0644]
maintenance/archives/patch-ipb_expiry.sql [new file with mode: 0644]
maintenance/archives/patch-ipblocks.sql [new file with mode: 0644]
maintenance/archives/patch-linkscc-1.3.sql [new file with mode: 0644]
maintenance/archives/patch-linkscc.sql [new file with mode: 0644]
maintenance/archives/patch-linktables.sql [new file with mode: 0644]
maintenance/archives/patch-list.txt [new file with mode: 0644]
maintenance/archives/patch-log_params.sql [new file with mode: 0644]
maintenance/archives/patch-logging-title.sql [new file with mode: 0644]
maintenance/archives/patch-logging.sql [new file with mode: 0644]
maintenance/archives/patch-math.sql [new file with mode: 0644]
maintenance/archives/patch-objectcache.sql [new file with mode: 0644]
maintenance/archives/patch-oldestindex.sql [new file with mode: 0644]
maintenance/archives/patch-page_len.sql [new file with mode: 0644]
maintenance/archives/patch-pagelinks.sql [new file with mode: 0644]
maintenance/archives/patch-parsercache.sql [new file with mode: 0644]
maintenance/archives/patch-profiling.sql [new file with mode: 0644]
maintenance/archives/patch-querycache.sql [new file with mode: 0644]
maintenance/archives/patch-random-dateindex.sql [new file with mode: 0644]
maintenance/archives/patch-rc-newindex.sql [new file with mode: 0644]
maintenance/archives/patch-rc-patrol.sql [new file with mode: 0644]
maintenance/archives/patch-rc_id.sql [new file with mode: 0644]
maintenance/archives/patch-rc_ip.sql [new file with mode: 0644]
maintenance/archives/patch-rc_type.sql [new file with mode: 0644]
maintenance/archives/patch-rename-group.sql [new file with mode: 0644]
maintenance/archives/patch-rename-user_groups-and_rights.sql [new file with mode: 0644]
maintenance/archives/patch-restructure.sql [new file with mode: 0644]
maintenance/archives/patch-rev_deleted.sql [new file with mode: 0644]
maintenance/archives/patch-rev_text_id.sql [new file with mode: 0644]
maintenance/archives/patch-searchindex.sql [new file with mode: 0644]
maintenance/archives/patch-ss_total_articles.sql [new file with mode: 0644]
maintenance/archives/patch-trackbacks.sql [new file with mode: 0644]
maintenance/archives/patch-transcache.sql [new file with mode: 0644]
maintenance/archives/patch-user-realname.sql [new file with mode: 0644]
maintenance/archives/patch-user_email_token.sql [new file with mode: 0644]
maintenance/archives/patch-user_groups.sql [new file with mode: 0644]
maintenance/archives/patch-user_nameindex.sql [new file with mode: 0644]
maintenance/archives/patch-user_rights.sql [new file with mode: 0644]
maintenance/archives/patch-user_token.sql [new file with mode: 0644]
maintenance/archives/patch-userindex.sql [new file with mode: 0644]
maintenance/archives/patch-userlevels-defaultgroups.sql [new file with mode: 0644]
maintenance/archives/patch-userlevels-rights.sql [new file with mode: 0644]
maintenance/archives/patch-userlevels.sql [new file with mode: 0644]
maintenance/archives/patch-usernewtalk.sql [new file with mode: 0644]
maintenance/archives/patch-usernewtalk2.sql [new file with mode: 0644]
maintenance/archives/patch-val_ip.sql [new file with mode: 0644]
maintenance/archives/patch-validate.sql [new file with mode: 0644]
maintenance/archives/patch-watchlist.sql [new file with mode: 0644]
maintenance/archives/rebuildRecentchanges.inc [new file with mode: 0644]
maintenance/archives/upgradeWatchlist.php [new file with mode: 0644]
maintenance/attribute.php [new file with mode: 0644]
maintenance/benchmarkPurge.php [new file with mode: 0644]
maintenance/build-intl-wiki.sql [new file with mode: 0644]
maintenance/changeuser.sql [new file with mode: 0644]
maintenance/checktrans.php [new file with mode: 0644]
maintenance/cleanupCaps.php [new file with mode: 0644]
maintenance/cleanupDupes.inc [new file with mode: 0644]
maintenance/cleanupDupes.php [new file with mode: 0644]
maintenance/clear_interwiki_cache.php [new file with mode: 0644]
maintenance/clear_stats.php [new file with mode: 0644]
maintenance/commandLine.inc [new file with mode: 0644]
maintenance/convertLinks.inc [new file with mode: 0644]
maintenance/convertLinks.php [new file with mode: 0644]
maintenance/convertUtf8.php [new file with mode: 0644]
maintenance/database.sql [new file with mode: 0644]
maintenance/delete-idle-wiki-users.pl [new file with mode: 0644]
maintenance/deleteOldRevisions.inc [new file with mode: 0644]
maintenance/deleteOldRevisions.php [new file with mode: 0644]
maintenance/diffLanguage.php [new file with mode: 0644]
maintenance/dumpBackup.php [new file with mode: 0644]
maintenance/dumpHTML.inc [new file with mode: 0644]
maintenance/dumpHTML.php [new file with mode: 0644]
maintenance/dumpMessages.php [new file with mode: 0644]
maintenance/dumpReplayLog.php [new file with mode: 0644]
maintenance/dumpRev.php [new file with mode: 0644]
maintenance/duplicatetrans.php [new file with mode: 0644]
maintenance/entities2literals.pl [new file with mode: 0644]
maintenance/eval.php [new file with mode: 0644]
maintenance/fetchInterwiki.pl [new file with mode: 0644]
maintenance/importDump.php [new file with mode: 0644]
maintenance/importLogs.inc [new file with mode: 0644]
maintenance/importLogs.php [new file with mode: 0644]
maintenance/importPhase2.php [new file with mode: 0644]
maintenance/importUseModWiki.php [new file with mode: 0644]
maintenance/initStats.php [new file with mode: 0644]
maintenance/interwiki.sql [new file with mode: 0644]
maintenance/liveCmdLine.inc [new file with mode: 0644]
maintenance/mcc.php [new file with mode: 0644]
maintenance/mwdocgen.php [new file with mode: 0644]
maintenance/mysql5/tables.sql [new file with mode: 0644]
maintenance/namespace2sql.php [new file with mode: 0644]
maintenance/namespaceDupes.php [new file with mode: 0644]
maintenance/nukePage.inc [new file with mode: 0644]
maintenance/nukePage.php [new file with mode: 0644]
maintenance/orphans.php [new file with mode: 0644]
maintenance/ourusers.php [new file with mode: 0644]
maintenance/parserTests.inc [new file with mode: 0644]
maintenance/parserTests.php [new file with mode: 0644]
maintenance/parserTests.txt [new file with mode: 0644]
maintenance/portal.php [new file with mode: 0644]
maintenance/purgeOldText.inc [new file with mode: 0644]
maintenance/purgeOldText.php [new file with mode: 0644]
maintenance/rebuildImages.php [new file with mode: 0644]
maintenance/rebuildInterwiki.inc [new file with mode: 0644]
maintenance/rebuildInterwiki.php [new file with mode: 0644]
maintenance/rebuildMessages.php [new file with mode: 0644]
maintenance/rebuildall.php [new file with mode: 0644]
maintenance/rebuildrecentchanges.inc [new file with mode: 0644]
maintenance/rebuildrecentchanges.php [new file with mode: 0644]
maintenance/rebuildtextindex.inc [new file with mode: 0644]
maintenance/rebuildtextindex.php [new file with mode: 0644]
maintenance/redundanttrans.php [new file with mode: 0644]
maintenance/refreshLinks.inc [new file with mode: 0644]
maintenance/refreshLinks.php [new file with mode: 0644]
maintenance/removeUnusedAccounts.php [new file with mode: 0644]
maintenance/stats.php [new file with mode: 0644]
maintenance/storage/blobs.sql [new file with mode: 0644]
maintenance/storage/compressOld.inc [new file with mode: 0644]
maintenance/storage/compressOld.php [new file with mode: 0644]
maintenance/storage/dumpRev.php [new file with mode: 0644]
maintenance/storage/moveToExternal.php [new file with mode: 0644]
maintenance/storage/resolveStubs.php [new file with mode: 0644]
maintenance/tables.sql [new file with mode: 0644]
maintenance/transstat.php [new file with mode: 0644]
maintenance/trivialCmdLine.php [new file with mode: 0644]
maintenance/update.php [new file with mode: 0644]
maintenance/updateSearchIndex.inc [new file with mode: 0644]
maintenance/updateSearchIndex.php [new file with mode: 0644]
maintenance/updateSpecialPages.php [new file with mode: 0644]
maintenance/updaters.inc [new file with mode: 0644]
maintenance/upgrade1_5.php [new file with mode: 0644]
maintenance/userDupes.inc [new file with mode: 0644]
maintenance/userDupes.php [new file with mode: 0644]
maintenance/userFunctions.inc [new file with mode: 0644]
maintenance/users.sql [new file with mode: 0644]
maintenance/wikipedia-interwiki.sql [new file with mode: 0644]
maintenance/wiktionary-interwiki.sql [new file with mode: 0644]
math/.cvsignore [new file with mode: 0644]
math/.htaccess [new file with mode: 0644]
math/Makefile [new file with mode: 0644]
math/README [new file with mode: 0644]
math/TODO [new file with mode: 0644]
math/html.ml [new file with mode: 0644]
math/html.mli [new file with mode: 0644]
math/lexer.mll [new file with mode: 0644]
math/mathml.ml [new file with mode: 0644]
math/mathml.mli [new file with mode: 0644]
math/parser.mly [new file with mode: 0644]
math/render.ml [new file with mode: 0644]
math/render_info.mli [new file with mode: 0644]
math/tex.mli [new file with mode: 0644]
math/texutil.ml [new file with mode: 0644]
math/texutil.mli [new file with mode: 0644]
math/texvc.ml [new file with mode: 0644]
math/texvc_cgi.ml [new file with mode: 0644]
math/texvc_test.ml [new file with mode: 0644]
math/texvc_tex.ml [new file with mode: 0644]
math/util.ml [new file with mode: 0644]
profileinfo.php [new file with mode: 0644]
redirect.php [new file with mode: 0644]
redirect.phtml [new file with mode: 0644]
skins/Chick.php [new file with mode: 0644]
skins/CologneBlue.php [new file with mode: 0644]
skins/MonoBook.php [new file with mode: 0644]
skins/MySkin.php [new file with mode: 0644]
skins/Nostalgia.php [new file with mode: 0644]
skins/Simple.php [new file with mode: 0644]
skins/Skin.sample [new file with mode: 0644]
skins/SkinPHPTal.sample [new file with mode: 0644]
skins/Standard.php [new file with mode: 0644]
skins/chick/IE50Fixes.css [new file with mode: 0644]
skins/chick/IE55Fixes.css [new file with mode: 0644]
skins/chick/IE60Fixes.css [new file with mode: 0644]
skins/chick/main.css [new file with mode: 0644]
skins/common/IEFixes.js [new file with mode: 0644]
skins/common/cologneblue.css [new file with mode: 0644]
skins/common/common.css [new file with mode: 0644]
skins/common/commonPrint.css [new file with mode: 0644]
skins/common/common_rtl.css [new file with mode: 0644]
skins/common/feed.css [new file with mode: 0644]
skins/common/images/Arr_.png [new file with mode: 0644]
skins/common/images/Arr_d.png [new file with mode: 0644]
skins/common/images/Arr_l.png [new file with mode: 0644]
skins/common/images/Arr_r.png [new file with mode: 0644]
skins/common/images/Arr_r.xcf [new file with mode: 0644]
skins/common/images/Zoom_sans.gif [new file with mode: 0644]
skins/common/images/bullet.gif [new file with mode: 0644]
skins/common/images/button_bold.png [new file with mode: 0644]
skins/common/images/button_extlink.png [new file with mode: 0644]
skins/common/images/button_headline.png [new file with mode: 0644]
skins/common/images/button_hr.png [new file with mode: 0644]
skins/common/images/button_image.png [new file with mode: 0644]
skins/common/images/button_italic.png [new file with mode: 0644]
skins/common/images/button_link.png [new file with mode: 0644]
skins/common/images/button_math.png [new file with mode: 0644]
skins/common/images/button_media.png [new file with mode: 0644]
skins/common/images/button_nowiki.png [new file with mode: 0644]
skins/common/images/button_sig.png [new file with mode: 0644]
skins/common/images/button_template.png [new file with mode: 0644]
skins/common/images/fileicon.xcf [new file with mode: 0644]
skins/common/images/gnu-fdl.png [new file with mode: 0644]
skins/common/images/gnu-fdl.xcf [new file with mode: 0644]
skins/common/images/icons/COPYING [new file with mode: 0644]
skins/common/images/icons/fileicon-c.png [new file with mode: 0644]
skins/common/images/icons/fileicon-cpp.png [new file with mode: 0644]
skins/common/images/icons/fileicon-deb.png [new file with mode: 0644]
skins/common/images/icons/fileicon-dvi.png [new file with mode: 0644]
skins/common/images/icons/fileicon-exe.png [new file with mode: 0644]
skins/common/images/icons/fileicon-h.png [new file with mode: 0644]
skins/common/images/icons/fileicon-html.png [new file with mode: 0644]
skins/common/images/icons/fileicon-iso.png [new file with mode: 0644]
skins/common/images/icons/fileicon-java.png [new file with mode: 0644]
skins/common/images/icons/fileicon-mid.png [new file with mode: 0644]
skins/common/images/icons/fileicon-mov.png [new file with mode: 0644]
skins/common/images/icons/fileicon-o.png [new file with mode: 0644]
skins/common/images/icons/fileicon-ogg.png [new file with mode: 0644]
skins/common/images/icons/fileicon-ogg.xcf [new file with mode: 0644]
skins/common/images/icons/fileicon-pdf.png [new file with mode: 0644]
skins/common/images/icons/fileicon-ps.png [new file with mode: 0644]
skins/common/images/icons/fileicon-rm.png [new file with mode: 0644]
skins/common/images/icons/fileicon-rpm.png [new file with mode: 0644]
skins/common/images/icons/fileicon-svg.png [new file with mode: 0644]
skins/common/images/icons/fileicon-tar.png [new file with mode: 0644]
skins/common/images/icons/fileicon-tex.png [new file with mode: 0644]
skins/common/images/icons/fileicon-ttf.png [new file with mode: 0644]
skins/common/images/icons/fileicon-txt.png [new file with mode: 0644]
skins/common/images/icons/fileicon.png [new file with mode: 0644]
skins/common/images/link_icon.gif [new file with mode: 0644]
skins/common/images/magnify-clip.png [new file with mode: 0644]
skins/common/images/magnify-clip.png.old [new file with mode: 0644]
skins/common/images/mediawiki-small.xcf [new file with mode: 0644]
skins/common/images/mediawiki.png [new file with mode: 0644]
skins/common/images/poweredby_mediawiki_88x31.png [new file with mode: 0644]
skins/common/images/redirect.png [new file with mode: 0644]
skins/common/images/wiki.png [new file with mode: 0644]
skins/common/nostalgia.css [new file with mode: 0644]
skins/common/preview.js [new file with mode: 0644]
skins/common/quickbar-right.css [new file with mode: 0644]
skins/common/quickbar.css [new file with mode: 0644]
skins/common/sticky.js [new file with mode: 0644]
skins/common/wikibits.js [new file with mode: 0644]
skins/common/wikiprintable.css [new file with mode: 0644]
skins/common/wikistandard.css [new file with mode: 0644]
skins/disabled/Amethyst.php [new file with mode: 0644]
skins/disabled/Amethyst.pt [new file with mode: 0644]
skins/disabled/Chick.php [new file with mode: 0644]
skins/disabled/Chick.pt [new file with mode: 0644]
skins/disabled/HTMLDump.php [new file with mode: 0644]
skins/disabled/MonoBook.pt [new file with mode: 0644]
skins/disabled/MonoBookTal.php [new file with mode: 0644]
skins/disabled/WikimediaWiki.php [new file with mode: 0644]
skins/disabled/WikimediaWiki.pt [new file with mode: 0644]
skins/monobook/IE50Fixes.css [new file with mode: 0644]
skins/monobook/IE55Fixes.css [new file with mode: 0644]
skins/monobook/IE60Fixes.css [new file with mode: 0644]
skins/monobook/IEMacFixes.css [new file with mode: 0644]
skins/monobook/KHTMLFixes.css [new file with mode: 0644]
skins/monobook/Opera6Fixes.css [new file with mode: 0644]
skins/monobook/Opera7Fixes.css [new file with mode: 0644]
skins/monobook/bullet.gif [new file with mode: 0644]
skins/monobook/discussionitem_icon.gif [new file with mode: 0644]
skins/monobook/external.png [new file with mode: 0644]
skins/monobook/file_icon.gif [new file with mode: 0644]
skins/monobook/headbg.jpg [new file with mode: 0644]
skins/monobook/link_icon.gif [new file with mode: 0644]
skins/monobook/lock_icon.gif [new file with mode: 0644]
skins/monobook/magnify-clip.png [new file with mode: 0644]
skins/monobook/mail_icon.gif [new file with mode: 0644]
skins/monobook/main.css [new file with mode: 0644]
skins/monobook/news_icon.png [new file with mode: 0644]
skins/monobook/required.gif [new file with mode: 0644]
skins/monobook/rtl.css [new file with mode: 0644]
skins/monobook/user.gif [new file with mode: 0644]
skins/monobook/wiki-indexed.png [new file with mode: 0644]
skins/monobook/wiki.png [new file with mode: 0644]
skins/myskin/main.css [new file with mode: 0644]
skins/simple/discussionitem_icon.gif [new file with mode: 0644]
skins/simple/external.png [new file with mode: 0644]
skins/simple/file_icon.gif [new file with mode: 0644]
skins/simple/link_icon.gif [new file with mode: 0644]
skins/simple/lock_icon.gif [new file with mode: 0644]
skins/simple/mail_icon.gif [new file with mode: 0644]
skins/simple/main.css [new file with mode: 0644]
tests/.cvsignore [new file with mode: 0644]
tests/.htaccess [new file with mode: 0644]
tests/ArticleTest.php [new file with mode: 0644]
tests/DatabaseTest.php [new file with mode: 0644]
tests/GlobalTest.php [new file with mode: 0644]
tests/LocalTestSettings.sample [new file with mode: 0644]
tests/Makefile [new file with mode: 0644]
tests/README [new file with mode: 0644]
tests/RunTests.php [new file with mode: 0644]
tests/SanitizerTest.php [new file with mode: 0644]
tests/SearchEngineTest.php [new file with mode: 0644]
tests/SearchMySQL3Test.php [new file with mode: 0644]
tests/SearchMySQL4Test.php [new file with mode: 0644]
thumb.php [new file with mode: 0644]
trackback.php [new file with mode: 0644]
wiki.phtml [new file with mode: 0644]

diff --git a/.cvsignore b/.cvsignore
new file mode 100644 (file)
index 0000000..44ddd60
--- /dev/null
@@ -0,0 +1,9 @@
+LocalSettings.php
+AdminSettings.php
+*~
+bin
+.classpath
+.project
+project.index
+.metadata*
+.settings
diff --git a/AdminSettings.sample b/AdminSettings.sample
new file mode 100644 (file)
index 0000000..0eea90c
--- /dev/null
@@ -0,0 +1,31 @@
+<?php
+/**
+ * This file should be copied to AdminSettings.php, and modified
+ * to reflect local settings. It is required for the maintenance
+ * scripts which run on the command line, as an extra security
+ * measure to allow using a separate user account with higher
+ * privileges to do maintenance work.
+ *
+ * Developers: Do not check AdminSettings.php into CVS!
+ *
+ * @package MediaWiki
+ */
+
+/*
+ * This data is used by all database maintenance scripts
+ * (see directory maintenance/). The SQL user MUST BE
+ * MANUALLY CREATED or set to an existing user with
+ * necessary permissions.
+ *
+ * This is not to be confused with sysop accounts for the
+ * wiki.
+ */
+$wgDBadminuser      = 'wikiadmin';
+$wgDBadminpassword  = 'adminpass';
+
+/*
+ * Whether to enable the profileinfo.php script.
+ */
+$wgEnableProfileInfo = false;
+
+?>
diff --git a/COPYING b/COPYING
new file mode 100644 (file)
index 0000000..5b6e7c6
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/FAQ b/FAQ
new file mode 100644 (file)
index 0000000..b62ead9
--- /dev/null
+++ b/FAQ
@@ -0,0 +1 @@
+The FAQ is at: http://meta.wikimedia.org/wiki/MediaWiki_FAQ
diff --git a/HISTORY b/HISTORY
new file mode 100644 (file)
index 0000000..6b5a3b6
--- /dev/null
+++ b/HISTORY
@@ -0,0 +1,598 @@
+Change notes from older releases. For current info see RELEASE-NOTES.
+
+= MediaWiki release notes =
+
+Security reminder: MediaWiki does not require PHP's register_globals
+setting since version 1.2.0. If you have it on, turn it *off* if you can.
+
+== MediaWiki 1.4.3 ==
+
+(released 2005-04-28)
+
+MediaWiki 1.4.3 is a bugfix release for the 1.4 stable release series.
+
+Chiefly, this fixes a compatibility problem with PHP 5 and a minor link
+table corruption bug on initial page save.
+
+
+== MediaWiki 1.4.2 ==
+
+(released 2005-04-20)
+
+MediaWiki 1.4.2 is a security and bug fix release for the 1.4 stable release
+series.
+
+A cross-site scripting injection vulnerability was discovered, which
+affects only MSIE clients and is only open if MediaWiki has been
+manually configured to run output through HTML Tidy ($wgUseTidy).
+
+Several other bugs are fixed in this release, see the changelog below.
+
+All new installations are highly recommended to use 1.4.2 instead of
+1.3.x; 1.3.x users should consider upgrading for bug fixes and new
+features. Ealier 1.4.x release and beta users should upgrade to this
+release for relevant bug fixes; see the changelog later in this file.
+
+
+If you have trouble, remember to read this whole file and the online FAQ page
+before asking for help:
+
+http://meta.wikimedia.org/wiki/MediaWiki_FAQ
+
+
+=== READ THIS FIRST: Upgrading ===
+
+If upgrading from an older release, see the notes in the file UPGRADE.
+There are a couple of minor database changes from the beta releases,
+and somewhat larger changes from 1.3.x.
+
+Upgrading from a previous 1.4.x stable release installation should
+generally only require copying the new files over the old ones.
+
+
+==== READ THIS FIRST, TOO: MySQL 4.1 AND 5.0 ====
+
+MySQL 5.0 is a beta release, not yet ready for production use. If you
+are using it, the notes below about 4.1 apply to you too.
+
+If you have the choice of MySQL 4.0 or MySQL 4.1 and don't need 4.1 for
+some other application, you should consider sticking with 4.0 for the
+moment. 4.1 may require you to do extra fiddling to get things to work
+due to changes that aren't fully backwards-compatible.
+
+MySQL 4.1 has changed the authentication protocol in an incompatible
+way; many PHP installations still use the older client libraries and
+CANNOT CONNECT TO THE SERVER WITH A PASSWORD without some changes.
+
+See: http://dev.mysql.com/doc/mysql/en/Old_client.html
+
+If MySQL is set with utf-8 as the default character set, installation
+may fail with "key too long" errors. Set the default charset to 'latin1'
+for installation and it should work.
+
+The mysqldump backup generator now applies an automatic conversion to
+UTF-8, which may irretrivably corrupt your data. Pass the -charset option
+with the original default charset (eg 'latin1') to skip the conversion.
+
+
+==== READ THIS FIRST IF RUNNING ON A WINDOWS SERVER ====
+
+MediaWiki is tested and deployed primarily under the Apache web server
+on Linux Unix systems. There are known to be problems running on
+Microsoft's IIS which are not fully resolved. If you have a choice,
+try running under Apache on Windows, or on a Unix/Linux box instead.
+
+If you're having trouble with blank pages on IIS and can't switch,
+try the workaround suggested in this bug report:
+http://bugzilla.wikimedia.org/show_bug.cgi?id=1763
+
+
+=== New features ===
+
+* 'Recentchanges Patrol' to mark new edits that haven't yet been viewed.
+* New, searchable deletion/upload/protection logs
+* Image gallery generation (Special:Newimages and <gallery> tag)
+* SVG rasterization support (requires external support tools)
+* Users can select from the available localizations to override the
+  default user interface language.
+* Traditional/Simplified Chinese conversion support
+* rel="nofollow" support to combat linkspam
+
+The current implementation adds this attribute to _all_ external URL
+links in wiki text (but not internal [[wiki links]] or interwiki links).
+To disable the attribute for _all_ external links, add this line to your
+LocalSettings.php:
+
+  $wgNoFollowLinks = false
+
+For background information on nofollow see:
+
+  http://www.google.com/googleblog/2005/01/preventing-comment-spam.html
+
+
+=== Installation and compatibility ===
+
+* The default MonoBook theme now works with PHP 5.0
+* Installation on systems with PHP's safe mode or other oddities
+  should work more reliably, as MonoBook no longer needs to
+  create a compiled template file for the wiki to run.
+* A table prefix may be specified, to avoid conflicts with other
+  web applications forced to share a database.
+* More thorough UTF-8 input validation; fixes non-ASCII uploaded
+  filenames from Safari.
+* Command-line database upgrade script.
+
+
+=== Customizability ===
+
+* Default user options can now be overridden in LocalSettings.
+* Skins system more modular: templates and CSS are now in /skins/
+  New skins can be dropped into this directory and used immediately.
+* More extension hooks have been added.
+* Authentication plugin hook.
+* More internal code documentation, generated with phpdoc:
+  http://www.mediawiki.org/docs/html/
+
+
+=== Optimization ===
+
+* For many operations, MediaWiki 1.4 should run faster and use
+  less memory than MediaWiki 1.3. Page rendering is up to twice
+  as fast. (Use a PHP accelerator such as Turck MMCache for best
+  results with any PHP application, though!)
+* The parser cache no longer requires memcached, and is enabled
+  by default. This avoids a lot of re-rendering of pages that
+  have been shown recently, greatly speeding longer page views.
+* Support for compiled PHP modules to speed up page diff and
+  Unicode validation/normalization. (Requires ability to compile
+  and load PHP extensions).
+
+
+=== What isn't ready yet ===
+
+* A new user/groups permissions scheme has been held back to 1.5.
+* An experimental SOAP interface will be made available as an extension
+* PostgreSQL support is largely working, minus search and the installer.
+  You can perform a manual installation.
+* E-mail notification of watched page changes and verification of
+  user-submitted e-mail addresses is not yet included.
+* Log pages are not automatically imported into the new log table
+  at upgrade time. A script to import old text log entries is
+  incomplete, but may be available in later point releases.
+* Some localizations are still incomplete.
+
+
+
+== Changelog ==
+
+=== Important security updates ===
+
+A security audit found and fixed a number of problems. Users of MediaWiki
+1.3.10 and earlier should upgrade to 1.3.11; users of 1.4 beta releases
+prior to 1.4rc1 should upgrade immediately.
+
+==== Cross-site scripting vulnerability ====
+
+XSS injection points can be used to hijack session and authentication
+cookies as well as more serious attacks.
+
+* Media: links output raw text into an attribute value, potentially
+  abusable for JavaScript injection. This has been corrected.
+* Additional checks added to file upload to protect against MSIE and
+  Safari MIME-type autodetection bugs.
+
+As of 1.3.10/1.4beta6, per-user customized CSS and JavaScript is disabled
+by default as a general precaution. Sites which want this ability may set
+$wgAllowUserCss and $wgAllowUserJs in LocalSettings.php.
+
+
+==== Cross-site request forgery ====
+
+An attacker could use JavaScript-submitted forms to perform various
+restricted actions by tricking an authenticated user into visiting
+a malicious web page. A fix for page editing in 1.3.10/1.4beta6 has
+been expanded in this release to other forms and functions.
+
+Authors of bot tools may need to update their code to include the
+additional fields.
+
+
+==== Directory traversal ====
+
+An unchecked parameter in image deletion could allow an authenticated
+administrator to delete arbitary files in directories writable by the
+web server, and confirm existence of files not deletable.
+
+
+==== Older issues ====
+
+Note that 1.4 beta releases prior to beta 5 include an input validation
+error which could lead to execution of arbitrary PHP code on the server.
+Users of older betas should upgrade immediately to the current version.
+
+
+Beta 6 also introduces the use of rel="nofollow" attributes on external
+links in wiki pages to reduce the effectiveness of wiki spam. This will
+cause participating search engines to ignore external URL links from wiki
+pages for purposes of page relevancy ranking.
+
+
+=== Misc bugs fixed in beta 1 ===
+
+* (bug 95) Templates no longer limited to 5 inclusions per page
+* New user preference for limiting the image size for images on image description
+  pages
+* (bug 530) Allow user to preview article on first edit
+* (bug 479) [[RFC 1234]] will now make an internal link
+* (bug 511) PhpTal skins shown bogus 'What links here' etc on special pages
+* (bug 770) Adding filter and username exact search match for Special:Listusers
+* (bug 733) Installer die if it can not write LocalSettings.php
+* (bug 705) Various special pages no more show the rss/atom feed links
+* (bug 114) use category backlinks in Special:Recentchangeslinked
+
+=== Beta 2 fixes ===
+
+* (bug 987) Reverted bogus fix for bug 502
+* (bug 992) Fix enhanced recent changes in PHP5
+* (bug 1009) Fix Special:Makesysop when using table prefixes
+* (bug 1010) fix broken Commons image link on Classic & Cologne Blue
+* (bug 985) Fix auto-summary for section edits
+* (bug 995) Close <a> tag
+* (bug 1004) renamed norsk language links (twice)
+* Login works again when using an old-style default skin
+* Fix for load balancing mode, notify if using old settings format
+* (bug 1014) Missing image size option on old accounts handled gracefully
+* (bug 1027) Fix page moves with table prefix
+* (bug 1018) Some pages fail with stub threshold enabled
+* (bug 1024) Fix link to high-res image version on Image: pages
+* (bug 1016) Fix handling of lines omitting Image: in a <gallery> tag
+* security fix for image galleries
+* (bug 1039) Avoid error message in certain message cache failure modes
+* Fix string escaping with PostgreSQL
+* (bug 1015) [partial] -- use comment formatter on image gallery text
+* Allow customization of all UI languages
+* use $wgForceUIMsgAsContentMsg to make regular UI messages act as content
+* new user option for zh users to disable language conversion
+* Defer message cache initialization, shaving a few ms off file cache hits
+* Fixed Special:Allmessages when using table prefixes
+* (bug 996) Fix $wgWhitelistRead to work again
+* (bug 1028) fix page move over redirect to not fail on the unique index
+
+=== Beta 3 fixes ===
+
+* Hide RC patrol markers when patrol is disabled or not allowed to patrol.
+* Fix language selection for upgraded accounts
+* (bug 1076) navigation links in QueryPage should be translated by wgContLang.
+* (bug 922) bogus DOS line endings in LanguageEl.php
+* Fix index usage in contribs
+* Caching and load limiting options for Recentchanges RSS/Atom feed
+* (bug 1074) Add stock icons for non-image files in gallery/Newimages
+* Add width and height attributes on thumbs in gallery/Newimages
+* Enhance upload extension blacklist to protect against vulnerable
+  Apache configurations
+
+=== Beta 4 fixes ===
+
+* (bug 1090) Fix sitesupport links in CB/classic skins
+* Gracefully ignore non-legal titles in a <gallery>
+* Fix message page caching behavior when $wgCapitalLinks is turned off
+  after installation and the wiki is subsequently upgraded
+* Database error messages include the database server name/address
+* Paging support for large categories
+* Fix image page scaling when thumbnail generation is disabled
+* Select the content language in prefs when bogus interface language is set
+* Fix interwiki links in edit comments
+* Fix crash on banned user visit
+* Avoid PHP warning messages when thumbnail not generated
+* (bug 1157) List unblocks correctly in Special:Log
+* Fix fatal errors in LanguageLi.php
+* Undo overly bright, difficult to read colors in Cologne Blue
+* (bug 1162) fix five-tilde date inserter
+* Add raw signatures option for those who simply must have cute sigs
+* (bug 1164) Let wikitext be used in Loginprompt and Loginend messages
+* Add the dreaded <span> to the HTML whitelist
+* (bug 1170) Fix Russian linktrail
+* (bug 1168) Missing text on the bureaucrat log
+* (bug 1180) Fix Makesysop on shared-user-table sites
+* (bug 1178) Fix previous diff link when using 'oldid=0'
+* (bug 1173) Stop blocked accounts from reverting/deleting images
+* Keep generated stylesheets cache-separated for each user
+* (bug 1175) Fix "preview on first edit" mode
+* Fix revert bug caused by bug 1175 fix
+* Fix CSS classes on minor, new, unpatrolled markers in enhanced RC
+* Set MySQL 4 boolean search back to 'and' mode by default
+* (bug 1193) Fix move-only page protection mode
+* Fix zhtable Makefile to include the traditional manual table
+* Add memcache timeout for the zh conversion tables
+* Allow user customization of the zh conversion tables through 
+  Mediawiki:zhconversiontable
+* Add zh-min-man (back) to language names list
+* Ported $wgCopyrightIcon setting from REL1_3A
+* (bug 1218) Show the original image on image pages if the thumbnail would be
+  bigger than the original image
+* (bug 1213) i18n of Special:Log labels
+* (bug 1013) Fix jbo, minnan in language names list
+* Added magic word MAG_NOTITLECONVERT to indicate that the title of the page
+  do not need to be converted. Useful in zh:
+* (bug 1224) Use proper date messages for date reformatter
+* (bug 1241) Don't show 'cont.' for first entry of the category list
+* (bug 1240) Special:Preferences was broken in Slovenian locale when
+  $wgUseDynamicDates is enabled
+* Added magic word MAG_NOCONTENTCONVERT to supress the conversion of the
+  content of an article. Useful in zh:
+* write-lock for updating the zh conversion tables in memcache
+* recursively parse subpages of MediaWiki:Zhconversiontable
+* (bug 1144) Fix export for fy language
+* make removal of an entry from zhconversiontable work
+* (bug 752) Don't insert newline in link title for url with %0a
+* Fix missing search box contents in MonoBook skin
+* Add option to forward search directly to an external URL (eg google)
+* Correctly highlight the fallback language variant when the selected 
+  variant is disabled. Used in zh: only for now.
+
+=== Beta 5 fixes ===
+
+* (bug 1124) Fix ImageGallery XHTML compliance
+* (bug 1186) news: in the middle of a word
+* (bug 1283) Use underlining and borders to highlight additions/deletions
+  in diff-view
+* Use user's local timezone in Special:Log display
+* Show filename for images in gallery by default (restore beta 3 behaviour)
+* (bug 1201) Double-escaping in brokenlinks, imagelinks, categorylinks, searchindex
+* When using squid reverse proxy, cache the redirect to the Main_Page
+* (bug 1302) Fix Norwegian language file
+* (bug 1205) Fix broken article saving in PHP 5.1
+* (bug 1206) Implement CURRENTWEEK and CURRENTDOW magic keyword (will give
+  number of the week and number of the day).
+* (bug 1204) Blocks do not expire automatically
+* (bug 1184) expiry time of indefinite blocks shown as the current time
+* (bug 1317) Fix external links in image captions
+* (bug 1084) Fix logo not rendering centrally in IE
+* (bug 288) Fix tabs wrapping in IE6
+* (bug 119) Fix full-width tabs with RTL text in IE
+* (bug 1323) Fix logo rendering off-screen in IE with RTL language
+* Show "block" link in Special:Recentchanges for logged in users, too, if
+  wgUserSysopBans is true.
+* (bug 1326) Use content language for '1movedto2' in edit history
+* zh: Fix warning when HTTP_ACCEPT_LANGUAGE is not set
+* zh: Fix double conversion for zh-sg and zh-hk
+* (bug 1132) Fix concatenation of link lists in refreshLinks
+* (bug 1101) Fix memory leak in refreshLinks
+* (bug 1339) Fix order of @imports in Cologne Blue CSS
+* Don't try to create links without namespaces ([[Category:]] link bug)
+* Memcached data compression fixes
+* Several valid XHTML fixes
+* (bug 624) Fix IE freezing rendering whilst waiting for CSS with MonoBook
+* (bug 211) Fix tabbed preferences with XHTML MIME type 
+* Fix for script execution vulnerability.
+
+=== Beta 6 fixes ===
+
+* (bug 1335) implement 'tooltip-watch' in Language.php
+* Fix linktrail for nn: language
+* (bug 1214) Fix prev/next links in Special:Log
+* (bug 1354) Fix linktrail for fo: language
+* (bug 512) Reload generated CSS on preference change
+* (bug 63) Fix displaying as if logged in after logout
+* Set default MediaWiki:Sitenotice to '-', avoiding extra database hits
+* Skip message cache initialization on raw page view (quick hack)
+* Fix notice errors in wfDebugDieBacktrace() in XML callbacks
+* Suppress notice error on bogus timestamp input (returns epoch as before)
+* Remove unnecessary initialization and double-caching of parser variables
+* Call-tree output mode for profiling
+* (bug 730) configurable $wgRCMaxAge; don't try to update purged RC entries
+* Add $wgNoFollowLinks option to add rel="nofollow" on external links
+  (on by default)
+* (bug 1130) Show actual title when moving page instead of encoded one.
+* (bug 925) Fix headings containing <math>
+* (bug 1131) Fix headings containing interwiki links
+* (bug 1380) Update Nynorsk language file
+* (bug 1232) Fix sorting of cached Special:Wantedpages in miser mode
+* (bug 1217) Image within an image caption broke rendering
+* (bug 1384) Make patrol signs have the same width for page moves as for edits
+* (bug 1364) fix "clean up whitespace" in Title:SecureAndSplit
+* (bug 1389) i18n for proxyblocker message
+* Add fur/Furlan/Friulian to language names list
+* Add TitleMoveComplete hook on page renames
+* Allow simple comments for each translation rules in MW:Zhconversiontable
+* (bug 1402) Make link color of tab subject page link on talk page indicate whether article exists
+* (bug 1368) Fix SQL error on stopword/short word search w/ MySQL 3.x
+* Translated Hebrew namespace names
+* (bug 1429) Stop double-escaping of block comments; fix formatting
+* (bug 829) Fix URL-escaping on block success 
+* (bug 1228) Fix double-escaping on &amp; sequences in [enclosed] URLs
+* (bug 1435) Fixed many CSS errors
+* (bug 1457) Fix XHTML validation on category column list
+* (bug 1458) Don't save if edit form submission is incomplete
+* Logged-in edits and preview of user CSS/JS are now locked to a session token.
+* Per-user CSS and JavaScript subpage customizations now disabled by default.
+  They can be re-enabled via $wgAllowUserJs and $wgAllowUserCss.
+* Removed .ogg from the default uploads whitelist as an extra precaution.
+  If your web server is configured to serve Ogg files with the correct
+  Content-Type header, you can re-add it in LocalSettings.php:
+    $wgFileExtensions[] = 'ogg';
+
+=== RC1 fixes ===
+
+* Fix notice error on nonexistent template in wikitext system message
+* (bug 1469) add missing <ul> tags on Special:Log
+* (bug 1470) remove extra <ul> tags from Danish log messages
+* Fix notice on purge w/ squid mode off
+* (bug 1477) hide details of SQL error messages by default
+  Set $wgShowSQLErrors = true for debugging.
+* (bug 1430) Don't check for template data when editing page that doesn't exist
+* Recentchanges table purging fixed when using table prefix
+* (bug 1431) Avoid redundant objectcache garbage collection
+* (bug 1474) Switch to better-cached index for statistics page count
+* Run Unicode normalization on all input fields
+* Fix translation for allpagesformtext2 in LanguageZh_cn and LanguageZh_tw
+* Block image revert without valid login
+* (bug 1446) stub Bambara (bm) language file using French messages
+* (bug 1432) Update Estonian localization
+* (bug 1471) unclosed <p> tag in Danish messages
+* convertLinks script fixes
+* Corrections to template loop detection
+* XHTML encoding fix for usernames containing & in Special:Emailuser
+* (for zh) Search for variant links even when conversion is turned off, 
+  to help prevent duplicate articles.
+* Disallow ISO 8859-1 C1 characters and "no-break space" in user names
+  on Latin-1 wikis.
+* Correct the name of the main page it LanguageIt
+* Allow Special:Makesysop to work for usernames containing SQL special
+  characters.
+* Fix annoying blue line in Safari on scaled-down images on description page
+* Increase upload sanity checks
+* Fix XSS bug in Media: links
+* Add cross-site form submission protection to various actions
+* Fix fatal error on some dubious page titles
+* Stub threshold displays correctly again
+
+
+=== 1.4.0 final fixes ===
+
+* (bug 65) Fix broken interwiki link encoding on Latin-1 wikis; force to UTF-8
+* (bug 563) Fix UTF-8 interwiki URL redirects via Latin-1 wikis
+* (bug 1536) Fix page info
+* Support os (Ossetic) as language code, using Russian localization base
+* (bug 1610) Support non (Old Norse) as language code, using Icelandic localization base
+* (bug 1618) Properly list custom namespaces in Special:Allpages
+* (bug 1622) Remove trailing' >' when using category browser
+* (bug 1570) Fix php 4.2.x error on conflict merging
+* (bug 1585) Fix page title on post-login redirection page
+* Run UTF-8 validation on old text in Recentchanges RSS diffs
+* (bug 1642) fix a mime type typo in img_auth.php
+* Automated interwiki redirects only for local interwikis
+* Respect read-only mode on block removals
+* Trim old illegal characters from syndication feeds
+* Reduce message cache outage recovery delay from 1 day to 5 minutes
+* (bug 1403) Update Finnish localization
+* (bug 1478) Punjabi localization
+* (bug 1667) Update script 5 second countdown.
+* (bug 1057) Fix logging table encoding (error on MySQL 4.1)
+* (bug 1680) Fix linktrail for fo
+* (bug 1653) Removing hardcoded messages in Special:Allmessages
+* (bug 1594) Render a hyphen in a formula as &minus; in HTML
+* (bug 1495) Fall back to default language MediaWiki: for custom messages
+* (bug 1617) Show different error messages for "user does not
+    exist" and "wrong password" when using AuthPlugin
+* (bug 1532), (bug 1544) Changed language names for
+    'bn', 'bo', 'dv', 'dz', 'ht', 'ii', 'li', 'lo', 'ng', 'or', 'pa', 'si',
+    'ti', 've' 
+* Fix editing on non-Esperanto wiki with user language pref set to Esperanto
+* Make conversion table for zh-sg default to zh-cn, and zh-hk default to zh-tw
+* Fix PHP notice in MonoBook when counters disabled
+* (bug 1696) Update namespaces, dates in uk localization
+* (bug 551) Installer warns about magic_quotes_runtime and magic_quotes_sybase
+  instead of trying to install with corrupt table files
+* Installer no longer tries to move non-default MediaWiki: pages into Template:
+* User-to-user email disabled by default ($wgEnableUserEmail)
+
+
+=== 1.4.1 fixes ===
+
+* (bug 1720) fix genitive month names for uk
+* (bug 1704) fixed untranslateable string in Special:Log
+* (bug 1638) Added Belrusian language file
+* (bug 1736) typo in SpecialValidate.php
+* (bug 73) Upload doesn't run edit updates on description page (links,
+  search index and categories)
+* (bug 646) <math> fails to recognize \ll and \gg
+* (bug 926) \div element from TeX not supported in <math> element
+* (bug 1147) add \checkmark to whitelist in texutil.ml
+* (bug 937) \limits function from LaTeX not supported in <math> element
+* Support for manually converting article title to different Chinese
+  variants (for zh)
+* (bug 1488, bug 1744) Fix encoding for preferences, dates in Latin-1 mode
+* (bug 1042) Fix UTF-8 case conversion for PHP <4.3 with mbstring extension
+* Fix code typo that broke article credits display
+* Installation fixes for running under IIS
+* (bug 1556) login page tab order. "remember" checkbox now come after password.
+* SQL debug log fixlets
+* (bug 1815) Fix namespace in old revision display with mismatched title
+* (bug 1788) Fix link duplication when edit/upload comment includes newlines
+* Change default on $wgSysopUserBans and $wgSysopRangeBans to true
+* Fix link conversion for URL request
+* (bug 1851) Updated download URL for the SCIM packages used by zhtable
+* (bug 1853) Try stripping quotes from term for 'go' title match
+* Fix missing function in Latin1 mode
+* (bug 1860) Anchors of interwiki links did not get normalized
+* (bug 1847) accept lowercase x in ISBN, do not accept invalid A-W,Y,Z
+* Fix link conversion for URL request, hopefully without breaking the wiki
+* (bug 1849) New option allows to consider categorized images as used on
+  Special:Unusedimages
+* Localized category namespace for ka (Georgian)
+* (bug 1107) Work around includes problem in installer when parent dir is not
+  readable by the web server
+* (bug 1927) Incorrect escaping on wikitext message in Blockip
+
+
+=== 1.4.2 fixes ===
+
+* Fix math options in Finnish localization
+* Use in-process Tidy extension if available when $wgUseTidy is on
+* (bug 1933) Fix PATH_INFO usage under IIS with PHP ISAPI module
+* (bug 1188) <nowiki> in {{subst:}} includes fixed
+* (bug 1936) <!-- comments --> in {{subst:}} includes fixed
+* Fix a potential MSIE JavaScript injection vector in Tidy mode
+
+
+=== 1.4.3 fixes ===
+
+* (bug 1636) Refs like &#0355; were misinterpreted as octal in some places
+* (bug 1163) Special:Undelete showed oldest revision instead of newest
+* (bug 1938) Fix escaping of illegal character references in link text
+* (bug 1997) Fix for error on display of renamed items in Recentchanges on PHP5
+* (bug 1949) Profiling typo in rare error case
+* (bug 1963) Fix deletion log link when $wgCapitalLinks is off
+* (bug 1970) Don't show move tab for immobile pages
+* (bug 1770) Page creation recorded links from the 'newarticletext' message
+* Optional change to the site_stats table. When applied, this removes the need 
+  for expensive queries in Special:Statistics.
+
+
+=== 1.4.4 fixes ===
+
+* (bug 725) Let dir="ltr" attribute work again in MonoBook on RTL languages
+* (bug 2024) Skip JavaScript error for custom skins where .js message not set
+* (bug 2025) Updated Indonesian localization
+* (bug 2039) Updated Lithuanian localization
+
+
+=== Caveats ===
+
+Some output, particularly involving user-supplied inline HTML, may not
+produce 100% valid or well-formed XHTML output. Testers are welcome to
+set $wgMimeType = "application/xhtml+xml"; to test for remaining problem
+cases, but this is not recommended on live sites. (This must be set for
+MathML to display properly in Mozilla.)
+
+
+For notes on 1.3.x and older releases, see HISTORY.
+
+
+=== Online documentation ===
+
+Documentation for both end-users and site administrators is currently being
+built up on Meta-Wikipedia, and is covered under the GNU Free Documentation
+License:
+
+  http://meta.wikipedia.org/wiki/Help:Contents
+
+
+=== Mailing list ===
+
+A MediaWiki-l mailing list has been set up distinct from the Wikipedia
+wikitech-l list:
+
+  http://mail.wikipedia.org/mailman/listinfo/mediawiki-l
+
+A low-traffic announcements-only list is also available:
+  http://mail.wikipedia.org/mailman/listinfo/mediawiki-announce
+
+It's highly recommended that you sign up for one of these lists if you're
+going to run a public MediaWiki, so you can be notified of security fixes.
+
+
+=== IRC help ===
+
+There's usually someone online in #mediawiki on irc.freenode.net
diff --git a/INSTALL b/INSTALL
new file mode 100644 (file)
index 0000000..f639e46
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,81 @@
+---
+Installing MediaWiki
+---
+
+Starting with MediaWiki 1.2.0, it's possible to install
+and configure the wiki "in-place", as long as you have
+the necessary prerequesites available.
+
+In 1.3.0 the old command-line installer has been removed.
+A new command-line installer/upgrader may come soon...
+
+Required software:
+* Web server with PHP 4.1.2 or higher (4.3.x is preferred)
+* A MySQL server. 4.0.x is preferred, but 3.2.x should
+  work as well.
+
+MediaWiki is developed and tested mainly on Unix/Linux
+platforms, but should work on Windows as well.
+
+If your PHP is configured as a CGI plug-in rather than
+an Apache module you may experience problems, as this
+configuration is not well tested. safe_mode is also not
+tested and unlikely to work. 
+
+If you want math support see the instructions in math/README
+
+Don't forget to check the RELEASE-NOTES file...
+
+********************** WARNING **************************
+
+REMEMBER: ALWAYS BACK UP YOUR DATABASE BEFORE ATTEMPTING
+TO INSTALL OR UPGRADE!!!
+
+********************** WARNING **************************
+
+----
+In-place web install
+----
+
+Decompress the MediaWiki installation archive either on
+your server, or on your local machine and upload the
+directory tree. Rename it from "mediawiki-1.x.x" to
+something nice, like "wiki", since it'll be in your URL.
+
+To run the install script, you'll need to temporarily make
+the 'config' subdirectory writable by the web server. The
+simplest way to do this on a Unix/Linux system is to make
+it world-writable:
+
+  chmod a+w config
+
+Hop into your browser and surf into the wiki directory.
+It'll direct you into the config script. Fill out the form...
+remember you're probably not on an encrypted connection.
+Gaaah! :)
+
+If all goes well, you should soon be told that it's set up
+your wiki database and written a configuration file. There
+should now be a 'LocalSettings.php' in the config directory;
+move it back up to the main wiki directory, and the wiki
+should now be working.
+
+Once the wiki is set up, you should remove the config
+directory, or at least make it not world-writable (though
+it will refuse to config again if the wiki is set up).
+
+
+----
+
+Don't forget that this is free software under development!
+Chances are good there's a crucial step that hasn't made it
+into the documentation. You should probably sign up for the
+MediaWiki developers' mailing list; you can ask for help (please
+provide enough information to work with, and preferably be aware
+of what you're doing!) and keep track of major changes to the
+software, including performance improvements and security patches.
+
+http://mail.wikipedia.org/mailman/listinfo/mediawiki-l (site admin support)
+
+http://mail.wikipedia.org/mailman/listinfo/wikitech-l (development)
+
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..4caa158
--- /dev/null
+++ b/README
@@ -0,0 +1,76 @@
+2005-06-12
+
+MediaWiki
+---------
+
+MediaWiki is the software used for Wikipedia (http://www.wikipedia.org) and the
+other Wikimedia Foundation websites. Compared to other wikis, it has an
+excellent range of features and support for high-traffic websites using
+multiple servers (Wikipedia peaks in the 2500+ requests per second range
+as of June 2005).
+
+While quite usable on smaller sites, you may find you have to "roll your own"
+local documentation, and some aspects of configuration may seem overcomplicated
+because MediaWiki is primarily targeted as an in-house tool.
+
+See the files RELEASE-NOTES, INSTALL, and UPGRADE for details on system
+requirements and installation procedure.
+
+
+The MediaWiki software was written by:
+ * Lee Daniel Crocker
+ * Magnus Manske
+ * Jan Hidders
+ * Brion Vibber
+ * Axel Boldt
+ * Geoffrey T. Dairiki
+ * Tomasz Wegrzanowski
+ * Erik Moeller
+ * Tim Starling
+ * Gabriel Wicke
+ * Ashar Voultoiz
+ * Evan Prodromou
+ * Several others
+
+These developers hold the copyright to this work, and it is licensed under the
+terms of the GNU General Public License, version 2 (see
+http://www.fsf.org/licenses/gpl.html). Derivative works and later versions of
+the code will also be considered free software licensed under the same terms.
+
+The newly-founded Wikimedia Foundation currently has no legal rights to the
+software, although copyright may be assigned to it at a later date. Wikimedia
+has not funded any of the development work.
+
+Sections of code written exclusively by Lee Crocker or Erik Moeller are also
+released into the public domain, which does not impair the obligations of users
+under the GPL for use of the whole code or other sections thereof.
+
+Many thanks to the Wikipedia regulars for testing and suggestions.
+
+The code is currently maintained at SourceForge under the project "wikipedia",
+module name "phase3". You can view the code in CVS there:
+
+  http://www.mediawiki.org/
+
+Please report bugs and make feature requests in our Bugzilla system:
+
+  http://bugzilla.wikimedia.org
+
+Documentation and discussion on new features may be found at:
+
+  http://meta.wikimedia.org/wiki/MediaWiki_FAQ
+  http://meta.wikimedia.org/wiki/MediaWiki_User%27s_Guide
+  http://meta.wikimedia.org/wiki/MediaWiki_development
+  
+
+If you are setting up your own wiki based on this software, it is highly
+recommended that you subscribe to mediawiki-announce:
+
+  http://mail.wikipedia.org/mailman/listinfo/mediawiki-announce
+
+The mailing list is very low volume, and is intended primarily for
+announcements of new versions, bug fixes, and security issues.
+
+
+For installation and upgrade details, see the files RELEASE-NOTES, INSTALL,
+and UPGRADE.
diff --git a/RELEASE-NOTES b/RELEASE-NOTES
new file mode 100644 (file)
index 0000000..aefad37
--- /dev/null
@@ -0,0 +1,1151 @@
+= MediaWiki release notes =
+
+Security reminder: MediaWiki does not require PHP's register_globals
+setting since version 1.2.0. If you have it on, turn it *off* if you can.
+
+== MediaWiki 1.5.8 ==
+
+March 26, 2006
+
+MediaWiki 1.5.8 is a security and bugfix maintenance release.
+
+A bug in decoding of certain encoded links could allow injection of raw
+HTML into page output; this could potentially lead to XSS attacks.
+
+Some minor UI fixes were also made, see the change log at the bottom of
+this file.
+
+
+== MediaWiki 1.5.7 ==
+
+March 2, 2006
+
+MediaWiki 1.5.7 is a bugfix maintenance release.
+
+Most importantly, a security issue in the installer has been fixed. The bug 
+affects new installations of 1.5.6 only. If the user specified the MySQL root 
+password, to allow the installer to create an unprivileged account, the 
+installer would not only create the new account but also change the root 
+password to be equal to the password of the new account. 
+
+Anyone affected by this bug will need to change the root password back 
+manually. For information about how to change passwords in MySQL please see:
+http://dev.mysql.com/doc/refman/5.1/en/passwords.html
+
+This version includes fixes for compatibility with Internet Explorer 7
+beta 2, and various other bugs; see the full changelog at the end of
+the release notes.
+
+
+== MediaWiki 1.5.6 ==
+
+January 19, 2006
+
+MediaWiki 1.5.6 is a security and bugfix maintenance release.
+
+A bug in edit comment formatting could send PHP into an infinite loop
+if certain malformed links were included. In most installations, this
+would cause the script to fail after PHP's 30-second failsafe timeout.
+
+Some improvements have been made to the installer which should make
+installation possible on a system with a broken MySQL "root" account.
+
+For several other minor fixes, see the complete changelog at the end
+of this file.
+
+
+== MediaWiki 1.5.5 ==
+
+January 5, 2006
+
+MediaWiki 1.5.5 is a security and bugfix maintenance release.
+
+Detection for uploads of Windows Metafile (.wmf) images has been added
+to help protect against a client-side vulnerability in unpatched Microsoft
+Windows operating systems.
+
+Sites which have enabled uploads and added non-standard file types
+(such as .ogg, .doc, or .pdf) should upgrade to this release to ensure
+that malicious .wmf files can't be uploaded with a fake extension;
+such files could put visitors to the site at risk.
+
+For more details on this, see:
+http://en.wikipedia.org/wiki/Windows_Metafile_vulnerability
+
+Additionally, a maintenance script removeUnusedAccounts.php has been added;
+this replaces an older Perl script which had not been updated for the new
+schema in 1.5.
+
+
+== MediaWiki 1.5.4 ==
+
+December 21, 2005
+
+MediaWiki 1.5.4 is a security and bugfix maintenance release.
+
+A hardcoded internal placeholder string has been replaced with a random
+one. This closes a hole where security checks in inline style attributes
+could be bypassed, injecting JavaScript code that could execute in
+Microsoft Internet Explorer.
+
+Other browsers would not be vulnerable.
+
+Several minor fixes are included in this release, most notably a fix
+to clear the "you have new messages" flag properly for usernames
+containing spaces when e-mail notification is enabled.
+
+See the changelog at the end of the release notes for a full list of
+fixes.
+
+
+== MediaWiki 1.5.3 ==
+
+December 4, 2005
+
+MediaWiki 1.5.3 is a security and bugfix maintenance release.
+
+Validation of the user language option was broken by a code change in
+May 2005, opening the possibility of remote code execution as this
+parameter is used in forming a class name dynamically created with
+eval().
+
+The validation has been corrected in this version. All prior 1.5 release
+and prelease versions are affected; 1.4 and earlier and not affected.
+
+Additionally several bugs have been fixed; see the changelog later in
+this file for a complete list.
+
+
+== MediaWiki 1.5.2 ==
+
+November 2, 2005
+
+MediaWiki 1.5.2 is a bugfix maintenance release.
+
+A change in PHP 4.4.1 and PHP 5.1.0RC broke handling of extension and
+<pre> sections, causing garbage data to be inserted in output and saved
+edits. This version works around the change.
+
+Several other glitches with MySQL 5.0 and PHP 5.0.5 were also fixed;
+see the change log below for a complete list.
+
+
+== MediaWiki 1.5.1 ==
+
+October 26, 2005
+
+MediaWiki 1.5.1 is a bugfix and security maintenance release, and is a
+recommended upgrade for all installations.
+
+This release includes further corrections to the inline CSS style sanitation
+which works around a JavaScript "feature" on Microsoft Internet Explorer.
+Users of Microsoft Internet Explorer for Windows may be vulnerable to
+XSS injections on prior versions; users of standards-compliant browsers
+are not vulnerable.
+
+Major fixes include:
+* Image pages work again with resizing disabled
+* Works in MySQL 5.0 strict mode
+
+There is experimental support in this release for explicitly declaring
+the UTF-8 charset in the database; this has been tested with MySQL 5.0.15
+but should work on 4.1 as well.
+
+IMPORTANT: Changing this setting on an existing wiki may produce interesting
+data corruption, depending on server configuration. Page contents should,
+usually, be unaffected, but page titles and other items may be. Limitations
+in MySQL's Unicode support mean that characters outside the BMP cannot be used
+in page titles or various other fields when using this mode.
+
+Table definitions are in maintenance/mysql5/tables.sql, and the runtime
+option to send 'SET NAMES utf8' is set by $wgDBmysql5 = true.
+
+(MySQL 3.23.x and 4.0.x do not support character set declarations; on these
+versions MediaWiki simply works with UTF-8 data and MySQL is blissfully
+unaware of it.)
+
+
+
+== MediaWiki 1.5.0 final ==
+
+October 5, 2005
+
+MediaWiki 1.5.0 is the new stable release branch of MediaWiki, and is
+recommended for all new installations.
+
+Any wikis running a 1.5 beta or release candidate are strongly recommended
+to upgrade to the final release, which includes a number of bug fixes and
+a security fix for CSS bugs in Microsoft Internet Explorer.
+
+IMPORTANT: Running a 1.3 or 1.4 wiki and don't want to jump to 1.5 yet?
+Be sure to upgrade to 1.3.17 or 1.4.11, also released today. Versions
+prior to 1.3.16 and 1.4.10 have a serious data corruption bug which is
+triggered by a spambot known to operate in the wild.
+
+
+=== What's new in 1.5? ===
+
+Schema:
+  The core table schema has changed significantly. This should make better
+  use of the database's cache and disk I/O, and make significantly speed up
+  rename and delete operations on pages with very long edit histories.
+  
+  Unfortunately this does mean upgrading a wiki of size from 1.4 will require
+  some downtime for the schema restructuring, but future storage backend
+  changes should be able to integrate into the new system more easily.
+
+Permalinks:
+  The current revision of a page now has a permanent 'oldid' number assigned
+  immediately, and the id numbers are now preserved across deletion/undeletion.
+  A permanent reference to the current revision of a page is now just a matter
+  of going to the 'history' tab and copying the first link in the list.
+
+Page move log:
+  Renames of pages are now recorded in Special:Log and the page history.
+  A handy revert link is available from the log for sysops.
+
+Editing diff:
+  Ever lost track of what you'd done so far during an edit? A 'Show diff'
+  button on the edit page now makes it easy to remember.
+
+Uploads:
+  It's now possible to specify the final filename of an upload distinct
+  from the original filename on your disk.
+  
+  An image link for a missing file will now take you straight to the upload page.
+  
+  More metadata is pre-extracted from uploaded images, which will ease pressure
+  on disk or NFS volumes used to store images. EXIF metadata is displayed on
+  the image description page if PHP is configured with the necessary module.
+  
+  If .svg files are added to the upload whitelist, you can choose to render
+  them to rasterized .png images for inline display using one of several
+  external helper programs. See DefaultSettings.php for SVG options.
+
+User accounts:
+  There are some changes to the user permissions system, with assignable
+  groups. Note that this does *not* allow you to make pages which are only
+  accessible to certain groups.
+  
+  For details see: http://meta.wikimedia.org/wiki/Help:User_rights
+
+E-mail:
+  User-to-user e-mail can now be restricted to require a mail-back confirmation
+  first to reduce potential for abuse with false addresses.
+  
+  Updates to user talk pages and watchlist entries can optionally send e-mail
+  notifications.
+
+External hooks:
+  A somewhat experimental interface for hooking in an external editor
+  application is included.
+
+And...
+  A bunch of stuff we forgot to mention.
+
+
+=== What's gone? ===
+
+Latin-1:
+  Wikis must now be encoded in Unicode UTF-8; this has been the default for
+  some time, but some languages could optionally be installed in Latin-1 mode.
+  This is no longer supported.
+  
+  You can check if your current wiki is in Latin-1 mode by using your browser's
+  "view source"; look for a line like this:
+  
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+  
+  If it says charset=utf-8, you're ready. If it says charset=iso8859-1,
+  you may need to convert your data. (English-language wikis avoiding
+  any accented characters may be able to get away without conversion.)
+
+MySQL 3.x:
+  Some optimization hacks for MySQL 3.x have been removed as part of the schema
+  clean-up (specifically, the inverse_timestamp fields).
+  
+  MediaWiki 1.5 may still run on 3.x, but wikis of non-trivial size should
+  very seriously consider upgrading to a more modern release. MySQL 3.x support
+  will probably be entirely dropped in the next major release.
+
+Special:Maintenance
+  These tools were, ironically enough, not really maintained. This special
+  page has been removed; insofar as some of its pieces were useful and haven't
+  already been supplanted by other special pages they should be rewritten in
+  an efficient and safe manner in the future.
+
+
+=== Caveats ===
+
+Upgrade:
+  Wikis in Latin-1 encoding are no longer supported; only Unicode UTF-8.
+  A new option $wgLegacyEncoding is provided to allow on-the-fly recoding of
+  old page text entries, but other metadata fields (titles, comments etc) need
+  to be pre-converted. The standard upgrade process does not yet fully automate
+  this, but you can try the alternate partial-upgrader in upgrade1_5.php.
+  
+  The upgrade from 1.4 to 1.5 schema has not been tested for all cases, so
+  it's possible you may experience problems in some combinations.
+
+Backups:
+  The text entries of deleted pages are no longer removed from the main
+  text table on deletion. If you provide public backup dumps of your databases,
+  you will probably want to use the new XML-format dump generator, available
+  as maintenance/dumpBackup.php.
+  
+  For more information on how we run our own public data dumps at Wikimedia,
+  see http://meta.wikimedia.org/wiki/Data_dumps
+
+PostgreSQL:
+  The table definitions for PostgreSQL install are out of date. PostgreSQL
+  support may return in later releases, pending appropriate patches.
+
+MySQL 4.1+:
+  Some users may encounter installation problems with MySQL 4.1 or higher
+  due to strange charset encoding / collation configurations. Try setting
+  to 'latin1' or 'utf8' if you encounter problems.
+
+
+
+== MediaWiki 1.5 release candidate 4 ==
+
+August 29, 2005
+
+MediaWiki 1.5rc4 is a preview release of the new 1.5 release series.
+It fixes compatibility with PHP 5.1, and corrects two cross-site scripting
+security bugs:
+
+* <math> tags were handled incorrectly when TeX rendering support is off,
+  as in the default configuration.
+* Extension or <nowiki> sections in Wiki table syntax could bypass HTML
+  style attribute restrictions for cross-site scripting attacks against
+  Microsoft Internet Explorer
+
+Wikis where the optional math support has been *enabled* are not vulnerable
+to the first, but are vulnerable to the second.
+
+
+
+== MediaWiki 1.5 release candidate 3 ==
+
+August 24, 2005
+
+MediaWiki 1.5rc3 is a preview release of the new 1.5 release series.
+It fixes several major problems in 1.5rc2:
+
+* Fixed a cross-site scripting injection in the search form
+  (broken since 1.5beta1)
+
+* Fixed upgrades from 1.4 database schema
+  (broken since 1.5rc2)
+
+1.3 and 1.4 releases are not vulnerable to the XSS bug, but anyone
+running an earlier 1.5 beta or release candidate should upgrade
+immediately.
+
+
+== MediaWiki 1.5 release candidate 2 ==
+
+August 23, 2005
+
+MediaWiki 1.5rc2 is a preview release of the new 1.5 release series.
+Numerous bug fixes since last beta, plus a security fix; see change
+log below for full details.
+
+A flaw in the interaction between extensions and HTML attribute
+sanitization was discovered which could allow unauthorized use
+of offsite resources in style sheets, and possible exploitation
+of a JavaScript injection feature on Microsoft Internet Explorer.
+
+This version expands the returned text and properly checks it
+before output.
+
+A 1.5rc1 release was mistakenly made from the incorrect source code
+branch; 1.5rc2 is identical to the actual 1.5rc1 in revision control
+except for version number.
+
+
+== MediaWiki 1.5 beta 4 ==
+
+July 30, 2005
+
+MediaWiki 1.5 beta 4 is a preview release of the new 1.5 release series.
+A number of bugs have been fixed since beta 3; see the full changelist below.
+
+
+== MediaWiki 1.5 beta 3 ==
+
+July 7, 2005
+
+MediaWiki 1.5 beta 3 is a preview release of the new 1.5 release
+series, with a security update over beta 2.
+
+Incorrect escaping of a parameter in the page move template could
+be used to inject JavaScript code by getting a victim to visit a
+maliciously constructed URL. Users of vulnerable releases are
+recommended to upgrade to this release.
+
+Vulnerable versions:
+* 1.5 preview series: n <= 1.5beta2 vulnerable, fixed in 1.5beta3
+* 1.4 stable series: 1.4beta6 <= n <= 1.4.5 vulnerable, fixed in 1.4.6
+* 1.3 legacy series: not vulnerable
+
+This release also includes several bug fixes and localization updates.
+See the changelog at the end of this file for a detailed list.
+
+
+
+== MediaWiki 1.5 beta 2 ==
+
+July 5, 2005
+
+MediaWiki 1.5 beta 2 is a preview release of the new 1.5 release series.
+While most exciting new bugs should have been ironed out at this point,
+third-party wiki operators should probably not run this beta release
+on a public site without closely following additional development.
+
+Anyone who _has_ been running beta 1 is very very strongly advised to
+upgrade to beta 2, as it fixes many bugs from the previous beta including
+a couple of HTML and SQL injections.
+
+This release should be followed by one or two release candidates and
+a 1.5.0 final within the next few weeks.
+
+Beta upgraders, note there are some minor database changes. For upgrades
+from 1.4, see the file UPGRADE for details on significant database and
+configuration file changes.
+
+Beta 2 includes a preliminary command-line XML wiki dump importer tool,
+maintenance/importDump.php, paired with maintenance/dumpBackup.php.
+These use the same format as Special:Export and Special:Import, able
+to package a wiki's entire page set independent of the backend database
+and compression format.
+
+
+== MediaWiki 1.5 beta 1 ==
+
+June 26, 2005
+
+MediaWiki 1.5 beta 1 is a preview release, pretty much feature complete,
+of the new 1.5 release series. There are several known and likely a number
+of unknown bugs; it is not recommended to use this release in a production
+environment but would be recommended for testing in mind of an upcoming
+deployment.
+
+A number of significant changes have been made since the alpha releases,
+including database changes and a reworking of the user permissions settings.
+See the file UPGRADE for details of upgrading and changing your prior
+configuration settings for the new system.
+
+
+
+== MediaWiki 1.5 alpha 2 ==
+
+June 3, 2005
+
+MediaWiki 1.5 alpha 2 includes a lot of bug fixes, feature merges,
+and a security update.
+
+Incorrect handling of page template inclusions made it possible to
+inject JavaScript code into HTML attributes, which could lead to
+cross-site scripting attacks on a publicly editable wiki.
+
+Vulnerable releases and fix:
+* 1.5 prerelease: fixed in 1.5alpha2
+* 1.4 stable series: fixed in 1.4.5
+* 1.3 legacy series: fixed in 1.3.13
+* 1.2 series no longer supported; upgrade to 1.4.5 strongly recommended
+
+
+== MediaWiki 1.5 alpha 1 ==
+
+May 3, 2005
+
+This is a testing preview release, being put out mainly to aid testers in
+finding installation bugs and other major problems. It is strongly recommended
+NOT to run a live production web site on this alpha release.
+
+**  WARNING: USE OF THIS ALPHA RELEASE MAY INFEST YOUR HOUSE WITH  **
+**  TERMITES, ROT YOUR TEETH,  GROW HAIR ON YOUR PALMS, AND PASTE  **
+**  INNUENDO  INTO  YOUR  C.V.  RIGHT  BEFORE  A  JOB  INTERVIEW!  **
+**  DON'T SAY WE DIDN'T WARN YOU, MAN. WE TOTALLY DID RIGHT HERE.  **
+
+
+=== Smaller changes since 1.4 ===
+
+Various bugfixes, small features, and a few experimental things:
+
+* 'live preview' reduces preview reload burden on supported browsers
+* support for external editors for files and wiki pages:
+  http://meta.wikimedia.org/wiki/Help:External_editors
+* Schema reworking: http://meta.wikimedia.org/wiki/Proposed_Database_Schema_Changes/October_2004
+* (bug 15) Allow editors to view diff of their change before actually submitting an edit
+* (bug 190) Hide your own edits on the watchlist
+* (bug 510): Special:Randompage now works for other namespaces than NS_MAIN.
+* (bug 1015) support for the full wikisyntax in <gallery> captions.
+* (bug 1105) A "Destination filename" (save as) added to Special:Upload Upload.
+* (bug 1352) Images on description pages now get thumbnailed regardless of whether the thumbnail is larger than the original.
+* (bug 1662) A new magicword, {{CURRENTMONTHABBREV}} returns the abbreviation of the current month
+* (bug 1668) 'Date format' supported for other languages than English, see:
+  http://mail.wikipedia.org/pipermail/wikitech-l/2005-March/028364.html
+* (bug 1739) A new magicword, {{REVISIONID}} give you the article or diff database
+  revision id, useful for proper citation.
+* (bug 1998) Updated the Russian translation.
+* (bug 2064) Configurable JavaScript mimetype with $wgJsMimeType
+* (bug 2084) Fixed a regular expression in includes/Title.php that was accepting invalid syntax like #REDIRECT [[foo] in redirects
+* It's now possible to invert the namespace selection at Special:Allpages and Special:Contributions
+* No longer using sorbs.net to check for open proxies by default.
+* What was $wgDisableUploads is now $wgEnableUploads, and should be set to true if one wishes to enable uploads.
+* Supplying a reason for a block is no longer mandatory
+* Language conversion support for category pages
+* $wgStyleSheetDirectory is no longer an alias for $wgStyleDirectory;
+* Special:Movepage can now take paramaters like Special:Movepage/Page_to_move
+  (used to just be able to take paramaters via a GET request like index.php?title=Special:Movepage&target=Page_to_move)
+* (bug 2151) The delete summary now includes editor name, if only one has edited the article.
+* (bug 2105) Fixed from argument to the PHP mail() function. A missing space could prevent sending mail with some versions of sendmail.
+* (bug 2228) Updated the Slovak translation
+* ...and more!
+
+
+=== Changes since 1.5alpha1 ===
+
+* (bug 73) Category sort key is set to file name when adding category to
+  file description from upload page (previously it would be set to
+  "Special:Upload", causing problems with category paging)
+* (bug 419) The contents of the navigation toolbar are now editable through
+  the MediaWiki namespace on the  MediaWiki:navbar page.
+* (bug 498) The Views heading in MonoBook.php is now localizable
+* (bug 898) The wiki can now do advanced sanity check on uploaded files
+  including virus checks using external programs.
+* (bug 1692) Fix margin on unwatch tab
+* (bug 1906) Generalize project namespace for Latin localization, update namespaces
+* (bug 1975) The name for Limburgish (li) changed from "Lèmburgs" to "Limburgs
+* (bug 2019) Wrapped the output of Special:Version in <div dir='ltr'> in order
+  to preserve the correct flow of text on RTL wikis.
+* (bug 2067) Fixed crash on empty quoted HTML attribute
+* (bug 2075) Corrected namespace definitions in Tamil localization
+* (bug 2079) Removed links to Special:Maintenance from movepagetext message
+* (bug 2094) Multiple use of a template produced wrong results in some cases
+* (bug 2095) Triple-closing-bracket thing partly fixed
+* (bug 2110) "noarticletext" should not display on Image page for "sharedupload" media
+* (bug 2150) Fix tab indexes on edit form
+* (bug 2152) Add missing bgcolor to attribute whitelist for <td> and <th>
+* (bug 2176) Section edit 'show changes' button works correctly now
+* (bug 2178) Use temp dir from environment in parser tests
+* (bug 2217) Negative ISO years were incorrectly converted to BC notation
+* (bug 2234) allow special chars in database passwords during install
+* Deprecated the {{msg:template}} syntax for referring to templates, {{msg: is
+  now the wikisyntax representation of wfMsgForContent()
+* Fix for reading incorrectly re-gzipped HistoryBlob entries
+* HistoryBlobStub: the last-used HistoryBlob is kept open to speed up
+  multiple-revision pulls
+* Add $wgLegacySchemaConversion update-time option to reduce amount of
+  copying during the schema upgrade: creates HistoryBlobCurStub reference
+  records in text instead of copying all the cur_text fields. Requires
+  that the cur table be left in place until/unless such fields are migrated
+  into the main text store.
+* Special:Export now includes page, revision, and user id numbers by
+  default (previously this was disabled for no particular reason)
+* dumpBackup.php can dump the full database to Export XML, with current
+  revisions only or complete histories.
+* The group table was renamed to groups because "group" is a reserved word in
+  SQL which caused some inconveniances.
+* New fileicons for c, cpp, deb, dvi, exe, h, html, iso, java, mid, mov, o,
+  ogg, pdf, ps, rm, rpm, tar, tex, ttf and txt files based on the KDE
+  crystalsvg theme.
+* Fixed a bug in Special:Newimages that made it impossible to search for '0'
+* Added language variant support for Icelandic, now supports "Íslenzka"
+* The #p-nav id in MonoBook is now #p-navigation
+* Putting $4 in msg:userstatstext will now give the percentage of
+  admnistrators out of normal users.
+* links and brokenlinks tables merged to pagelinks; this will reduce pain
+  dealing with moves and deletes of widely-linked pages.
+* Add validate table and val_ip column through the updater.
+* Simple rate limiter for edits and page moves; set $wgRateLimits
+  (somewhat experimental; currently needs memcached)
+* (bug 2262) Hide math preferences when TeX is not enabled
+* (bug 2267) Don't generate thumbnail at the same size as the source image.
+* Fix rebuildtextindex.inc for new schema
+* Remove linkscc table code, no longer used.
+* (bug 2271) Use faster text-only link replacement in image alt text
+  instead of rerunning expensive link lookup and HTML generation.
+* Only build the HTML attribute whitelist tree once.
+* Replace wfMungeToUtf8 and do_html_entity_decode with a single function
+  that does both numeric and named chars: Sanitizer::decodeCharReferences
+* Removed some obsolete UTF-8 converter functions
+* Fix function comment in debug dump of SQL statements
+* (bug 2275) Update search index more or less right on page move
+* (bug 2053) Move comment whitespace trimming from edit page to save;
+  leaves the whitespace from the section comment there on preview.
+* (bug 2274) Respect stub threshold in category page list
+* (bug 2173) Fatal error when removing an article with an empty title from the watchlist
+* Removed -f parameter from mail() usage, likely to cause failures and bounces.
+* (bug 2130) Fixed interwiki links with fragments
+* (bug 684) Accept an attribute parameter array on parser hook tags
+* (bug 814) Integrate AuthPlugin changes to support Ryan Lane's external
+  LDAP authentication plugin
+* (bug 2034) Armor HTML attributes against template inclusion and links munging
+
+=== Changes since 1.5alpha2 ===
+
+* (bug 2319) Fix parse hook tag matching
+* (bug 2329) Fix title formatting in several special pages
+* (bug 2223) Add unique index on user_name field to prevent duplicate accounts
+* (bug 1976) fix shared user database with a table prefix set
+* (bug 2334) Accept null for attribs in wfElement without PHP warning
+* (bug 2309) Allow templates and template parameters in HTML attribute zone,
+  with proper validation checks. (regression from fix for 2304)
+* Disallow close tags and enforce empty tags for <hr> and <br>
+* Changed user_groups format quite a bit.
+* (bug 2368) Avoid fatally breaking PHP 4.1.2 in a debug line
+* (bug 2367) Insert correct redirect link record on page move
+* (bug 2372) Fix rendering of empty-title inline interwiki links
+* (bug 2384) Fix typo in regex for IP address checking
+* (bug 650) Prominently link MySQL 4.1 help page in installer if a possible
+  version conflict is detected
+* (bug 2394) Undo incompatible breakage to {{msg:}} compatiblity includes
+* (bug 1322) Use a shorter cl_sortkey field to avoid breaking on MySQL 4.1
+  when the default charset is set to utf8
+* (bug 2400) don't send confirmation mail on account creation if 
+  $wgEmailAuthentication is false.
+* (bug 2172) Fix problem with nowiki beeing replaced by marker strings
+  when a template with a gallery was used.
+* Guard Special:Userrights against form submission forgery
+* (bug 2408) page_is_new was inverted (whoops!)
+* Added wfMsgHtml() function for escaping messages and leaving params intact
+* Fix ordering of Special:Listusers; fix groups list so it shows all groups
+  when searching for a specific group and can't be split across pages
+* (bug 1702) Display a handy upload link instead of a useless blank link
+  for [[media:]] links to nonexistent files.
+* (bug 873) Fix usage of createaccount permission; replaces $wgWhitelistAccount
+* (bug 1805) Initialise $wgContLang before $wgUser
+* (bug 2277) Added Friulian language file
+* (bug 2457) The "Special page" href now links to the current special page
+  rather than to "".
+* (bug 1120) Updated the Czech translation
+* A new magic word, {{SCRIPTPATH}}, returns $wgScriptPath
+* A new magic word, {{SERVERNAME}}, returns $wgServerName
+* A new magic word, {{NUMBEROFFILES}}, returns the number of rows in the image table
+* Special:Imagelist displays titles with " " instead of "_"
+* Less gratuitous munging of content sample in delete summary
+* badaccess/badaccesstext to supercede sysop*, developer* messages
+* Changed $wgGroupPermissions to more cut-n-paste-friendly format
+* 'developer' group deprecated by default
+* Special:Upload now uses 'upload' permission instead of hardcoding login check
+* Add 'importupload' permission to disable direct uploads to Special:Import
+* (bug 2459) Correct escaping in Special:Log prev/next links
+* (bug 2462 etc) Taking out the experimental dash conversion; it broke too many
+  things for the current parser to handle cleanly
+* (bug 2467) Added a Turkish language file
+* Fixed a bug in Special:Contributions that caused the namespace selection to
+  be forgotten between submits
+* Special:Watchlist/edit now has namespace subheadings
+* (bug 1714) the "Save page" button now has right margin to seperate it from
+  "Show preview" and "Show changes"
+* Special:Statistics now supports action=raw, useful for bots designed to
+  harwest e.g. article counts from multiple wikis.
+* The copyright confirmation box at Special:Upload is now turned off by default
+  and can be turned back on by setting $wgCopyrightAffirmation to a true value.
+* Restored prior text for password reminder button and e-mail, replacing
+  the factually inaccurate text that was there.
+* (bug 2178) Fix temp dir check again
+* (bug 2488) Format 'deletedtext' message as wikitext
+* (bug 750) Keep line endings consistent in LocalSettings.php
+* (bug 1577) Add 'printable version' tab in MonoBook for people who don't
+  realize you can just hit print to get a nicely formatted printable page.
+* Trim whitespace from option values to weather line-ending corruption problems
+* Fixed a typo in the Romanian language file (NS_MESIA => NS_MEDIA)
+* (bug 2504) Updated the Finnish translation
+* (bug 2506, 2512) Updated the Nynorsk translation
+* (bug 996) Replace $wgWhitelistEdit with 'edit' permission; fixup UPGRADE
+  documentation about edit and read whitelists.
+* (bug 2515) Fix incremental link table update
+* Removed some wikipedia-specifica from LanguageXx.php's
+* (bug 2496) Allow MediaWiki:edithelppage to point to external page
+* Added a versionRequired() function to OutputPage, useful for extension
+  writers that want to control what version of MediaWiki their extension
+  can be used with.
+* Serialized user objects now checked for versioning
+* Fix for interwiki link regression
+* Printable link shorter in monobook
+* Experimental Latin-1-and-replication-friendly upgrader script
+* (bug 2520) Don't show enotif options when disabled
+
+== Changes since 1.5beta1 ==
+
+* (bug 2531) Changed the interwiki name for sh (Serbocroatian) to
+  Srpskohrvatski/Српскохрватски (was Српскохрватски (Srbskohrvatski))
+* Nonzero return code for command-line scripts on wfDebugDieBacktrace()
+* Conversion fix for empty old table in upgrade1_5.php
+* Try reading revisions from master if no result on slave
+* (bug 2538) Suppress notice on user serialized checks
+* Fix paging on Special:Contributions
+* (bug 2541) Fix unprotect tab
+* (bug 1242) category list now show on edit page
+* Skip sidebar entries where link text is '-'
+* Convert non-UTF-8 URL parameters even if referer is local
+* (bug 2460) <img> width & height properly filled when resizing image
+* (bug 2273) deletion log comment used user interface langage
+* Try reading revision _text_ from master if no result on slave
+* Use content-language message cache for raw view of message pages
+* (bug 2530) Not displaying talk pages on Special:Watchlist/edit
+* Fixed a bug that would occour if $wgCapitalLinks was set to false, a user
+  agent could create a username that began with a lower case letter that was
+  not in the ASCII character set ( now user $wgContLang->ucfirst() instead of
+  PHP ucfirst() )
+* Moved the user name / password validity checking from
+  LoginForm::addNewAccountInternal() to two new functions,
+  User::isValidUserName() and User::isValidPassword(), extensions can now do
+  these checks without rewriting code.
+* Fix $wgSiteNotice when MediaWiki:Sitenotice is set to default '-'
+* Fixed a bug where the watchlist count without talk pages would be off by a
+  factor of two.
+* upgrade1_5.php uses insert ignore, allows to skip image info initialization
+* Fix namespaces in category list.
+* Add rebuildImages.php to update image metadata fields
+* Special:Ancientpages is expensive in new schema for now
+* (bug 2568) Fixed a logic error in the Special:Statistics code which caused
+  the displayed percentage of admins to be totally off.
+* (bug 2560) Don't show blank width/height attributes for missing size
+* Don't show bogus messages about watchlist notifications when disabled
+* Don't show old debug messages in watchlist
+* (bug 2576) Fix recording of transclusion links
+* (bug 2577) Allow sysops to enter non-standard block times
+* Fixed a bug where Special:Contributions wouldn't remember the 'invert'
+  status between next/previous buttons.
+* Move MonoBook printable link from tab to sidebar
+* (bug 2567) Fix HTML escaping on category titles in list
+* (bug 2562) Show rollback link for current revisions on diff pages
+* (bug 2583) Add --missinig option on rebuildImages.php to add db entries
+  for uploaded files that don't have them
+* (bug 2572) Fix edit conflict handling
+* (bug 2595) Show "Earlier" and "Latest" links on history go to the first/last
+  page in the article history pager.
+* Don't show empty-page text in 'Show changes' on new page
+* (bug 2591) Check for end, fix limits on Whatlinkshere
+* (bug 2584) Fix output of subcategory list
+* (bug 2597) Don't crash when undeleting an image description page
+* (bug 2564) Don't show "editingold" warning for recent revision
+* Various code cleanup and HTML escaping fixlets
+* Copy IRC-over-UDP update option from REL1_4
+* (bug 2548) Keep summary on 'show changes' of section edit
+* Move center on toc to title part to avoid breaking .toc style usage
+* HTML sanitizer: correct multiple attributes by keeping last, not first
+* (bug 2614) Fix section edit links on diff-to-current with oldid set
+  Also fix navigation links on current-with-oldid view.
+* (bug 2620) Return to prior behavior for some more things (such as
+  subpage parent links) on current-diff view.
+* (bug 2618) Fix regression from another fix; show initial preview for
+  categories only if the page does not exist.
+* (bug 2625) Keep group & user settings when paging in Listusers
+* (bug 2627) Fix regression: diff radio button initial selection
+* Copy fix for old search URLs with Lucene search plugin from REL1_4
+* (bug 619) Don't use incompatible diff3 executable on non-Linux systems.
+* (bug 2631) Fix Hebrew namespaces.
+* (bug 2630) Indicate no-longer-valid cached entries in BrokenRedirects list
+* (bug 2644, 2645) "cur" diff links in page history, watchlist and
+  recentchanges should specify current ID explicitly.
+* (bug 2609) Fix text justification preferenced with MonoBook skin.
+* (bug 2594) Display article tab as red for non-existent articles.
+* (bug 2656) Fix regression: prevent blocked users from reverting images
+* (bug 2629) Automatically capitalize usernames again instead of
+  rejecting lowercase with a useless error message
+* (bug 2661) Fix link generation in contribs
+* Add support for &preload=Page_name (load text of an existing page into
+edit area) and &editintro=Page_name (load text of an existing page instead
+of MediaWiki:Newpagetext) to &action=edit, if page is new.
+* (bugs 2633, 2672, 2685, 2695) Fix Estonian, Portuguese, Italian, Finnish and
+  Spanish numeric formatting
+* Fixed Swedish numeric formatting
+* (bug 2658) Fix signature time, localtime to match timezone offset again
+* Files from shared repositories (e.g. commons) now display with their
+  image description pages when viewed on local wikis.
+* Restore compatibility namespace aliases for French Wikipedia
+* Fix diff order on Enhanced RC 'changes' link
+* (bug 2650) Fix national date type display on wikis that don't support
+  dynamic date conversion.
+* FiveUpgrade: large table hacks, install iw_trans update before links
+* (bug 2648) Rename namespaces in Afrikaanse
+* Special:Booksources checks if custom list page exists before using it
+* (bug 1170) Fixed linktrail for da: and ru:
+* (bug 2683) Really fix apostrophe escaping for toolbox tips
+* (bug 923) Fix title and subtitle for rclinked special page
+* (bug 2642) watchdetails message in several languages used  <a></a> instead of [ ]
+* (bug 2181) basic CSB language localisation by Tomasz G. Sienicki (thanks for the patch)
+* Fix correct use of escaping in edit toolbar bits
+* Removed language conversion support from Icelandic
+* (bug 2616) Fix proportional image scaling, giving correct height
+* (bug 2640) Include width and height attributes on unscaled images
+* Workaround for mysterious problem with bogus epoch If-Last-Modified reqs
+* (bug 1109) Suppress compressed output on 304 responses
+* (bug 2674) Include some site configuration info in export data:
+  namespaces definitions, case-sensitivity, site name, version.
+* Use xml:space="preserve" hint on export <text> elements
+* Make language variant selection work again for zh
+
+== Changes since 1.5beta2 ==
+
+* Escaped & correctly in Special:Contributions
+* (bug 2534) Hide edit sections with CSS to make right click to edit section work 
+* (bug 2708) Avoid undefined notice on cookieless login attempt
+* (bug 2188) Correct template namespace for Greek localization
+* Fixed number formatting for Dutch
+* (bug 1355) add class noprint to commonPrint.css
+* (bug 2350) Massive update for Limburgish (li) language using Wikipédia
+* Massive update for Arab (ar) language using Wikipédia
+* (bug 1560) Massive update for Kurdish (ku) language using Wikipédia
+* (bug 2709) Some messages were not read from database
+* (bug 2416) Don't allow search engine robots to index or follow nonexisting articles
+* Fix escaping in page move template.
+* (bug 153) Discrepancy between thumbnail size and <img> height attribute
+
+== Changes since 1.5beta3 ==
+
+* Fix talk page move handling
+* (bug 2721) New language file for Vietnamese with the Vietnamese number notation
+* (bug 2749) &nbsp; would appear as a literal in image galleries for Cs, Fr, Fur, Pl and Sv
+* (bug 787) external links being rendered when they only have one slash
+* Fixed a missing typecast in Language::dateFormat() that would cause some
+  interesting errors with signitures.
+* (bug 2764) Number format for Nds
+* (bug 1553) Stop forcing lowercase in Monobook skin for German language.
+* (bug 1064) Implements Special:Unusedcategories
+* (bug 2311) New language file for Macedonian
+* Fix nohistory message on empty page history
+* Fix fatal error in history when validation on
+* Cleaned up email notification message formatting
+* Finally fixed Special:Disambiguations that was broke since SCHEMA_WORK
+* (bug 2761) fix capitalization of "i" in Turkish
+* (bug 2789) memcached image metadata now cleared after deletion
+* Add serialized version number to image metadata cache records
+* (bug 2780) Fix thumbnail generation with GD for new image schema
+* (bug 2791) Slovene numeric format
+* (bug 655) Provide empty search form when searching for nothing
+* Nynorsk numeric format fix
+* (bug 2825) Fix regression in newtalk notifications for anons w/ enotif off
+* (bug 2833) Fix bug in previous fix
+* With $wgCapitalLinks off, accept off-by-first-letter-case in 'go' match
+* Optional parameters for [[Special:Listusers]]
+* (bug 2832) [[Special:Listadmins]] redirects to [[Special:Listusers/sysop]]
+* (bug 785) Parser did not get out of <pre> with list elements
+* Some shared upload fixes
+* (bug 2768) section=new on nonexistent talk page does not add heading
+* support preload= parameter for section=new
+* show comment subject in preview when using section=new
+* use comment form when creating a new talk page
+* (bug 460) Properly handle <center> tags as a block.
+* Undo inconsistent editing behavior change
+* (bug 2835) Back out fix for bug 2802, caused regressions in category sort
+* PHP 4.1.2 compatibility fix: define floatval() equivalent if missing
+* (bug 2901) Number format for Catalan
+* Special:Allpages performance hacks: index memcached caching, removed
+  inverse checkbox, use friendlier relative offsets in index build
+* Bring back "Chick" skin for mobile devices. It needs testing.
+* Fix spelling of $wgForwardSearchUrl in DefaultSettings.php
+* Specify USE INDEX on Allpages chunk queries, sometimes gets lost
+  due to bogus optimization
+* (bug 275) Section duplication fix
+* Remove unused use of undefined variable in UserMailer
+* Fix notice on search index update due to non-array
+* (bug 2885) Fix fatal errors and notices in PHP 5.1.0beta3
+* (bug 2931) Fix additional notices on reference use in PHP 4.4.0
+* (bug 2774) Add three new $wgHooks to LogPage which enable extensions to add
+  their own logtypes, see extensions/Renameuser/SpecialRenameuser.php for an
+  example of this.
+* (bug 740) Messages from extensions now appear in Special:Allmessages
+* (bug 2857) fixed parsing of lists in <pre> sections
+* (bug 796) Trackback support
+* Fix 1.5 regression: weird, backwards diff links on new pages in enhanced RC
+  are now suppressed as before.
+* New skin: Simple
+* "uselang" and "useskin" URL parameters can now be used in the URL when
+  viewing a page, to change the language and skin of a page respectively.
+* Skins can now be previewed in preferences
+* (bug 2943) AuthPlugin::getCanonicalName() name canonicalization hook,
+  patch from robla
+* Wrap revision insert & page update in a transaction, rollback on late
+  edit conflict.
+* (bug 2953) 'other' didn't work in Special:Blockip when localized
+* (bug 2958) Rollback and delete auto-summary should be in the project's
+  content language
+* Removed useless protectreason message
+* Spelling fix: $wgUrlProtcols -> $wgUrlProtocols
+* Switch Moldovan local name to cyrillic
+* Fix typo in undefined array index access prevention
+* (bug 2947) Update namespaces for sr localization
+* (bug 2952) Added Asturian language file with translated namespaces
+* (bug 2676) Apply a protective transformation on editing input/output
+  for browsers that hit the Unicode blacklist. Patch by plugwash.
+* (bug 2999) Fix encoding conversion of pl_title in upgrade1_5.php
+* compressOld.php disabled, as it's known to be broken.
+
+
+=== Changes since 1.5beta4 ===
+
+* Fix Special:Allmessages under PHP 5
+* (bug 2911) Special:Watchlist allowed only one type of limit at a time
+* (bug 693) Special:Allmessages is excessively wide and redundant
+* (bug 3001) Updated and applied live hack for recentchanges-based watchlist
+* (bug 145) Finish 'exclude redirect' implementation in search form
+* Rearranged Special:Movepage form to reduce confusion between destination
+  title and reason input boxes
+* (bug 2527) Always set destination filename when new file is selected
+* (bug 3056) MySQL 3 compatibility fix: USE INDEX instead of FORCE INDEX
+* PHP 4.1 compatibility fix: don't use new_link parameter to mysql_connect
+  if running prior to 4.2.0 as it causes the call to fail
+* (bug 3117) Fix display of upload size and type with tidy on
+* (bug 1487) invalid html on empty list in banlist
+* (bug 3017) Hotkey conflict for delete and show changes
+* made pixel unit translateable and blocklistline now eats infiniteblock
+  and expiringblock
+* (bug 3092) Wrong numerical separator for big numbers in Serbian.
+* (bug 2855) Credit for a uniq author showed its realname even with
+  $wgAllowRealName=false.
+* New special page: SpecialMostlinked
+* (bug 2393) Fix MIME type for Atom feeds ( application/rss+atom )
+* Fix display of read-only lockfile message
+* Added a new hook, 'AddNewAccount', which is run after account creation
+* Update all stats fields on recount.sql
+* Include software-visible client IP address in Special:Version comment
+  as a proxy debugging aid
+* (bug 3162) Fix 'undefined property page_is_new' error on watchlist
+* (bug 1734) granting db permissions failed with db usernames containg '-'
+* (bug 3170) wikititlesuffix was removed, use pagetitle instead
+* (bug 3187) watchlist text refer to unexistent "Stop watching" action
+* (bug 3190) Added some date format choices for language sr
+* (bug 1334) LanguageGa.php update
+* (bug 1020) Changing user interface language does not work immediately
+* (bug 2753) Some namespaces were not translated in LanguageTa.php (Tamil)
+* (bug 3204) Fix typo breaking special pages in fy localization
+* (bug 3210) Fix Media: links with remote image URL path
+* (bug 3220) Fix escaping of block URLs in Recentchanges
+* (bug 3238): Updated LanguageNn.php for 1_5 branch
+* (bug 3192): properly check 'limit' parameter on Special:Contributions
+* (bug 3244) Fix remote image loading hack, JavaScript injection on MSIE
+* Fix URL sanitization in HTML attributes, which broke in this branch
+* (bug 3475) anon contrib links on Special:Newpages
+
+
+=== Changes since 1.5rc2 ===
+
+* Fix upgrade from 1.4 due to version number check breakage
+* Fix upgrade from 1.4 with no old revisions
+* (bug 2108) Sort entries when using category browser
+* XSS issue : now sanitize search query input
+
+
+=== Changes since 1.5rc3 ===
+
+* (bug 3280) Respect 'move' group permission on page moves
+* (bug 2885) More PHP 5.1 fixes: skin, search, log, undelete
+* Security fix for <math>
+* Security fix for tables
+
+
+=== Changes since 1.5rc4 ===
+
+* (bug 3292) Fix move-over-redirect test when current entries are not plaintext
+* (bug 2078) Don't hide watch tab on preview
+* (bug 3306) Document $wgLocalTZoffset
+* Support SVG rendering with rsvg
+* Cap arbitrary SVG renders to given image size or $wgSVGMaxSize pixels wide
+* (bug 3127) Render large SVGs at image page size correctly
+* (bug 3448) Set page_len on undelete
+* (bug 2800) Don't scale up small iamges on |thumb| without explicit size
+* Use the real file link instead of the default-size rasterized version for
+  large SVG images on image description page
+* Include the file name/type/size line for non-resized images
+* (bug 3412) Clean up date format handling so ~~~~-sigs work with default
+  format as designed. Documentation comments updated.
+* (bug 1423) LanguageJa.php update
+* (bug 3405) Don't use raw letters as aliases of MSGNW: and SUBST:
+* (bug 3485) Fix bogus warning about filename capitalization when off
+* (bug 2792) Update rebuildrecentchanges.inc for new schema
+* Special:Import/importDump fixes: report XML parse errors, accept <minor/>
+* (bug 3489) PHP 5.1 compat problem with captioned images
+* (bug 3350) Missing label for move talk page checkbox.
+* (bug 2570) Add 'watch this page' checkbox on uploads, watch uploads
+  by default when 'watchdefault' option is on
+* (bug 3182) Clear link cache during import to prevent memory leak
+* (bug 3573) Full Greek Translation
+* (bug 3595) Warn and abort if importDump.php called in read-only mode.
+* (bug 3598) Update message cache on message page deletion, patch by Tietew
+* Blacklist additional MSIE CSS safety tricks
+
+
+=== Changes since 1.5.0 ===
+
+* (bug 3629) Fix date & time format for Frisian
+* (bug 3641) Fix handling of unrecognized file uploads with known extensions
+* (bug 3643) Fix image page display of large images with resizing disabled
+* Fix meta robots tag on Special:Version again to avoid listing vulnerable
+  versions for convenient harvesting by automated worms
+* (bug 3684) Fix typo in fatal error backtraces in Hooks.php
+* Backport fix for reference usage notice in Special:Search on PHP 4.4.0
+* Backport database connect error display fix from HEAD
+* (bug 2773) Print style sheet no longer overrides RTL text direction
+* MonoBook skin top link id changed from "contentTop" to "top" (shared with
+  name attribute)
+* Wrap message page insertions in a transaction to speed up installation
+* Fix Special:MovePage invalid HTML attribute for reason textarea
+* Avoid notice warning on edit with no User-Agent header
+* (bug 3734) Swapped out obsolete recount.sql with initStats.php
+* (bug 3735) Fix to run under MySQL 5's strict mode
+* (bug 3786) Experimental support for MySQL 4.1/5.0 utf8 charset mode
+  NOTE: Enabling this may break existing wikis, and still doesn't
+  work for all Unicode characters due to MySQL limitations.
+* Sanitizer CSS comment processing order fix
+
+
+=== Changes since 1.5.1 ===
+
+* Fix Special:BrokenRedirects on MySQL 5.0
+* (bug 3809) Backport fix for detecting diff3 failure
+* MySQL 5.0 strict mode fix for moving unwatched pages
+* (bug 3782) Throw fatal installation warning if mbstring.func_overload on.
+  Why do people invent these crazy options that change language semantics?
+* (bug 3762) Define missing Special:Import UI messages
+* (bug 3771) Handle internal functions in backtrace in wfAbruptExit()
+* (bug 3649) Remove obsolete, broken moveCustomMessages script
+* (bug 3667) Add missing global in page move code
+* (bug 3761) Avoid deprecation warnings in Special:Import
+* (bug 2885) Remove unnecessary reference parameter which broke classic skin
+  talk notification on PHP 5.0.5
+* (bug 3845) Update attribute.php for 1.5 schema
+* Fix Parser::unstrip on PHP 4.4.1 and PHP 5.1.0RC4
+
+
+=== Changes since 1.5.2 ===
+
+* (bug 3612) Remove old broken version of maintenance/compressOld.php
+  The working version is in maintenance/storage/compressOld.php
+* (bug 2740) Accept image deletions on 'enter' submit from MSIE
+* (bug 3933) specify XML namespace for Atom 0.3 feeds
+* (bug 3939) Don't try to load text for interwiki redirect target
+* (bug 3948) Avoid notice warning in debug statement in bad search
+* Recognize Special:Search consistently so read whitelist works
+* (bug 4013) typo in fr
+* (bug 3996) Fix text for new entries in RC RSS/Atom feed
+* (bug 2894) Enhanced Recent Changes link fixes
+* (bug 3065) Update both watched namespaces when renaming pages
+* Move parentheses out of <a> link in Special:Contributions
+* (bug 4071) Generate passwords long enough for $wgMinimalPasswordLength
+* (bug 4035) Fix prev/next revision links on edit page
+* (bug 4165) Correct validation for user language selection (data taint)
+* Clearer message in DefaultSettings.php: edit LocalSettings.php instead
+
+
+=== Changes since 1.5.3 ===
+
+* (bug 3805) Clear 'new messages' flag properly in enotif mode
+  for usernames containing spaces
+* (bug 2714) Backlink from special:whatlinkshere was hard set as 'existing'
+* (bug 4249) Typo in entities2literals.pl
+* (bug 4233) Update for japanese language
+* (bug 4279) Small correction to LanguageDa.php
+* (bug 4267) Switch dv sd ug ks arc languages to RTL
+* (bug 3991) Allow the operation of wikicode on Protect move only text
+* Added AutoAuthenticate hook for external User object suppliers
+* Parser internal placeholder string now fully randomized for safety
+
+=== Changes since 1.5.4 ===
+
+* Maintenance script to delete unused user accounts
+* Added detection for WMF files (application/x-msmetafile), added this 
+  MIME type to the default blacklist. Prevented inline display of images
+  which are not of known image types. This is in response to
+  http://en.wikipedia.org/wiki/Windows_Metafile_vulnerability
+
+=== Changes since 1.5.5 ===
+
+* (bug 4258) When installing under IIS, $wgArticlePath = "$wgScript?title=$1" 
+  should be set
+* (bug 4510) Correct Barnes & Noble bookstore URLs
+* (bug 4504) Use site language for namespace name resolution
+* Installer fixes from HEAD backported; now uses a more sensible method of 
+  establishing which mySQL user to use, which clears up bug 921 et al. Minor 
+  changes to installer.
+* Fix problem reported on mailing list where re-initialising stats didn't work 
+  (can't insert duplicate rows with the same id field)
+* (bug 1122) gray out 'older revision' when viewing first article revision.
+* Respect database prefix in dumpHTML.inc
+* Minor improvements to removeUnusedAccounts.php maintenance script
+* Fix for single-digit week numbers from {{CURRENTWEEK}}, broken by PHP 4.4.1
+* Removed read-only check from Database::query()
+* Added --conf option to command line scripts, allowing the user to specify a 
+  different LocalSettings.php.
+
+=== Changes since 1.5.6 ===
+
+* Default main page content improved per bug 4690
+* Fix dependence on hardcoded UNIQ_PREFIX in LanguageConverter.php 
+* Fixed Special:Unlockdb
+* Maintenance script to delete unused text records
+* Maintenance script to delete non-current revisions
+* Maintenance script to wipe a page and all revisions from the database
+* (bug 4768) Wrong Russian translation (typo)
+* Performance bugfix: propagate equality manually for Revision fetches
+* (bug 4773) PHP fatal error when invalid title passed to Special:Export
+* Added missing table defs. for transcache to installer schemas
+* (bug 4824) IE7 beta 2 broke compatibility with PNG logo workarounds,
+  and seems to work ok with other bits. No longer including the IE
+  workarounds JavaScript for IE 7 and above.
+* (bug 2532) Image directory structure migration bug
+* (bug 4881) Correction to the fix for 1487; Ipblocklist showed 'no blocks'
+  message at the end of the list even if there were blocks.
+* (bug 4805) Removed more wikipedia-references from LanguageUk.php
+* Introduce $wgWantedPagesThreshold per bug 5011; Special:Wantedpages will not
+  list pages with less than this number of links. Defaults to 1.
+* Allow customisation of paging limits for items in categories using the
+  $wgCategoryPagingLimit global, per bug 4970.
+* Improve "nogomatch" text to make it more obvious that a page can be created.
+* (bug 5113) Spelling error in French language file
+* Don't change the password of the MySQL root user.
+
+=== Changes since 1.5.7 ===
+
+* (bug 5180) User login page shows inappropriate email blurb
+* Add the "AbortNewAccount" hook on account creation; see hooks.txt for more info.
+* Update default "exporttext" to reflect that Special:Import exists
+* Add links to useful material to the default main page content
+* Fix fragment HTML injection
+
+
+=== Caveats ===
+
+Some output, particularly involving user-supplied inline HTML, may not
+produce 100% valid or well-formed XHTML output. Testers are welcome to
+set $wgMimeType = "application/xhtml+xml"; to test for remaining problem
+cases, but this is not recommended on live sites. (This must be set for
+MathML to display properly in Mozilla.)
+
+
+For notes on 1.4.x and older releases, see HISTORY.
+
+
+=== Online documentation ===
+
+Documentation for both end-users and site administrators is currently being
+built up on Meta-Wikipedia, and is covered under the GNU Free Documentation
+License:
+
+  http://meta.wikipedia.org/wiki/Help:Contents
+
+
+=== Mailing list ===
+
+A MediaWiki-l mailing list has been set up distinct from the Wikipedia
+wikitech-l list:
+
+  http://mail.wikipedia.org/mailman/listinfo/mediawiki-l
+
+A low-traffic announcements-only list is also available:
+  http://mail.wikipedia.org/mailman/listinfo/mediawiki-announce
+
+It's highly recommended that you sign up for one of these lists if you're
+going to run a public MediaWiki, so you can be notified of security fixes.
+
+
+=== IRC help ===
+
+There's usually someone online in #mediawiki on irc.freenode.net
diff --git a/UPGRADE b/UPGRADE
new file mode 100644 (file)
index 0000000..ae841ea
--- /dev/null
+++ b/UPGRADE
@@ -0,0 +1,236 @@
+== The basic theory ==
+
+Generally, within a stable release series (e.g. 1.4.0, 1.4.1, etc) there
+are no required database changes, and upgrading should require no more
+than copying the new source files over the old ones.
+
+If there are larger changes, such as upgrading from one release series
+to another (e.g. from 1.3.12 to 1.4.3), then you may need to update the
+database schema and configuration.
+
+Basically, to upgrade a wiki you:
+* Back up your data! (See Backups! below)
+* Extract the new archive. If you can do this in a clean directory that's
+  great, but it should work to extract over the old files too. This may
+  be easier if you have images etc in place and don't want to move them
+  around, but remember to back up first!
+* Run the installer to upgrade the database schema (if necessary).
+
+
+== IMPORTANT: Upgrading to 1.5 ==
+
+Major changes have been made to the schema from 1.4.x. The updater
+has not been fully tested for all conditions, and might well break
+under some combinations of versions.
+
+NEVER EVER ATTEMPT TO PERFORM AN UPGRADE WITHOUT BACKING UP FIRST!
+
+On a large site, the schema update might take a long time. It might
+explode, or leave your database half-done or otherwise badly hurting.
+
+Among other changes, note that Latin-1 encoding (ISO-8859-1) is
+no longer supported. Latin-1 wikis will need to be upgraded to
+UTF-8; an experimental command-line upgrade helper script,
+'upgrade1_5.php', can do this -- run it prior to 'update.php' or
+the web upgrader.
+
+Message changes:
+* A number of additional UI messages have been chagned from HTML to
+  wikitext, and will need to be manually fixed if customized.
+
+
+=== Configuration changes from 1.4.x: ===
+
+$wgDisableUploads has been replaced with $wgEnableUploads.
+
+$wgWhitelistAccount has been replaced by the 'createaccount' permission
+key in $wgGroupPermissions. To emulate the old effect of setting:
+  $wgWhitelistAccount['user'] = 0;
+set:
+  $wgGroupPermissions['*']['createaccount'] = false;
+
+$wgWhitelistEdit has been replaced by the 'edit' permission key.
+To emulate the old effect of setting:
+  $wgWhitelistEdit = true;
+set:
+  $wgGroupPermissions['*']['edit'] = false;
+
+If $wgWhitelistRead is set, you must also disable the 'read' permission
+for it to take affect on anonymous users:
+  $wgWhitelistRead = array( "Main Page", "Special:Userlogin" );
+  $wgGroupPermissions['*']['read'] = false;
+
+Note that you can disable/enable several other permissions by modifying
+this configuration array in your LocalSettings.php; see DefaultSettings.php
+for the complete default permission set.
+
+If using Memcached, you must enabled it differently now:
+  $wgUseMemCached = true;
+should be replaced with:
+  $wgMainCacheType = CACHE_MEMCACHED;
+
+
+=== Web installer ===
+
+You can use the web-based installer wizard if you first remove the
+LocalSettings.php (and AdminSettings.php, if any) files; be sure to
+give the installer the same information as you did on the original
+install (language/encoding, database name, password, etc). This will
+also generate a fresh LocalSettings.php, which you may need to customize.
+
+You may change some settings during the install, but be very careful!
+Changing the encoding in particular will generally leave you with a
+lot of corrupt pages, particularly if your wiki is not in English.
+
+=== Command-line upgrade ===
+
+Additionally, as of 1.4.0 you can run an in-place upgrade script from
+the command line, keeping your existing LocalSettings.php. This requires
+that you create an AdminSettings.php giving an appropriate database user
+and password with privileges to modify the database structure.
+
+Once the new files are in place, go into the maintenance subdirectory and
+run the script:
+
+  php update.php
+
+See caveats below on upgrading from 1.3.x or earlier.
+
+
+== Backups! ==
+
+To upgrade an existing MediaWiki installation, first BACK UP YOUR WIKI!
+If something goes wrong, you want to be able to start again.
+
+Your image files, configuration, etc can simply be copied or archived as
+you would any other files. (Make sure that the contents of your
+LocalSettings.php are not accidentally made public, as this contains
+a database password.)
+
+To back up the database, use the tools provided by your service provider
+(if applicable) or the standard mysqldump program.
+
+For general help on mysqldump:
+http://dev.mysql.com/doc/mysql/en/mysqldump.html
+
+WARNING: If using MySQL 4.1.x, mysqldump's charset conversion may in
+some cases damage data in your wiki. If necessary, set the charset
+option to 'latin1' to avoid the conversion. Fore more info see:
+http://mail.wikipedia.org/pipermail/wikitech-l/2004-November/026359.html
+
+
+== Caveats ==
+
+
+=== Upgrading from 1.4.2 or earlier ===
+
+1.4.3 has added new fields to the sitestats table. These fields are
+optional and help to speed Special:Statistics on large sites. If you
+choose not to run the database upgrades, everything will continue to
+work in 1.4.3.
+
+You can apply the update by running maintenance/update.php, or
+manually run the SQL commands from this file:
+  maintenance/archives/patch-ss_total_articles.sql
+
+
+=== Upgrading from 1.4rc1 or earlier betas ===
+
+The logging table has been altered from 1.4beta4 to 1.4beta5
+and again in 1.4.0 final. Copy in the new files and use the web
+installer to upgrade, or the command-line maintenance/update.php.
+
+If you cannot use the automated installers/updaters, you may
+update the table by manually running the SQL commands in these
+files:
+   maintenance/archives/patch-log_params.sql
+   maintenance/archives/patch-logging-title.sql
+
+
+=== Upgrading from 1.3.x ===
+
+This should generally go smoothly.
+
+If you keep your LocalSettings.php, you may need to change the style paths
+to match the newly rearranged skin modules. Change these lines:
+  $wgStylePath        = "$wgScriptPath/stylesheets";
+  $wgStyleDirectory   = "$IP/stylesheets";
+  $wgLogo             = "$wgStylePath/images/wiki.png";
+
+to this:
+  $wgStylePath        = "$wgScriptPath/skins";
+  $wgStyleDirectory   = "$IP/skins";
+  $wgLogo             = "$wgStylePath/common/images/wiki.png";
+
+As well as new messages, the processing of some messages has changed.
+If you have customized them, please compare the new format using
+Special:Allmessages or the relevant LanguageXX.php files:
+  copyrightwarning
+  dberrortext
+  editingcomment  (was named commentedit)
+  editingsection  (was named sectionedit)
+  numauthors
+  numedits
+  numtalkauthors
+  numtalkedits
+  numwatchers
+  protectedarticle
+  searchresulttext
+  showhideminor
+  unprotectedarticle
+
+Note that the 1.3 beta releases included a potential vulnerability if PHP
+is configured with register_globals on and the includes directory is
+served to the web. For general safety, turn register_globals *off* if you
+don't _really_ need it for another package.
+
+If your hosting provider turns it on and you can't turn it off yourself,
+send them a kind note explaining that it can expose their servers and their
+customers to attacks.
+
+
+=== Upgrading from 1.2.x ===
+
+If you've been using the MediaWiki: namespace for custom page templates,
+note that things are a little different. The Template: namespace has been
+added which is more powerful -- templates can include parameters for
+instance.
+
+If you were using custom MediaWiki: entries for text inclusions, they
+will *not* automatically be moved to Template: entries at upgrade time.
+Be sure to go through and check that everything is working properly;
+you can move them manually or you can try using moveCustomMessages.php
+in maintenance/archives to do it automatically, but this might break things.
+
+Also, be sure to pick the correct character encoding -- some languages were
+only available in Latin-1 on 1.2.x and are now available for Unicode as well.
+If you want to upgrade an existing wiki from Latin-1 to Unicode you'll have
+to dump the database to SQL, run it through iconv or another conversion tool,
+and restore it. Sorry.
+
+
+=== Upgrading from 1.1.x or earlier ===
+
+This is less thoroughly tested, but should work.
+
+You need to specify the *admin* database username and password to the
+installer in order for it to successfully upgrade the database structure.
+You may wish to manually change the GRANTs later.
+
+If you have a very old database (earlier than organized MediaWiki releases
+in late August 2003) you may need to manually run some of the update SQL
+scripts in maintenance/archives before the installer is able to pick up
+with remaining updates.
+
+
+=== Upgrading from UseModWiki or old "phase 2" Wikipedia code ===
+
+There is a semi-maintained UseModWiki to MediaWiki conversion script at
+maintenance/importUseModWiki.php; it may require tweaking and customization
+to work for you.
+
+Install a new MediaWiki first, then use the conversion script which will
+output SQL statements; direct these to a file and then run that into your
+database.
+
+You will have to rebuild the links tables etc after importing.
diff --git a/config/index.php b/config/index.php
new file mode 100644 (file)
index 0000000..4d28fe2
--- /dev/null
@@ -0,0 +1,1391 @@
+<?php
+
+# MediaWiki web-based config/installation
+# Copyright (C) 2004 Brion Vibber <brion@pobox.com>, 2006 Rob Church <robchur@gmail.com>
+# http://www.mediawiki.org/
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# http://www.gnu.org/copyleft/gpl.html
+
+error_reporting( E_ALL );
+header( "Content-type: text/html; charset=utf-8" );
+@ini_set( "display_errors", true );
+
+?><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+        "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+       <meta http-equiv="Content-type" content="text/html; charset=utf-8">
+       <meta name="robots" content="noindex,nofollow">
+       <title>MediaWiki 1.5 Installation</title>
+       <style type="text/css">
+       #credit {
+               float: right;
+               width: 200px;
+               font-size: 0.7em;
+               background-color: #eee;
+               color: black;
+               border: solid 1px #444;
+               padding: 8px;
+               margin-left: 8px;
+       }
+
+       dl.setup dd {
+               margin-left: 0;
+       }
+       dl.setup dd label.column {
+               clear: left;
+               font-weight: bold;
+               width: 12em;
+               float: left;
+               text-align: right;
+               padding-right: 1em;
+       }
+       dl.setup dt {
+               clear: left;
+               font-size: 0.8em;
+               margin-left: 10em;
+               /* margin-right: 200px; */
+               margin-bottom: 2em;
+       }
+       .error {
+               color: red;
+       }
+       ul.plain {
+               list-style: none;
+               clear: both;
+               margin-left: 12em;
+       }
+       </style>
+</head>
+
+<body>
+
+<div id="credit">
+ <center>
+  <a href="http://www.mediawiki.org/">
+   <img src="../skins/common/images/mediawiki.png" width="135" height="135" alt="" border="0" />
+  </a>
+ </center>
+
+ <p><strong><a href="http://www.mediawiki.org/">MediaWiki</a></strong> is
+ Copyright (C) 2001-2006 by Magnus Manske, Brion Vibber, Lee Daniel Crocker,
+ Tim Starling, Erik M&ouml;ller, Gabriel Wicke and others.</p>
+
+ <ul>
+  <li><a href="../README">Readme</a></li>
+  <li><a href="../RELEASE-NOTES">Release notes</a></li>
+  <li><a href="../docs/">doc/</a></li>
+  <li><a href="http://meta.wikipedia.org/wiki/MediaWiki_User's_Guide">User's Guide</a></li>
+ </ul>
+
+ <p>This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.</p>
+
+ <p>This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.</p>
+
+ <p>You should have received <a href="../COPYING">a copy of the GNU General Public License</a>
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ or <a href="http://www.gnu.org/copyleft/gpl.html">read it online</a></p>
+</div>
+
+<?php
+
+# Relative includes seem to break if a parent directory is not readable;
+# this is common for public_html subdirs under user home directories.
+#
+# As a dirty hack, we'll try to set up the include path first.
+#
+$IP = dirname( dirname( __FILE__ ) );
+$sep = (DIRECTORY_SEPARATOR == "\\") ? ";" : ":";
+ini_set( "include_path", ".$sep$IP$sep$IP/includes$sep$IP/languages" );
+
+define( "MEDIAWIKI", true );
+define( "MEDIAWIKI_INSTALL", true );
+require_once( "includes/Defines.php" );
+require_once( "includes/DefaultSettings.php" );
+require_once( "includes/MagicWord.php" );
+require_once( "includes/Namespace.php" );
+?>
+
+<h1>MediaWiki <?php print $wgVersion ?> installation</h1>
+
+
+<?php
+
+/* Check for existing configurations and bug out! */
+
+if( file_exists( "../LocalSettings.php" ) ) {
+       dieout( "<h2>Wiki is configured.</h2>
+
+       <p>Already configured... <a href='../index.php'>return to the wiki</a>.</p>
+
+       <p>(You should probably remove this directory for added security.)</p>" );
+}
+
+if( file_exists( "./LocalSettings.php" ) ) {
+       writeSuccessMessage();
+
+       dieout( '' );
+}
+
+if( !is_writable( "." ) ) {
+       dieout( "<h2>Can't write config file, aborting</h2>
+
+       <p>In order to configure the wiki you have to make the <tt>config</tt> subdirectory
+       writable by the web server. Once configuration is done you'll move the created
+       <tt>LocalSettings.php</tt> to the parent directory, and for added safety you can
+       then remove the <tt>config</tt> subdirectory entirely.</p>
+
+       <p>To make the directory writable on a Unix/Linux system:</p>
+
+       <pre>
+       cd <i>/path/to/wiki</i>
+       chmod a+w config
+       </pre>" );
+}
+
+
+require_once( "install-utils.inc" );
+require_once( "maintenance/updaters.inc" );
+
+class ConfigData {
+       function getEncoded( $data ) {
+               # removing latin1 support, no need...
+               return $data;
+       }
+       function getSitename() { return $this->getEncoded( $this->Sitename ); }
+       function getSysopName() { return $this->getEncoded( $this->SysopName ); }
+       function getSysopPass() { return $this->getEncoded( $this->SysopPass ); }
+}
+
+?>
+
+<p><em>Please include all of the lines below when reporting installation problems.</em></p>
+
+<h2>Checking environment...</h2>
+<ul>
+<?php
+$endl = "
+";
+$wgNoOutputBuffer = true;
+$conf = new ConfigData;
+
+install_version_checks();
+
+print "<li>PHP " . phpversion() . ": ok</li>\n";
+
+if( ini_get( "register_globals" ) ) {
+       ?>
+       <li><b class='error'>Warning:</b> <strong>PHP's
+       <tt><a href="http://php.net/register_globals">register_globals</a></tt>
+       option is enabled.</strong> MediaWiki will work correctly, but this setting
+       increases your exposure to potential security vulnerabilities in PHP-based
+       software running on your server. <strong>You should disable it if you are able.</strong></li>
+       <?php
+}
+
+$fatal = false;
+
+if( ini_get( "magic_quotes_runtime" ) ) {
+       $fatal = true;
+       ?><li class='error'><strong>Fatal: <a href='http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime'>magic_quotes_runtime</a> is active!</strong>
+       This option corrupts data input unpredictably; you cannot install or use
+       MediaWiki unless this option is disabled.
+       <?php
+}
+
+if( ini_get( "magic_quotes_sybase" ) ) {
+       $fatal = true;
+       ?><li class='error'><strong>Fatal: <a href='http://www.php.net/manual/en/ref.sybase.php#ini.magic-quotes-sybase'>magic_quotes_sybase</a> is active!</strong>
+       This option corrupts data input unpredictably; you cannot install or use
+       MediaWiki unless this option is disabled.
+       <?php
+}
+
+if( ini_get( "mbstring.func_overload" ) ) {
+       $fatal = true;
+       ?><li class='error'><strong>Fatal: <a href='http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload'>mbstring.func_overload</a> is active!</strong>
+       This option causes errors and may corrupt data unpredictably;
+       you cannot install or use MediaWiki unless this option is disabled.
+       <?php
+}
+
+if( $fatal ) {
+       dieout( "</ul><p>Cannot install wiki.</p>" );
+}
+
+if( ini_get( "safe_mode" ) ) {
+       $conf->safeMode = true;
+       ?>
+       <li><b class='error'>Warning:</b> <strong>PHP's
+       <a href='http://www.php.net/features.safe-mode'>safe mode</a> is active.</strong>
+       You may have problems caused by this, particularly if using image uploads.
+       </li>
+       <?php
+} else {
+       $conf->safeMode = false;
+}
+
+$sapi = php_sapi_name();
+$conf->prettyURLs = true;
+print "<li>PHP server API is $sapi; ";
+switch( $sapi ) {
+case "apache":
+case "apache2handler":
+       print "ok, using pretty URLs (<tt>index.php/Page_Title</tt>)";
+       break;
+default:
+       print "unknown; ";
+case "cgi":
+case "cgi-fcgi":
+case "apache2filter":
+case "isapi":
+       print "using ugly URLs (<tt>index.php?title=Page_Title</tt>)";
+       $conf->prettyURLs = false;
+       break;
+}
+print "</li>\n";
+
+$conf->xml = function_exists( "utf8_encode" );
+if( $conf->xml ) {
+       print "<li>Have XML / Latin1-UTF-8 conversion support.</li>\n";
+} else {
+       dieout( "PHP's XML module is missing; the wiki requires functions in
+               this module and won't work in this configuration.
+               If you're running Mandrake, install the php-xml package." );
+}
+
+$memlimit = ini_get( "memory_limit" );
+$conf->raiseMemory = false;
+if( empty( $memlimit ) || $memlimit == -1 ) {
+       print "<li>PHP is configured with no <tt>memory_limit</tt>.</li>\n";
+} else {
+       print "<li>PHP's <tt>memory_limit</tt> is " . htmlspecialchars( $memlimit ) . ". <strong>If this is too low, installation may fail!</strong> ";
+       $n = IntVal( $memlimit );
+       if( preg_match( '/^([0-9]+)[Mm]$/', trim( $memlimit ), $m ) ) {
+               $n = IntVal( $m[1] * (1024*1024) );
+       }
+       if( $n < 20*1024*1024 ) {
+               print "Attempting to raise limit to 20M... ";
+               if( false === ini_set( "memory_limit", "20M" ) ) {
+                       print "failed.";
+               } else {
+                       $conf->raiseMemory = true;
+                       print "ok.";
+               }
+       }
+       print "</li>\n";
+}
+
+$conf->zlib = function_exists( "gzencode" );
+if( $conf->zlib ) {
+       print "<li>Have zlib support; enabling output compression.</li>\n";
+} else {
+       print "<li>No zlib support.</li>\n";
+}
+
+$conf->turck = function_exists( 'mmcache_get' );
+if ( $conf->turck ) {
+       print "<li><a href=\"http://turck-mmcache.sourceforge.net/\">Turck MMCache</a> installed</li>\n";
+}
+$conf->eaccel = function_exists( 'eaccelerator_get' );
+if ( $conf->eaccel ) {
+    $conf->turck = 'eaccelerator';
+    print "<li><a href=\"http://eaccelerator.sourceforge.net/\">eAccelerator</a> installed</li>\n";
+}
+if (!$conf->turck && !$conf->eaccel) {
+       print "<li>Neither <a href=\"http://turck-mmcache.sourceforge.net/\">Turck MMCache</a> nor <a href=\"http://eaccelerator.sourceforge.net/\">eAccelerator</a> are installed, " .
+         "can't use object caching functions</li>\n";
+}
+
+$conf->diff3 = false;
+$diff3locations = array("/usr/bin", "/opt/csw/bin", "/usr/gnu/bin", "/usr/sfw/bin") + explode(":", getenv("PATH"));
+$diff3names = array("gdiff3", "diff3");
+
+$diff3versioninfo = array('$1 --version 2>&1', 'diff3 (GNU diffutils)');
+foreach ($diff3locations as $loc) {
+       $exe = locate_executable($loc, $diff3names, $diff3versioninfo);
+       if ($exe !== false) {
+               $conf->diff3 = $exe;
+               break;
+       }
+}
+
+if ($conf->diff3)
+       print "<li>Found GNU diff3: <tt>$conf->diff3</tt>.</li>";
+else
+       print "<li>GNU diff3 not found.</li>";
+
+$conf->ImageMagick = false;
+$imcheck = array( "/usr/bin", "/usr/local/bin", "/sw/bin", "/opt/local/bin" );
+foreach( $imcheck as $dir ) {
+       $im = "$dir/convert";
+       if( file_exists( $im ) ) {
+               print "<li>Found ImageMagick: <tt>$im</tt>; image thumbnailing will be enabled if you enable uploads.</li>\n";
+               $conf->ImageMagick = $im;
+               break;
+       }
+}
+
+$conf->HaveGD = function_exists( "imagejpeg" );
+if( $conf->HaveGD ) {
+       print "<li>Found GD graphics library built-in";
+       if( !$conf->ImageMagick ) {
+               print ", image thumbnailing will be enabled if you enable uploads";
+       }
+       print ".</li>\n";
+} else {
+       if( !$conf->ImageMagick ) {
+               print "<li>Couldn't find GD library or ImageMagick; image thumbnailing disabled.</li>\n";
+       }
+}
+
+$conf->UseImageResize = $conf->HaveGD || $conf->ImageMagick;
+
+# $conf->IP = "/Users/brion/Sites/inplace";
+$conf->IP = dirname( dirname( __FILE__ ) );
+print "<li>Installation directory: <tt>" . htmlspecialchars( $conf->IP ) . "</tt></li>\n";
+
+# $conf->ScriptPath = "/~brion/inplace";
+$conf->ScriptPath = preg_replace( '{^(.*)/config.*$}', '$1', $_SERVER["PHP_SELF"] ); # was SCRIPT_NAME
+print "<li>Script URI path: <tt>" . htmlspecialchars( $conf->ScriptPath ) . "</tt></li>\n";
+
+       $conf->posted = ($_SERVER["REQUEST_METHOD"] == "POST");
+
+       $conf->Sitename = ucfirst( importPost( "Sitename", "" ) );
+       $defaultEmail = empty( $_SERVER["SERVER_ADMIN"] )
+               ? 'root@localhost'
+               : $_SERVER["SERVER_ADMIN"];
+       $conf->EmergencyContact = importPost( "EmergencyContact", $defaultEmail );
+       $conf->DBserver = importPost( "DBserver", "localhost" );
+       $conf->DBname = importPost( "DBname", "wikidb" );
+       $conf->DBuser = importPost( "DBuser", "wikiuser" );
+       $conf->DBpassword = importPost( "DBpassword" );
+       $conf->DBpassword2 = importPost( "DBpassword2" );
+       $conf->DBprefix = importPost( "DBprefix" );
+       $conf->DBmysql5 = (importPost( "DBmysql5" ) == "true") ? "true" : "false";
+       $conf->RootUser = importPost( "RootUser", "root" );
+       $conf->RootPW = importPost( "RootPW", "-" );
+       $conf->LanguageCode = importPost( "LanguageCode", "en" );
+       $conf->SysopName = importPost( "SysopName", "WikiSysop" );
+       $conf->SysopPass = importPost( "SysopPass" );
+       $conf->SysopPass2 = importPost( "SysopPass2" );
+
+/* Check for validity */
+$errs = array();
+
+if( $conf->Sitename == "" || $conf->Sitename == "MediaWiki" || $conf->Sitename == "Mediawiki" ) {
+       $errs["Sitename"] = "Must not be blank or \"MediaWiki\".";
+}
+if( $conf->DBuser == "" ) {
+       $errs["DBuser"] = "Must not be blank";
+}
+if( $conf->DBpassword == "" ) {
+       $errs["DBpassword"] = "Must not be blank";
+}
+if( $conf->DBpassword != $conf->DBpassword2 ) {
+       $errs["DBpassword2"] = "Passwords don't match!";
+}
+if( !preg_match( '/^[A-Za-z_0-9]*$/', $conf->DBprefix ) ) {
+       $errs["DBprefix"] = "Invalid table prefix";
+}
+
+if( $conf->SysopPass == "" ) {
+       $errs["SysopPass"] = "Must not be blank";
+}
+if( $conf->SysopPass != $conf->SysopPass2 ) {
+       $errs["SysopPass2"] = "Passwords don't match!";
+}
+
+$conf->License = importRequest( "License", "none" );
+if( $conf->License == "gfdl" ) {
+       $conf->RightsUrl = "http://www.gnu.org/copyleft/fdl.html";
+       $conf->RightsText = "GNU Free Documentation License 1.2";
+       $conf->RightsCode = "gfdl";
+       $conf->RightsIcon = '${wgStylePath}/common/images/gnu-fdl.png';
+} elseif( $conf->License == "none" ) {
+       $conf->RightsUrl = $conf->RightsText = $conf->RightsCode = $conf->RightsIcon = "";
+} else {
+       $conf->RightsUrl = importRequest( "RightsUrl", "" );
+       $conf->RightsText = importRequest( "RightsText", "" );
+       $conf->RightsCode = importRequest( "RightsCode", "" );
+       $conf->RightsIcon = importRequest( "RightsIcon", "" );
+}
+
+$conf->Shm = importRequest( "Shm", "none" );
+$conf->MCServers = importRequest( "MCServers" );
+
+/* Test memcached servers */
+
+if ( $conf->Shm == 'memcached' && $conf->MCServers ) {
+       $conf->MCServerArray = array_map( 'trim', explode( ',', $conf->MCServers ) );
+       foreach ( $conf->MCServerArray as $server ) {
+               $error = testMemcachedServer( $server );
+               if ( $error ) {
+                       $errs["MCServers"] = $error;
+                       break;
+               }
+       }
+} else if ( $conf->Shm == 'memcached' ) {
+       $errs["MCServers"] = "Please specify at least one server if you wish to use memcached";
+}
+
+/* default values for installation */
+$conf->Email   =importRequest("Email", "email_enabled");
+$conf->Emailuser=importRequest("Emailuser", "emailuser_enabled");
+$conf->Enotif  =importRequest("Enotif", "enotif_allpages");
+$conf->Eauthent        =importRequest("Eauthent", "eauthent_enabled");
+
+if( $conf->posted && ( 0 == count( $errs ) ) ) {
+       do { /* So we can 'continue' to end prematurely */
+               $conf->Root = ($conf->RootPW != "");
+
+               /* Load up the settings and get installin' */
+               $local = writeLocalSettings( $conf );
+               $wgCommandLineMode = false;
+               chdir( ".." );
+               eval($local);
+               $wgDBadminuser = "root";
+               $wgDBadminpassword = $conf->RootPW;
+               $wgDBprefix = $conf->DBprefix;
+               $wgCommandLineMode = true;
+               $wgUseDatabaseMessages = false; /* FIXME: For database failure */
+               require_once( "includes/Setup.php" );
+               chdir( "config" );
+
+               require_once( "maintenance/InitialiseMessages.inc" );
+
+               $wgTitle = Title::newFromText( "Installation script" );
+               $mysqlOldClient = version_compare( mysql_get_client_info(), "4.1.0", "lt" );
+               if( $mysqlOldClient ) {
+                       print "<li><b>PHP is linked with old MySQL client libraries. If you are
+                               using a MySQL 4.1 server and have problems connecting to the database,
+                               see <a href='http://dev.mysql.com/doc/mysql/en/old-client.html'
+                               >http://dev.mysql.com/doc/mysql/en/old-client.html</a> for help.</b></li>\n";
+               }
+               
+               # Determine how we're going to connect to the database
+               if( $conf->RootPW == '-' ) {
+                       # Regular user
+                       $conf->Root = false;
+                       $db_user = $wgDBuser;
+                       $db_pass = $wgDBpassword;
+               } else {
+                       # Superuser
+                       $conf->Root = true;
+                       $db_user = $conf->RootUser;
+                       $db_pass = $conf->RootPW;
+               }
+               
+               # Now attempt the connection
+               echo( "<li>Connecting to $wgDBname on $wgDBserver as $db_user..." );
+               $wgDatabase = Database::newFromParams( $wgDBserver, $db_user, $db_pass, "", 1 );
+               if( $wgDatabase->isOpen() ) {
+                       # We're in; set up a few variables
+                       $ok = true;
+                       echo( "success.</li>\n" );
+                       $wgDatabase->ignoreErrors( true );
+                       $myver = mysql_get_server_info( $wgDatabase->mConn );
+                       $wgDBadminuser = $db_user;
+                       $wgDBadminpassword = $db_pass;
+               } else {
+                       # There was an error; if we recognise it, give some useful feedback
+                       $ok = false;
+                       $errno = mysql_errno();
+                       $errtx = htmlspecialchars( mysql_error() );
+                       echo( "failed with error $errno: $errtx.</li>\n" );
+                       switch( $errno ) {
+                               case 1045:
+                               case 2000:
+                                       # Authentication
+                                       if( $conf->Root ) {
+                                               # The superuser details are wrong
+                                               $errs["RootUser"] = "Check username";
+                                               $errs["RootPW"] = "and password";
+                                       } else {
+                                               # The regular user details are wrong
+                                               $errs["DBuser"] = "Check username";
+                                               $errs["DBpassword"] = "and password";
+                                       }
+                                       break;
+                               default:
+                                       # Something else
+                                       $errs["DBserver"] = "Couldn't connect to database";
+                                       break;
+                       } # switch
+               } # conn att
+
+               if( !$ok ) continue;
+
+               # Print out the mySQL version and enable mySQL 4 enhancements as needed
+               echo( "<li>Connected to $myver" );
+               if( version_compare( $myver, "4.0.0" ) >= 0 ) {
+                       echo( "; using enhancements for mySQL 4.</li>" );
+                       $conf->DBmysql4 = true;
+                       $local = writeLocalSettings( $conf );
+               }
+               
+               # Check for possible authentication problems re. password encryption in newer mySQL versions
+               $mysqlNewAuth = version_compare( $myver, "4.1.0", "ge" );
+               if( $mysqlNewAuth && $mysqlOldClient ) {
+                       echo( "<li><span class=\"error\"><strong>You are using mySQL 4.1, however, PHP is linked to older client libraries. If you encounter authentication problems, see <a href=\"http://dev.mysql.com/doc/mysql/en/old-client.html\">http://dev.mysql.com/doc/mysql/en/old-client.html</a> for pertinent solutions.</strong></span></li>\n" );
+               }
+               
+               # Check versions with regards to character sets, cough up an error if there are inconsistencies
+               if( $wgDBmysql5 ) {
+                       if( $mysqlNewAuth ) {
+                               echo( "<li>Enabling mySQL 4.1/5.0 character set mode.</li>\n" );
+                       } else {
+                               echo( "<li><span class=\"error\"><strong>mySQL 4.1/5.0 character set mode has been enabled, however, an older version of mySQL has been detected. This will likely cause the installation to fail.</li>\n" );
+                       }
+               }
+
+               @$sel = mysql_select_db( $wgDBname, $wgDatabase->mConn );
+               if( $sel ) {
+                       print "<li>Database <tt>" . htmlspecialchars( $wgDBname ) . "</tt> exists</li>\n";
+               } else {
+                       $err = mysql_errno();
+                       if ( $err != 1049 ) {
+                               print "<ul><li>Error selecting database $wgDBname: $err " . htmlspecialchars( mysql_error() ) .
+                                       "</li></ul>";
+                               continue;
+                       }
+                       $res = $wgDatabase->query( "CREATE DATABASE `$wgDBname`" );
+                       if( !$res ) {
+                               print "<li>Couldn't create database <tt>" .
+                                       htmlspecialchars( $wgDBname ) .
+                                       "</tt>; try with root access or check your username/pass.</li>\n";
+                               $errs["RootPW"] = "&lt;- Enter";
+                               continue;
+                       }
+                       print "<li>Created database <tt>" . htmlspecialchars( $wgDBname ) . "</tt></li>\n";
+               }
+
+               $wgDatabase->selectDB( $wgDBname );
+
+               if( $wgDatabase->tableExists( "cur" ) || $wgDatabase->tableExists( "revision" ) ) {
+                       print "<li>There are already MediaWiki tables in this database. Checking if updates are needed...</li>\n";
+
+                       # Create user if required
+                       if ( $conf->Root ) {
+                               $conn = Database::newFromParams( $wgDBserver, $wgDBuser, $wgDBpassword, $wgDBname, 1 );
+                               if ( $conn->isOpen() ) {
+                                       print "<li>DB user account ok</li>\n";
+                                       $conn->close();
+                               } else {
+                                       print "<li>Granting user permissions...";
+                                       if( $mysqlOldClient && $mysqlNewAuth ) {
+                                               print " <b class='error'>If the next step fails, see <a href='http://dev.mysql.com/doc/mysql/en/old-client.html'>http://dev.mysql.com/doc/mysql/en/old-client.html</a> for help.</b>";
+                                       }
+                                       print "</li>\n";
+                                       dbsource( "../maintenance/users.sql", $wgDatabase );
+                               }
+                       }
+                       print "<pre>\n";
+                       chdir( ".." );
+                       flush();
+                       do_all_updates();
+                       chdir( "config" );
+
+                       print "</pre>\n";
+                       print "<li>Finished update checks.</li>\n";
+               } else {
+                       # FIXME: Check for errors
+                       print "<li>Creating tables...";
+                       if( $wgDBmysql5 ) {
+                               print " using MySQL 5 table defs...";
+                               dbsource( "../maintenance/mysql5/tables.sql", $wgDatabase );
+                       } else {
+                               print " using MySQL 3/4 table defs...";
+                               dbsource( "../maintenance/tables.sql", $wgDatabase );
+                       }
+                       dbsource( "../maintenance/interwiki.sql", $wgDatabase );
+                       print " done.</li>\n";
+
+                       print "<li>Initializing data...";
+                       $wgDatabase->insert( 'site_stats',
+                               array( 'ss_row_id'        => 1,
+                                      'ss_total_views'   => 0,
+                                      'ss_total_edits'   => 0,
+                                      'ss_good_articles' => 0 ) );
+
+
+                       # Set up the DB user if we (i) can and (ii) need to
+                       if( $conf->Root ) {
+                               $db = Database::newFromParams( $wgDBserver, $wgDBuser, $wgDBpassword, $wgDBname, 1 );
+                               if( $db->isOpen() ) {
+                                       $db->close();
+                               } else {
+                                       print "<li>Granting user permissions...</li>\n";
+                                       dbsource( "../maintenance/users.sql", $wgDatabase );
+                                       $db->close();
+                               }
+                       }
+
+                       if( $conf->SysopName ) {
+                               $u = User::newFromName( $conf->getSysopName() );
+                               if ( 0 == $u->idForName() ) {
+                                       $u->addToDatabase();
+                                       $u->setPassword( $conf->getSysopPass() );
+                                       $u->saveSettings();
+
+                                       $u->addGroup( "sysop" );
+                                       $u->addGroup( "bureaucrat" );
+
+                                       print "<li>Created sysop account <tt>" .
+                                               htmlspecialchars( $conf->SysopName ) . "</tt>.</li>\n";
+                               } else {
+                                       print "<li>Could not create user - already exists!</li>\n";
+                               }
+                       } else {
+                               print "<li>Skipped sysop account creation, no name given.</li>\n";
+                       }
+
+                       $titleobj = Title::newFromText( wfMsgNoDB( "mainpage" ) );
+                       $article = new Article( $titleobj );
+                       $newid = $article->insertOn( $wgDatabase );
+                       $revision = new Revision( array(
+                               'page'      => $newid,
+                               'text'      => wfMsg( 'mainpagetext' ) . "\n\n" . wfMsg( 'mainpagedocfooter' ),
+                               'comment'   => '',
+                               'user'      => 0,
+                               'user_text' => 'MediaWiki default',
+                               ) );
+                       $revid = $revision->insertOn( $wgDatabase );
+                       $article->updateRevisionOn( $wgDatabase, $revision );
+
+                       print "<li><pre>";
+                       initialiseMessages();
+                       print "</pre></li>\n";
+               }
+
+               /* Write out the config file now that all is well */
+               print "<p>Creating LocalSettings.php...</p>\n\n";
+               $localSettings =  "<" . "?php$endl$local$endl?" . ">";
+               // Fix up a common line-ending problem (due to CVS on Windows)
+               $localSettings = str_replace( "\r\n", "\n", $localSettings );
+
+               if( version_compare( phpversion(), "4.3.2" ) >= 0 ) {
+                       $xt = "xt"; # Refuse to overwrite an existing file
+               } else {
+                       $xt = "wt"; # 'x' is not available prior to PHP 4.3.2. We did check above, but race conditions blah blah
+               }
+               $f = fopen( "LocalSettings.php", $xt );
+
+               if( $f == false ) {
+                       dieout( "<p>Couldn't write out LocalSettings.php. Check that the directory permissions are correct and that there isn't already a file of that name here...</p>\n" .
+                       "<p>Here's the file that would have been written, try to paste it into place manually:</p>\n" .
+                       "<pre>\n" . htmlspecialchars( $localSettings ) . "</pre>\n" );
+               }
+               if(fwrite( $f, $localSettings ) ) {
+                       fclose( $f );
+                       writeSuccessMessage();
+               } else {
+                       fclose( $f );
+                       die("<p class='error'>An error occured while writing the config/LocalSettings.php file. Check user rights and disk space then try again.</p>\n");
+
+               }
+
+       } while( false );
+}
+?>
+</ul>
+
+
+<?php
+
+if( count( $errs ) ) {
+       /* Display options form */
+
+       if( $conf->posted ) {
+               echo "<p class='error'>Something's not quite right yet; make sure everything below is filled out correctly.</p>\n";
+       }
+?>
+
+<form action="index.php" name="config" method="post">
+
+
+<h2>Site config</h2>
+
+<dl class="setup">
+       <dd>
+               <?php
+               aField( $conf, "Sitename", "Site name:" );
+               ?>
+       </dd>
+       <dt>
+               Your site name should be a relatively short word. It'll appear as the namespace
+               name for 'meta' pages as well as throughout the user interface. Good site names
+               are things like "<a href="http://www.wikipedia.org/">Wikipedia</a>" and
+               "<a href="http://openfacts.berlios.de/">OpenFacts</a>"; avoid punctuation,
+               which may cause problems.
+       </dt>
+
+       <dd>
+               <?php
+               aField( $conf, "EmergencyContact", "Contact e-mail" );
+               ?>
+       </dd>
+       <dt>
+               This will be used as the return address for password reminders and
+               may be displayed in some error conditions so visitors can get in
+               touch with you. It is also be used as the default sender address of e-mail
+               notifications (enotifs).
+       </dt>
+
+       <dd>
+               <label class='column' for="LanguageCode">Language</label>
+               <select id="LanguageCode" name="LanguageCode">
+
+               <?php
+                       $list = getLanguageList();
+                       foreach( $list as $code => $name ) {
+                               $sel = ($code == $conf->LanguageCode) ? 'selected="selected"' : '';
+                               echo "\t\t<option value=\"$code\" $sel>$name</option>\n";
+                       }
+               ?>
+               </select>
+       </dd>
+       <dt>
+               You may select the language for the user interface of the wiki...
+               Some localizations are less complete than others. Unicode (UTF-8 encoding)
+               is used for all localizations.
+       </dt>
+
+       <dd>
+               <label class='column'>Copyright/license metadata</label>
+               <div>Select one:</div>
+
+               <ul class="plain">
+               <li><?php aField( $conf, "License", "no license metadata", "radio", "none" ); ?></li>
+               <li><?php aField( $conf, "License", "GNU Free Documentation License 1.2 (Wikipedia-compatible)", "radio", "gfdl" ); ?></li>
+               <li><?php
+                       aField( $conf, "License", "a Creative Commons license...", "radio", "cc" );
+                       $partner = "MediaWiki";
+                       $exit = urlencode( "$wgServer{$conf->ScriptPath}/config/index.php?License=cc&RightsUrl=[license_url]&RightsText=[license_name]&RightsCode=[license_code]&RightsIcon=[license_button]" );
+                       $icon = urlencode( "$wgServer$wgUploadPath/wiki.png" );
+                       $ccApp = htmlspecialchars( "http://creativecommons.org/license/?partner=$partner&exit_url=$exit&partner_icon_url=$icon" );
+                       print "<a href=\"$ccApp\">choose</a>";
+                       ?> (link will wipe out any other data in this form!)
+               <?php if( $conf->License == "cc" ) { ?>
+                       <ul>
+                               <li><?php aField( $conf, "RightsIcon", "<img src=\"" . htmlspecialchars( $conf->RightsIcon ) . "\" alt='icon' />", "hidden" ); ?></li>
+                               <li><?php aField( $conf, "RightsText", htmlspecialchars( $conf->RightsText ), "hidden" ); ?></li>
+                               <li><?php aField( $conf, "RightsCode", "code: " . htmlspecialchars( $conf->RightsCode ), "hidden" ); ?></li>
+                               <li><?php aField( $conf, "RightsUrl", "<a href=\"" . htmlspecialchars( $conf->RightsUrl ) . "\">" . htmlspecialchars( $conf->RightsUrl ) . "</a>", "hidden" ); ?></li>
+                       </ul>
+               <?php } ?>
+                       </li>
+               </ul>
+       </dd>
+       <dt>
+               MediaWiki can include a basic license notice, icon, and machine-readable
+               copyright metadata if your wiki's content is to be licensed under
+               the GNU FDL or a Creative Commons license. If you're not sure, leave
+               it at "none".
+       </dt>
+
+
+       <dd>
+               <?php aField( $conf, "SysopName", "Sysop account name:", "" ) ?>
+       </dd>
+       <dd>
+               <?php aField( $conf, "SysopPass", "password:", "password" ) ?>
+       </dd>
+       <dd>
+               <?php aField( $conf, "SysopPass2", "again:", "password" ) ?>
+       </dd>
+       <dt>
+               A sysop user account can lock or delete pages, block problematic IP
+               addresses from editing, and other maintenance tasks. If creating a new
+               wiki database, a sysop account will be created with the given name
+               and password.
+       </dt>
+
+       <dd>
+               <label class='column'>Shared memory caching</label>
+               <div>Select one:</div>
+
+               <ul class="plain">
+               <li><?php aField( $conf, "Shm", "no caching", "radio", "none" ); ?></li>
+               <?php
+                       if ( $conf->turck ) {
+                               echo "<li>";
+                               aField( $conf, "Shm", "Turck MMCache", "radio", "turck" );
+                               echo "</li>";
+                       }
+               ?>
+               <?php
+                       if ( $conf->eaccel ) {
+                               echo "<li>";
+                               aField( $conf, "Shm", "eAccelerator", "radio", "eaccel" );
+                               echo "</li>";
+                       }
+               ?>
+               <li><?php aField( $conf, "Shm", "Memcached", "radio", "memcached" ); ?></li>
+               <li><?php aField( $conf, "MCServers", "Memcached servers", "" ) ?></li>
+               </ul>
+       </dd>
+       <dt>
+               Using a shared memory system such as Turck MMCache, eAccelerator, or Memcached will speed
+               up MediaWiki significantly. Memcached is the best solution but needs to be
+               installed. Specify the server addresses and ports in a comma-separted list. Only
+               use Turck shared memory if the wiki will be running on a single Apache server.
+       </dl>
+
+<h2>E-mail, e-mail notification and authentication setup</h2>
+
+<dl class="setup">
+       <dd>
+               <label class='column'>E-mail (general)</label>
+               <div>Select one:</div>
+
+               <ul class="plain">
+               <li><?php aField( $conf, "Email", "enabled", "radio", "email_enabled" ); ?></li>
+               <li><?php aField( $conf, "Email", "disabled", "radio", "email_disabled" ); ?></li>
+               </ul>
+       </dd>
+       <dt>
+               Use this to disable all e-mail functions (send a password reminder, user-to-user e-mail and e-mail notification),
+               if sending e-mails on your server doesn't work.
+       </dt>
+       <dd>
+               <label class='column'>User-to-user e-mail</label>
+               <div>Select one:</div>
+
+               <ul class="plain">
+               <li><?php aField( $conf, "Emailuser", "enabled", "radio", "emailuser_enabled" ); ?></li>
+               <li><?php aField( $conf, "Emailuser", "disabled", "radio", "emailuser_disabled" ); ?></li>
+               </ul>
+       </dd>
+       <dt>
+               Use this to disable only the user-to-user e-mail function (EmailUser).
+       </dt>
+       <dd>
+               <label class='column'>E-mail notification</label>
+               <div>Select one:</div>
+
+               <ul class="plain">
+               <li><?php aField( $conf, "Enotif", "disabled", "radio", "enotif_disabled" ); ?></li>
+               <li><?php aField( $conf, "Enotif", "enabled for changes of watch-listed and user_talk pages (recommended for small wikis; perhaps not suited for large wikis)", "radio", "enotif_allpages" ); ?></li>
+               <li><?php aField( $conf, "Enotif", "enabled for changes of user_talk pages only (suited for small and large wikis)", "radio", "enotif_usertalk" ); ?></li>
+               </ul>
+       </dd>
+       <dt>
+               <p>
+               E-mail notification sends a notification e-mail to a user, when the user_talk page is changed
+                and/or when watch-listed pages are changed, depending on the above settings.
+               When testing this feature, be reminded, that obviously an e-mail address must be present in your preferences
+               and that your own changes never trigger notifications to be sent to yourself.</p>
+
+               <p>Users get corresponding options to select or deselect in their users' preferences.
+               The user options are not shown on the preference page, if e-mail notification is disabled.</p>
+
+               <p>There are additional options for fine tuning in /includes/DefaultSettings.php .</p>
+       </dt>
+
+       <dd>
+               <label class='column'>E-mail address authentication</label>
+               <div>Select one:</div>
+
+               <ul class="plain">
+               <li><?php aField( $conf, "Eauthent", "disabled", "radio", "eauthent_disabled" ); ?></li>
+               <li><?php aField( $conf, "Eauthent", "enabled", "radio", "eauthent_enabled" ); ?></li>
+               </ul>
+       </dd>
+       <dt>
+               <p>E-mail address authentication uses a scheme to authenticate e-mail addresses of the users. The user who initially enters or changes his/her stored e-mail address
+               gets a link with a token mailed to that address. The stored e-mail address is authenticated at the moment the user comes back to the wiki via the link.</p>
+
+               <p>The e-mail address stays authenticated as long as the user does not change it; the time of authentication is indicated
+               on the user preference page.</p>
+
+               <p>If the option is enabled, only authenticated e-mail addresses can receive EmailUser mails and/or
+               e-mail notification mails.</p>
+       </dt>
+
+       </dl>
+
+<h2>Database config</h2>
+
+<dl class="setup">
+       <dd><?php
+               aField( $conf, "DBserver", "MySQL server" );
+       ?></dd>
+       <dt>
+               If your database server isn't on your web server, enter the name
+               or IP address here.
+       </dt>
+
+       <dd><?php
+               aField( $conf, "DBname", "Database name" );
+       ?></dd>
+       <dd><?php
+               aField( $conf, "DBuser", "DB username" );
+       ?></dd>
+       <dd><?php
+               aField( $conf, "DBpassword", "DB password", "password" );
+       ?></dd>
+       <dd><?php
+               aField( $conf, "DBpassword2", "again", "password" );
+       ?></dd>
+       <dt>
+               If you only have a single user account and database available,
+               enter those here. If you have database root access (see below)
+               you can specify new accounts/databases to be created.
+       </dt>
+
+       <dd><?php
+               aField( $conf, "DBprefix", "Database table prefix" );
+       ?></dd>
+       <dt>
+               <p>If you need to share one database between multiple wikis, or
+               MediaWiki and another web application, you may choose to
+               add a prefix to all the table names to avoid conflicts.</p>
+
+               <p>Avoid exotic characters; something like <tt>mw_</tt> is good.</p>
+       </dt>
+       
+       <dd><label class="column">Database charset</label>
+               <div>Select one:</div>
+               <ul class="plain">
+               <li><?php aField( $conf, "DBmysql5", "Backwards-compatible UTF-8", "radio", "false" ); ?></li>
+               <li><?php aField( $conf, "DBmysql5", "Experimental MySQL 4.1/5.0 UTF-8", "radio", "true" ); ?></li>
+               </ul>
+       </dd>
+       <dt>
+               <b>EXPERIMENTAL:</b> You can enable explicit Unicode charset support
+               for MySQL 4.1 and 5.0 servers. This is not well tested and may
+               cause things to break. <b>If upgrading an older installation, leave
+               in backwards-compatible mode.</b>
+       </dt>
+
+       <dd>
+               <?php
+               aField( $conf, "RootUser", "Super user:", "text" );
+               ?>
+       </dd>
+
+       <dd>
+               <?php
+               aField( $conf, "RootPW", "Password:", "password" );
+               ?>
+       </dd>
+       <dt>
+               If the database user specified above does not exist, or does not have permissions to create
+               the database or tables required, please provide details of a superuser account, such as <strong>root</strong>,
+               which does. If this is not needed, leave the password set to <strong>-</strong>.
+       </dt>
+
+       <dd>
+               <label class='column'>&nbsp;</label>
+               <input type="submit" value="Install!" />
+       </dd>
+</dl>
+
+
+</form>
+
+<?php
+}
+
+/* -------------------------------------------------------------------------------------- */
+function writeSuccessMessage() {
+       global $conf;
+       if ( ini_get( 'safe_mode' ) && !ini_get( 'open_basedir' ) ) {
+               echo <<<EOT
+<p>Installation successful!</p>
+<p>To complete the installation, please do the following:
+<ol>
+       <li>Download config/LocalSettings.php with your FTP client or file manager</li>
+       <li>Upload it to the parent directory</li>
+       <li>Delete config/LocalSettings.php</li>
+       <li>Start using <a href='../index.php'>your wiki</a>!
+</ol>
+<p>If you are in a shared hosting environment, do <strong>not</strong> just move LocalSettings.php
+remotely. LocalSettings.php is currently owned by the user your webserver is running under,
+which means that anyone on the same server can read your database password! Downloading
+it and uploading it again will hopefully change the ownership to a user ID specific to you.</p>
+EOT;
+       } else {
+               echo "<p>Installation successful! Move the config/LocalSettings.php file into the parent directory, then follow
+                       <a href='../index.php'>this link</a> to your wiki.</p>\n";
+       }
+}
+
+
+function escapePhpString( $string ) {
+       return strtr( $string,
+               array(
+                       "\n" => "\\n",
+                       "\r" => "\\r",
+                       "\t" => "\\t",
+                       "\\" => "\\\\",
+                       "\$" => "\\\$",
+                       "\"" => "\\\""
+               ));
+}
+
+function writeLocalSettings( $conf ) {
+       $conf->DBmysql4 = @$conf->DBmysql4 ? 'true' : 'false';
+       $conf->UseImageResize = $conf->UseImageResize ? 'true' : 'false';
+       $conf->PasswordSender = $conf->EmergencyContact;
+       $zlib = ($conf->zlib ? "" : "# ");
+       $magic = ($conf->ImageMagick ? "" : "# ");
+       $convert = ($conf->ImageMagick ? $conf->ImageMagick : "/usr/bin/convert" );
+       $pretty = ($conf->prettyURLs ? "" : "# ");
+       $ugly = ($conf->prettyURLs ? "# " : "");
+       $rights = ($conf->RightsUrl) ? "" : "# ";
+       $hashedUploads = $conf->safeMode ? '' : '# ';
+
+       switch ( $conf->Shm ) {
+               case 'memcached':
+                       $cacheType = 'CACHE_MEMCACHED';
+                       $mcservers = var_export( $conf->MCServerArray, true );
+                       break;
+               case 'turck':
+               case 'eaccel':
+                       $cacheType = 'CACHE_ACCEL';
+                       $mcservers = 'array()';
+                       break;
+               default:
+                       $cacheType = 'CACHE_NONE';
+                       $mcservers = 'array()';
+       }
+
+       if ( $conf->Email == 'email_enabled' ) {
+               $enableemail = 'true';
+               $enableuseremail = ( $conf->Emailuser == 'emailuser_enabled' ) ? 'true' : 'false' ;
+               $eauthent = ( $conf->Eauthent == 'eauthent_enabled' ) ? 'true' : 'false' ;
+               switch ( $conf->Enotif ) {
+                       case 'enotif_usertalk':
+                               $enotifusertalk = 'true';
+                               $enotifwatchlist = 'false';
+                               break;
+                       case 'enotif_allpages':
+                               $enotifusertalk = 'true';
+                               $enotifwatchlist = 'true';
+                               break;
+                       default:
+                               $enotifusertalk = 'false';
+                               $enotifwatchlist = 'false';
+               }
+       } else {
+               $enableuseremail = 'false';
+               $enableemail = 'false';
+               $eauthent = 'false';
+               $enotifusertalk = 'false';
+               $enotifwatchlist = 'false';
+       }
+
+       $file = @fopen( "/dev/urandom", "r" );
+       if ( $file ) {
+               $secretKey = bin2hex( fread( $file, 32 ) );
+               fclose( $file );
+       } else {
+               $secretKey = "";
+               for ( $i=0; $i<8; $i++ ) {
+                       $secretKey .= dechex(mt_rand(0, 0x7fffffff));
+               }
+               print "<li>Warning: \$wgSecretKey key is insecure, generated with mt_rand(). Consider changing it manually.</li>\n";
+       }
+
+       # Add slashes to strings for double quoting
+       $slconf = array_map( "escapePhpString", get_object_vars( $conf ) );
+       if( $conf->License == 'gfdl' ) {
+               # Needs literal string interpolation for the current style path
+               $slconf['RightsIcon'] = $conf->RightsIcon;
+       }
+
+       $sep = (DIRECTORY_SEPARATOR == "\\") ? ";" : ":";
+       $localsettings = "
+# This file was automatically generated by the MediaWiki installer.
+# If you make manual changes, please keep track in case you need to
+# recreate them later.
+
+\$IP = \"{$slconf['IP']}\";
+ini_set( \"include_path\", \".$sep\$IP$sep\$IP/includes$sep\$IP/languages\" );
+require_once( \"includes/DefaultSettings.php\" );
+
+# If PHP's memory limit is very low, some operations may fail.
+" . ($conf->raiseMemory ? '' : '# ' ) . "ini_set( 'memory_limit', '20M' );" . "
+
+if ( \$wgCommandLineMode ) {
+       if ( isset( \$_SERVER ) && array_key_exists( 'REQUEST_METHOD', \$_SERVER ) ) {
+               die( \"This script must be run from the command line\\n\" );
+       }
+} elseif ( empty( \$wgNoOutputBuffer ) ) {
+       ## Compress output if the browser supports it
+       {$zlib}if( !ini_get( 'zlib.output_compression' ) ) @ob_start( 'ob_gzhandler' );
+}
+
+\$wgSitename         = \"{$slconf['Sitename']}\";
+
+\$wgScriptPath     = \"{$slconf['ScriptPath']}\";
+\$wgScript           = \"\$wgScriptPath/index.php\";
+\$wgRedirectScript   = \"\$wgScriptPath/redirect.php\";
+
+## If using PHP as a CGI module, use the ugly URLs
+{$pretty}\$wgArticlePath      = \"\$wgScript/\$1\";
+{$ugly}\$wgArticlePath      = \"\$wgScript?title=\$1\";
+
+\$wgStylePath        = \"\$wgScriptPath/skins\";
+\$wgStyleDirectory   = \"\$IP/skins\";
+\$wgLogo             = \"\$wgStylePath/common/images/wiki.png\";
+
+\$wgUploadPath       = \"\$wgScriptPath/images\";
+\$wgUploadDirectory  = \"\$IP/images\";
+
+\$wgEnableEmail = $enableemail;
+\$wgEnableUserEmail = $enableuseremail;
+
+\$wgEmergencyContact = \"{$slconf['EmergencyContact']}\";
+\$wgPasswordSender     = \"{$slconf['PasswordSender']}\";
+
+## For a detailed description of the following switches see
+## http://meta.wikimedia.org/Enotif and http://meta.wikimedia.org/Eauthent
+## There are many more options for fine tuning available see
+## /includes/DefaultSettings.php
+## UPO means: this is also a user preference option
+\$wgEnotifUserTalk = $enotifusertalk; # UPO
+\$wgEnotifWatchlist = $enotifwatchlist; # UPO
+\$wgEmailAuthentication = $eauthent;
+
+\$wgDBserver         = \"{$slconf['DBserver']}\";
+\$wgDBname           = \"{$slconf['DBname']}\";
+\$wgDBuser           = \"{$slconf['DBuser']}\";
+\$wgDBpassword       = \"{$slconf['DBpassword']}\";
+\$wgDBprefix         = \"{$slconf['DBprefix']}\";
+
+# If you're on MySQL 3.x, this next line must be FALSE:
+\$wgDBmysql4 = {$conf->DBmysql4};
+
+# Experimental charset support for MySQL 4.1/5.0.
+\$wgDBmysql5 = {$conf->DBmysql5};
+
+## Shared memory settings
+\$wgMainCacheType = $cacheType;
+\$wgMemCachedServers = $mcservers;
+
+## To enable image uploads, make sure the 'images' directory
+## is writable, then uncomment this:
+# \$wgEnableUploads            = true;
+\$wgUseImageResize             = {$conf->UseImageResize};
+{$magic}\$wgUseImageMagick = true;
+{$magic}\$wgImageMagickConvertCommand = \"{$convert}\";
+
+## If you want to use image uploads under safe mode,
+## create the directories images/archive, images/thumb and
+## images/temp, and make them all writable. Then uncomment
+## this, if it's not already uncommented:
+{$hashedUploads}\$wgHashedUploadDirectory = false;
+
+## If you have the appropriate support software installed
+## you can enable inline LaTeX equations:
+# \$wgUseTeX                   = true;
+\$wgMathPath         = \"{\$wgUploadPath}/math\";
+\$wgMathDirectory    = \"{\$wgUploadDirectory}/math\";
+\$wgTmpDirectory     = \"{\$wgUploadDirectory}/tmp\";
+
+\$wgLocalInterwiki   = \$wgSitename;
+
+\$wgLanguageCode = \"{$slconf['LanguageCode']}\";
+
+\$wgProxyKey = \"$secretKey\";
+
+## Default skin: you can change the default skin. Use the internal symbolic
+## names, ie 'standard', 'nostalgia', 'cologneblue', 'monobook':
+# \$wgDefaultSkin = 'monobook';
+
+## For attaching licensing metadata to pages, and displaying an
+## appropriate copyright notice / icon. GNU Free Documentation
+## License and Creative Commons licenses are supported so far.
+{$rights}\$wgEnableCreativeCommonsRdf = true;
+\$wgRightsPage = \"\"; # Set to the title of a wiki page that describes your license/copyright
+\$wgRightsUrl = \"{$slconf['RightsUrl']}\";
+\$wgRightsText = \"{$slconf['RightsText']}\";
+\$wgRightsIcon = \"{$slconf['RightsIcon']}\";
+# \$wgRightsCode = \"{$slconf['RightsCode']}\"; # Not yet used
+
+\$wgDiff3 = \"{$slconf['diff3']}\";
+";
+       // Keep things in Unix line endings internally;
+       // the system will write out as local text type.
+       return str_replace( "\r\n", "\n", $localsettings );
+}
+
+function dieout( $text ) {
+       die( $text . "\n\n</body>\n</html>" );
+}
+
+function importVar( &$var, $name, $default = "" ) {
+       if( isset( $var[$name] ) ) {
+               $retval = $var[$name];
+               if ( get_magic_quotes_gpc() ) {
+                       $retval = stripslashes( $retval );
+               }
+       } else {
+               $retval = $default;
+       }
+       return $retval;
+}
+
+function importPost( $name, $default = "" ) {
+       return importVar( $_POST, $name, $default );
+}
+
+function importRequest( $name, $default = "" ) {
+       return importVar( $_REQUEST, $name, $default );
+}
+
+function aField( &$conf, $field, $text, $type = "", $value = "" ) {
+       if( $type != "" ) {
+               $xtype = "type=\"$type\"";
+       } else {
+               $xtype = "";
+       }
+
+       if(!(isset($id)) or ($id == "") ) $id = $field;
+       $nolabel = ($type == "radio") || ($type == "hidden");
+       if( $nolabel ) {
+               echo "\t\t<label>";
+       } else {
+               echo "\t\t<label class='column' for=\"$id\">$text</label>\n";
+       }
+
+       if( $type == "radio" && $value == $conf->$field ) {
+               $checked = "checked='checked'";
+       } else {
+               $checked = "";
+       }
+       echo "\t\t<input $xtype name=\"$field\" id=\"$id\" $checked value=\"";
+       if( $type == "radio" ) {
+               echo htmlspecialchars( $value );
+       } else {
+               echo htmlspecialchars( $conf->$field );
+       }
+       echo "\" />\n";
+       if( $nolabel ) {
+               echo " $text</label>\n";
+       }
+
+       global $errs;
+       if(isset($errs[$field])) echo "<span class='error'>" . $errs[$field] . "</span>\n";
+}
+
+function getLanguageList() {
+       global $wgLanguageNames;
+       if( !isset( $wgLanguageNames ) ) {
+               $wgContLanguageCode = "xxx";
+               function wfLocalUrl( $x ) { return $x; }
+               function wfLocalUrlE( $x ) { return $x; }
+               require_once( "languages/Names.php" );
+       }
+
+       $codes = array();
+
+       $d = opendir( "../languages" );
+       while( false !== ($f = readdir( $d ) ) ) {
+               if( preg_match( '/Language([A-Z][a-z_]+)\.php$/', $f, $m ) ) {
+                       $code = str_replace( '_', '-', strtolower( $m[1] ) );
+                       if( isset( $wgLanguageNames[$code] ) ) {
+                               $name = $code . ' - ' . $wgLanguageNames[$code];
+                       } else {
+                               $name = $code;
+                       }
+                       $codes[$code] = $name;
+               }
+       }
+       closedir( $d );
+       ksort( $codes );
+       return $codes;
+}
+
+#Check for location of an executable
+# @param string $loc single location to check
+# @param array $names filenames to check for.
+# @param mixed $versioninfo array of details to use when checking version, use false for no version checking
+function locate_executable($loc, $names, $versioninfo = false) {
+       if (!is_array($names))
+               $names = array($names);
+
+       foreach ($names as $name) {
+               if (file_exists("$loc/$name")) {
+                       if (!$versioninfo)
+                               return "$loc/$name";
+
+                       $file = str_replace('$1', "$loc/$name", $versioninfo[0]);
+                       if (strstr(`$file`, $versioninfo[1]) !== false)
+                               return "$loc/$name";
+               }
+       }
+       return false;
+}
+
+# Test a memcached server
+function testMemcachedServer( $server ) {
+       $hostport = explode(":", $server);
+       $errstr = false;
+       $fp = false;
+       if ( !function_exists( 'fsockopen' ) ) {
+               $errstr = "Can't connect to memcached, fsockopen() not present";
+       }
+       if ( !$errstr &&  count( $hostport ) != 2 ) {
+               $errstr = 'Please specify host and port';
+               var_dump( $hostport );
+       }
+       if ( !$errstr ) {
+               list( $host, $port ) = $hostport;
+               $errno = 0;
+               $fsockerr = '';
+
+               $fp = @fsockopen( $host, $port, $errno, $fsockerr, 1.0 );
+               if ( $fp === false ) {
+                       $errstr = "Cannot connect to memcached on $host:$port : $fsockerr";
+               }
+       }
+       if ( !$errstr ) {
+               $command = "version\r\n";
+               $bytes = fwrite( $fp, $command );
+               if ( $bytes != strlen( $command ) ) {
+                       $errstr = "Cannot write to memcached socket on $host:$port";
+               }
+       }
+       if ( !$errstr ) {
+               $expected = "VERSION ";
+               $response = fread( $fp, strlen( $expected ) );
+               if ( $response != $expected ) {
+                       $errstr = "Didn't get correct memcached response from $host:$port";
+               }
+       }
+       if ( $fp ) {
+               fclose( $fp );
+       }
+       if ( !$errstr ) {
+               echo "<li>Connected to memcached on $host:$port successfully";
+       }
+       return $errstr;
+}
+?>
+
+</body>
+</html>
diff --git a/docs/README b/docs/README
new file mode 100644 (file)
index 0000000..2c34d7b
--- /dev/null
@@ -0,0 +1,17 @@
+[July 5th 2005]
+
+The 'docs' directory contain various text files that should help you
+understand the most importants classes in MediaWiki.
+
+API documentation is sometime generated and uploaded at:
+  http://wikipedia.sourceforge.net/doc/
+
+You can get a fresh version using 'make doc' or mwdocgen.php
+in the ../maintenance/ directory.
+
+
+
+For end user / administrators, most of the documentation
+is located online at:
+  http://meta.wikimedia.org/wiki/Help:Help
+
diff --git a/docs/deferred.txt b/docs/deferred.txt
new file mode 100644 (file)
index 0000000..445eb0e
--- /dev/null
@@ -0,0 +1,19 @@
+
+deferred.txt
+
+A few of the database updates required by various functions here
+can be deferred until after the result page is displayed to the
+user.  For example, updating the view counts, updating the
+linked-to tables after a save, etc.  PHP does not yet have any
+way to tell the server to actually return and disconnect while
+still running these updates (as a Java servelet could), but it
+might have such a feature in the future.
+
+We handle these by creating a deferred-update object (in a real
+O-O language these would be classes that implement an interface)
+and putting those objects on a global list, then executing the
+whole list after the page is displayed. We don't do anything
+smart like collating updates to the same table or such because
+the list is almost always going to have just one item on it, if
+that, so it's not worth the trouble.
+
diff --git a/docs/design.txt b/docs/design.txt
new file mode 100644 (file)
index 0000000..5fff9fd
--- /dev/null
@@ -0,0 +1,128 @@
+This is a brief overview of the new design.
+
+Primary source files/objects:
+
+  index.php
+    Main script. It creates the necessary global objects and parses
+    the URL to determine what to do, which it then generally passes
+    off to somebody else (depending on the action to be taken).
+
+    All of the functions to which it might delegate generally do
+    their job by sending content to the $wgOut object. After returning,
+    the script flushes that out by calling $wgOut->output(). If there
+    are any changes that need to be made to the database that can be
+    deferred until after page display, those happen at the end.
+
+    Note that the order in the includes is touchy; Language uses
+    some global functions, etc. Likewise with the creation of the
+    global variables. Don't move them around without some forethought.
+
+  User
+    Encapsulates the state of the user viewing/using the site.
+    Can be queried for things like the user's settings, name, etc.
+    Handles the details of getting and saving to the "user" table
+    of the database, and dealing with sessions and cookies.
+    More details in USER.TXT.
+
+  OutputPage
+    Encapsulates the entire HTML page that will be sent in
+    response to any server request. It is used by calling its
+    functions to add text, headers, etc., in any order, and then
+    calling output() to send it all. It could be easily changed
+    to send incrementally if that becomes useful, but I prefer
+    the flexibility. This should also do the output encoding.
+    The system allocates a global one in $wgOut. This class
+    also handles converting wikitext format to HTML.
+
+  Title
+    Represents the title of an article, and does all the work
+    of translating among various forms such as plain text, URL,
+    database key, etc. For convenience, and for historical
+    reasons, it also represents a few features of articles that
+    don't involve their text, such as access rights.
+
+  Article
+    Encapsulates access to the "cur" table of the database. The
+    object represents a an article, and maintains state such as
+    text (in Wikitext format), flags, etc.
+
+  Skin
+    Encapsulates a "look and feel" for the wiki. All of the
+    functions that render HTML, and make choices about how to
+    render it, are here, and are called from various other
+    places when needed (most notably, OutputPage::addWikiText()).
+    The StandardSkin object is a complete implementation, and is
+    meant to be subclassed with other skins that may override
+    some of its functions. The User object contains a reference
+    to a skin (according to that user's preference), and so
+    rather than having a global skin object we just rely on the
+    global User and get the skin with $wgUser->getSkin().
+
+  Language
+    Represents the language used for incidental text, and also
+    has some character encoding functions and other locale stuff.
+    A global one is allocated in $wgLang.
+
+  LinkCache
+    Keeps information on existence of articles. See LINKCACHE.TXT.
+
+Naming/coding conventions:
+
+  These are meant to be descriptive, not dictatorial; I won't
+  presume to tell you how to program, I'm just describing the
+  methods I chose to use for myself. If you do choose to
+  follow these guidelines, it will probably be easier for you
+  to collaborate with others on the project, but if you want
+  to contribute without bothering, by all means do so (and don't
+  be surprised if I reformat your code).
+
+  - I have the code indented with tabs to save file size and
+    so that users can set their tab stops to any depth they like.
+    I use 4-space tab stops, which work well. I also use K&R brace
+    matching style. I know that's a religious issue for some,
+    so if you want to use a style that puts opening braces on the
+    next line, that's OK too, but please don't use a style where
+    closing braces don't align with either the opening brace on
+    its own line or the statement that opened the block--that's
+    confusing as hell.
+
+  - PHP doesn't have "private" member variables of functions,
+    so I've used the comment "/* private */" in some places to
+    indicate my intent. Don't access things marked that way
+    from outside the class def--use the accessor functions (or
+    make your own if you need them). Yes, even some globals
+    are marked private, because PHP is broken and doesn't
+    allow static class variables.
+
+  - Member variables are generally "mXxx" to distinguish them.
+    This should make it easier to spot errors of forgetting the
+    required "$this->", which PHP will happily accept by creating
+    a new local variable rather than complaining.
+
+  - Globals are particularly evil in PHP; it sets a lot of them
+    automatically from cookies, query strings, and such, leading to
+    namespace conflicts; when a variable name is used in a function,
+    it is silently declared as a new local masking the global, so
+    you'll get weird error because you forgot the global declaration;
+    lack of static class member variables means you have to use
+    globals for them, etc. Evil, evil.
+
+    I think I've managed to pare down the number of globals we use
+    to a scant few dozen or so, and I've prefixed them all with "wg"
+    so you can spot errors better (odds are, if you see a "wg"
+    variable being used in a function that doesn't declare it global,
+    that's probably an error).
+
+    Other conventions: Top-level functions are wfFuncname(), names
+    of session variables are wsName, cookies wcName, and form field
+    values wpName ("p" for "POST").
+
+  - Be kind to your release manager and don't use CVS keywords (Id,
+    Revision, etc.) to mark file versions. They make merging code
+    between different branches a pain for CVS, and are kind of sketchy
+    for versions after that. (Yes, you can use the '-kk' flag so that
+    merges ignore keywords, but that messes up binary  files. See
+    https://www.cvshome.org/docs/manual/cvs-1.11.18/cvs_5.html#SEC64).
+    
+
+    
diff --git a/docs/export-0.1.xsd b/docs/export-0.1.xsd
new file mode 100644 (file)
index 0000000..0b3eb17
--- /dev/null
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+       This is an XML Schema description of the format
+       output by MediaWiki's Special:Export system.
+       
+       The canonical URL to the schema document is:
+       http://www.mediawiki.org/xml/export-0.1.xsd
+       
+       Use the namespace:
+       http://www.mediawiki.org/xml/export-0.1/
+-->
+<schema xmlns="http://www.w3.org/2001/XMLSchema"
+        xmlns:mw="http://www.mediawiki.org/xml/export-0.1/"
+        targetNamespace="http://www.mediawiki.org/xml/export-0.1/"
+        elementFormDefault="qualified">
+
+       <annotation>
+               <documentation xml:lang="en">
+                       MediaWiki's page export format
+               </documentation>
+       </annotation>
+       
+       <!-- Need this to reference xml:lang -->
+       <import namespace="http://www.w3.org/XML/1998/namespace"
+               schemaLocation="http://www.w3.org/2001/xml.xsd"/>
+       
+       <!-- Our root element -->
+       <element name="mediawiki" type="mw:MediaWikiType"/>
+       
+       <complexType name="MediaWikiType">
+               <sequence>
+                       <element name="page" type="mw:PageType"
+                               minOccurs="0" maxOccurs="unbounded"/>
+               </sequence>
+               <attribute name="version" type="string" use="required"/>
+               <attribute ref="xml:lang" use="required"/>
+       </complexType>
+       
+       <complexType name="PageType">
+               <sequence>
+                       <!-- Title in text form. (Using spaces, not underscores; with namespace ) -->
+                       <element name="title" type="string"/>
+                       
+                       <!-- optional page ID number -->
+                       <element name="id" type="positiveInteger" minOccurs="0"/>
+                       
+                       <!-- comma-separated list of string tokens, if present -->
+                       <element name="restrictions" type="string" minOccurs="0"/>
+                       
+                       <!-- Zero or more sets of revision data -->
+                       <element name="revision" type="mw:RevisionType"
+                               minOccurs="0" maxOccurs="unbounded"/>
+               </sequence>
+       </complexType>
+       
+       <complexType name="RevisionType">
+               <sequence>
+                       <element name="id" type="positiveInteger" minOccurs="0"/>
+                       <element name="timestamp" type="dateTime"/>
+                       <element name="contributor" type="mw:ContributorType"/>
+                       <element name="minor" minOccurs="0" />
+                       <element name="comment" type="string" minOccurs="0"/>
+                       <element name="text" type="string"/>
+               </sequence>
+       </complexType>
+       
+       <complexType name="ContributorType">
+               <sequence>
+                       <element name="username" type="string" minOccurs="0"/>
+                       <element name="id" type="positiveInteger" minOccurs="0" />
+                       
+                       <element name="ip" type="string" minOccurs="0"/>
+               </sequence>
+       </complexType>
+
+</schema>
diff --git a/docs/export-0.2.xsd b/docs/export-0.2.xsd
new file mode 100644 (file)
index 0000000..8acbf54
--- /dev/null
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+       This is an XML Schema description of the format
+       output by MediaWiki's Special:Export system.
+       
+       Version 0.2 adds optional basic file upload info support,
+       which is used by our OAI export/import submodule.
+       
+       The canonical URL to the schema document is:
+       http://www.mediawiki.org/xml/export-0.2.xsd
+       
+       Use the namespace:
+       http://www.mediawiki.org/xml/export-0.2/
+-->
+<schema xmlns="http://www.w3.org/2001/XMLSchema"
+        xmlns:mw="http://www.mediawiki.org/xml/export-0.2/"
+        targetNamespace="http://www.mediawiki.org/xml/export-0.2/"
+        elementFormDefault="qualified">
+
+       <annotation>
+               <documentation xml:lang="en">
+                       MediaWiki's page export format
+               </documentation>
+       </annotation>
+       
+       <!-- Need this to reference xml:lang -->
+       <import namespace="http://www.w3.org/XML/1998/namespace"
+               schemaLocation="http://www.w3.org/2001/xml.xsd"/>
+       
+       <!-- Our root element -->
+       <element name="mediawiki" type="mw:MediaWikiType"/>
+       
+       <complexType name="MediaWikiType">
+               <sequence>
+                       <element name="page" type="mw:PageType"
+                               minOccurs="0" maxOccurs="unbounded"/>
+               </sequence>
+               <attribute name="version" type="string" use="required"/>
+               <attribute ref="xml:lang" use="required"/>
+       </complexType>
+       
+       <complexType name="PageType">
+               <sequence>
+                       <!-- Title in text form. (Using spaces, not underscores; with namespace ) -->
+                       <element name="title" type="string"/>
+                       
+                       <!-- optional page ID number -->
+                       <element name="id" type="positiveInteger" minOccurs="0"/>
+                       
+                       <!-- comma-separated list of string tokens, if present -->
+                       <element name="restrictions" type="string" minOccurs="0"/>
+                       
+                       <!-- Zero or more sets of revision or upload data -->
+                       <choice minOccurs="0" maxOccurs="unbounded">
+                               <element name="revision" type="mw:RevisionType" />
+                               <element name="upload" type="mw:UploadType" />
+                       </choice>
+               </sequence>
+       </complexType>
+       
+       <complexType name="RevisionType">
+               <sequence>
+                       <element name="id" type="positiveInteger" minOccurs="0"/>
+                       <element name="timestamp" type="dateTime"/>
+                       <element name="contributor" type="mw:ContributorType"/>
+                       <element name="minor" minOccurs="0" />
+                       <element name="comment" type="string" minOccurs="0"/>
+                       <element name="text" type="string"/>
+               </sequence>
+       </complexType>
+       
+       <complexType name="ContributorType">
+               <sequence>
+                       <element name="username" type="string" minOccurs="0"/>
+                       <element name="id" type="positiveInteger" minOccurs="0" />
+                       
+                       <element name="ip" type="string" minOccurs="0"/>
+               </sequence>
+       </complexType>
+       
+       <complexType name="UploadType">
+               <sequence>
+                       <!-- Revision-style data... -->
+                       <element name="timestamp" type="dateTime"/>
+                       <element name="contributor" type="mw:ContributorType"/>
+                       <element name="comment" type="string" minOccurs="0"/>
+                       
+                       <!-- Filename. (Using underscores, not spaces. No 'Image:' namespace marker.) -->
+                       <element name="filename" type="string"/>
+                       
+                       <!-- URI at which this resource can be obtained -->
+                       <element name="src" type="anyURI"/>
+                       
+                       <element name="size" type="positiveInteger" />
+                       
+                       <!-- TODO: add other metadata fields -->
+               </sequence>
+       </complexType>
+       
+</schema>
diff --git a/docs/export-0.3.xsd b/docs/export-0.3.xsd
new file mode 100644 (file)
index 0000000..1e0b7c8
--- /dev/null
@@ -0,0 +1,154 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+       This is an XML Schema description of the format
+       output by MediaWiki's Special:Export system.
+       
+       Version 0.2 adds optional basic file upload info support,
+       which is used by our OAI export/import submodule.
+       
+       Version 0.3 adds some site configuration information such
+       as a list of defined namespaces.
+       
+       The canonical URL to the schema document is:
+       http://www.mediawiki.org/xml/export-0.3.xsd
+       
+       Use the namespace:
+       http://www.mediawiki.org/xml/export-0.3/
+-->
+<schema xmlns="http://www.w3.org/2001/XMLSchema"
+        xmlns:mw="http://www.mediawiki.org/xml/export-0.3/"
+        targetNamespace="http://www.mediawiki.org/xml/export-0.3/"
+        elementFormDefault="qualified">
+
+       <annotation>
+               <documentation xml:lang="en">
+                       MediaWiki's page export format
+               </documentation>
+       </annotation>
+       
+       <!-- Need this to reference xml:lang -->
+       <import namespace="http://www.w3.org/XML/1998/namespace"
+               schemaLocation="http://www.w3.org/2001/xml.xsd"/>
+       
+       <!-- Our root element -->
+       <element name="mediawiki" type="mw:MediaWikiType"/>
+       
+       <complexType name="MediaWikiType">
+               <sequence>
+                       <element name="siteinfo" type="mw:SiteInfoType"
+                               minOccurs="0" maxOccurs="1"/>
+                       <element name="page" type="mw:PageType"
+                               minOccurs="0" maxOccurs="unbounded"/>
+               </sequence>
+               <attribute name="version" type="string" use="required"/>
+               <attribute ref="xml:lang" use="required"/>
+       </complexType>
+       
+       <complexType name="SiteInfoType">
+               <sequence>
+                       <element name="sitename" type="string" minOccurs="0" />
+                       <element name="base" type="anyURI" minOccurs="0" />
+                       <element name="generator" type="string" minOccurs="0" />
+                       <element name="case" type="mw:CaseType" minOccurs="0" />
+                       <element name="namespaces" type="mw:NamespacesType" minOccurs="0" />
+               </sequence>
+       </complexType>
+       
+       <simpleType name="CaseType">
+               <restriction base="NMTOKEN">
+                       <!-- Cannot have two titles differing only by case of first letter. -->
+                       <!-- Default behavior through 1.5, $wgCapitalLinks = true -->
+                       <enumeration value="first-letter" />
+                       
+                       <!-- Complete title is case-sensitive -->
+                       <!-- Behavior when $wgCapitalLinks = false -->
+                       <enumeration value="case-sensitive" />
+                       
+                       <!-- Cannot have two titles differing only by case. -->
+                       <!-- Not yet implemented as of MediaWiki 1.5 -->
+                       <enumeration value="case-insensitive" />
+               </restriction>
+       </simpleType>
+       
+       <complexType name="NamespacesType">
+               <sequence>
+                       <element name="namespace" type="mw:NamespaceType"
+                               minOccurs="0" maxOccurs="unbounded" />
+               </sequence>
+       </complexType>
+       
+       <complexType name="NamespaceType">
+               <simpleContent>
+                       <extension base="string">
+                               <attribute name="key" type="integer" />
+                       </extension>
+               </simpleContent>
+       </complexType>
+       
+       <complexType name="PageType">
+               <sequence>
+                       <!-- Title in text form. (Using spaces, not underscores; with namespace ) -->
+                       <element name="title" type="string"/>
+                       
+                       <!-- optional page ID number -->
+                       <element name="id" type="positiveInteger" minOccurs="0"/>
+                       
+                       <!-- comma-separated list of string tokens, if present -->
+                       <element name="restrictions" type="string" minOccurs="0"/>
+                       
+                       <!-- Zero or more sets of revision or upload data -->
+                       <choice minOccurs="0" maxOccurs="unbounded">
+                               <element name="revision" type="mw:RevisionType" />
+                               <element name="upload" type="mw:UploadType" />
+                       </choice>
+               </sequence>
+       </complexType>
+       
+       <complexType name="RevisionType">
+               <sequence>
+                       <element name="id" type="positiveInteger" minOccurs="0"/>
+                       <element name="timestamp" type="dateTime"/>
+                       <element name="contributor" type="mw:ContributorType"/>
+                       <element name="minor" minOccurs="0" />
+                       <element name="comment" type="string" minOccurs="0"/>
+                       <element name="text" type="mw:TextType" />
+               </sequence>
+       </complexType>
+       
+       <complexType name="TextType">
+               <simpleContent>
+                       <extension base="string">
+                               <attribute ref="xml:space" use="optional" default="preserve" />
+                       </extension>
+               </simpleContent>
+       </complexType>
+       
+       <complexType name="ContributorType">
+               <sequence>
+                       <element name="username" type="string" minOccurs="0"/>
+                       <element name="id" type="positiveInteger" minOccurs="0" />
+                       
+                       <element name="ip" type="string" minOccurs="0"/>
+               </sequence>
+       </complexType>
+       
+       <complexType name="UploadType">
+               <sequence>
+                       <!-- Revision-style data... -->
+                       <element name="timestamp" type="dateTime"/>
+                       <element name="contributor" type="mw:ContributorType"/>
+                       <element name="comment" type="string" minOccurs="0"/>
+                       
+                       <!-- Filename. (Using underscores, not spaces. No 'Image:' namespace marker.) -->
+                       <element name="filename" type="string"/>
+                       
+                       <!-- URI at which this resource can be obtained -->
+                       <element name="src" type="anyURI"/>
+                       
+                       <element name="size" type="positiveInteger" />
+                       
+                       <!-- TODO: add other metadata fields -->
+               </sequence>
+       </complexType>
+       
+</schema>
diff --git a/docs/export-demo.xml b/docs/export-demo.xml
new file mode 100644 (file)
index 0000000..1b4bd7c
--- /dev/null
@@ -0,0 +1,115 @@
+<mediawiki xmlns="http://www.mediawiki.org/xml/export-0.3/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.3/ http://www.mediawiki.org/xml/export-0.3.xsd" version="0.3" xml:lang="en">
+
+<!-- Optional global configuration info -->
+<siteinfo>
+  <!-- Site name, as set in $wgSitename -->
+  <sitename>DemoWiki</sitename>
+  
+  <!-- Forgot where you got this set? -->
+  <base>http://example.com/wiki/Main_Page</base>
+  
+  <!-- Source software version -->
+  <generator>MediaWiki 1.5.0</generator>
+  
+  <!-- Title case sensitivity options of the wiki this data came from -->
+  <!-- May be 'first-letter', 'case-sensitive', or 'case-insensitive' -->
+  <case>first-letter</case>
+  
+  <!-- Defined namespace keys on the source wiki. -->
+  <!-- Titles can be substring-split to obtain the symbolic numeric key -->
+  <namespaces>
+    <namespace key="-2">Media</namespace>
+    <namespace key="-1">Special</namespace>
+    <namespace key="0"></namespace>
+    <namespace key="1">Talk</namespace>
+    <namespace key="2">User</namespace>
+    <namespace key="3">User talk</namespace>
+    <namespace key="4">DemoWiki</namespace>
+    <namespace key="5">DemoWIki talk</namespace>
+    <namespace key="6">Image</namespace>
+    <namespace key="7">Image talk</namespace>
+    <namespace key="8">MediaWiki</namespace>
+    <namespace key="9">MediaWiki talk</namespace>
+    <namespace key="10">Template</namespace>
+    <namespace key="11">Template talk</namespace>
+    <namespace key="12">Help</namespace>
+    <namespace key="13">Help talk</namespace>
+    <namespace key="14">Category</namespace>
+    <namespace key="15">Category talk</namespace>
+  </namespaces>
+</siteinfo>
+
+<!-- The rest of the data will be a series of page records -->
+<page>
+  <!-- Titles are listed here in text form, with namespace prefix   -->
+  <!-- if any, and spaces rather than the underscores used in URLs. -->
+  <title>Page title</title>
+  
+  <!-- The page's immutable page_id number in the source database.  -->
+  <!-- Page ID numbers are kept across page moves, but may change   -->
+  <!-- if a page is deleted and recreated.                          -->
+  <id>1</id>
+  
+  <!-- If restricted, the ACL is listed here raw. -->
+  <restrictions>edit=sysop:move=sysop</restrictions>
+  
+  <!-- With a series of revision records... -->
+  
+  <!-- Remember this is XML; if you must use a regex-based extractor -->
+  <!-- in place of a standard XML parser, be very careful.           -->
+  <!-- * Don't forget to decode character entities!                  -->
+  <!-- * If using a 'loose' XML parser, ensure that whitespace is    -->
+  <!--    preserved in the <text> elements.                          -->
+  <revision>
+    <!-- Unique revision ID number (rev_id) in the source database.  -->
+    <!-- This number uniquely identifies the revision on that wiki.  -->
+    <id>100</id>
+    
+    <timestamp>2001-01-15T13:15:00Z</timestamp>
+    <contributor><username>Foobar</username><id>42</id></contributor>
+    <minor />
+    <comment>I have just one thing to say!</comment>
+    <text xml:space="preserve">A bunch of [[text]] here.</text>
+  </revision>
+  
+  <revision>
+    <timestamp>2001-01-15T13:10:27Z</timestamp>
+    <contributor><ip>10.0.0.2</ip></contributor>
+    <comment>new!</comment>
+    <text xml:space="preserve">An earlier [[revision]].</text>
+  </revision>
+</page>
+
+<page>
+  <title>Talk:Page title</title>
+  <id>2</id>
+  <revision>
+    <id>101</id>
+    <timestamp>2001-01-15T14:03:00Z</timestamp>
+    <contributor><ip>10.0.0.2</ip></contributor>
+    <comment>hey</comment>
+    <text xml:space="preserve">WHYD YOU LOCK PAGE??!!! i was editing that jerk</text>
+  </revision>
+</page>
+
+<page>
+  <title>Image:Some image.jpg</title>
+  <id>3</id>
+  <revision>
+    <id>102</id>
+    <timestamp>2001-01-15T20:34:12Z</timestamp>
+    <contributor><username>Foobar</username><id>42</id></contributor>
+    <comment>My awesomeest image!</comment>
+    <text xml:space="preserve">This is an awesome little imgae. I lurves it. {{PD}}</text>
+  </revision>
+  <upload>
+    <timestamp>2001-01-15T20:34:12Z</timestamp>
+    <contributor><username>Foobar</username><id>42</id></contributor>
+    <comment>My awesomeest image!</comment>
+    <filename>Some_image.jpg</filename>
+    <src>http://upload.wikimedia.org/commons/2/22/Some_image.jpg</src>
+    <size>12345</size>
+  </upload>
+</page>
+
+</mediawiki>
diff --git a/docs/globals.txt b/docs/globals.txt
new file mode 100644 (file)
index 0000000..519b416
--- /dev/null
@@ -0,0 +1,29 @@
+globals.txt
+
+PHP loves globals. I hate them. This is not a great
+combination, but I manage. I could get rid of most of
+them by having a single "HTTP request" object, and using
+it to hold everything that's now global (which is exactly
+what I'd do in a Java servlet). But that's really
+awkward in PHP, and wouldn't really provide much benefit
+in readability or maintainability, so I go with the flow
+of PHP and use globals.  Here's documentation on the
+important globals used by the system.
+
+$wgOut
+       OutputPage object for HTTP response.
+
+$wgTitle
+       Title object created from the request URL.
+
+$wgLang
+       Language object for this request.
+
+$wgArticle
+       Article object corresponsing to $wgTitle.
+
+$wgLinkCache
+       LinkCache object.
+
+...
+
diff --git a/docs/hooks.txt b/docs/hooks.txt
new file mode 100644 (file)
index 0000000..8161437
--- /dev/null
@@ -0,0 +1,369 @@
+hooks.txt
+
+This document describes how event hooks work in MediaWiki; how to add
+hooks for an event; and how to run hooks for an event.
+
+==Glossary==
+
+event
+     Something that happens with the wiki. For example: a user logs
+     in. A wiki page is saved. A wiki page is deleted. Often there are
+     two events associated with a single action: one before the code
+     is run to make the event happen, and one after. Each event has a
+     name, preferably in CamelCase. For example, 'UserLogin',
+     'ArticleSave', 'ArticleSaveComplete', 'ArticleDelete'.
+
+hook
+     A clump of code and data that should be run when an event
+     happens. This can be either a function and a chunk of data, or an
+     object and a method.
+     
+hook function
+     The function part of a hook.
+     
+==Rationale==
+
+Hooks allow us to decouple optionally-run code from code that is run
+for everyone. It allows MediaWiki hackers, third-party developers and
+local administrators to define code that will be run at certain points
+in the mainline code, and to modify the data run by that mainline
+code. Hooks can keep mainline code simple, and make it easier to
+write extensions. Hooks are a principled alternative to local patches.
+
+Consider, for example, two options in MediaWiki. One reverses the
+order of a title before displaying the article; the other converts the
+title to all uppercase letters. Currently, in MediaWiki code, we
+would handle this as follows (note: not real code, here):
+
+    function showAnArticle($article) {
+        global $wgReverseTitle, $wgCapitalizeTitle;
+       
+       if ($wgReverseTitle) {
+           wfReverseTitle($article);
+        }
+       
+       if ($wgCapitalizeTitle) {
+          wfCapitalizeTitle($article);
+        }
+       
+       # code to actually show the article goes here
+    }
+    
+An extension writer, or a local admin, will often add custom code to
+the function -- with or without a global variable. For example,
+someone wanting email notification when an article is shown may add:
+
+    function showAnArticle($article) {
+        global $wgReverseTitle, $wgCapitalizeTitle;
+       
+       if ($wgReverseTitle) {
+           wfReverseTitle($article);
+        }
+       
+       if ($wgCapitalizeTitle) {
+          wfCapitalizeTitle($article);
+        }
+
+       # code to actually show the article goes here
+       
+       if ($wgNotifyArticle) {
+          wfNotifyArticleShow($article));
+        }
+    }
+
+Using a hook-running strategy, we can avoid having all this
+option-specific stuff in our mainline code. Using hooks, the function
+becomes:
+
+    function showAnArticle($article) {
+
+       if (wfRunHooks('ArticleShow', array(&$article))) {
+       
+           # code to actually show the article goes here
+           
+           wfRunHooks('ArticleShowComplete', array(&$article));
+       }
+    }
+
+We've cleaned up the code here by removing clumps of weird,
+infrequently used code and moving them off somewhere else. It's much
+easier for someone working with this code to see what's _really_ going
+on, and make changes or fix bugs.
+
+In addition, we can take all the code that deals with the little-used
+title-reversing options (say) and put it in one place. Instead of
+having little title-reversing if-blocks spread all over the codebase
+in showAnArticle, deleteAnArticle, exportArticle, etc., we can
+concentrate it all in an extension file:
+
+    function reverseArticleTitle($article) {
+        # ...
+    }
+
+    function reverseForExport($article) {
+        # ...
+    }
+
+The setup function for the extension just has to add its hook
+functions to the appropriate events:
+
+    setupTitleReversingExtension() {
+        global $wgHooks;
+       
+       $wgHooks['ArticleShow'][] = 'reverseArticleTitle';
+       $wgHooks['ArticleDelete'][] = 'reverseArticleTitle';
+       $wgHooks['ArticleExport'][] = 'reverseForExport';
+    }
+
+Having all this code related to the title-reversion option in one
+place means that it's easier to read and understand; you don't have to
+do a grep-find to see where the $wgReverseTitle variable is used, say.
+
+If the code is well enough isolated, it can even be excluded when not
+used -- making for some slight savings in memory and load-up
+performance at runtime. Admins who want to have all the reversed
+titles can add:
+
+    require_once('extensions/ReverseTitle.php');
+    
+...to their LocalSettings.php file; those of us who don't want or need
+it can just leave it out.
+
+The extensions don't even have to be shipped with MediaWiki; they
+could be provided by a third-party developer or written by the admin
+him/herself.
+
+==Writing hooks==
+
+A hook is a chunk of code run at some particular event. It consists of:
+
+  * a function with some optional accompanying data, or
+  * an object with a method and some optional accompanying data.
+
+Hooks are registered by adding them to the global $wgHooks array for a
+given event. All the following are valid ways to define hooks:
+
+      $wgHooks['EventName'][] = 'someFunction'; # function, no data
+      $wgHooks['EventName'][] = array('someFunction', $someData);
+      $wgHooks['EventName'][] = array('someFunction'); # weird, but OK
+      
+      $wgHooks['EventName'][] = $object; # object only
+      $wgHooks['EventName'][] = array($object, 'someMethod');
+      $wgHooks['EventName'][] = array($object, 'someMethod', $someData);
+      $wgHooks['EventName'][] = array($object); # weird but OK
+
+When an event occurs, the function (or object method) will be called
+with the optional data provided as well as event-specific parameters.
+The above examples would result in the following code being executed
+when 'EventName' happened:
+
+      # function, no data
+      someFunction($param1, $param2)
+      # function with data
+      someFunction($someData, $param1, $param2)
+
+      # object only
+      $object->onEventName($param1, $param2)
+      # object with method
+      $object->someMethod($param1, $param2)
+      # object with method and data
+      $object->someMethod($someData, $param1, $param2)
+      
+Note that when an object is the hook, and there's no specified method,
+the default method called is 'onEventName'. For different events this
+would be different: 'onArticleSave', 'onUserLogin', etc.
+
+The extra data is useful if we want to use the same function or object
+for different purposes. For example:
+
+      $wgHooks['ArticleSaveComplete'][] = array('ircNotify', 'TimStarling');
+      $wgHooks['ArticleSaveComplete'][] = array('ircNotify', 'brion');
+
+This code would result in ircNotify being run twice when an article is
+saved: once for 'TimStarling', and once for 'brion'.
+
+Hooks can return three possible values:
+
+  * true: the hook has operated successfully
+  * "some string": an error occurred; processing should
+         stop and the error should be shown to the user
+  * false: the hook has successfully done the work
+          necessary and the calling function should skip
+       
+The last result would be for cases where the hook function replaces
+the main functionality. For example, if you wanted to authenticate
+users to a custom system (LDAP, another PHP program, whatever), you
+could do:
+
+    $wgHooks['UserLogin'][] = array('ldapLogin', $ldapServer);
+                               
+    function ldapLogin($username, $password) {
+        # log user into LDAP
+       return false;
+    }
+
+Returning false makes less sense for events where the action is
+complete, and will normally be ignored.
+
+==Using hooks==
+
+A calling function or method uses the wfRunHooks() function to run
+the hooks related to a particular event, like so:
+
+    class Article { 
+        # ...
+       function protect() {
+           global $wgUser;
+           if (wfRunHooks('ArticleProtect', array(&$this, &$wgUser))) {
+               # protect the article
+               wfRunHooks('ArticleProtectComplete', array(&$this, &$wgUser));
+           }
+       }
+                                                   
+wfRunHooks() returns true if the calling function should continue
+processing (the hooks ran OK, or there are no hooks to run), or false
+if it shouldn't (an error occurred, or one of the hooks handled the
+action already). Checking the return value matters more for "before"
+hooks than for "complete" hooks.
+
+Note that hook parameters are passed in an array; this is a necessary
+inconvenience to make it possible to pass reference values (that can
+be changed) into the hook code. Also note that earlier versions of
+wfRunHooks took a variable number of arguments; the array() calling
+protocol came about after MediaWiki 1.4rc1.
+
+==Events and parameters==
+
+This is a list of known events and parameters; please add to it if
+you're going to add events to the MediaWiki code.
+
+'AbortNewAccount': Prior to user account creation
+$user: User object representing the account to be created
+$abortError: Error message that will be passed back to the form if
+account creation is cancelled
+
+'AddNewAccount': after a user account is created
+null: This hook passes null as an argument
+
+'ArticleDelete': before an article is deleted
+$article: the article (object) being deleted
+$user: the user (object) deleting the article
+$reason: the reason (string) the article is being deleted
+
+'ArticleDeleteComplete': after an article is deleted
+$article: the article that was deleted
+$user: the user that deleted the article
+$reason: the reason the article was deleted
+
+'ArticleProtect': before an article is protected
+$article: the article being protected
+$user: the user doing the protection
+$protect: boolean whether this is a protect or an unprotect
+$reason: Reason for protect
+$moveonly: boolean whether this is for move only or not
+
+'ArticleProtectComplete': after an article is protected
+$article: the article that was protected
+$user: the user who did the protection
+$protect: boolean whether it was a protect or an unprotect
+$reason: Reason for protect
+$moveonly: boolean whether it was for move only or not
+
+'ArticleSave': before an article is saved
+$article: the article (object) being saved
+$user: the user (object) saving the article
+$text: the new article text
+$summary: the article summary (comment)
+$isminor: minor flag
+$iswatch: watch flag
+$section: section #
+
+'ArticleSaveComplete': after an article is saved
+$article: the article (object) saved
+$user: the user (object) who saved the article
+$text: the new article text
+$summary: the article summary (comment)
+$isminor: minor flag
+$iswatch: watch flag
+$section: section #
+
+'AutoAuthenticate': called to authenticate users on external/environmental means
+$user: writes user object to this parameter
+
+'BlockIp': before an IP address or user is blocked
+$block: the Block object about to be saved
+$user: the user _doing_ the block (not the one being blocked)
+
+'BlockIpComplete': after an IP address or user is blocked
+$block: the Block object that was saved
+$user: the user who did the block (not the one being blocked)
+
+'EmailUser': before sending email from one user to another
+$to: address of receiving user
+$from: address of sending user
+$subject: subject of the mail
+$text: text of the mail
+
+'EmailUserComplete': after sending email from one user to another
+$to: address of receiving user
+$from: address of sending user
+$subject: subject of the mail
+$text: text of the mail
+
+'LogPageValidTypes': action being logged.
+$type: array of strings
+
+'LogPageLogName': name of the logging page(s).
+$typeText: array of strings
+
+'LogPageLogHeader': strings used by wfMsg as a header.
+$headerText: array of strings
+
+'TitleMoveComplete': after moving an article (title)
+$old: old title
+$nt: new title
+$user: user who did the move
+$pageid: database ID of the page that's been moved
+$redirid: database ID of the created redirect
+
+'UnknownAction': An unknown "action" has occured (useful for defining
+                your own actions)
+$action: action name
+$article: article "acted on"
+
+'UnwatchArticle': before a watch is removed from an article
+$user: user watching
+$article: article object to be removed
+
+'UnwatchArticle': after a watch is removed from an article
+$user: user that was watching
+$article: article object removed
+
+'UserLoginComplete': after a user has logged in
+$user: the user object that was created on login
+                   
+'UserLogout': before a user logs out
+$user: the user object that is about to be logged out
+       
+'UserLogoutComplete': after a user has logged out
+$user: the user object _after_ logout (won't have name, ID, etc.)
+                     
+'WatchArticle': before a watch is added to an article
+$user: user that will watch
+$article: article object to be watched
+
+'WatchArticleComplete': after a watch is added to an article
+$user: user that watched
+$article: article object watched
+
+'CategoryPageView': before viewing a categorypage in CategoryPage::view
+$catpage: CategoryPage instance
+
+'SkinTemplateContentActions': after building the $content_action array right
+                              before returning it, see content_action.php in
+                             the extension module for a demonstration of how
+                             to use this hook.
+$content_actions: The array of content actions
+
+
+More hooks might not be available but undocumented.
diff --git a/docs/html/.cvsignore b/docs/html/.cvsignore
new file mode 100644 (file)
index 0000000..36e8474
--- /dev/null
@@ -0,0 +1,5 @@
+*.html
+media
+MediaWiki
+memcached-client
+UtfNormal
diff --git a/docs/html/README b/docs/html/README
new file mode 100644 (file)
index 0000000..d25b803
--- /dev/null
@@ -0,0 +1,4 @@
+This directory is for the auto-generated phpdoc documentation.
+Run 'php mwdocgen.php' in the maintenance subdirectory to build the docs.
+
+Get phpDocumentor from http://phpdoc.org/
diff --git a/docs/language.txt b/docs/language.txt
new file mode 100644 (file)
index 0000000..9d6a0db
--- /dev/null
@@ -0,0 +1,24 @@
+language.txt
+
+The Language object handles all readable text produced by the
+software. The most used function is getMessage(), usually
+called with the wrapper function wfMsg() which calls that method
+on the global language object. It just returns a piece of text
+given a text key. It is recommended that you use each key only
+once--bits of text in different contexts that happen to be
+identical in English may not be in other languages, so it's
+better to add new keys than to reuse them a lot. Likewise,
+if there is text that gets combined with things like names and
+titles, it is better to put markers like "$1" inside a piece
+of text and use str_replace() than to compose such messages in
+code, because their order may change in other languages too.
+
+While the system is running, there will be one global language
+object, which will be a subtype of Language. The methods in
+these objects will return the native text requested if available,
+otherwise they fall back to sending English text (which is why
+the LanguageEn object has no code at all--it just inherits the
+English defaults of the Language base class).
+
+The names of the namespaces are also contained in the language
+object, though the numbers are fixed.
diff --git a/docs/linkcache.txt b/docs/linkcache.txt
new file mode 100644 (file)
index 0000000..ab36587
--- /dev/null
@@ -0,0 +1,31 @@
+linkcache.txt
+
+The LinkCache class maintains a list of article titles and
+the information about whether or not the article exists in
+the database. This is used to mark up links when displaying
+a page. If the same link appears more than once on any page,
+then it only has to be looked up once.
+
+In practice, what happens is that the global cache object
+$wgLinkCache is consulted and updated every time the function
+getArticleID() from Title is called.
+
+This has a side benefit that we take advantage of. We have
+tables "links" and "brokenlinks" which we use to do things
+like the Orphans page and Whatlinkshere page. It just so
+happens that after we update a page, we display it--and as
+we're displaying it, we look up all the links on that page,
+causing them to be put into the cache. That information is
+exactly what we need to update those two tables. So, we do
+something tricky when we update pages: just after the update
+and before we display, we clear the cache. Then we display
+the updated page. Finally, we put a LinksUpdate object onto
+the deferred updates list, which fetches its information from
+the cache.
+
+There's a minor complication: displaying a page also looks up
+a few things like the talk page link in the quick bar and the
+date links. Since we don't want those in the link tables, we
+must take care to suspend the cache while we look those up.
+Skin.php does exactly that--see dateLink(), for example.
+
diff --git a/docs/memcached.txt b/docs/memcached.txt
new file mode 100644 (file)
index 0000000..6752e9c
--- /dev/null
@@ -0,0 +1,132 @@
+memcached support for MediaWiki:
+
+From ca August 2003, MediaWiki has optional support for memcached, a
+"high-performance, distributed memory object caching system".
+For general information on it, see: http://www.danga.com/memcached/
+
+Memcached is likely more trouble than a small site will need, but
+for a larger site with heavy load, like Wikipedia, it should help
+lighten the load on the database servers by caching data and objects
+in memory.
+
+== Requirements ==
+
+* PHP must be compiled with --enable-sockets
+
+* libevent: http://www.monkey.org/~provos/libevent/
+  (as of 2003-08-11, 0.7a is current)
+
+* optionally, epoll-rt patch for Linux kernel:
+  http://www.xmailserver.org/linux-patches/nio-improve.html
+
+* memcached: http://www.danga.com/memcached/download.bml
+  (as of this writing, 1.1.9 is current)
+  
+Memcached and libevent are under BSD-style licenses.
+
+The server should run on Linux and other Unix-like systems... you
+can run multiple servers on one machine or on multiple machines on
+a network; storage can be distributed across multiple servers, and
+multiple web servers can use the same cache cluster.
+
+
+********************* W A R N I N G ! ! ! ! ! ***********************
+Memcached has no security or authentication. Please ensure that your
+server is appropriately firewalled, and that the port(s) used for
+memcached servers are not publicly accessible. Otherwise, anyone on
+the internet can put data into and read data from your cache.
+
+An attacker familiar with MediaWiki internals could use this to give
+themselves developer access and delete all data from the wiki's
+database, as well as getting all users' password hashes and e-mail
+addresses.
+********************* W A R N I N G ! ! ! ! ! ***********************
+
+== Setup ==
+
+If you want to start small, just run one memcached on your web
+server:
+
+  memcached -d -l 127.0.0.1 -p 11000 -m 64
+
+(to run in daemon mode, accessible only via loopback interface,
+on port 11000, using up to 64MB of memory)
+
+In your LocalSettings.php file, set:
+
+  $wgUseMemCached = true;
+  $wgMemCachedServers = array( "127.0.0.1:11000" );
+
+The wiki should then use memcached to cache various data. To use
+multiple servers (physically separate boxes or multiple caches
+on one machine on a large-memory x86 box), just add more items
+to the array. To increase the weight of a server (say, because
+it has twice the memory of the others and you want to spread
+usage evenly), make its entry a subarray:
+
+  $wgMemCachedServers = array(
+    "127.0.0.1:11000", # one gig on this box
+    array("192.168.0.1:11000", 2) # two gigs on the other box
+  );
+
+
+== PHP client for memcached ==
+
+As of this writing, MediaWiki includes version 1.0.10 of the PHP
+memcached client by Ryan Gilfether <hotrodder@rocketmail.com>.
+You'll find some documentation for it in the 'php-memcached'
+subdirectory under the present one.
+
+We intend to track updates, but if you want to check for the lastest
+released version, see http://www.danga.com/memcached/apis.bml
+
+If you don't set $wgUseMemCached, we still create a MemCacheClient,
+but requests to it are no-ops and we always fall through to the
+database. If the cache daemon can't be contacted, it should also
+disable itself fairly smoothly.
+
+== Keys used ==
+
+User:
+       key: $wgDBname:user:id:$sId
+       ex: wikidb:user:id:51
+       stores: instance of class User
+       set in: User::loadFromSession()
+       cleared by: User::saveSettings(), UserTalkUpdate::doUpdate()
+       
+Newtalk:
+       key: $wgDBname:newtalk:ip:$ip
+       ex: wikidb:newtalk:ip:123.45.67.89
+       stores: integer, 0 or 1
+       set in: User::loadFromDatabase()
+       cleared by: User::saveSettings() # ?
+       expiry set to 30 minutes
+
+LinkCache:
+       key: $wgDBname:lc:title:$title
+       ex: wikidb:lc:title:Wikipedia:Welcome,_Newcomers!
+       stores: cur_id of page, or 0 if page does not exist
+       set in: LinkCache::addLink()
+       cleared by: LinkCache::clearBadLink()
+               should be cleared on page deletion and rename
+MediaWiki namespace:
+       key: $wgDBname:messages
+       ex: wikidb:messages
+       stores: an array where the keys are DB keys and the values are messages
+       set in: wfMsg(), Article::editUpdates() both call wfLoadAllMessages()
+       cleared by: nothing
+
+Watchlist:
+       key: $wgDBname:watchlist:id:$userID
+       ex: wikidb:watchlist:id:4635
+       stores: HTML string
+       cleared by: nothing, expiry time $wgWLCacheTimeout (1 hour)
+       note: emergency optimisation only
+
+IP blocks:
+       key: $wgDBname:ipblocks
+       ex: wikidb:ipblocks
+       stores: array of arrays, for the BlockCache class
+       cleared by: BlockCache:clear()
+       
+... more to come ...
diff --git a/docs/php-memcached/ChangeLog b/docs/php-memcached/ChangeLog
new file mode 100644 (file)
index 0000000..86792f6
--- /dev/null
@@ -0,0 +1,45 @@
+Release 1.0.10
+--------------
+* bug fix: changes hashing function to crc32, sprintf %u
+* feature: optional compression
+
+Release 1.0.9
+-------------
+* protocol parsing bug
+
+Release 1.0.8
+-------------
+* whitespace/punctuation/wording cleanups
+
+Release 1.0.7
+-------------
+* added 3 functions which handle error reporting
+  error() - returns error number of last error generated, else returns 0
+  error_string() - returns a string description of error number retuned
+  error_clear() - clears the last error number and error string
+* removed call to preg_match() in _loaditems()
+* only non-scalar values are serialize() before being
+  sent to the server
+* added the optional timestamp argument for delete()
+  read Documentation file for details
+* PHPDocs/PEAR style comments added
+* abstract debugging (Brion Vibber <brion@pobox.com>)
+       
+Release 1.0.6
+-------------
+* removed all array_push() calls
+* applied patch provided by Stuart Herbert<stuart@gentoo.org>
+  corrects possible endless loop. Available at
+  http://bugs.gentoo.org/show_bug.cgi?id=25385
+* fixed problem with storing large binary files
+* added more error checking, specifically on all socket functions
+* added support for the INCR and DECR commands
+  which increment or decrement a value stored in MemCached
+* Documentation removed from source and is now available
+  in the file Documentation
+
+Release 1.0.4
+-------------
+* initial release, version numbers kept
+  in sync with MemCached version
+* capable of storing any datatype in MemCached
diff --git a/docs/php-memcached/Documentation b/docs/php-memcached/Documentation
new file mode 100644 (file)
index 0000000..4782807
--- /dev/null
@@ -0,0 +1,258 @@
+Ryan Gilfether <hotrodder@rocketmail.com>
+http://www.gilfether.com
+This module is Copyright (c) 2003 Ryan Gilfether.
+All rights reserved.
+
+You may distribute under the terms of the GNU General Public License
+This is free software. IT COMES WITHOUT WARRANTY OF ANY KIND.
+
+See the memcached website: http://www.danga.com/memcached/
+
+
+// Takes one parameter, a array of options.  The most important key is
+// options["servers"], but that can also be set later with the set_servers()
+// method.  The servers must be an array of hosts, each of which is
+// either a scalar of the form <10.0.0.10:11211> or an array of the
+// former and an integer weight value.  (the default weight if
+// unspecified is 1.)  It's recommended that weight values be kept as low
+// as possible, as this module currently allocates memory for bucket
+// distribution proportional to the total host weights.
+// $options["debug"] turns the debugging on if set to true
+MemCachedClient::MemCachedClient($options);
+
+// sets up the list of servers and the ports to connect to
+// takes an array of servers in the same format as in the constructor
+MemCachedClient::set_servers($servers);
+
+// Retrieves a key from the memcache.  Returns the value (automatically
+// unserialized, if necessary) or FALSE if it fails.
+// The $key can optionally be an array, with the first element being the
+// hash value, if you want to avoid making this module calculate a hash
+// value.  You may prefer, for example, to keep all of a given user's
+// objects on the same memcache server, so you could use the user's
+// unique id as the hash value.
+// Possible errors set are:
+//             MC_ERR_GET
+MemCachedClient::get($key);
+
+// just like get(), but takes an array of keys, returns FALSE on error
+// Possible errors set are:
+//             MC_ERR_NOT_ACTIVE
+MemCachedClient::get_multi($keys)
+
+// Unconditionally sets a key to a given value in the memcache.  Returns true
+// if it was stored successfully.
+// The $key can optionally be an arrayref, with the first element being the
+// hash value, as described above.
+// returns TRUE on success else FALSE
+// Possible errors set are:
+//             MC_ERR_NOT_ACTIVE
+//             MC_ERR_GET_SOCK
+//             MC_ERR_SOCKET_WRITE
+//             MC_ERR_SOCKET_READ
+//             MC_ERR_SET
+MemCachedClient::set($key, $value, $exptime);
+
+// Like set(), but only stores in memcache if the key doesn't already exist.
+// returns TRUE on success else FALSE
+// Possible errors set are:
+//             MC_ERR_NOT_ACTIVE
+//             MC_ERR_GET_SOCK
+//             MC_ERR_SOCKET_WRITE
+//             MC_ERR_SOCKET_READ
+//             MC_ERR_SET
+MemCachedClient::add($key, $value, $exptime);
+
+// Like set(), but only stores in memcache if the key already exists.
+// returns TRUE on success else FALSE
+// Possible errors set are:
+//             MC_ERR_NOT_ACTIVE
+//             MC_ERR_GET_SOCK
+//             MC_ERR_SOCKET_WRITE
+//             MC_ERR_SOCKET_READ
+//             MC_ERR_SET
+MemCachedClient::replace($key, $value, $exptime);
+
+// removes the key from the MemCache
+// $time is the amount of time in seconds (or Unix time) until which
+// the client wishes the server to refuse "add" and "replace" commands
+// with this key. For this amount of item, the item is put into a
+// delete queue, which means that it won't possible to retrieve it by
+// the "get" command, but "add" and "replace" command with this key
+// will also fail (the "set" command will succeed, however). After the
+// time passes, the item is finally deleted from server memory.
+// The parameter $time is optional, and, if absent, defaults to 0
+// (which means that the item will be deleted immediately and further
+// storage commands with this key will succeed).
+// returns TRUE on success else returns FALSE
+// Possible errors set are:
+//             MC_ERR_NOT_ACTIVE
+//             MC_ERR_GET_SOCK
+//             MC_ERR_SOCKET_WRITE
+//             MC_ERR_SOCKET_READ
+//             MC_ERR_DELETE
+MemCachedClient::delete($key, $time = 0);
+
+// Sends a command to the server to atomically increment the value for
+// $key by $value, or by 1 if $value is undefined.  Returns FALSE if $key
+// doesn't exist on server, otherwise it returns the new value after
+// incrementing.  Value should be zero or greater.  Overflow on server
+// is not checked.  Be aware of values approaching 2**32.  See decr.
+// Possible errors set are:
+//             MC_ERR_NOT_ACTIVE
+//             MC_ERR_GET_SOCK
+//             MC_ERR_SOCKET_WRITE
+//             MC_ERR_SOCKET_READ
+// returns new value on success, else returns FALSE
+// ONLY WORKS WITH NUMERIC VALUES
+MemCachedClient::incr($key[, $value]);
+
+// Like incr, but decrements.  Unlike incr, underflow is checked and new
+// values are capped at 0.  If server value is 1, a decrement of 2
+// returns 0, not -1.
+// Possible errors set are:
+//             MC_ERR_NOT_ACTIVE
+//             MC_ERR_GET_SOCK
+//             MC_ERR_SOCKET_WRITE
+//             MC_ERR_SOCKET_READ
+// returns new value on success, else returns FALSE
+// ONLY WORKS WITH NUMERIC VALUES
+MemCachedClient::decr($key[, $value]);
+
+// disconnects from all servers
+MemCachedClient::disconnect_all();
+
+// if $do_debug is set to true, will print out
+// debugging info, else debug is turned off
+MemCachedClient::set_debug($do_debug);
+
+// remove all cached hosts that are no longer good
+MemCachedClient::forget_dead_hosts();
+
+// When a function returns FALSE, an error code is set.
+// This funtion will return the error code.
+// See error_string()
+// returns last error code set
+MemCachedClient::error()
+
+// Returns a string describing the error set in error()
+// See error()
+// returns a string describing the error code given
+MemCachedClient::error_string()
+
+// Resets the error number and error string
+MemCachedClient::error_clear()
+
+Error codes are as follows:
+MC_ERR_NOT_ACTIVE              // no active servers
+MC_ERR_SOCKET_WRITE            // socket_write() failed
+MC_ERR_SOCKET_READ             // socket_read() failed
+MC_ERR_SOCKET_CONNECT  // failed to connect to host
+MC_ERR_DELETE                  // delete() did not recieve DELETED command
+MC_ERR_HOST_FORMAT             // sock_to_host() invalid host format
+MC_ERR_HOST_DEAD               // sock_to_host() host is dead
+MC_ERR_GET_SOCK                        // get_sock() failed to find a valid socket
+MC_ERR_SET                             // _set() failed to receive the STORED response
+MC_ERR_LOADITEM_HEADER // _load_items failed to receive valid data header
+MC_ERR_LOADITEM_END            // _load_items failed to receive END response
+MC_ERR_LOADITEM_BYTES  // _load_items bytes read larger than bytes available
+MC_ERR_GET                             // failed to get value associated with key
+
+// Turns compression on or off; 0=off, 1=on
+MemCacheClient::set_compression($setting)
+
+EXAMPLE:
+<?php
+require("MemCachedClient.inc.php");
+
+// set the servers, with the last one having an interger weight value of 3
+$options["servers"] = array("10.0.0.15:11000","10.0.0.16:11001",array("10.0.0.17:11002", 3));
+$options["debug"] = false;
+
+$memc = new MemCachedClient($options);
+
+
+/***********************
+ * STORE AN ARRAY
+ ***********************/
+$myarr = array("one","two", 3);
+$memc->set("key_one", $myarr);
+$val = $memc->get("key_one");
+print $val[0]."\n";    // prints 'one'
+print $val[1]."\n";    // prints 'two'
+print $val[2]."\n";    // prints 3
+
+
+print "\n";
+
+
+/***********************
+ * STORE A CLASS
+ ***********************/
+class tester
+{
+       var $one;
+       var $two;
+       var $three;
+}
+
+$t = new tester;
+$t->one = "one";
+$t->two = "two";
+$t->three = 3;
+$memc->set("key_two", $t);
+$val = $memc->get("key_two");
+print $val->one."\n";
+print $val->two."\n";
+print $val->three."\n";
+
+
+print "\n";
+
+
+/***********************
+ * STORE A STRING
+ ***********************/
+$memc->set("key_three", "my string");
+$val = $memc->get("key_three");
+print $val;            // prints 'my string'
+
+$memc->delete("key_one");
+$memc->delete("key_two");
+$memc->delete("key_three");
+
+$memc->disconnect_all();
+
+
+
+print "\n";
+
+
+/***********************
+ * STORE A BINARY FILE
+ ***********************/
+
+ // first read the file and save it in memcache
+$fp = fopen( "./image.jpg", "rb" ) ;
+if ( !$fp )
+{
+       print "Could not open ./file.dat!\n" ;
+       exit ;
+}
+$data = fread( $fp, filesize( "./image.jpg" ) ) ;
+fclose( $fp ) ;
+print "Data length is " . strlen( $data ) . "\n" ;
+$memc->set( "key", $data ) ;
+
+// now open a file for writing and write the data
+// retrieved from memcache
+$fp = fopen("./test.jpg","wb");
+$data = $memc->get( "key" ) ;
+print "Data length is " . strlen( $data ) . "\n" ;
+fwrite($fp,$data,strlen( $data ));
+fclose($fp);
+
+
+?>
+
+
diff --git a/docs/schema.txt b/docs/schema.txt
new file mode 100644 (file)
index 0000000..f734846
--- /dev/null
@@ -0,0 +1,6 @@
+The most up-to-date schema for the tables in the database
+will always be "tables.sql" in the maintenance directory,
+which is called from the installation script.
+
+That file has been commented with details of the usage for
+each table and field.
diff --git a/docs/skin.txt b/docs/skin.txt
new file mode 100644 (file)
index 0000000..82a5b72
--- /dev/null
@@ -0,0 +1,48 @@
+
+skin.txt
+
+This document describes the overall architecture of MediaWiki's HTML rendering
+code as well as some history about the skin system. It is placed here rather
+than in comments in the code itself to help reduce the code size.
+
+== Version 1.4 ==
+
+MediaWiki still use the PHPTal skin system introduced in version 1.3 but some
+changes have been made to the file organisation.
+
+PHP class and PHPTal templates have been moved to /skins/ (respectivly from
+/includes/ and /templates/). This way skin designer and end user just stick to
+one directory.
+
+Two samples are provided to start with, one for PHPTal use (SkinPHPTal.sample)
+and one without (Skin.sample).
+
+
+== Version 1.3 ==
+
+The following might help a bit though.
+
+Firstly, there's Skin.php; this file will check various settings, and it 
+contains a base class from which new skins can be derived.
+
+Before version 1.3, each skin had its own PHP file (with a sub-class to Skin) 
+to generate the output. The files are:
+ * SkinCologneBlue.php
+ * SkinNostalgia.php
+ * SkinStandard.php
+ * SkinWikimediaWiki.php
+If you want to change those skins, you have to edit these PHP files.
+Since 1.3 a new special skin file is available: SkinPHPTal.php. It makes use of
+the PHPTal template engine and allows you to separate code and layout of the
+pages. The default 1.3 skin is MonoBook and it uses the SkinPHPTAL class.
+
+To change the layout, just edit the PHPTal template (templates/xhtml_slim.pt) 
+as well as the stylesheets (stylesheets/monobook/*).
+
+
+== pre 1.3 version ==
+
+Unfortunately there isn't any documentation, and the code's in a bit of a mess
+right now during the transition from the old skin code to the new template-based
+skin code in 1.3.
diff --git a/docs/title.txt b/docs/title.txt
new file mode 100644 (file)
index 0000000..b404bd3
--- /dev/null
@@ -0,0 +1,72 @@
+title.txt
+
+The MediaWiki software's "Title" class represents article
+titles, which are used for many purposes: as the human-readable
+text title of the article, in the URL used to access the article,
+the wikitext link to the article, the key into the article
+database, and so on. The class in instantiated from one of
+these forms and can be queried for the others, and for other
+attributes of the title. This is intended to be an
+immutable "value" class, so there are no mutator functions.
+
+To get a new instance, call one of the static factory
+methods WikiTitle::newFromURL(), WikiTitle::newFromDBKey(),
+or WikiTitle::newFromText(). Once instantiated, the
+other non-static accessor methods can be used, such as
+getText(), getDBKey(), getNamespace(), etc.
+
+The prefix rules: a title consists of an optional Interwiki
+prefix (such as "m:" for meta or "de:" for German), followed
+by an optional namespace, followed by the remainder of the
+title. Both Interwiki prefixes and namespace prefixes have
+the same rules: they contain only letters, digits, space, and
+underscore, must start with a letter, are case insensitive,
+and spaces and underscores are interchangeable.  Prefixes end
+with a ":". A prefix is only recognized if it is one of those
+specifically allowed by the software. For example, "de:name"
+is a link to the article "name" in the German Wikipedia, because
+"de" is recognized as one of the allowable interwikis. The
+title "talk:name" is a link to the article "name" in the "talk"
+namespace of the current wiki, because "talk" is a recognized
+namespace. Both may be present, and if so, the interwiki must
+come first, for example, "m:talk:name". If a title begins with
+a colon as its first character, no prefixes are scanned for,
+and the colon is just removed. Note that because of these
+rules, it is possible to have articles with colons in their
+names. "E. Coli 0157:H7" is a valid title, as is "2001: A Space
+Odyssey", because "E. Coli 0157" and "2001" are not valid
+interwikis or namespaces. Likewise, ":de:name" is a link to
+the article "de:name"--even though "de" is a valid interwiki,
+the initial colon stops all prefix matching.
+
+Character mapping rules: Once prefixes have been stripped, the
+rest of the title processed this way: spaces and underscores are
+treated as equivalent and each is converted to the other in the
+appropriate context (underscore in URL and database keys, spaces
+in plain text). "Extended" characters in the 0x80..0xFF range
+are allowed in all places, and are valid characters. They are
+encoded in URLs.  Other characters may be ASCII letters, digits,
+hyphen, comma, period, apostrophe, parentheses, and colon. No
+other ASCII characters are allowed, and will be deleted if found
+(they will probably cause a browser to misinterpret the URL).
+Extended characters are _not_ urlencoded when used as text or
+database keys.
+
+Character encoding rules: TODO
+
+Canonical forms: the canonical form of a title will always be
+returned by the object. In this form, the first (and only the
+first) character of the namespace and title will be uppercased;
+the rest of the namespace will be lowercased, while the title
+will be left as is. The text form will use spaces, the URL and
+DBkey forms will use underscores. Interwiki prefixes are all
+lowercase. The namespace will use underscores when returned
+alone; it will use spaces only when attached to the text title.
+
+getArticleID() needs some explanation: for "internal" articles,
+it should return the "cur_id" field if the article exists, else
+it returns 0. For all external articles it returns 0. All of
+the IDs for all instances of Title created during a request are
+cached, so they can be looked up wuickly while rendering wiki
+text with lots of internal links.
+
diff --git a/docs/user.txt b/docs/user.txt
new file mode 100644 (file)
index 0000000..3f1c820
--- /dev/null
@@ -0,0 +1,63 @@
+
+user.txt
+
+Documenting the MediaWiki User object.
+
+(DISCLAIMER: The documentation is not guaranteed to be in sync with
+the code at all times. If in doubt, check the table definitions
+and User.php.)
+
+Database fields:
+
+  user_id
+    Unique integer identifier; primary key. Sent to user in
+    cookie "{$wgDBname}UserID".
+
+  user_name
+    Text of full user name; title of "user:" page.  Displayed
+    on change lists, etc.  Sent to user as cookie "{$wgDBname}UserName".
+    Note that user names can contain spaces, while these are
+    converted to underscores in page titles.
+
+  user_rights
+    Comma-separated list of rights. Right now, only "sysop",
+    "developer", "bureaucrat", and "bot" have meaning.
+
+  user_password
+    Salted md5 hash of md5-hashed user login password.  If user option to
+    remember password is set, an md5 password hash is stored in cookie
+    "{$wgDBname}UserPassword". The original password and the hashed password
+    can be compared to the salted-hashed-hashed password.
+
+  user_newpassword
+    Hash for randomly generated password sent on 'send me a new password'.
+    If a match is made on login, the new password will replace the old one.
+
+  user_email
+    User's e-mail address. (Optional, used for user-to-user
+    e-mail and password recovery.)
+
+  user_options
+    A urlencoded string of name=value pairs to set various
+    user options.
+
+  user_touched
+    Timestamp updated when the user logs in, changes preferences, alters
+    watchlist, or when someone edits their user talk page or they clear
+    the new-talk field by viewing it. Used to invalidate old cached pages
+    from the user's browser cache.
+
+  user_real_name
+    "Real name" optionally used in some metadata lists.
+
+The user object encapsulates all of the settings, and clients
+classes use the getXXX() functions to access them. These functions
+do all the work of determining whether the user is logged in,
+whether the requested option can be satisfied from cookies or
+whether a database query is needed. Most of the settings needed
+for rendering normal pages are set in the cookie to minimize use
+of the database.
+
+Options
+  The user_options field is a list of name-value pairs.  The
+  following option names are used at various points in the system:
diff --git a/extensions/README b/extensions/README
new file mode 100644 (file)
index 0000000..cc93116
--- /dev/null
@@ -0,0 +1,3 @@
+Some extensions (such as the hieroglyphic module WikiHiero) are
+distributed separately. Drop them into this extensions directory
+and enable as per the extension's directions.
diff --git a/images/.cvsignore b/images/.cvsignore
new file mode 100644 (file)
index 0000000..27db1a7
--- /dev/null
@@ -0,0 +1,6 @@
+archive*
+math*
+thumb*
+timeline*
+tmp*
+?
diff --git a/images/README b/images/README
new file mode 100644 (file)
index 0000000..44f6835
--- /dev/null
@@ -0,0 +1,5 @@
+If uploads are enabled in the wiki, files will be put in subdirectories
+under here.
+
+Note to upgraders: as of MediaWiki 1.3, the images used in the user
+interface have been moved to stylesheets/images.
diff --git a/img_auth.php b/img_auth.php
new file mode 100644 (file)
index 0000000..6f6152e
--- /dev/null
@@ -0,0 +1,56 @@
+<?php
+/**
+ * Image download authorisation script
+ * 
+ * To use, in LocalSettings.php set $wgUploadDirectory to point to a non-public
+ * directory, and $wgUploadPath to point to this file. Also set $wgWhitelistRead
+ * to an array of pages you want everyone to be able to access. Your server must
+ * support PATH_INFO, CGI-based configurations generally don't. 
+ */
+# Valid web server entry point, enable includes
+define( 'MEDIAWIKI', true );
+
+require_once( 'includes/Defines.php' );
+require_once( './LocalSettings.php' );
+require_once( 'includes/Setup.php' );
+require_once( 'includes/StreamFile.php' );
+
+if( !isset( $_SERVER['PATH_INFO'] ) ) {
+       wfForbidden();
+}
+
+# Get filenames/directories
+$filename = realpath( $wgUploadDirectory . $_SERVER['PATH_INFO'] );
+$realUploadDirectory = realpath( $wgUploadDirectory );
+$imageName = $wgLang->getNsText( NS_IMAGE ) . ":" . basename( $_SERVER['PATH_INFO'] );
+
+# Check if the filename is in the correct directory
+if ( substr( $filename, 0, strlen( $realUploadDirectory ) ) != $realUploadDirectory ) {
+       wfForbidden();
+}
+
+if ( is_array( $wgWhitelistRead ) && !in_array( $imageName, $wgWhitelistRead ) && !$wgUser->getID() ) {
+       wfForbidden();
+}
+
+if( !file_exists( $filename ) ) {
+       wfForbidden();
+}
+if( is_dir( $filename ) ) {
+       wfForbidden();
+}
+
+# Write file
+wfStreamFile( $filename );
+
+function wfForbidden() {
+       header( 'HTTP/1.0 403 Forbidden' );
+       print 
+"<html><body>
+<h1>Access denied</h1>
+<p>You need to log in to access files on this server</p>
+</body></html>";
+       exit;
+}
+
+?>
diff --git a/includes/.htaccess b/includes/.htaccess
new file mode 100644 (file)
index 0000000..3a42882
--- /dev/null
@@ -0,0 +1 @@
+Deny from all
diff --git a/includes/Article.php b/includes/Article.php
new file mode 100644 (file)
index 0000000..373e7de
--- /dev/null
@@ -0,0 +1,2514 @@
+<?php
+/**
+ * File for articles
+ * @package MediaWiki
+ */
+
+/**
+ * Need the CacheManager to be loaded
+ */
+require_once( 'CacheManager.php' );
+require_once( 'Revision.php' );
+
+$wgArticleCurContentFields = false;
+$wgArticleOldContentFields = false;
+
+/**
+ * Class representing a MediaWiki article and history.
+ *
+ * See design.txt for an overview.
+ * Note: edit user interface and cache support functions have been
+ * moved to separate EditPage and CacheManager classes.
+ *
+ * @package MediaWiki
+ */
+class Article {
+       /**#@+
+        * @access private
+        */
+       var $mContent, $mContentLoaded;
+       var $mUser, $mTimestamp, $mUserText;
+       var $mCounter, $mComment, $mGoodAdjustment, $mTotalAdjustment;
+       var $mMinorEdit, $mRedirectedFrom;
+       var $mTouched, $mFileCache, $mTitle;
+       var $mId, $mTable;
+       var $mForUpdate;
+       var $mOldId;
+       var $mRevIdFetched;
+       var $mRevision;
+       /**#@-*/
+
+       /**
+        * Constructor and clear the article
+        * @param mixed &$title
+        */
+       function Article( &$title ) {
+               $this->mTitle =& $title;
+               $this->clear();
+       }
+
+       /**
+        * get the title object of the article
+        * @public
+        */
+       function getTitle() {
+               return $this->mTitle;
+       }
+
+       /**
+         * Clear the object
+         * @private
+         */
+       function clear() {
+               $this->mDataLoaded    = false;
+               $this->mContentLoaded = false;
+
+               $this->mCurID = $this->mUser = $this->mCounter = -1; # Not loaded
+               $this->mRedirectedFrom = $this->mUserText =
+               $this->mTimestamp = $this->mComment = $this->mFileCache = '';
+               $this->mGoodAdjustment = $this->mTotalAdjustment = 0;
+               $this->mTouched = '19700101000000';
+               $this->mForUpdate = false;
+               $this->mIsRedirect = false;
+               $this->mRevIdFetched = 0;
+       }
+
+       /**
+        * Note that getContent/loadContent may follow redirects if
+        * not told otherwise, and so may cause a change to mTitle.
+        *
+        * @param $noredir
+        * @return Return the text of this revision
+       */
+       function getContent( $noredir ) {
+               global $wgRequest, $wgUser, $wgOut;
+
+               # Get variables from query string :P
+               $action = $wgRequest->getText( 'action', 'view' );
+               $section = $wgRequest->getText( 'section' );
+               $preload = $wgRequest->getText( 'preload' );
+
+               $fname =  'Article::getContent';
+               wfProfileIn( $fname );
+
+               if ( 0 == $this->getID() ) {
+                       if ( 'edit' == $action ) {
+                               wfProfileOut( $fname );
+
+                               # If requested, preload some text.
+                               $text=$this->getPreloadedText($preload);
+
+                               # We used to put MediaWiki:Newarticletext here if
+                               # $text was empty at this point.
+                               # This is now shown above the edit box instead.
+                               return $text;
+                       }
+                       wfProfileOut( $fname );
+                       $wgOut->setRobotpolicy( 'noindex,nofollow' );
+                       return wfMsg( 'noarticletext' );
+               } else {
+                       $this->loadContent( $noredir );
+                       # check if we're displaying a [[User talk:x.x.x.x]] anonymous talk page
+                       if ( $this->mTitle->getNamespace() == NS_USER_TALK &&
+                         $wgUser->isIP($this->mTitle->getText()) &&
+                         $action=='view'
+                       ) {
+                               wfProfileOut( $fname );
+                               return $this->mContent . "\n" .wfMsg('anontalkpagetext');
+                       } else {
+                               if($action=='edit') {
+                                       if($section!='') {
+                                               if($section=='new') {
+                                                       wfProfileOut( $fname );
+                                                       $text=$this->getPreloadedText($preload);
+                                                       return $text;
+                                               }
+
+                                               # strip NOWIKI etc. to avoid confusion (true-parameter causes HTML
+                                               # comments to be stripped as well)
+                                               $rv=$this->getSection($this->mContent,$section);
+                                               wfProfileOut( $fname );
+                                               return $rv;
+                                       }
+                               }
+                               wfProfileOut( $fname );
+                               return $this->mContent;
+                       }
+               }
+       }
+
+       /**
+               This function accepts a title string as parameter
+               ($preload). If this string is non-empty, it attempts
+               to fetch the current revision text.
+       */
+       function getPreloadedText($preload) {
+               if($preload) {
+                       $preloadTitle=Title::newFromText($preload);
+                       if(isset($preloadTitle) && $preloadTitle->userCanRead()) {
+                       $rev=Revision::newFromTitle($preloadTitle);
+                       if($rev) {
+                               return $rev->getText();
+                               }
+                       }
+               }
+               return '';
+       }
+
+       /**
+        * This function returns the text of a section, specified by a number ($section).
+        * A section is text under a heading like == Heading == or <h1>Heading</h1>, or
+        * the first section before any such heading (section 0).
+        *
+        * If a section contains subsections, these are also returned.
+        *
+        * @param string $text text to look in
+        * @param integer $section section number
+        * @return string text of the requested section
+        */
+       function getSection($text,$section) {
+
+               # strip NOWIKI etc. to avoid confusion (true-parameter causes HTML
+               # comments to be stripped as well)
+               $striparray=array();
+               $parser=new Parser();
+               $parser->mOutputType=OT_WIKI;
+               $parser->mOptions = new ParserOptions();
+               $striptext=$parser->strip($text, $striparray, true);
+
+               # now that we can be sure that no pseudo-sections are in the source,
+               # split it up by section
+               $secs =
+                 preg_split(
+                 '/(^=+.+?=+|^<h[1-6].*?' . '>.*?<\/h[1-6].*?' . '>)(?!\S)/mi',
+                 $striptext, -1,
+                 PREG_SPLIT_DELIM_CAPTURE);
+               if($section==0) {
+                       $rv=$secs[0];
+               } else {
+                       $headline=$secs[$section*2-1];
+                       preg_match( '/^(=+).+?=+|^<h([1-6]).*?' . '>.*?<\/h[1-6].*?' . '>(?!\S)/mi',$headline,$matches);
+                       $hlevel=$matches[1];
+
+                       # translate wiki heading into level
+                       if(strpos($hlevel,'=')!==false) {
+                               $hlevel=strlen($hlevel);
+                       }
+
+                       $rv=$headline. $secs[$section*2];
+                       $count=$section+1;
+
+                       $break=false;
+                       while(!empty($secs[$count*2-1]) && !$break) {
+
+                               $subheadline=$secs[$count*2-1];
+                               preg_match( '/^(=+).+?=+|^<h([1-6]).*?' . '>.*?<\/h[1-6].*?' . '>(?!\S)/mi',$subheadline,$matches);
+                               $subhlevel=$matches[1];
+                               if(strpos($subhlevel,'=')!==false) {
+                                       $subhlevel=strlen($subhlevel);
+                               }
+                               if($subhlevel > $hlevel) {
+                                       $rv.=$subheadline.$secs[$count*2];
+                               }
+                               if($subhlevel <= $hlevel) {
+                                       $break=true;
+                               }
+                               $count++;
+
+                       }
+               }
+               # reinsert stripped tags
+               $rv=$parser->unstrip($rv,$striparray);
+               $rv=$parser->unstripNoWiki($rv,$striparray);
+               $rv=trim($rv);
+               return $rv;
+
+       }
+
+       /**
+        * Return an array of the columns of the "cur"-table
+        */
+       function getContentFields() {
+               return $wgArticleContentFields = array(
+                 'old_text','old_flags',
+                 'rev_timestamp','rev_user', 'rev_user_text', 'rev_comment','page_counter',
+                 'page_namespace', 'page_title', 'page_restrictions','page_touched','page_is_redirect' );
+       }
+
+       /**
+        * Return the oldid of the article that is to be shown.
+        * For requests with a "direction", this is not the oldid of the
+        * query
+        */
+       function getOldID() {
+               global $wgRequest, $wgOut;
+               static $lastid;
+
+               if ( isset( $lastid ) ) {
+                       return $lastid;
+               }
+               # Query variables :P
+               $oldid = $wgRequest->getVal( 'oldid' );
+               if ( isset( $oldid ) ) {
+                       $oldid = IntVal( $oldid );
+                       if ( $wgRequest->getVal( 'direction' ) == 'next' ) {
+                               $nextid = $this->mTitle->getNextRevisionID( $oldid );
+                               if ( $nextid  ) {
+                                       $oldid = $nextid;
+                               } else {
+                                       $wgOut->redirect( $this->mTitle->getFullURL( 'redirect=no' ) );
+                               }
+                       } elseif ( $wgRequest->getVal( 'direction' ) == 'prev' ) {
+                               $previd = $this->mTitle->getPreviousRevisionID( $oldid );
+                               if ( $previd ) {
+                                       $oldid = $previd;
+                               } else {
+                                       # TODO
+                               }
+                       }
+                       $lastid = $oldid;
+               }
+               return @$oldid; # "@" to be able to return "unset" without PHP complaining
+       }
+
+
+       /**
+        * Load the revision (including cur_text) into this object
+        */
+       function loadContent( $noredir = false ) {
+               global $wgOut, $wgRequest;
+
+               if ( $this->mContentLoaded ) return;
+
+               # Query variables :P
+               $oldid = $this->getOldID();
+               $redirect = $wgRequest->getVal( 'redirect' );
+
+               $fname = 'Article::loadContent';
+
+               # Pre-fill content with error message so that if something
+               # fails we'll have something telling us what we intended.
+
+               $t = $this->mTitle->getPrefixedText();
+
+               $noredir = $noredir || ($wgRequest->getVal( 'redirect' ) == 'no')
+                       || $wgRequest->getCheck( 'rdfrom' );
+               $this->mOldId = $oldid;
+               $this->fetchContent( $oldid, $noredir, true );
+       }
+
+
+       /**
+        * Fetch a page record with the given conditions
+        * @param Database $dbr
+        * @param array    $conditions
+        * @access private
+        */
+       function pageData( &$dbr, $conditions ) {
+               return $dbr->selectRow( 'page',
+                       array(
+                               'page_id',
+                               'page_namespace',
+                               'page_title',
+                               'page_restrictions',
+                               'page_counter',
+                               'page_is_redirect',
+                               'page_is_new',
+                               'page_random',
+                               'page_touched',
+                               'page_latest',
+                               'page_len' ),
+                       $conditions,
+                       'Article::pageData' );
+       }
+
+       function pageDataFromTitle( &$dbr, $title ) {
+               return $this->pageData( $dbr, array(
+                       'page_namespace' => $title->getNamespace(),
+                       'page_title'     => $title->getDBkey() ) );
+       }
+
+       function pageDataFromId( &$dbr, $id ) {
+               return $this->pageData( $dbr, array(
+                       'page_id' => IntVal( $id ) ) );
+       }
+
+       /**
+        * Set the general counter, title etc data loaded from
+        * some source.
+        *
+        * @param object $data
+        * @access private
+        */
+       function loadPageData( $data ) {
+               $this->mTitle->loadRestrictions( $data->page_restrictions );
+               $this->mTitle->mRestrictionsLoaded = true;
+
+               $this->mCounter    = $data->page_counter;
+               $this->mTouched    = wfTimestamp( TS_MW, $data->page_touched );
+               $this->mIsRedirect = $data->page_is_redirect;
+               $this->mLatest     = $data->page_latest;
+
+               $this->mDataLoaded = true;
+       }
+
+       /**
+        * Get text of an article from database
+        * @param int $oldid 0 for whatever the latest revision is
+        * @param bool $noredir Set to false to follow redirects
+        * @param bool $globalTitle Set to true to change the global $wgTitle object when following redirects or other unexpected title changes
+        * @return string
+        */
+       function fetchContent( $oldid = 0, $noredir = true, $globalTitle = false ) {
+               if ( $this->mContentLoaded ) {
+                       return $this->mContent;
+               }
+               $dbr =& $this->getDB();
+               $fname = 'Article::fetchContent';
+
+               # Pre-fill content with error message so that if something
+               # fails we'll have something telling us what we intended.
+               $t = $this->mTitle->getPrefixedText();
+               if( $oldid ) {
+                       $t .= ',oldid='.$oldid;
+               }
+               if( isset( $redirect ) ) {
+                       $redirect = ($redirect == 'no') ? 'no' : 'yes';
+                       $t .= ',redirect='.$redirect;
+               }
+               $this->mContent = wfMsg( 'missingarticle', $t );
+
+               if( $oldid ) {
+                       $revision = Revision::newFromId( $oldid );
+                       if( is_null( $revision ) ) {
+                               wfDebug( "$fname failed to retrieve specified revision, id $oldid\n" );
+                               return false;
+                       }
+                       $data = $this->pageDataFromId( $dbr, $revision->getPage() );
+                       if( !$data ) {
+                               wfDebug( "$fname failed to get page data linked to revision id $oldid\n" );
+                               return false;
+                       }
+                       $this->mTitle = Title::makeTitle( $data->page_namespace, $data->page_title );
+                       $this->loadPageData( $data );
+               } else {
+                       if( !$this->mDataLoaded ) {
+                               $data = $this->pageDataFromTitle( $dbr, $this->mTitle );
+                               if( !$data ) {
+                                       wfDebug( "$fname failed to find page data for title " . $this->mTitle->getPrefixedText() . "\n" );
+                                       return false;
+                               }
+                               $this->loadPageData( $data );
+                       }
+                       $revision = Revision::newFromId( $this->mLatest );
+                       if( is_null( $revision ) ) {
+                               wfDebug( "$fname failed to retrieve current page, rev_id $data->page_latest\n" );
+                               return false;
+                       }
+               }
+
+               # If we got a redirect, follow it (unless we've been told
+               # not to by either the function parameter or the query
+               if ( !$oldid && !$noredir ) {
+                       $rt = Title::newFromRedirect( $revision->getText() );
+                       # process if title object is valid and not special:userlogout
+                       if ( $rt && ! ( $rt->getNamespace() == NS_SPECIAL && $rt->getText() == 'Userlogout' ) ) {
+                               # Gotta hand redirects to special pages differently:
+                               # Fill the HTTP response "Location" header and ignore
+                               # the rest of the page we're on.
+                               global $wgDisableHardRedirects;
+                               if( $globalTitle && !$wgDisableHardRedirects ) {
+                                       global $wgOut;
+                                       if ( $rt->getInterwiki() != '' && $rt->isLocal() ) {
+                                               $source = $this->mTitle->getFullURL( 'redirect=no' );
+                                               $wgOut->redirect( $rt->getFullURL( 'rdfrom=' . urlencode( $source ) ) ) ;
+                                               return false;
+                                       }
+                                       if ( $rt->getNamespace() == NS_SPECIAL ) {
+                                               $wgOut->redirect( $rt->getFullURL() );
+                                               return false;
+                                       }
+                               }
+                               if( $rt->getInterwiki() == '' ) {
+                                       $redirData = $this->pageDataFromTitle( $dbr, $rt );
+                                       if( $redirData ) {
+                                               $redirRev = Revision::newFromId( $redirData->page_latest );
+                                               if( !is_null( $redirRev ) ) {
+                                                       $this->mRedirectedFrom = $this->mTitle->getPrefixedText();
+                                                       $this->mTitle = $rt;
+                                                       $data = $redirData;
+                                                       $this->loadPageData( $data );
+                                                       $revision = $redirRev;
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               # if the title's different from expected, update...
+               if( $globalTitle ) {
+                       global $wgTitle;
+                       if( !$this->mTitle->equals( $wgTitle ) ) {
+                               $wgTitle = $this->mTitle;
+                       }
+               }
+
+               # Back to the business at hand...
+               $this->mContent   = $revision->getText();
+
+               $this->mUser      = $revision->getUser();
+               $this->mUserText  = $revision->getUserText();
+               $this->mComment   = $revision->getComment();
+               $this->mTimestamp = wfTimestamp( TS_MW, $revision->getTimestamp() );
+
+               $this->mRevIdFetched = $revision->getID();
+               $this->mContentLoaded = true;
+               $this->mRevision =& $revision;
+
+               return $this->mContent;
+       }
+
+       /**
+        * Gets the article text without using so many damn globals
+        * Returns false on error
+        *
+        * @param integer $oldid
+        */
+       function getContentWithoutUsingSoManyDamnGlobals( $oldid = 0, $noredir = false ) {
+               return $this->fetchContent( $oldid, $noredir, false );
+       }
+
+       /**
+        * Read/write accessor to select FOR UPDATE
+        */
+       function forUpdate( $x = NULL ) {
+               return wfSetVar( $this->mForUpdate, $x );
+       }
+
+       /**
+        * Get the database which should be used for reads
+        */
+       function &getDB() {
+               #if ( $this->mForUpdate ) {
+                       $ret =& wfGetDB( DB_MASTER );
+               #} else {
+               #       $ret =& wfGetDB( DB_SLAVE );
+               #}
+               return $ret;
+       }
+
+       /**
+        * Get options for all SELECT statements
+        * Can pass an option array, to which the class-wide options will be appended
+        */
+       function getSelectOptions( $options = '' ) {
+               if ( $this->mForUpdate ) {
+                       if ( is_array( $options ) ) {
+                               $options[] = 'FOR UPDATE';
+                       } else {
+                               $options = 'FOR UPDATE';
+                       }
+               }
+               return $options;
+       }
+
+       /**
+        * Return the Article ID
+        */
+       function getID() {
+               if( $this->mTitle ) {
+                       return $this->mTitle->getArticleID();
+               } else {
+                       return 0;
+               }
+       }
+
+       /**
+        * Returns true if this article exists in the database.
+        * @return bool
+        */
+       function exists() {
+               return $this->getId() != 0;
+       }
+
+       /**
+        * Get the view count for this article
+        */
+       function getCount() {
+               if ( -1 == $this->mCounter ) {
+                       $id = $this->getID();
+                       $dbr =& $this->getDB();
+                       $this->mCounter = $dbr->selectField( 'page', 'page_counter', array( 'page_id' => $id ),
+                               'Article::getCount', $this->getSelectOptions() );
+               }
+               return $this->mCounter;
+       }
+
+       /**
+        * Would the given text make this article a "good" article (i.e.,
+        * suitable for including in the article count)?
+        * @param string $text Text to analyze
+        * @return integer 1 if it can be counted else 0
+        */
+       function isCountable( $text ) {
+               global $wgUseCommaCount;
+
+               if ( NS_MAIN != $this->mTitle->getNamespace() ) { return 0; }
+               if ( $this->isRedirect( $text ) ) { return 0; }
+               $token = ($wgUseCommaCount ? ',' : '[[' );
+               if ( false === strstr( $text, $token ) ) { return 0; }
+               return 1;
+       }
+
+       /**
+        * Tests if the article text represents a redirect
+        */
+       function isRedirect( $text = false ) {
+               if ( $text === false ) {
+                       $this->loadContent();
+                       $titleObj = Title::newFromRedirect( $this->fetchContent() );
+               } else {
+                       $titleObj = Title::newFromRedirect( $text );
+               }
+               return $titleObj !== NULL;
+       }
+
+       /**
+        * Returns true if the currently-referenced revision is the current edit
+        * to this page (and it exists).
+        * @return bool
+        */
+       function isCurrent() {
+               return $this->exists() &&
+                       isset( $this->mRevision ) &&
+                       $this->mRevision->isCurrent();
+       }
+
+       /**
+        * Loads everything except the text
+        * This isn't necessary for all uses, so it's only done if needed.
+        * @private
+        */
+       function loadLastEdit() {
+               global $wgOut;
+
+               if ( -1 != $this->mUser )
+                       return;
+
+               # New or non-existent articles have no user information
+               $id = $this->getID();
+               if ( 0 == $id ) return;
+
+               $this->mLastRevision = Revision::loadFromPageId( $this->getDB(), $id );
+               if( !is_null( $this->mLastRevision ) ) {
+                       $this->mUser      = $this->mLastRevision->getUser();
+                       $this->mUserText  = $this->mLastRevision->getUserText();
+                       $this->mTimestamp = $this->mLastRevision->getTimestamp();
+                       $this->mComment   = $this->mLastRevision->getComment();
+                       $this->mMinorEdit = $this->mLastRevision->isMinor();
+               }
+       }
+
+       function getTimestamp() {
+               $this->loadLastEdit();
+               return $this->mTimestamp;
+       }
+
+       function getUser() {
+               $this->loadLastEdit();
+               return $this->mUser;
+       }
+
+       function getUserText() {
+               $this->loadLastEdit();
+               return $this->mUserText;
+       }
+
+       function getComment() {
+               $this->loadLastEdit();
+               return $this->mComment;
+       }
+
+       function getMinorEdit() {
+               $this->loadLastEdit();
+               return $this->mMinorEdit;
+       }
+
+       function getRevIdFetched() {
+               $this->loadLastEdit();
+               return $this->mRevIdFetched;
+       }
+
+       function getContributors($limit = 0, $offset = 0) {
+               $fname = 'Article::getContributors';
+
+               # XXX: this is expensive; cache this info somewhere.
+
+               $title = $this->mTitle;
+               $contribs = array();
+               $dbr =& $this->getDB();
+               $revTable = $dbr->tableName( 'revision' );
+               $userTable = $dbr->tableName( 'user' );
+               $encDBkey = $dbr->addQuotes( $title->getDBkey() );
+               $ns = $title->getNamespace();
+               $user = $this->getUser();
+               $pageId = $this->getId();
+
+               $sql = "SELECT rev_user, rev_user_text, user_real_name, MAX(rev_timestamp) as timestamp
+                       FROM $revTable LEFT JOIN $userTable ON rev_user = user_id
+                       WHERE rev_page = $pageId
+                       AND rev_user != $user
+                       GROUP BY rev_user, rev_user_text, user_real_name
+                       ORDER BY timestamp DESC";
+
+               if ($limit > 0) { $sql .= ' LIMIT '.$limit; }
+               $sql .= ' '. $this->getSelectOptions();
+
+               $res = $dbr->query($sql, $fname);
+
+               while ( $line = $dbr->fetchObject( $res ) ) {
+                       $contribs[] = array($line->rev_user, $line->rev_user_text, $line->user_real_name);
+               }
+
+               $dbr->freeResult($res);
+               return $contribs;
+       }
+
+       /**
+        * This is the default action of the script: just view the page of
+        * the given title.
+       */
+       function view() {
+               global $wgUser, $wgOut, $wgRequest, $wgOnlySysopsCanPatrol, $wgLang;
+               global $wgLinkCache, $IP, $wgEnableParserCache, $wgStylePath, $wgUseRCPatrol;
+               global $wgEnotif, $wgParser, $wgParserCache, $wgUseTrackbacks;
+               $sk = $wgUser->getSkin();
+
+               $fname = 'Article::view';
+               wfProfileIn( $fname );
+               # Get variables from query string
+               $oldid = $this->getOldID();
+               $diff = $wgRequest->getVal( 'diff' );
+               $rcid = $wgRequest->getVal( 'rcid' );
+               $rdfrom = $wgRequest->getVal( 'rdfrom' );
+
+               $wgOut->setArticleFlag( true );
+               $wgOut->setRobotpolicy( 'index,follow' );
+               # If we got diff and oldid in the query, we want to see a
+               # diff page instead of the article.
+
+               if ( !is_null( $diff ) ) {
+                       require_once( 'DifferenceEngine.php' );
+                       $wgOut->setPageTitle( $this->mTitle->getPrefixedText() );
+
+                       $de = new DifferenceEngine( $oldid, $diff, $rcid );
+                       // DifferenceEngine directly fetched the revision:
+                       $this->mRevIdFetched = $de->mNewid;
+                       $de->showDiffPage();
+
+                       if( $diff == 0 ) {
+                               # Run view updates for current revision only
+                               $this->viewUpdates();
+                       }
+                       wfProfileOut( $fname );
+                       return;
+               }
+
+               if ( empty( $oldid ) && $this->checkTouched() ) {
+                       $wgOut->setETag($wgParserCache->getETag($this, $wgUser));
+
+                       if( $wgOut->checkLastModified( $this->mTouched ) ){
+                               wfProfileOut( $fname );
+                               return;
+                       } else if ( $this->tryFileCache() ) {
+                               # tell wgOut that output is taken care of
+                               $wgOut->disable();
+                               $this->viewUpdates();
+                               wfProfileOut( $fname );
+                               return;
+                       }
+               }
+               # Should the parser cache be used?
+               $pcache = $wgEnableParserCache &&
+                       intval( $wgUser->getOption( 'stubthreshold' ) ) == 0 &&
+                       $this->exists() &&
+                       empty( $oldid );
+               wfDebug( 'Article::view using parser cache: ' . ($pcache ? 'yes' : 'no' ) . "\n" );
+
+               $outputDone = false;
+               if ( $pcache ) {
+                       if ( $wgOut->tryParserCache( $this, $wgUser ) ) {
+                               $outputDone = true;
+                       }
+               }
+               if ( !$outputDone ) {
+                       $text = $this->getContent( false ); # May change mTitle by following a redirect
+
+                       # Another whitelist check in case oldid or redirects are altering the title
+                       if ( !$this->mTitle->userCanRead() ) {
+                               $wgOut->loginToUse();
+                               $wgOut->output();
+                               exit;
+                       }
+
+                       # We're looking at an old revision
+
+                       if ( !empty( $oldid ) ) {
+                               $this->setOldSubtitle( isset($this->mOldId) ? $this->mOldId : $oldid );
+                               $wgOut->setRobotpolicy( 'noindex,follow' );
+                       }
+                       if ( '' != $this->mRedirectedFrom ) {
+                               if ( wfRunHooks( 'ArticleViewRedirect', array( &$this ) ) ) {
+                                       $sk = $wgUser->getSkin();
+                                       $redir = $sk->makeKnownLink( $this->mRedirectedFrom, '', 'redirect=no' );
+                                       $s = wfMsg( 'redirectedfrom', $redir );
+                                       $wgOut->setSubtitle( $s );
+                                       # Can't cache redirects
+                                       $pcache = false;
+                               }
+                       } elseif ( !empty( $rdfrom ) ) {
+                               global $wgRedirectSources;
+                               if( $wgRedirectSources && preg_match( $wgRedirectSources, $rdfrom ) ) {
+                                       $sk = $wgUser->getSkin();
+                                       $redir = $sk->makeExternalLink( $rdfrom, $rdfrom );
+                                       $s = wfMsg( 'redirectedfrom', $redir );
+                                       $wgOut->setSubtitle( $s );
+                               }
+                       }
+
+                       # wrap user css and user js in pre and don't parse
+                       # XXX: use $this->mTitle->usCssJsSubpage() when php is fixed/ a workaround is found
+                       if (
+                               $this->mTitle->getNamespace() == NS_USER &&
+                               preg_match('/\\/[\\w]+\\.(css|js)$/', $this->mTitle->getDBkey())
+                       ) {
+                               $wgOut->addWikiText( wfMsg('clearyourcache'));
+                               $wgOut->addHTML( '<pre>'.htmlspecialchars($this->mContent)."\n</pre>" );
+                       } else if ( $rt = Title::newFromRedirect( $text ) ) {
+                               # Display redirect
+                               $imageUrl = $wgStylePath.'/common/images/redirect.png';
+                               $targetUrl = $rt->escapeLocalURL();
+                               $titleText = htmlspecialchars( $rt->getPrefixedText() );
+                               $link = $sk->makeLinkObj( $rt );
+
+                               $wgOut->addHTML( '<img valign="center" src="'.$imageUrl.'" alt="#REDIRECT" />' .
+                                 '<span class="redirectText">'.$link.'</span>' );
+
+                               $parseout = $wgParser->parse($text, $this->mTitle, ParserOptions::newFromUser($wgUser));
+                               $catlinks = $parseout->getCategoryLinks();
+                               $wgOut->addCategoryLinks($catlinks);
+                               $skin = $wgUser->getSkin();
+                       } else if ( $pcache ) {
+                               # Display content and save to parser cache
+                               $wgOut->addPrimaryWikiText( $text, $this );
+                       } else {
+                               # Display content, don't attempt to save to parser cache
+
+                               # Don't show section-edit links on old revisions... this way lies madness.
+                               if( !$this->isCurrent() ) {
+                                       $oldEditSectionSetting = $wgOut->mParserOptions->setEditSection( false );
+                               }
+                               $wgOut->addWikiText( $text );
+
+                               if( !$this->isCurrent() ) {
+                                       $wgOut->mParserOptions->setEditSection( $oldEditSectionSetting );
+                               }
+                       }
+               }
+               /* title may have been set from the cache */
+               $t = $wgOut->getPageTitle();
+               if( empty( $t ) ) {
+                       $wgOut->setPageTitle( $this->mTitle->getPrefixedText() );
+               }
+
+               # If we have been passed an &rcid= parameter, we want to give the user a
+               # chance to mark this new article as patrolled.
+               if ( $wgUseRCPatrol
+                       && !is_null($rcid)
+                       && $rcid != 0
+                       && $wgUser->isLoggedIn()
+                       && ( $wgUser->isAllowed('patrol') || !$wgOnlySysopsCanPatrol ) )
+               {
+                       $wgOut->addHTML(
+                               "<div class='patrollink'>" .
+                                       wfMsg ( 'markaspatrolledlink',
+                                       $sk->makeKnownLinkObj( $this->mTitle, wfMsg('markaspatrolledtext'), "action=markpatrolled&rcid=$rcid" )
+                                       ) .
+                               '</div>'
+                        );
+               }
+
+               # Trackbacks
+               if ($wgUseTrackbacks)
+                       $this->addTrackbacks();
+
+               # Put link titles into the link cache
+               $wgOut->transformBuffer();
+
+               # Add link titles as META keywords
+               $wgOut->addMetaTags() ;
+
+               $this->viewUpdates();
+               wfProfileOut( $fname );
+       }
+
+       function addTrackbacks() {
+               global $wgOut, $wgUser;
+
+               $dbr = wfGetDB(DB_SLAVE);
+               $tbs = $dbr->select(
+                               /* FROM   */ 'trackbacks',
+                               /* SELECT */ array('tb_id', 'tb_title', 'tb_url', 'tb_ex', 'tb_name'),
+                               /* WHERE  */ array('tb_page' => $this->getID())
+               );
+
+               if (!$dbr->numrows($tbs))
+                       return;
+
+               $tbtext = "";
+               while ($o = $dbr->fetchObject($tbs)) {
+                       $rmvtxt = "";
+                       if ($wgUser->isSysop()) {
+                               $delurl = $this->mTitle->getFullURL("action=deletetrackback&tbid="
+                                               . $o->tb_id . "&token=" . $wgUser->editToken());
+                               $rmvtxt = wfMsg('trackbackremove', $delurl);
+                       }
+                       $tbtext .= wfMsg(strlen($o->tb_ex) ? 'trackbackexcerpt' : 'trackback',
+                                       $o->tb_title,
+                                       $o->tb_url,
+                                       $o->tb_ex,
+                                       $o->tb_name,
+                                       $rmvtxt);
+               }
+               $wgOut->addWikitext(wfMsg('trackbackbox', $tbtext));
+       }
+
+       function deletetrackback() {
+               global $wgUser, $wgRequest, $wgOut, $wgTitle;
+
+               if (!$wgUser->matchEditToken($wgRequest->getVal('token'))) {
+                       $wgOut->addWikitext(wfMsg('sessionfailure'));
+                       return;
+               }
+
+               if ((!$wgUser->isAllowed('delete'))) {
+                       $wgOut->sysopRequired();
+                       return;
+               }
+
+               if (wfReadOnly()) {
+                       $wgOut->readOnlyPage();
+                       return;
+               }
+
+               $db = wfGetDB(DB_MASTER);
+               $db->delete('trackbacks', array('tb_id' => $wgRequest->getInt('tbid')));
+               $wgTitle->invalidateCache();
+               $wgOut->addWikiText(wfMsg('trackbackdeleteok'));
+       }
+
+       function render() {
+               global $wgOut;
+
+               $wgOut->setArticleBodyOnly(true);
+               $this->view();
+       }
+
+       /**
+        * Insert a new empty page record for this article.
+        * This *must* be followed up by creating a revision
+        * and running $this->updateToLatest( $rev_id );
+        * or else the record will be left in a funky state.
+        * Best if all done inside a transaction.
+        *
+        * @param Database $dbw
+        * @param string   $restrictions
+        * @return int     The newly created page_id key
+        * @access private
+        */
+       function insertOn( &$dbw, $restrictions = '' ) {
+               $fname = 'Article::insertOn';
+               wfProfileIn( $fname );
+
+               $page_id = $dbw->nextSequenceValue( 'page_page_id_seq' );
+               $dbw->insert( 'page', array(
+                       'page_id'           => $page_id,
+                       'page_namespace'    => $this->mTitle->getNamespace(),
+                       'page_title'        => $this->mTitle->getDBkey(),
+                       'page_counter'      => 0,
+                       'page_restrictions' => $restrictions,
+                       'page_is_redirect'  => 0, # Will set this shortly...
+                       'page_is_new'       => 1,
+                       'page_random'       => wfRandom(),
+                       'page_touched'      => $dbw->timestamp(),
+                       'page_latest'       => 0, # Fill this in shortly...
+                       'page_len'          => 0, # Fill this in shortly...
+               ), $fname );
+               $newid = $dbw->insertId();
+
+               $this->mTitle->resetArticleId( $newid );
+
+               wfProfileOut( $fname );
+               return $newid;
+       }
+
+       /**
+        * Update the page record to point to a newly saved revision.
+        *
+        * @param Database $dbw
+        * @param Revision $revision -- for ID number, and text used to set
+                                       length and redirect status fields
+        * @param int $lastRevision -- if given, will not overwrite the page field
+        *                             when different from the currently set value.
+        *                             Giving 0 indicates the new page flag should
+        *                             be set on.
+        * @return bool true on success, false on failure
+        * @access private
+        */
+       function updateRevisionOn( &$dbw, $revision, $lastRevision = null ) {
+               $fname = 'Article::updateToRevision';
+               wfProfileIn( $fname );
+
+               $conditions = array( 'page_id' => $this->getId() );
+               if( !is_null( $lastRevision ) ) {
+                       # An extra check against threads stepping on each other
+                       $conditions['page_latest'] = $lastRevision;
+               }
+
+               $text = $revision->getText();
+               $dbw->update( 'page',
+                       array( /* SET */
+                               'page_latest'      => $revision->getId(),
+                               'page_touched'     => $dbw->timestamp(),
+                               'page_is_new'      => ($lastRevision === 0) ? 1 : 0,
+                               'page_is_redirect' => Article::isRedirect( $text ) ? 1 : 0,
+                               'page_len'         => strlen( $text ),
+                       ),
+                       $conditions,
+                       $fname );
+
+               wfProfileOut( $fname );
+               return ( $dbw->affectedRows() != 0 );
+       }
+
+       /**
+        * If the given revision is newer than the currently set page_latest,
+        * update the page record. Otherwise, do nothing.
+        *
+        * @param Database $dbw
+        * @param Revision $revision
+        */
+       function updateIfNewerOn( &$dbw, $revision ) {
+               $fname = 'Article::updateIfNewerOn';
+               wfProfileIn( $fname );
+
+               $row = $dbw->selectRow(
+                       array( 'revision', 'page' ),
+                       array( 'rev_id', 'rev_timestamp' ),
+                       array(
+                               'page_id' => $this->getId(),
+                               'page_latest=rev_id' ),
+                       $fname );
+               if( $row ) {
+                       if( $row->rev_timestamp >= $revision->getTimestamp() ) {
+                               wfProfileOut( $fname );
+                               return false;
+                       }
+                       $prev = $row->rev_id;
+               } else {
+                       # No or missing previous revision; mark the page as new
+                       $prev = 0;
+               }
+
+               $ret = $this->updateRevisionOn( $dbw, $revision, $prev );
+               wfProfileOut( $fname );
+               return $ret;
+       }
+
+       /**
+        * Theoretically we could defer these whole insert and update
+        * functions for after display, but that's taking a big leap
+        * of faith, and we want to be able to report database
+        * errors at some point.
+        * @private
+        */
+       function insertNewArticle( $text, $summary, $isminor, $watchthis, $suppressRC=false, $comment=false ) {
+               global $wgOut, $wgUser;
+               global $wgUseSquid, $wgDeferredUpdateList, $wgInternalServer;
+
+               $fname = 'Article::insertNewArticle';
+               wfProfileIn( $fname );
+
+               $this->mGoodAdjustment = $this->isCountable( $text );
+               $this->mTotalAdjustment = 1;
+
+               $ns = $this->mTitle->getNamespace();
+               $ttl = $this->mTitle->getDBkey();
+
+               # If this is a comment, add the summary as headline
+               if($comment && $summary!="") {
+                       $text="== {$summary} ==\n\n".$text;
+               }
+               $text = $this->preSaveTransform( $text );
+               $isminor = ( $isminor && $wgUser->isLoggedIn() ) ? 1 : 0;
+               $now = wfTimestampNow();
+
+               $dbw =& wfGetDB( DB_MASTER );
+
+               # Add the page record; stake our claim on this title!
+               $newid = $this->insertOn( $dbw );
+
+               # Save the revision text...
+               $revision = new Revision( array(
+                       'page'       => $newid,
+                       'comment'    => $summary,
+                       'minor_edit' => $isminor,
+                       'text'       => $text
+                       ) );
+               $revisionId = $revision->insertOn( $dbw );
+
+               $this->mTitle->resetArticleID( $newid );
+
+               # Update the page record with revision data
+               $this->updateRevisionOn( $dbw, $revision, 0 );
+
+               Article::onArticleCreate( $this->mTitle );
+               if(!$suppressRC) {
+                       RecentChange::notifyNew( $now, $this->mTitle, $isminor, $wgUser, $summary, 'default',
+                         '', strlen( $text ), $revisionId );
+               }
+
+               if ($watchthis) {
+                       if(!$this->mTitle->userIsWatching()) $this->watch();
+               } else {
+                       if ( $this->mTitle->userIsWatching() ) {
+                               $this->unwatch();
+                       }
+               }
+
+               # The talk page isn't in the regular link tables, so we need to update manually:
+               $talkns = $ns ^ 1; # talk -> normal; normal -> talk
+               $dbw->update( 'page',
+                       array( 'page_touched' => $dbw->timestamp($now) ),
+                       array( 'page_namespace' => $talkns,
+                              'page_title' => $ttl ),
+                       $fname );
+
+               # standard deferred updates
+               $this->editUpdates( $text, $summary, $isminor, $now );
+
+               $oldid = 0; # new article
+               $this->showArticle( $text, wfMsg( 'newarticle' ), false, $isminor, $now, $summary, $oldid );
+               wfProfileOut( $fname );
+       }
+
+       function getTextOfLastEditWithSectionReplacedOrAdded($section, $text, $summary = '', $edittime = NULL) {
+               $fname = 'Article::getTextOfLastEditWithSectionReplacedOrAdded';
+               if ($section != '') {
+                       if( is_null( $edittime ) ) {
+                               $rev = Revision::newFromTitle( $this->mTitle );
+                       } else {
+                               $dbw =& wfGetDB( DB_MASTER );
+                               $rev = Revision::loadFromTimestamp( $dbw, $this->mTitle, $edittime );
+                       }
+                       $oldtext = $rev->getText();
+
+                       if($section=='new') {
+                               if($summary) $subject="== {$summary} ==\n\n";
+                               $text=$oldtext."\n\n".$subject.$text;
+                       } else {
+
+                               # strip NOWIKI etc. to avoid confusion (true-parameter causes HTML
+                               # comments to be stripped as well)
+                               $striparray=array();
+                               $parser=new Parser();
+                               $parser->mOutputType=OT_WIKI;
+                               $parser->mOptions = new ParserOptions();
+                               $oldtext=$parser->strip($oldtext, $striparray, true);
+
+                               # now that we can be sure that no pseudo-sections are in the source,
+                               # split it up
+                               # Unfortunately we can't simply do a preg_replace because that might
+                               # replace the wrong section, so we have to use the section counter instead
+                               $secs=preg_split('/(^=+.+?=+|^<h[1-6].*?' . '>.*?<\/h[1-6].*?' . '>)(?!\S)/mi',
+                                 $oldtext,-1,PREG_SPLIT_DELIM_CAPTURE);
+                               $secs[$section*2]=$text."\n\n"; // replace with edited
+
+                               # section 0 is top (intro) section
+                               if($section!=0) {
+
+                                       # headline of old section - we need to go through this section
+                                       # to determine if there are any subsections that now need to
+                                       # be erased, as the mother section has been replaced with
+                                       # the text of all subsections.
+                                       $headline=$secs[$section*2-1];
+                                       preg_match( '/^(=+).+?=+|^<h([1-6]).*?' . '>.*?<\/h[1-6].*?' . '>(?!\S)/mi',$headline,$matches);
+                                       $hlevel=$matches[1];
+
+                                       # determine headline level for wikimarkup headings
+                                       if(strpos($hlevel,'=')!==false) {
+                                               $hlevel=strlen($hlevel);
+                                       }
+
+                                       $secs[$section*2-1]=''; // erase old headline
+                                       $count=$section+1;
+                                       $break=false;
+                                       while(!empty($secs[$count*2-1]) && !$break) {
+
+                                               $subheadline=$secs[$count*2-1];
+                                               preg_match(
+                                                '/^(=+).+?=+|^<h([1-6]).*?' . '>.*?<\/h[1-6].*?' . '>(?!\S)/mi',$subheadline,$matches);
+                                               $subhlevel=$matches[1];
+                                               if(strpos($subhlevel,'=')!==false) {
+                                                       $subhlevel=strlen($subhlevel);
+                                               }
+                                               if($subhlevel > $hlevel) {
+                                                       // erase old subsections
+                                                       $secs[$count*2-1]='';
+                                                       $secs[$count*2]='';
+                                               }
+                                               if($subhlevel <= $hlevel) {
+                                                       $break=true;
+                                               }
+                                               $count++;
+
+                                       }
+
+                               }
+                               $text=join('',$secs);
+                               # reinsert the stuff that we stripped out earlier
+                               $text=$parser->unstrip($text,$striparray);
+                               $text=$parser->unstripNoWiki($text,$striparray);
+                       }
+
+               }
+               return $text;
+       }
+
+       /**
+        * Change an existing article. Puts the previous version back into the old table, updates RC
+        * and all necessary caches, mostly via the deferred update array.
+        *
+        * It is possible to call this function from a command-line script, but note that you should
+        * first set $wgUser, and clean up $wgDeferredUpdates after each edit.
+        */
+       function updateArticle( $text, $summary, $minor, $watchthis, $forceBot = false, $sectionanchor = '' ) {
+               global $wgOut, $wgUser;
+               global $wgDBtransactions, $wgMwRedir;
+               global $wgUseSquid, $wgInternalServer, $wgPostCommitUpdateList, $wgUseFileCache;
+
+               $fname = 'Article::updateArticle';
+               wfProfileIn( $fname );
+               $good = true;
+
+               $isminor = ( $minor && $wgUser->isLoggedIn() );
+               if ( $this->isRedirect( $text ) ) {
+                       # Remove all content but redirect
+                       # This could be done by reconstructing the redirect from a title given by
+                       # Title::newFromRedirect(), but then we wouldn't know which synonym the user
+                       # wants to see
+                       if ( preg_match( "/^((" . $wgMwRedir->getBaseRegex() . ')[^\\n]+)/i', $text, $m ) ) {
+                               $redir = 1;
+                               $text = $m[1] . "\n";
+                       }
+               }
+               else { $redir = 0; }
+
+               $text = $this->preSaveTransform( $text );
+               $dbw =& wfGetDB( DB_MASTER );
+               $now = wfTimestampNow();
+
+               # Update article, but only if changed.
+
+               # It's important that we either rollback or complete, otherwise an attacker could
+               # overwrite cur entries by sending precisely timed user aborts. Random bored users
+               # could conceivably have the same effect, especially if cur is locked for long periods.
+               if( !$wgDBtransactions ) {
+                       $userAbort = ignore_user_abort( true );
+               }
+
+               $oldtext = $this->getContent( true );
+               $oldsize = strlen( $oldtext );
+               $newsize = strlen( $text );
+               $lastRevision = 0;
+
+               if ( 0 != strcmp( $text, $oldtext ) ) {
+                       $this->mGoodAdjustment = $this->isCountable( $text )
+                         - $this->isCountable( $oldtext );
+                       $this->mTotalAdjustment = 0;
+                       $now = wfTimestampNow();
+
+                       $lastRevision = $dbw->selectField(
+                               'page', 'page_latest', array( 'page_id' => $this->getId() ) );
+
+                       $revision = new Revision( array(
+                               'page'       => $this->getId(),
+                               'comment'    => $summary,
+                               'minor_edit' => $isminor,
+                               'text'       => $text
+                               ) );
+                       
+                       $dbw->immediateCommit();
+                       $dbw->begin();
+                       $revisionId = $revision->insertOn( $dbw );
+
+                       # Update page
+                       $ok = $this->updateRevisionOn( $dbw, $revision, $lastRevision );
+
+                       if( !$ok ) {
+                               /* Belated edit conflict! Run away!! */
+                               $good = false;
+                               $dbw->rollback();
+                       } else {
+                               # Update recentchanges and purge cache and whatnot
+                               $bot = (int)($wgUser->isBot() || $forceBot);
+                               RecentChange::notifyEdit( $now, $this->mTitle, $isminor, $wgUser, $summary,
+                                       $lastRevision, $this->getTimestamp(), $bot, '', $oldsize, $newsize,
+                                       $revisionId );
+                               Article::onArticleEdit( $this->mTitle );
+                               $dbw->commit();
+                       }
+               }
+
+               if( !$wgDBtransactions ) {
+                       ignore_user_abort( $userAbort );
+               }
+
+               if ( $good ) {
+                       if ($watchthis) {
+                               if (!$this->mTitle->userIsWatching()) $this->watch();
+                       } else {
+                               if ( $this->mTitle->userIsWatching() ) {
+                                       $this->unwatch();
+                               }
+                       }
+                       # standard deferred updates
+                       $this->editUpdates( $text, $summary, $minor, $now );
+
+
+                       $urls = array();
+                       # Template namespace
+                       # Purge all articles linking here
+                       if ( $this->mTitle->getNamespace() == NS_TEMPLATE) {
+                               $titles = $this->mTitle->getLinksTo();
+                               Title::touchArray( $titles );
+                               if ( $wgUseSquid ) {
+                                               foreach ( $titles as $title ) {
+                                                       $urls[] = $title->getInternalURL();
+                                               }
+                               }
+                       }
+
+                       # Squid updates
+                       if ( $wgUseSquid ) {
+                               $urls = array_merge( $urls, $this->mTitle->getSquidURLs() );
+                               $u = new SquidUpdate( $urls );
+                               array_push( $wgPostCommitUpdateList, $u );
+                       }
+
+                       # File cache
+                       if ( $wgUseFileCache ) {
+                               $cm = new CacheManager($this->mTitle);
+                               @unlink($cm->fileCacheName());
+                       }
+
+                       $this->showArticle( $text, wfMsg( 'updated' ), $sectionanchor, $isminor, $now, $summary, $lastRevision );
+               }
+               wfProfileOut( $fname );
+               return $good;
+       }
+
+       /**
+        * After we've either updated or inserted the article, update
+        * the link tables and redirect to the new page.
+        */
+       function showArticle( $text, $subtitle , $sectionanchor = '', $me2, $now, $summary, $oldid ) {
+               global $wgUseDumbLinkUpdate, $wgAntiLockFlags, $wgOut, $wgUser, $wgLinkCache, $wgEnotif;
+               global $wgUseEnotif;
+
+               $fname = 'Article::showArticle';
+               wfProfileIn( $fname );
+
+               $wgLinkCache = new LinkCache();
+
+               if ( !$wgUseDumbLinkUpdate ) {
+                       # Preload links to reduce lock time
+                       if ( $wgAntiLockFlags & ALF_PRELOAD_LINKS ) {
+                               $wgLinkCache->preFill( $this->mTitle );
+                               $wgLinkCache->clear();
+                       }
+               }
+
+               # Parse the text and replace links with placeholders
+               $wgOut = new OutputPage();
+
+               # Pass the current title along in case we're creating a wiki page
+               # which is different than the currently displayed one (e.g. image
+               # pages created on file uploads); otherwise, link updates will
+               # go wrong.
+               $wgOut->addWikiTextWithTitle( $text, $this->mTitle );
+
+               if ( !$wgUseDumbLinkUpdate ) {
+                       # Move the current links back to the second register
+                       $wgLinkCache->swapRegisters();
+
+                       # Get old version of link table to allow incremental link updates
+                       # Lock this data now since it is needed for an update
+                       $wgLinkCache->forUpdate( true );
+                       $wgLinkCache->preFill( $this->mTitle );
+
+                       # Swap this old version back into its rightful place
+                       $wgLinkCache->swapRegisters();
+               }
+
+               if( $this->isRedirect( $text ) )
+                       $r = 'redirect=no';
+               else
+                       $r = '';
+               $wgOut->redirect( $this->mTitle->getFullURL( $r ).$sectionanchor );
+
+               if ( $wgUseEnotif  ) {
+                       # this would be better as an extension hook
+                       include_once( "UserMailer.php" );
+                       $wgEnotif = new EmailNotification ();
+                       $wgEnotif->notifyOnPageChange( $this->mTitle, $now, $summary, $me2, $oldid );
+               }
+               wfProfileOut( $fname );
+       }
+
+       /**
+        * Mark this particular edit as patrolled
+        */
+       function markpatrolled() {
+               global $wgOut, $wgRequest, $wgOnlySysopsCanPatrol, $wgUseRCPatrol, $wgUser;
+               $wgOut->setRobotpolicy( 'noindex,follow' );
+
+               if ( !$wgUseRCPatrol )
+               {
+                       $wgOut->errorpage( 'rcpatroldisabled', 'rcpatroldisabledtext' );
+                       return;
+               }
+               if ( $wgUser->isAnon() )
+               {
+                       $wgOut->loginToUse();
+                       return;
+               }
+               if ( $wgOnlySysopsCanPatrol && !$wgUser->isAllowed('patrol') )
+               {
+                       $wgOut->sysopRequired();
+                       return;
+               }
+               $rcid = $wgRequest->getVal( 'rcid' );
+               if ( !is_null ( $rcid ) )
+               {
+                       RecentChange::markPatrolled( $rcid );
+                       $wgOut->setPagetitle( wfMsg( 'markedaspatrolled' ) );
+                       $wgOut->addWikiText( wfMsg( 'markedaspatrolledtext' ) );
+
+                       $rcTitle = Title::makeTitle( NS_SPECIAL, 'Recentchanges' );
+                       $wgOut->returnToMain( false, $rcTitle->getPrefixedText() );
+               }
+               else
+               {
+                       $wgOut->errorpage( 'markedaspatrollederror', 'markedaspatrollederrortext' );
+               }
+       }
+
+       /**
+        * Validate function
+        */
+       function validate() {
+               global $wgOut, $wgUser, $wgRequest, $wgUseValidation;
+
+               if ( !$wgUseValidation ) # Are we using article validation at all?
+               {
+                       $wgOut->errorpage( "nosuchspecialpage", "nospecialpagetext" );
+                       return ;
+               }
+
+               $wgOut->setRobotpolicy( 'noindex,follow' );
+               $revision = $wgRequest->getVal( 'revision' );
+
+               include_once ( "SpecialValidate.php" ) ; # The "Validation" class
+
+               $v = new Validation ;
+               if ( $wgRequest->getVal ( "mode" , "" ) == "list" )
+                       $t = $v->showList ( $this ) ;
+               else if ( $wgRequest->getVal ( "mode" , "" ) == "details" )
+                       $t = $v->showDetails ( $this , $wgRequest->getVal( 'revision' ) ) ;
+               else
+                       $t = $v->validatePageForm ( $this , $revision ) ;
+
+               $wgOut->addHTML ( $t ) ;
+       }
+
+       /**
+        * Add this page to $wgUser's watchlist
+        */
+
+       function watch() {
+
+               global $wgUser, $wgOut;
+
+               if ( $wgUser->isAnon() ) {
+                       $wgOut->errorpage( 'watchnologin', 'watchnologintext' );
+                       return;
+               }
+               if ( wfReadOnly() ) {
+                       $wgOut->readOnlyPage();
+                       return;
+               }
+
+               if (wfRunHooks('WatchArticle', array(&$wgUser, &$this))) {
+
+                       $wgUser->addWatch( $this->mTitle );
+                       $wgUser->saveSettings();
+
+                       wfRunHooks('WatchArticleComplete', array(&$wgUser, &$this));
+
+                       $wgOut->setPagetitle( wfMsg( 'addedwatch' ) );
+                       $wgOut->setRobotpolicy( 'noindex,follow' );
+
+                       $link = $this->mTitle->getPrefixedText();
+                       $text = wfMsg( 'addedwatchtext', $link );
+                       $wgOut->addWikiText( $text );
+               }
+
+               $wgOut->returnToMain( true, $this->mTitle->getPrefixedText() );
+       }
+
+       /**
+        * Stop watching a page
+        */
+
+       function unwatch() {
+
+               global $wgUser, $wgOut;
+
+               if ( $wgUser->isAnon() ) {
+                       $wgOut->errorpage( 'watchnologin', 'watchnologintext' );
+                       return;
+               }
+               if ( wfReadOnly() ) {
+                       $wgOut->readOnlyPage();
+                       return;
+               }
+
+               if (wfRunHooks('UnwatchArticle', array(&$wgUser, &$this))) {
+
+                       $wgUser->removeWatch( $this->mTitle );
+                       $wgUser->saveSettings();
+
+                       wfRunHooks('UnwatchArticleComplete', array(&$wgUser, &$this));
+
+                       $wgOut->setPagetitle( wfMsg( 'removedwatch' ) );
+                       $wgOut->setRobotpolicy( 'noindex,follow' );
+
+                       $link = $this->mTitle->getPrefixedText();
+                       $text = wfMsg( 'removedwatchtext', $link );
+                       $wgOut->addWikiText( $text );
+               }
+
+               $wgOut->returnToMain( true, $this->mTitle->getPrefixedText() );
+       }
+
+       /**
+        * protect a page
+        */
+       function protect( $limit = 'sysop' ) {
+               global $wgUser, $wgOut, $wgRequest;
+
+               if ( ! $wgUser->isAllowed('protect') ) {
+                       $wgOut->sysopRequired();
+                       return;
+               }
+               if ( wfReadOnly() ) {
+                       $wgOut->readOnlyPage();
+                       return;
+               }
+               $id = $this->mTitle->getArticleID();
+               if ( 0 == $id ) {
+                       $wgOut->fatalError( wfMsg( 'badarticleerror' ) );
+                       return;
+               }
+
+               $confirm = $wgRequest->wasPosted() &&
+                       $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) );
+               $moveonly = $wgRequest->getBool( 'wpMoveOnly' );
+               $reason = $wgRequest->getText( 'wpReasonProtect' );
+
+               if ( $confirm ) {
+                       $dbw =& wfGetDB( DB_MASTER );
+                       $dbw->update( 'page',
+                               array( /* SET */
+                                       'page_touched' => $dbw->timestamp(),
+                                       'page_restrictions' => (string)$limit
+                               ), array( /* WHERE */
+                                       'page_id' => $id
+                               ), 'Article::protect'
+                       );
+
+                       $restrictions = "move=" . $limit;
+                       if( !$moveonly ) {
+                               $restrictions .= ":edit=" . $limit;
+                       }
+                       if (wfRunHooks('ArticleProtect', array(&$this, &$wgUser, $limit == 'sysop', $reason, $moveonly))) {
+
+                               $dbw =& wfGetDB( DB_MASTER );
+                               $dbw->update( 'page',
+                                                         array( /* SET */
+                                                                        'page_touched' => $dbw->timestamp(),
+                                                                        'page_restrictions' => $restrictions
+                                                                        ), array( /* WHERE */
+                                                                                          'page_id' => $id
+                                                                                          ), 'Article::protect'
+                                                         );
+
+                               wfRunHooks('ArticleProtectComplete', array(&$this, &$wgUser, $limit == 'sysop', $reason, $moveonly));
+
+                               $log = new LogPage( 'protect' );
+                               if ( $limit === '' ) {
+                                       $log->addEntry( 'unprotect', $this->mTitle, $reason );
+                               } else {
+                                       $log->addEntry( 'protect', $this->mTitle, $reason );
+                               }
+                               $wgOut->redirect( $this->mTitle->getFullURL() );
+                       }
+                       return;
+               } else {
+                       return $this->confirmProtect( '', '', $limit );
+               }
+       }
+
+       /**
+        * Output protection confirmation dialog
+        */
+       function confirmProtect( $par, $reason, $limit = 'sysop'  ) {
+               global $wgOut, $wgUser;
+
+               wfDebug( "Article::confirmProtect\n" );
+
+               $sub = htmlspecialchars( $this->mTitle->getPrefixedText() );
+               $wgOut->setRobotpolicy( 'noindex,nofollow' );
+
+               $check = '';
+               $protcom = '';
+               $moveonly = '';
+
+               if ( $limit === '' ) {
+                       $wgOut->setPageTitle( wfMsg( 'confirmunprotect' ) );
+                       $wgOut->setSubtitle( wfMsg( 'unprotectsub', $sub ) );
+                       $wgOut->addWikiText( wfMsg( 'confirmunprotecttext' ) );
+                       $protcom = htmlspecialchars( wfMsg( 'unprotectcomment' ) );
+                       $formaction = $this->mTitle->escapeLocalURL( 'action=unprotect' . $par );
+               } else {
+                       $wgOut->setPageTitle( wfMsg( 'confirmprotect' ) );
+                       $wgOut->setSubtitle( wfMsg( 'protectsub', $sub ) );
+                       $wgOut->addWikiText( wfMsg( 'confirmprotecttext' ) );
+                       $moveonly = wfMsg( 'protectmoveonly' ) ; // add it using addWikiText to prevent xss. bug:3991
+                       $protcom = htmlspecialchars( wfMsg( 'protectcomment' ) );
+                       $formaction = $this->mTitle->escapeLocalURL( 'action=protect' . $par );
+               }
+
+               $confirm = htmlspecialchars( wfMsg( 'confirm' ) );
+               $token = htmlspecialchars( $wgUser->editToken() );
+
+               $wgOut->addHTML( "
+<form id='protectconfirm' method='post' action=\"{$formaction}\">
+       <table border='0'>
+               <tr>
+                       <td align='right'>
+                               <label for='wpReasonProtect'>{$protcom}:</label>
+                       </td>
+                       <td align='left'>
+                               <input type='text' size='60' name='wpReasonProtect' id='wpReasonProtect' value=\"" . htmlspecialchars( $reason ) . "\" />
+                       </td>
+               </tr>" );
+               if($moveonly != '') {
+                       $wgOut->AddHTML( "
+               <tr>
+                       <td align='right'>
+                               <input type='checkbox' name='wpMoveOnly' value='1' id='wpMoveOnly' />
+                       </td>
+                       <td align='left'>
+                               <label for='wpMoveOnly'> ");
+                       $wgOut->addWikiText( $moveonly ); // bug 3991
+                       $wgOut->addHTML( "
+                               </label>
+                       </td>
+               </tr> " );
+               }
+               $wgOut->addHTML( "
+               <tr>
+                       <td>&nbsp;</td>
+                       <td>
+                               <input type='submit' name='wpConfirmProtectB' value=\"{$confirm}\" />
+                       </td>
+               </tr>
+       </table>
+       <input type='hidden' name='wpEditToken' value=\"{$token}\" />
+</form>" );
+
+               $wgOut->returnToMain( false );
+       }
+
+       /**
+        * Unprotect the pages
+        */
+       function unprotect() {
+               return $this->protect( '' );
+       }
+
+       /*
+        * UI entry point for page deletion
+        */
+       function delete() {
+               global $wgUser, $wgOut, $wgMessageCache, $wgRequest;
+               $fname = 'Article::delete';
+               $confirm = $wgRequest->wasPosted() &&
+                       $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) );
+               $reason = $wgRequest->getText( 'wpReason' );
+
+               # This code desperately needs to be totally rewritten
+
+               # Check permissions
+               if( ( !$wgUser->isAllowed( 'delete' ) ) ) {
+                       $wgOut->sysopRequired();
+                       return;
+               }
+               if( wfReadOnly() ) {
+                       $wgOut->readOnlyPage();
+                       return;
+               }
+
+               # Better double-check that it hasn't been deleted yet!
+               $wgOut->setPagetitle( wfMsg( 'confirmdelete' ) );
+               if( !$this->mTitle->exists() ) {
+                       $wgOut->fatalError( wfMsg( 'cannotdelete' ) );
+                       return;
+               }
+
+               if( $confirm ) {
+                       $this->doDelete( $reason );
+                       return;
+               }
+
+               # determine whether this page has earlier revisions
+               # and insert a warning if it does
+               # we select the text because it might be useful below
+               $dbr =& $this->getDB();
+               $ns = $this->mTitle->getNamespace();
+               $title = $this->mTitle->getDBkey();
+               $revisions = $dbr->select( array( 'page', 'revision' ),
+                       array( 'rev_id', 'rev_user_text' ),
+                       array(
+                               'page_namespace' => $ns,
+                               'page_title' => $title,
+                               'rev_page = page_id'
+                       ), $fname, $this->getSelectOptions( array( 'ORDER BY' => 'rev_timestamp DESC' ) )
+               );
+
+               if( $dbr->numRows( $revisions ) > 1 && !$confirm ) {
+                       $skin=$wgUser->getSkin();
+                       $wgOut->addHTML('<b>'.wfMsg('historywarning'));
+                       $wgOut->addHTML( $skin->historyLink() .'</b>');
+               }
+
+               # Fetch cur_text
+               $rev = Revision::newFromTitle( $this->mTitle );
+
+               # Fetch name(s) of contributors
+               $rev_name = '';
+               $all_same_user = true;
+               while( $row = $dbr->fetchObject( $revisions ) ) {
+                       if( $rev_name != '' && $rev_name != $row->rev_user_text ) {
+                               $all_same_user = false;
+                       } else {
+                               $rev_name = $row->rev_user_text;
+                       }
+               }
+
+               if( !is_null( $rev ) ) {
+                       # if this is a mini-text, we can paste part of it into the deletion reason
+                       $text = $rev->getText();
+
+                       #if this is empty, an earlier revision may contain "useful" text
+                       $blanked = false;
+                       if( $text == '' ) {
+                               $prev = $rev->getPrevious();
+                               if( $prev ) {
+                                       $text = $prev->getText();
+                                       $blanked = true;
+                               }
+                       }
+
+                       $length = strlen( $text );
+
+                       # this should not happen, since it is not possible to store an empty, new
+                       # page. Let's insert a standard text in case it does, though
+                       if( $length == 0 && $reason === '' ) {
+                               $reason = wfMsgForContent( 'exblank' );
+                       }
+
+                       if( $length < 500 && $reason === '' ) {
+                               # comment field=255, let's grep the first 150 to have some user
+                               # space left
+                               global $wgContLang;
+                               $text = $wgContLang->truncate( $text, 150, '...' );
+
+                               # let's strip out newlines
+                               $text = preg_replace( "/[\n\r]/", '', $text );
+
+                               if( !$blanked ) {
+                                       if( !$all_same_user ) {
+                                               $reason = wfMsgForContent( 'excontent', $text );
+                                       } else {
+                                               $reason = wfMsgForContent( 'excontentauthor', $text, $rev_name );
+                                       }
+                               } else {
+                                       $reason = wfMsgForContent( 'exbeforeblank', $text );
+                               }
+                       }
+               }
+
+               return $this->confirmDelete( '', $reason );
+       }
+
+       /**
+        * Output deletion confirmation dialog
+        */
+       function confirmDelete( $par, $reason ) {
+               global $wgOut, $wgUser;
+
+               wfDebug( "Article::confirmDelete\n" );
+
+               $sub = htmlspecialchars( $this->mTitle->getPrefixedText() );
+               $wgOut->setSubtitle( wfMsg( 'deletesub', $sub ) );
+               $wgOut->setRobotpolicy( 'noindex,nofollow' );
+               $wgOut->addWikiText( wfMsg( 'confirmdeletetext' ) );
+
+               $formaction = $this->mTitle->escapeLocalURL( 'action=delete' . $par );
+
+               $confirm = htmlspecialchars( wfMsg( 'confirm' ) );
+               $delcom = htmlspecialchars( wfMsg( 'deletecomment' ) );
+               $token = htmlspecialchars( $wgUser->editToken() );
+
+               $wgOut->addHTML( "
+<form id='deleteconfirm' method='post' action=\"{$formaction}\">
+       <table border='0'>
+               <tr>
+                       <td align='right'>
+                               <label for='wpReason'>{$delcom}:</label>
+                       </td>
+                       <td align='left'>
+                               <input type='text' size='60' name='wpReason' id='wpReason' value=\"" . htmlspecialchars( $reason ) . "\" />
+                       </td>
+               </tr>
+               <tr>
+                       <td>&nbsp;</td>
+                       <td>
+                               <input type='submit' name='wpConfirmB' value=\"{$confirm}\" />
+                       </td>
+               </tr>
+       </table>
+       <input type='hidden' name='wpEditToken' value=\"{$token}\" />
+</form>\n" );
+
+               $wgOut->returnToMain( false );
+       }
+
+
+       /**
+        * Perform a deletion and output success or failure messages
+        */
+       function doDelete( $reason ) {
+               global $wgOut, $wgUser, $wgContLang;
+               $fname = 'Article::doDelete';
+               wfDebug( $fname."\n" );
+
+               if (wfRunHooks('ArticleDelete', array(&$this, &$wgUser, &$reason))) {
+                       if ( $this->doDeleteArticle( $reason ) ) {
+                               $deleted = $this->mTitle->getPrefixedText();
+
+                               $wgOut->setPagetitle( wfMsg( 'actioncomplete' ) );
+                               $wgOut->setRobotpolicy( 'noindex,nofollow' );
+
+                               $loglink = '[[Special:Log/delete|' . wfMsg( 'deletionlog' ) . ']]';
+                               $text = wfMsg( 'deletedtext', $deleted, $loglink );
+
+                               $wgOut->addWikiText( $text );
+                               $wgOut->returnToMain( false );
+                               wfRunHooks('ArticleDeleteComplete', array(&$this, &$wgUser, $reason));
+                       } else {
+                               $wgOut->fatalError( wfMsg( 'cannotdelete' ) );
+                       }
+               }
+       }
+
+       /**
+        * Back-end article deletion
+        * Deletes the article with database consistency, writes logs, purges caches
+        * Returns success
+        */
+       function doDeleteArticle( $reason ) {
+               global $wgUser;
+               global $wgUseSquid, $wgDeferredUpdateList, $wgInternalServer, $wgPostCommitUpdateList;
+               global $wgUseTrackbacks;
+
+               $fname = 'Article::doDeleteArticle';
+               wfDebug( $fname."\n" );
+
+               $dbw =& wfGetDB( DB_MASTER );
+               $ns = $this->mTitle->getNamespace();
+               $t = $this->mTitle->getDBkey();
+               $id = $this->mTitle->getArticleID();
+
+               if ( $t == '' || $id == 0 ) {
+                       return false;
+               }
+
+               $u = new SiteStatsUpdate( 0, 1, -$this->isCountable( $this->getContent( true ) ), -1 );
+               array_push( $wgDeferredUpdateList, $u );
+
+               $linksTo = $this->mTitle->getLinksTo();
+
+               # Squid purging
+               if ( $wgUseSquid ) {
+                       $urls = array(
+                               $this->mTitle->getInternalURL(),
+                               $this->mTitle->getInternalURL( 'history' )
+                       );
+
+                       $u = SquidUpdate::newFromTitles( $linksTo, $urls );
+                       array_push( $wgPostCommitUpdateList, $u );
+
+               }
+
+               # Client and file cache invalidation
+               Title::touchArray( $linksTo );
+
+
+               // For now, shunt the revision data into the archive table.
+               // Text is *not* removed from the text table; bulk storage
+               // is left intact to avoid breaking block-compression or
+               // immutable storage schemes.
+               //
+               // For backwards compatibility, note that some older archive
+               // table entries will have ar_text and ar_flags fields still.
+               //
+               // In the future, we may keep revisions and mark them with
+               // the rev_deleted field, which is reserved for this purpose.
+               $dbw->insertSelect( 'archive', array( 'page', 'revision' ),
+                       array(
+                               'ar_namespace'  => 'page_namespace',
+                               'ar_title'      => 'page_title',
+                               'ar_comment'    => 'rev_comment',
+                               'ar_user'       => 'rev_user',
+                               'ar_user_text'  => 'rev_user_text',
+                               'ar_timestamp'  => 'rev_timestamp',
+                               'ar_minor_edit' => 'rev_minor_edit',
+                               'ar_rev_id'     => 'rev_id',
+                               'ar_text_id'    => 'rev_text_id',
+                       ), array(
+                               'page_id' => $id,
+                               'page_id = rev_page'
+                       ), $fname
+               );
+
+               # Now that it's safely backed up, delete it
+               $dbw->delete( 'revision', array( 'rev_page' => $id ), $fname );
+               $dbw->delete( 'page', array( 'page_id' => $id ), $fname);
+
+               if ($wgUseTrackbacks)
+                       $dbw->delete( 'trackbacks', array( 'tb_page' => $id ), $fname );
+
+               # Clean up recentchanges entries...
+               $dbw->delete( 'recentchanges', array( 'rc_namespace' => $ns, 'rc_title' => $t ), $fname );
+
+               # Finally, clean up the link tables
+               $t = $this->mTitle->getPrefixedDBkey();
+
+               Article::onArticleDelete( $this->mTitle );
+
+               # Delete outgoing links
+               $dbw->delete( 'pagelinks', array( 'pl_from' => $id ) );
+               $dbw->delete( 'imagelinks', array( 'il_from' => $id ) );
+               $dbw->delete( 'categorylinks', array( 'cl_from' => $id ) );
+
+               # Log the deletion
+               $log = new LogPage( 'delete' );
+               $log->addEntry( 'delete', $this->mTitle, $reason );
+
+               # Clear the cached article id so the interface doesn't act like we exist
+               $this->mTitle->resetArticleID( 0 );
+               $this->mTitle->mArticleID = 0;
+               return true;
+       }
+
+       /**
+        * Revert a modification
+        */
+       function rollback() {
+               global $wgUser, $wgOut, $wgRequest;
+               $fname = 'Article::rollback';
+
+               if ( ! $wgUser->isAllowed('rollback') ) {
+                       $wgOut->sysopRequired();
+                       return;
+               }
+               if ( wfReadOnly() ) {
+                       $wgOut->readOnlyPage( $this->getContent( true ) );
+                       return;
+               }
+               if( !$wgUser->matchEditToken( $wgRequest->getVal( 'token' ),
+                       array( $this->mTitle->getPrefixedText(),
+                               $wgRequest->getVal( 'from' ) )  ) ) {
+                       $wgOut->setPageTitle( wfMsg( 'rollbackfailed' ) );
+                       $wgOut->addWikiText( wfMsg( 'sessionfailure' ) );
+                       return;
+               }
+               $dbw =& wfGetDB( DB_MASTER );
+
+               # Enhanced rollback, marks edits rc_bot=1
+               $bot = $wgRequest->getBool( 'bot' );
+
+               # Replace all this user's current edits with the next one down
+               $tt = $this->mTitle->getDBKey();
+               $n = $this->mTitle->getNamespace();
+
+               # Get the last editor, lock table exclusively
+               $dbw->begin();
+               $current = Revision::newFromTitle( $this->mTitle );
+               if( is_null( $current ) ) {
+                       # Something wrong... no page?
+                       $dbw->rollback();
+                       $wgOut->addHTML( wfMsg( 'notanarticle' ) );
+                       return;
+               }
+
+               $from = str_replace( '_', ' ', $wgRequest->getVal( 'from' ) );
+               if( $from != $current->getUserText() ) {
+                       $wgOut->setPageTitle(wfmsg('rollbackfailed'));
+                       $wgOut->addWikiText( wfMsg( 'alreadyrolled',
+                               htmlspecialchars( $this->mTitle->getPrefixedText()),
+                               htmlspecialchars( $from ),
+                               htmlspecialchars( $current->getUserText() ) ) );
+                       if( $current->getComment() != '') {
+                               $wgOut->addHTML(
+                                       wfMsg( 'editcomment',
+                                       htmlspecialchars( $current->getComment() ) ) );
+                       }
+                       return;
+               }
+
+               # Get the last edit not by this guy
+               $user = IntVal( $current->getUser() );
+               $user_text = $dbw->addQuotes( $current->getUserText() );
+               $s = $dbw->selectRow( 'revision',
+                       array( 'rev_id', 'rev_timestamp' ),
+                       array(
+                               'rev_page' => $current->getPage(),
+                               "rev_user <> {$user} OR rev_user_text <> {$user_text}"
+                       ), $fname,
+                       array(
+                               'USE INDEX' => 'page_timestamp',
+                               'ORDER BY'  => 'rev_timestamp DESC' )
+                       );
+               if( $s === false ) {
+                       # Something wrong
+                       $dbw->rollback();
+                       $wgOut->setPageTitle(wfMsg('rollbackfailed'));
+                       $wgOut->addHTML( wfMsg( 'cantrollback' ) );
+                       return;
+               }
+
+               if ( $bot ) {
+                       # Mark all reverted edits as bot
+                       $dbw->update( 'recentchanges',
+                               array( /* SET */
+                                       'rc_bot' => 1
+                               ), array( /* WHERE */
+                                       'rc_cur_id'    => $current->getPage(),
+                                       'rc_user_text' => $current->getUserText(),
+                                       "rc_timestamp > '{$s->rev_timestamp}'",
+                               ), $fname
+                       );
+               }
+
+               # Save it!
+               $target = Revision::newFromId( $s->rev_id );
+               $newcomment = wfMsgForContent( 'revertpage', $target->getUserText(), $from );
+
+               $wgOut->setPagetitle( wfMsg( 'actioncomplete' ) );
+               $wgOut->setRobotpolicy( 'noindex,nofollow' );
+               $wgOut->addHTML( '<h2>' . htmlspecialchars( $newcomment ) . "</h2>\n<hr />\n" );
+
+               $this->updateArticle( $target->getText(), $newcomment, 1, $this->mTitle->userIsWatching(), $bot );
+               Article::onArticleEdit( $this->mTitle );
+
+               $dbw->commit();
+               $wgOut->returnToMain( false );
+       }
+
+
+       /**
+        * Do standard deferred updates after page view
+        * @private
+        */
+       function viewUpdates() {
+               global $wgDeferredUpdateList, $wgUseEnotif;
+
+               if ( 0 != $this->getID() ) {
+                       global $wgDisableCounters;
+                       if( !$wgDisableCounters ) {
+                               Article::incViewCount( $this->getID() );
+                               $u = new SiteStatsUpdate( 1, 0, 0 );
+                               array_push( $wgDeferredUpdateList, $u );
+                       }
+               }
+
+               # Update newtalk status if user is reading their own
+               # talk page
+
+               if (!wfRunHooks('UserClearNewTalkNotification', array(&$this)))
+                       return;
+
+               global $wgUser;
+               if (wfRunHooks('ArticleEditUpdateNewTalk', array(&$this)) ) {
+                       if ($this->mTitle->getNamespace() == NS_USER_TALK &&
+                               $this->mTitle->getText() == $wgUser->getName())
+                       {
+
+                               if ( $wgUseEnotif ) {
+                                       require_once( 'UserTalkUpdate.php' );
+                                       $u = new UserTalkUpdate( 0, $this->mTitle->getNamespace(),
+                                               $this->mTitle->getDBkey(), false, false, false );
+                               } else {
+                                       $wgUser->setNewtalk(0);
+                                       $wgUser->saveNewtalk();
+                               }
+                       } elseif ( $wgUseEnotif ) {
+                               $wgUser->clearNotification( $this->mTitle );
+                       }
+               }
+       }
+
+       /**
+        * Do standard deferred updates after page edit.
+        * Every 1000th edit, prune the recent changes table.
+        * @private
+        * @param string $text
+        */
+       function editUpdates( $text, $summary, $minoredit, $timestamp_of_pagechange) {
+               global $wgDeferredUpdateList, $wgDBname, $wgMemc;
+               global $wgMessageCache, $wgUser, $wgUseEnotif;
+
+               wfSeedRandom();
+               if ( 0 == mt_rand( 0, 999 ) ) {
+                       # Periodically flush old entries from the recentchanges table.
+                       global $wgRCMaxAge;
+                       $dbw =& wfGetDB( DB_MASTER );
+                       $cutoff = $dbw->timestamp( time() - $wgRCMaxAge );
+                       $recentchanges = $dbw->tableName( 'recentchanges' );
+                       $sql = "DELETE FROM $recentchanges WHERE rc_timestamp < '{$cutoff}'";
+                       //$dbw->query( $sql ); // HACK: disabled for now, slowness
+
+                       // re-enabled for commit of unrelated live changes -- TS
+                       $dbw->query( $sql );
+               }
+               $id = $this->getID();
+               $title = $this->mTitle->getPrefixedDBkey();
+               $shortTitle = $this->mTitle->getDBkey();
+
+               if ( 0 != $id ) {
+                       $u = new LinksUpdate( $id, $title );
+                       array_push( $wgDeferredUpdateList, $u );
+                       $u = new SiteStatsUpdate( 0, 1, $this->mGoodAdjustment, $this->mTotalAdjustment );
+                       array_push( $wgDeferredUpdateList, $u );
+                       $u = new SearchUpdate( $id, $title, $text );
+                       array_push( $wgDeferredUpdateList, $u );
+
+                       # If this is another user's talk page, update newtalk
+
+                       if ($this->mTitle->getNamespace() == NS_USER_TALK && $shortTitle != $wgUser->getName()) {
+                               if ( $wgUseEnotif ) {
+                                       require_once( 'UserTalkUpdate.php' );
+                                       $u = new UserTalkUpdate( 1, $this->mTitle->getNamespace(), $shortTitle, $summary,
+                                         $minoredit, $timestamp_of_pagechange);
+                               } else {
+                                       $other = User::newFromName( $shortTitle );
+                                       if( is_null( $other ) && User::isIP( $shortTitle ) ) {
+                                               // An anonymous user
+                                               $other = new User();
+                                               $other->setName( $shortTitle );
+                                       }
+                                       if( $other ) {
+                                               $other->setNewtalk(1);
+                                               $other->saveNewtalk();
+                                       }
+                               }
+                       }
+
+                       if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
+                               $wgMessageCache->replace( $shortTitle, $text );
+                       }
+               }
+       }
+
+       /**
+        * Generate the navigation links when browsing through an article revisions
+        * It shows the information as:
+        *   Revision as of <date>; view current revision
+        *   <- Previous version | Next Version ->
+        *
+        * @access private
+        * @param string $oldid         Revision ID of this article revision
+        */
+       function setOldSubtitle( $oldid=0 ) {
+               global $wgLang, $wgOut, $wgUser;
+
+               $current = ( $oldid == $this->mLatest );
+               $td = $wgLang->timeanddate( $this->mTimestamp, true );
+               $sk = $wgUser->getSkin();
+               $lnk = $current
+                       ? wfMsg( 'currentrevisionlink' )
+                       : $lnk = $sk->makeKnownLinkObj( $this->mTitle, wfMsg( 'currentrevisionlink' ) );
+               $prev = $this->mTitle->getPreviousRevisionID( $oldid ) ;
+               $prevlink = $prev
+                       ? $sk->makeKnownLinkObj( $this->mTitle, wfMsg( 'previousrevision' ), 'direction=prev&oldid='.$oldid )
+                       : wfMsg( 'previousrevision' );
+               $nextlink = $current
+                       ? wfMsg( 'nextrevision' )
+                       : $sk->makeKnownLinkObj( $this->mTitle, wfMsg( 'nextrevision' ), 'direction=next&oldid='.$oldid );
+               $r = wfMsg( 'revisionasofwithlink', $td, $lnk, $prevlink, $nextlink );
+               $wgOut->setSubtitle( $r );
+       }
+
+       /**
+        * This function is called right before saving the wikitext,
+        * so we can do things like signatures and links-in-context.
+        *
+        * @param string $text
+        */
+       function preSaveTransform( $text ) {
+               global $wgParser, $wgUser;
+               return $wgParser->preSaveTransform( $text, $this->mTitle, $wgUser, ParserOptions::newFromUser( $wgUser ) );
+       }
+
+       /* Caching functions */
+
+       /**
+        * checkLastModified returns true if it has taken care of all
+        * output to the client that is necessary for this request.
+        * (that is, it has sent a cached version of the page)
+        */
+       function tryFileCache() {
+               static $called = false;
+               if( $called ) {
+                       wfDebug( " tryFileCache() -- called twice!?\n" );
+                       return;
+               }
+               $called = true;
+               if($this->isFileCacheable()) {
+                       $touched = $this->mTouched;
+                       $cache = new CacheManager( $this->mTitle );
+                       if($cache->isFileCacheGood( $touched )) {
+                               global $wgOut;
+                               wfDebug( " tryFileCache() - about to load\n" );
+                               $cache->loadFromFileCache();
+                               return true;
+                       } else {
+                               wfDebug( " tryFileCache() - starting buffer\n" );
+                               ob_start( array(&$cache, 'saveToFileCache' ) );
+                       }
+               } else {
+                       wfDebug( " tryFileCache() - not cacheable\n" );
+               }
+       }
+
+       /**
+        * Check if the page can be cached
+        * @return bool
+        */
+       function isFileCacheable() {
+               global $wgUser, $wgUseFileCache, $wgShowIPinHeader, $wgRequest;
+               extract( $wgRequest->getValues( 'action', 'oldid', 'diff', 'redirect', 'printable' ) );
+
+               return $wgUseFileCache
+                       and (!$wgShowIPinHeader)
+                       and ($this->getID() != 0)
+                       and ($wgUser->isAnon())
+                       and (!$wgUser->getNewtalk())
+                       and ($this->mTitle->getNamespace() != NS_SPECIAL )
+                       and (empty( $action ) || $action == 'view')
+                       and (!isset($oldid))
+                       and (!isset($diff))
+                       and (!isset($redirect))
+                       and (!isset($printable))
+                       and (!$this->mRedirectedFrom);
+       }
+
+       /**
+        * Loads cur_touched and returns a value indicating if it should be used
+        *
+        */
+       function checkTouched() {
+               $fname = 'Article::checkTouched';
+               if( !$this->mDataLoaded ) {
+                       $dbr =& $this->getDB();
+                       $data = $this->pageDataFromId( $dbr, $this->getId() );
+                       if( $data ) {
+                               $this->loadPageData( $data );
+                       }
+               }
+               return !$this->mIsRedirect;
+       }
+
+       /**
+        * Edit an article without doing all that other stuff
+        * The article must already exist; link tables etc
+        * are not updated, caches are not flushed.
+        *
+        * @param string $text text submitted
+        * @param string $comment comment submitted
+        * @param bool $minor whereas it's a minor modification
+        */
+       function quickEdit( $text, $comment = '', $minor = 0 ) {
+               $fname = 'Article::quickEdit';
+               wfProfileIn( $fname );
+
+               $dbw =& wfGetDB( DB_MASTER );
+               $dbw->begin();
+               $revision = new Revision( array(
+                       'page'       => $this->getId(),
+                       'text'       => $text,
+                       'comment'    => $comment,
+                       'minor_edit' => $minor ? 1 : 0,
+                       ) );
+               $revisionId = $revision->insertOn( $dbw );
+               $this->updateRevisionOn( $dbw, $revision );
+               $dbw->commit();
+
+               wfProfileOut( $fname );
+       }
+
+       /**
+        * Used to increment the view counter
+        *
+        * @static
+        * @param integer $id article id
+        */
+       function incViewCount( $id ) {
+               $id = intval( $id );
+               global $wgHitcounterUpdateFreq;
+
+               $dbw =& wfGetDB( DB_MASTER );
+               $pageTable = $dbw->tableName( 'page' );
+               $hitcounterTable = $dbw->tableName( 'hitcounter' );
+               $acchitsTable = $dbw->tableName( 'acchits' );
+
+               if( $wgHitcounterUpdateFreq <= 1 ){ //
+                       $dbw->query( "UPDATE $pageTable SET page_counter = page_counter + 1 WHERE page_id = $id" );
+                       return;
+               }
+
+               # Not important enough to warrant an error page in case of failure
+               $oldignore = $dbw->ignoreErrors( true );
+
+               $dbw->query( "INSERT INTO $hitcounterTable (hc_id) VALUES ({$id})" );
+
+               $checkfreq = intval( $wgHitcounterUpdateFreq/25 + 1 );
+               if( (rand() % $checkfreq != 0) or ($dbw->lastErrno() != 0) ){
+                       # Most of the time (or on SQL errors), skip row count check
+                       $dbw->ignoreErrors( $oldignore );
+                       return;
+               }
+
+               $res = $dbw->query("SELECT COUNT(*) as n FROM $hitcounterTable");
+               $row = $dbw->fetchObject( $res );
+               $rown = intval( $row->n );
+               if( $rown >= $wgHitcounterUpdateFreq ){
+                       wfProfileIn( 'Article::incViewCount-collect' );
+                       $old_user_abort = ignore_user_abort( true );
+
+                       $dbw->query("LOCK TABLES $hitcounterTable WRITE");
+                       $dbw->query("CREATE TEMPORARY TABLE $acchitsTable TYPE=HEAP ".
+                               "SELECT hc_id,COUNT(*) AS hc_n FROM $hitcounterTable ".
+                               'GROUP BY hc_id');
+                       $dbw->query("DELETE FROM $hitcounterTable");
+                       $dbw->query('UNLOCK TABLES');
+                       $dbw->query("UPDATE $pageTable,$acchitsTable SET page_counter=page_counter + hc_n ".
+                               'WHERE page_id = hc_id');
+                       $dbw->query("DROP TABLE $acchitsTable");
+
+                       ignore_user_abort( $old_user_abort );
+                       wfProfileOut( 'Article::incViewCount-collect' );
+               }
+               $dbw->ignoreErrors( $oldignore );
+       }
+
+       /**#@+
+        * The onArticle*() functions are supposed to be a kind of hooks
+        * which should be called whenever any of the specified actions
+        * are done.
+        *
+        * This is a good place to put code to clear caches, for instance.
+        *
+        * This is called on page move and undelete, as well as edit
+        * @static
+        * @param $title_obj a title object
+        */
+
+       function onArticleCreate($title_obj) {
+               global $wgUseSquid, $wgPostCommitUpdateList;
+
+               $title_obj->touchLinks();
+               $titles = $title_obj->getLinksTo();
+
+               # Purge squid
+               if ( $wgUseSquid ) {
+                       $urls = $title_obj->getSquidURLs();
+                       foreach ( $titles as $linkTitle ) {
+                               $urls[] = $linkTitle->getInternalURL();
+                       }
+                       $u = new SquidUpdate( $urls );
+                       array_push( $wgPostCommitUpdateList, $u );
+               }
+       }
+
+       function onArticleDelete( $title ) {
+               global $wgMessageCache;
+               
+               $title->touchLinks();
+               
+               if( $title->getNamespace() == NS_MEDIAWIKI) {
+                       $wgMessageCache->replace( $title->getDBkey(), false );
+               }
+       }
+
+       function onArticleEdit($title_obj) {
+               // This would be an appropriate place to purge caches.
+               // Why's this not in here now?
+       }
+
+       /**#@-*/
+
+       /**
+        * Info about this page
+        * Called for ?action=info when $wgAllowPageInfo is on.
+        *
+        * @access public
+        */
+       function info() {
+               global $wgLang, $wgOut, $wgAllowPageInfo;
+               $fname = 'Article::info';
+
+               if ( !$wgAllowPageInfo ) {
+                       $wgOut->errorpage( 'nosuchaction', 'nosuchactiontext' );
+                       return;
+               }
+
+               $page = $this->mTitle->getSubjectPage();
+
+               $wgOut->setPagetitle( $page->getPrefixedText() );
+               $wgOut->setSubtitle( wfMsg( 'infosubtitle' ));
+
+               # first, see if the page exists at all.
+               $exists = $page->getArticleId() != 0;
+               if( !$exists ) {
+                       $wgOut->addHTML( wfMsg('noarticletext') );
+               } else {
+                       $dbr =& $this->getDB( DB_SLAVE );
+                       $wl_clause = array(
+                               'wl_title'     => $page->getDBkey(),
+                               'wl_namespace' => $page->getNamespace() );
+                       $numwatchers = $dbr->selectField(
+                               'watchlist',
+                               'COUNT(*)',
+                               $wl_clause,
+                               $fname,
+                               $this->getSelectOptions() );
+
+                       $pageInfo = $this->pageCountInfo( $page );
+                       $talkInfo = $this->pageCountInfo( $page->getTalkPage() );
+
+                       $wgOut->addHTML( "<ul><li>" . wfMsg("numwatchers", $wgLang->formatNum( $numwatchers ) ) . '</li>' );
+                       $wgOut->addHTML( "<li>" . wfMsg('numedits', $wgLang->formatNum( $pageInfo['edits'] ) ) . '</li>');
+                       if( $talkInfo ) {
+                               $wgOut->addHTML( '<li>' . wfMsg("numtalkedits", $wgLang->formatNum( $talkInfo['edits'] ) ) . '</li>');
+                       }
+                       $wgOut->addHTML( '<li>' . wfMsg("numauthors", $wgLang->formatNum( $pageInfo['authors'] ) ) . '</li>' );
+                       if( $talkInfo ) {
+                               $wgOut->addHTML( '<li>' . wfMsg('numtalkauthors', $wgLang->formatNum( $talkInfo['authors'] ) ) . '</li>' );
+                       }
+                       $wgOut->addHTML( '</ul>' );
+
+               }
+       }
+
+       /**
+        * Return the total number of edits and number of unique editors
+        * on a given page. If page does not exist, returns false.
+        *
+        * @param Title $title
+        * @return array
+        * @access private
+        */
+       function pageCountInfo( $title ) {
+               $id = $title->getArticleId();
+               if( $id == 0 ) {
+                       return false;
+               }
+
+               $dbr =& $this->getDB( DB_SLAVE );
+
+               $rev_clause = array( 'rev_page' => $id );
+               $fname = 'Article::pageCountInfo';
+
+               $edits = $dbr->selectField(
+                       'revision',
+                       'COUNT(rev_page)',
+                       $rev_clause,
+                       $fname,
+                       $this->getSelectOptions() );
+
+               $authors = $dbr->selectField(
+                       'revision',
+                       'COUNT(DISTINCT rev_user_text)',
+                       $rev_clause,
+                       $fname,
+                       $this->getSelectOptions() );
+
+               return array( 'edits' => $edits, 'authors' => $authors );
+       }
+
+       /**
+        * Return a list of templates used by this article.
+        * Uses the links table to find the templates
+        *
+        * @return array
+        */
+       function getUsedTemplates() {
+               $result = array();
+               $id = $this->mTitle->getArticleID();
+
+               $db =& wfGetDB( DB_SLAVE );
+               $res = $db->select( array( 'pagelinks' ),
+                       array( 'pl_title' ),
+                       array(
+                               'pl_from' => $id,
+                               'pl_namespace' => NS_TEMPLATE ),
+                       'Article:getUsedTemplates' );
+               if ( false !== $res ) {
+                       if ( $db->numRows( $res ) ) {
+                               while ( $row = $db->fetchObject( $res ) ) {
+                                       $result[] = $row->pl_title;
+                               }
+                       }
+               }
+               $db->freeResult( $res );
+               return $result;
+       }
+}
+
+?>
diff --git a/includes/AuthPlugin.php b/includes/AuthPlugin.php
new file mode 100644 (file)
index 0000000..bc15f30
--- /dev/null
@@ -0,0 +1,223 @@
+<?php
+/**
+ * @package MediaWiki
+ */
+# Copyright (C) 2004 Brion Vibber <brion@pobox.com>
+# http://www.mediawiki.org/
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or 
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# http://www.gnu.org/copyleft/gpl.html
+
+/**
+ * Authentication plugin interface. Instantiate a subclass of AuthPlugin
+ * and set $wgAuth to it to authenticate against some external tool.
+ *
+ * The default behavior is not to do anything, and use the local user
+ * database for all authentication. A subclass can require that all
+ * accounts authenticate externally, or use it only as a fallback; also
+ * you can transparently create internal wiki accounts the first time
+ * someone logs in who can be authenticated externally.
+ *
+ * This interface is new, and might change a bit before 1.4.0 final is
+ * done...
+ *
+ * @package MediaWiki
+ */
+class AuthPlugin {
+       /**
+        * Check whether there exists a user account with the given name.
+        * The name will be normalized to MediaWiki's requirements, so
+        * you might need to munge it (for instance, for lowercase initial
+        * letters).
+        *
+        * @param string $username
+        * @return bool
+        * @access public
+        */
+       function userExists( $username ) {
+               # Override this!
+               return false;
+       }
+       
+       /**
+        * Check if a username+password pair is a valid login.
+        * The name will be normalized to MediaWiki's requirements, so
+        * you might need to munge it (for instance, for lowercase initial
+        * letters).
+        *
+        * @param string $username
+        * @param string $password
+        * @return bool
+        * @access public
+        */
+       function authenticate( $username, $password ) {
+               # Override this!
+               return false;
+       }
+       
+       /**
+        * Modify options in the login template.
+        *
+        * @param UserLoginTemplate $template
+        * @access public
+        */
+       function modifyUITemplate( &$template ) {
+               # Override this!
+               $template->set( 'usedomain', false );
+       }
+
+       /**
+        * Set the domain this plugin is supposed to use when authenticating.
+        *
+        * @param string $domain
+        * @access public
+        */
+       function setDomain( $domain ) {
+               $this->domain = $domain;
+       }
+
+       /**
+        * Check to see if the specific domain is a valid domain.
+        *
+        * @param string $domain
+        * @return bool
+        * @access public
+        */
+       function validDomain( $domain ) {
+               # Override this!
+               return true;
+       }
+
+       /**
+        * When a user logs in, optionally fill in preferences and such.
+        * For instance, you might pull the email address or real name from the
+        * external user database.
+        *
+        * The User object is passed by reference so it can be modified; don't
+        * forget the & on your function declaration.
+        *
+        * @param User $user
+        * @access public
+        */
+       function updateUser( &$user ) {
+               # Override this and do something
+               return true;
+       }
+
+
+       /**
+        * Return true if the wiki should create a new local account automatically
+        * when asked to login a user who doesn't exist locally but does in the
+        * external auth database.
+        *
+        * If you don't automatically create accounts, you must still create
+        * accounts in some way. It's not possible to authenticate without
+        * a local account.
+        *
+        * This is just a question, and shouldn't perform any actions.
+        *
+        * @return bool
+        * @access public
+        */
+       function autoCreate() {
+               return false;
+       }
+       
+       /**
+        * Set the given password in the authentication database.
+        * Return true if successful.
+        *
+        * @param string $password
+        * @return bool
+        * @access public
+        */
+       function setPassword( $password ) {
+               return true;
+       }
+
+       /**
+        * Update user information in the external authentication database.
+        * Return true if successful.
+        *
+        * @param User $user
+        * @return bool
+        * @access public
+        */
+       function updateExternalDB( $user ) {
+               return true;
+       }
+
+       /**
+        * Check to see if external accounts can be created.
+        * Return true if external accounts can be created.
+        * @return bool
+        * @access public
+        */
+       function canCreateAccounts() {
+               return false;
+       }
+
+       /**
+        * Add a user to the external authentication database.
+        * Return true if successful.
+        *
+        * @param User $user
+        * @param string $password
+        * @return bool
+        * @access public
+        */
+       function addUser( $user, $password ) {
+               return true;
+       }
+
+
+       /**
+        * Return true to prevent logins that don't authenticate here from being
+        * checked against the local database's password fields.
+        *
+        * This is just a question, and shouldn't perform any actions.
+        *
+        * @return bool
+        * @access public
+        */
+       function strict() {
+               return false;
+       }
+       
+       /**
+        * When creating a user account, optionally fill in preferences and such.
+        * For instance, you might pull the email address or real name from the
+        * external user database.
+        *
+        * The User object is passed by reference so it can be modified; don't
+        * forget the & on your function declaration.
+        *
+        * @param User $user
+        * @access public
+        */
+       function initUser( &$user ) {
+               # Override this to do something.
+       }
+       
+       /**
+        * If you want to munge the case of an account name before the final
+        * check, now is your chance.
+        */
+       function getCanonicalName( $username ) {
+               return $username;
+       }
+}
+
+?>
diff --git a/includes/BagOStuff.php b/includes/BagOStuff.php
new file mode 100644 (file)
index 0000000..9ac3064
--- /dev/null
@@ -0,0 +1,498 @@
+<?php
+#
+# Copyright (C) 2003-2004 Brion Vibber <brion@pobox.com>
+# http://www.mediawiki.org/
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or 
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# http://www.gnu.org/copyleft/gpl.html
+/**
+ *
+ * @package MediaWiki
+ */
+/**
+ * Simple generic object store
+ *
+ * interface is intended to be more or less compatible with
+ * the PHP memcached client.
+ *
+ * backends for local hash array and SQL table included:
+ * $bag = new HashBagOStuff();
+ * $bag = new MysqlBagOStuff($tablename); # connect to db first
+ *
+ * @package MediaWiki
+ * @abstract
+ */
+class BagOStuff {
+       var $debugmode;
+       
+       function BagOStuff() {
+               $this->set_debug( false );
+       }
+       
+       function set_debug($bool) {
+               $this->debugmode = $bool;
+       }
+       
+       /* *** THE GUTS OF THE OPERATION *** */
+       /* Override these with functional things in subclasses */
+       
+       function get($key) {
+               /* stub */
+               return false;
+       }
+
+       function set($key, $value, $exptime=0) {
+               /* stub */
+               return false;
+       }
+       
+       function delete($key, $time=0) {
+               /* stub */
+               return false;
+       }
+       
+       function lock($key, $timeout = 0) {
+               /* stub */
+               return true;
+       }
+
+       function unlock($key) {
+               /* stub */
+               return true;
+       }
+       
+       /* *** Emulated functions *** */
+       /* Better performance can likely be got with custom written versions */
+       function get_multi($keys) {
+               $out = array();
+               foreach($keys as $key)
+                       $out[$key] = $this->get($key);
+               return $out;
+       }
+       
+       function set_multi($hash, $exptime=0) {
+               foreach($hash as $key => $value)
+                       $this->set($key, $value, $exptime);
+       }
+       
+       function add($key, $value, $exptime=0) {
+               if( $this->get($key) == false ) {
+                       $this->set($key, $value, $exptime);
+                       return true;
+               }
+       }
+       
+       function add_multi($hash, $exptime=0) {
+               foreach($hash as $key => $value)
+                       $this->add($key, $value, $exptime);
+       }
+
+       function delete_multi($keys, $time=0) {
+               foreach($keys as $key)
+                       $this->delete($key, $time);
+       }
+       
+       function replace($key, $value, $exptime=0) {
+               if( $this->get($key) !== false )
+                       $this->set($key, $value, $exptime);
+       }
+       
+       function incr($key, $value=1) {
+               if ( !$this->lock($key) ) {
+                       return false;
+               }
+               $value = intval($value);
+               if($value < 0) $value = 0;
+
+               $n = false;
+               if( ($n = $this->get($key)) !== false ) {
+                       $n += $value;
+                       $this->set($key, $n); // exptime?
+               }
+               $this->unlock($key);
+               return $n;
+       }
+       
+       function decr($key, $value=1) {
+               if ( !$this->lock($key) ) {
+                       return false;
+               }
+               $value = intval($value);
+               if($value < 0) $value = 0;
+
+               $m = false;
+               if( ($n = $this->get($key)) !== false ) {
+                       $m = $n - $value;
+                       if($m < 0) $m = 0;
+                       $this->set($key, $m); // exptime?
+               }
+               $this->unlock($key);
+               return $m;
+       }
+       
+       function _debug($text) {
+               if($this->debugmode)
+                       wfDebug("BagOStuff debug: $text\n");
+       }
+}
+
+
+/**
+ * Functional versions!
+ * @todo document
+ * @package MediaWiki
+ */
+class HashBagOStuff extends BagOStuff {
+       /*
+          This is a test of the interface, mainly. It stores
+          things in an associative array, which is not going to
+          persist between program runs.
+       */
+       var $bag;
+       
+       function HashBagOStuff() {
+               $this->bag = array();
+       }
+       
+       function _expire($key) {
+               $et = $this->bag[$key][1];
+               if(($et == 0) || ($et > time()))
+                       return false;
+               $this->delete($key);
+               return true;
+       }
+       
+       function get($key) {
+               if(!$this->bag[$key])
+                       return false;
+               if($this->_expire($key))
+                       return false;
+               return $this->bag[$key][0];
+       }
+       
+       function set($key,$value,$exptime=0) {
+               if(($exptime != 0) && ($exptime < 3600*24*30))
+                       $exptime = time() + $exptime;
+               $this->bag[$key] = array( $value, $exptime );
+       }
+       
+       function delete($key,$time=0) {
+               if(!$this->bag[$key])
+                       return false;
+               unset($this->bag[$key]);
+               return true;
+       }
+}
+
+/*
+CREATE TABLE objectcache (
+  keyname char(255) binary not null default '',
+  value mediumblob,
+  exptime datetime,
+  unique key (keyname),
+  key (exptime)
+);
+*/
+
+/**
+ * @todo document
+ * @abstract
+ * @package MediaWiki
+ */
+class SqlBagOStuff extends BagOStuff {
+       var $table;
+       var $lastexpireall = 0;
+
+       function SqlBagOStuff($tablename = 'objectcache') {
+               $this->table = $tablename;
+       }
+       
+       function get($key) {
+               /* expire old entries if any */
+               $this->garbageCollect();
+               
+               $res = $this->_query(
+                       "SELECT value,exptime FROM $0 WHERE keyname='$1'", $key);
+               if(!$res) {
+                       $this->_debug("get: ** error: " . $this->_dberror($res) . " **");
+                       return false;
+               }
+               if($row=$this->_fetchobject($res)) {
+                       $this->_debug("get: retrieved data; exp time is " . $row->exptime);
+                       return $this->_unserialize($row->value);
+               } else {
+                       $this->_debug('get: no matching rows');
+               }
+               return false;
+       }
+       
+       function set($key,$value,$exptime=0) {
+               $exptime = intval($exptime);
+               if($exptime < 0) $exptime = 0;
+               if($exptime == 0) {
+                       $exp = $this->_maxdatetime();
+               } else {
+                       if($exptime < 3600*24*30)
+                               $exptime += time();
+                       $exp = $this->_fromunixtime($exptime);
+               }
+               $this->delete( $key );
+               $this->_query(
+                       "INSERT INTO $0 (keyname,value,exptime) VALUES('$1','$2','$exp')",
+                       $key, $this->_serialize($value));
+               return true; /* ? */
+       }
+       
+       function delete($key,$time=0) {
+               $this->_query(
+                       "DELETE FROM $0 WHERE keyname='$1'", $key );
+               return true; /* ? */
+       }
+       
+       function getTableName() {
+               return $this->table;
+       }
+       
+       function _query($sql) {
+               $reps = func_get_args();
+               $reps[0] = $this->getTableName();
+               // ewwww
+               for($i=0;$i<count($reps);$i++) {
+                       $sql = str_replace(
+                               '$' . $i,
+                               $this->_strencode($reps[$i]),
+                               $sql);
+               }
+               $res = $this->_doquery($sql);
+               if($res == false) {
+                       $this->_debug('query failed: ' . $this->_dberror($res));
+               }
+               return $res;
+       }
+       
+       function _strencode($str) {
+               /* Protect strings in SQL */
+               return str_replace( "'", "''", $str );
+       }
+       
+       function _doquery($sql) {
+               die( 'abstract function SqlBagOStuff::_doquery() must be defined' );
+       }
+       
+       function _fetchrow($res) {
+               die( 'abstract function SqlBagOStuff::_fetchrow() must be defined' );
+       }
+       
+       function _freeresult($result) {
+               /* stub */
+               return false;
+       }
+       
+       function _dberror($result) {
+               /* stub */
+               return 'unknown error';
+       }
+       
+       function _maxdatetime() {
+               die( 'abstract function SqlBagOStuff::_maxdatetime() must be defined' );
+       }
+       
+       function _fromunixtime() {
+               die( 'abstract function SqlBagOStuff::_fromunixtime() must be defined' );
+       }
+       
+       function garbageCollect() {
+               /* Ignore 99% of requests */
+               if ( !mt_rand( 0, 100 ) ) {
+                       $nowtime = time();
+                       /* Avoid repeating the delete within a few seconds */
+                       if ( $nowtime > ($this->lastexpireall + 1) ) {
+                               $this->lastexpireall = $nowtime;
+                               $this->expireall();
+                       }
+               }
+       }
+       
+       function expireall() {
+               /* Remove any items that have expired */
+               $now = $this->_fromunixtime( time() );
+               $this->_query( "DELETE FROM $0 WHERE exptime<'$now'" );
+       }
+       
+       function deleteall() {
+               /* Clear *all* items from cache table */
+               $this->_query( "DELETE FROM $0" );
+       }
+       
+       /**
+        * Serialize an object and, if possible, compress the representation.
+        * On typical message and page data, this can provide a 3X decrease
+        * in storage requirements.
+        *
+        * @param mixed $data
+        * @return string
+        */
+       function _serialize( &$data ) {
+               $serial = serialize( $data );
+               if( function_exists( 'gzdeflate' ) ) {
+                       return gzdeflate( $serial );
+               } else {
+                       return $serial;
+               }
+       }
+       
+       /**
+        * Unserialize and, if necessary, decompress an object.
+        * @param string $serial
+        * @return mixed
+        */
+       function _unserialize( $serial ) {
+               if( function_exists( 'gzinflate' ) ) {
+                       $decomp = @gzinflate( $serial );
+                       if( false !== $decomp ) {
+                               $serial = $decomp;
+                       }
+               }
+               return unserialize( $serial );
+       }
+}
+
+/**
+ * @todo document
+ * @package MediaWiki
+ */
+class MediaWikiBagOStuff extends SqlBagOStuff {
+       var $tableInitialised = false;
+
+       function _doquery($sql) {
+               $dbw =& wfGetDB( DB_MASTER );
+               return $dbw->query($sql, 'MediaWikiBagOStuff:_doquery');
+       }
+       function _fetchobject($result) {
+               $dbw =& wfGetDB( DB_MASTER );
+               return $dbw->fetchObject($result);
+       }
+       function _freeresult($result) {
+               $dbw =& wfGetDB( DB_MASTER );
+               return $dbw->freeResult($result);
+       }
+       function _dberror($result) {
+               $dbw =& wfGetDB( DB_MASTER );
+               return $dbw->lastError();
+       }
+       function _maxdatetime() {
+               return '9999-12-31 12:59:59';
+       }
+       function _fromunixtime($ts) {
+               return gmdate( 'Y-m-d H:i:s', $ts );
+       }
+       function _strencode($s) {
+               $dbw =& wfGetDB( DB_MASTER );
+               return $dbw->strencode($s);
+       }
+       function getTableName() {
+               if ( !$this->tableInitialised ) {
+                       $dbw =& wfGetDB( DB_MASTER );
+                       $this->table = $dbw->tableName( $this->table );
+                       $this->tableInitialised = true;
+               }
+               return $this->table;
+       }
+}
+
+/**
+ * This is a wrapper for Turck MMCache's shared memory functions. 
+ * 
+ * You can store objects with mmcache_put() and mmcache_get(), but Turck seems 
+ * to use a weird custom serializer that randomly segfaults. So we wrap calls 
+ * with serialize()/unserialize().
+ * 
+ * The thing I noticed about the Turck serialized data was that unlike ordinary
+ * serialize(), it contained the names of methods, and judging by the amount of 
+ * binary data, perhaps even the bytecode of the methods themselves. It may be 
+ * that Turck's serializer is faster, so a possible future extension would be 
+ * to use it for arrays but not for objects.
+ *
+ * @package MediaWiki
+ */
+class TurckBagOStuff extends BagOStuff {
+       function get($key) {
+               $val = mmcache_get( $key );
+               if ( is_string( $val ) ) {
+                       $val = unserialize( $val );
+               }
+               return $val;
+       }
+
+       function set($key, $value, $exptime=0) {
+               mmcache_put( $key, serialize( $value ), $exptime );
+               return true;
+       }
+       
+       function delete($key, $time=0) {
+               mmcache_rm( $key );
+               return true;
+       }
+
+       function lock($key, $waitTimeout = 0 ) {
+               mmcache_lock( $key );
+               return true;
+       }
+
+       function unlock($key) {
+               mmcache_unlock( $key );
+               return true;
+       }
+}      
+
+/**
+ * This is a wrapper for eAccelerator's shared memory functions. 
+ * 
+ * This is basically identical to the Turck MMCache version,
+ * mostly because eAccelerator is based on Turck MMCache.
+ *
+ * @package MediaWiki
+ */
+class eAccelBagOStuff extends BagOStuff {
+       function get($key) {
+               $val = eaccelerator_get( $key );
+               if ( is_string( $val ) ) {
+                       $val = unserialize( $val );
+               }
+               return $val;
+       }
+
+       function set($key, $value, $exptime=0) {
+               eaccelerator_put( $key, serialize( $value ), $exptime );
+               return true;
+       }
+       
+       function delete($key, $time=0) {
+               eaccelerator_rm( $key );
+               return true;
+       }
+
+       function lock($key, $waitTimeout = 0 ) {
+               eaccelerator_lock( $key );
+               return true;
+       }
+
+       function unlock($key) {
+               eaccelerator_unlock( $key );
+               return true;
+       }
+}      
+?>
diff --git a/includes/Block.php b/includes/Block.php
new file mode 100644 (file)
index 0000000..d25d16e
--- /dev/null
@@ -0,0 +1,339 @@
+<?php
+/**
+ * Blocks and bans object
+ * @package MediaWiki
+ */
+
+/**
+ * Some globals
+ */
+define ( 'EB_KEEP_EXPIRED', 1 );
+define ( 'EB_FOR_UPDATE', 2 );
+
+/**
+ * The block class
+ * All the functions in this class assume the object is either explicitly 
+ * loaded or filled. It is not load-on-demand. There are no accessors.
+ * 
+ * To use delete(), you only need to fill $mAddress
+ * Globals used: $wgBlockCache, $wgAutoblockExpiry
+ *
+ * @todo This could be used everywhere, but it isn't.
+ * @package MediaWiki
+ */
+class Block
+{
+       /* public*/ var $mAddress, $mUser, $mBy, $mReason, $mTimestamp, $mAuto, $mId, $mExpiry;
+       /* private */ var $mNetworkBits, $mIntegerAddr, $mForUpdate;
+       
+       function Block( $address = '', $user = '', $by = 0, $reason = '', 
+               $timestamp = '' , $auto = 0, $expiry = '' ) 
+       {
+               $this->mAddress = $address;
+               $this->mUser = $user;
+               $this->mBy = $by;
+               $this->mReason = $reason;
+               $this->mTimestamp = wfTimestamp(TS_MW,$timestamp);
+               $this->mAuto = $auto;
+               if( empty( $expiry ) ) {
+                       $this->mExpiry = $expiry;
+               } else {
+                       $this->mExpiry = wfTimestamp( TS_MW, $expiry );
+               }
+               
+               $this->mForUpdate = false;
+               $this->initialiseRange();
+       }
+       
+       /*static*/ function newFromDB( $address, $user = 0, $killExpired = true ) 
+       {
+               $ban = new Block();
+               $ban->load( $address, $user, $killExpired );
+               return $ban;
+       }
+       
+       function clear() 
+       {
+               $mAddress = $mReason = $mTimestamp = '';
+               $mUser = $mBy = 0;
+       }
+
+       /**
+        * Get a ban from the DB, with either the given address or the given username
+        */
+       function load( $address = '', $user = 0, $killExpired = true ) 
+       {
+               global $wgDBmysql4, $wgAntiLockFlags;
+               $fname = 'Block::load';
+               wfDebug( "Block::load: '$address', '$user', $killExpired\n" );
+
+               $ret = false;
+               $killed = false;
+               if ( $this->forUpdate() ) {
+                       $db =& wfGetDB( DB_MASTER );
+                       if ( $wgAntiLockFlags & ALF_NO_BLOCK_LOCK ) {
+                               $options = '';
+                       } else {
+                               $options = 'FOR UPDATE';
+                       }
+               } else {
+                       $db =& wfGetDB( DB_SLAVE );
+                       $options = '';
+               }
+               $ipblocks = $db->tableName( 'ipblocks' );
+
+               if ( 0 == $user && $address=='' ) {
+                       $sql = "SELECT * from $ipblocks $options";
+               } elseif ($address=="") {
+                       $sql = "SELECT * FROM $ipblocks WHERE ipb_user={$user} $options";
+               } elseif ($user=="") {
+                       $sql = "SELECT * FROM $ipblocks WHERE ipb_address='" . $db->strencode( $address ) . "' $options";
+               } elseif ( $options=='' && $wgDBmysql4 ) {
+                       # If there are no optiones (e.g. FOR UPDATE), use a UNION
+                       # so that the query can make efficient use of indices
+                       $sql = "SELECT * FROM $ipblocks WHERE ipb_address='" . $db->strencode( $address ) .
+                               "' UNION SELECT * FROM $ipblocks WHERE ipb_user={$user}";
+               } else {
+                       # If there are options, a UNION can not be used, use one
+                       # SELECT instead. Will do a full table scan.
+                       $sql = "SELECT * FROM $ipblocks WHERE (ipb_address='" . $db->strencode( $address ) . 
+                               "' OR ipb_user={$user}) $options";
+               }
+
+               $res = $db->query( $sql, $fname );
+               if ( 0 == $db->numRows( $res ) ) {
+                       # User is not blocked
+                       $this->clear();
+               } else {
+                       # Get first block
+                       $row = $db->fetchObject( $res );
+                       $this->initFromRow( $row );
+
+                       if ( $killExpired ) {
+                               # If requested, delete expired rows
+                               do {
+                                       $killed = $this->deleteIfExpired();
+                                       if ( $killed ) {
+                                               $row = $db->fetchObject( $res );
+                                               if ( $row ) {
+                                                       $this->initFromRow( $row );
+                                               }
+                                       }
+                               } while ( $killed && $row );
+                               
+                               # If there were any left after the killing finished, return true
+                               if ( !$row ) {
+                                       $ret = false;
+                                       $this->clear();
+                               } else {
+                                       $ret = true;
+                               }
+                       } else {
+                               $ret = true;
+                       }
+               }
+               $db->freeResult( $res );
+               return $ret;
+       }
+       
+       function initFromRow( $row ) 
+       {
+               $this->mAddress = $row->ipb_address;
+               $this->mReason = $row->ipb_reason;
+               $this->mTimestamp = wfTimestamp(TS_MW,$row->ipb_timestamp);
+               $this->mUser = $row->ipb_user;
+               $this->mBy = $row->ipb_by;
+               $this->mAuto = $row->ipb_auto;
+               $this->mId = $row->ipb_id;
+               $this->mExpiry = $row->ipb_expiry ?
+                       wfTimestamp(TS_MW,$row->ipb_expiry) :
+                       $row->ipb_expiry;
+
+               $this->initialiseRange();
+       }       
+
+       function initialiseRange()
+       {
+               if ( $this->mUser == 0 ) {
+                       $rangeParts = explode( '/', $this->mAddress );
+                       if ( count( $rangeParts ) == 2 ) {
+                               $this->mNetworkBits = $rangeParts[1];
+                       } else {
+                               $this->mNetworkBits = 32;
+                       }
+                       $this->mIntegerAddr = ip2long( $rangeParts[0] );
+               } else {
+                       $this->mNetworkBits = false;
+                       $this->mIntegerAddr = false;
+               }
+       }
+       
+       /**
+        * Callback with a Block object for every block
+        * @return integer number of blocks;
+        */
+       /*static*/ function enumBlocks( $callback, $tag, $flags = 0 ) 
+       {
+               global $wgAntiLockFlags;
+
+               $block = new Block();
+               if ( $flags & EB_FOR_UPDATE ) {
+                       $db =& wfGetDB( DB_MASTER );
+                       if ( $wgAntiLockFlags & ALF_NO_BLOCK_LOCK ) {
+                               $options = '';
+                       } else {
+                               $options = 'FOR UPDATE';
+                       }
+                       $block->forUpdate( true );
+               } else {
+                       $db =& wfGetDB( DB_SLAVE );
+                       $options = '';
+               }       
+               $ipblocks = $db->tableName( 'ipblocks' );
+               
+               $sql = "SELECT * FROM $ipblocks ORDER BY ipb_timestamp DESC $options";
+               $res = $db->query( $sql, 'Block::enumBans' );
+               $num_rows = $db->numRows( $res );
+
+               while ( $row = $db->fetchObject( $res ) ) {
+                       $block->initFromRow( $row );
+                       if ( !( $flags & EB_KEEP_EXPIRED ) ) {
+                               if ( !$block->deleteIfExpired() ) {
+                                       $callback( $block, $tag );
+                               }
+                       } else {
+                               $callback( $block, $tag );
+                       }
+               }
+               wfFreeResult( $res );
+               return $num_rows;
+       }
+
+       function delete() 
+       {
+               $fname = 'Block::delete';
+               if (wfReadOnly()) {
+                       return;
+               }
+               $dbw =& wfGetDB( DB_MASTER );
+
+               if ( $this->mAddress == '' ) {
+                       $condition = array( 'ipb_id' => $this->mId );
+               } else {
+                       $condition = array( 'ipb_address' => $this->mAddress );
+               }
+               $dbw->delete( 'ipblocks', $condition, $fname );
+               $this->clearCache();
+       }
+
+       function insert() 
+       {
+               wfDebug( "Block::insert; timestamp {$this->mTimestamp}\n" );
+               $dbw =& wfGetDB( DB_MASTER );
+               $dbw->insert( 'ipblocks',
+                       array(
+                               'ipb_address' => $this->mAddress,
+                               'ipb_user' => $this->mUser,
+                               'ipb_by' => $this->mBy,
+                               'ipb_reason' => $this->mReason,
+                               'ipb_timestamp' => $dbw->timestamp($this->mTimestamp),
+                               'ipb_auto' => $this->mAuto,
+                               'ipb_expiry' => $this->mExpiry ?
+                                       $dbw->timestamp($this->mExpiry) :
+                                       $this->mExpiry,
+                       ), 'Block::insert' 
+               );
+
+               $this->clearCache();
+       }
+
+       function deleteIfExpired() 
+       {
+               if ( $this->isExpired() ) {
+                       wfDebug( "Block::deleteIfExpired() -- deleting\n" );
+                       $this->delete();
+                       return true;
+               } else {
+                       wfDebug( "Block::deleteIfExpired() -- not expired\n" );
+                       return false;
+               }
+       }
+
+       function isExpired() 
+       {       
+               wfDebug( "Block::isExpired() checking current " . wfTimestampNow() . " vs $this->mExpiry\n" );
+               if ( !$this->mExpiry ) {
+                       return false;
+               } else {
+                       return wfTimestampNow() > $this->mExpiry;
+               }
+       }
+
+       function isValid() 
+       {
+               return $this->mAddress != '';
+       }
+       
+       function updateTimestamp() 
+       {
+               if ( $this->mAuto ) {
+                       $this->mTimestamp = wfTimestamp();
+                       $this->mExpiry = Block::getAutoblockExpiry( $this->mTimestamp );
+
+                       $dbw =& wfGetDB( DB_MASTER );
+                       $dbw->update( 'ipblocks', 
+                               array( /* SET */ 
+                                       'ipb_timestamp' => $dbw->timestamp($this->mTimestamp),
+                                       'ipb_expiry' => $dbw->timestamp($this->mExpiry),
+                               ), array( /* WHERE */
+                                       'ipb_address' => $this->mAddress
+                               ), 'Block::updateTimestamp' 
+                       );
+                       
+                       $this->clearCache();
+               }
+       }
+
+       /* private */ function clearCache()
+       {
+               global $wgBlockCache;
+               if ( is_object( $wgBlockCache ) ) {
+                       $wgBlockCache->loadFromDB();
+               }
+       }
+       
+       function getIntegerAddr()
+       {
+               return $this->mIntegerAddr;
+       }
+       
+       function getNetworkBits()
+       {
+               return $this->mNetworkBits;
+       }
+
+       function forUpdate( $x = NULL ) {
+               return wfSetVar( $this->mForUpdate, $x );
+       }
+
+       /* static */ function getAutoblockExpiry( $timestamp )
+       {
+               global $wgAutoblockExpiry;
+               return wfTimestamp( TS_MW, wfTimestamp( TS_UNIX, $timestamp ) + $wgAutoblockExpiry );
+       }
+
+       /* static */ function normaliseRange( $range )
+       {
+               $parts = explode( '/', $range );
+               if ( count( $parts ) == 2 ) {
+                       $shift = 32 - $parts[1];
+                       $ipint = ip2long( $parts[0] );
+                       $ipint = $ipint >> $shift << $shift;
+                       $newip = long2ip( $ipint );
+                       $range = "$newip/{$parts[1]}";
+               }
+               return $range;
+       }
+
+}
+?>
diff --git a/includes/BlockCache.php b/includes/BlockCache.php
new file mode 100644 (file)
index 0000000..0df3a14
--- /dev/null
@@ -0,0 +1,145 @@
+<?php
+/**
+ * Contain the blockcache class
+ * @package Cache
+ */
+
+/**
+ * Object for fast lookup of IP blocks
+ * Represents a memcached value, and in some sense, the entire ipblocks table
+ * @package MediaWiki
+ */
+class BlockCache
+{
+       var $mData = false, $mMemcKey;
+
+       /**
+        * Constructor
+        * Create a new BlockCache object
+        *
+        * @param Boolean $deferLoad   specifies whether to immediately load the data from memcached.
+        * @param String $dbName       specifies the memcached dbName prefix to be used. Defaults to $wgDBname.
+        */
+       function BlockCache( $deferLoad = false, $dbName = '' ) {
+               global $wgDBname;
+
+               if ( $dbName == '' ) {
+                       $dbName = $wgDBname;
+               }
+
+               $this->mMemcKey = $dbName.':ipblocks';
+
+               if ( !$deferLoad ) {
+                       $this->load();
+               }
+       }
+
+       /**
+        * Load the blocks from the database and save them to memcached
+        *  @param bool $bFromSlave Whether to load data from slaves or master
+        */
+       function loadFromDB( $bFromSlave = false ) {
+               global $wgUseMemCached, $wgMemc;
+               $this->mData = array();
+               # Selecting FOR UPDATE is a convenient way to serialise the memcached and DB operations,
+               # which is necessary even though we don't update the DB
+               if ( !$bFromSlave ) {
+                       Block::enumBlocks( 'wfBlockCacheInsert', '', EB_FOR_UPDATE );
+                       #$wgMemc->set( $this->mMemcKey, $this->mData, 0 );
+               } else {
+                       Block::enumBlocks( 'wfBlockCacheInsert', '' );
+               }
+       }
+               
+       /**
+        * Load the cache from memcached or, if that's not possible, from the DB
+        */
+       function load( $bFromSlave ) {
+               global $wgUseMemCached, $wgMemc;
+
+               if ( $this->mData === false) {
+                       $this->loadFromDB( $bFromSlave );
+/*
+               // Memcache disabled for performance issues.
+                       # Try memcached
+                       if ( $wgUseMemCached ) {
+                               $this->mData = $wgMemc->get( $this->mMemcKey );
+                       }
+
+                       if ( !is_array( $this->mData ) ) {
+                               $this->loadFromDB( $bFromSlave );
+                       }*/
+               }
+       }
+
+       /**
+        * Add a block to the cache
+        *
+        * @param Object &$block   Reference to a "Block" object.
+        */
+       function insert( &$block ) {
+               if ( $block->mUser == 0 ) {
+                       $nb = $block->getNetworkBits();
+                       $ipint = $block->getIntegerAddr();
+                       $index = $ipint >> ( 32 - $nb );
+
+                       if ( !array_key_exists( $nb, $this->mData ) ) {
+                               $this->mData[$nb] = array();
+                       }
+               
+                       $this->mData[$nb][$index] = 1;
+               }
+       }
+       
+       /**
+        * Find out if a given IP address is blocked
+        *
+        * @param String $ip   IP address
+        * @param bool $bFromSlave True means to load check against slave, else check against master.
+        */
+       function get( $ip, $bFromSlave ) {
+               $this->load( $bFromSlave );
+               $ipint = ip2long( $ip );
+               $blocked = false;
+
+               foreach ( $this->mData as $networkBits => $blockInts ) {
+                       if ( array_key_exists( $ipint >> ( 32 - $networkBits ), $blockInts ) ) {
+                               $blocked = true;
+                               break;
+                       }
+               }
+               if ( $blocked ) {
+                       # Clear low order bits
+                       if ( $networkBits != 32 ) {
+                               $ip .= '/'.$networkBits;
+                               $ip = Block::normaliseRange( $ip );
+                       }
+                       $block = new Block();
+                       $block->forUpdate( $bFromSlave );
+                       $block->load( $ip );
+               } else {
+                       $block = false;
+               }
+
+               return $block;
+       }
+
+       /**
+        * Clear the local cache
+        * There was once a clear() to clear memcached too, but I deleted it
+        */
+       function clearLocal() {
+               $this->mData = false;
+       }
+}
+
+/**
+ * Add a block to the global $wgBlockCache
+ *
+ * @param Object $block  A "Block"-object
+ * @param Any    $tag    unused
+ */
+function wfBlockCacheInsert( $block, $tag ) {
+       global $wgBlockCache;
+       $wgBlockCache->insert( $block );
+}
diff --git a/includes/CacheManager.php b/includes/CacheManager.php
new file mode 100644 (file)
index 0000000..66121de
--- /dev/null
@@ -0,0 +1,164 @@
+<?php
+/**
+ * Contain the CacheManager class
+ * @package MediaWiki
+ * @subpackage Cache
+ */
+
+/**
+ * We need the title class
+ */
+require_once( 'Title.php' );
+
+/**
+ * Handles talking to the file cache, putting stuff in and taking it back out.
+ * Mostly called from Article.php, also from DatabaseFunctions.php for the
+ * emergency abort/fallback to cache.
+ * 
+ * Global options that affect this module:
+ * $wgCachePages
+ * $wgCacheEpoch
+ * $wgUseFileCache
+ * $wgFileCacheDirectory
+ * $wgUseGzip
+ * @package MediaWiki 
+ */
+class CacheManager {
+       var $mTitle, $mFileCache;
+       
+       function CacheManager( &$title ) {
+               $this->mTitle =& $title;
+               $this->mFileCache = '';
+       }
+       
+       function fileCacheName() {
+               global $wgFileCacheDirectory, $wgContLang;
+               if( !$this->mFileCache ) {
+                       $key = $this->mTitle->getPrefixedDbkey();
+                       $hash = md5( $key );
+                       $key = str_replace( '.', '%2E', urlencode( $key ) );
+                       
+                       $hash1 = substr( $hash, 0, 1 );
+                       $hash2 = substr( $hash, 0, 2 );
+                       $this->mFileCache = "{$wgFileCacheDirectory}/{$hash1}/{$hash2}/{$key}.html";
+                       
+                       if($this->useGzip())
+                               $this->mFileCache .= '.gz';
+                       
+                       wfDebug( " fileCacheName() - {$this->mFileCache}\n" );
+               }
+               return $this->mFileCache;
+       }
+
+       function isFileCached() {
+               return file_exists( $this->fileCacheName() );
+       }
+       
+       function fileCacheTime() {
+               return wfTimestamp( TS_MW, filemtime( $this->fileCacheName() ) );
+       }
+       
+       function isFileCacheGood( $timestamp ) {
+               global $wgCacheEpoch;
+               
+               if( !$this->isFileCached() ) return false;
+               
+               $cachetime = $this->fileCacheTime();
+               $good = (( $timestamp <= $cachetime ) &&
+                        ( $wgCacheEpoch <= $cachetime ));
+               
+               wfDebug(" isFileCacheGood() - cachetime $cachetime, touched {$timestamp} epoch {$wgCacheEpoch}, good $good\n");
+               return $good;
+       }
+
+       function useGzip() {
+               global $wgUseGzip;
+               return $wgUseGzip;
+       }
+       
+       /* In handy string packages */
+       function fetchRawText() {
+               return file_get_contents( $this->fileCacheName() );
+       }
+       
+       function fetchPageText() {
+               if( $this->useGzip() ) {
+                       /* Why is there no gzfile_get_contents() or gzdecode()? */
+                       return implode( '', gzfile( $this->fileCacheName() ) );
+               } else {
+                       return $this->fetchRawText();
+               }
+       }
+       
+       /* Working directory to/from output */
+       function loadFromFileCache() {
+               global $wgOut, $wgMimeType, $wgOutputEncoding, $wgContLanguageCode;
+               wfDebug(" loadFromFileCache()\n");
+               
+               $filename=$this->fileCacheName();
+               $wgOut->sendCacheControl();
+
+               header( "Content-type: $wgMimeType; charset={$wgOutputEncoding}" );
+               header( "Content-language: $wgContLanguageCode" );
+               
+               if( $this->useGzip() ) {
+                       if( wfClientAcceptsGzip() ) {
+                               header( 'Content-Encoding: gzip' );
+                       } else {
+                               /* Send uncompressed */
+                               readgzfile( $filename );
+                               return;
+                       }
+               }
+               readfile( $filename );
+       }
+       
+       function checkCacheDirs() {
+               $filename = $this->fileCacheName();
+               $mydir2=substr($filename,0,strrpos($filename,'/')); # subdirectory level 2
+               $mydir1=substr($mydir2,0,strrpos($mydir2,'/')); # subdirectory level 1
+               
+               if(!file_exists($mydir1)) { mkdir($mydir1,0775); } # create if necessary
+               if(!file_exists($mydir2)) { mkdir($mydir2,0775); }
+       }
+       
+       function saveToFileCache( $origtext ) {
+               $text = $origtext;
+               if(strcmp($text,'') == 0) return '';
+               
+               wfDebug(" saveToFileCache()\n", false);
+               
+               $this->checkCacheDirs();
+               
+               $f = fopen( $this->fileCacheName(), 'w' );
+               if($f) {
+                       $now = wfTimestampNow();
+                       if( $this->useGzip() ) {
+                               $rawtext = str_replace( '</html>',
+                                       '<!-- Cached/compressed '.$now." -->\n</html>",
+                                       $text );
+                               $text = gzencode( $rawtext );
+                       } else {
+                               $text = str_replace( '</html>',
+                                       '<!-- Cached '.$now." -->\n</html>",
+                                       $text );
+                       }
+                       fwrite( $f, $text );
+                       fclose( $f );
+                       if( $this->useGzip() ) {
+                               if( wfClientAcceptsGzip() ) {
+                                       header( 'Content-Encoding: gzip' );
+                                       return $text;
+                               } else {
+                                       return $rawtext;
+                               }
+                       } else {
+                               return $text;
+                       }
+               }
+               return $text;
+       }
+
+}
+
+?>
diff --git a/includes/CategoryPage.php b/includes/CategoryPage.php
new file mode 100644 (file)
index 0000000..39d862c
--- /dev/null
@@ -0,0 +1,332 @@
+<?php
+/**
+ * Special handling for category description pages
+ * Modelled after ImagePage.php
+ *
+ * @package MediaWiki
+ */
+if( !defined( 'MEDIAWIKI' ) )
+       die();
+
+global $wgCategoryMagicGallery;
+if( $wgCategoryMagicGallery )
+       /** */
+       require_once('ImageGallery.php');
+
+/**
+ * @package MediaWiki 
+ */
+class CategoryPage extends Article {
+
+       function view() {
+               if(!wfRunHooks('CategoryPageView', array(&$this))) return;
+
+               if ( NS_CATEGORY == $this->mTitle->getNamespace() ) {
+                       $this->openShowCategory();
+               }
+
+               Article::view();
+               
+               # If the article we've just shown is in the "Image" namespace,
+               # follow it with the history list and link list for the image
+               # it describes.
+
+               if ( NS_CATEGORY == $this->mTitle->getNamespace() ) {
+                       $this->closeShowCategory();
+               }
+       }
+
+       function openShowCategory() {
+               # For overloading
+       }
+       
+       # generate a list of subcategories and pages for a category
+       # depending on wfMsg("usenewcategorypage") it either calls the new
+       # or the old code. The new code will not work properly for some
+       # languages due to sorting issues, so they might want to turn it
+       # off.
+
+       function closeShowCategory() {
+               global $wgOut, $wgRequest;
+               $pageConditions = array();
+               $from = $wgRequest->getVal( 'from' );
+               $until = $wgRequest->getVal( 'until' );
+               $wgOut->addHTML( $this->doCategoryMagic( $from, $until ) );
+       }
+
+       /**
+        * Format the category data list.
+        *
+        * @param string $from -- return only sort keys from this item on
+        * @param string $until -- don't return keys after this point.
+        * @return string HTML output
+        * @access private
+        */
+       function doCategoryMagic( $from = '', $until = '' ) {
+               global $wgContLang,$wgUser, $wgCategoryMagicGallery, $wgCategoryPagingLimit;
+               $fname = 'CategoryPage::doCategoryMagic';
+               wfProfileIn( $fname );
+
+               $articles = array();
+               $articles_start_char = array();
+               $children = array();
+               $children_start_char = array();
+               $data = array();
+               if( $wgCategoryMagicGallery ) {
+                       $ig = new ImageGallery();
+               }
+
+               $dbr =& wfGetDB( DB_SLAVE );
+               if( $from != '' ) {
+                       $pageCondition = 'cl_sortkey >= ' . $dbr->addQuotes( $from );
+                       $flip = false;
+               } elseif( $until != '' ) {
+                       $pageCondition = 'cl_sortkey < ' . $dbr->addQuotes( $until );
+                       $flip = true;
+               } else {
+                       $pageCondition = '1';
+                       $flip = false;
+               }
+               $limit = $wgCategoryPagingLimit;
+               $res = $dbr->select(
+                       array( 'page', 'categorylinks' ),
+                       array( 'page_title', 'page_namespace', 'page_len', 'cl_sortkey' ),
+                       array( $pageCondition,
+                              'cl_from          =  page_id',
+                              'cl_to'           => $this->mTitle->getDBKey()),
+                              #'page_is_redirect' => 0),
+                       #+ $pageCondition,
+                       $fname,
+                       array( 'ORDER BY' => $flip ? 'cl_sortkey DESC' : 'cl_sortkey',
+                              'LIMIT'    => $limit + 1 ) );
+               
+               $sk =& $wgUser->getSkin();
+               $r = "<br style=\"clear:both;\"/>\n";
+               $count = 0;
+               $nextPage = null;
+               while( $x = $dbr->fetchObject ( $res ) ) {
+                       if( ++$count > $limit ) {
+                               // We've reached the one extra which shows that there are
+                               // additional pages to be had. Stop here...
+                               $nextPage = $x->cl_sortkey;
+                               break;
+                       }
+                       
+                       $title = Title::makeTitle( $x->page_namespace, $x->page_title );
+                       
+                       if( $title->getNamespace() == NS_CATEGORY ) {
+                               // Subcategory; strip the 'Category' namespace from the link text.
+                               array_push( $children, $sk->makeKnownLinkObj( $title, $wgContLang->convertHtml( $title->getText() ) ) );
+                               
+                               // If there's a link from Category:A to Category:B, the sortkey of the resulting
+                               // entry in the categorylinks table is Category:A, not A, which it SHOULD be.
+                               // Workaround: If sortkey == "Category:".$title, than use $title for sorting,
+                               // else use sortkey...
+                               $sortkey='';
+                               if( $title->getPrefixedText() == $x->cl_sortkey ) {
+                                       $sortkey=$wgContLang->firstChar( $x->page_title );
+                               } else {
+                                       $sortkey=$wgContLang->firstChar( $x->cl_sortkey );
+                               }
+                               array_push( $children_start_char, $wgContLang->convert( $sortkey ) ) ;
+                       } elseif( $wgCategoryMagicGallery && $title->getNamespace() == NS_IMAGE ) {
+                               // Show thumbnails of categorized images, in a separate chunk
+                               if( $flip ) {
+                                       $ig->insert( Image::newFromTitle( $title ) );
+                               } else {
+                                       $ig->add( Image::newFromTitle( $title ) );
+                               }
+                       } else {
+                               // Page in this category
+                               array_push( $articles, $sk->makeSizeLinkObj( $x->page_len, $title, $wgContLang->convert( $title->getPrefixedText() ) ) ) ;
+                               array_push( $articles_start_char, $wgContLang->convert( $wgContLang->firstChar( $x->cl_sortkey ) ) );
+                       }
+               }
+               $dbr->freeResult( $res );
+
+               if( $flip ) {
+                       $children            = array_reverse( $children );
+                       $children_start_char = array_reverse( $children_start_char );
+                       $articles            = array_reverse( $articles );
+                       $articles_start_char = array_reverse( $articles_start_char );
+               }
+               
+               if( $until != '' ) {
+                       $r .= $this->pagingLinks( $this->mTitle, $nextPage, $until, $limit );
+               } elseif( $nextPage != '' || $from != '' ) {
+                       $r .= $this->pagingLinks( $this->mTitle, $from, $nextPage, $limit );
+               }
+               
+               # Don't show subcategories section if there are none.
+               if( count( $children ) > 0 ) {
+                       # Showing subcategories
+                       $r .= '<h2>' . wfMsg( 'subcategories' ) . "</h2>\n";
+                       $r .= $this->formatCount( $children, 'subcategorycount' );
+                       $r .= $this->formatList( $children, $children_start_char );
+               }
+
+               # Showing articles in this category
+               $ti = htmlspecialchars( $this->mTitle->getText() );
+               $r .= '<h2>' . wfMsg( 'category_header', $ti ) . "</h2>\n";
+               $r .= $this->formatCount( $articles, 'categoryarticlecount' );
+               $r .= $this->formatList( $articles, $articles_start_char );
+
+               if( $wgCategoryMagicGallery && ! $ig->isEmpty() ) {
+                       $r.= $ig->toHTML();
+               }
+
+               wfProfileOut( $fname );
+               return $r;
+       }
+
+       /**
+        * @param array $articles
+        * @param string $message
+        * @return string
+        * @access private
+        */
+       function formatCount( $articles, $message ) {
+               global $wgContLang;
+               $numart = count( $articles );
+               if( $numart == 1 ) {
+                       # Slightly different message to avoid silly plural
+                       $message .= '1';
+               }
+               return wfMsg( $message, $wgContLang->formatNum( $numart ) );
+       }
+       /**
+        * Format a list of articles chunked by letter, either as a
+        * bullet list or a columnar format, depending on the length.
+        *
+        * @param array $articles
+        * @param array $articles_start_char
+        * @param int   $cutoff
+        * @return string
+        * @access private
+        */
+       function formatList( $articles, $articles_start_char, $cutoff = 6 ) {
+               if ( count ( $articles ) > $cutoff ) {
+                       return $this->columnList( $articles, $articles_start_char );
+               } elseif ( count($articles) > 0) {
+                       // for short lists of articles in categories.
+                       return $this->shortList( $articles, $articles_start_char );
+               }
+               return '';
+       }
+       
+       /**
+        * Format a list of articles chunked by letter in a three-column
+        * list, ordered vertically.
+        *
+        * @param array $articles
+        * @param array $articles_start_char
+        * @return string
+        * @access private
+        */
+       function columnList( $articles, $articles_start_char ) {
+               // divide list into three equal chunks
+               $chunk = (int) (count ( $articles ) / 3);
+
+               // get and display header
+               $r = '<table width="100%"><tr valign="top">';
+
+               $prev_start_char = 'none'; 
+
+               // loop through the chunks
+               for($startChunk = 0, $endChunk = $chunk, $chunkIndex = 0;
+                       $chunkIndex < 3;
+                       $chunkIndex++, $startChunk = $endChunk, $endChunk += $chunk + 1)
+               {
+                       $r .= "<td>\n";
+                       $atColumnTop = true;
+
+                       // output all articles in category
+                       for ($index = $startChunk ;
+                               $index < $endChunk && $index < count($articles);
+                               $index++ )
+                       {
+                               // check for change of starting letter or begining of chunk
+                               if ( ($index == $startChunk) ||
+                                        ($articles_start_char[$index] != $articles_start_char[$index - 1]) )
+
+                               {
+                                       if( $atColumnTop ) {
+                                               $atColumnTop = false;
+                                       } else {
+                                               $r .= "</ul>\n";
+                                       }
+                                       $cont_msg = "";
+                                       if ( $articles_start_char[$index] == $prev_start_char )
+                                               $cont_msg = wfMsg('listingcontinuesabbrev');
+                                       $r .= "<h3>{$articles_start_char[$index]}$cont_msg</h3>\n<ul>";
+                                       $prev_start_char = $articles_start_char[$index];
+                               }
+
+                               $r .= "<li>{$articles[$index]}</li>";
+                       }
+                       if( !$atColumnTop ) {
+                               $r .= "</ul>\n";
+                       }
+                       $r .= "</td>\n";
+
+
+               }
+               $r .= '</tr></table>';
+               return $r;
+       }
+       
+       /**
+        * Format a list of articles chunked by letter in a bullet list.
+        * @param array $articles
+        * @param array $articles_start_char
+        * @return string
+        * @access private
+        */
+       function shortList( $articles, $articles_start_char ) {
+               $r = '<h3>'.$articles_start_char[0]."</h3>\n";
+               $r .= '<ul><li>'.$articles[0].'</li>';
+               for ($index = 1; $index < count($articles); $index++ )
+               {
+                       if ($articles_start_char[$index] != $articles_start_char[$index - 1])
+                       {
+                               $r .= "</ul><h3>{$articles_start_char[$index]}</h3>\n<ul>";
+                       }
+
+                       $r .= "<li>{$articles[$index]}</li>";
+               }
+               $r .= '</ul>';
+               return $r;
+       }
+       
+       /**
+        * @param Title  $title
+        * @param string $first
+        * @param string $last
+        * @param int    $limit
+        * @param array  $query - additional query options to pass
+        * @return string
+        * @access private
+        */
+       function pagingLinks( $title, $first, $last, $limit, $query = array() ) {
+               global $wgUser, $wgLang;
+               $sk =& $wgUser->getSkin();
+               $limitText = $wgLang->formatNum( $limit );
+               
+               $prevLink = htmlspecialchars( wfMsg( 'prevn', $limitText ) );
+               if( $first != '' ) {
+                       $prevLink = $sk->makeLinkObj( $title, $prevLink,
+                               wfArrayToCGI( $query + array( 'until' => $first ) ) );
+               }
+               $nextLink = htmlspecialchars( wfMsg( 'nextn', $limitText ) );
+               if( $last != '' ) {
+                       $nextLink = $sk->makeLinkObj( $title, $nextLink,
+                               wfArrayToCGI( $query + array( 'from' => $last ) ) );
+               }
+               
+               return "($prevLink) ($nextLink)";
+       }
+}
+
+
+?>
diff --git a/includes/ChangesList.php b/includes/ChangesList.php
new file mode 100644 (file)
index 0000000..3578d27
--- /dev/null
@@ -0,0 +1,550 @@
+<?php
+/**
+ * @package MediaWiki
+ */
+
+/**
+ * @package MediaWiki
+ */
+class ChangesList {
+       # Called by history lists and recent changes
+       #
+
+       /** @todo document */
+       function ChangesList( &$skin ) {
+               $this->skin =& $skin;
+       }
+
+       /**
+        * Returns the appropiate flags for new page, minor change and patrolling
+        */
+       function recentChangesFlags( $new, $minor, $patrolled, $nothing = '&nbsp;' ) {
+               $f = $new ? '<span class="newpage">' . htmlspecialchars( wfMsg( 'newpageletter' ) ) . '</span>'
+                               : $nothing;
+               $f .= $minor ? '<span class="minor">' . htmlspecialchars( wfMsg( 'minoreditletter' ) ) . '</span>'
+                               : $nothing;
+               $f .= $patrolled ? '<span class="unpatrolled">!</span>' : $nothing;
+               return $f;
+
+       }
+
+       /**
+        * Returns text for the start of the tabular part of RC
+        */
+       function beginRecentChangesList() {
+               $this->rc_cache = array() ;
+               $this->rcMoveIndex = 0;
+               $this->rcCacheIndex = 0 ;
+               $this->lastdate = '';
+               $this->rclistOpen = false;
+               return '';
+       }
+
+       /**
+        * Returns text for the end of RC
+        * If enhanced RC is in use, returns pretty much all the text
+        */
+       function endRecentChangesList() {
+               $s = $this->recentChangesBlock() ;
+               if( $this->rclistOpen ) {
+                       $s .= "</ul>\n";
+               }
+               return $s;
+       }
+
+       /**
+        * Enhanced RC ungrouped line
+        */
+       function recentChangesBlockLine ( $rcObj ) {
+               global $wgStylePath, $wgContLang ;
+
+               # Get rc_xxxx variables
+               extract( $rcObj->mAttribs ) ;
+               $curIdEq = 'curid='.$rc_cur_id;
+
+               # Spacer image
+               $r = '' ;
+
+               $r .= '<img src="'.$wgStylePath.'/common/images/Arr_.png" width="12" height="12" border="0" />' ;
+               $r .= '<tt>' ;
+
+               if ( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
+                       $r .= '&nbsp;&nbsp;&nbsp;';
+               } else {
+                       $r .= $this->recentChangesFlags( $rc_type == RC_NEW, $rc_minor, $rcObj->unpatrolled );
+               }
+
+               # Timestamp
+               $r .= ' '.$rcObj->timestamp.' ' ;
+               $r .= '</tt>' ;
+
+               # Article link
+               $link = $rcObj->link ;
+               if ( $rcObj->watched ) $link = '<strong>'.$link.'</strong>' ;
+               $r .= $link ;
+
+               # Diff
+               $r .= ' (' ;
+               $r .= $rcObj->difflink ;
+               $r .= '; ' ;
+
+               # Hist
+               $r .= $this->skin->makeKnownLinkObj( $rcObj->getTitle(), wfMsg( 'hist' ), $curIdEq.'&action=history' );
+
+               # User/talk
+               $r .= ') . . '.$rcObj->userlink ;
+               $r .= $rcObj->usertalklink ;
+
+               # Comment
+                if ( $rc_type != RC_MOVE && $rc_type != RC_MOVE_OVER_REDIRECT ) {
+                       $r .= $this->skin->commentBlock( $rc_comment, $rcObj->getTitle() );
+               }
+
+               if ($rcObj->numberofWatchingusers > 0) {
+                       $r .= wfMsg('number_of_watching_users_RCview',  $wgContLang->formatNum($rcObj->numberofWatchingusers));
+               }
+
+               $r .= "<br />\n" ;
+               return $r ;
+       }
+
+       /**
+        * Enhanced RC group
+        */
+       function recentChangesBlockGroup ( $block ) {
+               global $wgStylePath, $wgContLang ;
+
+               $r = '';
+
+               # Collate list of users
+               $isnew = false ;
+               $unpatrolled = false;
+               $userlinks = array () ;
+               foreach ( $block AS $rcObj ) {
+                       $oldid = $rcObj->mAttribs['rc_last_oldid'];
+                       $newid = $rcObj->mAttribs['rc_this_oldid'];
+                       if ( $rcObj->mAttribs['rc_new'] ) {
+                               $isnew = true ;
+                       }
+                       $u = $rcObj->userlink ;
+                       if ( !isset ( $userlinks[$u] ) ) {
+                               $userlinks[$u] = 0 ;
+                       }
+                       if ( $rcObj->unpatrolled ) {
+                               $unpatrolled = true;
+                       }
+                       $userlinks[$u]++ ;
+               }
+
+               # Sort the list and convert to text
+               krsort ( $userlinks ) ;
+               asort ( $userlinks ) ;
+               $users = array () ;
+               foreach ( $userlinks as $userlink => $count) {
+                       $text = $userlink ;
+                       if ( $count > 1 ) $text .= " ({$count}&times;)" ;
+                       array_push ( $users , $text ) ;
+               }
+               $users = ' <span class="changedby">['.implode('; ',$users).']</span>';
+
+               # Arrow
+               $rci = 'RCI'.$this->rcCacheIndex ;
+               $rcl = 'RCL'.$this->rcCacheIndex ;
+               $rcm = 'RCM'.$this->rcCacheIndex ;
+               $toggleLink = "javascript:toggleVisibility('$rci','$rcm','$rcl')" ;
+               $arrowdir = $wgContLang->isRTL() ? 'l' : 'r';
+               $tl  = '<span id="'.$rcm.'"><a href="'.$toggleLink.'"><img src="'.$wgStylePath.'/common/images/Arr_'.$arrowdir.'.png" width="12" height="12" alt="+" /></a></span>' ;
+               $tl .= '<span id="'.$rcl.'" style="display:none"><a href="'.$toggleLink.'"><img src="'.$wgStylePath.'/common/images/Arr_d.png" width="12" height="12" alt="-" /></a></span>' ;
+               $r .= $tl ;
+
+               # Main line
+
+               $r .= '<tt>' ;
+               $r .= $this->recentChangesFlags( $isnew, false, $unpatrolled );
+
+               # Timestamp
+               $r .= ' '.$block[0]->timestamp.' ' ;
+               $r .= '</tt>' ;
+
+               # Article link
+               $link = $block[0]->link ;
+               if ( $block[0]->watched ) $link = '<strong>'.$link.'</strong>' ;
+               $r .= $link ;
+
+               $curIdEq = 'curid=' . $block[0]->mAttribs['rc_cur_id'];
+               $currentRevision = $block[0]->mAttribs['rc_this_oldid'];
+               if ( $block[0]->mAttribs['rc_type'] != RC_LOG ) {
+                       # Changes
+                       $r .= ' ('.count($block).' ' ;
+                       if ( $isnew ) $r .= wfMsg('changes');
+                       else $r .= $this->skin->makeKnownLinkObj( $block[0]->getTitle() , wfMsg('changes') ,
+                               $curIdEq."&diff=$currentRevision&oldid=$oldid" ) ;
+                       $r .= '; ' ;
+
+                       # History
+                       $r .= $this->skin->makeKnownLinkObj( $block[0]->getTitle(), wfMsg( 'history' ), $curIdEq.'&action=history' );
+                       $r .= ')' ;
+               }
+
+               $r .= $users ;
+
+               if ($block[0]->numberofWatchingusers > 0) {
+                       $r .= wfMsg('number_of_watching_users_RCview',  $wgContLang->formatNum($block[0]->numberofWatchingusers));
+               }
+               $r .= "<br />\n" ;
+
+               # Sub-entries
+               $r .= '<div id="'.$rci.'" style="display:none">' ;
+               foreach ( $block AS $rcObj ) {
+                       # Get rc_xxxx variables
+                       extract( $rcObj->mAttribs );
+
+                       $r .= '<img src="'.$wgStylePath.'/common/images/Arr_.png" width="12" height="12" />';
+                       $r .= '<tt>&nbsp; &nbsp; &nbsp; &nbsp;' ;
+                       $r .= $this->recentChangesFlags( $rc_new, $rc_minor, $rcObj->unpatrolled );
+                       $r .= '&nbsp;</tt>' ;
+
+                       $o = '' ;
+                       if ( $rc_this_oldid != 0 ) {
+                               $o = 'oldid='.$rc_this_oldid ;
+                       }
+                       if ( $rc_type == RC_LOG ) {
+                               $link = $rcObj->timestamp ;
+                       } else {
+                               $link = $this->skin->makeKnownLinkObj( $rcObj->getTitle(), $rcObj->timestamp , "{$curIdEq}&$o" ) ;
+                       }
+                       $link = '<tt>'.$link.'</tt>' ;
+
+                       $r .= $link ;
+                       $r .= ' (' ;
+                       $r .= $rcObj->curlink ;
+                       $r .= '; ' ;
+                       $r .= $rcObj->lastlink ;
+                       $r .= ') . . '.$rcObj->userlink ;
+                       $r .= $rcObj->usertalklink ;
+                       $r .= $this->skin->commentBlock( $rc_comment, $rcObj->getTitle() );
+                       $r .= "<br />\n" ;
+               }
+               $r .= "</div>\n" ;
+
+               $this->rcCacheIndex++ ;
+               return $r ;
+       }
+
+       /**
+        * If enhanced RC is in use, this function takes the previously cached
+        * RC lines, arranges them, and outputs the HTML
+        */
+       function recentChangesBlock () {
+               global $wgStylePath ;
+               if ( count ( $this->rc_cache ) == 0 ) return '' ;
+               $blockOut = '';
+               foreach ( $this->rc_cache AS $secureName => $block ) {
+                       if ( count ( $block ) < 2 ) {
+                               $blockOut .= $this->recentChangesBlockLine ( array_shift ( $block ) ) ;
+                       } else {
+                               $blockOut .= $this->recentChangesBlockGroup ( $block ) ;
+                       }
+               }
+
+               return '<div>'.$blockOut.'</div>' ;
+       }
+
+       /**
+        * Called in a loop over all displayed RC entries
+        * Either returns the line, or caches it for later use
+        */
+       function recentChangesLine( &$rc, $watched = false ) {
+               global $wgUser;
+               $usenew = $wgUser->getOption( 'usenewrc' );
+               if ( $usenew )
+                       $line = $this->recentChangesLineNew ( $rc, $watched ) ;
+               else
+                       $line = $this->recentChangesLineOld ( $rc, $watched ) ;
+               return $line ;
+       }
+
+
+       function recentChangesLineOld( &$rc, $watched = false ) {
+               global $wgTitle, $wgLang, $wgContLang, $wgUser, $wgUseRCPatrol,
+                       $wgOnlySysopsCanPatrol, $wgSysopUserBans;
+
+               $fname = 'Skin::recentChangesLineOld';
+               wfProfileIn( $fname );
+
+               static $message;
+               if( !isset( $message ) ) {
+                       foreach( explode(' ', 'diff hist minoreditletter newpageletter blocklink' ) as $msg ) {
+                               $message[$msg] = wfMsg( $msg );
+                       }
+               }
+
+               # Extract DB fields into local scope
+               extract( $rc->mAttribs );
+               $curIdEq = 'curid=' . $rc_cur_id;
+
+               # Should patrol-related stuff be shown?
+               $unpatrolled = $wgUseRCPatrol && $wgUser->isLoggedIn() &&
+                 ( !$wgOnlySysopsCanPatrol || $wgUser->isAllowed('patrol') ) && $rc_patrolled == 0;
+
+               # Make date header if necessary
+               $date = $wgLang->date( $rc_timestamp, true, true );
+               $s = '';
+               if ( $date != $this->lastdate ) {
+                       if ( '' != $this->lastdate ) { $s .= "</ul>\n"; }
+                       $s .= "<h4>{$date}</h4>\n<ul class=\"special\">";
+                       $this->lastdate = $date;
+                       $this->rclistOpen = true;
+               }
+
+               $s .= '<li>';
+
+               if ( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
+                       # Diff
+                       $s .= '(' . $message['diff'] . ') (';
+                       # Hist
+                       $s .= $this->skin->makeKnownLinkObj( $rc->getMovedToTitle(), $message['hist'], 'action=history' ) .
+                               ') . . ';
+
+                       # "[[x]] moved to [[y]]"
+                       $msg = ( $rc_type == RC_MOVE ) ? '1movedto2' : '1movedto2_redir';
+                       $s .= wfMsg( $msg, $this->skin->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ),
+                               $this->skin->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) );
+               } elseif( $rc_namespace == NS_SPECIAL && preg_match( '!^Log/(.*)$!', $rc_title, $matches ) ) {
+                       # Log updates, etc
+                       $logtype = $matches[1];
+                       $logname = LogPage::logName( $logtype );
+                       $s .= '(' . $this->skin->makeKnownLinkObj( $rc->getTitle(), $logname ) . ')';
+               } else {
+                       wfProfileIn("$fname-page");
+                       # Diff link
+                       if ( $rc_type == RC_NEW || $rc_type == RC_LOG ) {
+                               $diffLink = $message['diff'];
+                       } else {
+                               if ( $unpatrolled )
+                                       $rcidparam = "&rcid={$rc_id}";
+                               else
+                                       $rcidparam = "";
+                               $diffLink = $this->skin->makeKnownLinkObj( $rc->getTitle(), $message['diff'],
+                                 "{$curIdEq}&diff={$rc_this_oldid}&oldid={$rc_last_oldid}{$rcidparam}",
+                                 '', '', ' tabindex="'.$rc->counter.'"');
+                       }
+                       $s .= '('.$diffLink.') (';
+
+                       # History link
+                       $s .= $this->skin->makeKnownLinkObj( $rc->getTitle(), $message['hist'], $curIdEq.'&action=history' );
+                       $s .= ') . . ';
+
+                       # M, N and ! (minor, new and unpatrolled)
+                       $s .= ' ' . $this->recentChangesFlags( $rc_type == RC_NEW, $rc_minor, $unpatrolled, '' );
+
+                       # Article link
+                       # If it's a new article, there is no diff link, but if it hasn't been
+                       # patrolled yet, we need to give users a way to do so
+                       if ( $unpatrolled && $rc_type == RC_NEW )
+                               $articleLink = $this->skin->makeKnownLinkObj( $rc->getTitle(), '', "rcid={$rc_id}" );
+                       else
+                               $articleLink = $this->skin->makeKnownLinkObj( $rc->getTitle(), '' );
+
+                       if ( $watched ) {
+                               $articleLink = '<strong>'.$articleLink.'</strong>';
+                       }
+
+                       $s .= ' '.$articleLink;
+                       wfProfileOut("$fname-page");
+               }
+
+               wfProfileIn( "$fname-rest" );
+               # Timestamp
+               $s .= '; ' . $wgLang->time( $rc_timestamp, true, true ) . ' . . ';
+
+               # User link (or contributions for unregistered users)
+               if ( 0 == $rc_user ) {
+                       $contribsPage =& Title::makeTitle( NS_SPECIAL, 'Contributions' );
+                       $userLink = $this->skin->makeKnownLinkObj( $contribsPage,
+                               $rc_user_text, 'target=' . $rc_user_text );
+               } else {
+                       $userPage =& Title::makeTitle( NS_USER, $rc_user_text );
+                       $userLink = $this->skin->makeLinkObj( $userPage, htmlspecialchars( $rc_user_text ) );
+               }
+               $s .= $userLink;
+
+               # User talk link
+               $talkname = $wgContLang->getNsText(NS_TALK); # use the shorter name
+               global $wgDisableAnonTalk;
+               if( 0 == $rc_user && $wgDisableAnonTalk ) {
+                       $userTalkLink = '';
+               } else {
+                       $userTalkPage =& Title::makeTitle( NS_USER_TALK, $rc_user_text );
+                       $userTalkLink= $this->skin->makeLinkObj( $userTalkPage, htmlspecialchars( $talkname ) );
+               }
+               # Block link
+               $blockLink='';
+               if ( ( $wgSysopUserBans || 0 == $rc_user ) && $wgUser->isAllowed('block') ) {
+                       $blockLinkPage = Title::makeTitle( NS_SPECIAL, 'Blockip' );
+                       $blockLink = $this->skin->makeKnownLinkObj( $blockLinkPage,
+                               htmlspecialchars( $message['blocklink'] ), 'ip=' . urlencode( $rc_user_text ) );
+
+               }
+               if($blockLink) {
+                       if($userTalkLink) $userTalkLink .= ' | ';
+                       $userTalkLink .= $blockLink;
+               }
+               if($userTalkLink) $s.=' ('.$userTalkLink.')';
+
+               # Add comment
+               if ( $rc_type != RC_MOVE && $rc_type != RC_MOVE_OVER_REDIRECT ) {
+                       $s .= $this->skin->commentBlock( $rc_comment, $rc->getTitle() );
+               }
+
+               if ($rc->numberofWatchingusers > 0) {
+                       $s .= ' ' . wfMsg('number_of_watching_users_RCview',  $wgContLang->formatNum($rc->numberofWatchingusers));
+               }
+
+               $s .= "</li>\n";
+
+               wfProfileOut( "$fname-rest" );
+               wfProfileOut( $fname );
+               return $s;
+       }
+
+       function recentChangesLineNew( &$baseRC, $watched = false ) {
+               global $wgTitle, $wgLang, $wgContLang, $wgUser,
+                       $wgUseRCPatrol, $wgOnlySysopsCanPatrol, $wgSysopUserBans;
+
+               static $message;
+               if( !isset( $message ) ) {
+                       foreach( explode(' ', 'cur diff hist minoreditletter newpageletter last blocklink' ) as $msg ) {
+                               $message[$msg] = wfMsg( $msg );
+                       }
+               }
+
+               # Create a specialised object
+               $rc = RCCacheEntry::newFromParent( $baseRC ) ;
+
+               # Extract fields from DB into the function scope (rc_xxxx variables)
+               extract( $rc->mAttribs );
+               $curIdEq = 'curid=' . $rc_cur_id;
+
+               # If it's a new day, add the headline and flush the cache
+               $date = $wgLang->date( $rc_timestamp, true);
+               $ret = '';
+               if ( $date != $this->lastdate ) {
+                       # Process current cache
+                       $ret = $this->recentChangesBlock () ;
+                       $this->rc_cache = array() ;
+                       $ret .= "<h4>{$date}</h4>\n";
+                       $this->lastdate = $date;
+               }
+
+               # Should patrol-related stuff be shown?
+               if ( $wgUseRCPatrol && $wgUser->isLoggedIn() &&
+                 ( !$wgOnlySysopsCanPatrol || $wgUser->isAllowed('patrol') )) {
+                       $rc->unpatrolled = !$rc_patrolled;
+               } else {
+                       $rc->unpatrolled = false;
+               }
+
+               # Make article link
+               if ( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
+                       $msg = ( $rc_type == RC_MOVE ) ? "1movedto2" : "1movedto2_redir";
+                       $clink = wfMsg( $msg, $this->skin->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ),
+                         $this->skin->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) );
+               } elseif( $rc_namespace == NS_SPECIAL && preg_match( '!^Log/(.*)$!', $rc_title, $matches ) ) {
+                       # Log updates, etc
+                       $logtype = $matches[1];
+                       $logname = LogPage::logName( $logtype );
+                       $clink = '(' . $this->skin->makeKnownLinkObj( $rc->getTitle(), $logname ) . ')';
+               } elseif ( $rc->unpatrolled && $rc_type == RC_NEW ) {
+                       # Unpatrolled new page, give rc_id in query
+                       $clink = $this->skin->makeKnownLinkObj( $rc->getTitle(), '', "rcid={$rc_id}" );
+               } else {
+                       $clink = $this->skin->makeKnownLinkObj( $rc->getTitle(), '' ) ;
+               }
+
+               $time = $wgContLang->time( $rc_timestamp, true, true );
+               $rc->watched = $watched ;
+               $rc->link = $clink ;
+               $rc->timestamp = $time;
+               $rc->numberofWatchingusers = $baseRC->numberofWatchingusers;
+
+               # Make "cur" and "diff" links
+               $titleObj = $rc->getTitle();
+               if ( $rc->unpatrolled ) {
+                       $rcIdQuery = "&rcid={$rc_id}";
+               } else {
+                       $rcIdQuery = '';
+               }
+               $querycur = $curIdEq."&diff=0&oldid=$rc_this_oldid";
+               $querydiff = $curIdEq."&diff=$rc_this_oldid&oldid=$rc_last_oldid";
+               $aprops = ' tabindex="'.$baseRC->counter.'"';
+               $curLink = $this->skin->makeKnownLinkObj( $rc->getTitle(), $message['cur'], $querycur, '' ,'' , $aprops );
+               if( $rc_type == RC_NEW || $rc_type == RC_LOG || $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
+                       if( $rc_type != RC_NEW ) {
+                               $curLink = $message['cur'];
+                       }
+                       $diffLink = $message['diff'];
+               } else {
+                       $diffLink = $this->skin->makeKnownLinkObj( $rc->getTitle(), $message['diff'], $querydiff . $rcIdQuery, '' ,'' , $aprops );
+               }
+
+               # Make "last" link
+               if ( $rc_last_oldid == 0 || $rc_type == RC_LOG || $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
+                       $lastLink = $message['last'];
+               } else {
+                       $lastLink = $this->skin->makeKnownLinkObj( $rc->getTitle(), $message['last'],
+                         $curIdEq.'&diff='.$rc_this_oldid.'&oldid='.$rc_last_oldid . $rcIdQuery );
+               }
+
+               # Make user link (or user contributions for unregistered users)
+               if ( $rc_user == 0 ) {
+                       $contribsPage =& Title::makeTitle( NS_SPECIAL, 'Contributions' );
+                       $userLink = $this->skin->makeKnownLinkObj( $contribsPage,
+                               $rc_user_text, 'target=' . $rc_user_text );
+               } else {
+                       $userPage =& Title::makeTitle( NS_USER, $rc_user_text );
+                       $userLink = $this->skin->makeLinkObj( $userPage, $rc_user_text );
+               }
+
+               $rc->userlink = $userLink;
+               $rc->lastlink = $lastLink;
+               $rc->curlink  = $curLink;
+               $rc->difflink = $diffLink;
+
+               # Make user talk link
+               $talkname = $wgContLang->getNsText( NS_TALK ); # use the shorter name
+               $userTalkPage =& Title::makeTitle( NS_USER_TALK, $rc_user_text );
+               $userTalkLink = $this->skin->makeLinkObj( $userTalkPage, $talkname );
+
+               global $wgDisableAnonTalk;
+               if ( ( $wgSysopUserBans || 0 == $rc_user ) && $wgUser->isAllowed('block') ) {
+                       $blockPage =& Title::makeTitle( NS_SPECIAL, 'Blockip' );
+                       $blockLink = $this->skin->makeKnownLinkObj( $blockPage,
+                               $message['blocklink'], 'ip='.$rc_user_text );
+                       if( $wgDisableAnonTalk )
+                               $rc->usertalklink = ' ('.$blockLink.')';
+                       else
+                               $rc->usertalklink = ' ('.$userTalkLink.' | '.$blockLink.')';
+               } else {
+                       if( $wgDisableAnonTalk && ($rc_user == 0) )
+                               $rc->usertalklink = '';
+                       else
+                               $rc->usertalklink = ' ('.$userTalkLink.')';
+               }
+
+               # Put accumulated information into the cache, for later display
+               # Page moves go on their own line
+               $title = $rc->getTitle();
+               $secureName = $title->getPrefixedDBkey();
+               if ( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
+                       # Use an @ character to prevent collision with page names
+                       $this->rc_cache['@@' . ($this->rcMoveIndex++)] = array($rc);
+               } else {
+                       if ( !isset ( $this->rc_cache[$secureName] ) ) $this->rc_cache[$secureName] = array() ;
+                       array_push ( $this->rc_cache[$secureName] , $rc ) ;
+               }
+               return $ret;
+       }
+
+}
+?>
diff --git a/includes/Credits.php b/includes/Credits.php
new file mode 100644 (file)
index 0000000..7131789
--- /dev/null
@@ -0,0 +1,187 @@
+<?php
+/**
+ * Credits.php -- formats credits for articles
+ * Copyright 2004, Evan Prodromou <evan@wikitravel.org>.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @author <evan@wikitravel.org>
+ * @package MediaWiki
+ */
+
+/**
+ * This is largely cadged from PageHistory::history
+ */
+function showCreditsPage($article) {
+    global $wgOut;
+
+    $fname = 'showCreditsPage';
+
+    wfProfileIn( $fname );
+
+    $wgOut->setPageTitle( $article->mTitle->getPrefixedText() );
+    $wgOut->setSubtitle( wfMsg( 'creditspage' ) );
+    $wgOut->setArticleFlag( false );
+    $wgOut->setArticleRelated( true );
+    $wgOut->setRobotpolicy( 'noindex,nofollow' );
+
+    if( $article->mTitle->getArticleID() == 0 ) {
+               $s = wfMsg( 'nocredits' );
+    } else {
+               $s = getCredits($article, -1);
+    }
+
+    $wgOut->addHTML( $s );
+
+    wfProfileOut( $fname );
+}
+
+function getCredits($article, $cnt, $showIfMax=true) {
+       $fname = 'getCredits';
+       wfProfileIn( $fname );
+    $s = '';
+
+    if (isset($cnt) && $cnt != 0) {
+               $s = getAuthorCredits($article);
+               if ($cnt > 1 || $cnt < 0) {
+                       $s .= ' ' . getContributorCredits($article, $cnt - 1, $showIfMax);
+               }
+    }
+
+       wfProfileOut( $fname );
+    return $s;
+}
+
+/**
+ *
+ */
+function getAuthorCredits($article) {
+    global $wgLang, $wgAllowRealName;
+
+    $last_author = $article->getUser();
+
+    if ($last_author == 0) {
+               $author_credit = wfMsg('anonymous');
+    } else {
+               if($wgAllowRealName) { $real_name = User::whoIsReal($last_author); }
+               $user_name = User::whoIs($last_author);
+
+               if (!empty($real_name)) {
+                       $author_credit = creditLink($user_name, $real_name);
+               } else {
+                       $author_credit = wfMsg('siteuser', creditLink($user_name));
+               }
+    }
+
+    $timestamp = $article->getTimestamp();
+    if ($timestamp) {
+               $d = $wgLang->timeanddate($article->getTimestamp(), true);
+    } else {
+               $d = '';
+    }
+    return wfMsg('lastmodifiedby', $d, $author_credit);
+}
+
+/**
+ *
+ */
+function getContributorCredits($article, $cnt, $showIfMax) {
+
+    global $wgLang, $wgAllowRealName;
+
+    $contributors = $article->getContributors();
+
+    $others_link = '';
+
+    # Hmm... too many to fit!
+
+    if ($cnt > 0 && count($contributors) > $cnt) {
+               $others_link = creditOthersLink($article);
+               if (!$showIfMax) {
+                       return wfMsg('othercontribs', $others_link);
+               } else {
+                       $contributors = array_slice($contributors, 0, $cnt);
+               }
+    }
+
+    $real_names = array();
+    $user_names = array();
+
+    $anon = '';
+
+    # Sift for real versus user names
+
+    foreach ($contributors as $user_parts) {
+               if ($user_parts[0] != 0) {
+                       if ($wgAllowRealName && !empty($user_parts[2])) {
+                               $real_names[] = creditLink($user_parts[1], $user_parts[2]);
+                       } else {
+                               $user_names[] = creditLink($user_parts[1]);
+                       }
+               } else {
+                       $anon = wfMsg('anonymous');
+               }
+    }
+
+    # Two strings: real names, and user names
+
+    $real = $wgLang->listToText($real_names);
+    $user = $wgLang->listToText($user_names);
+
+    # "ThisSite user(s) A, B and C"
+
+    if (!empty($user)) {
+        $user = wfMsg('siteusers', $user);
+    }
+
+    # This is the big list, all mooshed together. We sift for blank strings
+
+    $fulllist = array();
+
+    foreach (array($real, $user, $anon, $others_link) as $s) {
+               if (!empty($s)) {
+                       array_push($fulllist, $s);
+               }
+    }
+
+    # Make the list into text...
+
+    $creds = $wgLang->listToText($fulllist);
+
+    # "Based on work by ..."
+
+    return (empty($creds)) ? '' : wfMsg('othercontribs', $creds);
+}
+
+/**
+ *
+ */
+function creditLink($user_name, $link_text = '') {
+    global $wgUser, $wgContLang;
+    $skin = $wgUser->getSkin();
+    return $skin->makeLink($wgContLang->getNsText(NS_USER) . ':' . $user_name,
+                                                  htmlspecialchars( (empty($link_text)) ? $user_name : $link_text ));
+}
+
+/**
+ *
+ */
+function creditOthersLink($article) {
+    global $wgUser, $wgLang;
+    $skin = $wgUser->getSkin();
+    return $skin->makeKnownLink($article->mTitle->getPrefixedText(), wfMsg('others'), 'action=credits');
+}
+
+?>
diff --git a/includes/Database.php b/includes/Database.php
new file mode 100644 (file)
index 0000000..06c4b61
--- /dev/null
@@ -0,0 +1,1712 @@
+<?php
+/**
+ * This file deals with MySQL interface functions 
+ * and query specifics/optimisations
+ * @package MediaWiki
+ */
+
+/**
+ * Depends on the CacheManager
+ */
+require_once( 'CacheManager.php' );
+
+/** See Database::makeList() */
+define( 'LIST_COMMA', 0 );
+define( 'LIST_AND', 1 );
+define( 'LIST_SET', 2 );
+define( 'LIST_NAMES', 3);
+
+/** Number of times to re-try an operation in case of deadlock */
+define( 'DEADLOCK_TRIES', 4 );
+/** Minimum time to wait before retry, in microseconds */
+define( 'DEADLOCK_DELAY_MIN', 500000 );
+/** Maximum time to wait before retry */
+define( 'DEADLOCK_DELAY_MAX', 1500000 );
+
+/**
+ * Database abstraction object
+ * @package MediaWiki
+ */
+class Database {
+
+#------------------------------------------------------------------------------
+# Variables
+#------------------------------------------------------------------------------
+       /**#@+
+        * @access private
+        */
+       var $mLastQuery = '';
+       
+       var $mServer, $mUser, $mPassword, $mConn = null, $mDBname;
+       var $mOut, $mOpened = false;
+       
+       var $mFailFunction; 
+       var $mTablePrefix;
+       var $mFlags;
+       var $mTrxLevel = 0;
+       var $mErrorCount = 0;
+       /**#@-*/
+
+#------------------------------------------------------------------------------
+# Accessors
+#------------------------------------------------------------------------------
+       # These optionally set a variable and return the previous state
+       
+       /**
+        * Fail function, takes a Database as a parameter
+        * Set to false for default, 1 for ignore errors
+        */
+       function failFunction( $function = NULL ) { 
+               return wfSetVar( $this->mFailFunction, $function ); 
+       }
+       
+       /**
+        * Output page, used for reporting errors
+        * FALSE means discard output
+        */
+       function &setOutputPage( &$out ) { 
+               $this->mOut =& $out; 
+       }
+       
+       /**
+        * Boolean, controls output of large amounts of debug information
+        */
+       function debug( $debug = NULL ) { 
+               return wfSetBit( $this->mFlags, DBO_DEBUG, $debug ); 
+       }
+       
+       /**
+        * Turns buffering of SQL result sets on (true) or off (false).
+        * Default is "on" and it should not be changed without good reasons.
+        */
+       function bufferResults( $buffer = NULL ) {
+               if ( is_null( $buffer ) ) {
+                       return !(bool)( $this->mFlags & DBO_NOBUFFER );
+               } else {
+                       return !wfSetBit( $this->mFlags, DBO_NOBUFFER, !$buffer ); 
+               }
+       }
+
+       /**
+        * Turns on (false) or off (true) the automatic generation and sending
+        * of a "we're sorry, but there has been a database error" page on
+        * database errors. Default is on (false). When turned off, the
+        * code should use wfLastErrno() and wfLastError() to handle the
+        * situation as appropriate.
+        */
+       function ignoreErrors( $ignoreErrors = NULL ) { 
+               return wfSetBit( $this->mFlags, DBO_IGNORE, $ignoreErrors ); 
+       }
+       
+       /**
+        * The current depth of nested transactions
+        * @param integer $level
+        */
+       function trxLevel( $level = NULL ) {
+               return wfSetVar( $this->mTrxLevel, $level );
+       }
+
+       /** 
+        * Number of errors logged, only useful when errors are ignored
+        */
+       function errorCount( $count = NULL ) {
+               return wfSetVar( $this->mErrorCount, $count );
+       }
+
+       /**#@+
+        * Get function
+        */
+       function lastQuery() { return $this->mLastQuery; }
+       function isOpen() { return $this->mOpened; }
+       /**#@-*/
+
+#------------------------------------------------------------------------------
+# Other functions
+#------------------------------------------------------------------------------
+
+       /**#@+
+        * @param string $server database server host
+        * @param string $user database user name
+        * @param string $password database user password
+        * @param string $dbname database name
+        */
+        
+       /**
+        * @param failFunction
+        * @param $flags
+        * @param string $tablePrefix Database table prefixes. By default use the prefix gave in LocalSettings.php
+        */
+       function Database( $server = false, $user = false, $password = false, $dbName = false, 
+               $failFunction = false, $flags = 0, $tablePrefix = 'get from global' ) {
+               
+               global $wgOut, $wgDBprefix, $wgCommandLineMode;
+               # Can't get a reference if it hasn't been set yet
+               if ( !isset( $wgOut ) ) {
+                       $wgOut = NULL;
+               }
+               $this->mOut =& $wgOut;
+
+               $this->mFailFunction = $failFunction;
+               $this->mFlags = $flags;
+               
+               if ( $this->mFlags & DBO_DEFAULT ) {
+                       if ( $wgCommandLineMode ) {
+                               $this->mFlags &= ~DBO_TRX;
+                       } else {
+                               $this->mFlags |= DBO_TRX;
+                       }
+               }
+
+               /*
+               // Faster read-only access
+               if ( wfReadOnly() ) {
+                       $this->mFlags |= DBO_PERSISTENT;
+                       $this->mFlags &= ~DBO_TRX;
+               }*/
+               
+               /** Get the default table prefix*/
+               if ( $tablePrefix == 'get from global' ) {
+                       $this->mTablePrefix = $wgDBprefix;
+               } else {
+                       $this->mTablePrefix = $tablePrefix;
+               }
+
+               if ( $server ) {
+                       $this->open( $server, $user, $password, $dbName );
+               }
+       }
+       
+       /**
+        * @static
+        * @param failFunction
+        * @param $flags
+        */
+       function newFromParams( $server, $user, $password, $dbName, 
+               $failFunction = false, $flags = 0 )
+       {
+               return new Database( $server, $user, $password, $dbName, $failFunction, $flags );
+       }
+       
+       /**
+        * Usually aborts on failure
+        * If the failFunction is set to a non-zero integer, returns success
+        */
+       function open( $server, $user, $password, $dbName ) {
+               # Test for missing mysql.so
+               # First try to load it
+               if (!@extension_loaded('mysql')) {
+                       @dl('mysql.so');
+               }
+
+               # Otherwise we get a suppressed fatal error, which is very hard to track down
+               if ( !function_exists( 'mysql_connect' ) ) {
+                       die( "MySQL functions missing, have you compiled PHP with the --with-mysql option?\n" );
+               }
+               
+               $this->close();
+               $this->mServer = $server;
+               $this->mUser = $user;
+               $this->mPassword = $password;
+               $this->mDBname = $dbName;
+               
+               $success = false;
+               
+               if ( $this->mFlags & DBO_PERSISTENT ) {
+                       @/**/$this->mConn = mysql_pconnect( $server, $user, $password );
+               } else {
+                       # Create a new connection...
+                       if( version_compare( PHP_VERSION, '4.2.0', 'ge' ) ) {
+                               @/**/$this->mConn = mysql_connect( $server, $user, $password, true );
+                       } else {
+                               # On PHP 4.1 the new_link parameter is not available. We cannot
+                               # guarantee that we'll actually get a new connection, and this
+                               # may cause some operations to fail possibly.
+                               @/**/$this->mConn = mysql_connect( $server, $user, $password );
+                       }
+               }
+
+               if ( $dbName != '' ) {
+                       if ( $this->mConn !== false ) {
+                               $success = @/**/mysql_select_db( $dbName, $this->mConn );
+                               if ( !$success ) {
+                                       wfDebug( "Error selecting database \"$dbName\": " . $this->lastError() . "\n" );
+                               }
+                       } else {
+                               wfDebug( "DB connection error\n" );
+                               wfDebug( "Server: $server, User: $user, Password: " . 
+                                       substr( $password, 0, 3 ) . "..., error: " . mysql_error() . "\n" );
+                               $success = false;
+                       }
+               } else {
+                       # Delay USE query
+                       $success = (bool)$this->mConn;
+               }
+               
+               if ( !$success ) {
+                       $this->reportConnectionError();
+               }
+               
+               global $wgDBmysql5;
+               if( $wgDBmysql5 ) {
+                       // Tell the server we're communicating with it in UTF-8.
+                       // This may engage various charset conversions.
+                       $this->query( 'SET NAMES utf8' );
+               }
+               
+               $this->mOpened = $success;
+               return $success;
+       }
+       /**#@-*/
+       
+       /**
+        * Closes a database connection.
+        * if it is open : commits any open transactions
+        *
+        * @return bool operation success. true if already closed.
+        */
+       function close()
+       {
+               $this->mOpened = false;
+               if ( $this->mConn ) {
+                       if ( $this->trxLevel() ) {
+                               $this->immediateCommit();
+                       }
+                       return mysql_close( $this->mConn );
+               } else {
+                       return true;
+               }
+       }
+       
+       /**
+        * @access private
+        * @param string $msg error message ?
+        */
+       function reportConnectionError() {
+               if ( $this->mFailFunction ) {
+                       if ( !is_int( $this->mFailFunction ) ) {
+                               $ff = $this->mFailFunction;
+                               $ff( $this, mysql_error() );
+                       }
+               } else {
+                       wfEmergencyAbort( $this, $this->lastError() );
+               }
+       }
+       
+       /**
+        * Usually aborts on failure
+        * If errors are explicitly ignored, returns success
+        */
+       function query( $sql, $fname = '', $tempIgnore = false ) {
+               global $wgProfiling, $wgCommandLineMode;
+
+               if ( $wgProfiling ) {
+                       # generalizeSQL will probably cut down the query to reasonable
+                       # logging size most of the time. The substr is really just a sanity check.
+                       $profName = 'query: ' . $fname . ' ' . substr( Database::generalizeSQL( $sql ), 0, 255 ); 
+                       wfProfileIn( 'Database::query' );
+                       wfProfileIn( $profName );
+               }
+               
+               $this->mLastQuery = $sql;
+               
+               # Add a comment for easy SHOW PROCESSLIST interpretation
+               if ( $fname ) {
+                       $commentedSql = "/* $fname */ $sql";
+               } else {
+                       $commentedSql = $sql;
+               }
+
+               # If DBO_TRX is set, start a transaction
+               if ( ( $this->mFlags & DBO_TRX ) && !$this->trxLevel() && $sql != 'BEGIN' ) {
+                       $this->begin();
+               }
+
+               if ( $this->debug() ) {
+                       $sqlx = substr( $commentedSql, 0, 500 );
+                       $sqlx = strtr( $sqlx, "\t\n", '  ' );
+                       wfDebug( "SQL: $sqlx\n" );
+               }
+               
+               # Do the query and handle errors
+               $ret = $this->doQuery( $commentedSql );
+
+               # Try reconnecting if the connection was lost
+               if ( false === $ret && ( $this->lastErrno() == 2013 || $this->lastErrno() == 2006 ) ) {
+                       # Transaction is gone, like it or not
+                       $this->mTrxLevel = 0;
+                       wfDebug( "Connection lost, reconnecting...\n" );
+                       if ( $this->ping() ) {
+                               wfDebug( "Reconnected\n" );
+                               $ret = $this->doQuery( $commentedSql );
+                       } else {
+                               wfDebug( "Failed\n" );
+                       }
+               }
+
+               if ( false === $ret ) {
+                       $this->reportQueryError( $this->lastError(), $this->lastErrno(), $sql, $fname, $tempIgnore );
+               }
+                               
+               if ( $wgProfiling ) {
+                       wfProfileOut( $profName );
+                       wfProfileOut( 'Database::query' );
+               }
+               return $ret;
+       }
+       
+       /**
+        * The DBMS-dependent part of query()
+        * @param string $sql SQL query.
+        */
+       function doQuery( $sql ) {
+               if( $this->bufferResults() ) {
+                       $ret = mysql_query( $sql, $this->mConn );
+               } else {
+                       $ret = mysql_unbuffered_query( $sql, $this->mConn );
+               }       
+               return $ret;
+       }
+
+       /**
+        * @param $error
+        * @param $errno
+        * @param $sql
+        * @param string $fname
+        * @param bool $tempIgnore
+        */
+       function reportQueryError( $error, $errno, $sql, $fname, $tempIgnore = false ) {
+               global $wgCommandLineMode, $wgFullyInitialised;
+               # Ignore errors during error handling to avoid infinite recursion
+               $ignore = $this->ignoreErrors( true );
+               $this->mErrorCount ++;
+
+               if( $ignore || $tempIgnore ) {
+                       wfDebug("SQL ERROR (ignored): " . $error . "\n");
+               } else {
+                       $sql1line = str_replace( "\n", "\\n", $sql );
+                       wfLogDBError("$fname\t{$this->mServer}\t$errno\t$error\t$sql1line\n");
+                       wfDebug("SQL ERROR: " . $error . "\n");
+                       if ( $wgCommandLineMode || !$this->mOut || empty( $wgFullyInitialised ) ) {
+                               $message = "A database error has occurred\n" .
+                                 "Query: $sql\n" .
+                                 "Function: $fname\n" .
+                                 "Error: $errno $error\n";
+                               if ( !$wgCommandLineMode ) {    
+                                       $message = nl2br( $message );
+                               }
+                               wfDebugDieBacktrace( $message );
+                       } else {
+                               // this calls wfAbruptExit()
+                               $this->mOut->databaseError( $fname, $sql, $error, $errno );                             
+                       }
+               }
+               $this->ignoreErrors( $ignore );
+       }
+
+
+       /**
+        * Intended to be compatible with the PEAR::DB wrapper functions.
+        * http://pear.php.net/manual/en/package.database.db.intro-execute.php
+        *
+        * ? = scalar value, quoted as necessary
+        * ! = raw SQL bit (a function for instance)
+        * & = filename; reads the file and inserts as a blob
+        *     (we don't use this though...)
+        */
+       function prepare( $sql, $func = 'Database::prepare' ) {
+               /* MySQL doesn't support prepared statements (yet), so just
+                  pack up the query for reference. We'll manually replace
+                  the bits later. */
+               return array( 'query' => $sql, 'func' => $func );
+       }
+       
+       function freePrepared( $prepared ) {
+               /* No-op for MySQL */
+       }
+       
+       /**
+        * Execute a prepared query with the various arguments
+        * @param string $prepared the prepared sql
+        * @param mixed $args Either an array here, or put scalars as varargs
+        */
+       function execute( $prepared, $args = null ) {
+               if( !is_array( $args ) ) {
+                       # Pull the var args
+                       $args = func_get_args();
+                       array_shift( $args );
+               }
+               $sql = $this->fillPrepared( $prepared['query'], $args );
+               return $this->query( $sql, $prepared['func'] );
+       }
+       
+       /**
+        * Prepare & execute an SQL statement, quoting and inserting arguments
+        * in the appropriate places.
+        * @param string $query
+        * @param string $args ...
+        */
+       function safeQuery( $query, $args = null ) {
+               $prepared = $this->prepare( $query, 'Database::safeQuery' );
+               if( !is_array( $args ) ) {
+                       # Pull the var args
+                       $args = func_get_args();
+                       array_shift( $args );
+               }
+               $retval = $this->execute( $prepared, $args );
+               $this->freePrepared( $prepared );
+               return $retval;
+       }
+       
+       /**
+        * For faking prepared SQL statements on DBs that don't support
+        * it directly.
+        * @param string $preparedSql - a 'preparable' SQL statement
+        * @param array $args - array of arguments to fill it with
+        * @return string executable SQL
+        */
+       function fillPrepared( $preparedQuery, $args ) {
+               $n = 0;
+               reset( $args );
+               $this->preparedArgs =& $args;
+               return preg_replace_callback( '/(\\\\[?!&]|[?!&])/',
+                       array( &$this, 'fillPreparedArg' ), $preparedQuery );
+       }
+       
+       /**
+        * preg_callback func for fillPrepared()
+        * The arguments should be in $this->preparedArgs and must not be touched
+        * while we're doing this.
+        * 
+        * @param array $matches
+        * @return string
+        * @access private
+        */
+       function fillPreparedArg( $matches ) {
+               switch( $matches[1] ) {
+                       case '\\?': return '?';
+                       case '\\!': return '!';
+                       case '\\&': return '&';
+               }
+               list( $n, $arg ) = each( $this->preparedArgs );
+               switch( $matches[1] ) {
+                       case '?': return $this->addQuotes( $arg );
+                       case '!': return $arg;
+                       case '&':
+                               # return $this->addQuotes( file_get_contents( $arg ) );
+                               wfDebugDieBacktrace( '& mode is not implemented. If it\'s really needed, uncomment the line above.' );
+                       default:
+                               wfDebugDieBacktrace( 'Received invalid match. This should never happen!' );
+               }
+       }
+       
+       /**#@+
+        * @param mixed $res A SQL result
+        */
+       /**
+        * Free a result object
+        */
+       function freeResult( $res ) {
+               if ( !@/**/mysql_free_result( $res ) ) {
+                       wfDebugDieBacktrace( "Unable to free MySQL result\n" );
+               }
+       }
+       
+       /**
+        * Fetch the next row from the given result object, in object form
+        */
+       function fetchObject( $res ) {
+               @/**/$row = mysql_fetch_object( $res );
+               if( mysql_errno() ) {
+                       wfDebugDieBacktrace( 'Error in fetchObject(): ' . htmlspecialchars( mysql_error() ) );
+               }
+               return $row;
+       }
+
+       /**
+        * Fetch the next row from the given result object
+        * Returns an array
+        */
+       function fetchRow( $res ) {
+               @/**/$row = mysql_fetch_array( $res );
+               if (mysql_errno() ) {
+                       wfDebugDieBacktrace( 'Error in fetchRow(): ' . htmlspecialchars( mysql_error() ) );
+               }
+               return $row;
+       }       
+
+       /**
+        * Get the number of rows in a result object
+        */
+       function numRows( $res ) {
+               @/**/$n = mysql_num_rows( $res ); 
+               if( mysql_errno() ) {
+                       wfDebugDieBacktrace( 'Error in numRows(): ' . htmlspecialchars( mysql_error() ) );
+               }
+               return $n;
+       }
+       
+       /**
+        * Get the number of fields in a result object
+        * See documentation for mysql_num_fields()
+        */
+       function numFields( $res ) { return mysql_num_fields( $res ); }
+
+       /**
+        * Get a field name in a result object
+        * See documentation for mysql_field_name()
+        */
+       function fieldName( $res, $n ) { return mysql_field_name( $res, $n ); }
+
+       /**
+        * Get the inserted value of an auto-increment row
+        *
+        * The value inserted should be fetched from nextSequenceValue()
+        *
+        * Example:
+        * $id = $dbw->nextSequenceValue('page_page_id_seq');
+        * $dbw->insert('page',array('page_id' => $id));
+        * $id = $dbw->insertId();
+        */
+       function insertId() { return mysql_insert_id( $this->mConn ); }
+       
+       /**
+        * Change the position of the cursor in a result object
+        * See mysql_data_seek()
+        */
+       function dataSeek( $res, $row ) { return mysql_data_seek( $res, $row ); }
+       
+       /**
+        * Get the last error number
+        * See mysql_errno()
+        */
+       function lastErrno() { 
+               if ( $this->mConn ) {
+                       return mysql_errno( $this->mConn ); 
+               } else {
+                       return mysql_errno();
+               }
+       }
+       
+       /**
+        * Get a description of the last error
+        * See mysql_error() for more details
+        */
+       function lastError() { 
+               if ( $this->mConn ) {
+                       # Even if it's non-zero, it can still be invalid
+                       wfSuppressWarnings();
+                       $error = mysql_error( $this->mConn );
+                       if ( !$error ) {
+                               $error = mysql_error();
+                       }
+                       wfRestoreWarnings();
+               } else {
+                       $error = mysql_error();
+               }
+               if( $error ) {
+                       $error .= ' (' . $this->mServer . ')';
+               }
+               return $error;
+       }       
+       /**
+        * Get the number of rows affected by the last write query
+        * See mysql_affected_rows() for more details
+        */
+       function affectedRows() { return mysql_affected_rows( $this->mConn ); }
+       /**#@-*/ // end of template : @param $result
+
+       /**
+        * Simple UPDATE wrapper
+        * Usually aborts on failure
+        * If errors are explicitly ignored, returns success
+        *
+        * This function exists for historical reasons, Database::update() has a more standard 
+        * calling convention and feature set
+        */
+       function set( $table, $var, $value, $cond, $fname = 'Database::set' )
+       {
+               $table = $this->tableName( $table );
+               $sql = "UPDATE $table SET $var = '" .
+                 $this->strencode( $value ) . "' WHERE ($cond)";
+               return (bool)$this->query( $sql, $fname );
+       }
+       
+       /**
+        * Simple SELECT wrapper, returns a single field, input must be encoded
+        * Usually aborts on failure
+        * If errors are explicitly ignored, returns FALSE on failure
+        */
+       function selectField( $table, $var, $cond='', $fname = 'Database::selectField', $options = array() ) {
+               if ( !is_array( $options ) ) {
+                       $options = array( $options );
+               }
+               $options['LIMIT'] = 1;
+
+               $res = $this->select( $table, $var, $cond, $fname, $options );
+               if ( $res === false || !$this->numRows( $res ) ) {
+                       return false;
+               }
+               $row = $this->fetchRow( $res );
+               if ( $row !== false ) {
+                       $this->freeResult( $res );
+                       return $row[0];
+               } else {
+                       return false;
+               }
+       }
+       
+       /**
+        * Returns an optional USE INDEX clause to go after the table, and a
+        * string to go at the end of the query
+        *
+        * @access private
+        *
+        * @param array $options an associative array of options to be turned into
+        *              an SQL query, valid keys are listed in the function.
+        * @return array
+        */
+       function makeSelectOptions( $options ) {
+               $tailOpts = '';
+
+               if ( isset( $options['GROUP BY'] ) ) {
+                       $tailOpts .= " GROUP BY {$options['GROUP BY']}";
+               }
+               if ( isset( $options['ORDER BY'] ) ) {
+                       $tailOpts .= " ORDER BY {$options['ORDER BY']}";
+               } 
+               if ( isset( $options['LIMIT'] ) ) {
+                       $tailOpts .= " LIMIT {$options['LIMIT']}";
+               }
+
+               if ( is_numeric( array_search( 'FOR UPDATE', $options ) ) ) {
+                       $tailOpts .= ' FOR UPDATE';
+               }
+               
+               if ( is_numeric( array_search( 'LOCK IN SHARE MODE', $options ) ) ) {
+                       $tailOpts .= ' LOCK IN SHARE MODE';
+               }
+
+               if ( isset( $options['USE INDEX'] ) ) {
+                       $useIndex = $this->useIndexClause( $options['USE INDEX'] );
+               } else {
+                       $useIndex = '';
+               }
+               return array( $useIndex, $tailOpts );
+       }
+
+       /**
+        * SELECT wrapper
+        */
+       function select( $table, $vars, $conds='', $fname = 'Database::select', $options = array() )
+       {
+               if( is_array( $vars ) ) {
+                       $vars = implode( ',', $vars );
+               }
+               if( is_array( $table ) ) {
+                       $from = ' FROM ' . implode( ',', array_map( array( &$this, 'tableName' ), $table ) );
+               } elseif ($table!='') {
+                       $from = ' FROM ' .$this->tableName( $table );
+               } else {
+                       $from = '';
+               }
+
+               list( $useIndex, $tailOpts ) = $this->makeSelectOptions( (array)$options );
+               
+               if( !empty( $conds ) ) {
+                       if ( is_array( $conds ) ) {
+                               $conds = $this->makeList( $conds, LIST_AND );
+                       }
+                       $sql = "SELECT $vars $from $useIndex WHERE $conds $tailOpts";
+               } else {
+                       $sql = "SELECT $vars $from $useIndex $tailOpts";
+               }
+               return $this->query( $sql, $fname );
+       }
+
+       /**
+        * Single row SELECT wrapper
+        * Aborts or returns FALSE on error
+        * 
+        * $vars: the selected variables
+        * $conds: a condition map, terms are ANDed together. 
+        *   Items with numeric keys are taken to be literal conditions
+        * Takes an array of selected variables, and a condition map, which is ANDed
+        * e.g: selectRow( "page", array( "page_id" ), array( "page_namespace" =>
+        * NS_MAIN, "page_title" => "Astronomy" ) )   would return an object where
+        * $obj- >page_id is the ID of the Astronomy article
+        *
+        * @todo migrate documentation to phpdocumentor format
+        */
+       function selectRow( $table, $vars, $conds, $fname = 'Database::selectRow', $options = array() ) {
+               $options['LIMIT'] = 1;
+               $res = $this->select( $table, $vars, $conds, $fname, $options );
+               if ( $res === false || !$this->numRows( $res ) ) {
+                       return false;
+               }
+               $obj = $this->fetchObject( $res );
+               $this->freeResult( $res );
+               return $obj;
+               
+       }
+       
+       /**
+        * Removes most variables from an SQL query and replaces them with X or N for numbers.
+        * It's only slightly flawed. Don't use for anything important.
+        *
+        * @param string $sql A SQL Query
+        * @static
+        */
+       function generalizeSQL( $sql ) {        
+               # This does the same as the regexp below would do, but in such a way
+               # as to avoid crashing php on some large strings.
+               # $sql = preg_replace ( "/'([^\\\\']|\\\\.)*'|\"([^\\\\\"]|\\\\.)*\"/", "'X'", $sql);
+       
+               $sql = str_replace ( "\\\\", '', $sql);
+               $sql = str_replace ( "\\'", '', $sql);
+               $sql = str_replace ( "\\\"", '', $sql);
+               $sql = preg_replace ("/'.*'/s", "'X'", $sql);
+               $sql = preg_replace ('/".*"/s', "'X'", $sql);
+       
+               # All newlines, tabs, etc replaced by single space
+               $sql = preg_replace ( "/\s+/", ' ', $sql);
+       
+               # All numbers => N      
+               $sql = preg_replace ('/-?[0-9]+/s', 'N', $sql);
+       
+               return $sql;
+       }
+       
+       /**
+        * Determines whether a field exists in a table
+        * Usually aborts on failure
+        * If errors are explicitly ignored, returns NULL on failure
+        */
+       function fieldExists( $table, $field, $fname = 'Database::fieldExists' ) {
+               $table = $this->tableName( $table );
+               $res = $this->query( 'DESCRIBE '.$table, $fname );
+               if ( !$res ) {
+                       return NULL;
+               }
+               
+               $found = false;
+               
+               while ( $row = $this->fetchObject( $res ) ) {
+                       if ( $row->Field == $field ) {
+                               $found = true;
+                               break;
+                       }
+               }
+               return $found;
+       }
+       
+       /**
+        * Determines whether an index exists
+        * Usually aborts on failure
+        * If errors are explicitly ignored, returns NULL on failure
+        */
+       function indexExists( $table, $index, $fname = 'Database::indexExists' ) {
+               $info = $this->indexInfo( $table, $index, $fname );
+               if ( is_null( $info ) ) {
+                       return NULL;
+               } else {
+                       return $info !== false;
+               }
+       }
+       
+       
+       /**
+        * Get information about an index into an object
+        * Returns false if the index does not exist
+        */
+       function indexInfo( $table, $index, $fname = 'Database::indexInfo' ) {
+               # SHOW INDEX works in MySQL 3.23.58, but SHOW INDEXES does not.
+               # SHOW INDEX should work for 3.x and up:
+               # http://dev.mysql.com/doc/mysql/en/SHOW_INDEX.html
+               $table = $this->tableName( $table );
+               $sql = 'SHOW INDEX FROM '.$table;
+               $res = $this->query( $sql, $fname );
+               if ( !$res ) {
+                       return NULL;
+               }
+               
+               while ( $row = $this->fetchObject( $res ) ) {
+                       if ( $row->Key_name == $index ) {
+                               return $row;
+                       }
+               }
+               return false;
+       }
+       
+       /**
+        * Query whether a given table exists
+        */
+       function tableExists( $table ) {
+               $table = $this->tableName( $table );
+               $old = $this->ignoreErrors( true );
+               $res = $this->query( "SELECT 1 FROM $table LIMIT 1" );
+               $this->ignoreErrors( $old );
+               if( $res ) {
+                       $this->freeResult( $res );
+                       return true;
+               } else {
+                       return false;
+               }
+       }
+
+       /**
+        * mysql_fetch_field() wrapper
+        * Returns false if the field doesn't exist
+        *
+        * @param $table
+        * @param $field
+        */
+       function fieldInfo( $table, $field ) {
+               $table = $this->tableName( $table );
+               $res = $this->query( "SELECT * FROM $table LIMIT 1" );
+               $n = mysql_num_fields( $res );
+               for( $i = 0; $i < $n; $i++ ) {
+                       $meta = mysql_fetch_field( $res, $i );
+                       if( $field == $meta->name ) {
+                               return $meta;
+                       }
+               }
+               return false;
+       }
+       
+       /**
+        * mysql_field_type() wrapper
+        */
+       function fieldType( $res, $index ) {
+               return mysql_field_type( $res, $index );
+       }
+
+       /**
+        * Determines if a given index is unique
+        */
+       function indexUnique( $table, $index ) {
+               $indexInfo = $this->indexInfo( $table, $index );
+               if ( !$indexInfo ) {
+                       return NULL;
+               }
+               return !$indexInfo->Non_unique;
+       }
+
+       /**
+        * INSERT wrapper, inserts an array into a table
+        *
+        * $a may be a single associative array, or an array of these with numeric keys, for 
+        * multi-row insert.
+        *
+        * Usually aborts on failure
+        * If errors are explicitly ignored, returns success
+        */
+       function insert( $table, $a, $fname = 'Database::insert', $options = array() ) {
+               # No rows to insert, easy just return now
+               if ( !count( $a ) ) {
+                       return true;
+               }
+
+               $table = $this->tableName( $table );
+               if ( !is_array( $options ) ) {
+                       $options = array( $options );
+               }
+               if ( isset( $a[0] ) && is_array( $a[0] ) ) {
+                       $multi = true;
+                       $keys = array_keys( $a[0] );
+               } else {
+                       $multi = false;
+                       $keys = array_keys( $a );
+               }
+
+               $sql = 'INSERT ' . implode( ' ', $options ) . 
+                       " INTO $table (" . implode( ',', $keys ) . ') VALUES ';
+
+               if ( $multi ) {
+                       $first = true;
+                       foreach ( $a as $row ) {
+                               if ( $first ) {
+                                       $first = false;
+                               } else {
+                                       $sql .= ',';
+                               }
+                               $sql .= '(' . $this->makeList( $row ) . ')';
+                       }
+               } else {
+                       $sql .= '(' . $this->makeList( $a ) . ')';
+               }
+               return (bool)$this->query( $sql, $fname );
+       }
+
+       /**
+        * Make UPDATE options for the Database::update function
+        *
+        * @access private
+        * @param array $options The options passed to Database::update
+        * @return string
+        */
+       function makeUpdateOptions( $options ) {
+               if( !is_array( $options ) ) {
+                       wfDebugDieBacktrace( 'makeUpdateOptions given non-array' );
+               }
+               $opts = array();
+               if ( in_array( 'LOW_PRIORITY', $options ) )
+                       $opts[] = $this->lowPriorityOption();
+               if ( in_array( 'IGNORE', $options ) ) 
+                       $opts[] = 'IGNORE';
+               return implode(' ', $opts);
+       }
+       
+       /**
+        * UPDATE wrapper, takes a condition array and a SET array
+        *
+        * @param string $table  The table to UPDATE
+        * @param array  $values An array of values to SET
+        * @param array  $conds  An array of conditions (WHERE)
+        * @param string $fname  The Class::Function calling this function
+        *                       (for the log)
+        * @param array  $options An array of UPDATE options, can be one or
+        *                        more of IGNORE, LOW_PRIORITY
+        */
+       function update( $table, $values, $conds, $fname = 'Database::update', $options = array() ) {
+               $table = $this->tableName( $table );
+               $opts = $this->makeUpdateOptions( $options );
+               $sql = "UPDATE $opts $table SET " . $this->makeList( $values, LIST_SET );
+               if ( $conds != '*' ) {
+                       $sql .= " WHERE " . $this->makeList( $conds, LIST_AND );
+               }
+               $this->query( $sql, $fname );
+       }
+       
+       /**
+        * Makes a wfStrencoded list from an array
+        * $mode: LIST_COMMA         - comma separated, no field names
+        *        LIST_AND           - ANDed WHERE clause (without the WHERE)
+        *        LIST_SET           - comma separated with field names, like a SET clause
+        *        LIST_NAMES         - comma separated field names
+        */
+       function makeList( $a, $mode = LIST_COMMA ) {
+               if ( !is_array( $a ) ) {
+                       wfDebugDieBacktrace( 'Database::makeList called with incorrect parameters' );
+               }
+
+               $first = true;
+               $list = '';
+               foreach ( $a as $field => $value ) {
+                       if ( !$first ) {
+                               if ( $mode == LIST_AND ) {
+                                       $list .= ' AND ';
+                               } else {
+                                       $list .= ',';
+                               }
+                       } else {
+                               $first = false;
+                       }
+                       if ( $mode == LIST_AND && is_numeric( $field ) ) {
+                               $list .= "($value)";
+                       } elseif ( $mode == LIST_AND && is_array ($value) ) {
+                               $list .= $field." IN (".$this->makeList($value).") ";
+                       } else {
+                               if ( $mode == LIST_AND || $mode == LIST_SET ) {
+                                       $list .= "$field = ";
+                               }
+                               $list .= $mode == LIST_NAMES ? $value : $this->addQuotes( $value );
+                       }
+               }
+               return $list;
+       }
+       
+       /**
+        * Change the current database
+        */
+       function selectDB( $db ) {
+               $this->mDBname = $db;
+               return mysql_select_db( $db, $this->mConn );
+       }
+
+       /**
+        * Starts a timer which will kill the DB thread after $timeout seconds
+        */
+       function startTimer( $timeout ) {
+               global $IP;
+               if( function_exists( 'mysql_thread_id' ) ) {
+                       # This will kill the query if it's still running after $timeout seconds.
+                       $tid = mysql_thread_id( $this->mConn );
+                       exec( "php $IP/includes/killthread.php $timeout $tid &>/dev/null &" );
+               }
+       }
+
+       /**
+        * Stop a timer started by startTimer()
+        * Currently unimplemented.
+        *
+        */
+       function stopTimer() { }
+
+       /**
+        * Format a table name ready for use in constructing an SQL query
+        * 
+        * This does two important things: it quotes table names which as necessary, 
+        * and it adds a table prefix if there is one.
+        * 
+        * All functions of this object which require a table name call this function 
+        * themselves. Pass the canonical name to such functions. This is only needed
+        * when calling query() directly. 
+        *
+        * @param string $name database table name
+        */
+       function tableName( $name ) {
+               global $wgSharedDB;
+               # Skip quoted literals
+               if ( $name{0} != '`' ) {
+                       if ( $this->mTablePrefix !== '' &&  strpos( '.', $name ) === false ) {
+                               $name = "{$this->mTablePrefix}$name";
+                       }
+                       if ( isset( $wgSharedDB ) && "{$this->mTablePrefix}user" == $name ) {
+                               $name = "`$wgSharedDB`.`$name`";
+                       } else {
+                               # Standard quoting
+                               $name = "`$name`";
+                       }
+               }               
+               return $name;
+       }
+
+       /**
+        * Fetch a number of table names into an array
+        * This is handy when you need to construct SQL for joins
+        *
+        * Example:
+        * extract($dbr->tableNames('user','watchlist'));
+        * $sql = "SELECT wl_namespace,wl_title FROM $watchlist,$user 
+        *         WHERE wl_user=user_id AND wl_user=$nameWithQuotes";
+        */
+       function tableNames() {
+               $inArray = func_get_args();
+               $retVal = array();
+               foreach ( $inArray as $name ) {
+                       $retVal[$name] = $this->tableName( $name );
+               }
+               return $retVal;
+       }
+       
+       /**
+        * Wrapper for addslashes()
+        * @param string $s String to be slashed.
+        * @return string slashed string.
+        */
+       function strencode( $s ) {
+               return addslashes( $s );
+       }
+
+       /**
+        * If it's a string, adds quotes and backslashes
+        * Otherwise returns as-is
+        */
+       function addQuotes( $s ) {
+               if ( is_null( $s ) ) {
+                       return 'NULL';
+               } else {
+                       # This will also quote numeric values. This should be harmless,
+                       # and protects against weird problems that occur when they really
+                       # _are_ strings such as article titles and string->number->string
+                       # conversion is not 1:1.
+                       return "'" . $this->strencode( $s ) . "'";
+               } 
+       }
+               
+       /**
+        * Returns an appropriately quoted sequence value for inserting a new row.
+        * MySQL has autoincrement fields, so this is just NULL. But the PostgreSQL
+        * subclass will return an integer, and save the value for insertId()
+        */
+       function nextSequenceValue( $seqName ) {
+               return NULL;
+       }
+
+       /**
+        * USE INDEX clause
+        * PostgreSQL doesn't have them and returns ""
+        */
+       function useIndexClause( $index ) {
+               global $wgDBmysql4;
+               return $wgDBmysql4
+                       ? "FORCE INDEX ($index)"
+                       : "USE INDEX ($index)";
+       }
+
+       /**
+        * REPLACE query wrapper
+        * PostgreSQL simulates this with a DELETE followed by INSERT
+        * $row is the row to insert, an associative array
+        * $uniqueIndexes is an array of indexes. Each element may be either a 
+        * field name or an array of field names
+        * 
+        * It may be more efficient to leave off unique indexes which are unlikely to collide. 
+        * However if you do this, you run the risk of encountering errors which wouldn't have 
+        * occurred in MySQL
+        *
+        * @todo migrate comment to phodocumentor format
+        */
+       function replace( $table, $uniqueIndexes, $rows, $fname = 'Database::replace' ) {
+               $table = $this->tableName( $table );
+
+               # Single row case
+               if ( !is_array( reset( $rows ) ) ) {
+                       $rows = array( $rows );
+               }
+
+               $sql = "REPLACE INTO $table (" . implode( ',', array_keys( $rows[0] ) ) .') VALUES ';
+               $first = true;
+               foreach ( $rows as $row ) {
+                       if ( $first ) {
+                               $first = false;
+                       } else {
+                               $sql .= ',';
+                       }
+                       $sql .= '(' . $this->makeList( $row ) . ')';
+               }
+               return $this->query( $sql, $fname );
+       }
+
+       /**
+        * DELETE where the condition is a join
+        * MySQL does this with a multi-table DELETE syntax, PostgreSQL does it with sub-selects
+        *
+        * For safety, an empty $conds will not delete everything. If you want to delete all rows where the 
+        * join condition matches, set $conds='*'
+        *
+        * DO NOT put the join condition in $conds
+        *
+        * @param string $delTable The table to delete from.
+        * @param string $joinTable The other table.
+        * @param string $delVar The variable to join on, in the first table.
+        * @param string $joinVar The variable to join on, in the second table.
+        * @param array $conds Condition array of field names mapped to variables, ANDed together in the WHERE clause
+        */
+       function deleteJoin( $delTable, $joinTable, $delVar, $joinVar, $conds, $fname = 'Database::deleteJoin' ) {
+               if ( !$conds ) {
+                       wfDebugDieBacktrace( 'Database::deleteJoin() called with empty $conds' );
+               }
+
+               $delTable = $this->tableName( $delTable );
+               $joinTable = $this->tableName( $joinTable );
+               $sql = "DELETE $delTable FROM $delTable, $joinTable WHERE $delVar=$joinVar ";
+               if ( $conds != '*' ) {
+                       $sql .= ' AND ' . $this->makeList( $conds, LIST_AND );
+               }
+               
+               return $this->query( $sql, $fname );
+       }
+
+       /**
+        * Returns the size of a text field, or -1 for "unlimited"
+        */
+       function textFieldSize( $table, $field ) {
+               $table = $this->tableName( $table );
+               $sql = "SHOW COLUMNS FROM $table LIKE \"$field\";";
+               $res = $this->query( $sql, 'Database::textFieldSize' );
+               $row = $this->fetchObject( $res );
+               $this->freeResult( $res );
+
+               if ( preg_match( "/\((.*)\)/", $row->Type, $m ) ) {
+                       $size = $m[1];
+               } else {
+                       $size = -1;
+               }
+               return $size;
+       }
+
+       /**
+        * @return string Returns the text of the low priority option if it is supported, or a blank string otherwise
+        */
+       function lowPriorityOption() {
+               return 'LOW_PRIORITY';
+       }
+
+       /**
+        * DELETE query wrapper
+        *
+        * Use $conds == "*" to delete all rows
+        */
+       function delete( $table, $conds, $fname = 'Database::delete' ) {
+               if ( !$conds ) {
+                       wfDebugDieBacktrace( 'Database::delete() called with no conditions' );
+               }
+               $table = $this->tableName( $table );
+               $sql = "DELETE FROM $table";
+               if ( $conds != '*' ) {
+                       $sql .= ' WHERE ' . $this->makeList( $conds, LIST_AND );
+               }
+               return $this->query( $sql, $fname );
+       }
+
+       /**
+        * INSERT SELECT wrapper
+        * $varMap must be an associative array of the form array( 'dest1' => 'source1', ...)
+        * Source items may be literals rather than field names, but strings should be quoted with Database::addQuotes()
+        * $conds may be "*" to copy the whole table
+        * srcTable may be an array of tables.
+        */
+       function insertSelect( $destTable, $srcTable, $varMap, $conds, $fname = 'Database::insertSelect', 
+               $options = array() ) 
+       {
+               $destTable = $this->tableName( $destTable );
+               if ( is_array( $options ) ) {
+                       $options = implode( ' ', $options );
+               }
+               if( is_array( $srcTable ) ) {
+                       $srcTable =  implode( ',', array_map( array( &$this, 'tableName' ), $srcTable ) );
+               } else { 
+                       $srcTable = $this->tableName( $srcTable );
+               }
+               $sql = "INSERT $options INTO $destTable (" . implode( ',', array_keys( $varMap ) ) . ')' .
+                       ' SELECT ' . implode( ',', $varMap ) . 
+                       " FROM $srcTable";
+               if ( $conds != '*' ) {
+                       $sql .= ' WHERE ' . $this->makeList( $conds, LIST_AND );
+               }
+               return $this->query( $sql, $fname );
+       }
+
+       /**
+        * Construct a LIMIT query with optional offset
+        * This is used for query pages
+        */
+       function limitResult($limit,$offset) {
+               return ' LIMIT '.(is_numeric($offset)?"{$offset},":"")."{$limit} ";
+       }
+
+       /**
+        * Returns an SQL expression for a simple conditional.
+        * Uses IF on MySQL.
+        *
+        * @param string $cond SQL expression which will result in a boolean value
+        * @param string $trueVal SQL expression to return if true
+        * @param string $falseVal SQL expression to return if false
+        * @return string SQL fragment
+        */
+       function conditional( $cond, $trueVal, $falseVal ) {
+               return " IF($cond, $trueVal, $falseVal) ";
+       }
+
+       /**
+        * Determines if the last failure was due to a deadlock
+        */
+       function wasDeadlock() {
+               return $this->lastErrno() == 1213;
+       }
+
+       /**
+        * Perform a deadlock-prone transaction.
+        *
+        * This function invokes a callback function to perform a set of write 
+        * queries. If a deadlock occurs during the processing, the transaction 
+        * will be rolled back and the callback function will be called again.
+        *
+        * Usage: 
+        *   $dbw->deadlockLoop( callback, ... );
+        *
+        * Extra arguments are passed through to the specified callback function. 
+        * 
+        * Returns whatever the callback function returned on its successful, 
+        * iteration, or false on error, for example if the retry limit was 
+        * reached.
+        */
+       function deadlockLoop() {
+               $myFname = 'Database::deadlockLoop';
+               
+               $this->query( 'BEGIN', $myFname );
+               $args = func_get_args();
+               $function = array_shift( $args );
+               $oldIgnore = $this->ignoreErrors( true );
+               $tries = DEADLOCK_TRIES;
+               if ( is_array( $function ) ) {
+                       $fname = $function[0];
+               } else {
+                       $fname = $function;
+               }
+               do {
+                       $retVal = call_user_func_array( $function, $args );
+                       $error = $this->lastError();
+                       $errno = $this->lastErrno();
+                       $sql = $this->lastQuery();
+                       
+                       if ( $errno ) {
+                               if ( $this->wasDeadlock() ) {
+                                       # Retry
+                                       usleep( mt_rand( DEADLOCK_DELAY_MIN, DEADLOCK_DELAY_MAX ) );
+                               } else {
+                                       $this->reportQueryError( $error, $errno, $sql, $fname );
+                               }
+                       }
+               } while( $this->wasDeadlock() && --$tries > 0 );
+               $this->ignoreErrors( $oldIgnore );
+               if ( $tries <= 0 ) {
+                       $this->query( 'ROLLBACK', $myFname );
+                       $this->reportQueryError( $error, $errno, $sql, $fname );
+                       return false;
+               } else {
+                       $this->query( 'COMMIT', $myFname );
+                       return $retVal;
+               }
+       }
+
+       /**
+        * Do a SELECT MASTER_POS_WAIT()
+        *
+        * @param string $file the binlog file
+        * @param string $pos the binlog position
+        * @param integer $timeout the maximum number of seconds to wait for synchronisation
+        */
+       function masterPosWait( $file, $pos, $timeout ) {
+               $fname = 'Database::masterPosWait';
+               wfProfileIn( $fname );
+               
+               
+               # Commit any open transactions
+               $this->immediateCommit();
+               
+               # Call doQuery() directly, to avoid opening a transaction if DBO_TRX is set
+               $encFile = $this->strencode( $file );
+               $sql = "SELECT MASTER_POS_WAIT('$encFile', $pos, $timeout)";
+               $res = $this->doQuery( $sql );
+               if ( $res && $row = $this->fetchRow( $res ) ) {
+                       $this->freeResult( $res );
+                       wfProfileOut( $fname );
+                       return $row[0];
+               } else {
+                       wfProfileOut( $fname );
+                       return false;
+               }
+       }
+
+       /**
+        * Get the position of the master from SHOW SLAVE STATUS
+        */
+       function getSlavePos() {
+               $res = $this->query( 'SHOW SLAVE STATUS', 'Database::getSlavePos' );
+               $row = $this->fetchObject( $res );
+               if ( $row ) {
+                       return array( $row->Master_Log_File, $row->Read_Master_Log_Pos );
+               } else {
+                       return array( false, false );
+               }
+       }
+       
+       /**
+        * Get the position of the master from SHOW MASTER STATUS
+        */
+       function getMasterPos() {
+               $res = $this->query( 'SHOW MASTER STATUS', 'Database::getMasterPos' );
+               $row = $this->fetchObject( $res );
+               if ( $row ) {
+                       return array( $row->File, $row->Position );
+               } else {
+                       return array( false, false );
+               }
+       }
+
+       /**
+        * Begin a transaction, or if a transaction has already started, continue it
+        */
+       function begin( $fname = 'Database::begin' ) {
+               if ( !$this->mTrxLevel ) {
+                       $this->immediateBegin( $fname );
+               } else {
+                       $this->mTrxLevel++;
+               }
+       }
+
+       /**
+        * End a transaction, or decrement the nest level if transactions are nested
+        */
+       function commit( $fname = 'Database::commit' ) {
+               if ( $this->mTrxLevel ) {
+                       $this->mTrxLevel--;
+               }
+               if ( !$this->mTrxLevel ) {
+                       $this->immediateCommit( $fname );
+               }
+       }
+
+       /**
+        * Rollback a transaction
+        */
+       function rollback( $fname = 'Database::rollback' ) {
+               $this->query( 'ROLLBACK', $fname );
+               $this->mTrxLevel = 0;
+       }
+
+       /**
+        * Begin a transaction, committing any previously open transaction
+        */
+       function immediateBegin( $fname = 'Database::immediateBegin' ) {
+               $this->query( 'BEGIN', $fname );
+               $this->mTrxLevel = 1;
+       }
+       
+       /**
+        * Commit transaction, if one is open
+        */
+       function immediateCommit( $fname = 'Database::immediateCommit' ) {
+               $this->query( 'COMMIT', $fname );
+               $this->mTrxLevel = 0;
+       }
+
+       /**
+        * Return MW-style timestamp used for MySQL schema
+        */
+       function timestamp( $ts=0 ) {
+               return wfTimestamp(TS_MW,$ts);
+       }
+       
+       /**
+        * Local database timestamp format or null
+        */
+       function timestampOrNull( $ts = null ) {
+               if( is_null( $ts ) ) {
+                       return null;
+               } else {
+                       return $this->timestamp( $ts );
+               }
+       }
+       
+       /**
+        * @todo document
+        */
+       function resultObject( $result ) {
+               if( empty( $result ) ) {
+                       return NULL;
+               } else {
+                       return new ResultWrapper( $this, $result );
+               }
+       }
+
+       /**
+        * Return aggregated value alias
+        */
+       function aggregateValue ($valuedata,$valuename='value') {
+               return $valuename;
+       }
+       
+       /**
+        * @return string wikitext of a link to the server software's web site
+        */
+       function getSoftwareLink() {
+               return "[http://www.mysql.com/ MySQL]";
+       }
+       
+       /**
+        * @return string Version information from the database
+        */
+       function getServerVersion() {
+               return mysql_get_server_info();
+       }
+
+       /**
+        * Ping the server and try to reconnect if it there is no connection
+        */
+       function ping() {
+               if( function_exists( 'mysql_ping' ) ) {
+                       return mysql_ping( $this->mConn );
+               } else {
+                       wfDebug( "Tried to call mysql_ping but this is ancient PHP version. Faking it!\n" );
+                       return true;
+               }
+       }
+       
+       /**
+        * Get slave lag.
+        * At the moment, this will only work if the DB user has the PROCESS privilege
+        */
+       function getLag() {
+               $res = $this->query( 'SHOW PROCESSLIST' );
+               # Find slave SQL thread. Assumed to be the second one running, which is a bit 
+               # dubious, but unfortunately there's no easy rigorous way
+               $slaveThreads = 0;
+               while ( $row = $this->fetchObject( $res ) ) {
+                       if ( $row->User == 'system user' ) {
+                               if ( ++$slaveThreads == 2 ) {
+                                       # This is it, return the time
+                                       return $row->Time;
+                               }
+                       }
+               }
+               return false;
+       }
+
+       /**
+        * Get status information from SHOW STATUS in an associative array
+        */
+       function getStatus() {
+               $res = $this->query( 'SHOW STATUS' );
+               $status = array();
+               while ( $row = $this->fetchObject( $res ) ) {
+                       $status[$row->Variable_name] = $row->Value;
+               }
+               return $status;
+       }
+} 
+
+/**
+ * Database abstraction object for mySQL
+ * Inherit all methods and properties of Database::Database()
+ *
+ * @package MediaWiki
+ * @see Database
+ */
+class DatabaseMysql extends Database {
+       # Inherit all
+}
+
+
+/**
+ * Result wrapper for grabbing data queried by someone else
+ *
+ * @package MediaWiki
+ */
+class ResultWrapper {
+       var $db, $result;
+       
+       /**
+        * @todo document
+        */
+       function ResultWrapper( $database, $result ) {
+               $this->db =& $database;
+               $this->result =& $result;
+       }
+
+       /**
+        * @todo document
+        */
+       function numRows() {
+               return $this->db->numRows( $this->result );
+       }
+       
+       /**
+        * @todo document
+        */
+       function fetchObject() {
+               return $this->db->fetchObject( $this->result );
+       }
+       
+       /**
+        * @todo document
+        */
+       function &fetchRow() {
+               return $this->db->fetchRow( $this->result );
+       }
+       
+       /**
+        * @todo document
+        */
+       function free() {
+               $this->db->freeResult( $this->result );
+               unset( $this->result );
+               unset( $this->db );
+       }
+
+       function seek( $row ) {
+               $this->db->dataSeek( $this->result, $row );
+       }
+}
+
+#------------------------------------------------------------------------------
+# Global functions
+#------------------------------------------------------------------------------
+
+/**
+ * Standard fail function, called by default when a connection cannot be
+ * established.
+ * Displays the file cache if possible
+ */
+function wfEmergencyAbort( &$conn, $error ) {
+       global $wgTitle, $wgUseFileCache, $title, $wgInputEncoding, $wgOutputEncoding;
+       global $wgSitename, $wgServer, $wgMessageCache, $wgLogo;
+
+       # I give up, Brion is right. Getting the message cache to work when there is no DB is tricky.
+       # Hard coding strings instead.
+
+       $noconnect = "<h1><img src='$wgLogo' style='float:left;margin-right:1em' alt=''>$wgSitename has a problem</h1><p><strong>Sorry! This site is experiencing technical difficulties.</strong></p><p>Try waiting a few minutes and reloading.</p><p><small>(Can't contact the database server: $1)</small></p>";
+       $mainpage = 'Main Page';
+       $searchdisabled = <<<EOT
+<p style="margin: 1.5em 2em 1em">$wgSitename search is disabled for performance reasons. You can search via Google in the meantime.
+<span style="font-size: 89%; display: block; margin-left: .2em">Note that their indexes of $wgSitename content may be out of date.</span></p>',
+EOT;
+
+       $googlesearch = "
+<!-- SiteSearch Google -->
+<FORM method=GET action=\"http://www.google.com/search\">
+<TABLE bgcolor=\"#FFFFFF\"><tr><td>
+<A HREF=\"http://www.google.com/\">
+<IMG SRC=\"http://www.google.com/logos/Logo_40wht.gif\"
+border=\"0\" ALT=\"Google\"></A>
+</td>
+<td>
+<INPUT TYPE=text name=q size=31 maxlength=255 value=\"$1\">
+<INPUT type=submit name=btnG VALUE=\"Google Search\">
+<font size=-1>
+<input type=hidden name=domains value=\"$wgServer\"><br /><input type=radio name=sitesearch value=\"\"> WWW <input type=radio name=sitesearch value=\"$wgServer\" checked> $wgServer <br />
+<input type='hidden' name='ie' value='$2'>
+<input type='hidden' name='oe' value='$2'>
+</font>
+</td></tr></TABLE>
+</FORM>
+<!-- SiteSearch Google -->";
+       $cachederror = "The following is a cached copy of the requested page, and may not be up to date. ";
+
+
+       if( !headers_sent() ) {
+               header( 'HTTP/1.0 500 Internal Server Error' );
+               header( 'Content-type: text/html; charset='.$wgOutputEncoding );
+               /* Don't cache error pages!  They cause no end of trouble... */
+               header( 'Cache-control: none' );
+               header( 'Pragma: nocache' );
+       }
+
+       # No database access
+       if ( is_object( $wgMessageCache ) ) {
+               $wgMessageCache->disable();
+       }
+       
+       $msg = wfGetSiteNotice();
+       if($msg == '') {
+               $msg = str_replace( '$1', htmlspecialchars( $error ), $noconnect );
+       }
+       $text = $msg;
+
+       if($wgUseFileCache) {
+               if($wgTitle) {
+                       $t =& $wgTitle;
+               } else {
+                       if($title) {
+                               $t = Title::newFromURL( $title );
+                       } elseif (@/**/$_REQUEST['search']) {
+                               $search = $_REQUEST['search'];
+                               echo $searchdisabled;
+                               echo str_replace( array( '$1', '$2' ), array( htmlspecialchars( $search ), 
+                                 $wgInputEncoding ), $googlesearch );
+                               wfErrorExit();
+                       } else {
+                               $t = Title::newFromText( $mainpage );
+                       }
+               }
+
+               $cache = new CacheManager( $t );
+               if( $cache->isFileCached() ) {
+                       $msg = '<p style="color: red"><b>'.$msg."<br />\n" .
+                               $cachederror . "</b></p>\n";
+                       
+                       $tag = '<div id="article">';
+                       $text = str_replace(
+                               $tag,
+                               $tag . $msg,
+                               $cache->fetchPageText() );
+               }
+       }
+       
+       echo $text;
+       wfErrorExit();
+}
+
+?>
diff --git a/includes/DatabaseFunctions.php b/includes/DatabaseFunctions.php
new file mode 100644 (file)
index 0000000..3705969
--- /dev/null
@@ -0,0 +1,371 @@
+<?php
+/**
+ * Backwards compatibility wrapper for Database.php
+ * 
+ * Note: $wgDatabase has ceased to exist. Destroy all references.
+ *
+ * @package MediaWiki
+ */
+
+/**
+ * Usually aborts on failure
+ * If errors are explicitly ignored, returns success
+ * @param string $sql SQL query
+ * @param mixed $db database handler
+ * @param string $fname name of the php function calling
+ */
+function wfQuery( $sql, $db, $fname = '' ) {
+       global $wgOut;
+       if ( !is_numeric( $db ) ) {
+               # Someone has tried to call this the old way
+               $wgOut->fatalError( wfMsgNoDB( 'wrong_wfQuery_params', $db, $sql ) );
+       }
+       $c =& wfGetDB( $db );
+       if ( $c !== false ) {
+               return $c->query( $sql, $fname );
+       } else {        
+               return false;
+       }
+}
+
+/**
+ *
+ * @param string $sql SQL query
+ * @param $dbi
+ * @param string $fname name of the php function calling
+ * @return array first row from the database
+ */
+function wfSingleQuery( $sql, $dbi, $fname = '' ) {
+       $db =& wfGetDB( $dbi );
+       $res = $db->query($sql, $fname );
+       $row = $db->fetchRow( $res );
+       $ret = $row[0];
+       $db->freeResult( $res );
+       return $ret;
+}
+
+/*
+ * @todo document function
+ */
+function &wfGetDB( $db = DB_LAST, $groups = array() ) {
+       global $wgLoadBalancer;
+       $ret =& $wgLoadBalancer->getConnection( $db, true, $groups );
+       return $ret;
+}
+       
+/**
+ * Turns on (false) or off (true) the automatic generation and sending
+ * of a "we're sorry, but there has been a database error" page on
+ * database errors. Default is on (false). When turned off, the
+ * code should use wfLastErrno() and wfLastError() to handle the
+ * situation as appropriate.
+ *
+ * @param $newstate
+ * @param $dbi
+ * @return Returns the previous state.
+ */
+function wfIgnoreSQLErrors( $newstate, $dbi = DB_LAST ) {
+       $db =& wfGetDB( $dbi );
+       if ( $db !== false ) {
+               return $db->ignoreErrors( $newstate );
+       } else {
+               return NULL;
+       }
+}
+
+/**#@+
+ * @param $res database result handler
+ * @param $dbi
+*/
+
+/**
+ * Free a database result
+ * @return bool whether result is sucessful or not
+ */
+function wfFreeResult( $res, $dbi = DB_LAST ) 
+{ 
+       $db =& wfGetDB( $dbi );
+       if ( $db !== false ) {
+               $db->freeResult( $res ); 
+               return true;
+       } else {        
+               return false;
+       }
+}
+
+/**
+ * Get an object from a database result
+ * @return object|false object we requested
+ */
+function wfFetchObject( $res, $dbi = DB_LAST ) { 
+       $db =& wfGetDB( $dbi );
+       if ( $db !== false ) {
+               return $db->fetchObject( $res, $dbi = DB_LAST ); 
+       } else {        
+               return false;
+       }
+}
+
+/**
+ * Get a row from a database result
+ * @return object|false row we requested
+ */
+function wfFetchRow( $res, $dbi = DB_LAST ) {
+       $db =& wfGetDB( $dbi );
+       if ( $db !== false ) {
+               return $db->fetchRow ( $res, $dbi = DB_LAST );
+       } else {        
+               return false;
+       }
+}
+
+/**
+ * Get a number of rows from a database result
+ * @return integer|false number of rows
+ */
+function wfNumRows( $res, $dbi = DB_LAST ) { 
+       $db =& wfGetDB( $dbi );
+       if ( $db !== false ) {
+               return $db->numRows( $res, $dbi = DB_LAST ); 
+       } else {        
+               return false;
+       }
+}
+
+/**
+ * Get the number of fields from a database result
+ * @return integer|false number of fields
+ */
+function wfNumFields( $res, $dbi = DB_LAST ) { 
+       $db =& wfGetDB( $dbi );
+       if ( $db !== false ) {
+               return $db->numFields( $res ); 
+       } else {        
+               return false;
+       }
+}
+
+/**
+ * Return name of a field in a result
+ * @param integer $n id of the field
+ * @return string|false name of field
+ */
+function wfFieldName( $res, $n, $dbi = DB_LAST ) 
+{ 
+       $db =& wfGetDB( $dbi );
+       if ( $db !== false ) {
+               return $db->fieldName( $res, $n, $dbi = DB_LAST ); 
+       } else {        
+               return false;
+       }
+}
+/**#@-*/
+
+/**
+ * @todo document function
+ */
+function wfInsertId( $dbi = DB_LAST ) { 
+       $db =& wfGetDB( $dbi );
+       if ( $db !== false ) {
+               return $db->insertId(); 
+       } else {        
+               return false;
+       }
+}
+
+/**
+ * @todo document function
+ */
+function wfDataSeek( $res, $row, $dbi = DB_LAST ) { 
+       $db =& wfGetDB( $dbi );
+       if ( $db !== false ) {
+               return $db->dataSeek( $res, $row ); 
+       } else {        
+               return false;
+       }
+}
+
+/**
+ * @todo document function
+ */
+function wfLastErrno( $dbi = DB_LAST ) { 
+       $db =& wfGetDB( $dbi );
+       if ( $db !== false ) {
+               return $db->lastErrno(); 
+       } else {        
+               return false;
+       }
+}
+
+/**
+ * @todo document function
+ */
+function wfLastError( $dbi = DB_LAST ) { 
+       $db =& wfGetDB( $dbi );
+       if ( $db !== false ) {
+               return $db->lastError(); 
+       } else {        
+               return false;
+       }
+}
+
+/**
+ * @todo document function
+ */
+function wfAffectedRows( $dbi = DB_LAST ) { 
+       $db =& wfGetDB( $dbi );
+       if ( $db !== false ) {
+               return $db->affectedRows(); 
+       } else {        
+               return false;
+       }
+}
+
+/**
+ * @todo document function
+ */
+function wfLastDBquery( $dbi = DB_LAST ) {
+       $db =& wfGetDB( $dbi );
+       if ( $db !== false ) {
+               return $db->lastQuery();
+       } else {        
+               return false;
+       }
+}
+
+/**
+ * @todo document function
+ */
+function wfSetSQL( $table, $var, $value, $cond, $dbi = DB_MASTER )
+{
+       $db =& wfGetDB( $dbi );
+       if ( $db !== false ) {
+               return $db->set( $table, $var, $value, $cond );
+       } else {        
+               return false;
+       }
+}
+
+
+/**
+ * @todo document function
+ */
+function wfGetSQL( $table, $var, $cond='', $dbi = DB_LAST )
+{
+       $db =& wfGetDB( $dbi );
+       if ( $db !== false ) {
+               return $db->selectField( $table, $var, $cond );
+       } else {        
+               return false;
+       }
+}
+
+/**
+ * @todo document function
+ */
+function wfFieldExists( $table, $field, $dbi = DB_LAST ) {
+       $db =& wfGetDB( $dbi );
+       if ( $db !== false ) {
+               return $db->fieldExists( $table, $field );
+       } else {        
+               return false;
+       }
+}
+
+/**
+ * @todo document function
+ */
+function wfIndexExists( $table, $index, $dbi = DB_LAST ) {
+       $db =& wfGetDB( $dbi );
+       if ( $db !== false ) {
+               return $db->indexExists( $table, $index );
+       } else {        
+               return false;
+       }
+}
+
+/**
+ * @todo document function
+ */
+function wfInsertArray( $table, $array, $fname = 'wfInsertArray', $dbi = DB_MASTER ) {
+       $db =& wfGetDB( $dbi );
+       if ( $db !== false ) {
+               return $db->insert( $table, $array, $fname );
+       } else {        
+               return false;
+       }
+}
+
+/**
+ * @todo document function
+ */
+function wfGetArray( $table, $vars, $conds, $fname = 'wfGetArray', $dbi = DB_LAST ) {
+       $db =& wfGetDB( $dbi );
+       if ( $db !== false ) {
+               return $db->getArray( $table, $vars, $conds, $fname );
+       } else {        
+               return false;
+       }
+}
+
+/**
+ * @todo document function
+ */
+function wfUpdateArray( $table, $values, $conds, $fname = 'wfUpdateArray', $dbi = DB_MASTER ) {
+       $db =& wfGetDB( $dbi );
+       if ( $db !== false ) {
+               $db->update( $table, $values, $conds, $fname );
+               return true;
+       } else {
+               return false;
+       }
+}
+
+/**
+ * @todo document function
+ */
+function wfTableName( $name, $dbi = DB_LAST ) {
+       $db =& wfGetDB( $dbi );
+       if ( $db !== false ) {
+               return $db->tableName( $name );
+       } else {
+               return false;
+       }
+}
+
+/**
+ * @todo document function
+ */
+function wfStrencode( $s, $dbi = DB_LAST ) {
+       $db =& wfGetDB( $dbi );
+       if ( $db !== false ) {
+               return $db->strencode( $s );
+       } else {
+               return false;
+       }
+}
+
+/**
+ * @todo document function
+ */
+function wfNextSequenceValue( $seqName, $dbi = DB_MASTER ) {
+       $db =& wfGetDB( $dbi );
+       if ( $db !== false ) {
+               return $db->nextSequenceValue( $seqName );
+       } else {
+               return false;
+       }
+}
+
+/**
+ * @todo document function
+ */
+function wfUseIndexClause( $index, $dbi = DB_SLAVE ) {
+       $db =& wfGetDB( $dbi );
+       if ( $db !== false ) {
+               return $db->useIndexClause( $index );
+       } else {
+               return false;
+       }
+}
+?>
diff --git a/includes/DatabasePostgreSQL.php b/includes/DatabasePostgreSQL.php
new file mode 100644 (file)
index 0000000..c92a824
--- /dev/null
@@ -0,0 +1,451 @@
+<?php
+
+/**
+ * This is PostgreSQL database abstraction layer.
+ * 
+ * As it includes more generic version for DB functions, 
+ * than MySQL ones, some of them should be moved to parent
+ * Database class.
+ *
+ * STATUS: Working PG implementation of MediaWiki
+ * TODO: Installer support
+ *
+ * @package MediaWiki
+ */
+
+/**
+ * Depends on database
+ */
+require_once( 'Database.php' );
+
+/**
+ *
+ * @package MediaWiki
+ */
+class DatabasePgsql extends Database {
+       var $mInsertId = NULL;
+       var $mLastResult = NULL;
+
+       function DatabasePgsql($server = false, $user = false, $password = false, $dbName = false, 
+               $failFunction = false, $flags = 0, $tablePrefix = 'get from global' )
+       {
+               Database::Database( $server, $user, $password, $dbName, $failFunction, $flags, $tablePrefix );
+       }
+
+       /* static */ function newFromParams( $server = false, $user = false, $password = false, $dbName = false, 
+               $failFunction = false, $flags = 0, $tablePrefix = 'get from global' )
+       {
+               return new DatabasePgsql( $server, $user, $password, $dbName, $failFunction, $flags, $tablePrefix );
+       }
+
+       /**
+        * Usually aborts on failure
+        * If the failFunction is set to a non-zero integer, returns success
+        */
+       function open( $server, $user, $password, $dbName ) {
+               # Test for PostgreSQL support, to avoid suppressed fatal error
+               if ( !function_exists( 'pg_connect' ) ) {
+                       die( "PostgreSQL functions missing, have you compiled PHP with the --with-pgsql option?\n" );
+               }
+
+               global $wgDBschema;
+
+               $this->close();
+               $this->mServer = $server;
+               $this->mUser = $user;
+               $this->mPassword = $password;
+               $this->mDBname = $dbName;
+               $this->mSchemas = array($wgDBschema,'public');
+               
+               $success = false;
+               
+               if ( '' != $dbName ) {
+                       # start a database connection
+                       $hstring="";
+                       if ($server!=false && $server!="") {
+                               $hstring="host=$server ";
+                       }
+                       @$this->mConn = pg_connect("$hstring dbname=$dbName user=$user password=$password");
+                       if ( $this->mConn == false ) {
+                               wfDebug( "DB connection error\n" );
+                               wfDebug( "Server: $server, Database: $dbName, User: $user, Password: " . substr( $password, 0, 3 ) . "...\n" );
+                               wfDebug( $this->lastError()."\n" );
+                       } else { 
+                               $this->setSchema();
+                               $this->mOpened = true;
+                       }
+               }
+               return $this->mConn;
+       }
+       
+       /**
+        * Closes a database connection, if it is open
+        * Returns success, true if already closed
+        */
+       function close() {
+               $this->mOpened = false;
+               if ( $this->mConn ) {
+                       return pg_close( $this->mConn );
+               } else {
+                       return true;
+               }
+       }
+       
+       function doQuery( $sql ) {
+               return $this->mLastResult=pg_query( $this->mConn , $sql);
+       }
+               
+       function queryIgnore( $sql, $fname = '' ) {
+               return $this->query( $sql, $fname, true );
+       }
+       
+       function freeResult( $res ) {
+               if ( !@pg_free_result( $res ) ) {
+                       wfDebugDieBacktrace( "Unable to free PostgreSQL result\n" );
+               }
+       }
+       
+       function fetchObject( $res ) {
+               @$row = pg_fetch_object( $res );
+               # FIXME: HACK HACK HACK HACK debug
+               
+               # TODO:
+               # hashar : not sure if the following test really trigger if the object
+               #          fetching failled.
+               if( pg_last_error($this->mConn) ) {
+                       wfDebugDieBacktrace( 'SQL error: ' . htmlspecialchars( pg_last_error($this->mConn) ) );
+               }
+               return $row;
+       }
+
+       function fetchRow( $res ) {
+               @$row = pg_fetch_array( $res );
+                if( pg_last_error($this->mConn) ) {
+                        wfDebugDieBacktrace( 'SQL error: ' . htmlspecialchars( pg_last_error($this->mConn) ) );
+                }
+               return $row;
+       }
+
+       function numRows( $res ) {
+               @$n = pg_num_rows( $res ); 
+               if( pg_last_error($this->mConn) ) {
+                       wfDebugDieBacktrace( 'SQL error: ' . htmlspecialchars( pg_last_error($this->mConn) ) );
+               }
+               return $n;
+       }
+       function numFields( $res ) { return pg_num_fields( $res ); }
+       function fieldName( $res, $n ) { return pg_field_name( $res, $n ); }
+       
+       /**
+        * This must be called after nextSequenceVal
+        */
+       function insertId() { 
+               return $this->mInsertId;
+       }
+
+       function dataSeek( $res, $row ) { return pg_result_seek( $res, $row ); }
+       function lastError() { return pg_last_error(); }
+       function lastErrno() { return 1; }
+
+       function affectedRows() { 
+               return pg_affected_rows( $this->mLastResult ); 
+       }
+       
+       /**
+        * Returns information about an index
+        * If errors are explicitly ignored, returns NULL on failure
+        */
+       function indexInfo( $table, $index, $fname = 'Database::indexExists' ) {
+               $sql = "SELECT indexname FROM pg_indexes WHERE tablename='$table'";
+               $res = $this->query( $sql, $fname );
+               if ( !$res ) {
+                       return NULL;
+               }
+               
+               while ( $row = $this->fetchObject( $res ) ) {
+                       if ( $row->Key_name == $index ) {
+                               return $row;
+                       }
+               }
+               return false;
+       }
+
+       function indexUnique ($table, $index, $fname = 'Database::indexUnique' ) {
+               $sql = "SELECT indexname FROM pg_indexes WHERE tablename='{$table}'".
+                       " AND indexdef LIKE 'CREATE UNIQUE%({$index})'";
+               $res = $this->query( $sql, $fname );
+               if ( !$res )
+                       return NULL;
+               while ($row = $this->fetchObject( $res )) 
+                       return true;
+               return false;
+               
+       }
+
+       function fieldInfo( $table, $field ) {
+               wfDebugDieBacktrace( 'Database::fieldInfo() error : mysql_fetch_field() not implemented for postgre' );
+               /*
+               $res = $this->query( "SELECT * FROM '$table' LIMIT 1" );
+               $n = pg_num_fields( $res );
+               for( $i = 0; $i < $n; $i++ ) {
+                       // FIXME
+                       wfDebugDieBacktrace( "Database::fieldInfo() error : mysql_fetch_field() not implemented for postgre" );
+                       $meta = mysql_fetch_field( $res, $i );
+                       if( $field == $meta->name ) {
+                               return $meta;
+                       }
+               }
+               return false;*/
+       }
+
+       function insert( $table, $a, $fname = 'Database::insert', $options = array() ) {
+               # PostgreSQL doesn't support options
+               # We have a go at faking one of them
+               # TODO: DELAYED, LOW_PRIORITY 
+
+               if ( !is_array($options))
+                       $options = array($options);
+
+               if ( in_array( 'IGNORE', $options ) ) 
+                       $oldIgnore = $this->ignoreErrors( true );
+
+               # IGNORE is performed using single-row inserts, ignoring errors in each
+               # FIXME: need some way to distiguish between key collision and other types of error
+               $oldIgnore = $this->ignoreErrors( true );
+               if ( !is_array( reset( $a ) ) ) {
+                       $a = array( $a );
+               }
+               foreach ( $a as $row ) {
+                       parent::insert( $table, $row, $fname, array() );
+               }
+               $this->ignoreErrors( $oldIgnore );
+               $retVal = true;
+
+               if ( in_array( 'IGNORE', $options ) ) 
+                       $this->ignoreErrors( $oldIgnore );
+
+               return $retVal;
+       }
+       
+       function startTimer( $timeout )
+       {
+               global $IP;
+               wfDebugDieBacktrace( 'Database::startTimer() error : mysql_thread_id() not implemented for postgre' );
+               /*$tid = mysql_thread_id( $this->mConn );
+               exec( "php $IP/killthread.php $timeout $tid &>/dev/null &" );*/
+       }
+
+       function tableName( $name ) {
+               # First run any transformations from the parent object
+               $name = parent::tableName( $name );
+
+               # Replace backticks into double quotes
+               $name = strtr($name,'`','"');
+
+               # Now quote PG reserved keywords
+               switch( $name ) {
+                       case 'user':
+                       case 'old':
+                       case 'group':
+                               return '"' . $name . '"';
+                       
+                       default:
+                               return $name;
+               }
+       }
+
+       function strencode( $s ) {
+               return pg_escape_string( $s );
+       }
+
+       /**
+        * Return the next in a sequence, save the value for retrieval via insertId()
+        */
+       function nextSequenceValue( $seqName ) {
+               $value = $this->selectField(''," nextval('" . $seqName . "')");
+               $this->mInsertId = $value;
+               return $value;
+       }
+
+       /**
+        * USE INDEX clause
+        * PostgreSQL doesn't have them and returns ""
+        */
+       function useIndexClause( $index ) {
+               return '';
+       }
+
+       # REPLACE query wrapper
+       # PostgreSQL simulates this with a DELETE followed by INSERT
+       # $row is the row to insert, an associative array
+       # $uniqueIndexes is an array of indexes. Each element may be either a 
+       # field name or an array of field names
+       #
+       # It may be more efficient to leave off unique indexes which are unlikely to collide. 
+       # However if you do this, you run the risk of encountering errors which wouldn't have 
+       # occurred in MySQL
+       function replace( $table, $uniqueIndexes, $rows, $fname = 'Database::replace' ) {
+               $table = $this->tableName( $table );
+       
+               if (count($rows)==0) {
+                       return;
+               }
+
+               # Single row case
+               if ( !is_array( reset( $rows ) ) ) {
+                       $rows = array( $rows );
+               }
+
+               foreach( $rows as $row ) {
+                       # Delete rows which collide
+                       if ( $uniqueIndexes ) {
+                               $sql = "DELETE FROM $table WHERE ";
+                               $first = true;
+                               foreach ( $uniqueIndexes as $index ) {
+                                       if ( $first ) {
+                                               $first = false;
+                                               $sql .= "(";
+                                       } else {
+                                               $sql .= ') OR (';
+                                       }
+                                       if ( is_array( $index ) ) {
+                                               $first2 = true;
+                                               foreach ( $index as $col ) {
+                                                       if ( $first2 ) { 
+                                                               $first2 = false;
+                                                       } else {
+                                                               $sql .= ' AND ';
+                                                       }
+                                                       $sql .= $col.'=' . $this->addQuotes( $row[$col] );
+                                               }
+                                       } else {
+                                               $sql .= $index.'=' . $this->addQuotes( $row[$index] );
+                                       }
+                               }
+                               $sql .= ')';
+                               $this->query( $sql, $fname );
+                       }
+
+                       # Now insert the row
+                       $sql = "INSERT INTO $table (" . $this->makeList( array_keys( $row ), LIST_NAMES ) .') VALUES (' .
+                               $this->makeList( $row, LIST_COMMA ) . ')';
+                       $this->query( $sql, $fname );
+               }
+       }
+
+       # DELETE where the condition is a join
+       function deleteJoin( $delTable, $joinTable, $delVar, $joinVar, $conds, $fname = "Database::deleteJoin" ) {
+               if ( !$conds ) {
+                       wfDebugDieBacktrace( 'Database::deleteJoin() called with empty $conds' );
+               }
+
+               $delTable = $this->tableName( $delTable );
+               $joinTable = $this->tableName( $joinTable );
+               $sql = "DELETE FROM $delTable WHERE $delVar IN (SELECT $joinVar FROM $joinTable ";
+               if ( $conds != '*' ) {
+                       $sql .= 'WHERE ' . $this->makeList( $conds, LIST_AND );
+               }
+               $sql .= ')';
+
+               $this->query( $sql, $fname );
+       }
+
+       # Returns the size of a text field, or -1 for "unlimited"
+       function textFieldSize( $table, $field ) {
+               $table = $this->tableName( $table );
+               $sql = "SELECT t.typname as ftype,a.atttypmod as size
+                       FROM pg_class c, pg_attribute a, pg_type t 
+                       WHERE relname='$table' AND a.attrelid=c.oid AND 
+                               a.atttypid=t.oid and a.attname='$field'";
+               $res =$this->query($sql);
+               $row=$this->fetchObject($res);
+               if ($row->ftype=="varchar") {
+                       $size=$row->size-4;     
+               } else {
+                       $size=$row->size;
+               }
+               $this->freeResult( $res );
+               return $size;
+       }
+       
+       function lowPriorityOption() {
+               return '';
+       }
+
+       function limitResult($limit,$offset) {
+               return " LIMIT $limit ".(is_numeric($offset)?" OFFSET {$offset} ":"");
+       }
+       
+       /**
+        * Returns an SQL expression for a simple conditional.
+        * Uses CASE on PostgreSQL.
+        *
+        * @param string $cond SQL expression which will result in a boolean value
+        * @param string $trueVal SQL expression to return if true
+        * @param string $falseVal SQL expression to return if false
+        * @return string SQL fragment
+        */
+       function conditional( $cond, $trueVal, $falseVal ) {
+               return " (CASE WHEN $cond THEN $trueVal ELSE $falseVal END) ";
+       }
+
+       # FIXME: actually detecting deadlocks might be nice
+       function wasDeadlock() {
+               return false;
+       }
+
+       # Return DB-style timestamp used for MySQL schema
+       function timestamp( $ts=0 ) {
+               return wfTimestamp(TS_DB,$ts);
+       }
+
+        /**
+         * Return aggregated value function call
+         */
+        function aggregateValue ($valuedata,$valuename='value') {
+                return $valuedata;
+        }
+
+
+       function reportQueryError( $error, $errno, $sql, $fname, $tempIgnore = false ) {
+               $message = "A database error has occurred\n" .
+                       "Query: $sql\n" .
+                       "Function: $fname\n" .
+                       "Error: $errno $error\n";
+               wfDebugDieBacktrace($message);
+       }
+
+       /**
+        * @return string wikitext of a link to the server software's web site
+        */
+       function getSoftwareLink() {
+               return "[http://www.postgresql.org/ PostgreSQL]";
+       }
+       
+       /**
+        * @return string Version information from the database
+        */
+       function getServerVersion() {
+               $res = $this->query( "SELECT version()" );
+               $row = $this->fetchRow( $res );
+               $version = $row[0];
+               $this->freeResult( $res );
+               return $version;
+       }
+
+       function setSchema($schema=false) {
+               $schemas=$this->mSchemas;
+               if ($schema) { array_unshift($schemas,$schema); }
+               $searchpath=$this->makeList($schemas,LIST_NAMES);
+               $this->query("SET search_path = $searchpath");
+       }
+}
+
+/**
+ * Just an alias.
+ * @package MediaWiki
+ */
+class DatabasePostgreSQL extends DatabasePgsql {
+}
+
+?>
diff --git a/includes/DateFormatter.php b/includes/DateFormatter.php
new file mode 100644 (file)
index 0000000..f5cad86
--- /dev/null
@@ -0,0 +1,293 @@
+<?php
+/**
+ * Contain things
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Parser
+ */
+
+/** */
+define('DF_ALL', -1);
+define('DF_NONE', 0);
+define('DF_MDY', 1);
+define('DF_DMY', 2);
+define('DF_YMD', 3);
+define('DF_ISO1', 4);
+define('DF_LASTPREF', 4);
+define('DF_ISO2', 5);
+define('DF_YDM', 6);
+define('DF_DM', 7);
+define('DF_MD', 8);
+define('DF_LAST', 8);
+
+/**
+ * @todo preferences, OutputPage
+ * @package MediaWiki
+ * @subpackage Parser
+ */
+class DateFormatter
+{
+       var $mSource, $mTarget;
+       var $monthNames = '', $rxDM, $rxMD, $rxDMY, $rxYDM, $rxMDY, $rxYMD;
+       
+       var $regexes, $pDays, $pMonths, $pYears;
+       var $rules, $xMonths;
+       
+       /**
+        * @todo document
+        */
+       function DateFormatter() {
+               global $wgContLang, $wgInputEncoding;
+               
+               $this->monthNames = $this->getMonthRegex();
+               for ( $i=1; $i<=12; $i++ ) {
+                       $this->xMonths[strtolower( $wgContLang->getMonthName( $i ) )] = $i;
+               }
+               for ( $i=1; $i<=12; $i++ ) {
+                       $this->xMonths[strtolower( $wgContLang->getMonthAbbreviation( $i ) )] = $i;
+               }
+               
+               # Attempt at UTF-8 support, untested at the moment
+               if ( $wgInputEncoding == 'UTF-8' ) {
+                       $this->regexTrail = '(?![a-z])/iu';
+               } else {
+                       $this->regexTrail = '(?![a-z])/i';
+               }
+
+               # Partial regular expressions
+               $this->prxDM = '\[\[(\d{1,2})[ _](' . $this->monthNames . ')]]';
+               $this->prxMD = '\[\[(' . $this->monthNames . ')[ _](\d{1,2})]]';
+               $this->prxY = '\[\[(\d{1,4}([ _]BC|))]]';
+               $this->prxISO1 = '\[\[(-?\d{4})]]-\[\[(\d{2})-(\d{2})]]';
+               $this->prxISO2 = '\[\[(-?\d{4})-(\d{2})-(\d{2})]]';
+               
+               # Real regular expressions
+               $this->regexes[DF_DMY] = "/{$this->prxDM} *,? *{$this->prxY}{$this->regexTrail}";       
+               $this->regexes[DF_YDM] = "/{$this->prxY} *,? *{$this->prxDM}{$this->regexTrail}";
+               $this->regexes[DF_MDY] = "/{$this->prxMD} *,? *{$this->prxY}{$this->regexTrail}";
+               $this->regexes[DF_YMD] = "/{$this->prxY} *,? *{$this->prxMD}{$this->regexTrail}";
+               $this->regexes[DF_DM] = "/{$this->prxDM}{$this->regexTrail}";
+               $this->regexes[DF_MD] = "/{$this->prxMD}{$this->regexTrail}";
+               $this->regexes[DF_ISO1] = "/{$this->prxISO1}{$this->regexTrail}";
+               $this->regexes[DF_ISO2] = "/{$this->prxISO2}{$this->regexTrail}";
+               
+               # Extraction keys
+               # See the comments in replace() for the meaning of the letters
+               $this->keys[DF_DMY] = 'jFY';
+               $this->keys[DF_YDM] = 'Y jF';
+               $this->keys[DF_MDY] = 'FjY';
+               $this->keys[DF_YMD] = 'Y Fj';
+               $this->keys[DF_DM] = 'jF';
+               $this->keys[DF_MD] = 'Fj';
+               $this->keys[DF_ISO1] = 'ymd'; # y means ISO year
+               $this->keys[DF_ISO2] = 'ymd';
+
+               # Target date formats
+               $this->targets[DF_DMY] = '[[F j|j F]] [[Y]]';
+               $this->targets[DF_YDM] = '[[Y]], [[F j|j F]]';
+               $this->targets[DF_MDY] = '[[F j]], [[Y]]';
+               $this->targets[DF_YMD] = '[[Y]] [[F j]]';
+               $this->targets[DF_DM] = '[[F j|j F]]';
+               $this->targets[DF_MD] = '[[F j]]';
+               $this->targets[DF_ISO1] = '[[Y|y]]-[[F j|m-d]]';
+               $this->targets[DF_ISO2] = '[[y-m-d]]';
+
+               # Rules
+               #            pref    source       target
+               $this->rules[DF_DMY][DF_MD]     = DF_DM;
+               $this->rules[DF_ALL][DF_MD]     = DF_MD;
+               $this->rules[DF_MDY][DF_DM]     = DF_MD;
+               $this->rules[DF_ALL][DF_DM]     = DF_DM;
+               $this->rules[DF_NONE][DF_ISO2]  = DF_ISO1;
+       }
+       
+       /**
+        * @static
+        */
+       function &getInstance() {
+               global $wgDBname, $wgMemc;
+               static $dateFormatter = false;
+               if ( !$dateFormatter ) {
+                       $dateFormatter = $wgMemc->get( "$wgDBname:dateformatter" );
+                       if ( !$dateFormatter ) {
+                               $dateFormatter = new DateFormatter;
+                               $wgMemc->set( "$wgDBname:dateformatter", $dateFormatter, 3600 );
+                       }
+               }
+               return $dateFormatter;
+       }       
+       
+       /**
+        * @param $preference
+        * @param $text
+        */
+       function reformat( $preference, $text ) {
+               if ($preference == 'ISO 8601') $preference = 4; # The ISO 8601 option used to be 4
+               for ( $i=1; $i<=DF_LAST; $i++ ) {
+                       $this->mSource = $i;
+                       if ( @$this->rules[$preference][$i] ) {
+                               # Specific rules
+                               $this->mTarget = $this->rules[$preference][$i];
+                       } elseif ( @$this->rules[DF_ALL][$i] ) {
+                               # General rules
+                               $this->mTarget = $this->rules[DF_ALL][$i];
+                       } elseif ( $preference ) {
+                               # User preference
+                               $this->mTarget = $preference;
+                       } else {
+                               # Default
+                               $this->mTarget = $i;
+                       }
+                       $text = preg_replace_callback( $this->regexes[$i], 'wfMainDateReplace', $text );
+               }
+               return $text;
+       }
+
+       /**
+        * @param $matches
+        */
+       function replace( $matches ) {
+               # Extract information from $matches
+               $bits = array();
+               $key = $this->keys[$this->mSource];
+               for ( $p=0; $p < strlen($key); $p++ ) {
+                       if ( $key{$p} != ' ' ) {
+                               $bits[$key{$p}] = $matches[$p+1];
+                       }
+               }
+
+               $format = $this->targets[$this->mTarget];
+               
+               # Construct new date
+               $text = '';
+               $fail = false;
+               
+               for ( $p=0; $p < strlen( $format ); $p++ ) {
+                       $char = $format{$p};
+                       switch ( $char ) {
+                               case 'd': # ISO day of month
+                                       if ( !isset($bits['d']) ) {
+                                               $text .= sprintf( '%02d', $bits['j'] );
+                                       } else {
+                                               $text .= $bits['d'];
+                                       }
+                                       break;
+                               case 'm': # ISO month
+                                       if ( !isset($bits['m']) ) {
+                                               $m = $this->makeIsoMonth( $bits['F'] );
+                                               if ( !$m || $m == '00' ) {
+                                                       $fail = true;
+                                               } else {
+                                                       $text .= $m;
+                                               }
+                                       } else {
+                                               $text .= $bits['m'];
+                                       }
+                                       break;
+                               case 'y': # ISO year
+                                       if ( !isset( $bits['y'] ) ) {
+                                               $text .= $this->makeIsoYear( $bits['Y'] );
+                                       } else {
+                                               $text .= $bits['y'];
+                                       }
+                                       break;
+                               case 'j': # ordinary day of month
+                                       if ( !isset($bits['j']) ) {
+                                               $text .= IntVal( $bits['d'] );
+                                       } else {
+                                               $text .= $bits['j'];
+                                       }
+                                       break;
+                               case 'F': # long month
+                                       if ( !isset( $bits['F'] ) ) {
+                                               $m = IntVal($bits['m']);
+                                               if ( $m > 12 || $m < 1 ) {
+                                                       $fail = true;
+                                               } else {
+                                                       global $wgContLang;
+                                                       $text .= $wgContLang->getMonthName( $m );
+                                               }
+                                       } else {
+                                               $text .= ucfirst( $bits['F'] );
+                                       }
+                                       break;
+                               case 'Y': # ordinary (optional BC) year
+                                       if ( !isset( $bits['Y'] ) ) {
+                                               $text .= $this->makeNormalYear( $bits['y'] );
+                                       } else {
+                                               $text .= $bits['Y'];
+                                       }
+                                       break;
+                               default:
+                                       $text .= $char;
+                       }
+               }
+               if ( $fail ) {
+                       $text = $matches[0];
+               }
+               return $text;
+       }
+       
+       /**
+        * @todo document
+        */
+       function getMonthRegex() {
+               global $wgContLang;
+               $names = array();
+               for( $i = 1; $i <= 12; $i++ ) {
+                       $names[] = $wgContLang->getMonthName( $i );
+                       $names[] = $wgContLang->getMonthAbbreviation( $i );
+               }
+               return implode( '|', $names );
+       }
+
+       /**
+        * Makes an ISO month, e.g. 02, from a month name
+        * @param string $monthName Month name
+        * @return string ISO month name
+        */
+       function makeIsoMonth( $monthName ) {
+               $n = $this->xMonths[strtolower( $monthName )];
+               return sprintf( '%02d', $n );
+       }
+
+       /**
+        * @todo document
+        * @param string $year Year name
+        * @return string ISO year name
+        */
+       function makeIsoYear( $year ) {
+               # Assumes the year is in a nice format, as enforced by the regex
+               if ( substr( $year, -2 ) == 'BC' ) {
+                       $num = IntVal(substr( $year, 0, -3 )) - 1;
+                       # PHP bug note: sprintf( "%04d", -1 ) fails poorly
+                       $text = sprintf( '-%04d', $num );
+
+               } else {
+                       $text = sprintf( '%04d', $year );
+               }
+               return $text;
+       }
+
+       /**
+        * @todo document
+        */
+       function makeNormalYear( $iso ) {
+               if ( $iso{0} == '-' ) {
+                       $text = (IntVal( substr( $iso, 1 ) ) + 1) . ' BC';
+               } else {
+                       $text = IntVal( $iso );
+               }
+               return $text;
+       }
+}
+
+/**
+ * @todo document
+ */
+function wfMainDateReplace( $matches ) {
+       $df =& DateFormatter::getInstance();
+       return $df->replace( $matches );
+}
+
+?>
diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php
new file mode 100644 (file)
index 0000000..d914d89
--- /dev/null
@@ -0,0 +1,1675 @@
+<?php
+/**
+ *
+ *                 DO NOT EVER EDIT THIS FILE!
+ *
+ *
+ * To customize your installation, edit "LocalSettings.php". If you make
+ * changes here, they will be lost on next upgrade of MediaWiki!
+ *
+ * Note that since all these string interpolations are expanded
+ * before LocalSettings is included, if you localize something
+ * like $wgScriptPath, you must also localize everything that
+ * depends on it.
+ *
+ * Documentation is in the source and on:
+ * http://www.mediawiki.org/wiki/Help:Configuration_settings
+ *
+ * @package MediaWiki
+ */
+
+# This is not a valid entry point, perform no further processing unless MEDIAWIKI is defined
+if( !defined( 'MEDIAWIKI' ) ) {
+       die( "This file is part of MediaWiki and is not a valid entry point\n" );
+}
+
+/**
+ * Create a site configuration object
+ * Not used for much in a default install
+ */
+require_once( 'includes/SiteConfiguration.php' );
+$wgConf = new SiteConfiguration;
+
+/** MediaWiki version number */
+$wgVersion                     = '1.5.8';
+
+/** Name of the site. It must be changed in LocalSettings.php */
+$wgSitename         = 'MediaWiki';
+
+/** Will be same as you set @see $wgSitename */
+$wgMetaNamespace    = FALSE;
+
+
+/** URL of the server. It will be automaticly build including https mode */
+$wgServer = '';
+
+if( isset( $_SERVER['SERVER_NAME'] ) ) {
+       $wgServerName = $_SERVER['SERVER_NAME'];
+} elseif( isset( $_SERVER['HOSTNAME'] ) ) {
+       $wgServerName = $_SERVER['HOSTNAME'];
+} elseif( isset( $_SERVER['HTTP_HOST'] ) ) {
+       $wgServerName = $_SERVER['HTTP_HOST'];
+} elseif( isset( $_SERVER['SERVER_ADDR'] ) ) {
+       $wgServerName = $_SERVER['SERVER_ADDR'];
+} else {
+       $wgServerName = 'localhost';
+}
+
+# check if server use https:
+$wgProto = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https' : 'http';
+
+$wgServer = $wgProto.'://' . $wgServerName;
+# If the port is a non-standard one, add it to the URL
+if(    isset( $_SERVER['SERVER_PORT'] )
+    && (    ( $wgProto == 'http' && $_SERVER['SERVER_PORT'] != 80 )
+         || ( $wgProto == 'https' && $_SERVER['SERVER_PORT'] != 443 ) ) ) {
+
+       $wgServer .= ":" . $_SERVER['SERVER_PORT'];
+}
+unset($wgProto);
+
+
+/**
+ * The path we should point to.
+ * It might be a virtual path in case with use apache mod_rewrite for example
+ */
+$wgScriptPath      = '/wiki';
+
+/**
+ * Whether to support URLs like index.php/Page_title
+ * @global bool $wgUsePathInfo
+ */
+$wgUsePathInfo         = ( strpos( php_sapi_name(), 'cgi' ) === false );
+
+
+/**#@+
+ * Script users will request to get articles
+ * ATTN: Old installations used wiki.phtml and redirect.phtml -
+ * make sure that LocalSettings.php is correctly set!
+ * @deprecated
+ */
+/**
+ *     @global string $wgScript
+ */
+$wgScript           = "{$wgScriptPath}/index.php";
+/**
+ *     @global string $wgRedirectScript
+ */
+$wgRedirectScript   = "{$wgScriptPath}/redirect.php";
+/**#@-*/
+
+
+/**#@+
+ * @global string
+ */
+/**
+ * style path as seen by users
+ * @global string $wgStylePath
+ */
+$wgStylePath   = "{$wgScriptPath}/skins";
+/**
+ * filesystem stylesheets directory
+ * @global string $wgStyleDirectory
+ */
+$wgStyleDirectory = "{$IP}/skins";
+$wgStyleSheetPath = &$wgStylePath;
+$wgArticlePath      = "{$wgScript}?title=$1";
+$wgUploadPath       = "{$wgScriptPath}/upload";
+$wgUploadDirectory     = "{$IP}/upload";
+$wgHashedUploadDirectory       = true;
+$wgLogo                                = "{$wgUploadPath}/wiki.png";
+$wgMathPath         = "{$wgUploadPath}/math";
+$wgMathDirectory    = "{$wgUploadDirectory}/math";
+$wgTmpDirectory     = "{$wgUploadDirectory}/tmp";
+$wgUploadBaseUrl    = "";
+/**#@-*/
+
+/**
+ * The external URL protocols (regexp)
+ */
+$wgUrlProtocols = 'http:\/\/|https:\/\/|ftp:\/\/|irc:\/\/|gopher:\/\/|news:|mailto:';
+
+/** internal name of virus scanner. This servers as a key to the $wgAntivirusSetup array.
+ * Set this to NULL to disable virus scanning. If not null, every file uploaded will be scanned for viruses.
+ * @global string $wgAntivirus
+ */
+$wgAntivirus= NULL;
+
+/** Configuration for different virus scanners. This an associative array of associative arrays:
+ * it contains on setup array per known scanner type. The entry is selected by $wgAntivirus, i.e.
+ * valid values for $wgAntivirus are the keys defined in this array.
+ *
+ * The configuration array for each scanner contains the following keys: "command", "codemap", "messagepattern";
+ *
+ * "command" is the full command to call the virus scanner - %f will be replaced with the name of the
+ * file to scan. If not present, the filename will be appended to the command. Note that this must be
+ * overwritten if the scanner is not in the system path; in that case, plase set
+ * $wgAntivirusSetup[$wgAntivirus]['command'] to the desired command with full path.
+ *
+ * "codemap" is a mapping of exit code to return codes of the detectVirus function in SpecialUpload.
+ * An exit code mapped to AV_SCAN_FAILED causes the function to consider the scan to be failed. This will pass
+ * the file if $wgAntivirusRequired is not set.
+ * An exit code mapped to AV_SCAN_ABORTED causes the function to consider the file to have an usupported format,
+ * which is probably imune to virusses. This causes the file to pass.
+ * An exit code mapped to AV_NO_VIRUS will cause the file to pass, meaning no virus was found.
+ * All other codes (like AV_VIRUS_FOUND) will cause the function to report a virus.
+ * You may use "*" as a key in the array to catch all exit codes not mapped otherwise.
+ *
+ * "messagepattern" is a perl regular expression to extract the meaningful part of the scanners
+ * output. The relevant part should be matched as group one (\1).
+ * If not defined or the pattern does not match, the full message is shown to the user.
+ *
+ * @global array $wgAntivirusSetup
+ */
+$wgAntivirusSetup= array(
+
+       #setup for clamav
+       'clamav' => array (
+               'command' => "clamscan --no-summary ",
+
+               'codemap'=> array (
+                       "0"=>  AV_NO_VIRUS, #no virus
+                       "1"=>  AV_VIRUS_FOUND, #virus found
+                       "52"=> AV_SCAN_ABORTED, #unsupported file format (probably imune)
+                       "*"=>  AV_SCAN_FAILED, #else scan failed
+               ),
+
+               'messagepattern'=> '/.*?:(.*)/sim',
+       ),
+
+       #setup for f-prot
+       'f-prot' => array (
+               'command' => "f-prot ",
+
+               'codemap'=> array (
+                       "0"=> AV_NO_VIRUS, #no virus
+                       "3"=> AV_VIRUS_FOUND, #virus found
+                       "6"=> AV_VIRUS_FOUND, #virus found
+                       "*"=> AV_SCAN_FAILED, #else scan failed
+               ),
+
+               'messagepattern'=> '/.*?Infection:(.*)$/m',
+       ),
+);
+
+
+/** Determines if a failed virus scan (AV_SCAN_FAILED) will cause the file to be rejected.
+ * @global boolean $wgAntivirusRequired
+*/
+$wgAntivirusRequired= true;
+
+/** Determines if the mime type of uploaded files should be checked
+ * @global boolean $wgVerifyMimeType
+*/
+$wgVerifyMimeType= true;
+
+/** Sets the mime type definition file to use by MimeMagic.php.
+* @global string $wgMimeTypeFile
+*/
+#$wgMimeTypeFile= "/etc/mime.types";
+$wgMimeTypeFile= "includes/mime.types";
+#$wgMimeTypeFile= NULL; #use build in defaults only.
+
+/** Sets the mime type info file to use by MimeMagic.php.
+* @global string $wgMimeInfoFile
+*/
+$wgMimeInfoFile= "includes/mime.info";
+#$wgMimeInfoFile= NULL; #use build in defaults only.
+
+/** Switch for loading the FileInfo extension by PECL at runtime.
+* This should be used only if fileinfo is installed as a shared object / dynamic libary
+* @global string $wgLoadFileinfoExtension
+*/
+$wgLoadFileinfoExtension= false;
+
+/** Sets an external mime detector program. The command must print only the mime type to standard output.
+* the name of the file to process will be appended to the command given here.
+* If not set or NULL, mime_content_type will be used if available.
+*/
+$wgMimeDetectorCommand= NULL; # use internal mime_content_type function, available since php 4.3.0
+#$wgMimeDetectorCommand= "file -bi" #use external mime detector (linux)
+
+/** Switch for trivial mime detection. Used by thumb.php to disable all fance things,
+* because only a few types of images are needed and file extensions can be trusted.
+*/
+$wgTrivialMimeDetection= false;
+
+/**
+ * Produce hashed HTML article paths. Used internally, do not set.
+ */
+$wgMakeDumpLinks = false;
+
+/**
+ * To set 'pretty' URL paths for actions other than
+ * plain page views, add to this array. For instance:
+ *   'edit' => "$wgScriptPath/edit/$1"
+ *
+ * There must be an appropriate script or rewrite rule
+ * in place to handle these URLs.
+ */
+$wgActionPaths = array();
+
+/**
+ * If you operate multiple wikis, you can define a shared upload path here.
+ * Uploads to this wiki will NOT be put there - they will be put into
+ * $wgUploadDirectory.
+ * If $wgUseSharedUploads is set, the wiki will look in the shared repository if
+ * no file of the given name is found in the local repository (for [[Image:..]],
+ * [[Media:..]] links). Thumbnails will also be looked for and generated in this
+ * directory.
+ */
+$wgUseSharedUploads = false;
+/** Full path on the web server where shared uploads can be found */
+$wgSharedUploadPath = "http://commons.wikimedia.org/shared/images";
+/** Fetch commons image description pages and display them on the local wiki? */
+$wgFetchCommonsDescriptions = false;
+/** Path on the file system where shared uploads can be found. */
+$wgSharedUploadDirectory = "/var/www/wiki3/images";
+/** DB name with metadata about shared directory. Set this to false if the uploads do not come from a wiki. */
+$wgSharedUploadDBname = false;
+/** Optional table prefix used in database. */
+$wgSharedUploadDBprefix = '';
+/** Cache shared metadata in memcached. Don't do this if the commons wiki is in a different memcached domain */
+$wgCacheSharedUploads = true;
+
+/**
+ * Point the upload navigation link to an external URL
+ * Useful if you want to use a shared repository by default
+ * without disabling local uploads
+ * e.g. $wgUploadNavigationUrl = 'http://commons.wikimedia.org/wiki/Special:Upload';
+*/
+$wgUploadNavigationUrl = false;
+
+/**
+ * Give a path here to use thumb.php for thumbnail generation on client request, instead of
+ * generating them on render and outputting a static URL. This is necessary if some of your
+ * apache servers don't have read/write access to the thumbnail path.
+ *
+ * Example:
+ *   $wgThumbnailScriptPath = "{$wgScriptPath}/thumb.php";
+ */
+$wgThumbnailScriptPath = false;
+$wgSharedThumbnailScriptPath = false;
+
+/**
+ * Set the following to false especially if you have a set of files that need to
+ * be accessible by all wikis, and you do not want to use the hash (path/a/aa/)
+ * directory layout.
+ */
+$wgHashedSharedUploadDirectory = true;
+
+/**
+ * Base URL for a repository wiki. Leave this blank if uploads are just stored
+ * in a shared directory and not meant to be accessible through a separate wiki.
+ * Otherwise the image description pages on the local wiki will link to the
+ * image description page on this wiki.
+ *
+ * Please specify the namespace, as in the example below.
+ */
+$wgRepositoryBaseUrl="http://commons.wikimedia.org/wiki/Image:";
+
+
+#
+# Email settings
+#
+
+/**
+ * Site admin email address
+ * Default to wikiadmin@SERVER_NAME
+ * @global string $wgEmergencyContact
+ */
+$wgEmergencyContact = 'wikiadmin@' . $wgServerName;
+
+/**
+ * Password reminder email address
+ * The address we should use as sender when a user is requesting his password
+ * Default to apache@SERVER_NAME
+ * @global string $wgPasswordSender
+ */
+$wgPasswordSender      = 'Wikipedia Mail <apache@' . $wgServerName . '>';
+
+/**
+ * dummy address which should be accepted during mail send action
+ * It might be necessay to adapt the address or to set it equal
+ * to the $wgEmergencyContact address
+ */
+#$wgNoReplyAddress     = $wgEmergencyContact;
+$wgNoReplyAddress      = 'reply@not.possible';
+
+/**
+ * Set to true to enable the e-mail basic features:
+ * Password reminders, etc. If sending e-mail on your
+ * server doesn't work, you might want to disable this.
+ * @global bool $wgEnableEmail
+ */
+$wgEnableEmail = true;
+
+/**
+ * Set to true to enable user-to-user e-mail.
+ * This can potentially be abused, as it's hard to track.
+ * @global bool $wgEnableUserEmail
+ */
+$wgEnableUserEmail = true;
+
+/**
+ * SMTP Mode
+ * For using a direct (authenticated) SMTP server connection.
+ * Default to false or fill an array :
+ * <code>
+ * "host" => 'SMTP domain',
+ * "IDHost" => 'domain for MessageID',
+ * "port" => "25",
+ * "auth" => true/false,
+ * "username" => user,
+ * "password" => password
+ * </code>
+ *
+ * @global mixed $wgSMTP
+ */
+$wgSMTP                                = false;
+
+
+/**#@+
+ * Database settings
+ */
+/** database host name or ip address */
+$wgDBserver         = 'localhost';
+/** name of the database */
+$wgDBname           = 'wikidb';
+/** */
+$wgDBconnection     = '';
+/** Database username */
+$wgDBuser           = 'wikiuser';
+/** Database type
+ * "mysql" for working code and "PostgreSQL" for development/broken code
+ */
+$wgDBtype           = "mysql";
+/** Search type
+ * Leave as null to select the default search engine for the
+ * selected database type (eg SearchMySQL4), or set to a class
+ * name to override to a custom search engine.
+ */
+$wgSearchType      = null;
+/** Table name prefix */
+$wgDBprefix         = '';
+/** Database schema
+ * on some databases this allows separate
+ * logical namespace for application data
+ */
+$wgDBschema        = 'mediawiki';
+/**#@-*/
+
+
+
+/**
+ * Shared database for multiple wikis. Presently used for storing a user table
+ * for single sign-on. The server for this database must be the same as for the
+ * main database.
+ * EXPERIMENTAL
+ */
+$wgSharedDB = null;
+
+# Database load balancer
+# This is a two-dimensional array, an array of server info structures
+# Fields are:
+#   host:        Host name
+#   dbname:      Default database name
+#   user:        DB user
+#   password:    DB password
+#   type:        "mysql" or "pgsql"
+#   load:        ratio of DB_SLAVE load, must be >=0, the sum of all loads must be >0
+#   groupLoads:  array of load ratios, the key is the query group name. A query may belong
+#                to several groups, the most specific group defined here is used.
+#
+#   flags:       bit field
+#                   DBO_DEFAULT -- turns on DBO_TRX only if !$wgCommandLineMode (recommended)
+#                   DBO_DEBUG -- equivalent of $wgDebugDumpSql
+#                   DBO_TRX -- wrap entire request in a transaction
+#                   DBO_IGNORE -- ignore errors (not useful in LocalSettings.php)
+#                   DBO_NOBUFFER -- turn off buffering (not useful in LocalSettings.php)
+#
+# Leave at false to use the single-server variables above
+$wgDBservers           = false;
+
+/** How long to wait for a slave to catch up to the master */
+$wgMasterWaitTimeout = 10;
+
+/** File to log MySQL errors to */
+$wgDBerrorLog          = false;
+
+/** When to give an error message */
+$wgDBClusterTimeout = 10;
+
+/**
+ * wgDBminWordLen :
+ * MySQL 3.x : used to discard words that MySQL will not return any results for
+ * shorter values configure mysql directly.
+ * MySQL 4.x : ignore it and configure mySQL
+ * See: http://dev.mysql.com/doc/mysql/en/Fulltext_Fine-tuning.html
+ */
+$wgDBminWordLen     = 4;
+/** Set to true if using InnoDB tables */
+$wgDBtransactions      = false;
+/** Set to true to use enhanced fulltext search */
+$wgDBmysql4                    = false;
+
+/**
+ * Set to true to engage MySQL 4.1/5.0 charset-related features;
+ * for now will just cause sending of 'SET NAMES=utf8' on connect.
+ *
+ * WARNING: THIS IS EXPERIMENTAL!
+ *
+ * May break if you're not using the table defs from mysql5/tables.sql.
+ * May break if you're upgrading an existing wiki if set differently.
+ * Broken symptoms likely to include incorrect behavior with page titles,
+ * usernames, comments etc containing non-ASCII characters.
+ * Might also cause failures on the object cache and other things.
+ *
+ * Even correct usage may cause failures with Unicode supplementary
+ * characters (those not in the Basic Multilingual Plane) unless MySQL
+ * has enhanced their Unicode support.
+ */
+$wgDBmysql5                    = false;
+
+/**
+ * Other wikis on this site, can be administered from a single developer
+ * account.
+ * Array, interwiki prefix => database name
+ */
+$wgLocalDatabases   = array();
+
+/**
+ * Object cache settings
+ * See Defines.php for types
+ */
+$wgMainCacheType = CACHE_NONE;
+$wgMessageCacheType = CACHE_ANYTHING;
+$wgParserCacheType = CACHE_ANYTHING;
+
+$wgSessionsInMemcached = false;
+$wgLinkCacheMemcached = false; # Not fully tested
+
+/**
+ * Memcached-specific settings
+ * See docs/memcached.txt
+ */
+$wgMemCachedDebug   = false; # Will be set to false in Setup.php, if the server isn't working
+$wgMemCachedServers = array( '127.0.0.1:11000' );
+$wgMemCachedDebug   = false;
+
+
+
+# Language settings
+#
+/** Site language code, should be one of ./languages/Language(.*).php */
+$wgLanguageCode     = 'en';
+
+/** Treat language links as magic connectors, not inline links */
+$wgInterwikiMagic      = true;
+
+/** Hide interlanguage links from the sidebar */
+$wgHideInterlanguageLinks = false;
+
+
+/** We speak UTF-8 all the time now, unless some oddities happen */
+$wgInputEncoding       = 'UTF-8';
+$wgOutputEncoding      = 'UTF-8';
+$wgEditEncoding                = '';
+
+# Set this to eg 'ISO-8859-1' to perform character set
+# conversion when loading old revisions not marked with
+# "utf-8" flag. Use this when converting wiki to UTF-8
+# without the burdensome mass conversion of old text data.
+#
+# NOTE! This DOES NOT touch any fields other than old_text.
+# Titles, comments, user names, etc still must be converted
+# en masse in the database before continuing as a UTF-8 wiki.
+$wgLegacyEncoding   = false;
+
+/**
+ * If set to true, the MediaWiki 1.4 to 1.5 schema conversion will
+ * create stub reference rows in the text table instead of copying
+ * the full text of all current entries from 'cur' to 'text'.
+ *
+ * This will speed up the conversion step for large sites, but
+ * requires that the cur table be kept around for those revisions
+ * to remain viewable.
+ *
+ * maintenance/migrateCurStubs.php can be used to complete the
+ * migration in the background once the wiki is back online.
+ *
+ * This option affects the updaters *only*. Any present cur stub
+ * revisions will be readable at runtime regardless of this setting.
+ */
+$wgLegacySchemaConversion = false;
+
+$wgMimeType                    = 'text/html';
+$wgJsMimeType                  = 'text/javascript';
+$wgDocType                     = '-//W3C//DTD XHTML 1.0 Transitional//EN';
+$wgDTD                         = 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd';
+
+/** Enable to allow rewriting dates in page text.
+ * DOES NOT FORMAT CORRECTLY FOR MOST LANGUAGES */
+$wgUseDynamicDates  = false;
+/** Enable dates like 'May 12' instead of '12 May', this only takes effect if
+ * the interface is set to English
+ */
+$wgAmericanDates    = false;
+/**
+ * For Hindi and Arabic use local numerals instead of Western style (0-9)
+ * numerals in interface.
+ */
+$wgTranslateNumerals = true;
+
+
+# Translation using MediaWiki: namespace
+# This will increase load times by 25-60% unless memcached is installed
+# Interface messages will be loaded from the database.
+$wgUseDatabaseMessages = true;
+$wgMsgCacheExpiry      = 86400;
+
+# Whether to enable language variant conversion.
+$wgDisableLangConversion = false;
+
+# Use article validation feature; turned off by default
+$wgUseValidation = false;
+$wgValidationForAnons = true ;
+
+# Whether to use zhdaemon to perform Chinese text processing
+# zhdaemon is under developement, so normally you don't want to
+# use it unless for testing
+$wgUseZhdaemon = false;
+$wgZhdaemonHost="localhost";
+$wgZhdaemonPort=2004;
+
+/** Normally you can ignore this and it will be something
+    like $wgMetaNamespace . "_talk". In some languages, you
+    may want to set this manually for grammatical reasons.
+    It is currently only respected by those languages
+    where it might be relevant and where no automatic
+    grammar converter exists.
+*/
+$wgMetaNamespaceTalk = false;
+
+# Miscellaneous configuration settings
+#
+
+$wgLocalInterwiki   = 'w';
+$wgInterwikiExpiry = 10800; # Expiry time for cache of interwiki table
+
+/**
+ * If local interwikis are set up which allow redirects,
+ * set this regexp to restrict URLs which will be displayed
+ * as 'redirected from' links.
+ *
+ * It might look something like this:
+ * $wgRedirectSources = '!^https?://[a-z-]+\.wikipedia\.org/!';
+ *
+ * Leave at false to avoid displaying any incoming redirect markers.
+ * This does not affect intra-wiki redirects, which don't change
+ * the URL.
+ */
+$wgRedirectSources = false;
+
+
+$wgShowIPinHeader      = true; # For non-logged in users
+$wgMaxNameChars                = 255;  # Maximum number of bytes in username
+
+$wgExtraSubtitle       = '';
+$wgSiteSupportPage     = ''; # A page where you users can receive donations
+
+$wgReadOnlyFile         = "{$wgUploadDirectory}/lock_yBgMBwiR";
+
+/**
+ * The debug log file should be not be publicly accessible if it is used, as it
+ * may contain private data. */
+$wgDebugLogFile         = '';
+
+/**#@+
+ * @global bool
+ */
+$wgDebugRedirects              = false;
+$wgDebugRawPage         = false; # Avoid overlapping debug entries by leaving out CSS
+
+$wgDebugComments        = false;
+$wgReadOnly             = null;
+$wgLogQueries           = false;
+$wgDebugDumpSql         = false;
+
+/**
+ * Set to an array of log group keys to filenames.
+ * If set, wfDebugLog() output for that group will go to that file instead 
+ * of the regular $wgDebugLogFile. Useful for enabling selective logging
+ * in production.
+ */
+$wgDebugLogGroups       = array();
+
+/**
+ * Whether to show "we're sorry, but there has been a database error" pages.
+ * Displaying errors aids in debugging, but may display information useful
+ * to an attacker.
+ */
+$wgShowSQLErrors        = false;
+
+# Should [[Category:Dog]] on a page associate it with the
+# category "Dog"? (a link to that category page will be
+# added to the article, clicking it reveals a list of
+# all articles in the category)
+$wgUseCategoryMagic            = true;
+
+/**
+ * disable experimental dmoz-like category browsing. Output things like:
+ * Encyclopedia > Music > Style of Music > Jazz
+ */
+$wgUseCategoryBrowser   = false;
+
+/**
+ * Keep parsed pages in a cache (objectcache table, turck, or memcached)
+ * to speed up output of the same page viewed by another user with the
+ * same options.
+ *
+ * This can provide a significant speedup for medium to large pages,
+ * so you probably want to keep it on.
+ */
+$wgEnableParserCache = true;
+
+/**
+ * Under which condition should a page in the main namespace be counted
+ * as a valid article? If $wgUseCommaCount is set to true, it will be
+ * counted if it contains at least one comma. If it is set to false
+ * (default), it will only be counted if it contains at least one [[wiki
+ * link]]. See http://meta.wikimedia.org/wiki/Help:Article_count
+ *
+ * Retroactively changing this variable will not affect
+ * the existing count (cf. maintenance/recount.sql).
+*/
+$wgUseCommaCount = false;
+
+/**#@-*/
+
+/**
+ * wgHitcounterUpdateFreq sets how often page counters should be updated, higher
+ * values are easier on the database. A value of 1 causes the counters to be
+ * updated on every hit, any higher value n cause them to update *on average*
+ * every n hits. Should be set to either 1 or something largish, eg 1000, for
+ * maximum efficiency.
+*/
+$wgHitcounterUpdateFreq = 1;
+
+# User rights settings
+#
+#  It's not 100% safe, there could be security hole using that one. Use at your
+# own risks.
+
+$wgWhitelistRead = false;      # Pages anonymous user may see, like: = array ( "Main Page", "Special:Userlogin", "Wikipedia:Help");
+
+$wgAllowAnonymousMinor = false; # Allow anonymous users to mark changes as 'minor'
+
+$wgSysopUserBans        = true; # Allow sysops to ban logged-in users
+$wgSysopRangeBans              = true; # Allow sysops to ban IP ranges
+
+$wgAutoblockExpiry             = 86400; # Number of seconds before autoblock entries expire
+$wgBlockAllowsUTEdit    = false; # Blocks allow users to edit their own user talk page
+
+/**
+ * Permission keys given to users in each group.
+ * All users are implicitly in the '*' group including anonymous visitors;
+ * logged-in users are all implicitly in the 'user' group. These will be
+ * combined with the permissions of all groups that a given user is listed
+ * in in the user_groups table.
+ *
+ * This replaces wgWhitelistAccount and wgWhitelistEdit
+ */
+$wgGroupPermissions = array();
+
+$wgGroupPermissions['*'    ]['createaccount']   = true;
+$wgGroupPermissions['*'    ]['read']            = true;
+$wgGroupPermissions['*'    ]['edit']            = true;
+
+$wgGroupPermissions['user' ]['move']            = true;
+$wgGroupPermissions['user' ]['read']            = true;
+$wgGroupPermissions['user' ]['edit']            = true;
+$wgGroupPermissions['user' ]['upload']          = true;
+
+$wgGroupPermissions['bot'  ]['bot']             = true;
+
+$wgGroupPermissions['sysop']['block']           = true;
+$wgGroupPermissions['sysop']['createaccount']   = true;
+$wgGroupPermissions['sysop']['delete']          = true;
+$wgGroupPermissions['sysop']['editinterface']   = true;
+$wgGroupPermissions['sysop']['import']          = true;
+$wgGroupPermissions['sysop']['importupload']    = true;
+$wgGroupPermissions['sysop']['move']            = true;
+$wgGroupPermissions['sysop']['patrol']          = true;
+$wgGroupPermissions['sysop']['protect']         = true;
+$wgGroupPermissions['sysop']['rollback']        = true;
+$wgGroupPermissions['sysop']['upload']          = true;
+
+$wgGroupPermissions['bureaucrat']['userrights'] = true;
+// Used by the Special:Renameuser extension
+$wgGroupPermissions['bureaucrat']['renameuser'] = true;
+
+/**
+ * The developer group is deprecated, but can be activated if need be
+ * to use the 'lockdb' and 'unlockdb' special pages. Those require
+ * that a lock file be defined and creatable/removable by the web
+ * server.
+ */
+# $wgGroupPermissions['developer']['siteadmin'] = true;
+
+
+
+# Proxy scanner settings
+#
+
+/**
+ * If you enable this, every editor's IP address will be scanned for open HTTP
+ * proxies.
+ *
+ * Don't enable this. Many sysops will report "hostile TCP port scans" to your
+ * ISP and ask for your server to be shut down.
+ *
+ * You have been warned.
+ */
+$wgBlockOpenProxies = false;
+/** Port we want to scan for a proxy */
+$wgProxyPorts = array( 80, 81, 1080, 3128, 6588, 8000, 8080, 8888, 65506 );
+/** Script used to scan */
+$wgProxyScriptPath = "$IP/proxy_check.php";
+/** */
+$wgProxyMemcExpiry = 86400;
+/** This should always be customised in LocalSettings.php */
+$wgSecretKey = false;
+/** big list of banned IP addresses, in the keys not the values */
+$wgProxyList = array();
+/** deprecated */
+$wgProxyKey = false;
+
+/** Number of accounts each IP address may create, 0 to disable.
+ * Requires memcached */
+$wgAccountCreationThrottle = 0;
+
+# Client-side caching:
+
+/** Allow client-side caching of pages */
+$wgCachePages       = true;
+
+/**
+ * Set this to current time to invalidate all prior cached pages. Affects both
+ * client- and server-side caching.
+ */
+$wgCacheEpoch = '20030516000000';
+
+
+# Server-side caching:
+
+/**
+ * This will cache static pages for non-logged-in users to reduce
+ * database traffic on public sites.
+ * Must set $wgShowIPinHeader = false
+ */
+$wgUseFileCache = false;
+/** Directory where the cached page will be saved */
+$wgFileCacheDirectory = "{$wgUploadDirectory}/cache";
+
+/**
+ * When using the file cache, we can store the cached HTML gzipped to save disk
+ * space. Pages will then also be served compressed to clients that support it.
+ * THIS IS NOT COMPATIBLE with ob_gzhandler which is now enabled if supported in
+ * the default LocalSettings.php! If you enable this, remove that setting first.
+ *
+ * Requires zlib support enabled in PHP.
+ */
+$wgUseGzip = false;
+
+# Email notification settings
+#
+
+/** For email notification on page changes */
+$wgPasswordSender = $wgEmergencyContact;
+
+# true: from page editor if s/he opted-in
+# false: Enotif mails appear to come from $wgEmergencyContact
+$wgEnotifFromEditor    = false;
+
+// TODO move UPO to preferences probably ?
+# If set to true, users get a corresponding option in their preferences and can choose to enable or disable at their discretion
+# If set to false, the corresponding input form on the user preference page is suppressed
+# It call this to be a "user-preferences-option (UPO)"
+$wgEmailAuthentication                         = true; # UPO (if this is set to false, texts referring to authentication are suppressed)
+$wgEnotifWatchlist             = false; # UPO
+$wgEnotifUserTalk              = false;        # UPO
+$wgEnotifRevealEditorAddress   = false;        # UPO; reply-to address may be filled with page editor's address (if user allowed this in the preferences)
+$wgEnotifMinorEdits            = true; # UPO; false: "minor edits" on pages do not trigger notification mails.
+#                                                      # Attention: _every_ change on a user_talk page trigger a notification mail (if the user is not yet notified)
+
+
+/** Show watching users in recent changes, watchlist and page history views */
+$wgRCShowWatchingUsers                                 = false; # UPO
+/** Show watching users in Page views */
+$wgPageShowWatchingUsers                       = false;
+/**
+ * Show "Updated (since my last visit)" marker in RC view, watchlist and history
+ * view for watched pages with new changes */
+$wgShowUpdatedMarker                           = true;
+
+$wgCookieExpiration = 2592000;
+
+/** Clock skew or the one-second resolution of time() can occasionally cause cache
+ * problems when the user requests two pages within a short period of time. This
+ * variable adds a given number of seconds to vulnerable timestamps, thereby giving
+ * a grace period.
+ */
+$wgClockSkewFudge = 5;
+
+# Squid-related settings
+#
+
+/** Enable/disable Squid */
+$wgUseSquid = false;
+
+/** If you run Squid3 with ESI support, enable this (default:false): */
+$wgUseESI = false;
+
+/** Internal server name as known to Squid, if different */
+# $wgInternalServer = 'http://yourinternal.tld:8000';
+$wgInternalServer = $wgServer;
+
+/**
+ * Cache timeout for the squid, will be sent as s-maxage (without ESI) or
+ * Surrogate-Control (with ESI). Without ESI, you should strip out s-maxage in
+ * the Squid config. 18000 seconds = 5 hours, more cache hits with 2678400 = 31
+ * days
+ */
+$wgSquidMaxage = 18000;
+
+/**
+ * A list of proxy servers (ips if possible) to purge on changes don't specify
+ * ports here (80 is default)
+ */
+# $wgSquidServers = array('127.0.0.1');
+$wgSquidServers = array();
+$wgSquidServersNoPurge = array();
+
+/** Maximum number of titles to purge in any one client operation */
+$wgMaxSquidPurgeTitles = 400;
+
+/** HTCP multicast purging */
+$wgHTCPPort = 4827;
+$wgHTCPMulticastTTL = 1;
+# $wgHTCPMulticastAddress = "224.0.0.85";
+
+# Cookie settings:
+#
+/**
+ * Set to set an explicit domain on the login cookies eg, "justthis.domain. org"
+ * or ".any.subdomain.net"
+ */
+$wgCookieDomain = '';
+$wgCookiePath = '/';
+$wgDisableCookieCheck = false;
+
+/**  Whether to allow inline image pointing to other websites */
+$wgAllowExternalImages = true;
+
+/** Disable database-intensive features */
+$wgMiserMode = false;
+/** Disable all query pages if miser mode is on, not just some */
+$wgDisableQueryPages = false;
+/** Generate a watchlist once every hour or so */
+$wgUseWatchlistCache = false;
+/** The hour or so mentioned above */
+$wgWLCacheTimeout = 3600;
+/** Minimum number of links to a page required before it appears on Special:Wantedpages */
+$wgWantedPagesThreshold = 1;
+
+/**
+ * To use inline TeX, you need to compile 'texvc' (in the 'math' subdirectory of
+ * the MediaWiki package and have latex, dvips, gs (ghostscript), andconvert
+ * (ImageMagick) installed and available in the PATH.
+ * Please see math/README for more information.
+ */
+$wgUseTeX = false;
+/** Location of the texvc binary */
+$wgTexvc = './math/texvc';
+
+#
+# Profiling / debugging
+#
+
+/** Enable for more detailed by-function times in debug log */
+$wgProfiling = false;
+/** Only record profiling info for pages that took longer than this */
+$wgProfileLimit = 0.0;
+/** Don't put non-profiling info into log file */
+$wgProfileOnly = false;
+/** Log sums from profiling into "profiling" table in db. */
+$wgProfileToDatabase = false;
+/** Only profile every n requests when profiling is turned on */
+$wgProfileSampleRate = 1;
+/** If true, print a raw call tree instead of per-function report */
+$wgProfileCallTree = false;
+
+/** Detects non-matching wfProfileIn/wfProfileOut calls */
+$wgDebugProfiling = false;
+/** Output debug message on every wfProfileIn/wfProfileOut */
+$wgDebugFunctionEntry = 0;
+/** Lots of debugging output from SquidUpdate.php */
+$wgDebugSquid = false;
+
+$wgDisableCounters = false;
+$wgDisableTextSearch = false;
+/**
+ * If you've disabled search semi-permanently, this also disables updates to the
+ * table. If you ever re-enable, be sure to rebuild the search table.
+ */
+$wgDisableSearchUpdate = false;
+/** Uploads have to be specially set up to be secure */
+$wgEnableUploads = false;
+/**
+ * Show EXIF data, on by default if available.
+ * Requires PHP's EXIF extension: http://www.php.net/manual/en/ref.exif.php
+ */
+$wgShowEXIF = function_exists( 'exif_read_data' );
+
+/**
+ * Set to true to enable the upload _link_ while local uploads are disabled.
+ * Assumes that the special page link will be bounced to another server where
+ * uploads do work.
+ */
+$wgRemoteUploads = false;
+$wgDisableAnonTalk = false;
+/**
+ * Do DELETE/INSERT for link updates instead of incremental
+ */
+$wgUseDumbLinkUpdate = false;
+
+/**
+ * Anti-lock flags - bitfield
+ *   ALF_PRELOAD_LINKS
+ *       Preload links during link update for save
+ *   ALF_PRELOAD_EXISTENCE
+ *       Preload cur_id during replaceLinkHolders
+ *   ALF_NO_LINK_LOCK
+ *       Don't use locking reads when updating the link table. This is 
+ *       necessary for wikis with a high edit rate for performance 
+ *       reasons, but may cause link table inconsistency
+ *   ALF_NO_BLOCK_LOCK
+ *       As for ALF_LINK_LOCK, this flag is a necessity for high-traffic
+ *       wikis.
+ */
+$wgAntiLockFlags = 0;
+
+/**
+ * Path to the GNU diff3 utility. If the file doesn't exist, edit conflicts will
+ * fall back to the old behaviour (no merging).
+ */
+$wgDiff3 = '/usr/bin/diff3';
+
+/**
+ * We can also compress text in the old revisions table. If this is set on, old
+ * revisions will be compressed on page save if zlib support is available. Any
+ * compressed revisions will be decompressed on load regardless of this setting
+ * *but will not be readable at all* if zlib support is not available.
+ */
+$wgCompressRevisions = false;
+
+/**
+ * This is the list of preferred extensions for uploading files. Uploading files
+ * with extensions not in this list will trigger a warning.
+ */
+$wgFileExtensions = array( 'png', 'gif', 'jpg', 'jpeg' );
+
+/** Files with these extensions will never be allowed as uploads. */
+$wgFileBlacklist = array(
+       # HTML may contain cookie-stealing JavaScript and web bugs
+       'html', 'htm', 'js', 'jsb',
+       # PHP scripts may execute arbitrary code on the server
+       'php', 'phtml', 'php3', 'php4', 'phps',
+       # Other types that may be interpreted by some servers
+       'shtml', 'jhtml', 'pl', 'py', 'cgi',
+       # May contain harmful executables for Windows victims
+       'exe', 'scr', 'dll', 'msi', 'vbs', 'bat', 'com', 'pif', 'cmd', 'vxd', 'cpl' );
+
+/** Files with these mime types will never be allowed as uploads
+ * if $wgVerifyMimeType is enabled.
+ */
+$wgMimeTypeBlacklist= array(
+       # HTML may contain cookie-stealing JavaScript and web bugs
+       'text/html', 'text/javascript', 'text/x-javascript',  'application/x-shellscript',
+       # PHP scripts may execute arbitrary code on the server
+       'application/x-php', 'text/x-php',
+       # Other types that may be interpreted by some servers
+       'text/x-python', 'text/x-perl', 'text/x-bash', 'text/x-sh', 'text/x-csh',
+       # Windows metafile, client-side vulnerability on some systems
+       'application/x-msmetafile'
+);
+
+/** This is a flag to determine whether or not to check file extensions on upload. */
+$wgCheckFileExtensions = true;
+
+/**
+ * If this is turned off, users may override the warning for files not covered
+ * by $wgFileExtensions.
+ */
+$wgStrictFileExtensions = true;
+
+/** Warn if uploaded files are larger than this */
+$wgUploadSizeWarning = 150 * 1024;
+
+/** For compatibility with old installations set to false */
+$wgPasswordSalt = true;
+
+/** Which namespaces should support subpages?
+ * See Language.php for a list of namespaces.
+ */
+$wgNamespacesWithSubpages = array(
+       NS_TALK           => true,
+       NS_USER           => true,
+       NS_USER_TALK      => true,
+       NS_PROJECT_TALK   => true,
+       NS_IMAGE_TALK     => true,
+       NS_MEDIAWIKI_TALK => true,
+       NS_TEMPLATE_TALK  => true,
+       NS_HELP_TALK      => true,
+       NS_CATEGORY_TALK  => true
+ );
+
+$wgNamespacesToBeSearchedDefault = array(
+       NS_MAIN           => true,
+);
+
+/** If set, a bold ugly notice will show up at the top of every page. */
+$wgSiteNotice = '';
+
+
+#
+# Images settings
+#
+
+/** dynamic server side image resizing ("Thumbnails") */
+$wgUseImageResize              = false;
+
+/**
+ * Resizing can be done using PHP's internal image libraries or using
+ * ImageMagick. The later supports more file formats than PHP, which only
+ * supports PNG, GIF, JPG, XBM and WBMP.
+ *
+ * Use Image Magick instead of PHP builtin functions.
+ */
+$wgUseImageMagick              = false;
+/** The convert command shipped with ImageMagick */
+$wgImageMagickConvertCommand    = '/usr/bin/convert';
+
+# Scalable Vector Graphics (SVG) may be uploaded as images.
+# Since SVG support is not yet standard in browsers, it is
+# necessary to rasterize SVGs to PNG as a fallback format.
+#
+# An external program is required to perform this conversion:
+$wgSVGConverters = array(
+       'ImageMagick' => '$path/convert -background white -geometry $width $input $output',
+       'sodipodi' => '$path/sodipodi -z -w $width -f $input -e $output',
+       'inkscape' => '$path/inkscape -z -w $width -f $input -e $output',
+       'batik' => 'java -Djava.awt.headless=true -jar $path/batik-rasterizer.jar -w $width -d $output $input',
+       'rsvg' => '$path/rsvg -w$width -h$height $input $output',
+       );
+/** Pick one of the above */
+$wgSVGConverter = 'ImageMagick';
+/** If not in the executable PATH, specify */
+$wgSVGConverterPath = '';
+/** Don't scale a SVG larger than this unless its native size is larger */
+$wgSVGMaxSize = 1024;
+
+/** Set $wgCommandLineMode if it's not set already, to avoid notices */
+if( !isset( $wgCommandLineMode ) ) {
+       $wgCommandLineMode = false;
+}
+
+
+#
+# Recent changes settings
+#
+
+/** Log IP addresses in the recentchanges table */
+$wgPutIPinRC = false;
+
+/**
+ * Recentchanges items are periodically purged; entries older than this many
+ * seconds will go.
+ * For one week : 7 * 24 * 3600
+ */
+$wgRCMaxAge = 7 * 24 * 3600;
+
+
+# Send RC updates via UDP
+$wgRC2UDPAddress = false;
+$wgRC2UDPPort = false;
+$wgRC2UDPPrefix = '';
+
+#
+# Copyright and credits settings
+#
+
+/** RDF metadata toggles */
+$wgEnableDublinCoreRdf = false;
+$wgEnableCreativeCommonsRdf = false;
+
+/** Override for copyright metadata.
+ * TODO: these options need documentation
+ */
+$wgRightsPage = NULL;
+$wgRightsUrl = NULL;
+$wgRightsText = NULL;
+$wgRightsIcon = NULL;
+
+/** Set this to some HTML to override the rights icon with an arbitrary logo */
+$wgCopyrightIcon = NULL;
+
+/** Set this to true if you want detailed copyright information forms on Upload. */
+$wgUseCopyrightUpload = false;
+
+/** Set this to false if you want to disable checking that detailed copyright
+ * information values are not empty. */
+$wgCheckCopyrightUpload = true;
+
+/**
+ * Set this to the number of authors that you want to be credited below an
+ * article text. Set it to zero to hide the attribution block, and a negative
+ * number (like -1) to show all authors. Note that this will require 2-3 extra
+ * database hits, which can have a not insignificant impact on performance for
+ * large wikis.
+ */
+$wgMaxCredits = 0;
+
+/** If there are more than $wgMaxCredits authors, show $wgMaxCredits of them.
+ * Otherwise, link to a separate credits page. */
+$wgShowCreditsIfMax = true;
+
+
+
+/**
+ * Set this to false to avoid forcing the first letter of links to capitals.
+ * WARNING: may break links! This makes links COMPLETELY case-sensitive. Links
+ * appearing with a capital at the beginning of a sentence will *not* go to the
+ * same place as links in the middle of a sentence using a lowercase initial.
+ */
+$wgCapitalLinks = true;
+
+/**
+ * List of interwiki prefixes for wikis we'll accept as sources for
+ * Special:Import (for sysops). Since complete page history can be imported,
+ * these should be 'trusted'.
+ *
+ * If a user has the 'import' permission but not the 'importupload' permission,
+ * they will only be able to run imports through this transwiki interface.
+ */
+$wgImportSources = array();
+
+
+
+/** Text matching this regular expression will be recognised as spam
+ * See http://en.wikipedia.org/wiki/Regular_expression */
+$wgSpamRegex = false;
+/** Similarly if this function returns true */
+$wgFilterCallback = false;
+
+/** Go button goes straight to the edit screen if the article doesn't exist. */
+$wgGoToEdit = false;
+
+/** Allow limited user-specified HTML in wiki pages?
+ * It  will be run through a whitelist for security. Set this to false if you
+ * want wiki pages to consist only of wiki markup. Note that replacements do not
+ * yet exist for all HTML constructs.*/
+$wgUserHtml = true;
+
+/** Allow raw, unchecked HTML in <html>...</html> sections.
+ * THIS IS VERY DANGEROUS on a publically editable site, so USE wgGroupPermissions
+ * TO RESTRICT EDITING to only those that you trust
+ */
+$wgRawHtml = false;
+
+/**
+ * $wgUseTidy: use tidy to make sure HTML output is sane.
+ * This should only be enabled if $wgUserHtml is true.
+ * tidy is a free tool that fixes broken HTML.
+ * See http://www.w3.org/People/Raggett/tidy/
+ * $wgTidyBin should be set to the path of the binary and
+ * $wgTidyConf to the path of the configuration file.
+ * $wgTidyOpts can include any number of parameters.
+ *
+ * $wgTidyInternal controls the use of the PECL extension to use an in-
+ *   process tidy library instead of spawning a separate program.
+ *   Normally you shouldn't need to override the setting except for
+ *   debugging. To install, use 'pear install tidy' and add a line
+ *   'extension=tidy.so' to php.ini.
+ */
+$wgUseTidy = false;
+$wgTidyBin = 'tidy';
+$wgTidyConf = $IP.'/extensions/tidy/tidy.conf';
+$wgTidyOpts = '';
+$wgTidyInternal = function_exists( 'tidy_load_config' );
+
+/** See list of skins and their symbolic names in languages/Language.php */
+$wgDefaultSkin = 'monobook';
+
+/**
+ * Settings added to this array will override the language globals for the user
+ * preferences used by anonymous visitors and newly created accounts. (See names
+ * and sample values in languages/Language.php)
+ * For instance, to disable section editing links:
+ *  $wgDefaultUserOptions ['editsection'] = 0;
+ *
+ */
+$wgDefaultUserOptions = array();
+
+/** Whether or not to allow and use real name fields. Defaults to true. */
+$wgAllowRealName = true;
+
+/** Use XML parser? */
+$wgUseXMLparser = false ;
+
+/** Extensions */
+$wgSkinExtensionFunctions = array();
+$wgExtensionFunctions = array();
+/**
+ * An array of extension types and inside that their names, versions, authors
+ * and urls, note that the version and url key can be omitted.
+ *
+ * <code>
+ * $wgExtensionCredits[$type][] = array(
+ *     'name' => 'Example extension',
+ *      'version' => 1.9,
+ *     'author' => 'Foo Barstein',
+ *     'url' => 'http://wwww.example.com/Example%20Extension/',
+ * );
+ * </code>
+ *
+ * Where $type is 'specialpage', 'parserhook', or 'other'.
+ */
+$wgExtensionCredits = array();
+
+/**
+ * Allow user Javascript page?
+ * This enables a lot of neat customizations, but may
+ * increase security risk to users and server load.
+ */
+$wgAllowUserJs = false;
+
+/**
+ * Allow user Cascading Style Sheets (CSS)?
+ * This enables a lot of neat customizations, but may
+ * increase security risk to users and server load.
+ */
+$wgAllowUserCss = false;
+
+/** Use the site's Javascript page? */
+$wgUseSiteJs = true;
+
+/** Use the site's Cascading Style Sheets (CSS)? */
+$wgUseSiteCss = true;
+
+/** Filter for Special:Randompage. Part of a WHERE clause */
+$wgExtraRandompageSQL = false;
+
+/** Allow the "info" action, very inefficient at the moment */
+$wgAllowPageInfo = false;
+
+/** Maximum indent level of toc. */
+$wgMaxTocLevel = 999;
+
+/** Use external C++ diff engine (module wikidiff from the extensions package) */
+$wgUseExternalDiffEngine = false;
+
+/** Use RC Patrolling to check for vandalism */
+$wgUseRCPatrol = true;
+
+/** Set maximum number of results to return in syndication feeds (RSS, Atom) for
+ * eg Recentchanges, Newpages. */
+$wgFeedLimit = 50;
+
+/** _Minimum_ timeout for cached Recentchanges feed, in seconds.
+ * A cached version will continue to be served out even if changes
+ * are made, until this many seconds runs out since the last render. */
+$wgFeedCacheTimeout = 60;
+
+/** When generating Recentchanges RSS/Atom feed, diffs will not be generated for
+ * pages larger than this size. */
+$wgFeedDiffCutoff = 32768;
+
+
+/**
+ * Additional namespaces. If the namespaces defined in Language.php and
+ * Namespace.php are insufficient, you can create new ones here, for example,
+ * to import Help files in other languages.
+ * PLEASE  NOTE: Once you delete a namespace, the pages in that namespace will
+ * no longer be accessible. If you rename it, then you can access them through
+ * the new namespace name.
+ *
+ * Custom namespaces should start at 100 to avoid conflicting with standard
+ * namespaces, and should always follow the even/odd main/talk pattern.
+ */
+#$wgExtraNamespaces =
+#      array(100 => "Hilfe",
+#            101 => "Hilfe_Diskussion",
+#            102 => "Aide",
+#            103 => "Discussion_Aide"
+#            );
+$wgExtraNamespaces = NULL;
+
+/**
+ * Limit images on image description pages to a user-selectable limit. In order
+ * to reduce disk usage, limits can only be selected from a list. This is the
+ * list of settings the user can choose from:
+ */
+$wgImageLimits = array (
+       array(320,240),
+       array(640,480),
+       array(800,600),
+       array(1024,768),
+       array(1280,1024),
+       array(10000,10000) );
+
+/**
+ * Adjust thumbnails on image pages according to a user setting. In order to
+ * reduce disk usage, the values can only be selected from a list. This is the
+ * list of settings the user can choose from:
+ */
+$wgThumbLimits = array(
+       120,
+       150,
+       180,
+       200,
+       250,
+       300
+);
+
+/**
+ *  On  category pages, show thumbnail gallery for images belonging to that
+ * category instead of listing them as articles.
+ */
+$wgCategoryMagicGallery = true;
+
+/**
+ * Paging limit for items in categories
+ */
+$wgCategoryPagingLimit = 200;
+
+/**
+ * Browser Blacklist for unicode non compliant browsers
+ * Contains a list of regexps : "/regexp/"  matching problematic browsers
+ */
+$wgBrowserBlackList = array(
+       "/Mozilla\/4\.78 \[en\] \(X11; U; Linux/",
+       /**
+        * MSIE on Mac OS 9 is teh sux0r, converts þ to <thorn>, ð to <eth>, Þ to <THORN> and Ð to <ETH>
+        *
+        * Known useragents:
+        * - Mozilla/4.0 (compatible; MSIE 5.0; Mac_PowerPC)
+        * - Mozilla/4.0 (compatible; MSIE 5.15; Mac_PowerPC)
+        * - Mozilla/4.0 (compatible; MSIE 5.23; Mac_PowerPC)
+        * - [...]
+        *
+        * @link http://en.wikipedia.org/w/index.php?title=User%3A%C6var_Arnfj%F6r%F0_Bjarmason%2Ftestme&diff=12356041&oldid=12355864
+        * @link http://en.wikipedia.org/wiki/Template%3AOS9
+        */
+       "/Mozilla\/4\.0 \(compatible; MSIE \d+\.\d+; Mac_PowerPC\)/"
+);
+
+/**
+ * Fake out the timezone that the server thinks it's in. This will be used for
+ * date display and not for what's stored in the DB. Leave to null to retain
+ * your server's OS-based timezone value. This is the same as the timezone.
+ *
+ * This variable is currently used ONLY for signature formatting, not for
+ * anything else.
+ */
+# $wgLocaltimezone = 'GMT';
+# $wgLocaltimezone = 'PST8PDT';
+# $wgLocaltimezone = 'Europe/Sweden';
+# $wgLocaltimezone = 'CET';
+$wgLocaltimezone = null;
+
+/**
+ * Set an offset from UTC in hours to use for the default timezone setting
+ * for anonymous users and new user accounts.
+ *
+ * This setting is used for most date/time displays in the software, and is
+ * overrideable in user preferences. It is *not* used for signature timestamps.
+ *
+ * You can set it to match the configured server timezone like this:
+ *   $wgLocalTZoffset = date("Z") / 3600;
+ *
+ * If your server is not configured for the timezone you want, you can set
+ * this in conjunction with the signature timezone and override the TZ
+ * environment variable like so:
+ *   $wgLocaltimezone="Europe/Berlin";
+ *   putenv("TZ=$wgLocaltimezone");
+ *   $wgLocalTZoffset = date("Z") / 3600;
+ *
+ * Leave at NULL to show times in universal time (UTC/GMT).
+ */
+$wgLocalTZoffset = null;
+
+
+/**
+ * When translating messages with wfMsg(), it is not always clear what should be
+ * considered UI messages and what shoud be content messages.
+ *
+ * For example, for regular wikipedia site like en, there should be only one
+ * 'mainpage', therefore when getting the link of 'mainpage', we should treate
+ * it as content of the site and call wfMsgForContent(), while for rendering the
+ * text of the link, we call wfMsg(). The code in default behaves this way.
+ * However, sites like common do offer different versions of 'mainpage' and the
+ * like for different languages. This array provides a way to override the
+ * default behavior. For example, to allow language specific mainpage and
+ * community portal, set
+ *
+ * $wgForceUIMsgAsContentMsg = array( 'mainpage', 'portal-url' );
+ */
+$wgForceUIMsgAsContentMsg = array();
+
+
+/**
+ * Authentication plugin.
+ */
+$wgAuth = null;
+
+/**
+ * Global list of hooks.
+ * Add a hook by doing:
+ *     $wgHooks['event_name'][] = $function;
+ * or:
+ *     $wgHooks['event_name'][] = array($function, $data);
+ * or:
+ *     $wgHooks['event_name'][] = array($object, 'method');
+ */
+$wgHooks = array();
+
+/**
+ * Experimental preview feature to fetch rendered text
+ * over an XMLHttpRequest from JavaScript instead of
+ * forcing a submit and reload of the whole page.
+ * Leave disabled unless you're testing it.
+ */
+$wgLivePreview = false;
+
+/**
+ * Disable the internal MySQL-based search, to allow it to be
+ * implemented by an extension instead.
+ */
+$wgDisableInternalSearch = false;
+
+/**
+ * Set this to a URL to forward search requests to some external location.
+ * If the URL includes '$1', this will be replaced with the URL-encoded
+ * search term.
+ *
+ * For example, to forward to Google you'd have something like:
+ * $wgSearchForwardUrl = 'http://www.google.com/search?q=$1' .
+ *                       '&domains=http://example.com' .
+ *                       '&sitesearch=http://example.com' .
+ *                       '&ie=utf-8&oe=utf-8';
+ */
+$wgSearchForwardUrl = null;
+
+/**
+ * If true, external URL links in wiki text will be given the
+ * rel="nofollow" attribute as a hint to search engines that
+ * they should not be followed for ranking purposes as they
+ * are user-supplied and thus subject to spamming.
+ */
+$wgNoFollowLinks = true;
+
+/**
+ * Specifies the minimal length of a user password. If set to
+ * 0, empty passwords are allowed.
+ */
+$wgMinimalPasswordLength = 0;
+
+/**
+ * Activate external editor interface for files and pages
+ * See http://meta.wikimedia.org/wiki/Help:External_editors
+ */
+$wgUseExternalEditor = true;
+
+/** Whether or not to sort special pages in Special:Specialpages */
+
+$wgSortSpecialPages = true;
+
+/**
+ * Specify the name of a skin that should not be presented in the
+ * list of available skins.
+ * Use for blacklisting a skin which you do not want to remove
+ * from the .../skins/ directory
+ */
+$wgSkipSkin = '';
+$wgSkipSkins = array(); # More of the same
+
+/**
+ * Array of disabled article actions, e.g. view, edit, dublincore, delete, etc.
+ */
+$wgDisabledActions = array();
+
+/**
+ * Disable redirects to special pages and interwiki redirects, which use a 302 and have no "redirected from" link
+ */
+$wgDisableHardRedirects = false;
+
+/**
+ * Use http.dnsbl.sorbs.net to check for open proxies
+ */
+$wgEnableSorbs = false;
+
+/**
+ * Use opm.blitzed.org to check for open proxies.
+ * Not yet actually used.
+ */
+$wgEnableOpm = false;
+
+/**
+ * Proxy whitelist, list of addresses that are assumed to be non-proxy despite what the other
+ * methods might say
+ */
+$wgProxyWhitelist = array();
+
+/**
+ * Simple rate limiter options to brake edit floods.
+ * Maximum number actions allowed in the given number of seconds;
+ * after that the violating client receives HTTP 500 error pages
+ * until the period elapses.
+ *
+ * array( 4, 60 ) for a maximum of 4 hits in 60 seconds.
+ *
+ * This option set is experimental and likely to change.
+ * Requires memcached.
+ */
+$wgRateLimits = array(
+       'edit' => array(
+               'anon'   => null, // for any and all anonymous edits (aggregate)
+               'user'   => null, // for each logged-in user
+               'newbie' => null, // for each recent account; overrides 'user'
+               'ip'     => null, // for each anon and recent account
+               'subnet' => null, // ... with final octet removed
+               ),
+       'move' => array(
+               'user'   => null,
+               'newbie' => null,
+               'ip'     => null,
+               'subnet' => null,
+               ),
+       );
+
+/**
+ * Set to a filename to log rate limiter hits.
+ */
+$wgRateLimitLog = null;
+
+/**
+ * On Special:Unusedimages, consider images "used", if they are put
+ * into a category. Default (false) is not to count those as used.
+ */
+$wgCountCategorizedImagesAsUsed = false;
+
+/**
+ * External stores allow including content
+ * from non database sources following URL links
+ *
+ * Short names of ExternalStore classes may be specified in an array here:
+ * $wgExternalStores = array("http","file","custom")...
+ *
+ * CAUTION: Access to database might lead to code execution
+ */
+$wgExternalStores = false;
+
+/**
+ * An array of external mysql servers, e.g.
+ * $wgExternalServers = array( 'cluster1' => array( 'srv28', 'srv29', 'srv30' ) );
+ */
+$wgExternalServers = array();
+
+/**
+* list of trusted media-types and mime types.
+* Use the MEDIATYPE_xxx constants to represent media types.
+* This list is used by Image::isSafeFile
+*
+* Types not listed here will have a warning about unsafe content
+* displayed on the images description page. It would also be possible
+* to use this for further restrictions, like disabling direct
+* [[media:...]] links for non-trusted formats.
+*/
+$wgTrustedMediaFormats= array(
+       MEDIATYPE_BITMAP, //all bitmap formats
+       MEDIATYPE_AUDIO,  //all audio formats
+       MEDIATYPE_VIDEO,  //all plain video formats
+       "image/svg",  //svg (only needed if inline rendering of svg is not supported)
+       "application/pdf",  //PDF files
+       #"application/x-shockwafe-flash", //flash/shockwave movie
+);
+
+/**
+ * Allow special page inclusions such as {{Special:Allpages}}
+ */
+$wgAllowSpecialInclusion = true;
+
+/**
+ * Timeout for HTTP requests done via CURL
+ */
+$wgHTTPTimeout = 3;
+
+/**
+ * Proxy to use for CURL requests.
+ */
+$wgHTTPProxy = false;
+
+/**
+ * Enable interwiki transcluding.  Only when iw_trans=1.
+ */
+$wgEnableScaryTranscluding = false;
+
+/**
+ * Support blog-style "trackbacks" for articles.  See
+ * http://www.sixapart.com/pronet/docs/trackback_spec for details.
+ */
+$wgUseTrackbacks = false;
+
+?>
diff --git a/includes/Defines.php b/includes/Defines.php
new file mode 100644 (file)
index 0000000..e17dc2b
--- /dev/null
@@ -0,0 +1,143 @@
+<?php
+/**
+ * A few constants that might be needed during LocalSettings.php
+ * @package MediaWiki
+ */
+
+/**#@+
+ * Database related constants
+ */
+define( 'DBO_DEBUG', 1 );
+define( 'DBO_NOBUFFER', 2 );
+define( 'DBO_IGNORE', 4 );
+define( 'DBO_TRX', 8 );
+define( 'DBO_DEFAULT', 16 );
+define( 'DBO_PERSISTENT', 32 );
+/**#@-*/
+
+/**#@+
+ * Virtual namespaces; don't appear in the page database
+ */
+define('NS_MEDIA', -2);
+define('NS_SPECIAL', -1);
+/**#@-*/
+
+/**#@+
+ * Real namespaces
+ *
+ * Number 100 and beyond are reserved for custom namespaces;
+ * DO NOT assign standard namespaces at 100 or beyond.
+ * DO NOT Change integer values as they are most probably hardcoded everywhere
+ * see bug #696 which talked about that.
+ */
+define('NS_MAIN', 0);
+define('NS_TALK', 1);
+define('NS_USER', 2);
+define('NS_USER_TALK', 3);
+define('NS_PROJECT', 4);
+define('NS_PROJECT_TALK', 5);
+define('NS_IMAGE', 6);
+define('NS_IMAGE_TALK', 7);
+define('NS_MEDIAWIKI', 8);
+define('NS_MEDIAWIKI_TALK', 9);
+define('NS_TEMPLATE', 10);
+define('NS_TEMPLATE_TALK', 11);
+define('NS_HELP', 12);
+define('NS_HELP_TALK', 13);
+define('NS_CATEGORY', 14);
+define('NS_CATEGORY_TALK', 15);
+/**#@-*/
+
+/**
+ * Available feeds objects
+ * Should probably only be defined when a page is syndicated ie when
+ * $wgOut->isSyndicated() is true
+ */
+$wgFeedClasses = array(
+       'rss' => 'RSSFeed',
+       'atom' => 'AtomFeed',
+);
+
+/**#@+
+ * Maths constants
+ */
+define( 'MW_MATH_PNG',    0 );
+define( 'MW_MATH_SIMPLE', 1 );
+define( 'MW_MATH_HTML',   2 );
+define( 'MW_MATH_SOURCE', 3 );
+define( 'MW_MATH_MODERN', 4 );
+define( 'MW_MATH_MATHML', 5 );
+/**#@-*/
+
+/**
+ * User rights management
+ * a big array of string defining a right, that's how they are saved in the
+ * database.
+ * @todo Is this necessary?
+ */
+$wgAvailableRights = array('read', 'edit', 'move', 'delete', 'undelete',
+'protect', 'block', 'userrights', 'createaccount', 'upload',
+'rollback', 'patrol', 'editinterface', 'siteadmin', 'bot', 'validate', 
+'import', 'importupload', 'renameuser' );
+
+/**#@+
+ * Cache type
+ */
+define( 'CACHE_ANYTHING', -1 );  // Use anything, as long as it works
+define( 'CACHE_NONE', 0 );       // Do not cache
+define( 'CACHE_DB', 1 );         // Store cache objects in the DB
+define( 'CACHE_MEMCACHED', 2 );  // MemCached, must specify servers in $wgMemCacheServers
+define( 'CACHE_ACCEL', 3 );      // eAccelerator or Turck, whichever is available
+/**#@-*/
+
+
+
+/**#@+
+ * Media types. 
+ * This defines constants for the value returned by Image::getMediaType()
+ */
+
+define( 'MEDIATYPE_UNKNOWN',    'UNKNOWN' );     // unknown format
+define( 'MEDIATYPE_BITMAP',     'BITMAP' );      // some bitmap image or image source (like psd, etc). Can't scale up.
+define( 'MEDIATYPE_DRAWING',    'DRAWING' );     // some vector drawing (SVG, WMF, PS, ...) or image source (oo-draw, etc). Can scale up.
+define( 'MEDIATYPE_AUDIO',      'AUDIO' );       // simple audio file (ogg, mp3, wav, midi, whatever)
+define( 'MEDIATYPE_VIDEO',      'VIDEO' );       // simple video file (ogg, mpg, etc; no not include formats here that may contain executable sections or scripts!)
+define( 'MEDIATYPE_MULTIMEDIA', 'MULTIMEDIA' );  // Scriptable Multimedia (flash, advanced video container formats, etc)
+define( 'MEDIATYPE_OFFICE',     'OFFICE' );      // Office Documents, Spreadsheets (office formats possibly containing apples, scripts, etc)
+define( 'MEDIATYPE_TEXT',       'TEXT' );        // Plain text (possibly containing program code or scripts)
+define( 'MEDIATYPE_EXECUTABLE', 'EXECUTABLE' );  // binary executable
+define( 'MEDIATYPE_ARCHIVE',    'ARCHIVE' );     // archive file (zip, tar, etc)
+/**#@-*/
+
+/**#@+
+ * Antivirus result codes, for use in $wgAntivirusSetup. 
+ */
+
+define( 'AV_NO_VIRUS', 0 );  #scan ok, no virus found
+define( 'AV_VIRUS_FOUND', 1 );  #virus found!
+define( 'AV_SCAN_ABORTED', -1 );  #scan aborted, the file is probably imune
+define( 'AV_SCAN_FAILED', false );  #scan failed (scanner not found or error in scanner)
+/**#@-*/
+
+/**#@+
+ * Anti-lock flags
+ * See DefaultSettings.php for a description
+ */
+define( 'ALF_PRELOAD_LINKS', 1 );
+define( 'ALF_PRELOAD_EXISTENCE', 2 );
+define( 'ALF_NO_LINK_LOCK', 4 );
+define( 'ALF_NO_BLOCK_LOCK', 8 );
+/**#@-*/
+
+/**#@+
+ * Date format selectors; used in user preference storage and by
+ * Language::date() and co.
+ */
+define( 'MW_DATE_DEFAULT', '0' );
+define( 'MW_DATE_MDY', '1' );
+define( 'MW_DATE_DMY', '2' );
+define( 'MW_DATE_YMD', '3' );
+define( 'MW_DATE_ISO', 'ISO 8601' );
+/**#@-*/
+
+?>
diff --git a/includes/DifferenceEngine.php b/includes/DifferenceEngine.php
new file mode 100644 (file)
index 0000000..e056eee
--- /dev/null
@@ -0,0 +1,1496 @@
+<?php
+/**
+ * See diff.doc
+ * @package MediaWiki 
+ * @subpackage DifferenceEngine
+ */
+
+/** */
+require_once( 'Revision.php' );
+
+/**
+ * @todo document
+ * @access public
+ * @package MediaWiki 
+ * @subpackage DifferenceEngine
+ */
+class DifferenceEngine {
+       /**#@+
+        * @access private
+        */
+       var $mOldid, $mNewid;
+       var $mOldtitle, $mNewtitle, $mPagetitle;
+       var $mOldtext, $mNewtext;
+       var $mOldUser, $mNewUser;
+       var $mOldComment, $mNewComment;
+       var $mOldPage, $mNewPage;
+       var $mRcidMarkPatrolled;
+       /**#@-*/
+
+       /**
+        * Constructor
+        * @param integer $old Old ID we want to show and diff with.
+        * @param string $new Either 'prev' or 'next'. 
+        * @param integer $rcid ??? (default 0)
+        */
+       function DifferenceEngine( $old, $new, $rcid = 0 ) {
+               global $wgTitle;
+
+               if ( 'prev' == $new ) {
+                       # Show diff between revision $old and the previous one.
+                       # Get previous one from DB.
+                       #
+                       $this->mNewid = intval($old);
+
+                       $this->mOldid = $wgTitle->getPreviousRevisionID( $this->mNewid );
+
+               } elseif ( 'next' == $new ) {
+                       # Show diff between revision $old and the previous one.
+                       # Get previous one from DB.
+                       #
+                       $this->mOldid = intval($old);
+                       $this->mNewid = $wgTitle->getNextRevisionID( $this->mOldid );
+                       if ( false === $this->mNewid ) {
+                               # if no result, NewId points to the newest old revision. The only newer
+                               # revision is cur, which is "0".
+                               $this->mNewid = 0;
+                       }
+
+               } else {
+                       $this->mOldid = intval($old);
+                       $this->mNewid = intval($new);
+               }
+               $this->mRcidMarkPatrolled = intval($rcid);  # force it to be an integer
+       }
+
+       function showDiffPage() {
+               global $wgUser, $wgTitle, $wgOut, $wgContLang, $wgOnlySysopsCanPatrol,
+                      $wgUseExternalEditor, $wgUseRCPatrol;
+               $fname = 'DifferenceEngine::showDiffPage';
+               wfProfileIn( $fname );
+                               
+               # If external diffs are enabled both globally and for the user,
+               # we'll use the application/x-external-editor interface to call
+               # an external diff tool like kompare, kdiff3, etc.
+               if($wgUseExternalEditor && $wgUser->getOption('externaldiff')) {
+                       global $wgInputEncoding,$wgServer,$wgScript,$wgLang;
+                       $wgOut->disable();
+                       header ( "Content-type: application/x-external-editor; charset=".$wgInputEncoding );
+                       $url1=$wgTitle->getFullURL("action=raw&oldid=".$this->mOldid);                  
+                       $url2=$wgTitle->getFullURL("action=raw&oldid=".$this->mNewid);
+                       $special=$wgLang->getNsText(NS_SPECIAL);
+                       $control=<<<CONTROL
+[Process]
+Type=Diff text
+Engine=MediaWiki
+Script={$wgServer}{$wgScript}
+Special namespace={$special}
+
+[File]
+Extension=wiki
+URL=$url1
+
+[File 2]
+Extension=wiki
+URL=$url2
+CONTROL;
+                       echo($control);
+                       return;
+               }
+
+               # mOldid is false if the difference engine is called with a "vague" query for
+               # a diff between a version V and its previous version V' AND the version V
+               # is the first version of that article. In that case, V' does not exist.
+               if ( $this->mOldid === false ) {
+                       $this->showFirstRevision();
+                       wfProfileOut( $fname );
+                       return;
+               }
+
+               $t = $wgTitle->getPrefixedText() . " (Diff: {$this->mOldid}, " .
+                 "{$this->mNewid})";
+               $mtext = wfMsg( 'missingarticle', $t );
+
+               $wgOut->setArticleFlag( false );
+               if ( ! $this->loadText() ) {
+                       $wgOut->setPagetitle( wfMsg( 'errorpagetitle' ) );
+                       $wgOut->addHTML( $mtext );
+                       wfProfileOut( $fname );
+                       return;
+               }
+               $wgOut->suppressQuickbar();
+
+               $oldTitle = $this->mOldPage->getPrefixedText();
+               $newTitle = $this->mNewPage->getPrefixedText();
+               if( $oldTitle == $newTitle ) {
+                       $wgOut->setPageTitle( $newTitle );
+               } else {
+                       $wgOut->setPageTitle( $oldTitle . ', ' . $newTitle );
+               }
+               $wgOut->setSubtitle( wfMsg( 'difference' ) );
+               $wgOut->setRobotpolicy( 'noindex,follow' );
+
+               if ( !( $this->mOldPage->userCanRead() && $this->mNewPage->userCanRead() ) ) {
+                       $wgOut->loginToUse();
+                       $wgOut->output();
+                       wfProfileOut( $fname );
+                       exit;
+               }
+
+               $sk = $wgUser->getSkin();
+               $talk = $wgContLang->getNsText( NS_TALK );
+               $contribs = wfMsg( 'contribslink' );
+
+               $this->mOldComment = $sk->formatComment($this->mOldComment);
+               $this->mNewComment = $sk->formatComment($this->mNewComment);
+
+               $oldUserLink = $sk->makeLinkObj( Title::makeTitleSafe( NS_USER, $this->mOldUser ), $this->mOldUser );
+               $newUserLink = $sk->makeLinkObj( Title::makeTitleSafe( NS_USER, $this->mNewUser ), $this->mNewUser );
+               $oldUTLink = $sk->makeLinkObj( Title::makeTitleSafe( NS_USER_TALK, $this->mOldUser ), $talk );
+               $newUTLink = $sk->makeLinkObj( Title::makeTitleSafe( NS_USER_TALK, $this->mNewUser ), $talk );
+               $oldContribs = $sk->makeKnownLinkObj( Title::makeTitle( NS_SPECIAL, 'Contributions' ), $contribs,
+                       'target=' . urlencode($this->mOldUser) );
+               $newContribs = $sk->makeKnownLinkObj( Title::makeTitle( NS_SPECIAL, 'Contributions' ), $contribs,
+                       'target=' . urlencode($this->mNewUser) );
+               if ( $this->newRev->isCurrent() && $wgUser->isAllowed('rollback') ) {
+                       $rollback = '&nbsp;&nbsp;&nbsp;<strong>[' . $sk->makeKnownLinkObj( $wgTitle, wfMsg( 'rollbacklink' ),
+                               'action=rollback&from=' . urlencode($this->mNewUser) .
+                               '&token=' . urlencode( $wgUser->editToken( array( $wgTitle->getPrefixedText(), $this->mNewUser ) ) ) ) .
+                               ']</strong>';
+               } else {
+                       $rollback = '';
+               }
+               if ( $wgUseRCPatrol && $this->mRcidMarkPatrolled != 0 && $wgUser->isLoggedIn() &&
+                    ( $wgUser->isAllowed('rollback') || !$wgOnlySysopsCanPatrol ) )
+               {
+                       $patrol = ' [' . $sk->makeKnownLinkObj( $wgTitle, wfMsg( 'markaspatrolleddiff' ),
+                               "action=markpatrolled&rcid={$this->mRcidMarkPatrolled}" ) . ']';
+               } else {
+                       $patrol = '';
+               }
+
+               $prevlink = $sk->makeKnownLinkObj( $wgTitle, wfMsgHtml( 'previousdiff' ),
+                       'diff=prev&oldid='.$this->mOldid, '', '', 'id="differences-prevlink"' );
+               if ( $this->newRev->isCurrent() ) {
+                       $nextlink = '';
+               } else {
+                       $nextlink = $sk->makeKnownLinkObj( $wgTitle, wfMsgHtml( 'nextdiff' ),
+                               'diff=next&oldid='.$this->mNewid, '', '', 'id="differences-nextlink"' );
+               }
+
+               $oldHeader = "<strong>{$this->mOldtitle}</strong><br />$oldUserLink " .
+                       "($oldUTLink | $oldContribs)<br />" . $this->mOldComment .
+                       '<br />' . $prevlink;
+               $newHeader = "<strong>{$this->mNewtitle}</strong><br />$newUserLink " .
+                       "($newUTLink | $newContribs) $rollback<br />" . $this->mNewComment .
+                       '<br />' . $nextlink . $patrol;
+
+               DifferenceEngine::showDiff( $this->mOldtext, $this->mNewtext,
+                 $oldHeader, $newHeader );
+               $wgOut->addHTML( "<hr /><h2>{$this->mPagetitle}</h2>\n" );
+
+               if( !$this->newRev->isCurrent() ) {
+                       $oldEditSectionSetting = $wgOut->mParserOptions->setEditSection( false );
+               }
+               $wgOut->addWikiText( $this->mNewtext );
+               if( !$this->newRev->isCurrent() ) {
+                       $wgOut->mParserOptions->setEditSection( $oldEditSectionSetting );
+               }
+
+               wfProfileOut( $fname );
+       }
+
+       /**
+        * Show the first revision of an article. Uses normal diff headers in
+        * contrast to normal "old revision" display style.
+        */
+       function showFirstRevision() {
+               global $wgOut, $wgTitle, $wgUser, $wgLang;
+
+               $fname = 'DifferenceEngine::showFirstRevision';
+               wfProfileIn( $fname );
+
+
+               $this->mOldid = $this->mNewid; # hack to make loadText() work.
+
+               # Get article text from the DB
+               #
+               if ( ! $this->loadText() ) {
+                       $t = $wgTitle->getPrefixedText() . " (Diff: {$this->mOldid}, " .
+                         "{$this->mNewid})";
+                       $mtext = wfMsg( 'missingarticle', $t );
+                       $wgOut->setPagetitle( wfMsg( 'errorpagetitle' ) );
+                       $wgOut->addHTML( $mtext );
+                       wfProfileOut( $fname );
+                       return;
+               }
+
+               # Check if user is allowed to look at this page. If not, bail out.
+               #
+               if ( !( $this->mOldPage->userCanRead() ) ) {
+                       $wgOut->loginToUse();
+                       $wgOut->output();
+                       wfProfileOut( $fname );
+                       exit;
+               }
+
+               # Prepare the header box
+               #
+               $sk = $wgUser->getSkin();
+
+               $uTLink = $sk->makeLinkObj( Title::makeTitleSafe( NS_USER_TALK, $this->mOldUser ),  $wgLang->getNsText( NS_TALK ) );
+               $userLink = $sk->makeLinkObj( Title::makeTitleSafe( NS_USER, $this->mOldUser ), $this->mOldUser );
+               $contribs = $sk->makeKnownLinkObj( Title::makeTitle( NS_SPECIAL, 'Contributions' ), wfMsg( 'contribslink' ),
+                       'target=' . urlencode($this->mOldUser) );
+               $nextlink = $sk->makeKnownLinkObj( $wgTitle, wfMsgHtml( 'nextdiff' ), 'diff=next&oldid='.$this->mNewid, '', '', 'id="differences-nextlink"' );
+               $header = "<div class=\"firstrevisionheader\" style=\"text-align: center\"><strong>{$this->mOldtitle}</strong><br />$userLink " .
+                       "($uTLink | $contribs)<br />" . $this->mOldComment .
+                       '<br />' . $nextlink. "</div>\n";
+
+               $wgOut->addHTML( $header );
+
+               $wgOut->setSubtitle( wfMsg( 'difference' ) );
+               $wgOut->setRobotpolicy( 'noindex,follow' );
+
+
+               # Show current revision
+               #
+               $wgOut->addHTML( "<hr /><h2>{$this->mPagetitle}</h2>\n" );
+               $wgOut->addWikiText( $this->mNewtext );
+
+               wfProfileOut( $fname );
+       }
+
+       function showDiff( $otext, $ntext, $otitle, $ntitle ) {
+               global $wgOut;
+               $wgOut->addHTML( DifferenceEngine::getDiff( $otext, $ntext, $otitle, $ntitle ) );
+       }
+       
+       function getDiff( $otext, $ntext, $otitle, $ntitle ) {
+               global $wgUseExternalDiffEngine, $wgContLang;
+               $out = "
+                       <table border='0' width='98%' cellpadding='0' cellspacing='4' class='diff'>
+                       <tr>
+                               <td colspan='2' width='50%' align='center' class='diff-otitle'>{$otitle}</td>
+                               <td colspan='2' width='50%' align='center' class='diff-ntitle'>{$ntitle}</td>
+                       </tr>
+               ";
+               $otext = $wgContLang->segmentForDiff($otext);
+               $ntext = $wgContLang->segmentForDiff($ntext);
+               $difftext='';
+               if ( $wgUseExternalDiffEngine ) {
+                       # For historical reasons, external diff engine expects
+                       # input text to be HTML-escaped already
+                       $otext = str_replace( "\r\n", "\n", htmlspecialchars ( $otext ) );
+                       $ntext = str_replace( "\r\n", "\n", htmlspecialchars ( $ntext ) );
+                       if( !function_exists( 'wikidiff_do_diff' ) ) {
+                               dl('php_wikidiff.so');
+                       }
+                       $difftext = wikidiff_do_diff( $otext, $ntext, 2 );
+               } else {
+                       $ota = explode( "\n", str_replace( "\r\n", "\n", $otext ) );
+                       $nta = explode( "\n", str_replace( "\r\n", "\n", $ntext ) );
+                       $diffs =& new Diff( $ota, $nta );
+                       $formatter =& new TableDiffFormatter();
+                       $difftext = $formatter->format( $diffs );
+               }
+               $difftext = $wgContLang->unsegmentForDiff($difftext);
+               $out .= $difftext."</table>\n";
+               return $out;
+       }
+
+       /**
+        * Load the text of the articles to compare.  If newid is 0, then compare
+        * the old article in oldid to the current article; if oldid is 0, then
+        * compare the current article to the immediately previous one (ignoring the
+        * value of newid).
+        */     
+       function loadText() {
+               global $wgTitle, $wgOut, $wgLang;
+               $fname = 'DifferenceEngine::loadText';
+
+               $dbr =& wfGetDB( DB_SLAVE );
+               if( $this->mNewid ) {
+                       $this->newRev = Revision::newFromId( $this->mNewid );
+               } else {
+                       $this->newRev = Revision::newFromTitle( $wgTitle );
+               }
+               if( is_null( $this->newRev ) ) {
+                       return false;
+               }
+               
+               if( $this->newRev->isCurrent() ) {
+                       $wgOut->setArticleFlag( true );
+                       $this->mPagetitle = htmlspecialchars( wfMsg( 'currentrev' ) );
+                       $this->mNewPage = $wgTitle;
+                       $newLink = $this->mNewPage->escapeLocalUrl();
+                       $this->mNewtitle = "<a href='$newLink'>{$this->mPagetitle}</a>";
+               } else {
+                       $this->mNewPage = $this->newRev->getTitle();
+                       $newLink = $this->mNewPage->escapeLocalUrl ('oldid=' . $this->mNewid );
+                       $t = $wgLang->timeanddate( $this->newRev->getTimestamp(), true );
+                       $this->mPagetitle = htmlspecialchars( wfMsg( 'revisionasof', $t ) );
+                       $this->mNewtitle = "<a href='$newLink'>{$this->mPagetitle}</a>";
+               }
+               
+               if( $this->mOldid ) {
+                       $this->oldRev = Revision::newFromId( $this->mOldid );
+               } else {
+                       $this->oldRev = $this->newRev->getPrevious();
+                       $this->mOldid = $this->oldRev->getId();
+               }
+               if( is_null( $this->oldRev ) ) {
+                       return false;
+               }
+                       
+               $this->mOldPage = $this->oldRev->getTitle();
+
+               $t = $wgLang->timeanddate( $this->oldRev->getTimestamp(), true );
+               $oldLink = $this->mOldPage->escapeLocalUrl( 'oldid=' . $this->mOldid );
+               $this->mOldtitle = "<a href='$oldLink'>" . htmlspecialchars( wfMsg( 'revisionasof', $t ) ) . '</a>';
+               
+               $this->mNewUser = $this->newRev->getUserText();
+               $this->mNewComment = $this->newRev->getComment();
+               $this->mNewtext = $this->newRev->getText();
+               
+               $this->mOldUser = $this->oldRev->getUserText();
+               $this->mOldComment = $this->oldRev->getComment();
+               $this->mOldtext = $this->oldRev->getText();
+
+               return true;
+       }
+}
+
+// A PHP diff engine for phpwiki. (Taken from phpwiki-1.3.3)
+//
+// Copyright (C) 2000, 2001 Geoffrey T. Dairiki <dairiki@dairiki.org>
+// You may copy this code freely under the conditions of the GPL.
+//
+
+define('USE_ASSERTS', function_exists('assert'));
+
+/**
+ * @todo document
+ * @access private
+ * @package MediaWiki 
+ * @subpackage DifferenceEngine
+ */
+class _DiffOp {
+       var $type;
+       var $orig;
+       var $closing;
+
+       function reverse() {
+               trigger_error('pure virtual', E_USER_ERROR);
+       }
+
+       function norig() {
+               return $this->orig ? sizeof($this->orig) : 0;
+       }
+
+       function nclosing() {
+               return $this->closing ? sizeof($this->closing) : 0;
+       }
+}
+
+/**
+ * @todo document
+ * @access private
+ * @package MediaWiki 
+ * @subpackage DifferenceEngine
+ */
+class _DiffOp_Copy extends _DiffOp {
+       var $type = 'copy';
+
+       function _DiffOp_Copy ($orig, $closing = false) {
+               if (!is_array($closing))
+                       $closing = $orig;
+               $this->orig = $orig;
+               $this->closing = $closing;
+       }
+
+       function reverse() {
+               return new _DiffOp_Copy($this->closing, $this->orig);
+       }
+}
+
+/**
+ * @todo document
+ * @access private
+ * @package MediaWiki 
+ * @subpackage DifferenceEngine
+ */
+class _DiffOp_Delete extends _DiffOp {
+       var $type = 'delete';
+
+       function _DiffOp_Delete ($lines) {
+               $this->orig = $lines;
+               $this->closing = false;
+       }
+
+       function reverse() {
+               return new _DiffOp_Add($this->orig);
+       }
+}
+
+/**
+ * @todo document
+ * @access private
+ * @package MediaWiki 
+ * @subpackage DifferenceEngine
+ */
+class _DiffOp_Add extends _DiffOp {
+       var $type = 'add';
+
+       function _DiffOp_Add ($lines) {
+               $this->closing = $lines;
+               $this->orig = false;
+       }
+
+       function reverse() {
+               return new _DiffOp_Delete($this->closing);
+       }
+}
+
+/**
+ * @todo document
+ * @access private
+ * @package MediaWiki 
+ * @subpackage DifferenceEngine
+ */
+class _DiffOp_Change extends _DiffOp {
+       var $type = 'change';
+
+       function _DiffOp_Change ($orig, $closing) {
+               $this->orig = $orig;
+               $this->closing = $closing;
+       }
+
+       function reverse() {
+               return new _DiffOp_Change($this->closing, $this->orig);
+       }
+}
+
+
+/**
+ * Class used internally by Diff to actually compute the diffs.
+ *
+ * The algorithm used here is mostly lifted from the perl module
+ * Algorithm::Diff (version 1.06) by Ned Konz, which is available at:
+ *      http://www.perl.com/CPAN/authors/id/N/NE/NEDKONZ/Algorithm-Diff-1.06.zip
+ *
+ * More ideas are taken from:
+ *      http://www.ics.uci.edu/~eppstein/161/960229.html
+ *
+ * Some ideas are (and a bit of code) are from from analyze.c, from GNU
+ * diffutils-2.7, which can be found at:
+ *      ftp://gnudist.gnu.org/pub/gnu/diffutils/diffutils-2.7.tar.gz
+ *
+ * closingly, some ideas (subdivision by NCHUNKS > 2, and some optimizations)
+ * are my own.
+ *
+ * @author Geoffrey T. Dairiki
+ * @access private
+ * @package MediaWiki 
+ * @subpackage DifferenceEngine
+ */
+class _DiffEngine
+{
+       function diff ($from_lines, $to_lines) {
+               $fname = '_DiffEngine::diff';
+               wfProfileIn( $fname );
+               
+               $n_from = sizeof($from_lines);
+               $n_to = sizeof($to_lines);
+
+               $this->xchanged = $this->ychanged = array();
+               $this->xv = $this->yv = array();
+               $this->xind = $this->yind = array();
+               unset($this->seq);
+               unset($this->in_seq);
+               unset($this->lcs);
+
+               // Skip leading common lines.
+               for ($skip = 0; $skip < $n_from && $skip < $n_to; $skip++) {
+                       if ($from_lines[$skip] != $to_lines[$skip])
+                               break;
+                       $this->xchanged[$skip] = $this->ychanged[$skip] = false;
+               }
+               // Skip trailing common lines.
+               $xi = $n_from; $yi = $n_to;
+               for ($endskip = 0; --$xi > $skip && --$yi > $skip; $endskip++) {
+                       if ($from_lines[$xi] != $to_lines[$yi])
+                               break;
+                       $this->xchanged[$xi] = $this->ychanged[$yi] = false;
+               }
+
+               // Ignore lines which do not exist in both files.
+               for ($xi = $skip; $xi < $n_from - $endskip; $xi++)
+                       $xhash[$from_lines[$xi]] = 1;
+               for ($yi = $skip; $yi < $n_to - $endskip; $yi++) {
+                       $line = $to_lines[$yi];
+                       if ( ($this->ychanged[$yi] = empty($xhash[$line])) )
+                               continue;
+                       $yhash[$line] = 1;
+                       $this->yv[] = $line;
+                       $this->yind[] = $yi;
+               }
+               for ($xi = $skip; $xi < $n_from - $endskip; $xi++) {
+                       $line = $from_lines[$xi];
+                       if ( ($this->xchanged[$xi] = empty($yhash[$line])) )
+                               continue;
+                       $this->xv[] = $line;
+                       $this->xind[] = $xi;
+               }
+
+               // Find the LCS.
+               $this->_compareseq(0, sizeof($this->xv), 0, sizeof($this->yv));
+
+               // Merge edits when possible
+               $this->_shift_boundaries($from_lines, $this->xchanged, $this->ychanged);
+               $this->_shift_boundaries($to_lines, $this->ychanged, $this->xchanged);
+
+               // Compute the edit operations.
+               $edits = array();
+               $xi = $yi = 0;
+               while ($xi < $n_from || $yi < $n_to) {
+                       USE_ASSERTS && assert($yi < $n_to || $this->xchanged[$xi]);
+                       USE_ASSERTS && assert($xi < $n_from || $this->ychanged[$yi]);
+
+                       // Skip matching "snake".
+                       $copy = array();
+                       while ( $xi < $n_from && $yi < $n_to
+                                       && !$this->xchanged[$xi] && !$this->ychanged[$yi]) {
+                               $copy[] = $from_lines[$xi++];
+                               ++$yi;
+                       }
+                       if ($copy)
+                               $edits[] = new _DiffOp_Copy($copy);
+
+                       // Find deletes & adds.
+                       $delete = array();
+                       while ($xi < $n_from && $this->xchanged[$xi])
+                               $delete[] = $from_lines[$xi++];
+
+                       $add = array();
+                       while ($yi < $n_to && $this->ychanged[$yi])
+                               $add[] = $to_lines[$yi++];
+
+                       if ($delete && $add)
+                               $edits[] = new _DiffOp_Change($delete, $add);
+                       elseif ($delete)
+                               $edits[] = new _DiffOp_Delete($delete);
+                       elseif ($add)
+                               $edits[] = new _DiffOp_Add($add);
+               }
+               wfProfileOut( $fname );
+               return $edits;
+       }
+
+
+       /* Divide the Largest Common Subsequence (LCS) of the sequences
+        * [XOFF, XLIM) and [YOFF, YLIM) into NCHUNKS approximately equally
+        * sized segments.
+        *
+        * Returns (LCS, PTS).  LCS is the length of the LCS. PTS is an
+        * array of NCHUNKS+1 (X, Y) indexes giving the diving points between
+        * sub sequences.  The first sub-sequence is contained in [X0, X1),
+        * [Y0, Y1), the second in [X1, X2), [Y1, Y2) and so on.  Note
+        * that (X0, Y0) == (XOFF, YOFF) and
+        * (X[NCHUNKS], Y[NCHUNKS]) == (XLIM, YLIM).
+        *
+        * This function assumes that the first lines of the specified portions
+        * of the two files do not match, and likewise that the last lines do not
+        * match.  The caller must trim matching lines from the beginning and end
+        * of the portions it is going to specify.
+        */
+       function _diag ($xoff, $xlim, $yoff, $ylim, $nchunks) {
+               $fname = '_DiffEngine::_diag';
+               wfProfileIn( $fname );
+               $flip = false;
+
+               if ($xlim - $xoff > $ylim - $yoff) {
+                       // Things seems faster (I'm not sure I understand why)
+                               // when the shortest sequence in X.
+                               $flip = true;
+                       list ($xoff, $xlim, $yoff, $ylim)
+                       = array( $yoff, $ylim, $xoff, $xlim);
+               }
+
+               if ($flip)
+                       for ($i = $ylim - 1; $i >= $yoff; $i--)
+                               $ymatches[$this->xv[$i]][] = $i;
+               else
+                       for ($i = $ylim - 1; $i >= $yoff; $i--)
+                               $ymatches[$this->yv[$i]][] = $i;
+       
+               $this->lcs = 0;
+               $this->seq[0]= $yoff - 1;
+               $this->in_seq = array();
+               $ymids[0] = array();
+       
+               $numer = $xlim - $xoff + $nchunks - 1;
+               $x = $xoff;
+               for ($chunk = 0; $chunk < $nchunks; $chunk++) {
+                       wfProfileIn( "$fname-chunk" );
+                       if ($chunk > 0)
+                               for ($i = 0; $i <= $this->lcs; $i++)
+                                       $ymids[$i][$chunk-1] = $this->seq[$i];
+       
+                       $x1 = $xoff + (int)(($numer + ($xlim-$xoff)*$chunk) / $nchunks);
+                       for ( ; $x < $x1; $x++) {
+                               $line = $flip ? $this->yv[$x] : $this->xv[$x];
+                                       if (empty($ymatches[$line]))
+                                               continue;
+                               $matches = $ymatches[$line];
+                               reset($matches);
+                               while (list ($junk, $y) = each($matches))
+                                       if (empty($this->in_seq[$y])) {
+                                               $k = $this->_lcs_pos($y);
+                                               USE_ASSERTS && assert($k > 0);
+                                               $ymids[$k] = $ymids[$k-1];
+                                               break;
+                                       }
+                               while (list ($junk, $y) = each($matches)) {
+                                       if ($y > $this->seq[$k-1]) {
+                                               USE_ASSERTS && assert($y < $this->seq[$k]);
+                                               // Optimization: this is a common case:
+                                               //      next match is just replacing previous match.
+                                               $this->in_seq[$this->seq[$k]] = false;
+                                               $this->seq[$k] = $y;
+                                               $this->in_seq[$y] = 1;
+                                       } else if (empty($this->in_seq[$y])) {
+                                               $k = $this->_lcs_pos($y);
+                                               USE_ASSERTS && assert($k > 0);
+                                               $ymids[$k] = $ymids[$k-1];
+                                       }
+                               }
+                       }
+                       wfProfileOut( "$fname-chunk" );
+               }
+       
+               $seps[] = $flip ? array($yoff, $xoff) : array($xoff, $yoff);
+               $ymid = $ymids[$this->lcs];
+               for ($n = 0; $n < $nchunks - 1; $n++) {
+                       $x1 = $xoff + (int)(($numer + ($xlim - $xoff) * $n) / $nchunks);
+                       $y1 = $ymid[$n] + 1;
+                       $seps[] = $flip ? array($y1, $x1) : array($x1, $y1);
+               }
+               $seps[] = $flip ? array($ylim, $xlim) : array($xlim, $ylim);
+       
+               wfProfileOut( $fname );
+               return array($this->lcs, $seps);
+       }
+
+       function _lcs_pos ($ypos) {
+               $fname = '_DiffEngine::_lcs_pos';
+               wfProfileIn( $fname );
+               
+               $end = $this->lcs;
+               if ($end == 0 || $ypos > $this->seq[$end]) {
+                       $this->seq[++$this->lcs] = $ypos;
+                       $this->in_seq[$ypos] = 1;
+                       wfProfileOut( $fname );
+                       return $this->lcs;
+               }
+
+               $beg = 1;
+               while ($beg < $end) {
+                       $mid = (int)(($beg + $end) / 2);
+                       if ( $ypos > $this->seq[$mid] )
+                               $beg = $mid + 1;
+                       else
+                               $end = $mid;
+               }
+       
+               USE_ASSERTS && assert($ypos != $this->seq[$end]);
+       
+               $this->in_seq[$this->seq[$end]] = false;
+               $this->seq[$end] = $ypos;
+               $this->in_seq[$ypos] = 1;
+               wfProfileOut( $fname );
+               return $end;
+       }
+
+       /* Find LCS of two sequences.
+        *
+        * The results are recorded in the vectors $this->{x,y}changed[], by
+        * storing a 1 in the element for each line that is an insertion
+        * or deletion (ie. is not in the LCS).
+        *
+        * The subsequence of file 0 is [XOFF, XLIM) and likewise for file 1.
+        *
+        * Note that XLIM, YLIM are exclusive bounds.
+        * All line numbers are origin-0 and discarded lines are not counted.
+        */
+       function _compareseq ($xoff, $xlim, $yoff, $ylim) {
+               $fname = '_DiffEngine::_compareseq';
+               wfProfileIn( $fname );
+               
+               // Slide down the bottom initial diagonal.
+               while ($xoff < $xlim && $yoff < $ylim
+                          && $this->xv[$xoff] == $this->yv[$yoff]) {
+                       ++$xoff;
+                       ++$yoff;
+               }
+
+               // Slide up the top initial diagonal.
+               while ($xlim > $xoff && $ylim > $yoff
+                          && $this->xv[$xlim - 1] == $this->yv[$ylim - 1]) {
+                       --$xlim;
+                       --$ylim;
+               }
+
+               if ($xoff == $xlim || $yoff == $ylim)
+                       $lcs = 0;
+               else {
+                       // This is ad hoc but seems to work well.
+                       //$nchunks = sqrt(min($xlim - $xoff, $ylim - $yoff) / 2.5);
+                       //$nchunks = max(2,min(8,(int)$nchunks));
+                       $nchunks = min(7, $xlim - $xoff, $ylim - $yoff) + 1;
+                       list ($lcs, $seps)
+                       = $this->_diag($xoff,$xlim,$yoff, $ylim,$nchunks);
+               }
+
+               if ($lcs == 0) {
+                       // X and Y sequences have no common subsequence:
+                       // mark all changed.
+                       while ($yoff < $ylim)
+                               $this->ychanged[$this->yind[$yoff++]] = 1;
+                       while ($xoff < $xlim)
+                               $this->xchanged[$this->xind[$xoff++]] = 1;
+               } else {
+                       // Use the partitions to split this problem into subproblems.
+                       reset($seps);
+                       $pt1 = $seps[0];
+                       while ($pt2 = next($seps)) {
+                               $this->_compareseq ($pt1[0], $pt2[0], $pt1[1], $pt2[1]);
+                               $pt1 = $pt2;
+                       }
+               }
+               wfProfileOut( $fname );
+       }
+
+       /* Adjust inserts/deletes of identical lines to join changes
+        * as much as possible.
+        *
+        * We do something when a run of changed lines include a
+        * line at one end and has an excluded, identical line at the other.
+        * We are free to choose which identical line is included.
+        * `compareseq' usually chooses the one at the beginning,
+        * but usually it is cleaner to consider the following identical line
+        * to be the "change".
+        *
+        * This is extracted verbatim from analyze.c (GNU diffutils-2.7).
+        */
+       function _shift_boundaries ($lines, &$changed, $other_changed) {
+               $fname = '_DiffEngine::_shift_boundaries';
+               wfProfileIn( $fname );
+               $i = 0;
+               $j = 0;
+       
+               USE_ASSERTS && assert('sizeof($lines) == sizeof($changed)');
+               $len = sizeof($lines);
+               $other_len = sizeof($other_changed);
+       
+               while (1) {
+                       /*
+                        * Scan forwards to find beginning of another run of changes.
+                        * Also keep track of the corresponding point in the other file.
+                        *
+                        * Throughout this code, $i and $j are adjusted together so that
+                        * the first $i elements of $changed and the first $j elements
+                        * of $other_changed both contain the same number of zeros
+                        * (unchanged lines).
+                        * Furthermore, $j is always kept so that $j == $other_len or
+                        * $other_changed[$j] == false.
+                        */
+                       while ($j < $other_len && $other_changed[$j])
+                               $j++;
+       
+                       while ($i < $len && ! $changed[$i]) {
+                               USE_ASSERTS && assert('$j < $other_len && ! $other_changed[$j]');
+                               $i++; $j++;
+                               while ($j < $other_len && $other_changed[$j])
+                                       $j++;
+                       }
+                       
+                       if ($i == $len)
+                               break;
+                       
+                       $start = $i;
+                       
+                       // Find the end of this run of changes.
+                       while (++$i < $len && $changed[$i])
+                               continue;
+                       
+                       do {
+                               /*
+                                * Record the length of this run of changes, so that
+                                * we can later determine whether the run has grown.
+                                */
+                               $runlength = $i - $start;
+                               
+                               /*
+                                * Move the changed region back, so long as the
+                                * previous unchanged line matches the last changed one.
+                                * This merges with previous changed regions.
+                                */
+                               while ($start > 0 && $lines[$start - 1] == $lines[$i - 1]) {
+                                       $changed[--$start] = 1;
+                                       $changed[--$i] = false;
+                                       while ($start > 0 && $changed[$start - 1])
+                                               $start--;
+                                       USE_ASSERTS && assert('$j > 0');
+                                       while ($other_changed[--$j])
+                                               continue;
+                                       USE_ASSERTS && assert('$j >= 0 && !$other_changed[$j]');
+                               }
+       
+                               /*
+                                * Set CORRESPONDING to the end of the changed run, at the last
+                                * point where it corresponds to a changed run in the other file.
+                                * CORRESPONDING == LEN means no such point has been found.
+                                */
+                               $corresponding = $j < $other_len ? $i : $len;
+               
+                               /*
+                                * Move the changed region forward, so long as the
+                                * first changed line matches the following unchanged one.
+                                * This merges with following changed regions.
+                                * Do this second, so that if there are no merges,
+                                * the changed region is moved forward as far as possible.
+                                */
+                               while ($i < $len && $lines[$start] == $lines[$i]) {
+                                       $changed[$start++] = false;
+                                       $changed[$i++] = 1;
+                                       while ($i < $len && $changed[$i])
+                                               $i++;
+               
+                                       USE_ASSERTS && assert('$j < $other_len && ! $other_changed[$j]');
+                                       $j++;
+                                       if ($j < $other_len && $other_changed[$j]) {
+                                               $corresponding = $i;
+                                               while ($j < $other_len && $other_changed[$j])
+                                                       $j++;
+                                       }
+                               }
+                       } while ($runlength != $i - $start);
+       
+                       /*
+                        * If possible, move the fully-merged run of changes
+                        * back to a corresponding run in the other file.
+                        */
+                       while ($corresponding < $i) {
+                               $changed[--$start] = 1;
+                               $changed[--$i] = 0;
+                               USE_ASSERTS && assert('$j > 0');
+                               while ($other_changed[--$j])
+                                       continue;
+                               USE_ASSERTS && assert('$j >= 0 && !$other_changed[$j]');
+                       }
+               }
+               wfProfileOut( $fname );
+       }
+}
+
+/**
+ * Class representing a 'diff' between two sequences of strings.
+ * @todo document
+ * @access private
+ * @package MediaWiki 
+ * @subpackage DifferenceEngine
+ */
+class Diff
+{
+       var $edits;
+
+       /**
+        * Constructor.
+        * Computes diff between sequences of strings.
+        *
+        * @param $from_lines array An array of strings.
+        *                (Typically these are lines from a file.)
+        * @param $to_lines array An array of strings.
+        */
+       function Diff($from_lines, $to_lines) {
+               $eng = new _DiffEngine;
+               $this->edits = $eng->diff($from_lines, $to_lines);
+               //$this->_check($from_lines, $to_lines);
+       }
+
+       /**
+        * Compute reversed Diff.
+        *
+        * SYNOPSIS:
+        *
+        *      $diff = new Diff($lines1, $lines2);
+        *      $rev = $diff->reverse();
+        * @return object A Diff object representing the inverse of the
+        *                                original diff.
+        */
+       function reverse () {
+               $rev = $this;
+               $rev->edits = array();
+               foreach ($this->edits as $edit) {
+                       $rev->edits[] = $edit->reverse();
+               }
+               return $rev;
+       }
+
+       /**
+        * Check for empty diff.
+        *
+        * @return bool True iff two sequences were identical.
+        */
+       function isEmpty () {
+               foreach ($this->edits as $edit) {
+                       if ($edit->type != 'copy')
+                               return false;
+               }
+               return true;
+       }
+
+       /**
+        * Compute the length of the Longest Common Subsequence (LCS).
+        *
+        * This is mostly for diagnostic purposed.
+        *
+        * @return int The length of the LCS.
+        */
+       function lcs () {
+               $lcs = 0;
+               foreach ($this->edits as $edit) {
+                       if ($edit->type == 'copy')
+                               $lcs += sizeof($edit->orig);
+               }
+               return $lcs;
+       }
+
+       /**
+        * Get the original set of lines.
+        *
+        * This reconstructs the $from_lines parameter passed to the
+        * constructor.
+        *
+        * @return array The original sequence of strings.
+        */
+       function orig() {
+               $lines = array();
+
+               foreach ($this->edits as $edit) {
+                       if ($edit->orig)
+                               array_splice($lines, sizeof($lines), 0, $edit->orig);
+               }
+               return $lines;
+       }
+
+       /**
+        * Get the closing set of lines.
+        *
+        * This reconstructs the $to_lines parameter passed to the
+        * constructor.
+        *
+        * @return array The sequence of strings.
+        */
+       function closing() {
+               $lines = array();
+
+               foreach ($this->edits as $edit) {
+                       if ($edit->closing)
+                               array_splice($lines, sizeof($lines), 0, $edit->closing);
+               }
+               return $lines;
+       }
+
+       /**
+        * Check a Diff for validity.
+        *
+        * This is here only for debugging purposes.
+        */
+       function _check ($from_lines, $to_lines) {
+               $fname = 'Diff::_check';
+               wfProfileIn( $fname );
+               if (serialize($from_lines) != serialize($this->orig()))
+                       trigger_error("Reconstructed original doesn't match", E_USER_ERROR);
+               if (serialize($to_lines) != serialize($this->closing()))
+                       trigger_error("Reconstructed closing doesn't match", E_USER_ERROR);
+
+               $rev = $this->reverse();
+               if (serialize($to_lines) != serialize($rev->orig()))
+                       trigger_error("Reversed original doesn't match", E_USER_ERROR);
+               if (serialize($from_lines) != serialize($rev->closing()))
+                       trigger_error("Reversed closing doesn't match", E_USER_ERROR);
+
+
+               $prevtype = 'none';
+               foreach ($this->edits as $edit) {
+                       if ( $prevtype == $edit->type )
+                               trigger_error("Edit sequence is non-optimal", E_USER_ERROR);
+                       $prevtype = $edit->type;
+               }
+
+               $lcs = $this->lcs();
+               trigger_error('Diff okay: LCS = '.$lcs, E_USER_NOTICE);
+               wfProfileOut( $fname );
+       }
+}
+
+/**
+ * FIXME: bad name.
+ * @todo document
+ * @access private
+ * @package MediaWiki 
+ * @subpackage DifferenceEngine
+ */
+class MappedDiff extends Diff
+{
+       /**
+        * Constructor.
+        *
+        * Computes diff between sequences of strings.
+        *
+        * This can be used to compute things like
+        * case-insensitve diffs, or diffs which ignore
+        * changes in white-space.
+        *
+        * @param $from_lines array An array of strings.
+        *      (Typically these are lines from a file.)
+        *
+        * @param $to_lines array An array of strings.
+        *
+        * @param $mapped_from_lines array This array should
+        *      have the same size number of elements as $from_lines.
+        *      The elements in $mapped_from_lines and
+        *      $mapped_to_lines are what is actually compared
+        *      when computing the diff.
+        *
+        * @param $mapped_to_lines array This array should
+        *      have the same number of elements as $to_lines.
+        */
+       function MappedDiff($from_lines, $to_lines,
+                                               $mapped_from_lines, $mapped_to_lines) {
+               $fname = 'MappedDiff::MappedDiff';
+               wfProfileIn( $fname );
+               
+               assert(sizeof($from_lines) == sizeof($mapped_from_lines));
+               assert(sizeof($to_lines) == sizeof($mapped_to_lines));
+
+               $this->Diff($mapped_from_lines, $mapped_to_lines);
+
+               $xi = $yi = 0;
+               for ($i = 0; $i < sizeof($this->edits); $i++) {
+                       $orig = &$this->edits[$i]->orig;
+                       if (is_array($orig)) {
+                               $orig = array_slice($from_lines, $xi, sizeof($orig));
+                               $xi += sizeof($orig);
+                       }
+
+                       $closing = &$this->edits[$i]->closing;
+                       if (is_array($closing)) {
+                               $closing = array_slice($to_lines, $yi, sizeof($closing));
+                               $yi += sizeof($closing);
+                       }
+               }
+               wfProfileOut( $fname );
+       }
+}
+
+/**
+ * A class to format Diffs
+ *
+ * This class formats the diff in classic diff format.
+ * It is intended that this class be customized via inheritance,
+ * to obtain fancier outputs.
+ * @todo document
+ * @access private
+ * @package MediaWiki 
+ * @subpackage DifferenceEngine
+ */
+class DiffFormatter
+{
+       /**
+        * Number of leading context "lines" to preserve.
+        *
+        * This should be left at zero for this class, but subclasses
+        * may want to set this to other values.
+        */
+       var $leading_context_lines = 0;
+
+       /**
+        * Number of trailing context "lines" to preserve.
+        *
+        * This should be left at zero for this class, but subclasses
+        * may want to set this to other values.
+        */
+       var $trailing_context_lines = 0;
+
+       /**
+        * Format a diff.
+        *
+        * @param $diff object A Diff object.
+        * @return string The formatted output.
+        */
+       function format($diff) {
+               $fname = 'DiffFormatter::format';
+               wfProfileIn( $fname );
+
+               $xi = $yi = 1;
+               $block = false;
+               $context = array();
+
+               $nlead = $this->leading_context_lines;
+               $ntrail = $this->trailing_context_lines;
+
+               $this->_start_diff();
+
+               foreach ($diff->edits as $edit) {
+                       if ($edit->type == 'copy') {
+                               if (is_array($block)) {
+                                       if (sizeof($edit->orig) <= $nlead + $ntrail) {
+                                               $block[] = $edit;
+                                       }
+                                       else{
+                                               if ($ntrail) {
+                                                       $context = array_slice($edit->orig, 0, $ntrail);
+                                                       $block[] = new _DiffOp_Copy($context);
+                                               }
+                                               $this->_block($x0, $ntrail + $xi - $x0,
+                                                                         $y0, $ntrail + $yi - $y0,
+                                                                         $block);
+                                               $block = false;
+                                       }
+                               }
+                               $context = $edit->orig;
+                       }
+                       else {
+                               if (! is_array($block)) {
+                                       $context = array_slice($context, sizeof($context) - $nlead);
+                                       $x0 = $xi - sizeof($context);
+                                       $y0 = $yi - sizeof($context);
+                                       $block = array();
+                                       if ($context)
+                                               $block[] = new _DiffOp_Copy($context);
+                               }
+                               $block[] = $edit;
+                       }
+
+                       if ($edit->orig)
+                               $xi += sizeof($edit->orig);
+                       if ($edit->closing)
+                               $yi += sizeof($edit->closing);
+               }
+
+               if (is_array($block))
+                       $this->_block($x0, $xi - $x0,
+                                                 $y0, $yi - $y0,
+                                                 $block);
+
+               $end = $this->_end_diff();
+               wfProfileOut( $fname );
+               return $end;
+       }
+
+       function _block($xbeg, $xlen, $ybeg, $ylen, &$edits) {
+               $fname = 'DiffFormatter::_block';
+               wfProfileIn( $fname );
+               $this->_start_block($this->_block_header($xbeg, $xlen, $ybeg, $ylen));
+               foreach ($edits as $edit) {
+                       if ($edit->type == 'copy')
+                               $this->_context($edit->orig);
+                       elseif ($edit->type == 'add')
+                               $this->_added($edit->closing);
+                       elseif ($edit->type == 'delete')
+                               $this->_deleted($edit->orig);
+                       elseif ($edit->type == 'change')
+                               $this->_changed($edit->orig, $edit->closing);
+                       else
+                               trigger_error('Unknown edit type', E_USER_ERROR);
+               }
+               $this->_end_block();
+               wfProfileOut( $fname );
+       }
+
+       function _start_diff() {
+               ob_start();
+       }
+
+       function _end_diff() {
+               $val = ob_get_contents();
+               ob_end_clean();
+               return $val;
+       }
+
+       function _block_header($xbeg, $xlen, $ybeg, $ylen) {
+               if ($xlen > 1)
+                       $xbeg .= "," . ($xbeg + $xlen - 1);
+               if ($ylen > 1)
+                       $ybeg .= "," . ($ybeg + $ylen - 1);
+
+               return $xbeg . ($xlen ? ($ylen ? 'c' : 'd') : 'a') . $ybeg;
+       }
+
+       function _start_block($header) {
+               echo $header;
+       }
+
+       function _end_block() {
+       }
+
+       function _lines($lines, $prefix = ' ') {
+               foreach ($lines as $line)
+                       echo "$prefix $line\n";
+       }
+
+       function _context($lines) {
+               $this->_lines($lines);
+       }
+
+       function _added($lines) {
+               $this->_lines($lines, '>');
+       }
+       function _deleted($lines) {
+               $this->_lines($lines, '<');
+       }
+
+       function _changed($orig, $closing) {
+               $this->_deleted($orig);
+               echo "---\n";
+               $this->_added($closing);
+       }
+}
+
+
+/**
+ *     Additions by Axel Boldt follow, partly taken from diff.php, phpwiki-1.3.3
+ *
+ */
+
+define('NBSP', '&#160;');                      // iso-8859-x non-breaking space.
+
+/**
+ * @todo document
+ * @access private
+ * @package MediaWiki 
+ * @subpackage DifferenceEngine
+ */
+class _HWLDF_WordAccumulator {
+       function _HWLDF_WordAccumulator () {
+               $this->_lines = array();
+               $this->_line = '';
+               $this->_group = '';
+               $this->_tag = '';
+       }
+
+       function _flushGroup ($new_tag) {
+               if ($this->_group !== '') {
+                       if ($this->_tag == 'mark')
+                               $this->_line .= '<span class="diffchange">' .
+                                       htmlspecialchars ( $this->_group ) . '</span>';
+                       else
+                               $this->_line .= htmlspecialchars ( $this->_group );
+               }
+               $this->_group = '';
+               $this->_tag = $new_tag;
+       }
+
+       function _flushLine ($new_tag) {
+               $this->_flushGroup($new_tag);
+               if ($this->_line != '')
+                       array_push ( $this->_lines, $this->_line );
+               else
+                       # make empty lines visible by inserting an NBSP
+                       array_push ( $this->_lines, NBSP );
+               $this->_line = '';
+       }
+
+       function addWords ($words, $tag = '') {
+               if ($tag != $this->_tag)
+                       $this->_flushGroup($tag);
+
+               foreach ($words as $word) {
+                       // new-line should only come as first char of word.
+                       if ($word == '')
+                               continue;
+                       if ($word[0] == "\n") {
+                               $this->_flushLine($tag);
+                               $word = substr($word, 1);
+                       }
+                       assert(!strstr($word, "\n"));
+                       $this->_group .= $word;
+               }
+       }
+
+       function getLines() {
+               $this->_flushLine('~done');
+               return $this->_lines;
+       }
+}
+
+/**
+ * @todo document
+ * @access private
+ * @package MediaWiki 
+ * @subpackage DifferenceEngine
+ */
+class WordLevelDiff extends MappedDiff
+{
+       function WordLevelDiff ($orig_lines, $closing_lines) {
+               $fname = 'WordLevelDiff::WordLevelDiff';
+               wfProfileIn( $fname );
+               
+               list ($orig_words, $orig_stripped) = $this->_split($orig_lines);
+               list ($closing_words, $closing_stripped) = $this->_split($closing_lines);
+
+
+               $this->MappedDiff($orig_words, $closing_words,
+                                                 $orig_stripped, $closing_stripped);
+               wfProfileOut( $fname );
+       }
+
+       function _split($lines) {
+               $fname = 'WordLevelDiff::_split';
+               wfProfileIn( $fname );
+               if (!preg_match_all('/ ( [^\S\n]+ | [0-9_A-Za-z\x80-\xff]+ | . ) (?: (?!< \n) [^\S\n])? /xs',
+                                                       implode("\n", $lines),
+                                                       $m)) {
+                       wfProfileOut( $fname );
+                       return array(array(''), array(''));
+               }
+               wfProfileOut( $fname );
+               return array($m[0], $m[1]);
+       }
+
+       function orig () {
+               $fname = 'WordLevelDiff::orig';
+               wfProfileIn( $fname );
+               $orig = new _HWLDF_WordAccumulator;
+
+               foreach ($this->edits as $edit) {
+                       if ($edit->type == 'copy')
+                               $orig->addWords($edit->orig);
+                       elseif ($edit->orig)
+                               $orig->addWords($edit->orig, 'mark');
+               }
+               $lines = $orig->getLines();
+               wfProfileOut( $fname );
+               return $lines;
+       }
+
+       function closing () {
+               $fname = 'WordLevelDiff::closing';
+               wfProfileIn( $fname );
+               $closing = new _HWLDF_WordAccumulator;
+
+               foreach ($this->edits as $edit) {
+                       if ($edit->type == 'copy')
+                               $closing->addWords($edit->closing);
+                       elseif ($edit->closing)
+                               $closing->addWords($edit->closing, 'mark');
+               }
+               $lines = $closing->getLines();
+               wfProfileOut( $fname );
+               return $lines;
+       }
+}
+
+/**
+ *     Wikipedia Table style diff formatter.
+ * @todo document
+ * @access private
+ * @package MediaWiki 
+ * @subpackage DifferenceEngine
+ */
+class TableDiffFormatter extends DiffFormatter
+{
+       function TableDiffFormatter() {
+               $this->leading_context_lines = 2;
+               $this->trailing_context_lines = 2;
+       }
+
+       function _block_header( $xbeg, $xlen, $ybeg, $ylen ) {
+               $l1 = wfMsg( 'lineno', $xbeg );
+               $l2 = wfMsg( 'lineno', $ybeg );
+
+               $r = '<tr><td colspan="2" align="left"><strong>'.$l1."</strong></td>\n" .
+                 '<td colspan="2" align="left"><strong>'.$l2."</strong></td></tr>\n";
+               return $r;
+       }
+
+       function _start_block( $header ) {
+               global $wgOut;
+               echo $header;
+       }
+
+       function _end_block() {
+       }
+
+       function _lines( $lines, $prefix=' ', $color='white' ) {
+       }
+
+       # HTML-escape parameter before calling this
+       function addedLine( $line ) {
+               return "<td>+</td><td class='diff-addedline'>{$line}</td>";
+       }
+
+       # HTML-escape parameter before calling this
+       function deletedLine( $line ) {
+               return "<td>-</td><td class='diff-deletedline'>{$line}</td>";
+       }
+
+       # HTML-escape parameter before calling this
+       function contextLine( $line ) {
+               return "<td> </td><td class='diff-context'>{$line}</td>";
+       }
+
+       function emptyLine() {
+               return '<td colspan="2">&nbsp;</td>';
+       }
+
+       function _added( $lines ) {
+               foreach ($lines as $line) {
+                       echo '<tr>' . $this->emptyLine() .
+                               $this->addedLine( htmlspecialchars ( $line ) ) . "</tr>\n";
+               }
+       }
+
+       function _deleted($lines) {
+               foreach ($lines as $line) {
+                       echo '<tr>' . $this->deletedLine( htmlspecialchars ( $line ) ) .
+                         $this->emptyLine() . "</tr>\n";
+               }
+       }
+
+       function _context( $lines ) {
+               foreach ($lines as $line) {
+                       echo '<tr>' .
+                               $this->contextLine( htmlspecialchars ( $line ) ) .
+                               $this->contextLine( htmlspecialchars ( $line ) ) . "</tr>\n";
+               }
+       }
+
+       function _changed( $orig, $closing ) {
+               $fname = 'TableDiffFormatter::_changed';
+               wfProfileIn( $fname );
+               
+               $diff = new WordLevelDiff( $orig, $closing );
+               $del = $diff->orig();
+               $add = $diff->closing();
+
+               # Notice that WordLevelDiff returns HTML-escaped output.
+               # Hence, we will be calling addedLine/deletedLine without HTML-escaping.
+
+               while ( $line = array_shift( $del ) ) {
+                       $aline = array_shift( $add );
+                       echo '<tr>' . $this->deletedLine( $line ) .
+                               $this->addedLine( $aline ) . "</tr>\n";
+               }
+               foreach ($add as $line) {       # If any leftovers
+                       echo '<tr>' . $this->emptyLine() .
+                               $this->addedLine( $line ) . "</tr>\n";
+               }
+               wfProfileOut( $fname );
+       }
+}
+
+?>
diff --git a/includes/EditPage.php b/includes/EditPage.php
new file mode 100644 (file)
index 0000000..675255b
--- /dev/null
@@ -0,0 +1,1296 @@
+<?php
+/**
+ * Contain the EditPage class
+ * @package MediaWiki
+ */
+
+/**
+ * Splitting edit page/HTML interface from Article...
+ * The actual database and text munging is still in Article,
+ * but it should get easier to call those from alternate
+ * interfaces.
+ *
+ * @package MediaWiki
+ */
+
+class EditPage {
+       var $mArticle;
+       var $mTitle;
+       var $mMetaData = '';
+       
+       # Form values
+       var $save = false, $preview = false, $diff = false;
+       var $minoredit = false, $watchthis = false;
+       var $textbox1 = '', $textbox2 = '', $summary = '';
+       var $edittime = '', $section = '';
+       var $oldid = 0;
+       
+       /**
+        * @todo document
+        * @param $article
+        */
+       function EditPage( $article ) {
+               $this->mArticle =& $article;
+               global $wgTitle;
+               $this->mTitle =& $wgTitle;
+       }
+
+       /**
+        * This is the function that extracts metadata from the article body on the first view.
+        * To turn the feature on, set $wgUseMetadataEdit = true ; in LocalSettings
+        *  and set $wgMetadataWhitelist to the *full* title of the template whitelist
+        */
+       function extractMetaDataFromArticle () {
+               global $wgUseMetadataEdit , $wgMetadataWhitelist , $wgLang ;
+               $this->mMetaData = '' ;
+               if ( !$wgUseMetadataEdit ) return ;
+               if ( $wgMetadataWhitelist == '' ) return ;
+               $s = '' ;
+               $t = $this->mArticle->getContent ( true ) ;
+
+               # MISSING : <nowiki> filtering
+
+               # Categories and language links
+               $t = explode ( "\n" , $t ) ;
+               $catlow = strtolower ( $wgLang->getNsText ( NS_CATEGORY ) ) ;
+               $cat = $ll = array() ;
+               foreach ( $t AS $key => $x )
+               {
+                       $y = trim ( strtolower ( $x ) ) ;
+                       while ( substr ( $y , 0 , 2 ) == '[[' )
+                       {
+                               $y = explode ( ']]' , trim ( $x ) ) ;
+                               $first = array_shift ( $y ) ;
+                               $first = explode ( ':' , $first ) ;
+                               $ns = array_shift ( $first ) ;
+                               $ns = trim ( str_replace ( '[' , '' , $ns ) ) ;
+                               if ( strlen ( $ns ) == 2 OR strtolower ( $ns ) == $catlow )
+                               {
+                                       $add = '[[' . $ns . ':' . implode ( ':' , $first ) . ']]' ;
+                                       if ( strtolower ( $ns ) == $catlow ) $cat[] = $add ;
+                                       else $ll[] = $add ;
+                                       $x = implode ( ']]' , $y ) ;
+                                       $t[$key] = $x ;
+                                       $y = trim ( strtolower ( $x ) ) ;
+                               }
+                       }
+               }
+               if ( count ( $cat ) ) $s .= implode ( ' ' , $cat ) . "\n" ;
+               if ( count ( $ll ) ) $s .= implode ( ' ' , $ll ) . "\n" ;
+               $t = implode ( "\n" , $t ) ;
+
+               # Load whitelist
+               $sat = array () ; # stand-alone-templates; must be lowercase
+               $wl_title = Title::newFromText ( $wgMetadataWhitelist ) ;
+               $wl_article = new Article ( $wl_title ) ;
+               $wl = explode ( "\n" , $wl_article->getContent(true) ) ;
+               foreach ( $wl AS $x )
+               {
+                       $isentry = false ;
+                       $x = trim ( $x ) ;
+                       while ( substr ( $x , 0 , 1 ) == '*' )
+                       {
+                               $isentry = true ;
+                               $x = trim ( substr ( $x , 1 ) ) ;
+                       }
+                       if ( $isentry )
+                       {
+                               $sat[] = strtolower ( $x ) ;
+                       }
+                          
+               }
+
+               # Templates, but only some
+               $t = explode ( '{{' , $t ) ;
+               $tl = array () ;
+               foreach ( $t AS $key => $x )
+               {
+                       $y = explode ( '}}' , $x , 2 ) ;
+                       if ( count ( $y ) == 2 )
+                       {
+                               $z = $y[0] ;
+                               $z = explode ( '|' , $z ) ;
+                               $tn = array_shift ( $z ) ;
+                               if ( in_array ( strtolower ( $tn ) , $sat ) )
+                               {
+                                       $tl[] = '{{' . $y[0] . '}}' ;
+                                       $t[$key] = $y[1] ;
+                                       $y = explode ( '}}' , $y[1] , 2 ) ;
+                               }
+                               else $t[$key] = '{{' . $x ;
+                       }
+                       else if ( $key != 0 ) $t[$key] = '{{' . $x ;
+                       else $t[$key] = $x ;
+               }
+               if ( count ( $tl ) ) $s .= implode ( ' ' , $tl ) ;
+               $t = implode ( '' , $t ) ;
+
+               $t = str_replace ( "\n\n\n" , "\n" , $t ) ;
+               $this->mArticle->mContent = $t ;
+               $this->mMetaData = $s ;
+       }
+
+       /**
+        * This is the function that gets called for "action=edit".
+        */
+       function edit() {
+               global $wgOut, $wgUser, $wgRequest;
+               // this is not an article
+               $wgOut->setArticleFlag(false);
+
+               $this->importFormData( $wgRequest );
+               
+               if( $this->live ) {
+                       $this->livePreview();
+                       return;
+               }
+
+               if ( ! $this->mTitle->userCanEdit() ) {
+                       $wgOut->readOnlyPage( $this->mArticle->getContent( true ), true );
+                       return;
+               }
+               if ( !$this->preview && !$this->diff && $wgUser->isBlockedFrom( $this->mTitle, !$this->save ) ) {
+                       # When previewing, don't check blocked state - will get caught at save time.
+                       # Also, check when starting edition is done against slave to improve performance.
+                       $this->blockedIPpage();
+                       return;
+               }
+               if ( !$wgUser->isAllowed('edit') ) {
+                       if ( $wgUser->isAnon() ) {
+                               $this->userNotLoggedInPage();
+                               return;
+                       } else {
+                               $wgOut->readOnlyPage( $this->mArticle->getContent( true ), true );
+                               return;
+                       }
+               }
+               if ( wfReadOnly() ) {
+                       if( $this->save || $this->preview ) {
+                               $this->editForm( 'preview' );
+                       } else if ( $this->diff ) {
+                               $this->editForm( 'diff' );
+                       } else {
+                               $wgOut->readOnlyPage( $this->mArticle->getContent( true ) );
+                       }
+                       return;
+               }
+               if ( $this->save ) {
+                       $this->editForm( 'save' );
+               } else if ( $this->preview ) {
+                       $this->editForm( 'preview' );
+               } else if ( $this->diff ) {
+                       $this->editForm( 'diff' );
+               } else { # First time through
+                       if( $this->previewOnOpen() ) {
+                               $this->editForm( 'preview', true );
+                       } else {
+                               $this->extractMetaDataFromArticle () ;
+                               $this->editForm( 'initial', true );
+                       }
+               }
+       }
+       
+       /**
+        * Return true if this page should be previewed when the edit form
+        * is initially opened.
+        * @return bool
+        * @access private
+        */
+       function previewOnOpen() {
+               global $wgUser;
+               return $wgUser->getOption( 'previewonfirst' ) ||
+                       ( $this->mTitle->getNamespace() == NS_CATEGORY &&
+                               !$this->mTitle->exists() );
+       }
+
+       /**
+        * @todo document
+        */
+       function importFormData( &$request ) {
+               if( $request->wasPosted() ) {
+                       # These fields need to be checked for encoding.
+                       # Also remove trailing whitespace, but don't remove _initial_
+                       # whitespace from the text boxes. This may be significant formatting.
+                       $this->textbox1 = $this->safeUnicodeInput( $request, 'wpTextbox1' );
+                       $this->textbox2 = $this->safeUnicodeInput( $request, 'wpTextbox2' );
+                       $this->mMetaData = rtrim( $request->getText( 'metadata'   ) );
+                       $this->summary   =        $request->getText( 'wpSummary'  );
+       
+                       $this->edittime = $request->getVal( 'wpEdittime' );
+                       if( is_null( $this->edittime ) ) {
+                               # If the form is incomplete, force to preview.
+                               $this->preview  = true;
+                       } else {
+                               if( $this->tokenOk( $request ) ) {
+                                       # Some browsers will not report any submit button
+                                       # if the user hits enter in the comment box.
+                                       # The unmarked state will be assumed to be a save,
+                                       # if the form seems otherwise complete.
+                                       $this->preview = $request->getCheck( 'wpPreview' );
+                                       $this->diff = $request->getCheck( 'wpDiff' );
+                               } else {
+                                       # Page might be a hack attempt posted from
+                                       # an external site. Preview instead of saving.
+                                       $this->preview = true;
+                               }
+                       }
+                       $this->save    = ! ( $this->preview OR $this->diff );
+                       if( !preg_match( '/^\d{14}$/', $this->edittime )) {
+                               $this->edittime = null;
+                       }
+       
+                       $this->minoredit = $request->getCheck( 'wpMinoredit' );
+                       $this->watchthis = $request->getCheck( 'wpWatchthis' );
+               } else {
+                       # Not a posted form? Start with nothing.
+                       $this->textbox1  = '';
+                       $this->textbox2  = '';
+                       $this->mMetaData = '';
+                       $this->summary   = '';
+                       $this->edittime  = '';
+                       $this->preview   = false;
+                       $this->save      = false;
+                       $this->diff      = false;
+                       $this->minoredit = false;
+                       $this->watchthis = false;
+               }
+
+               $this->oldid = $request->getInt( 'oldid' );
+
+               # Section edit can come from either the form or a link
+               $this->section = $request->getVal( 'wpSection', $request->getVal( 'section' ) );
+               
+               $this->live = $request->getCheck( 'live' );
+       }
+
+       /**
+        * Make sure the form isn't faking a user's credentials.
+        *
+        * @param WebRequest $request
+        * @return bool
+        * @access private
+        */
+       function tokenOk( &$request ) {
+               global $wgUser;
+               if( $wgUser->isAnon() ) {
+                       # Anonymous users may not have a session
+                       # open. Don't tokenize.
+                       return true;
+               } else {
+                       return $wgUser->matchEditToken( $request->getVal( 'wpEditToken' ) );
+               }
+       }
+       
+       function submit() {
+               $this->edit();
+       }
+
+       /**
+        * The edit form is self-submitting, so that when things like
+        * preview and edit conflicts occur, we get the same form back
+        * with the extra stuff added.  Only when the final submission
+        * is made and all is well do we actually save and redirect to
+        * the newly-edited page.
+        *
+        * @param string $formtype Type of form either : save, initial, diff or preview
+        * @param bool $firsttime True to load form data from db
+        */
+       function editForm( $formtype, $firsttime = false ) {
+               global $wgOut, $wgUser;
+               global $wgLang, $wgContLang, $wgParser, $wgTitle;
+               global $wgAllowAnonymousMinor, $wgRequest;
+               global $wgSpamRegex, $wgFilterCallback;
+
+               $sk = $wgUser->getSkin();
+               $isConflict = false;
+               // css / js subpages of user pages get a special treatment
+               $isCssJsSubpage = $wgTitle->isCssJsSubpage();
+               
+               if(!$this->mTitle->getArticleID()) { # new article
+                       $editintro = $wgRequest->getText( 'editintro' );
+                       $addstandardintro=true;
+                       if($editintro) {
+                               $introtitle=Title::newFromText($editintro);
+                               if(isset($introtitle) && $introtitle->userCanRead()) {
+                                       $rev=Revision::newFromTitle($introtitle);
+                                       if($rev) {
+                                               $wgOut->addWikiText($rev->getText());   
+                                               $addstandardintro=false;
+                                       }
+                               }
+                       }
+                       if($addstandardintro) {
+                               $wgOut->addWikiText(wfmsg('newarticletext'));                           
+                       }
+               }
+
+               if( $this->mTitle->isTalkPage() ) {
+                       $wgOut->addWikiText(wfmsg('talkpagetext'));
+               }
+
+               # Attempt submission here.  This will check for edit conflicts,
+               # and redundantly check for locked database, blocked IPs, etc.
+               # that edit() already checked just in case someone tries to sneak
+               # in the back door with a hand-edited submission URL.
+
+               if ( 'save' == $formtype ) {
+                       # Reintegrate metadata
+                       if ( $this->mMetaData != '' ) $this->textbox1 .= "\n" . $this->mMetaData ;
+                       $this->mMetaData = '' ;
+
+                       # Check for spam
+                       if ( $wgSpamRegex && preg_match( $wgSpamRegex, $this->textbox1, $matches ) ) {
+                               $this->spamPage ( $matches[0] );
+                               return;
+                       }
+                       if ( $wgFilterCallback && $wgFilterCallback( $this->mTitle, $this->textbox1, $this->section ) ) {
+                               # Error messages or other handling should be performed by the filter function
+                               return;
+                       }
+                       if ( $wgUser->isBlockedFrom( $this->mTitle, false ) ) {
+                               # Check block state against master, thus 'false'.
+                               $this->blockedIPpage();
+                               return;
+                       }
+
+                       if ( !$wgUser->isAllowed('edit') ) {
+                               if ( $wgUser->isAnon() ) {
+                               $this->userNotLoggedInPage();
+                               return;
+                       }
+                               else {
+                                       $wgOut->readOnlyPage();
+                                       return;
+                               }
+                       }
+
+                       if ( wfReadOnly() ) {
+                               $wgOut->readOnlyPage();
+                               return;
+                       }
+                       if ( $wgUser->pingLimiter() ) {
+                               $wgOut->rateLimited();
+                               return;
+                       }
+
+                       # If article is new, insert it.
+                       $aid = $this->mTitle->getArticleID( GAID_FOR_UPDATE );
+                       if ( 0 == $aid ) {
+                               # Don't save a new article if it's blank.
+                               if ( ( '' == $this->textbox1 ) ||
+                                 ( wfMsg( 'newarticletext' ) == $this->textbox1 ) ) {
+                                       $wgOut->redirect( $this->mTitle->getFullURL() );
+                                       return;
+                               }
+                               if (wfRunHooks('ArticleSave', array(&$this->mArticle, &$wgUser, &$this->textbox1,
+                                                          &$this->summary, &$this->minoredit, &$this->watchthis, NULL)))
+                               {                                       
+                                       
+                                       $isComment=($this->section=='new');
+                                       $this->mArticle->insertNewArticle( $this->textbox1, $this->summary,
+                                                                                                          $this->minoredit, $this->watchthis, false, $isComment);
+                                       wfRunHooks('ArticleSaveComplete', array(&$this->mArticle, &$wgUser, $this->textbox1,
+                                                                                                                       $this->summary, $this->minoredit,
+                                                                                                                       $this->watchthis, NULL));
+                               }
+                               return;
+                       }
+
+                       # Article exists. Check for edit conflict.
+
+                       $this->mArticle->clear(); # Force reload of dates, etc.
+                       $this->mArticle->forUpdate( true ); # Lock the article
+
+                       if( ( $this->section != 'new' ) &&
+                               ($this->mArticle->getTimestamp() != $this->edittime ) ) {
+                               $isConflict = true;
+                       }
+                       $userid = $wgUser->getID();
+
+                       if ( $isConflict) {
+                               wfDebug( "EditPage::editForm conflict! getting section '$this->section' for time '$this->edittime' (article time '" .
+                                       $this->mArticle->getTimestamp() . "'\n" );
+                               $text = $this->mArticle->getTextOfLastEditWithSectionReplacedOrAdded(
+                                       $this->section, $this->textbox1, $this->summary, $this->edittime);
+                       }
+                       else {
+                               wfDebug( "EditPage::editForm getting section '$this->section'\n" );
+                               $text = $this->mArticle->getTextOfLastEditWithSectionReplacedOrAdded(
+                                       $this->section, $this->textbox1, $this->summary);
+                       }
+                       # Suppress edit conflict with self
+
+                       if ( ( 0 != $userid ) && ( $this->mArticle->getUser() == $userid ) ) {
+                               wfDebug( "Suppressing edit conflict, same user.\n" );
+                               $isConflict = false;
+                       } else {
+                               # switch from section editing to normal editing in edit conflict
+                               if($isConflict) {
+                                       # Attempt merge
+                                       if( $this->mergeChangesInto( $text ) ){
+                                               // Successful merge! Maybe we should tell the user the good news?
+                                               $isConflict = false;
+                                               wfDebug( "Suppressing edit conflict, successful merge.\n" );
+                                       } else {
+                                               $this->section = '';
+                                               $this->textbox1 = $text;
+                                               wfDebug( "Keeping edit conflict, failed merge.\n" );
+                                       }
+                               }
+                       }
+                       if ( ! $isConflict ) {
+                               # All's well
+                               $sectionanchor = '';
+                               if( $this->section == 'new' ) {
+                                       if( $this->summary != '' ) {
+                                               $sectionanchor = $this->sectionAnchor( $this->summary );
+                                       }
+                               } elseif( $this->section != '' ) {
+                                       # Try to get a section anchor from the section source, redirect to edited section if header found
+                                       # XXX: might be better to integrate this into Article::getTextOfLastEditWithSectionReplacedOrAdded
+                                       # for duplicate heading checking and maybe parsing
+                                       $hasmatch = preg_match( "/^ *([=]{1,6})(.*?)(\\1) *\\n/i", $this->textbox1, $matches );
+                                       # we can't deal with anchors, includes, html etc in the header for now, 
+                                       # headline would need to be parsed to improve this
+                                       #if($hasmatch and strlen($matches[2]) > 0 and !preg_match( "/[\\['{<>]/", $matches[2])) {
+                                       if($hasmatch and strlen($matches[2]) > 0) {
+                                               $sectionanchor = $this->sectionAnchor( $matches[2] );
+                                       }
+                               }
+                               
+                               // Save errors may fall down to the edit form, but we've now
+                               // merged the section into full text. Clear the section field
+                               // so that later submission of conflict forms won't try to
+                               // replace that into a duplicated mess.
+                               $this->textbox1 = $text;
+                               $this->section = '';
+                               
+                               if (wfRunHooks('ArticleSave', array(&$this->mArticle, &$wgUser, &$text,
+                                                                                                       &$this->summary, &$this->minoredit,
+                                                                                                       &$this->watchthis, &$sectionanchor)))
+                               {
+                                       # update the article here
+                                       if($this->mArticle->updateArticle( $text, $this->summary, $this->minoredit,
+                                                                                                          $this->watchthis, '', $sectionanchor ))
+                                       {
+                                               wfRunHooks('ArticleSaveComplete', array(&$this->mArticle, &$wgUser, $text,
+                                                                                                                               $this->summary, $this->minoredit,
+                                                                                                                               $this->watchthis, $sectionanchor));
+                                               return;
+                                       } else {
+                                               $isConflict = true;
+                                       }
+                               }
+                       }
+               }
+               # First time through: get contents, set time for conflict
+               # checking, etc.
+
+               if ( 'initial' == $formtype || $firsttime ) {
+                       $this->edittime = $this->mArticle->getTimestamp();
+                       $this->textbox1 = $this->mArticle->getContent( true );
+                       $this->summary = '';
+                       $this->proxyCheck();
+               }
+               $wgOut->setRobotpolicy( 'noindex,nofollow' );
+
+               # Enabled article-related sidebar, toplinks, etc.
+               $wgOut->setArticleRelated( true );
+
+               if ( $isConflict ) {
+                       $s = wfMsg( 'editconflict', $this->mTitle->getPrefixedText() );
+                       $wgOut->setPageTitle( $s );
+                       $wgOut->addWikiText( wfMsg( 'explainconflict' ) );
+
+                       $this->textbox2 = $this->textbox1;
+                       $this->textbox1 = $this->mArticle->getContent( true );
+                       $this->edittime = $this->mArticle->getTimestamp();
+               } else {
+
+                       if( $this->section != '' ) {
+                               if( $this->section == 'new' ) {
+                                       $s = wfMsg('editingcomment', $this->mTitle->getPrefixedText() );
+                               } else {
+                                       $s = wfMsg('editingsection', $this->mTitle->getPrefixedText() );
+                                       if( !$this->preview && !$this->diff ) {
+                                               preg_match( "/^(=+)(.+)\\1/mi",
+                                                       $this->textbox1,
+                                                       $matches );
+                                               if( !empty( $matches[2] ) ) {
+                                                       $this->summary = "/* ". trim($matches[2])." */ ";
+                                               }
+                                       }                                       
+                               }
+                       } else {
+                               $s = wfMsg( 'editing', $this->mTitle->getPrefixedText() );
+                       }
+                       $wgOut->setPageTitle( $s );
+                       if ( !$this->checkUnicodeCompliantBrowser() ) {
+                               $wgOut->addWikiText( wfMsg( 'nonunicodebrowser') );
+                       }
+                       if ( isset( $this->mArticle )
+                            && isset( $this->mArticle->mRevision )
+                            && !$this->mArticle->mRevision->isCurrent() ) {
+                               $this->mArticle->setOldSubtitle( $this->mArticle->mRevision->getId() );
+                               $wgOut->addWikiText( wfMsg( 'editingold' ) );
+                       }
+               }
+
+               if( wfReadOnly() ) {
+                       $wgOut->addWikiText( wfMsg( 'readonlywarning' ) );
+               } else if ( $isCssJsSubpage and 'preview' != $formtype) {
+                       $wgOut->addWikiText( wfMsg( 'usercssjsyoucanpreview' ));
+               }
+               if( $this->mTitle->isProtected('edit') ) {
+                       $wgOut->addWikiText( wfMsg( 'protectedpagewarning' ) );
+               }
+
+               $kblength = (int)(strlen( $this->textbox1 ) / 1024);
+               if( $kblength > 29 ) {
+                       $wgOut->addWikiText( wfMsg( 'longpagewarning', $wgLang->formatNum( $kblength ) ) );
+               }
+
+               $rows = $wgUser->getOption( 'rows' );
+               $cols = $wgUser->getOption( 'cols' );
+
+               $ew = $wgUser->getOption( 'editwidth' );
+               if ( $ew ) $ew = " style=\"width:100%\"";
+               else $ew = '';
+
+               $q = 'action=submit';
+               #if ( "no" == $redirect ) { $q .= "&redirect=no"; }
+               $action = $this->mTitle->escapeLocalURL( $q );
+
+               $summary = wfMsg('summary');
+               $subject = wfMsg('subject');
+               $minor   = wfMsg('minoredit');
+               $watchthis = wfMsg ('watchthis');
+               $save = wfMsg('savearticle');
+               $prev = wfMsg('showpreview');
+               $diff = wfMsg('showdiff');
+
+               $cancel = $sk->makeKnownLink( $this->mTitle->getPrefixedText(),
+                               wfMsg('cancel') );
+               $edithelpurl = $sk->makeInternalOrExternalUrl( wfMsg( 'edithelppage' ));
+               $edithelp = '<a target="helpwindow" href="'.$edithelpurl.'">'.
+                       htmlspecialchars( wfMsg( 'edithelp' ) ).'</a> '.
+                       htmlspecialchars( wfMsg( 'newwindow' ) );
+
+               global $wgRightsText;
+               $copywarn = "<div id=\"editpage-copywarn\">\n" .
+                       wfMsg( $wgRightsText ? 'copyrightwarning' : 'copyrightwarning2',
+                               '[[' . wfMsgForContent( 'copyrightpage' ) . ']]',
+                               $wgRightsText ) . "\n</div>";
+
+               if( $wgUser->getOption('showtoolbar') and !$isCssJsSubpage ) {
+                       # prepare toolbar for edit buttons
+                       $toolbar = $this->getEditToolbar();
+               } else {
+                       $toolbar = '';
+               }
+
+               // activate checkboxes if user wants them to be always active
+               if( !$this->preview && !$this->diff ) {
+                       if( $wgUser->getOption( 'watchdefault' ) ) $this->watchthis = true;
+                       if( $wgUser->getOption( 'minordefault' ) ) $this->minoredit = true;
+
+                       // activate checkbox also if user is already watching the page,
+                       // require wpWatchthis to be unset so that second condition is not
+                       // checked unnecessarily
+                       if( !$this->watchthis && $this->mTitle->userIsWatching() ) $this->watchthis = true;
+               }
+
+               $minoredithtml = '';
+
+               if ( $wgUser->isLoggedIn() || $wgAllowAnonymousMinor ) {
+                       $minoredithtml =
+                               "<input tabindex='3' type='checkbox' value='1' name='wpMinoredit'".($this->minoredit?" checked='checked'":"").
+                               " accesskey='".wfMsg('accesskey-minoredit')."' id='wpMinoredit' />".
+                               "<label for='wpMinoredit' title='".wfMsg('tooltip-minoredit')."'>{$minor}</label>";
+               }
+
+               $watchhtml = '';
+
+               if ( $wgUser->isLoggedIn() ) {
+                       $watchhtml = "<input tabindex='4' type='checkbox' name='wpWatchthis'".($this->watchthis?" checked='checked'":"").
+                               " accesskey='".wfMsg('accesskey-watch')."' id='wpWatchthis'  />".
+                               "<label for='wpWatchthis' title='".wfMsg('tooltip-watch')."'>{$watchthis}</label>";
+               }
+
+               $checkboxhtml = $minoredithtml . $watchhtml . '<br />';
+
+               $wgOut->addHTML( '<div id="wikiPreview">' );
+               if ( 'preview' == $formtype) {
+                       $previewOutput = $this->getPreviewText( $isConflict, $isCssJsSubpage );
+                       if ( $wgUser->getOption('previewontop' ) ) {
+                               $wgOut->addHTML( $previewOutput );
+                               if($this->mTitle->getNamespace() == NS_CATEGORY) {
+                                       $this->mArticle->closeShowCategory();
+                               }                               
+                               $wgOut->addHTML( "<br style=\"clear:both;\" />\n" );
+                       }
+               }
+               $wgOut->addHTML( '</div>' );
+               if ( 'diff' == $formtype ) {
+                       if ( $wgUser->getOption('previewontop' ) ) {
+                               $wgOut->addHTML( $this->getDiff() );
+                       }
+               }
+
+
+               # if this is a comment, show a subject line at the top, which is also the edit summary.
+               # Otherwise, show a summary field at the bottom
+               $summarytext = htmlspecialchars( $wgContLang->recodeForEdit( $this->summary ) ); # FIXME
+                       if( $this->section == 'new' ) {
+                               $commentsubject="{$subject}: <input tabindex='1' type='text' value=\"$summarytext\" name=\"wpSummary\" maxlength='200' size='60' /><br />";
+                               $editsummary = '';
+                       } else {
+                               $commentsubject = '';
+                               $editsummary="{$summary}: <input tabindex='2' type='text' value=\"$summarytext\" name=\"wpSummary\" maxlength='200' size='60' /><br />";
+                       }
+
+               if( !$this->preview && !$this->diff ) {
+               # Don't select the edit box on preview; this interferes with seeing what's going on.
+                       $wgOut->setOnloadHandler( 'document.editform.wpTextbox1.focus()' );
+               }
+               # Prepare a list of templates used by this page
+               $templates = '';
+               $articleTemplates = $this->mArticle->getUsedTemplates();
+               if ( count( $articleTemplates ) > 0 ) {
+                       $templates = '<br />'. wfMsg( 'templatesused' ) . '<ul>';
+                       foreach ( $articleTemplates as $tpl ) {
+                               if ( $titleObj = Title::makeTitle( NS_TEMPLATE, $tpl ) ) {
+                                       $templates .= '<li>' . $sk->makeLinkObj( $titleObj ) . '</li>';
+                               }
+                       }
+                       $templates .= '</ul>';
+               }
+               
+               global $wgLivePreview, $wgStylePath;
+               /**
+                * Live Preview lets us fetch rendered preview page content and
+                * add it to the page without refreshing the whole page.
+                * Set up the button for it; if not supported by the browser
+                * it will fall through to the normal form submission method.
+                */
+               if( $wgLivePreview ) {
+                       global $wgJsMimeType;
+                       $wgOut->addHTML( '<script type="'.$wgJsMimeType.'" src="' .
+                               htmlspecialchars( $wgStylePath . '/common/preview.js' ) .
+                               '"></script>' . "\n" );
+                       $liveAction = $wgTitle->getLocalUrl( 'action=submit&wpPreview=true&live=true' );
+                       $liveOnclick = 'onclick="return !livePreview('.
+                               'getElementById(\'wikiPreview\'),' .
+                               'editform.wpTextbox1.value,' .
+                               htmlspecialchars( '"' . $liveAction . '"' ) . ')"';
+               } else {
+                       $liveOnclick = '';
+               }
+               
+               global $wgUseMetadataEdit ;
+               if ( $wgUseMetadataEdit )
+               {
+                       $metadata = $this->mMetaData ;
+                       $metadata = htmlspecialchars( $wgContLang->recodeForEdit( $metadata ) ) ;
+                       $helppage = Title::newFromText ( wfmsg("metadata_page") ) ;
+                       $top = str_replace ( "$1" , $helppage->getInternalURL() , wfmsg("metadata") ) ;
+                       $metadata = $top . "<textarea name='metadata' rows='3' cols='{$cols}'{$ew}>{$metadata}</textarea>" ;
+               }
+               else $metadata = "" ;
+
+               $safemodehtml = $this->checkUnicodeCompliantBrowser()
+                       ? ""
+                       : "<input type='hidden' name=\"safemode\" value='1' />\n";
+
+               $wgOut->addHTML( <<<END
+{$toolbar}
+<form id="editform" name="editform" method="post" action="$action"
+enctype="multipart/form-data">
+{$commentsubject}
+<textarea tabindex='1' accesskey="," name="wpTextbox1" rows='{$rows}'
+cols='{$cols}'{$ew}>
+END
+. htmlspecialchars( $this->safeUnicodeOutput( $this->textbox1 ) ) .
+"
+</textarea>
+{$metadata}
+<br />{$editsummary}
+{$checkboxhtml}
+{$safemodehtml}
+<input tabindex='5' id='wpSave' type='submit' value=\"{$save}\" name=\"wpSave\" accesskey=\"".wfMsg('accesskey-save')."\"".
+" title=\"".wfMsg('tooltip-save')."\"/>
+<input tabindex='6' id='wpPreview' type='submit' $liveOnclick value=\"{$prev}\" name=\"wpPreview\" accesskey=\"".wfMsg('accesskey-preview')."\"".
+" title=\"".wfMsg('tooltip-preview')."\"/>
+<input tabindex='7' id='wpDiff' type='submit' value=\"{$diff}\" name=\"wpDiff\" accesskey=\"".wfMsg('accesskey-diff')."\"".
+" title=\"".wfMsg('tooltip-diff')."\"/>
+<em>{$cancel}</em> | <em>{$edithelp}</em>{$templates}" );
+               $wgOut->addWikiText( $copywarn );
+               $wgOut->addHTML( "
+<input type='hidden' value=\"" . htmlspecialchars( $this->section ) . "\" name=\"wpSection\" />
+<input type='hidden' value=\"{$this->edittime}\" name=\"wpEdittime\" />\n" );
+
+               if ( $wgUser->isLoggedIn() ) {
+                       /**
+                        * To make it harder for someone to slip a user a page
+                        * which submits an edit form to the wiki without their
+                        * knowledge, a random token is associated with the login
+                        * session. If it's not passed back with the submission,
+                        * we won't save the page, or render user JavaScript and
+                        * CSS previews.
+                        */
+                       $token = htmlspecialchars( $wgUser->editToken() );
+                       $wgOut->addHTML( "
+<input type='hidden' value=\"$token\" name=\"wpEditToken\" />\n" );
+               }
+               
+               
+               if ( $isConflict ) {
+                       require_once( "DifferenceEngine.php" );
+                       $wgOut->addWikiText( '==' . wfMsg( "yourdiff" ) . '==' );
+                       DifferenceEngine::showDiff( $this->textbox2, $this->textbox1,
+                         wfMsg( "yourtext" ), wfMsg( "storedversion" ) );
+
+                       $wgOut->addWikiText( '==' . wfMsg( "yourtext" ) . '==' );
+                       $wgOut->addHTML( "<textarea tabindex=6 id='wpTextbox2' name=\"wpTextbox2\" rows='{$rows}' cols='{$cols}' wrap='virtual'>"
+. htmlspecialchars( $this->safeUnicodeOutput( $this->textbox2 ) ) .
+"
+</textarea>" );
+               }
+               $wgOut->addHTML( "</form>\n" );
+               if ( $formtype == 'preview' && !$wgUser->getOption( 'previewontop' ) ) {
+                       $wgOut->addHTML( '<div id="wikiPreview">' . $previewOutput . '</div>' );
+               }
+               if ( $formtype == 'diff' && !$wgUser->getOption( 'previewontop' ) ) {
+                       #$wgOut->addHTML( '<div id="wikiPreview">' . $difftext . '</div>' );
+                       $wgOut->addHTML( $this->getDiff() );
+               }
+       }
+
+       /**
+        * @todo document
+        */
+       function getPreviewText( $isConflict, $isCssJsSubpage ) {
+               global $wgOut, $wgUser, $wgTitle, $wgParser, $wgAllowDiffPreview, $wgEnableDiffPreviewPreference;
+               $previewhead = '<h2>' . htmlspecialchars( wfMsg( 'preview' ) ) . "</h2>\n" .
+                       "<p class='previewnote'>" . htmlspecialchars( wfMsg( 'previewnote' ) ) . "</p>\n";
+               if ( $isConflict ) {
+                       $previewhead.='<h2>' . htmlspecialchars( wfMsg( 'previewconflict' ) ) .
+                               "</h2>\n";
+               }
+
+               $parserOptions = ParserOptions::newFromUser( $wgUser );
+               $parserOptions->setEditSection( false );
+
+               # don't parse user css/js, show message about preview
+               # XXX: stupid php bug won't let us use $wgTitle->isCssJsSubpage() here
+
+               if ( $isCssJsSubpage ) {
+                       if(preg_match("/\\.css$/", $wgTitle->getText() ) ) {
+                               $previewtext = wfMsg('usercsspreview');
+                       } else if(preg_match("/\\.js$/", $wgTitle->getText() ) ) {
+                               $previewtext = wfMsg('userjspreview');
+                       }
+                       $parserOutput = $wgParser->parse( $previewtext , $wgTitle, $parserOptions );
+                       $wgOut->addHTML( $parserOutput->mText );
+                       return $previewhead;
+               } else {
+                       # if user want to see preview when he edit an article
+                       if( $wgUser->getOption('previewonfirst') and ($this->textbox1 == '')) {
+                               $this->textbox1 = $this->mArticle->getContent(true);
+                       }
+
+                       $toparse = $this->textbox1;
+                       
+                       # If we're adding a comment, we need to show the
+                       # summary as the headline
+                       if($this->section=="new" && $this->summary!="") {
+                               $toparse="== {$this->summary} ==\n\n".$toparse;
+                       }
+                       
+                       if ( $this->mMetaData != "" ) $toparse .= "\n" . $this->mMetaData ;
+                       
+                       $parserOutput = $wgParser->parse( $this->mArticle->preSaveTransform( $toparse ) ."\n\n",
+                                       $wgTitle, $parserOptions );             
+                       
+                       $previewHTML = $parserOutput->mText;
+                       
+                       $wgOut->addCategoryLinks($parserOutput->getCategoryLinks());
+                       $wgOut->addLanguageLinks($parserOutput->getLanguageLinks());
+                       return $previewhead . $previewHTML;
+               }
+       }
+       
+       /**
+        * @todo document
+        */
+       function blockedIPpage() {
+               global $wgOut, $wgUser, $wgContLang, $wgIP;
+
+               $wgOut->setPageTitle( wfMsg( 'blockedtitle' ) );
+               $wgOut->setRobotpolicy( 'noindex,nofollow' );
+               $wgOut->setArticleRelated( false );
+
+               $id = $wgUser->blockedBy();
+               $reason = $wgUser->blockedFor();
+               $ip = $wgIP;
+               
+               if ( is_numeric( $id ) ) {
+                       $name = User::whoIs( $id );
+               } else {
+                       $name = $id;
+               }
+               $link = '[[' . $wgContLang->getNsText( NS_USER ) .
+                 ":{$name}|{$name}]]";
+
+               $wgOut->addWikiText( wfMsg( 'blockedtext', $link, $reason, $ip, $name ) );
+               $wgOut->returnToMain( false );
+       }
+
+       /**
+        * @todo document
+        */
+       function userNotLoggedInPage() {
+               global $wgOut;
+
+               $wgOut->setPageTitle( wfMsg( 'whitelistedittitle' ) );
+               $wgOut->setRobotpolicy( 'noindex,nofollow' );
+               $wgOut->setArticleRelated( false );
+
+               $wgOut->addWikiText( wfMsg( 'whitelistedittext' ) );
+               $wgOut->returnToMain( false );
+       }
+
+       /**
+        * @todo document
+        */
+       function spamPage ( $match = false )
+       {
+               global $wgOut;
+               $wgOut->setPageTitle( wfMsg( 'spamprotectiontitle' ) );
+               $wgOut->setRobotpolicy( 'noindex,nofollow' );
+               $wgOut->setArticleRelated( false );
+
+               $wgOut->addWikiText( wfMsg( 'spamprotectiontext' ) );
+               if ( $match ) {
+                       $wgOut->addWikiText( wfMsg( 'spamprotectionmatch', "<nowiki>{$match}</nowiki>" ) );
+               }
+               $wgOut->returnToMain( false );
+       }
+
+       /**
+        * Forks processes to scan the originating IP for an open proxy server
+        * MemCached can be used to skip IPs that have already been scanned
+        */
+       function proxyCheck() {
+               global $wgBlockOpenProxies, $wgProxyPorts, $wgProxyScriptPath;
+               global $wgIP, $wgUseMemCached, $wgMemc, $wgDBname, $wgProxyMemcExpiry;
+               
+               if ( !$wgBlockOpenProxies ) {
+                       return;
+               }
+               
+               # Get MemCached key
+               $skip = false;
+               if ( $wgUseMemCached ) {
+                       $mcKey = $wgDBname.':proxy:ip:'.$wgIP;
+                       $mcValue = $wgMemc->get( $mcKey );
+                       if ( $mcValue ) {
+                               $skip = true;
+                       }
+               }
+
+               # Fork the processes
+               if ( !$skip ) {
+                       $title = Title::makeTitle( NS_SPECIAL, 'Blockme' );
+                       $iphash = md5( $wgIP . $wgProxyKey );
+                       $url = $title->getFullURL( 'ip='.$iphash );
+
+                       foreach ( $wgProxyPorts as $port ) {
+                               $params = implode( ' ', array(
+                                                       escapeshellarg( $wgProxyScriptPath ),
+                                                       escapeshellarg( $wgIP ),
+                                                       escapeshellarg( $port ),
+                                                       escapeshellarg( $url )
+                                                       ));
+                               exec( "php $params &>/dev/null &" );
+                       }
+                       # Set MemCached key
+                       if ( $wgUseMemCached ) {
+                               $wgMemc->set( $mcKey, 1, $wgProxyMemcExpiry );
+                       }
+               }
+       }
+
+       /**
+        * @access private
+        * @todo document
+        */
+       function mergeChangesInto( &$editText ){
+               $fname = 'EditPage::mergeChangesInto';
+               wfProfileIn( $fname );
+
+               $db =& wfGetDB( DB_MASTER );
+               
+               // This is the revision the editor started from
+               $baseRevision = Revision::loadFromTimestamp(
+                       $db, $this->mArticle->mTitle, $this->edittime );
+               if( is_null( $baseRevision ) ) {
+                       wfProfileOut( $fname );
+                       return false;
+               }
+               $baseText = $baseRevision->getText();
+
+               // The current state, we want to merge updates into it
+               $currentRevision =  Revision::loadFromTitle(
+                       $db, $this->mArticle->mTitle );
+               if( is_null( $currentRevision ) ) {
+                       wfProfileOut( $fname );
+                       return false;
+               }
+               $currentText = $currentRevision->getText();
+               
+               if( wfMerge( $baseText, $editText, $currentText, $result ) ){
+                       $editText = $result;
+                       wfProfileOut( $fname );
+                       return true;
+               } else {
+                       wfProfileOut( $fname );
+                       return false;
+               }
+       }
+
+       /**
+        * Check if the browser is on a blacklist of user-agents known to
+        * mangle UTF-8 data on form submission. Returns true if Unicode
+        * should make it through, false if it's known to be a problem.
+        * @return bool
+        * @access private
+        */
+       function checkUnicodeCompliantBrowser() {
+               global $wgBrowserBlackList;
+               if( empty( $_SERVER["HTTP_USER_AGENT"] ) ) {
+                       // No User-Agent header sent? Trust it by default...
+                       return true;
+               }
+               $currentbrowser = $_SERVER["HTTP_USER_AGENT"];
+               foreach ( $wgBrowserBlackList as $browser ) {
+                       if ( preg_match($browser, $currentbrowser) ) {
+                               return false;
+                       }
+               }
+               return true;
+       }
+
+       /**
+        * Format an anchor fragment as it would appear for a given section name
+        * @param string $text
+        * @return string
+        * @access private
+        */
+       function sectionAnchor( $text ) {
+               $headline = Sanitizer::decodeCharReferences( $text );
+               # strip out HTML 
+               $headline = preg_replace( '/<.*?' . '>/', '', $headline );
+               $headline = trim( $headline );
+               $sectionanchor = '#' . urlencode( str_replace( ' ', '_', $headline ) );
+               $replacearray = array(
+                       '%3A' => ':',
+                       '%' => '.'
+               );
+               return str_replace(
+                       array_keys( $replacearray ),
+                       array_values( $replacearray ),
+                       $sectionanchor );
+       }
+
+       /**
+        * Shows a bulletin board style toolbar for common editing functions.
+        * It can be disabled in the user preferences.
+        * The necessary JavaScript code can be found in style/wikibits.js.
+        */
+       function getEditToolbar() {
+               global $wgStylePath, $wgContLang, $wgMimeType, $wgJsMimeType;
+
+               /**
+                * toolarray an array of arrays which each include the filename of
+                * the button image (without path), the opening tag, the closing tag,
+                * and optionally a sample text that is inserted between the two when no
+                * selection is highlighted.
+                * The tip text is shown when the user moves the mouse over the button.
+                *
+                * Already here are accesskeys (key), which are not used yet until someone
+                * can figure out a way to make them work in IE. However, we should make
+                * sure these keys are not defined on the edit page.
+                */
+               $toolarray=array(
+                       array(  'image'=>'button_bold.png',
+                                       'open'  =>      "\'\'\'",
+                                       'close' =>      "\'\'\'",
+                                       'sample'=>      wfMsg('bold_sample'),
+                                       'tip'   =>      wfMsg('bold_tip'),
+                                       'key'   =>      'B'
+                               ),
+                       array(  'image'=>'button_italic.png',
+                                       'open'  =>      "\'\'",
+                                       'close' =>      "\'\'",
+                                       'sample'=>      wfMsg('italic_sample'),
+                                       'tip'   =>      wfMsg('italic_tip'),
+                                       'key'   =>      'I'
+                               ),
+                       array(  'image'=>'button_link.png',
+                                       'open'  =>      '[[',
+                                       'close' =>      ']]',
+                                       'sample'=>      wfMsg('link_sample'),
+                                       'tip'   =>      wfMsg('link_tip'),
+                                       'key'   =>      'L'
+                               ),
+                       array(  'image'=>'button_extlink.png',
+                                       'open'  =>      '[',
+                                       'close' =>      ']',
+                                       'sample'=>      wfMsg('extlink_sample'),
+                                       'tip'   =>      wfMsg('extlink_tip'),
+                                       'key'   =>      'X'
+                               ),
+                       array(  'image'=>'button_headline.png',
+                                       'open'  =>      "\\n== ",
+                                       'close' =>      " ==\\n",
+                                       'sample'=>      wfMsg('headline_sample'),
+                                       'tip'   =>      wfMsg('headline_tip'),
+                                       'key'   =>      'H'
+                               ),
+                       array(  'image'=>'button_image.png',
+                                       'open'  =>      '[['.$wgContLang->getNsText(NS_IMAGE).":",
+                                       'close' =>      ']]',
+                                       'sample'=>      wfMsg('image_sample'),
+                                       'tip'   =>      wfMsg('image_tip'),
+                                       'key'   =>      'D'
+                               ),
+                       array(  'image' =>'button_media.png',
+                                       'open'  =>      '[['.$wgContLang->getNsText(NS_MEDIA).':',
+                                       'close' =>      ']]',
+                                       'sample'=>      wfMsg('media_sample'),
+                                       'tip'   =>      wfMsg('media_tip'),
+                                       'key'   =>      'M'
+                               ),
+                       array(  'image' =>'button_math.png',
+                                       'open'  =>      "\\<math\\>",
+                                       'close' =>      "\\</math\\>",
+                                       'sample'=>      wfMsg('math_sample'),
+                                       'tip'   =>      wfMsg('math_tip'),
+                                       'key'   =>      'C'
+                               ),
+                       array(  'image' =>'button_nowiki.png',
+                                       'open'  =>      "\\<nowiki\\>",
+                                       'close' =>      "\\</nowiki\\>",
+                                       'sample'=>      wfMsg('nowiki_sample'),
+                                       'tip'   =>      wfMsg('nowiki_tip'),
+                                       'key'   =>      'N'
+                               ),
+                       array(  'image' =>'button_sig.png',
+                                       'open'  =>      '--~~~~',
+                                       'close' =>      '',
+                                       'sample'=>      '',
+                                       'tip'   =>      wfMsg('sig_tip'),
+                                       'key'   =>      'Y'
+                               ),
+                       array(  'image' =>'button_hr.png',
+                                       'open'  =>      "\\n----\\n",
+                                       'close' =>      '',
+                                       'sample'=>      '',
+                                       'tip'   =>      wfMsg('hr_tip'),
+                                       'key'   =>      'R'
+                               )
+               );
+               $toolbar ="<script type='$wgJsMimeType'>\n/*<![CDATA[*/\n";
+
+               $toolbar.="document.writeln(\"<div id='toolbar'>\");\n";
+               foreach($toolarray as $tool) {
+
+                       $image=$wgStylePath.'/common/images/'.$tool['image'];
+                       $open=$tool['open'];
+                       $close=$tool['close'];
+                       $sample = wfEscapeJsString( $tool['sample'] );
+
+                       // Note that we use the tip both for the ALT tag and the TITLE tag of the image.
+                       // Older browsers show a "speedtip" type message only for ALT.
+                       // Ideally these should be different, realistically they
+                       // probably don't need to be.
+                       $tip = wfEscapeJsString( $tool['tip'] );
+
+                       #$key = $tool["key"];
+
+                       $toolbar.="addButton('$image','$tip','$open','$close','$sample');\n";
+               }
+
+               $toolbar.="addInfobox('" . wfEscapeJsString( wfMsg( "infobox" ) ) .
+                       "','" . wfEscapeJsString( wfMsg( "infobox_alert" ) ) . "');\n";
+               $toolbar.="document.writeln(\"</div>\");\n";
+
+               $toolbar.="/*]]>*/\n</script>";
+               return $toolbar;
+       }
+       
+       /**
+        * Output preview text only. This can be sucked into the edit page
+        * via JavaScript, and saves the server time rendering the skin as
+        * well as theoretically being more robust on the client (doesn't
+        * disturb the edit box's undo history, won't eat your text on
+        * failure, etc).
+        *
+        * @todo This doesn't include category or interlanguage links.
+        *       Would need to enhance it a bit, maybe wrap them in XML
+        *       or something... that might also require more skin
+        *       initialization, so check whether that's a problem.
+        */
+       function livePreview() {
+               global $wgOut;
+               $wgOut->disable();
+               header( 'Content-type: text/xml' );
+               header( 'Cache-control: no-cache' );
+               # FIXME
+               echo $this->getPreviewText( false, false );
+       }
+
+
+       /**
+        * Get a diff between the current contents of the edit box and the
+        * version of the page we're editing from.
+        *
+        * If this is a section edit, we'll replace the section as for final
+        * save and then make a comparison.
+        *
+        * @return string HTML
+        */
+       function getDiff() {
+               require_once( 'DifferenceEngine.php' );
+               $oldtext = $this->mArticle->fetchContent();
+               $newtext = $this->mArticle->getTextOfLastEditWithSectionReplacedOrAdded(
+                       $this->section, $this->textbox1, $this->summary, $this->edittime );
+               $oldtitle = wfMsg( 'currentrev' );
+               $newtitle = wfMsg( 'yourtext' );
+               if ( $oldtext != wfMsg( 'noarticletext' ) || $newtext != '' ) {
+                       $difftext = DifferenceEngine::getDiff( $oldtext, $newtext, $oldtitle, $newtitle );
+               }
+               
+               return '<div id="wikiDiff">' . $difftext . '</div>';
+       }
+
+       /**
+        * Filter an input field through a Unicode de-armoring process if it
+        * came from an old browser with known broken Unicode editing issues.
+        *
+        * @param WebRequest $request
+        * @param string $field
+        * @return string
+        * @access private
+        */
+       function safeUnicodeInput( $request, $field ) {
+               $text = rtrim( $request->getText( $field ) );
+               return $request->getBool( 'safemode' )
+                       ? $this->unmakesafe( $text )
+                       : $text;
+       }
+       
+       /**
+        * Filter an output field through a Unicode armoring process if it is
+        * going to an old browser with known broken Unicode editing issues.
+        *
+        * @param string $text
+        * @return string
+        * @access private
+        */
+       function safeUnicodeOutput( $text ) {
+               global $wgContLang;
+               $codedText = $wgContLang->recodeForEdit( $text );
+               return $this->checkUnicodeCompliantBrowser()
+                       ? $codedText
+                       : $this->makesafe( $codedText );
+       }
+       
+       /**
+        * A number of web browsers are known to corrupt non-ASCII characters
+        * in a UTF-8 text editing environment. To protect against this,
+        * detected browsers will be served an armored version of the text,
+        * with non-ASCII chars converted to numeric HTML character references.
+        *
+        * Preexisting such character references will have a 0 added to them
+        * to ensure that round-trips do not alter the original data.
+        *
+        * @param string $invalue
+        * @return string
+        * @access private
+        */
+       function makesafe( $invalue ) {
+               // Armor existing references for reversability.
+               $invalue = strtr( $invalue, array( "&#x" => "&#x0" ) );
+               
+               $bytesleft = 0;
+               $result = "";
+               $working = 0;
+               for( $i = 0; $i < strlen( $invalue ); $i++ ) {
+                       $bytevalue = ord( $invalue{$i} );
+                       if( $bytevalue <= 0x7F ) { //0xxx xxxx
+                               $result .= chr( $bytevalue );
+                               $bytesleft = 0;
+                       } elseif( $bytevalue <= 0xBF ) { //10xx xxxx
+                               $working = $working << 6;
+                               $working += ($bytevalue & 0x3F);
+                               $bytesleft--;
+                               if( $bytesleft <= 0 ) {
+                                       $result .= "&#x" . strtoupper( dechex( $working ) ) . ";";
+                               }
+                       } elseif( $bytevalue <= 0xDF ) { //110x xxxx
+                               $working = $bytevalue & 0x1F;
+                               $bytesleft = 1;
+                       } elseif( $bytevalue <= 0xEF ) { //1110 xxxx
+                               $working = $bytevalue & 0x0F;
+                               $bytesleft = 2;
+                       } else { //1111 0xxx
+                               $working = $bytevalue & 0x07;
+                               $bytesleft = 3;
+                       }
+               }
+               return $result;
+       }
+       
+       /**
+        * Reverse the previously applied transliteration of non-ASCII characters
+        * back to UTF-8. Used to protect data from corruption by broken web browsers
+        * as listed in $wgBrowserBlackList.
+        *
+        * @param string $invalue
+        * @return string
+        * @access private
+        */
+       function unmakesafe( $invalue ) {
+               $result = "";
+               for( $i = 0; $i < strlen( $invalue ); $i++ ) {
+                       if( ( substr( $invalue, $i, 3 ) == "&#x" ) && ( $invalue{$i+3} != '0' ) ) {
+                               $i += 3;
+                               $hexstring = "";
+                               do {
+                                       $hexstring .= $invalue{$i};
+                                       $i++;
+                               } while( ctype_xdigit( $invalue{$i} ) && ( $i < strlen( $invalue ) ) );
+                               
+                               // Do some sanity checks. These aren't needed for reversability,
+                               // but should help keep the breakage down if the editor 
+                               // breaks one of the entities whilst editing.
+                               if ((substr($invalue,$i,1)==";") and (strlen($hexstring) <= 6)) { 
+                                       $codepoint = hexdec($hexstring);
+                                       $result .= codepointToUtf8( $codepoint );
+                               } else {
+                                       $result .= "&#x" . $hexstring . substr( $invalue, $i, 1 );
+                               }
+                       } else {
+                               $result .= substr( $invalue, $i, 1 );
+                       }
+               }
+               // reverse the transform that we made for reversability reasons.
+               return strtr( $result, array( "&#x0" => "&#x" ) );
+       }
+       
+
+}
+
+?>
diff --git a/includes/Exif.php b/includes/Exif.php
new file mode 100644 (file)
index 0000000..629a946
--- /dev/null
@@ -0,0 +1,984 @@
+<?php
+if ( !defined( 'MEDIAWIKI' ) ) die();
+/**
+ * @package MediaWiki
+ * @subpackage Metadata
+ *
+ * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
+ * @copyright Copyright © 2005, Ævar Arnfjörð Bjarmason
+ * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or 
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @link http://exif.org/Exif2-2.PDF The Exif 2.2 specification
+ * @bug 1555, 1947
+ */
+
+/**#@+
+ * Exif tag type definition
+ */
+define('MW_EXIF_BYTE', 1);             # An 8-bit unsigned integer.
+define('MW_EXIF_ASCII', 2);            # An 8-bit byte containing one 7-bit ASCII code. The final byte is terminated with NULL.
+define('MW_EXIF_SHORT', 3);            # A 16-bit (2-byte) unsigned integer.
+define('MW_EXIF_LONG', 4);             # A 32-bit (4-byte) unsigned integer.
+define('MW_EXIF_RATIONAL', 5);         # Two LONGs. The first LONG is the numerator and the second LONG expresses the denominator
+define('MW_EXIF_UNDEFINED', 7);                # An 8-bit byte that can take any value depending on the field definition
+define('MW_EXIF_SLONG', 9);            # A 32-bit (4-byte) signed integer (2's complement notation),
+define('MW_EXIF_SRATIONAL', 10);       # Two SLONGs. The first SLONG is the numerator and the second SLONG is the denominator.
+/**#@-*/
+
+
+/**
+ * @package MediaWiki
+ * @subpackage Metadata
+ */
+class Exif {
+       /**#@+
+        * @var array
+        * @access private
+        */
+       
+       /**
+        * Exif tags grouped by category, the tagname itself is the key and the type
+        * is the value, in the case of more than one possible value type they are 
+        * seperated by commas.
+        */
+       var $mExifTags;
+
+       /**
+        * A one dimentional array of all Exif tags
+        */
+       var $mFlatExifTags;
+
+       /**
+        * The raw Exif data returned by exif_read_data()
+        */
+       var $mRawExifData;
+
+       /**
+        * A Filtered version of $mRawExifData that has been pruned of invalid
+        * tags and tags that contain content they shouldn't contain according
+        * to the Exif specification
+        */
+       var $mFilteredExifData;
+
+       /**
+        * Filtered and formatted Exif data, see FormatExif::getFormattedData()
+        */
+       var $mFormattedExifData;
+       
+       /**#@-*/
+
+       /**
+        * Constructor
+        *
+        * @param string $file
+        */
+       function Exif( $file ) {
+               /**
+                * Page numbers here refer to pages in the EXIF 2.2 standard
+                *
+                * @link http://exif.org/Exif2-2.PDF The Exif 2.2 specification
+                */
+               $this->mExifTags = array(
+                       # TIFF Rev. 6.0 Attribute Information (p22)
+                       'tiff' => array(
+                               # Tags relating to image structure
+                               'structure' => array(
+                                       'ImageWidth' => MW_EXIF_SHORT.','.MW_EXIF_LONG,         # Image width
+                                       'ImageLength' => MW_EXIF_SHORT.','.MW_EXIF_LONG,        # Image height
+                                       'BitsPerSample' => MW_EXIF_SHORT,                       # Number of bits per component
+                                       # "When a primary image is JPEG compressed, this designation is not"
+                                       # "necessary and is omitted." (p23)
+                                       'Compression' => MW_EXIF_SHORT,                         # Compression scheme #p23
+                                       'PhotometricInterpretation' => MW_EXIF_SHORT,           # Pixel composition #p23
+                                       'Orientation' => MW_EXIF_SHORT,                         # Orientation of image #p24
+                                       'SamplesPerPixel' => MW_EXIF_SHORT,                     # Number of components
+                                       'PlanarConfiguration' => MW_EXIF_SHORT,                 # Image data arrangement #p24
+                                       'YCbCrSubSampling' => MW_EXIF_SHORT,                    # Subsampling ratio of Y to C #p24
+                                       'YCbCrPositioning' => MW_EXIF_SHORT,                    # Y and C positioning #p24-25
+                                       'XResolution' => MW_EXIF_RATIONAL,                      # Image resolution in width direction
+                                       'YResolution' => MW_EXIF_RATIONAL,                      # Image resolution in height direction
+                                       'ResolutionUnit' => MW_EXIF_SHORT,                      # Unit of X and Y resolution #(p26)
+                               ),
+                               
+                               # Tags relating to recording offset
+                               'offset' => array(
+                                       'StripOffsets' => MW_EXIF_SHORT.','.MW_EXIF_LONG,                       # Image data location
+                                       'RowsPerStrip' => MW_EXIF_SHORT.','.MW_EXIF_LONG,                       # Number of rows per strip
+                                       'StripByteCounts' => MW_EXIF_SHORT.','.MW_EXIF_LONG,                    # Bytes per compressed strip
+                                       'JPEGInterchangeFormat' => MW_EXIF_SHORT.','.MW_EXIF_LONG,              # Offset to JPEG SOI
+                                       'JPEGInterchangeFormatLength' => MW_EXIF_SHORT.','.MW_EXIF_LONG,        # Bytes of JPEG data
+                               ),
+                       
+                               # Tags relating to image data characteristics
+                               'characteristics' => array(
+                                       'TransferFunction' => MW_EXIF_SHORT,            # Transfer function
+                                       'WhitePoint' => MW_EXIF_RATIONAL,               # White point chromaticity
+                                       'PrimaryChromaticities' => MW_EXIF_RATIONAL,    # Chromaticities of primarities
+                                       'YCbCrCoefficients' => MW_EXIF_RATIONAL,        # Color space transformation matrix coefficients #p27
+                                       'ReferenceBlackWhite' => MW_EXIF_RATIONAL       # Pair of black and white reference values
+                               ),
+                       
+                               # Other tags
+                               'other' => array(
+                                       'DateTime' => MW_EXIF_ASCII,            # File change date and time
+                                       'ImageDescription' => MW_EXIF_ASCII,    # Image title
+                                       'Make' => MW_EXIF_ASCII,                # Image input equipment manufacturer
+                                       'Model' => MW_EXIF_ASCII,               # Image input equipment model
+                                       'Software' => MW_EXIF_ASCII,            # Software used
+                                       'Artist' => MW_EXIF_ASCII,              # Person who created the image
+                                       'Copyright' => MW_EXIF_ASCII,           # Copyright holder
+                               ),
+                       ),
+               
+                       # Exif IFD Attribute Information (p30-31)
+                       'exif' => array(
+                               # Tags relating to version
+                               'version' => array(
+                                       # TODO: NOTE: Nonexistence of this field is taken to mean nonconformance
+                                       # to the EXIF 2.1 AND 2.2 standards
+                                       'ExifVersion' => MW_EXIF_UNDEFINED,     # Exif version
+                                       'FlashpixVersion' => MW_EXIF_UNDEFINED, # Supported Flashpix version #p32
+                               ),
+                               
+                               # Tags relating to Image Data Characteristics
+                               'characteristics' => array(
+                                       'ColorSpace' => MW_EXIF_SHORT,          # Color space information #p32
+                               ),
+               
+                               # Tags relating to image configuration
+                               'configuration' => array(
+                                       'ComponentsConfiguration' => MW_EXIF_UNDEFINED,         # Meaning of each component #p33
+                                       'CompressedBitsPerPixel' => MW_EXIF_RATIONAL,           # Image compression mode
+                                       'PixelYDimension' => MW_EXIF_SHORT.','.MW_EXIF_LONG,    # Valid image width
+                                       'PixelXDimension' => MW_EXIF_SHORT.','.MW_EXIF_LONG,    # Valind image height
+                               ),
+                               
+                               # Tags relating to related user information
+                               'user' => array(
+                                       'MakerNote' => MW_EXIF_UNDEFINED,                       # Manufacturer notes
+                                       'UserComment' => MW_EXIF_UNDEFINED,                     # User comments #p34
+                               ),
+               
+                               # Tags relating to related file information
+                               'related' => array(
+                                       'RelatedSoundFile' => MW_EXIF_ASCII,                    # Related audio file
+                               ),
+               
+                               # Tags relating to date and time
+                               'dateandtime' => array(
+                                       'DateTimeOriginal' => MW_EXIF_ASCII,                    # Date and time of original data generation #p36
+                                       'DateTimeDigitized' => MW_EXIF_ASCII,                   # Date and time of original data generation
+                                       'SubSecTime' => MW_EXIF_ASCII,                          # DateTime subseconds 
+                                       'SubSecTimeOriginal' => MW_EXIF_ASCII,                  # DateTimeOriginal subseconds
+                                       'SubSecTimeDigitized' => MW_EXIF_ASCII,                 # DateTimeDigitized subseconds
+                               ),
+                               
+                               # Tags relating to picture-taking conditions (p31)
+                               'conditions' => array(
+                                       'ExposureTime' => MW_EXIF_RATIONAL,                     # Exposure time
+                                       'FNumber' => MW_EXIF_RATIONAL,                          # F Number
+                                       'ExposureProgram' => MW_EXIF_SHORT,                     # Exposure Program #p38
+                                       'SpectralSensitivity' => MW_EXIF_ASCII,                 # Spectral sensitivity
+                                       'ISOSpeedRatings' => MW_EXIF_SHORT,                     # ISO speed rating
+                                       'OECF' => MW_EXIF_UNDEFINED,                            # Optoelectronic conversion factor
+                                       'ShutterSpeedValue' => MW_EXIF_SRATIONAL,               # Shutter speed
+                                       'ApertureValue' => MW_EXIF_RATIONAL,                    # Aperture
+                                       'BrightnessValue' => MW_EXIF_SRATIONAL,                 # Brightness
+                                       'ExposureBiasValue' => MW_EXIF_SRATIONAL,               # Exposure bias
+                                       'MaxApertureValue' => MW_EXIF_RATIONAL,                 # Maximum land aperture
+                                       'SubjectDistance' => MW_EXIF_RATIONAL,                  # Subject distance
+                                       'MeteringMode' => MW_EXIF_SHORT,                        # Metering mode #p40
+                                       'LightSource' => MW_EXIF_SHORT,                         # Light source #p40-41
+                                       'Flash' => MW_EXIF_SHORT,                               # Flash #p41-42
+                                       'FocalLength' => MW_EXIF_RATIONAL,                      # Lens focal length
+                                       'SubjectArea' => MW_EXIF_SHORT,                         # Subject area
+                                       'FlashEnergy' => MW_EXIF_RATIONAL,                      # Flash energy
+                                       'SpatialFrequencyResponse' => MW_EXIF_UNDEFINED,        # Spatial frequency response
+                                       'FocalPlaneXResolution' => MW_EXIF_RATIONAL,            # Focal plane X resolution
+                                       'FocalPlaneYResolution' => MW_EXIF_RATIONAL,            # Focal plane Y resolution
+                                       'FocalPlaneResolutionUnit' => MW_EXIF_SHORT,            # Focal plane resolution unit #p46
+                                       'SubjectLocation' => MW_EXIF_SHORT,                     # Subject location
+                                       'ExposureIndex' => MW_EXIF_RATIONAL,                    # Exposure index
+                                       'SensingMethod' => MW_EXIF_SHORT,                       # Sensing method #p46
+                                       'FileSource' => MW_EXIF_UNDEFINED,                      # File source #p47
+                                       'SceneType' => MW_EXIF_UNDEFINED,                       # Scene type #p47
+                                       'CFAPattern' => MW_EXIF_UNDEFINED,                      # CFA pattern
+                                       'CustomRendered' => MW_EXIF_SHORT,                      # Custom image processing #p48
+                                       'ExposureMode' => MW_EXIF_SHORT,                        # Exposure mode #p48
+                                       'WhiteBalance' => MW_EXIF_SHORT,                        # White Balance #p49
+                                       'DigitalZoomRatio' => MW_EXIF_RATIONAL,                 # Digital zoom ration
+                                       'FocalLengthIn35mmFilm' => MW_EXIF_SHORT,               # Focal length in 35 mm film
+                                       'SceneCaptureType' => MW_EXIF_SHORT,                    # Scene capture type #p49
+                                       'GainControl' => MW_EXIF_RATIONAL,                      # Scene control #p49-50
+                                       'Contrast' => MW_EXIF_SHORT,                            # Contrast #p50
+                                       'Saturation' => MW_EXIF_SHORT,                          # Saturation #p50
+                                       'Sharpness' => MW_EXIF_SHORT,                           # Sharpness #p50
+                                       'DeviceSettingDescription' => MW_EXIF_UNDEFINED,        # Desice settings description
+                                       'SubjectDistanceRange' => MW_EXIF_SHORT,                # Subject distance range #p51
+                               ),
+                               
+                               'other' => array(
+                                       'ImageUniqueID' => MW_EXIF_ASCII,       # Unique image ID
+                               ),
+                       ),
+               
+                       # GPS Attribute Information (p52)
+                       'gps' => array(
+                               'GPSVersionID' => MW_EXIF_BYTE,                 # GPS tag version
+                               'GPSLatitudeRef' => MW_EXIF_ASCII,              # North or South Latitude #p52-53
+                               'GPSLatitude' => MW_EXIF_RATIONAL,              # Latitude
+                               'GPSLongitudeRef' => MW_EXIF_ASCII,             # East or West Longitude #p53
+                               'GPSLongitude' => MW_EXIF_RATIONAL,             # Longitude
+                               'GPSAltitudeRef' => MW_EXIF_BYTE,               # Altitude reference
+                               'GPSAltitude' => MW_EXIF_RATIONAL,              # Altitude
+                               'GPSTimeStamp' => MW_EXIF_RATIONAL,             # GPS time (atomic clock)
+                               'GPSSatellites' => MW_EXIF_ASCII,               # Satellites used for measurement
+                               'GPSStatus' => MW_EXIF_ASCII,                   # Receiver status #p54
+                               'GPSMeasureMode' => MW_EXIF_ASCII,              # Measurement mode #p54-55
+                               'GPSDOP' => MW_EXIF_RATIONAL,                   # Measurement precision
+                               'GPSSpeedRef' => MW_EXIF_ASCII,                 # Speed unit #p55
+                               'GPSSpeed' => MW_EXIF_RATIONAL,                 # Speed of GPS receiver
+                               'GPSTrackRef' => MW_EXIF_ASCII,                 # Reference for direction of movement #p55
+                               'GPSTrack' => MW_EXIF_RATIONAL,                 # Direction of movement
+                               'GPSImgDirectionRef' => MW_EXIF_ASCII,          # Reference for direction of image #p56
+                               'GPSImgDirection' => MW_EXIF_RATIONAL,          # Direction of image
+                               'GPSMapDatum' => MW_EXIF_ASCII,                 # Geodetic survey data used
+                               'GPSDestLatitudeRef' => MW_EXIF_ASCII,          # Reference for latitude of destination #p56
+                               'GPSDestLatitude' => MW_EXIF_RATIONAL,          # Latitude destination
+                               'GPSDestLongitudeRef' => MW_EXIF_ASCII,         # Reference for longitude of destination #p57
+                               'GPSDestLongitude' => MW_EXIF_RATIONAL,         # Longitude of destination
+                               'GPSDestBearingRef' => MW_EXIF_ASCII,           # Reference for bearing of destination #p57
+                               'GPSDestBearing' => MW_EXIF_RATIONAL,           # Bearing of destination
+                               'GPSDestDistanceRef' => MW_EXIF_ASCII,          # Reference for distance to destination #p57-58
+                               'GPSDestDistance' => MW_EXIF_RATIONAL,          # Distance to destination
+                               'GPSProcessingMethod' => MW_EXIF_UNDEFINED,     # Name of GPS processing method
+                               'GPSAreaInformation' => MW_EXIF_UNDEFINED,      # Name of GPS area
+                               'GPSDateStamp' => MW_EXIF_ASCII,                # GPS date
+                               'GPSDifferential' => MW_EXIF_SHORT,             # GPS differential correction
+                       ),
+               );
+
+               $this->makeFlatExifTags();
+               wfSuppressWarnings();
+               $this->mRawExifData = exif_read_data( $file );
+               wfRestoreWarnings();
+               $this->makeFilteredData();
+               $this->makeFormattedData();
+       }
+       
+       /**#@+
+        * @access private
+        */
+       /**
+        * Generate a flat list of the exif tags
+        */
+       function makeFlatExifTags() {
+               $this->extractTags( $this->mExifTags );
+       }
+       
+       /**
+        * A recursing extractor function used by makeFlatExifTags()
+        *
+        * Note: This used to use an array_walk function, but it made PHP5
+        * segfault, see `cvs diff -u -r 1.4 -r 1.5 Exif.php`
+        */
+       function extractTags( &$tagset ) {
+               foreach( $tagset as $key => $val ) {
+                       if( is_array( $val ) ) {
+                               $this->extractTags( $val );
+                       } else {
+                               $this->mFlatExifTags[$key] = $val;
+                       }
+               }
+       }
+       
+       /**
+        * Make $this->mFilteredExifData
+        */
+       function makeFilteredData() {
+               $this->mFilteredExifData = $this->mRawExifData;
+               
+               foreach( $this->mFilteredExifData as $k => $v ) {
+                       if ( !in_array( $k, array_keys( $this->mFlatExifTags ) ) ) {
+                               $this->debug( $v, __FUNCTION__, "'$k' is not a valid Exif tag" );
+                               unset( $this->mFilteredExifData[$k] );
+                       }
+               }
+
+               foreach( $this->mFilteredExifData as $k => $v ) {
+                       if ( !$this->validate($k, $v) ) {
+                               $this->debug( $v, __FUNCTION__, "'$k' contained invalid data" );
+                               unset( $this->mFilteredExifData[$k] );
+                       }
+               }
+       }
+
+       function makeFormattedData( $data = null ) {
+               $format = new FormatExif( $this->getFilteredData() );
+               $this->mFormattedExifData = $format->getFormattedData();
+       }
+       /**#@-*/
+
+       /**#@+
+        * @return array
+        */
+       /**
+        * Get $this->mRawExifData
+        */
+       function getData() {
+               return $this->mRawExifData;
+       }
+
+       /**
+        * Get $this->mFilteredExifData
+        */
+       function getFilteredData() {
+               return $this->mFilteredExifData;
+       }
+
+       /**
+        * Get $this->mFormattedExifData
+        */
+       function getFormattedData() {
+               return $this->mFormattedExifData;
+       }
+       /**#@-*/
+       
+       /**
+        * The version of the output format
+        *
+        * Before the actual metadata information is saved in the database we
+        * strip some of it since we don't want to save things like thumbnails
+        * which usually accompany Exif data. This value gets saved in the
+        * database along with the actual Exif data, and if the version in the
+        * database doesn't equal the value returned by this function the Exif
+        * data is regenerated.
+        *
+        * @return int
+        */
+       function version() {
+               return 1; // We don't need no bloddy constants!
+       }
+
+       /**#@+
+        * Validates if a tag value is of the type it should be according to the Exif spec
+        *
+        * @access private
+        *
+        * @param mixed $in The input value to check
+        * @return bool
+        */
+       function isByte( $in ) {
+               if ( sprintf('%d', $in) == $in && $in >= 0 && $in <= 255 ) {
+                       $this->debug( $in, __FUNCTION__, true );
+                       return true;
+               } else {
+                       $this->debug( $in, __FUNCTION__, false );
+                       return false;
+               }
+       }
+       
+       function isASCII( $in ) {
+               if ( preg_match( "/[^\x0a\x20-\x7e]/", $in ) ) {
+                       $this->debug( $in, __FUNCTION__, 'found a character not in our whitelist' );
+                       return false;
+               }
+               
+               if ( preg_match( "/^\s*$/", $in ) ) {
+                       $this->debug( $in, __FUNCTION__, 'input consisted solely of whitespace' );
+                       return false;
+               }
+               
+               return true;
+       }
+
+       function isShort( $in ) {
+               if ( sprintf('%d', $in) == $in && $in >= 0 && $in <= 65536 ) {
+                       $this->debug( $in, __FUNCTION__, true );
+                       return true;
+               } else {
+                       $this->debug( $in, __FUNCTION__, false );
+                       return false;
+               }
+       }
+
+       function isLong( $in ) {
+               if ( sprintf('%d', $in) == $in && $in >= 0 && $in <= 4294967296 ) {
+                       $this->debug( $in, __FUNCTION__, true );
+                       return true;
+               } else {
+                       $this->debug( $in, __FUNCTION__, false );
+                       return false;
+               }
+       }
+       
+       function isRational( $in ) {
+               if ( @preg_match( "/^(\d+)\/(\d+[1-9]|[1-9]\d*)$/", $in, $m ) ) { # Avoid division by zero
+                       return $this->isLong( $m[1] ) && $this->isLong( $m[2] );
+               } else {
+                       $this->debug( $in, __FUNCTION__, 'fed a non-fraction value' );
+                       return false;
+               }
+       }
+
+       function isUndefined( $in ) {
+               if ( preg_match( "/^\d{4}$/", $in ) ) { // Allow ExifVersion and FlashpixVersion
+                       $this->debug( $in, __FUNCTION__, true );
+                       return true;
+               } else {
+                       $this->debug( $in, __FUNCTION__, false );
+                       return false;
+               }
+       }
+
+       function isSlong( $in ) {
+               if ( $this->isLong( abs( $in ) ) ) {
+                       $this->debug( $in, __FUNCTION__, true );
+                       return true;
+               } else {
+                       $this->debug( $in, __FUNCTION__, false );
+                       return false;
+               }
+       }
+
+       function isSrational( $in ) {
+               if ( preg_match( "/^(\d+)\/(\d+[1-9]|[1-9]\d*)$/", $in, $m ) ) { # Avoid division by zero
+                       return $this->isSlong( $m[0] ) && $this->isSlong( $m[1] );
+               } else {
+                       $this->debug( $in, __FUNCTION__, 'fed a non-fraction value' );
+                       return false;
+               }
+       }
+       /**#@-*/
+
+       /**
+        * Validates if a tag has a legal value according to the Exif spec
+        *
+        * @access private
+        *
+        * @param string $tag The tag to check
+        * @param mixed  $val The value of the tag
+        * @return bool
+        */
+       function validate( $tag, $val ) {
+               $debug = "tag is '$tag'";
+               // Fucks up if not typecast 
+               switch( (string)$this->mFlatExifTags[$tag] ) {
+                       case (string)MW_EXIF_BYTE:
+                               $this->debug( $val, __FUNCTION__, $debug );
+                               return $this->isByte( $val );
+                       case (string)MW_EXIF_ASCII:
+                               $this->debug( $val, __FUNCTION__, $debug );
+                               return $this->isASCII( $val );
+                       case (string)MW_EXIF_SHORT:
+                               $this->debug( $val, __FUNCTION__, $debug );
+                               return $this->isShort( $val );
+                       case (string)MW_EXIF_LONG:
+                               $this->debug( $val, __FUNCTION__, $debug );
+                               return $this->isLong( $val );
+                       case (string)MW_EXIF_RATIONAL:
+                               $this->debug( $val, __FUNCTION__, $debug );
+                               return $this->isRational( $val );
+                       case (string)MW_EXIF_UNDEFINED:
+                               $this->debug( $val, __FUNCTION__, $debug );
+                               return $this->isUndefined( $val );
+                       case (string)MW_EXIF_SLONG:
+                               $this->debug( $val, __FUNCTION__, $debug );
+                               return $this->isSlong( $val );
+                       case (string)MW_EXIF_SRATIONAL:
+                               $this->debug( $val, __FUNCTION__, $debug );
+                               return $this->isSrational( $val );
+                       case (string)MW_EXIF_SHORT.','.MW_EXIF_LONG:
+                               $this->debug( $val, __FUNCTION__, $debug );
+                               return $this->isShort( $val ) || $this->isLong( $val );
+                       default:
+                               $this->debug( $val, __FUNCTION__, "The tag '$tag' is unknown" );
+                               return false;
+               }
+       }
+
+       /**
+        * Conviniance function for debugging output
+        *
+        * @access private
+        *
+        * @param mixed $in 
+        * @param string $fname
+        * @param mixed $action
+        */
+        function debug( $in, $fname, $action = null ) {
+               $type = gettype( $in );
+               $class = ucfirst( __CLASS__ );
+               if ( $type === 'array' )
+                       $in = print_r( $in, true ); 
+        
+               if ( $action === true )
+                       wfDebug( "$class::$fname: accepted: '$in' (type: $type)\n");
+               elseif ( $action === false ) 
+                       wfDebug( "$class::$fname: rejected: '$in' (type: $type)\n");
+               elseif ( $action === null )
+                       wfDebug( "$class::$fname: input was: '$in' (type: $type)\n");
+               else
+                       wfDebug( "$class::$fname: $action (type: $type; content: '$in')\n");
+       }
+
+}
+
+/**
+ * @package MediaWiki
+ * @subpackage Metadata
+ */
+class FormatExif {
+       /**
+        * The Exif data to format
+        *
+        * @var array
+        * @access private
+        */
+       var $mExif;
+       
+       /**
+        * Constructor
+        *
+        * @param array $exif The Exif data to format ( as returned by
+        *                    Exif::getFilteredData() )
+        */
+       function FormatExif( $exif ) {
+               $this->mExif = $exif;
+       }
+       
+       /**
+        * Numbers given by Exif user agents are often magical, that is they
+        * should be replaced by a detailed explanation depending on their
+        * value which most of the time are plain integers. This function
+        * formats Exif values into human readable form.
+        *
+        * @return array
+        */
+       function getFormattedData() {
+               global $wgLang;
+               
+               $tags =& $this->mExif;
+
+               $resolutionunit = !isset( $tags['ResolutionUnit'] ) || $tags['ResolutionUnit'] == 2 ? 2 : 3;
+               unset( $tags['ResolutionUnit'] );
+               
+               foreach( $tags as $tag => $val ) {
+                       switch( $tag ) {
+                       case 'Compression':
+                               switch( $val ) {
+                               case 1: case 6:
+                                       $tags[$tag] = $this->msg( $tag, $val );
+                                       break;
+                               default:
+                                       $tags[$tag] = $val;
+                                       break;
+                               }
+                               break;
+       
+                       case 'PhotometricInterpretation':
+                               switch( $val ) {
+                               case 2: case 6:
+                                       $tags[$tag] = $this->msg( $tag, $val );
+                                       break;
+                               default:
+                                       $tags[$tag] = $val;
+                                       break;
+                               }
+                               break;
+                       
+                       case 'Orientation':
+                               switch( $val ) {
+                               case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8:
+                                       $tags[$tag] = $this->msg( $tag, $val );
+                                       break;
+                               default:
+                                       $tags[$tag] = $val;
+                                       break;
+                               }
+                               break;
+                       
+                       case 'PlanarConfiguration':
+                               switch( $val ) {
+                               case 1: case 2:
+                                       $tags[$tag] = $this->msg( $tag, $val );
+                                       break;
+                               default:
+                                       $tags[$tag] = $val;
+                                       break;
+                               }
+                               break;
+                       
+                       // TODO: YCbCrSubSampling
+                       // TODO: YCbCrPositioning
+                       
+                       case 'XResolution':
+                       case 'YResolution':
+                               switch( $resolutionunit ) {
+                                       case 2:
+                                               $tags[$tag] = $this->msg( 'XYResolution', 'i', $this->formatNum( $val ) );
+                                               break;
+                                       case 3:
+                                               $this->msg( 'XYResolution', 'c', $this->formatNum( $val ) );
+                                               break;
+                                       default:
+                                               $tags[$tag] = $val;
+                                               break;
+                               }
+                               break;
+                               
+                       // TODO: YCbCrCoefficients  #p27 (see annex E)
+                       case 'ExifVersion': case 'FlashpixVersion':
+                               $tags[$tag] = "$val"/100;
+                               break;
+                       
+                       case 'ColorSpace':
+                               switch( $val ) {
+                               case 1: case 'FFFF.H':
+                                       $tags[$tag] = $this->msg( $tag, $val );
+                                       break;
+                               default:
+                                       $tags[$tag] = $val;
+                                       break;
+                               }
+                               break;
+                       
+                       case 'ComponentsConfiguration':
+                               switch( $val ) {
+                               case 0: case 1: case 2: case 3: case 4: case 5: case 6:
+                                       $tags[$tag] = $this->msg( $tag, $val );
+                                       break;
+                               default:
+                                       $tags[$tag] = $val;
+                                       break;
+                               }
+                               break;
+                       
+                       case 'DateTime':
+                       case 'DateTimeOriginal':
+                       case 'DateTimeDigitized':
+                               $tags[$tag] = $wgLang->timeanddate( wfTimestamp(TS_MW, $val) );
+                               break;
+                       
+                       case 'ExposureProgram':
+                               switch( $val ) {
+                               case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8:
+                                       $tags[$tag] = $this->msg( $tag, $val );
+                                       break;
+                               default:
+                                       $tags[$tag] = $val;
+                                       break;
+                               }
+                               break;
+
+                       case 'SubjectDistance':
+                               $tags[$tag] = $this->msg( $tag, '', $this->formatNum( $val ) );
+                               break;
+       
+                       case 'MeteringMode':
+                               switch( $val ) {
+                               case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 255:
+                                       $tags[$tag] = $this->msg( $tag, $val );
+                                       break;
+                               default:
+                                       $tags[$tag] = $val;
+                                       break;
+                               }
+                               break;
+       
+                       case 'LightSource':
+                               switch( $val ) {
+                               case 0: case 1: case 2: case 3: case 4: case 9: case 10: case 11:
+                               case 12: case 13: case 14: case 15: case 17: case 18: case 19: case 20:
+                               case 21: case 22: case 23: case 24: case 255:
+                                       $tags[$tag] = $this->msg( $tag, $val );
+                                       break;
+                               default:
+                                       $tags[$tag] = $val;
+                                       break;
+                               }
+                               break;
+       
+                       // TODO: Flash
+                       case 'FocalPlaneResolutionUnit':
+                               switch( $val ) {
+                               case 2:
+                                       $tags[$tag] = $this->msg( $tag, $val );
+                                       break;
+                               default:
+                                       $tags[$tag] = $val;
+                                       break;
+                               }
+                               break;
+                                               
+                       case 'SensingMethod':
+                               switch( $val ) {
+                               case 1: case 2: case 3: case 4: case 5: case 7: case 8:
+                                       $tags[$tag] = $this->msg( $tag, $val );
+                                       break;
+                               default:
+                                       $tags[$tag] = $val;
+                                       break;
+                               }
+                               break;
+       
+                       case 'FileSource':
+                               switch( $val ) {
+                               case 3:
+                                       $tags[$tag] = $this->msg( $tag, $val );
+                                       break;
+                               default:
+                                       $tags[$tag] = $val;
+                                       break;
+                               }
+                               break;
+       
+                       case 'SceneType':
+                               switch( $val ) {
+                               case 1:
+                                       $tags[$tag] = $this->msg( $tag, $val );
+                                       break;
+                               default:
+                                       $tags[$tag] = $val;
+                                       break;
+                               }
+                               break;
+       
+                       case 'CustomRendered':
+                               switch( $val ) {
+                               case 0: case 1:
+                                       $tags[$tag] = $this->msg( $tag, $val );
+                                       break;
+                               default:
+                                       $tags[$tag] = $val;
+                                       break;
+                               }
+                               break;
+       
+                       case 'ExposureMode':
+                               switch( $val ) {
+                               case 0: case 1: case 2:
+                                       $tags[$tag] = $this->msg( $tag, $val );
+                                       break;
+                               default:
+                                       $tags[$tag] = $val;
+                                       break;
+                               }
+                               break;
+       
+                       case 'WhiteBalance':
+                               switch( $val ) {
+                               case 0: case 1:
+                                       $tags[$tag] = $this->msg( $tag, $val );
+                                       break;
+                               default:
+                                       $tags[$tag] = $val;
+                                       break;
+                               }
+                               break;
+       
+                       case 'SceneCaptureType':
+                               switch( $val ) {
+                               case 0: case 1: case 2: case 3:
+                                       $tags[$tag] = $this->msg( $tag, $val );
+                                       break;
+                               default:
+                                       $tags[$tag] = $val;
+                                       break;
+                               }
+                               break;
+       
+                       case 'GainControl':
+                               switch( $val ) {
+                               case 0: case 1: case 2: case 3: case 4:
+                                       $tags[$tag] = $this->msg( $tag, $val );
+                                       break;
+                               default:
+                                       $tags[$tag] = $val;
+                                       break;
+                               }
+                               break;
+                               
+                       case 'Contrast':
+                               switch( $val ) {
+                               case 0: case 1: case 2:
+                                       $tags[$tag] = $this->msg( $tag, $val );
+                                       break;
+                               default:
+                                       $tags[$tag] = $val;
+                                       break;
+                               }
+                               break;
+                               
+                       case 'Saturation':
+                               switch( $val ) {
+                               case 0: case 1: case 2:
+                                       $tags[$tag] = $this->msg( $tag, $val );
+                                       break;
+                               default:
+                                       $tags[$tag] = $val;
+                                       break;
+                               }
+                               break;
+                               
+                       case 'Sharpness':
+                               switch( $val ) {
+                               case 0: case 1: case 2:
+                                       $tags[$tag] = $this->msg( $tag, $val );
+                                       break;
+                               default:
+                                       $tags[$tag] = $val;
+                                       break;
+                               }
+                               break;
+                               
+                       case 'SubjectDistanceRange':
+                               switch( $val ) {
+                               case 0: case 1: case 2: case 3:
+                                       $tags[$tag] = $this->msg( $tag, $val );
+                                       break;
+                               default:
+                                       $tags[$tag] = $val;
+                                       break;
+                               }
+                               break;
+                               
+                       case 'GPSLatitudeRef':
+                       case 'GPSDestLatitudeRef':
+                               switch( $val ) {
+                               case 'N': case 'S':
+                                       $tags[$tag] = $this->msg( 'GPSLatitude', $val );
+                                       break;
+                               default:
+                                       $tags[$tag] = $val;
+                                       break;
+                               }
+                               break;
+                               
+                       case 'GPSLongitudeRef':
+                       case 'GPSDestLongitudeRef':
+                               switch( $val ) {
+                               case 'E': case 'W':
+                                       $tags[$tag] = $this->msg( 'GPSLongitude', $val );
+                                       break;
+                               default:
+                                       $tags[$tag] = $val;
+                                       break;
+                               }
+                               break;
+                               
+                       case 'GPSStatus':
+                               switch( $val ) {
+                               case 'A': case 'V':
+                                       $tags[$tag] = $this->msg( $tag, $val );
+                                       break;
+                               default:
+                                       $tags[$tag] = $val;
+                                       break;
+                               }
+                               break;
+                               
+                       case 'GPSMeasureMode':
+                               switch( $val ) {
+                               case 2: case 3:
+                                       $tags[$tag] = $this->msg( $tag, $val );
+                                       break;
+                               default:
+                                       $tags[$tag] = $val;
+                                       break;
+                               }
+                               break;
+                               
+                       case 'GPSSpeedRef':
+                       case 'GPSDestDistanceRef':
+                               switch( $val ) {
+                               case 'K': case 'M': case 'N':
+                                       $tags[$tag] = $this->msg( 'GPSSpeed', $val );
+                                       break;
+                               default:
+                                       $tags[$tag] = $val;
+                                       break;
+                               }
+                               break;
+                               
+                       case 'GPSTrackRef':
+                       case 'GPSImgDirectionRef':
+                       case 'GPSDestBearingRef':
+                               switch( $val ) {
+                               case 'T': case 'M':
+                                       $tags[$tag] = $this->msg( 'GPSDirection', $val );
+                                       break;
+                               default:
+                                       $tags[$tag] = $val;
+                                       break;
+                               }
+                               break;
+                               
+                       case 'GPSDateStamp':
+                               $tags[$tag] = $wgLang->date( substr( $val, 0, 4 ) . substr( $val, 5, 2 ) . substr( $val, 8, 2 ) . '000000' );
+                               break;
+       
+                       // This is not in the Exif standard, just a special
+                       // case for our purposes which enables wikis to wikify
+                       // the make, model and software name to link to their articles.
+                       case 'Make':
+                       case 'Model':
+                       case 'Software':
+                               $tags[$tag] = $this->msg( $tag, '', $val );
+                               break;
+                       default:
+                               $tags[$tag] = $this->formatNum( $val );
+                               break;
+                       }
+               }
+
+               return $tags;
+       }
+
+       /**
+        * Conviniance function for getFormattedData()
+        *
+        * @access private
+        *
+        * @param string $tag The tag name to pass on
+        * @param string $val The value of the tag
+        * @param string $arg An argument to pass ($1)
+        * @return string A wfMsg of "exif-$tag-$val" in lower case
+        */
+       function msg( $tag, $val, $arg = null ) {
+               if ($val === '')
+                       $val = 'value';
+               return wfMsg( strtolower( "exif-$tag-$val" ), $arg );
+       }
+
+       /**
+        * Format a number, convert numbers from fractions into floating point
+        * numbers
+        *
+        * @access private
+        *
+        * @param mixed $num The value to format
+        * @return mixed A floating point number or whatever we were fed
+        */
+       function formatNum( $num ) {
+               if ( preg_match( '/^(\d+)\/(\d+)$/', $num, $m ) )
+                       return $m[2] != 0 ? $m[1] / $m[2] : $num;
+               else
+                       return $num;
+       }
+}
diff --git a/includes/ExternalEdit.php b/includes/ExternalEdit.php
new file mode 100644 (file)
index 0000000..e3effe6
--- /dev/null
@@ -0,0 +1,78 @@
+<?php
+/**
+ * License: Public domain
+ *
+ * @author Erik Moeller <moeller@scireview.de>
+ * @package MediaWiki
+ */
+
+/**
+ * 
+ * @package MediaWiki
+ *
+ * Support for external editors to modify both text and files
+ * in external applications. It works as follows: MediaWiki
+ * sends a meta-file with the MIME type 'application/x-external-editor'
+ * to the client. The user has to associate that MIME type with
+ * a helper application (a reference implementation in Perl
+ * can be found in extensions/ee), which will launch the editor,
+ * and save the modified data back to the server.
+ *
+ */
+class ExternalEdit {
+
+       function ExternalEdit ( $article, $mode ) {
+               global $wgInputEncoding;
+               $this->mArticle =& $article;
+               $this->mTitle =& $article->mTitle;
+               $this->mCharset = $wgInputEncoding;
+               $this->mMode = $mode;
+       }
+       
+       function edit() {
+               global $wgUser, $wgOut, $wgScript, $wgScriptPath, $wgServer,
+                      $wgLang;
+               $wgOut->disable();
+               $name=$this->mTitle->getText();
+               $pos=strrpos($name,".")+1;
+               header ( "Content-type: application/x-external-editor; charset=".$this->mCharset );
+               
+               # $type can be "Edit text", "Edit file" or "Diff text" at the moment
+               # See the protocol specifications at [[m:Help:External editors/Tech]] for
+               # details.
+               if(!isset($this->mMode)) {              
+                       $type="Edit text";              
+                       $url=$this->mTitle->getFullURL("action=edit&internaledit=true");
+                       # *.wiki file extension is used by some editors for syntax 
+                       # highlighting, so we follow that convention
+                       $extension="wiki"; 
+               } elseif($this->mMode=="file") {
+                       $type="Edit file"; 
+                       $image = Image::newFromTitle( $this->mTitle );
+                       $img_url = $image->getURL();
+                       if(strpos($img_url,"://")) {
+                               $url = $img_url;
+                       } else {
+                               $url = $wgServer . $img_url;
+                       }
+                       $extension=substr($name, $pos);
+               }
+               $special=$wgLang->getNsText(NS_SPECIAL);                 
+               $control = <<<CONTROL
+[Process]
+Type=$type
+Engine=MediaWiki
+Script={$wgServer}{$wgScript}
+Server={$wgServer}
+Path={$wgScriptPath}
+Special namespace=$special
+
+[File]
+Extension=$extension
+URL=$url
+CONTROL;
+               echo $control;
+       }
+}
+?>
diff --git a/includes/ExternalStore.php b/includes/ExternalStore.php
new file mode 100644 (file)
index 0000000..78e1b84
--- /dev/null
@@ -0,0 +1,44 @@
+<?php
+/**
+ * 
+ * @package MediaWiki
+ *
+ * Constructor class for data kept in external repositories
+ *
+ * External repositories might be populated by maintenance/async 
+ * scripts, thus partial moving of data may be possible, as well 
+ * as possibility to have any storage format (i.e. for archives)
+ *
+ */
+class ExternalStore {
+       /* Fetch data from given URL */
+       function fetchFromURL($url) {
+               global $wgExternalStores;
+
+               if (!$wgExternalStores) 
+                       return false;
+
+               @list($proto,$path)=explode('://',$url,2);
+               /* Bad URL */
+               if ($path=="") 
+                       return false;
+               /* Protocol not enabled */
+               if (!in_array( $proto, $wgExternalStores ))
+                       return false;
+
+               $class='ExternalStore'.ucfirst($proto);
+               /* Preloaded modules might exist, especially ones serving multiple protocols */
+               if (!class_exists($class)) {
+                       if (!include_once($class.'.php'))
+                               return false;   
+               }
+               $store=new $class();
+               return $store->fetchFromURL($url);
+       }
+
+       /* XXX: may require other methods, for store, delete, 
+        * whatever, for initial ext storage  
+        */
+}
+?>
diff --git a/includes/ExternalStoreDB.php b/includes/ExternalStoreDB.php
new file mode 100644 (file)
index 0000000..3c61726
--- /dev/null
@@ -0,0 +1,83 @@
+<?php
+/**
+ * 
+ * @package MediaWiki
+ *
+ * DB accessable external objects
+ *
+ */
+require_once( 'LoadBalancer.php' ); 
+
+
+/** @package MediaWiki */
+
+class ExternalStoreDB {
+       var $loadBalancers = array();
+       
+       /**
+        * Fetch data from given URL
+        * @param string $url An url
+        */
+
+       function &getLoadBalancer( $cluster ) {
+               global $wgExternalServers;
+               if ( !array_key_exists( $cluster, $this->loadBalancers ) ) {
+                       $this->loadBalancers[$cluster] = LoadBalancer::newFromParams( $wgExternalServers[$cluster] );
+               }
+               return $this->loadBalancers[$cluster];
+       }
+       
+       function &getSlave( $cluster ) {
+               $lb =& $this->getLoadBalancer( $cluster );
+               return $lb->getConnection( DB_SLAVE );
+       }
+
+       function &getMaster( $cluster ) {
+               $lb =& $this->getLoadBalancer( $cluster );
+               return $lb->getConnection( DB_MASTER );
+       }               
+       
+       function fetchFromURL($url) {
+               global $wgExternalServers;
+               #
+               # URLs have the form DB://cluster/id or DB://cluster/id/itemid for concatenated storage
+               #
+               $path = explode( '/', $url );
+               $cluster  = $path[2];
+               $id       = $path[3];
+               if ( isset( $path[4] ) ) {
+                       $itemID = $path[4];
+               } else {
+                       $itemID = false;
+               }
+
+               $dbr =& $this->getSlave( $cluster );
+               $ret = $dbr->selectField( 'blobs', 'blob_text', array( 'blob_id' => $id ) ); 
+
+               if ( $itemID !== false ) {
+                       # Unserialise object and get item
+                       $obj = unserialize( $ret );
+                       $ret = $obj->getItem( $itemID );
+               }
+               return $ret;
+       }
+
+       /**
+        * Insert a data item into a given cluster
+        *
+        * @param string $cluster The cluster name
+        * @param string $data The data item
+        * @return string URL
+        */
+       function store( $cluster, $data ) {
+               global $wgExternalServers;
+               $fname = 'ExternalStoreDB::store';
+
+               $dbw =& $this->getMaster( $cluster );
+
+               $id = $dbw->nextSequenceValue( 'blob_blob_id_seq' );
+               $dbw->insert( 'blobs', array( 'blob_id' => $id, 'blob_text' => $data ), $fname );
+               return "DB://$cluster/" . $dbw->insertId();
+       }
+}
+?>
diff --git a/includes/ExternalStoreHttp.php b/includes/ExternalStoreHttp.php
new file mode 100644 (file)
index 0000000..d7c1cc8
--- /dev/null
@@ -0,0 +1,23 @@
+<?php
+/**
+ * 
+ * @package MediaWiki
+ *
+ * Example class for HTTP accessable external objects
+ *
+ */
+class ExternalStoreHttp {
+       /* Fetch data from given URL */
+       function fetchFromURL($url) {
+        ini_set( "allow_url_fopen", true );
+        $ret = file_get_contents( $url );
+        ini_set( "allow_url_fopen", false );
+               return $ret;
+       }
+
+       /* XXX: may require other methods, for store, delete, 
+        * whatever, for initial ext storage  
+        */
+}
+?>
diff --git a/includes/Feed.php b/includes/Feed.php
new file mode 100644 (file)
index 0000000..6a28627
--- /dev/null
@@ -0,0 +1,285 @@
+<?php
+# Basic support for outputting syndication feeds in RSS, other formats
+# 
+# Copyright (C) 2004 Brion Vibber <brion@pobox.com>
+# http://www.mediawiki.org/
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or 
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# http://www.gnu.org/copyleft/gpl.html
+
+/**
+ * Contain a feed class as well as classes to build rss / atom ... feeds
+ * Available feeds are defined in Defines.php
+ * @package MediaWiki
+ */
+
+
+/**
+ * @todo document
+ * @package MediaWiki
+ */
+class FeedItem {
+       /**#@+
+        * @var string
+        * @access private
+        */
+       var $Title = 'Wiki';
+       var $Description = '';
+       var $Url = '';
+       var $Date = '';
+       var $Author = '';
+       /**#@-*/
+       
+       /**#@+
+        * @todo document
+        */
+       function FeedItem( $Title, $Description, $Url, $Date = '', $Author = '', $Comments = '' ) {
+               $this->Title = $Title;
+               $this->Description = $Description;
+               $this->Url = $Url;
+               $this->Date = $Date;
+               $this->Author = $Author;
+               $this->Comments = $Comments;
+       }
+       
+       /**
+        * @static
+        */
+       function xmlEncode( $string ) {
+               $string = str_replace( "\r\n", "\n", $string );
+               $string = preg_replace( '/[\x00-\x08\x0b\x0c\x0e-\x1f]/', '', $string );
+               return htmlspecialchars( $string );
+       }
+       
+       function getTitle() { return $this->xmlEncode( $this->Title ); }
+       function getUrl() { return $this->xmlEncode( $this->Url ); }
+       function getDescription() { return $this->xmlEncode( $this->Description ); }
+       function getLanguage() {
+               global $wgContLanguageCode;
+               return $wgContLanguageCode;
+       }
+       function getDate() { return $this->Date; }
+       function getAuthor() { return $this->xmlEncode( $this->Author ); }
+       function getComments() { return $this->xmlEncode( $this->Comments ); }
+       /**#@-*/
+}
+
+/**
+ * @todo document
+ * @package MediaWiki
+ */
+class ChannelFeed extends FeedItem {
+       /**#@+
+        * Abstract function, override!
+        * @abstract
+        */
+        
+       /**
+        * Generate Header of the feed
+        */
+       function outHeader() {
+               # print "<feed>";
+       }
+       
+       /**
+        * Generate an item
+        * @param $item
+        */
+       function outItem( $item ) {
+               # print "<item>...</item>";
+       }
+       
+       /**
+        * Generate Footer of the feed
+        */
+       function outFooter() {
+               # print "</feed>";
+       }
+       /**#@-*/
+       
+       /**
+        * Setup and send HTTP headers. Don't send any content;
+        * content might end up being cached and re-sent with
+        * these same headers later.
+        *
+        * This should be called from the outHeader() method,
+        * but can also be called separately.
+        *
+        * @access public
+        */
+       function httpHeaders() {
+               global $wgOut;
+               
+               # We take over from $wgOut, excepting its cache header info
+               $wgOut->disable();
+               $mimetype = $this->contentType();
+               header( "Content-type: $mimetype; charset=UTF-8" );
+               $wgOut->sendCacheControl();
+               
+       }
+       
+       /**
+        * Return an internet media type to be sent in the headers.
+        *
+        * @return string
+        * @access private
+        */
+       function contentType() {
+               global $wgRequest;
+               $ctype = $wgRequest->getVal('ctype','application/xml');
+               $allowedctypes = array('application/xml','text/xml','application/rss+xml','application/atom+xml');
+               return (in_array($ctype, $allowedctypes) ? $ctype : 'application/xml');
+       }
+       
+       /**
+        * Output the initial XML headers with a stylesheet for legibility
+        * if someone finds it in a browser.
+        * @access private
+        */
+       function outXmlHeader() {
+               global $wgServer, $wgStylePath;
+               
+               $this->httpHeaders();
+               echo '<?xml version="1.0" encoding="utf-8"?' . ">\n";
+               echo '<?xml-stylesheet type="text/css" href="' .
+                       htmlspecialchars( "$wgServer$wgStylePath/common/feed.css" ) . '"?' . ">\n";
+       }
+}
+
+/**
+ * Generate a RSS feed
+ * @todo document
+ * @package MediaWiki
+ */
+class RSSFeed extends ChannelFeed {
+
+       /**
+        * Format a date given a timestamp
+        * @param integer $ts Timestamp
+        * @return string Date string
+        */
+       function formatTime( $ts ) {
+               return gmdate( 'D, d M Y H:i:s \G\M\T', wfTimestamp( TS_UNIX, $ts ) );
+       }
+       
+       /**
+        * Ouput an RSS 2.0 header
+        */
+       function outHeader() {
+               global $wgVersion;
+               
+               $this->outXmlHeader();
+               ?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
+       <channel>
+               <title><?php print $this->getTitle() ?></title>
+               <link><?php print $this->getUrl() ?></link>
+               <description><?php print $this->getDescription() ?></description>
+               <language><?php print $this->getLanguage() ?></language>
+               <generator>MediaWiki <?php print $wgVersion ?></generator>
+               <lastBuildDate><?php print $this->formatTime( wfTimestampNow() ) ?></lastBuildDate>
+<?php
+       }
+       
+       /**
+        * Output an RSS 2.0 item
+        * @param FeedItem item to be output
+        */
+       function outItem( $item ) {
+       ?>
+               <item>
+                       <title><?php print $item->getTitle() ?></title>
+                       <link><?php print $item->getUrl() ?></link>
+                       <description><?php print $item->getDescription() ?></description>
+                       <?php if( $item->getDate() ) { ?><pubDate><?php print $this->formatTime( $item->getDate() ) ?></pubDate><?php } ?>
+                       <?php if( $item->getAuthor() ) { ?><dc:creator><?php print $item->getAuthor() ?></dc:creator><?php }?>
+                       <?php if( $item->getComments() ) { ?><comments><?php print $item->getComments() ?></comments><?php }?>
+               </item>
+<?php
+       }
+
+       /**
+        * Ouput an RSS 2.0 footer
+        */
+       function outFooter() {
+       ?>
+       </channel>
+</rss><?php
+       }
+}
+
+/**
+ * Generate an Atom feed
+ * @todo document
+ * @package MediaWiki
+ */
+class AtomFeed extends ChannelFeed {
+       /**
+        * @todo document
+        */
+       function formatTime( $ts ) {
+               // need to use RFC 822 time format at least for rss2.0
+               return gmdate( 'Y-m-d\TH:i:s', wfTimestamp( TS_UNIX, $ts ) );
+       }
+
+       /**
+        * @todo document
+        */
+       function outHeader() {
+               global $wgVersion, $wgOut;
+               
+               $this->outXmlHeader();
+               ?><feed version="0.3" xmlns="http://purl.org/atom/ns#" xml:lang="<?php print $this->getLanguage() ?>">  
+               <title><?php print $this->getTitle() ?></title>
+               <link rel="alternate" type="text/html" href="<?php print $this->getUrl() ?>"/>
+               <modified><?php print $this->formatTime( wfTimestampNow() ) ?>Z</modified>
+               <tagline><?php print $this->getDescription() ?></tagline>
+               <generator>MediaWiki <?php print $wgVersion ?></generator>
+               
+<?php
+       }
+       
+       /**
+        * @todo document
+        */
+       function outItem( $item ) {
+               global $wgMimeType;
+       ?>
+       <entry>
+               <title><?php print $item->getTitle() ?></title>
+               <link rel="alternate" type="<?php print $wgMimeType ?>" href="<?php print $item->getUrl() ?>"/>
+               <?php if( $item->getDate() ) { ?>
+               <modified><?php print $this->formatTime( $item->getDate() ) ?>Z</modified>
+               <issued><?php print $this->formatTime( $item->getDate() ) ?></issued>
+               <created><?php print $this->formatTime( $item->getDate() ) ?>Z</created><?php } ?>
+       
+               <summary type="text/plain"><?php print $item->getDescription() ?></summary>
+               <?php if( $item->getAuthor() ) { ?><author><name><?php print $item->getAuthor() ?></name><!-- <url></url><email></email> --></author><?php }?>
+               <comment>foobar</comment>
+       </entry>
+
+<?php /* FIXME need to add comments
+       <?php if( $item->getComments() ) { ?><dc:comment><?php print $item->getComments() ?></dc:comment><?php }?>
+      */
+       }
+       
+       /**
+        * @todo document
+        */
+       function outFooter() {?>
+       </feed><?php
+       }
+}
+
+?>
diff --git a/includes/FulltextStoplist.php b/includes/FulltextStoplist.php
new file mode 100644 (file)
index 0000000..dba92dc
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+/**
+ * This is the MySQL fulltext search stoplist, copied from the
+ * source file "myisam/ft_static.c" in version 4.1.8 of MySQL
+ * If you use a later version of MySQL, it might have to be changed.
+ *
+ * The list is used to strip out stopwords from search queries to avoid
+ * nulling out the combined search results when using MySQL 3.x.
+ * @package MediaWiki
+ * @subpackage Search
+ */
+
+/**
+ * Words are separated by spaces (could be any character) so when doing search,
+ * we search for a word with a space appended at the end and in front of a word.
+ * @global string Provide a list of english words for MySQL 3.x
+ * @private
+ */
+global $wgFulltextStoplist;
+$wgFulltextStoplist = " a's able about above according accordingly across actually after afterwards again against ain't all allow allows almost alone along already also although always am among amongst an and another any anybody anyhow anyone anything anyway anyways anywhere apart appear appreciate appropriate are aren't around as aside ask asking associated at available away awfully be became because become becomes becoming been before beforehand behind being believe below beside besides best better between beyond both brief but by c'mon c's came can can't cannot cant cause causes certain certainly changes clearly co com come comes concerning consequently consider considering contain containing contains corresponding could couldn't course currently definitely described despite did didn't different do does doesn't doing don't done down downwards during each edu eg eight either else elsewhere enough entirely especially et etc even ever every everybody everyone everything everywhere ex exactly example except far few fifth first five followed following follows for former formerly forth four from further furthermore get gets getting given gives go goes going gone got gotten greetings had hadn't happens hardly has hasn't have haven't having he he's hello help hence her here here's hereafter hereby herein hereupon hers herself hi him himself his hither hopefully how howbeit however i'd i'll i'm i've ie if ignored immediate in inasmuch inc indeed indicate indicated indicates inner insofar instead into inward is isn't it it'd it'll it's its itself just keep keeps kept know knows known last lately later latter latterly least less lest let let's like liked likely little look looking looks ltd mainly many may maybe me mean meanwhile merely might more moreover most mostly much must my myself name namely nd near nearly necessary need needs neither never nevertheless new next nine no nobody non none noone nor normally not nothing novel now nowhere obviously of off often oh ok okay old on once one ones only onto or other others otherwise ought our ours ourselves out outside over overall own particular particularly per perhaps placed please plus possible presumably probably provides que quite qv rather rd re really reasonably regarding regardless regards relatively respectively right said same saw say saying says second secondly see seeing seem seemed seeming seems seen self selves sensible sent serious seriously seven several shall she should shouldn't since six so some somebody somehow someone something sometime sometimes somewhat somewhere soon sorry specified specify specifying still sub such sup sure t's take taken tell tends th than thank thanks thanx that that's thats the their theirs them themselves then thence there there's thereafter thereby therefore therein theres thereupon these they they'd they'll they're they've think third this thorough thoroughly those though three through throughout thru thus to together too took toward towards tried tries truly try trying twice two un under unfortunately unless unlikely until unto up upon us use used useful uses using usually value various very via viz vs want wants was wasn't way we we'd we'll we're we've welcome well went were weren't what what's whatever when whence whenever where where's whereafter whereas whereby wherein whereupon wherever whether which while whither who who's whoever whole whom whose why will willing wish with within without won't wonder would would wouldn't yes yet you you'd you'll you're you've your yours yourself yourselves zero ";
+
+/**
+ * @package MediaWiki
+ */
+class FulltextStoplist {
+
+       /**
+        * @static
+        */
+       function inList( $word )
+       {
+               global $wgFulltextStoplist;
+               # FIXME: this will fail badly in many circumstances
+               $w = strtolower( $word );
+               $w = preg_replace( "/[^a-z']+/", "", $w );
+               return strpos( $wgFulltextStoplist, " $w " );
+       }
+}
+
+?>
diff --git a/includes/GlobalFunctions.php b/includes/GlobalFunctions.php
new file mode 100644 (file)
index 0000000..f012d3c
--- /dev/null
@@ -0,0 +1,1384 @@
+<?php
+
+/**
+ * Global functions used everywhere
+ * @package MediaWiki
+ */
+
+/**
+ * Some globals and requires needed
+ */
+/**
+ * Total number of articles
+ * @global integer $wgNumberOfArticles
+ */
+$wgNumberOfArticles = -1; # Unset
+/**
+ * Total number of views
+ * @global integer $wgTotalViews
+ */
+$wgTotalViews = -1;
+/**
+ * Total number of edits
+ * @global integer $wgTotalEdits
+ */
+$wgTotalEdits = -1;
+
+
+require_once( 'DatabaseFunctions.php' );
+require_once( 'UpdateClasses.php' );
+require_once( 'LogPage.php' );
+require_once( 'normal/UtfNormalUtil.php' );
+
+/**
+ * Compatibility functions
+ * PHP <4.3.x is not actively supported; 4.1.x and 4.2.x might or might not work.
+ * <4.1.x will not work, as we use a number of features introduced in 4.1.0
+ * such as the new autoglobals.
+ */
+if( !function_exists('iconv') ) {
+       # iconv support is not in the default configuration and so may not be present.
+       # Assume will only ever use utf-8 and iso-8859-1.
+       # This will *not* work in all circumstances.
+       function iconv( $from, $to, $string ) {
+               if(strcasecmp( $from, $to ) == 0) return $string;
+               if(strcasecmp( $from, 'utf-8' ) == 0) return utf8_decode( $string );
+               if(strcasecmp( $to, 'utf-8' ) == 0) return utf8_encode( $string );
+               return $string;
+       }
+}
+
+if( !function_exists('file_get_contents') ) {
+       # Exists in PHP 4.3.0+
+       function file_get_contents( $filename ) {
+               return implode( '', file( $filename ) );
+       }
+}
+
+if( !function_exists('is_a') ) {
+       # Exists in PHP 4.2.0+
+       function is_a( $object, $class_name ) {
+               return
+                       (strcasecmp( get_class( $object ), $class_name ) == 0) ||
+                        is_subclass_of( $object, $class_name );
+       }
+}
+
+# UTF-8 substr function based on a PHP manual comment
+if ( !function_exists( 'mb_substr' ) ) {
+       function mb_substr( $str, $start ) { 
+               preg_match_all( '/./us', $str, $ar );
+
+               if( func_num_args() >= 3 ) {
+                       $end = func_get_arg( 2 ); 
+                       return join( '', array_slice( $ar[0], $start, $end ) ); 
+               } else { 
+                       return join( '', array_slice( $ar[0], $start ) ); 
+               }
+       }
+}
+
+if( !function_exists( 'floatval' ) ) {
+       /**
+        * First defined in PHP 4.2.0
+        * @param mixed $var;
+        * @return float
+        */
+       function floatval( $var ) {
+               return (float)$var;
+       }
+}
+
+/**
+ * Where as we got a random seed
+ * @var bool $wgTotalViews
+ */
+$wgRandomSeeded = false;
+
+/**
+ * Seed Mersenne Twister
+ * Only necessary in PHP < 4.2.0
+ *
+ * @return bool
+ */
+function wfSeedRandom() {
+       global $wgRandomSeeded;
+
+       if ( ! $wgRandomSeeded && version_compare( phpversion(), '4.2.0' ) < 0 ) {
+               $seed = hexdec(substr(md5(microtime()),-8)) & 0x7fffffff;
+               mt_srand( $seed );
+               $wgRandomSeeded = true;
+       }
+}
+
+/**
+ * Get a random decimal value between 0 and 1, in a way
+ * not likely to give duplicate values for any realistic
+ * number of articles.
+ *
+ * @return string
+ */
+function wfRandom() {
+       # The maximum random value is "only" 2^31-1, so get two random
+       # values to reduce the chance of dupes
+       $max = mt_getrandmax();
+       $rand = number_format( (mt_rand() * $max + mt_rand())
+               / $max / $max, 12, '.', '' );
+       return $rand;
+}
+
+/**
+ * We want / and : to be included as literal characters in our title URLs.
+ * %2F in the page titles seems to fatally break for some reason.
+ *
+ * @param string $s
+ * @return string
+*/
+function wfUrlencode ( $s ) {
+       $s = urlencode( $s );
+       $s = preg_replace( '/%3[Aa]/', ':', $s );
+       $s = preg_replace( '/%2[Ff]/', '/', $s );
+
+       return $s;
+}
+
+/**
+ * Sends a line to the debug log if enabled or, optionally, to a comment in output.
+ * In normal operation this is a NOP.
+ *
+ * Controlling globals:
+ * $wgDebugLogFile - points to the log file
+ * $wgProfileOnly - if set, normal debug messages will not be recorded.
+ * $wgDebugRawPage - if false, 'action=raw' hits will not result in debug output.
+ * $wgDebugComments - if on, some debug items may appear in comments in the HTML output.
+ *
+ * @param string $text
+ * @param bool $logonly Set true to avoid appearing in HTML when $wgDebugComments is set
+ */
+function wfDebug( $text, $logonly = false ) {
+       global $wgOut, $wgDebugLogFile, $wgDebugComments, $wgProfileOnly, $wgDebugRawPage;
+
+       # Check for raw action using $_GET not $wgRequest, since the latter might not be initialised yet
+       if ( isset( $_GET['action'] ) && $_GET['action'] == 'raw' && !$wgDebugRawPage ) {
+               return;
+       }
+
+       if ( isset( $wgOut ) && $wgDebugComments && !$logonly ) {
+               $wgOut->debug( $text );
+       }
+       if ( '' != $wgDebugLogFile && !$wgProfileOnly ) {
+               # Strip unprintables; they can switch terminal modes when binary data
+               # gets dumped, which is pretty annoying.
+               $text = preg_replace( '![\x00-\x08\x0b\x0c\x0e-\x1f]!', ' ', $text );
+               @error_log( $text, 3, $wgDebugLogFile );
+       }
+}
+
+/**
+ * Send a line to a supplementary debug log file, if configured, or main debug log if not.
+ * $wgDebugLogGroups[$logGroup] should be set to a filename to send to a separate log.
+ * @param string $logGroup
+ * @param string $text
+ */
+function wfDebugLog( $logGroup, $text ) {
+       global $wgDebugLogGroups, $wgDBname;
+       if( $text{strlen( $text ) - 1} != "\n" ) $text .= "\n";
+       if( isset( $wgDebugLogGroups[$logGroup] ) ) {
+               @error_log( "$wgDBname: $text", 3, $wgDebugLogGroups[$logGroup] );
+       } else {
+               wfDebug( $text, true );
+       }
+}
+
+/**
+ * Log for database errors
+ * @param string $text Database error message.
+ */
+function wfLogDBError( $text ) {
+       global $wgDBerrorLog;
+       if ( $wgDBerrorLog ) {
+               $text = date('D M j G:i:s T Y') . "\t".$text;
+               error_log( $text, 3, $wgDBerrorLog );
+       }
+}
+
+/**
+ * @todo document
+ */
+function logProfilingData() {
+       global $wgRequestTime, $wgDebugLogFile, $wgDebugRawPage, $wgRequest;
+       global $wgProfiling, $wgProfileStack, $wgProfileLimit, $wgUser;
+       $now = wfTime();
+
+       list( $usec, $sec ) = explode( ' ', $wgRequestTime );
+       $start = (float)$sec + (float)$usec;
+       $elapsed = $now - $start;
+       if ( $wgProfiling ) {
+               $prof = wfGetProfilingOutput( $start, $elapsed );
+               $forward = '';
+               if( !empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) )
+                       $forward = ' forwarded for ' . $_SERVER['HTTP_X_FORWARDED_FOR'];
+               if( !empty( $_SERVER['HTTP_CLIENT_IP'] ) )
+                       $forward .= ' client IP ' . $_SERVER['HTTP_CLIENT_IP'];
+               if( !empty( $_SERVER['HTTP_FROM'] ) )
+                       $forward .= ' from ' . $_SERVER['HTTP_FROM'];
+               if( $forward )
+                       $forward = "\t(proxied via {$_SERVER['REMOTE_ADDR']}{$forward})";
+               if( $wgUser->isAnon() )
+                       $forward .= ' anon';
+               $log = sprintf( "%s\t%04.3f\t%s\n",
+                 gmdate( 'YmdHis' ), $elapsed,
+                 urldecode( $_SERVER['REQUEST_URI'] . $forward ) );
+               if ( '' != $wgDebugLogFile && ( $wgRequest->getVal('action') != 'raw' || $wgDebugRawPage ) ) {
+                       error_log( $log . $prof, 3, $wgDebugLogFile );
+               }
+       }
+}
+
+/**
+ * Check if the wiki read-only lock file is present. This can be used to lock
+ * off editing functions, but doesn't guarantee that the database will not be
+ * modified.
+ * @return bool
+ */
+function wfReadOnly() {
+       global $wgReadOnlyFile, $wgReadOnly;
+
+       if ( !is_null( $wgReadOnly ) ) {
+               return (bool)$wgReadOnly;
+       }
+       if ( '' == $wgReadOnlyFile ) {
+               return false;
+       }
+       
+       // Set $wgReadOnly for faster access next time
+       if ( is_file( $wgReadOnlyFile ) ) {
+               $wgReadOnly = file_get_contents( $wgReadOnlyFile );
+       } else {
+               $wgReadOnly = false;
+       }
+       return $wgReadOnly;
+}
+
+
+/**
+ * Get a message from anywhere, for the current user language
+ *
+ * @param string 
+ */
+function wfMsg( $key ) {
+       $args = func_get_args();
+       array_shift( $args );
+       return wfMsgReal( $key, $args, true );
+}
+
+/**
+ * Get a message from anywhere, for the current global language
+ */
+function wfMsgForContent( $key ) {
+       global $wgForceUIMsgAsContentMsg;
+       $args = func_get_args();
+       array_shift( $args );
+       $forcontent = true;
+       if( is_array( $wgForceUIMsgAsContentMsg ) &&
+               in_array( $key, $wgForceUIMsgAsContentMsg ) )
+               $forcontent = false;
+       return wfMsgReal( $key, $args, true, $forcontent );
+}
+
+/**
+ * Get a message from the language file, for the UI elements
+ */
+function wfMsgNoDB( $key ) {
+       $args = func_get_args();
+       array_shift( $args );
+       return wfMsgReal( $key, $args, false );
+}
+
+/**
+ * Get a message from the language file, for the content
+ */
+function wfMsgNoDBForContent( $key ) {
+       global $wgForceUIMsgAsContentMsg;
+       $args = func_get_args();
+       array_shift( $args );
+       $forcontent = true;
+       if( is_array( $wgForceUIMsgAsContentMsg ) &&
+               in_array( $key, $wgForceUIMsgAsContentMsg ) )
+               $forcontent = false;
+       return wfMsgReal( $key, $args, false, $forcontent );
+}
+
+
+/**
+ * Really get a message
+ */
+function wfMsgReal( $key, $args, $useDB, $forContent=false ) {
+       $fname = 'wfMsgReal';
+       wfProfileIn( $fname );
+       
+       $message = wfMsgGetKey( $key, $useDB, $forContent );
+       $message = wfMsgReplaceArgs( $message, $args );
+       wfProfileOut( $fname );
+       return $message;
+}
+
+/**
+ * Fetch a message string value, but don't replace any keys yet.
+ * @param string $key
+ * @param bool $useDB
+ * @param bool $forContent
+ * @return string
+ * @access private
+ */
+function wfMsgGetKey( $key, $useDB, $forContent = false ) {
+       global $wgParser, $wgMsgParserOptions;
+       global $wgContLang, $wgLanguageCode;
+       global $wgMessageCache, $wgLang;
+       
+       if( is_object( $wgMessageCache ) ) {
+               $message = $wgMessageCache->get( $key, $useDB, $forContent );
+       } else {
+               if( $forContent ) {
+                       $lang = &$wgContLang;
+               } else {
+                       $lang = &$wgLang;
+               }
+
+               wfSuppressWarnings();
+               
+               if( is_object( $lang ) ) {
+                       $message = $lang->getMessage( $key );
+               } else {
+                       $message = '';
+               }
+               wfRestoreWarnings();
+               if(!$message)
+                       $message = Language::getMessage($key);
+               if(strstr($message, '{{' ) !== false) {
+                       $message = $wgParser->transformMsg($message, $wgMsgParserOptions);
+               }
+       }
+       return $message;
+}
+
+/**
+ * Replace message parameter keys on the given formatted output.
+ *
+ * @param string $message
+ * @param array $args
+ * @return string
+ * @access private
+ */
+function wfMsgReplaceArgs( $message, $args ) {
+       static $replacementKeys = array( '$1', '$2', '$3', '$4', '$5', '$6', '$7', '$8', '$9' );
+       
+       # Fix windows line-endings
+       # Some messages are split with explode("\n", $msg)
+       $message = str_replace( "\r", '', $message );
+
+       # Replace arguments
+       if( count( $args ) ) {
+               $message = str_replace( $replacementKeys, $args, $message );
+       }
+       return $message;
+}
+
+/**
+ * Return an HTML-escaped version of a message.
+ * Parameter replacements, if any, are done *after* the HTML-escaping,
+ * so parameters may contain HTML (eg links or form controls). Be sure
+ * to pre-escape them if you really do want plaintext, or just wrap
+ * the whole thing in htmlspecialchars().
+ *
+ * @param string $key
+ * @param string ... parameters
+ * @return string
+ */
+function wfMsgHtml( $key ) {
+       $args = func_get_args();
+       array_shift( $args );
+       return wfMsgReplaceArgs( htmlspecialchars( wfMsgGetKey( $key, true ) ), $args );
+}
+
+/**
+ * Just like exit() but makes a note of it.
+ * Commits open transactions except if the error parameter is set
+ */
+function wfAbruptExit( $error = false ){
+       global $wgLoadBalancer;
+       static $called = false;
+       if ( $called ){
+               exit();
+       }
+       $called = true;
+
+       if( function_exists( 'debug_backtrace' ) ){ // PHP >= 4.3
+               $bt = debug_backtrace();
+               for($i = 0; $i < count($bt) ; $i++){
+                       $file = isset($bt[$i]['file']) ? $bt[$i]['file'] : "unknown";
+                       $line = isset($bt[$i]['line']) ? $bt[$i]['line'] : "unknown";
+                       wfDebug("WARNING: Abrupt exit in $file at line $line\n");
+               }
+       } else {
+               wfDebug('WARNING: Abrupt exit\n');
+       }
+       if ( !$error ) {
+               $wgLoadBalancer->closeAll();
+       }
+       exit();
+}
+
+/**
+ * @todo document
+ */
+function wfErrorExit() {
+       wfAbruptExit( true );
+}
+
+/**
+ * Die with a backtrace
+ * This is meant as a debugging aid to track down where bad data comes from.
+ * Shouldn't be used in production code except maybe in "shouldn't happen" areas.
+ *
+ * @param string $msg Message shown when dieing.
+ */
+function wfDebugDieBacktrace( $msg = '' ) {
+       global $wgCommandLineMode;
+
+       $backtrace = wfBacktrace();
+       if ( $backtrace !== false ) {
+               if ( $wgCommandLineMode ) {
+                       $msg .= "\nBacktrace:\n$backtrace";
+               } else {
+                       $msg .= "\n<p>Backtrace:</p>\n$backtrace";
+               }
+        }
+        echo $msg;
+        die( -1 );
+}
+
+function wfBacktrace() {
+       global $wgCommandLineMode;
+       if ( !function_exists( 'debug_backtrace' ) ) {
+               return false;
+       }
+       
+       if ( $wgCommandLineMode ) {
+               $msg = '';
+       } else {
+               $msg = "<ul>\n";
+       }
+       $backtrace = debug_backtrace();
+       foreach( $backtrace as $call ) {
+               if( isset( $call['file'] ) ) {
+                       $f = explode( DIRECTORY_SEPARATOR, $call['file'] );
+                       $file = $f[count($f)-1];
+               } else {
+                       $file = '-';
+               }
+               if( isset( $call['line'] ) ) {
+                       $line = $call['line'];
+               } else {
+                       $line = '-';
+               }
+               if ( $wgCommandLineMode ) {
+                       $msg .= "$file line $line calls ";
+               } else {
+                       $msg .= '<li>' . $file . ' line ' . $line . ' calls ';
+               }
+               if( !empty( $call['class'] ) ) $msg .= $call['class'] . '::';
+               $msg .= $call['function'] . '()';
+
+               if ( $wgCommandLineMode ) {
+                       $msg .= "\n";
+               } else {
+                       $msg .= "</li>\n";
+               }
+       }
+       if ( $wgCommandLineMode ) {
+               $msg .= "\n";
+       } else {
+               $msg .= "</ul>\n";
+       }
+
+       return $msg;
+}
+
+
+/* Some generic result counters, pulled out of SearchEngine */
+
+
+/**
+ * @todo document
+ */
+function wfShowingResults( $offset, $limit ) {
+       global $wgLang;
+       return wfMsg( 'showingresults', $wgLang->formatNum( $limit ), $wgLang->formatNum( $offset+1 ) );
+}
+
+/**
+ * @todo document
+ */
+function wfShowingResultsNum( $offset, $limit, $num ) {
+       global $wgLang;
+       return wfMsg( 'showingresultsnum', $wgLang->formatNum( $limit ), $wgLang->formatNum( $offset+1 ), $wgLang->formatNum( $num ) );
+}
+
+/**
+ * @todo document
+ */
+function wfViewPrevNext( $offset, $limit, $link, $query = '', $atend = false ) {
+       global $wgUser, $wgLang;
+       $fmtLimit = $wgLang->formatNum( $limit );
+       $prev = wfMsg( 'prevn', $fmtLimit );
+       $next = wfMsg( 'nextn', $fmtLimit );
+       
+       if( is_object( $link ) ) {
+               $title =& $link;
+       } else {
+               $title = Title::newFromText( $link );
+               if( is_null( $title ) ) {
+                       return false;
+               }
+       }
+       
+       $sk = $wgUser->getSkin();
+       if ( 0 != $offset ) {
+               $po = $offset - $limit;
+               if ( $po < 0 ) { $po = 0; }
+               $q = "limit={$limit}&offset={$po}";
+               if ( '' != $query ) { $q .= '&'.$query; }
+               $plink = '<a href="' . $title->escapeLocalUrl( $q ) . "\">{$prev}</a>";
+       } else { $plink = $prev; }
+
+       $no = $offset + $limit;
+       $q = 'limit='.$limit.'&offset='.$no;
+       if ( '' != $query ) { $q .= '&'.$query; }
+
+       if ( $atend ) {
+               $nlink = $next;
+       } else {
+               $nlink = '<a href="' . $title->escapeLocalUrl( $q ) . "\">{$next}</a>";
+       }
+       $nums = wfNumLink( $offset, 20, $title, $query ) . ' | ' .
+         wfNumLink( $offset, 50, $title, $query ) . ' | ' .
+         wfNumLink( $offset, 100, $title, $query ) . ' | ' .
+         wfNumLink( $offset, 250, $title, $query ) . ' | ' .
+         wfNumLink( $offset, 500, $title, $query );
+
+       return wfMsg( 'viewprevnext', $plink, $nlink, $nums );
+}
+
+/**
+ * @todo document
+ */
+function wfNumLink( $offset, $limit, &$title, $query = '' ) {
+       global $wgUser, $wgLang;
+       if ( '' == $query ) { $q = ''; }
+       else { $q = $query.'&'; }
+       $q .= 'limit='.$limit.'&offset='.$offset;
+
+       $fmtLimit = $wgLang->formatNum( $limit );
+       $s = '<a href="' . $title->escapeLocalUrl( $q ) . "\">{$fmtLimit}</a>";
+       return $s;
+}
+
+/**
+ * @todo document
+ * @todo FIXME: we may want to blacklist some broken browsers
+ *
+ * @return bool Whereas client accept gzip compression
+ */
+function wfClientAcceptsGzip() {
+       global $wgUseGzip;
+       if( $wgUseGzip ) {
+               # FIXME: we may want to blacklist some broken browsers
+               if( preg_match(
+                       '/\bgzip(?:;(q)=([0-9]+(?:\.[0-9]+)))?\b/',
+                       $_SERVER['HTTP_ACCEPT_ENCODING'],
+                       $m ) ) {
+                       if( isset( $m[2] ) && ( $m[1] == 'q' ) && ( $m[2] == 0 ) ) return false;
+                       wfDebug( " accepts gzip\n" );
+                       return true;
+               }
+       }
+       return false;
+}
+
+/**
+ * Yay, more global functions!
+ */
+function wfCheckLimits( $deflimit = 50, $optionname = 'rclimit' ) {
+       global $wgRequest;
+       return $wgRequest->getLimitOffset( $deflimit, $optionname );
+}
+
+/**
+ * Escapes the given text so that it may be output using addWikiText()
+ * without any linking, formatting, etc. making its way through. This
+ * is achieved by substituting certain characters with HTML entities.
+ * As required by the callers, <nowiki> is not used. It currently does
+ * not filter out characters which have special meaning only at the
+ * start of a line, such as "*".
+ *
+ * @param string $text Text to be escaped
+ */
+function wfEscapeWikiText( $text ) {
+       $text = str_replace( 
+               array( '[',             '|',      '\'',    'ISBN '        , '://'         , "\n=", '{{' ),
+               array( '&#91;', '&#124;', '&#39;', 'ISBN&#32;', '&#58;//' , "\n&#61;", '&#123;&#123;' ),
+               htmlspecialchars($text) );
+       return $text;
+}
+
+/**
+ * @todo document
+ */
+function wfQuotedPrintable( $string, $charset = '' ) {
+       # Probably incomplete; see RFC 2045
+       if( empty( $charset ) ) {
+               global $wgInputEncoding;
+               $charset = $wgInputEncoding;
+       }
+       $charset = strtoupper( $charset );
+       $charset = str_replace( 'ISO-8859', 'ISO8859', $charset ); // ?
+
+       $illegal = '\x00-\x08\x0b\x0c\x0e-\x1f\x7f-\xff=';
+       $replace = $illegal . '\t ?_';
+       if( !preg_match( "/[$illegal]/", $string ) ) return $string;
+       $out = "=?$charset?Q?";
+       $out .= preg_replace( "/([$replace])/e", 'sprintf("=%02X",ord("$1"))', $string );
+       $out .= '?=';
+       return $out;
+}
+
+/**
+ * Returns an escaped string suitable for inclusion in a string literal
+ * for JavaScript source code.
+ * Illegal control characters are assumed not to be present.
+ *
+ * @param string $string
+ * @return string
+ */
+function wfEscapeJsString( $string ) {
+       // See ECMA 262 section 7.8.4 for string literal format
+       $pairs = array(
+               "\\" => "\\\\",
+               "\"" => "\\\"",
+               '\'' => '\\\'',
+               "\n" => "\\n",
+               "\r" => "\\r",
+               
+               # To avoid closing the element or CDATA section
+               "<" => "\\x3c",
+               ">" => "\\x3e",
+       );
+       return strtr( $string, $pairs );
+}
+
+/**
+ * @todo document
+ * @return float
+ */
+function wfTime() {
+       $st = explode( ' ', microtime() );
+       return (float)$st[0] + (float)$st[1];
+}
+
+/**
+ * Changes the first character to an HTML entity
+ */
+function wfHtmlEscapeFirst( $text ) {
+       $ord = ord($text);
+       $newText = substr($text, 1);
+       return "&#$ord;$newText";
+}
+
+/**
+ * Sets dest to source and returns the original value of dest
+ * If source is NULL, it just returns the value, it doesn't set the variable
+ */
+function wfSetVar( &$dest, $source ) {
+       $temp = $dest;
+       if ( !is_null( $source ) ) {
+               $dest = $source;
+       }
+       return $temp;
+}
+
+/**
+ * As for wfSetVar except setting a bit
+ */
+function wfSetBit( &$dest, $bit, $state = true ) {
+       $temp = (bool)($dest & $bit );
+       if ( !is_null( $state ) ) {
+               if ( $state ) {
+                       $dest |= $bit;
+               } else {
+                       $dest &= ~$bit;
+               }
+       }
+       return $temp;
+}
+
+/**
+ * This function takes two arrays as input, and returns a CGI-style string, e.g.
+ * "days=7&limit=100". Options in the first array override options in the second.
+ * Options set to "" will not be output.
+ */
+function wfArrayToCGI( $array1, $array2 = NULL )
+{
+       if ( !is_null( $array2 ) ) {
+               $array1 = $array1 + $array2;
+       }
+
+       $cgi = '';
+       foreach ( $array1 as $key => $value ) {
+               if ( '' !== $value ) {
+                       if ( '' != $cgi ) {
+                               $cgi .= '&';
+                       }
+                       $cgi .= urlencode( $key ) . '=' . urlencode( $value );
+               }
+       }
+       return $cgi;
+}
+
+/**
+ * This is obsolete, use SquidUpdate::purge()
+ * @deprecated
+ */
+function wfPurgeSquidServers ($urlArr) {
+       SquidUpdate::purge( $urlArr );
+}
+
+/**
+ * Windows-compatible version of escapeshellarg()
+ * Windows doesn't recognise single-quotes in the shell, but the escapeshellarg() 
+ * function puts single quotes in regardless of OS
+ */
+function wfEscapeShellArg( ) {
+       $args = func_get_args();
+       $first = true;
+       $retVal = '';
+       foreach ( $args as $arg ) {
+               if ( !$first ) {
+                       $retVal .= ' ';
+               } else {
+                       $first = false;
+               }
+       
+               if ( wfIsWindows() ) {
+                       $retVal .= '"' . str_replace( '"','\"', $arg ) . '"';
+               } else {
+                       $retVal .= escapeshellarg( $arg );
+               }
+       }
+       return $retVal;
+}
+
+/**
+ * wfMerge attempts to merge differences between three texts.
+ * Returns true for a clean merge and false for failure or a conflict.
+ */
+function wfMerge( $old, $mine, $yours, &$result ){
+       global $wgDiff3;
+
+       # This check may also protect against code injection in
+       # case of broken installations.
+       if(! file_exists( $wgDiff3 ) ){
+               wfDebug( "diff3 not found\n" );
+               return false;
+       }
+
+       # Make temporary files
+       $td = wfTempDir();
+       $oldtextFile = fopen( $oldtextName = tempnam( $td, 'merge-old-' ), 'w' );
+       $mytextFile = fopen( $mytextName = tempnam( $td, 'merge-mine-' ), 'w' );
+       $yourtextFile = fopen( $yourtextName = tempnam( $td, 'merge-your-' ), 'w' );
+
+       fwrite( $oldtextFile, $old ); fclose( $oldtextFile );
+       fwrite( $mytextFile, $mine ); fclose( $mytextFile );
+       fwrite( $yourtextFile, $yours ); fclose( $yourtextFile );
+
+       # Check for a conflict
+       $cmd = $wgDiff3 . ' -a --overlap-only ' .
+         wfEscapeShellArg( $mytextName ) . ' ' .
+         wfEscapeShellArg( $oldtextName ) . ' ' .
+         wfEscapeShellArg( $yourtextName );
+       $handle = popen( $cmd, 'r' );
+
+       if( fgets( $handle, 1024 ) ){
+               $conflict = true;
+       } else {
+               $conflict = false;
+       }
+       pclose( $handle );
+
+       # Merge differences
+       $cmd = $wgDiff3 . ' -a -e --merge ' .
+         wfEscapeShellArg( $mytextName, $oldtextName, $yourtextName );
+       $handle = popen( $cmd, 'r' );
+       $result = '';
+       do {
+               $data = fread( $handle, 8192 );
+               if ( strlen( $data ) == 0 ) {
+                       break;
+               }
+               $result .= $data;
+       } while ( true );
+       pclose( $handle );
+       unlink( $mytextName ); unlink( $oldtextName ); unlink( $yourtextName );
+
+       if ( $result === '' && $old !== '' && $conflict == false ) {
+               wfDebug( "Unexpected null result from diff3. Command: $cmd\n" );
+               $conflict = true;
+       }
+       return ! $conflict;
+}
+
+/**
+ * @todo document
+ */
+function wfVarDump( $var ) {
+       global $wgOut;
+       $s = str_replace("\n","<br />\n", var_export( $var, true ) . "\n");
+       if ( headers_sent() || !@is_object( $wgOut ) ) {
+               print $s;
+       } else {
+               $wgOut->addHTML( $s );
+       }
+}
+
+/**
+ * Provide a simple HTTP error.
+ */
+function wfHttpError( $code, $label, $desc ) {
+       global $wgOut;
+       $wgOut->disable();
+       header( "HTTP/1.0 $code $label" );
+       header( "Status: $code $label" );
+       $wgOut->sendCacheControl();
+
+       header( 'Content-type: text/html' );
+       print "<html><head><title>" .
+               htmlspecialchars( $label ) . 
+               "</title></head><body><h1>" . 
+               htmlspecialchars( $label ) .
+               "</h1><p>" .
+               htmlspecialchars( $desc ) .
+               "</p></body></html>\n";
+}
+
+/**
+ * Converts an Accept-* header into an array mapping string values to quality
+ * factors
+ */
+function wfAcceptToPrefs( $accept, $def = '*/*' ) {
+       # No arg means accept anything (per HTTP spec)
+       if( !$accept ) {
+               return array( $def => 1 );
+       }
+
+       $prefs = array();
+
+       $parts = explode( ',', $accept );
+
+       foreach( $parts as $part ) {
+               # FIXME: doesn't deal with params like 'text/html; level=1'
+               @list( $value, $qpart ) = explode( ';', $part );
+               if( !isset( $qpart ) ) {
+                       $prefs[$value] = 1;
+               } elseif( preg_match( '/q\s*=\s*(\d*\.\d+)/', $qpart, $match ) ) {
+                       $prefs[$value] = $match[1];
+               }
+       }
+
+       return $prefs;
+}
+
+/**
+ * Checks if a given MIME type matches any of the keys in the given
+ * array. Basic wildcards are accepted in the array keys.
+ *
+ * Returns the matching MIME type (or wildcard) if a match, otherwise
+ * NULL if no match.
+ *
+ * @param string $type
+ * @param array $avail
+ * @return string
+ * @access private
+ */
+function mimeTypeMatch( $type, $avail ) {
+       if( array_key_exists($type, $avail) ) {
+               return $type;
+       } else {
+               $parts = explode( '/', $type );
+               if( array_key_exists( $parts[0] . '/*', $avail ) ) {
+                       return $parts[0] . '/*';
+               } elseif( array_key_exists( '*/*', $avail ) ) {
+                       return '*/*';
+               } else {
+                       return NULL;
+               }
+       }
+}
+
+/**
+ * Returns the 'best' match between a client's requested internet media types
+ * and the server's list of available types. Each list should be an associative
+ * array of type to preference (preference is a float between 0.0 and 1.0).
+ * Wildcards in the types are acceptable.
+ *
+ * @param array $cprefs Client's acceptable type list
+ * @param array $sprefs Server's offered types
+ * @return string
+ *
+ * @todo FIXME: doesn't handle params like 'text/plain; charset=UTF-8'
+ * XXX: generalize to negotiate other stuff
+ */
+function wfNegotiateType( $cprefs, $sprefs ) {
+       $combine = array();
+
+       foreach( array_keys($sprefs) as $type ) {
+               $parts = explode( '/', $type );
+               if( $parts[1] != '*' ) {
+                       $ckey = mimeTypeMatch( $type, $cprefs );
+                       if( $ckey ) {
+                               $combine[$type] = $sprefs[$type] * $cprefs[$ckey];
+                       }
+               }
+       }
+
+       foreach( array_keys( $cprefs ) as $type ) {
+               $parts = explode( '/', $type );
+               if( $parts[1] != '*' && !array_key_exists( $type, $sprefs ) ) {
+                       $skey = mimeTypeMatch( $type, $sprefs );
+                       if( $skey ) {
+                               $combine[$type] = $sprefs[$skey] * $cprefs[$type];
+                       }
+               }
+       }
+
+       $bestq = 0;
+       $besttype = NULL;
+
+       foreach( array_keys( $combine ) as $type ) {
+               if( $combine[$type] > $bestq ) {
+                       $besttype = $type;
+                       $bestq = $combine[$type];
+               }
+       }
+
+       return $besttype;
+}
+
+/**
+ * Array lookup
+ * Returns an array where the values in the first array are replaced by the
+ * values in the second array with the corresponding keys
+ * 
+ * @return array
+ */
+function wfArrayLookup( $a, $b ) {
+       return array_flip( array_intersect( array_flip( $a ), array_keys( $b ) ) );
+}
+
+/**
+ * Convenience function; returns MediaWiki timestamp for the present time.
+ * @return string
+ */
+function wfTimestampNow() {
+       # return NOW
+       return wfTimestamp( TS_MW, time() );
+}
+
+/**
+ * Reference-counted warning suppression
+ */
+function wfSuppressWarnings( $end = false ) {
+       static $suppressCount = 0;
+       static $originalLevel = false;
+
+       if ( $end ) {
+               if ( $suppressCount ) {
+                       $suppressCount --;
+                       if ( !$suppressCount ) {
+                               error_reporting( $originalLevel );
+                       }
+               }
+       } else {
+               if ( !$suppressCount ) {
+                       $originalLevel = error_reporting( E_ALL & ~( E_WARNING | E_NOTICE ) );
+               }
+               $suppressCount++;
+       }
+}
+
+/**
+ * Restore error level to previous value
+ */
+function wfRestoreWarnings() {
+       wfSuppressWarnings( true );
+}
+
+# Autodetect, convert and provide timestamps of various types
+
+/** 
+ * Unix time - the number of seconds since 1970-01-01 00:00:00 UTC
+ */
+define('TS_UNIX', 0);
+
+/**
+ * MediaWiki concatenated string timestamp (YYYYMMDDHHMMSS)
+ */
+define('TS_MW', 1);
+
+/**
+ * MySQL DATETIME (YYYY-MM-DD HH:MM:SS)
+ */
+define('TS_DB', 2);
+
+/**
+ * RFC 2822 format, for E-mail and HTTP headers
+ */
+define('TS_RFC2822', 3);
+
+/**
+ * An Exif timestamp (YYYY:MM:DD HH:MM:SS)
+ *
+ * @link http://exif.org/Exif2-2.PDF The Exif 2.2 spec, see page 28 for the
+ *       DateTime tag and page 36 for the DateTimeOriginal and
+ *       DateTimeDigitized tags.
+ */
+define('TS_EXIF', 4);
+
+
+/**
+ * @param mixed $outputtype A timestamp in one of the supported formats, the
+ *                          function will autodetect which format is supplied
+                            and act accordingly.
+ * @return string Time in the format specified in $outputtype
+ */
+function wfTimestamp($outputtype=TS_UNIX,$ts=0) {
+       $uts = 0;
+       if ($ts==0) {
+               $uts=time();
+       } elseif (preg_match("/^(\d{4})\-(\d\d)\-(\d\d) (\d\d):(\d\d):(\d\d)$/",$ts,$da)) {
+               # TS_DB
+               $uts=gmmktime((int)$da[4],(int)$da[5],(int)$da[6],
+                           (int)$da[2],(int)$da[3],(int)$da[1]);
+       } elseif (preg_match("/^(\d{4}):(\d\d):(\d\d) (\d\d):(\d\d):(\d\d)$/",$ts,$da)) {
+               # TS_EXIF
+               $uts=gmmktime((int)$da[4],(int)$da[5],(int)$da[6],
+                       (int)$da[2],(int)$da[3],(int)$da[1]);
+       } elseif (preg_match("/^(\d{4})(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)$/",$ts,$da)) {
+               # TS_MW
+               $uts=gmmktime((int)$da[4],(int)$da[5],(int)$da[6],
+                           (int)$da[2],(int)$da[3],(int)$da[1]);
+       } elseif (preg_match("/^(\d{1,13})$/",$ts,$datearray)) {
+               # TS_UNIX
+               $uts=$ts;
+       } else {
+               # Bogus value; fall back to the epoch...
+               wfDebug("wfTimestamp() fed bogus time value: $outputtype; $ts\n");
+               $uts = 0;
+       }
+
+               
+       switch($outputtype) {
+               case TS_UNIX:
+                       return $uts;
+               case TS_MW:
+                       return gmdate( 'YmdHis', $uts );
+               case TS_DB:
+                       return gmdate( 'Y-m-d H:i:s', $uts );
+               // This shouldn't ever be used, but is included for completeness
+               case TS_EXIF:
+                       return gmdate(  'Y:m:d H:i:s', $uts );
+               case TS_RFC2822:
+                       return gmdate( 'D, d M Y H:i:s', $uts ) . ' GMT';
+               default:
+                       wfDebugDieBacktrace( 'wfTimestamp() called with illegal output type.');
+       }
+}
+
+/**
+ * Return a formatted timestamp, or null if input is null.
+ * For dealing with nullable timestamp columns in the database.
+ * @param int $outputtype
+ * @param string $ts
+ * @return string
+ */
+function wfTimestampOrNull( $outputtype = TS_UNIX, $ts = null ) {
+       if( is_null( $ts ) ) {
+               return null;
+       } else {
+               return wfTimestamp( $outputtype, $ts );
+       }
+}
+
+/**
+ * Check where as the operating system is Windows
+ *
+ * @return bool True if it's windows, False otherwise.
+ */
+function wfIsWindows() {   
+       if (substr(php_uname(), 0, 7) == 'Windows') {   
+               return true;   
+       } else {   
+               return false;   
+       }   
+} 
+
+/**
+ * Swap two variables
+ */
+function swap( &$x, &$y ) {
+       $z = $x;
+       $x = $y;
+       $y = $z;
+}
+
+function wfGetSiteNotice() {
+       global $wgSiteNotice, $wgTitle, $wgOut;
+       $fname = 'wfGetSiteNotice';
+       wfProfileIn( $fname );
+
+       $notice = wfMsg( 'sitenotice' );
+       if( $notice == '&lt;sitenotice&gt;' || $notice == '-' ) {
+               $notice = '';
+       }
+       if( $notice == '' ) {
+               # We may also need to override a message with eg downtime info
+               # FIXME: make this work!
+               $notice = $wgSiteNotice;
+       }
+       if($notice != '-' && $notice != '') {
+               $specialparser = new Parser();
+               $parserOutput = $specialparser->parse( $notice, $wgTitle, $wgOut->mParserOptions, false );
+               $notice = $parserOutput->getText();
+       }
+       wfProfileOut( $fname );
+       return $notice;
+}
+
+/**
+ * Format an XML element with given attributes and, optionally, text content.
+ * Element and attribute names are assumed to be ready for literal inclusion.
+ * Strings are assumed to not contain XML-illegal characters; special
+ * characters (<, >, &) are escaped but illegals are not touched.
+ *
+ * @param string $element
+ * @param array $attribs Name=>value pairs. Values will be escaped.
+ * @param string $contents NULL to make an open tag only; '' for a contentless closed tag (default)
+ * @return string
+ */
+function wfElement( $element, $attribs = null, $contents = '') {
+       $out = '<' . $element;
+       if( !is_null( $attribs ) ) {
+               foreach( $attribs as $name => $val ) {
+                       $out .= ' ' . $name . '="' . htmlspecialchars( $val ) . '"';
+               }
+       }
+       if( is_null( $contents ) ) {
+               $out .= '>';
+       } else {
+               if( $contents == '' ) {
+                       $out .= ' />';
+               } else {
+                       $out .= '>';
+                       $out .= htmlspecialchars( $contents );
+                       $out .= "</$element>";
+               }
+       }
+       return $out;
+}
+
+/**
+ * Format an XML element as with wfElement(), but run text through the
+ * UtfNormal::cleanUp() validator first to ensure that no invalid UTF-8
+ * is passed.
+ *
+ * @param string $element
+ * @param array $attribs Name=>value pairs. Values will be escaped.
+ * @param string $contents NULL to make an open tag only; '' for a contentless closed tag (default)
+ * @return string
+ */
+function wfElementClean( $element, $attribs = array(), $contents = '') {
+       if( $attribs ) {
+               $attribs = array_map( array( 'UtfNormal', 'cleanUp' ), $attribs );
+       }
+       if( $contents ) {
+               $contents = UtfNormal::cleanUp( $contents );
+       }
+       return wfElement( $element, $attribs, $contents );
+}
+
+/**
+ * Create a namespace selector
+ *
+ * @param mixed $selected The namespace which should be selected, default ''
+ * @param string $allnamespaces Value of a special item denoting all namespaces. Null to not include (default)
+ * @return Html string containing the namespace selector
+ */
+function &HTMLnamespaceselector($selected = '', $allnamespaces = null) {
+       global $wgContLang;
+       $s = "<select name='namespace' class='namespaceselector'>\n";
+       $arr = $wgContLang->getFormattedNamespaces();
+       if( !is_null($allnamespaces) ) {
+               $arr = array($allnamespaces => wfMsgHtml('namespacesall')) + $arr;
+       }
+       foreach ($arr as $index => $name) {
+               if ($index < NS_MAIN) continue;
+
+               $name = $index !== 0 ? $name : wfMsgHtml('blanknamespace');
+
+               if ($index === $selected) {
+                       $s .= wfElement("option",
+                                       array("value" => $index, "selected" => "selected"),
+                                       $name);
+               } else {
+                       $s .= wfElement("option", array("value" => $index), $name);
+               }
+       }
+       $s .= "</select>\n";
+       return $s;
+}
+
+/** Global singleton instance of MimeMagic. This is initialized on demand,
+* please always use the wfGetMimeMagic() function to get the instance.
+* 
+* @private
+*/
+$wgMimeMagic= NULL;
+
+/** Factory functions for the global MimeMagic object.
+* This function always returns the same singleton instance of MimeMagic.
+* That objects will be instantiated on the first call to this function.
+* If needed, the MimeMagic.php file is automatically included by this function.
+* @return MimeMagic the global MimeMagic objects.
+*/
+function &wfGetMimeMagic() {
+       global $wgMimeMagic;
+       
+       if (!is_null($wgMimeMagic)) {
+               return $wgMimeMagic;
+       }
+
+       if (!class_exists("MimeMagic")) {
+               #include on demand
+               require_once("MimeMagic.php");
+       }
+       
+       $wgMimeMagic= new MimeMagic();
+       
+       return $wgMimeMagic;
+}
+
+
+/**
+ * Tries to get the system directory for temporary files.
+ * The TMPDIR, TMP, and TEMP environment variables are checked in sequence,
+ * and if none are set /tmp is returned as the generic Unix default.
+ *
+ * NOTE: When possible, use the tempfile() function to create temporary
+ * files to avoid race conditions on file creation, etc.
+ *
+ * @return string
+ */
+function wfTempDir() {
+       foreach( array( 'TMPDIR', 'TMP', 'TEMP' ) as $var ) {
+               $tmp = getenv( $var );
+               if( $tmp && file_exists( $tmp ) && is_dir( $tmp ) && is_writable( $tmp ) ) {
+                       return $tmp;
+               }
+       }
+       # Hope this is Unix of some kind!
+       return '/tmp';
+}
+
+/**
+ * Make directory, and make all parent directories if they don't exist
+ */
+function wfMkdirParents( $fullDir, $mode ) {
+       $parts = explode( '/', $fullDir );
+       $path = '';
+       $success = false;
+       foreach ( $parts as $dir ) {
+               $path .= $dir . '/';
+               if ( !is_dir( $path ) ) {
+                       if ( !mkdir( $path, $mode ) ) {
+                               return false;
+                       }
+               }
+       }
+       return true;
+}
+
+/**
+ * Increment a statistics counter
+ */
+function wfIncrStats( $key ) {
+       global $wgDBname, $wgMemc;
+       $key = "$wgDBname:stats:$key";
+       if ( is_null( $wgMemc->incr( $key ) ) ) {
+               $wgMemc->add( $key, 1 );
+       }
+}
+
+/**
+ * @param mixed $nr The number to format
+ * @param int $acc The number of digits after the decimal point, default 2
+ * @param bool $round Whether or not to round the value, default true
+ * @return float
+ */
+function wfPercent( $nr, $acc = 2, $round = true ) {
+       $ret = sprintf( "%.${acc}f", $nr );
+       return $round ? round( $ret, $acc ) . '%' : "$ret%";
+}
+
+/**
+ * Encrypt a username/password.
+ *
+ * @param string $userid ID of the user
+ * @param string $password Password of the user
+ * @return string Hashed password
+ */
+function wfEncryptPassword( $userid, $password ) {
+       global $wgPasswordSalt;
+       $p = md5( $password);
+
+       if($wgPasswordSalt)
+               return md5( "{$userid}-{$p}" );
+       else
+               return $p;
+}
+
+/**
+ * Appends to second array if $value differs from that in $default
+ */
+function wfAppendToArrayIfNotDefault( $key, $value, $default, &$changed ) {
+       if ( is_null( $changed ) ) {
+               wfDebugDieBacktrace('GlobalFunctions::wfAppendToArrayIfNotDefault got null');
+       }
+       if ( $default[$key] !== $value ) {
+               $changed[$key] = $value;
+       }
+}
+
+/**
+ * Since wfMsg() and co suck, they don't return false if the message key they
+ * looked up didn't exist but a XHTML string, this function checks for the
+ * nonexistance of messages by looking at wfMsg() output
+ *
+ * @param $msg      The message key looked up
+ * @param $wfMsgOut The output of wfMsg*()
+ * @return bool
+ */
+function wfNoMsg( $msg, $wfMsgOut ) {
+       return $wfMsgOut === "&lt;$msg&gt;";
+}
+?>
diff --git a/includes/Group.php b/includes/Group.php
new file mode 100644 (file)
index 0000000..cfaeb46
--- /dev/null
@@ -0,0 +1,390 @@
+<?php
+/**
+ * @package MediaWiki
+ */
+
+/**
+ * Class to manage a group
+ * @package MediaWiki
+ */
+class Group {
+       /**#@+
+        * @access private
+        */
+       /** string $name Group name */
+       var $name;
+       /** integer $id Group id */
+       var $id;
+       /** string $description Description of the group */
+       var $description;
+       /** boolean $dataLoaded Whether data has been loaded from the database */
+       var $dataLoaded;
+       /** string $rights Contain rights values : "foo,bar,bla" */
+       var $rights;
+       /**#@-*/
+       
+       /** Constructor */
+       function Group() {
+               $this->clear();
+       }
+
+       /** Clear variables */
+       function clear() {
+               $this->name = '';
+               $this->id = 0;
+               $this->description = '';
+               $this->dataLoaded = false;
+               $this->rights = false;
+       }
+
+       /** Load group data from database */
+       function loadFromDatabase() {
+               $fname = 'Group::loadFromDatabase';
+
+               // See if it's already loaded
+               if ( $this->dataLoaded || Group::getStaticGroups() ) {
+                       return;
+               }
+
+               // be sure it's an integer
+               $this->id = IntVal($this->id);
+               
+               if($this->id) {
+                       // By ID
+                       $dbr =& wfGetDB( DB_SLAVE );
+                       $r = $dbr->selectRow('groups',
+                               array('gr_id', 'gr_name', 'gr_description', 'gr_rights'),
+                               array( 'gr_id' => $this->id ),
+                               $fname );
+                       if ( $r ) {
+                               $this->loadFromRow( $r );
+                       } else {
+                               $this->id = 0;
+                               $this->dataLoaded = true;
+                       }
+               } else {
+                       // By name
+                       $dbr =& wfGetDB( DB_SLAVE );
+                       $r = $dbr->selectRow('groups',
+                               array('gr_id', 'gr_name', 'gr_description', 'gr_rights'),
+                               array( 'gr_name' => $this->name ),
+                               $fname );
+                       if ( $r ) {
+                               $this->loadFromRow( $r );
+                       } else {
+                               $this->id = 0;
+                               $this->dataLoaded = true;
+                       }
+               }
+       }
+
+       /** Initialise from a result row */
+       function loadFromRow( &$row ) {
+               $this->id = $row->gr_id;
+               $this->name = $row->gr_name;
+               $this->description = $row->gr_description;
+               $this->rights = $row->gr_rights;
+               $this->dataLoaded = true;
+       }               
+       
+       /** Initialise a new row in the database */
+       function addToDatabase() {
+               if ( Group::getStaticGroups() ) {
+                       wfDebugDieBacktrace( "Can't modify groups in static mode" );
+               }
+
+               $fname = 'Group::addToDatabase';
+               $dbw =& wfGetDB( DB_MASTER );
+               $dbw->insert( 'groups',
+                       array(
+                               'gr_name' => $this->name,
+                               'gr_description' => $this->description,
+                               'gr_rights' => $this->rights
+                       ), $fname
+               );
+               $this->id = $dbw->insertId();
+       }
+
+       /** Save the group data into database */
+       function save() {
+               global $wgMemc;
+
+               if ( Group::getStaticGroups() ) {
+                       wfDebugDieBacktrace( "Can't modify groups in static mode" );
+               }
+               if($this->id == 0) { return; }
+               
+               $fname = 'Group::save';
+               $dbw =& wfGetDB( DB_MASTER );
+               
+               $dbw->update( 'groups',
+                       array( /* SET */
+                               'gr_name' => $this->name,
+                               'gr_description' => $this->description,
+                               'gr_rights' => $this->rights
+                       ), array( /* WHERE */
+                               'gr_id' => $this->id
+                       ), $fname
+               );
+       
+               $wgMemc->set( Group::getCacheKey( $this->id ), $this, 3600 );
+       }
+
+
+       /** Delete a group */
+       function delete() {
+               global $wgMemc;
+
+               if ( Group::getStaticGroups() ) {
+                       wfDebugDieBacktrace( "Can't modify groups in static mode" );
+               }
+               if($this->id == 0) { return; }
+               
+               $fname = 'Group::delete';
+               $dbw =& wfGetDB( DB_MASTER );
+
+               // First remove all users from the group
+               $dbw->delete( 'user_group', array( 'ug_group' => $this->id ), $fname );
+
+               // Now delete the group
+               $dbw->delete( 'groups', array( 'gr_id' => $this->id ), $fname );
+
+               $wgMemc->delete( Group::getCacheKey( $this->id ) );
+       }
+       
+       /** 
+        * Get memcached key 
+        * @static
+        */
+       function getCacheKey( $id ) {
+               global $wgDBname;
+               return "$wgDBname:groups:id:$id";
+       }
+
+// Factories
+       /**
+        * Uses Memcached if available.
+        * @param integer $id Group database id
+        */
+       function newFromId($id) {
+               global $wgMemc, $wgDBname;
+               $fname = 'Group::newFromId';
+               
+               $staticGroups =& Group::getStaticGroups();
+               if ( $staticGroups ) {
+                       if ( array_key_exists( $id, $staticGroups ) ) {
+                               return $staticGroups[$id];
+                       } else {
+                               return null;
+                       }
+               }
+
+               $key = Group::getCacheKey( $id );
+
+               if( $group = $wgMemc->get( $key ) ) {
+                       wfDebug( "$fname loaded group $id from cache\n" );
+                       return $group;
+               }
+               
+               $group = new Group();
+               $group->id = $id;
+               $group->loadFromDatabase();
+
+               if ( !$group->id ) {
+                       wfDebug( "$fname can't find group $id\n" );
+                       return null;
+               } else {
+                       wfDebug( "$fname caching group $id (name {$group->name})\n" );
+                       $wgMemc->add( $key, $group, 3600 );
+                       return $group;
+               }
+       }
+
+
+       /** @param string $name Group database name */
+       function newFromName($name) {
+               $fname = 'Group::newFromName';
+               
+               $staticGroups =& Group::getStaticGroups();
+               if ( $staticGroups ) {
+                       $id = Group::idFromName( $name );
+                       if ( array_key_exists( $id, $staticGroups ) ) {
+                               return $staticGroups[$id];
+                       } else {
+                               return null;
+                       }
+               }
+               
+               $g = new Group();
+               $g->name = $name;
+               $g->loadFromDatabase();
+
+               if( $g->getId() != 0 ) {
+                       return $g;
+               } else { 
+                       return null;
+               }
+       }
+
+       /**
+        * Get an array of Group objects, one for each valid group
+        * 
+        * @static
+        */
+       function &getAllGroups() {
+               $staticGroups =& Group::getStaticGroups();
+               if ( $staticGroups ) {
+                       return $staticGroups;
+               }
+
+               $fname = 'Group::getAllGroups';
+               wfProfileIn( $fname );
+
+               $dbr =& wfGetDB( DB_SLAVE );
+               $groupTable = $dbr->tableName( 'groups' );
+               $sql = "SELECT gr_id, gr_name, gr_description, gr_rights FROM $groupTable";
+               $res = $dbr->query($sql, $fname);
+
+               $groups = array();
+
+               while($row = $dbr->fetchObject( $res ) ) {
+                       $group = new Group;
+                       $group->loadFromRow( $row );
+                       $groups[$row->gr_id] = $group;
+               }
+
+               wfProfileOut( $fname );
+               return $groups;
+       }
+
+       /** 
+        * Get static groups, if they have been defined in LocalSettings.php
+        * 
+        * @static
+        */
+       function &getStaticGroups() {
+               global $wgStaticGroups;
+               if ( $wgStaticGroups === false ) {
+                       return $wgStaticGroups;
+               }
+
+               if ( !is_array( $wgStaticGroups ) ) {
+                       $wgStaticGroups = unserialize( $wgStaticGroups );
+               }
+
+               return $wgStaticGroups;
+       }
+
+
+// Converters
+       /**
+        * @param integer $id Group database id
+        * @return string Group database name
+        */
+       function nameFromId($id) {
+               $group = Group::newFromId( $id );
+               if ( is_null( $group ) ) {
+                       return '';
+               } else {
+                       return $group->getName();
+               }
+       }
+
+       /**
+        * @param string $name Group database name 
+        * @return integer Group database id
+        */
+       function idFromName($name) {
+               $fname = 'Group::idFromName';
+
+               $staticGroups =& Group::getStaticGroups();
+               if ( $staticGroups ) {
+                       foreach( $staticGroups as $id => $group ) {
+                               if ( $group->getName() === $name ) {
+                                       return $group->getId();
+                               }
+                       }
+                       return 0;
+               }
+
+
+               $dbr =& wfGetDB( DB_SLAVE );
+               $r = $dbr->selectRow( 'groups', array( 'gr_id' ), array( 'gr_name' => $name ), $fname );
+
+               if($r === false) {
+                       return 0;
+               } else {
+                       return $r->gr_id;
+               }
+       }
+
+// Accessors for private variables
+       function getName() {
+               $this->loadFromDatabase();
+               return $this->name;
+       }
+
+       function getExpandedName() { 
+               $this->loadFromDatabase();
+               return $this->getMessage( $this->name );
+       }
+       
+       function getNameForContent() {
+               $this->loadFromDatabase();
+               return $this->getMessageForContent( $this->name );
+       }
+
+       function setName($name) {
+               $this->loadFromDatabase();
+               $this->name = $name;
+       }
+       
+       function getId() { return $this->id; }
+       function setId($id) {
+               $this->id = IntVal($id);
+               $this->dataLoaded = false;
+       }
+       
+       function getDescription() { 
+               return $this->description;
+       }
+
+       function getExpandedDescription() {
+               return $this->getMessage( $this->description );
+       }
+
+       function setDescription($desc) {
+               $this->loadFromDatabase();
+               $this->description = $desc;
+       }
+
+       function getRights() { return $this->rights; }
+       function setRights($rights) {
+               $this->loadFromDatabase();
+               $this->rights = $rights;
+       }
+
+       /** 
+        * Gets a message if the text starts with a colon, otherwise returns the text itself
+        */
+       function getMessage( $text ) {
+               if ( strlen( $text ) && $text{0} == ':' ) {
+                       return wfMsg( substr( $text, 1 ) );
+               } else {
+                       return $text;
+               }
+       }
+
+       /**
+        * As for getMessage but for content
+        */
+       function getMessageForContent( $text ) {
+               if ( strlen( $text ) && $text{0} == ':' ) {
+                       return wfMsgForContent( substr( $text, 1 ) );
+               } else {
+                       return $text;
+               }
+       }
+
+}
+?>
diff --git a/includes/HTMLForm.php b/includes/HTMLForm.php
new file mode 100644 (file)
index 0000000..12147d5
--- /dev/null
@@ -0,0 +1,175 @@
+<?php
+/**
+ * This file contain a class to easily build HTML forms as well as custom
+ * functions used by SpecialUserrights.php and SpecialGroups.php
+ * @package MediaWiki
+ */
+
+/**
+ * Class to build various forms
+ *
+ * @package MediaWiki
+ * @author jeluf, hashar
+ */
+class HTMLForm {
+       /** name of our form. Used as prefix for labels */
+       var $mName, $mRequest;
+
+       function HTMLForm( &$request ) {
+               $this->mRequest = $request;
+       }
+
+       /**
+        * @access private
+        * @param string $name Name of the fieldset.
+        * @param string $content HTML content to put in.
+        * @return string HTML fieldset
+        */
+       function fieldset( $name, $content ) {
+               return "<fieldset><legend>".wfMsg($this->mName.'-'.$name)."</legend>\n" .
+                       $content . "\n</fieldset>\n";
+       }
+
+       /**
+        * @access private
+        * @param string $varname Name of the checkbox.
+        * @param boolean $checked Set true to check the box (default False).
+        */
+       function checkbox( $varname, $checked=false ) {
+               if ( $this->mRequest->wasPosted() && !is_null( $this->mRequest->getVal( $varname ) ) ) {
+                       $checked = $this->mRequest->getCheck( $varname );
+               }
+               return "<div><input type='checkbox' value=\"1\" id=\"{$varname}\" name=\"wpOp{$varname}\"" .
+                       ( $checked ? ' checked="checked"' : '' ) .
+                       " /><label for=\"{$varname}\">". wfMsg( $this->mName.'-'.$varname ) .
+                       "</label></div>\n";
+       }
+
+       /** 
+        * @access private
+        * @param string $varname Name of the textbox.
+        * @param string $value Optional value (default empty)
+        * @param integer $size Optional size of the textbox (default 20)
+        */
+       function textbox( $varname, $value='', $size=20 ) {
+               if ( $this->mRequest->wasPosted() ) {
+                       $value = $this->mRequest->getText( $varname, $value );
+               }
+               $value = htmlspecialchars( $value );
+               return "<div><label>". wfMsg( $this->mName.'-'.$varname ) .
+                       "<input type='text' name=\"{$varname}\" value=\"{$value}\" size=\"{$size}\" /></label></div>\n";
+       }
+
+       /** 
+        * @access private
+        * @param string $varname Name of the radiobox.
+        * @param array $fields Various fields.
+        */
+       function radiobox( $varname, $fields ) {
+               foreach ( $fields as $value => $checked ) {
+                       $s .= "<div><label><input type='radio' name=\"{$varname}\" value=\"{$value}\"" .
+                               ( $checked ? ' checked="checked"' : '' ) . " />" . wfMsg( $this->mName.'-'.$varname.'-'.$value ) .
+                               "</label></div>\n";
+               }
+               return $this->fieldset( $this->mName.'-'.$varname, $s );
+       }
+       
+       /** 
+        * @access private
+        * @param string $varname Name of the textareabox.
+        * @param string $value Optional value (default empty)
+        * @param integer $size Optional size of the textarea (default 20)
+        */
+       function textareabox ( $varname, $value='', $size=20 ) {
+               if ( $this->mRequest->wasPosted() ) {
+                       $value = $this->mRequest->getText( $varname, $value );
+               }       
+               $value = htmlspecialchars( $value );
+               return '<div><label>'.wfMsg( $this->mName.'-'.$varname ).
+                      "<textarea name=\"{$varname}\" rows=\"5\" cols=\"{$size}\">$value</textarea></label></div>\n";
+       }
+
+       /** 
+        * @access private
+        * @param string $varname Name of the arraybox.
+        * @param integer $size Optional size of the textarea (default 20)
+        */
+       function arraybox( $varname , $size=20 ) {
+               $s = '';
+               if ( $this->mRequest->wasPosted() ) {
+                       $arr = $this->mRequest->getArray( $varname );
+                       if ( is_array( $arr ) ) {
+                               foreach ( $_POST[$varname] as $index=>$element ) {
+                                       $s .= htmlspecialchars( $element )."\n";
+                               }
+                       }
+               }
+               return "<div><label>".wfMsg( $this->mName.'-'.$varname ).
+                       "<textarea name=\"{$varname}\" rows=\"5\" cols=\"{$size}\">{$s}</textarea>\n";
+       }
+} // end class
+
+
+// functions used by SpecialUserrights.php and SpecialGroups.php
+
+/** Build a select with all defined groups
+ * @param string $selectname Name of this element. Name of form is automaticly prefixed.
+ * @param array $selected Array of element selected when posted. Only multiples will show them.
+ * @param boolean $multiple A multiple elements select.
+ * @param integer $size Number of elements to be shown ignored for non-multiple (default 6).
+ * @param boolean $reverse If true, multiple select will hide selected elements (default false).
+*/
+function HTMLSelectGroups($selectname, $selectmsg, $selected=array(), $multiple=false, $size=6, $reverse=false) {
+       $groups = User::getAllGroups();
+       $out = htmlspecialchars( wfMsg( $selectmsg ) );
+       
+       if( $multiple ) {
+               $attribs = array(
+                       'name'    => $selectname . '[]',
+                       'multiple'=> 'multiple',
+                       'size'    => $size );
+       } else {
+               $attribs = array( 'name' => $selectname );
+       }
+       $out .= wfElement( 'select', $attribs, null );
+       
+       foreach( $groups as $group ) {
+               $attribs = array( 'value' => $group );
+               if( $multiple ) {
+                       // for multiple will only show the things we want
+                       if( !in_array( $group, $selected ) xor $reverse ) {
+                               continue;
+                       }
+               } else {
+                       if( in_array( $group, $selected ) ) {
+                               $attribs['selected'] = 'selected';
+                       }
+               }
+               $out .= wfElement( 'option', $attribs, User::getGroupName( $group ) ) . "\n";
+       }
+
+       $out .= "</select>\n";
+       return $out;
+}
+
+/** Build a select with all existent rights
+ * @param array $selected Names(?) of user rights that should be selected.
+ * @return string HTML select.
+ */
+function HTMLSelectRights($selected='') {
+       global $wgAvailableRights;
+       $out = '<select name="editgroup-getrights[]" multiple="multiple">';
+       $groupRights = explode(',',$selected);
+       
+       foreach($wgAvailableRights as $right) {
+       
+               // check box when right exist
+               if(in_array($right, $groupRights)) { $selected = 'selected="selected" '; }
+               else { $selected = ''; }
+                                       
+               $out .= '<option value="'.$right.'" '.$selected.'>'.$right."</option>\n";
+       }
+       $out .= "</select>\n";
+       return $out;
+}
+?>
diff --git a/includes/HistoryBlob.php b/includes/HistoryBlob.php
new file mode 100644 (file)
index 0000000..3eb2b6f
--- /dev/null
@@ -0,0 +1,307 @@
+<?php
+/**
+ *
+ * @package MediaWiki
+ */
+
+/**
+ * Pure virtual parent
+ * @package MediaWiki
+ */
+class HistoryBlob
+{
+       /**
+        * setMeta and getMeta currently aren't used for anything, I just thought
+        * they might be useful in the future.
+        * @param string $meta a single string
+        */
+       function setMeta( $meta ) {}
+
+       /**
+        * setMeta and getMeta currently aren't used for anything, I just thought
+        * they might be useful in the future.
+        * Gets the meta-value
+        */
+       function getMeta() {}
+
+       /**
+        * Adds an item of text, returns a stub object which points to the item.
+        * You must call setLocation() on the stub object before storing it to the
+        * database
+        */
+       function addItem() {}
+
+       /** 
+        * Get item by hash
+        */
+       function getItem( $hash ) {}
+       
+       # Set the "default text"
+       # This concept is an odd property of the current DB schema, whereby each text item has a revision
+       # associated with it. The default text is the text of the associated revision. There may, however, 
+       # be other revisions in the same object
+       function setText() {}
+
+       /**
+        * Get default text. This is called from Revision::getRevisionText()
+        */
+       function getText() {}
+}
+
+/**
+ * The real object
+ * @package MediaWiki
+ */
+class ConcatenatedGzipHistoryBlob extends HistoryBlob
+{
+       /* private */ var $mVersion = 0, $mCompressed = false, $mItems = array(), $mDefaultHash = '';
+       /* private */ var $mFast = 0, $mSize = 0;
+
+       function ConcatenatedGzipHistoryBlob() {
+               if ( !function_exists( 'gzdeflate' ) ) {
+                       die( "Need zlib support to read or write this kind of history object (ConcatenatedGzipHistoryBlob)\n" );
+               }
+       }
+
+       /** @todo document */
+       function setMeta( $metaData ) {
+               $this->uncompress();
+               $this->mItems['meta'] = $metaData;
+       }
+
+       /** @todo document */
+       function getMeta() {
+               $this->uncompress();
+               return $this->mItems['meta'];
+       }
+
+       /** @todo document */
+       function addItem( $text ) {
+               $this->uncompress();
+               $hash = md5( $text );
+               $this->mItems[$hash] = $text;
+               $this->mSize += strlen( $text );
+
+               $stub = new HistoryBlobStub( $hash );
+               return $stub;
+       }
+
+       /** @todo document */
+       function getItem( $hash ) {
+               $this->uncompress();
+               if ( array_key_exists( $hash, $this->mItems ) ) {
+                       return $this->mItems[$hash];
+               } else {
+                       return false;
+               }
+       }
+
+       /** @todo document */
+       function removeItem( $hash ) {
+               $this->mSize -= strlen( $this->mItems[$hash] );
+               unset( $this->mItems[$hash] );
+       }
+
+       /** @todo document */
+       function compress() {
+               if ( !$this->mCompressed  ) {
+                       $this->mItems = gzdeflate( serialize( $this->mItems ) );
+                       $this->mCompressed = true;
+               }
+       }
+
+       /** @todo document */
+       function uncompress() { 
+               if ( $this->mCompressed ) {
+                       $this->mItems = unserialize( gzinflate( $this->mItems ) );
+                       $this->mCompressed = false;
+               }
+       }
+
+       /** @todo document */
+       function getText() {
+               $this->uncompress();
+               return $this->getItem( $this->mDefaultHash );
+       }
+
+       /** @todo document */
+       function setText( $text ) {
+               $this->uncompress();
+               $stub = $this->addItem( $text );
+               $this->mDefaultHash = $stub->mHash;
+       }
+
+       /** @todo document */
+       function __sleep() {
+               $this->compress();
+               return array( 'mVersion', 'mCompressed', 'mItems', 'mDefaultHash' );
+       }
+
+       /** @todo document */
+       function __wakeup() {
+               $this->uncompress();
+       }
+
+       /**
+        * Determines if this object is happy
+        */
+       function isHappy( $maxFactor, $factorThreshold ) {
+               if ( count( $this->mItems ) == 0 ) {
+                       return true;
+               }
+               if ( !$this->mFast ) {
+                       $this->uncompress();
+                       $record = serialize( $this->mItems );
+                       $size = strlen( $record );
+                       $avgUncompressed = $size / count( $this->mItems );
+                       $compressed = strlen( gzdeflate( $record ) );
+
+                       if ( $compressed < $factorThreshold * 1024 ) {
+                               return true;
+                       } else {
+                               return $avgUncompressed * $maxFactor < $compressed;
+                       }
+               } else {
+                       return count( $this->mItems ) <= 10;
+               }
+       }
+}
+
+
+/**
+ * One-step cache variable to hold base blobs; operations that
+ * pull multiple revisions may often pull multiple times from
+ * the same blob. By keeping the last-used one open, we avoid
+ * redundant unserialization and decompression overhead.
+ */
+global $wgBlobCache;
+$wgBlobCache = array();
+
+
+/**
+ * @package MediaWiki
+ */
+class HistoryBlobStub {
+       var $mOldId, $mHash,$mRef;
+
+       /** @todo document */
+       function HistoryBlobStub( $hash = '', $oldid = 0 ) {
+               $this->mHash = $hash;
+       }
+       
+       /**
+        * Sets the location (old_id) of the main object to which this object
+        * points
+        */
+       function setLocation( $id ) {
+               $this->mOldId = $id;
+       }
+
+       /**
+        * Sets the location (old_id) of the referring object
+        */
+       function setReferrer( $id ) {
+               $this->mRef = $id;
+       }
+
+       /**
+        * Gets the location of the referring object
+        */
+       function getReferrer() {
+               return $this->mRef;
+       }
+
+       /** @todo document */
+       function getText() {
+               global $wgBlobCache;
+               if( isset( $wgBlobCache[$this->mOldId] ) ) {
+                       $obj = $wgBlobCache[$this->mOldId];
+               } else {
+                       $dbr =& wfGetDB( DB_SLAVE );
+                       $row = $dbr->selectRow( 'text', array( 'old_flags', 'old_text' ), array( 'old_id' => $this->mOldId ) );
+                       if( !$row ) {
+                               return false;
+                       }
+                       $flags = explode( ',', $row->old_flags );
+                       if( in_array( 'external', $flags ) ) {
+                               $url=$row->old_text;
+                               @list($proto,$path)=explode('://',$url,2);
+                               if ($path=="") {
+                                       wfProfileOut( $fname );
+                                       return false;
+                               }
+                               require_once('ExternalStore.php');
+                               $row->old_text=ExternalStore::fetchFromUrl($url);
+
+                       }
+                       if( !in_array( 'object', $flags ) ) {
+                               return false;
+                       }
+                       
+                       if( in_array( 'gzip', $flags ) ) {
+                               // This shouldn't happen, but a bug in the compress script
+                               // may at times gzip-compress a HistoryBlob object row.
+                               $obj = unserialize( gzinflate( $row->old_text ) );
+                       } else {
+                               $obj = unserialize( $row->old_text );
+                       }
+                       
+                       if( !is_object( $obj ) ) {
+                               // Correct for old double-serialization bug.
+                               $obj = unserialize( $obj );
+                       }
+                       
+                       // Save this item for reference; if pulling many
+                       // items in a row we'll likely use it again.
+                       $obj->uncompress();
+                       $wgBlobCache = array( $this->mOldId => $obj );
+               }
+               return $obj->getItem( $this->mHash );
+       }
+
+       /** @todo document */
+       function getHash() {
+               return $this->mHash;
+       }
+}
+
+
+/**
+ * To speed up conversion from 1.4 to 1.5 schema, text rows can refer to the
+ * leftover cur table as the backend. This avoids expensively copying hundreds
+ * of megabytes of data during the conversion downtime.
+ *
+ * Serialized HistoryBlobCurStub objects will be inserted into the text table
+ * on conversion if $wgFastSchemaUpgrades is set to true.
+ *
+ * @package MediaWiki
+ */
+class HistoryBlobCurStub {
+       var $mCurId;
+
+       /** @todo document */
+       function HistoryBlobCurStub( $curid = 0 ) {
+               $this->mCurId = $curid;
+       }
+       
+       /**
+        * Sets the location (cur_id) of the main object to which this object
+        * points
+        */
+       function setLocation( $id ) {
+               $this->mCurId = $id;
+       }
+
+       /** @todo document */
+       function getText() {
+               $dbr =& wfGetDB( DB_SLAVE );
+               $row = $dbr->selectRow( 'cur', array( 'cur_text' ), array( 'cur_id' => $this->mCurId ) );
+               if( !$row ) {
+                       return false;
+               }
+               return $row->cur_text;
+       }
+}
+
+
+?>
diff --git a/includes/Hooks.php b/includes/Hooks.php
new file mode 100644 (file)
index 0000000..3e337f8
--- /dev/null
@@ -0,0 +1,126 @@
+<?php
+/**
+ * Hooks.php -- a tool for running hook functions
+ * Copyright 2004, 2005 Evan Prodromou <evan@wikitravel.org>.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @author Evan Prodromou <evan@wikitravel.org>
+ * @package MediaWiki
+ * @see hooks.txt
+ */
+
+if (defined('MEDIAWIKI')) {
+       
+       /** 
+        * Because programmers assign to $wgHooks, we need to be very
+        * careful about its contents. So, there's a lot more error-checking
+        * in here than would normally be necessary.
+        */
+       
+       function wfRunHooks($event, $args = null) {
+               
+               global $wgHooks;
+
+               if (!is_array($wgHooks)) {
+                       wfDebugDieBacktrace("Global hooks array is not an array!\n");
+                       return false;
+               }
+
+               if (!array_key_exists($event, $wgHooks)) {
+                       return true;
+               }
+               
+               if (!is_array($wgHooks[$event])) {
+                       wfDebugDieBacktrace("Hooks array for event '$event' is not an array!\n");
+                       return false;
+               }
+               
+               foreach ($wgHooks[$event] as $hook) {
+                       
+                       $object = NULL;
+                       $method = NULL;
+                       $func = NULL;
+                       $data = NULL;
+                       $have_data = false;
+                       
+                       /* $hook can be: a function, an object, an array of $function and $data,
+                        * an array of just a function, an array of object and method, or an
+                        * array of object, method, and data.
+                        */
+                       
+                       if (is_array($hook)) {
+                               if (count($hook) < 1) {
+                                       wfDebugDieBacktrace("Empty array in hooks for " . $event . "\n");
+                               } else if (is_object($hook[0])) {
+                                       $object = $hook[0];
+                                       if (count($hook) < 2) {
+                                               $method = "on" . $event;
+                                       } else {
+                                               $method = $hook[1];
+                                               if (count($hook) > 2) {
+                                                       $data = $hook[2];
+                                                       $have_data = true;
+                                               }
+                                       }
+                               } else if (is_string($hook[0])) {
+                                       $func = $hook[0];
+                                       if (count($hook) > 1) {
+                                               $data = $hook[1];
+                                               $have_data = true;
+                                       }
+                               } else {
+                                       wfDebugDieBacktrace("Unknown datatype in hooks for " . $event . "\n");
+                               }
+                       } else if (is_string($hook)) { # functions look like strings, too
+                               $func = $hook;
+                       } else if (is_object($hook)) {
+                               $object = $hook;
+                               $method = "on" . $event;
+                       } else {
+                               wfDebugDieBacktrace("Unknown datatype in hooks for " . $event . "\n");
+                       }
+                       
+                       /* We put the first data element on, if needed. */
+                       
+                       if ($have_data) {
+                               $hook_args = array_merge(array($data), $args);
+                       } else {
+                               $hook_args = $args;
+                       }
+                       
+                       /* Call the hook. */
+                       
+                       if ($object) {
+                               $retval = call_user_func_array(array($object, $method), $hook_args);
+                       } else {
+                               $retval = call_user_func_array($func, $hook_args);
+                       }
+                       
+                       /* String return is an error; false return means stop processing. */
+                       
+                       if (is_string($retval)) {
+                               global $wgOut;
+                               $wgOut->fatalError($retval);
+                               return false;
+                       } else if (!$retval) {
+                               return false;
+                       }
+               }
+               
+               return true;
+       }
+} /* if defined(MEDIAWIKI) */ 
+?>
diff --git a/includes/HttpFunctions.php b/includes/HttpFunctions.php
new file mode 100644 (file)
index 0000000..19cd63e
--- /dev/null
@@ -0,0 +1,69 @@
+<?php
+/**
+ * Various HTTP related functions
+ */
+
+/**
+ * Get the contents of a file by HTTP
+ * 
+ * if $timeout is 'default', $wgHTTPTimeout is used
+ */
+function wfGetHTTP( $url, $timeout = 'default' ) {
+       global $wgServer, $wgHTTPTimeout, $wgHTTPProxy;
+       
+
+       # Use curl if available
+       if ( function_exists( 'curl_init' ) ) {
+               $c = curl_init( $url );
+               if ( wfIsLocalURL( $url ) ) {
+                       curl_setopt( $c, CURLOPT_PROXY, 'localhost:80' );
+               } else if ($wgHTTPProxy)
+                       curl_setopt($c, CURLOPT_PROXY, $wgHTTPProxy);
+
+               if ( $timeout == 'default' ) {
+                       $timeout = $wgHTTPTimeout;
+               }
+               curl_setopt( $c, CURLOPT_TIMEOUT, $timeout );
+               ob_start();
+               curl_exec( $c );
+               $text = ob_get_contents();
+               ob_end_clean();
+               curl_close( $c );
+       } else {
+               # Otherwise use file_get_contents, or its compatibility function from GlobalFunctions.php
+               # This may take 3 minutes to time out, and doesn't have local fetch capabilities
+               $url_fopen = ini_set( 'allow_url_fopen', 1 );
+               $text = file_get_contents( $url );
+               ini_set( 'allow_url_fopen', $url_fopen );
+       }
+       return $text;
+}
+
+/**
+ * Check if the URL can be served by localhost
+ */
+function wfIsLocalURL( $url ) {
+       global $wgConf;
+       // Extract host part
+       if ( preg_match( '!^http://([\w.-]+)[/:].*$!', $url, $matches ) ) {
+               $host = $matches[1];
+               // Split up dotwise
+               $domainParts = explode( '.', $host );
+               // Check if this domain or any superdomain is listed in $wgConf as a local virtual host
+               $domainParts = array_reverse( $domainParts );
+               for ( $i = 0; $i < count( $domainParts ); $i++ ) {
+                       $domainPart = $domainParts[$i];
+                       if ( $i == 0 ) {
+                               $domain = $domainPart;
+                       } else {
+                               $domain = $domainPart . '.' . $domain;
+                       }
+                       if ( $wgConf->isLocalVHost( $domain ) ) {
+                               return true;
+                       }
+               }
+       }
+       return false;
+}
+
+?>
diff --git a/includes/Image.php b/includes/Image.php
new file mode 100644 (file)
index 0000000..52750be
--- /dev/null
@@ -0,0 +1,1814 @@
+<?php
+/**
+ * @package MediaWiki
+ */
+
+/**
+ * NOTE FOR WINDOWS USERS:
+ * To enable EXIF functions, add the folloing lines to the
+ * "Windows extensions" section of php.ini:
+ *
+ * extension=extensions/php_mbstring.dll
+ * extension=extensions/php_exif.dll
+ */
+
+if ($wgShowEXIF)
+       require_once('Exif.php');
+
+/**
+ * Bump this number when serialized cache records may be incompatible.
+ */
+define( 'MW_IMAGE_VERSION', 1 );
+
+/**
+ * Class to represent an image
+ * 
+ * Provides methods to retrieve paths (physical, logical, URL),
+ * to generate thumbnails or for uploading.
+ * @package MediaWiki
+ */
+class Image
+{
+       /**#@+
+        * @access private
+        */
+       var     $name,          # name of the image (constructor)
+               $imagePath,     # Path of the image (loadFromXxx)
+               $url,           # Image URL (accessor)
+               $title,         # Title object for this image (constructor)
+               $fileExists,    # does the image file exist on disk? (loadFromXxx)
+               $fromSharedDirectory, # load this image from $wgSharedUploadDirectory (loadFromXxx)
+               $historyLine,   # Number of line to return by nextHistoryLine() (constructor)
+               $historyRes,    # result of the query for the image's history (nextHistoryLine)
+               $width,         # \
+               $height,        #  |
+               $bits,          #   --- returned by getimagesize (loadFromXxx)
+               $attr,          # /
+               $type,          # MEDIATYPE_xxx (bitmap, drawing, audio...)
+               $mime,          # MIME type, determined by MimeMagic::guessMimeType
+               $size,          # Size in bytes (loadFromXxx)
+               $metadata,      # Metadata
+               $dataLoaded;    # Whether or not all this has been loaded from the database (loadFromXxx)
+
+
+       /**#@-*/
+
+       /**
+        * Create an Image object from an image name
+        *
+        * @param string $name name of the image, used to create a title object using Title::makeTitleSafe
+        * @access public
+        */
+       function newFromName( $name ) {
+               $title = Title::makeTitleSafe( NS_IMAGE, $name );
+               return new Image( $title );
+       }
+
+       /** 
+        * Obsolete factory function, use constructor
+        */
+       function newFromTitle( $title ) {
+               return new Image( $title );
+       }
+       
+       function Image( $title ) {
+               global $wgShowEXIF;
+               
+               if( !is_object( $title ) ) {
+                       wfDebugDieBacktrace( 'Image constructor given bogus title.' );
+               }
+               $this->title =& $title;
+               $this->name = $title->getDBkey();
+               $this->metadata = serialize ( array() ) ;
+
+               $n = strrpos( $this->name, '.' );
+               $this->extension = strtolower( $n ? substr( $this->name, $n + 1 ) : '' );
+               $this->historyLine = 0;
+
+               $this->dataLoaded = false;
+       }
+
+       /**
+        * Get the memcached keys
+        * Returns an array, first element is the local cache key, second is the shared cache key, if there is one
+        */
+       function getCacheKeys( $shared = false ) {
+               global $wgDBname, $wgUseSharedUploads, $wgSharedUploadDBname, $wgCacheSharedUploads;
+               
+               $foundCached = false;
+               $hashedName = md5($this->name);
+               $keys = array( "$wgDBname:Image:$hashedName" );
+               if ( $wgUseSharedUploads && $wgSharedUploadDBname && $wgCacheSharedUploads ) {
+                       $keys[] = "$wgSharedUploadDBname:Image:$hashedName";
+               }
+               return $keys;
+       }
+       
+       /** 
+        * Try to load image metadata from memcached. Returns true on success.
+        */
+       function loadFromCache() {
+               global $wgUseSharedUploads, $wgMemc;
+               $fname = 'Image::loadFromMemcached';
+               wfProfileIn( $fname );
+               $this->dataLoaded = false;
+               $keys = $this->getCacheKeys();
+               $cachedValues = $wgMemc->get( $keys[0] );
+
+               // Check if the key existed and belongs to this version of MediaWiki
+               if (!empty($cachedValues) && is_array($cachedValues)
+                 && isset($cachedValues['version']) && ( $cachedValues['version'] == MW_IMAGE_VERSION )
+                 && $cachedValues['fileExists'] && isset( $cachedValues['mime'] ) && isset( $cachedValues['metadata'] ) ) 
+               {
+                       if ( $wgUseSharedUploads && $cachedValues['fromShared']) {
+                               # if this is shared file, we need to check if image
+                               # in shared repository has not changed
+                               if ( isset( $keys[1] ) ) {
+                                       $commonsCachedValues = $wgMemc->get( $keys[1] );
+                                       if (!empty($commonsCachedValues) && is_array($commonsCachedValues)
+                                         && isset($commonsCachedValues['version'])
+                                         && ( $commonsCachedValues['version'] == MW_IMAGE_VERSION )
+                                         && isset($commonsCachedValues['mime'])) {
+                                               wfDebug( "Pulling image metadata from shared repository cache\n" );
+                                               $this->name = $commonsCachedValues['name'];
+                                               $this->imagePath = $commonsCachedValues['imagePath'];
+                                               $this->fileExists = $commonsCachedValues['fileExists'];
+                                               $this->width = $commonsCachedValues['width'];
+                                               $this->height = $commonsCachedValues['height'];
+                                               $this->bits = $commonsCachedValues['bits'];
+                                               $this->type = $commonsCachedValues['type'];
+                                               $this->mime = $commonsCachedValues['mime'];
+                                               $this->metadata = $commonsCachedValues['metadata'];
+                                               $this->size = $commonsCachedValues['size'];
+                                               $this->fromSharedDirectory = true;
+                                               $this->dataLoaded = true;
+                                               $this->imagePath = $this->getFullPath(true);
+                                       }
+                               }
+                       } else {
+                               wfDebug( "Pulling image metadata from local cache\n" );
+                               $this->name = $cachedValues['name'];
+                               $this->imagePath = $cachedValues['imagePath'];
+                               $this->fileExists = $cachedValues['fileExists'];
+                               $this->width = $cachedValues['width'];
+                               $this->height = $cachedValues['height'];
+                               $this->bits = $cachedValues['bits'];
+                               $this->type = $cachedValues['type'];
+                               $this->mime = $cachedValues['mime'];
+                               $this->metadata = $cachedValues['metadata'];
+                               $this->size = $cachedValues['size'];
+                               $this->fromSharedDirectory = false;
+                               $this->dataLoaded = true;
+                               $this->imagePath = $this->getFullPath();
+                       }
+               }
+               if ( $this->dataLoaded ) {
+                       wfIncrStats( 'image_cache_hit' );
+               } else {
+                       wfIncrStats( 'image_cache_miss' );
+               }
+
+               wfProfileOut( $fname );
+               return $this->dataLoaded;
+       }
+
+       /** 
+        * Save the image metadata to memcached
+        */
+       function saveToCache() {
+               global $wgMemc;
+               $this->load();
+               $keys = $this->getCacheKeys();
+               if ( $this->fileExists ) {
+                       // We can't cache negative metadata for non-existent files,
+                       // because if the file later appears in commons, the local
+                       // keys won't be purged.
+                       $cachedValues = array(
+                               'version'    => MW_IMAGE_VERSION,
+                               'name'       => $this->name,
+                               'imagePath'  => $this->imagePath,
+                               'fileExists' => $this->fileExists,
+                               'fromShared' => $this->fromSharedDirectory,
+                               'width'      => $this->width,
+                               'height'     => $this->height,
+                               'bits'       => $this->bits,
+                               'type'       => $this->type,
+                               'mime'       => $this->mime,
+                               'metadata'   => $this->metadata,
+                               'size'       => $this->size );
+
+                       $wgMemc->set( $keys[0], $cachedValues );
+               } else {
+                       // However we should clear them, so they aren't leftover
+                       // if we've deleted the file.
+                       $wgMemc->delete( $keys[0] );
+               }
+       }
+       
+       /** 
+        * Load metadata from the file itself
+        */
+       function loadFromFile() {
+               global $wgUseSharedUploads, $wgSharedUploadDirectory, $wgLang,
+                      $wgShowEXIF;
+               $fname = 'Image::loadFromFile';
+               wfProfileIn( $fname );
+               $this->imagePath = $this->getFullPath();
+               $this->fileExists = file_exists( $this->imagePath );
+               $this->fromSharedDirectory = false;
+               $gis = array();
+               
+               if (!$this->fileExists) wfDebug("$fname: ".$this->imagePath." not found locally!\n"); 
+
+               # If the file is not found, and a shared upload directory is used, look for it there.
+               if (!$this->fileExists && $wgUseSharedUploads && $wgSharedUploadDirectory) {                    
+                       # In case we're on a wgCapitalLinks=false wiki, we 
+                       # capitalize the first letter of the filename before 
+                       # looking it up in the shared repository.
+                       $sharedImage = Image::newFromName( $wgLang->ucfirst($this->name) );
+                       $this->fileExists = file_exists( $sharedImage->getFullPath(true) );
+                       if ( $this->fileExists ) {
+                               $this->name = $sharedImage->name;
+                               $this->imagePath = $this->getFullPath(true);
+                               $this->fromSharedDirectory = true;
+                       }
+               }
+
+
+               if ( $this->fileExists ) {
+                       $magic=& wfGetMimeMagic();
+               
+                       $this->mime = $magic->guessMimeType($this->imagePath,true);
+                       $this->type = $magic->getMediaType($this->imagePath,$this->mime);
+                       
+                       # Get size in bytes
+                       $this->size = filesize( $this->imagePath );
+
+                       $magic=& wfGetMimeMagic();
+                       
+                       # Height and width
+                       if( $this->mime == 'image/svg' ) {
+                               wfSuppressWarnings();
+                               $gis = wfGetSVGsize( $this->imagePath );
+                               wfRestoreWarnings();
+                       }
+                       elseif ( !$magic->isPHPImageType( $this->mime ) ) {
+                               # Don't try to get the width and height of sound and video files, that's bad for performance
+                               $gis[0]= 0; //width
+                               $gis[1]= 0; //height
+                               $gis[2]= 0; //unknown
+                               $gis[3]= ""; //width height string
+                       }
+                       else {
+                               wfSuppressWarnings();
+                               $gis = getimagesize( $this->imagePath );
+                               wfRestoreWarnings();
+                       }
+                       
+                       wfDebug("$fname: ".$this->imagePath." loaded, ".$this->size." bytes, ".$this->mime.".\n"); 
+               }
+               else {
+                       $gis[0]= 0; //width
+                       $gis[1]= 0; //height
+                       $gis[2]= 0; //unknown
+                       $gis[3]= ""; //width height string
+                       
+                       $this->mime = NULL;
+                       $this->type = MEDIATYPE_UNKNOWN;
+                       wfDebug("$fname: ".$this->imagePath." NOT FOUND!\n"); 
+               }
+               
+               $this->width = $gis[0];
+               $this->height = $gis[1];
+               
+               #NOTE: $gis[2] contains a code for the image type. This is no longer used.
+               
+               #NOTE: we have to set this flag early to avoid load() to be called 
+               # be some of the functions below. This may lead to recursion or other bad things!
+               # as ther's only one thread of execution, this should be safe anyway.
+               $this->dataLoaded = true;
+               
+               
+               if ($this->fileExists && $wgShowEXIF) $this->metadata = serialize ( $this->retrieveExifData() ) ;
+               else $this->metadata = serialize ( array() ) ;
+               
+               if ( isset( $gis['bits'] ) )  $this->bits = $gis['bits'];
+               else $this->bits = 0;
+               
+               wfProfileOut( $fname );
+       }
+
+       /** 
+        * Load image metadata from the DB
+        */
+       function loadFromDB() {
+               global $wgUseSharedUploads, $wgSharedUploadDBname, $wgSharedUploadDBprefix, $wgLang;
+               $fname = 'Image::loadFromDB';
+               wfProfileIn( $fname );
+               
+               $dbr =& wfGetDB( DB_SLAVE );
+               
+               $this->checkDBSchema($dbr);
+               
+               $row = $dbr->selectRow( 'image', 
+                       array( 'img_size', 'img_width', 'img_height', 'img_bits', 
+                              'img_media_type', 'img_major_mime', 'img_minor_mime', 'img_metadata' ),
+                       array( 'img_name' => $this->name ), $fname );
+               if ( $row ) {
+                       $this->fromSharedDirectory = false;
+                       $this->fileExists = true;
+                       $this->loadFromRow( $row );
+                       $this->imagePath = $this->getFullPath();
+                       // Check for rows from a previous schema, quietly upgrade them
+                       if ( is_null($this->type) ) {
+                               $this->upgradeRow();
+                       }
+               } elseif ( $wgUseSharedUploads && $wgSharedUploadDBname ) {
+                       # In case we're on a wgCapitalLinks=false wiki, we 
+                       # capitalize the first letter of the filename before 
+                       # looking it up in the shared repository.
+                       $name = $wgLang->ucfirst($this->name);
+
+                       $row = $dbr->selectRow( "`$wgSharedUploadDBname`.{$wgSharedUploadDBprefix}image",
+                               array( 
+                                       'img_size', 'img_width', 'img_height', 'img_bits', 
+                                       'img_media_type', 'img_major_mime', 'img_minor_mime', 'img_metadata' ),
+                               array( 'img_name' => $name ), $fname );
+                       if ( $row ) {
+                               $this->fromSharedDirectory = true;
+                               $this->fileExists = true;
+                               $this->imagePath = $this->getFullPath(true);
+                               $this->name = $name;
+                               $this->loadFromRow( $row );
+                               
+                               // Check for rows from a previous schema, quietly upgrade them
+                               if ( is_null($this->type) ) {
+                                       $this->upgradeRow();
+                               }
+                       }
+               }
+               
+               if ( !$row ) {
+                       $this->size = 0;
+                       $this->width = 0;
+                       $this->height = 0;
+                       $this->bits = 0;
+                       $this->type = 0;
+                       $this->fileExists = false;
+                       $this->fromSharedDirectory = false;
+                       $this->metadata = serialize ( array() ) ;
+               }
+
+               # Unconditionally set loaded=true, we don't want the accessors constantly rechecking
+               $this->dataLoaded = true;
+               wfProfileOut( $fname );
+       }
+
+       /*
+        * Load image metadata from a DB result row
+        */
+       function loadFromRow( &$row ) {
+               $this->size = $row->img_size;
+               $this->width = $row->img_width;
+               $this->height = $row->img_height;
+               $this->bits = $row->img_bits;
+               $this->type = $row->img_media_type;
+               
+               $major= $row->img_major_mime;
+               $minor= $row->img_minor_mime;
+               
+               if (!$major) $this->mime = "unknown/unknown";
+               else {
+                       if (!$minor) $minor= "unknown";
+                       $this->mime = $major.'/'.$minor;
+               }
+               
+               $this->metadata = $row->img_metadata;
+               if ( $this->metadata == "" ) $this->metadata = serialize ( array() ) ;
+               
+               $this->dataLoaded = true;
+       }
+
+       /**
+        * Load image metadata from cache or DB, unless already loaded
+        */
+       function load() {
+               global $wgSharedUploadDBname, $wgUseSharedUploads;
+               if ( !$this->dataLoaded ) {
+                       if ( !$this->loadFromCache() ) {
+                               $this->loadFromDB();
+                               if ( !$wgSharedUploadDBname && $wgUseSharedUploads ) {
+                                       $this->loadFromFile();
+                               } elseif ( $this->fileExists ) {
+                                       $this->saveToCache();
+                               }
+                       }
+                       $this->dataLoaded = true;
+               }
+       }
+
+       /** 
+        * Metadata was loaded from the database, but the row had a marker indicating it needs to be 
+        * upgraded from the 1.4 schema, which had no width, height, bits or type. Upgrade the row.
+        */
+       function upgradeRow() {
+               global $wgDBname, $wgSharedUploadDBname;
+               $fname = 'Image::upgradeRow';
+               wfProfileIn( $fname );
+
+               $this->loadFromFile();
+               $dbw =& wfGetDB( DB_MASTER );
+
+               if ( $this->fromSharedDirectory ) {
+                       if ( !$wgSharedUploadDBname ) {
+                               wfProfileOut( $fname );
+                               return;
+                       }
+
+                       // Write to the other DB using selectDB, not database selectors
+                       // This avoids breaking replication in MySQL
+                       $dbw->selectDB( $wgSharedUploadDBname );
+               }
+               
+               $this->checkDBSchema($dbw);
+               
+               if (strpos($this->mime,'/')!==false) {
+                       list($major,$minor)= explode('/',$this->mime,2);
+               }
+               else {
+                       $major= $this->mime;
+                       $minor= "unknown";
+               }
+               
+               wfDebug("$fname: upgrading ".$this->name." to 1.5 schema\n");
+               
+               $dbw->update( 'image', 
+                       array( 
+                               'img_width' => $this->width,
+                               'img_height' => $this->height,
+                               'img_bits' => $this->bits,
+                               'img_media_type' => $this->type,
+                               'img_major_mime' => $major,
+                               'img_minor_mime' => $minor,
+                               'img_metadata' => $this->metadata,
+                       ), array( 'img_name' => $this->name ), $fname
+               );
+               if ( $this->fromSharedDirectory ) {
+                       $dbw->selectDB( $wgDBname );
+               }
+               wfProfileOut( $fname );
+       }
+                               
+       /**
+        * Return the name of this image
+        * @access public
+        */
+       function getName() {
+               return $this->name;
+       }
+
+       /**
+        * Return the associated title object
+        * @access public
+        */
+       function getTitle() {
+               return $this->title;
+       }
+
+       /**
+        * Return the URL of the image file
+        * @access public
+        */
+       function getURL() {
+               if ( !$this->url ) {
+                       $this->load();
+                       if($this->fileExists) {                 
+                               $this->url = Image::imageUrl( $this->name, $this->fromSharedDirectory );
+                       } else {
+                               $this->url = '';
+                       }
+               }
+               return $this->url;
+       }
+       
+       function getViewURL() {
+               if( $this->mustRender()) {
+                       if( $this->canRender() ) {
+                               return $this->createThumb( $this->getWidth() );
+                       }
+                       else {
+                               wfDebug('Image::getViewURL(): supposed to render '.$this->name.' ('.$this->mime."), but can't!\n");
+                               return $this->getURL(); #hm... return NULL?
+                       }
+               } else {
+                       return $this->getURL();
+               }
+       }
+
+       /**
+        * Return the image path of the image in the
+        * local file system as an absolute path
+        * @access public
+        */
+       function getImagePath() {
+               $this->load();
+               return $this->imagePath;
+       }
+
+       /**
+        * Return the width of the image
+        *
+        * Returns -1 if the file specified is not a known image type
+        * @access public
+        */
+       function getWidth() {
+               $this->load();
+               return $this->width;
+       }
+
+       /**
+        * Return the height of the image
+        *
+        * Returns -1 if the file specified is not a known image type
+        * @access public
+        */
+       function getHeight() {
+               $this->load();
+               return $this->height;
+       }
+
+       /**
+        * Return the size of the image file, in bytes
+        * @access public
+        */
+       function getSize() {
+               $this->load();
+               return $this->size;
+       }
+
+       /**
+        * Returns the mime type of the file.
+        */
+       function getMimeType() {
+               $this->load();
+               return $this->mime;
+       }
+       
+       /**
+        * Return the type of the media in the file. 
+        * Use the value returned by this function with the MEDIATYPE_xxx constants.
+        */
+       function getMediaType() {
+               $this->load();
+               return $this->type;
+       }
+
+       /**
+        * Checks if the file can be presented to the browser as a bitmap.
+        * 
+        * Currently, this checks if the file is an image format 
+        * that can be converted to a format
+        * supported by all browsers (namely GIF, PNG and JPEG), 
+        * or if it is an SVG image and SVG conversion is enabled.
+        *
+        * @todo remember the result of this check.
+        */
+       function canRender() {
+               global $wgUseImageMagick;
+               
+               if( $this->getWidth()<=0 || $this->getHeight()<=0 ) return false;
+       
+               $mime= $this->getMimeType();
+               
+               if (!$mime || $mime==='unknown' || $mime==='unknown/unknown') return false;
+               
+               #if it's SVG, check if there's a converter enabled    
+               if ($mime === 'image/svg') {
+                       global $wgSVGConverters, $wgSVGConverter;
+                       
+                       if ($wgSVGConverter && isset( $wgSVGConverters[$wgSVGConverter])) {
+                               return true;
+                       }
+               }
+               
+               #image formats available on ALL browsers
+               if (  $mime === 'image/gif'
+                  || $mime === 'image/png'
+                  || $mime === 'image/jpeg' ) return true;
+                   
+               #image formats that can be converted to the above formats
+               if ($wgUseImageMagick) {
+                       #convertable by ImageMagick (there are more...)
+                       if ( $mime === 'image/vnd.wap.wbmp'
+                         || $mime === 'image/x-xbitmap' 
+                         || $mime === 'image/x-xpixmap' 
+                         #|| $mime === 'image/x-icon'   #file may be split into multiple parts
+                         || $mime === 'image/x-portable-anymap'
+                         || $mime === 'image/x-portable-bitmap'
+                         || $mime === 'image/x-portable-graymap'
+                         || $mime === 'image/x-portable-pixmap'
+                         #|| $mime === 'image/x-photoshop'  #this takes a lot of CPU and RAM!
+                         || $mime === 'image/x-rgb'
+                         || $mime === 'image/x-bmp'
+                         || $mime === 'image/tiff' ) return true;
+               }
+               else {
+                       #convertable by the PHP GD image lib
+                       if ( $mime === 'image/vnd.wap.wbmp'
+                         || $mime === 'image/x-xbitmap' ) return true;
+               }
+                  
+               return false;
+       }
+       
+
+       /**
+        * Return true if the file is of a type that can't be directly
+        * rendered by typical browsers and needs to be re-rasterized.
+        * 
+        * This returns true for everything but the bitmap types 
+        * supported by all browsers, i.e. JPEG; GIF and PNG. It will
+        * also return true for any non-image formats.
+        *
+        * @return bool
+        */
+       function mustRender() {
+               $mime= $this->getMimeType();
+               
+               if (  $mime === "image/gif"
+                  || $mime === "image/png"
+                  || $mime === "image/jpeg" ) return false;
+                  
+               return true;
+       }
+       
+       /**
+        * Determines if this media file may be shown inline on a page.
+        * 
+        * This is currently synonymous to canRender(), but this could be 
+        * extended to also allow inline display of other media,
+        * like flash animations or videos. If you do so, please keep in mind that 
+        * that could be a security risk.
+        */
+       function allowInlineDisplay() {
+               return $this->canRender();
+       }
+       
+       /**
+        * Determines if this media file is in a format that is unlikely to
+        * contain viruses or malicious content. It uses the global
+        * $wgTrustedMediaFormats list to determine if the file is safe.
+        * 
+        * This is used to show a warning on the description page of non-safe files.
+        * It may also be used to disallow direct [[media:...]] links to such files.
+        *
+        * Note that this function will always return ture if allowInlineDisplay() 
+        * or isTrustedFile() is true for this file.
+        */
+       function isSafeFile() {
+               if ($this->allowInlineDisplay()) return true;
+               if ($this->isTrustedFile()) return true;
+               
+               global $wgTrustedMediaFormats;
+               
+               $type= $this->getMediaType();
+               $mime= $this->getMimeType();
+               #wfDebug("Image::isSafeFile: type= $type, mime= $mime\n");
+               
+               if (!$type || $type===MEDIATYPE_UNKNOWN) return false; #unknown type, not trusted
+               if ( in_array( $type, $wgTrustedMediaFormats) ) return true;
+               
+               if ($mime==="unknown/unknown") return false; #unknown type, not trusted
+               if ( in_array( $mime, $wgTrustedMediaFormats) ) return true;
+               
+               return false;
+       }
+       
+       /** Returns true if the file is flagegd as trusted. Files flagged that way
+       * can be linked to directly, even if that is not allowed for this type of
+       * file normally.
+       *
+       * This is a dummy function right now and always returns false. It could be
+       * implemented to extract a flag from the database. The trusted flag could be
+       * set on upload, if the user has sufficient privileges, to bypass script-
+       * and html-filters. It may even be coupeled with cryptographics signatures
+       * or such.
+       */
+       function isTrustedFile() {
+               #this could be implemented to check a flag in the databas,
+               #look for signatures, etc
+               return false; 
+       }
+
+       /**
+        * Return the escapeLocalURL of this image
+        * @access public
+        */
+       function getEscapeLocalURL() {
+               $this->getTitle();
+               return $this->title->escapeLocalURL();
+       }
+
+       /**
+        * Return the escapeFullURL of this image
+        * @access public
+        */
+       function getEscapeFullURL() {
+               $this->getTitle();
+               return $this->title->escapeFullURL();
+       }
+
+       /**
+        * Return the URL of an image, provided its name.
+        *
+        * @param string $name  Name of the image, without the leading "Image:"
+        * @param boolean $fromSharedDirectory  Should this be in $wgSharedUploadPath?   
+        * @return string URL of $name image
+        * @access public
+        * @static
+        */
+       function imageUrl( $name, $fromSharedDirectory = false ) {
+               global $wgUploadPath,$wgUploadBaseUrl,$wgSharedUploadPath;
+               if($fromSharedDirectory) {
+                       $base = '';
+                       $path = $wgSharedUploadPath;
+               } else {
+                       $base = $wgUploadBaseUrl;
+                       $path = $wgUploadPath;
+               }                       
+               $url = "{$base}{$path}" .  wfGetHashPath($name, $fromSharedDirectory) . "{$name}";
+               return wfUrlencode( $url );
+       }
+
+       /**
+        * Returns true if the image file exists on disk.
+        * @return boolean Whether image file exist on disk.
+        * @access public
+        */
+       function exists() {
+               $this->load();
+               return $this->fileExists;
+       }
+
+       /**
+        * @todo document
+        * @access private
+        */
+       function thumbUrl( $width, $subdir='thumb') {
+               global $wgUploadPath, $wgUploadBaseUrl,
+                      $wgSharedUploadPath,$wgSharedUploadDirectory,
+                          $wgSharedThumbnailScriptPath, $wgThumbnailScriptPath;
+
+               // Generate thumb.php URL if possible
+               $script = false;
+               $url = false;
+
+               if ( $this->fromSharedDirectory ) {
+                       if ( $wgSharedThumbnailScriptPath ) {
+                               $script = $wgSharedThumbnailScriptPath;
+                       }
+               } else {
+                       if ( $wgThumbnailScriptPath ) {
+                               $script = $wgThumbnailScriptPath;
+                       }
+               }
+               if ( $script ) {
+                       $url = $script . '?f=' . urlencode( $this->name ) . '&w=' . urlencode( $width );
+                       if( $this->mustRender() ) {
+                               $url.= '&r=1';
+                       }
+               } else {  
+                       $name = $this->thumbName( $width );             
+                       if($this->fromSharedDirectory) {
+                               $base = '';
+                               $path = $wgSharedUploadPath;
+                       } else {
+                               $base = $wgUploadBaseUrl;
+                               $path = $wgUploadPath;
+                       }
+                       if ( Image::isHashed( $this->fromSharedDirectory ) ) {
+                               $url = "{$base}{$path}/{$subdir}" . 
+                               wfGetHashPath($this->name, $this->fromSharedDirectory)
+                               . $this->name.'/'.$name;
+                               $url = wfUrlencode( $url );
+                       } else {
+                               $url = "{$base}{$path}/{$subdir}/{$name}";
+                       }
+               }
+               return array( $script !== false, $url );
+       }
+
+       /**
+        * Return the file name of a thumbnail of the specified width
+        *
+        * @param integer $width        Width of the thumbnail image
+        * @param boolean $shared       Does the thumbnail come from the shared repository?
+        * @access private
+        */
+       function thumbName( $width ) {
+               $thumb = $width."px-".$this->name;
+               
+               if( $this->mustRender() ) {
+                       if( $this->canRender() ) {
+                               # Rasterize to PNG (for SVG vector images, etc)
+                               $thumb .= '.png';
+                       }
+                       else {
+                               #should we use iconThumb here to get a symbolic thumbnail?
+                               #or should we fail with an internal error?
+                               return NULL; //can't make bitmap
+                       }
+               }
+               return $thumb;
+       }
+
+       /**
+        * Create a thumbnail of the image having the specified width/height.
+        * The thumbnail will not be created if the width is larger than the
+        * image's width. Let the browser do the scaling in this case.
+        * The thumbnail is stored on disk and is only computed if the thumbnail
+        * file does not exist OR if it is older than the image.
+        * Returns the URL.
+        * 
+        * Keeps aspect ratio of original image. If both width and height are
+        * specified, the generated image will be no bigger than width x height,
+        * and will also have correct aspect ratio.
+        *
+        * @param integer $width        maximum width of the generated thumbnail
+        * @param integer $height       maximum height of the image (optional)
+        * @access public
+        */
+       function createThumb( $width, $height=-1 ) {
+               $thumb = $this->getThumbnail( $width, $height );
+               if( is_null( $thumb ) ) return '';
+               return $thumb->getUrl();
+       }
+       
+       /**
+        * As createThumb, but returns a ThumbnailImage object. This can
+        * provide access to the actual file, the real size of the thumb,
+        * and can produce a convenient <img> tag for you.
+        *
+        * @param integer $width        maximum width of the generated thumbnail
+        * @param integer $height       maximum height of the image (optional)
+        * @return ThumbnailImage
+        * @access public
+        */
+       function getThumbnail( $width, $height=-1 ) {
+               if ( $height == -1 ) {
+                       return $this->renderThumb( $width );
+               }
+               $this->load();
+               
+               if ($this->canRender()) {
+                       if ( $width < $this->width ) {
+                               $thumbheight = $this->height * $width / $this->width;
+                               $thumbwidth = $width;
+                       } else {
+                               $thumbheight = $this->height;
+                               $thumbwidth = $this->width;
+                       }
+                       if ( $thumbheight > $height ) {
+                               $thumbwidth = $thumbwidth * $height / $thumbheight;
+                               $thumbheight = $height;
+                       }
+                       
+                       $thumb = $this->renderThumb( $thumbwidth );
+               }
+               else $thumb= NULL; #not a bitmap or renderable image, don't try.
+               
+               if( is_null( $thumb ) ) {
+                       $thumb = $this->iconThumb();
+               }
+               return $thumb;
+       }
+       
+       /**
+        * @return ThumbnailImage
+        */
+       function iconThumb() {
+               global $wgStylePath, $wgStyleDirectory;
+               
+               $try = array( 'fileicon-' . $this->extension . '.png', 'fileicon.png' );
+               foreach( $try as $icon ) {
+                       $path = '/common/images/icons/' . $icon;
+                       $filepath = $wgStyleDirectory . $path;
+                       if( file_exists( $filepath ) ) {
+                               return new ThumbnailImage( $wgStylePath . $path, 120, 120 );
+                       }
+               }
+               return null;
+       }
+               
+       /**
+        * Create a thumbnail of the image having the specified width.
+        * The thumbnail will not be created if the width is larger than the
+        * image's width. Let the browser do the scaling in this case.
+        * The thumbnail is stored on disk and is only computed if the thumbnail
+        * file does not exist OR if it is older than the image.
+        * Returns an object which can return the pathname, URL, and physical
+        * pixel size of the thumbnail -- or null on failure.
+        *
+        * @return ThumbnailImage
+        * @access private
+        */
+       function renderThumb( $width, $useScript = true ) {
+               global $wgUseSquid, $wgInternalServer;
+               global $wgThumbnailScriptPath, $wgSharedThumbnailScriptPath;
+
+               $fname = 'Image::renderThumb';
+               wfProfileIn( $fname );
+               
+               $width = IntVal( $width );
+
+               $this->load();
+               if ( ! $this->exists() )
+               {
+                       # If there is no image, there will be no thumbnail
+                       wfProfileOut( $fname );
+                       return null;
+               }
+               
+               # Sanity check $width
+               if( $width <= 0 || $this->width <= 0) {
+                       # BZZZT
+                       wfProfileOut( $fname );
+                       return null;
+               }
+
+               global $wgSVGMaxSize;
+               $maxsize = $this->mustRender()
+                       ? max( $this->width, $wgSVGMaxSize )
+                       : $this->width - 1;
+               if( $width > $maxsize ) {
+                       # Don't make an image bigger than the source
+                       $thumb = new ThumbnailImage( $this->getViewURL(), $this->getWidth(), $this->getHeight() );
+                       wfProfileOut( $fname );
+                       return $thumb;
+               }
+               
+               $height = floor( $this->height * ( $width/$this->width ) );
+               
+               list( $isScriptUrl, $url ) = $this->thumbUrl( $width );
+               if ( $isScriptUrl && $useScript ) {
+                       // Use thumb.php to render the image
+                       $thumb = new ThumbnailImage( $url, $width, $height );
+                       wfProfileOut( $fname );
+                       return $thumb;
+               }
+
+               $thumbName = $this->thumbName( $width, $this->fromSharedDirectory );
+               $thumbPath = wfImageThumbDir( $this->name, $this->fromSharedDirectory ).'/'.$thumbName;
+
+               if ( is_dir( $thumbPath ) ) {
+                       // Directory where file should be
+                       // This happened occasionally due to broken migration code in 1.5
+                       // Rename to broken-*
+                       global $wgUploadDirectory;
+                       for ( $i = 0; $i < 100 ; $i++ ) {
+                               $broken = "$wgUploadDirectory/broken-$i-$thumbName";
+                               if ( !file_exists( $broken ) ) {
+                                       rename( $thumbPath, $broken );
+                                       break;
+                               }
+                       }
+                       // Code below will ask if it exists, and the answer is now no
+                       clearstatcache();
+               }
+
+               if ( !file_exists( $thumbPath ) ) {
+                       $oldThumbPath = wfDeprecatedThumbDir( $thumbName, 'thumb', $this->fromSharedDirectory ).
+                               '/'.$thumbName;
+                       $done = false;
+
+                       // Migration from old directory structure
+                       if ( is_file( $oldThumbPath ) ) {
+                               if ( filemtime($oldThumbPath) >= filemtime($this->imagePath) ) {
+                                       if ( file_exists( $thumbPath ) ) {
+                                               if ( !is_dir( $thumbPath ) ) {
+                                                       // Old image in the way of rename
+                                                       unlink( $thumbPath );
+                                               } else {
+                                                       // This should have been dealt with already
+                                                       wfDebugDieBacktrace( "Directory where image should be: $thumbPath" );
+                                               }
+                                       }
+                                       // Rename the old image into the new location
+                                       rename( $oldThumbPath, $thumbPath );
+                                       $done = true;
+                               } else {
+                                       unlink( $oldThumbPath );
+                               }
+                       }
+                       if ( !$done ) {
+                               $this->reallyRenderThumb( $thumbPath, $width, $height );
+
+                               # Purge squid
+                               # This has to be done after the image is updated and present for all machines on NFS, 
+                               # or else the old version might be stored into the squid again
+                               if ( $wgUseSquid ) {
+                                       if ( substr( $url, 0, 4 ) == 'http' ) {
+                                               $urlArr = array( $url );
+                                       } else {
+                                               $urlArr = array( $wgInternalServer.$url );
+                                       }
+                                       wfPurgeSquidServers($urlArr);
+                               }
+                       }
+               }
+               
+               $thumb = new ThumbnailImage( $url, $width, $height, $thumbPath );
+               wfProfileOut( $fname );
+               return $thumb;
+       } // END OF function renderThumb
+
+       /**
+        * Really render a thumbnail
+        * Call this only for images for which canRender() returns true.
+        *
+        * @access private
+        */
+       function reallyRenderThumb( $thumbPath, $width, $height ) {
+               global $wgSVGConverters, $wgSVGConverter,
+                       $wgUseImageMagick, $wgImageMagickConvertCommand;
+               
+               $this->load();
+               
+               if( $this->mime === "image/svg" ) {
+                       #Right now we have only SVG
+                       
+                       global $wgSVGConverters, $wgSVGConverter;
+                       if( isset( $wgSVGConverters[$wgSVGConverter] ) ) {
+                               global $wgSVGConverterPath;
+                               $cmd = str_replace(
+                                       array( '$path/', '$width', '$height', '$input', '$output' ),
+                                       array( $wgSVGConverterPath ? "$wgSVGConverterPath/" : "",
+                                                  intval( $width ),
+                                                  intval( $height ),
+                                                  wfEscapeShellArg( $this->imagePath ),
+                                                  wfEscapeShellArg( $thumbPath ) ),
+                                       $wgSVGConverters[$wgSVGConverter] );
+                               wfDebug( "reallyRenderThumb SVG: $cmd\n" );
+                               $conv = shell_exec( $cmd );
+                       } else {
+                               $conv = false;
+                       }
+               } elseif ( $wgUseImageMagick ) {
+                       # use ImageMagick
+                       # Specify white background color, will be used for transparent images
+                       # in Internet Explorer/Windows instead of default black.
+                       $cmd  =  $wgImageMagickConvertCommand .
+                               " -quality 85 -background white -geometry {$width} ".
+                               wfEscapeShellArg($this->imagePath) . " " .
+                               wfEscapeShellArg($thumbPath);                           
+                       wfDebug("reallyRenderThumb: running ImageMagick: $cmd\n");
+                       $conv = shell_exec( $cmd );
+               } else {
+                       # Use PHP's builtin GD library functions.
+                       #
+                       # First find out what kind of file this is, and select the correct
+                       # input routine for this.
+
+                       $typemap = array(
+                               'image/gif'          => array( 'imagecreatefromgif',  'palette',   'imagegif'  ),
+                               'image/jpeg'         => array( 'imagecreatefromjpeg', 'truecolor', array( &$this, 'imageJpegWrapper' ) ),
+                               'image/png'          => array( 'imagecreatefrompng',  'bits',      'imagepng'  ),
+                               'image/vnd.wap.wmbp' => array( 'imagecreatefromwbmp', 'palette',   'imagewbmp'  ),
+                               'image/xbm'          => array( 'imagecreatefromxbm',  'palette',   'imagexbm'  ),
+                       );
+                       if( !isset( $typemap[$this->mime] ) ) {
+                               $err = 'Image type not supported';
+                               wfDebug( "$err\n" );
+                               return $err;
+                       }
+                       list( $loader, $colorStyle, $saveType ) = $typemap[$this->mime];
+                       
+                       if( !function_exists( $loader ) ) {
+                               $err = "Incomplete GD library configuration: missing function $loader";
+                               wfDebug( "$err\n" );
+                               return $err;
+                       }
+                       if( $colorStyle == 'palette' ) {
+                               $truecolor = false;
+                       } elseif( $colorStyle == 'truecolor' ) {
+                               $truecolor = true;
+                       } elseif( $colorStyle == 'bits' ) {
+                               $truecolor = ( $this->bits > 8 );
+                       }
+                       
+                       $src_image = call_user_func( $loader, $this->imagePath );
+                       if ( $truecolor ) {
+                               $dst_image = imagecreatetruecolor( $width, $height );
+                       } else {
+                               $dst_image = imagecreate( $width, $height );
+                       }
+                       imagecopyresampled( $dst_image, $src_image, 
+                                               0,0,0,0,
+                                               $width, $height, $this->width, $this->height );
+                       call_user_func( $saveType, $dst_image, $thumbPath );
+                       imagedestroy( $dst_image );
+                       imagedestroy( $src_image );
+               }
+               
+               #
+               # Check for zero-sized thumbnails. Those can be generated when 
+               # no disk space is available or some other error occurs
+               #
+               if( file_exists( $thumbPath ) ) {
+                       $thumbstat = stat( $thumbPath );
+                       if( $thumbstat['size'] == 0 ) {
+                               unlink( $thumbPath );
+                       }
+               }
+       }
+
+       function imageJpegWrapper( $dst_image, $thumbPath ) {
+               imageinterlace( $dst_image );
+               imagejpeg( $dst_image, $thumbPath, 95 );
+       }
+               
+       /** 
+        * Get all thumbnail names previously generated for this image
+        */
+       function getThumbnails( $shared = false ) {
+               if ( Image::isHashed( $shared ) ) {
+                       $this->load();
+                       $files = array();
+                       $dir = wfImageThumbDir( $this->name, $shared );
+
+                       // This generates an error on failure, hence the @
+                       $handle = @opendir( $dir );
+                       
+                       if ( $handle ) {
+                               while ( false !== ( $file = readdir($handle) ) ) { 
+                                       if ( $file{0} != '.' ) {
+                                               $files[] = $file;
+                                       }
+                               }
+                               closedir( $handle );
+                       }
+               } else {
+                       $files = array();
+               }
+               
+               return $files;
+       }
+
+       /**
+        * Delete all previously generated thumbnails, refresh metadata in memcached and purge the squid
+        */
+       function purgeCache( $archiveFiles = array(), $shared = false ) {
+               global $wgInternalServer, $wgUseSquid;
+
+               // Refresh metadata cache
+               clearstatcache();
+               $this->loadFromFile();
+               $this->saveToCache();
+
+               // Delete thumbnails
+               $files = $this->getThumbnails( $shared );
+               $dir = wfImageThumbDir( $this->name, $shared );
+               $urls = array();
+               foreach ( $files as $file ) {
+                       if ( preg_match( '/^(\d+)px/', $file, $m ) ) {
+                               $urls[] = $wgInternalServer . $this->thumbUrl( $m[1], $this->fromSharedDirectory );
+                               @unlink( "$dir/$file" );
+                       }
+               }
+
+               // Purge the squid
+               if ( $wgUseSquid ) {
+                       $urls[] = $wgInternalServer . $this->getViewURL();
+                       foreach ( $archiveFiles as $file ) {
+                               $urls[] = $wgInternalServer . wfImageArchiveUrl( $file );
+                       }
+                       wfPurgeSquidServers( $urls );
+               }
+       }
+       
+       function checkDBSchema(&$db) {
+               # img_name must be unique
+               if ( !$db->indexUnique( 'image', 'img_name' ) && !$db->indexExists('image','PRIMARY') ) {
+                       wfDebugDieBacktrace( 'Database schema not up to date, please run maintenance/archives/patch-image_name_unique.sql' );
+               }
+               
+               #new fields must exist
+               if ( !$db->fieldExists( 'image', 'img_media_type' ) 
+                 || !$db->fieldExists( 'image', 'img_metadata' )
+                 || !$db->fieldExists( 'image', 'img_width' ) ) {
+                 
+                       wfDebugDieBacktrace( 'Database schema not up to date, please run maintenance/update.php' );
+               }
+       }
+
+       /**
+        * Return the image history of this image, line by line.
+        * starts with current version, then old versions.
+        * uses $this->historyLine to check which line to return:
+        *  0      return line for current version
+        *  1      query for old versions, return first one
+        *  2, ... return next old version from above query
+        *
+        * @access public
+        */
+       function nextHistoryLine() {
+               $fname = 'Image::nextHistoryLine()';
+               $dbr =& wfGetDB( DB_SLAVE );
+               
+               $this->checkDBSchema($dbr);
+               
+               if ( $this->historyLine == 0 ) {// called for the first time, return line from cur 
+                       $this->historyRes = $dbr->select( 'image', 
+                               array( 'img_size','img_description','img_user','img_user_text','img_timestamp', "'' AS oi_archive_name" ), 
+                               array( 'img_name' => $this->title->getDBkey() ),
+                               $fname
+                       );
+                       if ( 0 == wfNumRows( $this->historyRes ) ) { 
+                               return FALSE; 
+                       }
+               } else if ( $this->historyLine == 1 ) {
+                       $this->historyRes = $dbr->select( 'oldimage', 
+                               array( 'oi_size AS img_size', 'oi_description AS img_description', 'oi_user AS img_user',
+                                       'oi_user_text AS img_user_text', 'oi_timestamp AS img_timestamp', 'oi_archive_name'
+                               ), array( 'oi_name' => $this->title->getDBkey() ), $fname, array( 'ORDER BY' => 'oi_timestamp DESC' ) 
+                       );
+               }
+               $this->historyLine ++;
+
+               return $dbr->fetchObject( $this->historyRes );
+       }
+
+       /**
+        * Reset the history pointer to the first element of the history
+        * @access public
+        */
+       function resetHistory() {
+               $this->historyLine = 0;
+       }
+       
+       /**
+       * Return the full filesystem path to the file. Note that this does
+       * not mean that a file actually exists under that location.
+       *
+       * This path depends on whether directory hashing is active or not,
+       * i.e. whether the images are all found in the same directory,
+       * or in hashed paths like /images/3/3c.
+       *
+       * @access public
+       * @param boolean $fromSharedDirectory Return the path to the file
+       *   in a shared repository (see $wgUseSharedRepository and related
+       *   options in DefaultSettings.php) instead of a local one.
+       * 
+       */
+       function getFullPath( $fromSharedRepository = false ) {
+               global $wgUploadDirectory, $wgSharedUploadDirectory;
+               global $wgHashedUploadDirectory, $wgHashedSharedUploadDirectory;
+               
+               $dir      = $fromSharedRepository ? $wgSharedUploadDirectory :
+                                                   $wgUploadDirectory;
+               
+               // $wgSharedUploadDirectory may be false, if thumb.php is used
+               if ( $dir ) {
+                       $fullpath = $dir . wfGetHashPath($this->name, $fromSharedRepository) . $this->name;             
+               } else {
+                       $fullpath = false;
+               }
+
+               return $fullpath;
+       }
+
+       /**
+        * @return bool
+        * @static
+        */
+       function isHashed( $shared ) {
+               global $wgHashedUploadDirectory, $wgHashedSharedUploadDirectory;
+               return $shared ? $wgHashedSharedUploadDirectory : $wgHashedUploadDirectory;
+       }
+       
+       /**
+        * Record an image upload in the upload log and the image table
+        */
+       function recordUpload( $oldver, $desc, $copyStatus = '', $source = '', $watch = false ) {
+               global $wgUser, $wgLang, $wgTitle, $wgDeferredUpdateList;
+               global $wgUseCopyrightUpload, $wgUseSquid, $wgPostCommitUpdateList;
+
+               $fname = 'Image::recordUpload';
+               $dbw =& wfGetDB( DB_MASTER );
+
+               $this->checkDBSchema($dbw);
+
+               // Delete thumbnails and refresh the metadata cache
+               $this->purgeCache();
+
+               // Fail now if the image isn't there
+               if ( !$this->fileExists || $this->fromSharedDirectory ) {
+                       wfDebug( "Image::recordUpload: File ".$this->imagePath." went missing!\n" );
+                       return false;
+               }
+
+               if ( $wgUseCopyrightUpload ) {
+                       $textdesc = '== ' . wfMsg ( 'filedesc' ) . " ==\n" . $desc . "\n" .
+                         '== ' . wfMsg ( 'filestatus' ) . " ==\n" . $copyStatus . "\n" .
+                         '== ' . wfMsg ( 'filesource' ) . " ==\n" . $source ;
+               } else {
+                       $textdesc = $desc;
+               }
+
+               $now = $dbw->timestamp();
+
+               #split mime type
+               if (strpos($this->mime,'/')!==false) {
+                       list($major,$minor)= explode('/',$this->mime,2);
+               }
+               else {
+                       $major= $this->mime;
+                       $minor= "unknown";
+               }
+               
+               # Test to see if the row exists using INSERT IGNORE
+               # This avoids race conditions by locking the row until the commit, and also
+               # doesn't deadlock. SELECT FOR UPDATE causes a deadlock for every race condition.
+               $dbw->insert( 'image',
+                       array(
+                               'img_name' => $this->name,
+                               'img_size'=> $this->size,
+                               'img_width' => IntVal( $this->width ),
+                               'img_height' => IntVal( $this->height ),
+                               'img_bits' => $this->bits,
+                               'img_media_type' => $this->type,
+                               'img_major_mime' => $major,
+                               'img_minor_mime' => $minor,
+                               'img_timestamp' => $now,
+                               'img_description' => $desc,
+                               'img_user' => $wgUser->getID(),
+                               'img_user_text' => $wgUser->getName(),
+                               'img_metadata' => $this->metadata,
+                       ), $fname, 'IGNORE' 
+               );
+               $descTitle = $this->getTitle();
+               $purgeURLs = array();
+
+               if( $dbw->affectedRows() == 0 ) {
+                       # Collision, this is an update of an image
+                       # Insert previous contents into oldimage
+                       $dbw->insertSelect( 'oldimage', 'image', 
+                               array(
+                                       'oi_name' => 'img_name',
+                                       'oi_archive_name' => $dbw->addQuotes( $oldver ),
+                                       'oi_size' => 'img_size',
+                                       'oi_width' => 'img_width',
+                                       'oi_height' => 'img_height',
+                                       'oi_bits' => 'img_bits',
+                                       'oi_timestamp' => 'img_timestamp',
+                                       'oi_description' => 'img_description',
+                                       'oi_user' => 'img_user',
+                                       'oi_user_text' => 'img_user_text',
+                               ), array( 'img_name' => $this->name ), $fname
+                       );
+                       
+                       # Update the current image row
+                       $dbw->update( 'image',
+                               array( /* SET */
+                                       'img_size' => $this->size,
+                                       'img_width' => intval( $this->width ),
+                                       'img_height' => intval( $this->height ),
+                                       'img_bits' => $this->bits,
+                                       'img_media_type' => $this->type,
+                                       'img_major_mime' => $major,
+                                       'img_minor_mime' => $minor,
+                                       'img_timestamp' => $now,
+                                       'img_description' => $desc,
+                                       'img_user' => $wgUser->getID(),
+                                       'img_user_text' => $wgUser->getName(),
+                                       'img_metadata' => $this->metadata,
+                               ), array( /* WHERE */
+                                       'img_name' => $this->name
+                               ), $fname
+                       );
+               }
+
+               $article = new Article( $descTitle );
+               $minor = false;
+               $watch = $watch || $wgUser->isWatched( $descTitle );
+               $suppressRC = true; // There's already a log entry, so don't double the RC load
+               
+               if( $descTitle->exists() ) {
+                       // TODO: insert a null revision into the page history for this update.
+                       if( $watch ) {
+                               $wgUser->addWatch( $descTitle );
+                       }
+                       
+                       # Invalidate the cache for the description page
+                       $descTitle->invalidateCache();
+                       $purgeURLs[] = $descTitle->getInternalURL();
+               } else {
+                       // New image; create the description page.
+                       $article->insertNewArticle( $textdesc, $desc, $minor, $watch, $suppressRC );
+               }
+               
+               # Invalidate cache for all pages using this image
+               $linksTo = $this->getLinksTo();
+               
+               if ( $wgUseSquid ) {
+                       $u = SquidUpdate::newFromTitles( $linksTo, $purgeURLs );
+                       array_push( $wgPostCommitUpdateList, $u );
+               }
+               Title::touchArray( $linksTo );
+               
+               $log = new LogPage( 'upload' );
+               $log->addEntry( 'upload', $descTitle, $desc );
+
+               return true;
+       }
+
+       /**
+        * Get an array of Title objects which are articles which use this image
+        * Also adds their IDs to the link cache
+        * 
+        * This is mostly copied from Title::getLinksTo()
+        */
+       function getLinksTo( $options = '' ) {
+               global $wgLinkCache;
+               $fname = 'Image::getLinksTo';
+               wfProfileIn( $fname );
+               
+               if ( $options ) {
+                       $db =& wfGetDB( DB_MASTER );
+               } else {
+                       $db =& wfGetDB( DB_SLAVE );
+               }
+
+               extract( $db->tableNames( 'page', 'imagelinks' ) );
+               $encName = $db->addQuotes( $this->name );
+               $sql = "SELECT page_namespace,page_title,page_id FROM $page,$imagelinks WHERE page_id=il_from AND il_to=$encName $options";
+               $res = $db->query( $sql, $fname );
+               
+               $retVal = array();
+               if ( $db->numRows( $res ) ) {
+                       while ( $row = $db->fetchObject( $res ) ) {
+                               if ( $titleObj = Title::makeTitle( $row->page_namespace, $row->page_title ) ) {
+                                       $wgLinkCache->addGoodLinkObj( $row->page_id, $titleObj );
+                                       $retVal[] = $titleObj;
+                               }
+                       }
+               }
+               $db->freeResult( $res );
+               return $retVal;
+       }
+       /**
+        * Retrive Exif data from the database
+        *
+        * Retrive Exif data from the database and prune unrecognized tags
+        * and/or tags with invalid contents
+        *
+        * @return array
+        */
+       function retrieveExifData () {
+               if ( $this->getMimeType() !== "image/jpeg" ) return array ();
+
+               $exif = new Exif( $this->imagePath );
+               return $exif->getFilteredData();
+       }
+               
+       function getExifData () {
+               global $wgRequest;
+               if ( $this->metadata === '0' )
+                       return array();
+               
+               $purge = $wgRequest->getVal( 'action' ) == 'purge';
+               $ret = unserialize ( $this->metadata );
+
+               $oldver = isset( $ret['MEDIAWIKI_EXIF_VERSION'] ) ? $ret['MEDIAWIKI_EXIF_VERSION'] : 0;
+               $newver = Exif::version();
+               
+               if ( !count( $ret ) || $purge || $oldver != $newver ) {
+                       $this->updateExifData( $newver );
+               }
+               if ( isset( $ret['MEDIAWIKI_EXIF_VERSION'] ) )
+                       unset( $ret['MEDIAWIKI_EXIF_VERSION'] );
+               $format = new FormatExif( $ret );
+               return $format->getFormattedData();
+       }
+
+       function updateExifData( $version ) {
+               $fname = 'Image:updateExifData';
+               
+               if ( $this->getImagePath() === false ) # Not a local image
+                       return;
+               
+               # Get EXIF data from image
+               $exif = $this->retrieveExifData();
+               if ( count( $exif ) ) {
+                       $exif['MEDIAWIKI_EXIF_VERSION'] = $version;
+                       $this->metadata = serialize( $exif );
+               } else {
+                       $this->metadata = '0';
+               }
+               
+               # Update EXIF data in database
+               $dbw =& wfGetDB( DB_MASTER );
+               
+               $this->checkDBSchema($dbw);
+               
+               $dbw->update( 'image', 
+                       array( 'img_metadata' => $this->metadata ),
+                       array( 'img_name' => $this->name ),
+                       $fname
+               );
+       }
+
+} //class
+
+
+/**
+ * Returns the image directory of an image
+ * If the directory does not exist, it is created.
+ * The result is an absolute path.
+ *
+ * This function is called from thumb.php before Setup.php is included
+ * 
+ * @param string $fname                file name of the image file
+ * @access public
+ */
+function wfImageDir( $fname ) {
+       global $wgUploadDirectory, $wgHashedUploadDirectory;
+       
+       if (!$wgHashedUploadDirectory) { return $wgUploadDirectory; }
+
+       $hash = md5( $fname );
+       $oldumask = umask(0);
+       $dest = $wgUploadDirectory . '/' . $hash{0};
+       if ( ! is_dir( $dest ) ) { mkdir( $dest, 0777 ); }
+       $dest .= '/' . substr( $hash, 0, 2 );
+       if ( ! is_dir( $dest ) ) { mkdir( $dest, 0777 ); }
+
+       umask( $oldumask );
+       return $dest;
+}
+
+/**
+ * Returns the image directory of an image's thubnail
+ * If the directory does not exist, it is created.
+ * The result is an absolute path.
+ *
+ * This function is called from thumb.php before Setup.php is included
+ * 
+ * @param string $fname                file name of the original image file
+ * @param string $subdir       (optional) subdirectory of the image upload directory that should be used for storing the thumbnail. Default is 'thumb'
+ * @param boolean $shared      (optional) use the shared upload directory
+ * @access public
+ */
+function wfImageThumbDir( $fname, $shared = false ) {
+       $base = wfImageArchiveDir( $fname, 'thumb', $shared );
+       if ( Image::isHashed( $shared ) ) {
+               $dir =  "$base/$fname";
+
+               if ( !is_dir( $base ) ) {
+                       $oldumask = umask(0);
+                       @mkdir( $base, 0777 ); 
+                       umask( $oldumask );
+               }
+
+               if ( ! is_dir( $dir ) ) {
+                       if ( is_file( $dir ) ) {
+                               // Old thumbnail in the way of directory creation, kill it
+                               unlink( $dir );
+                       }
+                       $oldumask = umask(0);
+                       @mkdir( $dir, 0777 ); 
+                       umask( $oldumask );
+               }
+       } else {
+               $dir = $base;
+       }
+
+       return $dir;
+}
+
+/**
+ * Old thumbnail directory, kept for conversion
+ */
+function wfDeprecatedThumbDir( $thumbName , $subdir='thumb', $shared=false) {
+       return wfImageArchiveDir( $thumbName, $subdir, $shared );
+}
+
+/**
+ * Returns the image directory of an image's old version
+ * If the directory does not exist, it is created.
+ * The result is an absolute path.
+ *
+ * This function is called from thumb.php before Setup.php is included
+ * 
+ * @param string $fname                file name of the thumbnail file, including file size prefix
+ * @param string $subdir       (optional) subdirectory of the image upload directory that should be used for storing the old version. Default is 'archive'
+ * @param boolean $shared      (optional) use the shared upload directory (only relevant for other functions which call this one)
+ * @access public
+ */
+function wfImageArchiveDir( $fname , $subdir='archive', $shared=false ) {
+       global $wgUploadDirectory, $wgHashedUploadDirectory,
+              $wgSharedUploadDirectory, $wgHashedSharedUploadDirectory;
+       $dir = $shared ? $wgSharedUploadDirectory : $wgUploadDirectory;
+       $hashdir = $shared ? $wgHashedSharedUploadDirectory : $wgHashedUploadDirectory; 
+       if (!$hashdir) { return $dir.'/'.$subdir; }
+       $hash = md5( $fname );
+       $oldumask = umask(0);
+       
+       # Suppress warning messages here; if the file itself can't
+       # be written we'll worry about it then.
+       wfSuppressWarnings();
+       
+       $archive = $dir.'/'.$subdir;
+       if ( ! is_dir( $archive ) ) { mkdir( $archive, 0777 ); }
+       $archive .= '/' . $hash{0};
+       if ( ! is_dir( $archive ) ) { mkdir( $archive, 0777 ); }
+       $archive .= '/' . substr( $hash, 0, 2 );
+       if ( ! is_dir( $archive ) ) { mkdir( $archive, 0777 ); }
+
+       wfRestoreWarnings();
+       umask( $oldumask );
+       return $archive;
+}
+
+
+/*
+ * Return the hash path component of an image path (URL or filesystem),
+ * e.g. "/3/3c/", or just "/" if hashing is not used.
+ *
+ * @param $dbkey The filesystem / database name of the file
+ * @param $fromSharedDirectory Use the shared file repository? It may
+ *   use different hash settings from the local one.
+ */
+function wfGetHashPath ( $dbkey, $fromSharedDirectory = false ) {
+       global $wgHashedSharedUploadDirectory, $wgSharedUploadDirectory;
+       global $wgHashedUploadDirectory;
+       
+       if( Image::isHashed( $fromSharedDirectory ) ) {
+               $hash = md5($dbkey);
+               return '/' . $hash{0} . '/' . substr( $hash, 0, 2 ) . '/';
+       } else {
+               return '/';
+       }
+}
+
+/**
+ * Returns the image URL of an image's old version
+ * 
+ * @param string $fname                file name of the image file
+ * @param string $subdir       (optional) subdirectory of the image upload directory that is used by the old version. Default is 'archive'
+ * @access public
+ */
+function wfImageArchiveUrl( $name, $subdir='archive' ) {
+       global $wgUploadPath, $wgHashedUploadDirectory;
+
+       if ($wgHashedUploadDirectory) {
+               $hash = md5( substr( $name, 15) );
+               $url = $wgUploadPath.'/'.$subdir.'/' . $hash{0} . '/' .
+                 substr( $hash, 0, 2 ) . '/'.$name;
+       } else {
+               $url = $wgUploadPath.'/'.$subdir.'/'.$name;
+       }
+       return wfUrlencode($url);
+}
+
+/**
+ * Return a rounded pixel equivalent for a labeled CSS/SVG length.
+ * http://www.w3.org/TR/SVG11/coords.html#UnitIdentifiers
+ *
+ * @param string $length
+ * @return int Length in pixels
+ */
+function wfScaleSVGUnit( $length ) {
+       static $unitLength = array(
+               'px' => 1.0,
+               'pt' => 1.25,
+               'pc' => 15.0,
+               'mm' => 3.543307,
+               'cm' => 35.43307,
+               'in' => 90.0,
+               ''   => 1.0, // "User units" pixels by default
+               '%'  => 2.0, // Fake it!
+               );
+       if( preg_match( '/^(\d+)(em|ex|px|pt|pc|cm|mm|in|%|)$/', $length, $matches ) ) {
+               $length = FloatVal( $matches[1] );
+               $unit = $matches[2];
+               return round( $length * $unitLength[$unit] );
+       } else {
+               // Assume pixels
+               return round( FloatVal( $length ) );
+       }
+}
+
+/**
+ * Compatible with PHP getimagesize()
+ * @todo support gzipped SVGZ
+ * @todo check XML more carefully
+ * @todo sensible defaults
+ *
+ * @param string $filename
+ * @return array
+ */
+function wfGetSVGsize( $filename ) {
+       $width = 256;
+       $height = 256;
+       
+       // Read a chunk of the file
+       $f = fopen( $filename, "rt" );
+       if( !$f ) return false;
+       $chunk = fread( $f, 4096 );
+       fclose( $f );
+       
+       // Uber-crappy hack! Run through a real XML parser.
+       if( !preg_match( '/<svg\s*([^>]*)\s*>/s', $chunk, $matches ) ) {
+               return false;
+       }
+       $tag = $matches[1];
+       if( preg_match( '/\bwidth\s*=\s*("[^"]+"|\'[^\']+\')/s', $tag, $matches ) ) {
+               $width = wfScaleSVGUnit( trim( substr( $matches[1], 1, -1 ) ) );
+       }
+       if( preg_match( '/\bheight\s*=\s*("[^"]+"|\'[^\']+\')/s', $tag, $matches ) ) {
+               $height = wfScaleSVGUnit( trim( substr( $matches[1], 1, -1 ) ) );
+       }
+       
+       return array( $width, $height, 'SVG',
+               "width=\"$width\" height=\"$height\"" );
+}
+
+/**
+ * Determine if an image exists on the 'bad image list'
+ *
+ * @param string $name The image to check
+ * @return bool
+ */
+function wfIsBadImage( $name ) {
+       global $wgContLang;
+       static $titleList = false;
+       if ( $titleList === false ) {
+               $titleList = array();
+
+               $lines = explode("\n", wfMsgForContent( 'bad_image_list' ));
+               foreach ( $lines as $line ) {
+                       if ( preg_match( '/^\*\s*\[{2}:(' . $wgContLang->getNsText( NS_IMAGE ) . ':.*?)\]{2}/', $line, $m ) ) {
+                               $t = Title::newFromText( $m[1] );
+                               $titleList[$t->getDBkey()] = 1;
+                       }
+               }
+       }
+
+       return array_key_exists( $name, $titleList );
+}
+
+
+
+/**
+ * Wrapper class for thumbnail images
+ * @package MediaWiki
+ */
+class ThumbnailImage {
+       /**
+        * @param string $path Filesystem path to the thumb
+        * @param string $url URL path to the thumb
+        * @access private
+        */
+       function ThumbnailImage( $url, $width, $height, $path = false ) {
+               $this->url = $url;
+               $this->width = $width;
+               $this->height = $height;
+               $this->path = $path;
+       }
+
+       /**
+        * @return string The thumbnail URL
+        */     
+       function getUrl() {
+               return $this->url;
+       }
+       
+       /**
+        * Return HTML <img ... /> tag for the thumbnail, will include
+        * width and height attributes and a blank alt text (as required).
+        *
+        * You can set or override additional attributes by passing an
+        * associative array of name => data pairs. The data will be escaped
+        * for HTML output, so should be in plaintext.
+        *
+        * @param array $attribs
+        * @return string
+        * @access public
+        */
+       function toHtml( $attribs = array() ) {
+               $attribs['src'] = $this->url;
+               $attribs['width'] = $this->width;
+               $attribs['height'] = $this->height;
+               if( !isset( $attribs['alt'] ) ) $attribs['alt'] = '';
+
+               $html = '<img ';
+               foreach( $attribs as $name => $data ) {
+                       $html .= $name . '="' . htmlspecialchars( $data ) . '" ';
+               }
+               $html .= '/>';
+               return $html;
+       }
+
+}
+?>
diff --git a/includes/ImageGallery.php b/includes/ImageGallery.php
new file mode 100644 (file)
index 0000000..faea274
--- /dev/null
@@ -0,0 +1,160 @@
+<?php
+/**
+ * @package MediaWiki
+ */
+
+/**
+ * This is not a valid entry point, perform no further processing unless MEDIAWIKI is defined
+ */
+if( defined( 'MEDIAWIKI' ) ) {
+
+
+/**
+ * Image gallery
+ * 
+ * Add images to the gallery using add(), then render that list to HTML using toHTML().
+ *
+ * @package MediaWiki
+ */
+class ImageGallery
+{
+       var $mImages, $mShowBytes, $mShowFilename;
+
+       /** 
+        * Create a new image gallery object.
+        */
+       function ImageGallery( ) {
+               $this->mImages = array();
+               $this->mShowBytes = true;
+               $this->mShowFilename = true;
+       }
+
+       /**
+        * Add an image to the gallery.
+        *
+        * @param Image  $image  Image object that is added to the gallery
+        * @param string $html   Additional HTML text to be shown. The name and size of the image are always shown.
+        */
+       function add( $image, $html='' ) {
+               $this->mImages[] = array( &$image, $html );
+       }
+
+       /**
+       * Add an image at the beginning of the gallery.
+       *
+       * @param Image  $image  Image object that is added to the gallery
+       * @param string $html   Additional HTML text to be shown. The name and size of the image are always shown.
+       */
+       function insert( $image, $html='' ) {
+               array_unshift( $this->mImages, array( &$image, $html ) );
+       }
+
+
+       /**
+        * isEmpty() returns true if the gallery contains no images
+        */
+       function isEmpty() {
+               return empty( $this->mImages );
+       }
+
+       /**
+        * Enable/Disable showing of the file size of an image in the gallery.
+        * Enabled by default.
+        * 
+        * @param boolean $f    set to false to disable
+        */
+       function setShowBytes( $f ) {
+               $this->mShowBytes = ( $f == true);
+       }
+
+       /**
+        * Enable/Disable showing of the filename of an image in the gallery.
+        * Enabled by default.
+        * 
+        * @param boolean $f    set to false to disable
+        */
+       function setShowFilename( $f ) {
+               $this->mShowFilename = ( $f == true);
+       }
+
+       /**
+        * Return a HTML representation of the image gallery
+        * 
+        * For each image in the gallery, display
+        * - a thumbnail
+        * - the image name
+        * - the additional text provided when adding the image
+        * - the size of the image
+        *
+        */
+       function toHTML() {
+               global $wgLang, $wgContLang, $wgUser;
+
+               $sk = $wgUser->getSkin();
+
+               $s = '<table class="gallery" cellspacing="0" cellpadding="0">';
+               $i = 0;
+               foreach ( $this->mImages as $pair ) {
+                       $img =& $pair[0];
+                       $text = $pair[1];
+
+                       $name = $img->getName();
+                       $nt = $img->getTitle();
+
+                       // Not an image. Just print the name and skip.
+                       if ( $nt->getNamespace() != NS_IMAGE ) {
+                               $s .= '<td><div class="gallerybox" style="height: 152px;">' .
+                                       htmlspecialchars( $nt->getText() ) . '</div></td>' .  (($i%4==3) ? "</tr>\n" : '');
+                               $i++;
+
+                               continue;
+                       }
+
+                       //TODO
+                       //$ul = $sk->makeLink( $wgContLang->getNsText( Namespace::getUser() ) . ":{$ut}", $ut );
+
+                       if( $this->mShowBytes ) {
+                               if( $img->exists() ) {
+                                       $nb = wfMsg( 'nbytes', $wgLang->formatNum( $img->getSize() ) );
+                               } else {
+                                       $nb = wfMsg( 'filemissing' );
+                               }
+                               $nb = htmlspecialchars( $nb ) . "<br />\n";
+                       } else {
+                               $nb = '';
+                       }
+                               
+                       $textlink = $this->mShowFilename ?
+                               $sk->makeKnownLinkObj( $nt, htmlspecialchars( $wgLang->truncate( $nt->getText(), 20, '...' ) ) ) . "<br />\n" :
+                               '' ;
+
+                       $s .= ($i%4==0) ? '<tr>' : '';
+                       $thumb = $img->getThumbnail( 120, 120 );
+                       $vpad = floor( ( 150 - $thumb->height ) /2 ) - 2;
+                       $s .= '<td><div class="gallerybox">' . '<div class="thumb" style="padding: ' . $vpad . 'px 0;">';
+                       
+                       # ATTENTION: The newline after <div class="gallerytext"> is needed to accommodate htmltidy which
+                       # in version 4.8.6 generated crackpot html in its absence, see:
+                       # http://bugzilla.wikimedia.org/show_bug.cgi?id=1765
+                       $s .= $sk->makeKnownLinkObj( $nt, $thumb->toHtml() ) . '</div><div class="gallerytext">' . "\n" .
+                               $textlink . $text . $nb .
+                               '</div>';
+                       $s .= "</div></td>\n";
+                       $s .= ($i%4==3) ? '</tr>' : '';
+                       $i++;
+               }
+               if( $i %4 != 0 ) {
+                       $s .= "</tr>\n";
+               }
+               $s .= '</table>';
+
+               return $s;
+       }
+
+} //class
+
+
+
+
+} // defined( 'MEDIAWIKI' )
+?>
diff --git a/includes/ImagePage.php b/includes/ImagePage.php
new file mode 100644 (file)
index 0000000..b6524e1
--- /dev/null
@@ -0,0 +1,693 @@
+<?php
+/**
+ * @package MediaWiki
+ */
+
+/**
+ *
+ */
+if( !defined( 'MEDIAWIKI' ) )
+       die();
+
+require_once( 'Image.php' );
+
+/**
+ * Special handling for image description pages
+ * @package MediaWiki
+ */
+class ImagePage extends Article {
+
+       /* private */ var $img;  // Image object this page is shown for
+       var $mExtraDescription = false;
+
+       function render() {
+               global $wgOut;
+               $wgOut->setArticleBodyOnly(true);
+               $wgOut->addWikitext($this->getContent(true));
+       }
+
+       function view() {
+               global $wgUseExternalEditor, $wgOut, $wgShowEXIF;
+
+               $this->img = new Image( $this->mTitle );
+
+               if( $this->mTitle->getNamespace() == NS_IMAGE  ) {
+                       if ($wgShowEXIF && $this->img->exists()) {
+                               $exif = $this->img->getExifData();
+                               $showmeta = count($exif) ? true : false;
+                       } else {
+                               $exif = false;
+                               $showmeta = false;
+                       }
+
+                       if ($this->img->exists())
+                               $wgOut->addHTML($this->showTOC($showmeta));
+
+                       $this->openShowImage();
+                       if ($exif)
+                               $wgOut->addWikiText($this->makeMetadataTable($exif));
+
+                       # No need to display noarticletext, we use our own message, output in openShowImage()
+                       if( $this->getID() ) {
+                               Article::view();
+                       } else {
+                               # Just need to set the right headers
+                               $wgOut->setArticleFlag( true );
+                               $wgOut->setRobotpolicy( 'index,follow' );
+                               $wgOut->setPageTitle( $this->mTitle->getPrefixedText() );
+                               $wgOut->addMetaTags();
+                               $this->viewUpdates();
+                       }
+
+                       if ($this->mExtraDescription) {
+                               $fol = wfMsg('shareddescriptionfollows');
+                               if ($fol != '-')
+                                       $wgOut->addWikiText(wfMsg('shareddescriptionfollows'));
+                               $wgOut->addHTML($this->mExtraDescription);
+                       }
+
+                       $this->closeShowImage();
+                       $this->imageHistory();
+                       $this->imageLinks();
+               } else {
+                       Article::view();
+               }
+       }
+
+       /**
+        * Create the TOC
+        *
+        * @access private
+        *
+        * @param bool $metadata Whether or not to show the metadata link
+        * @return string
+        */
+       function showTOC( $metadata ) {
+               global $wgLang;
+               $r = '<ul id="filetoc">
+                       <li><a href="#file">' . $wgLang->getNsText( NS_IMAGE ) . '</a></li>' .
+                       ($metadata ? '<li><a href="#metadata">' . wfMsg( 'metadata' ) . '</a></li>' : '') . '
+                       <li><a href="#filehistory">' . wfMsg( 'imghistory' ) . '</a></li>
+                       <li><a href="#filelinks">' . wfMsg( 'imagelinks' ) . '</a></li>
+               </ul>';
+               return $r;
+       }
+
+       /**
+        * Make a table with metadata to be shown in the output page.
+        *
+        * @access private
+        *
+        * @param array $exif The array containing the EXIF data
+        * @return string
+        */
+       function makeMetadataTable( $exif ) {
+               $r = "{| class=metadata align=right width=250px\n";
+               $r .= '|+ id=metadata | '. htmlspecialchars( wfMsg( 'metadata' ) ) . "\n";
+               foreach( $exif as $k => $v ) {
+                       $tag = strtolower( $k );
+                       $r .= "! class=$tag |" . wfMsg( "exif-$tag" ) . "\n";
+                       $r .= "| class=$tag |" . htmlspecialchars( $v ) . "\n";
+                       $r .= "|-\n";
+               }
+               return substr($r, 0, -3) . '|}';
+       }
+
+       /**
+        * Overloading Article's getContent method.
+        * Omit noarticletext if sharedupload
+        *
+        * @param $noredir If true, do not follow redirects
+        */
+       function getContent( $noredir )
+       {
+               if ( $this->img && $this->img->fromSharedDirectory && 0 == $this->getID() ) {
+                       return '';
+               }
+               return Article::getContent( $noredir );
+       }
+
+       function openShowImage()
+       {
+               global $wgOut, $wgUser, $wgImageLimits, $wgRequest,
+                      $wgUseImageResize, $wgRepositoryBaseUrl,
+                      $wgUseExternalEditor, $wgServer, $wgFetchCommonsDescriptions;
+               $full_url  = $this->img->getURL();
+               $anchoropen = '';
+               $anchorclose = '';
+
+               if( $wgUser->getOption( 'imagesize' ) == '' ) {
+                       $sizeSel = User::getDefaultOption( 'imagesize' );
+               } else {
+                       $sizeSel = IntVal( $wgUser->getOption( 'imagesize' ) );
+               }
+               if( !isset( $wgImageLimits[$sizeSel] ) ) {
+                       $sizeSel = User::getDefaultOption( 'imagesize' );
+               }
+               $max = $wgImageLimits[$sizeSel];
+               $maxWidth = $max[0];
+               $maxHeight = $max[1];
+               $sk = $wgUser->getSkin();
+
+               if ( $this->img->exists() ) {
+                       # image
+                       $width = $this->img->getWidth();
+                       $height = $this->img->getHeight();
+                       $showLink = false;
+
+                       if ( $this->img->allowInlineDisplay() and $width and $height) {
+                               # image
+
+                               # "Download high res version" link below the image
+                               $msg = wfMsg('showbigimage', $width, $height, intval( $this->img->getSize()/1024 ) );
+                               if ( $width > $maxWidth ) {
+                                       $height = floor( $height * $maxWidth / $width );
+                                       $width  = $maxWidth;
+                               }
+                               if ( $height > $maxHeight ) {
+                                       $width = floor( $width * $maxHeight / $height );
+                                       $height = $maxHeight;
+                               }
+                               if ( $width != $this->img->getWidth() || $height != $this->img->getHeight() ) {
+                                       if( $wgUseImageResize ) {
+                                               $thumbnail = $this->img->getThumbnail( $width );
+                                               if ( $thumbnail == null ) {
+                                                       $url = $this->img->getViewURL();
+                                               } else {
+                                                       $url = $thumbnail->getURL();
+                                               }
+                                       } else {
+                                               # No resize ability? Show the full image, but scale
+                                               # it down in the browser so it fits on the page.
+                                               $url = $this->img->getViewURL();
+                                       }
+                                       $anchoropen  = "<a href=\"{$full_url}\">";
+                                       $anchorclose = "</a><br />";
+                                       if( $this->img->mustRender() ) {
+                                               $showLink = true;
+                                       } else {
+                                               $anchorclose .= "\n$anchoropen{$msg}</a>";
+                                       }
+                               } else {
+                                       $url = $this->img->getViewURL();
+                                       $showLink = true;
+                               }
+                               $wgOut->addHTML( '<div class="fullImageLink" id="file">' . $anchoropen .
+                                    "<img border=\"0\" src=\"{$url}\" width=\"{$width}\" height=\"{$height}\" alt=\"" .
+                                    htmlspecialchars( $wgRequest->getVal( 'image' ) ).'" />' . $anchorclose . '</div>' );
+                       } else {
+                               #if direct link is allowed but it's not a renderable image, show an icon.
+                               if ($this->img->isSafeFile()) {
+                                       $icon= $this->img->iconThumb();
+
+                                       $wgOut->addHTML( '<div class="fullImageLink" id="file"><a href="' . $full_url . '">' .
+                                       $icon->toHtml() .
+                                       '</a></div>' );
+                               }
+                               
+                               $showLink = true;
+                       }
+
+
+                       if ($showLink) {
+                               $filename = wfEscapeWikiText( $this->img->getName() );
+                               $info = wfMsg( 'fileinfo',
+                                       ceil($this->img->getSize()/1024.0),
+                                       $this->img->getMimeType() );
+       
+                               if (!$this->img->isSafeFile()) {
+                                       $warning = wfMsg( 'mediawarning' );
+                                       $wgOut->addWikiText( <<<END
+<div class="fullMedia">
+<span class="dangerousLink">[[Media:$filename|$filename]]</span>
+<span class="fileInfo"> ($info)</span>
+</div>
+
+<div class="mediaWarning">$warning</div>
+END
+                                               );
+                               } else {
+                                       $wgOut->addWikiText( <<<END
+<div class="fullMedia">
+[[Media:$filename|$filename]] <span class="fileInfo"> ($info)</span>
+</div>
+END
+                                               );
+                               }
+                       }
+
+                       if($this->img->fromSharedDirectory) {
+                               $this->printSharedImageText();
+                       }
+               } else {
+                       # Image does not exist
+                       $wgOut->addWikiText( wfMsg( 'noimage', $this->getUploadUrl() ) );
+               }
+       }
+
+       function printSharedImageText() {
+               global $wgRepositoryBaseUrl, $wgFetchCommonsDescriptions, $wgOut;
+
+               $url = $wgRepositoryBaseUrl . urlencode($this->mTitle->getDBkey());
+               $sharedtext = "<div class='sharedUploadNotice'>" . wfMsg("sharedupload");
+               if ($wgRepositoryBaseUrl && !$wgFetchCommonsDescriptions) {
+                       $sharedtext .= " " . wfMsg("shareduploadwiki", $url);
+               }
+               $sharedtext .= "</div>";
+               $wgOut->addWikiText($sharedtext);
+
+               if ($wgRepositoryBaseUrl && $wgFetchCommonsDescriptions) {
+                       require_once("HttpFunctions.php");
+                       $ur = ini_set('allow_url_fopen', true);
+                       $text = wfGetHTTP($url . '?action=render');
+                       ini_set('allow_url_fopen', $ur);
+                       if ($text)
+                               $this->mExtraDescription = $text;
+               }
+       }
+
+       function getUploadUrl() {
+               global $wgServer;
+               $uploadTitle = Title::makeTitle( NS_SPECIAL, 'Upload' );
+               return $wgServer . $uploadTitle->getLocalUrl( 'wpDestFile=' . urlencode( $this->img->getName() ) );
+       }
+
+
+       function uploadLinksBox()
+       {
+               global $wgUser, $wgOut;
+
+               if ($this->img->fromSharedDirectory)
+                       return;
+
+               $sk = $wgUser->getSkin();
+               $wgOut->addHTML( '<br /><ul><li>' );
+               $wgOut->addWikiText( '<div>'. wfMsg( 'uploadnewversion', $this->getUploadUrl() ) .'</div>' );
+               $wgOut->addHTML( '</li><li>' );
+               $wgOut->addHTML( $sk->makeKnownLinkObj( $this->mTitle,
+                       wfMsg( 'edit-externally' ), "action=edit&externaledit=true&mode=file" ) );
+               $wgOut->addWikiText( '<div>' .  wfMsg('edit-externally-help') . '</div>' );
+               $wgOut->addHTML( '</li></ul>' );
+       }
+
+       function closeShowImage()
+       {
+               # For overloading
+
+       }
+
+       /**
+        * If the page we've just displayed is in the "Image" namespace,
+        * we follow it with an upload history of the image and its usage.
+        */
+       function imageHistory()
+       {
+               global $wgUser, $wgOut, $wgUseExternalEditor;
+
+               $sk = $wgUser->getSkin();
+
+               $line = $this->img->nextHistoryLine();
+
+               if ( $line ) {
+                       $list =& new ImageHistoryList( $sk );
+                       $s = $list->beginImageHistoryList() .
+                               $list->imageHistoryLine( true, $line->img_timestamp,
+                                       $this->mTitle->getDBkey(),  $line->img_user,
+                                       $line->img_user_text, $line->img_size, $line->img_description );
+
+                       while ( $line = $this->img->nextHistoryLine() ) {
+                               $s .= $list->imageHistoryLine( false, $line->img_timestamp,
+                               $line->oi_archive_name, $line->img_user,
+                               $line->img_user_text, $line->img_size, $line->img_description );
+                       }
+                       $s .= $list->endImageHistoryList();
+               } else { $s=''; }
+               $wgOut->addHTML( $s );
+
+               # Exist check because we don't want to show this on pages where an image
+               # doesn't exist along with the noimage message, that would suck. -ævar
+               if( $wgUseExternalEditor && $this->img->exists() ) {
+                       $this->uploadLinksBox();
+               }
+
+       }
+
+       function imageLinks()
+       {
+               global $wgUser, $wgOut;
+
+               $wgOut->addHTML( '<h2 id="filelinks">' . wfMsg( 'imagelinks' ) . "</h2>\n" );
+
+               $dbr =& wfGetDB( DB_SLAVE );
+               $page = $dbr->tableName( 'page' );
+               $imagelinks = $dbr->tableName( 'imagelinks' );
+
+               $sql = "SELECT page_namespace,page_title FROM $imagelinks,$page WHERE il_to=" .
+                 $dbr->addQuotes( $this->mTitle->getDBkey() ) . " AND il_from=page_id"
+                 . " LIMIT 500"; # quickie emergency brake
+               $res = $dbr->query( $sql, "ImagePage::imageLinks" );
+
+               if ( 0 == $dbr->numRows( $res ) ) {
+                       $wgOut->addHtml( '<p>' . wfMsg( "nolinkstoimage" ) . "</p>\n" );
+                       return;
+               }
+               $wgOut->addHTML( '<p>' . wfMsg( 'linkstoimage' ) .  "</p>\n<ul>" );
+
+               $sk = $wgUser->getSkin();
+               while ( $s = $dbr->fetchObject( $res ) ) {
+                       $name = Title::MakeTitle( $s->page_namespace, $s->page_title );
+                       $link = $sk->makeKnownLinkObj( $name, "" );
+                       $wgOut->addHTML( "<li>{$link}</li>\n" );
+               }
+               $wgOut->addHTML( "</ul>\n" );
+       }
+
+       function delete()
+       {
+               global $wgUser, $wgOut, $wgRequest;
+
+               $confirm = $wgRequest->wasPosted();
+               $image = $wgRequest->getVal( 'image' );
+               $oldimage = $wgRequest->getVal( 'oldimage' );
+
+               # Only sysops can delete images. Previously ordinary users could delete
+               # old revisions, but this is no longer the case.
+               if ( !$wgUser->isAllowed('delete') ) {
+                       $wgOut->sysopRequired();
+                       return;
+               }
+               if ( $wgUser->isBlocked() ) {
+                       return $this->blockedIPpage();
+               }
+               if ( wfReadOnly() ) {
+                       $wgOut->readOnlyPage();
+                       return;
+               }
+
+               # Better double-check that it hasn't been deleted yet!
+               $wgOut->setPagetitle( wfMsg( 'confirmdelete' ) );
+               if ( ( !is_null( $image ) )
+                 && ( '' == trim( $image ) ) ) {
+                       $wgOut->fatalError( wfMsg( 'cannotdelete' ) );
+                       return;
+               }
+
+               $this->img  = new Image( $this->mTitle );
+
+               # Deleting old images doesn't require confirmation
+               if ( !is_null( $oldimage ) || $confirm ) {
+                       if( $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ), $oldimage ) ) {
+                               $this->doDelete();
+                       } else {
+                               $wgOut->fatalError( wfMsg( 'sessionfailure' ) );
+                       }
+                       return;
+               }
+
+               if ( !is_null( $image ) ) {
+                       $q = '&image=' . urlencode( $image );
+               } else if ( !is_null( $oldimage ) ) {
+                       $q = '&oldimage=' . urlencode( $oldimage );
+               } else {
+                       $q = '';
+               }
+               return $this->confirmDelete( $q, $wgRequest->getText( 'wpReason' ) );
+       }
+
+       function doDelete()
+       {
+               global $wgOut, $wgUser, $wgContLang, $wgRequest;
+               global $wgUseSquid, $wgInternalServer, $wgPostCommitUpdateList;
+               $fname = 'ImagePage::doDelete';
+
+               $reason = $wgRequest->getVal( 'wpReason' );
+               $oldimage = $wgRequest->getVal( 'oldimage' );
+
+               $dbw =& wfGetDB( DB_MASTER );
+
+               if ( !is_null( $oldimage ) ) {
+                       if ( strlen( $oldimage ) < 16 ) {
+                               $wgOut->unexpectedValueError( 'oldimage', htmlspecialchars($oldimage) );
+                               return;
+                       }
+                       if ( strstr( $oldimage, "/" ) || strstr( $oldimage, "\\" ) ) {
+                               $wgOut->unexpectedValueError( 'oldimage', htmlspecialchars($oldimage) );
+                               return;
+                       }
+
+                       # Invalidate description page cache
+                       $this->mTitle->invalidateCache();
+
+                       # Squid purging
+                       if ( $wgUseSquid ) {
+                               $urlArr = Array(
+                                       $wgInternalServer.wfImageArchiveUrl( $oldimage ),
+                                       $wgInternalServer.$this->mTitle->getFullURL()
+                               );
+                               wfPurgeSquidServers($urlArr);
+                       }
+                       $this->doDeleteOldImage( $oldimage );
+                       $dbw->delete( 'oldimage', array( 'oi_archive_name' => $oldimage ) );
+                       $deleted = $oldimage;
+               } else {
+                       $image = $this->mTitle->getDBkey();
+                       $dest = wfImageDir( $image );
+                       $archive = wfImageDir( $image );
+
+                       # Delete the image file if it exists; due to sync problems
+                       # or manual trimming sometimes the file will be missing.
+                       $targetFile = "{$dest}/{$image}";
+                       if( file_exists( $targetFile ) && ! @unlink( $targetFile ) ) {
+                               # If the deletion operation actually failed, bug out:
+                               $wgOut->fileDeleteError( $targetFile );
+                               return;
+                       }
+                       $dbw->delete( 'image', array( 'img_name' => $image ) );
+                       $res = $dbw->select( 'oldimage', array( 'oi_archive_name' ), array( 'oi_name' => $image ) );
+
+                       # Purge archive URLs from the squid
+                       $urlArr = Array();
+                       while ( $s = $dbw->fetchObject( $res ) ) {
+                               $this->doDeleteOldImage( $s->oi_archive_name );
+                               $urlArr[] = $wgInternalServer.wfImageArchiveUrl( $s->oi_archive_name );
+                       }
+
+                       # And also the HTML of all pages using this image
+                       $linksTo = $this->img->getLinksTo();
+                       if ( $wgUseSquid ) {
+                               $u = SquidUpdate::newFromTitles( $linksTo, $urlArr );
+                               array_push( $wgPostCommitUpdateList, $u );
+                       }
+
+                       $dbw->delete( 'oldimage', array( 'oi_name' => $image ) );
+
+                       # Image itself is now gone, and database is cleaned.
+                       # Now we remove the image description page.
+
+                       $article = new Article( $this->mTitle );
+                       $article->doDeleteArticle( $reason ); # ignore errors
+
+                       # Invalidate parser cache and client cache for pages using this image
+                       # This is left until relatively late to reduce lock time
+                       Title::touchArray( $linksTo );
+
+                       /* Delete thumbnails and refresh image metadata cache */
+                       $this->img->purgeCache();
+
+
+                       $deleted = $image;
+               }
+
+               $wgOut->setPagetitle( wfMsg( 'actioncomplete' ) );
+               $wgOut->setRobotpolicy( 'noindex,nofollow' );
+
+               $loglink = '[[Special:Log/delete|' . wfMsg( 'deletionlog' ) . ']]';
+               $text = wfMsg( 'deletedtext', $deleted, $loglink );
+
+               $wgOut->addWikiText( $text );
+
+               $wgOut->returnToMain( false, $this->mTitle->getPrefixedText() );
+       }
+
+       function doDeleteOldImage( $oldimage )
+       {
+               global $wgOut;
+
+               $name = substr( $oldimage, 15 );
+               $archive = wfImageArchiveDir( $name );
+
+               # Delete the image if it exists. Sometimes the file will be missing
+               # due to manual intervention or weird sync problems; treat that
+               # condition gracefully and continue to delete the database entry.
+               # Also some records may end up with an empty oi_archive_name field
+               # if the original file was missing when a new upload was made;
+               # don't try to delete the directory then!
+               #
+               $targetFile = "{$archive}/{$oldimage}";
+               if( $oldimage != '' && file_exists( $targetFile ) && !@unlink( $targetFile ) ) {
+                       # If we actually have a file and can't delete it, throw an error.
+                       $wgOut->fileDeleteError( "{$archive}/{$oldimage}" );
+               } else {
+                       # Log the deletion
+                       $log = new LogPage( 'delete' );
+                       $log->addEntry( 'delete', $this->mTitle, wfMsg('deletedrevision',$oldimage) );
+               }
+       }
+
+       function revert()
+       {
+               global $wgOut, $wgRequest, $wgUser;
+               global $wgUseSquid, $wgInternalServer, $wgDeferredUpdateList;
+
+               $oldimage = $wgRequest->getText( 'oldimage' );
+               if ( strlen( $oldimage ) < 16 ) {
+                       $wgOut->unexpectedValueError( 'oldimage', htmlspecialchars($oldimage) );
+                       return;
+               }
+               if ( strstr( $oldimage, "/" ) || strstr( $oldimage, "\\" ) ) {
+                       $wgOut->unexpectedValueError( 'oldimage', htmlspecialchars($oldimage) );
+                       return;
+               }
+
+               if ( wfReadOnly() ) {
+                       $wgOut->readOnlyPage();
+                       return;
+               }
+               if( $wgUser->isAnon() ) {
+                       $wgOut->errorpage( 'uploadnologin', 'uploadnologintext' );
+                       return;
+               }
+               if ( ! $this->mTitle->userCanEdit() ) {
+                       $wgOut->sysopRequired();
+                       return;
+               }
+               if ( $wgUser->isBlocked() ) {
+                       return $this->blockedIPpage();
+               }
+               if( !$wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ), $oldimage ) ) {
+                       $wgOut->errorpage( 'internalerror', 'sessionfailure' );
+                       return;
+               }
+               $name = substr( $oldimage, 15 );
+
+               $dest = wfImageDir( $name );
+               $archive = wfImageArchiveDir( $name );
+               $curfile = "{$dest}/{$name}";
+
+               if ( ! is_file( $curfile ) ) {
+                       $wgOut->fileNotFoundError( htmlspecialchars( $curfile ) );
+                       return;
+               }
+               $oldver = wfTimestampNow() . "!{$name}";
+
+               $dbr =& wfGetDB( DB_SLAVE );
+               $size = $dbr->selectField( 'oldimage', 'oi_size', array( 'oi_archive_name' => $oldimage )  );
+
+               if ( ! rename( $curfile, "${archive}/{$oldver}" ) ) {
+                       $wgOut->fileRenameError( $curfile, "${archive}/{$oldver}" );
+                       return;
+               }
+               if ( ! copy( "{$archive}/{$oldimage}", $curfile ) ) {
+                       $wgOut->fileCopyError( "${archive}/{$oldimage}", $curfile );
+               }
+
+               # Record upload and update metadata cache
+               $img = Image::newFromName( $name );
+               $img->recordUpload( $oldver, wfMsg( "reverted" ) );
+
+               $wgOut->setPagetitle( wfMsg( 'actioncomplete' ) );
+               $wgOut->setRobotpolicy( 'noindex,nofollow' );
+               $wgOut->addHTML( wfMsg( 'imagereverted' ) );
+
+               $descTitle = $img->getTitle();
+               $wgOut->returnToMain( false, $descTitle->getPrefixedText() );
+       }
+
+       function blockedIPpage() {
+               require_once( 'EditPage.php' );
+               $edit = new EditPage( $this );
+               return $edit->blockedIPpage();
+       }
+
+}
+
+/**
+ * @todo document
+ * @package MediaWiki
+ */
+class ImageHistoryList {
+       function ImageHistoryList( &$skin ) {
+               $this->skin =& $skin;
+       }
+
+       function beginImageHistoryList() {
+               $s = "\n<h2 id=\"filehistory\">" . wfMsg( 'imghistory' ) . "</h2>\n" .
+                 "<p>" . wfMsg( 'imghistlegend' ) . "</p>\n".'<ul class="special">';
+               return $s;
+       }
+
+       function endImageHistoryList() {
+               $s = "</ul>\n";
+               return $s;
+       }
+
+       function imageHistoryLine( $iscur, $timestamp, $img, $user, $usertext, $size, $description ) {
+               global $wgUser, $wgLang, $wgContLang, $wgTitle;
+
+               $datetime = $wgLang->timeanddate( $timestamp, true );
+               $del = wfMsg( 'deleteimg' );
+               $delall = wfMsg( 'deleteimgcompletely' );
+               $cur = wfMsg( 'cur' );
+
+               if ( $iscur ) {
+                       $url = Image::imageUrl( $img );
+                       $rlink = $cur;
+                       if ( $wgUser->isAllowed('delete') ) {
+                               $link = $wgTitle->escapeLocalURL( 'image=' . $wgTitle->getPartialURL() .
+                                 '&action=delete' );
+                               $style = $this->skin->getInternalLinkAttributes( $link, $delall );
+
+                               $dlink = '<a href="'.$link.'"'.$style.'>'.$delall.'</a>';
+                       } else {
+                               $dlink = $del;
+                       }
+               } else {
+                       $url = htmlspecialchars( wfImageArchiveUrl( $img ) );
+                       if( $wgUser->getID() != 0 && $wgTitle->userCanEdit() ) {
+                               $token = urlencode( $wgUser->editToken( $img ) );
+                               $rlink = $this->skin->makeKnownLinkObj( $wgTitle,
+                                          wfMsg( 'revertimg' ), 'action=revert&oldimage=' .
+                                          urlencode( $img ) . "&wpEditToken=$token" );
+                               $dlink = $this->skin->makeKnownLinkObj( $wgTitle,
+                                          $del, 'action=delete&oldimage=' . urlencode( $img ) .
+                                          "&wpEditToken=$token" );
+                       } else {
+                               # Having live active links for non-logged in users
+                               # means that bots and spiders crawling our site can
+                               # inadvertently change content. Baaaad idea.
+                               $rlink = wfMsg( 'revertimg' );
+                               $dlink = $del;
+                       }
+               }
+               if ( 0 == $user ) {
+                       $userlink = $usertext;
+               } else {
+                       $userlink = $this->skin->makeLinkObj(
+                               Title::makeTitle( NS_USER, $usertext ),
+                               $usertext );
+               }
+               $nbytes = wfMsg( 'nbytes', $size );
+               $style = $this->skin->getInternalLinkAttributes( $url, $datetime );
+
+               $s = "<li> ({$dlink}) ({$rlink}) <a href=\"{$url}\"{$style}>{$datetime}</a>"
+                 . " . . {$userlink} ({$nbytes})";
+
+               $s .= $this->skin->commentBlock( $description, $wgTitle );
+               $s .= "</li>\n";
+               return $s;
+       }
+
+}
+
+
+?>
diff --git a/includes/LinkCache.php b/includes/LinkCache.php
new file mode 100644 (file)
index 0000000..dae7533
--- /dev/null
@@ -0,0 +1,457 @@
+<?php
+/**
+ * Cache for article titles (prefixed DB keys) and ids linked from one source
+ * @package MediaWiki
+ * @subpackage Cache
+ */
+
+/**
+ *
+ */
+# These are used in incrementalSetup()
+define ('LINKCACHE_GOOD', 0);
+define ('LINKCACHE_BAD', 1);
+define ('LINKCACHE_IMAGE', 2);
+define ('LINKCACHE_PAGE', 3);
+
+/**
+ * @package MediaWiki
+ * @subpackage Cache
+ */
+class LinkCache {      
+       // Increment $mClassVer whenever old serialized versions of this class
+       // becomes incompatible with the new version.
+       /* private */ var $mClassVer = 3;
+
+       /* private */ var $mPageLinks;
+       /* private */ var $mGoodLinks, $mBadLinks, $mActive;
+       /* private */ var $mImageLinks, $mCategoryLinks;
+       /* private */ var $mPreFilled, $mOldGoodLinks, $mOldBadLinks;
+       /* private */ var $mForUpdate;
+
+       /* private */ function getKey( $title ) {
+               global $wgDBname;
+               return $wgDBname.':lc:title:'.$title;
+       }
+       
+       function LinkCache() {
+               $this->mActive = true;
+               $this->mPreFilled = false;
+               $this->mForUpdate = false;
+               $this->mPageLinks = array();
+               $this->mGoodLinks = array();
+               $this->mBadLinks = array();
+               $this->mImageLinks = array();
+               $this->mCategoryLinks = array();
+               $this->mOldGoodLinks = array();
+               $this->mOldBadLinks = array();
+               $this->mOldPageLinks = array();
+       }
+
+       /**
+        * General accessor to get/set whether SELECT FOR UPDATE should be used
+        */
+       function forUpdate( $update = NULL ) { 
+               return wfSetVar( $this->mForUpdate, $update );
+       }
+       
+       function getGoodLinkID( $title ) {
+               if ( array_key_exists( $title, $this->mGoodLinks ) ) {
+                       return $this->mGoodLinks[$title];
+               } else {
+                       return 0;
+               }
+       }
+
+       function isBadLink( $title ) {
+               return array_key_exists( $title, $this->mBadLinks ); 
+       }
+
+       function addGoodLinkObj( $id, $title ) {
+               if ( $this->mActive ) {
+                       $dbkey = $title->getPrefixedDbKey();
+                       $this->mGoodLinks[$dbkey] = $id;
+                       $this->mPageLinks[$dbkey] = $title;
+               }
+       }
+
+       function addBadLinkObj( $title ) {
+               $dbkey = $title->getPrefixedDbKey();
+               if ( $this->mActive && ( ! $this->isBadLink( $dbkey ) ) ) {
+                       $this->mBadLinks[$dbkey] = 1;
+                       $this->mPageLinks[$dbkey] = $title;
+               }
+       }
+
+       function addImageLink( $title ) {
+               if ( $this->mActive ) { $this->mImageLinks[$title] = 1; }
+       }
+
+       function addImageLinkObj( $nt ) {
+               if ( $this->mActive ) { $this->mImageLinks[$nt->getDBkey()] = 1; }
+       }
+       
+       function addCategoryLink( $title, $sortkey ) {
+               if ( $this->mActive ) { $this->mCategoryLinks[$title] = $sortkey; }
+       }
+       
+       function addCategoryLinkObj( &$nt, $sortkey ) {
+               $this->addCategoryLink( $nt->getDBkey(), $sortkey );
+       }
+
+       function clearBadLink( $title ) {
+               unset( $this->mBadLinks[$title] );
+               $this->clearLink( $title );
+       }
+       
+       function clearLink( $title ) {
+               global $wgMemc, $wgLinkCacheMemcached;
+               if( $wgLinkCacheMemcached )
+                       $wgMemc->delete( $this->getKey( $title ) );
+       }
+
+       function suspend() { $this->mActive = false; }
+       function resume() { $this->mActive = true; }
+       function getPageLinks() { return $this->mPageLinks; }
+       function getGoodLinks() { return $this->mGoodLinks; }
+       function getBadLinks() { return array_keys( $this->mBadLinks ); }
+       function getImageLinks() { return $this->mImageLinks; }
+       function getCategoryLinks() { return $this->mCategoryLinks; }
+
+       function addLink( $title ) {
+               $nt = Title::newFromDBkey( $title );
+               if( $nt ) {
+                       return $this->addLinkObj( $nt );
+               } else {
+                       return 0;
+               }
+       }
+       
+       function addLinkObj( &$nt ) {
+               global $wgMemc, $wgLinkCacheMemcached, $wgAntiLockFlags;
+               $title = $nt->getPrefixedDBkey();
+               if ( $this->isBadLink( $title ) ) { return 0; }         
+               $id = $this->getGoodLinkID( $title );
+               if ( 0 != $id ) { return $id; }
+
+               $fname = 'LinkCache::addLinkObj';
+               wfProfileIn( $fname );
+
+               $ns = $nt->getNamespace();
+               $t = $nt->getDBkey();
+
+               if ( '' == $title ) { 
+                       wfProfileOut( $fname );
+                       return 0; 
+               }
+               
+               $id = NULL;
+               if( $wgLinkCacheMemcached )
+                       $id = $wgMemc->get( $key = $this->getKey( $title ) );
+               if( ! is_integer( $id ) ) {
+                       if ( $this->mForUpdate ) {
+                               $db =& wfGetDB( DB_MASTER );
+                               if ( !( $wgAntiLockFlags & ALF_NO_LINK_LOCK ) ) {
+                                       $options = array( 'FOR UPDATE' );
+                               }
+                       } else {
+                               $db =& wfGetDB( DB_SLAVE );
+                               $options = array();
+                       }
+
+                       $id = $db->selectField( 'page', 'page_id', array( 'page_namespace' => $ns, 'page_title' => $t ), $fname, $options );
+                       if ( !$id ) {
+                               $id = 0;
+                       }
+                       if( $wgLinkCacheMemcached )
+                               $wgMemc->add( $key, $id, 3600*24 );
+               }
+               
+               if( 0 == $id ) {
+                       $this->addBadLinkObj( $nt );
+               } else {
+                       $this->addGoodLinkObj( $id, $nt );
+               }
+               wfProfileOut( $fname );
+               return $id;
+       }
+
+       /**
+        * Bulk-check the pagelinks and page arrays for existence info.
+        * @param Title $fromtitle
+        */
+       function preFill( &$fromtitle ) {
+               global $wgAntiLockFlags;
+               $fname = 'LinkCache::preFill';
+               wfProfileIn( $fname );
+
+               $this->suspend();
+               $id = $fromtitle->getArticleID();
+               $this->resume();
+               
+               if( $id == 0 ) {
+                       wfDebug( "$fname - got id 0 for title '" . $fromtitle->getPrefixedDBkey() . "'\n" );
+                       wfProfileOut( $fname );
+                       return;
+               }
+               
+               if ( $this->mForUpdate ) {
+                       $db =& wfGetDB( DB_MASTER );
+                       if ( !( $wgAntiLockFlags & ALF_NO_LINK_LOCK ) ) {
+                               $options = 'FOR UPDATE';
+                       } else {
+                               $options = '';
+                       }
+               } else {
+                       $db =& wfGetDB( DB_SLAVE );
+                       $options = '';
+               }
+
+               $page = $db->tableName( 'page' );
+               $pagelinks = $db->tableName( 'pagelinks' );
+
+               $sql = "SELECT page_id,pl_namespace,pl_title
+                       FROM $pagelinks
+                       LEFT JOIN $page
+                       ON pl_namespace=page_namespace AND pl_title=page_title
+                       WHERE pl_from=$id $options";
+               $res = $db->query( $sql, $fname );
+               while( $s = $db->fetchObject( $res ) ) {
+                       $title = Title::makeTitle( $s->pl_namespace, $s->pl_title );
+                       if( $s->page_id ) {
+                               $this->addGoodLinkObj( $s->page_id, $title );
+                       } else {
+                               $this->addBadLinkObj( $title );
+                       }
+               }
+               $this->mPreFilled = true;
+
+               wfProfileOut( $fname );
+       }
+
+       function getGoodAdditions() {
+               return array_diff( $this->mGoodLinks, $this->mOldGoodLinks );
+       }
+
+       function getBadAdditions() {
+               #wfDebug( "mOldBadLinks: " . implode( ', ', array_keys( $this->mOldBadLinks ) ) . "\n" );
+               #wfDebug( "mBadLinks: " . implode( ', ', array_keys( $this->mBadLinks ) ) . "\n" );
+               return array_values( array_diff( array_keys( $this->mBadLinks ), array_keys( $this->mOldBadLinks ) ) );
+       }
+
+       function getImageAdditions() {
+               return array_diff_assoc( $this->mImageLinks, $this->mOldImageLinks );
+       }
+
+       function getGoodDeletions() {
+               return array_diff( $this->mOldGoodLinks, $this->mGoodLinks );
+       }
+
+       function getBadDeletions() {
+               return array_values( array_diff( array_keys( $this->mOldBadLinks ), array_keys( $this->mBadLinks ) ));
+       }
+
+       function getImageDeletions() {
+               return array_diff_assoc( $this->mOldImageLinks, $this->mImageLinks );
+       }
+       
+       function getPageAdditions() {
+               $set = array_diff( array_keys( $this->mPageLinks ), array_keys( $this->mOldPageLinks ) );
+               $out = array();
+               foreach( $set as $key ) {
+                       $out[$key] = $this->mPageLinks[$key];
+               }
+               return $out;
+       }
+       
+       function getPageDeletions() {
+               $set = array_diff( array_keys( $this->mOldPageLinks ), array_keys( $this->mPageLinks ) );
+               $out = array();
+               foreach( $set as $key ) {
+                       $out[$key] = $this->mOldPageLinks[$key];
+               }
+               return $out;
+       }
+
+       /**
+        * Parameters:
+        * @param $which is one of the LINKCACHE_xxx constants
+        * @param $del,$add are the incremental update arrays which will be filled.
+        *
+        * @return Returns whether or not it's worth doing the incremental version.
+        *
+        * For example, if [[List of mathematical topics]] was blanked,
+        * it would take a long, long time to do incrementally.
+        */
+       function incrementalSetup( $which, &$del, &$add ) {
+               if ( ! $this->mPreFilled ) {
+                       return false;
+               }
+
+               switch ( $which ) {
+                       case LINKCACHE_GOOD:
+                               $old =& $this->mOldGoodLinks;
+                               $cur =& $this->mGoodLinks;
+                               $del = $this->getGoodDeletions();
+                               $add = $this->getGoodAdditions();
+                               break;
+                       case LINKCACHE_BAD:
+                               $old =& $this->mOldBadLinks;
+                               $cur =& $this->mBadLinks;
+                               $del = $this->getBadDeletions();
+                               $add = $this->getBadAdditions();
+                               break;
+                       case LINKCACHE_PAGE:
+                               $old =& $this->mOldPageLinks;
+                               $cur =& $this->mPageLinks;
+                               $del = $this->getPageDeletions();
+                               $add = $this->getPageAdditions();
+                               break;
+                       default: # LINKCACHE_IMAGE
+                               return false;           
+               }
+               
+               return true;
+       }
+
+       /**
+        * Clears cache 
+        */
+       function clear() {
+               $this->mPageLinks = array();
+               $this->mGoodLinks = array();
+               $this->mBadLinks = array();
+               $this->mImageLinks = array();
+               $this->mCategoryLinks = array();
+               $this->mOldGoodLinks = array();
+               $this->mOldBadLinks = array();
+               $this->mOldPageLinks = array();
+       }
+
+       /**
+        * Swaps old and current link registers
+        */
+       function swapRegisters() {
+               swap( $this->mGoodLinks, $this->mOldGoodLinks );
+               swap( $this->mBadLinks, $this->mOldBadLinks );
+               swap( $this->mImageLinks, $this->mOldImageLinks );
+               swap( $this->mPageLinks, $this->mOldPageLinks );
+       }
+}
+
+/**
+ * Class representing a list of titles
+ * The execute() method checks them all for existence and adds them to a LinkCache object
+ +
+ * @package MediaWiki
+ * @subpackage Cache
+ */
+class LinkBatch {
+       /** 
+        * 2-d array, first index namespace, second index dbkey, value arbitrary
+        */
+       var $data = array();
+
+       function LinkBatch( $arr = array() ) {
+               foreach( $arr as $item ) {
+                       $this->addObj( $item );
+               }
+       }
+       
+       function addObj( $title ) {
+               $this->add( $title->getNamespace(), $title->getDBkey() );
+       }
+
+       function add( $ns, $dbkey ) {
+               if ( $ns < 0 ) {
+                       return;
+               }
+               if ( !array_key_exists( $ns, $this->data ) ) {
+                       $this->data[$ns] = array();
+               }
+
+               $this->data[$ns][$dbkey] = 1;
+       }
+
+       function execute( &$cache ) {
+               $fname = 'LinkBatch::execute';
+               $namespaces = array();
+
+               if ( !count( $this->data ) ) {
+                       return;
+               }
+
+               wfProfileIn( $fname );
+
+               // Construct query
+               // This is very similar to Parser::replaceLinkHolders
+               $dbr = wfGetDB( DB_SLAVE );
+               $page = $dbr->tableName( 'page' );
+               $sql = "SELECT page_id, page_namespace, page_title FROM $page WHERE "
+                       . $this->constructSet( 'page', $dbr );
+               
+               // Do query
+               $res = $dbr->query( $sql, $fname );
+
+               // Process results
+               // For each returned entry, add it to the list of good links, and remove it from $remaining
+
+               $remaining = $this->data;
+               while ( $row = $dbr->fetchObject( $res ) ) {
+                       $title = Title::makeTitle( $row->page_namespace, $row->page_title );
+                       $cache->addGoodLinkObj( $row->page_id, $title );
+                       unset( $remaining[$row->page_namespace][$row->page_title] );
+               }
+               $dbr->freeResult( $res );
+
+               // The remaining links in $data are bad links, register them as such
+               foreach ( $remaining as $ns => $dbkeys ) {
+                       foreach ( $dbkeys as $dbkey => $nothing ) {
+                               $title = Title::makeTitle( $ns, $dbkey );
+                               $cache->addBadLinkObj( $title );
+                       }
+               }
+
+               wfProfileOut( $fname );
+       }
+       
+       /**
+        * Construct a WHERE clause which will match all the given titles.
+        * Give the appropriate table's field name prefix ('page', 'pl', etc).
+        *
+        * @param string $prefix
+        * @return string
+        * @access public
+        */
+       function constructSet( $prefix, $db ) {
+               $first = true;
+               $sql = '';
+               foreach ( $this->data as $ns => $dbkeys ) {
+                       if ( !count( $dbkeys ) ) {
+                               continue;
+                       }
+
+                       if ( $first ) {
+                               $first = false;
+                       } else {
+                               $sql .= ' OR ';
+                       }
+                       $sql .= "({$prefix}_namespace=$ns AND {$prefix}_title IN (";
+
+                       $firstTitle = true;
+                       foreach( $dbkeys as $dbkey => $nothing ) {
+                               if ( $firstTitle ) {
+                                       $firstTitle = false;
+                               } else {
+                                       $sql .= ',';
+                               }
+                               $sql .= $db->addQuotes( $dbkey );
+                       }
+
+                       $sql .= '))';
+               }
+               return $sql;
+       }
+}
+
+?>
diff --git a/includes/Linker.php b/includes/Linker.php
new file mode 100644 (file)
index 0000000..0a5df0e
--- /dev/null
@@ -0,0 +1,847 @@
+<?php
+/**
+ * Split off some of the internal bits from Skin.php.
+ * These functions are used for primarily page content:
+ * links, embedded images, table of contents. Links are
+ * also used in the skin.
+ * @package MediaWiki
+ */
+
+/**
+ * For the moment, Skin is a descendent class of Linker.
+ * In the future, it should probably be further split
+ * so that ever other bit of the wiki doesn't have to
+ * go loading up Skin to get at it.
+ *
+ * @package MediaWiki
+ */
+class Linker {
+
+       function Linker() {}
+
+       /**
+        * @deprecated
+        */
+       function postParseLinkColour( $s = NULL ) {
+               return NULL;
+       }
+
+       /** @todo document */
+       function getExternalLinkAttributes( $link, $text, $class='' ) {
+               global $wgContLang;
+
+               $same = ($link == $text);
+               $link = urldecode( $link );
+               $link = $wgContLang->checkTitleEncoding( $link );
+               $link = preg_replace( '/[\\x00-\\x1f_]/', ' ', $link );
+               $link = htmlspecialchars( $link );
+
+               $r = ($class != '') ? " class='$class'" : " class='external'";
+
+               $r .= " title=\"{$link}\"";
+               return $r;
+       }
+
+       /** @todo document */
+       function getInternalLinkAttributes( $link, $text, $broken = false ) {
+               $link = urldecode( $link );
+               $link = str_replace( '_', ' ', $link );
+               $link = htmlspecialchars( $link );
+
+               if( $broken == 'stub' ) {
+                       $r = ' class="stub"';
+               } else if ( $broken == 'yes' ) {
+                       $r = ' class="new"';
+               } else {
+                       $r = '';
+               }
+
+               $r .= " title=\"{$link}\"";
+               return $r;
+       }
+
+       /**
+        * @param bool $broken
+        */
+       function getInternalLinkAttributesObj( &$nt, $text, $broken = false ) {
+               if( $broken == 'stub' ) {
+                       $r = ' class="stub"';
+               } else if ( $broken == 'yes' ) {
+                       $r = ' class="new"';
+               } else {
+                       $r = '';
+               }
+
+               $r .= ' title="' . $nt->getEscapedText() . '"';
+               return $r;
+       }
+
+       /**
+        * Note: This function MUST call getArticleID() on the link,
+        * otherwise the cache won't get updated properly.  See LINKCACHE.DOC.
+        */
+       function makeLink( $title, $text = '', $query = '', $trail = '' ) {
+               wfProfileIn( 'Linker::makeLink' );
+               $nt = Title::newFromText( $title );
+               if ($nt) {
+                       $result = $this->makeLinkObj( Title::newFromText( $title ), $text, $query, $trail );
+               } else {
+                       wfDebug( 'Invalid title passed to Linker::makeLink(): "'.$title."\"\n" );
+                       $result = $text == "" ? $title : $text;
+               }
+
+               wfProfileOut( 'Linker::makeLink' );
+               return $result;
+       }
+
+       /** @todo document */
+       function makeKnownLink( $title, $text = '', $query = '', $trail = '', $prefix = '',$aprops = '') {
+               $nt = Title::newFromText( $title );
+               if ($nt) {
+                       return $this->makeKnownLinkObj( Title::newFromText( $title ), $text, $query, $trail, $prefix , $aprops );
+               } else {
+                       wfDebug( 'Invalid title passed to Linker::makeKnownLink(): "'.$title."\"\n" );
+                       return $text == '' ? $title : $text;
+               }
+       }
+
+       /** @todo document */
+       function makeBrokenLink( $title, $text = '', $query = '', $trail = '' ) {
+               $nt = Title::newFromText( $title );
+               if ($nt) {
+                       return $this->makeBrokenLinkObj( Title::newFromText( $title ), $text, $query, $trail );
+               } else {
+                       wfDebug( 'Invalid title passed to Linker::makeBrokenLink(): "'.$title."\"\n" );
+                       return $text == '' ? $title : $text;
+               }
+       }
+
+       /** @todo document */
+       function makeStubLink( $title, $text = '', $query = '', $trail = '' ) {
+               $nt = Title::newFromText( $title );
+               if ($nt) {
+                       return $this->makeStubLinkObj( Title::newFromText( $title ), $text, $query, $trail );
+               } else {
+                       wfDebug( 'Invalid title passed to Linker::makeStubLink(): "'.$title."\"\n" );
+                       return $text == '' ? $title : $text;
+               }
+       }
+
+       /**
+        * Pass a title object, not a title string
+        */
+       function makeLinkObj( $nt, $text= '', $query = '', $trail = '', $prefix = '' ) {
+               global $wgUser;
+               $fname = 'Linker::makeLinkObj';
+               wfProfileIn( $fname );
+
+               # Fail gracefully
+               if ( ! is_object($nt) ) {
+                       # wfDebugDieBacktrace();
+                       wfProfileOut( $fname );
+                       return "<!-- ERROR -->{$prefix}{$text}{$trail}";
+               }
+
+               $ns = $nt->getNamespace();
+               $dbkey = $nt->getDBkey();
+               if ( $nt->isExternal() ) {
+                       $u = $nt->getFullURL();
+                       $link = $nt->getPrefixedURL();
+                       if ( '' == $text ) { $text = $nt->getPrefixedText(); }
+                       $style = $this->getExternalLinkAttributes( $link, $text, 'extiw' );
+
+                       $inside = '';
+                       if ( '' != $trail ) {
+                               if ( preg_match( '/^([a-z]+)(.*)$$/sD', $trail, $m ) ) {
+                                       $inside = $m[1];
+                                       $trail = $m[2];
+                               }
+                       }
+
+                       # Check for anchors, normalize the anchor
+
+                       $parts = explode( '#', $u, 2 );
+                       if ( count( $parts ) == 2 ) {
+                               $anchor = urlencode( Sanitizer::decodeCharReferences( str_replace(' ', '_', $parts[1] ) ) );
+                               $replacearray = array(
+                                       '%3A' => ':',
+                                       '%' => '.'
+                               );
+                               $u = $parts[0] . '#' .
+                                    str_replace( array_keys( $replacearray ),
+                                                array_values( $replacearray ),
+                                                $anchor );
+                       }
+
+                       $t = "<a href=\"{$u}\"{$style}>{$text}{$inside}</a>";
+                               
+                       wfProfileOut( $fname );
+                       return $t;
+               } elseif ( $nt->isAlwaysKnown() ) {
+                       # Image links, special page links and self-links with fragements are always known.
+                       $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
+               } else {
+                       wfProfileIn( $fname.'-immediate' );
+                       # Work out link colour immediately
+                       $aid = $nt->getArticleID() ;
+                       if ( 0 == $aid ) {
+                               $retVal = $this->makeBrokenLinkObj( $nt, $text, $query, $trail, $prefix );
+                       } else {
+                               $threshold = $wgUser->getOption('stubthreshold') ;
+                               if ( $threshold > 0 ) {
+                                       $dbr =& wfGetDB( DB_SLAVE );
+                                       $s = $dbr->selectRow(
+                                               array( 'page' ),
+                                               array( 'page_len',
+                                                       'page_namespace',
+                                                       'page_is_redirect' ),
+                                               array( 'page_id' => $aid ), $fname ) ;
+                                       if ( $s !== false ) {
+                                               $size = $s->page_len;
+                                               if ( $s->page_is_redirect OR $s->page_namespace != NS_MAIN ) {
+                                                       $size = $threshold*2 ; # Really big
+                                               }
+                                       } else {
+                                               $size = $threshold*2 ; # Really big
+                                       }
+                               } else {
+                                       $size = 1 ;
+                               }
+                               if ( $size < $threshold ) {
+                                       $retVal = $this->makeStubLinkObj( $nt, $text, $query, $trail, $prefix );
+                               } else {
+                                       $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
+                               }
+                       }
+                       wfProfileOut( $fname.'-immediate' );
+               }
+               wfProfileOut( $fname );
+               return $retVal;
+       }
+
+       /**
+        * Pass a title object, not a title string
+        */
+       function makeKnownLinkObj( $nt, $text = '', $query = '', $trail = '', $prefix = '' , $aprops = '' ) {
+               global $wgTitle;
+
+               $fname = 'Linker::makeKnownLinkObj';
+               wfProfileIn( $fname );
+
+               if ( !is_object( $nt ) ) {
+                       wfProfileOut( $fname );
+                       return $text;
+               }
+               
+               $u = $nt->escapeLocalURL( $query );
+               if ( '' != $nt->getFragment() ) {
+                       if( $nt->getPrefixedDbkey() == '' ) {
+                               $u = '';
+                               if ( '' == $text ) {
+                                       $text = htmlspecialchars( $nt->getFragment() );
+                               }
+                       }
+                       $anchor = urlencode( Sanitizer::decodeCharReferences( str_replace( ' ', '_', $nt->getFragment() ) ) );
+                       $replacearray = array(
+                               '%3A' => ':',
+                               '%' => '.'
+                       );
+                       $u .= '#' . str_replace(array_keys($replacearray),array_values($replacearray),$anchor);
+               }
+               if ( '' == $text ) {
+                       $text = htmlspecialchars( $nt->getPrefixedText() );
+               }
+               $style = $this->getInternalLinkAttributesObj( $nt, $text );
+               
+               list( $inside, $trail ) = Linker::splitTrail( $trail );
+               $r = "<a href=\"{$u}\"{$style}{$aprops}>{$prefix}{$text}{$inside}</a>{$trail}";
+               wfProfileOut( $fname );
+               return $r;
+       }
+
+       /**
+        * Pass a title object, not a title string
+        */
+       function makeBrokenLinkObj( $nt, $text = '', $query = '', $trail = '', $prefix = '' ) {
+               # Fail gracefully
+               if ( ! isset($nt) ) {
+                       # wfDebugDieBacktrace();
+                       return "<!-- ERROR -->{$prefix}{$text}{$trail}";
+               }
+
+               $fname = 'Linker::makeBrokenLinkObj';
+               wfProfileIn( $fname );
+
+               if ( '' == $query ) {
+                       $q = 'action=edit';
+               } else {
+                       $q = 'action=edit&'.$query;
+               }
+               $u = $nt->escapeLocalURL( $q );
+
+               if ( '' == $text ) {
+                       $text = htmlspecialchars( $nt->getPrefixedText() );
+               }
+               $style = $this->getInternalLinkAttributesObj( $nt, $text, "yes" );
+               
+               list( $inside, $trail ) = Linker::splitTrail( $trail );
+               $s = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
+
+               wfProfileOut( $fname );
+               return $s;
+       }
+
+       /**
+        * Pass a title object, not a title string
+        */
+       function makeStubLinkObj( $nt, $text = '', $query = '', $trail = '', $prefix = '' ) {
+               $link = $nt->getPrefixedURL();
+
+               $u = $nt->escapeLocalURL( $query );
+
+               if ( '' == $text ) {
+                       $text = htmlspecialchars( $nt->getPrefixedText() );
+               }
+               $style = $this->getInternalLinkAttributesObj( $nt, $text, 'stub' );
+
+               list( $inside, $trail ) = Linker::splitTrail( $trail );
+               $s = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
+               return $s;
+       }
+
+       /**
+        * Generate either a normal exists-style link or a stub link, depending
+        * on the given page size.
+        *
+        * @param int $size
+        * @param Title $nt
+        * @param string $text
+        * @param string $query
+        * @param string $trail
+        * @param string $prefix
+        * @return string HTML of link
+        */
+       function makeSizeLinkObj( $size, $nt, $text = '', $query = '', $trail = '', $prefix = '' ) {
+               global $wgUser;
+               $threshold = IntVal( $wgUser->getOption( 'stubthreshold' ) );
+               if( $size < $threshold ) {
+                       return $this->makeStubLinkObj( $nt, $text, $query, $trail, $prefix );
+               } else {
+                       return $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
+               }
+       }
+
+       /** @todo document */
+       function makeSelfLinkObj( $nt, $text = '', $query = '', $trail = '', $prefix = '' ) {
+               $u = $nt->escapeLocalURL( $query );
+               if ( '' == $text ) {
+                       $text = htmlspecialchars( $nt->getPrefixedText() );
+               }
+               list( $inside, $trail ) = Linker::splitTrail( $trail );
+               return "<strong>{$prefix}{$text}{$inside}</strong>{$trail}";
+       }
+
+       /** @todo document */
+       function fnamePart( $url ) {
+               $basename = strrchr( $url, '/' );
+               if ( false === $basename ) {
+                       $basename = $url;
+               } else {
+                       $basename = substr( $basename, 1 );
+               }
+               return htmlspecialchars( $basename );
+       }
+
+       /** Obsolete alias */
+       function makeImage( $url, $alt = '' ) {
+               return $this->makeExternalImage( $url, $alt );
+       }
+
+       /** @todo document */
+       function makeExternalImage( $url, $alt = '' ) {
+               if ( '' == $alt ) {
+                       $alt = $this->fnamePart( $url );
+               }
+               $s = '<img src="'.$url.'" alt="'.$alt.'" />';
+               return $s;
+       }
+
+       /** @todo document */
+       function makeImageLinkObj( $nt, $label, $alt, $align = '', $width = false, $height = false, $framed = false, 
+         $thumb = false, $manual_thumb = '' ) 
+       {
+               global $wgContLang, $wgUser, $wgThumbLimits;
+               
+               $img   = new Image( $nt );
+               if ( !$img->allowInlineDisplay() ) {
+                       return $this->makeKnownLinkObj( $nt );
+               }
+
+               $url   = $img->getViewURL();
+               $prefix = $postfix = '';
+               
+               wfDebug( "makeImageLinkObj: '$width'x'$height'\n" );
+               
+               if ( 'center' == $align )
+               {
+                       $prefix  = '<div class="center">';
+                       $postfix = '</div>';
+                       $align   = 'none';
+               }
+
+               if ( $thumb || $framed ) {
+
+                       # Create a thumbnail. Alignment depends on language
+                       # writing direction, # right aligned for left-to-right-
+                       # languages ("Western languages"), left-aligned
+                       # for right-to-left-languages ("Semitic languages")
+                       #
+                       # If  thumbnail width has not been provided, it is set
+                       # to the default user option as specified in Language*.php
+                       if ( $align == '' ) {
+                               $align = $wgContLang->isRTL() ? 'left' : 'right';
+                       }
+
+                       
+                       if ( $width === false ) {
+                               $wopt = $wgUser->getOption( 'thumbsize' );
+
+                               if( !isset( $wgThumbLimits[$wopt] ) ) {
+                                        $wopt = User::getDefaultOption( 'thumbsize' );
+                               }
+                               
+                               $width = min( $img->getWidth(), $wgThumbLimits[$wopt] );
+                       }
+                       
+                       return $prefix.$this->makeThumbLinkObj( $img, $label, $alt, $align, $width, $height, $framed, $manual_thumb ).$postfix;
+
+               } elseif ( $width ) {
+
+                       # Create a resized image, without the additional thumbnail
+                       # features
+
+                       if ( $height !== false && ( $img->getHeight() * $width / $img->getWidth() > $height ) ) {
+                               $width = $img->getWidth() * $height / $img->getHeight();
+                       }
+                       if ( $manual_thumb == '') {
+                               $thumb = $img->getThumbnail( $width );
+                               if ( $thumb ) {
+                                       if( $width > $thumb->width ) {
+                                               // Requested a display size larger than the actual image;
+                                               // fake it up!
+                                               $height = floor($thumb->height * $width / $thumb->width);
+                                               wfDebug( "makeImageLinkObj: client-size height set to '$height'\n" );
+                                       } else {
+                                               $height = $thumb->height;
+                                               wfDebug( "makeImageLinkObj: thumb height set to '$height'\n" );
+                                       }
+                                       $url = $thumb->getUrl();
+                               }
+                       }
+               } else {
+                       $width = $img->width;
+                       $height = $img->height;
+               }
+
+               wfDebug( "makeImageLinkObj2: '$width'x'$height'\n" );
+               $u = $nt->escapeLocalURL();
+               if ( $url == '' ) {
+                       $s = $this->makeBrokenImageLinkObj( $img->getTitle() );
+                       //$s .= "<br />{$alt}<br />{$url}<br />\n";
+               } else {
+                       $s = '<a href="'.$u.'" class="image" title="'.$alt.'">' .
+                                '<img src="'.$url.'" alt="'.$alt.'" ' .
+                                ( $width
+                                       ? ( 'width="'.$width.'" height="'.$height.'" ' )
+                                       : '' ) .
+                                'longdesc="'.$u.'" /></a>';
+               }
+               if ( '' != $align ) {
+                       $s = "<div class=\"float{$align}\"><span>{$s}</span></div>";
+               }
+               return str_replace("\n", ' ',$prefix.$s.$postfix);
+       }
+
+       /**
+        * Make HTML for a thumbnail including image, border and caption
+        * $img is an Image object
+        */
+       function makeThumbLinkObj( $img, $label = '', $alt, $align = 'right', $boxwidth = 180, $boxheight=false, $framed=false , $manual_thumb = "" ) {
+               global $wgStylePath, $wgContLang;
+               $url  = $img->getViewURL();
+
+               $width = $height = 0;
+               if ( $img->exists() )
+               {
+                       $width  = $img->getWidth();
+                       $height = $img->getHeight();
+               }
+               if ( 0 == $width || 0 == $height )
+               {
+                       $width = $height = 200;
+               }
+               if ( $boxwidth == 0 )
+               {
+                       $boxwidth = 200;
+               }
+               if ( $framed )
+               {
+                       // Use image dimensions, don't scale
+                       $boxwidth  = $width;
+                       $oboxwidth = $boxwidth + 2;
+                       $boxheight = $height;
+                       $thumbUrl  = $url;
+               } else {
+                       $h  = round( $height/($width/$boxwidth) );
+                       $oboxwidth = $boxwidth + 2;
+                       if ( ( ! $boxheight === false ) &&  ( $h > $boxheight ) )
+                       {
+                               $boxwidth *= $boxheight/$h;
+                       } else {
+                               $boxheight = $h;
+                       }
+                       if ( '' == $manual_thumb ) $thumbUrl = $img->createThumb( $boxwidth );
+               }
+
+               if ( $manual_thumb != '' ) # Use manually specified thumbnail
+               {
+                       $manual_title = Title::makeTitleSafe( NS_IMAGE, $manual_thumb ); #new Title ( $manual_thumb ) ;
+                       $manual_img = new Image( $manual_title );
+                       $thumbUrl = $manual_img->getViewURL();
+                       if ( $manual_img->exists() )
+                       {
+                               $width  = $manual_img->getWidth();
+                               $height = $manual_img->getHeight();
+                               $boxwidth = $width ;
+                               $boxheight = $height ;
+                               $oboxwidth = $boxwidth + 2 ;
+                       }
+               }
+
+               $u = $img->getEscapeLocalURL();
+
+               $more = htmlspecialchars( wfMsg( 'thumbnail-more' ) );
+               $magnifyalign = $wgContLang->isRTL() ? 'left' : 'right';
+               $textalign = $wgContLang->isRTL() ? ' style="text-align:right"' : '';
+
+               $s = "<div class=\"thumb t{$align}\"><div style=\"width:{$oboxwidth}px;\">";
+               if ( $thumbUrl == '' ) {
+                       $s .= $this->makeBrokenImageLinkObj( $img->getTitle() );
+                       $zoomicon = '';
+               } else {
+                       $s .= '<a href="'.$u.'" class="internal" title="'.$alt.'">'.
+                               '<img src="'.$thumbUrl.'" alt="'.$alt.'" ' .
+                               'width="'.$boxwidth.'" height="'.$boxheight.'" ' .
+                               'longdesc="'.$u.'" /></a>';
+                       if ( $framed ) {
+                               $zoomicon="";
+                       } else {
+                               $zoomicon =  '<div class="magnify" style="float:'.$magnifyalign.'">'.
+                                       '<a href="'.$u.'" class="internal" title="'.$more.'">'.
+                                       '<img src="'.$wgStylePath.'/common/images/magnify-clip.png" ' .
+                                       'width="15" height="11" alt="'.$more.'" /></a></div>';
+                       }
+               }
+               $s .= '  <div class="thumbcaption" '.$textalign.'>'.$zoomicon.$label."</div></div></div>";
+               return str_replace("\n", ' ', $s);
+       }
+       
+       /**
+        * Pass a title object, not a title string
+        */
+       function makeBrokenImageLinkObj( $nt, $text = '', $query = '', $trail = '', $prefix = '' ) {
+               # Fail gracefully
+               if ( ! isset($nt) ) {
+                       # wfDebugDieBacktrace();
+                       return "<!-- ERROR -->{$prefix}{$text}{$trail}";
+               }
+
+               $fname = 'Linker::makeBrokenImageLinkObj';
+               wfProfileIn( $fname );
+
+               $q = 'wpDestFile=' . urlencode( $nt->getDBkey() );
+               if ( '' != $query ) {
+                       $q .= "&$query";
+               }
+               $uploadTitle = Title::makeTitle( NS_SPECIAL, 'Upload' );
+               $url = $uploadTitle->escapeLocalURL( $q );
+
+               if ( '' == $text ) {
+                       $text = htmlspecialchars( $nt->getPrefixedText() );
+               }
+               $style = $this->getInternalLinkAttributesObj( $nt, $text, "yes" );
+               list( $inside, $trail ) = Linker::splitTrail( $trail );
+               $s = "<a href=\"{$url}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
+
+               wfProfileOut( $fname );
+               return $s;
+       }
+       
+       /** @todo document */
+       function makeMediaLink( $name, $url, $alt = '' ) {
+               $nt = Title::makeTitleSafe( NS_IMAGE, $name );
+               return $this->makeMediaLinkObj( $nt, $alt );
+       }
+
+       /**
+        * Create a direct link to a given uploaded file.
+        *
+        * @param Title  $title
+        * @param string $text   pre-sanitized HTML
+        * @param bool   $nourl  Mask absolute URLs, so the parser doesn't
+        *                       linkify them (it is currently not context-aware)
+        * @return string HTML
+        *
+        * @access public
+        * @todo Handle invalid or missing images better.
+        */
+       function makeMediaLinkObj( $title, $text = '' ) {
+               if( is_null( $title ) ) {
+                       ### HOTFIX. Instead of breaking, return empty string.
+                       return $text;
+               } else {
+                       $name = $title->getDBKey();     
+                       $img  = new Image( $title );
+                       if( $img->exists() ) {
+                               $url  = $img->getURL();
+                               $class = 'internal';
+                       } else {
+                               $upload = Title::makeTitle( NS_SPECIAL, 'Upload' );
+                               $url = $upload->getLocalUrl( 'wpDestFile=' . urlencode( $img->getName() ) );
+                               $class = 'new';
+                       }
+                       $alt = htmlspecialchars( $title->getText() );
+                       if( $text == '' ) {
+                               $text = $alt;
+                       }
+                       $u = htmlspecialchars( $url );
+                       return "<a href=\"{$u}\" class='$class' title=\"{$alt}\">{$text}</a>";                  
+               }
+       }
+
+       /** @todo document */
+       function specialLink( $name, $key = '' ) {
+               global $wgContLang;
+
+               if ( '' == $key ) { $key = strtolower( $name ); }
+               $pn = $wgContLang->ucfirst( $name );
+               return $this->makeKnownLink( $wgContLang->specialPage( $pn ),
+                 wfMsg( $key ) );
+       }
+
+       /** @todo document */
+       function makeExternalLink( $url, $text, $escape = true, $linktype = '' ) {
+               $style = $this->getExternalLinkAttributes( $url, $text, 'external ' . $linktype );
+               global $wgNoFollowLinks;
+               if( $wgNoFollowLinks ) {
+                       $style .= ' rel="nofollow"';
+               }
+               $url = htmlspecialchars( $url );
+               if( $escape ) {
+                       $text = htmlspecialchars( $text );
+               }
+               return '<a href="'.$url.'"'.$style.'>'.$text.'</a>';
+       }
+
+       /**
+        * This function is called by all recent changes variants, by the page history,
+        * and by the user contributions list. It is responsible for formatting edit
+        * comments. It escapes any HTML in the comment, but adds some CSS to format
+        * auto-generated comments (from section editing) and formats [[wikilinks]].
+        *
+        * The &$title parameter must be a title OBJECT. It is used to generate a
+        * direct link to the section in the autocomment.
+        * @author Erik Moeller <moeller@scireview.de>
+        *
+        * Note: there's not always a title to pass to this function.
+        * Since you can't set a default parameter for a reference, I've turned it
+        * temporarily to a value pass. Should be adjusted further. --brion
+        */
+       function formatComment($comment, $title = NULL) {
+               $fname = 'Linker::formatComment';
+               wfProfileIn( $fname );
+               
+               global $wgContLang;
+               $comment = str_replace( "\n", " ", $comment );
+               $comment = htmlspecialchars( $comment );
+
+               # The pattern for autogen comments is / * foo * /, which makes for
+               # some nasty regex.
+               # We look for all comments, match any text before and after the comment,
+               # add a separator where needed and format the comment itself with CSS
+               while (preg_match('/(.*)\/\*\s*(.*?)\s*\*\/(.*)/', $comment,$match)) {
+                       $pre=$match[1];
+                       $auto=$match[2];
+                       $post=$match[3];
+                       $link='';
+                       if($title) {
+                               $section=$auto;
+
+                               # This is hackish but should work in most cases.
+                               $section=str_replace('[[','',$section);
+                               $section=str_replace(']]','',$section);
+                               $title->mFragment=$section;
+                               $link=$this->makeKnownLinkObj($title,wfMsg('sectionlink'));
+                       }
+                       $sep='-';
+                       $auto=$link.$auto;
+                       if($pre) { $auto = $sep.' '.$auto; }
+                       if($post) { $auto .= ' '.$sep; }
+                       $auto='<span class="autocomment">'.$auto.'</span>';
+                       $comment=$pre.$auto.$post;
+               }
+
+               # format regular and media links - all other wiki formatting
+               # is ignored
+               $medians = $wgContLang->getNsText( NS_MEDIA ) . ':';
+               while(preg_match('/\[\[(.*?)(\|(.*?))*\]\](.*)$/',$comment,$match)) {
+                       # Handle link renaming [[foo|text]] will show link as "text"
+                       if( "" != $match[3] ) {
+                               $text = $match[3];
+                       } else {
+                               $text = $match[1];
+                       }
+                       if( preg_match( '/^' . $medians . '(.*)$/i', $match[1], $submatch ) ) {
+                               # Media link; trail not supported.
+                               $linkRegexp = '/\[\[(.*?)\]\]/';
+                               $thelink = $this->makeMediaLink( $submatch[1], "", $text );
+                       } else {
+                               # Other kind of link
+                               if( preg_match( wfMsgForContent( "linktrail" ), $match[4], $submatch ) ) {
+                                       $trail = $submatch[1];
+                               } else {
+                                       $trail = "";
+                               }
+                               $linkRegexp = '/\[\[(.*?)\]\]' . preg_quote( $trail, '/' ) . '/';
+                               if ($match[1][0] == ':')
+                                       $match[1] = substr($match[1], 1);
+                               $thelink = $this->makeLink( $match[1], $text, "", $trail );
+                       }
+                       # Quote backreferences, then run preg_replace
+                       $thelink = strtr( $thelink, array( "\\" => "\\\\", '$' => "\\$" ) );
+                       $comment = preg_replace( $linkRegexp, $thelink, $comment, 1 );
+               }
+               wfProfileOut( $fname );
+               return $comment;
+       }
+       
+       /**
+        * Wrap a comment in standard punctuation and formatting if
+        * it's non-empty, otherwise return empty string.
+        *
+        * @param string $comment
+        * @param Title $title
+        * @return string
+        * @access public
+        */
+       function commentBlock( $comment, $title = NULL ) {
+               if( $comment == '' || $comment == '*' ) {
+                       return '';
+               } else {
+                       $formatted = $this->formatComment( $comment, $title );
+                       return " <span class='comment'>($formatted)</span>";
+               }
+       }
+
+       /** @todo document */
+       function tocIndent() {
+               return "\n<ul>";
+       }
+
+       /** @todo document */
+       function tocUnindent($level) {
+               return "</li>\n" . str_repeat( "</ul>\n</li>\n", $level>0 ? $level : 0 );
+       }
+
+       /**
+        * parameter level defines if we are on an indentation level
+        */
+       function tocLine( $anchor, $tocline, $tocnumber, $level ) {
+               return "\n<li class='toclevel-$level'><a href=\"#" .
+                       $anchor . '"><span class="tocnumber">' .
+                       $tocnumber . '</span> <span class="toctext">' .
+                       $tocline . '</span></a>';
+       }
+
+       /** @todo document */
+       function tocLineEnd() {
+               return "</li>\n";
+       }
+
+       /** @todo document */
+       function tocList($toc) {
+               global $wgJsMimeType;
+               return "<table id='toc' class='toc'><tr><td>" 
+                          . "<div id='toctitle'><h2>" . wfMsgForContent('toc') . "</h2></div>\n"
+                    . $toc
+                                . "</ul>\n</td></tr></table>\n"
+                                . '<script type="'.$wgJsMimeType.'">'
+                                . ' if (window.showTocToggle) {'
+                                . ' var tocShowText = "' . wfEscapeJsString( wfMsgForContent('showtoc') ) . '";'
+                                . ' var tocHideText = "' . wfEscapeJsString( wfMsgForContent('hidetoc') ) . '";'
+                                . ' showTocToggle();'
+                                . ' } '
+                                . "</script>\n";
+       }
+
+       /** @todo document */
+       function editSectionLinkForOther( $title, $section ) {
+               global $wgRequest;
+               global $wgContLang;
+
+               $title = Title::newFromText($title);
+               $editurl = '&section='.$section;
+               $url = $this->makeKnownLink($title->getPrefixedText(),wfMsg('editsection'),'action=edit'.$editurl);
+
+               if( $wgContLang->isRTL() ) {
+                       $farside = 'left';
+                       $nearside = 'right';
+               } else {
+                       $farside = 'right';
+                       $nearside = 'left';
+               }
+               return "<div class=\"editsection\" style=\"float:$farside;margin-$nearside:5px;\">[".$url."]</div>";
+
+       }
+
+       /** @todo document */
+       function editSectionLink( $nt, $section ) {
+               global $wgContLang;
+
+               $editurl = '&section='.$section;
+               $url = $this->makeKnownLink($nt->getPrefixedText(),wfMsg('editsection'),'action=edit'.$editurl);
+
+               if( $wgContLang->isRTL() ) {
+                       $farside = 'left';
+                       $nearside = 'right';
+               } else {
+                       $farside = 'right';
+                       $nearside = 'left';
+               }
+               return "<div class=\"editsection\" style=\"float:$farside;margin-$nearside:5px;\">[".$url."]</div>";
+       }
+
+       /** 
+        * Split a link trail, return the "inside" portion and the remainder of the trail
+        * as a two-element array
+        * 
+        * @static
+        */
+       function splitTrail( $trail ) {
+               static $regex = false;
+               if ( $regex === false ) {
+                       global $wgContLang;
+                       $regex = $wgContLang->linkTrail();
+               }
+               $inside = '';
+               if ( '' != $trail ) {
+                       if ( preg_match( $regex, $trail, $m ) ) {
+                               $inside = $m[1];
+                               $trail = $m[2];
+                       }
+               }
+               return array( $inside, $trail );
+       }
+
+}
+?>
diff --git a/includes/LinksUpdate.php b/includes/LinksUpdate.php
new file mode 100644 (file)
index 0000000..30b1b50
--- /dev/null
@@ -0,0 +1,255 @@
+<?php
+/**
+ * See deferred.txt
+ * @package MediaWiki
+ */
+
+/**
+ * @todo document
+ * @package MediaWiki
+ */
+class LinksUpdate {
+
+       /**#@+
+        * @access private
+        */
+       var $mId, $mTitle;
+       /**#@-*/
+
+       /**
+        * Constructor
+        * Initialize private variables
+        * @param integer $id
+        * @param string $title
+        */
+       function LinksUpdate( $id, $title ) {
+               $this->mId = $id;
+               $this->mTitle = $title;
+       }
+
+       /**
+        * Update link tables with outgoing links from an updated article
+        * Relies on the 'link cache' to be filled out.
+        */
+       
+       function doUpdate() {
+               global $wgUseDumbLinkUpdate, $wgLinkCache, $wgDBtransactions;
+               global $wgUseCategoryMagic;
+
+               if ( $wgUseDumbLinkUpdate ) {
+                       $this->doDumbUpdate();
+                       return;
+               }
+
+               $fname = 'LinksUpdate::doUpdate';
+               wfProfileIn( $fname );
+
+               $del = array();
+               $add = array();
+
+               $dbw =& wfGetDB( DB_MASTER );
+               $pagelinks = $dbw->tableName( 'pagelinks' );
+               $imagelinks = $dbw->tableName( 'imagelinks' );
+               $categorylinks = $dbw->tableName( 'categorylinks' );
+               
+               #------------------------------------------------------------------------------
+               # Good links
+
+               if ( $wgLinkCache->incrementalSetup( LINKCACHE_PAGE, $del, $add ) ) {
+                       # Delete where necessary
+                       if ( count( $del ) ) {
+                               $batch = new LinkBatch( $del );
+                               $set = $batch->constructSet( 'pl', $dbw );
+                               if ( $set ) {
+                                       $sql = "DELETE FROM $pagelinks WHERE pl_from={$this->mId} AND ($set)";
+                                       $dbw->query( $sql, $fname );
+                               }
+                       }
+               } else {
+                       # Delete everything
+                       $dbw->delete( 'pagelinks', array( 'pl_from' => $this->mId ), $fname );
+                                               
+                       # Get the addition list
+                       $add = $wgLinkCache->getPageLinks();
+               }
+
+               # Do the insertion
+               if( 0 != count( $add ) ) {
+                       $arr = array();
+                       foreach( $add as $lt => $target ) {
+                               array_push( $arr, array(
+                                                       'pl_from' => $this->mId,
+                                                       'pl_namespace' => $target->getNamespace(),
+                                                       'pl_title'     => $target->getDbKey() ) );
+                       }
+                       
+                       # The link cache was constructed without FOR UPDATE, so there may be collisions
+                       # Ignoring for now, I'm not sure if that causes problems or not, but I'm fairly
+                       # sure it's better than without IGNORE
+                       $dbw->insert( 'pagelinks', $arr, $fname, array( 'IGNORE' ) );
+               }
+
+               #------------------------------------------------------------------------------
+               # Image links
+               $dbw->delete('imagelinks',array('il_from'=>$this->mId),$fname);
+               
+               # Get addition list
+               $add = $wgLinkCache->getImageLinks();
+               
+               # Do the insertion
+               $sql = '';
+               $image = NS_IMAGE;
+               if ( 0 != count ( $add ) ) {
+                       $arr = array();
+                       foreach ($add as $iname => $val ) {
+                               $nt = Title::makeTitle( $image, $iname );
+                               if( !$nt ) continue;
+                               $nt->invalidateCache();
+                               array_push( $arr, array(
+                                       'il_from' => $this->mId,
+                                       'il_to'   => $iname ) );
+                       }
+                       $dbw->insert('imagelinks', $arr, $fname, array('IGNORE'));
+               }
+
+               #------------------------------------------------------------------------------
+               # Category links
+               if( $wgUseCategoryMagic ) {
+                       global $messageMemc, $wgDBname;
+                       
+                       # Get addition list
+                       $add = $wgLinkCache->getCategoryLinks();
+                       
+                       # select existing catlinks for this page
+                       $res = $dbw->select( 'categorylinks',
+                               array( 'cl_to', 'cl_sortkey' ),
+                               array( 'cl_from' => $this->mId ), 
+                               $fname,
+                               'FOR UPDATE' );
+
+                       $del = array();
+                       if( 0 != $dbw->numRows( $res ) ) {
+                               while( $row = $dbw->fetchObject( $res ) ) {
+                                       if( !isset( $add[$row->cl_to] ) || $add[$row->cl_to] != $row->cl_sortkey ) {
+                                               // in the db, but no longer in the page
+                                               // or sortkey has changed -> delete
+                                               $del[] = $row->cl_to;
+                                       } else {
+                                               // remove already existing category memberships
+                                               // from the add array
+                                               unset( $add[$row->cl_to] );
+                                       }
+                               }
+                       }
+                       
+                       // delete any removed categorylinks
+                       if( count( $del ) > 0) {
+                               // delete old ones
+                               $dbw->delete( 'categorylinks',
+                                       array(
+                                               'cl_from' => $this->mId,
+                                               'cl_to'   => $del ),
+                                       $fname );
+                               foreach( $del as $cname ){
+                                       $nt = Title::makeTitle( NS_CATEGORY, $cname );
+                                       $nt->invalidateCache();
+                                       // update the timestamp which indicates when the last article
+                                       // was added or removed to/from this article
+                                       $key = $wgDBname . ':Category:' . md5( $nt->getDBkey() ) . ':adddeltimestamp';
+                                       $messageMemc->set( $key , wfTimestamp( TS_MW ), 24*3600 );
+                               }
+                       }
+                       
+                       // add any new category memberships
+                       if( count( $add ) > 0 ) {
+                               $arr = array();
+                               foreach( $add as $cname => $sortkey ) {
+                                       $nt = Title::makeTitle( NS_CATEGORY, $cname );
+                                       $nt->invalidateCache();
+                                       // update the timestamp which indicates when the last article
+                                       // was added or removed to/from this article
+                                       $key = $wgDBname . ':Category:' . md5( $nt->getDBkey() ) . ':adddeltimestamp';
+                                       $messageMemc->set( $key , wfTimestamp( TS_MW ), 24*3600 );
+                                       array_push( $arr, array(
+                                               'cl_from'    => $this->mId,
+                                               'cl_to'      => $cname,
+                                               'cl_sortkey' => $sortkey ) );
+                               }
+                               // do the actual sql insertion
+                               $dbw->insert( 'categorylinks', $arr, $fname, array( 'IGNORE' ) );
+                       }
+               }
+               
+               wfProfileOut( $fname );
+       }
+
+       /**
+         * Link update which clears the previous entries and inserts new ones
+         * May be slower or faster depending on level of lock contention and write speed of DB
+         * Also useful where link table corruption needs to be repaired, e.g. in refreshLinks.php
+        */
+       function doDumbUpdate() {
+               global $wgLinkCache, $wgDBtransactions, $wgUseCategoryMagic;
+               $fname = 'LinksUpdate::doDumbUpdate';
+               wfProfileIn( $fname );
+               
+               
+               $dbw =& wfGetDB( DB_MASTER );
+               $pagelinks = $dbw->tableName( 'pagelinks' );
+               $imagelinks = $dbw->tableName( 'imagelinks' );
+               $categorylinks = $dbw->tableName( 'categorylinks' );
+               
+               $dbw->delete('pagelinks', array('pl_from'=>$this->mId),$fname);
+
+               $a = $wgLinkCache->getPageLinks();
+               if ( 0 != count( $a ) ) {
+                       $arr = array();
+                       foreach( $a as $lt => $target ) {
+                               array_push( $arr, array(
+                                       'pl_from'      => $this->mId,
+                                       'pl_namespace' => $target->getNamespace(),
+                                       'pl_title'     => $target->getDBkey() ) );
+                       }
+                       $dbw->insert( 'pagelinks', $arr, $fname, array( 'IGNORE' ) );
+               }
+
+               $dbw->delete('imagelinks', array('il_from'=>$this->mId),$fname);
+
+               $a = $wgLinkCache->getImageLinks();
+               $sql = '';
+               if ( 0 != count ( $a ) ) {
+                       $arr = array();
+                       foreach( $a as $iname => $val )
+                               array_push( $arr, array(
+                                       'il_from' => $this->mId,
+                                       'il_to'   => $iname ) );
+                       $dbw->insert( 'imagelinks', $arr, $fname, array( 'IGNORE' ) );
+               }
+
+               if( $wgUseCategoryMagic ) {
+                       $dbw->delete('categorylinks', array('cl_from'=>$this->mId),$fname);
+                       
+                       # Get addition list
+                       $add = $wgLinkCache->getCategoryLinks();
+                       
+                       # Do the insertion
+                       $sql = '';
+                       if ( 0 != count ( $add ) ) {
+                               $arr = array();
+                               foreach( $add as $cname => $sortkey ) {
+                                       # FIXME: Change all this to avoid unnecessary duplication
+                                       $nt = Title::makeTitle( NS_CATEGORY, $cname );
+                                        if( !$nt ) continue;
+                                        $nt->invalidateCache();
+                                       array_push( $arr, array(
+                                               'cl_from'    => $this->mId,
+                                               'cl_to'      => $cname,
+                                               'cl_sortkey' => $sortkey ) );
+                               }
+                               $dbw->insert( 'categorylinks', $arr, $fname, array( 'IGNORE' ) );
+                       }
+               }
+               wfProfileOut( $fname );
+       }
+}
+?>
diff --git a/includes/LoadBalancer.php b/includes/LoadBalancer.php
new file mode 100644 (file)
index 0000000..c4c7805
--- /dev/null
@@ -0,0 +1,609 @@
+<?php
+/**
+ *
+ * @package MediaWiki
+ */
+
+/**
+ * Depends on the database object
+ */
+require_once( 'Database.php' );
+
+# Valid database indexes
+# Operation-based indexes
+define( 'DB_SLAVE', -1 );     # Read from the slave (or only server)
+define( 'DB_MASTER', -2 );    # Write to master (or only server)
+define( 'DB_LAST', -3 );     # Whatever database was used last
+
+# Obsolete aliases
+define( 'DB_READ', -1 );
+define( 'DB_WRITE', -2 );
+
+/**
+ * Database load balancing object
+ *
+ * @todo document
+ * @package MediaWiki
+ */
+class LoadBalancer {
+       /* private */ var $mServers, $mConnections, $mLoads, $mGroupLoads;
+       /* private */ var $mFailFunction, $mErrorConnection;
+       /* private */ var $mForce, $mReadIndex, $mLastIndex;
+       /* private */ var $mWaitForFile, $mWaitForPos, $mWaitTimeout;
+       /* private */ var $mLaggedSlaveMode;
+
+       function LoadBalancer()
+       {
+               $this->mServers = array();
+               $this->mConnections = array();
+               $this->mFailFunction = false;
+               $this->mReadIndex = -1;
+               $this->mForce = -1;
+               $this->mLastIndex = -1;
+               $this->mErrorConnection = false;
+       }
+
+       function newFromParams( $servers, $failFunction = false, $waitTimeout = 10 )
+       {
+               $lb = new LoadBalancer;
+               $lb->initialise( $servers, $failFunction, $waitTimeout );
+               return $lb;
+       }
+
+       function initialise( $servers, $failFunction = false, $waitTimeout = 10 )
+       {
+               $this->mServers = $servers;
+               $this->mFailFunction = $failFunction;
+               $this->mReadIndex = -1;
+               $this->mWriteIndex = -1;
+               $this->mForce = -1;
+               $this->mConnections = array();
+               $this->mLastIndex = 1;
+               $this->mLoads = array();
+               $this->mWaitForFile = false;
+               $this->mWaitForPos = false;
+               $this->mWaitTimeout = $waitTimeout;
+               $this->mLaggedSlaveMode = false;
+
+               foreach( $servers as $i => $server ) {
+                       $this->mLoads[$i] = $server['load'];
+                       if ( isset( $server['groupLoads'] ) ) {
+                               foreach ( $server['groupLoads'] as $group => $ratio ) {
+                                       if ( !isset( $this->mGroupLoads[$group] ) ) {
+                                               $this->mGroupLoads[$group] = array();
+                                       }
+                                       $this->mGroupLoads[$group][$i] = $ratio;
+                               }
+                       }
+               }       
+       }
+       
+       /**
+        * Given an array of non-normalised probabilities, this function will select
+        * an element and return the appropriate key
+        */
+       function pickRandom( $weights )
+       {
+               if ( !is_array( $weights ) || count( $weights ) == 0 ) {
+                       return false;
+               }
+
+               $sum = 0;
+               foreach ( $weights as $w ) {
+                       $sum += $w;
+               }
+
+               if ( $sum == 0 ) {
+                       # No loads on any of them
+                       # Just pick one at random
+                       foreach ( $weights as $i => $w ) {
+                               $weights[$i] = 1;
+                       }
+               }
+               $max = mt_getrandmax();
+               $rand = mt_rand(0, $max) / $max * $sum;
+               
+               $sum = 0;
+               foreach ( $weights as $i => $w ) {
+                       $sum += $w;
+                       if ( $sum >= $rand ) {
+                               break;
+                       }
+               }
+               return $i;
+       }
+
+       function getRandomNonLagged( $loads ) {
+               # Unset excessively lagged servers
+               $lags = $this->getLagTimes();
+               foreach ( $lags as $i => $lag ) {
+                       if ( isset( $this->mServers[$i]['max lag'] ) && $lag > $this->mServers[$i]['max lag'] ) {
+                               unset( $loads[$i] );
+                       }
+               }
+
+
+               # Find out if all the slaves with non-zero load are lagged
+               $sum = 0;
+               foreach ( $loads as $load ) {
+                       $sum += $load;
+               }
+               if ( $sum == 0 ) {
+                       # No appropriate DB servers except maybe the master and some slaves with zero load
+                       # Do NOT use the master
+                       # Instead, this function will return false, triggering read-only mode, 
+                       # and a lagged slave will be used instead.
+                       unset ( $loads[0] );
+               }
+
+               if ( count( $loads ) == 0 ) {
+                       return false;
+               }
+
+               #wfDebugLog( 'connect', var_export( $loads, true ) );
+
+               # Return a random representative of the remainder
+               return $this->pickRandom( $loads );
+       }
+
+       /**
+        * Get the index of the reader connection, which may be a slave
+        * This takes into account load ratios and lag times. It should 
+        * always return a consistent index during a given invocation
+        *
+        * Side effect: opens connections to databases
+        */
+       function getReaderIndex()
+       {
+               global $wgMaxLag, $wgReadOnly, $wgDBClusterTimeout;
+
+               $fname = 'LoadBalancer::getReaderIndex';
+               wfProfileIn( $fname );
+
+               $i = false;
+               if ( $this->mForce >= 0 ) {
+                       $i = $this->mForce;
+               } else {
+                       if ( $this->mReadIndex >= 0 ) {
+                               $i = $this->mReadIndex;
+                       } else {
+                               # $loads is $this->mLoads except with elements knocked out if they
+                               # don't work
+                               $loads = $this->mLoads;
+                               $done = false;
+                               $totalElapsed = 0;
+                               do {
+                                       if ( $wgReadOnly ) {
+                                               $i = $this->pickRandom( $loads );
+                                       } else {
+                                               $i = $this->getRandomNonLagged( $loads );
+                                               if ( $i === false && count( $loads ) != 0 )  {
+                                                       # All slaves lagged. Switch to read-only mode
+                                                       $wgReadOnly = wfMsgNoDB( 'readonly_lag' );
+                                                       $i = $this->pickRandom( $loads );
+                                               }
+                                       }
+                                       $serverIndex = $i;
+                                       if ( $i !== false ) {
+                                               wfDebugLog( 'connect', "Using reader #$i: {$this->mServers[$i]['host']}...\n" );
+                                               $this->openConnection( $i );
+                                               
+                                               if ( !$this->isOpen( $i ) ) {
+                                                       wfDebug( "Failed\n" );
+                                                       unset( $loads[$i] );
+                                                       $sleepTime = 0;
+                                               } else {
+                                                       $status = $this->mConnections[$i]->getStatus();
+                                                       if ( isset( $this->mServers[$i]['max threads'] ) && 
+                                                         $status['Threads_running'] > $this->mServers[$i]['max threads'] ) 
+                                                       {
+                                                               # Slave is lagged, wait for a while
+                                                               $sleepTime = 5000 * $status['Threads_connected'];
+
+                                                               # If we reach the timeout and exit the loop, don't use it
+                                                               $i = false;
+                                                       } else {
+                                                               $done = true;
+                                                               $sleepTime = 0;
+                                                       }
+                                               }
+                                       } else {
+                                               $sleepTime = 500000;
+                                       }
+                                       if ( $sleepTime ) {
+                                                       $totalElapsed += $sleepTime;
+                                                       $x = "{$this->mServers[$serverIndex]['host']} $sleepTime [$serverIndex]";
+                                                       wfProfileIn( "$fname-sleep $x" );
+                                                       usleep( $sleepTime );
+                                                       wfProfileOut( "$fname-sleep $x" );
+                                       }
+                               } while ( count( $loads ) && !$done && $totalElapsed / 1e6 < $wgDBClusterTimeout );
+
+                               if ( $i !== false && $this->isOpen( $i ) ) {
+                                       # Wait for the session master pos for a short time
+                                       if ( $this->mWaitForFile ) {
+                                               if ( !$this->doWait( $i ) ) {
+                                                       $this->mServers[$i]['slave pos'] = $this->mConnections[$i]->getSlavePos();
+                                               }
+                                       }
+                                       if ( $i !== false ) {
+                                               $this->mReadIndex = $i;
+                                       }
+                               } else {
+                                       $i = false;
+                               }
+                       }
+               }
+               wfProfileOut( $fname );
+               return $i;
+       }
+       
+       /**
+        * Get a random server to use in a query group
+        */
+       function getGroupIndex( $group ) {
+               if ( isset( $this->mGroupLoads[$group] ) ) {
+                       $i = $this->pickRandom( $this->mGroupLoads[$group] );
+               } else {
+                       $i = false;
+               }
+               wfDebug( "Query group $group => $i\n" );
+               return $i;
+       }
+       
+       /**
+        * Set the master wait position
+        * If a DB_SLAVE connection has been opened already, waits
+        * Otherwise sets a variable telling it to wait if such a connection is opened
+        */
+       function waitFor( $file, $pos ) {
+               $fname = 'LoadBalancer::waitFor';
+               wfProfileIn( $fname );
+
+               wfDebug( "User master pos: $file $pos\n" );
+               $this->mWaitForFile = false;
+               $this->mWaitForPos = false;
+
+               if ( count( $this->mServers ) > 1 ) {
+                       $this->mWaitForFile = $file;
+                       $this->mWaitForPos = $pos;
+                       $i = $this->mReadIndex;
+
+                       if ( $i > 0 ) {
+                               if ( !$this->doWait( $i ) ) {
+                                       $this->mServers[$i]['slave pos'] = $this->mConnections[$i]->getSlavePos();
+                                       $this->mLaggedSlaveMode = true;
+                               }
+                       } 
+               }
+               wfProfileOut( $fname );
+       }
+
+       /**
+        * Wait for a given slave to catch up to the master pos stored in $this
+        */
+       function doWait( $index ) {
+               global $wgMemc;
+               
+               $retVal = false;
+
+               # Debugging hacks
+               if ( isset( $this->mServers[$index]['lagged slave'] ) ) {
+                       return false;
+               } elseif ( isset( $this->mServers[$index]['fake slave'] ) ) {
+                       return true;
+               }
+
+               $key = 'masterpos:' . $index;
+               $memcPos = $wgMemc->get( $key );
+               if ( $memcPos ) {
+                       list( $file, $pos ) = explode( ' ', $memcPos );
+                       # If the saved position is later than the requested position, return now
+                       if ( $file == $this->mWaitForFile && $this->mWaitForPos <= $pos ) {
+                               $retVal = true;
+                       }
+               }
+
+               if ( !$retVal && $this->isOpen( $index ) ) {
+                       $conn =& $this->mConnections[$index];
+                       wfDebug( "Waiting for slave #$index to catch up...\n" );
+                       $result = $conn->masterPosWait( $this->mWaitForFile, $this->mWaitForPos, $this->mWaitTimeout );
+
+                       if ( $result == -1 || is_null( $result ) ) {
+                               # Timed out waiting for slave, use master instead
+                               wfDebug( "Timed out waiting for slave #$index pos {$this->mWaitForFile} {$this->mWaitForPos}\n" );
+                               $retVal = false;
+                       } else {
+                               $retVal = true;
+                               wfDebug( "Done\n" );
+                       }
+               }
+               return $retVal;
+       }               
+
+       /**
+        * Get a connection by index
+        */
+       function &getConnection( $i, $fail = true, $groups = array() )
+       {
+               $fname = 'LoadBalancer::getConnection';
+               wfProfileIn( $fname );
+               
+               # Query groups
+               $groupIndex = false;
+               foreach ( $groups as $group ) {
+                       $groupIndex = $this->getGroupIndex( $group );
+                       if ( $groupIndex !== false ) {
+                               $i = $groupIndex;
+                               break;
+                       }
+               }
+               
+               # Operation-based index
+               if ( $i == DB_SLAVE ) { 
+                       $i = $this->getReaderIndex();
+               } elseif ( $i == DB_MASTER ) {
+                       $i = $this->getWriterIndex();
+               } elseif ( $i == DB_LAST ) {
+                       # Just use $this->mLastIndex, which should already be set
+                       $i = $this->mLastIndex;
+                       if ( $i === -1 ) {
+                               # Oh dear, not set, best to use the writer for safety
+                               wfDebug( "Warning: DB_LAST used when there was no previous index\n" );
+                               $i = $this->getWriterIndex();
+                       }
+               }
+               # Couldn't find a working server in getReaderIndex()?
+               if ( $i === false ) {
+                       $this->reportConnectionError( $this->mErrorConnection );
+               }
+               # Now we have an explicit index into the servers array
+               $this->openConnection( $i, $fail );
+               
+               wfProfileOut( $fname );
+               return $this->mConnections[$i];
+       }
+
+       /**
+        * Open a connection to the server given by the specified index
+        * Index must be an actual index into the array
+        * Returns success
+        * @private
+        */
+       function openConnection( $i, $fail = false ) {
+               $fname = 'LoadBalancer::openConnection';
+               wfProfileIn( $fname );
+               $success = true;
+
+               if ( !$this->isOpen( $i ) ) {
+                       $this->mConnections[$i] = $this->reallyOpenConnection( $this->mServers[$i] );
+               }
+               if ( !$this->isOpen( $i ) ) {
+                       wfDebug( "Failed to connect to database $i at {$this->mServers[$i]['host']}\n" );
+                       if ( $fail ) {
+                               $this->reportConnectionError( $this->mConnections[$i] );
+                       }
+                       $this->mErrorConnection = $this->mConnections[$i];
+                       $this->mConnections[$i] = false;
+                       $success = false;
+               }
+               $this->mLastIndex = $i;
+               wfProfileOut( $fname );
+               return $success;
+       }
+
+       /**
+        * Test if the specified index represents an open connection
+        * @private
+        */
+       function isOpen( $index ) {
+               if( !is_integer( $index ) ) {
+                       return false;
+               }
+               if ( array_key_exists( $index, $this->mConnections ) && is_object( $this->mConnections[$index] ) && 
+                 $this->mConnections[$index]->isOpen() ) 
+               {
+                       return true;
+               } else {
+                       return false;
+               }
+       }
+       
+       /**
+        * Really opens a connection
+        * @private
+        */
+       function reallyOpenConnection( &$server ) {
+               if( !is_array( $server ) ) {
+                       wfDebugDieBacktrace( 'You must update your load-balancing configuration. See DefaultSettings.php entry for $wgDBservers.' );
+               }
+               
+               extract( $server );
+               # Get class for this database type
+               $class = 'Database' . ucfirst( $type );
+               if ( !class_exists( $class ) ) {
+                       require_once( "$class.php" );
+               }
+
+               # Create object
+               return new $class( $host, $user, $password, $dbname, 1, $flags );
+       }
+       
+       function reportConnectionError( &$conn )
+       {
+               $fname = 'LoadBalancer::reportConnectionError';
+               wfProfileIn( $fname );
+               # Prevent infinite recursion
+               
+               static $reporting = false;
+               if ( !$reporting ) {
+                       $reporting = true;
+                       if ( !is_object( $conn ) ) {
+                               $conn = new Database;
+                       }
+                       if ( $this->mFailFunction ) {
+                               $conn->failFunction( $this->mFailFunction );
+                       } else {
+                               $conn->failFunction( false );
+                       }
+                       $conn->reportConnectionError();
+                       $reporting = false;
+               }
+               wfProfileOut( $fname );
+       }
+       
+       function getWriterIndex()
+       {
+               return 0;
+       }
+
+       function force( $i )
+       {
+               $this->mForce = $i;
+       }
+
+       function haveIndex( $i )
+       {
+               return array_key_exists( $i, $this->mServers );
+       }
+
+       /**
+        * Get the number of defined servers (not the number of open connections)
+        */
+       function getServerCount() {
+               return count( $this->mServers );
+       }
+
+       /**
+        * Save master pos to the session and to memcached, if the session exists
+        */
+       function saveMasterPos() {
+               global $wgSessionStarted;
+               if ( $wgSessionStarted && count( $this->mServers ) > 1 ) {
+                       # If this entire request was served from a slave without opening a connection to the 
+                       # master (however unlikely that may be), then we can fetch the position from the slave.
+                       if ( empty( $this->mConnections[0] ) ) {
+                               $conn =& $this->getConnection( DB_SLAVE );
+                               list( $file, $pos ) = $conn->getSlavePos();
+                               wfDebug( "Saving master pos fetched from slave: $file $pos\n" );
+                       } else {
+                               $conn =& $this->getConnection( 0 );
+                               list( $file, $pos ) = $conn->getMasterPos();
+                               wfDebug( "Saving master pos: $file $pos\n" );
+                       }
+                       if ( $file !== false ) {
+                               $_SESSION['master_log_file'] = $file;
+                               $_SESSION['master_pos'] = $pos;
+                       }
+               }
+       }
+
+       /**
+        * Loads the master pos from the session, waits for it if necessary
+        */
+       function loadMasterPos() {
+               if ( isset( $_SESSION['master_log_file'] ) && isset( $_SESSION['master_pos'] ) ) {
+                       $this->waitFor( $_SESSION['master_log_file'], $_SESSION['master_pos'] );
+               }
+       }
+
+       /**
+        * Close all open connections
+        */
+       function closeAll() {
+               foreach( $this->mConnections as $i => $conn ) {
+                       if ( $this->isOpen( $i ) ) {
+                               // Need to use this syntax because $conn is a copy not a reference
+                               $this->mConnections[$i]->close();
+                       }
+               }
+       }
+
+       function commitAll() {
+               foreach( $this->mConnections as $i => $conn ) {
+                       if ( $this->isOpen( $i ) ) {
+                               // Need to use this syntax because $conn is a copy not a reference
+                               $this->mConnections[$i]->immediateCommit();
+                       }
+               }
+       }
+
+       function waitTimeout( $value = NULL ) {
+               return wfSetVar( $this->mWaitTimeout, $value );
+       }
+
+       function getLaggedSlaveMode() {
+               return $this->mLaggedSlaveMode;
+       }
+
+       function pingAll() {
+               $success = true;
+               foreach ( $this->mConnections as $i => $conn ) {
+                       if ( $this->isOpen( $i ) ) {
+                               if ( !$this->mConnections[$i]->ping() ) {
+                                       $success = false;
+                               }
+                       }
+               }
+               return $success;
+       }
+
+       /**
+        * Get the hostname and lag time of the most-lagged slave
+        * This is useful for maintenance scripts that need to throttle their updates
+        */
+       function getMaxLag() {
+               $maxLag = -1;
+               $host = '';
+               foreach ( $this->mServers as $i => $conn ) {
+                       if ( $this->openConnection( $i ) ) {
+                               $lag = $this->mConnections[$i]->getLag();
+                               if ( $lag > $maxLag ) {
+                                       $maxLag = $lag;
+                                       $host = $this->mServers[$i]['host'];
+                               }
+                       }
+               }
+               return array( $host, $maxLag );
+       }
+       
+       /**
+        * Get lag time for each DB
+        * Results are cached for a short time in memcached
+        */
+       function getLagTimes() {
+               $expiry = 5;
+               $requestRate = 10;
+
+               global $wgMemc;
+               $times = $wgMemc->get( 'lag_times' );
+               if ( $times ) {
+                       # Randomly recache with probability rising over $expiry
+                       $elapsed = time() - $times['timestamp'];
+                       $chance = max( 0, ( $expiry - $elapsed ) * $requestRate );
+                       if ( mt_rand( 0, $chance ) != 0 ) {
+                               unset( $times['timestamp'] );
+                               return $times;
+                       }
+               }
+
+               # Cache key missing or expired
+
+               $times = array();
+               foreach ( $this->mServers as $i => $conn ) {
+                       if ( $this->openConnection( $i ) ) {
+                               $times[$i] = $this->mConnections[$i]->getLag();
+                       }
+               }
+
+               # Add a timestamp key so we know when it was cached
+               $times['timestamp'] = time();
+               $wgMemc->set( 'lag_times', $times, $expiry );
+
+               # But don't give the timestamp to the caller
+               unset($times['timestamp']);
+               return $times;
+       }
+}
+
+?>
diff --git a/includes/LogPage.php b/includes/LogPage.php
new file mode 100644 (file)
index 0000000..4447dd7
--- /dev/null
@@ -0,0 +1,253 @@
+<?php
+#
+# Copyright (C) 2002, 2004 Brion Vibber <brion@pobox.com>
+# http://www.mediawiki.org/
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or 
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# http://www.gnu.org/copyleft/gpl.html
+
+/**
+ * Contain log classes
+ *
+ * @package MediaWiki
+ */
+
+/**
+ * Class to simplify the use of log pages.
+ * The logs are now kept in a table which is easier to manage and trim
+ * than ever-growing wiki pages.
+ *
+ * @package MediaWiki
+ */
+class LogPage {
+       /* private */ var $type, $action, $comment, $params, $target;
+       var $updateRecentChanges = true;
+
+       /**
+         * Constructor
+         *
+         * @param string $type One of '', 'block', 'protect', 'rights', 'delete',
+         *               'upload', 'move'
+         */
+       function LogPage( $type ) {
+               $this->type = $type;
+       }
+
+       function saveContent() {
+               if( wfReadOnly() ) return;
+
+               global $wgUser;
+               $fname = 'LogPage::saveContent';
+
+               $dbw =& wfGetDB( DB_MASTER );
+               $uid = $wgUser->getID();
+
+               $this->timestamp = $now = wfTimestampNow();
+               $dbw->insert( 'logging',
+                       array(
+                               'log_type' => $this->type,
+                               'log_action' => $this->action,
+                               'log_timestamp' => $dbw->timestamp( $now ),
+                               'log_user' => $uid,
+                               'log_namespace' => $this->target->getNamespace(),
+                               'log_title' => $this->target->getDBkey(),
+                               'log_comment' => $this->comment,
+                               'log_params' => $this->params
+                       ), $fname
+               );
+               
+               # And update recentchanges
+               if ( $this->updateRecentChanges ) {
+                       $titleObj = Title::makeTitle( NS_SPECIAL, 'Log/' . $this->type );
+                       $rcComment = $this->actionText;
+                       if( '' != $this->comment ) {
+                               if ($rcComment == '')
+                                       $rcComment = $this->comment;
+                               else
+                                       $rcComment .= ': ' . $this->comment;
+                       }
+                       
+                       RecentChange::notifyLog( $now, $titleObj, $wgUser, $rcComment );
+               }
+               return true;
+       }
+
+       /**
+        * @static
+        */
+       function validTypes() {
+               static $types = array( '', 'block', 'protect', 'rights', 'delete', 'upload', 'move' );
+               wfRunHooks( 'LogPageValidTypes', array( &$types) );
+               return $types;
+       }
+       
+       /**
+        * @static
+        */
+       function validActions( $type ) {
+               static $actions = array(
+                       '' => NULL,
+                       'block' => array( 'block', 'unblock' ),
+                       'protect' => array( 'protect', 'unprotect' ),
+                       'rights' => array( 'rights' ),
+                       'delete' => array( 'delete', 'restore' ),
+                       'upload' => array( 'upload' ),
+                       'move' => array( 'move' )
+               );
+               return $actions[$type];
+       }
+       
+       /**
+        * @static
+        */
+       function isLogType( $type ) {
+               return in_array( $type, LogPage::validTypes() );
+       }
+       
+       /**
+        * @static
+        */
+       function logName( $type ) {
+               static $typeText = array(
+                       ''        => 'log',
+                       'block'   => 'blocklogpage',
+                       'protect' => 'protectlogpage',
+                       'rights'  => 'bureaucratlog',
+                       'delete'  => 'dellogpage',
+                       'upload'  => 'uploadlogpage',
+                       'move'    => 'movelogpage'
+               );
+               wfRunHooks( 'LogPageLogName', array( &$typeText) );
+               
+               return str_replace( '_', ' ', wfMsg( $typeText[$type] ) );
+       }
+       
+       /**
+        * @static
+        */
+       function logHeader( $type ) {
+               static $headerText = array(
+                       ''        => 'alllogstext',
+                       'block'   => 'blocklogtext',
+                       'protect' => 'protectlogtext',
+                       'rights'  => 'rightslogtext',
+                       'delete'  => 'dellogpagetext',
+                       'upload'  => 'uploadlogpagetext',
+                       'move'    => 'movelogpagetext'
+               );
+               wfRunHooks( 'LogPageLogHeader', array( &$headerText ) );
+               
+               return wfMsg( $headerText[$type] );
+       }
+       
+       /**
+        * @static
+        */
+       function actionText( $type, $action, $title = NULL, $skin = NULL, $params = array(), $filterWikilinks=false ) {
+               static $actions = array(
+                       'block/block'       => 'blocklogentry',
+                       'block/unblock'     => 'unblocklogentry',
+                       'protect/protect'   => 'protectedarticle',
+                       'protect/unprotect' => 'unprotectedarticle',
+                       'rights/rights'     => 'bureaucratlogentry',
+                       'rights/addgroup'   => 'addgrouplogentry',
+                       'rights/rngroup'    => 'renamegrouplogentry',
+                       'rights/chgroup'    => 'changegrouplogentry',
+                       'delete/delete'     => 'deletedarticle',
+                       'delete/restore'    => 'undeletedarticle',
+                       'upload/upload'     => 'uploadedimage',
+                       'upload/revert'     => 'uploadedimage',
+                       'move/move'         => '1movedto2',
+                       'move/move_redir'   => '1movedto2_redir'
+               );
+               $key = "$type/$action";
+               if( isset( $actions[$key] ) ) {
+                       if( is_null( $title ) ) {
+                               $rv=wfMsgForContent( $actions[$key] );
+                       } else {
+                               if( $skin ) {
+                                       if ( $type == 'move' ) {
+                                               $titleLink = $skin->makeLinkObj( $title, $title->getPrefixedText(), 'redirect=no' );
+                                               // Change $param[0] into a link to the title specified in $param[0]
+                                               $movedTo = Title::newFromText( $params[0] );
+                                               $params[0] = $skin->makeLinkObj( $movedTo, $params[0] );
+                                       } else {
+                                               $titleLink = $skin->makeLinkObj( $title );
+                                       }
+                               } else {
+                                       $titleLink = $title->getPrefixedText();
+                               }
+                               if( count( $params ) == 0 ) {
+                                       $rv = wfMsgForContent( $actions[$key], $titleLink );
+                               } else {
+                                       array_unshift( $params, $titleLink );
+                                       $rv = wfMsgReal( $actions[$key], $params, true, true );
+                               }
+                       }
+               } else {
+                       wfDebug( "LogPage::actionText - unknown action $key\n" );
+                       $rv = "$action";
+               }
+               if( $filterWikilinks ) {
+                       $rv = str_replace( "[[", "", $rv );
+                       $rv = str_replace( "]]", "", $rv );
+               }
+               return $rv;
+       }
+
+       /**
+        * Add a log entry
+        * @param string $action one of '', 'block', 'protect', 'rights', 'delete', 'upload', 'move', 'move_redir'
+        * @param object &$target A title object.
+        * @param string $comment Description associated
+        * @param array $params Parameters passed later to wfMsg.* functions
+        */
+       function addEntry( $action, &$target, $comment, $params = array() ) {
+               if ( !is_array( $params ) ) {
+                       $params = array( $params );
+               }
+               
+               $this->action = $action;
+               $this->target =& $target;
+               $this->comment = $comment;
+               $this->params = LogPage::makeParamBlob( $params );
+               
+               $this->actionText = LogPage::actionText( $this->type, $action, $target, NULL, $params );
+
+               return $this->saveContent();
+       }
+
+       /** 
+        * Create a blob from a parameter array
+        * @static
+        */
+       function makeParamBlob( $params ) {
+               return implode( "\n", $params );
+       }
+
+       /**
+        * Extract a parameter array from a blob
+        * @static
+        */
+       function extractParams( $blob ) {
+               if ( $blob === '' ) {
+                       return array();
+               } else {
+                       return explode( "\n", $blob );
+               }
+       }
+}
+
+?>
diff --git a/includes/MagicWord.php b/includes/MagicWord.php
new file mode 100644 (file)
index 0000000..0fbe370
--- /dev/null
@@ -0,0 +1,343 @@
+<?php
+/**
+ * File for magic words
+ * @package MediaWiki
+ * @subpackage Parser
+ */
+
+/**
+ * private
+ */
+$wgMagicFound = false;
+
+/** Actual keyword to be used is set in Language.php */
+define('MAG_REDIRECT',                 0);
+define('MAG_NOTOC',                    1);
+define('MAG_START',                    2);
+define('MAG_CURRENTMONTH',             3);
+define('MAG_CURRENTMONTHNAME',         4);
+define('MAG_CURRENTMONTHNAMEGEN',      5);
+define('MAG_CURRENTMONTHABBREV',       6);
+define('MAG_CURRENTDAY',               7);
+define('MAG_CURRENTDAYNAME',           8);
+define('MAG_CURRENTYEAR',              9);
+define('MAG_CURRENTTIME',              10);
+define('MAG_NUMBEROFARTICLES',         11);
+define('MAG_SUBST',                    12);
+define('MAG_MSG',                      13);
+define('MAG_MSGNW',                    14);
+define('MAG_NOEDITSECTION',            15);
+define('MAG_END',                      16);
+define('MAG_IMG_THUMBNAIL',            17);
+define('MAG_IMG_RIGHT',                        18);
+define('MAG_IMG_LEFT',                 19);
+define('MAG_IMG_NONE',                 20);
+define('MAG_IMG_WIDTH',                        21);
+define('MAG_IMG_CENTER',               22);
+define('MAG_INT',                      23);
+define('MAG_FORCETOC',                 24);
+define('MAG_SITENAME',                 25);
+define('MAG_NS',                       26);
+define('MAG_LOCALURL',                 27);
+define('MAG_LOCALURLE',                        28);
+define('MAG_SERVER',                   29);
+define('MAG_IMG_FRAMED',               30);
+define('MAG_PAGENAME',                 31);
+define('MAG_PAGENAMEE',                        32);
+define('MAG_NAMESPACE',                        33);
+define('MAG_TOC',                      34);
+define('MAG_GRAMMAR',                  35);
+define('MAG_NOTITLECONVERT',           36);
+define('MAG_NOCONTENTCONVERT',         37);
+define('MAG_CURRENTWEEK',              38);
+define('MAG_CURRENTDOW',               39);
+define('MAG_REVISIONID',               40);
+define('MAG_SCRIPTPATH',               41);
+define('MAG_SERVERNAME',               42);
+define('MAG_NUMBEROFFILES',            43);
+
+$wgVariableIDs = array(
+       MAG_CURRENTMONTH,
+       MAG_CURRENTMONTHNAME,
+       MAG_CURRENTMONTHNAMEGEN,
+       MAG_CURRENTMONTHABBREV,
+       MAG_CURRENTDAY,
+       MAG_CURRENTDAYNAME,
+       MAG_CURRENTYEAR,
+       MAG_CURRENTTIME,
+       MAG_NUMBEROFARTICLES,
+       MAG_NUMBEROFFILES,
+       MAG_SITENAME,
+       MAG_SERVER,
+       MAG_SERVERNAME,
+       MAG_SCRIPTPATH,
+       MAG_PAGENAME,
+       MAG_PAGENAMEE,
+       MAG_NAMESPACE,
+       MAG_CURRENTWEEK,
+       MAG_CURRENTDOW,
+       MAG_REVISIONID,
+);
+
+/**
+ * This class encapsulates "magic words" such as #redirect, __NOTOC__, etc.
+ * Usage:
+ *     if (MagicWord::get( MAG_REDIRECT )->match( $text ) )
+ * 
+ * Possible future improvements: 
+ *   * Simultaneous searching for a number of magic words
+ *   * $wgMagicWords in shared memory
+ *
+ * Please avoid reading the data out of one of these objects and then writing 
+ * special case code. If possible, add another match()-like function here.
+ *
+ * @package MediaWiki
+ */
+class MagicWord {
+       /**#@+
+        * @access private
+        */
+       var $mId, $mSynonyms, $mCaseSensitive, $mRegex;
+       var $mRegexStart, $mBaseRegex, $mVariableRegex;
+       var $mModified; 
+       /**#@-*/
+
+       function MagicWord($id = 0, $syn = '', $cs = false) {
+               $this->mId = $id;
+               $this->mSynonyms = (array)$syn;
+               $this->mCaseSensitive = $cs;
+               $this->mRegex = '';
+               $this->mRegexStart = '';
+               $this->mVariableRegex = '';
+               $this->mVariableStartToEndRegex = '';
+               $this->mModified = false;
+       }
+
+       /**
+        * Factory: creates an object representing an ID
+        * @static
+        */
+       function &get( $id ) {
+               global $wgMagicWords;
+               
+               if ( !is_array( $wgMagicWords ) ) {
+                       wfDebugDieBacktrace( "Incorrect initialisation order, \$wgMagicWords does not exist\n" );
+               }
+               if (!array_key_exists( $id, $wgMagicWords ) ) {
+                       $mw = new MagicWord();
+                       $mw->load( $id );
+                       $wgMagicWords[$id] = $mw;
+               }
+               return $wgMagicWords[$id];
+       }
+       
+       # Initialises this object with an ID
+       function load( $id ) {
+               global $wgContLang;             
+               $this->mId = $id;
+               $wgContLang->getMagic( $this );
+       }
+       
+       /**
+        * Preliminary initialisation
+        * @private
+        */
+       function initRegex() {
+               #$variableClass = Title::legalChars();
+               # This was used for matching "$1" variables, but different uses of the feature will have
+               # different restrictions, which should be checked *after* the MagicWord has been matched,
+               # not here. - IMSoP
+               $escSyn = array_map( 'preg_quote', $this->mSynonyms );
+               $this->mBaseRegex = implode( '|', $escSyn );
+               $case = $this->mCaseSensitive ? '' : 'i';
+               $this->mRegex = "/{$this->mBaseRegex}/{$case}";
+               $this->mRegexStart = "/^(?:{$this->mBaseRegex})/{$case}";
+               $this->mVariableRegex = str_replace( "\\$1", "(.*?)", $this->mRegex );
+               $this->mVariableStartToEndRegex = str_replace( "\\$1", "(.*?)", 
+                       "/^(?:{$this->mBaseRegex})$/{$case}" );
+       }
+       
+       /**
+        * Gets a regex representing matching the word
+        */
+       function getRegex() {
+               if ($this->mRegex == '' ) {
+                       $this->initRegex();
+               }
+               return $this->mRegex;
+       }
+
+       /**
+        * Gets a regex matching the word, if it is at the string start
+        */
+       function getRegexStart() {
+               if ($this->mRegex == '' ) {
+                       $this->initRegex();
+               }
+               return $this->mRegexStart;
+       }
+
+       /**
+        * regex without the slashes and what not
+        */
+       function getBaseRegex() {
+               if ($this->mRegex == '') {
+                       $this->initRegex();
+               }
+               return $this->mBaseRegex;
+       }
+               
+       /**
+        * Returns true if the text contains the word
+        * @return bool
+        */
+       function match( $text ) {
+               return preg_match( $this->getRegex(), $text );
+       }
+
+       /**
+        * Returns true if the text starts with the word
+        * @return bool
+        */
+       function matchStart( $text ) {
+               return preg_match( $this->getRegexStart(), $text );
+       }
+
+       /**
+        * Returns NULL if there's no match, the value of $1 otherwise
+        * The return code is the matched string, if there's no variable
+        * part in the regex and the matched variable part ($1) if there
+        * is one.
+        */
+       function matchVariableStartToEnd( $text ) {
+               $matchcount = preg_match( $this->getVariableStartToEndRegex(), $text, $matches );
+               if ( $matchcount == 0 ) {
+                       return NULL;
+               } elseif ( count($matches) == 1 ) {
+                       return $matches[0];
+               } else {
+                       # multiple matched parts (variable match); some will be empty because of synonyms
+                       # the variable will be the second non-empty one so remove any blank elements and re-sort the indices
+                       $matches = array_values(array_filter($matches));
+                       return $matches[1];
+               }
+       }
+
+
+       /**
+        * Returns true if the text matches the word, and alters the
+        * input string, removing all instances of the word
+        */
+       function matchAndRemove( &$text ) {
+               global $wgMagicFound;
+               $wgMagicFound = false;
+               $text = preg_replace_callback( $this->getRegex(), 'pregRemoveAndRecord', $text );
+               return $wgMagicFound;
+       }
+
+       function matchStartAndRemove( &$text ) {
+               global $wgMagicFound;
+               $wgMagicFound = false;
+               $text = preg_replace_callback( $this->getRegexStart(), 'pregRemoveAndRecord', $text );
+               return $wgMagicFound;
+       }               
+
+
+       /**
+        * Replaces the word with something else
+        */
+       function replace( $replacement, $subject ) {
+               $res = preg_replace( $this->getRegex(), $replacement, $subject );
+               $this->mModified = !($res === $subject);
+               return $res;
+       }
+
+       /**
+        * Variable handling: {{SUBST:xxx}} style words
+        * Calls back a function to determine what to replace xxx with
+        * Input word must contain $1
+        */
+       function substituteCallback( $text, $callback ) {
+               $regex = $this->getVariableRegex();
+               $res = preg_replace_callback( $this->getVariableRegex(), $callback, $text );
+               $this->mModified = !($res === $text);
+               return $res;
+       }
+
+       /**
+        * Matches the word, where $1 is a wildcard
+        */
+       function getVariableRegex()     {
+               if ( $this->mVariableRegex == '' ) {
+                       $this->initRegex();
+               } 
+               return $this->mVariableRegex;
+       }
+
+       /**
+        * Matches the entire string, where $1 is a wildcard
+        */
+       function getVariableStartToEndRegex() {
+               if ( $this->mVariableStartToEndRegex == '' ) {
+                       $this->initRegex();
+               } 
+               return $this->mVariableStartToEndRegex;
+       }
+
+       /**
+        * Accesses the synonym list directly
+        */
+       function getSynonym( $i ) {
+               return $this->mSynonyms[$i];
+       }
+
+       /**
+        * Returns true if the last call to replace() or substituteCallback() 
+        * returned a modified text, otherwise false.
+        */
+       function getWasModified(){
+               return $this->mModified;
+       }
+
+       /**
+        * $magicarr is an associative array of (magic word ID => replacement)
+        * This method uses the php feature to do several replacements at the same time,
+        * thereby gaining some efficiency. The result is placed in the out variable
+        * $result. The return value is true if something was replaced.
+        * @static 
+        **/
+       function replaceMultiple( $magicarr, $subject, &$result ){
+               $search = array();
+               $replace = array();
+               foreach( $magicarr as $id => $replacement ){
+                       $mw = MagicWord::get( $id );
+                       $search[] = $mw->getRegex();
+                       $replace[] = $replacement;
+               }
+
+               $result = preg_replace( $search, $replace, $subject );
+               return !($result === $subject);
+       }
+
+       /**
+        * Adds all the synonyms of this MagicWord to an array, to allow quick
+        * lookup in a list of magic words
+        */
+       function addToArray( &$array, $value ) {
+               foreach ( $this->mSynonyms as $syn ) {
+                       $array[$syn] = $value;
+               }
+       }
+}
+
+/**
+ * Used in matchAndRemove()
+ * @private
+ **/
+function pregRemoveAndRecord( $match ) {
+       global $wgMagicFound;
+       $wgMagicFound = true;
+       return '';
+}
+
+?>
diff --git a/includes/Math.php b/includes/Math.php
new file mode 100644 (file)
index 0000000..d24f30d
--- /dev/null
@@ -0,0 +1,225 @@
+<?php
+/**
+ * Contain everything related to <math> </math> parsing
+ * @package MediaWiki
+ */
+
+/**
+ * Takes LaTeX fragments, sends them to a helper program (texvc) for rendering
+ * to rasterized PNG and HTML and MathML approximations. An appropriate
+ * rendering form is picked and returned.
+ * 
+ * by Tomasz Wegrzanowski, with additions by Brion Vibber (2003, 2004)
+ *
+ * @package MediaWiki
+ */
+class MathRenderer {
+       var $mode = MW_MATH_MODERN;
+       var $tex = '';
+       var $inputhash = '';
+       var $hash = '';
+       var $html = '';
+       var $mathml = '';
+       var $conservativeness = 0;
+       
+       function MathRenderer( $tex ) {
+               $this->tex = $tex;
+       }
+       
+       function setOutputMode( $mode ) {
+               $this->mode = $mode;
+       }
+
+       function render() {
+               global $wgMathDirectory, $wgTmpDirectory, $wgInputEncoding;
+               global $wgTexvc;
+               $fname = 'MathRenderer::render';
+       
+               if( $this->mode == MW_MATH_SOURCE ) {
+                       # No need to render or parse anything more!
+                       return ('$ '.htmlspecialchars( $this->tex ).' $');
+               }
+               
+               if( !$this->_recall() ) {
+                       # Ensure that the temp and output directories are available before continuing...
+                       if( !file_exists( $wgMathDirectory ) ) {
+                               if( !@mkdir( $wgMathDirectory ) ) {
+                                       return $this->_error( 'math_bad_output' );
+                               }
+                       } elseif( !is_dir( $wgMathDirectory ) || !is_writable( $wgMathDirectory ) ) {
+                               return $this->_error( 'math_bad_output' );
+                       }
+                       if( !file_exists( $wgTmpDirectory ) ) {
+                               if( !@mkdir( $wgTmpDirectory ) ) {
+                                       return $this->_error( 'math_bad_tmpdir' );
+                               }
+                       } elseif( !is_dir( $wgTmpDirectory ) || !is_writable( $wgTmpDirectory ) ) {
+                               return $this->_error( 'math_bad_tmpdir' );
+                       }
+                       
+                       if( function_exists( 'is_executable' ) && !is_executable( $wgTexvc ) ) {
+                               return $this->_error( 'math_notexvc' );
+                       }
+                       $cmd = $wgTexvc . ' ' . 
+                                       escapeshellarg( $wgTmpDirectory ).' '.
+                                       escapeshellarg( $wgMathDirectory ).' '.
+                                       escapeshellarg( $this->tex ).' '.
+                                       escapeshellarg( $wgInputEncoding );
+                                       
+                       if ( wfIsWindows() ) {
+                               # Invoke it within cygwin sh, because texvc expects sh features in its default shell
+                               $cmd = 'sh -c ' . wfEscapeShellArg( $cmd );
+                       } 
+
+                       wfDebug( "TeX: $cmd\n" );
+                       $contents = `$cmd`;
+                       wfDebug( "TeX output:\n $contents\n---\n" );
+               
+                       if (strlen($contents) == 0) {
+                               return $this->_error( 'math_unknown_error' );
+                       }
+                       
+                       $retval = substr ($contents, 0, 1);
+                       if (($retval == 'C') || ($retval == 'M') || ($retval == 'L')) {
+                               if ($retval == 'C')
+                                       $this->conservativeness = 2;
+                               else if ($retval == 'M')
+                                       $this->conservativeness = 1;
+                               else
+                                       $this->conservativeness = 0;
+                               $outdata = substr ($contents, 33);
+               
+                               $i = strpos($outdata, "\000");
+               
+                               $this->html = substr($outdata, 0, $i);
+                               $this->mathml = substr($outdata, $i+1);
+                       } else if (($retval == 'c') || ($retval == 'm') || ($retval == 'l'))  {
+                               $this->html = substr ($contents, 33);
+                               if ($retval == 'c')
+                                       $this->conservativeness = 2;
+                               else if ($retval == 'm')
+                                       $this->conservativeness = 1;
+                               else
+                                       $this->conservativeness = 0;
+                               $this->mathml = NULL;
+                       } else if ($retval == 'X') {
+                               $this->html = NULL;
+                               $this->mathml = substr ($contents, 33);
+                               $this->conservativeness = 0;
+                       } else if ($retval == '+') {
+                               $this->html = NULL;
+                               $this->mathml = NULL;
+                               $this->conservativeness = 0;
+                       } else {
+                               $errbit = htmlspecialchars( substr($contents, 1) );
+                               switch( $retval ) {
+                                       case 'E': return $this->_error( 'math_lexing_error', $errbit );
+                                       case 'S': return $this->_error( 'math_syntax_error', $errbit );
+                                       case 'F': return $this->_error( 'math_unknown_function', $errbit );
+                                       default:  return $this->_error( 'math_unknown_error', $errbit );
+                               }
+                       }
+               
+                       $this->hash = substr ($contents, 1, 32);
+                       if (!preg_match("/^[a-f0-9]{32}$/", $this->hash)) {
+                               return $this->_error( 'math_unknown_error' );
+                       }
+               
+                       if( !file_exists( "$wgMathDirectory/{$this->hash}.png" ) ) {
+                               return $this->_error( 'math_image_error' );
+                       }
+                       
+                       # Now save it back to the DB:
+                       if ( !wfReadOnly() ) {
+                               $outmd5_sql = pack('H32', $this->hash);
+                       
+                               $md5_sql = pack('H32', $this->md5); # Binary packed, not hex
+                               
+                               $dbw =& wfGetDB( DB_MASTER );
+                               $dbw->replace( 'math', array( 'math_inputhash' ),
+                                 array( 
+                                       'math_inputhash' => $md5_sql, 
+                                       'math_outputhash' => $outmd5_sql,
+                                       'math_html_conservativeness' => $this->conservativeness,
+                                       'math_html' => $this->html,
+                                       'math_mathml' => $this->mathml,
+                                 ), $fname, array( 'IGNORE' ) 
+                               );
+                       }
+                       
+               }
+               
+               return $this->_doRender();
+       }
+       
+       function _error( $msg, $append = '' ) {
+               $mf   = htmlspecialchars( wfMsg( 'math_failure' ) );
+               $munk = htmlspecialchars( wfMsg( 'math_unknown_error' ) );
+               $errmsg = htmlspecialchars( wfMsg( $msg ) );
+               $source = htmlspecialchars($this->tex);
+               return "<strong class='error'>$mf ($errmsg$append): $source</strong>\n";
+       }
+       
+       function _recall() {
+               global $wgMathDirectory;
+               $fname = 'MathRenderer::_recall';
+
+               $this->md5 = md5( $this->tex );
+               $dbr =& wfGetDB( DB_SLAVE );
+               $rpage = $dbr->selectRow( 'math', 
+                       array( 'math_outputhash','math_html_conservativeness','math_html','math_mathml' ),
+                       array( 'math_inputhash' => pack("H32", $this->md5)), # Binary packed, not hex
+                       $fname
+               );
+
+               if( $rpage !== false ) {
+                       # Tailing 0x20s can get dropped by the database, add it back on if necessary:
+                       $xhash = unpack( 'H32md5', $rpage->math_outputhash . "                " );
+                       $this->hash = $xhash ['md5'];
+                       
+                       $this->conservativeness = $rpage->math_html_conservativeness;
+                       $this->html = $rpage->math_html;
+                       $this->mathml = $rpage->math_mathml;
+                       
+                       if( file_exists( "$wgMathDirectory/{$this->hash}.png" ) ) {
+                               return true;
+                       }
+               }
+               
+               # Missing from the database and/or the render cache
+               return false;
+       }
+
+       /**
+        * Select among PNG, HTML, or MathML output depending on
+        */
+       function _doRender() {
+               if( $this->mode == MW_MATH_MATHML && $this->mathml != '' ) {
+                       return "<math xmlns='http://www.w3.org/1998/Math/MathML'>{$this->mathml}</math>";
+               }
+               if (($this->mode == MW_MATH_PNG) || ($this->html == '') ||
+                  (($this->mode == MW_MATH_SIMPLE) && ($this->conservativeness != 2)) ||
+                  (($this->mode == MW_MATH_MODERN || $this->mode == MW_MATH_MATHML) && ($this->conservativeness == 0))) {
+                       return $this->_linkToMathImage();
+               } else {
+                       return '<span class="texhtml">'.$this->html.'</span>';
+               }
+       }
+
+       function _linkToMathImage() {
+               global $wgMathPath;
+               $url = htmlspecialchars( "$wgMathPath/{$this->hash}.png" );
+               $alt = trim(str_replace("\n", ' ', htmlspecialchars( $this->tex )));
+               return "<img class='tex' src=\"$url\" alt=\"$alt\" />";
+       }
+
+}
+
+function renderMath( $tex ) {
+       global $wgUser;
+       $math = new MathRenderer( $tex );
+       $math->setOutputMode( $wgUser->getOption('math'));
+       return $math->render();
+}
+
+?>
diff --git a/includes/MemcachedSessions.php b/includes/MemcachedSessions.php
new file mode 100644 (file)
index 0000000..af49109
--- /dev/null
@@ -0,0 +1,74 @@
+<?php
+/**
+ * This file gets included if $wgSessionsInMemcache is set in the config.
+ * It redirects session handling functions to store their data in memcached
+ * instead of the local filesystem. Depending on circumstances, it may also
+ * be necessary to change the cookie settings to work across hostnames.
+ * See: http://www.php.net/manual/en/function.session-set-save-handler.php
+ *
+ * @package MediaWiki
+ */
+
+/**
+ * @todo document
+ */
+function memsess_key( $id ) {
+       global $wgDBname;
+       return "$wgDBname:session:$id";
+}
+
+/**
+ * @todo document
+ */
+function memsess_open( $save_path, $session_name ) {
+       # NOP, $wgMemc should be set up already
+       return true;
+}
+
+/**
+ * @todo document
+ */
+function memsess_close() {
+       # NOP
+       return true;
+}
+
+/**
+ * @todo document
+ */
+function memsess_read( $id ) {
+       global $wgMemc;
+       $data = $wgMemc->get( memsess_key( $id ) );
+       if( ! $data ) return '';
+       return $data;
+}
+
+/**
+ * @todo document
+ */
+function memsess_write( $id, $data ) {
+       global $wgMemc;
+       $wgMemc->set( memsess_key( $id ), $data, 3600 );
+       return true;
+}
+
+/**
+ * @todo document
+ */
+function memsess_destroy( $id ) {
+       global $wgMemc;
+       $wgMemc->delete( memsess_key( $id ) );
+       return true;
+}
+
+/**
+ * @todo document
+ */
+function memsess_gc( $maxlifetime ) {
+       # NOP: Memcached performs garbage collection.
+       return true;
+}
+
+session_set_save_handler( 'memsess_open', 'memsess_close', 'memsess_read', 'memsess_write', 'memsess_destroy', 'memsess_gc' );
+
+?>
diff --git a/includes/MessageCache.php b/includes/MessageCache.php
new file mode 100644 (file)
index 0000000..7f94cc9
--- /dev/null
@@ -0,0 +1,374 @@
+<?php
+/**
+ *
+ * @package MediaWiki
+ * @subpackage Cache
+ */
+
+/** */
+require_once( 'Revision.php' );
+
+/**
+ *
+ */
+define( 'MSG_LOAD_TIMEOUT', 60);
+define( 'MSG_LOCK_TIMEOUT', 10);
+define( 'MSG_WAIT_TIMEOUT', 10);
+
+/**
+ * Message cache
+ * Performs various useful MediaWiki namespace-related functions
+ *
+ * @package MediaWiki
+ */
+class MessageCache
+{
+       var $mCache, $mUseCache, $mDisable, $mExpiry;
+       var $mMemcKey, $mKeys, $mParserOptions, $mParser;
+       var $mExtensionMessages = array();
+       var $mInitialised = false;
+       var $mDeferred = true;
+
+       function initialise( &$memCached, $useDB, $expiry, $memcPrefix) {
+               $fname = 'MessageCache::initialise';
+               wfProfileIn( $fname );
+
+               $this->mUseCache = !is_null( $memCached );
+               $this->mMemc = &$memCached;
+               $this->mDisable = !$useDB;
+               $this->mExpiry = $expiry;
+               $this->mDisableTransform = false;
+               $this->mMemcKey = $memcPrefix.':messages';
+               $this->mKeys = false; # initialised on demand
+               $this->mInitialised = true;
+
+               wfProfileIn( $fname.'-parseropt' );
+               $this->mParserOptions = ParserOptions::newFromUser( $u=NULL );
+               wfProfileOut( $fname.'-parseropt' );
+               wfProfileIn( $fname.'-parser' );
+               $this->mParser = new Parser;
+               wfProfileOut( $fname.'-parser' );
+
+               # When we first get asked for a message,
+               # then we'll fill up the cache. If we
+               # can return a cache hit, this saves
+               # some extra milliseconds
+               $this->mDeferred = true;
+
+               wfProfileOut( $fname );
+       }
+
+       /**
+        * Loads messages either from memcached or the database, if not disabled
+        * On error, quietly switches to a fallback mode
+        * Returns false for a reportable error, true otherwise
+        */
+       function load() {
+               global $wgAllMessagesEn;
+
+               if ( $this->mDisable ) {
+                       static $shownDisabled = false;
+                       if ( !$shownDisabled ) {
+                               wfDebug( "MessageCache::load(): disabled\n" );
+                               $shownDisabled = true;
+                       }
+                       return true;
+               }
+               $fname = 'MessageCache::load';
+               wfProfileIn( $fname );
+               $success = true;
+
+               if ( $this->mUseCache ) {
+                       wfProfileIn( $fname.'-fromcache' );
+                       $this->mCache = $this->mMemc->get( $this->mMemcKey );
+                       wfProfileOut( $fname.'-fromcache' );
+
+                       # If there's nothing in memcached, load all the messages from the database
+                       if ( !$this->mCache ) {
+                               wfDebug( "MessageCache::load(): loading all messages\n" );
+                               $this->lock();
+                               # Other threads don't need to load the messages if another thread is doing it.
+                               $success = $this->mMemc->add( $this->mMemcKey.'-status', "loading", MSG_LOAD_TIMEOUT );
+                               if ( $success ) {
+                                       wfProfileIn( $fname.'-load' );
+                                       $this->loadFromDB();
+                                       wfProfileOut( $fname.'-load' );
+                                       # Save in memcached
+                                       # Keep trying if it fails, this is kind of important
+                                       wfProfileIn( $fname.'-save' );
+                                       for ($i=0; $i<20 &&
+                                                  !$this->mMemc->set( $this->mMemcKey, $this->mCache, $this->mExpiry );
+                                            $i++ ) {
+                                               usleep(mt_rand(500000,1500000));
+                                       }
+                                       wfProfileOut( $fname.'-save' );
+                                       if ( $i == 20 ) {
+                                               $this->mMemc->set( $this->mMemcKey.'-status', 'error', 60*5 );
+                                               wfDebug( "MemCached set error in MessageCache: restart memcached server!\n" );
+                                       }
+                               }
+                               $this->unlock();
+                       }
+
+                       if ( !is_array( $this->mCache ) ) {
+                               wfDebug( "MessageCache::load(): individual message mode\n" );
+                               # If it is 'loading' or 'error', switch to individual message mode, otherwise disable
+                               # Causing too much DB load, disabling -- TS
+                               $this->mDisable = true;
+                               /*
+                               if ( $this->mCache == "loading" ) {
+                                       $this->mUseCache = false;
+                               } elseif ( $this->mCache == "error" ) {
+                                       $this->mUseCache = false;
+                                       $success = false;
+                               } else {
+                                       $this->mDisable = true;
+                                       $success = false;
+                               }*/
+                               $this->mCache = false;
+                       }
+               }
+               wfProfileOut( $fname );
+               $this->mDeferred = false;
+               return $success;
+       }
+
+       /**
+        * Loads all or main part of cacheable messages from the database
+        */
+       function loadFromDB() {
+               $fname = 'MessageCache::loadFromDB';
+               $dbr =& wfGetDB( DB_SLAVE );
+               $conditions = array( 'page_is_redirect' => 0,
+                                       'page_namespace' => NS_MEDIAWIKI);
+               $res = $dbr->select( array( 'page', 'revision', 'text' ),
+                       array( 'page_title', 'old_text', 'old_flags' ),
+                       'page_is_redirect=0 AND page_namespace='.NS_MEDIAWIKI.' AND page_latest=rev_id AND rev_text_id=old_id',
+                       $fname
+               );
+
+               $this->mCache = array();
+               for ( $row = $dbr->fetchObject( $res ); $row; $row = $dbr->fetchObject( $res ) ) {
+                       $this->mCache[$row->page_title] = Revision::getRevisionText( $row );
+               }
+
+               $dbr->freeResult( $res );
+               /*
+               # FIXME: This is too slow currently.
+               # We need to bulk-fetch revisions, but in a portable way...
+               $resultSet = Revision::fetchFromConds( $dbr, array(
+                       'page_namespace'   => NS_MEDIAWIKI,
+                       'page_is_redirect' => 0,
+                       'page_id=rev_page' ) );
+               while( $row = $resultSet->fetchObject() ) {
+                       $revision = new Revision( $row );
+                       $title = $revision->getTitle();
+                       $this->mCache[$title->getDBkey()] = $revision->getText();
+               }
+               $resultSet->free();
+               */
+       }
+
+       /**
+        * Not really needed anymore
+        */
+       function getKeys() {
+               global $wgAllMessagesEn, $wgContLang;
+               if ( !$this->mKeys ) {
+                       $this->mKeys = array();
+                       foreach ( $wgAllMessagesEn as $key => $value ) {
+                               $title = $wgContLang->ucfirst( $key );
+                               array_push( $this->mKeys, $title );
+                       }
+               }
+               return $this->mKeys;
+       }
+
+       /**
+        * @deprecated
+        */
+       function isCacheable( $key ) {
+               return true;
+       }
+
+       function replace( $title, $text ) {
+               $this->lock();
+               $this->load();
+               if ( is_array( $this->mCache ) ) {
+                       $this->mCache[$title] = $text;
+                       $this->mMemc->set( $this->mMemcKey, $this->mCache, $this->mExpiry );
+               }
+               $this->unlock();
+       }
+
+       /**
+        * Returns success
+        * Represents a write lock on the messages key
+        */
+       function lock() {
+               if ( !$this->mUseCache ) {
+                       return true;
+               }
+
+               $lockKey = $this->mMemcKey . 'lock';
+               for ($i=0; $i < MSG_WAIT_TIMEOUT && !$this->mMemc->add( $lockKey, 1, MSG_LOCK_TIMEOUT ); $i++ ) {
+                       sleep(1);
+               }
+
+               return $i >= MSG_WAIT_TIMEOUT;
+       }
+
+       function unlock() {
+               if ( !$this->mUseCache ) {
+                       return;
+               }
+
+               $lockKey = $this->mMemcKey . 'lock';
+               $this->mMemc->delete( $lockKey );
+       }
+
+       function get( $key, $useDB, $forcontent=true, $isfullkey = false ) {
+               global $wgContLanguageCode;
+               if( $forcontent ) {
+                       global $wgContLang;
+                       $lang =& $wgContLang;
+                       $langcode = $wgContLanguageCode;
+               } else {
+                       global $wgLang, $wgLanguageCode;
+                       $lang =& $wgLang;
+                       $langcode = $wgLanguageCode;
+               }
+               # If uninitialised, someone is trying to call this halfway through Setup.php
+               if( !$this->mInitialised ) {
+                       return '&lt;' . htmlspecialchars($key) . '&gt;';
+               }
+               # If cache initialization was deferred, start it now.
+               if( $this->mDeferred ) {
+                       $this->load();
+               }
+
+               $message = false;
+               if( !$this->mDisable && $useDB ) {
+                       $title = $lang->ucfirst( $key );
+                       if(!$isfullkey && ($langcode != $wgContLanguageCode) ) {
+                               $title .= '/' . $langcode;
+                       }
+                       $message = $this->getFromCache( $title );
+               }
+               # Try the extension array
+               if( !$message ) {
+                       $message = @$this->mExtensionMessages[$key];
+               }
+
+               # Try the array in the language object
+               if( !$message ) {
+                       wfSuppressWarnings();
+                       $message = $lang->getMessage( $key );
+                       wfRestoreWarnings();
+               }
+
+               # Try the English array
+               if( !$message && $langcode != 'en' ) {
+                       wfSuppressWarnings();
+                       $message = Language::getMessage( $key );
+                       wfRestoreWarnings();
+               }
+
+               # Is this a custom message? Try the default language in the db...
+               if( !$message &&
+                       !$this->mDisable && $useDB &&
+                       !$isfullkey && ($langcode != $wgContLanguageCode) ) {
+                       $message = $this->getFromCache( $lang->ucfirst( $key ) );
+               }
+
+               # Final fallback
+               if( !$message ) {
+                       return '&lt;' . htmlspecialchars($key) . '&gt;';
+               }
+
+               # Replace brace tags
+               $message = $this->transform( $message );
+               return $message;
+       }
+
+       function getFromCache( $title ) {
+               $message = false;
+
+               # Try the cache
+               if( $this->mUseCache && is_array( $this->mCache ) && array_key_exists( $title, $this->mCache ) ) {
+                       $message = $this->mCache[$title];
+               }
+
+               if ( !$message && $this->mUseCache ) {
+                       $message = $this->mMemc->get( $this->mMemcKey . ':' . $title );
+                       if( $message ) {
+                               $this->mCache[$title] = $message;
+                       }
+               }
+
+               # Call message Hooks, in case they are defined
+               wfRunHooks('MessagesPreLoad',array($title,&$message));
+
+               # If it wasn't in the cache, load each message from the DB individually
+               if ( !$message ) {
+                       $revision = Revision::newFromTitle( Title::makeTitle( NS_MEDIAWIKI, $title ) );
+                       if( $revision ) {
+                               $message = $revision->getText();
+                               if ($this->mUseCache) {
+                                       $this->mCache[$title]=$message;
+                                       /* individual messages may be often
+                                          recached until proper purge code exists
+                                       */
+                                       $this->mMemc->set( $this->mMemcKey . ':' . $title, $message, 300 );
+                               }
+                       }
+               }
+
+               return $message;
+       }
+
+       function transform( $message ) {
+               if( !$this->mDisableTransform ) {
+                       if( strpos( $message, '{{' ) !== false ) {
+                               $message = $this->mParser->transformMsg( $message, $this->mParserOptions );
+                       }
+               }
+               return $message;
+       }
+
+       function disable() { $this->mDisable = true; }
+       function enable() { $this->mDisable = false; }
+       function disableTransform() { $this->mDisableTransform = true; }
+       function enableTransform() { $this->mDisableTransform = false; }
+
+       /**
+        * Add a message to the cache
+        *
+        * @param mixed $key
+        * @param mixed $value
+        */
+       function addMessage( $key, $value ) {
+               $this->mExtensionMessages[$key] = $value;
+       }
+
+       /**
+        * Add an associative array of message to the cache
+        *
+        * @param array $messages An associative array of key => values to be added
+        */
+       function addMessages( $messages ) {
+               foreach ( $messages as $key => $value ) {
+                       $this->addMessage( $key, $value );
+               }
+       }
+
+       /**
+        * Clear all stored messages. Mainly used after a mass rebuild.
+        */
+       function clear() {
+               if( $this->mUseCache ) {
+                       $this->mMemc->delete( $this->mMemcKey );
+               }
+       }
+}
+?>
diff --git a/includes/Metadata.php b/includes/Metadata.php
new file mode 100644 (file)
index 0000000..c60fe43
--- /dev/null
@@ -0,0 +1,362 @@
+<?php
+/**
+ * Metadata.php -- provides DublinCore and CreativeCommons metadata
+ * Copyright 2004, Evan Prodromou <evan@wikitravel.org>.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @author Evan Prodromou <evan@wikitravel.org>
+ * @package MediaWiki
+ */
+
+/**
+ *
+ */
+define('RDF_TYPE_PREFS', "application/rdf+xml,text/xml;q=0.7,application/xml;q=0.5,text/rdf;q=0.1");
+
+function wfDublinCoreRdf($article) {
+
+       $url = dcReallyFullUrl($article->mTitle);
+
+       if (rdfSetup()) {
+               dcPrologue($url);
+               dcBasics($article);
+               dcEpilogue();
+       }
+}
+
+function wfCreativeCommonsRdf($article) {
+
+       if (rdfSetup()) {
+               global $wgRightsUrl;
+
+               $url = dcReallyFullUrl($article->mTitle);
+
+               ccPrologue();
+               ccSubPrologue('Work', $url);
+               dcBasics($article);
+               if (isset($wgRightsUrl)) {
+                       $url = htmlspecialchars( $wgRightsUrl );
+                       print "    <cc:license rdf:resource=\"$url\" />\n";
+               }
+
+               ccSubEpilogue('Work');
+
+               if (isset($wgRightsUrl)) {
+                       $terms = ccGetTerms($wgRightsUrl);
+                       if ($terms) {
+                               ccSubPrologue('License', $wgRightsUrl);
+                               ccLicense($terms);
+                               ccSubEpilogue('License');
+                       }
+               }
+       }
+
+       ccEpilogue();
+}
+
+/**
+ * @private
+ */
+function rdfSetup() {
+       global $wgOut, $wgRdfMimeType, $_SERVER;
+
+       $rdftype = wfNegotiateType(wfAcceptToPrefs($_SERVER['HTTP_ACCEPT']), wfAcceptToPrefs(RDF_TYPE_PREFS));
+
+       if (!$rdftype) {
+               wfHttpError(406, "Not Acceptable", wfMsg("notacceptable"));
+               return false;
+       } else {
+               $wgOut->disable();
+               header( "Content-type: {$rdftype}" );
+               $wgOut->sendCacheControl();
+               return true;
+       }
+}
+
+/**
+ * @private
+ */
+function dcPrologue($url) {
+       global $wgOutputEncoding;
+
+       $url = htmlspecialchars( $url );
+       print "<" . "?xml version=\"1.0\" encoding=\"{$wgOutputEncoding}\" ?" . ">
+
+                                                                                                                                                         <!DOCTYPE rdf:RDF PUBLIC \"-//DUBLIN CORE//DCMES DTD 2002/07/31//EN\" \"http://dublincore.org/documents/2002/07/31/dcmes-xml/dcmes-xml-dtd.dtd\">
+
+                                                                                                                                                         <rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"
+                                                                                                                                                         xmlns:dc=\"http://purl.org/dc/elements/1.1/\">
+                                                                                                                                                         <rdf:Description rdf:about=\"$url\">
+                                                                                                                                                         ";
+}
+
+/**
+ * @private
+ */
+function dcEpilogue() {
+       print "
+                       </rdf:Description>
+                       </rdf:RDF>
+                       ";
+}
+
+/**
+ * @private
+ */
+function dcBasics($article) {
+       global $wgContLanguageCode, $wgSitename;
+
+       dcElement('title', $article->mTitle->getText());
+       dcPageOrString('publisher', wfMsg('aboutpage'), $wgSitename);
+       dcElement('language', $wgContLanguageCode);
+       dcElement('type', 'Text');
+       dcElement('format', 'text/html');
+       dcElement('identifier', dcReallyFullUrl($article->mTitle));
+       dcElement('date', dcDate($article->getTimestamp()));
+
+       $last_editor = $article->getUser();
+
+       if ($last_editor == 0) {
+               dcPerson('creator', 0);
+       } else {
+               dcPerson('creator', $last_editor, $article->getUserText(),
+                                User::whoIsReal($last_editor));
+       }
+
+       $contributors = $article->getContributors();
+
+       foreach ($contributors as $user_parts) {
+               dcPerson('contributor', $user_parts[0], $user_parts[1], $user_parts[2]);
+       }
+
+       dcRights($article);
+}
+
+/**
+ * @private
+ */
+function ccPrologue() {
+       global $wgOutputEncoding;
+
+       echo "<" . "?xml version='1.0'  encoding='{$wgOutputEncoding}' ?" . ">
+
+                                                                                                                                                 <rdf:RDF xmlns:cc=\"http://web.resource.org/cc/\"
+                                                                                                                                                 xmlns:dc=\"http://purl.org/dc/elements/1.1/\"
+                                                                                                                                                 xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">
+                                                                                                                                                 ";
+}
+
+/**
+ * @private
+ */
+function ccSubPrologue($type, $url) {
+       $url = htmlspecialchars( $url );
+       echo "  <cc:{$type} rdf:about=\"{$url}\">\n";
+}
+
+/**
+ * @private
+ */
+function ccSubEpilogue($type) {
+       echo "  </cc:{$type}>\n";
+}
+
+/**
+ * @private
+ */
+function ccLicense($terms) {
+
+       foreach ($terms as $term) {
+               switch ($term) {
+                case 're':
+                       ccTerm('permits', 'Reproduction'); break;
+                case 'di':
+                       ccTerm('permits', 'Distribution'); break;
+                case 'de':
+                       ccTerm('permits', 'DerivativeWorks'); break;
+                case 'nc':
+                       ccTerm('prohibits', 'CommercialUse'); break;
+                case 'no':
+                       ccTerm('requires', 'Notice'); break;
+                case 'by':
+                       ccTerm('requires', 'Attribution'); break;
+                case 'sa':
+                       ccTerm('requires', 'ShareAlike'); break;
+                case 'sc':
+                       ccTerm('requires', 'SourceCode'); break;
+               }
+       }
+}
+
+/**
+ * @private
+ */
+function ccTerm($term, $name) {
+       print "    <cc:{$term} rdf:resource=\"http://web.resource.org/cc/{$name}\" />\n";
+}
+
+/**
+ * @private
+ */
+function ccEpilogue() {
+       echo "</rdf:RDF>\n";
+}
+
+/**
+ * @private
+ */
+function dcElement($name, $value) {
+       $value = htmlspecialchars( $value );
+       print "    <dc:{$name}>{$value}</dc:{$name}>\n";
+}
+
+/**
+ * @private
+ */
+function dcDate($timestamp) {
+       return substr($timestamp, 0, 4) . '-'
+         . substr($timestamp, 4, 2) . '-'
+         . substr($timestamp, 6, 2);
+}
+
+/**
+ * @private
+ */
+function dcReallyFullUrl($title) {
+       return $title->getFullURL();
+}
+
+/**
+ * @private
+ */
+function dcPageOrString($name, $page, $str) {
+       $nt = Title::newFromText($page);
+
+       if (!$nt || $nt->getArticleID() == 0) {
+               dcElement($name, $str);
+       } else {
+               dcPage($name, $nt);
+       }
+}
+
+/**
+ * @private
+ */
+function dcPage($name, $title) {
+       dcUrl($name, dcReallyFullUrl($title));
+}
+
+/**
+ * @private
+ */
+function dcUrl($name, $url) {
+       $url = htmlspecialchars( $url );
+       print "    <dc:{$name} rdf:resource=\"{$url}\" />\n";
+}
+
+/**
+ * @private
+ */
+function dcPerson($name, $id, $user_name='', $user_real_name='') {
+       global $wgContLang;
+
+       if ($id == 0) {
+               dcElement($name, wfMsg('anonymous'));
+       } else if ( !empty($user_real_name) ) {
+               dcElement($name, $user_real_name);
+       } else {
+               # XXX: This shouldn't happen.
+               if( empty( $user_name ) ) {
+                       $user_name = User::whoIs($id);
+               }
+               dcPageOrString($name, $wgContLang->getNsText(NS_USER) . ':' . $user_name, wfMsg('siteuser', $user_name));
+       }
+}
+
+/**
+ * Takes an arg, for future enhancement with different rights for
+ * different pages.
+ * @private
+ */
+function dcRights($article) {
+
+       global $wgRightsPage, $wgRightsUrl, $wgRightsText;
+
+       if (isset($wgRightsPage) &&
+               ($nt = Title::newFromText($wgRightsPage))
+               && ($nt->getArticleID() != 0)) {
+               dcPage('rights', $nt);
+       } else if (isset($wgRightsUrl)) {
+               dcUrl('rights', $wgRightsUrl);
+       } else if (isset($wgRightsText)) {
+               dcElement('rights', $wgRightsText);
+       }
+}
+
+/**
+ * @private
+ */
+function ccGetTerms($url) {
+       global $wgLicenseTerms;
+
+       if (isset($wgLicenseTerms)) {
+               return $wgLicenseTerms;
+       } else {
+               $known = getKnownLicenses();
+               return $known[$url];
+       }
+}
+
+/**
+ * @private
+ */
+function getKnownLicenses() {
+
+       $ccLicenses = array('by', 'by-nd', 'by-nd-nc', 'by-nc',
+                                               'by-nc-sa', 'by-sa');
+       $ccVersions = array('1.0', '2.0');
+       $knownLicenses = array();
+
+       foreach ($ccVersions as $version) {
+               foreach ($ccLicenses as $license) {
+                       if( $version == '2.0' && substr( $license, 0, 2) != 'by' ) {
+                               # 2.0 dropped the non-attribs licenses
+                               continue;
+                       }
+                       $lurl = "http://creativecommons.org/licenses/{$license}/{$version}/";
+                       $knownLicenses[$lurl] = explode('-', $license);
+                       $knownLicenses[$lurl][] = 're';
+                       $knownLicenses[$lurl][] = 'di';
+                       $knownLicenses[$lurl][] = 'no';
+                       if (!in_array('nd', $knownLicenses[$lurl])) {
+                               $knownLicenses[$lurl][] = 'de';
+                       }
+               }
+       }
+
+       /* Handle the GPL and LGPL, too. */
+
+       $knownLicenses['http://creativecommons.org/licenses/GPL/2.0/'] =
+         array('de', 're', 'di', 'no', 'sa', 'sc');
+       $knownLicenses['http://creativecommons.org/licenses/LGPL/2.1/'] =
+         array('de', 're', 'di', 'no', 'sa', 'sc');
+       $knownLicenses['http://www.gnu.org/copyleft/fdl.html'] =
+         array('de', 're', 'di', 'no', 'sa', 'sc');
+
+       return $knownLicenses;
+}
+
+?>
diff --git a/includes/MimeMagic.php b/includes/MimeMagic.php
new file mode 100644 (file)
index 0000000..31f57d0
--- /dev/null
@@ -0,0 +1,686 @@
+<?php
+/** Module defining helper functions for detecting and dealing with mime types.
+ *
+ * @package MediaWiki
+ */
+
+ /** Defines a set of well known mime types
+ * This is used as a fallback to mime.types files.
+ * An extensive list of well known mime types is provided by 
+ * the file mime.types in the includes directory.
+ */
+define('MM_WELL_KNOWN_MIME_TYPES',<<<END_STRING
+application/ogg ogg ogm
+application/pdf pdf
+application/x-javascript js
+application/x-shockwave-flash swf
+audio/midi mid midi kar
+audio/mpeg mpga mpa mp2 mp3
+audio/x-aiff aif aiff aifc
+audio/x-wav wav
+audio/ogg ogg
+image/x-bmp bmp
+image/gif gif
+image/jpeg jpeg jpg jpe
+image/png png
+image/svg+xml svg
+image/tiff tiff tif
+text/plain txt
+text/html html htm 
+video/ogg ogm ogg
+video/mpeg mpg mpeg
+END_STRING
+);
+
+ /** Defines a set of well known mime info entries
+ * This is used as a fallback to mime.info files.
+ * An extensive list of well known mime types is provided by 
+ * the file mime.info in the includes directory.
+ */
+define('MM_WELL_KNOWN_MIME_INFO', <<<END_STRING
+application/pdf [OFFICE]
+text/javascript application/x-javascript [EXECUTABLE]
+application/x-shockwave-flash [MULTIMEDIA]
+audio/midi [AUDIO]
+audio/x-aiff [AUDIO]
+audio/x-wav [AUDIO]
+audio/mp3 audio/mpeg [AUDIO]
+application/ogg audio/ogg video/ogg [MULTIMEDIA]
+image/x-bmp image/bmp [BITMAP]
+image/gif [BITMAP]
+image/jpeg [BITMAP]
+image/png [BITMAP]
+image/svg image/svg+xml [DRAWING]
+image/tiff [BITMAP]
+text/plain [TEXT]
+text/html [TEXT]
+video/ogg [VIDEO]
+video/mpeg [VIDEO]
+unknown/unknown application/octet-stream application/x-empty [UNKNOWN]
+END_STRING
+);
+
+#note: because this file is possibly included by a function, 
+#we need to access the global scope explicitely!
+global $wgLoadFileinfoExtension;
+
+if ($wgLoadFileinfoExtension) { 
+       if(!extension_loaded('fileinfo')) dl('fileinfo.' . PHP_SHLIB_SUFFIX);
+}
+
+/** Implements functions related to mime types such as detection and mapping to 
+* file extension,
+*
+* Instances of this class are stateles, there only needs to be one global instance
+* of MimeMagic. Please use wfGetMimeMagic to get that instance. 
+* @package MediaWiki
+*/
+class MimeMagic {
+       
+       /**
+       * Mapping of media types to arrays of mime types.
+       * This is used by findMediaType and getMediaType, respectively
+       */
+       var $mMediaTypes= NULL; 
+       
+       /** Map of mime type aliases
+       */
+       var $mMimeTypeAliases= NULL;
+       
+       /** map of mime types to file extensions (as a space seprarated list)
+       */
+       var $mMimeToExt= NULL; 
+       
+       /** map of file extensions types to mime types (as a space seprarated list)
+       */
+       var $mExtToMime= NULL; 
+       
+       /** Initializes the MimeMagic object. This is called by wfGetMimeMagic when instantiation 
+       * the global MimeMagic singleton object.
+       *
+       * This constructor parses the mime.types and mime.info files and build internal mappings.
+       */
+       function MimeMagic() {
+               /*
+               *   --- load mime.types ---
+               */
+               
+               global $wgMimeTypeFile;
+               
+               $types= MM_WELL_KNOWN_MIME_TYPES;
+               
+               if ($wgMimeTypeFile) {
+                       if (is_file($wgMimeTypeFile) and is_readable($wgMimeTypeFile)) {
+                               wfDebug("MimeMagic::MimeMagic: loading mime types from $wgMimeTypeFile\n");
+                       
+                               $types.= "\n";
+                               $types.= file_get_contents($wgMimeTypeFile);
+                       }
+                       else wfDebug("MimeMagic::MimeMagic: can't load mime types from $wgMimeTypeFile\n");
+               }
+               else wfDebug("MimeMagic::MimeMagic: no mime types file defined, using build-ins only.\n");
+               
+               $types= str_replace(array("\r\n","\n\r","\n\n","\r\r","\r"),"\n",$types);
+               $types= str_replace("\t"," ",$types);
+               
+               $this->mMimeToExt= array();
+               $this->mToMime= array();
+               
+               $lines= explode("\n",$types);
+               foreach ($lines as $s) {
+                       $s= trim($s);
+                       if (empty($s)) continue;
+                       if (strpos($s,'#')===0) continue;
+                       
+                       $s= strtolower($s);
+                       $i= strpos($s,' ');
+                       
+                       if ($i===false) continue;
+                       
+                       #print "processing MIME line $s<br>";
+                       
+                       $mime= substr($s,0,$i);
+                       $ext= trim(substr($s,$i+1));
+                       
+                       if (empty($ext)) continue;
+                       
+                       if (@$this->mMimeToExt[$mime]) $this->mMimeToExt[$mime] .= ' '.$ext;
+                       else $this->mMimeToExt[$mime]= $ext;
+                       
+                       $extensions= explode(' ',$ext);
+                       
+                       foreach ($extensions as $e) {
+                               $e= trim($e);
+                               if (empty($e)) continue;
+                               
+                               if (@$this->mExtToMime[$e]) $this->mExtToMime[$e] .= ' '.$mime;
+                               else $this->mExtToMime[$e]= $mime;
+                       }
+               }
+       
+               /*
+               *   --- load mime.info ---
+               */
+               
+               global $wgMimeInfoFile;
+               
+               $info= MM_WELL_KNOWN_MIME_INFO;
+               
+               if ($wgMimeInfoFile) {
+                       if (is_file($wgMimeInfoFile) and is_readable($wgMimeInfoFile)) {
+                               wfDebug("MimeMagic::MimeMagic: loading mime info from $wgMimeInfoFile\n");
+                       
+                               $info.= "\n";
+                               $info.= file_get_contents($wgMimeInfoFile);
+                       }
+                       else wfDebug("MimeMagic::MimeMagic: can't load mime info from $wgMimeInfoFile\n");
+               }
+               else wfDebug("MimeMagic::MimeMagic: no mime info file defined, using build-ins only.\n");
+               
+               $info= str_replace(array("\r\n","\n\r","\n\n","\r\r","\r"),"\n",$info);
+               $info= str_replace("\t"," ",$info);
+               
+               $this->mMimeTypeAliases= array();
+               $this->mMediaTypes= array();
+               
+               $lines= explode("\n",$info);
+               foreach ($lines as $s) {
+                       $s= trim($s);
+                       if (empty($s)) continue;
+                       if (strpos($s,'#')===0) continue;
+                       
+                       $s= strtolower($s);
+                       $i= strpos($s,' ');
+                       
+                       if ($i===false) continue;
+                       
+                       #print "processing MIME INFO line $s<br>";
+                       
+                       $match= array();
+                       if (preg_match('!\[\s*(\w+)\s*\]!',$s,$match)) {
+                               $s= preg_replace('!\[\s*(\w+)\s*\]!','',$s);
+                               $mtype= trim(strtoupper($match[1]));
+                       }
+                       else $mtype= MEDIATYPE_UNKNOWN;
+                       
+                       $m= explode(' ',$s);
+                       
+                       if (!isset($this->mMediaTypes[$mtype])) $this->mMediaTypes[$mtype]= array();
+                       
+                       foreach ($m as $mime) {
+                               $mime= trim($mime);
+                               if (empty($mime)) continue;
+                               
+                               $this->mMediaTypes[$mtype][]= $mime;
+                       }
+                       
+                       if (sizeof($m)>1) {
+                               $main= $m[0];
+                               for ($i=1; $i<sizeof($m); $i+= 1) {
+                                       $mime= $m[$i];
+                                       $this->mMimeTypeAliases[$mime]= $main;
+                               }
+                       }
+               }
+               
+       }
+       
+       /** returns a list of file extensions for a given mime type
+       * as a space separated string.
+       */
+       function getExtensionsForType($mime) {
+               $mime= strtolower($mime);
+               
+               $r= @$this->mMimeToExt[$mime];
+               
+               if (@!$r and isset($this->mMimeTypeAliases[$mime])) {
+                       $mime= $this->mMimeTypeAliases[$mime];
+                       $r= @$this->mMimeToExt[$mime];
+               }
+               
+               return $r;
+       }
+       
+       /** returns a list of mime types for a given file extension
+       * as a space separated string.
+       */
+       function getTypesForExtension($ext) {
+               $ext= strtolower($ext);
+               
+               $r= @$this->mExtToMime[$ext];
+               return $r;
+       }
+       
+       /** returns a single mime type for a given file extension.
+       * This is always the first type from the list returned by getTypesForExtension($ext).
+       */
+       function guessTypesForExtension($ext) {
+               $m= $this->getTypesForExtension( $ext );
+               if( is_null($m) ) return NULL;
+               
+               $m= trim( $m );
+               $m= preg_replace('/\s.*$/','',$m);
+               
+               return $m;
+       }
+       
+       
+       /** tests if the extension matches the given mime type.
+       * returns true if a match was found, NULL if the mime type is unknown, 
+       * and false if the mime type is known but no matches where found.
+       */
+       function isMatchingExtension($extension,$mime) {
+               $ext= $this->getExtensionsForType($mime);
+               
+               if (!$ext) {
+                       return NULL;  //unknown
+               }
+               
+               $ext= explode(' ',$ext);
+               
+               $extension= strtolower($extension);
+               if (in_array($extension,$ext)) {
+                       return true;
+               }
+               
+               return false;
+       }
+       
+       /** returns true if the mime type is known to represent
+       * an image format supported by the PHP GD library.
+       */
+       function isPHPImageType( $mime ) {
+               #as defined by imagegetsize and image_type_to_mime
+               static $types = array( 
+                       'image/gif', 'image/jpeg', 'image/png', 
+                       'image/x-bmp', 'image/xbm', 'image/tiff',
+                       'image/jp2', 'image/jpeg2000', 'image/iff', 
+                       'image/xbm', 'image/x-xbitmap',
+                       'image/vnd.wap.wbmp', 'image/vnd.xiff', 
+                       'image/x-photoshop',
+                       'application/x-shockwave-flash',
+               ); 
+               
+               return in_array( $mime, $types );
+       }
+       
+       /**
+        * Returns true if the extension represents a type which can
+        * be reliably detected from its content. Use this to determine
+        * whether strict content checks should be applied to reject
+        * invalid uploads; if we can't identify the type we won't
+        * be able to say if it's invalid.
+        *
+        * @todo Be more accurate when using fancy mime detector plugins;
+        *       right now this is the bare minimum getimagesize() list.
+        * @return bool
+        */
+       function isRecognizableExtension( $extension ) {
+               static $types = array(
+                       'gif', 'jpeg', 'jpg', 'png', 'swf', 'psd',
+                       'bmp', 'tiff', 'tif', 'jpc', 'jp2',
+                       'jpx', 'jb2', 'swc', 'iff', 'wbmp',
+                       'xbm'
+               );
+               return in_array( strtolower( $extension ), $types );
+       }
+       
+       
+       /** mime type detection. This uses detectMimeType to detect the mim type of the file,
+       * but applies additional checks to determine some well known file formats that may be missed
+       * or misinterpreter by the default mime detection (namely xml based formats like XHTML or SVG).
+       *
+       * @param string $file The file to check
+       * @param bool $useExt switch for allowing to use the file extension to guess the mime type. true by default.
+       *
+       * @return string the mime type of $file
+       */
+       function guessMimeType( $file, $useExt=true ) {
+               $fname = 'MimeMagic::guessMimeType';
+               $mime= $this->detectMimeType($file,$useExt);
+               
+               // Read a chunk of the file
+               $f = fopen( $file, "rt" );
+               if( !$f ) return "unknown/unknown";
+               $head = fread( $f, 1024 );
+               fclose( $f );
+               
+               $sub4 =  substr( $head, 0, 4 );
+               if ( $sub4 == "\x01\x00\x09\x00" || $sub4 == "\xd7\xcd\xc6\x9a" ) {
+                       // WMF kill kill kill
+                       // Note that WMF may have a bare header, no magic number.
+                       // The former of the above two checks is theoretically prone to false positives
+                       $mime = "application/x-msmetafile";
+               }
+               
+               if (strpos($mime,"text/")===0 || $mime==="application/xml") {
+                       
+                       $xml_type= NULL;
+                       $script_type= NULL;
+                       
+                       /*
+                       * look for XML formats (XHTML and SVG)
+                       */
+                       if ($mime==="text/sgml" ||
+                           $mime==="text/plain" ||
+                           $mime==="text/html" ||
+                           $mime==="text/xml" ||
+                           $mime==="application/xml") {
+                       
+                               if (substr($head,0,5)=="<?xml") $xml_type= "ASCII"; 
+                               elseif (substr($head,0,8)=="\xef\xbb\xbf<?xml") $xml_type= "UTF-8"; 
+                               elseif (substr($head,0,10)=="\xfe\xff\x00<\x00?\x00x\x00m\x00l") $xml_type= "UTF-16BE"; 
+                               elseif (substr($head,0,10)=="\xff\xfe<\x00?\x00x\x00m\x00l\x00") $xml_type= "UTF-16LE"; 
+                               
+                               if ($xml_type) {
+                                       if ($xml_type!=="UTF-8" && $xml_type!=="ASCII") $head= iconv($xml_type,"ASCII//IGNORE",$head);
+                                       
+                                       $match= array();
+                                       $doctype= "";
+                                       $tag= "";
+                                       
+                                       if (preg_match('%<!DOCTYPE\s+[\w-]+\s+PUBLIC\s+["'."'".'"](.*?)["'."'".'"].*>%sim',$head,$match)) $doctype= $match[1];
+                                       if (preg_match('%<(\w+).*>%sim',$head,$match)) $tag= $match[1];
+                                       
+                                       #print "<br>ANALYSING $file ($mime): doctype= $doctype; tag= $tag<br>";
+                                       
+                                       if (strpos($doctype,"-//W3C//DTD SVG")===0) $mime= "image/svg";
+                                       elseif ($tag==="svg") $mime= "image/svg";
+                                       elseif (strpos($doctype,"-//W3C//DTD XHTML")===0) $mime= "text/html";
+                                       elseif ($tag==="html") $mime= "text/html";
+                                       
+                                       $test_more= false;
+                               }
+                       }
+                       
+                       /*
+                       * look for shell scripts
+                       */
+                       if (!$xml_type) {
+                               $script_type= NULL;
+                               
+                               #detect by shebang
+                               if (substr($head,0,2)=="#!") $script_type= "ASCII"; 
+                               elseif (substr($head,0,5)=="\xef\xbb\xbf#!") $script_type= "UTF-8"; 
+                               elseif (substr($head,0,7)=="\xfe\xff\x00#\x00!") $script_type= "UTF-16BE"; 
+                               elseif (substr($head,0,7)=="\xff\xfe#\x00!") $script_type= "UTF-16LE"; 
+                               
+                               if ($script_type) {
+                                       if ($script_type!=="UTF-8" && $script_type!=="ASCII") $head= iconv($script_type,"ASCII//IGNORE",$head);
+                                       
+                                       $match= array();
+                                       $prog= "";
+                                       
+                                       if (preg_match('%/?([^\s]+/)(w+)%sim',$head,$match)) $script= $match[2];
+                                       
+                                       $mime= "application/x-$prog";
+                               }
+                       }
+                       
+                       /*
+                       * look for PHP
+                       */
+                       if( !$xml_type && !$script_type ) {
+                       
+                               if( ( strpos( $head, '<?php' ) !== false ) || 
+                                   ( strpos( $head, '<? ' ) !== false ) ||
+                                   ( strpos( $head, "<?\n" ) !== false ) ||
+                                   ( strpos( $head, "<?\t" ) !== false ) ||
+                                   ( strpos( $head, "<?=" ) !== false ) ||
+                               
+                                   ( strpos( $head, "<\x00?\x00p\x00h\x00p" ) !== false ) || 
+                                   ( strpos( $head, "<\x00?\x00 " ) !== false ) ||
+                                   ( strpos( $head, "<\x00?\x00\n" ) !== false ) ||
+                                   ( strpos( $head, "<\x00?\x00\t" ) !== false ) ||
+                                   ( strpos( $head, "<\x00?\x00=" ) !== false ) ) {
+                                   
+                                       $mime= "application/x-php";
+                               }
+                       }
+                       
+               }
+               
+               if (isset($this->mMimeTypeAliases[$mime])) $mime= $this->mMimeTypeAliases[$mime];
+               
+               wfDebug("$fname: final mime type of $file: $mime\n");
+               return $mime;
+       }
+       
+       /** Internal mime type detection, please use guessMimeType() for application code instead. 
+       * Detection is done using an external program, if $wgMimeDetectorCommand is set.
+       * Otherwise, the fileinfo extension and mime_content_type are tried (in this order), if they are available. 
+       * If the dections fails and $useExt is true, the mime type is guessed from the file extension, using guessTypesForExtension. 
+       * If the mime type is still unknown, getimagesize is used to detect the mime type if the file is an image.
+       * If no mime type can be determined, this function returns "unknown/unknown".
+       *
+       * @param string $file The file to check
+       * @param bool $useExt switch for allowing to use the file extension to guess the mime type. true by default.
+       *
+       * @return string the mime type of $file
+       * @private
+       */
+       function detectMimeType( $file, $useExt=true ) {
+               $fname = 'MimeMagic::detectMimeType';
+               
+               global $wgMimeDetectorCommand;
+       
+               $m= NULL;
+               if ($wgMimeDetectorCommand) {
+                       $fn= wfEscapeShellArg($file);
+                       $m= `$wgMimeDetectorCommand $fn`;
+               }
+               else if (function_exists("finfo_open") && function_exists("finfo_file")) {
+               
+                       # This required the fileinfo extension by PECL,
+                       # see http://pecl.php.net/package/fileinfo
+                       # This must be compiled into PHP
+                       #
+                       # finfo is the official replacement for the deprecated 
+                       # mime_content_type function, see below.
+                       #
+                       # If you may need to load the fileinfo extension at runtime, set
+                       # $wgLoadFileinfoExtension in LocalSettings.php
+               
+                       $mime_magic_resource = finfo_open(FILEINFO_MIME); /* return mime type ala mimetype extension */
+                       
+                       if ($mime_magic_resource) {
+                               $m= finfo_file($mime_magic_resource, $file);
+                               
+                               finfo_close($mime_magic_resource);
+                       }
+                       else wfDebug("$fname: finfo_open failed on ".FILEINFO_MIME."!\n");
+               }
+               else if (function_exists("mime_content_type")) { 
+                       
+                       # NOTE: this function is available since PHP 4.3.0, but only if
+                       # PHP was compiled with --with-mime-magic or, before 4.3.2, with --enable-mime-magic.
+                       #
+                       # On Winodws, you must set mime_magic.magicfile in php.ini to point to the mime.magic file bundeled with PHP;
+                       # sometimes, this may even be needed under linus/unix.
+                       #
+                       # Also note that this has been DEPRECATED in favor of the fileinfo extension by PECL, see above.
+                       # see http://www.php.net/manual/en/ref.mime-magic.php for details.
+                       
+                       $m= mime_content_type($file);
+               }
+               else wfDebug("$fname: no magic mime detector found!\n");
+       
+               if ($m) { 
+                       #normalize
+                       $m= preg_replace('![;, ].*$!','',$m); #strip charset, etc
+                       $m= trim($m);
+                       $m= strtolower($m);
+                       
+                       if (strpos($m,'unknown')!==false) $m= NULL;
+                       else {
+                               wfDebug("$fname: magic mime type of $file: $m\n");
+                               return $m;
+                       }
+               }
+                       
+               #if still not known, use getimagesize to find out the type of image
+               #TODO: skip things that do not have a well-known image extension? Would that be safe?
+               wfSuppressWarnings();
+               $gis = getimagesize( $file );
+               wfRestoreWarnings();
+               
+               $notAnImage= false;
+               
+               if ($gis && is_array($gis) && $gis[2]) {
+                       switch ($gis[2]) {
+                               case IMAGETYPE_GIF: $m= "image/gif"; break;
+                               case IMAGETYPE_JPEG: $m= "image/jpeg"; break;
+                               case IMAGETYPE_PNG: $m= "image/png"; break;
+                               case IMAGETYPE_SWF: $m= "application/x-shockwave-flash"; break;
+                               case IMAGETYPE_PSD: $m= "application/photoshop"; break;
+                               case IMAGETYPE_BMP: $m= "image/bmp"; break;
+                               case IMAGETYPE_TIFF_II: $m= "image/tiff"; break;
+                               case IMAGETYPE_TIFF_MM: $m= "image/tiff"; break;
+                               case IMAGETYPE_JPC: $m= "image"; break;
+                               case IMAGETYPE_JP2: $m= "image/jpeg2000"; break;
+                               case IMAGETYPE_JPX: $m= "image/jpeg2000"; break;
+                               case IMAGETYPE_JB2: $m= "image"; break;
+                               case IMAGETYPE_SWC: $m= "application/x-shockwave-flash"; break;
+                               case IMAGETYPE_IFF: $m= "image/vnd.xiff"; break;
+                               case IMAGETYPE_WBMP: $m= "image/vnd.wap.wbmp"; break;
+                               case IMAGETYPE_XBM: $m= "image/x-xbitmap"; break;
+                       }
+                       
+                       if ($m) {
+                               wfDebug("$fname: image mime type of $file: $m\n");
+                               return $m;
+                       }
+                       else $notAnImage= true;
+               }
+       
+               #if desired, look at extension as a fallback.
+               if ($useExt) {
+                       $i = strrpos( $file, '.' );
+                       $e= strtolower( $i ? substr( $file, $i + 1 ) : '' );
+                       
+                       $m= $this->guessTypesForExtension($e);
+                       
+                       #TODO: if $notAnImage is set, do not trust the file extension if 
+                       # the results is one of the image types that should have been recognized 
+                       # by getimagesize
+                       
+                       if ($m) {
+                               wfDebug("$fname: extension mime type of $file: $m\n");
+                               return $m;
+                       }
+               }
+               
+               #unknown type   
+               wfDebug("$fname: failed to guess mime type for $file!\n");
+               return "unknown/unknown";
+       }
+       
+       /**
+       * Determine the media type code for a file, using its mime type, name and possibly
+       * its contents.
+       *
+       * This function relies on the findMediaType(), mapping extensions and mime 
+       * types to media types.
+       *
+       * @todo analyse file if need be 
+       * @todo look at multiple extension, separately and together.
+       *
+       * @param string $path full path to the image file, in case we have to look at the contents 
+       *        (if null, only the mime type is used to determine the media type code).
+       * @param string $mime mime type. If null it will be guessed using guessMimeType.
+       * 
+       * @return (int?string?) a value to be used with the MEDIATYPE_xxx constants.
+       */
+       function getMediaType($path=NULL,$mime=NULL) {
+               if( !$mime && !$path ) return MEDIATYPE_UNKNOWN;
+               
+               #if mime type is unknown, guess it
+               if( !$mime ) $mime= $this->guessMimeType($path,false);
+
+               #special code for ogg - detect if it's video (theora),
+               #else label it as sound.
+               if( $mime=="application/ogg" && file_exists($path) ) {
+               
+                       // Read a chunk of the file
+                       $f = fopen( $path, "rt" );
+                       if( !$f ) return MEDIATYPE_UNKNOWN;
+                       $head = fread( $f, 256 );
+                       fclose( $f );
+                       
+                       $head= strtolower( $head );
+                       
+                       #This is an UGLY HACK, file should be parsed correctly
+                       if( strpos($head,'theora')!==false ) return MEDIATYPE_VIDEO;
+                       elseif( strpos($head,'vorbis')!==false ) return MEDIATYPE_AUDIO;
+                       elseif( strpos($head,'flac')!==false ) return MEDIATYPE_AUDIO;
+                       elseif( strpos($head,'speex')!==false ) return MEDIATYPE_AUDIO;
+                       else return MEDIATYPE_MULTIMEDIA;
+               }       
+       
+               #check for entry for full mime type
+               if( $mime ) {
+                       $type= $this->findMediaType($mime);
+                       if( $type!==MEDIATYPE_UNKNOWN ) return $type;
+               }
+               
+               #check for entry for file extension
+               $e= NULL;
+               if( $path ) {
+                       $i = strrpos( $path, '.' );
+                       $e= strtolower( $i ? substr( $path, $i + 1 ) : '' );
+                       
+                       #TODO: look at multi-extension if this fails, parse from full path
+                       
+                       $type= $this->findMediaType('.'.$e);
+                       if( $type!==MEDIATYPE_UNKNOWN ) return $type;
+               }
+               
+               #check major mime type
+               if( $mime ) {
+                       $i= strpos($mime,'/');
+                       if( $i !== false ) {
+                               $major= substr($mime,0,$i);
+                               $type= $this->findMediaType($major);
+                               if( $type!==MEDIATYPE_UNKNOWN ) return $type;
+                       }
+               }
+               
+               if( !$type ) $type= MEDIATYPE_UNKNOWN;
+               
+               return $type;
+       }
+       
+       /** returns a media code matching the given mime type or file extension.
+       * File extensions are represented by a string starting with a dot (.) to 
+       * distinguish them from mime types.
+       *
+       * This funktion relies on the mapping defined by $this->mMediaTypes
+       * @private
+       */
+       function findMediaType($extMime) {
+               
+               if (strpos($extMime,'.')===0) { #if it's an extension, look up the mime types
+                       $m= $this->getTypesForExtension(substr($extMime,1));
+                       if (!$m) return MEDIATYPE_UNKNOWN;
+                       
+                       $m= explode(' ',$m);
+               }
+               else { #normalize mime type
+                       if (isset($this->mMimeTypeAliases[$extMime])) {
+                               $extMime= $this->mMimeTypeAliases[$extMime];
+                       }
+                       
+                       $m= array($extMime);
+               }
+               
+               foreach ($m as $mime) {
+                       foreach ($this->mMediaTypes as $type => $codes) {
+                               if (in_array($mime,$codes,true)) return $type;
+                       }
+               }
+               
+               return MEDIATYPE_UNKNOWN;
+       }
+}
+
+?>
diff --git a/includes/Namespace.php b/includes/Namespace.php
new file mode 100644 (file)
index 0000000..d1d06ac
--- /dev/null
@@ -0,0 +1,130 @@
+<?php
+/**
+ * Provide things related to namespaces
+ * @package MediaWiki
+ */
+/**
+ * This is not a valid entry point, perform no further processing unless MEDIAWIKI is defined
+ */
+if( defined( 'MEDIAWIKI' ) ) {
+
+/**
+ * Definitions of the NS_ constants are in Defines.php
+ * @private
+ */
+$wgCanonicalNamespaceNames = array(
+       NS_MEDIA            => 'Media',
+       NS_SPECIAL          => 'Special',
+       NS_TALK             => 'Talk',
+       NS_USER             => 'User',
+       NS_USER_TALK        => 'User_talk',
+       NS_PROJECT          => 'Project',
+       NS_PROJECT_TALK     => 'Project_talk',
+       NS_IMAGE            => 'Image',
+       NS_IMAGE_TALK       => 'Image_talk',
+       NS_MEDIAWIKI        => 'MediaWiki',
+       NS_MEDIAWIKI_TALK   => 'MediaWiki_talk',
+       NS_TEMPLATE         => 'Template',
+       NS_TEMPLATE_TALK    => 'Template_talk',
+       NS_HELP             => 'Help',
+       NS_HELP_TALK        => 'Help_talk',
+       NS_CATEGORY         => 'Category',
+       NS_CATEGORY_TALK    => 'Category_talk',
+);
+
+if( is_array( $wgExtraNamespaces ) ) {
+       $wgCanonicalNamespaceNames = $wgCanonicalNamespaceNames + $wgExtraNamespaces;
+}
+
+/**
+ * This is a utility class with only static functions
+ * for dealing with namespaces that encodes all the
+ * "magic" behaviors of them based on index.  The textual
+ * names of the namespaces are handled by Language.php.
+ *
+ * These are synonyms for the names given in the language file
+ * Users and translators should not change them
+ *
+ * @package MediaWiki
+ */
+class Namespace {
+
+       /**
+        * Check if the given namespace might be moved
+        * @return bool
+        */
+       function isMovable( $index ) {
+               if ( $index < NS_MAIN || $index == NS_IMAGE  || $index == NS_CATEGORY ) { 
+                       return false; 
+               }
+               return true;
+       }
+
+       /**
+        * Check if the give namespace is a talk page
+        * @return bool
+        */
+       function isTalk( $index ) {
+               global $wgExtraNamespaces;
+               return ( $index == NS_TALK           || $index == NS_USER_TALK     ||
+                                $index == NS_PROJECT_TALK   || $index == NS_IMAGE_TALK    ||
+                                $index == NS_MEDIAWIKI_TALK || $index == NS_TEMPLATE_TALK ||
+                                $index == NS_HELP_TALK      || $index == NS_CATEGORY_TALK 
+                                ||  ( (isset($wgExtraNamespaces) && $index % 2) )
+                                );
+               
+       }
+
+       /**
+        * Get the talk namespace corresponding to the given index
+        */
+       function getTalk( $index ) {
+               if ( Namespace::isTalk( $index ) ) {
+                       return $index;
+               } else {
+                       # FIXME
+                       return $index + 1;
+               }
+       }
+
+       function getSubject( $index ) {
+               if ( Namespace::isTalk( $index ) ) {
+                       return $index - 1;
+               } else {
+                       return $index;
+               }
+       }
+
+       /**
+        * Returns the canonical (English Wikipedia) name for a given index
+        */
+       function getCanonicalName( $index ) {
+               global $wgCanonicalNamespaceNames;
+               return $wgCanonicalNamespaceNames[$index];
+       }
+
+       /**
+        * Returns the index for a given canonical name, or NULL
+        * The input *must* be converted to lower case first
+        */
+       function getCanonicalIndex( $name ) {
+               global $wgCanonicalNamespaceNames;
+               static $xNamespaces = false;
+               if ( $xNamespaces === false ) {
+                       $xNamespaces = array();
+                       foreach ( $wgCanonicalNamespaceNames as $i => $text ) {
+                               $xNamespaces[strtolower($text)] = $i;
+                       }
+               }
+               if ( array_key_exists( $name, $xNamespaces ) ) {
+                       return $xNamespaces[$name];
+               } else {
+                       return NULL;
+               }
+       }
+}
+
+}
+?>
diff --git a/includes/ObjectCache.php b/includes/ObjectCache.php
new file mode 100644 (file)
index 0000000..dbf6221
--- /dev/null
@@ -0,0 +1,126 @@
+<?php
+/**
+ * @package MediaWiki
+ * @subpackage Cache
+ */
+
+/** */
+if (!defined('MEDIAWIKI')) die( "Not a valid entry point\n");
+
+
+/**
+ * FakeMemCachedClient imitates the API of memcached-client v. 0.1.2.
+ * It acts as a memcached server with no RAM, that is, all objects are
+ * cleared the moment they are set. All set operations succeed and all
+ * get operations return null.
+ * @package MediaWiki
+ * @subpackage Cache
+ */
+class FakeMemCachedClient {
+       function add ($key, $val, $exp = 0) { return true; }
+       function decr ($key, $amt=1) { return null; }
+       function delete ($key, $time = 0) { return false; }
+       function disconnect_all () { }
+       function enable_compress ($enable) { }
+       function forget_dead_hosts () { }
+       function get ($key) { return null; }
+       function get_multi ($keys) { return array_pad(array(), count($keys), null); }
+       function incr ($key, $amt=1) { return null; }
+       function replace ($key, $value, $exp=0) { return false; }
+       function run_command ($sock, $cmd) { return null; }
+       function set ($key, $value, $exp=0){ return true; }
+       function set_compress_threshold ($thresh){ }
+       function set_debug ($dbg) { }
+       function set_servers ($list) { }
+}
+
+global $wgCaches;
+$wgCaches = array();
+
+/** @todo document */
+function &wfGetCache( $inputType ) {
+       global $wgCaches, $wgMemCachedServers, $wgMemCachedDebug;
+       $cache = false;
+
+       if ( $inputType == CACHE_ANYTHING ) {
+               reset( $wgCaches );
+               $type = key( $wgCaches );
+               if ( $type === false || $type === CACHE_NONE ) {
+                       $type = CACHE_DB;
+               }
+       } else {
+               $type = $inputType;
+       }
+
+       if ( $type == CACHE_MEMCACHED ) {
+               if ( !array_key_exists( CACHE_MEMCACHED, $wgCaches ) ){ 
+                       require_once( 'memcached-client.php' );
+                       
+                       if (!class_exists("MemcachedClientforWiki")) {
+                               class MemCachedClientforWiki extends memcached {
+                                       function _debugprint( $text ) {
+                                               wfDebug( "memcached: $text\n" );
+                                       }
+                               }
+                       }
+
+                       $wgCaches[CACHE_DB] = new MemCachedClientforWiki( 
+                               array('persistant' => false, 'compress_threshold' => 1500 ) );
+                       $cache =& $wgCaches[CACHE_DB];
+                       $cache->set_servers( $wgMemCachedServers );
+                       $cache->set_debug( $wgMemCachedDebug );
+               }
+       } elseif ( $type == CACHE_ACCEL ) {
+               if ( !array_key_exists( CACHE_ACCEL, $wgCaches ) ) {
+                       if ( function_exists( 'eaccelerator_get' ) ) {
+                               require_once( 'BagOStuff.php' );
+                               $wgCaches[CACHE_ACCEL] = new eAccelBagOStuff;
+                       } elseif ( function_exists( 'mmcache_get' ) ) {
+                               require_once( 'BagOStuff.php' );
+                               $wgCaches[CACHE_ACCEL] = new TurckBagOStuff;
+                       } else {
+                               $wgCaches[CACHE_ACCEL] = false;
+                       }
+               }
+               if ( $wgCaches[CACHE_ACCEL] !== false ) {
+                       $cache =& $wgCaches[CACHE_ACCEL];
+               }
+       }
+
+       if ( $type == CACHE_DB || ( $inputType == CACHE_ANYTHING && $cache === false ) ) {
+               if ( !array_key_exists( CACHE_DB, $wgCaches ) ) {
+                       require_once( 'BagOStuff.php' );
+                       $wgCaches[CACHE_DB] = new MediaWikiBagOStuff('objectcache');
+               }
+               $cache =& $wgCaches[CACHE_DB];
+       }
+       
+       if ( $cache === false ) {
+               if ( !array_key_exists( CACHE_NONE, $wgCaches ) ) {
+                       $wgCaches[CACHE_NONE] = new FakeMemCachedClient;
+               }
+               $cache =& $wgCaches[CACHE_NONE];
+       }
+
+       return $cache;
+}
+
+function &wfGetMainCache() {
+       global $wgMainCacheType;
+       $ret =& wfGetCache( $wgMainCacheType );
+       return $ret;
+}
+
+function &wfGetMessageCacheStorage() {
+       global $wgMessageCacheType;
+       $ret =& wfGetCache( $wgMessageCacheType );
+       return $ret;
+}
+
+function &wfGetParserCacheStorage() {
+       global $wgParserCacheType;
+       $ret =& wfGetCache( $wgParserCacheType );
+       return $ret;
+}
+
+?>
diff --git a/includes/OutputPage.php b/includes/OutputPage.php
new file mode 100644 (file)
index 0000000..e2e63fc
--- /dev/null
@@ -0,0 +1,911 @@
+<?php
+/**
+ * @package MediaWiki
+ */
+
+/**
+ * This is not a valid entry point, perform no further processing unless MEDIAWIKI is defined
+ */
+if( defined( 'MEDIAWIKI' ) ) {
+
+# See design.txt
+
+if($wgUseTeX) require_once( 'Math.php' );
+
+/**
+ * @todo document
+ * @package MediaWiki
+ */
+class OutputPage {
+       var $mHeaders, $mCookies, $mMetatags, $mKeywords;
+       var $mLinktags, $mPagetitle, $mBodytext, $mDebugtext;
+       var $mHTMLtitle, $mRobotpolicy, $mIsarticle, $mPrintable;
+       var $mSubtitle, $mRedirect;
+       var $mLastModified, $mETag, $mCategoryLinks;
+       var $mScripts, $mLinkColours;
+
+       var $mSuppressQuickbar;
+       var $mOnloadHandler;
+       var $mDoNothing;
+       var $mContainsOldMagic, $mContainsNewMagic;
+       var $mIsArticleRelated;
+       var $mParserOptions;
+       var $mShowFeedLinks = false;
+       var $mEnableClientCache = true;
+       var $mArticleBodyOnly = false;
+
+       /**
+        * Constructor
+        * Initialise private variables
+        */
+       function OutputPage() {
+               $this->mHeaders = $this->mCookies = $this->mMetatags =
+               $this->mKeywords = $this->mLinktags = array();
+               $this->mHTMLtitle = $this->mPagetitle = $this->mBodytext =
+               $this->mRedirect = $this->mLastModified =
+               $this->mSubtitle = $this->mDebugtext = $this->mRobotpolicy =
+               $this->mOnloadHandler = '';
+               $this->mIsArticleRelated = $this->mIsarticle = $this->mPrintable = true;
+               $this->mSuppressQuickbar = $this->mPrintable = false;
+               $this->mLanguageLinks = array();
+               $this->mCategoryLinks = array() ;
+               $this->mDoNothing = false;
+               $this->mContainsOldMagic = $this->mContainsNewMagic = 0;
+               $this->mParserOptions = ParserOptions::newFromUser( $temp = NULL );
+               $this->mSquidMaxage = 0;
+               $this->mScripts = '';
+               $this->mETag = false;
+       }
+
+       function addHeader( $name, $val ) { array_push( $this->mHeaders, $name.': '.$val ) ; }
+       function addCookie( $name, $val ) { array_push( $this->mCookies, array( $name, $val ) ); }
+       function redirect( $url, $responsecode = '302' ) { $this->mRedirect = $url; $this->mRedirectCode = $responsecode; }
+
+       # To add an http-equiv meta tag, precede the name with "http:"
+       function addMeta( $name, $val ) { array_push( $this->mMetatags, array( $name, $val ) ); }
+       function addKeyword( $text ) { array_push( $this->mKeywords, $text ); }
+       function addScript( $script ) { $this->mScripts .= $script; }
+       function getScript() { return $this->mScripts; }
+
+       function setETag($tag) { $this->mETag = $tag; }
+       function setArticleBodyOnly($only) { $this->mArticleBodyOnly = $only; }
+       function getArticleBodyOnly($only) { return $this->mArticleBodyOnly; }
+
+       function addLink( $linkarr ) {
+               # $linkarr should be an associative array of attributes. We'll escape on output.
+               array_push( $this->mLinktags, $linkarr );
+       }
+
+       function addMetadataLink( $linkarr ) {
+               # note: buggy CC software only reads first "meta" link
+               static $haveMeta = false;
+               $linkarr['rel'] = ($haveMeta) ? 'alternate meta' : 'meta';
+               $this->addLink( $linkarr );
+               $haveMeta = true;
+       }
+
+       /**
+        * checkLastModified tells the client to use the client-cached page if
+        * possible. If sucessful, the OutputPage is disabled so that
+        * any future call to OutputPage->output() have no effect. The method
+        * returns true iff cache-ok headers was sent.
+        */
+       function checkLastModified ( $timestamp ) {
+               global $wgLang, $wgCachePages, $wgUser;
+               if ( !$timestamp || $timestamp == '19700101000000' ) {
+                       wfDebug( "CACHE DISABLED, NO TIMESTAMP\n" );
+                       return;
+               }
+               if( !$wgCachePages ) {
+                       wfDebug( "CACHE DISABLED\n", false );
+                       return;
+               }
+               if( $wgUser->getOption( 'nocache' ) ) {
+                       wfDebug( "USER DISABLED CACHE\n", false );
+                       return;
+               }
+
+               $timestamp=wfTimestamp(TS_MW,$timestamp);
+               $lastmod = wfTimestamp( TS_RFC2822, max( $timestamp, $wgUser->mTouched ) );
+
+               if( !empty( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) ) {
+                       # IE sends sizes after the date like this:
+                       # Wed, 20 Aug 2003 06:51:19 GMT; length=5202
+                       # this breaks strtotime().
+                       $modsince = preg_replace( '/;.*$/', '', $_SERVER["HTTP_IF_MODIFIED_SINCE"] );
+                       $modsinceTime = strtotime( $modsince );
+                       $ismodsince = wfTimestamp( TS_MW, $modsinceTime ? $modsinceTime : 1 );
+                       wfDebug( "-- client send If-Modified-Since: " . $modsince . "\n", false );
+                       wfDebug( "--  we might send Last-Modified : $lastmod\n", false );
+                       if( ($ismodsince >= $timestamp ) && $wgUser->validateCache( $ismodsince ) ) {
+                               # Make sure you're in a place you can leave when you call us!
+                               header( "HTTP/1.0 304 Not Modified" );
+                               $this->mLastModified = $lastmod;
+                               $this->sendCacheControl();
+                               wfDebug( "CACHED client: $ismodsince ; user: $wgUser->mTouched ; page: $timestamp\n", false );
+                               $this->disable();
+                               @ob_end_clean(); // Don't output compressed blob
+                               return true;
+                       } else {
+                               wfDebug( "READY  client: $ismodsince ; user: $wgUser->mTouched ; page: $timestamp\n", false );
+                               $this->mLastModified = $lastmod;
+                       }
+               } else {
+                       wfDebug( "client did not send If-Modified-Since header\n", false );
+                       $this->mLastModified = $lastmod;
+               }
+       }
+
+       function getPageTitleActionText () {
+               global $action;
+               switch($action) {
+                       case 'edit':
+                               return wfMsg('edit');
+                       case 'history':
+                               return wfMsg('history_short');
+                       case 'protect':
+                               return wfMsg('protect');
+                       case 'unprotect':
+                               return wfMsg('unprotect');
+                       case 'delete':
+                               return wfMsg('delete');
+                       case 'watch':
+                               return wfMsg('watch');
+                       case 'unwatch':
+                               return wfMsg('unwatch');
+                       case 'submit':
+                               return wfMsg('preview');
+                       case 'info':
+                               return wfMsg('info_short');
+                       default:
+                               return '';
+               }
+       }
+
+       function setRobotpolicy( $str ) { $this->mRobotpolicy = $str; }
+       function setHTMLTitle( $name ) {$this->mHTMLtitle = $name; }
+       function setPageTitle( $name ) {
+               global $action, $wgContLang;
+               $name = $wgContLang->convert($name, true);
+               $this->mPagetitle = $name;
+               if(!empty($action)) {
+                       $taction =  $this->getPageTitleActionText();
+                       if( !empty( $taction ) ) {
+                               $name .= ' - '.$taction;
+                       }
+               }
+               
+               $this->setHTMLTitle( wfMsg( 'pagetitle', $name ) );
+       }
+       function getHTMLTitle() { return $this->mHTMLtitle; }
+       function getPageTitle() { return $this->mPagetitle; }
+       function setSubtitle( $str ) { $this->mSubtitle = /*$this->parse(*/$str/*)*/; } // @bug 2514
+       function getSubtitle() { return $this->mSubtitle; }
+       function isArticle() { return $this->mIsarticle; }
+       function setPrintable() { $this->mPrintable = true; }
+       function isPrintable() { return $this->mPrintable; }
+       function setSyndicated( $show = true ) { $this->mShowFeedLinks = $show; }
+       function isSyndicated() { return $this->mShowFeedLinks; }
+       function setOnloadHandler( $js ) { $this->mOnloadHandler = $js; }
+       function getOnloadHandler() { return $this->mOnloadHandler; }
+       function disable() { $this->mDoNothing = true; }
+
+       function setArticleRelated( $v ) {
+               $this->mIsArticleRelated = $v;
+               if ( !$v ) {
+                       $this->mIsarticle = false;
+               }
+       }
+       function setArticleFlag( $v ) {
+               $this->mIsarticle = $v;
+               if ( $v ) {
+                       $this->mIsArticleRelated = $v;
+               }
+       }
+
+       function isArticleRelated() { return $this->mIsArticleRelated; }
+
+       function getLanguageLinks() { return $this->mLanguageLinks; }
+       function addLanguageLinks($newLinkArray) {
+               $this->mLanguageLinks += $newLinkArray;
+       }
+       function setLanguageLinks($newLinkArray) {
+               $this->mLanguageLinks = $newLinkArray;
+       }
+
+       function getCategoryLinks() {
+               return $this->mCategoryLinks;
+       }
+       function addCategoryLinks($newLinkArray) {
+               $this->mCategoryLinks += $newLinkArray;
+       }
+       function setCategoryLinks($newLinkArray) {
+               $this->mCategoryLinks += $newLinkArray;
+       }
+
+       function suppressQuickbar() { $this->mSuppressQuickbar = true; }
+       function isQuickbarSuppressed() { return $this->mSuppressQuickbar; }
+
+       function addHTML( $text ) { $this->mBodytext .= $text; }
+       function clearHTML() { $this->mBodytext = ''; }
+       function getHTML() { return $this->mBodytext; }
+       function debug( $text ) { $this->mDebugtext .= $text; }
+
+       function setParserOptions( $options ) {
+               return wfSetVar( $this->mParserOptions, $options );
+       }
+
+       /**
+        * Convert wikitext to HTML and add it to the buffer
+        * Default assumes that the current page title will
+        * be used.
+        */
+       function addWikiText( $text, $linestart = true ) {
+               global $wgTitle;
+               $this->addWikiTextTitle($text, $wgTitle, $linestart);
+       }
+
+       function addWikiTextWithTitle($text, &$title, $linestart = true) {
+               $this->addWikiTextTitle($text, $title, $linestart);
+       }
+
+       function addWikiTextTitle($text, &$title, $linestart) {
+               global $wgParser, $wgUseTidy;
+               $parserOutput = $wgParser->parse( $text, $title, $this->mParserOptions, $linestart );
+               $this->mLanguageLinks += $parserOutput->getLanguageLinks();
+               $this->mCategoryLinks += $parserOutput->getCategoryLinks();
+               if ( $parserOutput->getCacheTime() == -1 ) {
+                       $this->enableClientCache( false );
+               }
+               $this->addHTML( $parserOutput->getText() );
+       }
+
+       /**
+        * Add wikitext to the buffer, assuming that this is the primary text for a page view
+        * Saves the text into the parser cache if possible
+        */
+       function addPrimaryWikiText( $text, $cacheArticle ) {
+               global $wgParser, $wgParserCache, $wgUser, $wgTitle, $wgUseTidy;
+
+               $parserOutput = $wgParser->parse( $text, $wgTitle, $this->mParserOptions, true );
+
+               $text = $parserOutput->getText();
+
+               if ( $cacheArticle && $parserOutput->getCacheTime() != -1 ) {
+                       $wgParserCache->save( $parserOutput, $cacheArticle, $wgUser );
+               }
+
+               $this->mLanguageLinks += $parserOutput->getLanguageLinks();
+               $this->mCategoryLinks += $parserOutput->getCategoryLinks();
+               if ( $parserOutput->getCacheTime() == -1 ) {
+                       $this->enableClientCache( false );
+               }
+               $this->addHTML( $text );
+       }
+
+       /**
+        * Add the output of a QuickTemplate to the output buffer
+        * @param QuickTemplate $template
+        */
+       function addTemplate( &$template ) {
+               ob_start();
+               $template->execute();
+               $this->addHtml( ob_get_contents() );
+               ob_end_clean();
+       }
+
+       /**
+        * Parse wikitext and return the HTML. This is for special pages that add the text later
+        */
+       function parse( $text, $linestart = true ) {
+               global $wgParser, $wgTitle;
+               $parserOutput = $wgParser->parse( $text, $wgTitle, $this->mParserOptions, $linestart );
+               return $parserOutput->getText();
+       }
+
+       /**
+        * @param $article
+        * @param $user
+        *
+        * @return bool
+        */
+       function tryParserCache( $article, $user ) {
+               global $wgParserCache;
+               $parserOutput = $wgParserCache->get( $article, $user );
+               if ( $parserOutput !== false ) {
+                       $this->mLanguageLinks += $parserOutput->getLanguageLinks();
+                       $this->mCategoryLinks += $parserOutput->getCategoryLinks();
+                       $this->addHTML( $parserOutput->getText() );
+                       $t = $parserOutput->getTitleText();
+                       if( !empty( $t ) ) {
+                               $this->setPageTitle( $t );
+                       }
+                       return true;
+               } else {
+                       return false;
+               }
+       }
+
+       /**
+        * Set the maximum cache time on the Squid in seconds
+        * @param $maxage
+        */
+       function setSquidMaxage( $maxage ) {
+               $this->mSquidMaxage = $maxage;
+       }
+
+       /**
+        * Use enableClientCache(false) to force it to send nocache headers
+        * @param $state
+        */
+       function enableClientCache( $state ) {
+               return wfSetVar( $this->mEnableClientCache, $state );
+       }
+
+       function uncacheableBecauseRequestvars() {
+               global $wgRequest;
+               return  $wgRequest->getText('useskin', false) === false
+                       && $wgRequest->getText('uselang', false) === false;
+       }
+
+       function sendCacheControl() {
+               global $wgUseSquid, $wgUseESI;
+
+               if ($this->mETag)
+                       header("ETag: $this->mETag");
+
+               # don't serve compressed data to clients who can't handle it
+               # maintain different caches for logged-in users and non-logged in ones
+               header( 'Vary: Accept-Encoding, Cookie' );
+               if( !$this->uncacheableBecauseRequestvars() && $this->mEnableClientCache ) {
+                       if( $wgUseSquid && ! isset( $_COOKIE[ini_get( 'session.name') ] ) &&
+                         ! $this->isPrintable() && $this->mSquidMaxage != 0 )
+                       {
+                               if ( $wgUseESI ) {
+                                       # We'll purge the proxy cache explicitly, but require end user agents
+                                       # to revalidate against the proxy on each visit.
+                                       # Surrogate-Control controls our Squid, Cache-Control downstream caches
+                                       wfDebug( "** proxy caching with ESI; {$this->mLastModified} **\n", false );
+                                       # start with a shorter timeout for initial testing
+                                       # header( 'Surrogate-Control: max-age=2678400+2678400, content="ESI/1.0"');
+                                       header( 'Surrogate-Control: max-age='.$wgSquidMaxage.'+'.$this->mSquidMaxage.', content="ESI/1.0"');
+                                       header( 'Cache-Control: s-maxage=0, must-revalidate, max-age=0' );
+                               } else {
+                                       # We'll purge the proxy cache for anons explicitly, but require end user agents
+                                       # to revalidate against the proxy on each visit.
+                                       # IMPORTANT! The Squid needs to replace the Cache-Control header with
+                                       # Cache-Control: s-maxage=0, must-revalidate, max-age=0
+                                       wfDebug( "** local proxy caching; {$this->mLastModified} **\n", false );
+                                       # start with a shorter timeout for initial testing
+                                       # header( "Cache-Control: s-maxage=2678400, must-revalidate, max-age=0" );
+                                       header( 'Cache-Control: s-maxage='.$this->mSquidMaxage.', must-revalidate, max-age=0' );
+                               }
+                       } else {
+                               # We do want clients to cache if they can, but they *must* check for updates
+                               # on revisiting the page.
+                               wfDebug( "** private caching; {$this->mLastModified} **\n", false );
+                               header( "Expires: -1" );
+                               header( "Cache-Control: private, must-revalidate, max-age=0" );
+                       }
+                       if($this->mLastModified) header( "Last-modified: {$this->mLastModified}" );
+               } else {
+                       wfDebug( "** no caching **\n", false );
+
+                       # In general, the absence of a last modified header should be enough to prevent
+                       # the client from using its cache. We send a few other things just to make sure.
+                       header( 'Expires: -1' );
+                       header( 'Cache-Control: no-cache, no-store, max-age=0, must-revalidate' );
+                       header( 'Pragma: no-cache' );
+               }
+       }
+
+       /**
+        * Finally, all the text has been munged and accumulated into
+        * the object, let's actually output it:
+        */
+       function output() {
+               global $wgUser, $wgLang, $wgDebugComments, $wgCookieExpiration;
+               global $wgInputEncoding, $wgOutputEncoding, $wgContLanguageCode;
+               global $wgDebugRedirects, $wgMimeType, $wgProfiler;
+
+               if( $this->mDoNothing ){
+                       return;
+               }
+               $fname = 'OutputPage::output';
+               wfProfileIn( $fname );
+               $sk = $wgUser->getSkin();
+
+               if ( '' != $this->mRedirect ) {
+                       if( substr( $this->mRedirect, 0, 4 ) != 'http' ) {
+                               # Standards require redirect URLs to be absolute
+                               global $wgServer;
+                               $this->mRedirect = $wgServer . $this->mRedirect;
+                       }
+                       if( $this->mRedirectCode == '301') {
+                               if( !$wgDebugRedirects ) {
+                                       header("HTTP/1.1 {$this->mRedirectCode} Moved Permanently");
+                               }
+                               $this->mLastModified = wfTimestamp( TS_RFC2822 );
+                       }
+
+                       $this->sendCacheControl();
+
+                       if( $wgDebugRedirects ) {
+                               $url = htmlspecialchars( $this->mRedirect );
+                               print "<html>\n<head>\n<title>Redirect</title>\n</head>\n<body>\n";
+                               print "<p>Location: <a href=\"$url\">$url</a></p>\n";
+                               print "</body>\n</html>\n";
+                       } else {
+                               header( 'Location: '.$this->mRedirect );
+                       }
+                       if ( isset( $wgProfiler ) ) { wfDebug( $wgProfiler->getOutput() ); }
+                       wfProfileOut( $fname );
+                       return;
+               }
+
+
+               # Buffer output; final headers may depend on later processing
+               ob_start();
+
+               $this->transformBuffer();
+
+               # Disable temporary placeholders, so that the skin produces HTML
+               $sk->postParseLinkColour( false );
+
+               header( "Content-type: $wgMimeType; charset={$wgOutputEncoding}" );
+               header( 'Content-language: '.$wgContLanguageCode );
+
+               $exp = time() + $wgCookieExpiration;
+               foreach( $this->mCookies as $name => $val ) {
+                       setcookie( $name, $val, $exp, '/' );
+               }
+
+               if ($this->mArticleBodyOnly) {
+                       $this->out($this->mBodytext);
+               } else {
+                       wfProfileIn( 'Output-skin' );
+                       $sk->outputPage( $this );
+                       wfProfileOut( 'Output-skin' );
+               }
+
+               $this->sendCacheControl();
+               ob_end_flush();
+               wfProfileOut( $fname );
+       }
+
+       function out( $ins ) {
+               global $wgInputEncoding, $wgOutputEncoding, $wgContLang;
+               if ( 0 == strcmp( $wgInputEncoding, $wgOutputEncoding ) ) {
+                       $outs = $ins;
+               } else {
+                       $outs = $wgContLang->iconv( $wgInputEncoding, $wgOutputEncoding, $ins );
+                       if ( false === $outs ) { $outs = $ins; }
+               }
+               print $outs;
+       }
+
+       function setEncodings() {
+               global $wgInputEncoding, $wgOutputEncoding;
+               global $wgUser, $wgContLang;
+
+               $wgInputEncoding = strtolower( $wgInputEncoding );
+
+               if( $wgUser->getOption( 'altencoding' ) ) {
+                       $wgContLang->setAltEncoding();
+                       return;
+               }
+
+               if ( empty( $_SERVER['HTTP_ACCEPT_CHARSET'] ) ) {
+                       $wgOutputEncoding = strtolower( $wgOutputEncoding );
+                       return;
+               }
+               $wgOutputEncoding = $wgInputEncoding;
+       }
+
+       /**
+        * Returns a HTML comment with the elapsed time since request.
+        * This method has no side effects.
+        * @return string
+        */
+       function reportTime() {
+               global $wgRequestTime;
+
+               $now = wfTime();
+               list( $usec, $sec ) = explode( ' ', $wgRequestTime );
+               $start = (float)$sec + (float)$usec;
+               $elapsed = $now - $start;
+
+               # Use real server name if available, so we know which machine
+               # in a server farm generated the current page.
+               if ( function_exists( 'posix_uname' ) ) {
+                       $uname = @posix_uname();
+               } else {
+                       $uname = false;
+               }
+               if( is_array( $uname ) && isset( $uname['nodename'] ) ) {
+                       $hostname = $uname['nodename'];
+               } else {
+                       # This may be a virtual server.
+                       $hostname = $_SERVER['SERVER_NAME'];
+               }
+               $com = sprintf( "<!-- Served by %s in %01.2f secs. -->",
+                 $hostname, $elapsed );
+               return $com;
+       }
+
+       /**
+        * Note: these arguments are keys into wfMsg(), not text!
+        */
+       function errorpage( $title, $msg ) {
+               global $wgTitle;
+
+               $this->mDebugtext .= 'Original title: ' .
+                 $wgTitle->getPrefixedText() . "\n";
+               $this->setPageTitle( wfMsg( $title ) );
+               $this->setHTMLTitle( wfMsg( 'errorpagetitle' ) );
+               $this->setRobotpolicy( 'noindex,nofollow' );
+               $this->setArticleRelated( false );
+               $this->enableClientCache( false );
+               $this->mRedirect = '';
+
+               $this->mBodytext = '';
+               $this->addWikiText( wfMsg( $msg ) );
+               $this->returnToMain( false );
+
+               $this->output();
+               wfErrorExit();
+       }
+
+       /**
+        * Display an error page indicating that a given version of MediaWiki is
+        * required to use it
+        *
+        * @param mixed $version The version of MediaWiki needed to use the page
+        */
+       function versionRequired( $version ) {
+               global $wgUser;
+
+               $this->setPageTitle( wfMsg( 'versionrequired', $version ) );
+               $this->setHTMLTitle( wfMsg( 'versionrequired', $version ) );
+               $this->setRobotpolicy( 'noindex,nofollow' );
+               $this->setArticleRelated( false );
+               $this->mBodytext = '';
+
+               $sk = $wgUser->getSkin();
+               $this->addWikiText( wfMsg( 'versionrequiredtext', $version ) );
+               $this->returnToMain();
+       }
+
+       /**
+        * Display an error page noting that a given permission bit is required.
+        * This should generally replace the sysopRequired, developerRequired etc.
+        * @param string $permission key required
+        */
+       function permissionRequired( $permission ) {
+               global $wgUser;
+
+               $this->setPageTitle( wfMsg( 'badaccess' ) );
+               $this->setHTMLTitle( wfMsg( 'errorpagetitle' ) );
+               $this->setRobotpolicy( 'noindex,nofollow' );
+               $this->setArticleRelated( false );
+               $this->mBodytext = '';
+
+               $sk = $wgUser->getSkin();
+               $ap = $sk->makeKnownLink( wfMsgForContent( 'administrators' ) );
+               $this->addHTML( wfMsgHtml( 'badaccesstext', $ap, $permission ) );
+               $this->returnToMain();
+       }
+
+       /**
+        * @deprecated
+        */
+       function sysopRequired() {
+               global $wgUser;
+
+               $this->setPageTitle( wfMsg( 'sysoptitle' ) );
+               $this->setHTMLTitle( wfMsg( 'errorpagetitle' ) );
+               $this->setRobotpolicy( 'noindex,nofollow' );
+               $this->setArticleRelated( false );
+               $this->mBodytext = '';
+
+               $sk = $wgUser->getSkin();
+               $ap = $sk->makeKnownLink( wfMsgForContent( 'administrators' ), '' );
+               $this->addHTML( wfMsgHtml( 'sysoptext', $ap ) );
+               $this->returnToMain();
+       }
+
+       /**
+        * @deprecated
+        */
+       function developerRequired() {
+               global $wgUser;
+
+               $this->setPageTitle( wfMsg( 'developertitle' ) );
+               $this->setHTMLTitle( wfMsg( 'errorpagetitle' ) );
+               $this->setRobotpolicy( 'noindex,nofollow' );
+               $this->setArticleRelated( false );
+               $this->mBodytext = '';
+
+               $sk = $wgUser->getSkin();
+               $ap = $sk->makeKnownLink( wfMsgForContent( 'administrators' ), '' );
+               $this->addHTML( wfMsgHtml( 'developertext', $ap ) );
+               $this->returnToMain();
+       }
+
+       function loginToUse() {
+               global $wgUser, $wgTitle, $wgContLang;
+
+               $this->setPageTitle( wfMsg( 'loginreqtitle' ) );
+               $this->setHTMLTitle( wfMsg( 'errorpagetitle' ) );
+               $this->setRobotpolicy( 'noindex,nofollow' );
+               $this->setArticleFlag( false );
+               $this->mBodytext = '';
+               $this->addWikiText( wfMsg( 'loginreqtext' ) );
+
+               # We put a comment in the .html file so a Sysop can diagnose the page the
+               # user can't see.
+               $this->addHTML( "\n<!--" .
+                                               $wgContLang->getNsText( $wgTitle->getNamespace() ) .
+                                               ':' .
+                                               $wgTitle->getDBkey() . '-->' );
+               $this->returnToMain();          # Flip back to the main page after 10 seconds.
+       }
+
+       function databaseError( $fname, $sql, $error, $errno ) {
+               global $wgUser, $wgCommandLineMode, $wgShowSQLErrors;
+
+               $this->setPageTitle( wfMsgNoDB( 'databaseerror' ) );
+               $this->setRobotpolicy( 'noindex,nofollow' );
+               $this->setArticleRelated( false );
+               $this->enableClientCache( false );
+               $this->mRedirect = '';
+
+               if( !$wgShowSQLErrors ) {
+                       $sql = wfMsg( 'sqlhidden' );
+               }
+
+               if ( $wgCommandLineMode ) {
+                       $msg = wfMsgNoDB( 'dberrortextcl', htmlspecialchars( $sql ),
+                                               htmlspecialchars( $fname ), $errno, htmlspecialchars( $error ) );
+               } else {
+                       $msg = wfMsgNoDB( 'dberrortext', htmlspecialchars( $sql ),
+                                               htmlspecialchars( $fname ), $errno, htmlspecialchars( $error ) );
+               }
+
+               if ( $wgCommandLineMode || !is_object( $wgUser )) {
+                       print $msg."\n";
+                       wfErrorExit();
+               }
+               $this->mBodytext = $msg;
+               $this->output();
+               wfErrorExit();
+       }
+
+       function readOnlyPage( $source = null, $protected = false ) {
+               global $wgUser, $wgReadOnlyFile, $wgReadOnly;
+
+               $this->setRobotpolicy( 'noindex,nofollow' );
+               $this->setArticleRelated( false );
+
+               if( $protected ) {
+                       $this->setPageTitle( wfMsg( 'viewsource' ) );
+                       $this->addWikiText( wfMsg( 'protectedtext' ) );
+               } else {
+                       $this->setPageTitle( wfMsg( 'readonly' ) );
+                       if ( $wgReadOnly ) {
+                               $reason = $wgReadOnly;
+                       } else {
+                               $reason = file_get_contents( $wgReadOnlyFile );
+                       }
+                       $this->addWikiText( wfMsg( 'readonlytext', $reason ) );
+               }
+
+               if( is_string( $source ) ) {
+                       if( strcmp( $source, '' ) == 0 ) {
+                               $source = wfMsg( 'noarticletext' );
+                       }
+                       $rows = $wgUser->getOption( 'rows' );
+                       $cols = $wgUser->getOption( 'cols' );
+                       $text = "\n<textarea cols='$cols' rows='$rows' readonly='readonly'>" .
+                               htmlspecialchars( $source ) . "\n</textarea>";
+                       $this->addHTML( $text );
+               }
+
+               $this->returnToMain( false );
+       }
+
+       function fatalError( $message ) {
+               $this->setPageTitle( wfMsg( "internalerror" ) );
+               $this->setRobotpolicy( "noindex,nofollow" );
+               $this->setArticleRelated( false );
+               $this->enableClientCache( false );
+               $this->mRedirect = '';
+
+               $this->mBodytext = $message;
+               $this->output();
+               wfErrorExit();
+       }
+
+       function unexpectedValueError( $name, $val ) {
+               $this->fatalError( wfMsg( 'unexpected', $name, $val ) );
+       }
+
+       function fileCopyError( $old, $new ) {
+               $this->fatalError( wfMsg( 'filecopyerror', $old, $new ) );
+       }
+
+       function fileRenameError( $old, $new ) {
+               $this->fatalError( wfMsg( 'filerenameerror', $old, $new ) );
+       }
+
+       function fileDeleteError( $name ) {
+               $this->fatalError( wfMsg( 'filedeleteerror', $name ) );
+       }
+
+       function fileNotFoundError( $name ) {
+               $this->fatalError( wfMsg( 'filenotfound', $name ) );
+       }
+
+       /**
+        * return from error messages or notes
+        * @param $auto automatically redirect the user after 10 seconds
+        * @param $returnto page title to return to. Default is Main Page.
+        */
+       function returnToMain( $auto = true, $returnto = NULL ) {
+               global $wgUser, $wgOut, $wgRequest;
+
+               if ( $returnto == NULL ) {
+                       $returnto = $wgRequest->getText( 'returnto' );
+               }
+               $returnto = htmlspecialchars( $returnto );
+
+               $sk = $wgUser->getSkin();
+               if ( '' == $returnto ) {
+                       $returnto = wfMsgForContent( 'mainpage' );
+               }
+               $link = $sk->makeKnownLink( $returnto, '' );
+
+               $r = wfMsg( 'returnto', $link );
+               if ( $auto ) {
+                       $titleObj = Title::newFromText( $returnto );
+                       $wgOut->addMeta( 'http:Refresh', '10;url=' . $titleObj->escapeFullURL() );
+               }
+               $wgOut->addHTML( "\n<p>$r</p>\n" );
+       }
+
+       /**
+        * This function takes the title (first item of mGoodLinks), categories, existing and broken links for the page
+        * and uses the first 10 of them for META keywords
+        */
+       function addMetaTags () {
+               global $wgLinkCache , $wgOut ;
+               $categories = array_keys ( $wgLinkCache->mCategoryLinks ) ;
+               $good = array_keys ( $wgLinkCache->mGoodLinks ) ;
+               $bad = array_keys ( $wgLinkCache->mBadLinks ) ;
+               $a = array_merge ( array_slice ( $good , 0 , 1 ), $categories, array_slice ( $good , 1 , 9 ) , $bad ) ;
+               $a = array_slice ( $a , 0 , 10 ) ; # 10 keywords max
+               $a = implode ( ',' , $a ) ;
+               $strip = array(
+                       "/<.*?>/" => '',
+                       "/_/" => ' '
+               );
+               $a = htmlspecialchars(preg_replace(array_keys($strip), array_values($strip),$a ));
+
+               $wgOut->addMeta ( 'KEYWORDS' , $a ) ;
+       }
+
+       /**
+        * @private
+        * @return string
+        */
+       function headElement() {
+               global $wgDocType, $wgDTD, $wgContLanguageCode, $wgOutputEncoding, $wgMimeType;
+               global $wgUser, $wgContLang, $wgRequest, $wgUseTrackbacks, $wgTitle;
+
+               if( $wgMimeType == 'text/xml' || $wgMimeType == 'application/xhtml+xml' || $wgMimeType == 'application/xml' ) {
+                       $ret = "<?xml version=\"1.0\" encoding=\"$wgOutputEncoding\" ?>\n";
+               } else {
+                       $ret = '';
+               }
+
+               $ret .= "<!DOCTYPE html PUBLIC \"$wgDocType\"\n        \"$wgDTD\">\n";
+
+               if ( '' == $this->getHTMLTitle() ) {
+                       $this->setHTMLTitle(  wfMsg( 'pagetitle', $this->getPageTitle() ));
+               }
+
+               $rtl = $wgContLang->isRTL() ? " dir='RTL'" : '';
+               $ret .= "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"$wgContLanguageCode\" lang=\"$wgContLanguageCode\" $rtl>\n";
+               $ret .= "<head>\n<title>" . htmlspecialchars( $this->getHTMLTitle() ) . "</title>\n";
+               array_push( $this->mMetatags, array( "http:Content-type", "$wgMimeType; charset={$wgOutputEncoding}" ) );
+
+               $ret .= $this->getHeadLinks();
+               global $wgStylePath;
+               if( $this->isPrintable() ) {
+                       $media = '';
+               } else {
+                       $media = "media='print'";
+               }
+               $printsheet = htmlspecialchars( "$wgStylePath/common/wikiprintable.css" );
+               $ret .= "<link rel='stylesheet' type='text/css' $media href='$printsheet' />\n";
+
+               $sk = $wgUser->getSkin();
+               $ret .= $sk->getHeadScripts();
+               $ret .= $this->mScripts;
+               $ret .= $sk->getUserStyles();
+
+               if ($wgUseTrackbacks && $this->isArticleRelated())
+                       $ret .= $wgTitle->trackbackRDF();
+
+               $ret .= "</head>\n";
+               return $ret;
+       }
+
+       function getHeadLinks() {
+               global $wgRequest, $wgStylePath;
+               $ret = '';
+               foreach ( $this->mMetatags as $tag ) {
+                       if ( 0 == strcasecmp( 'http:', substr( $tag[0], 0, 5 ) ) ) {
+                               $a = 'http-equiv';
+                               $tag[0] = substr( $tag[0], 5 );
+                       } else {
+                               $a = 'name';
+                       }
+                       $ret .= "<meta $a=\"{$tag[0]}\" content=\"{$tag[1]}\" />\n";
+               }
+               $p = $this->mRobotpolicy;
+               if ( '' == $p ) { $p = 'index,follow'; }
+               $ret .= "<meta name=\"robots\" content=\"$p\" />\n";
+
+               if ( count( $this->mKeywords ) > 0 ) {
+                       $strip = array(
+                               "/<.*?>/" => '',
+                               "/_/" => ' '
+                       );
+                       $ret .= "<meta name=\"keywords\" content=\"" .
+                         htmlspecialchars(preg_replace(array_keys($strip), array_values($strip),implode( ",", $this->mKeywords ))) . "\" />\n";
+               }
+               foreach ( $this->mLinktags as $tag ) {
+                       $ret .= '<link';
+                       foreach( $tag as $attr => $val ) {
+                               $ret .= " $attr=\"" . htmlspecialchars( $val ) . "\"";
+                       }
+                       $ret .= " />\n";
+               }
+               if( $this->isSyndicated() ) {
+                       # FIXME: centralize the mime-type and name information in Feed.php
+                       $link = $wgRequest->escapeAppendQuery( 'feed=rss' );
+                       $ret .= "<link rel='alternate' type='application/rss+xml' title='RSS 2.0' href='$link' />\n";
+                       $link = $wgRequest->escapeAppendQuery( 'feed=atom' );
+                       $ret .= "<link rel='alternate' type='application/atom+xml' title='Atom 0.3' href='$link' />\n";
+               }
+
+               return $ret;
+       }
+
+       /**
+        * Run any necessary pre-output transformations on the buffer text
+        */
+       function transformBuffer( $options = 0 ) {
+       }
+
+
+       /**
+        * Turn off regular page output and return an error reponse
+        * for when rate limiting has triggered.
+        * @todo i18n
+        * @access public
+        */
+       function rateLimited() {
+               global $wgOut;
+               $wgOut->disable();
+               wfHttpError( 500, 'Internal Server Error',
+                       'Sorry, the server has encountered an internal error. ' .
+                       'Please wait a moment and hit "refresh" to submit the request again.' );
+       }
+
+}
+
+} // MediaWiki
+
+?>
diff --git a/includes/PageHistory.php b/includes/PageHistory.php
new file mode 100644 (file)
index 0000000..1bf67a5
--- /dev/null
@@ -0,0 +1,543 @@
+<?php
+/**
+ * Page history
+ *
+ * Split off from Article.php and Skin.php, 2003-12-22
+ * @package MediaWiki
+ */
+
+/** */
+include_once ( 'SpecialValidate.php' );
+
+define('DIR_PREV', 0);
+define('DIR_NEXT', 1);
+
+/**
+ * This class handles printing the history page for an article.  In order to
+ * be efficient, it uses timestamps rather than offsets for paging, to avoid
+ * costly LIMIT,offset queries.
+ *
+ * Construct it by passing in an Article, and call $h->history() to print the
+ * history.
+ *
+ * @package MediaWiki
+ */
+
+class PageHistory {
+       var $mArticle, $mTitle, $mSkin;
+       var $lastdate;
+       var $linesonpage;
+       var $mNotificationTimestamp;
+
+       /**
+        * Construct a new PageHistory.
+        *
+        * @param Article $article
+        * @returns nothing
+        */
+       function PageHistory($article) {
+               global $wgUser;
+
+               $this->mArticle =& $article;
+               $this->mTitle =& $article->mTitle;
+               $this->mNotificationTimestamp = NULL;
+               $this->mSkin = $wgUser->getSkin();
+       }
+
+       /**
+        * Print the history page for an article.
+        *
+        * @returns nothing
+        */
+       function history() {
+               global $wgUser, $wgOut, $wgLang, $wgShowUpdatedMarker, $wgRequest,
+                       $wgTitle, $wgUseValidation;
+
+               /*
+                * Allow client caching.
+                */
+
+               if( $wgOut->checkLastModified( $this->mArticle->getTimestamp() ) )
+                       /* Client cache fresh and headers sent, nothing more to do. */
+                       return;
+
+               $fname = 'PageHistory::history';
+               wfProfileIn( $fname );
+
+               /*
+                * Setup page variables.
+                */
+               $wgOut->setPageTitle( $this->mTitle->getPrefixedText() );
+               $wgOut->setSubtitle( wfMsg( 'revhistory' ) );
+               $wgOut->setArticleFlag( false );
+               $wgOut->setArticleRelated( true );
+               $wgOut->setRobotpolicy( 'noindex,nofollow' );
+
+               /*
+                * Fail if article doesn't exist.
+                */
+               $id = $this->mTitle->getArticleID();
+               if( $id == 0 ) {
+                       $wgOut->addWikiText( wfMsg( 'nohistory' ) );
+                       wfProfileOut( $fname );
+                       return;
+               }
+
+               /*
+                * Extract limit, the number of revisions to show, and
+                * offset, the timestamp to begin at, from the URL.
+                */
+               $limit = $wgRequest->getInt('limit', 50);
+               $offset = $wgRequest->getText('offset');
+
+               /* Offset must be an integral. */
+               if (!strlen($offset) || !preg_match("/^[0-9]+$/", $offset))
+                       $offset = 0;
+
+               /*
+                * "go=last" means to jump to the last history page.
+                */
+               if (($gowhere = $wgRequest->getText("go")) !== NULL) {
+                       switch ($gowhere) {
+                       case "first":
+                               if (($lastid = $this->getLastOffsetForPaging($id, $limit)) === NULL)
+                                       break;
+                               $gourl = $wgTitle->getLocalURL("action=history&limit={$limit}&offset={$lastid}");
+                               break;
+                       default:
+                               $gourl = NULL;
+                       }
+
+                       if (!is_null($gourl)) {
+                               $wgOut->redirect($gourl);
+                               return;
+                       }
+               }
+
+               /*
+                * Fetch revisions.
+                *
+                * If the user clicked "previous", we retrieve the revisions backwards,
+                * then reverse them.  This is to avoid needing to know the timestamp of
+                * previous revisions when generating the URL.
+                */
+               $direction = $this->getDirection();
+               $revisions = $this->fetchRevisions($limit, $offset, $direction);
+               $navbar = $this->makeNavbar($revisions, $offset, $limit, $direction);
+
+               /*
+                * We fetch one more revision than needed to get the timestamp of the
+                * one after this page (and to know if it exists).
+                *
+                * linesonpage stores the actual number of lines.
+                */
+               if (count($revisions) < $limit + 1)
+                       $this->linesonpage = count($revisions);
+               else
+                       $this->linesonpage = count($revisions) - 1;
+
+               /* Un-reverse revisions */
+               if ($direction == DIR_PREV)
+                       $revisions = array_reverse($revisions);
+
+               /*
+                * Print the top navbar.
+                */
+               $s = $navbar;
+               $s .= $this->beginHistoryList();
+               $counter = 1;
+
+               /*
+                * Print each revision, excluding the one-past-the-end, if any.
+                */
+               foreach (array_slice($revisions, 0, $limit) as $i => $line) {
+                       $first = !$i && $offset == 0;
+                       $next = isset( $revisions[$i + 1] ) ? $revisions[$i + 1 ] : null;
+                       $s .= $this->historyLine($line, $next, $counter, $this->getNotificationTimestamp(), $first);
+                       $counter++;
+               }
+
+               /*
+                * End navbar.
+               */
+               $s .= $this->endHistoryList();
+               $s .= $navbar;
+
+               /*
+                * Article validation line.
+                */
+               if ($wgUseValidation)
+                       $s .= '<p>' . Validation::getStatisticsLink( $this->mArticle ) . '</p>' ;
+
+               $wgOut->addHTML( $s );
+               wfProfileOut( $fname );
+       }
+
+       /** @todo document */
+       function beginHistoryList() {
+               global $wgTitle;
+               $this->lastdate = '';
+               $s = '<p>' . wfMsg( 'histlegend' ) . '</p>';
+               $s .= '<form action="' . $wgTitle->escapeLocalURL( '-' ) . '" method="get">';
+               $prefixedkey = htmlspecialchars($wgTitle->getPrefixedDbKey());
+               $s .= "<input type='hidden' name='title' value=\"{$prefixedkey}\" />\n";
+               $s .= $this->submitButton();
+               $s .= '<ul id="pagehistory">';
+               return $s;
+       }
+
+       /** @todo document */
+       function endHistoryList() {
+               $last = wfMsg( 'last' );
+
+               $s = '</ul>';
+               $s .= $this->submitButton( array( 'id' => 'historysubmit' ) );
+               $s .= '</form>';
+               return $s;
+       }
+
+       /** @todo document */
+       function submitButton( $bits = array() ) {
+               return ( $this->linesonpage > 0 )
+                       ? wfElement( 'input', array_merge( $bits,
+                               array(
+                                       'class'     => 'historysubmit',
+                                       'type'      => 'submit',
+                                       'accesskey' => wfMsg( 'accesskey-compareselectedversions' ),
+                                       'title'     => wfMsg( 'tooltip-compareselectedversions' ),
+                                       'value'     => wfMsg( 'compareselectedversions' ),
+                               ) ) )
+                       : '';
+       }
+
+       /** @todo document */
+       function historyLine( $row, $next, $counter = '', $notificationtimestamp = false, $latest = false ) {
+               global $wgLang, $wgContLang;
+
+               static $message;
+               if( !isset( $message ) ) {
+                       foreach( explode( ' ', 'cur last selectolderversionfordiff selectnewerversionfordiff minoreditletter' ) as $msg ) {
+                               $message[$msg] = wfMsg( $msg );
+                       }
+               }
+
+               $link = $this->revLink( $row );
+
+               if ( 0 == $row->rev_user ) {
+                       $contribsPage =& Title::makeTitle( NS_SPECIAL, 'Contributions' );
+                       $ul = $this->mSkin->makeKnownLinkObj( $contribsPage,
+                               htmlspecialchars( $row->rev_user_text ),
+                               'target=' . urlencode( $row->rev_user_text ) );
+               } else {
+                       $userPage =& Title::makeTitle( NS_USER, $row->rev_user_text );
+                       $ul = $this->mSkin->makeLinkObj( $userPage , htmlspecialchars( $row->rev_user_text ) );
+               }
+
+               $s = '<li>';
+               if( $row->rev_deleted ) {
+                       $s .= '<span class="deleted">';
+               }
+               $curlink = $this->curLink( $row, $latest );
+               $lastlink = $this->lastLink( $row, $next, $counter );
+               $arbitrary = $this->diffButtons( $row, $latest, $counter );
+               $s .= "({$curlink}) ({$lastlink}) $arbitrary {$link} <span class='user'>{$ul}</span>";
+
+               if( $row->rev_minor_edit ) {
+                       $s .= ' ' . wfElement( 'span', array( 'class' => 'minor' ), $message['minoreditletter'] );
+               }
+
+               $s .= $this->mSkin->commentBlock( $row->rev_comment, $this->mTitle );
+               if ($this->getNotificationTimestamp() && ($row->rev_timestamp >= $this->getNotificationTimestamp())) {
+                       $s .= wfMsg( 'updatedmarker' );
+               }
+               if( $row->rev_deleted ) {
+                       $s .= "</span> " . htmlspecialchars( wfMsg( 'deletedrev' ) );
+               }
+               $s .= '</li>';
+
+               return $s;
+       }
+
+       /** @todo document */
+       function revLink( $row ) {
+               global $wgUser, $wgLang;
+               $date = $wgLang->timeanddate( $row->rev_timestamp, true );
+               if( $row->rev_deleted && !$wgUser->isAllowed( 'undelete' ) ) {
+                       return $date;
+               } else {
+                       return $this->mSkin->makeKnownLinkObj(
+                               $this->mTitle,
+                               $date,
+                               'oldid='.$row->rev_id );
+               }
+       }
+
+       /** @todo document */
+       function curLink( $row, $latest ) {
+               global $wgUser;
+               $cur = htmlspecialchars( wfMsg( 'cur' ) );
+               if( $latest
+                       || ( $row->rev_deleted && !$wgUser->isAllowed( 'undelete' ) ) ) {
+                       return $cur;
+               } else {
+                       return $this->mSkin->makeKnownLinkObj(
+                               $this->mTitle,
+                               $cur,
+                               'diff=' . $this->getLatestID($this->mTitle->getArticleID())
+                               . '&oldid=' . $row->rev_id );
+               }
+       }
+
+       /** @todo document */
+       function lastLink( $row, $next, $counter ) {
+               global $wgUser;
+               $last = htmlspecialchars( wfMsg( 'last' ) );
+               if( is_null( $next )
+                       || ( $row->rev_deleted && !$wgUser->isAllowed( 'undelete' ) ) ) {
+                       return $last;
+               } else {
+                       return $this->mSkin->makeKnownLinkObj(
+                         $this->mTitle,
+                         $last,
+                         "diff={$row->rev_id}&oldid={$next->rev_id}",
+                         '',
+                         '',
+                         ' tabindex="'.$counter.'"' );
+               }
+       }
+
+       /** @todo document */
+       function diffButtons( $row, $latest, $counter ) {
+               global $wgUser;
+               if( $this->linesonpage > 1) {
+                       $radio = array(
+                               'type'  => 'radio',
+                               'value' => $row->rev_id,
+                               'title' => wfMsg( 'selectolderversionfordiff' )
+                       );
+                       if( $row->rev_deleted && !$wgUser->isAllowed( 'undelete' ) ) {
+                               $radio['disabled'] = 'disabled';
+                       }
+
+                       # XXX: move title texts to javascript
+                       if ( $latest ) {
+                               $first = wfElement( 'input', array_merge(
+                                       $radio,
+                                       array(
+                                               'style' => 'visibility:hidden',
+                                               'name'  => 'oldid' ) ) );
+                               $checkmark = array( 'checked' => 'checked' );
+                       } else {
+                               if( $counter == 2 ) {
+                                       $checkmark = array( 'checked' => 'checked' );
+                               } else {
+                                       $checkmark = array();
+                               }
+                               $first = wfElement( 'input', array_merge(
+                                       $radio,
+                                       $checkmark,
+                                       array( 'name'  => 'oldid' ) ) );
+                               $checkmark = array();
+                       }
+                       $second = wfElement( 'input', array_merge(
+                               $radio,
+                               $checkmark,
+                               array( 'name'  => 'diff' ) ) );
+                       return $first . $second;
+               } else {
+                       return '';
+               }
+       }
+
+       /** @todo document */
+       function getLatestOffset($id) {
+               return $this->getExtremeOffset( $id, 'max' );
+       }
+
+       /** @todo document */
+       function getEarliestOffset($id) {
+               return $this->getExtremeOffset( $id, 'min' );
+       }
+
+       /** @todo document */
+       function getExtremeOffset( $id, $func ) {
+               $db =& wfGetDB(DB_SLAVE);
+               return $db->selectField( 'revision',
+                       "$func(rev_timestamp)",
+                       array( 'rev_page' => $id ),
+                       'PageHistory::getExtremeOffset' );
+       }
+
+       /** @todo document */
+       function getLatestID( $id ) {
+               $db =& wfGetDB(DB_SLAVE);
+               return $db->selectField( 'revision',
+                       "max(rev_id)",
+                       array( 'rev_page' => $id ),
+                       'PageHistory::getLatestID' );
+       }
+
+       /** @todo document */
+       function getLastOffsetForPaging( $id, $step = 50 ) {
+               $db =& wfGetDB(DB_SLAVE);
+               $revision = $db->tableName( 'revision' );
+               $sql = "SELECT rev_timestamp FROM $revision WHERE rev_page = $id " .
+                       "ORDER BY rev_timestamp ASC LIMIT $step";
+               $res = $db->query( $sql, "PageHistory::getLastOffsetForPaging" );
+               $n = $db->numRows( $res );
+
+               $last = null;
+               while( $obj = $db->fetchObject( $res ) ) {
+                       $last = $obj->rev_timestamp;
+               }
+               $db->freeResult( $res );
+               return $last;
+       }
+
+       /** @todo document */
+       function getDirection() {
+               global $wgRequest;
+
+               if ($wgRequest->getText("dir") == "prev")
+                       return DIR_PREV;
+               else
+                       return DIR_NEXT;
+       }
+
+       /** @todo document */
+       function fetchRevisions($limit, $offset, $direction) {
+               global $wgUser, $wgShowUpdatedMarker;
+
+               /* Check one extra row to see whether we need to show 'next' and diff links */
+               $limitplus = $limit + 1;
+
+               $namespace = $this->mTitle->getNamespace();
+               $title = $this->mTitle->getText();
+               $uid = $wgUser->getID();
+               $db =& wfGetDB( DB_SLAVE );
+
+               $use_index = $db->useIndexClause( 'page_timestamp' );
+               $revision = $db->tableName( 'revision' );
+
+               $limits = $offsets = "";
+
+               if ($direction == DIR_PREV)
+                       list($dirs, $oper) = array("ASC", ">=");
+               else    /* $direction = DIR_NEXT */
+                       list($dirs, $oper) = array("DESC", "<=");
+
+               if ($offset)
+                       $offsets .= " AND rev_timestamp $oper '$offset' ";
+
+               if ($limit)
+                       $limits .= " LIMIT $limitplus ";
+               $page_id = $this->mTitle->getArticleID();
+
+               $sql = "SELECT rev_id,rev_user," .
+                 "rev_comment,rev_user_text,rev_timestamp,rev_minor_edit,rev_deleted ".
+                 "FROM $revision $use_index " .
+                 "WHERE rev_page=$page_id " .
+                 $offsets .
+                 "ORDER BY rev_timestamp $dirs " .
+                 $limits;
+               $res = $db->query($sql, "PageHistory::fetchRevisions");
+
+               $result = array();
+               while (($obj = $db->fetchObject($res)) != NULL)
+                       $result[] = $obj;
+
+               return $result;
+       }
+
+       /** @todo document */
+       function getNotificationTimestamp() {
+               global $wgUser, $wgShowUpdatedMarker;
+
+               if ($this->mNotificationTimestamp !== NULL)
+                       return $this->mNotificationTimestamp;
+
+               if ($wgUser->getID() == 0 || !$wgShowUpdatedMarker)
+                       return $this->mNotificationTimestamp = false;
+
+               $db =& wfGetDB(DB_SLAVE);
+
+               $this->mNotificationTimestamp = $db->selectField(
+                       'watchlist',
+                       'wl_notificationtimestamp',
+                       array(  'wl_namespace' => $this->mTitle->getNamespace(),
+                               'wl_title' => $this->mTitle->getDBkey(),
+                               'wl_user' => $wgUser->getID()
+                       ),
+                       "PageHistory::getNotficationTimestamp");
+
+               return $this->mNotificationTimestamp;
+       }
+
+       /** @todo document */
+       function makeNavbar($revisions, $offset, $limit, $direction) {
+               global $wgTitle, $wgLang;
+
+               $revisions = array_slice($revisions, 0, $limit);
+
+               $pageid = $this->mTitle->getArticleID();
+               $latestTimestamp = $this->getLatestOffset( $pageid );
+               $earliestTimestamp = $this->getEarliestOffset( $pageid );
+
+               /*
+                * When we're displaying previous revisions, we need to reverse
+                * the array, because it's queried in reverse order.
+                */
+               if ($direction == DIR_PREV)
+                       $revisions = array_reverse($revisions);
+
+               /*
+                * lowts is the timestamp of the first revision on this page.
+                * hights is the timestamp of the last revision.
+                */
+
+               $lowts = $hights = 0;
+
+               if( count( $revisions ) ) {
+                       $latestShown = $revisions[0]->rev_timestamp;
+                       $earliestShown = $revisions[count($revisions) - 1]->rev_timestamp;
+               }
+
+               $firsturl = $wgTitle->escapeLocalURL("action=history&limit={$limit}&go=first");
+               $lasturl = $wgTitle->escapeLocalURL("action=history&limit={$limit}");
+               $firsttext = wfMsgHtml('histfirst');
+               $lasttext = wfMsgHtml('histlast');
+
+               $prevurl = $wgTitle->escapeLocalURL("action=history&dir=prev&offset={$latestShown}&limit={$limit}");
+               $nexturl = $wgTitle->escapeLocalURL("action=history&offset={$earliestShown}&limit={$limit}");
+
+               $urls = array();
+               foreach (array(20, 50, 100, 250, 500) as $num) {
+                       $urls[] = "<a href=\"".$wgTitle->escapeLocalURL(
+                               "action=history&offset={$offset}&limit={$num}")."\">".$wgLang->formatNum($num)."</a>";
+               }
+
+               $bits = implode($urls, ' | ');
+
+               wfDebug("latestShown=$latestShown latestTimestamp=$latestTimestamp\n");
+               if( $latestShown < $latestTimestamp ) {
+                       $prevtext = "<a href=\"$prevurl\">".wfMsgHtml("prevn", $limit)."</a>";
+                       $lasttext = "<a href=\"$lasturl\">$lasttext</a>";
+               } else {
+                       $prevtext = wfMsgHtml("prevn", $limit);
+               }
+
+               wfDebug("earliestShown=$earliestShown earliestTimestamp=$earliestTimestamp\n");
+               if( $earliestShown > $earliestTimestamp ) {
+                       $nexttext = "<a href=\"$nexturl\">".wfMsgHtml("nextn", $limit)."</a>";
+                       $firsttext = "<a href=\"$firsturl\">$firsttext</a>";
+               } else {
+                       $nexttext = wfMsgHtml("nextn", $limit);
+               }
+
+               $firstlast = "($lasttext | $firsttext)";
+
+               return "$firstlast " . wfMsgHtml("viewprevnext", $prevtext, $nexttext, $bits);
+       }
+}
+
+?>
diff --git a/includes/Parser.php b/includes/Parser.php
new file mode 100644 (file)
index 0000000..53fd823
--- /dev/null
@@ -0,0 +1,3564 @@
+<?php
+/**
+ * File for Parser and related classes
+ *
+ * @package MediaWiki
+ * @subpackage Parser
+ */
+
+/** */
+require_once( 'Sanitizer.php' );
+require_once( 'HttpFunctions.php' );
+
+/**
+ * Update this version number when the ParserOutput format
+ * changes in an incompatible way, so the parser cache
+ * can automatically discard old data.
+ */
+define( 'MW_PARSER_VERSION', '1.5.0' );
+
+/**
+ * Variable substitution O(N^2) attack
+ *
+ * Without countermeasures, it would be possible to attack the parser by saving
+ * a page filled with a large number of inclusions of large pages. The size of
+ * the generated page would be proportional to the square of the input size.
+ * Hence, we limit the number of inclusions of any given page, thus bringing any
+ * attack back to O(N).
+ */
+
+define( 'MAX_INCLUDE_REPEAT', 100 );
+define( 'MAX_INCLUDE_SIZE', 1000000 ); // 1 Million
+
+define( 'RLH_FOR_UPDATE', 1 );
+
+# Allowed values for $mOutputType
+define( 'OT_HTML', 1 );
+define( 'OT_WIKI', 2 );
+define( 'OT_MSG' , 3 );
+
+# string parameter for extractTags which will cause it
+# to strip HTML comments in addition to regular
+# <XML>-style tags. This should not be anything we
+# may want to use in wikisyntax
+define( 'STRIP_COMMENTS', 'HTMLCommentStrip' );
+
+# Constants needed for external link processing
+define( 'HTTP_PROTOCOLS', 'http:\/\/|https:\/\/' );
+# Everything except bracket, space, or control characters
+define( 'EXT_LINK_URL_CLASS', '[^]<>"\\x00-\\x20\\x7F]' );
+# Including space
+define( 'EXT_LINK_TEXT_CLASS', '[^\]\\x00-\\x1F\\x7F]' );
+define( 'EXT_IMAGE_FNAME_CLASS', '[A-Za-z0-9_.,~%\\-+&;#*?!=()@\\x80-\\xFF]' );
+define( 'EXT_IMAGE_EXTENSIONS', 'gif|png|jpg|jpeg' );
+define( 'EXT_LINK_BRACKETED',  '/\[(\b('.$wgUrlProtocols.')'.EXT_LINK_URL_CLASS.'+) *('.EXT_LINK_TEXT_CLASS.'*?)\]/S' );
+define( 'EXT_IMAGE_REGEX',
+       '/^('.HTTP_PROTOCOLS.')'.  # Protocol
+       '('.EXT_LINK_URL_CLASS.'+)\\/'.  # Hostname and path
+       '('.EXT_IMAGE_FNAME_CLASS.'+)\\.((?i)'.EXT_IMAGE_EXTENSIONS.')$/S' # Filename
+);
+
+/**
+ * PHP Parser
+ *
+ * Processes wiki markup
+ *
+ * <pre>
+ * There are three main entry points into the Parser class:
+ * parse()
+ *   produces HTML output
+ * preSaveTransform().
+ *   produces altered wiki markup.
+ * transformMsg()
+ *   performs brace substitution on MediaWiki messages
+ *
+ * Globals used:
+ *    objects:   $wgLang, $wgLinkCache
+ *
+ * NOT $wgArticle, $wgUser or $wgTitle. Keep them away!
+ *
+ * settings:
+ *  $wgUseTex*, $wgUseDynamicDates*, $wgInterwikiMagic*,
+ *  $wgNamespacesWithSubpages, $wgAllowExternalImages*,
+ *  $wgLocaltimezone, $wgAllowSpecialInclusion*
+ *
+ *  * only within ParserOptions
+ * </pre>
+ *
+ * @package MediaWiki
+ */
+class Parser
+{
+       /**#@+
+        * @access private
+        */
+       # Persistent:
+       var $mTagHooks;
+
+       # Cleared with clearState():
+       var $mOutput, $mAutonumber, $mDTopen, $mStripState = array();
+       var $mVariables, $mIncludeCount, $mArgStack, $mLastSection, $mInPre;
+       var $mInterwikiLinkHolders, $mLinkHolders, $mUniqPrefix;
+
+       # Temporary:
+       var $mOptions, $mTitle, $mOutputType,
+           $mTemplates,        // cache of already loaded templates, avoids
+                               // multiple SQL queries for the same string
+           $mTemplatePath;     // stores an unsorted hash of all the templates already loaded
+                               // in this path. Used for loop detection.
+
+       var $mIWTransData = array();
+
+       /**#@-*/
+
+       /**
+        * Constructor
+        *
+        * @access public
+        */
+       function Parser() {
+               global $wgContLang;
+               $this->mTemplates = array();
+               $this->mTemplatePath = array();
+               $this->mTagHooks = array();
+               $this->clearState();
+       }
+
+       /**
+        * Clear Parser state
+        *
+        * @access private
+        */
+       function clearState() {
+               $this->mOutput = new ParserOutput;
+               $this->mAutonumber = 0;
+               $this->mLastSection = '';
+               $this->mDTopen = false;
+               $this->mVariables = false;
+               $this->mIncludeCount = array();
+               $this->mStripState = array();
+               $this->mArgStack = array();
+               $this->mInPre = false;
+               $this->mInterwikiLinkHolders = array(
+                       'texts' => array(),
+                       'titles' => array()
+               );
+               $this->mLinkHolders = array(
+                       'namespaces' => array(),
+                       'dbkeys' => array(),
+                       'queries' => array(),
+                       'texts' => array(),
+                       'titles' => array()
+               );
+               $this->mUniqPrefix = 'UNIQ' . Parser::getRandomString();
+       }
+
+       /**
+        * Accessor for mUniqPrefix.
+        *
+        * @access public
+        */
+       function UniqPrefix() {
+               return $this->mUniqPrefix;
+       }
+
+       /**
+        * First pass--just handle <nowiki> sections, pass the rest off
+        * to internalParse() which does all the real work.
+        *
+        * @access private
+        * @param string $text Text we want to parse
+        * @param Title &$title A title object
+        * @param array $options
+        * @param boolean $linestart
+        * @param boolean $clearState
+        * @return ParserOutput a ParserOutput
+        */
+       function parse( $text, &$title, $options, $linestart = true, $clearState = true ) {
+               global $wgUseTidy, $wgContLang;
+               $fname = 'Parser::parse';
+               wfProfileIn( $fname );
+
+               if ( $clearState ) {
+                       $this->clearState();
+               }
+
+               $this->mOptions = $options;
+               $this->mTitle =& $title;
+               $this->mOutputType = OT_HTML;
+
+               $this->mStripState = NULL;
+
+               //$text = $this->strip( $text, $this->mStripState );
+               // VOODOO MAGIC FIX! Sometimes the above segfaults in PHP5.
+               $x =& $this->mStripState;
+
+               wfRunHooks( 'ParserBeforeStrip', array( &$this, &$text, &$x ) );
+               $text = $this->strip( $text, $x );
+               wfRunHooks( 'ParserAfterStrip', array( &$this, &$text, &$x ) );
+
+               $text = $this->internalParse( $text );
+
+               $text = $this->unstrip( $text, $this->mStripState );
+
+               # Clean up special characters, only run once, next-to-last before doBlockLevels
+               $fixtags = array(
+                       # french spaces, last one Guillemet-left
+                       # only if there is something before the space
+                       '/(.) (?=\\?|:|;|!|\\302\\273)/' => '\\1&nbsp;\\2',
+                       # french spaces, Guillemet-right
+                       '/(\\302\\253) /' => '\\1&nbsp;',
+                       '/<center *>(.*)<\\/center *>/i' => '<div class="center">\\1</div>',
+               );
+               $text = preg_replace( array_keys($fixtags), array_values($fixtags), $text );
+
+               # only once and last
+               $text = $this->doBlockLevels( $text, $linestart );
+
+               $this->replaceLinkHolders( $text );
+
+               # the position of the convert() call should not be changed. it
+               # assumes that the links are all replaces and the only thing left
+               # is the <nowiki> mark.
+               $text = $wgContLang->convert($text);
+               $this->mOutput->setTitleText($wgContLang->getParsedTitle());
+
+               $text = $this->unstripNoWiki( $text, $this->mStripState );
+
+               wfRunHooks( 'ParserBeforeTidy', array( &$this, &$text ) );
+
+               $text = Sanitizer::normalizeCharReferences( $text );
+               global $wgUseTidy;
+               if ($wgUseTidy) {
+                       $text = Parser::tidy($text);
+               }
+
+               wfRunHooks( 'ParserAfterTidy', array( &$this, &$text ) );
+
+               $this->mOutput->setText( $text );
+               wfProfileOut( $fname );
+               return $this->mOutput;
+       }
+
+       /**
+        * Get a random string
+        *
+        * @access private
+        * @static
+        */
+       function getRandomString() {
+               return dechex(mt_rand(0, 0x7fffffff)) . dechex(mt_rand(0, 0x7fffffff));
+       }
+
+       /**
+        * Replaces all occurrences of <$tag>content</$tag> in the text
+        * with a random marker and returns the new text. the output parameter
+        * $content will be an associative array filled with data on the form
+        * $unique_marker => content.
+        *
+        * If $content is already set, the additional entries will be appended
+        * If $tag is set to STRIP_COMMENTS, the function will extract
+        * <!-- HTML comments -->
+        *
+        * @access private
+        * @static
+        */
+       function extractTagsAndParams($tag, $text, &$content, &$tags, &$params, $uniq_prefix = ''){
+               $rnd = $uniq_prefix . '-' . $tag . Parser::getRandomString();
+               if ( !$content ) {
+                       $content = array( );
+               }
+               $n = 1;
+               $stripped = '';
+
+               if ( !$tags ) {
+                       $tags = array( );
+               }
+
+               if ( !$params ) {
+                       $params = array( );
+               }
+
+               if( $tag == STRIP_COMMENTS ) {
+                       $start = '/<!--()/';
+                       $end   = '/-->/';
+               } else {
+                       $start = "/<$tag(\\s+[^>]*|\\s*)>/i";
+                       $end   = "/<\\/$tag\\s*>/i";
+               }
+
+               while ( '' != $text ) {
+                       $p = preg_split( $start, $text, 2, PREG_SPLIT_DELIM_CAPTURE );
+                       $stripped .= $p[0];
+                       if( count( $p ) < 3 ) {
+                               break;
+                       }
+                       $attributes = $p[1];
+                       $inside     = $p[2];
+
+                       $marker = $rnd . sprintf('%08X', $n++);
+                       $stripped .= $marker;
+
+                       $tags[$marker] = "<$tag$attributes>";
+                       $params[$marker] = Sanitizer::decodeTagAttributes( $attributes );
+
+                       $q = preg_split( $end, $inside, 2 );
+                       $content[$marker] = $q[0];
+                       if( count( $q ) < 2 ) {
+                               # No end tag -- let it run out to the end of the text.
+                               break;
+                       } else {
+                               $text = $q[1];
+                       }
+               }
+               return $stripped;
+       }
+
+       /**
+        * Wrapper function for extractTagsAndParams
+        * for cases where $tags and $params isn't needed
+        * i.e. where tags will never have params, like <nowiki>
+        *
+        * @access private
+        * @static
+        */
+       function extractTags( $tag, $text, &$content, $uniq_prefix = '' ) {
+               $dummy_tags = array();
+               $dummy_params = array();
+
+               return Parser::extractTagsAndParams( $tag, $text, $content,
+                       $dummy_tags, $dummy_params, $uniq_prefix );
+       }
+
+       /**
+        * Strips and renders nowiki, pre, math, hiero
+        * If $render is set, performs necessary rendering operations on plugins
+        * Returns the text, and fills an array with data needed in unstrip()
+        * If the $state is already a valid strip state, it adds to the state
+        *
+        * @param bool $stripcomments when set, HTML comments <!-- like this -->
+        *  will be stripped in addition to other tags. This is important
+        *  for section editing, where these comments cause confusion when
+        *  counting the sections in the wikisource
+        *
+        * @access private
+        */
+       function strip( $text, &$state, $stripcomments = false ) {
+               $render = ($this->mOutputType == OT_HTML);
+               $html_content = array();
+               $nowiki_content = array();
+               $math_content = array();
+               $pre_content = array();
+               $comment_content = array();
+               $ext_content = array();
+               $ext_tags = array();
+               $ext_params = array();
+               $gallery_content = array();
+
+               # Replace any instances of the placeholders
+               $uniq_prefix = $this->mUniqPrefix;
+               #$text = str_replace( $uniq_prefix, wfHtmlEscapeFirst( $uniq_prefix ), $text );
+
+               # html
+               global $wgRawHtml;
+               if( $wgRawHtml ) {
+                       $text = Parser::extractTags('html', $text, $html_content, $uniq_prefix);
+                       foreach( $html_content as $marker => $content ) {
+                               if ($render ) {
+                                       # Raw and unchecked for validity.
+                                       $html_content[$marker] = $content;
+                               } else {
+                                       $html_content[$marker] = '<html>'.$content.'</html>';
+                               }
+                       }
+               }
+
+               # nowiki
+               $text = Parser::extractTags('nowiki', $text, $nowiki_content, $uniq_prefix);
+               foreach( $nowiki_content as $marker => $content ) {
+                       if( $render ){
+                               $nowiki_content[$marker] = wfEscapeHTMLTagsOnly( $content );
+                       } else {
+                               $nowiki_content[$marker] = '<nowiki>'.$content.'</nowiki>';
+                       }
+               }
+
+               # math
+               if( $this->mOptions->getUseTeX() ) {
+                       $text = Parser::extractTags('math', $text, $math_content, $uniq_prefix);
+                       foreach( $math_content as $marker => $content ){
+                               if( $render ) {
+                                       $math_content[$marker] = renderMath( $content );
+                               } else {
+                                       $math_content[$marker] = '<math>'.$content.'</math>';
+                               }
+                       }
+               }
+
+               # pre
+               $text = Parser::extractTags('pre', $text, $pre_content, $uniq_prefix);
+               foreach( $pre_content as $marker => $content ){
+                       if( $render ){
+                               $pre_content[$marker] = '<pre>' . wfEscapeHTMLTagsOnly( $content ) . '</pre>';
+                       } else {
+                               $pre_content[$marker] = '<pre>'.$content.'</pre>';
+                       }
+               }
+
+               # gallery
+               $text = Parser::extractTags('gallery', $text, $gallery_content, $uniq_prefix);
+               foreach( $gallery_content as $marker => $content ) {
+                       require_once( 'ImageGallery.php' );
+                       if ( $render ) {
+                               $gallery_content[$marker] = Parser::renderImageGallery( $content );
+                       } else {
+                               $gallery_content[$marker] = '<gallery>'.$content.'</gallery>';
+                       }
+               }
+
+               # Comments
+               if($stripcomments) {
+                       $text = Parser::extractTags(STRIP_COMMENTS, $text, $comment_content, $uniq_prefix);
+                       foreach( $comment_content as $marker => $content ){
+                               $comment_content[$marker] = '<!--'.$content.'-->';
+                       }
+               }
+
+               # Extensions
+               foreach ( $this->mTagHooks as $tag => $callback ) {
+                       $ext_content[$tag] = array();
+                       $text = Parser::extractTagsAndParams( $tag, $text, $ext_content[$tag],
+                               $ext_tags[$tag], $ext_params[$tag], $uniq_prefix );
+                       foreach( $ext_content[$tag] as $marker => $content ) {
+                               $full_tag = $ext_tags[$tag][$marker];
+                               $params = $ext_params[$tag][$marker];
+                               if ( $render ) {
+                                       $ext_content[$tag][$marker] = call_user_func_array( $callback, array( $content, $params, &$this ) );;
+                               } else {
+                                       $ext_content[$tag][$marker] = "$full_tag$content</$tag>";
+                               }
+                       }
+               }
+
+               # Merge state with the pre-existing state, if there is one
+               if ( $state ) {
+                       $state['html'] = $state['html'] + $html_content;
+                       $state['nowiki'] = $state['nowiki'] + $nowiki_content;
+                       $state['math'] = $state['math'] + $math_content;
+                       $state['pre'] = $state['pre'] + $pre_content;
+                       $state['comment'] = $state['comment'] + $comment_content;
+                       $state['gallery'] = $state['gallery'] + $gallery_content;
+
+                       foreach( $ext_content as $tag => $array ) {
+                               if ( array_key_exists( $tag, $state ) ) {
+                                       $state[$tag] = $state[$tag] + $array;
+                               }
+                       }
+               } else {
+                       $state = array(
+                         'html' => $html_content,
+                         'nowiki' => $nowiki_content,
+                         'math' => $math_content,
+                         'pre' => $pre_content,
+                         'comment' => $comment_content,
+                         'gallery' => $gallery_content,
+                       ) + $ext_content;
+               }
+               return $text;
+       }
+
+       /**
+        * restores pre, math, and hiero removed by strip()
+        *
+        * always call unstripNoWiki() after this one
+        * @access private
+        */
+       function unstrip( $text, &$state ) {
+               # Must expand in reverse order, otherwise nested tags will be corrupted
+               foreach( array_reverse( $state, true ) as $tag => $contentDict ) {
+                       if( $tag != 'nowiki' && $tag != 'html' ) {
+                               foreach( array_reverse( $contentDict, true ) as $uniq => $content ) {
+                                       $text = str_replace( $uniq, $content, $text );
+                               }
+                       }
+               }
+
+               return $text;
+       }
+
+       /**
+        * always call this after unstrip() to preserve the order
+        *
+        * @access private
+        */
+       function unstripNoWiki( $text, &$state ) {
+               # Must expand in reverse order, otherwise nested tags will be corrupted
+               for ( $content = end($state['nowiki']); $content !== false; $content = prev( $state['nowiki'] ) ) {
+                       $text = str_replace( key( $state['nowiki'] ), $content, $text );
+               }
+
+               global $wgRawHtml;
+               if ($wgRawHtml) {
+                       for ( $content = end($state['html']); $content !== false; $content = prev( $state['html'] ) ) {
+                               $text = str_replace( key( $state['html'] ), $content, $text );
+                       }
+               }
+
+               return $text;
+       }
+
+       /**
+        * Add an item to the strip state
+        * Returns the unique tag which must be inserted into the stripped text
+        * The tag will be replaced with the original text in unstrip()
+        *
+        * @access private
+        */
+       function insertStripItem( $text, &$state ) {
+               $rnd = $this->mUniqPrefix . '-item' . Parser::getRandomString();
+               if ( !$state ) {
+                       $state = array(
+                         'html' => array(),
+                         'nowiki' => array(),
+                         'math' => array(),
+                         'pre' => array(),
+                         'comment' => array(),
+                         'gallery' => array(),
+                       );
+               }
+               $state['item'][$rnd] = $text;
+               return $rnd;
+       }
+
+       /**
+        * Interface with html tidy, used if $wgUseTidy = true.
+        * If tidy isn't able to correct the markup, the original will be
+        * returned in all its glory with a warning comment appended.
+        *
+        * Either the external tidy program or the in-process tidy extension
+        * will be used depending on availability. Override the default
+        * $wgTidyInternal setting to disable the internal if it's not working.
+        *
+        * @param string $text Hideous HTML input
+        * @return string Corrected HTML output
+        * @access public
+        * @static
+        */
+       function tidy( $text ) {
+               global $wgTidyInternal;
+               $wrappedtext = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"'.
+' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html>'.
+'<head><title>test</title></head><body>'.$text.'</body></html>';
+               if( $wgTidyInternal ) {
+                       $correctedtext = Parser::internalTidy( $wrappedtext );
+               } else {
+                       $correctedtext = Parser::externalTidy( $wrappedtext );
+               }
+               if( is_null( $correctedtext ) ) {
+                       wfDebug( "Tidy error detected!\n" );
+                       return $text . "\n<!-- Tidy found serious XHTML errors -->\n";
+               }
+               return $correctedtext;
+       }
+
+       /**
+        * Spawn an external HTML tidy process and get corrected markup back from it.
+        *
+        * @access private
+        * @static
+        */
+       function externalTidy( $text ) {
+               global $wgTidyConf, $wgTidyBin, $wgTidyOpts;
+               $fname = 'Parser::externalTidy';
+               wfProfileIn( $fname );
+
+               $cleansource = '';
+               $opts = ' -utf8';
+
+               $descriptorspec = array(
+                       0 => array('pipe', 'r'),
+                       1 => array('pipe', 'w'),
+                       2 => array('file', '/dev/null', 'a')
+               );
+               $pipes = array();
+               $process = proc_open("$wgTidyBin -config $wgTidyConf $wgTidyOpts$opts", $descriptorspec, $pipes);
+               if (is_resource($process)) {
+                       fwrite($pipes[0], $text);
+                       fclose($pipes[0]);
+                       while (!feof($pipes[1])) {
+                               $cleansource .= fgets($pipes[1], 1024);
+                       }
+                       fclose($pipes[1]);
+                       proc_close($process);
+               }
+
+               wfProfileOut( $fname );
+
+               if( $cleansource == '' && $text != '') {
+                       // Some kind of error happened, so we couldn't get the corrected text.
+                       // Just give up; we'll use the source text and append a warning.
+                       return null;
+               } else {
+                       return $cleansource;
+               }
+       }
+
+       /**
+        * Use the HTML tidy PECL extension to use the tidy library in-process,
+        * saving the overhead of spawning a new process. Currently written to
+        * the PHP 4.3.x version of the extension, may not work on PHP 5.
+        *
+        * 'pear install tidy' should be able to compile the extension module.
+        *
+        * @access private
+        * @static
+        */
+       function internalTidy( $text ) {
+               global $wgTidyConf;
+               $fname = 'Parser::internalTidy';
+               wfProfileIn( $fname );
+
+               tidy_load_config( $wgTidyConf );
+               tidy_set_encoding( 'utf8' );
+               tidy_parse_string( $text );
+               tidy_clean_repair();
+               if( tidy_get_status() == 2 ) {
+                       // 2 is magic number for fatal error
+                       // http://www.php.net/manual/en/function.tidy-get-status.php
+                       $cleansource = null;
+               } else {
+                       $cleansource = tidy_get_output();
+               }
+               wfProfileOut( $fname );
+               return $cleansource;
+       }
+
+       /**
+        * parse the wiki syntax used to render tables
+        *
+        * @access private
+        */
+       function doTableStuff ( $t ) {
+               $fname = 'Parser::doTableStuff';
+               wfProfileIn( $fname );
+
+               $t = explode ( "\n" , $t ) ;
+               $td = array () ; # Is currently a td tag open?
+               $ltd = array () ; # Was it TD or TH?
+               $tr = array () ; # Is currently a tr tag open?
+               $ltr = array () ; # tr attributes
+               $indent_level = 0; # indent level of the table
+               foreach ( $t AS $k => $x )
+               {
+                       $x = trim ( $x ) ;
+                       $fc = substr ( $x , 0 , 1 ) ;
+                       if ( preg_match( '/^(:*)\{\|(.*)$/', $x, $matches ) ) {
+                               $indent_level = strlen( $matches[1] );
+                               
+                               $attributes = $this->unstripForHTML( $matches[2] );
+
+                               $t[$k] = str_repeat( '<dl><dd>', $indent_level ) .
+                                       '<table' . Sanitizer::fixTagAttributes ( $attributes, 'table' ) . '>' ;
+                               array_push ( $td , false ) ;
+                               array_push ( $ltd , '' ) ;
+                               array_push ( $tr , false ) ;
+                               array_push ( $ltr , '' ) ;
+                       }
+                       else if ( count ( $td ) == 0 ) { } # Don't do any of the following
+                       else if ( '|}' == substr ( $x , 0 , 2 ) ) {
+                               $z = "</table>" . substr ( $x , 2);
+                               $l = array_pop ( $ltd ) ;
+                               if ( array_pop ( $tr ) ) $z = '</tr>' . $z ;
+                               if ( array_pop ( $td ) ) $z = '</'.$l.'>' . $z ;
+                               array_pop ( $ltr ) ;
+                               $t[$k] = $z . str_repeat( '</dd></dl>', $indent_level );
+                       }
+                       else if ( '|-' == substr ( $x , 0 , 2 ) ) { # Allows for |---------------
+                               $x = substr ( $x , 1 ) ;
+                               while ( $x != '' && substr ( $x , 0 , 1 ) == '-' ) $x = substr ( $x , 1 ) ;
+                               $z = '' ;
+                               $l = array_pop ( $ltd ) ;
+                               if ( array_pop ( $tr ) ) $z = '</tr>' . $z ;
+                               if ( array_pop ( $td ) ) $z = '</'.$l.'>' . $z ;
+                               array_pop ( $ltr ) ;
+                               $t[$k] = $z ;
+                               array_push ( $tr , false ) ;
+                               array_push ( $td , false ) ;
+                               array_push ( $ltd , '' ) ;
+                               $attributes = $this->unstripForHTML( $x );
+                               array_push ( $ltr , Sanitizer::fixTagAttributes ( $attributes, 'tr' ) ) ;
+                       }
+                       else if ( '|' == $fc || '!' == $fc || '|+' == substr ( $x , 0 , 2 ) ) { # Caption
+                               # $x is a table row
+                               if ( '|+' == substr ( $x , 0 , 2 ) ) {
+                                       $fc = '+' ;
+                                       $x = substr ( $x , 1 ) ;
+                               }
+                               $after = substr ( $x , 1 ) ;
+                               if ( $fc == '!' ) $after = str_replace ( '!!' , '||' , $after ) ;
+                               $after = explode ( '||' , $after ) ;
+                               $t[$k] = '' ;
+
+                               # Loop through each table cell
+                               foreach ( $after AS $theline )
+                               {
+                                       $z = '' ;
+                                       if ( $fc != '+' )
+                                       {
+                                               $tra = array_pop ( $ltr ) ;
+                                               if ( !array_pop ( $tr ) ) $z = '<tr'.$tra.">\n" ;
+                                               array_push ( $tr , true ) ;
+                                               array_push ( $ltr , '' ) ;
+                                       }
+
+                                       $l = array_pop ( $ltd ) ;
+                                       if ( array_pop ( $td ) ) $z = '</'.$l.'>' . $z ;
+                                       if ( $fc == '|' ) $l = 'td' ;
+                                       else if ( $fc == '!' ) $l = 'th' ;
+                                       else if ( $fc == '+' ) $l = 'caption' ;
+                                       else $l = '' ;
+                                       array_push ( $ltd , $l ) ;
+
+                                       # Cell parameters
+                                       $y = explode ( '|' , $theline , 2 ) ;
+                                       # Note that a '|' inside an invalid link should not
+                                       # be mistaken as delimiting cell parameters
+                                       if ( strpos( $y[0], '[[' ) !== false ) {
+                                               $y = array ($theline);
+                                       }
+                                       if ( count ( $y ) == 1 )
+                                               $y = "{$z}<{$l}>{$y[0]}" ;
+                                       else {
+                                               $attributes = $this->unstripForHTML( $y[0] );
+                                               $y = "{$z}<{$l}".Sanitizer::fixTagAttributes($attributes, $l).">{$y[1]}" ;
+                                       }
+                                       $t[$k] .= $y ;
+                                       array_push ( $td , true ) ;
+                               }
+                       }
+               }
+
+               # Closing open td, tr && table
+               while ( count ( $td ) > 0 )
+               {
+                       if ( array_pop ( $td ) ) $t[] = '</td>' ;
+                       if ( array_pop ( $tr ) ) $t[] = '</tr>' ;
+                       $t[] = '</table>' ;
+               }
+
+               $t = implode ( "\n" , $t ) ;
+               wfProfileOut( $fname );
+               return $t ;
+       }
+
+       /**
+        * Helper function for parse() that transforms wiki markup into
+        * HTML. Only called for $mOutputType == OT_HTML.
+        *
+        * @access private
+        */
+       function internalParse( $text ) {
+               global $wgContLang;
+               $args = array();
+               $isMain = true;
+               $fname = 'Parser::internalParse';
+               wfProfileIn( $fname );
+
+               # Remove <noinclude> tags and <includeonly> sections
+               $text = strtr( $text, array( '<noinclude>' => '', '</noinclude>' => '') );
+               $text = preg_replace( '/<includeonly>.*?<\/includeonly>/s', '', $text );
+
+               $text = Sanitizer::removeHTMLtags( $text, array( &$this, 'attributeStripCallback' ) );
+               $text = $this->replaceVariables( $text, $args );
+
+               $text = preg_replace( '/(^|\n)-----*/', '\\1<hr />', $text );
+
+               $text = $this->doHeadings( $text );
+               if($this->mOptions->getUseDynamicDates()) {
+                       $df =& DateFormatter::getInstance();
+                       $text = $df->reformat( $this->mOptions->getDateFormat(), $text );
+               }
+               $text = $this->doAllQuotes( $text );
+               $text = $this->replaceInternalLinks( $text );
+               $text = $this->replaceExternalLinks( $text );
+
+               # replaceInternalLinks may sometimes leave behind
+               # absolute URLs, which have to be masked to hide them from replaceExternalLinks
+               $text = str_replace($this->mUniqPrefix."NOPARSE", "", $text);
+
+               $text = $this->doMagicLinks( $text );
+               $text = $this->doTableStuff( $text );
+               $text = $this->formatHeadings( $text, $isMain );
+
+               $regex = '/<!--IW_TRANSCLUDE (\d+)-->/';
+               $text = preg_replace_callback($regex, array(&$this, 'scarySubstitution'), $text);
+
+               wfProfileOut( $fname );
+               return $text;
+       }
+
+       function scarySubstitution($matches) {
+#              return "[[".$matches[0]."]]";
+               return $this->mIWTransData[(int)$matches[0]];
+       }
+
+       /**
+        * Replace special strings like "ISBN xxx" and "RFC xxx" with
+        * magic external links.
+        *
+        * @access private
+        */
+       function &doMagicLinks( &$text ) {
+               $text = $this->magicISBN( $text );
+               $text = $this->magicRFC( $text, 'RFC ', 'rfcurl' );
+               $text = $this->magicRFC( $text, 'PMID ', 'pubmedurl' );
+               return $text;
+       }
+
+       /**
+        * Parse ^^ tokens and return html
+        *
+        * @access private
+        */
+       function doExponent( $text ) {
+               $fname = 'Parser::doExponent';
+               wfProfileIn( $fname );
+               $text = preg_replace('/\^\^(.*)\^\^/','<small><sup>\\1</sup></small>', $text);
+               wfProfileOut( $fname );
+               return $text;
+       }
+
+       /**
+        * Parse headers and return html
+        *
+        * @access private
+        */
+       function doHeadings( $text ) {
+               $fname = 'Parser::doHeadings';
+               wfProfileIn( $fname );
+               for ( $i = 6; $i >= 1; --$i ) {
+                       $h = substr( '======', 0, $i );
+                       $text = preg_replace( "/^{$h}(.+){$h}(\\s|$)/m",
+                         "<h{$i}>\\1</h{$i}>\\2", $text );
+               }
+               wfProfileOut( $fname );
+               return $text;
+       }
+
+       /**
+        * Replace single quotes with HTML markup
+        * @access private
+        * @return string the altered text
+        */
+       function doAllQuotes( $text ) {
+               $fname = 'Parser::doAllQuotes';
+               wfProfileIn( $fname );
+               $outtext = '';
+               $lines = explode( "\n", $text );
+               foreach ( $lines as $line ) {
+                       $outtext .= $this->doQuotes ( $line ) . "\n";
+               }
+               $outtext = substr($outtext, 0,-1);
+               wfProfileOut( $fname );
+               return $outtext;
+       }
+
+       /**
+        * Helper function for doAllQuotes()
+        * @access private
+        */
+       function doQuotes( $text ) {
+               $arr = preg_split( "/(''+)/", $text, -1, PREG_SPLIT_DELIM_CAPTURE );
+               if ( count( $arr ) == 1 )
+                       return $text;
+               else
+               {
+                       # First, do some preliminary work. This may shift some apostrophes from
+                       # being mark-up to being text. It also counts the number of occurrences
+                       # of bold and italics mark-ups.
+                       $i = 0;
+                       $numbold = 0;
+                       $numitalics = 0;
+                       foreach ( $arr as $r )
+                       {
+                               if ( ( $i % 2 ) == 1 )
+                               {
+                                       # If there are ever four apostrophes, assume the first is supposed to
+                                       # be text, and the remaining three constitute mark-up for bold text.
+                                       if ( strlen( $arr[$i] ) == 4 )
+                                       {
+                                               $arr[$i-1] .= "'";
+                                               $arr[$i] = "'''";
+                                       }
+                                       # If there are more than 5 apostrophes in a row, assume they're all
+                                       # text except for the last 5.
+                                       else if ( strlen( $arr[$i] ) > 5 )
+                                       {
+                                               $arr[$i-1] .= str_repeat( "'", strlen( $arr[$i] ) - 5 );
+                                               $arr[$i] = "'''''";
+                                       }
+                                       # Count the number of occurrences of bold and italics mark-ups.
+                                       # We are not counting sequences of five apostrophes.
+                                       if ( strlen( $arr[$i] ) == 2 ) $numitalics++;  else
+                                       if ( strlen( $arr[$i] ) == 3 ) $numbold++;     else
+                                       if ( strlen( $arr[$i] ) == 5 ) { $numitalics++; $numbold++; }
+                               }
+                               $i++;
+                       }
+
+                       # If there is an odd number of both bold and italics, it is likely
+                       # that one of the bold ones was meant to be an apostrophe followed
+                       # by italics. Which one we cannot know for certain, but it is more
+                       # likely to be one that has a single-letter word before it.
+                       if ( ( $numbold % 2 == 1 ) && ( $numitalics % 2 == 1 ) )
+                       {
+                               $i = 0;
+                               $firstsingleletterword = -1;
+                               $firstmultiletterword = -1;
+                               $firstspace = -1;
+                               foreach ( $arr as $r )
+                               {
+                                       if ( ( $i % 2 == 1 ) and ( strlen( $r ) == 3 ) )
+                                       {
+                                               $x1 = substr ($arr[$i-1], -1);
+                                               $x2 = substr ($arr[$i-1], -2, 1);
+                                               if ($x1 == ' ') {
+                                                       if ($firstspace == -1) $firstspace = $i;
+                                               } else if ($x2 == ' ') {
+                                                       if ($firstsingleletterword == -1) $firstsingleletterword = $i;
+                                               } else {
+                                                       if ($firstmultiletterword == -1) $firstmultiletterword = $i;
+                                               }
+                                       }
+                                       $i++;
+                               }
+
+                               # If there is a single-letter word, use it!
+                               if ($firstsingleletterword > -1)
+                               {
+                                       $arr [ $firstsingleletterword ] = "''";
+                                       $arr [ $firstsingleletterword-1 ] .= "'";
+                               }
+                               # If not, but there's a multi-letter word, use that one.
+                               else if ($firstmultiletterword > -1)
+                               {
+                                       $arr [ $firstmultiletterword ] = "''";
+                                       $arr [ $firstmultiletterword-1 ] .= "'";
+                               }
+                               # ... otherwise use the first one that has neither.
+                               # (notice that it is possible for all three to be -1 if, for example,
+                               # there is only one pentuple-apostrophe in the line)
+                               else if ($firstspace > -1)
+                               {
+                                       $arr [ $firstspace ] = "''";
+                                       $arr [ $firstspace-1 ] .= "'";
+                               }
+                       }
+
+                       # Now let's actually convert our apostrophic mush to HTML!
+                       $output = '';
+                       $buffer = '';
+                       $state = '';
+                       $i = 0;
+                       foreach ($arr as $r)
+                       {
+                               if (($i % 2) == 0)
+                               {
+                                       if ($state == 'both')
+                                               $buffer .= $r;
+                                       else
+                                               $output .= $r;
+                               }
+                               else
+                               {
+                                       if (strlen ($r) == 2)
+                                       {
+                                               if ($state == 'i')
+                                               { $output .= '</i>'; $state = ''; }
+                                               else if ($state == 'bi')
+                                               { $output .= '</i>'; $state = 'b'; }
+                                               else if ($state == 'ib')
+                                               { $output .= '</b></i><b>'; $state = 'b'; }
+                                               else if ($state == 'both')
+                                               { $output .= '<b><i>'.$buffer.'</i>'; $state = 'b'; }
+                                               else # $state can be 'b' or ''
+                                               { $output .= '<i>'; $state .= 'i'; }
+                                       }
+                                       else if (strlen ($r) == 3)
+                                       {
+                                               if ($state == 'b')
+                                               { $output .= '</b>'; $state = ''; }
+                                               else if ($state == 'bi')
+                                               { $output .= '</i></b><i>'; $state = 'i'; }
+                                               else if ($state == 'ib')
+                                               { $output .= '</b>'; $state = 'i'; }
+                                               else if ($state == 'both')
+                                               { $output .= '<i><b>'.$buffer.'</b>'; $state = 'i'; }
+                                               else # $state can be 'i' or ''
+                                               { $output .= '<b>'; $state .= 'b'; }
+                                       }
+                                       else if (strlen ($r) == 5)
+                                       {
+                                               if ($state == 'b')
+                                               { $output .= '</b><i>'; $state = 'i'; }
+                                               else if ($state == 'i')
+                                               { $output .= '</i><b>'; $state = 'b'; }
+                                               else if ($state == 'bi')
+                                               { $output .= '</i></b>'; $state = ''; }
+                                               else if ($state == 'ib')
+                                               { $output .= '</b></i>'; $state = ''; }
+                                               else if ($state == 'both')
+                                               { $output .= '<i><b>'.$buffer.'</b></i>'; $state = ''; }
+                                               else # ($state == '')
+                                               { $buffer = ''; $state = 'both'; }
+                                       }
+                               }
+                               $i++;
+                       }
+                       # Now close all remaining tags.  Notice that the order is important.
+                       if ($state == 'b' || $state == 'ib')
+                               $output .= '</b>';
+                       if ($state == 'i' || $state == 'bi' || $state == 'ib')
+                               $output .= '</i>';
+                       if ($state == 'bi')
+                               $output .= '</b>';
+                       if ($state == 'both')
+                               $output .= '<b><i>'.$buffer.'</i></b>';
+                       return $output;
+               }
+       }
+
+       /**
+        * Replace external links
+        *
+        * Note: this is all very hackish and the order of execution matters a lot.
+        * Make sure to run maintenance/parserTests.php if you change this code.
+        *
+        * @access private
+        */
+       function replaceExternalLinks( $text ) {
+               global $wgContLang;
+               $fname = 'Parser::replaceExternalLinks';
+               wfProfileIn( $fname );
+
+               $sk =& $this->mOptions->getSkin();
+
+               $bits = preg_split( EXT_LINK_BRACKETED, $text, -1, PREG_SPLIT_DELIM_CAPTURE );
+
+               $s = $this->replaceFreeExternalLinks( array_shift( $bits ) );
+
+               $i = 0;
+               while ( $i<count( $bits ) ) {
+                       $url = $bits[$i++];
+                       $protocol = $bits[$i++];
+                       $text = $bits[$i++];
+                       $trail = $bits[$i++];
+
+                       # The characters '<' and '>' (which were escaped by
+                       # removeHTMLtags()) should not be included in
+                       # URLs, per RFC 2396.
+                       if (preg_match('/&(lt|gt);/', $url, $m2, PREG_OFFSET_CAPTURE)) {
+                               $text = substr($url, $m2[0][1]) . ' ' . $text;
+                               $url = substr($url, 0, $m2[0][1]);
+                       }
+
+                       # If the link text is an image URL, replace it with an <img> tag
+                       # This happened by accident in the original parser, but some people used it extensively
+                       $img = $this->maybeMakeExternalImage( $text );
+                       if ( $img !== false ) {
+                               $text = $img;
+                       }
+
+                       $dtrail = '';
+
+                       # Set linktype for CSS - if URL==text, link is essentially free
+                       $linktype = ($text == $url) ? 'free' : 'text';
+
+                       # No link text, e.g. [http://domain.tld/some.link]
+                       if ( $text == '' ) {
+                               # Autonumber if allowed
+                               if ( strpos( HTTP_PROTOCOLS, str_replace('/','\/', $protocol) ) !== false ) {
+                                       $text = '[' . ++$this->mAutonumber . ']';
+                                       $linktype = 'autonumber';
+                               } else {
+                                       # Otherwise just use the URL
+                                       $text = htmlspecialchars( $url );
+                                       $linktype = 'free';
+                               }
+                       } else {
+                               # Have link text, e.g. [http://domain.tld/some.link text]s
+                               # Check for trail
+                               list( $dtrail, $trail ) = Linker::splitTrail( $trail );
+                       }
+
+                       $text = $wgContLang->markNoConversion($text);
+
+                       # Replace &amp; from obsolete syntax with &.
+                       # All HTML entities will be escaped by makeExternalLink()
+                       # or maybeMakeExternalImage()
+                       $url = str_replace( '&amp;', '&', $url );
+
+                       # Process the trail (i.e. everything after this link up until start of the next link),
+                       # replacing any non-bracketed links
+                       $trail = $this->replaceFreeExternalLinks( $trail );
+
+
+                       # Use the encoded URL
+                       # This means that users can paste URLs directly into the text
+                       # Funny characters like &ouml; aren't valid in URLs anyway
+                       # This was changed in August 2004
+                       $s .= $sk->makeExternalLink( $url, $text, false, $linktype ) . $dtrail . $trail;
+               }
+
+               wfProfileOut( $fname );
+               return $s;
+       }
+
+       /**
+        * Replace anything that looks like a URL with a link
+        * @access private
+        */
+       function replaceFreeExternalLinks( $text ) {
+               global $wgUrlProtocols;
+               global $wgContLang;
+               $fname = 'Parser::replaceFreeExternalLinks';
+               wfProfileIn( $fname );
+
+               $bits = preg_split( '/(\b(?:'.$wgUrlProtocols.'))/S', $text, -1, PREG_SPLIT_DELIM_CAPTURE );
+               $s = array_shift( $bits );
+               $i = 0;
+
+               $sk =& $this->mOptions->getSkin();
+
+               while ( $i < count( $bits ) ){
+                       $protocol = $bits[$i++];
+                       $remainder = $bits[$i++];
+
+                       if ( preg_match( '/^('.EXT_LINK_URL_CLASS.'+)(.*)$/s', $remainder, $m ) ) {
+                               # Found some characters after the protocol that look promising
+                               $url = $protocol . $m[1];
+                               $trail = $m[2];
+
+                               # The characters '<' and '>' (which were escaped by
+                               # removeHTMLtags()) should not be included in
+                               # URLs, per RFC 2396.
+                               if (preg_match('/&(lt|gt);/', $url, $m2, PREG_OFFSET_CAPTURE)) {
+                                       $trail = substr($url, $m2[0][1]) . $trail;
+                                       $url = substr($url, 0, $m2[0][1]);
+                               }
+
+                               # Move trailing punctuation to $trail
+                               $sep = ',;\.:!?';
+                               # If there is no left bracket, then consider right brackets fair game too
+                               if ( strpos( $url, '(' ) === false ) {
+                                       $sep .= ')';
+                               }
+
+                               $numSepChars = strspn( strrev( $url ), $sep );
+                               if ( $numSepChars ) {
+                                       $trail = substr( $url, -$numSepChars ) . $trail;
+                                       $url = substr( $url, 0, -$numSepChars );
+                               }
+
+                               # Replace &amp; from obsolete syntax with &.
+                               # All HTML entities will be escaped by makeExternalLink()
+                               # or maybeMakeExternalImage()
+                               $url = str_replace( '&amp;', '&', $url );
+
+                               # Is this an external image?
+                               $text = $this->maybeMakeExternalImage( $url );
+                               if ( $text === false ) {
+                                       # Not an image, make a link
+                                       $text = $sk->makeExternalLink( $url, $wgContLang->markNoConversion($url), true, 'free' );
+                               }
+                               $s .= $text . $trail;
+                       } else {
+                               $s .= $protocol . $remainder;
+                       }
+               }
+               wfProfileOut( $fname );
+               return $s;
+       }
+
+       /**
+        * make an image if it's allowed
+        * @access private
+        */
+       function maybeMakeExternalImage( $url ) {
+               $sk =& $this->mOptions->getSkin();
+               $text = false;
+               if ( $this->mOptions->getAllowExternalImages() ) {
+                       if ( preg_match( EXT_IMAGE_REGEX, $url ) ) {
+                               # Image found
+                               $text = $sk->makeExternalImage( htmlspecialchars( $url ) );
+                       }
+               }
+               return $text;
+       }
+
+       /**
+        * Process [[ ]] wikilinks
+        *
+        * @access private
+        */
+       function replaceInternalLinks( $s ) {
+               global $wgContLang, $wgLinkCache, $wgUrlProtocols;
+               static $fname = 'Parser::replaceInternalLinks' ;
+
+               wfProfileIn( $fname );
+
+               wfProfileIn( $fname.'-setup' );
+               static $tc = FALSE;
+               # the % is needed to support urlencoded titles as well
+               if ( !$tc ) { $tc = Title::legalChars() . '#%'; }
+
+               $sk =& $this->mOptions->getSkin();
+
+               #split the entire text string on occurences of [[
+               $a = explode( '[[', ' ' . $s );
+               #get the first element (all text up to first [[), and remove the space we added
+               $s = array_shift( $a );
+               $s = substr( $s, 1 );
+
+               # Match a link having the form [[namespace:link|alternate]]trail
+               static $e1 = FALSE;
+               if ( !$e1 ) { $e1 = "/^([{$tc}]+)(?:\\|(.+?))?]](.*)\$/sD"; }
+               # Match cases where there is no "]]", which might still be images
+               static $e1_img = FALSE;
+               if ( !$e1_img ) { $e1_img = "/^([{$tc}]+)\\|(.*)\$/sD"; }
+               # Match the end of a line for a word that's not followed by whitespace,
+               # e.g. in the case of 'The Arab al[[Razi]]', 'al' will be matched
+               $e2 = wfMsgForContent( 'linkprefix' );
+
+               $useLinkPrefixExtension = $wgContLang->linkPrefixExtension();
+
+               if( is_null( $this->mTitle ) ) {
+                       wfDebugDieBacktrace( 'nooo' );
+               }
+               $nottalk = !$this->mTitle->isTalkPage();
+
+               if ( $useLinkPrefixExtension ) {
+                       if ( preg_match( $e2, $s, $m ) ) {
+                               $first_prefix = $m[2];
+                       } else {
+                               $first_prefix = false;
+                       }
+               } else {
+                       $prefix = '';
+               }
+
+               $selflink = $this->mTitle->getPrefixedText();
+               wfProfileOut( $fname.'-setup' );
+
+               $checkVariantLink = sizeof($wgContLang->getVariants())>1;
+               $useSubpages = $this->areSubpagesAllowed();
+
+               # Loop for each link
+               for ($k = 0; isset( $a[$k] ); $k++) {
+                       $line = $a[$k];
+                       if ( $useLinkPrefixExtension ) {
+                               wfProfileIn( $fname.'-prefixhandling' );
+                               if ( preg_match( $e2, $s, $m ) ) {
+                                       $prefix = $m[2];
+                                       $s = $m[1];
+                               } else {
+                                       $prefix='';
+                               }
+                               # first link
+                               if($first_prefix) {
+                                       $prefix = $first_prefix;
+                                       $first_prefix = false;
+                               }
+                               wfProfileOut( $fname.'-prefixhandling' );
+                       }
+
+                       $might_be_img = false;
+
+                       if ( preg_match( $e1, $line, $m ) ) { # page with normal text or alt
+                               $text = $m[2];
+                               # If we get a ] at the beginning of $m[3] that means we have a link that's something like:
+                               # [[Image:Foo.jpg|[http://example.com desc]]] <- having three ] in a row fucks up,
+                               # the real problem is with the $e1 regex
+                               # See bug 1300.
+                               #
+                               # Still some problems for cases where the ] is meant to be outside punctuation,
+                               # and no image is in sight. See bug 2095.
+                               #
+                               if( $text !== '' && preg_match( "/^\](.*)/s", $m[3], $n ) ) {
+                                       $text .= ']'; # so that replaceExternalLinks($text) works later
+                                       $m[3] = $n[1];
+                               }
+                               # fix up urlencoded title texts
+                               //if(preg_match('/%/', $m[1] )) $m[1] = urldecode($m[1]);
+                               if(preg_match('/%/', $m[1] )) 
+                                       # Should anchors '#' also be rejected?
+                                       $m[1] = str_replace( array('<', '>'), array('&lt;', '&gt;'), urldecode($m[1]) );
+                               $trail = $m[3];
+                       } elseif( preg_match($e1_img, $line, $m) ) { # Invalid, but might be an image with a link in its caption
+                               $might_be_img = true;
+                               $text = $m[2];
+                               if(preg_match('/%/', $m[1] )) 
+                                       # Should anchors '#' also be rejected?
+                                       $m[1] = str_replace( array('<', '>'), array('&lt;', '&gt;'), urldecode($m[1]) );
+                               $trail = "";
+                       } else { # Invalid form; output directly
+                               $s .= $prefix . '[[' . $line ;
+                               continue;
+                       }
+
+                       # Don't allow internal links to pages containing
+                       # PROTO: where PROTO is a valid URL protocol; these
+                       # should be external links.
+                       if (preg_match('/^(\b(?:'.$wgUrlProtocols.'))/', $m[1])) {
+                               $s .= $prefix . '[[' . $line ;
+                               continue;
+                       }
+
+                       # Make subpage if necessary
+                       if( $useSubpages ) {
+                               $link = $this->maybeDoSubpageLink( $m[1], $text );
+                       } else {
+                               $link = $m[1];
+                       }
+
+                       $noforce = (substr($m[1], 0, 1) != ':');
+                       if (!$noforce) {
+                               # Strip off leading ':'
+                               $link = substr($link, 1);
+                       }
+
+                       $nt = Title::newFromText( $this->unstripNoWiki($link, $this->mStripState) );
+                       if( !$nt ) {
+                               $s .= $prefix . '[[' . $line;
+                               continue;
+                       }
+
+                       #check other language variants of the link
+                       #if the article does not exist
+                       if( $checkVariantLink
+                           && $nt->getArticleID() == 0 ) {
+                               $wgContLang->findVariantLink($link, $nt);
+                       }
+
+                       $ns = $nt->getNamespace();
+                       $iw = $nt->getInterWiki();
+
+                       if ($might_be_img) { # if this is actually an invalid link
+                               if ($ns == NS_IMAGE && $noforce) { #but might be an image
+                                       $found = false;
+                                       while (isset ($a[$k+1]) ) {
+                                               #look at the next 'line' to see if we can close it there
+                                               $spliced = array_splice( $a, $k + 1, 1 );
+                                               $next_line = array_shift( $spliced );
+                                               if( preg_match("/^(.*?]].*?)]](.*)$/sD", $next_line, $m) ) {
+                                               # the first ]] closes the inner link, the second the image
+                                                       $found = true;
+                                                       $text .= '[[' . $m[1];
+                                                       $trail = $m[2];
+                                                       break;
+                                               } elseif( preg_match("/^.*?]].*$/sD", $next_line, $m) ) {
+                                                       #if there's exactly one ]] that's fine, we'll keep looking
+                                                       $text .= '[[' . $m[0];
+                                               } else {
+                                                       #if $next_line is invalid too, we need look no further
+                                                       $text .= '[[' . $next_line;
+                                                       break;
+                                               }
+                                       }
+                                       if ( !$found ) {
+                                               # we couldn't find the end of this imageLink, so output it raw
+                                               #but don't ignore what might be perfectly normal links in the text we've examined
+                                               $text = $this->replaceInternalLinks($text);
+                                               $s .= $prefix . '[[' . $link . '|' . $text;
+                                               # note: no $trail, because without an end, there *is* no trail
+                                               continue;
+                                       }
+                               } else { #it's not an image, so output it raw
+                                       $s .= $prefix . '[[' . $link . '|' . $text;
+                                       # note: no $trail, because without an end, there *is* no trail
+                                       continue;
+                               }
+                       }
+
+                       $wasblank = ( '' == $text );
+                       if( $wasblank ) $text = $link;
+
+
+                       # Link not escaped by : , create the various objects
+                       if( $noforce ) {
+
+                               # Interwikis
+                               if( $iw && $this->mOptions->getInterwikiMagic() && $nottalk && $wgContLang->getLanguageName( $iw ) ) {
+                                       array_push( $this->mOutput->mLanguageLinks, $nt->getFullText() );
+                                       $s = rtrim($s . "\n");
+                                       $s .= trim($prefix . $trail, "\n") == '' ? '': $prefix . $trail;
+                                       continue;
+                               }
+
+                               if ( $ns == NS_IMAGE ) {
+                                       wfProfileIn( "$fname-image" );
+                                       if ( !wfIsBadImage( $nt->getDBkey() ) ) {
+                                               # recursively parse links inside the image caption
+                                               # actually, this will parse them in any other parameters, too,
+                                               # but it might be hard to fix that, and it doesn't matter ATM
+                                               $text = $this->replaceExternalLinks($text);
+                                               $text = $this->replaceInternalLinks($text);
+
+                                               # cloak any absolute URLs inside the image markup, so replaceExternalLinks() won't touch them
+                                               $s .= $prefix . preg_replace( "/\b($wgUrlProtocols)/", "{$this->mUniqPrefix}NOPARSE$1", $this->makeImage( $nt, $text) ) . $trail;
+                                               $wgLinkCache->addImageLinkObj( $nt );
+
+                                               wfProfileOut( "$fname-image" );
+                                               continue;
+                                       }
+                                       wfProfileOut( "$fname-image" );
+
+                               }
+
+                               if ( $ns == NS_CATEGORY ) {
+                                       wfProfileIn( "$fname-category" );
+                                       $t = $wgContLang->convertHtml( $nt->getText() );
+                                       $s = rtrim($s . "\n"); # bug 87
+
+                                       $wgLinkCache->suspend(); # Don't save in links/brokenlinks
+                                       $t = $sk->makeLinkObj( $nt, $t, '', '' , $prefix );
+                                       $wgLinkCache->resume();
+
+                                       if ( $wasblank ) {
+                                               if ( $this->mTitle->getNamespace() == NS_CATEGORY ) {
+                                                       $sortkey = $this->mTitle->getText();
+                                               } else {
+                                                       $sortkey = $this->mTitle->getPrefixedText();
+                                               }
+                                       } else {
+                                               $sortkey = $text;
+                                       }
+                                       $sortkey = $wgContLang->convertCategoryKey( $sortkey );
+                                       $wgLinkCache->addCategoryLinkObj( $nt, $sortkey );
+                                       $this->mOutput->addCategoryLink( $t );
+
+                                       /**
+                                        * Strip the whitespace Category links produce, see bug 87
+                                        * @todo We might want to use trim($tmp, "\n") here.
+                                        */
+                                       $s .= trim($prefix . $trail, "\n") == '' ? '': $prefix . $trail;
+
+                                       wfProfileOut( "$fname-category" );
+                                       continue;
+                               }
+                       }
+
+                       if( ( $nt->getPrefixedText() === $selflink ) &&
+                           ( $nt->getFragment() === '' ) ) {
+                               # Self-links are handled specially; generally de-link and change to bold.
+                               $s .= $prefix . $sk->makeSelfLinkObj( $nt, $text, '', $trail );
+                               continue;
+                       }
+
+                       # Special and Media are pseudo-namespaces; no pages actually exist in them
+                       if( $ns == NS_MEDIA ) {
+                               $link = $sk->makeMediaLinkObj( $nt, $text );
+                               # Cloak with NOPARSE to avoid replacement in replaceExternalLinks
+                               $s .= $prefix . str_replace( 'http://', "http{$this->mUniqPrefix}NOPARSE://", $link ) . $trail;
+                               $wgLinkCache->addImageLinkObj( $nt );
+                               continue;
+                       } elseif( $ns == NS_SPECIAL ) {
+                               $s .= $prefix . $sk->makeKnownLinkObj( $nt, $text, '', $trail );
+                               continue;
+                       }
+                       if( !$nt->isExternal() && $nt->isAlwaysKnown() ) {
+                               /**
+                                * Skip lookups for special pages and self-links.
+                                * External interwiki links are not included here because
+                                * the HTTP urls would break output in the next parse step;
+                                * they will have placeholders kept.
+                                */
+                               $s .= $sk->makeKnownLinkObj( $nt, $text, '', $trail, $prefix );
+                       } else {
+                               /**
+                                * Add a link placeholder
+                                * Later, this will be replaced by a real link, after the existence or
+                                * non-existence of all the links is known
+                                */
+                               $s .= $this->makeLinkHolder( $nt, $text, '', $trail, $prefix );
+                       }
+               }
+               wfProfileOut( $fname );
+               return $s;
+       }
+
+       /**
+        * Make a link placeholder. The text returned can be later resolved to a real link with
+        * replaceLinkHolders(). This is done for two reasons: firstly to avoid further
+        * parsing of interwiki links, and secondly to allow all extistence checks and
+        * article length checks (for stub links) to be bundled into a single query.
+        *
+        */
+       function makeLinkHolder( &$nt, $text = '', $query = '', $trail = '', $prefix = '' ) {
+               if ( ! is_object($nt) ) {
+                       # Fail gracefully
+                       $retVal = "<!-- ERROR -->{$prefix}{$text}{$trail}";
+               } else {
+                       # Separate the link trail from the rest of the link
+                       list( $inside, $trail ) = Linker::splitTrail( $trail );
+
+                       if ( $nt->isExternal() ) {
+                               $nr = array_push( $this->mInterwikiLinkHolders['texts'], $prefix.$text.$inside );
+                               $this->mInterwikiLinkHolders['titles'][] = $nt;
+                               $retVal = '<!--IWLINK '. ($nr-1) ."-->{$trail}";
+                       } else {
+                               $nr = array_push( $this->mLinkHolders['namespaces'], $nt->getNamespace() );
+                               $this->mLinkHolders['dbkeys'][] = $nt->getDBkey();
+                               $this->mLinkHolders['queries'][] = $query;
+                               $this->mLinkHolders['texts'][] = $prefix.$text.$inside;
+                               $this->mLinkHolders['titles'][] = $nt;
+
+                               $retVal = '<!--LINK '. ($nr-1) ."-->{$trail}";
+                       }
+               }
+               return $retVal;
+       }
+
+       /**
+        * Return true if subpage links should be expanded on this page.
+        * @return bool
+        */
+       function areSubpagesAllowed() {
+               # Some namespaces don't allow subpages
+               global $wgNamespacesWithSubpages;
+               return !empty($wgNamespacesWithSubpages[$this->mTitle->getNamespace()]);
+       }
+
+       /**
+        * Handle link to subpage if necessary
+        * @param string $target the source of the link
+        * @param string &$text the link text, modified as necessary
+        * @return string the full name of the link
+        * @access private
+        */
+       function maybeDoSubpageLink($target, &$text) {
+               # Valid link forms:
+               # Foobar -- normal
+               # :Foobar -- override special treatment of prefix (images, language links)
+               # /Foobar -- convert to CurrentPage/Foobar
+               # /Foobar/ -- convert to CurrentPage/Foobar, strip the initial / from text
+               # ../ -- convert to CurrentPage, from CurrentPage/CurrentSubPage
+               # ../Foobar -- convert to CurrentPage/Foobar, from CurrentPage/CurrentSubPage
+
+               $fname = 'Parser::maybeDoSubpageLink';
+               wfProfileIn( $fname );
+               $ret = $target; # default return value is no change
+
+               # Some namespaces don't allow subpages,
+               # so only perform processing if subpages are allowed
+               if( $this->areSubpagesAllowed() ) {
+                       # Look at the first character
+                       if( $target != '' && $target{0} == '/' ) {
+                               # / at end means we don't want the slash to be shown
+                               if( substr( $target, -1, 1 ) == '/' ) {
+                                       $target = substr( $target, 1, -1 );
+                                       $noslash = $target;
+                               } else {
+                                       $noslash = substr( $target, 1 );
+                               }
+
+                               $ret = $this->mTitle->getPrefixedText(). '/' . trim($noslash);
+                               if( '' === $text ) {
+                                       $text = $target;
+                               } # this might be changed for ugliness reasons
+                       } else {
+                               # check for .. subpage backlinks
+                               $dotdotcount = 0;
+                               $nodotdot = $target;
+                               while( strncmp( $nodotdot, "../", 3 ) == 0 ) {
+                                       ++$dotdotcount;
+                                       $nodotdot = substr( $nodotdot, 3 );
+                               }
+                               if($dotdotcount > 0) {
+                                       $exploded = explode( '/', $this->mTitle->GetPrefixedText() );
+                                       if( count( $exploded ) > $dotdotcount ) { # not allowed to go below top level page
+                                               $ret = implode( '/', array_slice( $exploded, 0, -$dotdotcount ) );
+                                               # / at the end means don't show full path
+                                               if( substr( $nodotdot, -1, 1 ) == '/' ) {
+                                                       $nodotdot = substr( $nodotdot, 0, -1 );
+                                                       if( '' === $text ) {
+                                                               $text = $nodotdot;
+                                                       }
+                                               }
+                                               $nodotdot = trim( $nodotdot );
+                                               if( $nodotdot != '' ) {
+                                                       $ret .= '/' . $nodotdot;
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               wfProfileOut( $fname );
+               return $ret;
+       }
+
+       /**#@+
+        * Used by doBlockLevels()
+        * @access private
+        */
+       /* private */ function closeParagraph() {
+               $result = '';
+               if ( '' != $this->mLastSection ) {
+                       $result = '</' . $this->mLastSection  . ">\n";
+               }
+               $this->mInPre = false;
+               $this->mLastSection = '';
+               return $result;
+       }
+       # getCommon() returns the length of the longest common substring
+       # of both arguments, starting at the beginning of both.
+       #
+       /* private */ function getCommon( $st1, $st2 ) {
+               $fl = strlen( $st1 );
+               $shorter = strlen( $st2 );
+               if ( $fl < $shorter ) { $shorter = $fl; }
+
+               for ( $i = 0; $i < $shorter; ++$i ) {
+                       if ( $st1{$i} != $st2{$i} ) { break; }
+               }
+               return $i;
+       }
+       # These next three functions open, continue, and close the list
+       # element appropriate to the prefix character passed into them.
+       #
+       /* private */ function openList( $char ) {
+               $result = $this->closeParagraph();
+
+               if ( '*' == $char ) { $result .= '<ul><li>'; }
+               else if ( '#' == $char ) { $result .= '<ol><li>'; }
+               else if ( ':' == $char ) { $result .= '<dl><dd>'; }
+               else if ( ';' == $char ) {
+                       $result .= '<dl><dt>';
+                       $this->mDTopen = true;
+               }
+               else { $result = '<!-- ERR 1 -->'; }
+
+               return $result;
+       }
+
+       /* private */ function nextItem( $char ) {
+               if ( '*' == $char || '#' == $char ) { return '</li><li>'; }
+               else if ( ':' == $char || ';' == $char ) {
+                       $close = '</dd>';
+                       if ( $this->mDTopen ) { $close = '</dt>'; }
+                       if ( ';' == $char ) {
+                               $this->mDTopen = true;
+                               return $close . '<dt>';
+                       } else {
+                               $this->mDTopen = false;
+                               return $close . '<dd>';
+                       }
+               }
+               return '<!-- ERR 2 -->';
+       }
+
+       /* private */ function closeList( $char ) {
+               if ( '*' == $char ) { $text = '</li></ul>'; }
+               else if ( '#' == $char ) { $text = '</li></ol>'; }
+               else if ( ':' == $char ) {
+                       if ( $this->mDTopen ) {
+                               $this->mDTopen = false;
+                               $text = '</dt></dl>';
+                       } else {
+                               $text = '</dd></dl>';
+                       }
+               }
+               else {  return '<!-- ERR 3 -->'; }
+               return $text."\n";
+       }
+       /**#@-*/
+
+       /**
+        * Make lists from lines starting with ':', '*', '#', etc.
+        *
+        * @access private
+        * @return string the lists rendered as HTML
+        */
+       function doBlockLevels( $text, $linestart ) {
+               $fname = 'Parser::doBlockLevels';
+               wfProfileIn( $fname );
+
+               # Parsing through the text line by line.  The main thing
+               # happening here is handling of block-level elements p, pre,
+               # and making lists from lines starting with * # : etc.
+               #
+               $textLines = explode( "\n", $text );
+
+               $lastPrefix = $output = '';
+               $this->mDTopen = $inBlockElem = false;
+               $prefixLength = 0;
+               $paragraphStack = false;
+
+               if ( !$linestart ) {
+                       $output .= array_shift( $textLines );
+               }
+               foreach ( $textLines as $oLine ) {
+                       $lastPrefixLength = strlen( $lastPrefix );
+                       $preCloseMatch = preg_match('/<\\/pre/i', $oLine );
+                       $preOpenMatch = preg_match('/<pre/i', $oLine );
+                       if ( !$this->mInPre ) {
+                               # Multiple prefixes may abut each other for nested lists.
+                               $prefixLength = strspn( $oLine, '*#:;' );
+                               $pref = substr( $oLine, 0, $prefixLength );
+
+                               # eh?
+                               $pref2 = str_replace( ';', ':', $pref );
+                               $t = substr( $oLine, $prefixLength );
+                               $this->mInPre = !empty($preOpenMatch);
+                       } else {
+                               # Don't interpret any other prefixes in preformatted text
+                               $prefixLength = 0;
+                               $pref = $pref2 = '';
+                               $t = $oLine;
+                       }
+
+                       # List generation
+                       if( $prefixLength && 0 == strcmp( $lastPrefix, $pref2 ) ) {
+                               # Same as the last item, so no need to deal with nesting or opening stuff
+                               $output .= $this->nextItem( substr( $pref, -1 ) );
+                               $paragraphStack = false;
+
+                               if ( substr( $pref, -1 ) == ';') {
+                                       # The one nasty exception: definition lists work like this:
+                                       # ; title : definition text
+                                       # So we check for : in the remainder text to split up the
+                                       # title and definition, without b0rking links.
+                                       $term = $t2 = '';
+                                       if ($this->findColonNoLinks($t, $term, $t2) !== false) {
+                                               $t = $t2;
+                                               $output .= $term . $this->nextItem( ':' );
+                                       }
+                               }
+                       } elseif( $prefixLength || $lastPrefixLength ) {
+                               # Either open or close a level...
+                               $commonPrefixLength = $this->getCommon( $pref, $lastPrefix );
+                               $paragraphStack = false;
+
+                               while( $commonPrefixLength < $lastPrefixLength ) {
+                                       $output .= $this->closeList( $lastPrefix{$lastPrefixLength-1} );
+                                       --$lastPrefixLength;
+                               }
+                               if ( $prefixLength <= $commonPrefixLength && $commonPrefixLength > 0 ) {
+                                       $output .= $this->nextItem( $pref{$commonPrefixLength-1} );
+                               }
+                               while ( $prefixLength > $commonPrefixLength ) {
+                                       $char = substr( $pref, $commonPrefixLength, 1 );
+                                       $output .= $this->openList( $char );
+
+                                       if ( ';' == $char ) {
+                                               # FIXME: This is dupe of code above
+                                               if ($this->findColonNoLinks($t, $term, $t2) !== false) {
+                                                       $t = $t2;
+                                                       $output .= $term . $this->nextItem( ':' );
+                                               }
+                                       }
+                                       ++$commonPrefixLength;
+                               }
+                               $lastPrefix = $pref2;
+                       }
+                       if( 0 == $prefixLength ) {
+                               wfProfileIn( "$fname-paragraph" );
+                               # No prefix (not in list)--go to paragraph mode
+                               // XXX: use a stack for nestable elements like span, table and div
+                               $openmatch = preg_match('/(<table|<blockquote|<h1|<h2|<h3|<h4|<h5|<h6|<pre|<tr|<p|<ul|<li|<\\/tr|<\\/td|<\\/th)/iS', $t );
+                               $closematch = preg_match(
+                                       '/(<\\/table|<\\/blockquote|<\\/h1|<\\/h2|<\\/h3|<\\/h4|<\\/h5|<\\/h6|'.
+                                       '<td|<th|<div|<\\/div|<hr|<\\/pre|<\\/p|'.$this->mUniqPrefix.'-pre|<\\/li|<\\/ul)/iS', $t );
+                               if ( $openmatch or $closematch ) {
+                                       $paragraphStack = false;
+                                       $output .= $this->closeParagraph();
+                                       if ( $preOpenMatch and !$preCloseMatch ) {
+                                               $this->mInPre = true;
+                                       }
+                                       if ( $closematch ) {
+                                               $inBlockElem = false;
+                                       } else {
+                                               $inBlockElem = true;
+                                       }
+                               } else if ( !$inBlockElem && !$this->mInPre ) {
+                                       if ( ' ' == $t{0} and ( $this->mLastSection == 'pre' or trim($t) != '' ) ) {
+                                               // pre
+                                               if ($this->mLastSection != 'pre') {
+                                                       $paragraphStack = false;
+                                                       $output .= $this->closeParagraph().'<pre>';
+                                                       $this->mLastSection = 'pre';
+                                               }
+                                               $t = substr( $t, 1 );
+                                       } else {
+                                               // paragraph
+                                               if ( '' == trim($t) ) {
+                                                       if ( $paragraphStack ) {
+                                                               $output .= $paragraphStack.'<br />';
+                                                               $paragraphStack = false;
+                                                               $this->mLastSection = 'p';
+                                                       } else {
+                                                               if ($this->mLastSection != 'p' ) {
+                                                                       $output .= $this->closeParagraph();
+                                                                       $this->mLastSection = '';
+                                                                       $paragraphStack = '<p>';
+                                                               } else {
+                                                                       $paragraphStack = '</p><p>';
+                                                               }
+                                                       }
+                                               } else {
+                                                       if ( $paragraphStack ) {
+                                                               $output .= $paragraphStack;
+                                                               $paragraphStack = false;
+                                                               $this->mLastSection = 'p';
+                                                       } else if ($this->mLastSection != 'p') {
+                                                               $output .= $this->closeParagraph().'<p>';
+                                                               $this->mLastSection = 'p';
+                                                       }
+                                               }
+                                       }
+                               }
+                               wfProfileOut( "$fname-paragraph" );
+                       }
+                       // somewhere above we forget to get out of pre block (bug 785)
+                       if($preCloseMatch && $this->mInPre) {
+                               $this->mInPre = false;
+                       }
+                       if ($paragraphStack === false) {
+                               $output .= $t."\n";
+                       }
+               }
+               while ( $prefixLength ) {
+                       $output .= $this->closeList( $pref2{$prefixLength-1} );
+                       --$prefixLength;
+               }
+               if ( '' != $this->mLastSection ) {
+                       $output .= '</' . $this->mLastSection . '>';
+                       $this->mLastSection = '';
+               }
+
+               wfProfileOut( $fname );
+               return $output;
+       }
+
+       /**
+        * Split up a string on ':', ignoring any occurences inside
+        * <a>..</a> or <span>...</span>
+        * @param string $str the string to split
+        * @param string &$before set to everything before the ':'
+        * @param string &$after set to everything after the ':'
+        * return string the position of the ':', or false if none found
+        */
+       function findColonNoLinks($str, &$before, &$after) {
+               # I wonder if we should make this count all tags, not just <a>
+               # and <span>. That would prevent us from matching a ':' that
+               # comes in the middle of italics other such formatting....
+               # -- Wil
+               $fname = 'Parser::findColonNoLinks';
+               wfProfileIn( $fname );
+               $pos = 0;
+               do {
+                       $colon = strpos($str, ':', $pos);
+
+                       if ($colon !== false) {
+                               $before = substr($str, 0, $colon);
+                               $after = substr($str, $colon + 1);
+
+                               # Skip any ':' within <a> or <span> pairs
+                               $a = substr_count($before, '<a');
+                               $s = substr_count($before, '<span');
+                               $ca = substr_count($before, '</a>');
+                               $cs = substr_count($before, '</span>');
+
+                               if ($a <= $ca and $s <= $cs) {
+                                       # Tags are balanced before ':'; ok
+                                       break;
+                               }
+                               $pos = $colon + 1;
+                       }
+               } while ($colon !== false);
+               wfProfileOut( $fname );
+               return $colon;
+       }
+
+       /**
+        * Return value of a magic variable (like PAGENAME)
+        *
+        * @access private
+        */
+       function getVariableValue( $index ) {
+               global $wgContLang, $wgSitename, $wgServer, $wgServerName, $wgArticle, $wgScriptPath;
+
+               /**
+                * Some of these require message or data lookups and can be
+                * expensive to check many times.
+                */
+               static $varCache = array();
+               if( isset( $varCache[$index] ) ) return $varCache[$index];
+
+               switch ( $index ) {
+                       case MAG_CURRENTMONTH:
+                               return $varCache[$index] = $wgContLang->formatNum( date( 'm' ) );
+                       case MAG_CURRENTMONTHNAME:
+                               return $varCache[$index] = $wgContLang->getMonthName( date('n') );
+                       case MAG_CURRENTMONTHNAMEGEN:
+                               return $varCache[$index] = $wgContLang->getMonthNameGen( date('n') );
+                       case MAG_CURRENTMONTHABBREV:
+                               return $varCache[$index] = $wgContLang->getMonthAbbreviation( date('n') );
+                       case MAG_CURRENTDAY:
+                               return $varCache[$index] = $wgContLang->formatNum( date('j') );
+                       case MAG_PAGENAME:
+                               return $this->mTitle->getText();
+                       case MAG_PAGENAMEE:
+                               return $this->mTitle->getPartialURL();
+                       case MAG_REVISIONID:
+                               return $wgArticle->getRevIdFetched();
+                       case MAG_NAMESPACE:
+                               # return Namespace::getCanonicalName($this->mTitle->getNamespace());
+                               return $wgContLang->getNsText($this->mTitle->getNamespace()); # Patch by Dori
+                       case MAG_CURRENTDAYNAME:
+                               return $varCache[$index] = $wgContLang->getWeekdayName( date('w')+1 );
+                       case MAG_CURRENTYEAR:
+                               return $varCache[$index] = $wgContLang->formatNum( date( 'Y' ), true );
+                       case MAG_CURRENTTIME:
+                               return $varCache[$index] = $wgContLang->time( wfTimestampNow(), false );
+                       case MAG_CURRENTWEEK:
+                               return $varCache[$index] = $wgContLang->formatNum( intval( date('W') ) );
+                       case MAG_CURRENTDOW:
+                               return $varCache[$index] = $wgContLang->formatNum( date('w') );
+                       case MAG_NUMBEROFARTICLES:
+                               return $varCache[$index] = $wgContLang->formatNum( wfNumberOfArticles() );
+                       case MAG_NUMBEROFFILES:
+                               return $varCache[$index] = $wgContLang->formatNum( wfNumberOfFiles() );
+                       case MAG_SITENAME:
+                               return $wgSitename;
+                       case MAG_SERVER:
+                               return $wgServer;
+                       case MAG_SERVERNAME:
+                               return $wgServerName;
+                       case MAG_SCRIPTPATH:
+                               return $wgScriptPath;
+                       default:
+                               return NULL;
+               }
+       }
+
+       /**
+        * initialise the magic variables (like CURRENTMONTHNAME)
+        *
+        * @access private
+        */
+       function initialiseVariables() {
+               $fname = 'Parser::initialiseVariables';
+               wfProfileIn( $fname );
+               global $wgVariableIDs;
+               $this->mVariables = array();
+               foreach ( $wgVariableIDs as $id ) {
+                       $mw =& MagicWord::get( $id );
+                       $mw->addToArray( $this->mVariables, $id );
+               }
+               wfProfileOut( $fname );
+       }
+
+       /**
+        * Replace magic variables, templates, and template arguments
+        * with the appropriate text. Templates are substituted recursively,
+        * taking care to avoid infinite loops.
+        *
+        * Note that the substitution depends on value of $mOutputType:
+        *  OT_WIKI: only {{subst:}} templates
+        *  OT_MSG: only magic variables
+        *  OT_HTML: all templates and magic variables
+        *
+        * @param string $tex The text to transform
+        * @param array $args Key-value pairs representing template parameters to substitute
+        * @access private
+        */
+       function replaceVariables( $text, $args = array() ) {
+
+               # Prevent too big inclusions
+               if( strlen( $text ) > MAX_INCLUDE_SIZE ) {
+                       return $text;
+               }
+
+               $fname = 'Parser::replaceVariables';
+               wfProfileIn( $fname );
+
+               $titleChars = Title::legalChars();
+
+               # This function is called recursively. To keep track of arguments we need a stack:
+               array_push( $this->mArgStack, $args );
+
+               # Variable substitution
+               $text = preg_replace_callback( "/{{([$titleChars]*?)}}/", array( &$this, 'variableSubstitution' ), $text );
+
+               if ( $this->mOutputType == OT_HTML || $this->mOutputType == OT_WIKI ) {
+                       # Argument substitution
+                       $text = preg_replace_callback( "/{{{([$titleChars]*?)}}}/", array( &$this, 'argSubstitution' ), $text );
+               }
+               # Template substitution
+               $regex = '/(\\n|{)?{{(['.$titleChars.']*)(\\|.*?|)}}/s';
+               $text = preg_replace_callback( $regex, array( &$this, 'braceSubstitution' ), $text );
+
+               array_pop( $this->mArgStack );
+
+               wfProfileOut( $fname );
+               return $text;
+       }
+
+       /**
+        * Replace magic variables
+        * @access private
+        */
+       function variableSubstitution( $matches ) {
+               $fname = 'parser::variableSubstitution';
+               $varname = $matches[1];
+               wfProfileIn( $fname );
+               if ( !$this->mVariables ) {
+                       $this->initialiseVariables();
+               }
+               $skip = false;
+               if ( $this->mOutputType == OT_WIKI ) {
+                       # Do only magic variables prefixed by SUBST
+                       $mwSubst =& MagicWord::get( MAG_SUBST );
+                       if (!$mwSubst->matchStartAndRemove( $varname ))
+                               $skip = true;
+                       # Note that if we don't substitute the variable below,
+                       # we don't remove the {{subst:}} magic word, in case
+                       # it is a template rather than a magic variable.
+               }
+               if ( !$skip && array_key_exists( $varname, $this->mVariables ) ) {
+                       $id = $this->mVariables[$varname];
+                       $text = $this->getVariableValue( $id );
+                       $this->mOutput->mContainsOldMagic = true;
+               } else {
+                       $text = $matches[0];
+               }
+               wfProfileOut( $fname );
+               return $text;
+       }
+
+       # Split template arguments
+       function getTemplateArgs( $argsString ) {
+               if ( $argsString === '' ) {
+                       return array();
+               }
+
+               $args = explode( '|', substr( $argsString, 1 ) );
+
+               # If any of the arguments contains a '[[' but no ']]', it needs to be
+               # merged with the next arg because the '|' character between belongs
+               # to the link syntax and not the template parameter syntax.
+               $argc = count($args);
+
+               for ( $i = 0; $i < $argc-1; $i++ ) {
+                       if ( substr_count ( $args[$i], '[[' ) != substr_count ( $args[$i], ']]' ) ) {
+                               $args[$i] .= '|'.$args[$i+1];
+                               array_splice($args, $i+1, 1);
+                               $i--;
+                               $argc--;
+                       }
+               }
+
+               return $args;
+       }
+
+       /**
+        * Return the text of a template, after recursively
+        * replacing any variables or templates within the template.
+        *
+        * @param array $matches The parts of the template
+        *  $matches[1]: the title, i.e. the part before the |
+        *  $matches[2]: the parameters (including a leading |), if  any
+        * @return string the text of the template
+        * @access private
+        */
+       function braceSubstitution( $matches ) {
+               global $wgLinkCache, $wgContLang;
+               $fname = 'Parser::braceSubstitution';
+               wfProfileIn( $fname );
+
+               $found = false;
+               $nowiki = false;
+               $noparse = false;
+
+               $title = NULL;
+
+               # Need to know if the template comes at the start of a line,
+               # to treat the beginning of the template like the beginning
+               # of a line for tables and block-level elements.
+               $linestart = $matches[1];
+
+               # $part1 is the bit before the first |, and must contain only title characters
+               # $args is a list of arguments, starting from index 0, not including $part1
+
+               $part1 = $matches[2];
+               # If the third subpattern matched anything, it will start with |
+
+               $args = $this->getTemplateArgs($matches[3]);
+               $argc = count( $args );
+
+               # Don't parse {{{}}} because that's only for template arguments
+               if ( $linestart === '{' ) {
+                       $text = $matches[0];
+                       $found = true;
+                       $noparse = true;
+               }
+
+               # SUBST
+               if ( !$found ) {
+                       $mwSubst =& MagicWord::get( MAG_SUBST );
+                       if ( $mwSubst->matchStartAndRemove( $part1 ) xor ($this->mOutputType == OT_WIKI) ) {
+                               # One of two possibilities is true:
+                               # 1) Found SUBST but not in the PST phase
+                               # 2) Didn't find SUBST and in the PST phase
+                               # In either case, return without further processing
+                               $text = $matches[0];
+                               $found = true;
+                               $noparse = true;
+                       }
+               }
+
+               # MSG, MSGNW and INT
+               if ( !$found ) {
+                       # Check for MSGNW:
+                       $mwMsgnw =& MagicWord::get( MAG_MSGNW );
+                       if ( $mwMsgnw->matchStartAndRemove( $part1 ) ) {
+                               $nowiki = true;
+                       } else {
+                               # Remove obsolete MSG:
+                               $mwMsg =& MagicWord::get( MAG_MSG );
+                               $mwMsg->matchStartAndRemove( $part1 );
+                       }
+
+                       # Check if it is an internal message
+                       $mwInt =& MagicWord::get( MAG_INT );
+                       if ( $mwInt->matchStartAndRemove( $part1 ) ) {
+                               if ( $this->incrementIncludeCount( 'int:'.$part1 ) ) {
+                                       $text = $linestart . wfMsgReal( $part1, $args, true );
+                                       $found = true;
+                               }
+                       }
+               }
+
+               # NS
+               if ( !$found ) {
+                       # Check for NS: (namespace expansion)
+                       $mwNs = MagicWord::get( MAG_NS );
+                       if ( $mwNs->matchStartAndRemove( $part1 ) ) {
+                               if ( intval( $part1 ) ) {
+                                       $text = $linestart . $wgContLang->getNsText( intval( $part1 ) );
+                                       $found = true;
+                               } else {
+                                       $index = Namespace::getCanonicalIndex( strtolower( $part1 ) );
+                                       if ( !is_null( $index ) ) {
+                                               $text = $linestart . $wgContLang->getNsText( $index );
+                                               $found = true;
+                                       }
+                               }
+                       }
+               }
+
+               # LOCALURL and LOCALURLE
+               if ( !$found ) {
+                       $mwLocal = MagicWord::get( MAG_LOCALURL );
+                       $mwLocalE = MagicWord::get( MAG_LOCALURLE );
+
+                       if ( $mwLocal->matchStartAndRemove( $part1 ) ) {
+                               $func = 'getLocalURL';
+                       } elseif ( $mwLocalE->matchStartAndRemove( $part1 ) ) {
+                               $func = 'escapeLocalURL';
+                       } else {
+                               $func = '';
+                       }
+
+                       if ( $func !== '' ) {
+                               $title = Title::newFromText( $part1 );
+                               if ( !is_null( $title ) ) {
+                                       if ( $argc > 0 ) {
+                                               $text = $linestart . $title->$func( $args[0] );
+                                       } else {
+                                               $text = $linestart . $title->$func();
+                                       }
+                                       $found = true;
+                               }
+                       }
+               }
+
+               # GRAMMAR
+               if ( !$found && $argc == 1 ) {
+                       $mwGrammar =& MagicWord::get( MAG_GRAMMAR );
+                       if ( $mwGrammar->matchStartAndRemove( $part1 ) ) {
+                               $text = $linestart . $wgContLang->convertGrammar( $args[0], $part1 );
+                               $found = true;
+                       }
+               }
+
+               # Template table test
+
+               # Did we encounter this template already? If yes, it is in the cache
+               # and we need to check for loops.
+               if ( !$found && isset( $this->mTemplates[$part1] ) ) {
+                       $found = true;
+
+                       # Infinite loop test
+                       if ( isset( $this->mTemplatePath[$part1] ) ) {
+                               $noparse = true;
+                               $found = true;
+                               $text = $linestart .
+                                       "\{\{$part1}}" .
+                                       '<!-- WARNING: template loop detected -->';
+                               wfDebug( "$fname: template loop broken at '$part1'\n" );
+                       } else {
+                               # set $text to cached message.
+                               $text = $linestart . $this->mTemplates[$part1];
+                       }
+               }
+
+               # Load from database
+               $replaceHeadings = false;
+               $isHTML = false;
+               $lastPathLevel = $this->mTemplatePath;
+               if ( !$found ) {
+                       $ns = NS_TEMPLATE;
+                       $part1 = $this->maybeDoSubpageLink( $part1, $subpage='' );
+                       if ($subpage !== '') {
+                               $ns = $this->mTitle->getNamespace();
+                       }
+                       $title = Title::newFromText( $part1, $ns );
+
+                        if ($title) {
+                            $interwiki = Title::getInterwikiLink($title->getInterwiki());
+                            if ($interwiki != '' && $title->isTrans()) {
+                                    return $this->scarytransclude($title, $interwiki);
+                            }
+                        }
+
+                       if ( !is_null( $title ) && !$title->isExternal() ) {
+                               # Check for excessive inclusion
+                               $dbk = $title->getPrefixedDBkey();
+                               if ( $this->incrementIncludeCount( $dbk ) ) {
+                                       if ( $title->getNamespace() == NS_SPECIAL && $this->mOptions->getAllowSpecialInclusion() ) {
+                                               # Capture special page output
+                                               $text = SpecialPage::capturePath( $title );
+                                               if ( is_string( $text ) ) {
+                                                       $found = true;
+                                                       $noparse = true;
+                                                       $isHTML = true;
+                                                       $this->mOutput->setCacheTime( -1 );
+                                               }
+                                       } else {
+                                               $article = new Article( $title );
+                                               $articleContent = $article->getContentWithoutUsingSoManyDamnGlobals();
+                                               if ( $articleContent !== false ) {
+                                                       $found = true;
+                                                       $text = $articleContent;
+                                                       $replaceHeadings = true;
+                                               }
+                                       }
+                               }
+
+                               # If the title is valid but undisplayable, make a link to it
+                               if ( $this->mOutputType == OT_HTML && !$found ) {
+                                       $text = '[['.$title->getPrefixedText().']]';
+                                       $found = true;
+                               }
+
+                               # Template cache array insertion
+                               if( $found ) {
+                                       $this->mTemplates[$part1] = $text;
+                                       $text = $linestart . $text;
+                               }
+                       }
+               }
+
+               # Recursive parsing, escaping and link table handling
+               # Only for HTML output
+               if ( $nowiki && $found && $this->mOutputType == OT_HTML ) {
+                       $text = wfEscapeWikiText( $text );
+               } elseif ( ($this->mOutputType == OT_HTML || $this->mOutputType == OT_WIKI) && $found && !$noparse) {
+                       # Clean up argument array
+                       $assocArgs = array();
+                       $index = 1;
+                       foreach( $args as $arg ) {
+                               $eqpos = strpos( $arg, '=' );
+                               if ( $eqpos === false ) {
+                                       $assocArgs[$index++] = $arg;
+                               } else {
+                                       $name = trim( substr( $arg, 0, $eqpos ) );
+                                       $value = trim( substr( $arg, $eqpos+1 ) );
+                                       if ( $value === false ) {
+                                               $value = '';
+                                       }
+                                       if ( $name !== false ) {
+                                               $assocArgs[$name] = $value;
+                                       }
+                               }
+                       }
+
+                       # Add a new element to the templace recursion path
+                       $this->mTemplatePath[$part1] = 1;
+
+                       if( $this->mOutputType == OT_HTML ) {
+                               # Remove <noinclude> sections and <includeonly> tags
+                               $text = preg_replace( '/<noinclude>.*?<\/noinclude>/s', '', $text );
+                               $text = strtr( $text, array( '<includeonly>' => '' , '</includeonly>' => '' ) );
+                               # Strip <nowiki>, <pre>, etc.
+                               $text = $this->strip( $text, $this->mStripState );
+                               $text = Sanitizer::removeHTMLtags( $text, array( &$this, 'replaceVariables' ), $assocArgs );
+                       }
+                       $text = $this->replaceVariables( $text, $assocArgs );
+
+                       # Resume the link cache and register the inclusion as a link
+                       if ( $this->mOutputType == OT_HTML && !is_null( $title ) ) {
+                               $wgLinkCache->addLinkObj( $title );
+                       }
+
+                       # If the template begins with a table or block-level
+                       # element, it should be treated as beginning a new line.
+                       if ($linestart !== '\n' && preg_match('/^({\\||:|;|#|\*)/', $text)) {
+                               $text = "\n" . $text;
+                       }
+               }
+               # Prune lower levels off the recursion check path
+               $this->mTemplatePath = $lastPathLevel;
+
+               if ( !$found ) {
+                       wfProfileOut( $fname );
+                       return $matches[0];
+               } else {
+                       if ( $isHTML ) {
+                               # Replace raw HTML by a placeholder
+                               # Add a blank line preceding, to prevent it from mucking up
+                               # immediately preceding headings
+                               $text = "\n\n" . $this->insertStripItem( $text, $this->mStripState );
+                       } else {
+                               # replace ==section headers==
+                               # XXX this needs to go away once we have a better parser.
+                               if ( $this->mOutputType != OT_WIKI && $replaceHeadings ) {
+                                       if( !is_null( $title ) )
+                                               $encodedname = base64_encode($title->getPrefixedDBkey());
+                                       else
+                                               $encodedname = base64_encode("");
+                                       $m = preg_split('/(^={1,6}.*?={1,6}\s*?$)/m', $text, -1,
+                                               PREG_SPLIT_DELIM_CAPTURE);
+                                       $text = '';
+                                       $nsec = 0;
+                                       for( $i = 0; $i < count($m); $i += 2 ) {
+                                               $text .= $m[$i];
+                                               if (!isset($m[$i + 1]) || $m[$i + 1] == "") continue;
+                                               $hl = $m[$i + 1];
+                                               if( strstr($hl, "<!--MWTEMPLATESECTION") ) {
+                                                       $text .= $hl;
+                                                       continue;
+                                               }
+                                               preg_match('/^(={1,6})(.*?)(={1,6})\s*?$/m', $hl, $m2);
+                                               $text .= $m2[1] . $m2[2] . "<!--MWTEMPLATESECTION="
+                                                       . $encodedname . "&" . base64_encode("$nsec") . "-->" . $m2[3];
+
+                                               $nsec++;
+                                       }
+                               }
+                       }
+               }
+
+               # Prune lower levels off the recursion check path
+               $this->mTemplatePath = $lastPathLevel;
+
+               if ( !$found ) {
+                       wfProfileOut( $fname );
+                       return $matches[0];
+               } else {
+                       wfProfileOut( $fname );
+                       return $text;
+               }
+       }
+
+       /**
+        * Translude an interwiki link.
+        */
+       function scarytransclude($title, $interwiki) {
+               global $wgEnableScaryTranscluding;
+
+               if (!$wgEnableScaryTranscluding)
+                       return wfMsg('scarytranscludedisabled');
+
+               $articlename = "Template:" . $title->getDBkey();
+               $url = str_replace('$1', urlencode($articlename), $interwiki);
+               if (strlen($url) > 255)
+                       return wfMsg('scarytranscludetoolong');
+               $text = $this->fetchScaryTemplateMaybeFromCache($url);
+               $this->mIWTransData[] = $text;
+               return "<!--IW_TRANSCLUDE ".(count($this->mIWTransData) - 1)."-->";
+       }
+
+       function fetchScaryTemplateMaybeFromCache($url) {
+               $dbr = wfGetDB(DB_SLAVE);
+               $obj = $dbr->selectRow('transcache', array('tc_time', 'tc_contents'),
+                               array('tc_url' => $url));
+               if ($obj) {
+                       $time = $obj->tc_time;
+                       $text = $obj->tc_contents;
+                       if ($time && $time < (time() + (60*60))) {
+                               return $text;
+                       }
+               }
+
+               $text = wfGetHTTP($url . '?action=render');
+               if (!$text)
+                       return wfMsg('scarytranscludefailed', $url);
+
+               $dbw = wfGetDB(DB_MASTER);
+               $dbw->replace('transcache', array(), array(
+                       'tc_url' => $url,
+                       'tc_time' => time(),
+                       'tc_contents' => $text));
+               return $text;
+       }
+
+
+       /**
+        * Triple brace replacement -- used for template arguments
+        * @access private
+        */
+       function argSubstitution( $matches ) {
+               $arg = trim( $matches[1] );
+               $text = $matches[0];
+               $inputArgs = end( $this->mArgStack );
+
+               if ( array_key_exists( $arg, $inputArgs ) ) {
+                       $text = $inputArgs[$arg];
+               }
+
+               return $text;
+       }
+
+       /**
+        * Returns true if the function is allowed to include this entity
+        * @access private
+        */
+       function incrementIncludeCount( $dbk ) {
+               if ( !array_key_exists( $dbk, $this->mIncludeCount ) ) {
+                       $this->mIncludeCount[$dbk] = 0;
+               }
+               if ( ++$this->mIncludeCount[$dbk] <= MAX_INCLUDE_REPEAT ) {
+                       return true;
+               } else {
+                       return false;
+               }
+       }
+
+       /**
+        * This function accomplishes several tasks:
+        * 1) Auto-number headings if that option is enabled
+        * 2) Add an [edit] link to sections for logged in users who have enabled the option
+        * 3) Add a Table of contents on the top for users who have enabled the option
+        * 4) Auto-anchor headings
+        *
+        * It loops through all headlines, collects the necessary data, then splits up the
+        * string and re-inserts the newly formatted headlines.
+        *
+        * @param string $text
+        * @param boolean $isMain
+        * @access private
+        */
+       function formatHeadings( $text, $isMain=true ) {
+               global $wgMaxTocLevel, $wgContLang, $wgLinkHolders, $wgInterwikiLinkHolders;
+
+               $doNumberHeadings = $this->mOptions->getNumberHeadings();
+               $doShowToc = true;
+               $forceTocHere = false;
+               if( !$this->mTitle->userCanEdit() ) {
+                       $showEditLink = 0;
+               } else {
+                       $showEditLink = $this->mOptions->getEditSection();
+               }
+
+               # Inhibit editsection links if requested in the page
+               $esw =& MagicWord::get( MAG_NOEDITSECTION );
+               if( $esw->matchAndRemove( $text ) ) {
+                       $showEditLink = 0;
+               }
+               # if the string __NOTOC__ (not case-sensitive) occurs in the HTML,
+               # do not add TOC
+               $mw =& MagicWord::get( MAG_NOTOC );
+               if( $mw->matchAndRemove( $text ) ) {
+                       $doShowToc = false;
+               }
+
+               # Get all headlines for numbering them and adding funky stuff like [edit]
+               # links - this is for later, but we need the number of headlines right now
+               $numMatches = preg_match_all( '/<H([1-6])(.*?'.'>)(.*?)<\/H[1-6] *>/i', $text, $matches );
+
+               # if there are fewer than 4 headlines in the article, do not show TOC
+               if( $numMatches < 4 ) {
+                       $doShowToc = false;
+               }
+
+               # if the string __TOC__ (not case-sensitive) occurs in the HTML,
+               # override above conditions and always show TOC at that place
+
+               $mw =& MagicWord::get( MAG_TOC );
+               if($mw->match( $text ) ) {
+                       $doShowToc = true;
+                       $forceTocHere = true;
+               } else {
+                       # if the string __FORCETOC__ (not case-sensitive) occurs in the HTML,
+                       # override above conditions and always show TOC above first header
+                       $mw =& MagicWord::get( MAG_FORCETOC );
+                       if ($mw->matchAndRemove( $text ) ) {
+                               $doShowToc = true;
+                       }
+               }
+
+               # Never ever show TOC if no headers
+               if( $numMatches < 1 ) {
+                       $doShowToc = false;
+               }
+
+               # We need this to perform operations on the HTML
+               $sk =& $this->mOptions->getSkin();
+
+               # headline counter
+               $headlineCount = 0;
+               $sectionCount = 0; # headlineCount excluding template sections
+
+               # Ugh .. the TOC should have neat indentation levels which can be
+               # passed to the skin functions. These are determined here
+               $toc = '';
+               $full = '';
+               $head = array();
+               $sublevelCount = array();
+               $levelCount = array();
+               $toclevel = 0;
+               $level = 0;
+               $prevlevel = 0;
+               $toclevel = 0;
+               $prevtoclevel = 0;
+
+               foreach( $matches[3] as $headline ) {
+                       $istemplate = 0;
+                       $templatetitle = '';
+                       $templatesection = 0;
+                       $numbering = '';
+
+                       if (preg_match("/<!--MWTEMPLATESECTION=([^&]+)&([^_]+)-->/", $headline, $mat)) {
+                               $istemplate = 1;
+                               $templatetitle = base64_decode($mat[1]);
+                               $templatesection = 1 + (int)base64_decode($mat[2]);
+                               $headline = preg_replace("/<!--MWTEMPLATESECTION=([^&]+)&([^_]+)-->/", "", $headline);
+                       }
+
+                       if( $toclevel ) {
+                               $prevlevel = $level;
+                               $prevtoclevel = $toclevel;
+                       }
+                       $level = $matches[1][$headlineCount];
+
+                       if( $doNumberHeadings || $doShowToc ) {
+
+                               if ( $level > $prevlevel ) {
+                                       # Increase TOC level
+                                       $toclevel++;
+                                       $sublevelCount[$toclevel] = 0;
+                                       $toc .= $sk->tocIndent();
+                               }
+                               elseif ( $level < $prevlevel && $toclevel > 1 ) {
+                                       # Decrease TOC level, find level to jump to
+
+                                       if ( $toclevel == 2 && $level <= $levelCount[1] ) {
+                                               # Can only go down to level 1
+                                               $toclevel = 1;
+                                       } else {
+                                               for ($i = $toclevel; $i > 0; $i--) {
+                                                       if ( $levelCount[$i] == $level ) {
+                                                               # Found last matching level
+                                                               $toclevel = $i;
+                                                               break;
+                                                       }
+                                                       elseif ( $levelCount[$i] < $level ) {
+                                                               # Found first matching level below current level
+                                                               $toclevel = $i + 1;
+                                                               break;
+                                                       }
+                                               }
+                                       }
+
+                                       $toc .= $sk->tocUnindent( $prevtoclevel - $toclevel );
+                               }
+                               else {
+                                       # No change in level, end TOC line
+                                       $toc .= $sk->tocLineEnd();
+                               }
+
+                               $levelCount[$toclevel] = $level;
+
+                               # count number of headlines for each level
+                               @$sublevelCount[$toclevel]++;
+                               $dot = 0;
+                               for( $i = 1; $i <= $toclevel; $i++ ) {
+                                       if( !empty( $sublevelCount[$i] ) ) {
+                                               if( $dot ) {
+                                                       $numbering .= '.';
+                                               }
+                                               $numbering .= $wgContLang->formatNum( $sublevelCount[$i] );
+                                               $dot = 1;
+                                       }
+                               }
+                       }
+
+                       # The canonized header is a version of the header text safe to use for links
+                       # Avoid insertion of weird stuff like <math> by expanding the relevant sections
+                       $canonized_headline = $this->unstrip( $headline, $this->mStripState );
+                       $canonized_headline = $this->unstripNoWiki( $canonized_headline, $this->mStripState );
+
+                       # Remove link placeholders by the link text.
+                       #     <!--LINK number-->
+                       # turns into
+                       #     link text with suffix
+                       $canonized_headline = preg_replace( '/<!--LINK ([0-9]*)-->/e',
+                                                           "\$this->mLinkHolders['texts'][\$1]",
+                                                           $canonized_headline );
+                       $canonized_headline = preg_replace( '/<!--IWLINK ([0-9]*)-->/e',
+                                                           "\$this->mInterwikiLinkHolders['texts'][\$1]",
+                                                           $canonized_headline );
+
+                       # strip out HTML
+                       $canonized_headline = preg_replace( '/<.*?' . '>/','',$canonized_headline );
+                       $tocline = trim( $canonized_headline );
+                       $canonized_headline = urlencode( Sanitizer::decodeCharReferences( str_replace(' ', '_', $tocline) ) );
+                       $replacearray = array(
+                               '%3A' => ':',
+                               '%' => '.'
+                       );
+                       $canonized_headline = str_replace(array_keys($replacearray),array_values($replacearray),$canonized_headline);
+                       $refers[$headlineCount] = $canonized_headline;
+
+                       # count how many in assoc. array so we can track dupes in anchors
+                       @$refers[$canonized_headline]++;
+                       $refcount[$headlineCount]=$refers[$canonized_headline];
+
+                       # Don't number the heading if it is the only one (looks silly)
+                       if( $doNumberHeadings && count( $matches[3] ) > 1) {
+                               # the two are different if the line contains a link
+                               $headline=$numbering . ' ' . $headline;
+                       }
+
+                       # Create the anchor for linking from the TOC to the section
+                       $anchor = $canonized_headline;
+                       if($refcount[$headlineCount] > 1 ) {
+                               $anchor .= '_' . $refcount[$headlineCount];
+                       }
+                       if( $doShowToc && ( !isset($wgMaxTocLevel) || $toclevel<$wgMaxTocLevel ) ) {
+                               $toc .= $sk->tocLine($anchor, $tocline, $numbering, $toclevel);
+                       }
+                       if( $showEditLink && ( !$istemplate || $templatetitle !== "" ) ) {
+                               if ( empty( $head[$headlineCount] ) ) {
+                                       $head[$headlineCount] = '';
+                               }
+                               if( $istemplate )
+                                       $head[$headlineCount] .= $sk->editSectionLinkForOther($templatetitle, $templatesection);
+                               else
+                                       $head[$headlineCount] .= $sk->editSectionLink($this->mTitle, $sectionCount+1);
+                       }
+
+                       # give headline the correct <h#> tag
+                       @$head[$headlineCount] .= "<a name=\"$anchor\"></a><h".$level.$matches[2][$headlineCount] .$headline.'</h'.$level.'>';
+
+                       $headlineCount++;
+                       if( !$istemplate )
+                               $sectionCount++;
+               }
+
+               if( $doShowToc ) {
+                       $toc .= $sk->tocUnindent( $toclevel - 1 );
+                       $toc = $sk->tocList( $toc );
+               }
+
+               # split up and insert constructed headlines
+
+               $blocks = preg_split( '/<H[1-6].*?' . '>.*?<\/H[1-6]>/i', $text );
+               $i = 0;
+
+               foreach( $blocks as $block ) {
+                       if( $showEditLink && $headlineCount > 0 && $i == 0 && $block != "\n" ) {
+                               # This is the [edit] link that appears for the top block of text when
+                               # section editing is enabled
+
+                               # Disabled because it broke block formatting
+                               # For example, a bullet point in the top line
+                               # $full .= $sk->editSectionLink(0);
+                       }
+                       $full .= $block;
+                       if( $doShowToc && !$i && $isMain && !$forceTocHere) {
+                       # Top anchor now in skin
+                               $full = $full.$toc;
+                       }
+
+                       if( !empty( $head[$i] ) ) {
+                               $full .= $head[$i];
+                       }
+                       $i++;
+               }
+               if($forceTocHere) {
+                       $mw =& MagicWord::get( MAG_TOC );
+                       return $mw->replace( $toc, $full );
+               } else {
+                       return $full;
+               }
+       }
+
+       /**
+        * Return an HTML link for the "ISBN 123456" text
+        * @access private
+        */
+       function magicISBN( $text ) {
+               $fname = 'Parser::magicISBN';
+               wfProfileIn( $fname );
+
+               $a = split( 'ISBN ', ' '.$text );
+               if ( count ( $a ) < 2 ) {
+                       wfProfileOut( $fname );
+                       return $text;
+               }
+               $text = substr( array_shift( $a ), 1);
+               $valid = '0123456789-Xx';
+
+               foreach ( $a as $x ) {
+                       $isbn = $blank = '' ;
+                       while ( ' ' == $x{0} ) {
+                               $blank .= ' ';
+                               $x = substr( $x, 1 );
+                       }
+                       if ( $x == '' ) { # blank isbn
+                               $text .= "ISBN $blank";
+                               continue;
+                       }
+                       while ( strstr( $valid, $x{0} ) != false ) {
+                               $isbn .= $x{0};
+                               $x = substr( $x, 1 );
+                       }
+                       $num = str_replace( '-', '', $isbn );
+                       $num = str_replace( ' ', '', $num );
+                       $num = str_replace( 'x', 'X', $num );
+
+                       if ( '' == $num ) {
+                               $text .= "ISBN $blank$x";
+                       } else {
+                               $titleObj = Title::makeTitle( NS_SPECIAL, 'Booksources' );
+                               $text .= '<a href="' .
+                               $titleObj->escapeLocalUrl( 'isbn='.$num ) .
+                                       "\" class=\"internal\">ISBN $isbn</a>";
+                               $text .= $x;
+                       }
+               }
+               wfProfileOut( $fname );
+               return $text;
+       }
+
+       /**
+        * Return an HTML link for the "RFC 1234" text
+        *
+        * @access private
+        * @param string $text     Text to be processed
+        * @param string $keyword  Magic keyword to use (default RFC)
+        * @param string $urlmsg   Interface message to use (default rfcurl)
+        * @return string
+        */
+       function magicRFC( $text, $keyword='RFC ', $urlmsg='rfcurl'  ) {
+
+               $valid = '0123456789';
+               $internal = false;
+
+               $a = split( $keyword, ' '.$text );
+               if ( count ( $a ) < 2 ) {
+                       return $text;
+               }
+               $text = substr( array_shift( $a ), 1);
+
+               /* Check if keyword is preceed by [[.
+                * This test is made here cause of the array_shift above
+                * that prevent the test to be done in the foreach.
+                */
+               if ( substr( $text, -2 ) == '[[' ) {
+                       $internal = true;
+               }
+
+               foreach ( $a as $x ) {
+                       /* token might be empty if we have RFC RFC 1234 */
+                       if ( $x=='' ) {
+                               $text.=$keyword;
+                               continue;
+                               }
+
+                       $id = $blank = '' ;
+
+                       /** remove and save whitespaces in $blank */
+                       while ( $x{0} == ' ' ) {
+                               $blank .= ' ';
+                               $x = substr( $x, 1 );
+                       }
+
+                       /** remove and save the rfc number in $id */
+                       while ( strstr( $valid, $x{0} ) != false ) {
+                               $id .= $x{0};
+                               $x = substr( $x, 1 );
+                       }
+
+                       if ( $id == '' ) {
+                               /* call back stripped spaces*/
+                               $text .= $keyword.$blank.$x;
+                       } elseif( $internal ) {
+                               /* normal link */
+                               $text .= $keyword.$id.$x;
+                       } else {
+                               /* build the external link*/
+                               $url = wfMsg( $urlmsg, $id);
+                               $sk =& $this->mOptions->getSkin();
+                               $la = $sk->getExternalLinkAttributes( $url, $keyword.$id );
+                               $text .= "<a href='{$url}'{$la}>{$keyword}{$id}</a>{$x}";
+                       }
+
+                       /* Check if the next RFC keyword is preceed by [[ */
+                       $internal = ( substr($x,-2) == '[[' );
+               }
+               return $text;
+       }
+
+       /**
+        * Transform wiki markup when saving a page by doing \r\n -> \n
+        * conversion, substitting signatures, {{subst:}} templates, etc.
+        *
+        * @param string $text the text to transform
+        * @param Title &$title the Title object for the current article
+        * @param User &$user the User object describing the current user
+        * @param ParserOptions $options parsing options
+        * @param bool $clearState whether to clear the parser state first
+        * @return string the altered wiki markup
+        * @access public
+        */
+       function preSaveTransform( $text, &$title, &$user, $options, $clearState = true ) {
+               $this->mOptions = $options;
+               $this->mTitle =& $title;
+               $this->mOutputType = OT_WIKI;
+
+               if ( $clearState ) {
+                       $this->clearState();
+               }
+
+               $stripState = false;
+               $pairs = array(
+                       "\r\n" => "\n",
+               );
+               $text = str_replace( array_keys( $pairs ), array_values( $pairs ), $text );
+               $text = $this->strip( $text, $stripState, false );
+               $text = $this->pstPass2( $text, $user );
+               $text = $this->unstrip( $text, $stripState );
+               $text = $this->unstripNoWiki( $text, $stripState );
+               return $text;
+       }
+
+       /**
+        * Pre-save transform helper function
+        * @access private
+        */
+       function pstPass2( $text, &$user ) {
+               global $wgContLang, $wgLocaltimezone;
+
+               # Variable replacement
+               # Because mOutputType is OT_WIKI, this will only process {{subst:xxx}} type tags
+               $text = $this->replaceVariables( $text );
+
+               # Signatures
+               #
+               $n = $user->getName();
+               $k = $user->getOption( 'nickname' );
+               if ( '' == $k ) { $k = $n; }
+               if ( isset( $wgLocaltimezone ) ) {
+                       $oldtz = getenv( 'TZ' );
+                       putenv( 'TZ='.$wgLocaltimezone );
+               }
+
+               /* Note: This is the timestamp saved as hardcoded wikitext to
+                * the database, we use $wgContLang here in order to give
+                * everyone the same signiture and use the default one rather
+                * than the one selected in each users preferences.
+                */
+               $d = $wgContLang->timeanddate( date( 'YmdHis' ), false, false) .
+                 ' (' . date( 'T' ) . ')';
+               if ( isset( $wgLocaltimezone ) ) {
+                       putenv( 'TZ='.$oldtz );
+               }
+
+               if( $user->getOption( 'fancysig' ) ) {
+                       $sigText = $k;
+               } else {
+                       $sigText = '[[' . $wgContLang->getNsText( NS_USER ) . ":$n|$k]]";
+               }
+               $text = preg_replace( '/~~~~~/', $d, $text );
+               $text = preg_replace( '/~~~~/', "$sigText $d", $text );
+               $text = preg_replace( '/~~~/', $sigText, $text );
+
+               # Context links: [[|name]] and [[name (context)|]]
+               #
+               $tc = "[&;%\\-,.\\(\\)' _0-9A-Za-z\\/:\\x80-\\xff]";
+               $np = "[&;%\\-,.' _0-9A-Za-z\\/:\\x80-\\xff]"; # No parens
+               $namespacechar = '[ _0-9A-Za-z\x80-\xff]'; # Namespaces can use non-ascii!
+               $conpat = "/^({$np}+) \\(({$tc}+)\\)$/";
+
+               $p1 = "/\[\[({$np}+) \\(({$np}+)\\)\\|]]/";             # [[page (context)|]]
+               $p2 = "/\[\[\\|({$tc}+)]]/";                                    # [[|page]]
+               $p3 = "/\[\[(:*$namespacechar+):({$np}+)\\|]]/";                # [[namespace:page|]] and [[:namespace:page|]]
+               $p4 = "/\[\[(:*$namespacechar+):({$np}+) \\(({$np}+)\\)\\|]]/"; # [[ns:page (cont)|]] and [[:ns:page (cont)|]]
+               $context = '';
+               $t = $this->mTitle->getText();
+               if ( preg_match( $conpat, $t, $m ) ) {
+                       $context = $m[2];
+               }
+               $text = preg_replace( $p4, '[[\\1:\\2 (\\3)|\\2]]', $text );
+               $text = preg_replace( $p1, '[[\\1 (\\2)|\\1]]', $text );
+               $text = preg_replace( $p3, '[[\\1:\\2|\\2]]', $text );
+
+               if ( '' == $context ) {
+                       $text = preg_replace( $p2, '[[\\1]]', $text );
+               } else {
+                       $text = preg_replace( $p2, "[[\\1 ({$context})|\\1]]", $text );
+               }
+
+               # Trim trailing whitespace
+               # MAG_END (__END__) tag allows for trailing
+               # whitespace to be deliberately included
+               $text = rtrim( $text );
+               $mw =& MagicWord::get( MAG_END );
+               $mw->matchAndRemove( $text );
+
+               return $text;
+       }
+
+       /**
+        * Set up some variables which are usually set up in parse()
+        * so that an external function can call some class members with confidence
+        * @access public
+        */
+       function startExternalParse( &$title, $options, $outputType, $clearState = true ) {
+               $this->mTitle =& $title;
+               $this->mOptions = $options;
+               $this->mOutputType = $outputType;
+               if ( $clearState ) {
+                       $this->clearState();
+               }
+       }
+
+       /**
+        * Transform a MediaWiki message by replacing magic variables.
+        *
+        * @param string $text the text to transform
+        * @param ParserOptions $options  options
+        * @return string the text with variables substituted
+        * @access public
+        */
+       function transformMsg( $text, $options ) {
+               global $wgTitle;
+               static $executing = false;
+
+               # Guard against infinite recursion
+               if ( $executing ) {
+                       return $text;
+               }
+               $executing = true;
+
+               $this->mTitle = $wgTitle;
+               $this->mOptions = $options;
+               $this->mOutputType = OT_MSG;
+               $this->clearState();
+               $text = $this->replaceVariables( $text );
+
+               $executing = false;
+               return $text;
+       }
+
+       /**
+        * Create an HTML-style tag, e.g. <yourtag>special text</yourtag>
+        * Callback will be called with the text within
+        * Transform and return the text within
+        * @access public
+        */
+       function setHook( $tag, $callback ) {
+               $oldVal = @$this->mTagHooks[$tag];
+               $this->mTagHooks[$tag] = $callback;
+               return $oldVal;
+       }
+
+       /**
+        * Replace <!--LINK--> link placeholders with actual links, in the buffer
+        * Placeholders created in Skin::makeLinkObj()
+        * Returns an array of links found, indexed by PDBK:
+        *  0 - broken
+        *  1 - normal link
+        *  2 - stub
+        * $options is a bit field, RLH_FOR_UPDATE to select for update
+        */
+       function replaceLinkHolders( &$text, $options = 0 ) {
+               global $wgUser, $wgLinkCache;
+               global $wgOutputReplace;
+
+               $fname = 'Parser::replaceLinkHolders';
+               wfProfileIn( $fname );
+
+               $pdbks = array();
+               $colours = array();
+               $sk = $this->mOptions->getSkin();
+
+               if ( !empty( $this->mLinkHolders['namespaces'] ) ) {
+                       wfProfileIn( $fname.'-check' );
+                       $dbr =& wfGetDB( DB_SLAVE );
+                       $page = $dbr->tableName( 'page' );
+                       $threshold = $wgUser->getOption('stubthreshold');
+
+                       # Sort by namespace
+                       asort( $this->mLinkHolders['namespaces'] );
+
+                       # Generate query
+                       $query = false;
+                       foreach ( $this->mLinkHolders['namespaces'] as $key => $val ) {
+                               # Make title object
+                               $title = $this->mLinkHolders['titles'][$key];
+
+                               # Skip invalid entries.
+                               # Result will be ugly, but prevents crash.
+                               if ( is_null( $title ) ) {
+                                       continue;
+                               }
+                               $pdbk = $pdbks[$key] = $title->getPrefixedDBkey();
+
+                               # Check if it's in the link cache already
+                               if ( $wgLinkCache->getGoodLinkID( $pdbk ) ) {
+                                       $colours[$pdbk] = 1;
+                               } elseif ( $wgLinkCache->isBadLink( $pdbk ) ) {
+                                       $colours[$pdbk] = 0;
+                               } else {
+                                       # Not in the link cache, add it to the query
+                                       if ( !isset( $current ) ) {
+                                               $current = $val;
+                                               $query =  "SELECT page_id, page_namespace, page_title";
+                                               if ( $threshold > 0 ) {
+                                                       $query .= ', page_len, page_is_redirect';
+                                               }
+                                               $query .= " FROM $page WHERE (page_namespace=$val AND page_title IN(";
+                                       } elseif ( $current != $val ) {
+                                               $current = $val;
+                                               $query .= ")) OR (page_namespace=$val AND page_title IN(";
+                                       } else {
+                                               $query .= ', ';
+                                       }
+
+                                       $query .= $dbr->addQuotes( $this->mLinkHolders['dbkeys'][$key] );
+                               }
+                       }
+                       if ( $query ) {
+                               $query .= '))';
+                               if ( $options & RLH_FOR_UPDATE ) {
+                                       $query .= ' FOR UPDATE';
+                               }
+
+                               $res = $dbr->query( $query, $fname );
+
+                               # Fetch data and form into an associative array
+                               # non-existent = broken
+                               # 1 = known
+                               # 2 = stub
+                               while ( $s = $dbr->fetchObject($res) ) {
+                                       $title = Title::makeTitle( $s->page_namespace, $s->page_title );
+                                       $pdbk = $title->getPrefixedDBkey();
+                                       $wgLinkCache->addGoodLinkObj( $s->page_id, $title );
+
+                                       if ( $threshold >  0 ) {
+                                               $size = $s->page_len;
+                                               if ( $s->page_is_redirect || $s->page_namespace != 0 || $size >= $threshold ) {
+                                                       $colours[$pdbk] = 1;
+                                               } else {
+                                                       $colours[$pdbk] = 2;
+                                               }
+                                       } else {
+                                               $colours[$pdbk] = 1;
+                                       }
+                               }
+                       }
+                       wfProfileOut( $fname.'-check' );
+
+                       # Construct search and replace arrays
+                       wfProfileIn( $fname.'-construct' );
+                       $wgOutputReplace = array();
+                       foreach ( $this->mLinkHolders['namespaces'] as $key => $ns ) {
+                               $pdbk = $pdbks[$key];
+                               $searchkey = "<!--LINK $key-->";
+                               $title = $this->mLinkHolders['titles'][$key];
+                               if ( empty( $colours[$pdbk] ) ) {
+                                       $wgLinkCache->addBadLinkObj( $title );
+                                       $colours[$pdbk] = 0;
+                                       $wgOutputReplace[$searchkey] = $sk->makeBrokenLinkObj( $title,
+                                                                       $this->mLinkHolders['texts'][$key],
+                                                                       $this->mLinkHolders['queries'][$key] );
+                               } elseif ( $colours[$pdbk] == 1 ) {
+                                       $wgOutputReplace[$searchkey] = $sk->makeKnownLinkObj( $title,
+                                                                       $this->mLinkHolders['texts'][$key],
+                                                                       $this->mLinkHolders['queries'][$key] );
+                               } elseif ( $colours[$pdbk] == 2 ) {
+                                       $wgOutputReplace[$searchkey] = $sk->makeStubLinkObj( $title,
+                                                                       $this->mLinkHolders['texts'][$key],
+                                                                       $this->mLinkHolders['queries'][$key] );
+                               }
+                       }
+                       wfProfileOut( $fname.'-construct' );
+
+                       # Do the thing
+                       wfProfileIn( $fname.'-replace' );
+
+                       $text = preg_replace_callback(
+                               '/(<!--LINK .*?-->)/',
+                               "wfOutputReplaceMatches",
+                               $text);
+
+                       wfProfileOut( $fname.'-replace' );
+               }
+
+               # Now process interwiki link holders
+               # This is quite a bit simpler than internal links
+               if ( !empty( $this->mInterwikiLinkHolders['texts'] ) ) {
+                       wfProfileIn( $fname.'-interwiki' );
+                       # Make interwiki link HTML
+                       $wgOutputReplace = array();
+                       foreach( $this->mInterwikiLinkHolders['texts'] as $key => $link ) {
+                               $title = $this->mInterwikiLinkHolders['titles'][$key];
+                               $wgOutputReplace[$key] = $sk->makeLinkObj( $title, $link );
+                       }
+
+                       $text = preg_replace_callback(
+                               '/<!--IWLINK (.*?)-->/',
+                               "wfOutputReplaceMatches",
+                               $text );
+                       wfProfileOut( $fname.'-interwiki' );
+               }
+
+               wfProfileOut( $fname );
+               return $colours;
+       }
+
+       /**
+        * Replace <!--LINK--> link placeholders with plain text of links
+        * (not HTML-formatted).
+        * @param string $text
+        * @return string
+        */
+       function replaceLinkHoldersText( $text ) {
+               global $wgUser, $wgLinkCache;
+               global $wgOutputReplace;
+
+               $fname = 'Parser::replaceLinkHoldersText';
+               wfProfileIn( $fname );
+
+               $text = preg_replace_callback(
+                       '/<!--(LINK|IWLINK) (.*?)-->/',
+                       array( &$this, 'replaceLinkHoldersTextCallback' ),
+                       $text );
+
+               wfProfileOut( $fname );
+               return $text;
+       }
+
+       /**
+        * @param array $matches
+        * @return string
+        * @access private
+        */
+       function replaceLinkHoldersTextCallback( $matches ) {
+               $type = $matches[1];
+               $key  = $matches[2];
+               if( $type == 'LINK' ) {
+                       if( isset( $this->mLinkHolders['texts'][$key] ) ) {
+                               return $this->mLinkHolders['texts'][$key];
+                       }
+               } elseif( $type == 'IWLINK' ) {
+                       if( isset( $this->mInterwikiLinkHolders['texts'][$key] ) ) {
+                               return $this->mInterwikiLinkHolders['texts'][$key];
+                       }
+               }
+               return $matches[0];
+       }
+
+       /**
+        * Renders an image gallery from a text with one line per image.
+        * text labels may be given by using |-style alternative text. E.g.
+        *   Image:one.jpg|The number "1"
+        *   Image:tree.jpg|A tree
+        * given as text will return the HTML of a gallery with two images,
+        * labeled 'The number "1"' and
+        * 'A tree'.
+        *
+        * @static
+        */
+       function renderImageGallery( $text ) {
+               # Setup the parser
+               global $wgUser, $wgTitle;
+               $parserOptions = ParserOptions::newFromUser( $wgUser );
+               $localParser = new Parser();
+
+               global $wgLinkCache;
+               $ig = new ImageGallery();
+               $ig->setShowBytes( false );
+               $ig->setShowFilename( false );
+               $lines = explode( "\n", $text );
+
+               foreach ( $lines as $line ) {
+                       # match lines like these:
+                       # Image:someimage.jpg|This is some image
+                       preg_match( "/^([^|]+)(\\|(.*))?$/", $line, $matches );
+                       # Skip empty lines
+                       if ( count( $matches ) == 0 ) {
+                               continue;
+                       }
+                       $nt = Title::newFromURL( $matches[1] );
+                       if( is_null( $nt ) ) {
+                               # Bogus title. Ignore these so we don't bomb out later.
+                               continue;
+                       }
+                       if ( isset( $matches[3] ) ) {
+                               $label = $matches[3];
+                       } else {
+                               $label = '';
+                       }
+
+                       $html = $localParser->parse( $label , $wgTitle, $parserOptions );
+                       $html = $html->mText;
+
+                       $ig->add( new Image( $nt ), $html );
+                       $wgLinkCache->addImageLinkObj( $nt );
+               }
+               return $ig->toHTML();
+       }
+
+       /**
+        * Parse image options text and use it to make an image
+        */
+       function makeImage( &$nt, $options ) {
+               global $wgContLang, $wgUseImageResize;
+               global $wgUser, $wgThumbLimits;
+
+               $align = '';
+
+               # Check if the options text is of the form "options|alt text"
+               # Options are:
+               #  * thumbnail          make a thumbnail with enlarge-icon and caption, alignment depends on lang
+               #  * left               no resizing, just left align. label is used for alt= only
+               #  * right              same, but right aligned
+               #  * none               same, but not aligned
+               #  * ___px              scale to ___ pixels width, no aligning. e.g. use in taxobox
+               #  * center             center the image
+               #  * framed             Keep original image size, no magnify-button.
+
+               $part = explode( '|', $options);
+
+               $mwThumb  =& MagicWord::get( MAG_IMG_THUMBNAIL );
+               $mwLeft   =& MagicWord::get( MAG_IMG_LEFT );
+               $mwRight  =& MagicWord::get( MAG_IMG_RIGHT );
+               $mwNone   =& MagicWord::get( MAG_IMG_NONE );
+               $mwWidth  =& MagicWord::get( MAG_IMG_WIDTH );
+               $mwCenter =& MagicWord::get( MAG_IMG_CENTER );
+               $mwFramed =& MagicWord::get( MAG_IMG_FRAMED );
+               $caption = '';
+
+               $width = $height = $framed = $thumb = false;
+               $manual_thumb = '' ;
+
+               foreach( $part as $key => $val ) {
+                       $val_parts = explode ( '=' , $val , 2 ) ;
+                       $left_part = array_shift ( $val_parts ) ;
+                       if ( $wgUseImageResize && ! is_null( $mwThumb->matchVariableStartToEnd($val) ) ) {
+                               $thumb=true;
+                       } elseif ( $wgUseImageResize && count ( $val_parts ) == 1 && ! is_null( $mwThumb->matchVariableStartToEnd($left_part) ) ) {
+                               # use manually specified thumbnail
+                               $thumb=true;
+                               $manual_thumb = array_shift ( $val_parts ) ;
+                       } elseif ( ! is_null( $mwRight->matchVariableStartToEnd($val) ) ) {
+                               # remember to set an alignment, don't render immediately
+                               $align = 'right';
+                       } elseif ( ! is_null( $mwLeft->matchVariableStartToEnd($val) ) ) {
+                               # remember to set an alignment, don't render immediately
+                               $align = 'left';
+                       } elseif ( ! is_null( $mwCenter->matchVariableStartToEnd($val) ) ) {
+                               # remember to set an alignment, don't render immediately
+                               $align = 'center';
+                       } elseif ( ! is_null( $mwNone->matchVariableStartToEnd($val) ) ) {
+                               # remember to set an alignment, don't render immediately
+                               $align = 'none';
+                       } elseif ( $wgUseImageResize && ! is_null( $match = $mwWidth->matchVariableStartToEnd($val) ) ) {
+                               wfDebug( "MAG_IMG_WIDTH match: $match\n" );
+                               # $match is the image width in pixels
+                               if ( preg_match( '/^([0-9]*)x([0-9]*)$/', $match, $m ) ) {
+                                       $width = intval( $m[1] );
+                                       $height = intval( $m[2] );
+                               } else {
+                                       $width = intval($match);
+                               }
+                       } elseif ( ! is_null( $mwFramed->matchVariableStartToEnd($val) ) ) {
+                               $framed=true;
+                       } else {
+                               $caption = $val;
+                       }
+               }
+               # Strip bad stuff out of the alt text
+               $alt = $this->replaceLinkHoldersText( $caption );
+               $alt = Sanitizer::stripAllTags( $alt );
+
+               # Linker does the rest
+               $sk =& $this->mOptions->getSkin();
+               return $sk->makeImageLinkObj( $nt, $caption, $alt, $align, $width, $height, $framed, $thumb, $manual_thumb );
+       }
+
+       /**
+        * Set a flag in the output object indicating that the content is dynamic and 
+        * shouldn't be cached.
+        */
+       function disableCache() {
+               $this->mOutput->mCacheTime = -1;
+       }
+       
+       /**
+        * Callback from the Sanitizer for expanding items found in HTML attribute
+        * values, so they can be safely tested and escaped.
+        * @param string $text
+        * @param array $args
+        * @return string
+        * @access private
+        */
+       function attributeStripCallback( &$text, $args ) {
+               $text = $this->replaceVariables( $text, $args );
+               $text = $this->unstripForHTML( $text );
+               return $text;
+       }
+       
+       function unstripForHTML( $text ) {
+               $text = $this->unstrip( $text, $this->mStripState );
+               $text = $this->unstripNoWiki( $text, $this->mStripState );
+               return $text;
+       }
+}
+
+/**
+ * @todo document
+ * @package MediaWiki
+ */
+class ParserOutput
+{
+       var $mText, $mLanguageLinks, $mCategoryLinks, $mContainsOldMagic;
+       var $mCacheTime; # Timestamp on this article, or -1 for uncacheable. Used in ParserCache.
+       var $mVersion;   # Compatibility check
+       var $mTitleText; # title text of the chosen language variant
+
+       function ParserOutput( $text = '', $languageLinks = array(), $categoryLinks = array(),
+               $containsOldMagic = false, $titletext = '' )
+       {
+               $this->mText = $text;
+               $this->mLanguageLinks = $languageLinks;
+               $this->mCategoryLinks = $categoryLinks;
+               $this->mContainsOldMagic = $containsOldMagic;
+               $this->mCacheTime = '';
+               $this->mVersion = MW_PARSER_VERSION;
+               $this->mTitleText = $titletext;
+       }
+
+       function getText()                   { return $this->mText; }
+       function getLanguageLinks()          { return $this->mLanguageLinks; }
+       function getCategoryLinks()          { return array_keys( $this->mCategoryLinks ); }
+       function getCacheTime()              { return $this->mCacheTime; }
+       function getTitleText()              { return $this->mTitleText; }
+       function containsOldMagic()          { return $this->mContainsOldMagic; }
+       function setText( $text )            { return wfSetVar( $this->mText, $text ); }
+       function setLanguageLinks( $ll )     { return wfSetVar( $this->mLanguageLinks, $ll ); }
+       function setCategoryLinks( $cl )     { return wfSetVar( $this->mCategoryLinks, $cl ); }
+       function setContainsOldMagic( $com ) { return wfSetVar( $this->mContainsOldMagic, $com ); }
+       function setCacheTime( $t )          { return wfSetVar( $this->mCacheTime, $t ); }
+       function setTitleText( $t )          { return wfSetVar ($this->mTitleText, $t); }
+
+       function addCategoryLink( $c )       { $this->mCategoryLinks[$c] = 1; }
+
+       function merge( $other ) {
+               $this->mLanguageLinks = array_merge( $this->mLanguageLinks, $other->mLanguageLinks );
+               $this->mCategoryLinks = array_merge( $this->mCategoryLinks, $this->mLanguageLinks );
+               $this->mContainsOldMagic = $this->mContainsOldMagic || $other->mContainsOldMagic;
+       }
+
+       /**
+        * Return true if this cached output object predates the global or
+        * per-article cache invalidation timestamps, or if it comes from
+        * an incompatible older version.
+        *
+        * @param string $touched the affected article's last touched timestamp
+        * @return bool
+        * @access public
+        */
+       function expired( $touched ) {
+               global $wgCacheEpoch;
+               return $this->getCacheTime() == -1 || // parser says it's uncacheable
+                      $this->getCacheTime() <= $touched ||
+                      $this->getCacheTime() <= $wgCacheEpoch ||
+                      !isset( $this->mVersion ) ||
+                      version_compare( $this->mVersion, MW_PARSER_VERSION, "lt" );
+       }
+}
+
+/**
+ * Set options of the Parser
+ * @todo document
+ * @package MediaWiki
+ */
+class ParserOptions
+{
+       # All variables are private
+       var $mUseTeX;                    # Use texvc to expand <math> tags
+       var $mUseDynamicDates;           # Use DateFormatter to format dates
+       var $mInterwikiMagic;            # Interlanguage links are removed and returned in an array
+       var $mAllowExternalImages;       # Allow external images inline
+       var $mSkin;                      # Reference to the preferred skin
+       var $mDateFormat;                # Date format index
+       var $mEditSection;               # Create "edit section" links
+       var $mNumberHeadings;            # Automatically number headings
+       var $mAllowSpecialInclusion;     # Allow inclusion of special pages
+
+       function getUseTeX()                        { return $this->mUseTeX; }
+       function getUseDynamicDates()               { return $this->mUseDynamicDates; }
+       function getInterwikiMagic()                { return $this->mInterwikiMagic; }
+       function getAllowExternalImages()           { return $this->mAllowExternalImages; }
+       function &getSkin()                         { return $this->mSkin; }
+       function getDateFormat()                    { return $this->mDateFormat; }
+       function getEditSection()                   { return $this->mEditSection; }
+       function getNumberHeadings()                { return $this->mNumberHeadings; }
+       function getAllowSpecialInclusion()         { return $this->mAllowSpecialInclusion; }
+
+
+       function setUseTeX( $x )                    { return wfSetVar( $this->mUseTeX, $x ); }
+       function setUseDynamicDates( $x )           { return wfSetVar( $this->mUseDynamicDates, $x ); }
+       function setInterwikiMagic( $x )            { return wfSetVar( $this->mInterwikiMagic, $x ); }
+       function setAllowExternalImages( $x )       { return wfSetVar( $this->mAllowExternalImages, $x ); }
+       function setDateFormat( $x )                { return wfSetVar( $this->mDateFormat, $x ); }
+       function setEditSection( $x )               { return wfSetVar( $this->mEditSection, $x ); }
+       function setNumberHeadings( $x )            { return wfSetVar( $this->mNumberHeadings, $x ); }
+       function setAllowSpecialInclusion( $x )     { return wfSetVar( $this->mAllowSpecialInclusion, $x ); }
+
+       function setSkin( &$x ) { $this->mSkin =& $x; }
+
+       function ParserOptions() {
+               global $wgUser;
+               $this->initialiseFromUser( $wgUser );
+       }
+
+       /**
+        * Get parser options
+        * @static
+        */
+       function newFromUser( &$user ) {
+               $popts = new ParserOptions;
+               $popts->initialiseFromUser( $user );
+               return $popts;
+       }
+
+       /** Get user options */
+       function initialiseFromUser( &$userInput ) {
+               global $wgUseTeX, $wgUseDynamicDates, $wgInterwikiMagic, $wgAllowExternalImages,
+                      $wgAllowSpecialInclusion;
+               $fname = 'ParserOptions::initialiseFromUser';
+               wfProfileIn( $fname );
+               if ( !$userInput ) {
+                       $user = new User;
+                       $user->setLoaded( true );
+               } else {
+                       $user =& $userInput;
+               }
+
+               $this->mUseTeX = $wgUseTeX;
+               $this->mUseDynamicDates = $wgUseDynamicDates;
+               $this->mInterwikiMagic = $wgInterwikiMagic;
+               $this->mAllowExternalImages = $wgAllowExternalImages;
+               wfProfileIn( $fname.'-skin' );
+               $this->mSkin =& $user->getSkin();
+               wfProfileOut( $fname.'-skin' );
+               $this->mDateFormat = $user->getOption( 'date' );
+               $this->mEditSection = true;
+               $this->mNumberHeadings = $user->getOption( 'numberheadings' );
+               $this->mAllowSpecialInclusion = $wgAllowSpecialInclusion;
+               wfProfileOut( $fname );
+       }
+}
+
+/**
+ * Callback function used by Parser::replaceLinkHolders()
+ * to substitute link placeholders.
+ */
+function &wfOutputReplaceMatches( $matches ) {
+       global $wgOutputReplace;
+       return $wgOutputReplace[$matches[1]];
+}
+
+/**
+ * Return the total number of articles
+ */
+function wfNumberOfArticles() {
+       global $wgNumberOfArticles;
+
+       wfLoadSiteStats();
+       return $wgNumberOfArticles;
+}
+
+/**
+ * Return the number of files
+ */
+function wfNumberOfFiles() {
+       $fname = 'Parser::wfNumberOfFiles';
+
+       wfProfileIn( $fname );
+       $dbr =& wfGetDB( DB_SLAVE );
+       $res = $dbr->selectField('image', 'COUNT(*)', array(), $fname );
+       wfProfileOut( $fname );
+
+       return $res;
+}
+
+/**
+ * Get various statistics from the database
+ * @private
+ */
+function wfLoadSiteStats() {
+       global $wgNumberOfArticles, $wgTotalViews, $wgTotalEdits;
+       $fname = 'wfLoadSiteStats';
+
+       if ( -1 != $wgNumberOfArticles ) return;
+       $dbr =& wfGetDB( DB_SLAVE );
+       $s = $dbr->selectRow( 'site_stats',
+               array( 'ss_total_views', 'ss_total_edits', 'ss_good_articles' ),
+               array( 'ss_row_id' => 1 ), $fname
+       );
+
+       if ( $s === false ) {
+               return;
+       } else {
+               $wgTotalViews = $s->ss_total_views;
+               $wgTotalEdits = $s->ss_total_edits;
+               $wgNumberOfArticles = $s->ss_good_articles;
+       }
+}
+
+/**
+ * Escape html tags
+ * Basicly replacing " > and < with HTML entities ( &quot;, &gt;, &lt;)
+ *
+ * @param string $in Text that might contain HTML tags
+ * @return string Escaped string
+ */
+function wfEscapeHTMLTagsOnly( $in ) {
+       return str_replace(
+               array( '"', '>', '<' ),
+               array( '&quot;', '&gt;', '&lt;' ),
+               $in );
+}
+
+?>
diff --git a/includes/ParserCache.php b/includes/ParserCache.php
new file mode 100644 (file)
index 0000000..b6f5345
--- /dev/null
@@ -0,0 +1,94 @@
+<?php
+/**
+ *
+ * @package MediaWiki
+ * @subpackage Cache
+ */
+
+/**
+ *
+ * @package MediaWiki
+ */
+class ParserCache {
+       /**
+        * Setup a cache pathway with a given back-end storage mechanism.
+        * May be a memcached client or a BagOStuff derivative.
+        *
+        * @param object $memCached
+        */
+       function ParserCache( &$memCached ) {
+               $this->mMemc =& $memCached;
+       }
+
+       function getKey( &$article, &$user ) {
+               global $wgDBname, $action;
+               $hash = $user->getPageRenderingHash();
+               $pageid = intval( $article->getID() );
+               $renderkey = (int)($action == 'render');
+               $key = "$wgDBname:pcache:idhash:$pageid-$renderkey!$hash";
+               return $key;
+       }
+
+       function getETag( &$article, &$user ) {
+               return 'W/"' . $this->getKey($article, $user) . "--" . $article->mTouched. '"';
+       }
+
+       function get( &$article, &$user ) {
+               global $wgCacheEpoch;
+               $fname = 'ParserCache::get';
+               wfProfileIn( $fname );
+
+               $hash = $user->getPageRenderingHash();
+               $pageid = intval( $article->getID() );
+               $key = $this->getKey( $article, $user );
+
+               wfDebug( "Trying parser cache $key\n" );
+               $value = $this->mMemc->get( $key );
+               if ( is_object( $value ) ) {
+                       wfDebug( "Found.\n" );
+                       # Delete if article has changed since the cache was made
+                       $canCache = $article->checkTouched();
+                       $cacheTime = $value->getCacheTime();
+                       $touched = $article->mTouched;
+                       if ( !$canCache || $value->expired( $touched ) ) {
+                               if ( !$canCache ) {
+                                       wfIncrStats( "pcache_miss_invalid" );
+                                       wfDebug( "Invalid cached redirect, touched $touched, epoch $wgCacheEpoch, cached $cacheTime\n" );
+                               } else {
+                                       wfIncrStats( "pcache_miss_expired" );
+                                       wfDebug( "Key expired, touched $touched, epoch $wgCacheEpoch, cached $cacheTime\n" );
+                               }
+                               $this->mMemc->delete( $key );
+                               $value = false;
+
+                       } else {
+                               wfIncrStats( "pcache_hit" );
+                       }
+               } else {
+                       wfDebug( "Parser cache miss.\n" );
+                       wfIncrStats( "pcache_miss_absent" );
+                       $value = false;
+               }
+
+               wfProfileOut( $fname );
+               return $value;
+       }
+
+       function save( $parserOutput, &$article, &$user ){
+               $key = $this->getKey( $article, $user );
+               $now = wfTimestampNow();
+               $parserOutput->setCacheTime( $now );
+               $parserOutput->mText .= "\n<!-- Saved in parser cache with key $key and timestamp $now -->\n";
+               wfDebug( "Saved in parser cache with key $key and timestamp $now\n" );
+
+               if( $parserOutput->containsOldMagic() ){
+                       $expire = 3600; # 1 hour
+               } else {
+                       $expire = 86400; # 1 day
+               }
+               $this->mMemc->set( $key, $parserOutput, $expire );
+       }
+}
+
+
+?>
diff --git a/includes/ParserXML.php b/includes/ParserXML.php
new file mode 100644 (file)
index 0000000..f8b3b9b
--- /dev/null
@@ -0,0 +1,642 @@
+<?php 
+/**
+ * 
+ * @package MediaWiki
+ * @subpackage Experimental
+ */
+
+/** */
+require_once ('Parser.php');
+
+/**
+ * This should one day become the XML->(X)HTML parser
+ * Based on work by Jan Hidders and Magnus Manske
+ * To use, set
+ *    $wgUseXMLparser = true ;
+ *    $wgEnableParserCache = false ;
+ *    $wgWiki2xml to the path and executable of the command line version (cli)
+ * in LocalSettings.php
+ * @package MediaWiki
+ * @subpackage Experimental
+ */
+
+/**
+ * the base class for an element
+ * @package MediaWiki
+ * @subpackage Experimental
+ */
+class element {
+       var $name = '';
+       var $attrs = array ();
+       var $children = array ();
+
+       /**
+       * This finds the ATTRS element and returns the ATTR sub-children as a single string
+       */
+       function getSourceAttrs() {
+               $ret = '';
+               foreach ($this->children as $child) {
+                       if (!is_string($child) AND $child->name == 'ATTRS') {
+                               $ret = $child->makeXHTML($parser);
+                       }
+               }
+               return $ret;
+       }
+
+       /**
+        * This collects the ATTR thingies for getSourceAttrs()
+        */
+       function getTheseAttrs() {
+               $ret = array ();
+               foreach ($this->children as $child) {
+                       if (!is_string($child) AND $child->name == 'ATTR') {
+                               $ret[] = $child->attrs["NAME"]."='".$child->children[0]."'";
+                       }
+               }
+               return implode(' ', $ret);
+       }
+
+       function fixLinkTails(& $parser, $key) {
+               $k2 = $key +1;
+               if (!isset ($this->children[$k2]))
+                       return;
+               if (!is_string($this->children[$k2]))
+                       return;
+               if (is_string($this->children[$key]))
+                       return;
+               if ($this->children[$key]->name != "LINK")
+                       return;
+
+               $n = $this->children[$k2];
+               $s = '';
+               while ($n != '' AND (($n[0] >= 'a' AND $n[0] <= 'z') OR $n[0] == 'ä' OR $n[0] == 'ö' OR $n[0] == 'ü' OR $n[0] == 'ß')) {
+                       $s .= $n[0];
+                       $n = substr($n, 1);
+               }
+               $this->children[$k2] = $n;
+
+               if (count($this->children[$key]->children) > 1) {
+                       $kl = array_keys($this->children[$key]->children);
+                       $kl = array_pop($kl);
+                       $this->children[$key]->children[$kl]->children[] = $s;
+               } else {
+                       $e = new element;
+                       $e->name = "LINKOPTION";
+                       $t = $this->children[$key]->sub_makeXHTML($parser);
+                       $e->children[] = trim($t).$s;
+                       $this->children[$key]->children[] = $e;
+               }
+       }
+
+       /**
+       * This function generates the XHTML for the entire subtree
+       */
+       function sub_makeXHTML(& $parser, $tag = '', $attr = '') {
+               $ret = '';
+
+               $attr2 = $this->getSourceAttrs();
+               if ($attr != '' AND $attr2 != '')
+                       $attr .= ' ';
+               $attr .= $attr2;
+
+               if ($tag != '') {
+                       $ret .= '<'.$tag;
+                       if ($attr != '')
+                               $ret .= ' '.$attr;
+                       $ret .= '>';
+               }
+
+               # THIS SHOULD BE DONE IN THE WIKI2XML-PARSER INSTEAD
+               #       foreach ( array_keys ( $this->children ) AS $x )
+               #          $this->fixLinkTails ( $parser , $x ) ;
+
+               foreach ($this->children as $key => $child) {
+                       if (is_string($child)) {
+                               $ret .= $child;
+                       } elseif ($child->name != 'ATTRS') {
+                               $ret .= $child->makeXHTML($parser);
+                       }
+               }
+               if ($tag != '')
+                       $ret .= '</'.$tag.">\n";
+               return $ret;
+       }
+
+       /**
+       * Link functions
+       */
+       function createInternalLink(& $parser, $target, $display_title, $options) {
+               global $wgUser;
+               $skin = $wgUser->getSkin();
+               $tp = explode(':', $target); # tp = target parts
+               $title = ''; # The plain title
+               $language = ''; # The language/meta/etc. part
+               $namespace = ''; # The namespace, if any
+               $subtarget = ''; # The '#' thingy
+
+               $nt = Title :: newFromText($target);
+               $fl = strtoupper($this->attrs['FORCEDLINK']) == 'YES';
+
+               if ($fl || count($tp) == 1) {
+                       # Plain and simple case
+                       $title = $target;
+               } else {
+                       # There's stuff missing here...
+                       if ($nt->getNamespace() == NS_IMAGE) {
+                               $options[] = $display_title;
+                               return $parser->makeImage($nt, implode('|', $options));
+                       } else {
+                               # Default
+                               $title = $target;
+                       }
+               }
+
+               if ($language != '') {
+                       # External link within the WikiMedia project
+                       return "{language link}";
+               } else {
+                       if ($namespace != '') {
+                               # Link to another namespace, check for image/media stuff
+                               return "{namespace link}";
+                       } else {
+                               return $skin->makeLink($target, $display_title);
+                       }
+               }
+       }
+
+       /** @todo document */
+       function makeInternalLink(& $parser) {
+               $target = '';
+               $option = array ();
+               foreach ($this->children as $child) {
+                       if (is_string($child)) {
+                               # This shouldn't be the case!
+                       } else {
+                               if ($child->name == 'LINKTARGET') {
+                                       $target = trim($child->makeXHTML($parser));
+                               } else {
+                                       $option[] = trim($child->makeXHTML($parser));
+                               }
+                       }
+               }
+
+               if (count($option) == 0)
+                       $option[] = $target; # Create dummy display title
+               $display_title = array_pop($option);
+               return $this->createInternalLink($parser, $target, $display_title, $option);
+       }
+
+       /** @todo document */
+       function getTemplateXHTML($title, $parts, & $parser) {
+               global $wgLang, $wgUser;
+               $skin = $wgUser->getSkin();
+               $ot = $title; # Original title
+               if (count(explode(':', $title)) == 1)
+                       $title = $wgLang->getNsText(NS_TEMPLATE).":".$title;
+               $nt = Title :: newFromText($title);
+               $id = $nt->getArticleID();
+               if ($id == 0) {
+                       # No/non-existing page
+                       return $skin->makeBrokenLink($title, $ot);
+               }
+
+               $a = 0;
+               $tv = array (); # Template variables
+               foreach ($parts AS $part) {
+                       $a ++;
+                       $x = explode('=', $part, 2);
+                       if (count($x) == 1)
+                               $key = "{$a}";
+                       else
+                               $key = $x[0];
+                       $value = array_pop($x);
+                       $tv[$key] = $value;
+               }
+               $art = new Article($nt);
+               $text = $art->getContent(false);
+               $parser->plain_parse($text, true, $tv);
+
+               return $text;
+       }
+
+       /**
+        * This function actually converts wikiXML into XHTML tags
+        * @todo use switch() !
+        */
+       function makeXHTML(& $parser) {
+               $ret = '';
+               $n = $this->name; # Shortcut
+
+               if ($n == 'EXTENSION') {
+                       # Fix allowed HTML
+                       $old_n = $n;
+                       $ext = strtoupper($this->attrs['NAME']);
+                       
+                       switch($ext) {
+                               case 'B':
+                               case 'STRONG':
+                                       $n = 'BOLD';
+                                       break;
+                               case 'I':
+                               case 'EM':
+                                       $n = 'ITALICS';
+                                       break;
+                               case 'U':
+                                       $n = 'UNDERLINED'; # Hey, virtual wiki tag! ;-)
+                                       break;
+                               case 'S':
+                                       $n = 'STRIKE';
+                                       break;
+                               case 'P':
+                                       $n = 'PARAGRAPH';
+                                       break;
+                               case 'TABLE':
+                                       $n = 'TABLE';
+                                       break;
+                               case 'TR':
+                                       $n = 'TABLEROW';
+                                       break;
+                               case 'TD':
+                                       $n = 'TABLECELL';
+                                       break;
+                               case 'TH':
+                                       $n = 'TABLEHEAD';
+                                       break;
+                               case 'CAPTION':
+                                       $n = 'CAPTION';
+                                       break;
+                               case 'NOWIKI':
+                                       $n = 'NOWIKI';
+                                       break;
+                               }
+                       if ($n != $old_n) {
+                               unset ($this->attrs['NAME']); # Cleanup
+                       } elseif ($parser->nowiki > 0) {
+                               # No 'real' wiki tags allowed in nowiki section
+                               $n = '';
+                       }
+               } // $n = 'EXTENSION'
+
+               switch($n) {
+                       case 'ARTICLE':
+                               $ret .= $this->sub_makeXHTML($parser);
+                               break;
+                       case 'HEADING':
+                               $ret .= $this->sub_makeXHTML($parser, 'h'.$this->attrs['LEVEL']);
+                               break;
+                       case 'PARAGRAPH':
+                               $ret .= $this->sub_makeXHTML($parser, 'p');
+                               break;
+                       case 'BOLD':
+                               $ret .= $this->sub_makeXHTML($parser, 'strong');
+                               break;
+                       case 'ITALICS':
+                               $ret .= $this->sub_makeXHTML($parser, 'em');
+                               break;
+
+                       # These don't exist as wiki markup
+                       case 'UNDERLINED':
+                               $ret .= $this->sub_makeXHTML($parser, 'u');
+                               break;
+                       case 'STRIKE':
+                               $ret .= $this->sub_makeXHTML($parser, 'strike');
+                               break;
+
+                       # HTML comment
+                       case 'COMMENT':
+                               # Comments are parsed out
+                               $ret .= '';
+                               break;
+                               
+
+                       # Links
+                       case 'LINK':
+                               $ret .= $this->makeInternalLink($parser);
+                               break;
+                       case 'LINKTARGET':
+                       case 'LINKOPTION':
+                               $ret .= $this->sub_makeXHTML($parser);
+                               break;
+               
+                       case 'TEMPLATE':
+                               $parts = $this->sub_makeXHTML($parser);
+                               $parts = explode('|', $parts);
+                               $title = array_shift($parts);
+                               $ret .= $this->getTemplateXHTML($title, $parts, & $parser);
+                               break;
+
+                       case 'TEMPLATEVAR':
+                               $x = $this->sub_makeXHTML($parser);
+                               if (isset ($parser->mCurrentTemplateOptions["{$x}"]))
+                                       $ret .= $parser->mCurrentTemplateOptions["{$x}"];
+                               break;
+
+                       # Internal use, not generated by wiki2xml parser                                
+                       case 'IGNORE':
+                               $ret .= $this->sub_makeXHTML($parser);
+
+                       case 'NOWIKI':
+                               $parser->nowiki++;
+                               $ret .= $this->sub_makeXHTML($parser, '');
+                               $parser->nowiki--;
+
+
+                       # Unknown HTML extension
+                       case 'EXTENSION': # This is currently a dummy!!!
+                               $ext = $this->attrs['NAME'];
+
+                               $ret .= '&lt;'.$ext.'&gt;';
+                               $ret .= $this->sub_makeXHTML($parser);
+                               $ret .= '&lt;/'.$ext.'&gt; ';
+                               break;
+
+
+                       # Table stuff
+
+                       case 'TABLE':
+                               $ret .= $this->sub_makeXHTML($parser, 'table');
+                               break;
+                       case 'TABLEROW':
+                               $ret .= $this->sub_makeXHTML($parser, 'tr');
+                               break;
+                       case 'TABLECELL':
+                               $ret .= $this->sub_makeXHTML($parser, 'td');
+                               break;
+                       case 'TABLEHEAD':
+                               $ret .= $this->sub_makeXHTML($parser, 'th');
+                               break;
+                       case 'CAPTION':
+                               $ret .= $this->sub_makeXHTML($parser, 'caption');
+                               break;
+                       case 'ATTRS': # SPECIAL CASE : returning attributes
+                               return $this->getTheseAttrs();
+
+
+                       # Lists stuff
+                       case 'LISTITEM':
+                               if ($parser->mListType == 'dl')
+                                       $ret .= $this->sub_makeXHTML($parser, 'dd');
+                               else
+                                       $ret .= $this->sub_makeXHTML($parser, 'li');
+                               break;
+                       case 'LIST':
+                                       $type = 'ol'; # Default
+                                       if ($this->attrs['TYPE'] == 'bullet')
+                                               $type = 'ul';
+                                       else
+                                               if ($this->attrs['TYPE'] == 'indent')
+                                                       $type = 'dl';
+                                       $oldtype = $parser->mListType;
+                                       $parser->mListType = $type;
+                                       $ret .= $this->sub_makeXHTML($parser, $type);
+                                       $parser->mListType = $oldtype;
+                               break;
+                       
+                       # Something else entirely
+                       default:
+                               $ret .= '&lt;'.$n.'&gt;';
+                               $ret .= $this->sub_makeXHTML($parser);
+                               $ret .= '&lt;/'.$n.'&gt; ';
+                       } // switch($n)
+
+               $ret = "\n{$ret}\n";
+               $ret = str_replace("\n\n", "\n", $ret);
+               return $ret;
+       }
+
+       /**
+        * A function for additional debugging output
+        */
+       function myPrint() {
+               $ret = "<ul>\n";
+               $ret .= "<li> <b> Name: </b> $this->name </li>\n";
+               // print attributes
+               $ret .= '<li> <b> Attributes: </b>';
+               foreach ($this->attrs as $name => $value) {
+                       $ret .= "$name => $value; ";
+               }
+               $ret .= " </li>\n";
+               // print children
+               foreach ($this->children as $child) {
+                       if (is_string($child)) {
+                               $ret .= "<li> $child </li>\n";
+                       } else {
+                               $ret .= $child->myPrint();
+                       }
+               }
+               $ret .= "</ul>\n";
+               return $ret;
+       }
+}
+
+$ancStack = array (); // the stack with ancestral elements
+
+// START Three global functions needed for parsing, sorry guys
+/** @todo document */
+function wgXMLstartElement($parser, $name, $attrs) {
+       global $ancStack;
+
+       $newElem = new element;
+       $newElem->name = $name;
+       $newElem->attrs = $attrs;
+
+       array_push($ancStack, $newElem);
+}
+
+/** @todo document */
+function wgXMLendElement($parser, $name) {
+       global $ancStack, $rootElem;
+       // pop element off stack
+       $elem = array_pop($ancStack);
+       if (count($ancStack) == 0)
+               $rootElem = $elem;
+       else
+               // add it to its parent
+               array_push($ancStack[count($ancStack) - 1]->children, $elem);
+}
+
+/** @todo document */
+function wgXMLcharacterData($parser, $data) {
+       global $ancStack;
+       $data = trim($data); // Don't add blank lines, they're no use...
+       // add to parent if parent exists
+       if ($ancStack && $data != "") {
+               array_push($ancStack[count($ancStack) - 1]->children, $data);
+       }
+}
+// END Three global functions needed for parsing, sorry guys
+
+/**
+ * Here's the class that generates a nice tree
+ * @package MediaWiki
+ * @subpackage Experimental
+ */
+class xml2php {
+
+       /** @todo document */
+       function & scanFile($filename) {
+               global $ancStack, $rootElem;
+               $ancStack = array ();
+
+               $xml_parser = xml_parser_create();
+               xml_set_element_handler($xml_parser, 'wgXMLstartElement', 'wgXMLendElement');
+               xml_set_character_data_handler($xml_parser, 'wgXMLcharacterData');
+               if (!($fp = fopen($filename, 'r'))) {
+                       die('could not open XML input');
+               }
+               while ($data = fread($fp, 4096)) {
+                       if (!xml_parse($xml_parser, $data, feof($fp))) {
+                               die(sprintf("XML error: %s at line %d", xml_error_string(xml_get_error_code($xml_parser)), xml_get_current_line_number($xml_parser)));
+                       }
+               }
+               xml_parser_free($xml_parser);
+
+               // return the remaining root element we copied in the beginning
+               return $rootElem;
+       }
+
+       /** @todo document */
+       function scanString($input) {
+               global $ancStack, $rootElem;
+               $ancStack = array ();
+
+               $xml_parser = xml_parser_create();
+               xml_set_element_handler($xml_parser, 'wgXMLstartElement', 'wgXMLendElement');
+               xml_set_character_data_handler($xml_parser, 'wgXMLcharacterData');
+
+               if (!xml_parse($xml_parser, $input, true)) {
+                       die(sprintf("XML error: %s at line %d", xml_error_string(xml_get_error_code($xml_parser)), xml_get_current_line_number($xml_parser)));
+               }
+               xml_parser_free($xml_parser);
+
+               // return the remaining root element we copied in the beginning
+               return $rootElem;
+       }
+
+}
+
+/**
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Experimental
+ */
+class ParserXML extends Parser {
+       /**#@+
+        * @access private
+        */
+       # Persistent:
+       var $mTagHooks, $mListType;
+
+       # Cleared with clearState():
+       var $mOutput, $mAutonumber, $mDTopen, $mStripState = array ();
+       var $mVariables, $mIncludeCount, $mArgStack, $mLastSection, $mInPre;
+
+       # Temporary:
+       var $mOptions, $mTitle, $mOutputType, $mTemplates, // cache of already loaded templates, avoids
+       // multiple SQL queries for the same string
+       $mTemplatePath; // stores an unsorted hash of all the templates already loaded
+       // in this path. Used for loop detection.
+
+       var $nowikicount, $mCurrentTemplateOptions;
+
+       /**#@-*/
+
+       /**
+        * Constructor
+        * 
+        * @access public
+        */
+       function ParserXML() {
+               $this->mTemplates = array ();
+               $this->mTemplatePath = array ();
+               $this->mTagHooks = array ();
+               $this->clearState();
+       }
+
+       /**
+        * Clear Parser state
+        *
+        * @access private
+        */
+       function clearState() {
+               $this->mOutput = new ParserOutput;
+               $this->mAutonumber = 0;
+               $this->mLastSection = "";
+               $this->mDTopen = false;
+               $this->mVariables = false;
+               $this->mIncludeCount = array ();
+               $this->mStripState = array ();
+               $this->mArgStack = array ();
+               $this->mInPre = false;
+       }
+
+       /**
+       * Turns the wikitext into XML by calling the external parser
+       *
+       */
+       function html2xml(& $text) {
+               global $wgWiki2xml;
+
+               # generating html2xml command path
+               $a = $wgWiki2xml;
+               $a = explode('/', $a);
+               array_pop($a);
+               $a[] = 'html2xml';
+               $html2xml = implode('/', $a);
+               $a = array ();
+
+               $tmpfname = tempnam( wfTempDir(), 'FOO' );
+               $handle = fopen($tmpfname, 'w');
+               fwrite($handle, utf8_encode($text));
+               fclose($handle);
+               exec($html2xml.' < '.$tmpfname, $a);
+               $text = utf8_decode(implode("\n", $a));
+               unlink($tmpfname);
+       }
+
+       /** @todo document */
+       function runXMLparser(& $text) {
+               global $wgWiki2xml;
+
+               $this->html2xml($text);
+
+               $tmpfname = tempnam( wfTempDir(), 'FOO');
+               $handle = fopen($tmpfname, 'w');
+               fwrite($handle, $text);
+               fclose($handle);
+               exec($wgWiki2xml.' < '.$tmpfname, $a);
+               $text = utf8_decode(implode("\n", $a));
+               unlink($tmpfname);
+       }
+
+       /** @todo document */
+       function plain_parse(& $text, $inline = false, $templateOptions = array ()) {
+               $this->runXMLparser($text);
+               $nowikicount = 0;
+               $w = new xml2php;
+               $result = $w->scanString($text);
+
+               $oldTemplateOptions = $this->mCurrentTemplateOptions;
+               $this->mCurrentTemplateOptions = $templateOptions;
+
+               if ($inline) { # Inline rendering off for templates
+                       if (count($result->children) == 1)
+                               $result->children[0]->name = 'IGNORE';
+               }
+
+               if (1)
+                       $text = $result->makeXHTML($this); # No debugging info
+               else
+                       $text = $result->makeXHTML($this).'<hr>'.$text.'<hr>'.$result->myPrint();
+               $this->mCurrentTemplateOptions = $oldTemplateOptions;
+       }
+
+       /** @todo document */
+       function parse($text, & $title, $options, $linestart = true, $clearState = true) {
+               $this->plain_parse($text);
+               $this->mOutput->setText($text);
+               return $this->mOutput;
+       }
+
+}
+?>
diff --git a/includes/Profiling.php b/includes/Profiling.php
new file mode 100644 (file)
index 0000000..2fe5ada
--- /dev/null
@@ -0,0 +1,340 @@
+<?php 
+/**
+ * This file is only included if profiling is enabled
+ * @package MediaWiki
+ */
+
+/**
+ * @param $functioname name of the function we will profile
+ */
+function wfProfileIn($functionname) {
+       global $wgProfiler;
+       $wgProfiler->profileIn($functionname);
+}
+
+/**
+ * @param $functioname name of the function we have profiled
+ */
+function wfProfileOut($functionname = 'missing') {
+       global $wgProfiler;
+       $wgProfiler->profileOut($functionname);
+}
+
+function wfGetProfilingOutput($start, $elapsed) {
+       global $wgProfiler;
+       return $wgProfiler->getOutput($start, $elapsed);
+}
+
+function wfProfileClose() {
+       global $wgProfiler;
+       $wgProfiler->close();
+}
+
+if (!function_exists('memory_get_usage')) {
+       # Old PHP or --enable-memory-limit not compiled in
+       function memory_get_usage() {
+               return 0;
+       }
+}
+
+/**
+ * @todo document
+ * @package MediaWiki
+ */
+class Profiler {
+       var $mStack = array (), $mWorkStack = array (), $mCollated = array ();
+       var $mCalls = array (), $mTotals = array ();
+       /*
+       function Profiler()
+       {
+               $this->mProfileStack = array();
+               $this->mWorkStack = array();
+               $this->mCollated = array();
+       }
+       */
+
+       function profileIn($functionname) {
+               global $wgDebugFunctionEntry;
+               if ($wgDebugFunctionEntry && function_exists('wfDebug')) {
+                       wfDebug(str_repeat(' ', count($this->mWorkStack)).'Entering '.$functionname."\n");
+               }
+               $this->mWorkStack[] = array($functionname, count( $this->mWorkStack ), $this->getTime(), memory_get_usage());
+       }
+
+       function profileOut($functionname) {
+               $memory = memory_get_usage();
+               $time = $this->getTime();
+
+               global $wgDebugProfiling, $wgDebugFunctionEntry;
+
+               if ($wgDebugFunctionEntry && function_exists('wfDebug')) {
+                       wfDebug(str_repeat(' ', count($this->mWorkStack) - 1).'Exiting '.$functionname."\n");
+               }
+
+               $bit = array_pop($this->mWorkStack);
+
+               if (!$bit) {
+                       wfDebug("Profiling error, !\$bit: $functionname\n");
+               } else {
+                       //if ($wgDebugProfiling) {
+                               if ($functionname == 'close') {
+                                       $message = "Profile section ended by close(): {$bit[0]}\n";
+                                       wfDebug( $message );
+                                       $this->mStack[] = array( $message, 0, 0, 0 );
+                               }
+                               elseif ($bit[0] != $functionname) {
+                                       $message = "Profiling error: in({$bit[0]}), out($functionname)\n";
+                                       wfDebug( $message );
+                                       $this->mStack[] = array( $message, 0, 0, 0 );
+                               }
+                       //}
+                       $bit[] = $time;
+                       $bit[] = $memory;
+                       $this->mStack[] = $bit;
+               }
+       }
+
+       function close() {
+               while (count($this->mWorkStack)) {
+                       $this->profileOut('close');
+               }
+       }
+
+       function getOutput() {
+               global $wgDebugFunctionEntry;
+               $wgDebugFunctionEntry = false;
+
+               if (!count($this->mStack)) {
+                       return "No profiling output\n";
+               }
+               $this->close();
+
+               global $wgProfileCallTree;
+               if ($wgProfileCallTree) {
+                       return $this->getCallTree();
+               } else {
+                       return $this->getFunctionReport();
+               }
+       }
+
+       function getCallTree($start = 0) {
+               return implode('', array_map(array (& $this, 'getCallTreeLine'), $this->remapCallTree($this->mStack)));
+       }
+
+       function remapCallTree($stack) {
+               if (count($stack) < 2) {
+                       return $stack;
+               }
+               $outputs = array ();
+               for ($max = count($stack) - 1; $max > 0;) {
+                       /* Find all items under this entry */
+                       $level = $stack[$max][1];
+                       $working = array ();
+                       for ($i = $max -1; $i >= 0; $i --) {
+                               if ($stack[$i][1] > $level) {
+                                       $working[] = $stack[$i];
+                               } else {
+                                       break;
+                               }
+                       }
+                       $working = $this->remapCallTree(array_reverse($working));
+                       $output = array ();
+                       foreach ($working as $item) {
+                               array_push($output, $item);
+                       }
+                       array_unshift($output, $stack[$max]);
+                       $max = $i;
+
+                       array_unshift($outputs, $output);
+               }
+               $final = array ();
+               foreach ($outputs as $output) {
+                       foreach ($output as $item) {
+                               $final[] = $item;
+                       }
+               }
+               return $final;
+       }
+
+       function getCallTreeLine($entry) {
+               list ($fname, $level, $start, $x, $end) = $entry;
+               $delta = $this->microDelta($start, $end);
+               $space = str_repeat(' ', $level);
+
+               # The ugly double sprintf is to work around a PHP bug,
+               # which has been fixed in recent releases.
+               return sprintf( "%10s %s %s\n",
+                       trim( sprintf( "%7.3f", $delta * 1000.0 ) ),
+                       $space, $fname );
+       }
+       
+       function micro2Float( $micro ) {
+               list( $whole, $fractional ) = explode( ' ', $micro );
+               return (float)$whole + (float)$fractional;
+       }
+       
+       function microDelta( $start, $end ) {
+               return $this->micro2Float( $end ) -
+                      $this->micro2Float( $start );
+       }
+
+       function getTime() {
+               return microtime();
+               #return $this->getUserTime();
+       }
+
+       function getUserTime() {
+               $ru = getrusage();
+               return $ru['ru_utime.tv_sec'].' '.$ru['ru_utime.tv_usec'] / 1e6;
+       }
+
+       function getFunctionReport() {          
+               $width = 140;
+               $nameWidth = $width - 65;
+               $format =      "%-{$nameWidth}s %6d %13.3f %13.3f %13.3f%% %9d  (%13.3f -%13.3f) [%d]\n";
+               $titleFormat = "%-{$nameWidth}s %6s %13s %13s %13s %9s\n";
+               $prof = "\nProfiling data\n";
+               $prof .= sprintf($titleFormat, 'Name', 'Calls', 'Total', 'Each', '%', 'Mem');
+               $this->mCollated = array ();
+               $this->mCalls = array ();
+               $this->mMemory = array ();
+
+               # Estimate profiling overhead
+               $profileCount = count($this->mStack);
+               wfProfileIn('-overhead-total');
+               for ($i = 0; $i < $profileCount; $i ++) {
+                       wfProfileIn('-overhead-internal');
+                       wfProfileOut('-overhead-internal');
+               }
+               wfProfileOut('-overhead-total');
+
+               # First, subtract the overhead!
+               foreach ($this->mStack as $entry) {
+                       $fname = $entry[0];
+                       $thislevel = $entry[1];
+                       $start = explode(' ', $entry[2]);
+                       $start = (float) $start[0] + (float) $start[1];
+                       $end = explode(' ', $entry[4]);
+                       $end = (float) $end[0] + (float) $end[1];
+                       $elapsed = $end - $start;
+                       $memory = $entry[5] - $entry[3];
+
+                       if ($fname == '-overhead-total') {
+                               $overheadTotal[] = $elapsed;
+                               $overheadMemory[] = $memory;
+                       }
+                       elseif ($fname == '-overhead-internal') {
+                               $overheadInternal[] = $elapsed;
+                       }
+               }
+               $overheadTotal = array_sum($overheadTotal) / count($overheadInternal);
+               $overheadMemory = array_sum($overheadMemory) / count($overheadInternal);
+               $overheadInternal = array_sum($overheadInternal) / count($overheadInternal);
+
+               # Collate
+               foreach ($this->mStack as $index => $entry) {
+                       $fname = $entry[0];
+                       $thislevel = $entry[1];
+                       $start = explode(' ', $entry[2]);
+                       $start = (float) $start[0] + (float) $start[1];
+                       $end = explode(' ', $entry[4]);
+                       $end = (float) $end[0] + (float) $end[1];
+                       $elapsed = $end - $start;
+
+                       $memory = $entry[5] - $entry[3];
+                       $subcalls = $this->calltreeCount($this->mStack, $index);
+
+                       if (!preg_match('/^-overhead/', $fname)) {
+                               # Adjust for profiling overhead (except special values with elapsed=0
+                               if ( $elapsed ) {
+                                       $elapsed -= $overheadInternal;
+                                       $elapsed -= ($subcalls * $overheadTotal);
+                                       $memory -= ($subcalls * $overheadMemory);
+                               }
+                       }
+
+                       if (!array_key_exists($fname, $this->mCollated)) {
+                               $this->mCollated[$fname] = 0;
+                               $this->mCalls[$fname] = 0;
+                               $this->mMemory[$fname] = 0;
+                               $this->mMin[$fname] = 1 << 24;
+                               $this->mMax[$fname] = 0;
+                               $this->mOverhead[$fname] = 0;
+                       }
+
+                       $this->mCollated[$fname] += $elapsed;
+                       $this->mCalls[$fname]++;
+                       $this->mMemory[$fname] += $memory;
+                       $this->mMin[$fname] = min($this->mMin[$fname], $elapsed);
+                       $this->mMax[$fname] = max($this->mMax[$fname], $elapsed);
+                       $this->mOverhead[$fname] += $subcalls;
+               }
+
+               $total = @ $this->mCollated['-total'];
+               $this->mCalls['-overhead-total'] = $profileCount;
+
+               # Output
+               asort($this->mCollated, SORT_NUMERIC);
+               foreach ($this->mCollated as $fname => $elapsed) {
+                       $calls = $this->mCalls[$fname];
+                       $percent = $total ? 100. * $elapsed / $total : 0;
+                       $memory = $this->mMemory[$fname];
+                       $prof .= sprintf($format, $fname, $calls, (float) ($elapsed * 1000), (float) ($elapsed * 1000) / $calls, $percent, $memory, ($this->mMin[$fname] * 1000.0), ($this->mMax[$fname] * 1000.0), $this->mOverhead[$fname]);
+
+                       global $wgProfileToDatabase;
+                       if ($wgProfileToDatabase) {
+                               Profiler :: logToDB($fname, (float) ($elapsed * 1000), $calls);
+                       }
+               }
+               $prof .= "\nTotal: $total\n\n";
+
+               return $prof;
+       }
+
+       /**
+        * Counts the number of profiled function calls sitting under
+        * the given point in the call graph. Not the most efficient algo.
+        *
+        * @param array $stack
+        * @param int $start
+        * @return int
+        * @access private
+        */
+       function calltreeCount(& $stack, $start) {
+               $level = $stack[$start][1];
+               $count = 0;
+               for ($i = $start -1; $i >= 0 && $stack[$i][1] > $level; $i --) {
+                       $count ++;
+               }
+               return $count;
+       }
+
+       /**
+        * @static
+        */
+       function logToDB($name, $timeSum, $eventCount) {
+               $fname = 'Profiler::logToDB';
+               $dbw = & wfGetDB(DB_MASTER);
+               $profiling = $dbw->tableName('profiling');
+
+               $name = substr($name, 0, 255);
+               $encname = $dbw->strencode($name);
+               $sql = "UPDATE $profiling "."SET pf_count=pf_count+{$eventCount}, "."pf_time=pf_time + {$timeSum} "."WHERE pf_name='{$encname}'";
+               $dbw->query($sql);
+
+               $rc = $dbw->affectedRows();
+               if ($rc == 0) {
+                       $dbw->insert('profiling', array ('pf_name' => $name, 'pf_count' => $eventCount, 'pf_time' => $timeSum), $fname, array ('IGNORE'));
+               }
+               // When we upgrade to mysql 4.1, the insert+update
+               // can be merged into just a insert with this construct added:
+               //     "ON DUPLICATE KEY UPDATE ".
+               //     "pf_count=pf_count + VALUES(pf_count), ".
+               //     "pf_time=pf_time + VALUES(pf_time)"; 
+       }
+
+}
+
+$wgProfiler = new Profiler();
+$wgProfiler->profileIn('-total');
+?>
diff --git a/includes/ProxyTools.php b/includes/ProxyTools.php
new file mode 100644 (file)
index 0000000..3ef4a20
--- /dev/null
@@ -0,0 +1,93 @@
+<?php
+/**
+ * Functions for dealing with proxies
+ * @package MediaWiki
+ */
+
+if ( !defined( 'MEDIAWIKI' ) ) {
+       die();
+}
+
+/** Work out the IP address based on various globals */
+function wfGetIP() {
+       global $wgSquidServers, $wgSquidServersNoPurge;
+
+       /* collect the originating ips */
+       # Client connecting to this webserver
+       if ( isset( $_SERVER['REMOTE_ADDR'] ) ) {
+               $ipchain = array( $_SERVER['REMOTE_ADDR'] );
+       } else {
+               # Running on CLI?
+               $ipchain = array( '127.0.0.1' );
+       }
+       $ip = $ipchain[0];
+
+       # Get list of trusted proxies
+       # Flipped for quicker access
+       $trustedProxies = array_flip( array_merge( $wgSquidServers, $wgSquidServersNoPurge ) );
+       if ( count( $trustedProxies ) ) {
+               # Append XFF on to $ipchain
+               if ( isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
+                       $xff = array_map( 'trim', explode( ',', $_SERVER['HTTP_X_FORWARDED_FOR'] ) );
+                       $xff = array_reverse( $xff );
+                       $ipchain = array_merge( $ipchain, $xff );
+               }
+               # Step through XFF list and find the last address in the list which is a trusted server
+               # Set $ip to the IP address given by that trusted server, unless the address is not sensible (e.g. private)
+               foreach ( $ipchain as $i => $curIP ) {
+                       if ( array_key_exists( $curIP, $trustedProxies ) ) {
+                               if ( isset( $ipchain[$i + 1] ) && wfIsIPPublic( $ipchain[$i + 1] ) ) {
+                                       $ip = $ipchain[$i + 1];
+                               }
+                       } else {
+                               break;
+                       }
+               }
+       }
+
+       return $ip;
+}
+
+/** */
+function wfIP2Unsigned( $ip ) {
+       $n = ip2long( $ip );
+       if ( $n == -1 ) {
+               $n = false;
+       } elseif ( $n < 0 ) {
+               $n += pow( 2, 32 );
+       }
+       return $n;
+}
+
+/**
+ * Determine if an IP address really is an IP address, and if it is public, 
+ * i.e. not RFC 1918 or similar
+ */
+function wfIsIPPublic( $ip ) {
+       $n = wfIP2Unsigned( $ip );
+       if ( !$n ) {
+               return false;
+       }
+
+       static $privateRanges = false;
+       if ( !$privateRanges ) {
+               $privateRanges = array(
+                       array( '10.0.0.0',    '10.255.255.255' ),   # RFC 1918 (private)
+                       array( '172.16.0.0',  '172.31.255.255' ),   #     "
+                       array( '192.168.0.0', '192.168.255.255' ),  #     "
+                       array( '0.0.0.0',     '0.255.255.255' ),    # this network
+                       array( '127.0.0.0',   '127.255.255.255' ),  # loopback
+               );
+       }
+
+       foreach ( $privateRanges as $r ) {
+               $start = wfIP2Unsigned( $r[0] );
+               $end = wfIP2Unsigned( $r[1] );
+               if ( $n >= $start && $n <= $end ) {
+                       return false;
+               }
+       }
+       return true;
+}
+       
+?>
diff --git a/includes/QueryPage.php b/includes/QueryPage.php
new file mode 100644 (file)
index 0000000..6ed0de4
--- /dev/null
@@ -0,0 +1,405 @@
+<?php
+/**
+ * Contain a class for special pages
+ * @package MediaWiki
+ */
+
+/**
+ *
+ */
+require_once ( 'Feed.php' );
+
+/**
+ * List of query page classes and their associated special pages, for periodic update purposes
+ */
+$wgQueryPages = array(
+//         QueryPage subclass           Special page name
+//------------------------------------------------------------
+    array( 'AncientPagesPage',          'Ancientpages'      ),
+    array( 'BrokenRedirectsPage',       'BrokenRedirects'   ),
+    array( 'DeadendPagesPage',          'Deadendpages'      ),
+    array( 'DisambiguationsPage',       'Disambiguations'   ),
+    array( 'DoubleRedirectsPage',       'DoubleRedirects'   ),
+    array( 'ListUsersPage',             'Listusers'         ), 
+    array( 'LonelyPagesPage',           'Lonelypages'       ),
+    array( 'LongPagesPage',             'Longpages'         ),
+    array( 'NewPagesPage',              'Newpages'          ),
+    array( 'ShortPagesPage',            'Shortpages'        ),
+    array( 'UncategorizedCategoriesPage','Uncategorizedcategories'),
+    array( 'UncategorizedPagesPage',    'Uncategorizedpages'),
+    array( 'UnusedimagesPage',          'Unusedimages'      ),
+    array( 'WantedPagesPage',           'Wantedpages'       ),
+    array( 'MostlinkedPage',           'Mostlinked'        ),
+);
+    
+global $wgDisableCounters;
+if( !$wgDisableCounters ) {
+       $wgQueryPages[] = array( 'PopularPagesPage',          'Popularpages'      );
+}
+
+/**
+ * This is a class for doing query pages; since they're almost all the same,
+ * we factor out some of the functionality into a superclass, and let
+ * subclasses derive from it.
+ *
+ * @package MediaWiki
+ */
+class QueryPage {
+
+       /**
+        * Subclasses return their name here. Make sure the name is also
+        * specified in SpecialPage.php and in Language.php as a language message
+        * param.
+        */
+       function getName() {
+               return '';
+       }
+
+       /**
+        * Subclasses return an SQL query here.
+        *
+        * Note that the query itself should return the following four columns:
+        * 'type' (your special page's name), 'namespace', 'title', and 'value'
+        * *in that order*. 'value' is used for sorting.
+        *
+        * These may be stored in the querycache table for expensive queries,
+        * and that cached data will be returned sometimes, so the presence of
+        * extra fields can't be relied upon. The cached 'value' column will be
+        * an integer; non-numeric values are useful only for sorting the initial
+        * query.
+        *
+        * Don't include an ORDER or LIMIT clause, this will be added.
+        */
+       function getSQL() {
+               return "SELECT 'sample' as type, 0 as namespace, 'Sample result' as title, 42 as value";
+       }
+
+       /**
+        * Override to sort by increasing values
+        */
+       function sortDescending() {
+               return true;
+       }
+
+       function getOrder() {
+               return ' ORDER BY value ' .
+                       ($this->sortDescending() ? 'DESC' : '');
+       }
+
+       /**
+        * Is this query expensive (for some definition of expensive)? Then we
+        * don't let it run in miser mode. $wgDisableQueryPages causes all query
+        * pages to be declared expensive. Some query pages are always expensive.
+        */
+       function isExpensive( ) {
+               global $wgDisableQueryPages;
+               return $wgDisableQueryPages;
+       }
+
+       /**
+        * Sometime we dont want to build rss / atom feeds.
+        */
+       function isSyndicated() {
+               return true;
+       }
+
+       /**
+        * Formats the results of the query for display. The skin is the current
+        * skin; you can use it for making links. The result is a single row of
+        * result data. You should be able to grab SQL results off of it.
+        * If the function return "false", the line output will be skipped.
+        */
+       function formatResult( $skin, $result ) {
+               return '';
+       }
+
+       /**
+        * The content returned by this function will be output before any result
+        */
+       function getPageHeader( ) {
+               return '';
+       }
+       
+       /**
+        * If using extra form wheely-dealies, return a set of parameters here
+        * as an associative array. They will be encoded and added to the paging
+        * links (prev/next/lengths).
+        * @return array
+        */
+       function linkParameters() {
+               return array();
+       }
+       
+       /**
+        * Some special pages (for example SpecialListusers) might not return the
+        * current object formatted, but return the previous one instead.
+        * Setting this to return true, will call one more time wfFormatResult to
+        * be sure that the very last result is formatted and shown.
+        */
+       function tryLastResult( ) {
+               return false;
+       }
+
+       /**
+        * Clear the cache and save new results
+        */
+       function recache( $ignoreErrors = true ) {
+               $fname = get_class($this) . '::recache';
+               $dbw =& wfGetDB( DB_MASTER );
+               $dbr =& wfGetDB( DB_SLAVE, array( $this->getName(), 'QueryPage::recache', 'vslow' ) );
+               if ( !$dbw || !$dbr ) {
+                       return false;
+               }
+
+               $querycache = $dbr->tableName( 'querycache' );
+               
+               if ( $ignoreErrors ) {
+                       $ignoreW = $dbw->ignoreErrors( true );
+                       $ignoreR = $dbr->ignoreErrors( true );
+               }
+
+               # Clear out any old cached data
+               $dbw->delete( 'querycache', array( 'qc_type' => $this->getName() ), $fname );
+               # Do query
+               $res = $dbr->query( $this->getSQL() . $this->getOrder() . $dbr->limitResult( 1000,0 ), $fname );
+               $num = false;
+               if ( $res ) {
+                       $num = $dbr->numRows( $res );
+                       # Fetch results
+                       $insertSql = "INSERT INTO $querycache (qc_type,qc_namespace,qc_title,qc_value) VALUES ";
+                       $first = true;
+                       while ( $res && $row = $dbr->fetchObject( $res ) ) {
+                               if ( $first ) {
+                                       $first = false;
+                               } else {
+                                       $insertSql .= ',';
+                               }
+                               if ( isset( $row->value ) ) {
+                                       $value = $row->value;
+                               } else {
+                                       $value = '';
+                               }
+
+                               $insertSql .= '(' .
+                                       $dbw->addQuotes( $row->type ) . ',' .
+                                       $dbw->addQuotes( $row->namespace ) . ',' .
+                                       $dbw->addQuotes( $row->title ) . ',' .
+                                       $dbw->addQuotes( $value ) . ')';
+                       }
+
+                       # Save results into the querycache table on the master
+                       if ( !$first ) {
+                               if ( !$dbw->query( $insertSql, $fname ) ) {
+                                       // Set result to false to indicate error
+                                       $dbr->freeResult( $res );
+                                       $res = false;
+                               }
+                       }
+                       if ( $res ) {
+                               $dbr->freeResult( $res );
+                       }
+                       if ( $ignoreErrors ) {
+                               $dbw->ignoreErrors( $ignoreW );
+                               $dbr->ignoreErrors( $ignoreR );
+                       }
+               }
+               return $num;
+       }
+
+       /**
+        * This is the actual workhorse. It does everything needed to make a
+        * real, honest-to-gosh query page.
+        *
+        * @param $offset database query offset
+        * @param $limit database query limit
+        * @param $shownavigation show navigation like "next 200"?
+        */
+       function doQuery( $offset, $limit, $shownavigation=true ) {
+               global $wgUser, $wgOut, $wgLang, $wgRequest, $wgContLang;
+               global $wgMiserMode;
+
+               $sname = $this->getName();
+               $fname = get_class($this) . '::doQuery';
+               $sql = $this->getSQL();
+               $dbr =& wfGetDB( DB_SLAVE );
+               $dbw =& wfGetDB( DB_MASTER );
+               $querycache = $dbr->tableName( 'querycache' );
+
+               $wgOut->setSyndicated( $this->isSyndicated() );
+
+               if ( $this->isExpensive() ) {
+                       // Disabled recache parameter due to retry problems -- TS
+                       if( $wgMiserMode ) {
+                               $type = $dbr->strencode( $sname );
+                               $sql =
+                                       "SELECT qc_type as type, qc_namespace as namespace,qc_title as title, qc_value as value
+                                        FROM $querycache WHERE qc_type='$type'";
+                               $wgOut->addWikiText( wfMsg( 'perfcached' ) );
+                       }
+               }
+               
+               $res = $dbr->query( $sql . $this->getOrder() .
+                                   $dbr->limitResult( $limit,$offset ), $fname );
+               $num = $dbr->numRows($res);
+               
+               $sk = $wgUser->getSkin( );
+
+               if($shownavigation) {
+                       $wgOut->addHTML( $this->getPageHeader() );
+                       $top = wfShowingResults( $offset, $num);
+                       $wgOut->addHTML( "<p>{$top}\n" );
+       
+                       # often disable 'next' link when we reach the end
+                       if($num < $limit) { $atend = true; } else { $atend = false; }
+                       
+                       $sl = wfViewPrevNext( $offset, $limit ,
+                               $wgContLang->specialPage( $sname ),
+                               wfArrayToCGI( $this->linkParameters() ), $atend );
+                       $wgOut->addHTML( "<br />{$sl}</p>\n" );
+               }
+               if ( $num > 0 ) {
+                       $s = "<ol start='" . ( $offset + 1 ) . "' class='special'>";
+
+                       # Only read at most $num rows, because $res may contain the whole 1000
+                       for ( $i = 0; $i < $num && $obj = $dbr->fetchObject( $res ); $i++ ) {
+                               $format = $this->formatResult( $sk, $obj );
+                               if ( $format ) {
+                                       $attr = ( isset ( $obj->usepatrol ) && $obj->usepatrol &&
+                                                                               $obj->patrolled == 0 ) ? ' class="not-patrolled"' : '';
+                                       $s .= "<li{$attr}>{$format}</li>\n";
+                               }
+                       }
+
+                       if($this->tryLastResult()) {
+                               // flush the very last result
+                               $obj = null;
+                               $format = $this->formatResult( $sk, $obj );
+                               if( $format ) {
+                                       $attr = ( isset ( $obj->usepatrol ) && $obj->usepatrol &&
+                                                                               $obj->patrolled == 0 ) ? ' class="not-patrolled"' : '';
+                                       $s .= "<li{$attr}>{$format}</li>\n";
+                               }
+                       }
+                       
+                       $dbr->freeResult( $res );
+                       $s .= '</ol>';
+                       $wgOut->addHTML( $s );
+               }
+               if($shownavigation) {
+                       $wgOut->addHTML( "<p>{$sl}</p>\n" );
+               }
+               return $num;
+       }
+
+       /**
+        * Similar to above, but packaging in a syndicated feed instead of a web page
+        */
+       function doFeed( $class = '' ) {
+               global $wgFeedClasses;
+               global $wgOut, $wgLanguageCode, $wgLang;
+               if( isset($wgFeedClasses[$class]) ) {
+                       $feed = new $wgFeedClasses[$class](
+                               $this->feedTitle(),
+                               $this->feedDesc(),
+                               $this->feedUrl() );
+                       $feed->outHeader();
+
+                       $dbr =& wfGetDB( DB_SLAVE );
+                       $sql = $this->getSQL() . $this->getOrder().$dbr->limitResult( 50, 0 );
+                       $res = $dbr->query( $sql, 'QueryPage::doFeed' );
+                       while( $obj = $dbr->fetchObject( $res ) ) {
+                               $item = $this->feedResult( $obj );
+                               if( $item ) $feed->outItem( $item );
+                       }
+                       $dbr->freeResult( $res );
+
+                       $feed->outFooter();
+                       return true;
+               } else {
+                       return false;
+               }
+       }
+
+       /**
+        * Override for custom handling. If the titles/links are ok, just do
+        * feedItemDesc()
+        */
+       function feedResult( $row ) {
+               if( !isset( $row->title ) ) {
+                       return NULL;
+               }
+               $title = Title::MakeTitle( IntVal( $row->namespace ), $row->title );
+               if( $title ) {
+                       if( isset( $row->timestamp ) ) {
+                               $date = $row->timestamp;
+                       } else {
+                               $date = '';
+                       }
+
+                       $comments = '';
+                       if( $title ) {
+                               $talkpage = $title->getTalkPage();
+                               $comments = $talkpage->getFullURL();
+                       }
+
+                       return new FeedItem(
+                               $title->getPrefixedText(),
+                               $this->feedItemDesc( $row ),
+                               $title->getFullURL(),
+                               $date,
+                               $this->feedItemAuthor( $row ),
+                               $comments);
+               } else {
+                       return NULL;
+               }
+       }
+
+       function feedItemDesc( $row ) {
+               return isset( $row->comment )
+                       ? htmlspecialchars( $row->comment )
+                       : '';
+       }
+
+       function feedItemAuthor( $row ) {
+               if( isset( $row->user_text ) ) {
+                       return $row->user_text;
+               } else {
+                       return '';
+               }
+       }
+
+       function feedTitle() {
+               global $wgLanguageCode, $wgSitename, $wgLang;
+               $page = SpecialPage::getPage( $this->getName() );
+               $desc = $page->getDescription();
+               return "$wgSitename - $desc [$wgLanguageCode]";
+       }
+
+       function feedDesc() {
+               return wfMsg( 'tagline' );
+       }
+
+       function feedUrl() {
+               global $wgLang;
+               $title = Title::MakeTitle( NS_SPECIAL, $this->getName() );
+               return $title->getFullURL();
+       }
+}
+
+/**
+ * This is a subclass for very simple queries that are just looking for page
+ * titles that match some criteria. It formats each result item as a link to
+ * that page.
+ *
+ * @package MediaWiki
+ */
+class PageQueryPage extends QueryPage {
+
+       function formatResult( $skin, $result ) {
+               global $wgContLang;
+               $nt = Title::makeTitle( $result->namespace, $result->title );
+               return $skin->makeKnownLinkObj( $nt, $wgContLang->convert( $nt->getPrefixedText() ) );
+       }
+}
+
+?>
diff --git a/includes/RawPage.php b/includes/RawPage.php
new file mode 100644 (file)
index 0000000..1473922
--- /dev/null
@@ -0,0 +1,139 @@
+<?php
+/**
+ * Copyright (C) 2004 Gabriel Wicke <gw@wikidev.net>
+ * http://www.aulinx.de/
+ * Based on PageHistory and SpecialExport
+ * 
+ * License: GPL (http://www.gnu.org/copyleft/gpl.html)
+ *
+ * @author Gabriel Wicke <gw@wikidev.net>
+ * @package MediaWiki
+ */
+
+/** */
+require_once( 'Revision.php' );
+
+/**
+ * @todo document
+ * @package MediaWiki
+ */
+class RawPage {
+
+       function RawPage( $article ) {
+               global $wgRequest, $wgInputEncoding, $wgSquidMaxage, $wgJsMimeType;
+               $allowedCTypes = array('text/x-wiki', $wgJsMimeType, 'text/css', 'application/x-zope-edit');
+               $this->mArticle =& $article;
+               $this->mTitle =& $article->mTitle;
+                       
+               $ctype = $wgRequest->getText( 'ctype' );
+               $smaxage = $wgRequest->getInt( 'smaxage', $wgSquidMaxage );
+               $maxage = $wgRequest->getInt( 'maxage', $wgSquidMaxage );
+               $this->mOldId = $wgRequest->getInt( 'oldid' );
+               # special case for 'generated' raw things: user css/js
+               $gen = $wgRequest->getText( 'gen' );
+               if($gen == 'css') {
+                       $this->mGen = $gen;
+                       if($smaxage == '') $smaxage = $wgSquidMaxage;
+                       if($ctype == '') $ctype = 'text/css';
+               } else if ($gen == 'js') {
+                       $this->mGen = $gen;
+                       if($smaxage == '') $smaxage = $wgSquidMaxage;
+                       if($ctype == '') $ctype = $wgJsMimeType;
+               } else {
+                       $this->mGen = false;
+               }
+               $this->mCharset = $wgInputEncoding;
+               $this->mSmaxage = $smaxage;
+               $this->mMaxage = $maxage;
+               if(empty($ctype) or !in_array($ctype, $allowedCTypes)) {
+                       $this->mContentType = 'text/x-wiki';
+               } else {
+                       $this->mContentType = $ctype;
+               }
+       }
+       
+       function view() {
+               global $wgUser, $wgOut, $wgScript;
+
+               if( isset( $_SERVER['SCRIPT_URL'] ) ) {
+                       # Normally we use PHP_SELF to get the URL to the script
+                       # as it was called, minus the query string.
+                       #
+                       # Some sites use Apache rewrite rules to handle subdomains,
+                       # and have PHP set up in a weird way that causes PHP_SELF
+                       # to contain the rewritten URL instead of the one that the
+                       # outside world sees.
+                       #
+                       # If in this mode, use SCRIPT_URL instead, which mod_rewrite
+                       # provides containing the "before" URL.
+                       $url = $_SERVER['SCRIPT_URL'];
+               } else {
+                       $url = $_SERVER['PHP_SELF'];
+               }
+               if( strcmp( $wgScript, $url ) ) {
+                       # Internet Explorer will ignore the Content-Type header if it
+                       # thinks it sees a file extension it recognizes. Make sure that
+                       # all raw requests are done through the script node, which will
+                       # have eg '.php' and should remain safe.
+                       #
+                       # We used to redirect to a canonical-form URL as a general
+                       # backwards-compatibility / good-citizen nice thing. However
+                       # a lot of servers are set up in buggy ways, resulting in
+                       # redirect loops which hang the browser until the CSS load
+                       # times out.
+                       #
+                       # Just return a 403 Forbidden and get it over with.
+                       wfHttpError( 403, 'Forbidden',
+                               'Raw pages must be accessed through the primary script entry point.' );
+                       return;
+               }
+               
+               header( "Content-type: ".$this->mContentType.'; charset='.$this->mCharset );
+               # allow the client to cache this for 24 hours
+               header( 'Cache-Control: s-maxage='.$this->mSmaxage.', max-age='.$this->mMaxage );
+               if($this->mGen) {
+                       $sk = $wgUser->getSkin();
+                       $sk->initPage($wgOut);
+                       if($this->mGen == 'css') {
+                               echo $sk->getUserStylesheet();
+                       } else if($this->mGen == 'js') {
+                               echo $sk->getUserJs();
+                       }
+               } else {
+                       echo $this->getrawtext();
+               }
+               $wgOut->disable();
+       }
+       
+       function getrawtext () {
+               global $wgInputEncoding, $wgContLang;
+               $fname = 'RawPage::getrawtext';
+               
+               if( $this->mTitle ) {
+                       # Special case for MediaWiki: messages; we can hit the message cache.
+                       if( $this->mTitle->getNamespace() == NS_MEDIAWIKI) {
+                               $rawtext = wfMsgForContent( $this->mTitle->getDbkey() );
+                               return $rawtext;
+                       }
+                       
+                       # else get it from the DB
+                       $rev = Revision::newFromTitle( $this->mTitle, $this->mOldId );
+                       if( $rev ) {
+                               $lastmod = wfTimestamp( TS_RFC2822, $rev->getTimestamp() );
+                               header( 'Last-modified: ' . $lastmod );
+                               return $rev->getText();
+                       }
+               }
+               
+               # Bad title or page does not exist
+               if( $this->mContentType == 'text/x-wiki' ) {
+                       # Don't return a 404 response for CSS or JavaScript;
+                       # 404s aren't generally cached and it would create
+                       # extra hits when user CSS/JS are on and the user doesn't
+                       # have the pages.
+                       header( "HTTP/1.0 404 Not Found" );
+               }
+               return '';
+       }
+}
+?>
diff --git a/includes/RecentChange.php b/includes/RecentChange.php
new file mode 100644 (file)
index 0000000..69cbb17
--- /dev/null
@@ -0,0 +1,452 @@
+<?php
+/**
+ *
+ * @package MediaWiki
+ */
+
+/**
+ * Various globals
+ */
+define( 'RC_EDIT', 0);
+define( 'RC_NEW', 1);
+define( 'RC_MOVE', 2);
+define( 'RC_LOG', 3);
+define( 'RC_MOVE_OVER_REDIRECT', 4);
+
+
+/**
+ * Utility class for creating new RC entries
+ * mAttribs:
+ *     rc_id           id of the row in the recentchanges table
+ *     rc_timestamp    time the entry was made
+ *     rc_cur_time     timestamp on the cur row
+ *     rc_namespace    namespace #
+ *     rc_title        non-prefixed db key
+ *     rc_type         is new entry, used to determine whether updating is necessary
+ *     rc_minor        is minor
+ *     rc_cur_id       page_id of associated page entry
+ *     rc_user         user id who made the entry
+ *     rc_user_text    user name who made the entry
+ *     rc_comment      edit summary
+ *     rc_this_oldid   rev_id associated with this entry (or zero)
+ *     rc_last_oldid   rev_id associated with the entry before this one (or zero)
+ *     rc_bot          is bot, hidden
+ *     rc_ip           IP address of the user in dotted quad notation
+ *     rc_new          obsolete, use rc_type==RC_NEW
+ *     rc_patrolled    boolean whether or not someone has marked this edit as patrolled
+ *
+ * mExtra:
+ *     prefixedDBkey   prefixed db key, used by external app via msg queue
+ *     lastTimestamp   timestamp of previous entry, used in WHERE clause during update
+ *     lang            the interwiki prefix, automatically set in save()
+ *  oldSize         text size before the change
+ *  newSize         text size after the change
+ *
+ * temporary:          not stored in the database
+ *      notificationtimestamp
+ *      numberofWatchingusers
+ *
+ * @todo document functions and variables
+ * @package MediaWiki
+ */
+class RecentChange
+{
+       var $mAttribs = array(), $mExtra = array();
+       var $mTitle = false, $mMovedToTitle = false;
+
+       # Factory methods
+
+       /* static */ function newFromRow( $row )
+       {
+               $rc = new RecentChange;
+               $rc->loadFromRow( $row );
+               return $rc;
+       }
+
+       /* static */ function newFromCurRow( $row, $rc_this_oldid = 0 )
+       {
+               $rc = new RecentChange;
+               $rc->loadFromCurRow( $row, $rc_this_oldid );
+               $rc->notificationtimestamp = false;
+               $rc->numberofWatchingusers = false;
+               return $rc;
+       }
+
+       # Accessors
+
+       function setAttribs( $attribs )
+       {
+               $this->mAttribs = $attribs;
+       }
+
+       function setExtra( $extra )
+       {
+               $this->mExtra = $extra;
+       }
+
+       function &getTitle()
+       {
+               if ( $this->mTitle === false ) {
+                       $this->mTitle = Title::makeTitle( $this->mAttribs['rc_namespace'], $this->mAttribs['rc_title'] );
+               }
+               return $this->mTitle;
+       }
+
+       function getMovedToTitle()
+       {
+               if ( $this->mMovedToTitle === false ) {
+                       $this->mMovedToTitle = Title::makeTitle( $this->mAttribs['rc_moved_to_ns'],
+                               $this->mAttribs['rc_moved_to_title'] );
+               }
+               return $this->mMovedToTitle;
+       }
+
+       # Writes the data in this object to the database
+       function save()
+       {
+               global $wgLocalInterwiki, $wgPutIPinRC, $wgRC2UDPAddress, $wgRC2UDPPort, $wgRC2UDPPrefix;
+               $fname = 'RecentChange::save';
+
+               $dbw =& wfGetDB( DB_MASTER );
+               if ( !is_array($this->mExtra) ) {
+                       $this->mExtra = array();
+               }
+               $this->mExtra['lang'] = $wgLocalInterwiki;
+
+               if ( !$wgPutIPinRC ) {
+                       $this->mAttribs['rc_ip'] = '';
+               }
+
+               # Fixup database timestamps
+               $this->mAttribs['rc_timestamp']=$dbw->timestamp($this->mAttribs['rc_timestamp']);
+               $this->mAttribs['rc_cur_time']=$dbw->timestamp($this->mAttribs['rc_cur_time']);
+
+               # Insert new row
+               $dbw->insert( 'recentchanges', $this->mAttribs, $fname );
+
+               # Update old rows, if necessary
+               if ( $this->mAttribs['rc_type'] == RC_EDIT ) {
+                       $oldid = $this->mAttribs['rc_last_oldid'];
+                       $ns = $this->mAttribs['rc_namespace'];
+                       $title = $this->mAttribs['rc_title'];
+                       $lastTime = $this->mExtra['lastTimestamp'];
+                       $now = $this->mAttribs['rc_timestamp'];
+                       $curId = $this->mAttribs['rc_cur_id'];
+
+                       # Don't bother looking for entries that have probably
+                       # been purged, it just locks up the indexes needlessly.
+                       global $wgRCMaxAge;
+                       $age = time() - wfTimestamp( TS_UNIX, $lastTime );
+                       if( $age < $wgRCMaxAge ) {
+                                # live hack, will commit once tested - kate
+                               # Update rc_this_oldid for the entries which were current
+                               #$dbw->update( 'recentchanges',
+                               #       array( /* SET */
+                               #               'rc_this_oldid' => $oldid
+                               #       ), array( /* WHERE */
+                               #               'rc_namespace' => $ns,
+                               #               'rc_title' => $title,
+                               #               'rc_timestamp' => $dbw->timestamp( $lastTime )
+                               #       ), $fname
+                               #);
+                       }
+
+                       # Update rc_cur_time
+                       $dbw->update( 'recentchanges', array( 'rc_cur_time' => $now ),
+                               array( 'rc_cur_id' => $curId ), $fname );
+               }
+
+               # Notify external application via UDP
+               if ( $wgRC2UDPAddress ) {
+                       $conn = socket_create( AF_INET, SOCK_DGRAM, SOL_UDP );
+                       if ( $conn ) {
+                               $line = $wgRC2UDPPrefix . $this->getIRCLine();
+                               socket_sendto( $conn, $line, strlen($line), 0, $wgRC2UDPAddress, $wgRC2UDPPort );
+                               socket_close( $conn );
+                       }
+               }
+       }
+
+       # Marks a certain row as patrolled
+       function markPatrolled( $rcid )
+       {
+               $fname = 'RecentChange::markPatrolled';
+
+               $dbw =& wfGetDB( DB_MASTER );
+
+               $dbw->update( 'recentchanges',
+                       array( /* SET */
+                               'rc_patrolled' => 1
+                       ), array( /* WHERE */
+                               'rc_id' => $rcid
+                       ), $fname
+               );
+       }
+
+       # Makes an entry in the database corresponding to an edit
+       /*static*/ function notifyEdit( $timestamp, &$title, $minor, &$user, $comment,
+               $oldId, $lastTimestamp, $bot = "default", $ip = '', $oldSize = 0, $newSize = 0,
+               $newId = 0)
+       {
+               if ( $bot == 'default ' ) {
+                       $bot = $user->isBot();
+               }
+
+               if ( !$ip ) {
+                       global $wgIP;
+                       $ip = empty( $wgIP ) ? '' : $wgIP;
+               }
+
+               $rc = new RecentChange;
+               $rc->mAttribs = array(
+                       'rc_timestamp'  => $timestamp,
+                       'rc_cur_time'   => $timestamp,
+                       'rc_namespace'  => $title->getNamespace(),
+                       'rc_title'      => $title->getDBkey(),
+                       'rc_type'       => RC_EDIT,
+                       'rc_minor'      => $minor ? 1 : 0,
+                       'rc_cur_id'     => $title->getArticleID(),
+                       'rc_user'       => $user->getID(),
+                       'rc_user_text'  => $user->getName(),
+                       'rc_comment'    => $comment,
+                       'rc_this_oldid' => $newId,
+                       'rc_last_oldid' => $oldId,
+                       'rc_bot'        => $bot ? 1 : 0,
+                       'rc_moved_to_ns'        => 0,
+                       'rc_moved_to_title'     => '',
+                       'rc_ip' => $ip,
+                       'rc_patrolled' => 0,
+                       'rc_new'        => 0 # obsolete
+               );
+
+               $rc->mExtra =  array(
+                       'prefixedDBkey' => $title->getPrefixedDBkey(),
+                       'lastTimestamp' => $lastTimestamp,
+                       'oldSize'       => $oldSize,
+                       'newSize'       => $newSize,
+               );
+               $rc->save();
+       }
+
+       # Makes an entry in the database corresponding to page creation
+       # Note: the title object must be loaded with the new id using resetArticleID()
+       /*static*/ function notifyNew( $timestamp, &$title, $minor, &$user, $comment, $bot = "default",
+         $ip='', $size = 0, $newId = 0 )
+       {
+               if ( !$ip ) {
+                       global $wgIP;
+                       $ip = empty( $wgIP ) ? '' : $wgIP;
+               }
+               if ( $bot == 'default' ) {
+                       $bot = $user->isBot();
+               }
+
+               $rc = new RecentChange;
+               $rc->mAttribs = array(
+                       'rc_timestamp'      => $timestamp,
+                       'rc_cur_time'       => $timestamp,
+                       'rc_namespace'      => $title->getNamespace(),
+                       'rc_title'          => $title->getDBkey(),
+                       'rc_type'           => RC_NEW,
+                       'rc_minor'          => $minor ? 1 : 0,
+                       'rc_cur_id'         => $title->getArticleID(),
+                       'rc_user'           => $user->getID(),
+                       'rc_user_text'      => $user->getName(),
+                       'rc_comment'        => $comment,
+                       'rc_this_oldid'     => $newId,
+                       'rc_last_oldid'     => 0,
+                       'rc_bot'            => $bot ? 1 : 0,
+                       'rc_moved_to_ns'    => 0,
+                       'rc_moved_to_title' => '',
+                       'rc_ip'             => $ip,
+                       'rc_patrolled'      => 0,
+                       'rc_new'        => 1 # obsolete
+               );
+
+               $rc->mExtra =  array(
+                       'prefixedDBkey' => $title->getPrefixedDBkey(),
+                       'lastTimestamp' => 0,
+                       'oldSize' => 0,
+                       'newSize' => $size
+               );
+               $rc->save();
+       }
+
+       # Makes an entry in the database corresponding to a rename
+       /*static*/ function notifyMove( $timestamp, &$oldTitle, &$newTitle, &$user, $comment, $ip='', $overRedir = false )
+       {
+               if ( !$ip ) {
+                       global $wgIP;
+                       $ip = empty( $wgIP ) ? '' : $wgIP;
+               }
+               $rc = new RecentChange;
+               $rc->mAttribs = array(
+                       'rc_timestamp'  => $timestamp,
+                       'rc_cur_time'   => $timestamp,
+                       'rc_namespace'  => $oldTitle->getNamespace(),
+                       'rc_title'      => $oldTitle->getDBkey(),
+                       'rc_type'       => $overRedir ? RC_MOVE_OVER_REDIRECT : RC_MOVE,
+                       'rc_minor'      => 0,
+                       'rc_cur_id'     => $oldTitle->getArticleID(),
+                       'rc_user'       => $user->getID(),
+                       'rc_user_text'  => $user->getName(),
+                       'rc_comment'    => $comment,
+                       'rc_this_oldid' => 0,
+                       'rc_last_oldid' => 0,
+                       'rc_bot'        => $user->isBot() ? 1 : 0,
+                       'rc_moved_to_ns'        => $newTitle->getNamespace(),
+                       'rc_moved_to_title'     => $newTitle->getDBkey(),
+                       'rc_ip'         => $ip,
+                       'rc_new'        => 0, # obsolete
+                       'rc_patrolled' => 1
+               );
+
+               $rc->mExtra = array(
+                       'prefixedDBkey' => $oldTitle->getPrefixedDBkey(),
+                       'lastTimestamp' => 0,
+                       'prefixedMoveTo'        => $newTitle->getPrefixedDBkey()
+               );
+               $rc->save();
+       }
+
+       /* static */ function notifyMoveToNew( $timestamp, &$oldTitle, &$newTitle, &$user, $comment, $ip='' ) {
+               RecentChange::notifyMove( $timestamp, $oldTitle, $newTitle, $user, $comment, $ip, false );
+       }
+
+       /* static */ function notifyMoveOverRedirect( $timestamp, &$oldTitle, &$newTitle, &$user, $comment, $ip='' ) {
+               RecentChange::notifyMove( $timestamp, $oldTitle, $newTitle, $user, $comment, $ip='', true );
+       }
+
+       # A log entry is different to an edit in that previous revisions are
+       # not kept
+       /*static*/ function notifyLog( $timestamp, &$title, &$user, $comment, $ip='' )
+       {
+               if ( !$ip ) {
+                       global $wgIP;
+                       $ip = empty( $wgIP ) ? '' : $wgIP;
+               }
+               $rc = new RecentChange;
+               $rc->mAttribs = array(
+                       'rc_timestamp'  => $timestamp,
+                       'rc_cur_time'   => $timestamp,
+                       'rc_namespace'  => $title->getNamespace(),
+                       'rc_title'      => $title->getDBkey(),
+                       'rc_type'       => RC_LOG,
+                       'rc_minor'      => 0,
+                       'rc_cur_id'     => $title->getArticleID(),
+                       'rc_user'       => $user->getID(),
+                       'rc_user_text'  => $user->getName(),
+                       'rc_comment'    => $comment,
+                       'rc_this_oldid' => 0,
+                       'rc_last_oldid' => 0,
+                       'rc_bot'        => 0,
+                       'rc_moved_to_ns'        => 0,
+                       'rc_moved_to_title'     => '',
+                       'rc_ip' => $ip,
+                       'rc_patrolled' => 1,
+                       'rc_new'        => 0 # obsolete
+               );
+               $rc->mExtra =  array(
+                       'prefixedDBkey' => $title->getPrefixedDBkey(),
+                       'lastTimestamp' => 0
+               );
+               $rc->save();
+       }
+
+       # Initialises the members of this object from a mysql row object
+       function loadFromRow( $row )
+       {
+               $this->mAttribs = get_object_vars( $row );
+               $this->mExtra = array();
+       }
+
+       # Makes a pseudo-RC entry from a cur row, for watchlists and things
+       function loadFromCurRow( $row )
+       {
+               $this->mAttribs = array(
+                       'rc_timestamp' => $row->rev_timestamp,
+                       'rc_cur_time' => $row->rev_timestamp,
+                       'rc_user' => $row->rev_user,
+                       'rc_user_text' => $row->rev_user_text,
+                       'rc_namespace' => $row->page_namespace,
+                       'rc_title' => $row->page_title,
+                       'rc_comment' => $row->rev_comment,
+                       'rc_minor' => $row->rev_minor_edit ? 1 : 0,
+                       'rc_type' => $row->page_is_new ? RC_NEW : RC_EDIT,
+                       'rc_cur_id' => $row->page_id,
+                       'rc_this_oldid' => $row->rev_id,
+                       'rc_last_oldid' => isset($row->rc_last_oldid) ? $row->rc_last_oldid : 0,
+                       'rc_bot'        => 0,
+                       'rc_moved_to_ns'        => 0,
+                       'rc_moved_to_title'     => '',
+                       'rc_ip' => '',
+                       'rc_patrolled' => '1',  # we can't support patrolling on the Watchlist
+                                               # currently because it uses cur, not recentchanges
+                       'rc_new' => $row->page_is_new # obsolete
+               );
+
+               $this->mExtra = array();
+       }
+
+
+       /**
+        * Gets the end part of the diff URL associated with this object
+        * Blank if no diff link should be displayed
+        */
+       function diffLinkTrail( $forceCur )
+       {
+               if ( $this->mAttribs['rc_type'] == RC_EDIT ) {
+                       $trail = "curid=" . (int)($this->mAttribs['rc_cur_id']) .
+                               "&oldid=" . (int)($this->mAttribs['rc_last_oldid']);
+                       if ( $forceCur ) {
+                               $trail .= '&diff=0' ;
+                       } else {
+                               $trail .= '&diff=' . (int)($this->mAttribs['rc_this_oldid']);
+                       }
+               } else {
+                       $trail = '';
+               }
+               return $trail;
+       }
+
+       function getIRCLine() {
+               extract($this->mAttribs);
+               extract($this->mExtra);
+
+               $titleObj =& $this->getTitle();
+
+               $bad = array("\n", "\r");
+               $empty = array("", "");
+               $title = $titleObj->getPrefixedText();
+               $title = str_replace($bad, $empty, $title);
+
+               if ( $rc_new ) {
+                       $url = $titleObj->getFullURL();
+               } else {
+                       $url = $titleObj->getFullURL("diff=0&oldid=$rc_last_oldid");
+               }
+
+               if ( isset( $oldSize ) && isset( $newSize ) ) {
+                       $szdiff = $newSize - $oldSize;
+                       if ($szdiff < -500)
+                               $szdiff = "\002$szdiff\002";
+                       else if ($szdiff >= 0)
+                               $szdiff = "+$szdiff";
+                       $szdiff = "($szdiff)";
+               } else {
+                       $szdiff = '';
+               }
+
+               $comment = str_replace($bad, $empty, $rc_comment);
+               $user = str_replace($bad, $empty, $rc_user_text);
+               $flag = ($rc_minor ? "M" : "") . ($rc_new ? "N" : "");
+               # see http://www.irssi.org/?page=docs&doc=formats for some colour codes. prefix is \003,
+               # no colour (\003) switches back to the term default
+               $comment = preg_replace("/\/\* (.*) \*\/(.*)/", "\00315\$1\003 - \00310\$2\003", $comment);
+               $fullString = "\00314[[\00307$title\00314]]\0034 $flag\00310 " .
+                             "\00302$url\003 \0035*\003 \00303$user\003 \0035*\003 $szdiff \00310$comment\003\n";
+
+               return $fullString;
+       }
+}
+?>
diff --git a/includes/Revision.php b/includes/Revision.php
new file mode 100644 (file)
index 0000000..3348884
--- /dev/null
@@ -0,0 +1,630 @@
+<?php
+/**
+ * @package MediaWiki
+ * @todo document
+ */
+
+/** */
+require_once( 'Database.php' );
+require_once( 'Article.php' );
+
+/**
+ * @package MediaWiki
+ * @todo document
+ */
+class Revision {
+       /**
+        * Load a page revision from a given revision ID number.
+        * Returns null if no such revision can be found.
+        *
+        * @param int $id
+        * @static
+        * @access public
+        */
+       function newFromId( $id ) {
+               return Revision::newFromConds(
+                       array( 'page_id=rev_page',
+                              'rev_id' => IntVal( $id ) ) );
+       }
+       
+       /**
+        * Load either the current, or a specified, revision
+        * that's attached to a given title. If not attached
+        * to that title, will return null.
+        *
+        * @param Title $title
+        * @param int $id
+        * @return Revision
+        * @access public
+        * @static
+        */
+       function newFromTitle( &$title, $id = 0 ) {
+               if( $id ) {
+                       $matchId = IntVal( $id );
+               } else {
+                       $matchId = 'page_latest';
+               }
+               return Revision::newFromConds(
+                       array( "rev_id=$matchId",
+                              'page_id=rev_page',
+                              'page_namespace' => $title->getNamespace(),
+                              'page_title'     => $title->getDbkey() ) );
+       }
+       
+       /**
+        * Load either the current, or a specified, revision
+        * that's attached to a given page. If not attached
+        * to that page, will return null.
+        *
+        * @param Database $db
+        * @param int $pageid
+        * @param int $id
+        * @return Revision
+        * @access public
+        */
+       function loadFromPageId( &$db, $pageid, $id = 0 ) {
+               $conds=array('page_id=rev_page','rev_page'=>intval( $pageid ), 'page_id'=>intval( $pageid ));
+               if( $id ) {
+                       $conds['rev_id']=intval($id);
+               } else {
+                       $conds[]='rev_id=page_latest';
+               }
+               return Revision::loadFromConds( $db, $conds );
+       }
+       
+       /**
+        * Load either the current, or a specified, revision
+        * that's attached to a given page. If not attached
+        * to that page, will return null.
+        *
+        * @param Database $db
+        * @param Title $title
+        * @param int $id
+        * @return Revision
+        * @access public
+        */
+       function loadFromTitle( &$db, $title, $id = 0 ) {
+               if( $id ) {
+                       $matchId = IntVal( $id );
+               } else {
+                       $matchId = 'page_latest';
+               }
+               return Revision::loadFromConds(
+                       $db,
+                       array( "rev_id=$matchId",
+                              'page_id=rev_page',
+                              'page_namespace' => $title->getNamespace(),
+                              'page_title'     => $title->getDbkey() ) );
+       }
+       
+       /**
+        * Load the revision for the given title with the given timestamp.
+        * WARNING: Timestamps may in some circumstances not be unique,
+        * so this isn't the best key to use.
+        *
+        * @param Database $db
+        * @param Title $title
+        * @param string $timestamp
+        * @return Revision
+        * @access public
+        * @static
+        */
+       function loadFromTimestamp( &$db, &$title, $timestamp ) {
+               return Revision::loadFromConds(
+                       $db,
+                       array( 'rev_timestamp'  => $db->timestamp( $timestamp ),
+                              'page_id=rev_page',
+                              'page_namespace' => $title->getNamespace(),
+                              'page_title'     => $title->getDbkey() ) );
+       }
+       
+       /**
+        * Given a set of conditions, fetch a revision.
+        *
+        * @param array $conditions
+        * @return Revision
+        * @static
+        * @access private
+        */
+       function newFromConds( $conditions ) {
+               $db =& wfGetDB( DB_SLAVE );
+               $row = Revision::loadFromConds( $db, $conditions );
+               if( is_null( $row ) ) {
+                       $dbw =& wfGetDB( DB_MASTER );
+                       $row = Revision::loadFromConds( $dbw, $conditions );
+               }
+               return $row;
+       }
+       
+       /**
+        * Given a set of conditions, fetch a revision from
+        * the given database connection.
+        *
+        * @param Database $db
+        * @param array $conditions
+        * @return Revision
+        * @static
+        * @access private
+        */
+       function loadFromConds( &$db, $conditions ) {
+               $res = Revision::fetchFromConds( $db, $conditions );
+               if( $res ) {
+                       $row = $res->fetchObject();
+                       $res->free();
+                       if( $row ) {
+                               return new Revision( $row );
+                       }
+               }
+               return null;
+       }
+       
+       /**
+        * Return a wrapper for a series of database rows to
+        * fetch all of a given page's revisions in turn.
+        * Each row can be fed to the constructor to get objects.
+        *
+        * @param Title $title
+        * @return ResultWrapper
+        * @static
+        * @access public
+        */
+       function fetchAllRevisions( &$title ) {
+               return Revision::fetchFromConds(
+                       wfGetDB( DB_SLAVE ),
+                       array( 'page_namespace' => $title->getNamespace(),
+                              'page_title'     => $title->getDbkey(),
+                              'page_id=rev_page' ) );          
+       }
+       
+       /**
+        * Return a wrapper for a series of database rows to
+        * fetch all of a given page's revisions in turn.
+        * Each row can be fed to the constructor to get objects.
+        *
+        * @param Title $title
+        * @return ResultWrapper
+        * @static
+        * @access public
+        */
+       function fetchRevision( &$title ) {
+               return Revision::fetchFromConds(
+                       wfGetDB( DB_SLAVE ),
+                       array( 'rev_id=page_latest',
+                              'page_namespace' => $title->getNamespace(),
+                              'page_title'     => $title->getDbkey(),
+                              'page_id=rev_page' ) );          
+       }
+       
+       /**
+        * Given a set of conditions, return a ResultWrapper
+        * which will return matching database rows with the
+        * fields necessary to build Revision objects.
+        *
+        * @param Database $db
+        * @param array $conditions
+        * @return ResultWrapper
+        * @static
+        * @access private
+        */
+       function fetchFromConds( &$db, $conditions ) {
+               $res = $db->select(
+                       array( 'page', 'revision' ),
+                       array( 'page_namespace',
+                              'page_title',
+                              'page_latest',
+                              'rev_id',
+                              'rev_page',
+                              'rev_text_id',
+                              'rev_comment',
+                              'rev_user_text',
+                              'rev_user',
+                              'rev_minor_edit',
+                              'rev_timestamp',
+                              'rev_deleted' ),
+                       $conditions,
+                       'Revision::fetchRow',
+                       array( 'LIMIT' => 1 ) );
+               return $db->resultObject( $res );
+       }
+       
+       /**
+        * @param object $row
+        * @access private
+        */
+       function Revision( $row ) {
+               if( is_object( $row ) ) {
+                       $this->mId        = IntVal( $row->rev_id );
+                       $this->mPage      = IntVal( $row->rev_page );
+                       $this->mTextId    = IntVal( $row->rev_text_id );
+                       $this->mComment   =         $row->rev_comment;
+                       $this->mUserText  =         $row->rev_user_text;
+                       $this->mUser      = IntVal( $row->rev_user );
+                       $this->mMinorEdit = IntVal( $row->rev_minor_edit );
+                       $this->mTimestamp =         $row->rev_timestamp;
+                       $this->mDeleted   = IntVal( $row->rev_deleted );
+               
+                       $this->mCurrent   = ( $row->rev_id == $row->page_latest );
+                       $this->mTitle     = Title::makeTitle( $row->page_namespace,
+                                                             $row->page_title );
+                       
+                       if( isset( $row->old_text ) ) {
+                               $this->mText  = $this->getRevisionText( $row );
+                       } else {
+                               $this->mText  = null;
+                       }
+               } elseif( is_array( $row ) ) {
+                       // Build a new revision to be saved...
+                       global $wgUser;
+                       
+                       $this->mId        = isset( $row['id']         ) ? IntVal( $row['id']         ) : null;
+                       $this->mPage      = isset( $row['page']       ) ? IntVal( $row['page']       ) : null;
+                       $this->mTextId    = isset( $row['text_id']    ) ? IntVal( $row['text_id']    ) : null;
+                       $this->mUserText  = isset( $row['user_text']  ) ? StrVal( $row['user_text']  ) : $wgUser->getName();
+                       $this->mUser      = isset( $row['user']       ) ? IntVal( $row['user']       ) : $wgUser->getId();
+                       $this->mMinorEdit = isset( $row['minor_edit'] ) ? IntVal( $row['minor_edit'] ) : 0;
+                       $this->mTimestamp = isset( $row['timestamp']  ) ? StrVal( $row['timestamp']  ) : wfTimestamp( TS_MW );
+                       $this->mDeleted   = isset( $row['deleted']    ) ? IntVal( $row['deleted']    ) : 0;
+                       
+                       // Enforce spacing trimming on supplied text
+                       $this->mComment   = isset( $row['comment']    ) ?  trim( StrVal( $row['comment'] ) ) : null;
+                       $this->mText      = isset( $row['text']       ) ? rtrim( StrVal( $row['text']    ) ) : null;
+                       
+                       $this->mTitle     = null; # Load on demand if needed
+                       $this->mCurrent   = false;
+               } else {
+                       wfDebugDieBacktrace( 'Revision constructor passed invalid row format.' );
+               }
+       }
+       
+       /**#@+
+        * @access public
+        */
+       
+       /**
+        * @return int
+        */
+       function getId() {
+               return $this->mId;
+       }
+       
+       /**
+        * @return int
+        */
+       function getTextId() {
+               return $this->mTextId;
+       }
+       
+       /**
+        * Returns the title of the page associated with this entry.
+        * @return Title
+        */
+       function getTitle() {
+               if( isset( $this->mTitle ) ) {
+                       return $this->mTitle;
+               }
+               $dbr =& wfGetDB( DB_SLAVE );
+               $row = $dbr->selectRow(
+                       array( 'page', 'revision' ),
+                       array( 'page_namespace', 'page_title' ),
+                       array( 'page_id=rev_page',
+                              'rev_id' => $this->mId ),
+                       'Revision::getTItle' );
+               if( $row ) {
+                       $this->mTitle = Title::makeTitle( $row->page_namespace,
+                                                          $row->page_title );
+               }
+               return $this->mTitle;
+       }
+       
+       /**
+        * @return int
+        */
+       function getPage() {
+               return $this->mPage;
+       }
+       
+       /**
+        * @return int
+        */
+       function getUser() {
+               return $this->mUser;
+       }
+       
+       /**
+        * @return string
+        */
+       function getUserText() {
+               return $this->mUserText;
+       }
+       
+       /**
+        * @return string
+        */
+       function getComment() {
+               return $this->mComment;
+       }
+       
+       /**
+        * @return bool
+        */
+       function isMinor() {
+               return (bool)$this->mMinorEdit;
+       }
+       
+       /**
+        * @return bool
+        */
+       function isDeleted() {
+               return (bool)$this->mDeleted;
+       }
+       
+       /**
+        * @return string
+        */
+       function getText() {
+               if( is_null( $this->mText ) ) {
+                       // Revision text is immutable. Load on demand:
+                       $this->mText = $this->loadText();
+               }
+               return $this->mText;
+       }
+       
+       /**
+        * @return string
+        */
+       function getTimestamp() {
+               return $this->mTimestamp;
+       }
+       
+       /**
+        * @return bool
+        */
+       function isCurrent() {
+               return $this->mCurrent;
+       }
+       
+       /**
+        * @return Revision
+        */
+       function getPrevious() {
+               $prev = $this->mTitle->getPreviousRevisionID( $this->mId );
+               return Revision::newFromTitle( $this->mTitle, $prev );
+       }
+
+       /**
+        * @return Revision
+        */
+       function getNext() {
+               $next = $this->mTitle->getNextRevisionID( $this->mId );
+               return Revision::newFromTitle( $this->mTitle, $next );
+       }
+       /**#@-*/
+
+       /**
+         * Get revision text associated with an old or archive row
+         * $row is usually an object from wfFetchRow(), both the flags and the text
+         * field must be included
+         * @static
+         * @param integer $row Id of a row
+         * @param string $prefix table prefix (default 'old_')
+         * @return string $text|false the text requested
+         */
+       function getRevisionText( $row, $prefix = 'old_' ) {
+               $fname = 'Revision::getRevisionText';
+               wfProfileIn( $fname );
+               
+               # Get data
+               $textField = $prefix . 'text';
+               $flagsField = $prefix . 'flags';
+
+               if( isset( $row->$flagsField ) ) {
+                       $flags = explode( ',', $row->$flagsField );
+               } else {
+                       $flags = array();
+               }
+
+               if( isset( $row->$textField ) ) {
+                       $text = $row->$textField;
+               } else {
+                       wfProfileOut( $fname );
+                       return false;
+               }
+
+               # Use external methods for external objects, text in table is URL-only then
+               if ( in_array( 'external', $flags ) ) {
+                       $url=$text;
+                       @list($proto,$path)=explode('://',$url,2);
+                       if ($path=="") {
+                               wfProfileOut( $fname );
+                               return false;
+                       }
+                       require_once('ExternalStore.php');
+                       $text=ExternalStore::fetchFromURL($url);
+               }
+
+               if( in_array( 'gzip', $flags ) ) {
+                       # Deal with optional compression of archived pages.
+                       # This can be done periodically via maintenance/compressOld.php, and
+                       # as pages are saved if $wgCompressRevisions is set.
+                       $text = gzinflate( $text );
+               }
+                       
+               if( in_array( 'object', $flags ) ) {
+                       # Generic compressed storage
+                       $obj = unserialize( $text );
+
+                       # Bugger, corrupted my test database by double-serializing
+                       if ( !is_object( $obj ) ) {
+                               $obj = unserialize( $obj );
+                       }
+
+                       $text = $obj->getText();
+               }
+       
+               global $wgLegacyEncoding;
+               if( $wgLegacyEncoding && !in_array( 'utf-8', $flags ) ) {
+                       # Old revisions kept around in a legacy encoding?
+                       # Upconvert on demand.
+                       global $wgInputEncoding, $wgContLang;
+                       $text = $wgContLang->iconv( $wgLegacyEncoding, $wgInputEncoding, $text );
+               }
+               wfProfileOut( $fname );
+               return $text;
+       }
+
+       /**
+        * If $wgCompressRevisions is enabled, we will compress data.
+        * The input string is modified in place.
+        * Return value is the flags field: contains 'gzip' if the
+        * data is compressed, and 'utf-8' if we're saving in UTF-8
+        * mode.
+        *
+        * @static
+        * @param mixed $text reference to a text
+        * @return string
+        */
+       function compressRevisionText( &$text ) {
+               global $wgCompressRevisions;
+               $flags = array();
+               
+               # Revisions not marked this way will be converted
+               # on load if $wgLegacyCharset is set in the future.
+               $flags[] = 'utf-8';
+               
+               if( $wgCompressRevisions ) {
+                       if( function_exists( 'gzdeflate' ) ) {
+                               $text = gzdeflate( $text );
+                               $flags[] = 'gzip';
+                       } else {
+                               wfDebug( "Revision::compressRevisionText() -- no zlib support, not compressing\n" );
+                       }
+               }
+               return implode( ',', $flags );
+       }
+       
+       /**
+        * Insert a new revision into the database, returning the new revision ID
+        * number on success and dies horribly on failure.
+        *
+        * @param Database $dbw
+        * @return int
+        */
+       function insertOn( &$dbw ) {
+               $fname = 'Revision::insertOn';
+               wfProfileIn( $fname );
+               
+               $mungedText = $this->mText;
+               $flags = Revision::compressRevisionText( $mungedText );
+               
+               # Record the text to the text table
+               if( !isset( $this->mTextId ) ) {
+                       $old_id = $dbw->nextSequenceValue( 'text_old_id_val' );
+                       $dbw->insert( 'text',
+                               array(
+                                       'old_id'    => $old_id,
+                                       'old_text'  => $mungedText,
+                                       'old_flags' => $flags,
+                               ), $fname
+                       );
+                       $this->mTextId = $dbw->insertId();
+               }
+               
+               # Record the edit in revisions
+               $rev_id = isset( $this->mId )
+                       ? $this->mId
+                       : $dbw->nextSequenceValue( 'rev_rev_id_val' );
+               $dbw->insert( 'revision',
+                       array(
+                               'rev_id'         => $rev_id,
+                               'rev_page'       => $this->mPage,
+                               'rev_text_id'    => $this->mTextId,
+                               'rev_comment'    => $this->mComment,
+                               'rev_minor_edit' => $this->mMinorEdit ? 1 : 0,
+                               'rev_user'       => $this->mUser,
+                               'rev_user_text'  => $this->mUserText,
+                               'rev_timestamp'  => $dbw->timestamp( $this->mTimestamp ),
+                               'rev_deleted'    => $this->mDeleted,
+                       ), $fname
+               );
+               
+               $this->mId = $dbw->insertId();
+               
+               wfProfileOut( $fname );
+               return $this->mId;
+       }
+       
+       /**
+        * Lazy-load the revision's text.
+        * Currently hardcoded to the 'text' table storage engine.
+        *
+        * @return string
+        * @access private
+        */
+       function loadText() {
+               $fname = 'Revision::loadText';
+               wfProfileIn( $fname );
+               
+               $dbr =& wfGetDB( DB_SLAVE );
+               $row = $dbr->selectRow( 'text',
+                       array( 'old_text', 'old_flags' ),
+                       array( 'old_id' => $this->getTextId() ),
+                       $fname);
+               
+               if( !$row ) {
+                       $dbw =& wfGetDB( DB_MASTER );
+                       $row = $dbw->selectRow( 'text',
+                               array( 'old_text', 'old_flags' ),
+                               array( 'old_id' => $this->getTextId() ),
+                               $fname);
+               }
+               
+               $text = Revision::getRevisionText( $row );
+               wfProfileOut( $fname );
+               
+               return $text;
+       }
+
+       /**
+        * Create a new null-revision for insertion into a page's
+        * history. This will not re-save the text, but simply refer
+        * to the text from the previous version.
+        *
+        * Such revisions can for instance identify page rename
+        * operations and other such meta-modifications.
+        *
+        * @param Database $dbw
+        * @param int      $pageId ID number of the page to read from
+        * @param string   $summary
+        * @param bool     $minor
+        * @return Revision
+        */
+       function newNullRevision( &$dbw, $pageId, $summary, $minor ) {
+               $fname = 'Revision::newNullRevision';
+               wfProfileIn( $fname );
+               
+               $current = $dbw->selectRow(
+                       array( 'page', 'revision' ),
+                       array( 'page_latest', 'rev_text_id' ),
+                       array(
+                               'page_id' => $pageId,
+                               'page_latest=rev_id',
+                               ),
+                       $fname );
+               
+               if( $current ) {
+                       $revision = new Revision( array(
+                               'page'       => $pageId,
+                               'comment'    => $summary,
+                               'minor_edit' => $minor,
+                               'text_id'    => $current->rev_text_id,
+                               ) );
+               } else {
+                       $revision = null;
+               }
+               
+               wfProfileOut( $fname );
+               return $revision;
+       }
+       
+}
+?>
diff --git a/includes/Sanitizer.php b/includes/Sanitizer.php
new file mode 100644 (file)
index 0000000..3816b9d
--- /dev/null
@@ -0,0 +1,1033 @@
+<?php
+/**
+ * (X)HTML sanitizer for MediaWiki
+ *
+ * Copyright (C) 2002-2005 Brion Vibber <brion@pobox.com> et al
+ * http://www.mediawiki.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or 
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @package MediaWiki
+ * @subpackage Parser
+ */
+
+/**
+ * Regular expression to match various types of character references in
+ * Sanitizer::normalizeCharReferences and Sanitizer::decodeCharReferences
+ */
+define( 'MW_CHAR_REFS_REGEX',
+       '/&([A-Za-z0-9]+);
+        |&\#([0-9]+);
+        |&\#x([0-9A-Za-z]+);
+        |&\#X([0-9A-Za-z]+);
+        |(&)/x' );
+
+/**
+ * Regular expression to match HTML/XML attribute pairs within a tag.
+ * Allows some... latitude.
+ * Used in Sanitizer::fixTagAttributes and Sanitizer::decodeTagAttributes
+ */
+$attrib = '[A-Za-z0-9]'; 
+$space = '[\x09\x0a\x0d\x20]';
+define( 'MW_ATTRIBS_REGEX',
+       "/(?:^|$space)($attrib+)
+         ($space*=$space*
+               (?:
+                # The attribute value: quoted or alone
+                 \"([^<\"]*)\"
+                | '([^<']*)'
+                |  ([a-zA-Z0-9!#$%&()*,\\-.\\/:;<>?@[\\]^_`{|}~]+)
+                |  (\#[0-9a-fA-F]+) # Technically wrong, but lots of
+                                                        # colors are specified like this.
+                                                        # We'll be normalizing it.
+               )
+          )?(?=$space|\$)/sx" );
+
+/**
+ * List of all named character entities defined in HTML 4.01
+ * http://www.w3.org/TR/html4/sgml/entities.html
+ * @access private
+ */
+global $wgHtmlEntities;
+$wgHtmlEntities = array(
+       'Aacute'   => 193,
+       'aacute'   => 225,
+       'Acirc'    => 194,
+       'acirc'    => 226,
+       'acute'    => 180,
+       'AElig'    => 198,
+       'aelig'    => 230,
+       'Agrave'   => 192,
+       'agrave'   => 224,
+       'alefsym'  => 8501,
+       'Alpha'    => 913,
+       'alpha'    => 945,
+       'amp'      => 38,
+       'and'      => 8743,
+       'ang'      => 8736,
+       'Aring'    => 197,
+       'aring'    => 229,
+       'asymp'    => 8776,
+       'Atilde'   => 195,
+       'atilde'   => 227,
+       'Auml'     => 196,
+       'auml'     => 228,
+       'bdquo'    => 8222,
+       'Beta'     => 914,
+       'beta'     => 946,
+       'brvbar'   => 166,
+       'bull'     => 8226,
+       'cap'      => 8745,
+       'Ccedil'   => 199,
+       'ccedil'   => 231,
+       'cedil'    => 184,
+       'cent'     => 162,
+       'Chi'      => 935,
+       'chi'      => 967,
+       'circ'     => 710,
+       'clubs'    => 9827,
+       'cong'     => 8773,
+       'copy'     => 169,
+       'crarr'    => 8629,
+       'cup'      => 8746,
+       'curren'   => 164,
+       'dagger'   => 8224,
+       'Dagger'   => 8225,
+       'darr'     => 8595,
+       'dArr'     => 8659,
+       'deg'      => 176,
+       'Delta'    => 916,
+       'delta'    => 948,
+       'diams'    => 9830,
+       'divide'   => 247,
+       'Eacute'   => 201,
+       'eacute'   => 233,
+       'Ecirc'    => 202,
+       'ecirc'    => 234,
+       'Egrave'   => 200,
+       'egrave'   => 232,
+       'empty'    => 8709,
+       'emsp'     => 8195,
+       'ensp'     => 8194,
+       'Epsilon'  => 917,
+       'epsilon'  => 949,
+       'equiv'    => 8801,
+       'Eta'      => 919,
+       'eta'      => 951,
+       'ETH'      => 208,
+       'eth'      => 240,
+       'Euml'     => 203,
+       'euml'     => 235,
+       'euro'     => 8364,
+       'exist'    => 8707,
+       'fnof'     => 402,
+       'forall'   => 8704,
+       'frac12'   => 189,
+       'frac14'   => 188,
+       'frac34'   => 190,
+       'frasl'    => 8260,
+       'Gamma'    => 915,
+       'gamma'    => 947,
+       'ge'       => 8805,
+       'gt'       => 62,
+       'harr'     => 8596,
+       'hArr'     => 8660,
+       'hearts'   => 9829,
+       'hellip'   => 8230,
+       'Iacute'   => 205,
+       'iacute'   => 237,
+       'Icirc'    => 206,
+       'icirc'    => 238,
+       'iexcl'    => 161,
+       'Igrave'   => 204,
+       'igrave'   => 236,
+       'image'    => 8465,
+       'infin'    => 8734,
+       'int'      => 8747,
+       'Iota'     => 921,
+       'iota'     => 953,
+       'iquest'   => 191,
+       'isin'     => 8712,
+       'Iuml'     => 207,
+       'iuml'     => 239,
+       'Kappa'    => 922,
+       'kappa'    => 954,
+       'Lambda'   => 923,
+       'lambda'   => 955,
+       'lang'     => 9001,
+       'laquo'    => 171,
+       'larr'     => 8592,
+       'lArr'     => 8656,
+       'lceil'    => 8968,
+       'ldquo'    => 8220,
+       'le'       => 8804,
+       'lfloor'   => 8970,
+       'lowast'   => 8727,
+       'loz'      => 9674,
+       'lrm'      => 8206,
+       'lsaquo'   => 8249,
+       'lsquo'    => 8216,
+       'lt'       => 60,
+       'macr'     => 175,
+       'mdash'    => 8212,
+       'micro'    => 181,
+       'middot'   => 183,
+       'minus'    => 8722,
+       'Mu'       => 924,
+       'mu'       => 956,
+       'nabla'    => 8711,
+       'nbsp'     => 160,
+       'ndash'    => 8211,
+       'ne'       => 8800,
+       'ni'       => 8715,
+       'not'      => 172,
+       'notin'    => 8713,
+       'nsub'     => 8836,
+       'Ntilde'   => 209,
+       'ntilde'   => 241,
+       'Nu'       => 925,
+       'nu'       => 957,
+       'Oacute'   => 211,
+       'oacute'   => 243,
+       'Ocirc'    => 212,
+       'ocirc'    => 244,
+       'OElig'    => 338,
+       'oelig'    => 339,
+       'Ograve'   => 210,
+       'ograve'   => 242,
+       'oline'    => 8254,
+       'Omega'    => 937,
+       'omega'    => 969,
+       'Omicron'  => 927,
+       'omicron'  => 959,
+       'oplus'    => 8853,
+       'or'       => 8744,
+       'ordf'     => 170,
+       'ordm'     => 186,
+       'Oslash'   => 216,
+       'oslash'   => 248,
+       'Otilde'   => 213,
+       'otilde'   => 245,
+       'otimes'   => 8855,
+       'Ouml'     => 214,
+       'ouml'     => 246,
+       'para'     => 182,
+       'part'     => 8706,
+       'permil'   => 8240,
+       'perp'     => 8869,
+       'Phi'      => 934,
+       'phi'      => 966,
+       'Pi'       => 928,
+       'pi'       => 960,
+       'piv'      => 982,
+       'plusmn'   => 177,
+       'pound'    => 163,
+       'prime'    => 8242,
+       'Prime'    => 8243,
+       'prod'     => 8719,
+       'prop'     => 8733,
+       'Psi'      => 936,
+       'psi'      => 968,
+       'quot'     => 34,
+       'radic'    => 8730,
+       'rang'     => 9002,
+       'raquo'    => 187,
+       'rarr'     => 8594,
+       'rArr'     => 8658,
+       'rceil'    => 8969,
+       'rdquo'    => 8221,
+       'real'     => 8476,
+       'reg'      => 174,
+       'rfloor'   => 8971,
+       'Rho'      => 929,
+       'rho'      => 961,
+       'rlm'      => 8207,
+       'rsaquo'   => 8250,
+       'rsquo'    => 8217,
+       'sbquo'    => 8218,
+       'Scaron'   => 352,
+       'scaron'   => 353,
+       'sdot'     => 8901,
+       'sect'     => 167,
+       'shy'      => 173,
+       'Sigma'    => 931,
+       'sigma'    => 963,
+       'sigmaf'   => 962,
+       'sim'      => 8764,
+       'spades'   => 9824,
+       'sub'      => 8834,
+       'sube'     => 8838,
+       'sum'      => 8721,
+       'sup'      => 8835,
+       'sup1'     => 185,
+       'sup2'     => 178,
+       'sup3'     => 179,
+       'supe'     => 8839,
+       'szlig'    => 223,
+       'Tau'      => 932,
+       'tau'      => 964,
+       'there4'   => 8756,
+       'Theta'    => 920,
+       'theta'    => 952,
+       'thetasym' => 977,
+       'thinsp'   => 8201,
+       'THORN'    => 222,
+       'thorn'    => 254,
+       'tilde'    => 732,
+       'times'    => 215,
+       'trade'    => 8482,
+       'Uacute'   => 218,
+       'uacute'   => 250,
+       'uarr'     => 8593,
+       'uArr'     => 8657,
+       'Ucirc'    => 219,
+       'ucirc'    => 251,
+       'Ugrave'   => 217,
+       'ugrave'   => 249,
+       'uml'      => 168,
+       'upsih'    => 978,
+       'Upsilon'  => 933,
+       'upsilon'  => 965,
+       'Uuml'     => 220,
+       'uuml'     => 252,
+       'weierp'   => 8472,
+       'Xi'       => 926,
+       'xi'       => 958,
+       'Yacute'   => 221,
+       'yacute'   => 253,
+       'yen'      => 165,
+       'Yuml'     => 376,
+       'yuml'     => 255,
+       'Zeta'     => 918,
+       'zeta'     => 950,
+       'zwj'      => 8205,
+       'zwnj'     => 8204 );
+
+/** @package MediaWiki */
+class Sanitizer {
+       /**
+        * Cleans up HTML, removes dangerous tags and attributes, and
+        * removes HTML comments
+        * @access private
+        * @param string $text
+        * @param callback $processCallback to do any variable or parameter replacements in HTML attribute values
+        * @param array $args for the processing callback
+        * @return string
+        */
+       function removeHTMLtags( $text, $processCallback = null, $args = array() ) {
+               global $wgUseTidy, $wgUserHtml;
+               $fname = 'Parser::removeHTMLtags';
+               wfProfileIn( $fname );
+
+               if( $wgUserHtml ) {
+                       $htmlpairs = array( # Tags that must be closed
+                               'b', 'del', 'i', 'ins', 'u', 'font', 'big', 'small', 'sub', 'sup', 'h1',
+                               'h2', 'h3', 'h4', 'h5', 'h6', 'cite', 'code', 'em', 's',
+                               'strike', 'strong', 'tt', 'var', 'div', 'center',
+                               'blockquote', 'ol', 'ul', 'dl', 'table', 'caption', 'pre',
+                               'ruby', 'rt' , 'rb' , 'rp', 'p', 'span'
+                       );
+                       $htmlsingle = array(
+                               'br', 'hr', 'li', 'dt', 'dd'
+                       );
+                       $htmlsingleonly = array( # Elements that cannot have close tags
+                               'br', 'hr'
+                       );
+                       $htmlnest = array( # Tags that can be nested--??
+                               'table', 'tr', 'td', 'th', 'div', 'blockquote', 'ol', 'ul',
+                               'dl', 'font', 'big', 'small', 'sub', 'sup', 'span'
+                       );
+                       $tabletags = array( # Can only appear inside table
+                               'td', 'th', 'tr'
+                       );
+               } else {
+                       $htmlpairs = array();
+                       $htmlsingle = array();
+                       $htmlnest = array();
+                       $tabletags = array();
+               }
+
+               $htmlsingle = array_merge( $tabletags, $htmlsingle );
+               $htmlelements = array_merge( $htmlsingle, $htmlpairs );
+
+               # Remove HTML comments
+               $text = Sanitizer::removeHTMLcomments( $text );
+
+               $bits = explode( '<', $text );
+               $text = array_shift( $bits );
+               if(!$wgUseTidy) {
+                       $tagstack = array(); $tablestack = array();
+                       foreach ( $bits as $x ) {
+                               $prev = error_reporting( E_ALL & ~( E_NOTICE | E_WARNING ) );
+                               preg_match( '/^(\\/?)(\\w+)([^>]*?)(\\/{0,1}>)([^<]*)$/',
+                               $x, $regs );
+                               list( $qbar, $slash, $t, $params, $brace, $rest ) = $regs;
+                               error_reporting( $prev );
+
+                               $badtag = 0 ;
+                               if ( in_array( $t = strtolower( $t ), $htmlelements ) ) {
+                                       # Check our stack
+                                       if ( $slash ) {
+                                               # Closing a tag...
+                                               if( in_array( $t, $htmlsingleonly ) ) {
+                                                       $badtag = 1;
+                                               } elseif( !in_array( $t, $htmlsingle ) &&
+                                               ( $ot = @array_pop( $tagstack ) ) != $t ) {
+                                                       @array_push( $tagstack, $ot );
+                                                       $badtag = 1;
+                                               } else {
+                                                       if ( $t == 'table' ) {
+                                                               $tagstack = array_pop( $tablestack );
+                                                       }
+                                                       $newparams = '';
+                                               }
+                                       } else {
+                                               # Keep track for later
+                                               if ( in_array( $t, $tabletags ) &&
+                                               ! in_array( 'table', $tagstack ) ) {
+                                                       $badtag = 1;
+                                               } else if ( in_array( $t, $tagstack ) &&
+                                               ! in_array ( $t , $htmlnest ) ) {
+                                                       $badtag = 1 ;
+                                               } elseif( in_array( $t, $htmlsingleonly ) ) {
+                                                       # Hack to force empty tag for uncloseable elements
+                                                       $brace = '/>';
+                                               } else if ( ! in_array( $t, $htmlsingle ) ) {
+                                                       if ( $t == 'table' ) {
+                                                               array_push( $tablestack, $tagstack );
+                                                               $tagstack = array();
+                                                       }
+                                                       array_push( $tagstack, $t );
+                                               }
+
+                                               # Replace any variables or template parameters with
+                                               # plaintext results.
+                                               if( is_callable( $processCallback ) ) {
+                                                       call_user_func_array( $processCallback, array( &$params, $args ) );
+                                               }
+
+                                               # Strip non-approved attributes from the tag
+                                               $newparams = Sanitizer::fixTagAttributes( $params, $t );
+                                       }
+                                       if ( ! $badtag ) {
+                                               $rest = str_replace( '>', '&gt;', $rest );
+                                               $close = ( $brace == '/>' ) ? ' /' : '';
+                                               $text .= "<$slash$t$newparams$close>$rest";
+                                               continue;
+                                       }
+                               }
+                               $text .= '&lt;' . str_replace( '>', '&gt;', $x);
+                       }
+                       # Close off any remaining tags
+                       while ( is_array( $tagstack ) && ($t = array_pop( $tagstack )) ) {
+                               $text .= "</$t>\n";
+                               if ( $t == 'table' ) { $tagstack = array_pop( $tablestack ); }
+                       }
+               } else {
+                       # this might be possible using tidy itself
+                       foreach ( $bits as $x ) {
+                               preg_match( '/^(\\/?)(\\w+)([^>]*?)(\\/{0,1}>)([^<]*)$/',
+                               $x, $regs );
+                               @list( $qbar, $slash, $t, $params, $brace, $rest ) = $regs;
+                               if ( in_array( $t = strtolower( $t ), $htmlelements ) ) {
+                                       if( is_callable( $processCallback ) ) {
+                                               call_user_func_array( $processCallback, array( &$params, $args ) );
+                                       }
+                                       $newparams = Sanitizer::fixTagAttributes( $params, $t );
+                                       $rest = str_replace( '>', '&gt;', $rest );
+                                       $text .= "<$slash$t$newparams$brace$rest";
+                               } else {
+                                       $text .= '&lt;' . str_replace( '>', '&gt;', $x);
+                               }
+                       }
+               }
+               wfProfileOut( $fname );
+               return $text;
+       }
+
+       /**
+        * Remove '<!--', '-->', and everything between.
+        * To avoid leaving blank lines, when a comment is both preceded
+        * and followed by a newline (ignoring spaces), trim leading and
+        * trailing spaces and one of the newlines.
+        * 
+        * @access private
+        * @param string $text
+        * @return string
+        */
+       function removeHTMLcomments( $text ) {
+               $fname='Parser::removeHTMLcomments';
+               wfProfileIn( $fname );
+               while (($start = strpos($text, '<!--')) !== false) {
+                       $end = strpos($text, '-->', $start + 4);
+                       if ($end === false) {
+                               # Unterminated comment; bail out
+                               break;
+                       }
+
+                       $end += 3;
+
+                       # Trim space and newline if the comment is both
+                       # preceded and followed by a newline
+                       $spaceStart = max($start - 1, 0);
+                       $spaceLen = $end - $spaceStart;
+                       while (substr($text, $spaceStart, 1) === ' ' && $spaceStart > 0) {
+                               $spaceStart--;
+                               $spaceLen++;
+                       }
+                       while (substr($text, $spaceStart + $spaceLen, 1) === ' ')
+                               $spaceLen++;
+                       if (substr($text, $spaceStart, 1) === "\n" and substr($text, $spaceStart + $spaceLen, 1) === "\n") {
+                               # Remove the comment, leading and trailing
+                               # spaces, and leave only one newline.
+                               $text = substr_replace($text, "\n", $spaceStart, $spaceLen + 1);
+                       }
+                       else {
+                               # Remove just the comment.
+                               $text = substr_replace($text, '', $start, $end - $start);
+                       }
+               }
+               wfProfileOut( $fname );
+               return $text;
+       }
+
+       /**
+        * Take a tag soup fragment listing an HTML element's attributes
+        * and normalize it to well-formed XML, discarding unwanted attributes.
+        *
+        * - Normalizes attribute names to lowercase
+        * - Discards attributes not on a whitelist for the given element
+        * - Turns broken or invalid entities into plaintext
+        * - Double-quotes all attribute values
+        * - Attributes without values are given the name as attribute
+        * - Double attributes are discarded
+        * - Unsafe style attributes are discarded
+        * - Prepends space if there are attributes.
+        *
+        * @param string $text
+        * @param string $element
+        * @return string
+        *
+        * @todo Check for legal values where the DTD limits things.
+        * @todo Check for unique id attribute :P
+        */
+       function fixTagAttributes( $text, $element ) {
+               global $wgUrlProtocols;
+               if( trim( $text ) == '' ) {
+                       return '';
+               }
+               
+               # Unquoted attribute
+               # Since we quote this later, this can be anything distinguishable 
+               # from the end of the attribute
+               if( !preg_match_all(
+                       MW_ATTRIBS_REGEX,
+                       $text,
+                       $pairs,
+                       PREG_SET_ORDER ) ) {
+                       return '';
+               }
+
+               $whitelist = array_flip( Sanitizer::attributeWhitelist( $element ) );
+               $attribs = array();
+               foreach( $pairs as $set ) {
+                       $attribute = strtolower( $set[1] );
+                       if( !isset( $whitelist[$attribute] ) ) {
+                               continue;
+                       }
+                       
+                       $raw   = Sanitizer::getTagAttributeCallback( $set );
+                       $value = Sanitizer::normalizeAttributeValue( $raw );
+                       
+                       # Strip javascript "expression" from stylesheets.
+                       # http://msdn.microsoft.com/workshop/author/dhtml/overview/recalc.asp
+                       if( $attribute == 'style' ) {
+                               $stripped = Sanitizer::decodeCharReferences( $value );
+                               
+                               // Remove any comments; IE gets token splitting wrong
+                               $stripped = preg_replace( '!/\\*.*?\\*/!S', ' ', $stripped );
+                               $value = htmlspecialchars( $stripped );
+                               
+                               // ... and continue checks
+                               $stripped = preg_replace( '!\\\\([0-9A-Fa-f]{1,6})[ \\n\\r\\t\\f]?!e',
+                                       'codepointToUtf8(hexdec("$1"))', $stripped );
+                               $stripped = str_replace( '\\', '', $stripped );
+                               if( preg_match( '/(expression|tps*:\/\/|url\\s*\().*/is',
+                                               $stripped ) ) {
+                                       # haxx0r
+                                       continue;
+                               }
+                       }
+                       
+                       # Templates and links may be expanded in later parsing,
+                       # creating invalid or dangerous output. Suppress this.
+                       $value = strtr( $value, array(
+                               '{'    => '&#123;',
+                               '['    => '&#91;',
+                               "''"   => '&#39;&#39;',
+                               'ISBN' => '&#73;SBN',
+                               'RFC'  => '&#82;FC',
+                               'PMID' => '&#80;MID',
+                       ) );
+                       
+                       # Stupid hack
+                       $value = preg_replace_callback(
+                               '/(' . $wgUrlProtocols . ')/',
+                               array( 'Sanitizer', 'armorLinksCallback' ),
+                               $value );
+                       
+                       // If this attribute was previously set, override it.
+                       // Output should only have one attribute of each name.
+                       $attribs[$attribute] = "$attribute=\"$value\"";
+               }
+               if( empty( $attribs ) ) {
+                       return '';
+               } else {
+                       return ' ' . implode( ' ', $attribs );
+               }
+       }
+       
+       /**
+        * Regex replace callback for armoring links against further processing.
+        * @param array $matches
+        * @return string
+        * @access private
+        */
+       function armorLinksCallback( $matches ) {
+               return str_replace( ':', '&#58;', $matches[1] );
+       }
+       
+       /**
+        * Return an associative array of attribute names and values from
+        * a partial tag string. Attribute names are forces to lowercase,
+        * character references are decoded to UTF-8 text.
+        *
+        * @param string
+        * @return array
+        */
+       function decodeTagAttributes( $text ) {
+               $attribs = array();
+               
+               if( trim( $text ) == '' ) {
+                       return $attribs;
+               }
+               
+               if( !preg_match_all(
+                       MW_ATTRIBS_REGEX,
+                       $text,
+                       $pairs,
+                       PREG_SET_ORDER ) ) {
+                       return $attribs;
+               }
+
+               foreach( $pairs as $set ) {
+                       $attribute = strtolower( $set[1] );
+                       $value = Sanitizer::getTagAttributeCallback( $set );
+                       $attribs[$attribute] = Sanitizer::decodeCharReferences( $value );
+               }
+               return $attribs;
+       }
+       
+       /**
+        * Pick the appropriate attribute value from a match set from the
+        * MW_ATTRIBS_REGEX matches.
+        *
+        * @param array $set
+        * @return string
+        * @access private
+        */
+       function getTagAttributeCallback( $set ) {
+               if( isset( $set[6] ) ) {
+                       # Illegal #XXXXXX color with no quotes.
+                       return $set[6];
+               } elseif( isset( $set[5] ) ) {
+                       # No quotes.
+                       return $set[5];
+               } elseif( isset( $set[4] ) ) {
+                       # Single-quoted
+                       return $set[4];
+               } elseif( isset( $set[3] ) ) {
+                       # Double-quoted
+                       return $set[3];
+               } elseif( !isset( $set[2] ) ) {
+                       # In XHTML, attributes must have a value.
+                       # For 'reduced' form, return explicitly the attribute name here.
+                       return $set[1];
+               } else {
+                       wfDebugDieBacktrace( "Tag conditions not met. This should never happen and is a bug." );
+               }
+       }
+       
+       /**
+        * Normalize whitespace and character references in an XML source-
+        * encoded text for an attribute value.
+        *
+        * See http://www.w3.org/TR/REC-xml/#AVNormalize for background,
+        * but note that we're not returning the value, but are returning
+        * XML source fragments that will be slapped into output.
+        *
+        * @param string $text
+        * @return string
+        * @access private
+        */
+       function normalizeAttributeValue( $text ) {
+               return str_replace( '"', '&quot;',
+                       preg_replace(
+                               '/\r\n|[\x20\x0d\x0a\x09]/',
+                               ' ',
+                               Sanitizer::normalizeCharReferences( $text ) ) );
+       }
+       
+       /**
+        * Ensure that any entities and character references are legal
+        * for XML and XHTML specifically. Any stray bits will be
+        * &amp;-escaped to result in a valid text fragment.
+        *
+        * a. any named char refs must be known in XHTML
+        * b. any numeric char refs must be legal chars, not invalid or forbidden
+        * c. use &#x, not &#X
+        * d. fix or reject non-valid attributes
+        *
+        * @param string $text
+        * @return string
+        * @access private
+        */
+       function normalizeCharReferences( $text ) {
+               return preg_replace_callback(
+                       MW_CHAR_REFS_REGEX,
+                       array( 'Sanitizer', 'normalizeCharReferencesCallback' ),
+                       $text );
+       }
+       /**
+        * @param string $matches
+        * @return string
+        */
+       function normalizeCharReferencesCallback( $matches ) {
+               $ret = null;
+               if( $matches[1] != '' ) {
+                       $ret = Sanitizer::normalizeEntity( $matches[1] );
+               } elseif( $matches[2] != '' ) {
+                       $ret = Sanitizer::decCharReference( $matches[2] );
+               } elseif( $matches[3] != ''  ) {
+                       $ret = Sanitizer::hexCharReference( $matches[3] );
+               } elseif( $matches[4] != '' ) {
+                       $ret = Sanitizer::hexCharReference( $matches[4] );
+               }
+               if( is_null( $ret ) ) {
+                       return htmlspecialchars( $matches[0] );
+               } else {
+                       return $ret;
+               }
+       }
+       
+       /**
+        * If the named entity is defined in the HTML 4.0/XHTML 1.0 DTD,
+        * return the named entity reference as is. Otherwise, returns
+        * HTML-escaped text of pseudo-entity source (eg &amp;foo;)
+        *
+        * @param string $name
+        * @return string
+        */
+       function normalizeEntity( $name ) {
+               global $wgHtmlEntities;
+               if( isset( $wgHtmlEntities[$name] ) ) {
+                       return "&$name;";
+               } else {
+                       return "&amp;$name;";
+               }
+       }
+       
+       function decCharReference( $codepoint ) {
+               $point = IntVal( $codepoint );
+               if( Sanitizer::validateCodepoint( $point ) ) {
+                       return sprintf( '&#%d;', $point );
+               } else {
+                       return null;
+               }
+       }
+       
+       function hexCharReference( $codepoint ) {
+               $point = hexdec( $codepoint );
+               if( Sanitizer::validateCodepoint( $point ) ) {
+                       return sprintf( '&#x%x;', $point );
+               } else {
+                       return null;
+               }
+       }
+       
+       /**
+        * Returns true if a given Unicode codepoint is a valid character in XML.
+        * @param int $codepoint
+        * @return bool
+        */
+       function validateCodepoint( $codepoint ) {
+               return ($codepoint ==    0x09)
+                       || ($codepoint ==    0x0a)
+                       || ($codepoint ==    0x0d)
+                       || ($codepoint >=    0x20 && $codepoint <=   0xd7ff)
+                       || ($codepoint >=  0xe000 && $codepoint <=   0xfffd)
+                       || ($codepoint >= 0x10000 && $codepoint <= 0x10ffff);
+       }
+
+       /**
+        * Decode any character references, numeric or named entities,
+        * in the text and return a UTF-8 string.
+        *
+        * @param string $text
+        * @return string
+        * @access public
+        */
+       function decodeCharReferences( $text ) {
+               return preg_replace_callback(
+                       MW_CHAR_REFS_REGEX,
+                       array( 'Sanitizer', 'decodeCharReferencesCallback' ),
+                       $text );
+       }
+       
+       /**
+        * @param string $matches
+        * @return string
+        */
+       function decodeCharReferencesCallback( $matches ) {
+               if( $matches[1] != '' ) {
+                       return Sanitizer::decodeEntity( $matches[1] );
+               } elseif( $matches[2] != '' ) {
+                       return  Sanitizer::decodeChar( intval( $matches[2] ) );
+               } elseif( $matches[3] != ''  ) {
+                       return  Sanitizer::decodeChar( hexdec( $matches[3] ) );
+               } elseif( $matches[4] != '' ) {
+                       return  Sanitizer::decodeChar( hexdec( $matches[4] ) );
+               }
+               # Last case should be an ampersand by itself
+               return $matches[0];
+       }
+       
+       /**
+        * Return UTF-8 string for a codepoint if that is a valid
+        * character reference, otherwise U+FFFD REPLACEMENT CHARACTER.
+        * @param int $codepoint
+        * @return string
+        * @access private
+        */
+       function decodeChar( $codepoint ) {
+               if( Sanitizer::validateCodepoint( $codepoint ) ) {
+                       return codepointToUtf8( $codepoint );
+               } else {
+                       return UTF8_REPLACEMENT;
+               }
+       }
+       
+       /**
+        * If the named entity is defined in the HTML 4.0/XHTML 1.0 DTD,
+        * return the UTF-8 encoding of that character. Otherwise, returns
+        * pseudo-entity source (eg &foo;)
+        *
+        * @param string $name
+        * @return string
+        */
+       function decodeEntity( $name ) {
+               global $wgHtmlEntities;
+               if( isset( $wgHtmlEntities[$name] ) ) {
+                       return codepointToUtf8( $wgHtmlEntities[$name] );
+               } else {
+                       return "&$name;";
+               }
+       }
+       
+       /**
+        * Fetch the whitelist of acceptable attributes for a given
+        * element name.
+        *
+        * @param string $element
+        * @return array
+        */
+       function attributeWhitelist( $element ) {
+               static $list;
+               if( !isset( $list ) ) {
+                       $list = Sanitizer::setupAttributeWhitelist();
+               }
+               return isset( $list[$element] )
+                       ? $list[$element]
+                       : array();
+       }
+       
+       /**
+        * @return array
+        */
+       function setupAttributeWhitelist() {
+               $common = array( 'id', 'class', 'lang', 'dir', 'title', 'style' );
+               $block = array_merge( $common, array( 'align' ) );
+               $tablealign = array( 'align', 'char', 'charoff', 'valign' );
+               $tablecell = array( 'abbr',
+                                   'axis',
+                                   'headers',
+                                   'scope',
+                                   'rowspan',
+                                   'colspan',
+                                   'nowrap', # deprecated
+                                   'width',  # deprecated
+                                   'height', # deprecated
+                                   'bgcolor' # deprecated
+                                   );
+               
+               # Numbers refer to sections in HTML 4.01 standard describing the element.
+               # See: http://www.w3.org/TR/html4/
+               $whitelist = array (
+                       # 7.5.4
+                       'div'        => $block,
+                       'center'     => $common, # deprecated
+                       'span'       => $block, # ??
+               
+                       # 7.5.5
+                       'h1'         => $block,
+                       'h2'         => $block,
+                       'h3'         => $block,
+                       'h4'         => $block,
+                       'h5'         => $block,
+                       'h6'         => $block,
+                       
+                       # 7.5.6
+                       # address
+                       
+                       # 8.2.4
+                       # bdo
+               
+                       # 9.2.1
+                       'em'         => $common,
+                       'strong'     => $common,
+                       'cite'       => $common,
+                       # dfn
+                       'code'       => $common,
+                       # samp
+                       # kbd
+                       'var'        => $common,
+                       # abbr
+                       # acronym
+                       
+                       # 9.2.2
+                       'blockquote' => array_merge( $common, array( 'cite' ) ),
+                       # q
+                       
+                       # 9.2.3
+                       'sub'        => $common,
+                       'sup'        => $common,
+                       
+                       # 9.3.1
+                       'p'          => $block,
+                       
+                       # 9.3.2
+                       'br'         => array( 'id', 'class', 'title', 'style', 'clear' ),
+                       
+                       # 9.3.4
+                       'pre'        => array_merge( $common, array( 'width' ) ),
+                       
+                       # 9.4
+                       'ins'        => array_merge( $common, array( 'cite', 'datetime' ) ),
+                       'del'        => array_merge( $common, array( 'cite', 'datetime' ) ),
+                       
+                       # 10.2
+                       'ul'         => array_merge( $common, array( 'type' ) ),
+                       'ol'         => array_merge( $common, array( 'type', 'start' ) ),
+                       'li'         => array_merge( $common, array( 'type', 'value' ) ),
+                       
+                       # 10.3
+                       'dl'         => $common,
+                       'dd'         => $common,
+                       'dt'         => $common,
+               
+                       # 11.2.1
+                       'table'      => array_merge( $common,
+                                                               array( 'summary', 'width', 'border', 'frame',
+                                                                                        'rules', 'cellspacing', 'cellpadding',
+                                                                                        'align', 'bgcolor', 'frame', 'rules',
+                                                                                        'border' ) ),
+                       
+                       # 11.2.2
+                       'caption'    => array_merge( $common, array( 'align' ) ),
+                       
+                       # 11.2.3
+                       'thead'      => array_merge( $common, $tablealign ),
+                       'tfoot'      => array_merge( $common, $tablealign ),
+                       'tbody'      => array_merge( $common, $tablealign ),
+                       
+                       # 11.2.4
+                       'colgroup'   => array_merge( $common, array( 'span', 'width' ), $tablealign ),
+                       'col'        => array_merge( $common, array( 'span', 'width' ), $tablealign ),
+                       
+                       # 11.2.5
+                       'tr'         => array_merge( $common, array( 'bgcolor' ), $tablealign ),
+                       
+                       # 11.2.6
+                       'td'         => array_merge( $common, $tablecell, $tablealign ),
+                       'th'         => array_merge( $common, $tablecell, $tablealign ),
+                       
+                       # 15.2.1
+                       'tt'         => $common,
+                       'b'          => $common,
+                       'i'          => $common,
+                       'big'        => $common,
+                       'small'      => $common,
+                       'strike'     => $common,
+                       's'          => $common,
+                       'u'          => $common,
+               
+                       # 15.2.2
+                       'font'       => array_merge( $common, array( 'size', 'color', 'face' ) ),
+                       # basefont
+                       
+                       # 15.3
+                       'hr'         => array_merge( $common, array( 'noshade', 'size', 'width' ) ),
+                       
+                       # XHTML Ruby annotation text module, simple ruby only.
+                       # http://www.w3c.org/TR/ruby/
+                       'ruby'       => $common,
+                       # rbc
+                       # rtc
+                       'rb'         => $common,
+                       'rt'         => $common, #array_merge( $common, array( 'rbspan' ) ),
+                       'rp'         => $common,
+                       );
+               return $whitelist;
+       }
+       
+       /**
+        * Take a fragment of (potentially invalid) HTML and return
+        * a version with any tags removed, encoded suitably for literal
+        * inclusion in an attribute value.
+        *
+        * @param string $text HTML fragment
+        * @return string
+        */
+       function stripAllTags( $text ) {
+               # Actual <tags>
+               $text = preg_replace( '/<[^>]*>/', '', $text );
+               
+               # Normalize &entities and whitespace
+               $text = Sanitizer::normalizeAttributeValue( $text );
+               
+               # Will be placed into "double-quoted" attributes,
+               # make sure remaining bits are safe.
+               $text = str_replace(
+                       array('<', '>', '"'),
+                       array('&lt;', '&gt;', '&quot;'),
+                       $text );
+               
+               return $text;
+       }
+
+}
+
+?>
diff --git a/includes/SearchEngine.php b/includes/SearchEngine.php
new file mode 100644 (file)
index 0000000..45642ee
--- /dev/null
@@ -0,0 +1,334 @@
+<?php
+/**
+ * Contain a class for special pages
+ * @package MediaWiki
+ * @subpackage Search
+ */
+
+/**
+ * @package MediaWiki
+ */
+class SearchEngine {
+       var $limit = 10;
+       var $offset = 0;
+       var $searchTerms = array();
+       var $namespaces = array( 0 );
+       var $showRedirects = false;
+       
+       /**
+        * Perform a full text search query and return a result set.
+        * If title searches are not supported or disabled, return null.
+        *
+        * @param string $term - Raw search term
+        * @return SearchResultSet
+        * @access public
+        * @abstract
+        */
+       function searchText( $term ) {
+               return null;
+       }
+
+       /**
+        * Perform a title-only search query and return a result set.
+        * If title searches are not supported or disabled, return null.
+        *
+        * @param string $term - Raw search term
+        * @return SearchResultSet
+        * @access public
+        * @abstract
+        */
+       function searchTitle( $term ) {
+               return null;
+       }
+       
+       /**
+        * If an exact title match can be find, or a very slightly close match,
+        * return the title. If no match, returns NULL.
+        *
+        * @static
+        * @param string $term
+        * @return Title
+        * @access private
+        */
+       function getNearMatch( $term ) {
+               # Exact match? No need to look further.
+               $title = Title::newFromText( $term );
+               if (is_null($title))
+                       return NULL;
+
+               if ( $title->getNamespace() == NS_SPECIAL || $title->exists() ) {
+                       return $title;
+               }
+
+               # Now try all lower case (i.e. first letter capitalized)
+               #
+               $title = Title::newFromText( strtolower( $term ) );
+               if ( $title->exists() ) {
+                       return $title;
+               }
+
+               # Now try capitalized string
+               #
+               $title = Title::newFromText( ucwords( strtolower( $term ) ) );
+               if ( $title->exists() ) {
+                       return $title;
+               }
+
+               # Now try all upper case
+               #
+               $title = Title::newFromText( strtoupper( $term ) );
+               if ( $title->exists() ) {
+                       return $title;
+               }
+               
+               global $wgCapitalLinks, $wgContLang;
+               if( !$wgCapitalLinks ) {
+                       // Catch differs-by-first-letter-case-only
+                       $title = Title::newFromText( $wgContLang->ucfirst( $term ) );
+                       if ( $title->exists() ) {
+                               return $title;
+                       }
+                       $title = Title::newFromText( $wgContLang->lcfirst( $term ) );
+                       if ( $title->exists() ) {
+                               return $title;
+                       }
+               }
+
+               $title = Title::newFromText( $term );
+
+               # Entering an IP address goes to the contributions page
+               if ( ( $title->getNamespace() == NS_USER && User::isIP($title->getText() ) )
+                       || User::isIP( trim( $term ) ) ) {
+                       return Title::makeTitle( NS_SPECIAL, "Contributions/" . $title->getDbkey() );
+               }
+
+
+               # Entering a user goes to the user page whether it's there or not
+               if ( $title->getNamespace() == NS_USER ) {
+                       return $title;
+               }
+               
+               # Quoted term? Try without the quotes...
+               if( preg_match( '/^"([^"]+)"$/', $term, $matches ) ) {
+                       return SearchEngine::getNearMatch( $matches[1] );
+               }
+               
+               return NULL;
+       }
+       
+       function legalSearchChars() {
+               return "A-Za-z_'0-9\\x80-\\xFF\\-";
+       }
+
+       /**
+        * Set the maximum number of results to return
+        * and how many to skip before returning the first.
+        *
+        * @param int $limit
+        * @param int $offset
+        * @access public
+        */
+       function setLimitOffset( $limit, $offset = 0 ) {
+               $this->limit = IntVal( $limit );
+               $this->offset = IntVal( $offset );
+       }
+       
+       /**
+        * Set which namespaces the search should include.
+        * Give an array of namespace index numbers.
+        *
+        * @param array $namespaces
+        * @access public
+        */
+       function setNamespaces( $namespaces ) {
+               $this->namespaces = $namespaces;
+       }
+       
+       /**
+        * Make a list of searchable namespaces and their canonical names.
+        * @return array
+        * @access public
+        */
+       function searchableNamespaces() {
+               global $wgContLang;
+               $arr = array();
+               foreach( $wgContLang->getNamespaces() as $ns => $name ) {
+                       if( $ns >= NS_MAIN ) {
+                               $arr[$ns] = $name;
+                       }
+               }
+               return $arr;
+       }
+       
+       /**
+        * Return a 'cleaned up' search string
+        *
+        * @return string
+        * @access public
+        */
+       function filter( $text ) {
+               $lc = $this->legalSearchChars();
+               return trim( preg_replace( "/[^{$lc}]/", " ", $text ) );
+       }
+       /**
+        * Load up the appropriate search engine class for the currently
+        * active database backend, and return a configured instance.
+        *
+        * @return SearchEngine
+        * @access private
+        */
+       function create() {
+               global $wgDBtype, $wgDBmysql4, $wgSearchType;
+               if( $wgSearchType ) {
+                       $class = $wgSearchType;
+               } elseif( $wgDBtype == 'mysql' ) {
+                       if( $wgDBmysql4 ) {
+                               $class = 'SearchMySQL4';
+                               require_once( 'SearchMySQL4.php' );
+                       } else {
+                               $class = 'SearchMysql3';
+                               require_once( 'SearchMySQL3.php' );
+                       }
+               } else if ( $wgDBtype == 'PostgreSQL' ) {
+                       $class = 'SearchTsearch2';
+                       require_once( 'SearchTsearch2.php' );
+               } else {
+                       $class = 'SearchEngineDummy';
+               }
+               $search = new $class( wfGetDB( DB_SLAVE ) );
+               $search->setLimitOffset(0,0);
+               return $search;
+       }
+       
+       /**
+        * Create or update the search index record for the given page.
+        * Title and text should be pre-processed.
+        *
+        * @param int $id
+        * @param string $title
+        * @param string $text
+        * @abstract
+        */
+       function update( $id, $title, $text ) {
+               // no-op
+       }
+
+       /**
+        * Update a search index record's title only.
+        * Title should be pre-processed.
+        *
+        * @param int $id
+        * @param string $title
+        * @abstract
+        */
+    function updateTitle( $id, $title ) {
+               // no-op
+    }
+}
+
+/** @package MediaWiki */
+class SearchResultSet {
+       /**
+        * Fetch an array of regular expression fragments for matching
+        * the search terms as parsed by this engine in a text extract.
+        *
+        * @return array
+        * @access public
+        * @abstract
+        */
+       function termMatches() {
+               return array();
+       }
+       
+       function numRows() {
+               return 0;
+       }
+       
+       /**
+        * Return true if results are included in this result set.
+        * @return bool
+        * @abstract
+        */
+       function hasResults() {
+               return false;
+       }
+       
+       /**
+        * Some search modes return a total hit count for the query
+        * in the entire article database. This may include pages
+        * in namespaces that would not be matched on the given
+        * settings.
+        *
+        * Return null if no total hits number is supported.
+        *
+        * @return int
+        * @access public
+        */
+       function getTotalHits() {
+               return null;
+       }
+       
+       /**
+        * Some search modes return a suggested alternate term if there are
+        * no exact hits. Returns true if there is one on this set.
+        *
+        * @return bool
+        * @access public
+        */
+       function hasSuggestion() {
+               return false;
+       }
+       
+       /**
+        * Some search modes return a suggested alternate term if there are
+        * no exact hits. Check hasSuggestion() first.
+        *
+        * @return string
+        * @access public
+        */
+       function getSuggestion() {
+               return '';
+       }
+       
+       /**
+        * Fetches next search result, or false.
+        * @return SearchResult
+        * @access public
+        * @abstract
+        */
+       function next() {
+               return false;
+       }
+}
+
+/** @package MediaWiki */
+class SearchResult {
+       function SearchResult( $row ) {
+               $this->mTitle = Title::makeTitle( $row->page_namespace, $row->page_title );
+       }
+       
+       /**
+        * @return Title
+        * @access public
+        */
+       function getTitle() {
+               return $this->mTitle;
+       }
+       
+       /**
+        * @return double or null if not supported
+        */
+       function getScore() {
+               return null;
+       }
+}
+
+/**
+ * @package MediaWiki
+ */
+class SearchEngineDummy {
+       function search( $term ) {
+               return null;
+       }
+}
+
diff --git a/includes/SearchMySQL.php b/includes/SearchMySQL.php
new file mode 100644 (file)
index 0000000..bf90fdb
--- /dev/null
@@ -0,0 +1,209 @@
+<?php
+# Copyright (C) 2004 Brion Vibber <brion@pobox.com>
+# http://www.mediawiki.org/
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or 
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# http://www.gnu.org/copyleft/gpl.html
+
+/**
+ * Search engine hook base class for MySQL.
+ * Specific bits for MySQL 3 and 4 variants are in child classes.
+ * @package MediaWiki
+ * @subpackage Search
+ */
+
+/** */
+require_once( 'SearchEngine.php' );
+
+/** @package MediaWiki */
+class SearchMySQL extends SearchEngine {
+       /**
+        * Perform a full text search query and return a result set.
+        *
+        * @param string $term - Raw search term
+        * @return MySQLSearchResultSet
+        * @access public
+        */
+       function searchText( $term ) {
+               $resultSet = $this->db->resultObject( $this->db->query( $this->getQuery( $this->filter( $term ), true ) ) );
+               return new MySQLSearchResultSet( $resultSet, $this->searchTerms );
+       }
+
+       /**
+        * Perform a title-only search query and return a result set.
+        *
+        * @param string $term - Raw search term
+        * @return MySQLSearchResultSet
+        * @access public
+        */
+       function searchTitle( $term ) {
+               $resultSet = $this->db->resultObject( $this->db->query( $this->getQuery( $this->filter( $term ), false ) ) );
+               return new MySQLSearchResultSet( $resultSet, $this->searchTerms );
+       }
+       
+       
+       /**
+        * Return a partial WHERE clause to exclude redirects, if so set
+        * @return string
+        * @access private
+        */
+       function queryRedirect() {
+               if( $this->showRedirects ) {
+                       return '';
+               } else {
+                       return 'AND page_is_redirect=0';
+               }
+       }
+       
+       /**
+        * Return a partial WHERE clause to limit the search to the given namespaces
+        * @return string
+        * @access private
+        */
+       function queryNamespaces() {
+               $namespaces = implode( ',', $this->namespaces );
+               if ($namespaces == '') {
+                       $namespaces = '0';
+               }
+               return 'AND page_namespace IN (' . $namespaces . ')';
+       }
+       
+       /**
+        * Return a LIMIT clause to limit results on the query.
+        * @return string
+        * @access private
+        */
+       function queryLimit() {
+               return $this->db->limitResult( $this->limit, $this->offset );
+       }
+
+       /**
+        * Does not do anything for generic search engine
+        * subclasses may define this though
+        * @return string
+        * @access private
+        */
+       function queryRanking( $filteredTerm, $fulltext ) {
+               return '';
+       }
+       
+       /**
+        * Construct the full SQL query to do the search.
+        * The guts shoulds be constructed in queryMain()
+        * @param string $filteredTerm
+        * @param bool $fulltext
+        * @access private
+        */
+       function getQuery( $filteredTerm, $fulltext ) {
+               return $this->queryMain( $filteredTerm, $fulltext ) . ' ' .
+                       $this->queryRedirect() . ' ' .
+                       $this->queryNamespaces() . ' ' .
+                       $this->queryRanking( $filteredTerm, $fulltext ) . ' ' .
+                       $this->queryLimit();
+       }
+
+
+       /**
+        * Picks which field to index on, depending on what type of query.
+        * @param bool $fulltext
+        * @return string
+        */
+       function getIndexField( $fulltext ) {
+               return $fulltext ? 'si_text' : 'si_title';
+       }
+
+       /**
+        * Get the base part of the search query.
+        * The actual match syntax will depend on the server
+        * version; MySQL 3 and MySQL 4 have different capabilities
+        * in their fulltext search indexes.
+        *
+        * @param string $filteredTerm
+        * @param bool $fulltext
+        * @return string
+        * @access private
+        */
+       function queryMain( $filteredTerm, $fulltext ) {
+               $match = $this->parseQuery( $filteredTerm, $fulltext );
+               $page        = $this->db->tableName( 'page' );
+               $searchindex = $this->db->tableName( 'searchindex' );
+               return 'SELECT page_id, page_namespace, page_title ' .
+                       "FROM $page,$searchindex " .
+                       'WHERE page_id=si_page AND ' . $match;
+       }
+
+       /**
+        * Create or update the search index record for the given page.
+        * Title and text should be pre-processed.
+        *
+        * @param int $id
+        * @param string $title
+        * @param string $text
+        */
+       function update( $id, $title, $text ) {
+               $dbw=& wfGetDB( DB_MASTER );
+               $dbw->replace( 'searchindex',
+                       array( 'si_page' ),
+                       array(
+                               'si_page' => $id,
+                               'si_title' => $title,
+                               'si_text' => $text
+                       ), 'SearchMySQL4::update' );
+       }
+
+       /**
+        * Update a search index record's title only.
+        * Title should be pre-processed.
+        *
+        * @param int $id
+        * @param string $title
+        */
+    function updateTitle( $id, $title ) {
+               $dbw =& wfGetDB( DB_MASTER );
+               
+               $dbw->update( 'searchindex',
+                       array( 'si_title' => $title ),
+                       array( 'si_page'  => $id ),
+                       'SearchMySQL4::updateTitle',
+                       array( $dbw->lowPriorityOption() ) );
+       }
+}
+
+/** @package MediaWiki */
+class MySQLSearchResultSet extends SearchResultSet {
+       function MySQLSearchResultSet( $resultSet, $terms ) {
+               $this->mResultSet = $resultSet;
+               $this->mTerms = $terms;
+       }
+       
+       function termMatches() {
+               return $this->mTerms;
+       }
+       
+       function numRows() {
+               return $this->mResultSet->numRows();
+       }
+       
+       function next() {
+               $row = $this->mResultSet->fetchObject();
+               if( $row === false ) {
+                       return false;
+               } else {
+                       return new SearchResult( $row );
+               }
+       }
+}
+
+?>
diff --git a/includes/SearchMySQL3.php b/includes/SearchMySQL3.php
new file mode 100644 (file)
index 0000000..3636045
--- /dev/null
@@ -0,0 +1,81 @@
+<?php
+# Copyright (C) 2004 Brion Vibber <brion@pobox.com>
+# http://www.mediawiki.org/
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or 
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# http://www.gnu.org/copyleft/gpl.html
+
+/**
+ * Search engine hook for MySQL 3.23.x
+ * @package MediaWiki
+ * @subpackage Search
+ */
+
+/** */
+require_once( 'SearchMySQL.php' );
+
+/**
+ * @package MediaWiki
+ * @subpackage Search
+ */
+class SearchMySQL3 extends SearchMySQL {
+       function SearchMySQL3( &$db ) {
+               $this->db =& $db;
+       }
+
+       function parseQuery( $filteredText, $fulltext ) {
+               global $wgDBminWordLen, $wgContLang;
+               
+               $field = $this->getIndexField( $fulltext );
+
+               # on non mysql4 database: get list of words we don't want to search for
+               require_once( 'FulltextStoplist.php' );
+
+               $lc = SearchEngine::legalSearchChars() . '()';
+               $q = preg_replace( "/([()])/", " \\1 ", $filteredText );
+               $q = preg_replace( "/\\s+/", " ", $q );
+               $w = explode( ' ', trim( $q ) );
+
+               $last = $cond = '';
+               foreach ( $w as $word ) {
+                       $word = $wgContLang->stripForSearch( $word );
+                       if ( 'and' == $word || 'or' == $word || 'not' == $word
+                         || '(' == $word || ')' == $word ) {
+                               $cond .= ' ' . strtoupper( $word );
+                               $last = '';
+                       } else if ( strlen( $word ) < $wgDBminWordLen ) {
+                               continue;
+                       } else if ( FulltextStoplist::inList( $word ) ) {
+                               continue;
+                       } else {
+                               if ( '' != $last ) { $cond .= ' AND'; }
+                               $cond .= " (MATCH ($field) AGAINST ('" .
+                                 $this->db->strencode( $word ). "'))";
+                               $last = $word;
+                               $this->searchTerms[] = "\\b" . preg_quote( $word, '/' ) . "\\b";
+                       }
+               }
+               if ( 0 == count( $this->searchTerms ) ) {
+                       # No searchable terms remaining.
+                       # We have to return a term for the query or we get an SQL error.
+                       return "0";
+               }
+
+               return '(' . $cond . ' )';
+       }
+
+}
+
+?>
diff --git a/includes/SearchMySQL4.php b/includes/SearchMySQL4.php
new file mode 100644 (file)
index 0000000..256579f
--- /dev/null
@@ -0,0 +1,75 @@
+<?php
+# Copyright (C) 2004 Brion Vibber <brion@pobox.com>
+# http://www.mediawiki.org/
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or 
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# http://www.gnu.org/copyleft/gpl.html
+
+/**
+ * Search engine hook for MySQL 4+
+ * @package MediaWiki
+ * @subpackage Search
+ */
+
+require_once( 'SearchMySQL.php' );
+
+/**
+ * @package MediaWiki
+ * @subpackage Search
+ */
+class SearchMySQL4 extends SearchMySQL {
+       var $strictMatching = true;
+       
+       /** @todo document */
+       function SearchMySQL4( &$db ) {
+               $this->db =& $db;
+       }
+
+       /** @todo document */
+       function parseQuery( $filteredText, $fulltext ) {
+               global $wgContLang;
+               $lc = SearchEngine::legalSearchChars();
+               $searchon = '';
+               $this->searchTerms = array();
+
+               # FIXME: This doesn't handle parenthetical expressions.
+               if( preg_match_all( '/([-+<>~]?)(([' . $lc . ']+)(\*?)|"[^"]*")/',
+                         $filteredText, $m, PREG_SET_ORDER ) ) {
+                       foreach( $m as $terms ) {
+                               if( $searchon !== '' ) $searchon .= ' ';
+                               if( $this->strictMatching && ($terms[1] == '') ) {
+                                       $terms[1] = '+';
+                               }
+                               $searchon .= $terms[1] . $wgContLang->stripForSearch( $terms[2] );
+                               if( !empty( $terms[3] ) ) {
+                                       $regexp = preg_quote( $terms[3], '/' );
+                                       if( $terms[4] ) $regexp .= "[0-9A-Za-z_]+";
+                               } else {
+                                       $regexp = preg_quote( str_replace( '"', '', $terms[2] ), '/' );
+                               }
+                               $this->searchTerms[] = $regexp;
+                       }
+                       wfDebug( "Would search with '$searchon'\n" );
+                       wfDebug( "Match with /\b" . implode( '\b|\b', $this->searchTerms ) . "\b/\n" );
+               } else {
+                       wfDebug( "Can't understand search query '{$filteredText}'\n" );
+               }
+               
+               $searchon = $this->db->strencode( $searchon );
+               $field = $this->getIndexField( $fulltext );
+               return " MATCH($field) AGAINST('$searchon' IN BOOLEAN MODE) ";
+       }
+}
+?>
diff --git a/includes/SearchTsearch2.php b/includes/SearchTsearch2.php
new file mode 100644 (file)
index 0000000..655a48e
--- /dev/null
@@ -0,0 +1,127 @@
+<?php
+# Copyright (C) 2004 Brion Vibber <brion@pobox.com>, Domas Mituzas <domas.mituzas@gmail.com>
+# http://www.mediawiki.org/
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or 
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# http://www.gnu.org/copyleft/gpl.html
+
+/**
+ * Search engine hook for PostgreSQL / Tsearch2
+ * @package MediaWiki
+ * @subpackage Search
+ */
+
+/** */
+require_once( 'SearchEngine.php' );
+
+/**
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Search
+ */
+class SearchTsearch2 extends SearchEngine {
+       var $strictMatching = false;
+       
+       function SearchTsearch2( &$db ) {
+               $this->db =& $db;
+               $this->db->setSchema('tsearch');
+               $this->mRanking = true;
+       }
+       
+       function getIndexField( $fulltext ) {
+               return $fulltext ? 'si_text' : 'si_title';
+       }
+
+       function parseQuery( $filteredText, $fulltext ) {
+               global $wgContLang;
+               $lc = SearchEngine::legalSearchChars();
+               $searchon = '';
+               $this->searchTerms = array();
+
+               # FIXME: This doesn't handle parenthetical expressions.
+               if( preg_match_all( '/([-+<>~]?)(([' . $lc . ']+)(\*?)|"[^"]*")/',
+                         $filteredText, $m, PREG_SET_ORDER ) ) {
+                       foreach( $m as $terms ) {
+                               if( $searchon !== '' ) $searchon .= ' ';
+                               if( $this->strictMatching && ($terms[1] == '') ) {
+                                       $terms[1] = '+';
+                               }
+                               $searchon .= $terms[1] . $wgContLang->stripForSearch( $terms[2] );
+                               if( !empty( $terms[3] ) ) {
+                                       $regexp = preg_quote( $terms[3], '/' );
+                                       if( $terms[4] ) $regexp .= "[0-9A-Za-z_]+";
+                               } else {
+                                       $regexp = preg_quote( str_replace( '"', '', $terms[2] ), '/' );
+                               }
+                               $this->searchTerms[] = $regexp;
+                       }
+                       wfDebug( "Would search with '$searchon'\n" );
+                       wfDebug( "Match with /\b" . implode( '\b|\b', $this->searchTerms ) . "\b/\n" );
+               } else {
+                       wfDebug( "Can't understand search query '{$this->filteredText}'\n" );
+               }
+               
+               $searchon = preg_replace('/(\s+)/','&',$searchon);
+               $searchon = $this->db->strencode( $searchon );
+               return $searchon;
+       }
+
+       function queryRanking($filteredTerm, $fulltext) {
+               $field = $this->getIndexField( $fulltext );
+               $searchon = $this->parseQuery($filteredTerm,$fulltext);
+               if ($this->mRanking)
+                       return " ORDER BY rank($field,to_tsquery('$searchon')) DESC";
+               else
+                       return "";
+       }
+               
+
+       function queryMain( $filteredTerm, $fulltext ) {
+               $match = $this->parseQuery( $filteredTerm, $fulltext );
+               $field = $this->getIndexField( $fulltext );
+               $cur = $this->db->tableName( 'cur' );
+               $searchindex = $this->db->tableName( 'searchindex' );
+               return 'SELECT cur_id, cur_namespace, cur_title, cur_text ' .
+                       "FROM $cur,$searchindex " .
+                       'WHERE cur_id=si_page AND ' . 
+                       " $field @@ to_tsquery ('$match') " ;
+       }
+
+        function update( $id, $title, $text ) {
+                $dbw=& wfGetDB(DB_MASTER);
+               $searchindex = $dbw->tableName( 'searchindex' );
+               $sql = "DELETE FROM $searchindex WHERE si_page={$id}";
+               $dbw->query($sql,"SearchTsearch2:update");
+               $sql = "INSERT INTO $searchindex (si_page,si_title,si_text) ".
+                       " VALUES ( $id, to_tsvector('".
+                               $dbw->strencode($title).
+                               "'),to_tsvector('".
+                               $dbw->strencode( $text)."')) ";
+               $dbw->query($sql,"SearchTsearch2:update");
+        }
+
+        function updateTitle($id,$title) {
+                $dbw=& wfGetDB(DB_MASTER);
+                $searchindex = $dbw->tableName( 'searchindex' );
+                $sql = "UPDATE $searchindex SET si_title=to_tsvector('" .
+                          $db->strencode( $title ) .
+                          "') WHERE si_page={$id}";
+
+                $dbw->query( $sql, "SearchMySQL4::updateTitle" );
+        }
+
+}
+
+?>
diff --git a/includes/SearchUpdate.php b/includes/SearchUpdate.php
new file mode 100644 (file)
index 0000000..d64d53d
--- /dev/null
@@ -0,0 +1,116 @@
+<?php
+/**
+ * See deferred.txt
+ * @package MediaWiki
+ */
+
+/**
+ *
+ * @package MediaWiki
+ */
+class SearchUpdate {
+
+       /* private */ var $mId = 0, $mNamespace, $mTitle, $mText;
+       /* private */ var $mTitleWords;
+
+       function SearchUpdate( $id, $title, $text = false ) {
+               $nt = Title::newFromText( $title );
+               if( $nt ) {
+                       $this->mId = $id;
+                       $this->mText = $text;
+
+                       $this->mNamespace = $nt->getNamespace();
+                       $this->mTitle = $nt->getText(); # Discard namespace
+
+                       $this->mTitleWords = $this->mTextWords = array();
+               } else {
+                       wfDebug( "SearchUpdate object created with invalid title '$title'\n" );
+               }
+       }
+
+       function doUpdate() {
+               global $wgDBminWordLen, $wgContLang, $wgDisableSearchUpdate;
+
+               if( $wgDisableSearchUpdate || !$this->mId ) {
+                       return false;
+               }
+               $fname = 'SearchUpdate::doUpdate';
+               wfProfileIn( $fname );
+
+               require_once( 'SearchEngine.php' );
+               $search = SearchEngine::create();
+               $lc = $search->legalSearchChars() . '&#;';
+               
+               if( $this->mText === false ) {
+                       $search->updateTitle($this->mId,
+                               Title::indexTitle( $this->mNamespace, $this->mTitle ));
+                       wfProfileOut( $fname );
+                       return;
+               }
+
+               # Language-specific strip/conversion
+               $text = $wgContLang->stripForSearch( $this->mText );
+
+               wfProfileIn( $fname.'-regexps' );
+               $text = preg_replace( "/<\\/?\\s*[A-Za-z][A-Za-z0-9]*\\s*([^>]*?)>/",
+                 ' ', strtolower( " " . $text /*$this->mText*/ . " " ) ); # Strip HTML markup
+               $text = preg_replace( "/(^|\\n)\\s*==\\s+([^\\n]+)\\s+==\\s/sD",
+                 "\\2 \\2 \\2 ", $text ); # Emphasize headings
+
+               # Strip external URLs
+               $uc = "A-Za-z0-9_\\/:.,~%\\-+&;#?!=()@\\xA0-\\xFF";
+               $protos = "http|https|ftp|mailto|news|gopher";
+               $pat = "/(^|[^\\[])({$protos}):[{$uc}]+([^{$uc}]|$)/";
+               $text = preg_replace( $pat, "\\1 \\3", $text );
+
+               $p1 = "/([^\\[])\\[({$protos}):[{$uc}]+]/";
+               $p2 = "/([^\\[])\\[({$protos}):[{$uc}]+\\s+([^\\]]+)]/";
+               $text = preg_replace( $p1, "\\1 ", $text );
+               $text = preg_replace( $p2, "\\1 \\3 ", $text );
+
+               # Internal image links
+               $pat2 = "/\\[\\[image:([{$uc}]+)\\.(gif|png|jpg|jpeg)([^{$uc}])/i";
+               $text = preg_replace( $pat2, " \\1 \\3", $text );
+
+               $text = preg_replace( "/([^{$lc}])([{$lc}]+)]]([a-z]+)/",
+                 "\\1\\2 \\2\\3", $text ); # Handle [[game]]s
+
+               # Strip all remaining non-search characters
+               $text = preg_replace( "/[^{$lc}]+/", " ", $text );
+
+               # Handle 's, s'
+               #
+               #   $text = preg_replace( "/([{$lc}]+)'s /", "\\1 \\1's ", $text );
+               #   $text = preg_replace( "/([{$lc}]+)s' /", "\\1s ", $text );
+               #
+               # These tail-anchored regexps are insanely slow. The worst case comes
+               # when Japanese or Chinese text (ie, no word spacing) is written on
+               # a wiki configured for Western UTF-8 mode. The Unicode characters are
+               # expanded to hex codes and the "words" are very long paragraph-length
+               # monstrosities. On a large page the above regexps may take over 20
+               # seconds *each* on a 1GHz-level processor.
+               #
+               # Following are reversed versions which are consistently fast
+               # (about 3 milliseconds on 1GHz-level processor).
+               #
+               $text = strrev( preg_replace( "/ s'([{$lc}]+)/", " s'\\1 \\1", strrev( $text ) ) );
+               $text = strrev( preg_replace( "/ 's([{$lc}]+)/", " s\\1", strrev( $text ) ) );
+
+               # Strip wiki '' and '''
+               $text = preg_replace( "/''[']*/", " ", $text );
+               wfProfileOut( "$fname-regexps" );
+               $search->update($this->mId, Title::indexTitle( $this->mNamespace, $this->mTitle ),
+                               $text);
+               wfProfileOut( $fname );
+       }
+}
+
+/**
+ * Placeholder class
+ * @package MediaWiki
+ */
+class SearchUpdateMyISAM extends SearchUpdate {
+       # Inherits everything
+}
+
+?>
diff --git a/includes/Setup.php b/includes/Setup.php
new file mode 100644 (file)
index 0000000..22aaf90
--- /dev/null
@@ -0,0 +1,325 @@
+<?php
+/**
+ * Include most things that's need to customize the site
+ * @package MediaWiki
+ */
+
+/**
+ * This file is not a valid entry point, perform no further processing unless
+ * MEDIAWIKI is defined
+ */
+if( defined( 'MEDIAWIKI' ) ) {
+
+# The main wiki script and things like database
+# conversion and maintenance scripts all share a
+# common setup of including lots of classes and
+# setting up a few globals.
+#
+
+// Check to see if we are at the file scope
+if ( !isset( $wgVersion ) ) {
+       die( "Error, Setup.php must be included from the file scope, after DefaultSettings.php\n" );
+}
+
+if( !isset( $wgProfiling ) )
+       $wgProfiling = false;
+
+if ( $wgProfiling and (0 == rand() % $wgProfileSampleRate ) ) {
+        require_once( 'Profiling.php' );
+} else {
+        function wfProfileIn( $fn = '' ) {
+                global $hackwhere, $wgDBname;
+                $hackwhere[] = $fn;
+                if (function_exists("setproctitle"))
+                        setproctitle($fn . " [$wgDBname]");
+        }
+        function wfProfileOut( $fn = '' ) {
+                global $hackwhere, $wgDBname;
+                if (count($hackwhere))
+                        array_pop($hackwhere);
+                if (function_exists("setproctitle") && count($hackwhere))
+                        setproctitle($hackwhere[count($hackwhere)-1] . " [$wgDBname]");
+        }
+        function wfGetProfilingOutput( $s, $e ) {}
+        function wfProfileClose() {}
+}
+
+$fname = 'Setup.php';
+wfProfileIn( $fname );
+wfProfileIn( $fname.'-includes' );
+
+require_once( 'GlobalFunctions.php' );
+require_once( 'Hooks.php' );
+require_once( 'Namespace.php' );
+require_once( 'RecentChange.php' );
+require_once( 'User.php' );
+require_once( 'Skin.php' );
+require_once( 'OutputPage.php' );
+require_once( 'LinkCache.php' );
+require_once( 'Title.php' );
+require_once( 'Article.php' );
+require_once( 'MagicWord.php' );
+require_once( 'Block.php' );
+require_once( 'MessageCache.php' );
+require_once( 'BlockCache.php' );
+require_once( 'Parser.php' );
+require_once( 'ParserCache.php' );
+require_once( 'WebRequest.php' );
+require_once( 'LoadBalancer.php' );
+require_once( 'HistoryBlob.php' );
+require_once( 'ProxyTools.php' );
+require_once( 'ObjectCache.php' );
+require_once( 'WikiError.php' );
+require_once( 'SpecialPage.php' );
+
+if ( $wgUseDynamicDates ) {
+       require_once( 'DateFormatter.php' );
+}
+
+wfProfileOut( $fname.'-includes' );
+wfProfileIn( $fname.'-misc1' );
+
+$wgIP = wfGetIP();
+$wgRequest = new WebRequest();
+
+# Useful debug output
+if ( $wgCommandLineMode ) {
+       # wfDebug( '"' . implode( '"  "', $argv ) . '"' );
+} elseif ( function_exists( 'getallheaders' ) ) {
+       wfDebug( "\n\nStart request\n" );
+       wfDebug( $_SERVER['REQUEST_METHOD'] . ' ' . $_SERVER['REQUEST_URI'] . "\n" );
+       $headers = getallheaders();
+       foreach ($headers as $name => $value) {
+               wfDebug( "$name: $value\n" );
+       }
+       wfDebug( "\n" );
+} elseif( isset( $_SERVER['REQUEST_URI'] ) ) {
+       wfDebug( $_SERVER['REQUEST_METHOD'] . ' ' . $_SERVER['REQUEST_URI'] . "\n" );
+}
+
+if ( $wgSkipSkin ) {
+       $wgSkipSkins[] = $wgSkipSkin;
+}
+
+$wgUseEnotif = $wgEnotifUserTalk || $wgEnotifWatchlist;
+
+wfProfileOut( $fname.'-misc1' );
+wfProfileIn( $fname.'-memcached' );
+
+$wgMemc =& wfGetMainCache();
+$messageMemc =& wfGetMessageCacheStorage();
+$parserMemc =& wfGetParserCacheStorage();
+
+wfDebug( 'Main cache: ' . get_class( $wgMemc ) .
+       "\nMessage cache: " . get_class( $messageMemc ) .
+          "\nParser cache: " . get_class( $parserMemc ) . "\n" );
+
+wfProfileOut( $fname.'-memcached' );
+wfProfileIn( $fname.'-SetupSession' );
+
+if ( $wgDBprefix ) {
+       $wgCookiePrefix = $wgDBname . '_' . $wgDBprefix;
+} elseif ( $wgSharedDB ) {
+       $wgCookiePrefix = $wgSharedDB;
+} else {
+       $wgCookiePrefix = $wgDBname;
+}
+
+session_name( $wgCookiePrefix . '_session' );
+
+if( !$wgCommandLineMode && ( isset( $_COOKIE[session_name()] ) || isset( $_COOKIE[$wgCookiePrefix.'Token'] ) ) ) {
+       User::SetupSession();
+       $wgSessionStarted = true;
+} else {
+       $wgSessionStarted = false;
+}
+
+wfProfileOut( $fname.'-SetupSession' );
+wfProfileIn( $fname.'-database' );
+
+if ( !$wgDBservers ) {
+       $wgDBservers = array(array(
+               'host' => $wgDBserver,
+               'user' => $wgDBuser,
+               'password' => $wgDBpassword,
+               'dbname' => $wgDBname,
+               'type' => $wgDBtype,
+               'load' => 1,
+               'flags' => ($wgDebugDumpSql ? DBO_DEBUG : 0) | DBO_DEFAULT
+       ));
+}
+$wgLoadBalancer = LoadBalancer::newFromParams( $wgDBservers, false, $wgMasterWaitTimeout );
+$wgLoadBalancer->loadMasterPos();
+
+wfProfileOut( $fname.'-database' );
+wfProfileIn( $fname.'-language1' );
+
+require_once( "$IP/languages/Language.php" );
+
+function setupLangObj($langclass) {
+       global $IP;
+
+       if( ! class_exists( $langclass ) ) {
+               # Default to English/UTF-8
+               $baseclass = 'LanguageUtf8';
+               require_once( "$IP/languages/$baseclass.php" );
+               $lc = strtolower(substr($langclass, 8));
+               $snip = "
+                       class $langclass extends $baseclass {
+                               function getVariants() {
+                                       return array(\"$lc\");
+                               }
+
+                       }";
+               eval($snip);
+       }
+
+       $lang = new $langclass();
+
+       return $lang;
+}
+
+# $wgLanguageCode may be changed later to fit with user preference.
+# The content language will remain fixed as per the configuration,
+# so let's keep it.
+$wgContLanguageCode = $wgLanguageCode;
+$wgContLangClass = 'Language' . str_replace( '-', '_', ucfirst( $wgContLanguageCode ) );
+
+$wgContLang = setupLangObj( $wgContLangClass );
+$wgContLang->initEncoding();
+
+wfProfileOut( $fname.'-language1' );
+wfProfileIn( $fname.'-User' );
+
+# Skin setup functions
+# Entries can be added to this variable during the inclusion
+# of the extension file. Skins can then perform any necessary initialisation.
+foreach ( $wgSkinExtensionFunctions as $func ) {
+       $func();
+}
+
+if( !is_object( $wgAuth ) ) {
+       require_once( 'AuthPlugin.php' );
+       $wgAuth = new AuthPlugin();
+}
+
+if( $wgCommandLineMode ) {
+       # Used for some maintenance scripts; user session cookies can screw things up
+       # when the database is in an in-between state.
+       $wgUser = new User();
+       # Prevent loading User settings from the DB.
+       $wgUser->setLoaded( true );
+} else {
+        $wgUser = null;
+       wfRunHooks('AutoAuthenticate',array(&$wgUser));
+       if ($wgUser === null) {
+               $wgUser = User::loadFromSession();
+       }
+}
+
+wfProfileOut( $fname.'-User' );
+wfProfileIn( $fname.'-language2' );
+
+// wgLanguageCode now specifically means the UI language
+$wgLanguageCode = $wgRequest->getText('uselang', '');
+if ($wgLanguageCode == '')
+       $wgLanguageCode = $wgUser->getOption('language');
+# Validate $wgLanguageCode, which will soon be sent to an eval()
+if( empty( $wgLanguageCode ) || !preg_match( '/^[a-z]+(-[a-z]+)?$/', $wgLanguageCode ) ) {
+       $wgLanguageCode = $wgContLanguageCode;
+}
+
+$wgLangClass = 'Language'. str_replace( '-', '_', ucfirst( $wgLanguageCode ) );
+
+if( $wgLangClass == $wgContLangClass ) {
+       $wgLang = &$wgContLang;
+} else {
+       wfSuppressWarnings();
+       include_once("$IP/languages/$wgLangClass.php");
+       wfRestoreWarnings();
+
+       $wgLang = setupLangObj( $wgLangClass );
+}
+
+wfProfileOut( $fname.'-language2' );
+wfProfileIn( $fname.'-MessageCache' );
+
+$wgMessageCache = new MessageCache;
+$wgMessageCache->initialise( $parserMemc, $wgUseDatabaseMessages, $wgMsgCacheExpiry, $wgDBname);
+
+wfProfileOut( $fname.'-MessageCache' );
+
+#
+# I guess the warning about UI switching might still apply...
+#
+# FIXME: THE ABOVE MIGHT BREAK NAMESPACES, VARIABLES,
+# SEARCH INDEX UPDATES, AND MANY MANY THINGS.
+# DO NOT USE THIS MODE EXCEPT FOR TESTING RIGHT NOW.
+#
+# To disable it, the easiest thing could be to uncomment the
+# following; they should effectively disable the UI switch functionality
+#
+# $wgLangClass = $wgContLangClass;
+# $wgLanguageCode = $wgContLanguageCode;
+# $wgLang = $wgContLang;
+#
+# TODO: Need to change reference to $wgLang to $wgContLang at proper
+#       places, including namespaces, dates in signatures, magic words,
+#       and links
+#
+# TODO: Need to look at the issue of input/output encoding
+#
+
+
+wfProfileIn( $fname.'-OutputPage' );
+
+$wgOut = new OutputPage();
+
+wfProfileOut( $fname.'-OutputPage' );
+wfProfileIn( $fname.'-BlockCache' );
+
+$wgBlockCache = new BlockCache( true );
+
+wfProfileOut( $fname.'-BlockCache' );
+wfProfileIn( $fname.'-misc2' );
+
+$wgDeferredUpdateList = array();
+$wgPostCommitUpdateList = array();
+
+$wgLinkCache = new LinkCache();
+$wgMagicWords = array();
+$wgMwRedir =& MagicWord::get( MAG_REDIRECT );
+$wgParserCache = new ParserCache( $messageMemc );
+
+if ( $wgUseXMLparser ) {
+       require_once( 'ParserXML.php' );
+       $wgParser = new ParserXML();
+} else {
+       $wgParser = new Parser();
+}
+$wgOut->setParserOptions( ParserOptions::newFromUser( $wgUser ) );
+$wgMsgParserOptions = ParserOptions::newFromUser($wgUser);
+wfSeedRandom();
+
+# Placeholders in case of DB error
+$wgTitle = Title::makeTitle( NS_SPECIAL, 'Error' );
+$wgArticle = new Article($wgTitle);
+
+wfProfileOut( $fname.'-misc2' );
+wfProfileIn( $fname.'-extensions' );
+
+# Extension setup functions for extensions other than skins
+# Entries should be added to this variable during the inclusion
+# of the extension file. This allows the extension to perform
+# any necessary initialisation in the fully initialised environment
+foreach ( $wgExtensionFunctions as $func ) {
+       $func();
+}
+
+wfDebug( "\n" );
+$wgFullyInitialised = true;
+wfProfileOut( $fname.'-extensions' );
+wfProfileOut( $fname );
+
+}
+?>
diff --git a/includes/SiteConfiguration.php b/includes/SiteConfiguration.php
new file mode 100644 (file)
index 0000000..6aa7d45
--- /dev/null
@@ -0,0 +1,108 @@
+<?php
+/**
+ * This is a class used to hold configuration settings, particularly for multi-wiki sites. 
+ *
+ * @package MediaWiki
+ */
+
+/**
+ * The include paths change after this file is included from commandLine.inc, 
+ * meaning that require_once() fails to detect that it is including the same
+ * file again. We use DIY C-style protection as a workaround.
+ */
+if (!defined('SITE_CONFIGURATION')) {
+define('SITE_CONFIGURATION', 1);
+
+/** @package MediaWiki */
+class SiteConfiguration {
+       var $suffixes = array();
+       var $wikis = array();
+       var $settings = array();
+       var $localDatabases = array();
+       var $localVHosts = array();
+
+       /** */  
+       function get( $setting, $wiki, $suffix, $params = array() ) {
+               if ( array_key_exists( $wiki, $this->settings[$setting] ) ) {
+                       $retval = $this->settings[$setting][$wiki];
+               } elseif ( array_key_exists( $suffix, $this->settings[$setting] ) ) {
+                       $retval = $this->settings[$setting][$suffix];
+               } elseif ( array_key_exists( 'default', $this->settings[$setting] ) ) {
+                       $retval = $this->settings[$setting]['default'];
+               } else {
+                       $retval = NULL;
+               }
+               if ( !is_null( $retval ) && count( $params ) ) {
+                       foreach ( $params as $key => $value ) {
+                               $retval = str_replace( '$' . $key, $value, $retval );
+                       }
+               }
+               return $retval;
+       }
+
+       /** */
+       function getBool( $setting, $wiki, $suffix ) {
+               return (bool)($this->get( $setting, $wiki, $suffix ));
+       }
+
+       /** */
+       function &getLocalDatabases() {
+               return $this->localDatabases;
+       }
+
+       /** */
+       function initialise() {
+               foreach ( $this->wikis as $db ) {
+                       $this->localDatabases[$db] = $db;
+               }
+       }
+
+       /** */
+       function extractVar( $setting, $wiki, $suffix, &$var, $params ) {
+               $value = $this->get( $setting, $wiki, $suffix, $params );
+               if ( !is_null( $value ) ) {
+                       $var = $value;
+               }
+       }
+
+       /** */
+       function extractGlobal( $setting, $wiki, $suffix, $params ) {
+               $value = $this->get( $setting, $wiki, $suffix, $params );
+               if ( !is_null( $value ) ) {
+                       $GLOBALS[$setting] = $value;
+               }
+       }
+
+       /** */
+       function extractAllGlobals( $wiki, $suffix, $params ) {
+               foreach ( $this->settings as $varName => $setting ) {
+                       $this->extractGlobal( $varName, $wiki, $suffix, $params );
+               }
+       }
+
+       /**
+        * Work out the site and language name from a database name
+        * @param $db
+        */
+       function siteFromDB( $db ) {
+               $site = NULL;
+               $lang = NULL;
+               foreach ( $this->suffixes as $suffix ) {
+                       if ( substr( $db, -strlen( $suffix ) ) == $suffix ) {
+                               $site = $suffix == 'wiki' ? 'wikipedia' : $suffix;
+                               $lang = substr( $db, 0, strlen( $db ) - strlen( $suffix ) );
+                               break;
+                       }
+               }
+               $lang = str_replace( '_', '-', $lang );
+               return array( $site, $lang );
+       }
+
+       /** */
+       function isLocalVHost( $vhost ) {
+               return in_array( $vhost, $this->localVHosts );
+       }
+}
+}
+       
+?>
diff --git a/includes/SiteStatsUpdate.php b/includes/SiteStatsUpdate.php
new file mode 100644 (file)
index 0000000..00e5494
--- /dev/null
@@ -0,0 +1,83 @@
+<?php
+/**
+ * See deferred.txt
+ *
+ * @package MediaWiki
+ */
+
+/**
+ *
+ * @package MediaWiki
+ */
+class SiteStatsUpdate {
+
+       var $mViews, $mEdits, $mGood, $mPages, $mUsers;
+
+       function SiteStatsUpdate( $views, $edits, $good, $pages = 0, $users = 0 ) {
+               $this->mViews = $views;
+               $this->mEdits = $edits;
+               $this->mGood = $good;
+               $this->mPages = $pages;
+               $this->mUsers = $users;
+       }
+
+       function appendUpdate( &$sql, $field, $delta ) {
+               if ( $delta ) {
+                       if ( $sql ) {
+                               $sql .= ',';
+                       }
+                       if ( $delta < 0 ) {
+                               $sql .= "$field=$field-1";
+                       } else {
+                               $sql .= "$field=$field+1";
+                       }
+               }
+       }
+       
+       function doUpdate() {
+               global $wgDBname;
+               $fname = 'SiteStatsUpdate::doUpdate';
+               $dbw =& wfGetDB( DB_MASTER );
+
+               # First retrieve the row just to find out which schema we're in
+               $row = $dbw->selectRow( 'site_stats', '*', false, $fname );
+
+               $updates = '';
+               
+               $this->appendUpdate( $updates, 'ss_total_views', $this->mViews );
+               $this->appendUpdate( $updates, 'ss_total_edits', $this->mEdits );
+               $this->appendUpdate( $updates, 'ss_good_articles', $this->mGood );
+
+               if ( isset( $row->ss_total_pages ) ) {
+                       # Update schema if required
+                       if ( $row->ss_total_pages == -1 && !$this->mViews ) {
+                               $dbr =& wfGetDB( DB_SLAVE, array( 'SpecialStatistics', 'vslow') );
+                               extract( $dbr->tableNames( 'page', 'user' ) );
+
+                               $sql = "SELECT COUNT(page_namespace) AS total FROM $page";
+                               $res = $dbr->query( $sql, $fname );
+                               $pageRow = $dbr->fetchObject( $res );
+                               $pages = $pageRow->total + $this->mPages;
+
+                               $sql = "SELECT COUNT(user_id) AS total FROM $user";
+                               $res = $dbr->query( $sql, $fname );
+                               $userRow = $dbr->fetchObject( $res );
+                               $users = $userRow->total + $this->mUsers;
+                               
+                               if ( $updates ) {
+                                       $updates .= ',';
+                               }
+                               $updates .= "ss_total_pages=$pages, ss_users=$users";
+                       } else {        
+                               $this->appendUpdate( $updates, 'ss_total_pages', $this->mPages );
+                               $this->appendUpdate( $updates, 'ss_users', $this->mUsers );
+                       }
+               }
+               if ( $updates ) {
+                       $site_stats = $dbw->tableName( 'site_stats' );
+                       $sql = "UPDATE $site_stats SET $updates LIMIT 1";
+                       $dbw->query( $sql, $fname );
+               }
+       }
+}
+?>
diff --git a/includes/Skin.php b/includes/Skin.php
new file mode 100644 (file)
index 0000000..a84b3f3
--- /dev/null
@@ -0,0 +1,1346 @@
+<?php
+
+/**
+ *
+ * @package MediaWiki
+ * @subpackage Skins
+ */
+
+/**
+ * This is not a valid entry point, perform no further processing unless MEDIAWIKI is defined
+ */
+if( defined( "MEDIAWIKI" ) ) {
+
+# See skin.txt
+require_once( 'Linker.php' );
+require_once( 'Image.php' );
+
+# Get a list of all skins available in /skins/
+# Build using the regular expression '^(.*).php$'
+# Array keys are all lower case, array value keep the case used by filename
+#
+
+$skinDir = dir($IP.'/skins');
+
+# while code from www.php.net
+while (false !== ($file = $skinDir->read())) {
+       if(preg_match('/^([^.].*)\.php$/',$file, $matches)) {
+               $aSkin = $matches[1];
+               $wgValidSkinNames[strtolower($aSkin)] = $aSkin;
+       }
+}
+$skinDir->close();
+unset($matches);
+
+require_once( 'RecentChange.php' );
+
+/**
+ * @todo document
+ * @package MediaWiki
+ */
+class RCCacheEntry extends RecentChange
+{
+       var $secureName, $link;
+       var $curlink , $difflink, $lastlink , $usertalklink , $versionlink ;
+       var $userlink, $timestamp, $watched;
+
+       function newFromParent( $rc )
+       {
+               $rc2 = new RCCacheEntry;
+               $rc2->mAttribs = $rc->mAttribs;
+               $rc2->mExtra = $rc->mExtra;
+               return $rc2;
+       }
+} ;
+
+
+/**
+ * The main skin class that provide methods and properties for all other skins
+ * including PHPTal skins.
+ * This base class is also the "Standard" skin.
+ * @package MediaWiki
+ */
+class Skin extends Linker {
+       /**#@+
+        * @access private
+        */
+       var $lastdate, $lastline;
+       var $rc_cache ; # Cache for Enhanced Recent Changes
+       var $rcCacheIndex ; # Recent Changes Cache Counter for visibility toggle
+       var $rcMoveIndex;
+       /**#@-*/
+
+       /** Constructor, call parent constructor */
+       function Skin() { parent::Linker(); }
+
+       function getSkinNames() {
+               global $wgValidSkinNames;
+               return $wgValidSkinNames;
+       }
+
+       /** @return string path to the skin stylesheet */
+       function getStylesheet() { return 'common/wikistandard.css'; }
+
+       /** @return string skin name */
+       function getSkinName() {
+               return 'standard';
+       }
+
+       function qbSetting() {
+               global $wgOut, $wgUser;
+
+               if ( $wgOut->isQuickbarSuppressed() ) { return 0; }
+               $q = $wgUser->getOption( 'quickbar' );
+               if ( '' == $q ) { $q = 0; }
+               return $q;
+       }
+
+       function initPage( &$out ) {
+               $fname = 'Skin::initPage';
+               wfProfileIn( $fname );
+
+               $out->addLink( array( 'rel' => 'shortcut icon', 'href' => '/favicon.ico' ) );
+
+               $this->addMetadataLinks($out);
+
+               wfProfileOut( $fname );
+       }
+
+       function addMetadataLinks( &$out ) {
+               global $wgTitle, $wgEnableDublinCoreRdf, $wgEnableCreativeCommonsRdf, $wgRdfMimeType, $action;
+               global $wgRightsPage, $wgRightsUrl, $wgUseTrackbacks;
+
+               if( $out->isArticleRelated() ) {
+                       # note: buggy CC software only reads first "meta" link
+                       if( $wgEnableCreativeCommonsRdf ) {
+                               $out->addMetadataLink( array(
+                                       'title' => 'Creative Commons',
+                                       'type' => 'application/rdf+xml',
+                                       'href' => $wgTitle->getLocalURL( 'action=creativecommons') ) );
+                       }
+                       if( $wgEnableDublinCoreRdf ) {
+                               $out->addMetadataLink( array(
+                                       'title' => 'Dublin Core',
+                                       'type' => 'application/rdf+xml',
+                                       'href' => $wgTitle->getLocalURL( 'action=dublincore' ) ) );
+                       }
+               }
+               $copyright = '';
+               if( $wgRightsPage ) {
+                       $copy = Title::newFromText( $wgRightsPage );
+                       if( $copy ) {
+                               $copyright = $copy->getLocalURL();
+                       }
+               }
+               if( !$copyright && $wgRightsUrl ) {
+                       $copyright = $wgRightsUrl;
+               }
+               if( $copyright ) {
+                       $out->addLink( array(
+                               'rel' => 'copyright',
+                               'href' => $copyright ) );
+               }
+       }
+
+       function outputPage( &$out ) {
+               global $wgDebugComments;
+
+               wfProfileIn( 'Skin::outputPage' );
+               $this->initPage( $out );
+
+               $out->out( $out->headElement() );
+
+               $out->out( "\n<body" );
+               $ops = $this->getBodyOptions();
+               foreach ( $ops as $name => $val ) {
+                       $out->out( " $name='$val'" );
+               }
+               $out->out( ">\n" );
+               if ( $wgDebugComments ) {
+                       $out->out( "<!-- Wiki debugging output:\n" .
+                         $out->mDebugtext . "-->\n" );
+               }
+
+               $out->out( $this->beforeContent() );
+
+               $out->out( $out->mBodytext . "\n" );
+
+               $out->out( $this->afterContent() );
+
+               wfProfileClose();
+               $out->out( $out->reportTime() );
+
+               $out->out( "\n</body></html>" );
+       }
+
+       function getHeadScripts() {
+               global $wgStylePath, $wgUser, $wgContLang, $wgAllowUserJs, $wgJsMimeType;
+               $r = "<script type=\"{$wgJsMimeType}\" src=\"{$wgStylePath}/common/wikibits.js\"></script>\n";
+               if( $wgAllowUserJs && $wgUser->isLoggedIn() ) {
+                       $userpage = $wgUser->getUserPage();
+                       $userjs = htmlspecialchars( $this->makeUrl(
+                               $userpage->getPrefixedText().'/'.$this->getSkinName().'.js',
+                               'action=raw&ctype='.$wgJsMimeType));
+                       $r .= '<script type="'.$wgJsMimeType.'" src="'.$userjs."\"></script>\n";
+               }
+               return $r;
+       }
+
+       /**
+        * To make it harder for someone to slip a user a fake
+        * user-JavaScript or user-CSS preview, a random token
+        * is associated with the login session. If it's not
+        * passed back with the preview request, we won't render
+        * the code.
+        *
+        * @param string $action
+        * @return bool
+        * @access private
+        */
+       function userCanPreview( $action ) {
+               global $wgTitle, $wgRequest, $wgUser;
+
+               if( $action != 'submit' )
+                       return false;
+               if( !$wgRequest->wasPosted() )
+                       return false;
+               if( !$wgTitle->userCanEditCssJsSubpage() )
+                       return false;
+               return $wgUser->matchEditToken(
+                       $wgRequest->getVal( 'wpEditToken' ) );
+       }
+
+       # get the user/site-specific stylesheet, SkinPHPTal called from RawPage.php (settings are cached that way)
+       function getUserStylesheet() {
+               global $wgOut, $wgStylePath, $wgContLang, $wgUser, $wgRequest, $wgTitle, $wgAllowUserCss;
+               $sheet = $this->getStylesheet();
+               $action = $wgRequest->getText('action');
+               $s = "@import \"$wgStylePath/$sheet\";\n";
+               if($wgContLang->isRTL()) $s .= "@import \"$wgStylePath/common/common_rtl.css\";\n";
+               if( $wgAllowUserCss && $wgUser->isLoggedIn() ) { # logged in
+                       if($wgTitle->isCssSubpage() && $this->userCanPreview( $action ) ) {
+                               $s .= $wgRequest->getText('wpTextbox1');
+                       } else {
+                               $userpage = $wgUser->getUserPage();
+                               $s.= '@import "'.$this->makeUrl(
+                                       $userpage->getPrefixedText().'/'.$this->getSkinName().'.css',
+                                       'action=raw&ctype=text/css').'";'."\n";
+                       }
+               }
+               $s .= $this->doGetUserStyles();
+               return $s."\n";
+       }
+
+       /**
+        * placeholder, returns generated js in monobook
+        */
+       function getUserJs() { return; }
+
+       /**
+        * Return html code that include User stylesheets
+        */
+       function getUserStyles() {
+               global $wgOut, $wgStylePath, $wgLang;
+               $s = "<style type='text/css'>\n";
+               $s .= "/*/*/ /*<![CDATA[*/\n"; # <-- Hide the styles from Netscape 4 without hiding them from IE/Mac
+               $s .= $this->getUserStylesheet();
+               $s .= "/*]]>*/ /* */\n";
+               $s .= "</style>\n";
+               return $s;
+       }
+
+       /**
+        * Some styles that are set by user through the user settings interface.
+        */
+       function doGetUserStyles() {
+               global $wgUser, $wgContLang;
+
+               $csspage = $wgContLang->getNsText( NS_MEDIAWIKI ) . ':' . $this->getSkinName() . '.css';
+               $s = '@import "'.$this->makeUrl($csspage, 'action=raw&ctype=text/css')."\";\n";
+
+               return $s . $this->reallyDoGetUserStyles();
+       }
+
+       function reallyDoGetUserStyles() {
+               global $wgUser;
+               $s = '';
+               if (($undopt = $wgUser->getOption("underline")) != 2) {
+                       $underline = $undopt ? 'underline' : 'none';
+                       $s .= "a { text-decoration: $underline; }\n";
+               }
+               if( $wgUser->getOption( 'highlightbroken' ) ) {
+                       $s .= "a.new, #quickbar a.new { color: #CC2200; }\n";
+               } else {
+                       $s .= <<<END
+a.new, #quickbar a.new,
+a.stub, #quickbar a.stub {
+       color: inherit;
+       text-decoration: inherit;
+}
+a.new:after, #quickbar a.new:after {
+       content: "?";
+       color: #CC2200;
+       text-decoration: $underline;
+}
+a.stub:after, #quickbar a.stub:after {
+       content: "!";
+       color: #772233;
+       text-decoration: $underline;
+}
+END;
+               }
+               if( $wgUser->getOption( 'justify' ) ) {
+                       $s .= "#article, #bodyContent { text-align: justify; }\n";
+               }
+               if( !$wgUser->getOption( 'showtoc' ) ) {
+                       $s .= "#toc { display: none; }\n";
+               }
+               if( !$wgUser->getOption( 'editsection' ) ) {
+                       $s .= ".editsection { display: none; }\n";
+               }
+               return $s;
+       }
+
+       function getBodyOptions() {
+               global $wgUser, $wgTitle, $wgNamespaceBackgrounds, $wgOut, $wgRequest;
+
+               extract( $wgRequest->getValues( 'oldid', 'redirect', 'diff' ) );
+
+               if ( 0 != $wgTitle->getNamespace() ) {
+                       $a = array( 'bgcolor' => '#ffffec' );
+               }
+               else $a = array( 'bgcolor' => '#FFFFFF' );
+               if($wgOut->isArticle() && $wgUser->getOption('editondblclick') &&
+                 (!$wgTitle->isProtected() || $wgUser->isAllowed('protect')) ) {
+                       $t = wfMsg( 'editthispage' );
+                       $oid = $red = '';
+                       if ( !empty($redirect) && $redirect == 'no' ) {
+                               $red = "&redirect={$redirect}";
+                       }
+                       if ( !empty($oldid) && ! isset( $diff ) ) {
+                               $oid = "&oldid=" . IntVal( $oldid );
+                       }
+                       $s = $wgTitle->getFullURL( "action=edit{$oid}{$red}" );
+                       $s = 'document.location = "' .$s .'";';
+                       $a += array ('ondblclick' => $s);
+
+               }
+               $a['onload'] = $wgOut->getOnloadHandler();
+               if( $wgUser->getOption( 'editsectiononrightclick' ) ) {
+                       if( $a['onload'] != '' ) {
+                               $a['onload'] .= ';';
+                       }
+                       $a['onload'] .= 'setupRightClickEdit()';
+               }
+               return $a;
+       }
+
+       /**
+        * URL to the logo
+        */
+       function getLogo() {
+               global $wgLogo;
+               return $wgLogo;
+       }
+
+       /**
+        * This will be called immediately after the <body> tag.  Split into
+        * two functions to make it easier to subclass.
+        */
+       function beforeContent() {
+               return $this->doBeforeContent();
+       }
+
+       function doBeforeContent() {
+               global $wgOut, $wgTitle, $wgContLang;
+               $fname = 'Skin::doBeforeContent';
+               wfProfileIn( $fname );
+
+               $s = '';
+               $qb = $this->qbSetting();
+
+               if( $langlinks = $this->otherLanguages() ) {
+                       $rows = 2;
+                       $borderhack = '';
+               } else {
+                       $rows = 1;
+                       $langlinks = false;
+                       $borderhack = 'class="top"';
+               }
+
+               $s .= "\n<div id='content'>\n<div id='topbar'>\n" .
+                 "<table border='0' cellspacing='0' width='98%'>\n<tr>\n";
+
+               $shove = ($qb != 0);
+               $left = ($qb == 1 || $qb == 3);
+               if($wgContLang->isRTL()) $left = !$left;
+
+               if ( !$shove ) {
+                       $s .= "<td class='top' align='left' valign='top' rowspan='{$rows}'>\n" .
+                         $this->logoText() . '</td>';
+               } elseif( $left ) {
+                       $s .= $this->getQuickbarCompensator( $rows );
+               }
+               $l = $wgContLang->isRTL() ? 'right' : 'left';
+               $s .= "<td {$borderhack} align='$l' valign='top'>\n";
+
+               $s .= $this->topLinks() ;
+               $s .= "<p class='subtitle'>" . $this->pageTitleLinks() . "</p>\n";
+
+               $r = $wgContLang->isRTL() ? "left" : "right";
+               $s .= "</td>\n<td {$borderhack} valign='top' align='$r' nowrap='nowrap'>";
+               $s .= $this->nameAndLogin();
+               $s .= "\n<br />" . $this->searchForm() . "</td>";
+
+               if ( $langlinks ) {
+                       $s .= "</tr>\n<tr>\n<td class='top' colspan=\"2\">$langlinks</td>\n";
+               }
+
+               if ( $shove && !$left ) { # Right
+                       $s .= $this->getQuickbarCompensator( $rows );
+               }
+               $s .= "</tr>\n</table>\n</div>\n";
+               $s .= "\n<div id='article'>\n";
+
+               $notice = wfGetSiteNotice();
+               if( $notice ) {
+                       $s .= "\n<div id='siteNotice'>$notice</div>\n";
+               }
+               $s .= $this->pageTitle();
+               $s .= $this->pageSubtitle() ;
+               $s .= $this->getCategories();
+               wfProfileOut( $fname );
+               return $s;
+       }
+
+
+       function getCategoryLinks () {
+               global $wgOut, $wgTitle, $wgParser;
+               global $wgUseCategoryMagic, $wgUseCategoryBrowser, $wgLang;
+
+               if( !$wgUseCategoryMagic ) return '' ;
+               if( count( $wgOut->mCategoryLinks ) == 0 ) return '';
+
+               # Taken out so that they will be displayed in previews -- TS
+               #if( !$wgOut->isArticle() ) return '';
+
+               $t = implode ( ' | ' , $wgOut->mCategoryLinks ) ;
+               $s = $this->makeKnownLinkObj( Title::makeTitle( NS_SPECIAL, 'Categories' ),
+                       wfMsg( 'categories' ), 'article=' . urlencode( $wgTitle->getPrefixedDBkey() ) )
+                       . ': ' . $t;
+
+               # optional 'dmoz-like' category browser. Will be shown under the list
+               # of categories an article belong to
+               if($wgUseCategoryBrowser) {
+                       $s .= '<br /><hr />';
+
+                       # get a big array of the parents tree
+                       $parenttree = $wgTitle->getParentCategoryTree();
+                       # Skin object passed by reference cause it can not be
+                       # accessed under the method subfunction drawCategoryBrowser
+                       $tempout = explode("\n", Skin::drawCategoryBrowser($parenttree, $this) );
+                       # Clean out bogus first entry and sort them
+                       unset($tempout[0]);
+                       asort($tempout);
+                       # Output one per line
+                       $s .= implode("<br />\n", $tempout);
+               }
+
+               return $s;
+       }
+
+       /** Render the array as a serie of links.
+        * @param array $tree Categories tree returned by Title::getParentCategoryTree
+        * @param object &skin Skin passed by reference
+        * @return string separated by &gt;, terminate with "\n"
+        */
+       function drawCategoryBrowser($tree, &$skin) {
+               $return = '';
+               foreach ($tree as $element => $parent) {
+                       if (empty($parent)) {
+                               # element start a new list
+                               $return .= "\n";
+                       } else {
+                               # grab the others elements
+                               $return .= Skin::drawCategoryBrowser($parent, $skin) . ' &gt; ';
+                       }
+                       # add our current element to the list
+                       $eltitle = Title::NewFromText($element);
+                       $return .=  $skin->makeLinkObj( $eltitle, $eltitle->getText() ) ;
+               }
+               return $return;
+       }
+
+       function getCategories() {
+               $catlinks=$this->getCategoryLinks();
+               if(!empty($catlinks)) {
+                       return "<p class='catlinks'>{$catlinks}</p>";
+               }
+       }
+
+       function getQuickbarCompensator( $rows = 1 ) {
+               return "<td width='152' rowspan='{$rows}'>&nbsp;</td>";
+       }
+
+       /**
+        * This gets called immediately before the </body> tag.
+        * @return string HTML to be put after </body> ???
+        */
+       function afterContent() {
+               $printfooter = "<div class=\"printfooter\">\n" . $this->printFooter() . "</div>\n";
+               return $printfooter . $this->doAfterContent();
+       }
+
+       /** @return string Retrievied from HTML text */
+       function printSource() {
+               global $wgTitle;
+               $url = htmlspecialchars( $wgTitle->getFullURL() );
+               return wfMsg( 'retrievedfrom', '<a href="'.$url.'">'.$url.'</a>' );
+       }
+
+       function printFooter() {
+               return "<p>" .  $this->printSource() .
+                       "</p>\n\n<p>" . $this->pageStats() . "</p>\n";
+       }
+
+       /** overloaded by derived classes */
+       function doAfterContent() { }
+
+       function pageTitleLinks() {
+               global $wgOut, $wgTitle, $wgUser, $wgContLang, $wgRequest;
+
+               extract( $wgRequest->getValues( 'oldid', 'diff' ) );
+               $action = $wgRequest->getText( 'action' );
+
+               $s = $this->printableLink();
+               $disclaimer = $this->disclaimerLink(); # may be empty
+               if( $disclaimer ) {
+                       $s .= ' | ' . $disclaimer;
+               }
+
+               if ( $wgOut->isArticleRelated() ) {
+                       if ( $wgTitle->getNamespace() == NS_IMAGE ) {
+                               $name = $wgTitle->getDBkey();
+                               $image = new Image( $wgTitle );
+                               if( $image->exists() ) {
+                                       $link = htmlspecialchars( $image->getURL() );
+                                       $style = $this->getInternalLinkAttributes( $link, $name );
+                                       $s .= " | <a href=\"{$link}\"{$style}>{$name}</a>";
+                               }
+                       }
+               }
+               if ( 'history' == $action || isset( $diff ) || isset( $oldid ) ) {
+                       $s .= ' | ' . $this->makeKnownLinkObj( $wgTitle,
+                                       wfMsg( 'currentrev' ) );
+               }
+
+               if ( $wgUser->getNewtalk() ) {
+               # do not show "You have new messages" text when we are viewing our
+               # own talk page
+
+                       if( !$wgTitle->equals( $wgUser->getTalkPage() ) ) {
+                               $tl = $this->makeKnownLinkObj( $wgUser->getTalkPage(),
+                                               wfMsg('newmessageslink') );
+                               $s.= ' | <strong>'. wfMsg( 'newmessages', $tl ) . '</strong>';
+                               # disable caching
+                               $wgOut->setSquidMaxage(0);
+                               $wgOut->enableClientCache(false);
+                       }
+               }
+
+               $undelete = $this->getUndeleteLink();
+               if( !empty( $undelete ) ) {
+                       $s .= ' | '.$undelete;
+               }
+               return $s;
+       }
+
+       function getUndeleteLink() {
+               global $wgUser, $wgTitle, $wgContLang, $action;
+               if( $wgUser->isAllowed('rollback') &&
+                       (($wgTitle->getArticleId() == 0) || ($action == "history")) &&
+                       ($n = $wgTitle->isDeleted() ) ) {
+                       return wfMsg( 'thisisdeleted',
+                               $this->makeKnownLink(
+                                       $wgContLang->SpecialPage( 'Undelete/' . $wgTitle->getPrefixedDBkey() ),
+                                       wfMsg( 'restorelink' . ($n == 1 ? '1' : ''), $n ) ) );
+               }
+               return '';
+       }
+
+       function printableLink() {
+               global $wgOut, $wgFeedClasses, $wgRequest;
+
+               $baseurl = $_SERVER['REQUEST_URI'];
+               if( strpos( '?', $baseurl ) == false ) {
+                       $baseurl .= '?';
+               } else {
+                       $baseurl .= '&';
+               }
+               $baseurl = htmlspecialchars( $baseurl );
+               $printurl = $wgRequest->escapeAppendQuery( 'printable=yes' );
+
+               $s = "<a href=\"$printurl\">" . wfMsg( 'printableversion' ) . '</a>';
+               if( $wgOut->isSyndicated() ) {
+                       foreach( $wgFeedClasses as $format => $class ) {
+                               $feedurl = $wgRequest->escapeAppendQuery( "feed=$format" );
+                               $s .= " | <a href=\"$feedurl\">{$format}</a>";
+                       }
+               }
+               return $s;
+       }
+
+       function pageTitle() {
+               global $wgOut, $wgTitle, $wgUser;
+
+               $s = '<h1 class="pagetitle">' . htmlspecialchars( $wgOut->getPageTitle() ) . '</h1>';
+               return $s;
+       }
+
+       function pageSubtitle() {
+               global $wgOut;
+
+               $sub = $wgOut->getSubtitle();
+               if ( '' == $sub ) {
+                       global $wgExtraSubtitle;
+                       $sub = wfMsg( 'tagline' ) . $wgExtraSubtitle;
+               }
+               $subpages = $this->subPageSubtitle();
+               $sub .= !empty($subpages)?"</p><p class='subpages'>$subpages":'';
+               $s = "<p class='subtitle'>{$sub}</p>\n";
+               return $s;
+       }
+
+       function subPageSubtitle() {
+               global $wgOut,$wgTitle,$wgNamespacesWithSubpages;
+               $subpages = '';
+               if($wgOut->isArticle() && !empty($wgNamespacesWithSubpages[$wgTitle->getNamespace()])) {
+                       $ptext=$wgTitle->getPrefixedText();
+                       if(preg_match('/\//',$ptext)) {
+                               $links = explode('/',$ptext);
+                               $c = 0;
+                               $growinglink = '';
+                               foreach($links as $link) {
+                                       $c++;
+                                       if ($c<count($links)) {
+                                               $growinglink .= $link;
+                                               $getlink = $this->makeLink( $growinglink, $link );
+                                               if(preg_match('/class="new"/i',$getlink)) { break; } # this is a hack, but it saves time
+                                               if ($c>1) {
+                                                       $subpages .= ' | ';
+                                               } else  {
+                                                       $subpages .= '&lt; ';
+                                               }
+                                               $subpages .= $getlink;
+                                               $growinglink .= '/';
+                                       }
+                               }
+                       }
+               }
+               return $subpages;
+       }
+
+       function nameAndLogin() {
+               global $wgUser, $wgTitle, $wgLang, $wgContLang, $wgShowIPinHeader, $wgIP;
+
+               $li = $wgContLang->specialPage( 'Userlogin' );
+               $lo = $wgContLang->specialPage( 'Userlogout' );
+
+               $s = '';
+               if ( $wgUser->isAnon() ) {
+                       if( $wgShowIPinHeader && isset( $_COOKIE[ini_get('session.name')] ) ) {
+                               $n = $wgIP;
+
+                               $tl = $this->makeKnownLinkObj( $wgUser->getTalkPage(),
+                                 $wgContLang->getNsText( NS_TALK ) );
+
+                               $s .= $n . ' ('.$tl.')';
+                       } else {
+                               $s .= wfMsg('notloggedin');
+                       }
+
+                       $rt = $wgTitle->getPrefixedURL();
+                       if ( 0 == strcasecmp( urlencode( $lo ), $rt ) ) {
+                               $q = '';
+                       } else { $q = "returnto={$rt}"; }
+
+                       $s .= "\n<br />" . $this->makeKnownLinkObj(
+                               Title::makeTitle( NS_SPECIAL, 'Userlogin' ),
+                               wfMsg( 'login' ), $q );
+               } else {
+                       $n = $wgUser->getName();
+                       $rt = $wgTitle->getPrefixedURL();
+                       $tl = $this->makeKnownLinkObj( $wgUser->getTalkPage(),
+                         $wgContLang->getNsText( NS_TALK ) );
+
+                       $tl = " ({$tl})";
+
+                       $s .= $this->makeKnownLinkObj( $wgUser->getUserPage(),
+                         $n ) . "{$tl}<br />" .
+                         $this->makeKnownLinkObj( Title::makeTitle( NS_SPECIAL, 'Userlogout' ), wfMsg( 'logout' ),
+                         "returnto={$rt}" ) . ' | ' .
+                         $this->specialLink( 'preferences' );
+               }
+               $s .= ' | ' . $this->makeKnownLink( wfMsgForContent( 'helppage' ),
+                 wfMsg( 'help' ) );
+
+               return $s;
+       }
+
+       function getSearchLink() {
+               $searchPage =& Title::makeTitle( NS_SPECIAL, 'Search' );
+               return $searchPage->getLocalURL();
+       }
+
+       function escapeSearchLink() {
+               return htmlspecialchars( $this->getSearchLink() );
+       }
+
+       function searchForm() {
+               global $wgRequest;
+               $search = $wgRequest->getText( 'search' );
+
+               $s = '<form name="search" class="inline" method="post" action="'
+                 . $this->escapeSearchLink() . "\">\n"
+                 . '<input type="text" name="search" size="19" value="'
+                 . htmlspecialchars(substr($search,0,256)) . "\" />\n"
+                 . '<input type="submit" name="go" value="' . wfMsg ('go') . '" />&nbsp;'
+                 . '<input type="submit" name="fulltext" value="' . wfMsg ('search') . "\" />\n</form>";
+
+               return $s;
+       }
+
+       function topLinks() {
+               global $wgOut;
+               $sep = " |\n";
+
+               $s = $this->mainPageLink() . $sep
+                 . $this->specialLink( 'recentchanges' );
+
+               if ( $wgOut->isArticleRelated() ) {
+                       $s .=  $sep . $this->editThisPage()
+                         . $sep . $this->historyLink();
+               }
+               # Many people don't like this dropdown box
+               #$s .= $sep . $this->specialPagesList();
+
+               /* show links to different language variants */
+               global $wgDisableLangConversion, $wgContLang, $wgTitle;
+               $variants = $wgContLang->getVariants();
+               if( !$wgDisableLangConversion && sizeof( $variants ) > 1 ) {
+                       foreach( $variants as $code ) {
+                               $varname = $wgContLang->getVariantname( $code );
+                               if( $varname == 'disable' )
+                                       continue;
+                               $s .= ' | <a href="' . $wgTitle->getLocalUrl( 'variant=' . $code ) . '">' . $varname . '</a>';
+                       }
+               }
+
+               return $s;
+       }
+
+       function bottomLinks() {
+               global $wgOut, $wgUser, $wgTitle, $wgUseTrackbacks;
+               $sep = " |\n";
+
+               $s = '';
+               if ( $wgOut->isArticleRelated() ) {
+                       $s .= '<strong>' . $this->editThisPage() . '</strong>';
+                       if ( $wgUser->isLoggedIn() ) {
+                               $s .= $sep . $this->watchThisPage();
+                       }
+                       $s .= $sep . $this->talkLink()
+                         . $sep . $this->historyLink()
+                         . $sep . $this->whatLinksHere()
+                         . $sep . $this->watchPageLinksLink();
+
+                       if ($wgUseTrackbacks)
+                               $s .= $sep . $this->trackbackLink();
+
+                       if ( $wgTitle->getNamespace() == NS_USER
+                           || $wgTitle->getNamespace() == NS_USER_TALK )
+
+                       {
+                               $id=User::idFromName($wgTitle->getText());
+                               $ip=User::isIP($wgTitle->getText());
+
+                               if($id || $ip) { # both anons and non-anons have contri list
+                                       $s .= $sep . $this->userContribsLink();
+                               }
+                               if( $this->showEmailUser( $id ) ) {
+                                       $s .= $sep . $this->emailUserLink();
+                               }
+                       }
+                       if ( $wgTitle->getArticleId() ) {
+                               $s .= "\n<br />";
+                               if($wgUser->isAllowed('delete')) { $s .= $this->deleteThisPage(); }
+                               if($wgUser->isAllowed('protect')) { $s .= $sep . $this->protectThisPage(); }
+                               if($wgUser->isAllowed('move')) { $s .= $sep . $this->moveThisPage(); }
+                       }
+                       $s .= "<br />\n" . $this->otherLanguages();
+               }
+               return $s;
+       }
+
+       function pageStats() {
+               global $wgOut, $wgLang, $wgArticle, $wgRequest, $wgUser;
+               global $wgDisableCounters, $wgMaxCredits, $wgShowCreditsIfMax, $wgTitle, $wgPageShowWatchingUsers;
+
+               extract( $wgRequest->getValues( 'oldid', 'diff' ) );
+               if ( ! $wgOut->isArticle() ) { return ''; }
+               if ( isset( $oldid ) || isset( $diff ) ) { return ''; }
+               if ( 0 == $wgArticle->getID() ) { return ''; }
+
+               $s = '';
+               if ( !$wgDisableCounters ) {
+                       $count = $wgLang->formatNum( $wgArticle->getCount() );
+                       if ( $count ) {
+                               $s = wfMsg( 'viewcount', $count );
+                       }
+               }
+
+               if (isset($wgMaxCredits) && $wgMaxCredits != 0) {
+                   require_once('Credits.php');
+                   $s .= ' ' . getCredits($wgArticle, $wgMaxCredits, $wgShowCreditsIfMax);
+               } else {
+                   $s .= $this->lastModified();
+               }
+
+               if ($wgPageShowWatchingUsers && $wgUser->getOption( 'shownumberswatching' )) {
+                       $dbr =& wfGetDB( DB_SLAVE );
+                       extract( $dbr->tableNames( 'watchlist' ) );
+                       $sql = "SELECT COUNT(*) AS n FROM $watchlist
+                               WHERE wl_title='" . $dbr->strencode($wgTitle->getDBKey()) .
+                               "' AND  wl_namespace=" . $wgTitle->getNamespace() ;
+                       $res = $dbr->query( $sql, 'Skin::pageStats');
+                       $x = $dbr->fetchObject( $res );
+                       $s .= ' ' . wfMsg('number_of_watching_users_pageview', $x->n );
+               }
+
+               return $s . ' ' .  $this->getCopyright();
+       }
+
+       function getCopyright() {
+               global $wgRightsPage, $wgRightsUrl, $wgRightsText, $wgRequest;
+
+
+               $oldid = $wgRequest->getVal( 'oldid' );
+               $diff = $wgRequest->getVal( 'diff' );
+
+               if ( !is_null( $oldid ) && is_null( $diff ) && wfMsgForContent( 'history_copyright' ) !== '-' ) {
+                       $msg = 'history_copyright';
+               } else {
+                       $msg = 'copyright';
+               }
+
+               $out = '';
+               if( $wgRightsPage ) {
+                       $link = $this->makeKnownLink( $wgRightsPage, $wgRightsText );
+               } elseif( $wgRightsUrl ) {
+                       $link = $this->makeExternalLink( $wgRightsUrl, $wgRightsText );
+               } else {
+                       # Give up now
+                       return $out;
+               }
+               $out .= wfMsgForContent( $msg, $link );
+               return $out;
+       }
+
+       function getCopyrightIcon() {
+               global $wgRightsPage, $wgRightsUrl, $wgRightsText, $wgRightsIcon, $wgCopyrightIcon;
+               $out = '';
+               if ( isset( $wgCopyrightIcon ) && $wgCopyrightIcon ) {
+                       $out = $wgCopyrightIcon;
+               } else if ( $wgRightsIcon ) {
+                       $icon = htmlspecialchars( $wgRightsIcon );
+                       if ( $wgRightsUrl ) {
+                               $url = htmlspecialchars( $wgRightsUrl );
+                               $out .= '<a href="'.$url.'">';
+                       }
+                       $text = htmlspecialchars( $wgRightsText );
+                       $out .= "<img src=\"$icon\" alt='$text' />";
+                       if ( $wgRightsUrl ) {
+                               $out .= '</a>';
+                       }
+               }
+               return $out;
+       }
+
+       function getPoweredBy() {
+               global $wgStylePath;
+               $url = htmlspecialchars( "$wgStylePath/common/images/poweredby_mediawiki_88x31.png" );
+               $img = '<a href="http://www.mediawiki.org/"><img src="'.$url.'" alt="MediaWiki" /></a>';
+               return $img;
+       }
+
+       function lastModified() {
+               global $wgLang, $wgArticle, $wgLoadBalancer;
+
+               $timestamp = $wgArticle->getTimestamp();
+               if ( $timestamp ) {
+                       $d = $wgLang->timeanddate( $timestamp, true );
+                       $s = ' ' . wfMsg( 'lastmodified', $d );
+               } else {
+                       $s = '';
+               }
+               if ( $wgLoadBalancer->getLaggedSlaveMode() ) {
+                       $s .= ' <strong>' . wfMsg( 'laggedslavemode' ) . '</strong>';
+               }
+               return $s;
+       }
+
+       function logoText( $align = '' ) {
+               if ( '' != $align ) { $a = " align='{$align}'"; }
+               else { $a = ''; }
+
+               $mp = wfMsg( 'mainpage' );
+               $titleObj = Title::newFromText( $mp );
+               if ( is_object( $titleObj ) ) {
+                       $url = $titleObj->escapeLocalURL();
+               } else {
+                       $url = '';
+               }
+
+               $logourl = $this->getLogo();
+               $s = "<a href='{$url}'><img{$a} src='{$logourl}' alt='[{$mp}]' /></a>";
+               return $s;
+       }
+
+       /**
+        * show a drop-down box of special pages
+        * @TODO crash bug913. Need to be rewrote completly.
+        */
+       function specialPagesList() {
+               global $wgUser, $wgOut, $wgContLang, $wgServer, $wgRedirectScript, $wgAvailableRights;
+               require_once('SpecialPage.php');
+               $a = array();
+               $pages = SpecialPage::getPages();
+
+               // special pages without access restriction
+               foreach ( $pages[''] as $name => $page ) {
+                       $a[$name] = $page->getDescription();
+               }
+
+               // Other special pages that are restricted.
+               // Copied from SpecialSpecialpages.php
+               foreach($wgAvailableRights as $right) {
+                       if( $wgUser->isAllowed($right) ) {
+                               /** Add all pages for this right */
+                               if(isset($pages[$right])) {
+                                       foreach($pages[$right] as $name => $page) {
+                                       $a[$name] = $page->getDescription();
+                                       }
+                               }
+                       }
+               }
+
+               $go = wfMsg( 'go' );
+               $sp = wfMsg( 'specialpages' );
+               $spp = $wgContLang->specialPage( 'Specialpages' );
+
+               $s = '<form id="specialpages" method="get" class="inline" ' .
+                 'action="' . htmlspecialchars( "{$wgServer}{$wgRedirectScript}" ) . "\">\n";
+               $s .= "<select name=\"wpDropdown\">\n";
+               $s .= "<option value=\"{$spp}\">{$sp}</option>\n";
+
+
+               foreach ( $a as $name => $desc ) {
+                       $p = $wgContLang->specialPage( $name );
+                       $s .= "<option value=\"{$p}\">{$desc}</option>\n";
+               }
+               $s .= "</select>\n";
+               $s .= "<input type='submit' value=\"{$go}\" name='redirect' />\n";
+               $s .= "</form>\n";
+               return $s;
+       }
+
+       function mainPageLink() {
+               $mp = wfMsgForContent( 'mainpage' );
+               $mptxt = wfMsg( 'mainpage');
+               $s = $this->makeKnownLink( $mp, $mptxt );
+               return $s;
+       }
+
+       function copyrightLink() {
+               $s = $this->makeKnownLink( wfMsgForContent( 'copyrightpage' ),
+                 wfMsg( 'copyrightpagename' ) );
+               return $s;
+       }
+
+       function aboutLink() {
+               $s = $this->makeKnownLink( wfMsgForContent( 'aboutpage' ),
+                 wfMsg( 'aboutsite' ) );
+               return $s;
+       }
+
+
+       function disclaimerLink() {
+               $disclaimers = wfMsg( 'disclaimers' );
+               if ($disclaimers == '-') {
+                       return '';
+               } else {
+                       return $this->makeKnownLink( wfMsgForContent( 'disclaimerpage' ),
+                                                    $disclaimers );
+               }
+       }
+
+       function editThisPage() {
+               global $wgOut, $wgTitle, $wgRequest;
+
+               $oldid = $wgRequest->getVal( 'oldid' );
+               $diff = $wgRequest->getVal( 'diff' );
+               $redirect = $wgRequest->getVal( 'redirect' );
+
+               if ( ! $wgOut->isArticleRelated() ) {
+                       $s = wfMsg( 'protectedpage' );
+               } else {
+                       if ( $wgTitle->userCanEdit() ) {
+                               $t = wfMsg( 'editthispage' );
+                       } else {
+                               $t = wfMsg( 'viewsource' );
+                       }
+                       $oid = $red = '';
+
+                       if ( !is_null( $redirect ) ) { $red = "&redirect={$redirect}"; }
+                       if ( $oldid && ! isset( $diff ) ) {
+                               $oid = '&oldid='.$oldid;
+                       }
+                       $s = $this->makeKnownLinkObj( $wgTitle, $t, "action=edit{$oid}{$red}" );
+               }
+               return $s;
+       }
+
+       function deleteThisPage() {
+               global $wgUser, $wgOut, $wgTitle, $wgRequest;
+
+               $diff = $wgRequest->getVal( 'diff' );
+               if ( $wgTitle->getArticleId() && ( ! $diff ) && $wgUser->isAllowed('delete') ) {
+                       $t = wfMsg( 'deletethispage' );
+
+                       $s = $this->makeKnownLinkObj( $wgTitle, $t, 'action=delete' );
+               } else {
+                       $s = '';
+               }
+               return $s;
+       }
+
+       function protectThisPage() {
+               global $wgUser, $wgOut, $wgTitle, $wgRequest;
+
+               $diff = $wgRequest->getVal( 'diff' );
+               if ( $wgTitle->getArticleId() && ( ! $diff ) && $wgUser->isAllowed('protect') ) {
+                       if ( $wgTitle->isProtected() ) {
+                               $t = wfMsg( 'unprotectthispage' );
+                               $q = 'action=unprotect';
+                       } else {
+                               $t = wfMsg( 'protectthispage' );
+                               $q = 'action=protect';
+                       }
+                       $s = $this->makeKnownLinkObj( $wgTitle, $t, $q );
+               } else {
+                       $s = '';
+               }
+               return $s;
+       }
+
+       function watchThisPage() {
+               global $wgUser, $wgOut, $wgTitle;
+
+               if ( $wgOut->isArticleRelated() ) {
+                       if ( $wgTitle->userIsWatching() ) {
+                               $t = wfMsg( 'unwatchthispage' );
+                               $q = 'action=unwatch';
+                       } else {
+                               $t = wfMsg( 'watchthispage' );
+                               $q = 'action=watch';
+                       }
+                       $s = $this->makeKnownLinkObj( $wgTitle, $t, $q );
+               } else {
+                       $s = wfMsg( 'notanarticle' );
+               }
+               return $s;
+       }
+
+       function moveThisPage() {
+               global $wgTitle;
+
+               if ( $wgTitle->userCanMove() ) {
+                       return $this->makeKnownLinkObj( Title::makeTitle( NS_SPECIAL, 'Movepage' ),
+                         wfMsg( 'movethispage' ), 'target=' . $wgTitle->getPrefixedURL() );
+               } else {
+                       // no message if page is protected - would be redundant
+                       return '';
+               }
+       }
+
+       function historyLink() {
+               global $wgTitle;
+
+               return $this->makeKnownLinkObj( $wgTitle,
+                 wfMsg( 'history' ), 'action=history' );
+       }
+
+       function whatLinksHere() {
+               global $wgTitle;
+
+               return $this->makeKnownLinkObj( Title::makeTitle( NS_SPECIAL, 'Whatlinkshere' ),
+                 wfMsg( 'whatlinkshere' ), 'target=' . $wgTitle->getPrefixedURL() );
+       }
+
+       function userContribsLink() {
+               global $wgTitle;
+
+               return $this->makeKnownLinkObj( Title::makeTitle( NS_SPECIAL, 'Contributions' ),
+                 wfMsg( 'contributions' ), 'target=' . $wgTitle->getPartialURL() );
+       }
+
+       function showEmailUser( $id ) {
+               global $wgEnableEmail, $wgEnableUserEmail, $wgUser;
+               return $wgEnableEmail &&
+                      $wgEnableUserEmail &&
+                      $wgUser->isLoggedIn() && # show only to signed in users
+                      0 != $id; # we can only email to non-anons ..
+#                     '' != $id->getEmail() && # who must have an email address stored ..
+#                     0 != $id->getEmailauthenticationtimestamp() && # .. which is authenticated
+#                     1 != $wgUser->getOption('disablemail'); # and not disabled
+       }
+
+       function emailUserLink() {
+               global $wgTitle;
+
+               return $this->makeKnownLinkObj( Title::makeTitle( NS_SPECIAL, 'Emailuser' ),
+                 wfMsg( 'emailuser' ), 'target=' . $wgTitle->getPartialURL() );
+       }
+
+       function watchPageLinksLink() {
+               global $wgOut, $wgTitle;
+
+               if ( ! $wgOut->isArticleRelated() ) {
+                       return '(' . wfMsg( 'notanarticle' ) . ')';
+               } else {
+                       return $this->makeKnownLinkObj( Title::makeTitle( NS_SPECIAL,
+                         'Recentchangeslinked' ), wfMsg( 'recentchangeslinked' ),
+                         'target=' . $wgTitle->getPrefixedURL() );
+               }
+       }
+
+       function trackbackLink() {
+               global $wgTitle;
+
+               return "<a href=\"" . $wgTitle->trackbackURL() . "\">"
+                       . wfMsg('trackbacklink') . "</a>";
+       }
+
+       function otherLanguages() {
+               global $wgOut, $wgContLang, $wgTitle, $wgHideInterlanguageLinks;
+
+               if ( $wgHideInterlanguageLinks ) {
+                       return '';
+               }
+
+               $a = $wgOut->getLanguageLinks();
+               if ( 0 == count( $a ) ) {
+                       return '';
+               }
+
+               $s = wfMsg( 'otherlanguages' ) . ': ';
+               $first = true;
+               if($wgContLang->isRTL()) $s .= '<span dir="LTR">';
+               foreach( $a as $l ) {
+                       if ( ! $first ) { $s .= ' | '; }
+                       $first = false;
+
+                       $nt = Title::newFromText( $l );
+                       $url = $nt->escapeFullURL();
+                       $text = $wgContLang->getLanguageName( $nt->getInterwiki() );
+
+                       if ( '' == $text ) { $text = $l; }
+                       $style = $this->getExternalLinkAttributes( $l, $text );
+                       $s .= "<a href=\"{$url}\"{$style}>{$text}</a>";
+               }
+               if($wgContLang->isRTL()) $s .= '</span>';
+               return $s;
+       }
+
+       function bugReportsLink() {
+               $s = $this->makeKnownLink( wfMsgForContent( 'bugreportspage' ),
+                 wfMsg( 'bugreports' ) );
+               return $s;
+       }
+
+       function dateLink() {
+               global $wgLinkCache;
+               $t1 = Title::newFromText( gmdate( 'F j' ) );
+               $t2 = Title::newFromText( gmdate( 'Y' ) );
+
+               $wgLinkCache->suspend();
+               $id = $t1->getArticleID();
+               $wgLinkCache->resume();
+
+               if ( 0 == $id ) {
+                       $s = $this->makeBrokenLink( $t1->getText() );
+               } else {
+                       $s = $this->makeKnownLink( $t1->getText() );
+               }
+               $s .= ', ';
+
+               $wgLinkCache->suspend();
+               $id = $t2->getArticleID();
+               $wgLinkCache->resume();
+
+               if ( 0 == $id ) {
+                       $s .= $this->makeBrokenLink( $t2->getText() );
+               } else {
+                       $s .= $this->makeKnownLink( $t2->getText() );
+               }
+               return $s;
+       }
+
+       function talkLink() {
+               global $wgTitle, $wgLinkCache;
+
+               if ( NS_SPECIAL == $wgTitle->getNamespace() ) {
+                       # No discussion links for special pages
+                       return '';
+               }
+
+               if( $wgTitle->isTalkPage() ) {
+                       $link = $wgTitle->getSubjectPage();
+                       switch( $link->getNamespace() ) {
+                       case NS_MAIN:
+                               $text = wfMsg('articlepage');
+                               break;
+                       case NS_USER:
+                               $text = wfMsg('userpage');
+                               break;
+                       case NS_PROJECT:
+                               $text = wfMsg('wikipediapage');
+                               break;
+                       case NS_IMAGE:
+                               $text = wfMsg('imagepage');
+                               break;
+                       default:
+                               $text= wfMsg('articlepage');
+                       }
+               } else {
+                       $link = $wgTitle->getTalkPage();
+                       $text = wfMsg( 'talkpage' );
+               }
+
+               $wgLinkCache->suspend();
+               $s = $this->makeLinkObj( $link, $text );
+               $wgLinkCache->resume();
+
+               return $s;
+       }
+
+       function commentLink() {
+               global $wgContLang, $wgTitle, $wgLinkCache;
+
+               if ( $wgTitle->getNamespace() == NS_SPECIAL ) {
+                       return '';
+               }
+               return $this->makeKnownLinkObj( $wgTitle->getTalkPage(),
+                       wfMsg( 'postcomment' ), 'action=edit&section=new' );
+       }
+
+       /* these are used extensively in SkinPHPTal, but also some other places */
+       /*static*/ function makeSpecialUrl( $name, $urlaction='' ) {
+               $title = Title::makeTitle( NS_SPECIAL, $name );
+               return $title->getLocalURL( $urlaction );
+       }
+
+       /*static*/ function makeI18nUrl ( $name, $urlaction='' ) {
+               $title = Title::newFromText( wfMsgForContent($name) );
+               $this->checkTitle($title, $name);
+               return $title->getLocalURL( $urlaction );
+       }
+
+       /*static*/ function makeUrl ( $name, $urlaction='' ) {
+               $title = Title::newFromText( $name );
+               $this->checkTitle($title, $name);
+               return $title->getLocalURL( $urlaction );
+       }
+
+       # If url string starts with http, consider as external URL, else
+       # internal
+       /*static*/ function makeInternalOrExternalUrl( $name ) {
+               global $wgUrlProtocols;
+               if ( preg_match( '/^(?:' . $wgUrlProtocols . ')/', $name ) ) {
+                       return $name;
+               } else {
+                       return $this->makeUrl( $name );
+               }
+       }
+
+       # this can be passed the NS number as defined in Language.php
+       /*static*/ function makeNSUrl( $name, $urlaction='', $namespace=NS_MAIN ) {
+               $title = Title::makeTitleSafe( $namespace, $name );
+               $this->checkTitle($title, $name);
+               return $title->getLocalURL( $urlaction );
+       }
+
+       /* these return an array with the 'href' and boolean 'exists' */
+       /*static*/ function makeUrlDetails ( $name, $urlaction='' ) {
+               $title = Title::newFromText( $name );
+               $this->checkTitle($title, $name);
+               return array(
+                       'href' => $title->getLocalURL( $urlaction ),
+                       'exists' => $title->getArticleID() != 0?true:false
+               );
+       }
+
+       # make sure we have some title to operate on
+       /*static*/ function checkTitle ( &$title, &$name ) {
+               if(!is_object($title)) {
+                       $title = Title::newFromText( $name );
+                       if(!is_object($title)) {
+                               $title = Title::newFromText( '--error: link target missing--' );
+                       }
+               }
+       }
+
+       /**
+        * Build an array that represents the sidebar(s), the navigation bar among them
+        *
+        * @return array
+        * @access private
+        */
+       function buildSidebar() {
+               $fname = 'SkinTemplate::buildSidebar';
+               wfProfileIn( $fname );
+
+               $bar = array();
+               $lines = explode( "\n", wfMsgForContent( 'sidebar' ) );
+               foreach ($lines as $line) {
+                       if (strpos($line, '*') !== 0)
+                               continue;
+                       if (strpos($line, '**') !== 0) {
+                               $line = trim($line, '* ');
+                               $heading = $line;
+                       } else {
+                               if (strpos($line, '|') !== false) { // sanity check
+                                       $line = explode( '|' , trim($line, '* '), 2 );
+                                       $link = wfMsgForContent( $line[0] );
+                                       if ($link == '-')
+                                               continue;
+                                       if (wfNoMsg($line[1], $text = wfMsg($line[1])))
+                                               $text = $line[1];
+                                       if (wfNoMsg($line[0], $link))
+                                               $link = $line[0];
+                                       $bar[$heading][] = array(
+                                               'text' => $text,
+                                               'href' => $this->makeInternalOrExternalUrl( $link ),
+                                               'id' => 'n-' . strtr($line[1], ' ', '-'),
+                                       );
+                               } else { continue; }
+                       }
+               }
+
+               wfProfileOut( $fname );
+               return $bar;
+       }
+}
+
+}
+?>
diff --git a/includes/SkinPHPTal.php b/includes/SkinPHPTal.php
new file mode 100644 (file)
index 0000000..3efb2e3
--- /dev/null
@@ -0,0 +1,155 @@
+<?php
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# http://www.gnu.org/copyleft/gpl.html
+
+/**
+ * Generic PHPTal (http://phptal.sourceforge.net/) skin
+ * Based on Brion's smarty skin
+ * Copyright (C) Gabriel Wicke -- http://www.aulinx.de/
+ *
+ * The guts of this have moved to SkinTemplate.php
+ *
+ * Make sure the appropriate version of PHPTAL is installed (0.7.0 for PHP4,
+ * or 1.0.0 for PHP5) and available in the include_path. The system PEAR
+ * directory is good.
+ *
+ * If PEAR or PHPTAL can't be loaded, it will try to gracefully fall back.
+ * Turn on MediaWiki's debug log to see it complain.
+ *
+ * @package MediaWiki
+ * @subpackage Skins
+ */
+
+/**
+ * This is not a valid entry point, perform no further processing unless
+ * MEDIAWIKI is defined
+ */
+if( defined( 'MEDIAWIKI' ) ) {
+
+require_once 'GlobalFunctions.php';
+require_once 'SkinTemplate.php';
+
+if( version_compare( phpversion(), "5.0", "lt" ) ) {
+       define( 'OLD_PHPTAL', true );
+       # PEAR and PHPTAL 0.7.x must be installed and in include_path
+} else {
+       define( 'NEW_PHPTAL', true );
+       # PEAR and PHPTAL 1.0.x must be installed and in include_path
+}
+
+@include_once 'PEAR.php';
+if( !class_exists( 'PEAR' ) ) {
+       wfDebug( 'PHPTAL-based skin couldn\'t include PEAR.php' );
+} else {
+
+// PHPTAL may be in the libs dir direct, or under HTML/Template.
+// Try them both to be safe.
+@include_once 'HTML/Template/PHPTAL.php';
+if( !class_exists( 'PHPTAL' ) ) {
+       @include_once 'PHPTAL.php';
+}
+
+if( !class_exists( 'PHPTAL' ) ) {
+       wfDebug( 'PHPTAL-based skin couldn\'t include PHPTAL.php' );
+} else {
+
+/**
+ *
+ * @package MediaWiki
+ */
+class SkinPHPTal extends SkinTemplate {
+       /** */
+       function initPage( &$out ) {
+               parent::initPage( $out );
+               $this->skinname  = 'monobook';
+               $this->stylename = 'monobook';
+               $this->template  = 'MonoBook';
+       }
+
+       /**
+        * If using PHPTAL 0.7 on PHP 4.x, return a PHPTAL template object.
+        * If using PHPTAL 1.0 on PHP 5.x, return a bridge object.
+        * @return object
+        * @access private
+        */
+       function &setupTemplate( $file, $repository=false, $cache_dir=false ) {
+               if( defined( 'NEW_PHPTAL' ) ) {
+                       return new PHPTAL_version_bridge( $file . '.pt', $repository, $cache_dir );
+               } else {
+                       return new PHPTAL( $file . '.pt', $repository, $cache_dir );
+               }
+       }
+       
+       /**
+        * Output the string, or print error message if it's
+        * an error object of the appropriate type.
+        *
+        * @param mixed $str
+        * @access private
+        */
+       function printOrError( &$str ) {
+               if( PEAR::isError( $str ) ) {
+                       echo $str->toString(), "\n";
+               } else {
+                       echo $str;
+               }
+       }
+}
+
+/**
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Skins
+ */
+class PHPTAL_version_bridge {
+       function PHPTAL_version_bridge( $file, $repository=false, $cache_dir=false ) {
+               $this->tpl =& new PHPTAL( $file );
+               if( $repository ) {
+                       $this->tpl->setTemplateRepository( $repository );
+               }
+       }
+       
+       function set( $name, $value ) {
+               $this->tpl->$name = $value;
+       }
+       
+       function setRef($name, &$value) {
+               $this->set( $name, $value );
+       }
+       
+       function setTranslator( &$t ) {
+               $this->tpl->setTranslator( $t );
+       }
+       
+       function execute() {
+               /*
+               try {
+               */
+                       return $this->tpl->execute();
+               /*
+               }
+               catch (Exception $e) {
+                       echo "<div class='error' style='background: white; white-space: pre; position: absolute; z-index: 9999; border: solid 2px black; padding: 4px;'>We caught an exception...\n ";
+                       echo $e;
+                       echo "</div>";
+               }
+               */
+       }
+}
+
+} // end of if( class_exists( 'PHPTAL' ) )
+} // end of if( class_exists( 'PEAR' ) )
+} // end of if( defined( 'MEDIAWIKI' ) ) 
+?>
diff --git a/includes/SkinTemplate.php b/includes/SkinTemplate.php
new file mode 100644 (file)
index 0000000..8b64960
--- /dev/null
@@ -0,0 +1,1076 @@
+<?php
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# http://www.gnu.org/copyleft/gpl.html
+
+/**
+ * Template-filler skin base class
+ * Formerly generic PHPTal (http://phptal.sourceforge.net/) skin
+ * Based on Brion's smarty skin
+ * Copyright (C) Gabriel Wicke -- http://www.aulinx.de/
+ *
+ * Todo: Needs some serious refactoring into functions that correspond
+ * to the computations individual esi snippets need. Most importantly no body
+ * parsing for most of those of course.
+ *
+ * PHPTAL support has been moved to a subclass in SkinPHPTal.php,
+ * and is optional. You'll need to install PHPTAL manually to use
+ * skins that depend on it.
+ *
+ * @package MediaWiki
+ * @subpackage Skins
+ */
+
+/**
+ * This is not a valid entry point, perform no further processing unless
+ * MEDIAWIKI is defined
+ */
+if( defined( 'MEDIAWIKI' ) ) {
+
+require_once 'GlobalFunctions.php';
+
+/**
+ * Wrapper object for MediaWiki's localization functions,
+ * to be passed to the template engine.
+ *
+ * @access private
+ * @package MediaWiki
+ */
+class MediaWiki_I18N {
+       var $_context = array();
+
+       function set($varName, $value) {
+               $this->_context[$varName] = $value;
+       }
+
+       function translate($value) {
+               $fname = 'SkinTemplate-translate';
+               wfProfileIn( $fname );
+
+               // Hack for i18n:attributes in PHPTAL 1.0.0 dev version as of 2004-10-23
+               $value = preg_replace( '/^string:/', '', $value );
+
+               $value = wfMsg( $value );
+               // interpolate variables
+               while (preg_match('/\$([0-9]*?)/sm', $value, $m)) {
+                       list($src, $var) = $m;
+                       wfSuppressWarnings();
+                       $varValue = $this->_context[$var];
+                       wfRestoreWarnings();
+                       $value = str_replace($src, $varValue, $value);
+               }
+               wfProfileOut( $fname );
+               return $value;
+       }
+}
+
+/**
+ *
+ * @package MediaWiki
+ */
+class SkinTemplate extends Skin {
+       /**#@+
+        * @access private
+        */
+
+       /**
+        * Name of our skin, set in initPage()
+        * It probably need to be all lower case.
+        */
+       var $skinname;
+
+       /**
+        * Stylesheets set to use
+        * Sub directory in ./skins/ where various stylesheets are located
+        */
+       var $stylename;
+
+       /**
+        * For QuickTemplate, the name of the subclass which
+        * will actually fill the template.
+        *
+        * In PHPTal mode, name of PHPTal template to be used.
+        * '.pt' will be automaticly added to it on PHPTAL object creation
+        */
+       var $template;
+
+       /**#@-*/
+
+       /**
+        * Setup the base parameters...
+        * Child classes should override this to set the name,
+        * style subdirectory, and template filler callback.
+        *
+        * @param OutputPage $out
+        */
+       function initPage( &$out ) {
+               parent::initPage( $out );
+               $this->skinname  = 'monobook';
+               $this->stylename = 'monobook';
+               $this->template  = 'QuickTemplate';
+       }
+
+       /**
+        * Create the template engine object; we feed it a bunch of data
+        * and eventually it spits out some HTML. Should have interface
+        * roughly equivalent to PHPTAL 0.7.
+        *
+        * @param string $callback (or file)
+        * @param string $repository subdirectory where we keep template files
+        * @param string $cache_dir
+        * @return object
+        * @access private
+        */
+       function setupTemplate( $classname, $repository=false, $cache_dir=false ) {
+               return new $classname();
+       }
+
+       /**
+        * initialize various variables and generate the template
+        *
+        * @param OutputPage $out
+        * @access public
+        */
+       function outputPage( &$out ) {
+               global $wgTitle, $wgArticle, $wgUser, $wgLang, $wgContLang, $wgOut;
+               global $wgScript, $wgStylePath, $wgLanguageCode, $wgContLanguageCode, $wgUseNewInterlanguage;
+               global $wgMimeType, $wgJsMimeType, $wgOutputEncoding, $wgUseDatabaseMessages, $wgRequest;
+               global $wgDisableCounters, $wgLogo, $action, $wgFeedClasses, $wgHideInterlanguageLinks;
+               global $wgMaxCredits, $wgShowCreditsIfMax;
+               global $wgPageShowWatchingUsers;
+               global $wgUseTrackbacks;
+               global $wgDBname;
+
+               $fname = 'SkinTemplate::outputPage';
+               wfProfileIn( $fname );
+
+               extract( $wgRequest->getValues( 'oldid', 'diff' ) );
+
+               wfProfileIn( "$fname-init" );
+               $this->initPage( $out );
+
+               $this->mTitle =& $wgTitle;
+               $this->mUser =& $wgUser;
+
+               $tpl = $this->setupTemplate( $this->template, 'skins' );
+
+               #if ( $wgUseDatabaseMessages ) { // uncomment this to fall back to GetText
+               $tpl->setTranslator(new MediaWiki_I18N());
+               #}
+               wfProfileOut( "$fname-init" );
+
+               wfProfileIn( "$fname-stuff" );
+               $this->thispage = $this->mTitle->getPrefixedDbKey();
+               $this->thisurl = $this->mTitle->getPrefixedURL();
+               $this->loggedin = $wgUser->isLoggedIn();
+               $this->iscontent = ($this->mTitle->getNamespace() != NS_SPECIAL );
+               $this->iseditable = ($this->iscontent and !($action == 'edit' or $action == 'submit'));
+               $this->username = $wgUser->getName();
+               $userPage = $wgUser->getUserPage();
+               $this->userpage = $userPage->getPrefixedText();
+               $this->userpageUrlDetails = $this->makeUrlDetails($this->userpage);
+
+               $this->usercss =  $this->userjs = $this->userjsprev = false;
+               $this->setupUserCss();
+               $this->setupUserJs();
+               $this->titletxt = $this->mTitle->getPrefixedText();
+               wfProfileOut( "$fname-stuff" );
+
+               wfProfileIn( "$fname-stuff2" );
+               $tpl->set( 'title', $wgOut->getPageTitle() );
+               $tpl->set( 'pagetitle', $wgOut->getHTMLTitle() );
+
+               $tpl->setRef( "thispage", $this->thispage );
+               $subpagestr = $this->subPageSubtitle();
+               $tpl->set(
+                       'subtitle',  !empty($subpagestr)?
+                       '<span class="subpages">'.$subpagestr.'</span>'.$out->getSubtitle():
+                       $out->getSubtitle()
+               );
+               $undelete = $this->getUndeleteLink();
+               $tpl->set(
+                       "undelete", !empty($undelete)?
+                       '<span class="subpages">'.$undelete.'</span>':
+                       ''
+               );
+
+               $tpl->set( 'catlinks', $this->getCategories());
+               if( $wgOut->isSyndicated() ) {
+                       $feeds = array();
+                       foreach( $wgFeedClasses as $format => $class ) {
+                               $feeds[$format] = array(
+                                       'text' => $format,
+                                       'href' => $wgRequest->appendQuery( "feed=$format" ),
+                                       'ttip' => wfMsg('tooltip-'.$format)
+                               );
+                       }
+                       $tpl->setRef( 'feeds', $feeds );
+               } else {
+                       $tpl->set( 'feeds', false );
+               }
+               if ($wgUseTrackbacks && $out->isArticleRelated())
+                       $tpl->set( 'trackbackhtml', $wgTitle->trackbackRDF());
+
+               $tpl->setRef( 'mimetype', $wgMimeType );
+               $tpl->setRef( 'jsmimetype', $wgJsMimeType );
+               $tpl->setRef( 'charset', $wgOutputEncoding );
+               $tpl->set( 'headlinks', $out->getHeadLinks() );
+               $tpl->set('headscripts', $out->getScript() );
+               $tpl->setRef( 'wgScript', $wgScript );
+               $tpl->setRef( 'skinname', $this->skinname );
+               $tpl->setRef( 'stylename', $this->stylename );
+               $tpl->set( 'printable', $wgRequest->getBool( 'printable' ) );
+               $tpl->setRef( 'loggedin', $this->loggedin );
+               $tpl->set('nsclass', 'ns-'.$this->mTitle->getNamespace());
+               $tpl->set('notspecialpage', $this->mTitle->getNamespace() != NS_SPECIAL);
+               /* XXX currently unused, might get useful later
+               $tpl->set( "editable", ($this->mTitle->getNamespace() != NS_SPECIAL ) );
+               $tpl->set( "exists", $this->mTitle->getArticleID() != 0 );
+               $tpl->set( "watch", $this->mTitle->userIsWatching() ? "unwatch" : "watch" );
+               $tpl->set( "protect", count($this->mTitle->isProtected()) ? "unprotect" : "protect" );
+               $tpl->set( "helppage", wfMsg('helppage'));
+               */
+               $tpl->set( 'searchaction', $this->escapeSearchLink() );
+               $tpl->set( 'search', trim( $wgRequest->getVal( 'search' ) ) );
+               $tpl->setRef( 'stylepath', $wgStylePath );
+               $tpl->setRef( 'logopath', $wgLogo );
+               $tpl->setRef( "lang", $wgContLanguageCode );
+               $tpl->set( 'dir', $wgContLang->isRTL() ? "rtl" : "ltr" );
+               $tpl->set( 'rtl', $wgContLang->isRTL() );
+               $tpl->set( 'langname', $wgContLang->getLanguageName( $wgContLanguageCode ) );
+               $tpl->setRef( 'username', $this->username );
+               $tpl->setRef( 'userpage', $this->userpage);
+               $tpl->setRef( 'userpageurl', $this->userpageUrlDetails['href']);
+               $tpl->setRef( 'usercss', $this->usercss);
+               $tpl->setRef( 'userjs', $this->userjs);
+               $tpl->setRef( 'userjsprev', $this->userjsprev);
+               global $wgUseSiteJs;
+               if ($wgUseSiteJs) {
+                       if($this->loggedin) {
+                               $tpl->set( 'jsvarurl', $this->makeUrl('-','action=raw&smaxage=0&gen=js') );
+                       } else {
+                               $tpl->set( 'jsvarurl', $this->makeUrl('-','action=raw&gen=js') );
+                       }
+               } else {
+                       $tpl->set('jsvarurl', false);
+               }
+               $newtalks = $wgUser->getNewMessageLinks();
+
+               if (count($newtalks) == 1 && $newtalks[0]["wiki"] === $wgDBname) {
+                       $usertitle = $this->mUser->getUserPage();
+                       $usertalktitle = $usertitle->getTalkPage();
+                       if( !$usertalktitle->equals( $this->mTitle ) ) {
+                               $ntl = wfMsg( 'newmessages',
+                                       $this->makeKnownLinkObj(
+                                               $usertalktitle,
+                                               wfMsg('newmessageslink')
+                                       )
+                               );
+                               # Disable Cache
+                               $wgOut->setSquidMaxage(0);
+                       }
+               } else if (count($newtalks)) {
+                       $sep = str_replace("_", " ", wfMsgHtml("newtalkseperator"));
+                       $msgs = array();
+                       foreach ($newtalks as $newtalk) {
+                               $msgs[] = wfElement("a", 
+                                       array('href' => $newtalk["link"]), $newtalk["wiki"]);
+                       }
+                       $parts = implode($sep, $msgs);
+                       $ntl = wfMsgHtml('youhavenewmessagesmulti', $parts);
+                       $wgOut->setSquidMaxage(0);
+               } else {
+                       $ntl = '';
+               }
+               wfProfileOut( "$fname-stuff2" );
+
+               wfProfileIn( "$fname-stuff3" );
+               $tpl->setRef( 'newtalk', $ntl );
+               $tpl->setRef( 'skin', $this);
+               $tpl->set( 'logo', $this->logoText() );
+               if ( $wgOut->isArticle() and (!isset( $oldid ) or isset( $diff )) and 0 != $wgArticle->getID() ) {
+                       if ( !$wgDisableCounters ) {
+                               $viewcount = $wgLang->formatNum( $wgArticle->getCount() );
+                               if ( $viewcount ) {
+                                       $tpl->set('viewcount', wfMsg( "viewcount", $viewcount ));
+                               } else {
+                                       $tpl->set('viewcount', false);
+                               }
+                       } else {
+                               $tpl->set('viewcount', false);
+                       }
+
+                       if ($wgPageShowWatchingUsers) {
+                               $dbr =& wfGetDB( DB_SLAVE );
+                               extract( $dbr->tableNames( 'watchlist' ) );
+                               $sql = "SELECT COUNT(*) AS n FROM $watchlist
+                                       WHERE wl_title='" . $dbr->strencode($this->mTitle->getDBKey()) .
+                                       "' AND  wl_namespace=" . $this->mTitle->getNamespace() ;
+                               $res = $dbr->query( $sql, 'SkinPHPTal::outputPage');
+                               $x = $dbr->fetchObject( $res );
+                               $numberofwatchingusers = $x->n;
+                               if ($numberofwatchingusers > 0) {
+                                       $tpl->set('numberofwatchingusers', wfMsg('number_of_watching_users_pageview', $numberofwatchingusers));
+                               } else {
+                                       $tpl->set('numberofwatchingusers', false);
+                               }
+                       } else {
+                               $tpl->set('numberofwatchingusers', false);
+                       }
+
+                       $tpl->set('copyright',$this->getCopyright());
+
+                       $this->credits = false;
+
+                       if (isset($wgMaxCredits) && $wgMaxCredits != 0) {
+                               require_once("Credits.php");
+                               $this->credits = getCredits($wgArticle, $wgMaxCredits, $wgShowCreditsIfMax);
+                       } else {
+                               $tpl->set('lastmod', $this->lastModified());
+                       }
+
+                       $tpl->setRef( 'credits', $this->credits );
+
+               } elseif ( isset( $oldid ) && !isset( $diff ) ) {
+                       $tpl->set('copyright', $this->getCopyright());
+                       $tpl->set('viewcount', false);
+                       $tpl->set('lastmod', false);
+                       $tpl->set('credits', false);
+                       $tpl->set('numberofwatchingusers', false);
+               } else {
+                       $tpl->set('copyright', false);
+                       $tpl->set('viewcount', false);
+                       $tpl->set('lastmod', false);
+                       $tpl->set('credits', false);
+                       $tpl->set('numberofwatchingusers', false);
+               }
+               wfProfileOut( "$fname-stuff3" );
+
+               wfProfileIn( "$fname-stuff4" );
+               $tpl->set( 'copyrightico', $this->getCopyrightIcon() );
+               $tpl->set( 'poweredbyico', $this->getPoweredBy() );
+               $tpl->set( 'disclaimer', $this->disclaimerLink() );
+               $tpl->set( 'about', $this->aboutLink() );
+
+               $tpl->setRef( 'debug', $out->mDebugtext );
+               $tpl->set( 'reporttime', $out->reportTime() );
+               $tpl->set( 'sitenotice', wfGetSiteNotice() );
+
+               $printfooter = "<div class=\"printfooter\">\n" . $this->printSource() . "</div>\n";
+               $out->mBodytext .= $printfooter ;
+               $tpl->setRef( 'bodytext', $out->mBodytext );
+
+               # Language links
+               $language_urls = array();
+
+               if ( !$wgHideInterlanguageLinks ) {
+                       foreach( $wgOut->getLanguageLinks() as $l ) {
+                               $tmp = explode( ':', $l, 2 );
+                               $class = 'interwiki-' . $tmp[0];
+                               unset($tmp);
+                               $nt = Title::newFromText( $l );
+                               $language_urls[] = array(
+                                       'href' => $nt->getFullURL(),
+                                       'text' => ($wgContLang->getLanguageName( $nt->getInterwiki()) != ''?$wgContLang->getLanguageName( $nt->getInterwiki()) : $l),
+                                       'class' => $class
+                               );
+                       }
+               }
+               if(count($language_urls)) {
+                       $tpl->setRef( 'language_urls', $language_urls);
+               } else {
+                       $tpl->set('language_urls', false);
+               }
+               wfProfileOut( "$fname-stuff4" );
+
+               # Personal toolbar
+               $tpl->set('personal_urls', $this->buildPersonalUrls());
+               $content_actions = $this->buildContentActionUrls();
+               $tpl->setRef('content_actions', $content_actions);
+
+               // XXX: attach this from javascript, same with section editing
+               if($this->iseditable && $wgUser->getOption("editondblclick") )
+               {
+                       $tpl->set('body_ondblclick', 'document.location = "' .$content_actions['edit']['href'] .'";');
+               } else {
+                       $tpl->set('body_ondblclick', false);
+               }
+               if( $this->iseditable && $wgUser->getOption( 'editsectiononrightclick' ) ) {
+                       $tpl->set( 'body_onload', 'setupRightClickEdit()' );
+               } else {
+                       $tpl->set( 'body_onload', false );
+               }
+               $tpl->set( 'sidebar', $this->buildSidebar() );
+               $tpl->set( 'nav_urls', $this->buildNavUrls() );
+
+               // execute template
+               wfProfileIn( "$fname-execute" );
+               $res = $tpl->execute();
+               wfProfileOut( "$fname-execute" );
+
+               // result may be an error
+               $this->printOrError( $res );
+               wfProfileOut( $fname );
+       }
+
+       /**
+        * Output the string, or print error message if it's
+        * an error object of the appropriate type.
+        * For the base class, assume strings all around.
+        *
+        * @param mixed $str
+        * @access private
+        */
+       function printOrError( &$str ) {
+               echo $str;
+       }
+
+       /**
+        * build array of urls for personal toolbar
+        * @return array
+        * @access private
+        */
+       function buildPersonalUrls() {
+               $fname = 'SkinTemplate::buildPersonalUrls';
+               wfProfileIn( $fname );
+
+               /* set up the default links for the personal toolbar */
+               global $wgShowIPinHeader;
+               $personal_urls = array();
+               if ($this->loggedin) {
+                       $personal_urls['userpage'] = array(
+                               'text' => $this->username,
+                               'href' => &$this->userpageUrlDetails['href'],
+                               'class' => $this->userpageUrlDetails['exists']?false:'new'
+                       );
+                       $usertalkUrlDetails = $this->makeTalkUrlDetails($this->userpage);
+                       $personal_urls['mytalk'] = array(
+                               'text' => wfMsg('mytalk'),
+                               'href' => &$usertalkUrlDetails['href'],
+                               'class' => $usertalkUrlDetails['exists']?false:'new'
+                       );
+                       $personal_urls['preferences'] = array(
+                               'text' => wfMsg('preferences'),
+                               'href' => $this->makeSpecialUrl('Preferences')
+                       );
+                       $personal_urls['watchlist'] = array(
+                               'text' => wfMsg('watchlist'),
+                               'href' => $this->makeSpecialUrl('Watchlist')
+                       );
+                       $personal_urls['mycontris'] = array(
+                               'text' => wfMsg('mycontris'),
+                               'href' => $this->makeSpecialUrl("Contributions/$this->username")
+                       );
+                       $personal_urls['logout'] = array(
+                               'text' => wfMsg('userlogout'),
+                               'href' => $this->makeSpecialUrl('Userlogout','returnto=' . $this->thisurl )
+                       );
+               } else {
+                       if( $wgShowIPinHeader && isset(  $_COOKIE[ini_get("session.name")] ) ) {
+                               $personal_urls['anonuserpage'] = array(
+                                       'text' => $this->username,
+                                       'href' => &$this->userpageUrlDetails['href'],
+                                       'class' => $this->userpageUrlDetails['exists']?false:'new'
+                               );
+                               $usertalkUrlDetails = $this->makeTalkUrlDetails($this->userpage);
+                               $personal_urls['anontalk'] = array(
+                                       'text' => wfMsg('anontalk'),
+                                       'href' => &$usertalkUrlDetails['href'],
+                                       'class' => $usertalkUrlDetails['exists']?false:'new'
+                               );
+                               $personal_urls['anonlogin'] = array(
+                                       'text' => wfMsg('userlogin'),
+                                       'href' => $this->makeSpecialUrl('Userlogin', 'returnto=' . $this->thisurl )
+                               );
+                       } else {
+
+                               $personal_urls['login'] = array(
+                                       'text' => wfMsg('userlogin'),
+                                       'href' => $this->makeSpecialUrl('Userlogin', 'returnto=' . $this->thisurl )
+                               );
+                       }
+               }
+               wfProfileOut( $fname );
+               return $personal_urls;
+       }
+
+
+       function tabAction( $title, $message, $selected, $query='', $checkEdit=false ) {
+               $classes = array();
+               if( $selected ) {
+                       $classes[] = 'selected';
+               }
+               if( $checkEdit && $title->getArticleId() == 0 ) {
+                       $classes[] = 'new';
+                       $query = 'action=edit';
+               }
+               return array(
+                       'class' => implode( ' ', $classes ),
+                       'text' => wfMsg( $message ),
+                       'href' => $title->getLocalUrl( $query ) );
+       }
+
+       function makeTalkUrlDetails( $name, $urlaction='' ) {
+               $title = Title::newFromText( $name );
+               $title = $title->getTalkPage();
+               $this->checkTitle($title, $name);
+               return array(
+                       'href' => $title->getLocalURL( $urlaction ),
+                       'exists' => $title->getArticleID() != 0?true:false
+               );
+       }
+
+       function makeArticleUrlDetails( $name, $urlaction='' ) {
+               $title = Title::newFromText( $name );
+               $title= $title->getSubjectPage();
+               $this->checkTitle($title, $name);
+               return array(
+                       'href' => $title->getLocalURL( $urlaction ),
+                       'exists' => $title->getArticleID() != 0?true:false
+               );
+       }
+
+       /**
+        * an array of edit links by default used for the tabs
+        * @return array
+        * @access private
+        */
+       function buildContentActionUrls () {
+               global $wgContLang, $wgUseValidation, $wgDBprefix, $wgValidationForAnons;
+               $fname = 'SkinTemplate::buildContentActionUrls';
+               wfProfileIn( $fname );
+
+               global $wgUser, $wgRequest;
+               $action = $wgRequest->getText( 'action' );
+               $section = $wgRequest->getText( 'section' );
+               $oldid = $wgRequest->getVal( 'oldid' );
+               $diff = $wgRequest->getVal( 'diff' );
+               $content_actions = array();
+
+               if( $this->iscontent ) {
+
+                       $nskey = $this->getNameSpaceKey();
+                       $content_actions[$nskey] = $this->tabAction(
+                               $this->mTitle->getSubjectPage(),
+                               $nskey,
+                               !$this->mTitle->isTalkPage(),
+                               '', true);
+
+                       $content_actions['talk'] = $this->tabAction(
+                               $this->mTitle->getTalkPage(),
+                               'talk',
+                               $this->mTitle->isTalkPage(),
+                               '',
+                               true);
+
+                       wfProfileIn( "$fname-edit" );
+                       if ( $this->mTitle->userCanEdit() ) {
+                               $oid = ( $oldid && ! isset( $diff ) ) ? '&oldid='.IntVal( $oldid ) : false;
+                               $istalk = $this->mTitle->isTalkPage();
+                               $istalkclass = $istalk?' istalk':'';
+                               $content_actions['edit'] = array(
+                                       'class' => ((($action == 'edit' or $action == 'submit') and $section != 'new') ? 'selected' : '').$istalkclass,
+                                       'text' => wfMsg('edit'),
+                                       'href' => $this->mTitle->getLocalUrl( 'action=edit'.$oid )
+                               );
+
+                               if ( $istalk ) {
+                                       $content_actions['addsection'] = array(
+                                               'class' => $section == 'new'?'selected':false,
+                                               'text' => wfMsg('addsection'),
+                                               'href' => $this->mTitle->getLocalUrl( 'action=edit&section=new' )
+                                       );
+                               }
+                       } else {
+                               $oid = ( $oldid && ! isset( $diff ) ) ? '&oldid='.IntVal( $oldid ) : '';
+                               $content_actions['viewsource'] = array(
+                                       'class' => ($action == 'edit') ? 'selected' : false,
+                                       'text' => wfMsg('viewsource'),
+                                       'href' => $this->mTitle->getLocalUrl( 'action=edit'.$oid )
+                               );
+                       }
+                       wfProfileOut( "$fname-edit" );
+
+                       wfProfileIn( "$fname-live" );
+                       if ( $this->mTitle->getArticleId() ) {
+
+                               $content_actions['history'] = array(
+                                       'class' => ($action == 'history') ? 'selected' : false,
+                                       'text' => wfMsg('history_short'),
+                                       'href' => $this->mTitle->getLocalUrl( 'action=history')
+                               );
+
+                               if($wgUser->isAllowed('protect')){
+                                       if(!$this->mTitle->isProtected()){
+                                               $content_actions['protect'] = array(
+                                                       'class' => ($action == 'protect') ? 'selected' : false,
+                                                       'text' => wfMsg('protect'),
+                                                       'href' => $this->mTitle->getLocalUrl( 'action=protect' )
+                                               );
+
+                                       } else {
+                                               $content_actions['unprotect'] = array(
+                                                       'class' => ($action == 'unprotect') ? 'selected' : false,
+                                                       'text' => wfMsg('unprotect'),
+                                                       'href' => $this->mTitle->getLocalUrl( 'action=unprotect' )
+                                               );
+                                       }
+                               }
+                               if($wgUser->isAllowed('delete')){
+                                       $content_actions['delete'] = array(
+                                               'class' => ($action == 'delete') ? 'selected' : false,
+                                               'text' => wfMsg('delete'),
+                                               'href' => $this->mTitle->getLocalUrl( 'action=delete' )
+                                       );
+                               }
+                               if ( $this->mTitle->userCanMove()) {
+                                       $content_actions['move'] = array(
+                                               'class' => ($this->mTitle->getDbKey() == 'Movepage' and $this->mTitle->getNamespace == NS_SPECIAL) ? 'selected' : false,
+                                               'text' => wfMsg('move'),
+                                               'href' => $this->makeSpecialUrl("Movepage/$this->thispage" )
+                                       );
+                               }
+                       } else {
+                               //article doesn't exist or is deleted
+                               if($wgUser->isAllowed('delete')){
+                                       if( $n = $this->mTitle->isDeleted() ) {
+                                               $content_actions['undelete'] = array(
+                                                       'class' => false,
+                                                       'text' => ($n == 1) ? wfMsg( 'undelete_short1' ) : wfMsg('undelete_short', $n ),
+                                                       'href' => $this->makeSpecialUrl("Undelete/$this->thispage")
+                                               );
+                                       }
+                               }
+                       }
+                       wfProfileOut( "$fname-live" );
+
+                       if( $this->loggedin ) {
+                               if( !$this->mTitle->userIsWatching()) {
+                                       $content_actions['watch'] = array(
+                                               'class' => ($action == 'watch' or $action == 'unwatch') ? 'selected' : false,
+                                               'text' => wfMsg('watch'),
+                                               'href' => $this->mTitle->getLocalUrl( 'action=watch' )
+                                       );
+                               } else {
+                                       $content_actions['unwatch'] = array(
+                                               'class' => ($action == 'unwatch' or $action == 'watch') ? 'selected' : false,
+                                               'text' => wfMsg('unwatch'),
+                                               'href' => $this->mTitle->getLocalUrl( 'action=unwatch' )
+                                       );
+                               }
+                       }
+
+                       if( $wgUser->isLoggedIn() || $wgValidationForAnons ) { # and $action != 'submit' ) {
+                               # Validate tab. TODO: add validation to logged-in user rights
+                               if($wgUseValidation && ( $action == "" || $action=='view' ) ){ # && $wgUser->isAllowed('validate')){
+                                       if ( $oldid ) $oid = IntVal( $oldid ) ; # Use the oldid
+                                       else
+                                               {# Trying to get the current article revision through this weird stunt
+                                               $tid = $this->mTitle->getArticleID();
+                                               $tns = $this->mTitle->getNamespace();
+                                               $sql = "SELECT page_latest FROM {$wgDBprefix}page WHERE page_id={$tid} AND page_namespace={$tns}" ;
+                                               $res = wfQuery( $sql, DB_READ );
+                                               if( $s = wfFetchObject( $res ) )
+                                                       $oid = $s->page_latest ;
+                                               else $oid = "" ; # Something's wrong, like the article has been deleted in the last 10 ns
+                                               }
+                                       if ( $oid != "" ) {
+                                               $oid = "&revision={$oid}" ;
+                                               $content_actions['validate'] = array(
+                                                       'class' => ($action == 'validate') ? 'selected' : false,
+                                                       'text' => wfMsg('val_tab'),
+                                                       'href' => $this->mTitle->getLocalUrl( "action=validate{$oid}" )
+                                                       );
+                                       }
+                               }
+                       }
+               } else {
+                       /* show special page tab */
+
+                       $content_actions['article'] = array(
+                               'class' => 'selected',
+                               'text' => wfMsg('specialpage'),
+                               'href' => $wgRequest->getRequestURL(), // @bug 2457, 2510
+                       );
+               }
+
+               /* show links to different language variants */
+               global $wgDisableLangConversion;
+               $variants = $wgContLang->getVariants();
+               if( !$wgDisableLangConversion && sizeof( $variants ) > 1 ) {
+                       $preferred = $wgContLang->getPreferredVariant();
+                       $actstr = '';
+                       if( $action )
+                               $actstr = 'action=' . $action . '&';
+                       $vcount=0;
+                       foreach( $variants as $code ) {
+                               $varname = $wgContLang->getVariantname( $code );
+                               if( $varname == 'disable' )
+                                       continue;
+                               $selected = ( $code == $preferred )? 'selected' : false;
+                               $content_actions['varlang-' . $vcount] = array(
+                                               'class' => $selected,
+                                               'text' => $varname,
+                                               'href' => $this->mTitle->getLocalUrl( $actstr . 'variant=' . $code )
+                                       );
+                               $vcount ++;
+                       }
+               }
+
+               wfRunHooks( 'SkinTemplateContentActions', array(&$content_actions) );
+               
+               wfProfileOut( $fname );
+               return $content_actions;
+       }
+
+
+
+       /**
+        * build array of common navigation links
+        * @return array
+        * @access private
+        */
+       function buildNavUrls () {
+               global $wgUseTrackbacks, $wgTitle;
+
+               $fname = 'SkinTemplate::buildNavUrls';
+               wfProfileIn( $fname );
+
+               global $wgUser, $wgRequest;
+               global $wgSiteSupportPage, $wgEnableUploads, $wgUploadNavigationUrl;
+
+               $action = $wgRequest->getText( 'action' );
+               $oldid = $wgRequest->getVal( 'oldid' );
+               $diff = $wgRequest->getVal( 'diff' );
+
+               $nav_urls = array();
+               $nav_urls['mainpage'] = array('href' => $this->makeI18nUrl('mainpage'));
+               $nav_urls['randompage'] = array('href' => $this->makeSpecialUrl('Random'));
+               $nav_urls['recentchanges'] = array('href' => $this->makeSpecialUrl('Recentchanges'));
+               $nav_urls['currentevents'] = (wfMsgForContent('currentevents') != '-') ? array('href' => $this->makeI18nUrl('currentevents')) : false;
+               $nav_urls['portal'] =  (wfMsgForContent('portal') != '-') ? array('href' => $this->makeI18nUrl('portal-url')) : false;
+               $nav_urls['bugreports'] = array('href' => $this->makeI18nUrl('bugreportspage'));
+               // $nav_urls['sitesupport'] = array('href' => $this->makeI18nUrl('sitesupportpage'));
+               $nav_urls['sitesupport'] = array('href' => $wgSiteSupportPage);
+               $nav_urls['help'] = array('href' => $this->makeI18nUrl('helppage'));
+               if( $wgEnableUploads ) {
+                       if ($wgUploadNavigationUrl) {
+                               $nav_urls['upload'] = array('href' => $wgUploadNavigationUrl );
+                       } else {
+                               $nav_urls['upload'] = array('href' => $this->makeSpecialUrl('Upload'));
+                       }
+               } else {
+                       $nav_urls['upload'] = false;
+               }
+               $nav_urls['specialpages'] = array('href' => $this->makeSpecialUrl('Specialpages'));
+
+
+               // A print stylesheet is attached to all pages, but nobody ever
+               // figures that out. :)  Add a link...
+               if( $this->iscontent && ($action == '' || $action == 'view' || $action == 'purge' ) ) {
+                       $nav_urls['print'] = array(
+                               'text' => wfMsg( 'printableversion' ),
+                               'href' => $wgRequest->appendQuery( 'printable=yes' ) );
+               }
+
+               if( $this->mTitle->getNamespace() != NS_SPECIAL) {
+                       $nav_urls['whatlinkshere'] = array(
+                               'href' => $this->makeSpecialUrl("Whatlinkshere/$this->thispage")
+                       );
+                       $nav_urls['recentchangeslinked'] = array(
+                               'href' => $this->makeSpecialUrl("Recentchangeslinked/$this->thispage")
+                       );
+                       if ($wgUseTrackbacks)
+                               $nav_urls['trackbacklink'] = array(
+                                       'href' => $wgTitle->trackbackURL()
+                               );
+               }
+
+               if( $this->mTitle->getNamespace() == NS_USER || $this->mTitle->getNamespace() == NS_USER_TALK ) {
+                       $id = User::idFromName($this->mTitle->getText());
+                       $ip = User::isIP($this->mTitle->getText());
+               } else {
+                       $id = 0;
+                       $ip = false;
+               }
+
+               if($id || $ip) { # both anons and non-anons have contri list
+                       $nav_urls['contributions'] = array(
+                               'href' => $this->makeSpecialUrl('Contributions/' . $this->mTitle->getText() )
+                       );
+               } else {
+                       $nav_urls['contributions'] = false;
+               }
+               $nav_urls['emailuser'] = false;
+               if( $this->showEmailUser( $id ) ) {
+                       $nav_urls['emailuser'] = array(
+                               'href' => $this->makeSpecialUrl('Emailuser/' . $this->mTitle->getText() )
+                       );
+               }
+               wfProfileOut( $fname );
+               return $nav_urls;
+       }
+
+       /**
+        * Generate strings used for xml 'id' names
+        * @return string
+        * @private
+        */
+       function getNameSpaceKey () {
+               switch ($this->mTitle->getNamespace()) {
+                       case NS_MAIN:
+                       case NS_TALK:
+                               return 'nstab-main';
+                       case NS_USER:
+                       case NS_USER_TALK:
+                               return 'nstab-user';
+                       case NS_MEDIA:
+                               return 'nstab-media';
+                       case NS_SPECIAL:
+                               return 'nstab-special';
+                       case NS_PROJECT:
+                       case NS_PROJECT_TALK:
+                               return 'nstab-wp';
+                       case NS_IMAGE:
+                       case NS_IMAGE_TALK:
+                               return 'nstab-image';
+                       case NS_MEDIAWIKI:
+                       case NS_MEDIAWIKI_TALK:
+                               return 'nstab-mediawiki';
+                       case NS_TEMPLATE:
+                       case NS_TEMPLATE_TALK:
+                               return 'nstab-template';
+                       case NS_HELP:
+                       case NS_HELP_TALK:
+                               return 'nstab-help';
+                       case NS_CATEGORY:
+                       case NS_CATEGORY_TALK:
+                               return 'nstab-category';
+                       default:
+                               return 'nstab-main';
+               }
+       }
+
+       /**
+        * @access private
+        */
+       function setupUserCss() {
+               $fname = 'SkinTemplate::setupUserCss';
+               wfProfileIn( $fname );
+
+               global $wgRequest, $wgAllowUserCss, $wgUseSiteCss, $wgContLang, $wgSquidMaxage, $wgStylePath, $wgUser;
+
+               $sitecss = '';
+               $usercss = '';
+               $siteargs = '&maxage=' . $wgSquidMaxage;
+
+               # Add user-specific code if this is a user and we allow that kind of thing
+
+               if ( $wgAllowUserCss && $this->loggedin ) {
+                       $action = $wgRequest->getText('action');
+
+                       # if we're previewing the CSS page, use it
+                       if( $this->mTitle->isCssSubpage() and $this->userCanPreview( $action ) ) {
+                               $siteargs = "&smaxage=0&maxage=0";
+                               $usercss = $wgRequest->getText('wpTextbox1');
+                       } else {
+                               $usercss = '@import "' .
+                                 $this->makeUrl($this->userpage . '/'.$this->skinname.'.css',
+                                                                'action=raw&ctype=text/css') . '";' ."\n";
+                       }
+
+                       $siteargs .= '&ts=' . $wgUser->mTouched;
+               }
+
+               if ($wgContLang->isRTL()) $sitecss .= '@import "' . $wgStylePath . '/' . $this->stylename . '/rtl.css";' . "\n";
+
+               # If we use the site's dynamic CSS, throw that in, too
+               if ( $wgUseSiteCss ) {
+                       $sitecss .= '@import "' . $this->makeNSUrl(ucfirst($this->skinname) . '.css', 'action=raw&ctype=text/css&smaxage=' . $wgSquidMaxage, NS_MEDIAWIKI) . '";' . "\n";
+                       $sitecss .= '@import "' . $this->makeUrl('-','action=raw&gen=css' . $siteargs) . '";' . "\n";
+               }
+
+               # If we use any dynamic CSS, make a little CDATA block out of it.
+
+               if ( !empty($sitecss) || !empty($usercss) ) {
+                       $this->usercss = "/*<![CDATA[*/\n" . $sitecss . $usercss . '/*]]>*/';
+               }
+               wfProfileOut( $fname );
+       }
+
+       /**
+        * @access private
+        */
+       function setupUserJs() {
+               $fname = 'SkinTemplate::setupUserJs';
+               wfProfileIn( $fname );
+
+               global $wgRequest, $wgAllowUserJs, $wgJsMimeType;
+               $action = $wgRequest->getText('action');
+
+               if( $wgAllowUserJs && $this->loggedin ) {
+                       if( $this->mTitle->isJsSubpage() and $this->userCanPreview( $action ) ) {
+                               # XXX: additional security check/prompt?
+                               $this->userjsprev = '/*<![CDATA[*/ ' . $wgRequest->getText('wpTextbox1') . ' /*]]>*/';
+                       } else {
+                               $this->userjs = $this->makeUrl($this->userpage.'/'.$this->skinname.'.js', 'action=raw&ctype='.$wgJsMimeType.'&dontcountme=s');
+                       }
+               }
+               wfProfileOut( $fname );
+       }
+
+       /**
+        * returns css with user-specific options
+        * @access public
+        */
+
+       function getUserStylesheet() {
+               $fname = 'SkinTemplate::getUserStylesheet';
+               wfProfileIn( $fname );
+
+               global $wgUser;
+               $s = "/* generated user stylesheet */\n";
+               $s .= $this->reallyDoGetUserStyles();
+               wfProfileOut( $fname );
+               return $s;
+       }
+
+       /**
+        * @access public
+        */
+       function getUserJs() {
+               $fname = 'SkinTemplate::getUserJs';
+               wfProfileIn( $fname );
+
+               global $wgStylePath;
+               $s = '/* generated javascript */';
+               $s .= "var skin = '{$this->skinname}';\nvar stylepath = '{$wgStylePath}';";
+               $s .= '/* MediaWiki:'.ucfirst($this->skinname)." */\n";
+
+               // avoid inclusion of non defined user JavaScript (with custom skins only)
+               // by checking for default message content
+               $msgKey = ucfirst($this->skinname).'.js';
+               $userJS = wfMsg($msgKey);
+               if ('&lt;'.$msgKey.'&gt;' != $userJS) {
+                       $s .= $userJS;
+               }
+
+               wfProfileOut( $fname );
+               return $s;
+       }
+}
+
+/**
+ * Generic wrapper for template functions, with interface
+ * compatible with what we use of PHPTAL 0.7.
+ * @package MediaWiki
+ * @subpackage Skins
+ */
+class QuickTemplate {
+       /**
+        * @access public
+        */
+       function QuickTemplate() {
+               $this->data = array();
+               $this->translator = new MediaWiki_I18N();
+       }
+
+       /**
+        * @access public
+        */
+       function set( $name, $value ) {
+               $this->data[$name] = $value;
+       }
+
+       /**
+        * @access public
+        */
+       function setRef($name, &$value) {
+               $this->data[$name] =& $value;
+       }
+
+       /**
+        * @access public
+        */
+       function setTranslator( &$t ) {
+               $this->translator = &$t;
+       }
+
+       /**
+        * @access public
+        */
+       function execute() {
+               echo "Override this function.";
+       }
+
+
+       /**
+        * @access private
+        */
+       function text( $str ) {
+               echo htmlspecialchars( $this->data[$str] );
+       }
+
+       /**
+        * @access private
+        */
+       function html( $str ) {
+               echo $this->data[$str];
+       }
+
+       /**
+        * @access private
+        */
+       function msg( $str ) {
+               echo htmlspecialchars( $this->translator->translate( $str ) );
+       }
+
+       /**
+        * @access private
+        */
+       function msgHtml( $str ) {
+               echo $this->translator->translate( $str );
+       }
+
+       /**
+        * An ugly, ugly hack.
+        * @access private
+        */
+       function msgWiki( $str ) {
+               global $wgParser, $wgTitle, $wgOut, $wgUseTidy;
+
+               $text = $this->translator->translate( $str );
+               $parserOutput = $wgParser->parse( $text, $wgTitle,
+                       $wgOut->mParserOptions, true );
+               echo $parserOutput->getText();
+       }
+
+       /**
+        * @access private
+        */
+       function haveData( $str ) {
+               return $this->data[$str];
+       }
+
+       /**
+        * @access private
+        */
+       function haveMsg( $str ) {
+               $msg = $this->translator->translate( $str );
+               return ($msg != '-') && ($msg != ''); # ????
+       }
+}
+
+} // end of if( defined( 'MEDIAWIKI' ) )
+?>
diff --git a/includes/SpecialAllmessages.php b/includes/SpecialAllmessages.php
new file mode 100644 (file)
index 0000000..91975a8
--- /dev/null
@@ -0,0 +1,187 @@
+<?php
+/**
+ * Provide functions to generate a special page
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/**
+ *
+ */
+function wfSpecialAllmessages() {
+       global $wgOut, $wgAllMessagesEn, $wgRequest, $wgMessageCache, $wgTitle;
+       global $wgLanguageCode, $wgContLanguageCode, $wgContLang;
+       global $wgUseDatabaseMessages;
+
+       if(!$wgUseDatabaseMessages) {
+               $wgOut->addHTML(wfMsg('allmessagesnotsupportedDB'));
+               return;
+       }
+
+       $fname = "wfSpecialAllMessages";
+       wfProfileIn( $fname );
+       
+       wfProfileIn( "$fname-setup");
+       $ot = $wgRequest->getText( 'ot' );
+       
+       $navText = wfMsg( 'allmessagestext' );
+
+
+       $first = true;
+       $sortedArray = array_merge( $wgAllMessagesEn, $wgMessageCache->mExtensionMessages );
+       ksort( $sortedArray );
+       $messages = array();
+       $wgMessageCache->disableTransform();
+
+       foreach ( $sortedArray as $key => $enMsg ) {
+               $messages[$key]['enmsg'] = $enMsg;
+               $messages[$key]['statmsg'] = wfMsgNoDb( $key );
+               $messages[$key]['msg'] = wfMsg ( $key );
+       }
+
+       $wgMessageCache->enableTransform();
+       wfProfileOut( "$fname-setup" );
+       
+       wfProfileIn( "$fname-output" );
+       if ($ot == 'php') {
+               $navText .= makePhp($messages);
+               $wgOut->addHTML('PHP | <a href="'.$wgTitle->escapeLocalUrl('ot=html').'">HTML</a><pre>'.htmlspecialchars($navText).'</pre>');
+       } else {
+               $wgOut->addHTML( '<a href="'.$wgTitle->escapeLocalUrl('ot=php').'">PHP</a> | HTML' );
+               $wgOut->addWikiText( $navText );
+               $wgOut->addHTML( makeHTMLText( $messages ) );
+       }
+       wfProfileOut( "$fname-output" );
+       
+       wfProfileOut( $fname );
+}
+
+/**
+ *
+ */
+function makePhp($messages) {
+       global $wgLanguageCode;
+       $txt = "\n\n".'$wgAllMessages'.ucfirst($wgLanguageCode).' = array('."\n";
+       foreach( $messages as $key => $m ) {
+               if(strtolower($wgLanguageCode) != 'en' and $m['msg'] == $m['enmsg'] ) {
+                       if (strstr($m['msg'],"\n")) {
+                               $txt.='/* ';
+                               $comment=' */';
+                       } else {
+                               $txt .= '#';
+                               $comment = '';
+                       }
+               } elseif ($m['msg'] == '&lt;'.$key.'&gt;'){
+                       $m['msg'] = '';
+                       $comment = ' #empty';
+               } else {
+                       $comment = '';
+               }
+               $txt .= "'$key' => '" . preg_replace( "/(?<!\\\\)'/", "\'", $m['msg']) . "',$comment\n";
+       }
+       $txt .= ');';
+       return $txt;
+}
+
+/**
+ *
+ */
+function makeHTMLText( $messages ) {
+       global $wgLang, $wgUser, $wgLanguageCode, $wgContLanguageCode, $wgContLang;
+       $fname = "makeHTMLText";
+       wfProfileIn( $fname );
+       
+       $sk =& $wgUser->getSkin();
+       $talk = $wgLang->getNsText( NS_TALK );
+       $mwnspace = $wgLang->getNsText( NS_MEDIAWIKI );
+       $mwtalk = $wgLang->getNsText( NS_MEDIAWIKI_TALK );
+       $txt = "
+<table border='1' cellspacing='0' width='100%' id='allmessagestable'>
+       <tr >
+               <th rowspan='2'>" . wfMsgHtml('allmessagesname') . "</th>
+               <th>" . wfMsgHtml('allmessagesdefault') . "</th>
+       </tr>
+       <tr>
+               <th>" . wfMsgHtml('allmessagescurrent') . "</th>
+       </tr>";
+       
+       wfProfileIn( "$fname-check" );
+       # This is a nasty hack to avoid doing independent existence checks
+       # without sending the links and table through the slow wiki parser.
+       $pageExists = array(
+               NS_MEDIAWIKI => array(),
+               NS_MEDIAWIKI_TALK => array()
+       );
+       $dbr =& wfGetDB( DB_SLAVE );
+       $page = $dbr->tableName( 'page' );
+       $sql = "SELECT page_namespace,page_title FROM $page WHERE page_namespace IN (" . NS_MEDIAWIKI . ", " . NS_MEDIAWIKI_TALK . ")";
+       $res = $dbr->query( $sql );
+       while( $s = $dbr->fetchObject( $res ) ) {
+               $pageExists[$s->page_namespace][$s->page_title] = true;
+       }
+       $dbr->freeResult( $res );
+       wfProfileOut( "$fname-check" );
+
+       wfProfileIn( "$fname-output" );
+
+       foreach( $messages as $key => $m ) {
+
+               $title = $wgLang->ucfirst( $key );
+               if($wgLanguageCode != $wgContLanguageCode)
+                       $title.="/$wgLanguageCode";
+
+               $titleObj =& Title::makeTitle( NS_MEDIAWIKI, $title );
+               $talkPage =& Title::makeTitle( NS_MEDIAWIKI_TALK, $title );
+
+               $changed = ($m['statmsg'] != $m['msg']);
+               $message = htmlspecialchars( $m['statmsg'] );
+               $mw = htmlspecialchars( $m['msg'] );
+               
+               #$pageLink = $sk->makeLinkObj( $titleObj, htmlspecialchars( $key ) );
+               #$talkLink = $sk->makeLinkObj( $talkPage, htmlspecialchars( $talk ) );
+               if( isset( $pageExists[NS_MEDIAWIKI][$title] ) ) {
+                       $pageLink = $sk->makeKnownLinkObj( $titleObj, htmlspecialchars( $key ) );
+               } else {
+                       $pageLink = $sk->makeBrokenLinkObj( $titleObj, htmlspecialchars( $key ) );
+               }
+               if( isset( $pageExists[NS_MEDIAWIKI_TALK][$title] ) ) {
+                       $talkLink = $sk->makeKnownLinkObj( $talkPage, htmlspecialchars( $talk ) );
+               } else {
+                       $talkLink = $sk->makeBrokenLinkObj( $talkPage, htmlspecialchars( $talk ) );
+               }
+
+               if($changed) {
+
+                       $txt .=
+       "<tr class='orig'>
+               <td rowspan='2'>
+                       $pageLink<br />$talkLink
+               </td><td>
+$message
+               </td>
+       </tr><tr class='new'>
+               <td>
+$mw
+               </td>
+       </tr>";
+               } else {
+
+                       $txt .=
+       "<tr class='def'>
+               <td>
+                       $pageLink<br />$talkLink
+               </td><td>
+$mw
+               </td>
+       </tr>";
+
+               }
+       }
+       $txt .= "</table>";
+       wfProfileOut( "$fname-output" );
+
+       wfProfileOut( $fname );
+       return $txt;
+}
+
+?>
diff --git a/includes/SpecialAllpages.php b/includes/SpecialAllpages.php
new file mode 100644 (file)
index 0000000..5ba83c7
--- /dev/null
@@ -0,0 +1,279 @@
+<?php
+/**
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/**
+ * Entry point : initialise variables and call subfunctions.
+ * @param string $par Becomes "FOO" when called like Special:Allpages/FOO (default NULL)
+ */
+function wfSpecialAllpages( $par=NULL, $specialPage ) {
+       global $indexMaxperpage, $toplevelMaxperpage, $wgRequest, $wgOut, $wgContLang;
+       # Config
+       $indexMaxperpage = 960;
+       $toplevelMaxperpage = 50;
+       # GET values
+       $from = $wgRequest->getVal( 'from' );
+       $namespace = $wgRequest->getInt( 'namespace' );
+       
+       $namespaces = $wgContLang->getNamespaces();
+
+       if( !in_array($namespace, array_keys($namespaces)) )
+               $namespace = 0;
+
+       $wgOut->setPagetitle( $namespace > 0 ?
+               wfMsg( 'allinnamespace', $namespaces[$namespace] ) :
+               wfMsg( 'allarticles' )
+               );
+       
+       if ( isset($par) ) {
+               indexShowChunk( $namespace, $par, $specialPage->including() );
+       } elseif ( isset($from) ) {
+               indexShowChunk( $namespace, $from, $specialPage->including() );
+       } else {
+               indexShowToplevel ( $namespace, $specialPage->including() );
+       }
+}
+
+/**
+ * HTML for the top form
+ * @param integer $namespace A namespace constant (default NS_MAIN).
+ * @param string $from Article name we are starting listing at.
+ */
+function indexNamespaceForm ( $namespace = NS_MAIN, $from = '' ) {
+       global $wgContLang, $wgScript;
+       $t = Title::makeTitle( NS_SPECIAL, "Allpages" );
+
+       $namespaceselect = HTMLnamespaceselector($namespace, null);
+
+       $frombox = "<input type='text' size='20' name='from' id='nsfrom' value=\""
+                   . htmlspecialchars ( $from ) . '"/>';
+       $submitbutton = '<input type="submit" value="' . wfMsgHtml( 'allpagessubmit' ) . '" />';
+       
+       $out = "<div class='namespaceoptions'><form method='get' action='{$wgScript}'>";
+       $out .= '<input type="hidden" name="title" value="'.$t->getPrefixedText().'" />';
+       $out .= "
+<table id='nsselect' class='allpages'>
+       <tr>
+               <td align='right'>" . wfMsgHtml('allpagesfrom') . "</td>
+               <td align='left'><label for='nsfrom'>$frombox</label></td>
+       </tr>
+       <tr>    
+               <td align='right'><label for='namespace'>" . wfMsgHtml('namespace') . "</label></td>
+               <td align='left'>
+                       $namespaceselect $submitbutton
+               </td>
+       </tr>
+</table>
+";
+       $out .= '</form></div>';
+               return $out;
+}
+
+/**
+ * @param integer $namespace (default NS_MAIN)
+ */
+function indexShowToplevel ( $namespace = NS_MAIN, $including = false ) {
+       global $wgOut, $indexMaxperpage, $toplevelMaxperpage, $wgContLang, $wgRequest, $wgUser;
+       $sk = $wgUser->getSkin();
+       $fname = "indexShowToplevel";
+
+       # TODO: Either make this *much* faster or cache the title index points
+       # in the querycache table.
+
+       $dbr =& wfGetDB( DB_SLAVE );
+       $page = $dbr->tableName( 'page' );
+       $fromwhere = "FROM $page WHERE page_namespace=$namespace";
+       $order_arr = array ( 'ORDER BY' => 'page_title' );
+       $order_str = 'ORDER BY page_title';
+       $out = "";
+       $where = array( 'page_namespace' => $namespace );
+
+       global $wgMemc, $wgDBname;
+       $key = "$wgDBname:allpages:ns:$namespace";
+       $lines = $wgMemc->get( $key );
+       
+       if( !is_array( $lines ) ) {
+               $firstTitle = $dbr->selectField( 'page', 'page_title', $where, $fname, array( 'LIMIT' => 1 ) );
+               $lastTitle = $firstTitle;
+               
+               # This array is going to hold the page_titles in order.
+               $lines = array( $firstTitle );
+               
+               # If we are going to show n rows, we need n+1 queries to find the relevant titles.
+               $done = false;
+               for( $i = 0; !$done; ++$i ) {
+                       // Fetch the last title of this chunk and the first of the next
+                       $chunk = is_null( $lastTitle )
+                               ? '1=1'
+                               : 'page_title >= ' . $dbr->addQuotes( $lastTitle );
+                       $sql = "SELECT page_title $fromwhere AND $chunk $order_str " .
+                               $dbr->limitResult( 2, $indexMaxperpage - 1 );
+                       $res = $dbr->query( $sql, $fname );
+                       if ( $s = $dbr->fetchObject( $res ) ) {
+                               array_push( $lines, $s->page_title );
+                       } else {
+                               // Final chunk, but ended prematurely. Go back and find the end.
+                               $endTitle = $dbr->selectField( 'page', 'MAX(page_title)',
+                                       array(
+                                               'page_namespace' => $namespace,
+                                               $chunk
+                                       ), $fname );
+                               array_push( $lines, $endTitle );
+                               $done = true;
+                       }
+                       if( $s = $dbr->fetchObject( $res ) ) {
+                               array_push( $lines, $s->page_title );
+                               $lastTitle = $s->page_title;
+                       } else {
+                               // This was a final chunk and ended exactly at the limit.
+                               // Rare but convenient!
+                               $done = true;
+                       }
+                       $dbr->freeResult( $res );
+               }
+               $wgMemc->add( $key, $lines, 3600 );
+       }
+       
+       // If there are only two or less sections, don't even display them.
+       // Instead, display the first section directly.
+       if( count( $lines ) <= 2 ) {
+               indexShowChunk( $namespace, '', false, $including );
+               return;
+       }
+
+       # At this point, $lines should contain an even number of elements.
+       $out .= "<table style='background: inherit;'>";
+       while ( count ( $lines ) > 0 ) {
+               $inpoint = array_shift ( $lines );
+               $outpoint = array_shift ( $lines );
+               $out .= indexShowline ( $inpoint, $outpoint, $namespace, false );
+       }
+       $out .= '</table>';
+       
+       $nsForm = indexNamespaceForm ( $namespace, '', false );
+       
+       # Is there more?
+       if ( $including ) {
+               $out2 = '';
+       } else {
+               $morelinks = '';
+               if ( $morelinks != '' ) {
+                       $out2 = '<table style="background: inherit;" width="100%" cellpadding="0" cellspacing="0" border="0">';
+                       $out2 .= '<tr valign="top"><td align="left">' . $nsForm;
+                       $out2 .= '</td><td align="right" style="font-size: smaller; margin-bottom: 1em;">';
+                       $out2 .= $morelinks . '</td></tr></table><hr />';
+               } else {
+                       $out2 = $nsForm . '<hr />';
+               }
+       }
+
+       $wgOut->addHtml( $out2 . $out );
+}
+
+/**
+ * @todo Document
+ * @param string $from 
+ * @param integer $namespace (Default NS_MAIN)
+ */
+function indexShowline( $inpoint, $outpoint, $namespace = NS_MAIN ) {
+       global $wgOut, $wgLang, $wgUser;
+       $sk = $wgUser->getSkin();
+       $dbr =& wfGetDB( DB_SLAVE );
+
+       $inpointf = htmlspecialchars( str_replace( '_', ' ', $inpoint ) );
+       $outpointf = htmlspecialchars( str_replace( '_', ' ', $outpoint ) );
+       $queryparams = ($namespace ? "namespace=$namespace" : '');
+       $special = Title::makeTitle( NS_SPECIAL, 'Allpages/' . $inpoint );
+       $link = $special->escapeLocalUrl( $queryparams );
+       
+       $out = wfMsg(
+               'alphaindexline',
+               "<a href=\"$link\">$inpointf</a></td><td><a href=\"$link\">",
+               "</a></td><td align=\"left\"><a href=\"$link\">$outpointf</a>"
+       );
+       return '<tr><td align="right">'.$out.'</td></tr>';
+}
+
+/**
+ * @param integer $namespace (Default NS_MAIN)
+ * @param string $from list all pages from this name (default FALSE)
+ */
+function indexShowChunk( $namespace = NS_MAIN, $from, $including = false ) {
+       global $wgOut, $wgUser, $indexMaxperpage, $wgContLang;
+
+       $fname = 'indexShowChunk';
+       
+       $sk = $wgUser->getSkin();
+
+       $fromTitle = Title::newFromURL( $from );
+       $fromKey = is_null( $fromTitle ) ? '' : $fromTitle->getDBkey();
+       
+       $dbr =& wfGetDB( DB_SLAVE );
+       $res = $dbr->select( 'page',
+               array( 'page_namespace', 'page_title', 'page_is_redirect' ),
+               array(
+                       'page_namespace' => $namespace,
+                       'page_title >= ' . $dbr->addQuotes( $fromKey )
+               ),
+               $fname,
+               array(
+                       'ORDER BY'  => 'page_title',
+                       'LIMIT'     => $indexMaxperpage + 1,
+                       'USE INDEX' => 'name_title',
+               )
+       );
+
+       ### FIXME: side link to previous
+
+       $n = 0;
+       $out = '<table style="background: inherit;" border="0" width="100%">';
+       
+       $namespaces = $wgContLang->getFormattedNamespaces();
+       while( ($n < $indexMaxperpage) && ($s = $dbr->fetchObject( $res )) ) {
+               $t = Title::makeTitle( $s->page_namespace, $s->page_title );
+               if( $t ) {
+                       $link = ($s->page_is_redirect ? '<div class="allpagesredirect">' : '' ) . 
+                               $sk->makeKnownLinkObj( $t, htmlspecialchars( $t->getText() ), false, false ) .
+                               ($s->page_is_redirect ? '</div>' : '' );
+               } else {
+                       $link = '[[' . htmlspecialchars( $s->page_title ) . ']]';
+               }
+               if( $n % 3 == 0 ) {
+                       $out .= '<tr>';
+               }
+               $out .= "<td>$link</td>";
+               $n++;
+               if( $n % 3 == 0 ) {
+                       $out .= '</tr>';
+               }
+       }
+       if( ($n % 3) != 0 ) {
+               $out .= '</tr>';
+       }
+       $out .= '</table>';
+       
+       if ( $including ) {
+               $out2 = '';
+       } else {
+               $nsForm = indexNamespaceForm ( $namespace, $from );
+               $out2 = '<table style="background: inherit;" width="100%" cellpadding="0" cellspacing="0" border="0">';
+               $out2 .= '<tr valign="top"><td align="left">' . $nsForm;
+               $out2 .= '</td><td align="right" style="font-size: smaller; margin-bottom: 1em;">' .
+                               $sk->makeKnownLink( $wgContLang->specialPage( "Allpages" ),
+                                       wfMsg ( 'allpages' ) );
+               if ( ($n == $indexMaxperpage) && ($s = $dbr->fetchObject( $res )) ) {
+                       $namespaceparam = $namespace ? "&namespace=$namespace" : "";
+                       $out2 .= " | " . $sk->makeKnownLink(
+                               $wgContLang->specialPage( "Allpages" ),
+                               wfMsg ( 'nextpage', $s->page_title ),
+                               "from=" . wfUrlEncode ( $s->page_title ) . $namespaceparam );
+               }
+               $out2 .= "</td></tr></table><hr />";
+       }
+
+       $wgOut->addHtml( $out2 . $out );
+}
+
+?>
diff --git a/includes/SpecialAncientpages.php b/includes/SpecialAncientpages.php
new file mode 100644 (file)
index 0000000..a9a4231
--- /dev/null
@@ -0,0 +1,67 @@
+<?php
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/**
+ *
+ */
+require_once( 'QueryPage.php' );
+
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+class AncientPagesPage extends QueryPage {
+
+       function getName() {
+               return "Ancientpages";
+       }
+
+       function isExpensive() {
+               return true;
+       }
+       
+       function isSyndicated() { return false; }
+
+       function getSQL() {
+               $db =& wfGetDB( DB_SLAVE );
+               $page = $db->tableName( 'page' );
+               $revision = $db->tableName( 'revision' );
+               #$use_index = $db->useIndexClause( 'cur_timestamp' ); # FIXME! this is gone
+               return
+                       "SELECT 'Ancientpages' as type,
+                                       page_namespace as namespace,
+                               page_title as title,
+                               UNIX_TIMESTAMP(rev_timestamp) as value
+                       FROM $page, $revision
+                       WHERE page_namespace=".NS_MAIN." AND page_is_redirect=0
+                         AND page_latest=rev_id";
+       }
+       
+       function sortDescending() {
+               return false;
+       }
+
+       function formatResult( $skin, $result ) {
+               global $wgLang, $wgContLang;
+
+               $d = $wgLang->timeanddate( wfTimestamp( TS_MW, $result->value ), true );
+               $title = Title::makeTitle( $result->namespace, $result->title );
+               $link = $skin->makeKnownLinkObj( $title, $wgContLang->convert( $title->getPrefixedText() ) );
+               return "{$link} ({$d})";
+       }
+}
+
+function wfSpecialAncientpages() {
+       list( $limit, $offset ) = wfCheckLimits();
+
+       $app = new AncientPagesPage();
+
+       $app->doQuery( $offset, $limit );
+}
+
+?>
diff --git a/includes/SpecialBlockip.php b/includes/SpecialBlockip.php
new file mode 100644 (file)
index 0000000..28ef283
--- /dev/null
@@ -0,0 +1,239 @@
+<?php
+/**
+ * Constructor for Special:Blockip page
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/**
+ * Constructor
+ */
+function wfSpecialBlockip() {
+       global $wgUser, $wgOut, $wgRequest;
+
+       if ( ! $wgUser->isAllowed('block') ) {
+               $wgOut->sysopRequired();
+               return;
+       }
+       $ipb = new IPBlockForm();
+
+       $action = $wgRequest->getVal( 'action' );
+       if ( 'success' == $action ) {
+               $ipb->showSuccess();
+       } else if ( $wgRequest->wasPosted() && 'submit' == $action &&
+               $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) ) ) {
+               $ipb->doSubmit();
+       } else {
+               $ipb->showForm( '' );
+       }
+}
+
+/**
+ * Form object
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+class IPBlockForm {
+       var $BlockAddress, $BlockExpiry, $BlockReason;
+
+       function IPBlockForm() {
+               global $wgRequest;
+               $this->BlockAddress = $wgRequest->getVal( 'wpBlockAddress', $wgRequest->getVal( 'ip' ) );
+               $this->BlockReason = $wgRequest->getText( 'wpBlockReason' );
+               $this->BlockExpiry = $wgRequest->getVal( 'wpBlockExpiry', wfMsg('ipbotheroption') );
+               $this->BlockOther = $wgRequest->getVal( 'wpBlockOther', '' );
+       }
+       
+       function showForm( $err ) {
+               global $wgOut, $wgUser, $wgLang;
+               global $wgRequest, $wgSysopUserBans;
+
+               $wgOut->setPagetitle( htmlspecialchars( wfMsg( 'blockip' ) ) );
+               $wgOut->addWikiText( wfMsg( 'blockiptext' ) );
+
+               if($wgSysopUserBans) {
+                       $mIpaddress = htmlspecialchars( wfMsg( 'ipadressorusername' ) );
+               } else {
+                       $mIpaddress = htmlspecialchars( wfMsg( 'ipaddress' ) );
+               }
+               $mIpbexpiry = htmlspecialchars( wfMsg( 'ipbexpiry' ) );
+               $mIpbother = htmlspecialchars( wfMsg( 'ipbother' ) );
+               $mIpbothertime = htmlspecialchars( wfMsg( 'ipbotheroption' ) );
+               $mIpbreason = htmlspecialchars( wfMsg( 'ipbreason' ) );
+               $mIpbsubmit = htmlspecialchars( wfMsg( 'ipbsubmit' ) );
+               $titleObj = Title::makeTitle( NS_SPECIAL, 'Blockip' );
+               $action = $titleObj->escapeLocalURL( "action=submit" );
+
+               if ( "" != $err ) {
+                       $wgOut->setSubtitle( wfMsgHtml( 'formerror' ) );
+                       $wgOut->addHTML( "<p class='error'>{$err}</p>\n" );
+               }
+
+               $scBlockAddress = htmlspecialchars( $this->BlockAddress );
+               $scBlockExpiry = htmlspecialchars( $this->BlockExpiry );
+               $scBlockReason = htmlspecialchars( $this->BlockReason );
+               $scBlockOtherTime = htmlspecialchars( $this->BlockOther );
+               $scBlockExpiryOptions = htmlspecialchars( wfMsgForContent( 'ipboptions' ) );
+
+               $showblockoptions = $scBlockExpiryOptions != '-';
+               if (!$showblockoptions)
+                       $mIpbother = $mIpbexpiry;
+
+               $blockExpiryFormOptions = "<option value=\"other\">$mIpbothertime</option>";
+               foreach (explode(',', $scBlockExpiryOptions) as $option) {
+                       if ( strpos($option, ":") === false ) $option = "$option:$option";
+                       list($show, $value) = explode(":", $option);
+                       $show = htmlspecialchars($show);
+                       $value = htmlspecialchars($value);
+                       $selected = "";
+                       if ($this->BlockExpiry === $value)
+                               $selected = ' selected="selected"';
+                       $blockExpiryFormOptions .= "<option value=\"$value\"$selected>$show</option>";
+               }
+
+               $token = htmlspecialchars( $wgUser->editToken() );
+               
+               $wgOut->addHTML( "
+<form id=\"blockip\" method=\"post\" action=\"{$action}\">
+       <table border='0'>
+               <tr>
+                       <td align=\"right\">{$mIpaddress}:</td>
+                       <td align=\"left\">
+                               <input tabindex='1' type='text' size='20' name=\"wpBlockAddress\" value=\"{$scBlockAddress}\" />
+                       </td>
+               </tr>
+               <tr>");
+               if ($showblockoptions) {
+                       $wgOut->addHTML("
+                       <td align=\"right\">{$mIpbexpiry}:</td>
+                       <td align=\"left\">
+                               <select tabindex='2' id='wpBlockExpiry' name=\"wpBlockExpiry\" onchange=\"considerChangingExpiryFocus()\">
+                                       $blockExpiryFormOptions
+                               </select>
+                       </td>
+                       ");
+               }
+               $wgOut->addHTML("
+               </tr>
+               <tr id='wpBlockOther'>
+                       <td align=\"right\">{$mIpbother}:</td>
+                       <td align=\"left\">
+                               <input tabindex='3' type='text' size='40' name=\"wpBlockOther\" value=\"{$scBlockOtherTime}\" />
+                       </td>
+               </tr>
+               <tr>
+                       <td align=\"right\">{$mIpbreason}:</td>
+                       <td align=\"left\">
+                               <input tabindex='3' type='text' size='40' name=\"wpBlockReason\" value=\"{$scBlockReason}\" />
+                       </td>
+               </tr>
+               <tr>
+                       <td>&nbsp;</td>
+                       <td align=\"left\">
+                               <input tabindex='4' type='submit' name=\"wpBlock\" value=\"{$mIpbsubmit}\" />
+                       </td>
+               </tr>
+       </table>
+       <input type='hidden' name='wpEditToken' value=\"{$token}\" />
+</form>\n" );
+
+       }
+
+       function doSubmit() {
+               global $wgOut, $wgUser, $wgLang;
+               global $wgSysopUserBans, $wgSysopRangeBans;
+               
+               $userId = 0;
+               $this->BlockAddress = trim( $this->BlockAddress );
+               $rxIP = '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}';
+
+               # Check for invalid specifications
+               if ( ! preg_match( "/^$rxIP$/", $this->BlockAddress ) ) {
+                       if ( preg_match( "/^($rxIP)\\/(\\d{1,2})$/", $this->BlockAddress, $matches ) ) {
+                               if ( $wgSysopRangeBans ) {
+                                       if ( $matches[2] > 31 || $matches[2] < 16 ) {
+                                               $this->showForm( wfMsg( 'ip_range_invalid' ) );
+                                               return;
+                                       }
+                                       $this->BlockAddress = Block::normaliseRange( $this->BlockAddress );
+                               } else {
+                                       # Range block illegal
+                                       $this->showForm( wfMsg( 'range_block_disabled' ) );
+                                       return;
+                               }
+                       } else {
+                               # Username block
+                               if ( $wgSysopUserBans ) {       
+                                       $userId = User::idFromName( $this->BlockAddress );
+                                       if ( $userId == 0 ) {
+                                               $this->showForm( wfMsg( 'nosuchusershort', htmlspecialchars( $this->BlockAddress ) ) );
+                                               return;
+                                       }
+                               } else {
+                                       $this->showForm( wfMsg( 'badipaddress' ) );
+                                       return;
+                               }
+                       }
+               }
+
+               $expirestr = $this->BlockExpiry;
+               if( $expirestr == 'other' )
+                       $expirestr = $this->BlockOther;
+
+               if (strlen($expirestr) == 0) {
+                       $this->showForm( wfMsg( 'ipb_expiry_invalid' ) );
+                       return;
+               }
+
+               if ( $expirestr == 'infinite' || $expirestr == 'indefinite' ) {
+                       $expiry = '';
+               } else {
+                       # Convert GNU-style date, returns -1 on error
+                       $expiry = strtotime( $expirestr );
+
+                       if ( $expiry < 0 ) {
+                               $this->showForm( wfMsg( 'ipb_expiry_invalid' ) );
+                               return;
+                       }
+                       
+                       $expiry = wfTimestamp( TS_MW, $expiry );
+
+               }
+               
+               # Create block
+               # Note: for a user block, ipb_address is only for display purposes
+
+               $ban = new Block( $this->BlockAddress, $userId, $wgUser->getID(), 
+                       $this->BlockReason, wfTimestampNow(), 0, $expiry );
+               
+               if (wfRunHooks('BlockIp', array(&$ban, &$wgUser))) {
+                       
+                       $ban->insert();
+                       
+                       wfRunHooks('BlockIpComplete', array($ban, $wgUser));
+                       
+                       # Make log entry
+                       $log = new LogPage( 'block' );
+                       $log->addEntry( 'block', Title::makeTitle( NS_USER, $this->BlockAddress ), 
+                         $this->BlockReason, $expirestr );
+
+                       # Report to the user
+                       $titleObj = Title::makeTitle( NS_SPECIAL, 'Blockip' );
+                       $wgOut->redirect( $titleObj->getFullURL( 'action=success&ip=' .
+                               urlencode( $this->BlockAddress ) ) );
+               }
+       }
+
+       function showSuccess() {
+               global $wgOut, $wgUser;
+
+               $wgOut->setPagetitle( wfMsg( 'blockip' ) );
+               $wgOut->setSubtitle( wfMsg( 'blockipsuccesssub' ) );
+               $text = wfMsg( 'blockipsuccesstext', $this->BlockAddress );
+               $wgOut->addWikiText( $text );
+       }
+}
+
+?>
diff --git a/includes/SpecialBlockme.php b/includes/SpecialBlockme.php
new file mode 100644 (file)
index 0000000..6721d26
--- /dev/null
@@ -0,0 +1,39 @@
+<?php
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/**
+ *
+ */
+function wfSpecialBlockme()
+{
+       global $wgIP, $wgBlockOpenProxies, $wgOut, $wgProxyKey;
+
+       if ( !$wgBlockOpenProxies || $_REQUEST['ip'] != md5( $wgIP . $wgProxyKey ) ) {
+               $wgOut->addWikiText( wfMsg( "disabled" ) );
+               return;
+       }       
+
+       $blockerName = wfMsg( "proxyblocker" );
+       $reason = wfMsg( "proxyblockreason" );
+       $success = wfMsg( "proxyblocksuccess" );
+
+       $u = User::newFromName( $blockerName );
+       $id = $u->idForName();
+       if ( !$id ) {
+               $u = User::newFromName( $blockerName );
+               $u->addToDatabase();
+               $u->setPassword( bin2hex( mt_rand(0, 0x7fffffff ) ) );
+               $u->saveSettings();
+               $id = $u->getID();
+       }
+
+       $block = new Block( $wgIP, 0, $id, $reason, wfTimestampNow() );
+       $block->insert();
+
+       $wgOut->addWikiText( $success );
+}
+?>
diff --git a/includes/SpecialBooksources.php b/includes/SpecialBooksources.php
new file mode 100644 (file)
index 0000000..d582ed8
--- /dev/null
@@ -0,0 +1,107 @@
+<?php
+/**
+ * ISBNs in wiki pages will create links to this page, with the ISBN passed
+ * in via the query string.
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/**
+ * Constructor
+ */
+function wfSpecialBooksources( $par ) {
+       global $wgRequest;
+       
+       $isbn = $par;
+       if( empty( $par ) ) {
+               $isbn = $wgRequest->getVal( 'isbn' );
+       }
+       $isbn = preg_replace( '/[^0-9X]/', '', $isbn );
+       
+       $bsl = new BookSourceList( $isbn );
+       $bsl->show();
+}
+
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+class BookSourceList {
+       var $mIsbn;
+
+       function BookSourceList( $isbn ) {
+               $this->mIsbn = $isbn;
+       }
+
+       function show() {
+               global $wgOut;
+
+               $wgOut->setPagetitle( wfMsg( "booksources" ) );
+               if( $this->mIsbn == '' ) {
+                       $this->askForm();
+               } else {
+                       $this->showList();
+               }
+       }
+       
+       function showList() {
+               global $wgOut, $wgUser, $wgContLang;
+               $fname = "BookSourceList::showList()";
+               
+               # First, see if we have a custom list setup in
+               # [[Wikipedia:Book sources]] or equivalent.
+               $bstitle = Title::makeTitleSafe( NS_PROJECT, wfMsg( "booksources" ) );
+               $bsarticle = new Article( $bstitle );
+               if( $bsarticle->exists() ) {
+                       $bstext = $bsarticle->getContent( false );
+                       if( $bstext ) { 
+                               $bstext = str_replace( "MAGICNUMBER", $this->mIsbn, $bstext );
+                               $wgOut->addWikiText( $bstext );
+                               return;
+                       }
+               }
+               
+               # Otherwise, use the list of links in the default Language.php file.
+               $s = wfMsg( "booksourcetext" ) . "<ul>\n";
+               $bs = $wgContLang->getBookstoreList() ;
+               $bsn = array_keys ( $bs ) ;
+               foreach ( $bsn as $name ) {
+                       $adr = $bs[$name] ;
+                       if ( ! $this->mIsbn ) {
+                               $adr = explode( ":" , $adr , 2 );
+                               $adr = explode( "/" , $adr[1] );
+                               $a = "";
+                               while ( $a == "" ) {
+                                       $a = array_shift( $adr );
+                               }
+                               $adr = "http://".$a ;
+                       } else {
+                               $adr = str_replace ( "$1" , $this->mIsbn , $adr ) ;
+                       }
+                       $name = htmlspecialchars( $name );
+                       $adr = htmlspecialchars( $adr );
+                       $s .= "<li><a href=\"{$adr}\" class=\"external\">{$name}</a></li>\n" ;
+               }
+               $s .= "</ul>\n";
+
+               $wgOut->addHTML( $s );
+       }
+       
+       function askForm() {
+               global $wgOut, $wgLang, $wgTitle;
+               $fname = "BookSourceList::askForm()";
+               
+               $action = $wgTitle->escapeLocalUrl();
+               $isbn = htmlspecialchars( wfMsg( "isbn" ) );
+               $go = htmlspecialchars( wfMsg( "go" ) );
+               $out = "<form action=\"$action\" method='post'>
+                       $isbn: <input name='isbn' id='isbn' />
+                       <input type='submit' value=\"$go\" />
+               </form>";
+               $wgOut->addHTML( $out );
+       }
+}
+
+?>
diff --git a/includes/SpecialBrokenRedirects.php b/includes/SpecialBrokenRedirects.php
new file mode 100644 (file)
index 0000000..4c3a8ed
--- /dev/null
@@ -0,0 +1,91 @@
+<?php
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/**
+ *
+ */
+require_once('QueryPage.php');
+
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+class BrokenRedirectsPage extends PageQueryPage {
+       var $targets = array();
+
+       function getName() {
+               return 'BrokenRedirects';
+       }
+       
+       function isExpensive( ) { return true; }
+       function isSyndicated() { return false; }
+
+       function getPageHeader( ) {
+               return '<p>'.wfMsg('brokenredirectstext')."</p><br />\n";
+       }
+
+       function getSQL() {
+               $dbr =& wfGetDB( DB_SLAVE );
+               extract( $dbr->tableNames( 'page', 'pagelinks' ) );
+
+               $sql = "SELECT 'BrokenRedirects'  AS type,
+                               p1.page_namespace AS namespace,
+                               p1.page_title     AS title,
+                               pl_namespace,
+                               pl_title
+                          FROM ($pagelinks, $page AS p1)
+                     LEFT JOIN $page AS p2
+                            ON pl_namespace=p2.page_namespace AND pl_title=p2.page_title
+                         WHERE p1.page_is_redirect=1
+                           AND pl_from=p1.page_id
+                           AND p2.page_namespace IS NULL";
+               return $sql;
+       }
+
+       function getOrder() {
+               return '';
+       }
+
+       function formatResult( $skin, $result ) {
+               $fromObj = Title::makeTitle( $result->namespace, $result->title );
+               if ( isset( $result->pl_title ) ) {
+                       $toObj = Title::makeTitle( $result->pl_namespace, $result->pl_title );
+               } else {
+                       $blinks = $fromObj->getBrokenLinksFrom();
+                       if ( $blinks ) {
+                               $toObj = $blinks[0];
+                       } else {
+                               $toObj = false;
+                       }
+               }
+
+               // $toObj may very easily be false if the $result list is cached
+               if ( !is_object( $toObj ) ) {
+                       return '<s>' . $skin->makeLinkObj( $fromObj ) . '</s>';
+               }
+
+               $from = $skin->makeKnownLinkObj( $fromObj ,'', 'redirect=no' );
+               $edit = $skin->makeBrokenLinkObj( $fromObj , "(".wfMsg("qbedit").")" , 'redirect=no');
+               $to   = $skin->makeBrokenLinkObj( $toObj );
+                               
+               return "$from $edit &rarr; $to";
+       }
+}
+
+/**
+ * constructor
+ */
+function wfSpecialBrokenRedirects() {
+       list( $limit, $offset ) = wfCheckLimits();
+       
+       $sbr = new BrokenRedirectsPage();
+       
+       return $sbr->doQuery( $offset, $limit );
+
+}
+?>
diff --git a/includes/SpecialCategories.php b/includes/SpecialCategories.php
new file mode 100644 (file)
index 0000000..977484b
--- /dev/null
@@ -0,0 +1,66 @@
+<?php
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/**
+ *
+ */
+require_once("QueryPage.php");
+
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+class CategoriesPage extends QueryPage {
+
+       function getName() {
+               return "Categories";
+       }
+
+       function isExpensive() {
+               return false;
+       }
+
+       function isSyndicated() { return false; }
+
+       function getPageHeader() {
+               return '<p>'.wfMsg('categoriespagetext')."</p><br />\n";
+       }
+       function getSQL() {
+               $NScat = NS_CATEGORY;
+               $dbr =& wfGetDB( DB_SLAVE );
+               $categorylinks = $dbr->tableName( 'categorylinks' );
+               return "SELECT DISTINCT 'Categories' as type, 
+                               {$NScat} as namespace,
+                               cl_to as title,
+                               1 as value
+                          FROM $categorylinks";
+       }
+       
+       function sortDescending() {
+               return false;
+       }
+
+       function formatResult( $skin, $result ) {
+               global $wgLang;
+               $title = Title::makeTitle( NS_CATEGORY, $result->title );
+               return $skin->makeLinkObj( $title, $title->getText() );
+       }
+}
+
+/**
+ *
+ */
+function wfSpecialCategories() {
+       list( $limit, $offset ) = wfCheckLimits();
+
+       $cap = new CategoriesPage();
+
+       return $cap->doQuery( $offset, $limit );
+}
+
+?>
diff --git a/includes/SpecialConfirmemail.php b/includes/SpecialConfirmemail.php
new file mode 100644 (file)
index 0000000..ac6415e
--- /dev/null
@@ -0,0 +1,108 @@
+<?php
+/**
+ * Entry point to confirm a user's e-mail address.
+ * When a new address is entered, a random unique code is generated and
+ * mailed to the user. A clickable link to this page is provided.
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/** @todo document */
+function wfSpecialConfirmemail( $code ) {
+       $form = new ConfirmationForm();
+       $form->show( $code );
+}
+
+/** @package MediaWiki */
+class ConfirmationForm {
+       /** */
+       function show( $code ) {
+               if( empty( $code ) ) {
+                       $this->showEmpty( $this->checkAndSend() );
+               } else {
+                       $this->showCode( $code );
+               }
+       }
+
+       /** */
+       function showCode( $code ) {
+               $user = User::newFromConfirmationCode( $code );
+               if( is_null( $user ) ) {
+                       $this->showInvalidCode();
+               } else {
+                       $this->confirmAndShow( $user );
+               }
+       }
+
+       /** */  
+       function confirmAndShow( $user ) {
+               if( $user->confirmEmail() ) {
+                       $this->showSuccess();
+               } else {
+                       $this->showError();
+               }
+       }
+
+       /** */
+       function checkAndSend() {
+               global $wgUser, $wgRequest;
+               if( $wgRequest->wasPosted() &&
+                       $wgUser->isLoggedIn() &&
+                       $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) ) ) {
+                       $result = $wgUser->sendConfirmationMail();
+                       if( WikiError::isError( $result ) ) {
+                               return 'confirmemail_sendfailed';
+                       } else {
+                               return 'confirmemail_sent';
+                       }
+               } else {
+                       # boo
+                       return '';
+               }
+       }
+
+       /** */
+       function showEmpty( $err ) {
+               require_once( 'templates/Confirmemail.php' );
+               global $wgOut, $wgUser;
+               
+               $tpl = new ConfirmemailTemplate();
+               $tpl->set( 'error', $err );
+               $tpl->set( 'edittoken', $wgUser->editToken() );
+               
+               $title = Title::makeTitle( NS_SPECIAL, 'Confirmemail' );
+               $tpl->set( 'action', $title->getLocalUrl() );
+               
+               
+               $wgOut->addTemplate( $tpl );
+       }
+
+       /** */
+       function showInvalidCode() {
+               global $wgOut;
+               $wgOut->addWikiText( wfMsg( 'confirmemail_invalid' ) );
+       }
+
+       /** */
+       function showError() {
+               global $wgOut;
+               $wgOut->addWikiText( wfMsg( 'confirmemail_error' ) );
+       }
+
+       /** */
+       function showSuccess() {
+               global $wgOut, $wgRequest, $wgUser;
+               
+               if( $wgUser->isLoggedIn() ) {
+                       $wgOut->addWikiText( wfMsg( 'confirmemail_loggedin' ) );
+               } else {
+                       $wgOut->addWikiText( wfMsg( 'confirmemail_success' ) );
+                       require_once( 'SpecialUserlogin.php' );
+                       $form = new LoginForm( $wgRequest );
+                       $form->execute();
+               }
+       }
+}
+
+?>
diff --git a/includes/SpecialContributions.php b/includes/SpecialContributions.php
new file mode 100644 (file)
index 0000000..ffbfe91
--- /dev/null
@@ -0,0 +1,391 @@
+<?php
+/**
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/** @package MediaWiki */
+class contribs_finder {
+       var $username, $offset, $limit, $namespace;
+       var $dbr;
+
+       function contribs_finder($username) {
+               $this->username = $username;
+               $this->namespace = false;
+               $this->dbr =& wfGetDB(DB_SLAVE);
+       }
+
+       function set_namespace($ns) {
+               $this->namespace = $ns;
+       }
+
+       function set_limit($limit) {
+               $this->limit = $limit;
+       }
+
+       function set_offset($offset) {
+               $this->offset = $offset;
+       }
+
+       function get_edit_limit($dir) {
+               list($index, $usercond) = $this->get_user_cond();
+               $nscond = $this->get_namespace_cond();
+               $use_index = $this->dbr->useIndexClause($index);
+               extract($this->dbr->tableNames('revision', 'page'));
+               $sql =  "SELECT rev_timestamp " .
+                       " FROM $page,$revision $use_index " .
+                       " WHERE rev_page=page_id AND $usercond $nscond" .
+                       " ORDER BY rev_timestamp $dir LIMIT 1";
+
+               $res = $this->dbr->query($sql, "contribs_finder::get_edit_limit");
+               while ($o = $this->dbr->fetchObject($res))
+                       $row = $o;
+               return $row->rev_timestamp;
+       }
+
+       function get_edit_limits() {
+               return array(
+                       $this->get_edit_limit("ASC"),
+                       $this->get_edit_limit("DESC")
+               );
+       }
+
+       function get_user_cond() {
+               $condition = "";
+
+               if ($this->username == 'newbies') {
+                       $max = $this->dbr->selectField('user', 'max(user_id)', false, "make_sql");
+                       $condition = '>' . (int)($max - $max / 100);
+               }
+
+               if ($condition == "") {
+                       $condition = " rev_user_text=" . $this->dbr->addQuotes($this->username);
+                       $index = 'usertext_timestamp';
+               } else {
+                       $condition = " rev_user {$condition}";
+                       $index = 'user_timestamp';
+               }
+               return array($index, $condition);
+       }
+
+       function get_namespace_cond() {
+               if ($this->namespace !== false)
+                       return " AND page_namespace = " . (int)$this->namespace;
+               return "";
+       }
+
+       function get_previous_offset_for_paging() {
+               list($index, $usercond) = $this->get_user_cond();
+               $nscond = $this->get_namespace_cond();
+
+               $use_index = $this->dbr->useIndexClause($index);
+               extract($this->dbr->tableNames('page', 'revision'));
+
+               $sql =  "SELECT rev_timestamp FROM $page, $revision $use_index " .
+                       "WHERE page_id = rev_page AND rev_timestamp > '" . $this->offset . "' AND " .
+                       "rev_user_text = " . $this->dbr->addQuotes($this->username) .
+                       $nscond;
+               $sql .= " ORDER BY rev_timestamp ASC LIMIT " . ($this->limit+1);
+               $res = $this->dbr->query($sql);
+               $rows = array();
+               while ($obj = $this->dbr->fetchObject($res))
+                       $rows[] = $obj;
+               $this->dbr->freeResult($res);
+               return $rows[count($rows) - 1]->rev_timestamp;
+       }
+
+       function get_first_offset_for_paging() {
+               list($index, $usercond) = $this->get_user_cond();
+               $use_index = $this->dbr->useIndexClause($index);
+               extract($this->dbr->tableNames('page', 'revision'));
+               $nscond = $this->get_namespace_cond();
+               $sql =  "SELECT rev_timestamp FROM $page, $revision $use_index " .
+                       "WHERE page_id = rev_page AND " .
+                       "rev_user_text = " . $this->dbr->addQuotes($this->username) .
+                       $nscond;
+               $sql .= " ORDER BY rev_timestamp ASC LIMIT " . $this->limit;
+               $res = $this->dbr->query($sql);
+               $rows = array();
+               while ($obj = $this->dbr->fetchObject($res))
+                       $rows[] = $obj;
+               $this->dbr->freeResult($res);
+               return $rows[count($rows) - 1]->rev_timestamp;
+       }
+
+       /* private */ function make_sql() {
+               $userCond = $condition = $index = $offsetQuery = $limitQuery = "";
+
+               extract($this->dbr->tableNames('page', 'revision'));
+               list($index, $userCond) = $this->get_user_cond();
+
+               $limitQuery = "LIMIT {$this->limit}";
+               if ($this->offset)
+                       $offsetQuery = "AND rev_timestamp <= '{$this->offset}'";
+
+               $nscond = $this->get_namespace_cond();
+               $use_index = $this->dbr->useIndexClause($index);
+               $sql = "SELECT
+                       page_namespace,page_title,page_is_new,page_latest,
+                       rev_id,rev_timestamp,rev_comment,rev_minor_edit,rev_user_text,
+                       rev_deleted
+                       FROM $page,$revision $use_index
+                       WHERE page_id=rev_page AND $userCond $nscond $offsetQuery
+                       ORDER BY rev_timestamp DESC $limitQuery";
+               return $sql;
+       }
+
+       function find() {
+               $contribs = array();
+               $res = $this->dbr->query($this->make_sql(), "contribs_finder::find");
+               while ($c = $this->dbr->fetchObject($res))
+                       $contribs[] = $c;
+               $this->dbr->freeResult($res);
+               return $contribs;
+       }
+};
+
+/**
+ * Special page "user contributions".
+ * Shows a list of the contributions of a user.
+ *
+ * @return     none
+ * @param      string  $par    (optional) user name of the user for which to show the contributions
+ */
+function wfSpecialContributions( $par = null ) {
+       global $wgUser, $wgOut, $wgLang, $wgContLang, $wgRequest, $wgTitle,
+              $wgScript;
+       $fname = 'wfSpecialContributions';
+
+       $target = isset($par) ? $par : $wgRequest->getVal( 'target' );
+       if (!strlen($target)) {
+               $wgOut->errorpage('notargettitle', 'notargettext');
+               return;
+       }
+
+       $nt = Title::newFromURL( $target );
+       if (!$nt) {
+               $wgOut->errorpage( 'notargettitle', 'notargettext' );
+               return;
+       }
+       $nt =& Title::makeTitle(NS_USER, $nt->getDBkey());
+
+       list( $limit, $offset) = wfCheckLimits();
+       $offset = $wgRequest->getVal('offset');
+       /* Offset must be an integral. */
+       if (!strlen($offset) || !preg_match("/^[0-9]+$/", $offset))
+               $offset = 0;
+
+       $title = Title::makeTitle(NS_SPECIAL, "Contributions");
+       $urlbits = "target=" . wfUrlEncode($target);
+       $myurl = $title->escapeLocalURL($urlbits);
+
+       $finder = new contribs_finder(($target == 'newbies') ? 'newbies' : $nt->getText());
+
+       $finder->set_limit($limit);
+       $finder->set_offset($offset);
+
+       $nsurl = $xnsurl = "";
+       if (($ns = $wgRequest->getVal('namespace', null)) !== null) {
+               $nsurl = "&namespace=$ns";
+               $xnsurl = htmlspecialchars($nsurl);
+               $finder->set_namespace($ns);
+       }
+
+       if ($wgRequest->getText('go') == "prev") {
+               $prevts = $finder->get_previous_offset_for_paging();
+               $prevurl = $title->getLocalURL($urlbits . "&offset=$prevts&limit=$limit$nsurl");
+               $wgOut->redirect($prevurl);
+               return;
+       }
+
+       if ($wgRequest->getText('go') == "first") {
+               $prevts = $finder->get_first_offset_for_paging();
+               $prevurl = $title->getLocalURL($urlbits . "&offset=$prevts&limit=$limit$nsurl");
+               $wgOut->redirect($prevurl);
+               return;
+       }
+
+       $sk = $wgUser->getSkin();
+
+       $id = User::idFromName($nt->getText());
+
+       if ( 0 == $id ) {
+               $ul = $nt->getText();
+       } else {
+               $ul = $sk->makeLinkObj( $nt, htmlspecialchars( $nt->getText() ) );
+               $userCond = '=' . $id;
+       }
+       $talk = $nt->getTalkPage();
+       if( $talk ) {
+               $ul .= ' (' . $sk->makeLinkObj( $talk, $wgLang->getNsText( NS_TALK ) ) . ')';
+       }
+
+       if ($target == 'newbies') {
+               $ul = wfMsg ('newbies');
+       }
+
+       $wgOut->setSubtitle( wfMsgHtml( 'contribsub', $ul ) );
+
+       wfRunHooks('SpecialContributionsBeforeMainOutput', $id );
+
+       $arr =  $wgContLang->getFormattedNamespaces();
+       $nsform = "<form method='get' action=\"$wgScript\">\n";
+       $nsform .= wfElement("input", array(
+                       "name" => "title",
+                       "type" => "hidden",
+                       "value" => $wgTitle->getPrefixedText()));
+       $nsform .= wfElement("input", array(
+                       "name" => "offset",
+                       "type" => "hidden",
+                       "value" => $offset));
+       $nsform .= wfElement("input", array(
+                       "name" => "limit",
+                       "type" => "hidden",
+                       "value" => $limit));
+       $nsform .= wfElement("input", array(
+                       "name" => "target",
+                       "type" => "hidden",
+                       "value" => $target));
+       $nsform .= "<p>";
+       $nsform .= wfMsgHtml('namespace');
+
+       $nsform .= HTMLnamespaceselector($ns, '');
+
+       $nsform .= wfElement("input", array(
+                       "type" => "submit",
+                       "value" => wfMsg('allpagessubmit')));
+       $nsform .= "</p></form>\n";
+
+       $wgOut->addHTML($nsform);
+
+       $contribsPage = Title::makeTitle( NS_SPECIAL, 'Contributions' );
+       $contribs = $finder->find();
+
+       if (count($contribs) == 0) {
+               $wgOut->addWikiText( wfMsg( "nocontribs" ) );
+               return;
+       }
+
+       list($early, $late) = $finder->get_edit_limits();
+       $lastts = count($contribs) ? $contribs[count($contribs) - 1]->rev_timestamp : 0;
+       $atstart = (!count($contribs) || $late == $contribs[0]->rev_timestamp);
+       $atend = (!count($contribs) || $early == $lastts);
+
+       $lasturl = $wgTitle->escapeLocalURL("action=history&limit={$limit}");
+
+       $firsttext = wfMsgHtml("histfirst");
+       $lasttext = wfMsgHtml("histlast");
+
+       $prevtext = wfMsg("prevn", $limit);
+       if ($atstart) {
+               $lastlink = $lasttext;
+               $prevlink = $prevtext;
+       } else {
+               $lastlink = "<a href=\"$myurl&amp;limit=$limit$xnsurl\">$lasttext</a>";
+               $prevlink = "<a href=\"$myurl&amp;offset=$offset&amp;limit=$limit$xnsurl&amp;go=prev\">$prevtext</a>";
+       }
+
+       $nexttext = wfMsg("nextn", $limit);
+       if ($atend) {
+               $firstlink = $firsttext;
+               $nextlink = $nexttext;
+       } else {
+               $firstlink = "<a href=\"$myurl&amp;limit=$limit$xnsurl&amp;go=first\">$firsttext</a>";
+               $nextlink = "<a href=\"$myurl&amp;offset=$lastts&amp;limit=$limit$xnsurl\">$nexttext</a>";
+       }
+       $firstlast = "($lastlink | $firstlink)";
+
+       $urls = array();
+       foreach (array(20, 50, 100, 250, 500) as $num)
+               $urls[] = "<a href=\"$myurl&amp;offset=$offset&amp;limit={$num}$xnsurl\">".$wgLang->formatNum($num)."</a>";
+       $bits = implode($urls, ' | ');
+
+       $prevnextbits = "$firstlast " . wfMsgHtml("viewprevnext", $prevlink, $nextlink, $bits);
+
+       $wgOut->addHTML( "<p>{$prevnextbits}</p>\n");
+
+       $wgOut->addHTML( "<ul>\n" );
+
+       foreach ($contribs as $contrib)
+               $wgOut->addHTML(ucListEdit($sk, $contrib));
+
+       $wgOut->addHTML( "</ul>\n" );
+       $wgOut->addHTML( "<p>{$prevnextbits}</p>\n");
+}
+
+
+/**
+ * Generates each row in the contributions list.
+ *
+ * Contributions which are marked "top" are currently on top of the history.
+ * For these contributions, a [rollback] link is shown for users with sysop
+ * privileges. The rollback link restores the most recent version that was not
+ * written by the target user.
+ *
+ * If the contributions page is called with the parameter &bot=1, all rollback
+ * links also get that parameter. It causes the edit itself and the rollback
+ * to be marked as "bot" edits. Bot edits are hidden by default from recent
+ * changes, so this allows sysops to combat a busy vandal without bothering
+ * other users.
+ *
+ * @todo This would probably look a lot nicer in a table.
+ */
+function ucListEdit( $sk, $row ) {
+       $fname = 'ucListEdit';
+       wfProfileIn( $fname );
+
+       global $wgLang, $wgOut, $wgUser, $wgRequest;
+       static $messages;
+       if( !isset( $messages ) ) {
+               foreach( explode( ' ', 'uctop diff newarticle rollbacklink diff hist minoreditletter' ) as $msg ) {
+                       $messages[$msg] = wfMsg( $msg );
+               }
+       }
+
+       $page =& Title::makeTitle( $row->page_namespace, $row->page_title );
+       $link = $sk->makeKnownLinkObj( $page, '' );
+       $difftext = $topmarktext = '';
+       if( $row->rev_id == $row->page_latest ) {
+               $topmarktext .= '<strong>' . $messages['uctop'] . '</strong>';
+               if( !$row->page_is_new ) {
+                       $difftext .= '(' . $sk->makeKnownLinkObj( $page, $messages['diff'], 'diff=0' ) . ')';
+               } else {
+                       $difftext .= $messages['newarticle'];
+               }
+
+               if( $wgUser->isAllowed('rollback') ) {
+                       $extraRollback = $wgRequest->getBool( 'bot' ) ? '&bot=1' : '';
+                       $extraRollback .= '&token=' . urlencode(
+                               $wgUser->editToken( array( $page->getPrefixedText(), $row->rev_user_text ) ) );
+                       $topmarktext .= ' ['. $sk->makeKnownLinkObj( $page,
+                               $messages['rollbacklink'],
+                               'action=rollback&from=' . urlencode( $row->rev_user_text ) . $extraRollback ) .']';
+               }
+
+       }
+       if( $row->rev_deleted && !$wgUser->isAllowed( 'undelete' ) ) {
+               $difftext = '(' . $messages['diff'] . ')';
+       } else {
+               $difftext = '(' . $sk->makeKnownLinkObj( $page, $messages['diff'], 'diff=prev&oldid='.$row->rev_id ) . ')';
+       }
+       $histlink='('.$sk->makeKnownLinkObj( $page, $messages['hist'], 'action=history' ) . ')';
+
+       $comment = $sk->commentBlock( $row->rev_comment, $page );
+       $d = $wgLang->timeanddate( $row->rev_timestamp, true );
+
+       if( $row->rev_minor_edit ) {
+               $mflag = '<span class="minor">' . $messages['minoreditletter'] . '</span> ';
+       } else {
+               $mflag = '';
+       }
+
+       $ret = "{$d} {$histlink} {$difftext} {$mflag} {$link} {$comment} {$topmarktext}";
+       if( $row->rev_deleted ) {
+               $ret = '<span class="deleted">' . $ret . '</span> ' . htmlspecialchars( wfMsg( 'deletedrev' ) );
+       }
+       $ret = "<li>$ret</li>\n";
+       wfProfileOut( $fname );
+       return $ret;
+}
+
+?>
diff --git a/includes/SpecialDeadendpages.php b/includes/SpecialDeadendpages.php
new file mode 100644 (file)
index 0000000..286460d
--- /dev/null
@@ -0,0 +1,68 @@
+<?php
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/**
+ *
+ */
+require_once( "QueryPage.php" );
+
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+class DeadendPagesPage extends PageQueryPage {
+
+       function getName( ) {
+               return "Deadendpages";
+       }
+
+       /**
+        * LEFT JOIN is expensive
+        *
+        * @return true
+        */
+       function isExpensive( ) {
+               return 1;
+       }
+       
+       function isSyndicated() { return false; }
+
+       /**
+        * @return false
+        */
+       function sortDescending() {
+               return false;
+       }
+       
+    /**
+        * @return string an sqlquery
+        */
+       function getSQL() {
+               $dbr =& wfGetDB( DB_SLAVE );
+               extract( $dbr->tableNames( 'page', 'pagelinks' ) );
+               return "SELECT 'Deadendpages' as type, page_namespace AS namespace, page_title as title, page_title AS value " . 
+       "FROM $page LEFT JOIN $pagelinks ON page_id = pl_from " .
+       "WHERE pl_from IS NULL " .
+       "AND page_namespace = 0 " .
+       "AND page_is_redirect = 0";
+    }
+}
+
+/**
+ * Constructor
+ */
+function wfSpecialDeadendpages() {
+    
+    list( $limit, $offset ) = wfCheckLimits();
+
+    $depp = new DeadendPagesPage();
+    
+    return $depp->doQuery( $offset, $limit );
+}
+
+?>
diff --git a/includes/SpecialDisambiguations.php b/includes/SpecialDisambiguations.php
new file mode 100644 (file)
index 0000000..b8f4ba3
--- /dev/null
@@ -0,0 +1,81 @@
+<?php
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/**
+ *
+ */
+require_once('QueryPage.php');
+
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+class DisambiguationsPage extends PageQueryPage {
+
+       function getName() {
+               return 'Disambiguations';
+       }
+       
+       function isExpensive( ) { return true; }
+       function isSyndicated() { return false; }
+
+       function getPageHeader( ) {
+               global $wgUser;
+               $sk = $wgUser->getSkin();
+               
+               #FIXME : probably need to add a backlink to the maintenance page.
+               return '<p>'.wfMsg("disambiguationstext", $sk->makeKnownLink(wfMsgForContent('disambiguationspage')) )."</p><br />\n";
+       }
+
+       function getSQL() {
+               $dbr =& wfGetDB( DB_SLAVE );
+               extract( $dbr->tableNames( 'page', 'pagelinks' ) );
+               
+               $dp = Title::newFromText(wfMsgForContent("disambiguationspage"));
+               $id = $dp->getArticleId();
+        $dns = $dp->getNamespace();
+        $dtitle = $dbr->addQuotes( $dp->getDBkey() );
+
+               $sql = "SELECT 'Disambiguations' AS type, pa.page_namespace AS namespace,"
+                        ." pa.page_title AS title, la.pl_from AS value"
+                        ." FROM {$pagelinks} AS lb, {$page} AS pa, {$pagelinks} AS la"
+                        ." WHERE lb.pl_namespace = $dns AND lb.pl_title = $dtitle" # disambiguation template
+                        ." AND pa.page_id = lb.pl_from"        
+                        ." AND pa.page_namespace = la.pl_namespace"
+                        ." AND pa.page_title = la.pl_title";
+               return $sql;
+       }
+
+       function getOrder() {
+               return '';
+       }
+       
+       function formatResult( $skin, $result ) {
+               global $wgContLang ;
+               $title = Title::newFromId( $result->value );
+        $dp = Title::makeTitle( $result->namespace, $result->title );
+
+               $from = $skin->makeKnownLinkObj( $title,'');
+               $edit = $skin->makeBrokenLinkObj( $title, "(".wfMsg("qbedit").")" , 'redirect=no');
+               $to   = $skin->makeKnownLinkObj( $dp,'');
+               
+               return "$from $edit => $to";
+       }
+}
+
+/**
+ * Constructor
+ */
+function wfSpecialDisambiguations() {
+       list( $limit, $offset ) = wfCheckLimits();
+       
+       $sd = new DisambiguationsPage();
+       
+       return $sd->doQuery( $offset, $limit );
+}
+?>
diff --git a/includes/SpecialDoubleRedirects.php b/includes/SpecialDoubleRedirects.php
new file mode 100644 (file)
index 0000000..3169844
--- /dev/null
@@ -0,0 +1,109 @@
+<?php
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/**
+ * 
+ */
+require_once('QueryPage.php');
+
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+class DoubleRedirectsPage extends PageQueryPage {
+
+       function getName() {
+               return 'DoubleRedirects';
+       }
+       
+       function isExpensive( ) { return true; }
+       function isSyndicated() { return false; }
+
+       function getPageHeader( ) {
+               #FIXME : probably need to add a backlink to the maintenance page.
+               return '<p>'.wfMsg("doubleredirectstext")."</p><br />\n";
+       }
+
+       function getSQL() {
+               $dbr =& wfGetDB( DB_SLAVE );
+               extract( $dbr->tableNames( 'page', 'pagelinks' ) );
+
+               $sql = "SELECT 'DoubleRedirects' as type," .
+                        " pa.page_namespace as namespace, pa.page_title as title," .
+                            " pb.page_namespace as nsb, pb.page_title as tb," .
+                                " pc.page_namespace as nsc, pc.page_title as tc" .
+                          " FROM $pagelinks AS la, $pagelinks AS lb, $page AS pa, $page AS pb, $page AS pc" .
+                          " WHERE pa.page_is_redirect=1 AND pb.page_is_redirect=1" .
+                            " AND la.pl_from=pa.page_id" .
+                                " AND la.pl_namespace=pb.page_namespace" .
+                                " AND la.pl_title=pb.page_title" .
+                                " AND lb.pl_from=pb.page_id" .
+                                " AND lb.pl_namespace=pc.page_namespace" .
+                                " AND lb.pl_title=pc.page_title";
+               return $sql;
+       }
+
+       function getOrder() {
+               return '';
+       }
+       
+       function formatResult( $skin, $result ) {
+               $fname = 'DoubleRedirectsPage::formatResult';
+               $titleA = Title::makeTitle( $result->namespace, $result->title );
+
+               if ( $result && !isset( $result->nsb ) ) {
+                       $dbr =& wfGetDB( DB_SLAVE );
+                       extract( $dbr->tableNames( 'page', 'pagelinks' ) );
+                       $encTitle = $dbr->addQuotes( $result->title );
+
+                       $sql = "SELECT pa.page_namespace as namespace, pa.page_title as title," .
+                                        " pb.page_namespace as nsb, pb.page_title as tb," .
+                                        " pc.page_namespace as nsc, pc.page_title as tc" .
+                                  " FROM $pagelinks AS la, $pagelinks AS lb, $page AS pa, $page AS pb, $page AS pc" .
+                                  " WHERE pa.page_is_redirect=1 AND pb.page_is_redirect=1" .
+                                        " AND la.pl_from=pa.page_id" .
+                                        " AND la.pl_namespace=pb.page_namespace" .
+                                        " AND la.pl_title=pb.page_title" .
+                                        " AND lb.pl_from=pb.page_id" .
+                                        " AND lb.pl_namespace=pc.page_namespace" .
+                                        " AND lb.pl_title=pc.page_title" .
+                                        " AND pa.page_namespace={$result->namespace}" .
+                                        " AND pa.page_title=$encTitle";
+                       $res = $dbr->query( $sql, $fname );
+                       if ( $res ) {
+                               $result = $dbr->fetchObject( $res );
+                       }
+               }
+               if ( !$result ) {
+                       return '';
+               }
+               
+               $titleB = Title::makeTitle( $result->nsb, $result->tb );
+               $titleC = Title::makeTitle( $result->nsc, $result->tc );
+
+               $linkA = $skin->makeKnownLinkObj( $titleA,'', 'redirect=no' );
+               $edit = $skin->makeBrokenLinkObj( $titleA, "(".wfMsg("qbedit").")" , 'redirect=no');
+               $linkB = $skin->makeKnownLinkObj( $titleB, '', 'redirect=no' );
+               $linkC = $skin->makeKnownLinkObj( $titleC );
+               
+               return "$linkA $edit &rarr; $linkB &rarr; $linkC";
+       }
+}
+
+/**
+ * constructor
+ */
+function wfSpecialDoubleRedirects() {
+       list( $limit, $offset ) = wfCheckLimits();
+       
+       $sdr = new DoubleRedirectsPage();
+       
+       return $sdr->doQuery( $offset, $limit );
+
+}
+?>
diff --git a/includes/SpecialEmailuser.php b/includes/SpecialEmailuser.php
new file mode 100644 (file)
index 0000000..2e667d5
--- /dev/null
@@ -0,0 +1,162 @@
+<?php
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/**
+ *
+ */
+require_once('UserMailer.php');
+
+function wfSpecialEmailuser( $par ) {
+       global $wgUser, $wgOut, $wgRequest, $wgEnableEmail, $wgEnableUserEmail;
+
+       if( !( $wgEnableEmail && $wgEnableUserEmail ) ) {
+               $wgOut->errorpage( "nosuchspecialpage", "nospecialpagetext" );
+               return;
+       }
+       
+       if( !$wgUser->canSendEmail() ) {
+               wfDebug( "User can't send.\n" );
+               $wgOut->errorpage( "mailnologin", "mailnologintext" );
+               return;
+       }
+       
+       $action = $wgRequest->getVal( 'action' );
+       $target = isset($par) ? $par : $wgRequest->getVal( 'target' );
+       if ( "" == $target ) {
+               wfDebug( "Target is empty.\n" );
+               $wgOut->errorpage( "notargettitle", "notargettext" );
+               return;
+       }
+       
+       $nt = Title::newFromURL( $target );
+       if ( is_null( $nt ) ) {
+               wfDebug( "Target is invalid title.\n" );
+               $wgOut->errorpage( "notargettitle", "notargettext" );
+               return;
+       }
+       
+       $nu = User::newFromName( $nt->getText() );
+       if( is_null( $nu ) || !$nu->canReceiveEmail() ) {
+               wfDebug( "Target is invalid user or can't receive.\n" );
+               $wgOut->errorpage( "noemailtitle", "noemailtext" );
+               return;
+       }
+
+       $address = $nu->getEmail();
+       $f = new EmailUserForm( $nu->getName() . " <{$address}>", $target );
+
+       if ( "success" == $action ) {
+               $f->showSuccess();
+       } else if ( "submit" == $action && $wgRequest->wasPosted() &&
+               $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) ) ) {
+               $f->doSubmit();
+       } else {
+               $f->showForm();
+       }
+}
+
+/**
+ * @todo document
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+class EmailUserForm {
+
+       var $mAddress;
+       var $target;
+       var $text, $subject;
+
+       function EmailUserForm( $addr, $target ) {
+               global $wgRequest;
+               $this->mAddress = $addr;
+               $this->target = $target;
+               $this->text = $wgRequest->getText( 'wpText' );
+               $this->subject = $wgRequest->getText( 'wpSubject' );
+       }
+
+       function showForm() {
+               global $wgOut, $wgUser, $wgLang;
+
+               $wgOut->setPagetitle( wfMsg( "emailpage" ) );
+               $wgOut->addWikiText( wfMsg( "emailpagetext" ) );
+
+               if ( $this->subject === "" ) { 
+                       $this->subject = wfMsg( "defemailsubject" ); 
+               }
+
+               $emf = wfMsg( "emailfrom" );
+               $sender = $wgUser->getName();
+               $emt = wfMsg( "emailto" );
+               $rcpt = str_replace( "_", " ", $this->target );
+               $emr = wfMsg( "emailsubject" );
+               $emm = wfMsg( "emailmessage" );
+               $ems = wfMsg( "emailsend" );
+               $encSubject = htmlspecialchars( $this->subject );
+               
+               $titleObj = Title::makeTitle( NS_SPECIAL, "Emailuser" );
+               $action = $titleObj->escapeLocalURL( "target=" .
+                       urlencode( $this->target ) . "&action=submit" );
+               $token = $wgUser->editToken();
+
+               $wgOut->addHTML( "
+<form id=\"emailuser\" method=\"post\" action=\"{$action}\">
+<table border='0'><tr>
+<td align='right'>{$emf}:</td>
+<td align='left'><strong>" . htmlspecialchars( $sender ) . "</strong></td>
+</tr><tr>
+<td align='right'>{$emt}:</td>
+<td align='left'><strong>" . htmlspecialchars( $rcpt ) . "</strong></td>
+</tr><tr>
+<td align='right'>{$emr}:</td>
+<td align='left'>
+<input type='text' name=\"wpSubject\" value=\"{$encSubject}\" />
+</td>
+</tr><tr>
+<td align='right'>{$emm}:</td>
+<td align='left'>
+<textarea name=\"wpText\" rows='10' cols='60' wrap='virtual'>" . htmlspecialchars( $this->text ) .
+"</textarea>
+</td></tr><tr>
+<td>&nbsp;</td><td align='left'>
+<input type='submit' name=\"wpSend\" value=\"{$ems}\" />
+</td></tr></table>
+<input type='hidden' name='wpEditToken' value=\"$token\" />
+</form>\n" );
+
+       }
+
+       function doSubmit() {
+               global $wgOut, $wgUser, $wgLang, $wgOutputEncoding;
+           
+               $from = wfQuotedPrintable( $wgUser->getName() ) . " <" . $wgUser->getEmail() . ">";
+               $subject = wfQuotedPrintable( $this->subject );
+               
+               if (wfRunHooks('EmailUser', array(&$this->mAddress, &$from, &$subject, &$this->text))) {
+                       
+                       $mailResult = userMailer( $this->mAddress, $from, $subject, $this->text );
+                       
+                       if( WikiError::isError( $mailResult ) ) {
+                               $wgOut->addHTML( wfMsg( "usermailererror" ) . $mailResult);
+                       } else {
+                               $titleObj = Title::makeTitle( NS_SPECIAL, "Emailuser" );
+                               $encTarget = wfUrlencode( $this->target );
+                               $wgOut->redirect( $titleObj->getFullURL( "target={$encTarget}&action=success" ) );
+                               wfRunHooks('EmailUserComplete', array($this->mAddress, $from, $subject, $this->text));
+                       }
+               }
+       }
+
+       function showSuccess() {
+               global $wgOut, $wgUser;
+
+               $wgOut->setPagetitle( wfMsg( "emailsent" ) );
+               $wgOut->addHTML( wfMsg( "emailsenttext" ) );
+
+               $wgOut->returnToMain( false );
+       }
+}
+?>
diff --git a/includes/SpecialExport.php b/includes/SpecialExport.php
new file mode 100644 (file)
index 0000000..5fda2be
--- /dev/null
@@ -0,0 +1,435 @@
+<?php
+# Copyright (C) 2003 Brion Vibber <brion@pobox.com>
+# http://www.mediawiki.org/
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or 
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# http://www.gnu.org/copyleft/gpl.html
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/** */
+require_once( 'Revision.php' );
+
+/**
+ *
+ */
+function wfSpecialExport( $page = '' ) {
+       global $wgOut, $wgLang, $wgRequest;
+       
+       if( $wgRequest->getVal( 'action' ) == 'submit') {
+               $page = $wgRequest->getText( 'pages' );
+               $curonly = $wgRequest->getCheck( 'curonly' );
+       } else {
+               # Pre-check the 'current version only' box in the UI
+               $curonly = true;
+       }
+       
+       if( $page != '' ) {
+               $wgOut->disable();
+               header( "Content-type: application/xml; charset=utf-8" );
+               $pages = explode( "\n", $page );
+               
+               $db =& wfGetDB( DB_SLAVE );
+               $history = $curonly ? MW_EXPORT_CURRENT : MW_EXPORT_FULL;
+               $exporter = new WikiExporter( $db, $history );
+               $exporter->openStream();
+               $exporter->pagesByName( $pages );
+               $exporter->closeStream();
+               return;
+       }
+       
+       $wgOut->addWikiText( wfMsg( "exporttext" ) );
+       $titleObj = Title::makeTitle( NS_SPECIAL, "Export" );
+       $action = $titleObj->escapeLocalURL( 'action=submit' );
+       $wgOut->addHTML( "
+<form method='post' action=\"$action\">
+<input type='hidden' name='action' value='submit' />
+<textarea name='pages' cols='40' rows='10'></textarea><br />
+<label><input type='checkbox' name='curonly' value='true' checked='checked' />
+" . wfMsg( "exportcuronly" ) . "</label><br />
+<input type='submit' />
+</form>
+" );
+}
+
+define( 'MW_EXPORT_FULL',     0 );
+define( 'MW_EXPORT_CURRENT',  1 );
+
+define( 'MW_EXPORT_BUFFER',   0 );
+define( 'MW_EXPORT_STREAM',   1 );
+
+/**
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+class WikiExporter {
+       var $pageCallback = null;
+       var $revCallback = null;
+       
+       /**
+        * If using MW_EXPORT_STREAM to stream a large amount of data,
+        * provide a database connection which is not managed by
+        * LoadBalancer to read from: some history blob types will
+        * make additional queries to pull source data while the
+        * main query is still running.
+        *
+        * @param Database $db
+        * @param int $history one of MW_EXPORT_FULL or MW_EXPORT_CURRENT
+        * @param int $buffer one of MW_EXPORT_BUFFER or MW_EXPORT_STREAM
+        */
+       function WikiExporter( &$db, $history = MW_EXPORT_CURRENT,
+                       $buffer = MW_EXPORT_BUFFER ) {
+               $this->db =& $db;
+               $this->history = $history;
+               $this->buffer  = $buffer;
+       }
+       
+       /**
+        * Set a callback to be called after each page in the output
+        * stream is closed. The callback will be passed a database row
+        * object with the last revision output.
+        *
+        * A set callback can be removed by passing null here.
+        *
+        * @param mixed $callback
+        */
+       function setPageCallback( $callback ) {
+               $this->pageCallback = $callback;
+       }
+       
+       /**
+        * Set a callback to be called after each revision in the output
+        * stream is closed. The callback will be passed a database row
+        * object with the revision data.
+        *
+        * A set callback can be removed by passing null here.
+        *
+        * @param mixed $callback
+        */
+       function setRevisionCallback( $callback ) {
+               $this->revCallback = $callback;
+       }
+       
+       /**
+        * Returns the export schema version.
+        * @return string
+        */
+       function schemaVersion() {
+               return "0.3";
+       }
+       
+       /**
+        * Opens the XML output stream's root <mediawiki> element.
+        * This does not include an xml directive, so is safe to include
+        * as a subelement in a larger XML stream. Namespace and XML Schema
+        * references are included.
+        *
+        * To capture the stream to a string, use PHP's output buffering
+        * functions. Output will be encoded in UTF-8.
+        */
+       function openStream() {
+               global $wgContLanguageCode;
+               $ver = $this->schemaVersion();
+               print wfElement( 'mediawiki', array(
+                       'xmlns'              => "http://www.mediawiki.org/xml/export-$ver/",
+                       'xmlns:xsi'          => "http://www.w3.org/2001/XMLSchema-instance",
+                       'xsi:schemaLocation' => "http://www.mediawiki.org/xml/export-$ver/ " .
+                                               "http://www.mediawiki.org/xml/export-$ver.xsd",
+                       'version'            => $ver,
+                       'xml:lang'           => $wgContLanguageCode ),
+                       null ) . "\n";
+               $this->siteInfo();
+       }
+       
+       function siteInfo() {
+               $info = array(
+                       $this->sitename(),
+                       $this->homelink(),
+                       $this->generator(),
+                       $this->caseSetting(),
+                       $this->namespaces() );
+               print "<siteinfo>\n";
+               foreach( $info as $item ) {
+                       print "  $item\n";
+               }
+               print "</siteinfo>\n";
+       }
+       
+       function sitename() {
+               global $wgSitename;
+               return wfElement( 'sitename', array(), $wgSitename );
+       }
+       
+       function generator() {
+               global $wgVersion;
+               return wfElement( 'generator', array(), "MediaWiki $wgVersion" );
+       }
+       
+       function homelink() {
+               $page = Title::newFromText( wfMsgForContent( 'mainpage' ) );
+               return wfElement( 'base', array(), $page->getFullUrl() );
+       }
+       
+       function caseSetting() {
+               global $wgCapitalLinks;
+               // "case-insensitive" option is reserved for future
+               $sensitivity = $wgCapitalLinks ? 'first-letter' : 'case-sensitive';
+               return wfElement( 'case', array(), $sensitivity );
+       }
+       
+       function namespaces() {
+               global $wgContLang;
+               $spaces = "<namespaces>\n";
+               foreach( $wgContLang->getNamespaces() as $ns => $title ) {
+                       $spaces .= '    ' . wfElement( 'namespace',
+                               array( 'key' => $ns ),
+                               str_replace( '_', ' ', $title ) ) . "\n";
+               }
+               $spaces .= "  </namespaces>";
+               return $spaces;
+       }
+       
+       /**
+        * Closes the output stream with the closing root element.
+        * Call when finished dumping things.
+        */
+       function closeStream() {
+               print "</mediawiki>\n";
+       }
+       
+       /**
+        * Dumps a series of page and revision records for all pages
+        * in the database, either including complete history or only
+        * the most recent version.
+        *
+        *
+        * @param Database $db
+        */
+       function allPages() {
+               return $this->dumpFrom( '' );
+       }
+       
+       /**
+        * @param Title $title
+        */
+       function pageByTitle( $title ) {
+               return $this->dumpFrom(
+                       'page_namespace=' . $title->getNamespace() .
+                       ' AND page_title=' . $this->db->addQuotes( $title->getDbKey() ) );
+       }
+       
+       function pageByName( $name ) {
+               $title = Title::newFromText( $name );
+               if( is_null( $title ) ) {
+                       return new WikiError( "Can't export invalid title" );
+               } else {
+                       return $this->pageByTitle( $title );
+               }
+       }
+       
+       function pagesByName( $names ) {
+               foreach( $names as $name ) {
+                       $this->pageByName( $name );
+               }
+       }
+
+       
+       // -------------------- private implementation below --------------------
+       
+       function dumpFrom( $cond = '' ) {
+               $fname = 'WikiExporter::dumpFrom';
+               wfProfileIn( $fname );
+               
+               $page     = $this->db->tableName( 'page' );
+               $revision = $this->db->tableName( 'revision' );
+               $text     = $this->db->tableName( 'text' );
+               
+               if( $this->history == MW_EXPORT_FULL ) {
+                       $join = 'page_id=rev_page';
+               } elseif( $this->history == MW_EXPORT_CURRENT ) {
+                       $join = 'page_id=rev_page AND page_latest=rev_id';
+               } else {
+                       wfProfileOut( $fname );
+                       return new WikiError( "$fname given invalid history dump type." );
+               }
+               $where = ( $cond == '' ) ? '' : "$cond AND";
+               
+               if( $this->buffer == MW_EXPORT_STREAM ) {
+                       $prev = $this->db->bufferResults( false );
+               }
+               if( $cond == '' ) {
+                       // Optimization hack for full-database dump
+                       $pageindex = 'FORCE INDEX (PRIMARY)';
+                       $revindex = 'FORCE INDEX(page_timestamp)';
+               } else {
+                       $pageindex = '';
+                       $revindex = '';
+               }
+               $result = $this->db->query(
+                       "SELECT * FROM
+                               $page $pageindex,
+                               $revision $revindex,
+                               $text
+                               WHERE $where $join AND rev_text_id=old_id
+                               ORDER BY page_id", $fname );
+               $wrapper = $this->db->resultObject( $result );
+               $this->outputStream( $wrapper );
+               
+               if( $this->buffer == MW_EXPORT_STREAM ) {
+                       $this->db->bufferResults( $prev );
+               }
+               
+               wfProfileOut( $fname );
+       }
+       
+       /**
+        * Runs through a query result set dumping page and revision records.
+        * The result set should be sorted/grouped by page to avoid duplicate
+        * page records in the output.
+        *
+        * The result set will be freed once complete. Should be safe for
+        * streaming (non-buffered) queries, as long as it was made on a
+        * separate database connection not managed by LoadBalancer; some
+        * blob storage types will make queries to pull source data.
+        *
+        * @param ResultWrapper $resultset
+        * @access private
+        */
+       function outputStream( $resultset ) {
+               $last = null;
+               while( $row = $resultset->fetchObject() ) {
+                       if( is_null( $last ) ||
+                               $last->page_namespace != $row->page_namespace ||
+                               $last->page_title     != $row->page_title ) {
+                               if( isset( $last ) ) {
+                                       $this->closePage( $last );
+                               }
+                               $this->openPage( $row );
+                               $last = $row;
+                       }
+                       $this->dumpRev( $row );
+               }
+               if( isset( $last ) ) {
+                       $this->closePage( $last );
+               }
+               $resultset->free();
+       }
+       
+       /**
+        * Opens a <page> section on the output stream, with data
+        * from the given database row.
+        *
+        * @param object $row
+        * @access private
+        */
+       function openPage( $row ) {
+               print "<page>\n";
+               $title = Title::makeTitle( $row->page_namespace, $row->page_title );
+               print '  ' . wfElementClean( 'title', array(), $title->getPrefixedText() ) . "\n";
+               print '  ' . wfElement( 'id', array(), $row->page_id ) . "\n";
+               if( '' != $row->page_restrictions ) {
+                       print '  ' . wfElement( 'restrictions', array(),
+                               $row->page_restrictions ) . "\n";
+               }
+       }
+       
+       /**
+        * Closes a <page> section on the output stream.
+        * If a per-page callback has been set, it will be called
+        * and passed the last database row used for this page.
+        *
+        * @param object $row
+        * @access private
+        */
+       function closePage( $row ) {
+               print "</page>\n";
+               if( isset( $this->pageCallback ) ) {
+                       call_user_func( $this->pageCallback, $row );
+               }
+       }
+       
+       /**
+        * Dumps a <revision> section on the output stream, with
+        * data filled in from the given database row.
+        *
+        * @param object $row
+        * @access private
+        */
+       function dumpRev( $row ) {
+               $fname = 'WikiExporter::dumpRev';
+               wfProfileIn( $fname );
+               
+               print "    <revision>\n";
+               print "      " . wfElement( 'id', null, $row->rev_id ) . "\n";
+               
+               $ts = wfTimestamp2ISO8601( $row->rev_timestamp );
+               print "      " . wfElement( 'timestamp', null, $ts ) . "\n";
+               
+               print "      <contributor>";
+               if( $row->rev_user ) {
+                       print wfElementClean( 'username', null, $row->rev_user_text );
+                       print wfElement( 'id', null, $row->rev_user );
+               } else {
+                       print wfElementClean( 'ip', null, $row->rev_user_text );
+               }
+               print "</contributor>\n";
+               
+               if( $row->rev_minor_edit ) {
+                       print  "      <minor/>\n";
+               }
+               if( $row->rev_comment != '' ) {
+                       print "      " . wfElementClean( 'comment', null, $row->rev_comment ) . "\n";
+               }
+       
+               $text = Revision::getRevisionText( $row );
+               print "      " . wfElementClean( 'text',
+                       array( 'xml:space' => 'preserve' ), $text ) . "\n";
+               
+               print "    </revision>\n";
+               
+               wfProfileOut( $fname );
+               
+               if( isset( $this->revCallback ) ) {
+                       call_user_func( $this->revCallback, $row );
+               }
+       }
+
+}
+
+function wfTimestamp2ISO8601( $ts ) {
+       #2003-08-05T18:30:02Z
+       return preg_replace( '/^(....)(..)(..)(..)(..)(..)$/', '$1-$2-$3T$4:$5:$6Z', $ts );
+}
+
+function xmlsafe( $string ) {
+       $fname = 'xmlsafe';
+       wfProfileIn( $fname );
+       
+       /**
+        * The page may contain old data which has not been properly normalized.
+        * Invalid UTF-8 sequences or forbidden control characters will make our
+        * XML output invalid, so be sure to strip them out.
+        */
+       $string = UtfNormal::cleanUp( $string );
+       
+       $string = htmlspecialchars( $string );
+       wfProfileOut( $fname );
+       return $string;
+}
+
+?>
diff --git a/includes/SpecialGroups.php b/includes/SpecialGroups.php
new file mode 100644 (file)
index 0000000..39bbe62
--- /dev/null
@@ -0,0 +1,275 @@
+<?php
+/**
+ * Provide an administration interface
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/** */
+require_once('HTMLForm.php');
+require_once('Group.php');
+
+/** Entry point */
+function wfSpecialGroups() {
+       global $wgRequest;
+       
+       $form = new GroupsForm($wgRequest);
+       $form->execute();
+}
+
+/**
+ * A class to manage group levels rights.
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+class GroupsForm extends HTMLForm {
+       var $mPosted, $mRequest, $mSaveprefs, $mChangeAllowed;
+       var $mNewName, $mDescription, $mOldName, $mRights, $mId;
+       var $mAdd, $mEdit;
+       
+       /** Escaped local url name*/
+       var $action, $location;
+
+       /** Constructor*/
+       function GroupsForm ( &$request ) {
+               global $wgUser;
+               
+               $this->mPosted = $request->wasPosted();
+               $this->mRequest =& $request;
+               $this->mName = 'groups';
+
+               $this->mNewName = trim( $request->getText('editgroup-name') );
+               $this->mOldName = trim( $request->getText('editgroup-oldname' ) );
+               $this->mDescription = trim( $request->getText( 'editgroup-description' ) );
+               $this->mRights = $request->getArray( 'editgroup-getrights' );
+               $this->mId = $this->mRequest->getInt('id');
+               $this->mEdit = $request->getCheck('edit');
+               $this->mAdd = $request->getCheck('add');
+
+
+               $titleObj = Title::makeTitle( NS_SPECIAL, 'Groups' );
+               $this->action = $titleObj->escapeLocalURL();
+               if ( $this->mAdd ) {
+                       $this->location = $titleObj->getLocalURL( "add=1&id={$this->mId}" );
+               } elseif ( $this->mEdit ) {
+                       $this->location = $titleObj->getLocalURL( "edit=1&id={$this->mId}" );
+               } else {
+                       $this->location = $this->action;
+               }
+
+               $this->mChangeAllowed = $wgUser->isAllowed( 'grouprights' ) && !Group::getStaticGroups();
+       }
+
+       /**
+        * Manage forms to be shown according to posted data
+        * Depending on the submit button used, call a form or a saving function.
+        */
+       function execute() {
+               global $wgOut;
+
+               if ( $this->mRequest->getBool( 'showrecord' ) ) {
+                       $this->showRecord();
+               } elseif ( $this->mPosted && $this->mChangeAllowed && $this->mRequest->getCheck('savegroup') ) {
+                       // save settings
+                       $this->saveGroup();
+               } elseif ( $this->mEdit ) {
+                       if ( $this->mPosted ) {
+                               $wgOut->redirect( $this->location );
+                       } else {                        
+                               $this->switchForm();
+                               $this->editGroupForm( $this->mId ); 
+                       }
+               } elseif ( $this->mAdd ) {
+                       if ( $this->mPosted ) {
+                               $wgOut->redirect( $this->location );
+                       } else {
+                               $this->switchForm();
+                               $this->editGroupForm( ); 
+                       }
+               } else {
+                       $this->showAllGroups();
+                       if ( $this->mChangeAllowed ) {
+                               $this->switchForm();
+                       }
+               }
+       }
+
+       /**
+        * Save a group
+        */
+       function saveGroup() {
+               global $wgOut;
+
+               $this->mNewName = trim($this->mNewName);
+       
+               if ( $this->mNewName == '' ) {
+                       $this->editGroupForm( $this->mGroupID, 'groups-noname' );
+                       return false;
+               }
+
+               if($this->mOldName == '') {
+                       // Check if the group already exists
+                       $add = true;
+                       $g = Group::newFromName( $this->mNewName );
+                       if ( $g ) {
+                               $this->editGroupForm( 0, 'groups-already-exists' );
+                               return;
+                       }
+
+                       // Create a new group
+                       $g = new Group();
+                       $g->addToDatabase();
+               } else {
+                       $add = false;
+                       $g = Group::newFromName($this->mOldName);
+                       if ( !$g ) {
+                               $this->editGroupForm( 0, 'groups-noname' );
+                               return;
+                       }
+               }
+               
+               // save stuff
+               $g->setName($this->mNewName);
+               $g->setDescription($this->mDescription);
+               if( is_array( $this->mRights ) ) { 
+                       $g->setRights( implode(',',$this->mRights) ); 
+               }
+               
+               $g->save();
+               
+               // Make the log entry
+               $log = new LogPage( 'rights' );
+               $dummyTitle = Title::makeTitle( 0, '' );
+               if ( $add ) {
+                       $log->addEntry( 'addgroup', $dummyTitle, '', array( $g->getNameForContent() ) );
+               } else {
+                       if ( $this->mOldName != $this->mNewName ) {
+                               // Abbreviated action name, must be less than 10 bytes
+                               $log->addEntry( 'rngroup', $dummyTitle, '', array( Group::getMessageForContent( $this->mOldName ), 
+                               $g->getNameForContent() ) );
+                       } else {
+                               $log->addEntry( 'chgroup', $dummyTitle, '', array( $g->getNameForContent() ) );
+                       }
+               }
+
+               // Success, go back to all groups page
+               $titleObj = Title::makeTitle( NS_SPECIAL, 'Groups' );
+               $url = $titleObj->getLocalURL();
+
+               $wgOut->redirect( $url );
+       }
+
+       /**
+        * The entry form
+        * It allows a user to edit or eventually add a group
+        */
+       function switchForm() {
+               global $wgOut;
+               
+               // group selection              
+               $wgOut->addHTML( "<form name=\"ulgroup\" action=\"$this->action\" method=\"post\">\n" );
+               $wgOut->addHTML( $this->fieldset( 'lookup-group',
+                               HTMLSelectGroups('id', $this->mName.'-group-edit', array(0 => $this->mRequest->getVal('id')) ) .
+                               ' <input type="submit" name="edit" value="'.wfMsg('editgroup').'" />' .
+                               '<br /><input type="submit" name="add" value="'.wfMsg('addgroup').'" />'
+                       ));
+               $wgOut->addHTML( "</form>\n" );
+       }
+
+       /**
+        * Edit a group properties and rights.
+        * @param string $groupname Name of a group to be edited.
+        * @param string $error message name of the error to display
+        */
+       function editGroupForm($groupID = 0, $error = '') {
+               global $wgOut;
+
+               if ( $error ) {
+                       $errText = wfMsg( $error );
+                       $wgOut->addHTML( "<p class='error'>$errText</p>" );
+               }
+
+               if($this->mRequest->getVal('edit')) {
+               // fetch data if we edit a group
+                       $g = Group::newFromID($groupID);
+                       $fieldname = 'editgroup';
+               } else {
+               // default data when we add a group
+                       $g = new Group();
+                       $fieldname = 'addgroup';
+               }
+
+               $gName = htmlspecialchars( $g->getName() );
+               $gDescription = htmlspecialchars( $g->getDescription() );
+
+
+               $wgOut->addHTML( "<form name=\"editGroup\" action=\"{$this->action}\" method=\"post\">\n".
+                               '<input type="hidden" name="editgroup-oldname" value="'.$gName."\" />\n" );
+
+               $wgOut->addHTML( $this->fieldset( $fieldname,
+                       '<p>' . wfMsg( 'groups-editgroup-preamble' ) . "</p>\n" .
+                       $this->textbox( 'editgroup-name', $gName ) .
+                       $this->textareabox( 'editgroup-description', $gDescription ) .
+                       '<br /><table border="0" align="center"><tr><td>'.
+                       HTMLSelectRights($g->getRights()).
+                       '</td></tr></table>'."\n".
+                       '<input type="submit" name="savegroup" value="'.wfMsg('savegroup').'" />'
+                       ));
+
+               $wgOut->addHTML( "</form>\n" );
+       }
+
+       function showAllGroups() {
+               global $wgOut;
+               $groups =& Group::getAllGroups();
+
+               $groupsExisting = wfMsg( 'groups-existing' );
+               $groupsHeader = wfMsg( 'groups-tableheader' );
+
+               $s = "{| border=1
+|+'''$groupsExisting'''
+|-
+!$groupsHeader
+";
+               foreach ( $groups as $group ) {
+                       $s .= "|-\n| " . $group->getId() . ' || ' .
+                               $group->getExpandedName() . ' || ' .
+                               $group->getExpandedDescription() . ' || '. 
+                               // Insert spaces to make it wrap
+                               str_replace( ',', ', ', $group->getRights() ) . "\n";
+               }
+               $s .= "|}\n";
+               $wgOut->addWikiText( $s );
+       }
+               
+       function showRecord() {
+               global $wgOut;
+               
+               $groups =& Group::getAllGroups();
+               $rec = serialize( $groups );
+               // Split it into lines
+               $rec = explode( "\r\n", chunk_split( $rec ) );
+               $s = '';
+               foreach ( $rec as $index => $line ) {
+                       if ( trim( $line ) != '' ) {
+                               if ( $s ) {
+                                       $s .= "' .\n\t'";
+                               }
+                               // Escape it for PHP
+                               $line = str_replace( array( '\\', "'" ), array( '\\\\', "\\'" ), $line );
+                               // Escape it for HTML
+                               $line = htmlspecialchars( $line );
+                               // Add it to the string
+                               $s .= $line;
+                       }
+               }
+               $s .= "';";
+               $s = "<p>Copy the following into LocalSettings.php:</p>\n" .
+                 "<textarea readonly rows=20>\n" .
+                 "\$wgStaticGroups = \n\t'$s\n" .
+                 "</textarea>";
+               $wgOut->addHTML( $s );
+       }
+
+} // end class GroupsForm
+?>
diff --git a/includes/SpecialImagelist.php b/includes/SpecialImagelist.php
new file mode 100644 (file)
index 0000000..1ac3384
--- /dev/null
@@ -0,0 +1,136 @@
+<?php
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/**
+ *
+ */
+function wfSpecialImagelist() {
+       global $wgUser, $wgOut, $wgLang, $wgContLang, $wgRequest, $wgMiserMode;
+       
+       $sort = $wgRequest->getVal( 'sort' );
+       $wpIlMatch = $wgRequest->getText( 'wpIlMatch' );
+       $dbr =& wfGetDB( DB_SLAVE );
+       $image = $dbr->tableName( 'image' );
+       $sql = "SELECT img_size,img_name,img_user,img_user_text," .
+         "img_description,img_timestamp FROM $image";
+
+       $byname = wfMsg( "byname" );
+       $bydate = wfMsg( "bydate" );
+       $bysize = wfMsg( "bysize" );
+
+       if ( !$wgMiserMode && !empty( $wpIlMatch ) ) {
+               $nt = Title::newFromUrl( $wpIlMatch );
+               if($nt ) {
+                       $m = $dbr->strencode( strtolower( $nt->getDBkey() ) );
+                       $m = str_replace( "%", "\\%", $m );
+                       $m = str_replace( "_", "\\_", $m );
+                       $sql .= " WHERE LCASE(img_name) LIKE '%{$m}%'";
+               }
+       }
+       if ( "bysize" == $sort ) {
+               $sql .= " ORDER BY img_size DESC";
+               $st = $bysize;
+       } else if ( "byname" == $sort ) {
+               $sql .= " ORDER BY img_name";
+               $st = $byname;
+       } else {
+               $sort = "bydate";
+               $sql .= " ORDER BY img_timestamp DESC";
+               $st = $bydate;
+       }
+       list( $limit, $offset ) = wfCheckLimits( 50 );
+       if ( 0 == $limit ) {
+               $lt = wfMsg( 'imagelistall' );
+       } else {
+               $lt = $wgLang->formatNum( "${limit}" );
+               $sql .= " LIMIT {$limit}";
+       }
+       $wgOut->addHTML( "<p>" . wfMsg( "imglegend" ) . "</p>\n" );
+
+       $text = wfMsg( "imagelisttext",
+               "<strong>{$lt}</strong>", "<strong>{$st}</strong>" );
+       $wgOut->addHTML( "<p>{$text}\n</p>" );
+
+       $sk = $wgUser->getSkin();
+       $sub = wfMsg( "ilsubmit" );
+       $titleObj = Title::makeTitle( NS_SPECIAL, "Imagelist" );
+       $action = $titleObj->escapeLocalURL(  "sort={$sort}&limit={$limit}" );
+
+       if ( !$wgMiserMode ) {
+               $wgOut->addHTML( "<form id=\"imagesearch\" method=\"post\" action=\"" .
+                 "{$action}\">" .
+                 "<input type='text' size='20' name=\"wpIlMatch\" value=\"" .
+                 htmlspecialchars( $wpIlMatch ) . "\" /> " .
+                 "<input type='submit' name=\"wpIlSubmit\" value=\"{$sub}\" /></form>" );
+       }
+       $nums = array( 50, 100, 250, 500 );
+       $here = Title::makeTitle( NS_SPECIAL, 'Imagelist' );
+
+       $fill = "";
+       $first = true;
+       foreach ( $nums as $num ) {
+               if ( ! $first ) { $fill .= " | "; }
+               $first = false;
+
+               $fill .= $sk->makeKnownLinkObj( $here, $wgLang->formatNum( $num ),
+                 "sort=byname&limit={$num}&wpIlMatch=" . urlencode( $wpIlMatch ) );
+       }
+       $text = wfMsg( "showlast", $fill, $byname );
+       $wgOut->addHTML( "<p>{$text}<br />\n" );
+
+       $fill = "";
+       $first = true;
+       foreach ( $nums as $num ) {
+               if ( ! $first ) { $fill .= " | "; }
+               $first = false;
+
+               $fill .= $sk->makeKnownLinkObj( $here, $wgLang->formatNum( $num ),
+                 "sort=bysize&limit={$num}&wpIlMatch=" . urlencode( $wpIlMatch ) );
+       }
+       $text = wfMsg( "showlast", $fill, $bysize );
+       $wgOut->addHTML( "{$text}<br />\n" );
+
+       $fill = "";
+       $first = true;
+       foreach ( $nums as $num ) {
+               if ( ! $first ) { $fill .= " | "; }
+               $first = false;
+
+               $fill .= $sk->makeKnownLinkObj( $here, $wgLang->formatNum( $num ),
+                 "sort=bydate&limit={$num}&wpIlMatch=" . urlencode( $wpIlMatch ) );
+       }
+       $text = wfMsg( "showlast", $fill, $bydate );
+       $wgOut->addHTML( "{$text}</p>\n<p>" );
+
+       $res = $dbr->query( $sql, "wfSpecialImagelist" );
+       while ( $s = $dbr->fetchObject( $res ) ) {
+               $name = $s->img_name;
+               $ut = $s->img_user_text;
+               if ( 0 == $s->img_user ) {
+                       $ul = $ut;
+               } else {
+                       $ul = $sk->makeLinkObj( Title::makeTitle( NS_USER, $ut ), $ut );
+               }
+
+               $ilink = "<a href=\"" . htmlspecialchars( Image::imageUrl( $name ) ) .
+                 "\">" . strtr(htmlspecialchars( $name ), '_', ' ') . "</a>";
+
+               $nb = wfMsg( "nbytes", $wgLang->formatNum( $s->img_size ) );
+               $l = "(" .
+                 $sk->makeKnownLinkObj( Title::makeTitle( NS_IMAGE, $name ),
+                 wfMsg( "imgdesc" ) ) .
+                 ") {$ilink} . . {$nb} . . {$ul} . . " .
+                 $wgLang->timeanddate( $s->img_timestamp, true );
+
+               $l .= $sk->commentBlock( $s->img_description );
+               $wgOut->addHTML( "{$l}<br />\n" );
+       }
+       $wgOut->addHTML( "</p>" );
+       $dbr->freeResult( $res );
+}
+
+?>
diff --git a/includes/SpecialImport.php b/includes/SpecialImport.php
new file mode 100644 (file)
index 0000000..728f80c
--- /dev/null
@@ -0,0 +1,642 @@
+<?php
+/**
+ * MediaWiki page data importer
+ * Copyright (C) 2003,2005 Brion Vibber <brion@pobox.com>
+ * http://www.mediawiki.org/
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or 
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/** */
+require_once( 'WikiError.php' );
+
+/**
+ * Constructor
+ */
+function wfSpecialImport( $page = '' ) {
+       global $wgUser, $wgOut, $wgLang, $wgRequest, $wgTitle;
+       global $wgImportSources;
+       
+       ###
+#      $wgOut->addWikiText( "Special:Import is not ready for this beta release, sorry." );
+#      return;
+       ###
+       
+       if( $wgRequest->wasPosted() && $wgRequest->getVal( 'action' ) == 'submit') {
+               switch( $wgRequest->getVal( "source" ) ) {
+               case "upload":
+                       if( $wgUser->isAllowed( 'importupload' ) ) {
+                               $source = ImportStreamSource::newFromUpload( "xmlimport" );
+                       } else {
+                               return $wgOut->permissionRequired( 'importupload' );
+                       }
+                       break;
+               case "interwiki":
+                       $source = ImportStreamSource::newFromInterwiki(
+                               $wgRequest->getVal( "interwiki" ),
+                               $wgRequest->getText( "frompage" ) );
+                       break;
+               default:
+                       $source = new WikiError( "Unknown import source type" );
+               }
+               
+               if( WikiError::isError( $source ) ) {
+                       $wgOut->addWikiText( wfEscapeWikiText( $source->getMessage() ) );
+               } else {
+                       $importer = new WikiImporter( $source );
+                       $result = $importer->doImport();
+                       if( WikiError::isError( $result ) ) {
+                               $wgOut->addWikiText( wfMsg( "importfailed",
+                                       wfEscapeWikiText( $result->getMessage() ) ) );
+                       } else {
+                               # Success!
+                               $wgOut->addWikiText( wfMsg( "importsuccess" ) );
+                       }
+               }
+       }
+       
+       $action = $wgTitle->escapeLocalUrl( 'action=submit' );
+       
+       if( $wgUser->isAllowed( 'importupload' ) ) {
+               $wgOut->addWikiText( wfMsg( "importtext" ) );
+               $wgOut->addHTML( "
+<fieldset>
+       <legend>" . wfMsgHtml('upload') . "</legend>
+       <form enctype='multipart/form-data' method='post' action=\"$action\">
+               <input type='hidden' name='action' value='submit' />
+               <input type='hidden' name='source' value='upload' />
+               <input type='hidden' name='MAX_FILE_SIZE' value='2000000' />
+               <input type='file' name='xmlimport' value='' size='30' />
+               <input type='submit' value='" . wfMsgHtml( "uploadbtn" ) . "'/>
+       </form>
+</fieldset>
+" );
+       } else {
+               if( empty( $wgImportSources ) ) {
+                       $wgOut->addWikiText( wfMsg( 'importnosources' ) );
+               }
+       }
+       
+       if( !empty( $wgImportSources ) ) {
+               $wgOut->addHTML( "
+<fieldset>
+       <legend>" . wfMsgHtml('importinterwiki') . "</legend>
+       <form method='post' action=\"$action\">
+               <input type='hidden' name='action' value='submit' />
+               <input type='hidden' name='source' value='interwiki' />
+               <select name='interwiki'>
+" );
+               foreach( $wgImportSources as $interwiki ) {
+                       $iw = htmlspecialchars( $interwiki );
+                       $wgOut->addHTML( "<option value=\"$iw\">$iw</option>\n" );
+               }
+               $wgOut->addHTML( "
+               </select>
+               <input name='frompage' />
+               <input type='submit' />
+       </form>
+</fieldset>
+" );
+       }
+}
+
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+class WikiRevision {
+       var $title = NULL;
+       var $timestamp = "20010115000000";
+       var $user = 0;
+       var $user_text = "";
+       var $text = "";
+       var $comment = "";
+       var $minor = false;
+       
+       function setTitle( $text ) {
+               $this->title = Title::newFromText( $text );
+       }
+       
+       function setTimestamp( $ts ) {
+               # 2003-08-05T18:30:02Z
+               $this->timestamp = preg_replace( '/^(....)-(..)-(..)T(..):(..):(..)Z$/', '$1$2$3$4$5$6', $ts );
+       }
+       
+       function setUsername( $user ) {
+               $this->user_text = $user;
+       }
+       
+       function setUserIP( $ip ) {
+               $this->user_text = $ip;
+       }
+       
+       function setText( $text ) {
+               $this->text = $text;
+       }
+       
+       function setComment( $text ) {
+               $this->comment = $text;
+       }
+       
+       function setMinor( $minor ) {
+               $this->minor = (bool)$minor;
+       }
+       
+       function getTitle() {
+               return $this->title;
+       }
+       
+       function getTimestamp() {
+               return $this->timestamp;
+       }
+       
+       function getUser() {
+               return $this->user_text;
+       }
+       
+       function getText() {
+               return $this->text;
+       }
+       
+       function getComment() {
+               return $this->comment;
+       }
+       
+       function getMinor() {
+               return $this->minor;
+       }
+
+       function importOldRevision() {
+               $fname = "WikiImporter::importOldRevision";
+               $dbw =& wfGetDB( DB_MASTER );
+               
+               # Sneak a single revision into place
+               $user = User::newFromName( $this->getUser() );
+               if( $user ) {
+                       $userId = IntVal( $user->getId() );
+                       $userText = $user->getName();
+               } else {
+                       $userId = 0;
+                       $userText = $this->getUser();
+               }
+
+               // avoid memory leak...?
+               global $wgLinkCache;
+               $wgLinkCache->clear();
+               
+               $article = new Article( $this->title );
+               $pageId = $article->getId();
+               if( $pageId == 0 ) {
+                       # must create the page...
+                       $pageId = $article->insertOn( $dbw );
+               }
+               
+               # FIXME: Check for exact conflicts
+               # FIXME: Use original rev_id optionally
+               # FIXME: blah blah blah
+               
+               #if( $numrows > 0 ) {
+               #       return wfMsg( "importhistoryconflict" );
+               #}
+               
+               # Insert the row
+               $revision = new Revision( array(
+                       'page'       => $pageId,
+                       'text'       => $this->getText(),
+                       'comment'    => $this->getComment(),
+                       'user'       => $userId,
+                       'user_text'  => $userText,
+                       'timestamp'  => $this->timestamp,
+                       'minor_edit' => $this->minor,
+                       ) );
+               $revId = $revision->insertOn( $dbw );
+               $article->updateIfNewerOn( $dbw, $revision );
+               
+               return true;
+       }
+
+}
+
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+class WikiImporter {
+       var $mSource = null;
+       var $mPageCallback = null;
+       var $mRevisionCallback = null;
+       var $lastfield;
+       
+       function WikiImporter( $source ) {
+               $this->setRevisionCallback( array( &$this, "importRevision" ) );
+               $this->mSource = $source;
+       }
+       
+       function throwXmlError( $err ) {
+               $this->debug( "FAILURE: $err" );
+               wfDebug( "WikiImporter XML error: $err\n" );
+       }
+       
+       # --------------
+       
+       function doImport() {
+               if( empty( $this->mSource ) ) {
+                       return new WikiErrorMsg( "importnotext" );
+               }
+               
+               $parser = xml_parser_create( "UTF-8" );
+               
+               # case folding violates XML standard, turn it off
+               xml_parser_set_option( $parser, XML_OPTION_CASE_FOLDING, false );
+               
+               xml_set_object( $parser, $this );
+               xml_set_element_handler( $parser, "in_start", "" );
+               
+               $offset = 0; // for context extraction on error reporting
+               do {
+                       $chunk = $this->mSource->readChunk();
+                       if( !xml_parse( $parser, $chunk, $this->mSource->atEnd() ) ) {
+                               wfDebug( "WikiImporter::doImport encountered XML parsing error\n" );
+                               return new WikiXmlError( $parser, 'XML import parse failure', $chunk, $offset );
+                       }
+                       $offset += strlen( $chunk );
+               } while( $chunk !== false && !$this->mSource->atEnd() );
+               xml_parser_free( $parser );
+               
+               return true;
+       }
+       
+       function debug( $data ) {
+               #wfDebug( "IMPORT: $data\n" );
+       }
+       
+       function notice( $data ) {
+               global $wgCommandLineMode;
+               if( $wgCommandLineMode ) {
+                       print "$data\n";
+               } else {
+                       global $wgOut;
+                       $wgOut->addHTML( "<li>$data</li>\n" );
+               }
+       }
+       
+       /**
+        * Sets the action to perform as each new page in the stream is reached.
+        * @param callable $callback
+        * @return callable
+        */
+       function setPageCallback( $callback ) {
+               $previous = $this->mPageCallback;
+               $this->mPageCallback = $callback;
+               return $previous;
+       }
+       
+       /**
+        * Sets the action to perform as each page revision is reached.
+        * @param callable $callback
+        * @return callable
+        */
+       function setRevisionCallback( $callback ) {
+               $previous = $this->mRevisionCallback;
+               $this->mRevisionCallback = $callback;
+               return $previous;
+       }
+       
+       /**
+        * Default per-revision callback, performs the import.
+        * @param WikiRevision $revision
+        * @access private
+        */
+       function importRevision( &$revision ) {
+               $dbw =& wfGetDB( DB_MASTER );
+               $dbw->deadlockLoop( array( &$revision, 'importOldRevision' ) );
+       }
+
+       /**
+        * Alternate per-revision callback, for debugging.
+        * @param WikiRevision $revision
+        * @access private
+        */
+       function debugRevisionHandler( &$revision ) {
+               $this->debug( "Got revision:" );
+               if( is_object( $revision->title ) ) {
+                       $this->debug( "-- Title: " . $revision->title->getPrefixedText() );
+               } else {
+                       $this->debug( "-- Title: <invalid>" );
+               }
+               $this->debug( "-- User: " . $revision->user_text );
+               $this->debug( "-- Timestamp: " . $revision->timestamp );
+               $this->debug( "-- Comment: " . $revision->comment );
+               $this->debug( "-- Text: " . $revision->text );
+       }
+       
+       /**
+        * Notify the callback function when a new <page> is reached.
+        * @param Title $title
+        * @access private
+        */
+       function pageCallback( $title ) {
+               if( is_callable( $this->mPageCallback ) ) {
+                       call_user_func( $this->mPageCallback, $title );
+               }
+       }
+       
+       
+       # XML parser callbacks from here out -- beware!
+       function donothing( $parser, $x, $y="" ) {
+               #$this->debug( "donothing" );
+       }
+       
+       function in_start( $parser, $name, $attribs ) {
+               $this->debug( "in_start $name" );
+               if( $name != "mediawiki" ) {
+                       return $this->throwXMLerror( "Expected <mediawiki>, got <$name>" );
+               }
+               xml_set_element_handler( $parser, "in_mediawiki", "out_mediawiki" );
+       }
+       
+       function in_mediawiki( $parser, $name, $attribs ) {
+               $this->debug( "in_mediawiki $name" );
+               if( $name == 'siteinfo' ) {
+                       xml_set_element_handler( $parser, "in_siteinfo", "out_siteinfo" );
+               } elseif( $name == 'page' ) {
+                       xml_set_element_handler( $parser, "in_page", "out_page" );
+               } else {
+                       return $this->throwXMLerror( "Expected <page>, got <$name>" );
+               }
+       }
+       function out_mediawiki( $parser, $name ) {
+               $this->debug( "out_mediawiki $name" );
+               if( $name != "mediawiki" ) {
+                       return $this->throwXMLerror( "Expected </mediawiki>, got </$name>" );
+               }
+               xml_set_element_handler( $parser, "donothing", "donothing" );
+       }
+       
+       
+       function in_siteinfo( $parser, $name, $attribs ) {
+               // no-ops for now
+               $this->debug( "in_siteinfo $name" );
+               switch( $name ) {
+               case "sitename":
+               case "base":
+               case "generator":
+               case "case":
+               case "namespaces":
+               case "namespace":
+                       break;
+               default:
+                       return $this->throwXMLerror( "Element <$name> not allowed in <siteinfo>." );
+               }
+       }
+       
+       function out_siteinfo( $parser, $name ) {
+               if( $name == "siteinfo" ) {
+                       xml_set_element_handler( $parser, "in_mediawiki", "out_mediawiki" );
+               }
+       }
+       
+
+       function in_page( $parser, $name, $attribs ) {
+               $this->debug( "in_page $name" );
+               switch( $name ) {
+               case "id":
+               case "title":
+               case "restrictions":
+                       $this->appendfield = $name;
+                       $this->appenddata = "";
+                       $this->parenttag = "page";
+                       xml_set_element_handler( $parser, "in_nothing", "out_append" );
+                       xml_set_character_data_handler( $parser, "char_append" );
+                       break;
+               case "revision":
+                       $this->workRevision = new WikiRevision;
+                       $this->workRevision->setTitle( $this->workTitle );
+                       xml_set_element_handler( $parser, "in_revision", "out_revision" );
+                       break;
+               default:
+                       return $this->throwXMLerror( "Element <$name> not allowed in a <page>." );
+               }
+       }
+       
+       function out_page( $parser, $name ) {
+               $this->debug( "out_page $name" );
+               if( $name != "page" ) {
+                       return $this->throwXMLerror( "Expected </page>, got </$name>" );
+               }
+               xml_set_element_handler( $parser, "in_mediawiki", "out_mediawiki" );
+               
+               $this->workTitle = NULL;
+               $this->workRevision = NULL;
+       }
+       
+       function in_nothing( $parser, $name, $attribs ) {
+               $this->debug( "in_nothing $name" );
+               return $this->throwXMLerror( "No child elements allowed here; got <$name>" );
+       }
+       function char_append( $parser, $data ) {
+               $this->debug( "char_append '$data'" );
+               $this->appenddata .= $data;
+       }
+       function out_append( $parser, $name ) {
+               $this->debug( "out_append $name" );
+               if( $name != $this->appendfield ) {
+                       return $this->throwXMLerror( "Expected </{$this->appendfield}>, got </$name>" );
+               }
+               xml_set_element_handler( $parser, "in_$this->parenttag", "out_$this->parenttag" );
+               xml_set_character_data_handler( $parser, "donothing" );
+               
+               switch( $this->appendfield ) {
+               case "title":
+                       $this->workTitle = $this->appenddata;
+                       $this->pageCallback( $this->workTitle );
+                       break;
+               case "text":
+                       $this->workRevision->setText( $this->appenddata );
+                       break;
+               case "username":
+                       $this->workRevision->setUsername( $this->appenddata );
+                       break;
+               case "ip":
+                       $this->workRevision->setUserIP( $this->appenddata );
+                       break;
+               case "timestamp":
+                       $this->workRevision->setTimestamp( $this->appenddata );
+                       break;
+               case "comment":
+                       $this->workRevision->setComment( $this->appenddata );
+                       break;
+               case "minor":
+                       $this->workRevision->setMinor( true );
+                       break;
+               default:
+                       $this->debug( "Bad append: {$this->appendfield}" );
+               }
+               $this->appendfield = "";
+               $this->appenddata = "";
+       }
+       
+       function in_revision( $parser, $name, $attribs ) {
+               $this->debug( "in_revision $name" );
+               switch( $name ) {
+               case "id":
+               case "timestamp":
+               case "comment":
+               case "minor":
+               case "text":
+                       $this->parenttag = "revision";
+                       $this->appendfield = $name;
+                       xml_set_element_handler( $parser, "in_nothing", "out_append" );
+                       xml_set_character_data_handler( $parser, "char_append" );
+                       break;
+               case "contributor":
+                       xml_set_element_handler( $parser, "in_contributor", "out_contributor" );
+                       break;
+               default:
+                       return $this->throwXMLerror( "Element <$name> not allowed in a <revision>." );
+               }
+       }
+       
+       function out_revision( $parser, $name ) {
+               $this->debug( "out_revision $name" );
+               if( $name != "revision" ) {
+                       return $this->throwXMLerror( "Expected </revision>, got </$name>" );
+               }
+               xml_set_element_handler( $parser, "in_page", "out_page" );
+               
+               $out = call_user_func_array( $this->mRevisionCallback,
+                       array( &$this->workRevision, &$this ) );
+               if( !empty( $out ) ) {
+                       global $wgOut;
+                       $wgOut->addHTML( "<li>" . $out . "</li>\n" );
+               }
+       }
+       
+       function in_contributor( $parser, $name, $attribs ) {
+               $this->debug( "in_contributor $name" );
+               switch( $name ) {
+               case "username":
+               case "ip":
+               case "id":
+                       $this->parenttag = "contributor";
+                       $this->appendfield = $name;
+                       xml_set_element_handler( $parser, "in_nothing", "out_append" );
+                       xml_set_character_data_handler( $parser, "char_append" );
+                       break;
+               default:
+                       $this->throwXMLerror( "Invalid tag <$name> in <contributor>" );
+               }
+       }
+       
+       function out_contributor( $parser, $name ) {
+               $this->debug( "out_contributor $name" );
+               if( $name != "contributor" ) {
+                       return $this->throwXMLerror( "Expected </contributor>, got </$name>" );
+               }
+               xml_set_element_handler( $parser, "in_revision", "out_revision" );
+       }
+
+}
+
+/** @package MediaWiki */
+class ImportStringSource {
+       function ImportStringSource( $string ) {
+               $this->mString = $string;
+               $this->mRead = false;
+       }
+       
+       function atEnd() {
+               return $this->mRead;
+       }
+       
+       function readChunk() {
+               if( $this->atEnd() ) {
+                       return false;
+               } else {
+                       $this->mRead = true;
+                       return $this->mString;
+               }
+       }
+}
+
+/** @package MediaWiki */
+class ImportStreamSource {
+       function ImportStreamSource( $handle ) {
+               $this->mHandle = $handle;
+       }
+       
+       function atEnd() {
+               return feof( $this->mHandle );
+       }
+       
+       function readChunk() {
+               return fread( $this->mHandle, 32768 );
+       }
+       
+       function newFromFile( $filename ) {
+               $file = @fopen( $filename, 'rt' );
+               if( !$file ) {
+                       return new WikiError( "Couldn't open import file" );
+               }
+               return new ImportStreamSource( $file );
+       }
+
+       function newFromUpload( $fieldname = "xmlimport" ) {
+               global $wgOut;
+               
+               $upload =& $_FILES[$fieldname];
+               
+               if( !isset( $upload ) ) {
+                       return new WikiErrorMsg( 'importnofile' );
+               }
+               if( !empty( $upload['error'] ) ) {
+                       return new WikiErrorMsg( 'importuploaderror', $upload['error'] );
+               }
+               $fname = $upload['tmp_name'];
+               if( is_uploaded_file( $fname ) ) {
+                       return ImportStreamSource::newFromFile( $fname );
+               } else {
+                       return new WikiErrorMsg( 'importnofile' );
+               }
+       }
+       
+       function newFromURL( $url ) {
+               # fopen-wrappers are normally turned off for security.
+               ini_set( "allow_url_fopen", true );
+               $ret = ImportStreamSource::newFromFile( $url );
+               ini_set( "allow_url_fopen", false );
+               return $ret;
+       }
+       
+       function newFromInterwiki( $interwiki, $page ) {
+               $base = Title::getInterwikiLink( $interwiki );
+               if( empty( $base ) ) {
+                       return new WikiError( 'Bad interwiki link' );
+               } else {
+                       $import = wfUrlencode( "Special:Export/$page" );
+                       $url = str_replace( "$1", $import, $base );
+                       return ImportStreamSource::newFromURL( $url );
+               }
+       }
+}
+
+
+?>
diff --git a/includes/SpecialIpblocklist.php b/includes/SpecialIpblocklist.php
new file mode 100644 (file)
index 0000000..609bda2
--- /dev/null
@@ -0,0 +1,176 @@
+<?php
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/**
+ * @todo document
+ */
+function wfSpecialIpblocklist() {
+       global $wgUser, $wgOut, $wgRequest;
+       
+       $ip = $wgRequest->getVal( 'wpUnblockAddress', $wgRequest->getVal( 'ip' ) );
+       $reason = $wgRequest->getText( 'wpUnblockReason' );
+       $action = $wgRequest->getText( 'action' );
+       
+       $ipu = new IPUnblockForm( $ip, $reason );
+
+       if ( "success" == $action ) {
+               $msg = wfMsg( "ipusuccess", htmlspecialchars( $ip ) );
+               $ipu->showList( $msg );
+       } else if ( "submit" == $action && $wgRequest->wasPosted() &&
+               $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) ) ) {
+               if ( ! $wgUser->isAllowed('block') ) {
+                       $wgOut->sysopRequired();
+                       return;
+               }
+               $ipu->doSubmit();
+       } else if ( "unblock" == $action ) {
+               $ipu->showForm( "" );
+       } else {
+               $ipu->showList( "" );
+       }
+}
+
+/**
+ * 
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+class IPUnblockForm {
+       var $ip, $reason;
+       
+       function IPUnblockForm( $ip, $reason ) {
+               $this->ip = $ip;
+               $this->reason = $reason;
+       }
+       
+       function showForm( $err )
+       {
+               global $wgOut, $wgUser, $wgLang, $wgSysopUserBans;
+
+               $wgOut->setPagetitle( wfMsg( "unblockip" ) );
+               $wgOut->addWikiText( wfMsg( "unblockiptext" ) );
+
+               $ipa = wfMsgHtml( $wgSysopUserBans ? 'ipadressorusername' : 'ipaddress' );
+               $ipr = wfMsgHtml( 'ipbreason' );
+               $ipus = wfMsgHtml( 'ipusubmit' );
+               $titleObj = Title::makeTitle( NS_SPECIAL, "Ipblocklist" );
+               $action = $titleObj->escapeLocalURL( "action=submit" );
+
+               if ( "" != $err ) {
+                       $wgOut->setSubtitle( wfMsg( "formerror" ) );
+                       $wgOut->addWikitext( "<span class='error'>{$err}</span>\n" );
+               }
+               $token = htmlspecialchars( $wgUser->editToken() );
+               
+               $wgOut->addHTML( "
+<form id=\"unblockip\" method=\"post\" action=\"{$action}\">
+       <table border='0'>
+               <tr>
+                       <td align='right'>{$ipa}:</td>
+                       <td align='left'>
+                               <input tabindex='1' type='text' size='20' name=\"wpUnblockAddress\" value=\"" . htmlspecialchars( $this->ip ) . "\" />
+                       </td>
+               </tr>
+               <tr>
+                       <td align='right'>{$ipr}:</td>
+                       <td align='left'>
+                               <input tabindex='1' type='text' size='40' name=\"wpUnblockReason\" value=\"" . htmlspecialchars( $this->reason ) . "\" />
+                       </td>
+               </tr>
+               <tr>
+                       <td>&nbsp;</td>
+                       <td align='left'>
+                               <input tabindex='2' type='submit' name=\"wpBlock\" value=\"{$ipus}\" />
+                       </td>
+               </tr>
+       </table>
+       <input type='hidden' name='wpEditToken' value=\"{$token}\" />
+</form>\n" );
+
+       }
+       
+       function doSubmit() {
+               global $wgOut, $wgUser, $wgLang;
+
+               $block = new Block();
+               $this->ip = trim( $this->ip );
+
+               if ( $this->ip{0} == "#" ) {
+                       $block->mId = substr( $this->ip, 1 );
+               } else {
+                       $block->mAddress = $this->ip;
+               }
+
+               # Delete block (if it exists)
+               # We should probably check for errors rather than just declaring success
+               $block->delete();
+
+               # Make log entry
+               $log = new LogPage( 'block' );
+               $log->addEntry( 'unblock', Title::makeTitle( NS_USER, $this->ip ), $this->reason );
+
+               # Report to the user
+               $titleObj = Title::makeTitle( NS_SPECIAL, "Ipblocklist" );
+               $success = $titleObj->getFullURL( "action=success&ip=" . urlencode( $this->ip ) );
+               $wgOut->redirect( $success );
+       }
+
+       function showList( $msg ) {
+               global $wgOut;
+               
+               $wgOut->setPagetitle( wfMsg( "ipblocklist" ) );
+               if ( "" != $msg ) {
+                       $wgOut->setSubtitle( $msg );
+               }
+               $wgOut->addHTML( "<ul>" );
+               // FIXME hack to solve #bug 1487
+               if(!Block::enumBlocks( "wfAddRow", 0 ))
+                       $wgOut->addHTML( '<li>'.wfMsg( 'ipblocklistempty' ).'</li>' );
+               $wgOut->addHTML( "</ul>\n" );
+       }
+}
+
+/**
+ * Callback function to output a block
+ */
+function wfAddRow( $block, $tag ) {
+       global $wgOut, $wgUser, $wgLang, $wgContLang;
+
+       $sk = $wgUser->getSkin();
+
+       # Hide addresses blocked by User::spreadBlocks, for privacy
+       $addr = $block->mAuto ? "#{$block->mId}" : $block->mAddress;
+
+       $name = User::whoIs( $block->mBy );
+       $ulink = $sk->makeKnownLinkObj( Title::makeTitle( NS_USER, $name ), $name );
+       $formattedTime = $wgLang->timeanddate( $block->mTimestamp, true );
+       
+       if ( $block->mExpiry === "" ) {
+               $formattedExpiry = wfMsgHtml('infiniteblock');
+       } else {
+               $formattedExpiry = wfMsgHtml('expiringblock', $wgLang->timeanddate( $block->mExpiry, true ) );
+       }
+       
+       $line = wfMsg( "blocklistline", $formattedTime, $ulink, $addr, $formattedExpiry );
+       
+       $wgOut->addHTML( "<li>{$line}" );
+
+       if ( !$block->mAuto ) {
+               $titleObj = Title::makeTitle( NS_SPECIAL, "Contributions" );
+               $wgOut->addHTML( ' (' . $sk->makeKnownLinkObj($titleObj, wfMsgHtml( 'contribslink' ), "target={$block->mAddress}") . ')' );
+       }
+
+       if ( $wgUser->isAllowed('block') ) {
+               $titleObj = Title::makeTitle( NS_SPECIAL, "Ipblocklist" );
+               $wgOut->addHTML( ' (' . $sk->makeKnownLinkObj($titleObj, wfMsgHtml( 'unblocklink' ), 'action=unblock&ip=' . urlencode( $addr ) ) . ')' );
+       }
+       $wgOut->addHTML( $sk->commentBlock( $block->mReason ) );
+       $wgOut->addHTML( "</li>\n" );
+}
+
+
+?>
diff --git a/includes/SpecialListusers.php b/includes/SpecialListusers.php
new file mode 100644 (file)
index 0000000..892bbd6
--- /dev/null
@@ -0,0 +1,206 @@
+<?php
+# Copyright (C) 2004 Brion Vibber, lcrocker, Tim Starling,
+# Domas Mituzas, Ashar Voultoiz, Jens Frank, Zhengzhu.
+#
+# http://www.mediawiki.org/
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or 
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# http://www.gnu.org/copyleft/gpl.html
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/**
+ *
+ */
+require_once('QueryPage.php');
+
+/**
+ * This class is used to get a list of user. The ones with specials
+ * rights (sysop, bureaucrat, developer) will have them displayed
+ * next to their names.
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+class ListUsersPage extends QueryPage {
+       var $requestedGroup = '';
+       var $requestedUser = '';
+       var $previousResult = null;
+       var $concatGroups = '';
+       
+       function getName() {
+               return 'Listusers';
+       }
+       function isSyndicated() { return false; }
+
+       /**
+        * Show a drop down list to select a group as well as a user name
+        * search box.
+        * @todo localize
+        */
+       function getPageHeader( ) {
+               global $wgScript;
+               
+               // Various variables used for the form
+               $action = htmlspecialchars( $wgScript );
+               $title = Title::makeTitle( NS_SPECIAL, 'Listusers' );
+               $special = htmlspecialchars( $title->getPrefixedDBkey() );
+
+               // form header
+               $out = '<form method="get" action="'.$action.'">' .
+                               '<input type="hidden" name="title" value="'.$special.'" />' .
+                               wfMsgHtml( 'groups-editgroup-name' ) . '<select name="group">';
+
+               // get all group names and IDs
+               $groups = User::getAllGroups();
+               
+               // we want a default empty group
+               $out.= '<option value=""></option>';
+               
+               // build the dropdown list menu using datas from the database
+               foreach ( $groups as $group ) {
+                       $selected = ($group == $this->requestedGroup);
+                       $out .= wfElement( 'option',
+                               array_merge(
+                                       array( 'value' => $group ),
+                                       $selected ? array( 'selected' => 'selected' ) : array() ),
+                               User::getGroupName( $group ) );
+               }
+               $out .= '</select> ';
+
+               $out .= wfMsgHtml( 'specialloguserlabel' ) . '<input type="text" name="username" /> ';
+
+               // OK button, end of form.
+               $out .= '<input type="submit" /></form>';
+               // congratulations the form is now build
+               return $out;    
+       }
+       
+       function getSQL() {
+               $dbr =& wfGetDB( DB_SLAVE );
+               $user = $dbr->tableName( 'user' );
+               $user_groups = $dbr->tableName( 'user_groups' );
+               
+               // We need to get an 'atomic' list of users, so that we
+               // don't break the list half-way through a user's group set
+               // and so that lists by group will show all group memberships.
+               //
+               // On MySQL 4.1 we could use GROUP_CONCAT to grab group
+               // assignments together with users pretty easily. On other
+               // versions, it's not so easy to do it consistently.
+               // For now we'll just grab the number of memberships, so
+               // we can then do targetted checks on those who are in
+               // non-default groups as we go down the list.
+               
+               $userspace = NS_USER;
+               $sql = "SELECT 'Listusers' as type, $userspace AS namespace, user_name AS title, " .
+                       "user_name as value, user_id, COUNT(ug_group) as numgroups " .
+                       "FROM $user ".
+                       "LEFT JOIN $user_groups ON user_id=ug_user " .
+                       $this->userQueryWhere( $dbr ) .
+                       " GROUP BY user_name";
+               
+               return $sql;
+       }
+       
+       function userQueryWhere( &$dbr ) {
+               $conds = $this->userQueryConditions();
+               return empty( $conds )
+                       ? ""
+                       : "WHERE " . $dbr->makeList( $conds, LIST_AND );
+       }
+       
+       function userQueryConditions() {
+               $conds = array();
+               if( $this->requestedGroup != '' ) {
+                       $conds['ug_group'] = $this->requestedGroup;
+               }
+               if( $this->requestedUser != '' ) {
+                       $conds['user_name'] = $this->requestedUser;
+               }
+               return $conds;
+       }
+       
+       function linkParameters() {
+               $conds = array();
+               if( $this->requestedGroup != '' ) {
+                       $conds['group'] = $this->requestedGroup;
+               }
+               if( $this->requestedUser != '' ) {
+                       $conds['username'] = $this->requestedUser;
+               }
+               return $conds;
+       }
+       
+       function sortDescending() {
+               return false;
+       }
+
+       function formatResult( $skin, $result ) {
+               global $wgContLang;
+               
+               $userPage = Title::makeTitle( $result->namespace, $result->title );
+               $name = $skin->makeLinkObj( $userPage, htmlspecialchars( $userPage->getText() ) );
+               
+               if( !isset( $result->numgroups ) || $result->numgroups > 0 ) {
+                       $dbr =& wfGetDB( DB_SLAVE );
+                       $result = $dbr->select( 'user_groups',
+                               array( 'ug_group' ),
+                               array( 'ug_user' => $result->user_id ),
+                               'ListUsersPage::formatResult' );
+                       $groups = array();
+                       while( $row = $dbr->fetchObject( $result ) ) {
+                               $groups[] = User::getGroupName( $row->ug_group );
+                       }
+                       $dbr->freeResult( $result );
+                       
+                       if( count( $groups ) > 0 ) {
+                               $name .= ' (' .
+                                       $skin->makeLink( wfMsgForContent( 'administrators' ),
+                                               htmlspecialchars( implode( ', ', $groups ) ) ) .
+                                       ')';
+                       }
+               }
+
+               return $name;
+       }       
+}
+
+/**
+ * constructor
+ * $par string (optional) A group to list users from
+ */
+function wfSpecialListusers( $par = null ) {
+       global $wgRequest;
+
+       list( $limit, $offset ) = wfCheckLimits();
+
+
+       $slu = new ListUsersPage();
+       
+       /**
+        * Get some parameters
+        */
+       $groupTarget = isset($par) ? $par : $wgRequest->getVal( 'group' );
+       $slu->requestedGroup = $groupTarget;
+       $slu->requestedUser = $wgRequest->getVal('username');
+
+       return $slu->doQuery( $offset, $limit );
+}
+
+?>
diff --git a/includes/SpecialLockdb.php b/includes/SpecialLockdb.php
new file mode 100644 (file)
index 0000000..7297022
--- /dev/null
@@ -0,0 +1,119 @@
+<?php
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/**
+ * Constructor
+ */
+function wfSpecialLockdb() {
+       global $wgUser, $wgOut, $wgRequest;
+
+       if ( ! $wgUser->isAllowed('siteadmin') ) {
+               $wgOut->developerRequired();
+               return;
+       }
+       $action = $wgRequest->getVal( 'action' );
+       $f = new DBLockForm();
+
+       if ( 'success' == $action ) {
+               $f->showSuccess();
+       } else if ( 'submit' == $action && $wgRequest->wasPosted() &&
+               $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) ) ) {
+               $f->doSubmit();
+       } else {
+               $f->showForm( '' );
+       }
+}
+
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+class DBLockForm {
+       var $reason = '';
+       
+       function DBLockForm() {
+               global $wgRequest;
+               $this->reason = $wgRequest->getText( 'wpLockReason' );
+       }
+       
+       function showForm( $err )
+       {
+               global $wgOut, $wgUser, $wgLang;
+
+               $wgOut->setPagetitle( wfMsg( 'lockdb' ) );
+               $wgOut->addWikiText( wfMsg( 'lockdbtext' ) );
+
+               if ( "" != $err ) {
+                       $wgOut->setSubtitle( wfMsg( 'formerror' ) );
+                       $wgOut->addHTML( '<p class="error">' . htmlspecialchars( $err ) . "</p>\n" );
+               }
+               $lc = htmlspecialchars( wfMsg( 'lockconfirm' ) );
+               $lb = htmlspecialchars( wfMsg( 'lockbtn' ) );
+               $elr = htmlspecialchars( wfMsg( 'enterlockreason' ) );
+               $titleObj = Title::makeTitle( NS_SPECIAL, 'Lockdb' );
+               $action = $titleObj->escapeLocalURL( 'action=submit' );
+               $token = htmlspecialchars( $wgUser->editToken() );
+
+               $wgOut->addHTML( <<<END
+<form id="lockdb" method="post" action="{$action}">
+{$elr}:
+<textarea name="wpLockReason" rows="10" cols="60" wrap="virtual"></textarea>
+<table border="0">
+       <tr>
+               <td align="right">
+                       <input type="checkbox" name="wpLockConfirm" />
+               </td>
+               <td align="left">{$lc}</td>
+       </tr>
+       <tr>
+               <td>&nbsp;</td>
+               <td align="left">
+                       <input type="submit" name="wpLock" value="{$lb}" />
+               </td>
+       </tr>
+</table>
+<input type="hidden" name="wpEditToken" value="{$token}" />
+</form>
+END
+);
+
+       }
+
+       function doSubmit() {
+               global $wgOut, $wgUser, $wgLang, $wgRequest;
+               global $wgReadOnlyFile;
+
+               if ( ! $wgRequest->getCheck( 'wpLockConfirm' ) ) {
+                       $this->showForm( wfMsg( 'locknoconfirm' ) );
+                       return;
+               }
+               $fp = fopen( $wgReadOnlyFile, 'w' );
+
+               if ( false === $fp ) {
+                       $wgOut->fileNotFoundError( $wgReadOnlyFile );
+                       return;
+               }
+               fwrite( $fp, $this->reason );
+               fwrite( $fp, "\n<p>(by " . $wgUser->getName() . " at " .
+                 $wgLang->timeanddate( wfTimestampNow() ) . ")\n" );
+               fclose( $fp );
+
+               $titleObj = Title::makeTitle( NS_SPECIAL, 'Lockdb' );
+               $wgOut->redirect( $titleObj->getFullURL( 'action=success' ) );
+       }
+
+       function showSuccess() {
+               global $wgOut, $wgUser;
+
+               $wgOut->setPagetitle( wfMsg( 'lockdb' ) );
+               $wgOut->setSubtitle( wfMsg( 'lockdbsuccesssub' ) );
+               $wgOut->addWikiText( wfMsg( 'lockdbsuccesstext' ) );
+       }
+}
+
+?>
diff --git a/includes/SpecialLog.php b/includes/SpecialLog.php
new file mode 100644 (file)
index 0000000..7a7b046
--- /dev/null
@@ -0,0 +1,416 @@
+<?php
+# Copyright (C) 2004 Brion Vibber <brion@pobox.com>
+# http://www.mediawiki.org/
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or 
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# http://www.gnu.org/copyleft/gpl.html
+
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/**
+ * constructor
+ */
+function wfSpecialLog( $par = '' ) {
+       global $wgRequest;
+       $logReader =& new LogReader( $wgRequest );
+       if( '' == $wgRequest->getVal( 'type' ) && !empty( $par ) ) {
+               $logReader->limitType( $par );
+       }
+       $logViewer =& new LogViewer( $logReader );
+       $logViewer->show();
+}
+
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+class LogReader {
+       var $db, $joinClauses, $whereClauses;
+       var $type = '', $user = '', $title = null;
+       
+       /**
+        * @param WebRequest $request For internal use use a FauxRequest object to pass arbitrary parameters.
+        */
+       function LogReader( $request ) {
+               $this->db =& wfGetDB( DB_SLAVE );
+               $this->setupQuery( $request );
+       }
+       
+       /**
+        * Basic setup and applies the limiting factors from the WebRequest object.
+        * @param WebRequest $request
+        * @private
+        */
+       function setupQuery( $request ) {
+               $page = $this->db->tableName( 'page' );
+               $user = $this->db->tableName( 'user' );
+               $this->joinClauses = array( "LEFT OUTER JOIN $page ON log_namespace=page_namespace AND log_title=page_title" );
+               $this->whereClauses = array( 'user_id=log_user' );
+               
+               $this->limitType( $request->getVal( 'type' ) );
+               $this->limitUser( $request->getText( 'user' ) );
+               $this->limitTitle( $request->getText( 'page' ) );
+               $this->limitTime( $request->getVal( 'from' ), '>=' );
+               $this->limitTime( $request->getVal( 'until' ), '<=' );
+               
+               list( $this->limit, $this->offset ) = $request->getLimitOffset();
+       }
+       
+       /**
+        * Set the log reader to return only entries of the given type.
+        * @param string $type A log type ('upload', 'delete', etc)
+        * @private
+        */
+       function limitType( $type ) {
+               if( empty( $type ) ) {
+                       return false;
+               }
+               $this->type = $type;
+               $safetype = $this->db->strencode( $type );
+               $this->whereClauses[] = "log_type='$safetype'";
+       }
+       
+       /**
+        * Set the log reader to return only entries by the given user.
+        * @param string $name Valid user name
+        * @private
+        */
+       function limitUser( $name ) {
+               $title = Title::makeTitle( NS_USER, $name );
+               if( empty( $name ) || is_null( $title ) ) {
+                       return false;
+               }
+               $this->user = str_replace( '_', ' ', $title->getDBkey() );
+               $safename = $this->db->strencode( $this->user );
+               $user = $this->db->tableName( 'user' );
+               $this->whereClauses[] = "user_name='$safename'";
+       }
+       
+       /**
+        * Set the log reader to return only entries affecting the given page.
+        * (For the block and rights logs, this is a user page.)
+        * @param string $page Title name as text
+        * @private
+        */
+       function limitTitle( $page ) {
+               $title = Title::newFromText( $page );
+               if( empty( $page ) || is_null( $title )  ) {
+                       return false;
+               }
+               $this->title =& $title;
+               $safetitle = $this->db->strencode( $title->getDBkey() );
+               $ns = $title->getNamespace();
+               $this->whereClauses[] = "log_namespace=$ns AND log_title='$safetitle'";
+       }
+       
+       /**
+        * Set the log reader to return only entries in a given time range.
+        * @param string $time Timestamp of one endpoint
+        * @param string $direction either ">=" or "<=" operators
+        * @private
+        */
+       function limitTime( $time, $direction ) {
+               # Direction should be a comparison operator
+               if( empty( $time ) ) {
+                       return false;
+               }
+               $safetime = $this->db->strencode( wfTimestamp( TS_MW, $time ) );
+               $this->whereClauses[] = "log_timestamp $direction '$safetime'";
+       }
+       
+       /**
+        * Build an SQL query from all the set parameters.
+        * @return string the SQL query
+        * @private
+        */
+       function getQuery() {
+               $logging = $this->db->tableName( "logging" );
+               $user = $this->db->tableName( 'user' );
+               $sql = "SELECT log_type, log_action, log_timestamp,
+                       log_user, user_name,
+                       log_namespace, log_title, page_id,
+                       log_comment, log_params FROM $user, $logging ";
+               if( !empty( $this->joinClauses ) ) {
+                       $sql .= implode( ',', $this->joinClauses );
+               }
+               if( !empty( $this->whereClauses ) ) {
+                       $sql .= " WHERE " . implode( ' AND ', $this->whereClauses );
+               }
+               $sql .= " ORDER BY log_timestamp DESC ";
+               $sql .= $this->db->limitResult( $this->limit, $this->offset );
+               return $sql;
+       }
+       
+       /**
+        * Execute the query and start returning results.
+        * @return ResultWrapper result object to return the relevant rows
+        */
+       function getRows() {
+               return $this->db->resultObject( $this->db->query( $this->getQuery() ) );
+       }
+       
+       /**
+        * @return string The query type that this LogReader has been limited to.
+        */
+       function queryType() {
+               return $this->type;
+       }
+       
+       /**
+        * @return string The username type that this LogReader has been limited to, if any.
+        */
+       function queryUser() {
+               return $this->user;
+       }
+       
+       /**
+        * @return string The text of the title that this LogReader has been limited to.
+        */
+       function queryTitle() {
+               if( is_null( $this->title ) ) {
+                       return '';
+               } else {
+                       return $this->title->getPrefixedText();
+               }
+       }
+}
+
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+class LogViewer {
+       /**
+        * @var LogReader $reader
+        */
+       var $reader;
+       var $numResults = 0;
+       
+       /**
+        * @param LogReader &$reader where to get our data from
+        */
+       function LogViewer( &$reader ) {
+               global $wgUser;
+               $this->skin =& $wgUser->getSkin();
+               $this->reader =& $reader;
+       }
+       
+       /**
+        * Take over the whole output page in $wgOut with the log display.
+        */
+       function show() {
+               global $wgOut;
+               $this->showHeader( $wgOut );
+               $this->showOptions( $wgOut );
+               $result = $this->getLogRows();
+               $this->showPrevNext( $wgOut );
+               $this->doShowList( $wgOut, $result );
+               $this->showPrevNext( $wgOut );
+       }
+
+       /**
+        * Load the data from the linked LogReader
+        * Preload the link cache
+        * Initialise numResults
+        * 
+        * Must be called before calling showPrevNext
+        *
+        * @return object database result set
+        */
+       function getLogRows() {
+               global $wgLinkCache;
+               $result = $this->reader->getRows();
+               $this->numResults = 0;
+
+               // Fetch results and form a batch link existence query
+               $batch = new LinkBatch;
+               while ( $s = $result->fetchObject() ) {
+                       // User link
+                       $title = Title::makeTitleSafe( NS_USER, $s->user_name );
+                       $batch->addObj( $title );
+
+                       // Move destination link
+                       if ( $s->log_type == 'move' ) {
+                               $paramArray = LogPage::extractParams( $s->log_params );
+                               $title = Title::newFromText( $paramArray[0] );
+                               $batch->addObj( $title );
+                       }
+                       $this->numResults++;
+               }
+               $batch->execute( $wgLinkCache );
+
+               return $result;
+       }
+
+       
+       /**
+        * Output just the list of entries given by the linked LogReader,
+        * with extraneous UI elements. Use for displaying log fragments in
+        * another page (eg at Special:Undelete)
+        * @param OutputPage $out where to send output
+        */
+       function showList( &$out ) {
+               $this->doShowList( $out, $this->getLogRows() );
+       }
+       
+       function doShowList( &$out, $result ) {
+               // Rewind result pointer and go through it again, making the HTML
+               $html='';
+               if ($this->numResults > 0) {
+                       $html = "\n<ul>\n";
+                       $result->seek( 0 );
+                       while( $s = $result->fetchObject() ) {
+                               $html .= $this->logLine( $s );
+                       }
+                       $html .= "\n</ul>\n";
+               }
+               $result->free();
+               $out->addHTML( $html );
+       }
+       
+       /**
+        * @param Object $s a single row from the result set
+        * @return string Formatted HTML list item
+        * @private
+        */
+       function logLine( $s ) {
+               global $wgLang, $wgLinkCache;
+               $title = Title::makeTitle( $s->log_namespace, $s->log_title );
+               $user = Title::makeTitleSafe( NS_USER, $s->user_name );
+               $time = $wgLang->timeanddate( $s->log_timestamp, true );
+
+               // Enter the existence or non-existence of this page into the link cache,
+               // for faster makeLinkObj() in LogPage::actionText()
+               if( $s->page_id ) {
+                       $wgLinkCache->addGoodLinkObj( $s->page_id, $title );
+               } else {
+                       $wgLinkCache->addBadLinkObj( $title );
+               }
+               
+               $userLink = $this->skin->makeLinkObj( $user, htmlspecialchars( $s->user_name ) );
+               $comment = $this->skin->commentBlock( $s->log_comment );
+               $paramArray = LogPage::extractParams( $s->log_params );
+               $revert = '';
+               if ( $s->log_type == 'move' && isset( $paramArray[0] ) ) {
+                       $specialTitle = Title::makeTitle( NS_SPECIAL, 'Movepage' );
+                       $destTitle = Title::newFromText( $paramArray[0] );
+                       if ( $destTitle ) {
+                               $revert = '(' . $this->skin->makeKnownLinkObj( $specialTitle, wfMsg( 'revertmove' ),
+                                       'wpOldTitle=' . urlencode( $destTitle->getPrefixedDBkey() ) . 
+                                       '&wpNewTitle=' . urlencode( $title->getPrefixedDBkey() ) .
+                                       '&wpReason=' . urlencode( wfMsgForContent( 'revertmove' ) ) .
+                                       '&wpMovetalk=0' ) . ')';
+                       }
+               }
+
+               $action = LogPage::actionText( $s->log_type, $s->log_action, $title, $this->skin, $paramArray, true );
+               $out = "<li>$time $userLink $action $comment $revert</li>\n";
+               return $out;
+       }
+       
+       /**
+        * @param OutputPage &$out where to send output
+        * @private
+        */
+       function showHeader( &$out ) {
+               $type = $this->reader->queryType();
+               if( LogPage::isLogType( $type ) ) {
+                       $out->setPageTitle( LogPage::logName( $type ) );
+                       $out->addWikiText( LogPage::logHeader( $type ) );
+               }
+       }
+       
+       /**
+        * @param OutputPage &$out where to send output
+        * @private
+        */
+       function showOptions( &$out ) {
+               global $wgScript;
+               $action = htmlspecialchars( $wgScript );
+               $title = Title::makeTitle( NS_SPECIAL, 'Log' );
+               $special = htmlspecialchars( $title->getPrefixedDBkey() );
+               $out->addHTML( "<form action=\"$action\" method=\"get\">\n" .
+                       "<input type='hidden' name='title' value=\"$special\" />\n" .
+                       $this->getTypeMenu() .
+                       $this->getUserInput() .
+                       $this->getTitleInput() .
+                       "<input type='submit' value=\"" . wfMsg( 'allpagessubmit' ) . "\" />" .
+                       "</form>" );
+       }
+       
+       /**
+        * @return string Formatted HTML
+        * @private
+        */
+       function getTypeMenu() {
+               $out = "<select name='type'>\n";
+               foreach( LogPage::validTypes() as $type ) {
+                       $text = htmlspecialchars( LogPage::logName( $type ) );
+                       $selected = ($type == $this->reader->queryType()) ? ' selected="selected"' : '';
+                       $out .= "<option value=\"$type\"$selected>$text</option>\n";
+               }
+               $out .= "</select>\n";
+               return $out;
+       }
+       
+       /**
+        * @return string Formatted HTML
+        * @private
+        */
+       function getUserInput() {
+               $user = htmlspecialchars( $this->reader->queryUser() );
+               return wfMsg('specialloguserlabel') . "<input type='text' name='user' size='12' value=\"$user\" />\n";
+       }
+       
+       /**
+        * @return string Formatted HTML
+        * @private
+        */
+       function getTitleInput() {
+               $title = htmlspecialchars( $this->reader->queryTitle() );
+               return wfMsg('speciallogtitlelabel') . "<input type='text' name='page' size='20' value=\"$title\" />\n";
+       }
+       
+       /**
+        * @param OutputPage &$out where to send output
+        * @private
+        */
+       function showPrevNext( &$out ) {
+               global $wgContLang,$wgRequest;
+               $pieces = array();
+               $pieces[] = 'type=' . urlencode( $this->reader->queryType() );
+               $pieces[] = 'user=' . urlencode( $this->reader->queryUser() );
+               $pieces[] = 'page=' . urlencode( $this->reader->queryTitle() );
+               $bits = implode( '&', $pieces );
+               list( $limit, $offset ) = $wgRequest->getLimitOffset();
+               
+               # TODO: use timestamps instead of offsets to make it more natural
+               # to go huge distances in time
+               $html = wfViewPrevNext( $offset, $limit,
+                       $wgContLang->specialpage( 'Log' ),
+                       $bits,
+                       $this->numResults < $limit);
+               $out->addHTML( '<p>' . $html . '</p>' );
+       }
+}
+
+
+?>
diff --git a/includes/SpecialLonelypages.php b/includes/SpecialLonelypages.php
new file mode 100644 (file)
index 0000000..a143f14
--- /dev/null
@@ -0,0 +1,63 @@
+<?php
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/**
+ *
+ */
+require_once( "QueryPage.php" );
+
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+class LonelyPagesPage extends PageQueryPage {
+
+       function getName() {
+               return "Lonelypages";
+       }
+
+       function sortDescending() {
+               return false;
+       }
+
+       function isExpensive() {
+               return true;
+       }
+       function isSyndicated() { return false; }
+       
+       function getSQL() {
+               $dbr =& wfGetDB( DB_SLAVE );
+               extract( $dbr->tableNames( 'page', 'pagelinks' ) );
+
+               return
+                 "SELECT 'Lonelypages'  AS type,
+                         page_namespace AS namespace,
+                         page_title     AS title,
+                         page_title     AS value
+                    FROM $page
+               LEFT JOIN $pagelinks
+                      ON page_namespace=pl_namespace AND page_title=pl_title
+                   WHERE pl_namespace IS NULL
+                     AND page_namespace=".NS_MAIN."
+                     AND page_is_redirect=0";
+
+       }
+}
+
+/**
+ * Constructor
+ */
+function wfSpecialLonelypages() {
+       list( $limit, $offset ) = wfCheckLimits();
+
+       $lpp = new LonelyPagesPage();
+
+       return $lpp->doQuery( $offset, $limit );
+}
+
+?>
diff --git a/includes/SpecialLongpages.php b/includes/SpecialLongpages.php
new file mode 100644 (file)
index 0000000..75f6e5c
--- /dev/null
@@ -0,0 +1,41 @@
+<?php
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/**
+ *
+ */
+require_once( 'SpecialShortpages.php' );
+
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+class LongPagesPage extends ShortPagesPage {
+
+       function getName() {
+               return "Longpages";
+       }
+
+       function sortDescending() {
+               return true;
+       }
+}
+
+/**
+ * constructor
+ */
+function wfSpecialLongpages()
+{
+    list( $limit, $offset ) = wfCheckLimits();
+
+    $lpp = new LongPagesPage();
+    
+    $lpp->doQuery( $offset, $limit );
+}
+
+?>
diff --git a/includes/SpecialMaintenance.php b/includes/SpecialMaintenance.php
new file mode 100644 (file)
index 0000000..a52f2fd
--- /dev/null
@@ -0,0 +1,298 @@
+<?php
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/**
+ * shortcut to get the current language "special" namespace name
+ */
+function sns() {
+       global $wgContLang;
+       return $wgContLang->getNsText(NS_SPECIAL);
+}
+
+
+/**
+ * Entry point
+ */
+function wfSpecialMaintenance( $par=NULL ) {
+       global $wgUser, $wgOut, $wgContLang, $wgTitle, $wgRequest, $wgContLanguageCode;
+       global $wgMiserMode;
+
+       # This pages is expensive ressource wise
+       if ( $wgMiserMode ) {
+               $wgOut->addWikiText( wfMsg( 'perfdisabled' ) );
+               return;
+       }
+       
+       # Get parameters from the URL
+       $submitmll = $wgRequest->getVal( 'submitmll' );
+
+       if( $par ) {
+               $subfunction = $par;
+       } else {
+               $subfunction = $wgRequest->getText( 'subfunction' );
+       }
+
+       # Call the subfunction requested by the user
+       switch( $subfunction ) {
+       case 'disambiguations': return wfSpecialDisambiguations() ; break;
+       
+       # doubleredirects & brokenredirects are old maintenance subpages.
+       case 'doubleredirects': return wfSpecialDoubleRedirects() ; break;
+       case 'brokenredirects': return wfSpecialBrokenRedirects() ; break;
+       
+       case 'selflinks':       return wfSpecialSelfLinks()       ; break;
+       case 'mispeelings':     return wfSpecialMispeelings()     ; break;
+       case 'missinglanguagelinks': return wfSpecialMissingLanguageLinks() ; break;
+       }
+       
+       if ( !is_null( $submitmll ) ) return wfSpecialMissingLanguageLinks() ;
+
+       $sk = $wgUser->getSkin();
+
+       # Generate page output
+       
+       $r = wfMsg('maintnancepagetext') ;
+       
+       # Links to subfunctions
+       $r .= "<ul>\n" ;
+       $r .= "<li>".$sk->makeKnownLink( sns().':Disambiguations', wfMsg('disambiguations')) . "</li>\n";
+       $r .= '<li>'.$sk->makeKnownLink( sns().':DoubleRedirects', wfMsg('doubleredirects')) . "</li>\n";
+       $r .= '<li>'.$sk->makeKnownLink( sns().':BrokenRedirects', wfMsg('brokenredirects')) . "</li>\n";
+       #$r .= "<li>".getMPL("selflinks")."</li>\n" ; # Doesn't work
+       $r .= '<li>'.getMPL("mispeelings")."</li>\n" ;
+
+       # Interface for the missing language links
+       $r .= '<li>';
+         $l = getMPL('missinglanguagelinks');
+         $l = str_replace ( '</a>' , '' , $l ) ;
+         $l = str_replace ( '<a ' , '<form method="post" ' , $l ) ;
+         $l = str_replace ( ' href=' , ' action=' , $l ) ;
+         $l = explode ( '>' , $l ) ;
+         $l = $l[0] ;
+       $r .= $l.">\n" ;
+       $r .= '<input type="submit" name="submitmll" value="' ;
+       $r .= htmlspecialchars(wfMsg('missinglanguagelinksbutton'), ENT_QUOTES);
+       $r .= "\" />\n" ;
+       $r .= "<select name=\"thelang\">\n" ;
+       
+       $a = $wgContLang->getLanguageNames();
+       $ak = array_keys ( $a ) ;
+       foreach ( $ak AS $k ) {
+               if ( $k != $wgContLanguageCode )
+                       $r .= "<option value='{$k}'>{$a[$k]}</option>\n" ;
+       }
+       $r .= "</select>\n" ;
+       $r .= "</form>\n</li>" ;
+
+       $r .= "</ul>\n" ;
+       $wgOut->addHTML ( $r ) ;
+}
+
+/**
+ * Generate a maintenance page link
+ */
+function getMPL ( $x ) {
+       global $wgUser , $wgLang;
+       $sk = $wgUser->getSkin() ;
+       return $sk->makeKnownLink( sns().":Maintenance" , wfMsg($x), 'subfunction='.$x ) ;
+}
+
+
+function getMaintenancePageBacklink( $subfunction ) {
+       global $wgUser, $wgContLang;
+       $sk = $wgUser->getSkin();
+       $r = $sk->makeKnownLink (
+               $wgContLang->getNsText( NS_SPECIAL ) . ':Maintenance',
+               wfMsg( 'maintenancebacklink' ) ) ;
+       $t = wfMsg ( $subfunction ) ;
+       
+       $s = '<table width="100%" border="0"><tr><td>';
+       $s .= '<h2>'.$t.'</h2></td><td align="right">';
+       $s .= "{$r}</td></tr></table>\n" ;
+       return $s ;
+}
+
+
+/**#@+
+ * Disambiguations, DoubleRedirects and BrokenRedirects are now using the
+ * QueryPage class. Code is in a Special*.php file.
+ *
+ * @deprecated
+ */
+function wfSpecialDoubleRedirects() {
+       global $wgOut;
+       $t = Title::makeTitle( NS_SPECIAL, "DoubleRedirects" );
+       $wgOut->redirect ($t->getFullURL());
+}
+
+function wfSpecialBrokenRedirects() {
+       global $wgOut;
+       $t = Title::makeTitle( NS_SPECIAL, "BrokenRedirects" );
+       $wgOut->redirect ($t->getFullURL());
+}
+
+function wfSpecialDisambiguations() {
+       global $wgOut;
+       $t = Title::makeTitle( NS_SPECIAL, "Disambiguations" );
+       $wgOut->redirect ($t->getFullURL());
+}
+/**#@-*/
+
+
+/**
+ * This doesn't really work anymore, because self-links are now displayed as
+ * unlinked bold text, and are not entered into the link table.
+ *
+ * @deprecated
+ */
+function wfSpecialSelfLinks() {
+       global $wgUser, $wgOut, $wgLang, $wgTitle;
+       $fname = 'wfSpecialSelfLinks';
+
+       list( $limit, $offset ) = wfCheckLimits();
+
+       $sql = "SELECT page_namespace,page_title FROM page,links " . 
+         "WHERE l_from=l_to AND l_to=page_id " . 
+         "LIMIT {$offset}, {$limit}";
+
+       $res = wfQuery( $sql, DB_SLAVE, $fname );
+
+       $top = getMaintenancePageBacklink( 'selflinks' );
+       $top .= '<p>'.wfMsg('selflinkstext')."</p><br />\n";
+       $top .= wfShowingResults( $offset, $limit );
+       $wgOut->addHTML( "<p>{$top}\n" );
+
+       $sl = wfViewPrevNext( $offset, $limit, 'REPLACETHIS' ) ;
+       $sl = str_replace ( 'REPLACETHIS' , sns().":Maintenance&subfunction=selflinks" , $sl ) ;
+       $wgOut->addHTML( "<br />{$sl}\n" );
+
+       $sk = $wgUser->getSkin();
+       $s = '<ol start=' . ( $offset + 1 ) . '>';
+       while ( $obj = wfFetchObject( $res ) ) {
+               $title = Title::makeTitle( $obj->page_namespace, $obj->page_title );
+               $s .= "<li>".$sk->makeKnownLinkObj( $title )."</li>\n" ;
+       }
+       wfFreeResult( $res );
+       $s .= '</ol>';
+       $wgOut->addHTML( $s );
+       $wgOut->addHTML( "<p>{$sl}\n" );
+}
+
+/**
+ * 
+ */
+function wfSpecialMispeelings () {
+       global $wgUser, $wgOut, $wgContLang, $wgTitle;
+       $sk = $wgUser->getSkin();
+       $fname = 'wfSpecialMispeelings';
+
+       list( $limit, $offset ) = wfCheckLimits();
+       $dbr =& wfGetDB( DB_SLAVE );
+       extract( $dbr->tableNames( 'cur', 'searchindex' ) );
+
+       # Determine page name
+       $ms = wfMsg ( 'mispeelingspage' ) ;
+       $mss = str_replace ( ' ' , '_' , $ms );
+       $msp = $wgContLang->getNsText(4).':'.$ms ;
+       $msl = $sk->makeKnownLink ( $msp ) ;
+
+       # Load list from database
+       $l = $dbr->selectField( 'cur', 'cur_text', array( 'cur_title' => $mss, 'cur_namespace' => 4 ), $fname );
+       $l = explode ( "\n" , $l ) ;
+       $a = array () ;
+       foreach ( $l as $x )
+               if ( substr ( trim ( $x ) , 0 , 1 ) == '*' )
+                       $a[] = strtolower ( trim ( substr ( trim ( $x ) , 1 ) ) );
+       asort ( $a ) ;
+
+       $cnt = 0 ;
+       $b = array () ;
+       foreach ( $a AS $x ) {
+               if ( $cnt < $offset+$limit && $x != '' ) {
+                       $y = $x ;
+                       $x = preg_replace( '/^(\S+).*$/', '$1', $x );
+                       $sql = "SELECT DISTINCT cur_title FROM $cur,$searchindex WHERE cur_id=si_page AND ".
+                               "cur_namespace=".NS_MAIN." AND cur_is_redirect=0 AND " .
+                               "(MATCH(si_text) AGAINST ('" . $dbr->strencode( $wgContLang->stripForSearch( $x ) ) . "'))" ;
+                       $res = $dbr->query( $sql, $fname );
+                       while ( $obj = $dbr->fetchObject ( $res ) ) {
+                               if ( $cnt >= $offset AND $cnt < $offset+$limit ) {
+                                       if ( $y != '' ) {
+                                               if ( count ( $b ) > 0 ) $b[] = "</OL>\n" ;
+                                               $b[] = "<H3>{$y}</H3>\n<OL start=".($cnt+1).">\n" ;
+                                               $y = '' ;
+                                       }
+                                       $b[] = '<li>'.
+                                               $sk->makeKnownLink ( $obj->cur_title ).
+                                               ' ('.
+                                               $sk->makeBrokenLink ( $obj->cur_title , wfMsg ( "qbedit" ) ).
+                                               ")</li>\n" ;
+                               }
+                               $cnt++ ;
+                       }
+               }
+       }
+       $top = getMaintenancePageBacklink( 'mispeelings' );
+       $top .= "<p>".wfMsg( 'mispeelingstext', $msl )."</p><br />\n";
+       $top .= wfShowingResults( $offset, $limit );
+       $wgOut->addHTML( "<p>{$top}\n" );
+
+       $sl = wfViewPrevNext( $offset, $limit, 'REPLACETHIS' ) ;
+       $sl = str_replace ( 'REPLACETHIS' , sns().":Maintenance&subfunction=mispeelings" , $sl ) ;
+       $wgOut->addHTML( "<br />{$sl}\n" );
+
+       $s = implode ( '' , $b ) ;
+       if ( count ( $b ) > 0 ) $s .= '</ol>';
+       $wgOut->addHTML( $s );
+       $wgOut->addHTML( "<p>{$sl}\n" );
+}
+
+/**
+ *
+ */
+function wfSpecialMissingLanguageLinks() {
+       global $wgUser, $wgOut, $wgContLang, $wgTitle, $wgRequest;
+       
+       $fname = 'wfSpecialMissingLanguageLinks';
+       $thelang = $wgRequest->getText( 'thelang' );
+       if ( $thelang == 'w' ) $thelang = 'en' ; # Fix for international wikis
+
+       list( $limit, $offset ) = wfCheckLimits();
+       $dbr =& wfGetDB( DB_SLAVE );
+       $cur = $dbr->tableName( 'cur' );
+
+       $sql = "SELECT cur_title FROM $cur " .
+         "WHERE cur_namespace=".NS_MAIN." AND cur_is_redirect=0 " .
+         "AND cur_title NOT LIKE '%/%' AND cur_text NOT LIKE '%[[" . wfStrencode( $thelang ) . ":%' " .
+         "LIMIT {$offset}, {$limit}";
+
+       $res = $dbr->query( $sql, $fname );
+
+
+       $mll = wfMsg( 'missinglanguagelinkstext', $wgContLang->getLanguageName($thelang) );
+
+       $top = getMaintenancePageBacklink( 'missinglanguagelinks' );
+       $top .= "<p>$mll</p><br />";
+       $top .= wfShowingResults( $offset, $limit );
+       $wgOut->addHTML( "<p>{$top}\n" );
+
+       $sl = wfViewPrevNext( $offset, $limit, 'REPLACETHIS' ) ;
+       $sl = str_replace ( 'REPLACETHIS' , sns().":Maintenance&subfunction=missinglanguagelinks&thelang=".
+                                               htmlspecialchars($thelang), $sl ) ;
+       $wgOut->addHTML( "<br />{$sl}\n" );
+
+       $sk = $wgUser->getSkin();
+       $s = '<ol start=' . ( $offset + 1 ) . '>';
+       while ( $obj = $dbr->fetchObject( $res ) )
+               $s .= "<li>".$sk->makeKnownLink ( $obj->cur_title )."</li>\n" ;
+       $dbr->freeResult( $res );
+       $s .= '</ol>';
+       $wgOut->addHTML( $s );
+       $wgOut->addHTML( "<p>{$sl}\n" );
+}
+
+?>
diff --git a/includes/SpecialMostlinked.php b/includes/SpecialMostlinked.php
new file mode 100644 (file)
index 0000000..008a2d4
--- /dev/null
@@ -0,0 +1,69 @@
+<?php
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+require_once ( 'QueryPage.php' ) ;
+
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+class MostlinkedPage extends QueryPage {
+
+       function getName() {
+               return 'Mostlinked';
+       }
+
+       function isExpensive() {
+               return true;
+       }
+       function isSyndicated() { return false; }
+
+       function getSQL() {
+               $dbr =& wfGetDB( DB_SLAVE );
+               extract( $dbr->tableNames( 'pagelinks', 'page' ) );
+               return
+                       "SELECT 'Mostlinked' AS type,
+                               pl_namespace AS namespace,
+                               pl_title AS title,
+                               COUNT(*) AS value,
+                               page_namespace
+                       FROM $pagelinks
+                       LEFT JOIN $page ON pl_namespace=page_namespace AND pl_title=page_title
+                       GROUP BY pl_namespace,pl_title
+                       HAVING COUNT(*) > 1";
+       }
+
+       function formatResult( $skin, $result ) {
+               global $wgContLang;
+
+               $nt = Title::makeTitle( $result->namespace, $result->title );
+               $text = $wgContLang->convert( $nt->getPrefixedText() );
+               if ( is_null( $result->page_namespace ) )
+                       $plink = $skin->makeBrokenLink( $nt->getPrefixedText(), $text );
+               else
+                       $plink = $skin->makeKnownLink( $nt->getPrefixedText(), $text );
+               
+               $nl = wfMsg( "nlinks", $result->value );
+               $nlink = $skin->makeKnownLink( $wgContLang->specialPage( "Whatlinkshere" ), $nl, "target=" . $nt->getPrefixedURL() );
+
+               return "{$plink} ({$nlink})";
+       }
+}
+
+/**
+ * constructor
+ */
+function wfSpecialMostlinked() {
+       list( $limit, $offset ) = wfCheckLimits();
+
+       $wpp = new MostlinkedPage();
+
+       $wpp->doQuery( $offset, $limit );
+}
+
+?>
diff --git a/includes/SpecialMovepage.php b/includes/SpecialMovepage.php
new file mode 100644 (file)
index 0000000..b072740
--- /dev/null
@@ -0,0 +1,266 @@
+<?php
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/**
+ *
+ */
+require_once( "LinksUpdate.php" );
+
+/**
+ * Constructor
+ */
+function wfSpecialMovepage( $par = null ) {
+       global $wgUser, $wgOut, $wgRequest, $action, $wgOnlySysopMayMove;
+
+       # check rights. We don't want newbies to move pages to prevents possible attack
+       if ( !$wgUser->isAllowed( 'move' ) or $wgUser->isBlocked() or ($wgOnlySysopMayMove and $wgUser->isNewbie())) {
+               $wgOut->errorpage( "movenologin", "movenologintext" );
+               return;
+       }
+       # We don't move protected pages
+       if ( wfReadOnly() ) {
+               $wgOut->readOnlyPage();
+               return;
+       }
+
+       $f = new MovePageForm( $par );
+
+       if ( 'success' == $action ) {
+               $f->showSuccess();
+       } else if ( 'submit' == $action && $wgRequest->wasPosted()
+               && $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) ) ) {
+               $f->doSubmit();
+       } else {
+               $f->showForm( '' );
+       }
+}
+
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+class MovePageForm {
+       var $oldTitle, $newTitle, $reason; # Text input
+       var $moveTalk, $deleteAndMove;
+               
+       function MovePageForm( $par ) {
+               global $wgRequest;
+               $target = isset($par) ? $par : $wgRequest->getVal( 'target' );
+               $this->oldTitle = $wgRequest->getText( 'wpOldTitle', $target );
+               $this->newTitle = $wgRequest->getText( 'wpNewTitle' );
+               $this->reason = $wgRequest->getText( 'wpReason' );
+               $this->moveTalk = $wgRequest->getBool( 'wpMovetalk', true );
+               $this->deleteAndMove = $wgRequest->getBool( 'wpDeleteAndMove' );
+       }
+       
+       function showForm( $err ) {
+               global $wgOut, $wgUser, $wgLang;
+
+               $wgOut->setPagetitle( wfMsg( 'movepage' ) );
+
+               $ot = Title::newFromURL( $this->oldTitle );
+               if( is_null( $ot ) ) {
+                       $wgOut->errorpage( 'notargettitle', 'notargettext' );
+                       return;
+               }
+               $oldTitle = $ot->getPrefixedText();
+               
+               $encOldTitle = htmlspecialchars( $oldTitle );
+               if( $this->newTitle == '' ) {
+                       # Show the current title as a default
+                       # when the form is first opened.
+                       $encNewTitle = $encOldTitle;
+               } else {
+                       if( $err == '' ) {
+                               $nt = Title::newFromURL( $this->newTitle );
+                               if( $nt ) {
+                                       # If a title was supplied, probably from the move log revert
+                                       # link, check for validity. We can then show some diagnostic
+                                       # information and save a click.
+                                       $newerr = $ot->isValidMoveOperation( $nt );
+                                       if( is_string( $newerr ) ) {
+                                               $err = $newerr;
+                                       }
+                               }
+                       }
+                       $encNewTitle = htmlspecialchars( $this->newTitle );
+               }
+               $encReason = htmlspecialchars( $this->reason );
+
+               if ( $err == 'articleexists' && $wgUser->isAllowed( 'delete' ) ) {
+                       $wgOut->addWikiText( wfMsg( 'delete_and_move_text', $encNewTitle ) );
+                       $movepagebtn = wfMsgHtml( 'delete_and_move' );
+                       $submitVar = 'wpDeleteAndMove';
+                       $err = '';
+               } else {
+                       $wgOut->addWikiText( wfMsg( 'movepagetext' ) );
+                       $movepagebtn = wfMsgHtml( 'movepagebtn' );
+                       $submitVar = 'wpMove';
+               }
+
+               if ( !$ot->isTalkPage() ) {
+                       $wgOut->addWikiText( wfMsg( 'movepagetalktext' ) );
+               }
+
+               $movearticle = wfMsgHtml( 'movearticle' );
+               $newtitle = wfMsgHtml( 'newtitle' );
+               $movetalk = wfMsgHtml( 'movetalk' );
+               $movereason = wfMsgHtml( 'movereason' );
+
+               $titleObj = Title::makeTitle( NS_SPECIAL, 'Movepage' );
+               $action = $titleObj->escapeLocalURL( 'action=submit' );
+               $token = htmlspecialchars( $wgUser->editToken() );
+
+               if ( $err != '' ) {
+                       $wgOut->setSubtitle( wfMsg( 'formerror' ) );
+                       $wgOut->addWikiText( '<p class="error">' . wfMsg($err) . "</p>\n" );
+               }
+
+               $moveTalkChecked = $this->moveTalk ? ' checked="checked"' : '';
+               
+               $wgOut->addHTML( "
+<form id=\"movepage\" method=\"post\" action=\"{$action}\">
+       <table border='0'>
+               <tr>
+                       <td align='right'>{$movearticle}:</td>
+                       <td align='left'><strong>{$oldTitle}</strong></td>
+               </tr>
+               <tr>
+                       <td align='right'>{$newtitle}:</td>
+                       <td align='left'>
+                               <input type='text' size='40' name=\"wpNewTitle\" value=\"{$encNewTitle}\" />
+                               <input type='hidden' name=\"wpOldTitle\" value=\"{$encOldTitle}\" />
+                       </td>
+               </tr>
+               <tr>
+                       <td align='right' valign='top'><br />{$movereason}:</td>
+                       <td align='left' valign='top'><br />
+                               <textarea cols='60' rows='2' name='wpReason' id='wpReason'>{$encReason}</textarea>
+                       </td>
+               </tr>" );
+
+               if ( ! $ot->isTalkPage() ) {
+                       $wgOut->addHTML( "
+               <tr>
+                       <td align='right'>
+                               <input type='checkbox' id=\"wpMovetalk\" name=\"wpMovetalk\"{$moveTalkChecked} value=\"1\" />
+                       </td>
+                       <td><label for=\"wpMovetalk\">{$movetalk}</label></td>
+               </tr>" );
+               }
+               $wgOut->addHTML( "
+               <tr>
+                       <td>&nbsp;</td>
+                       <td align='left'>
+                               <input type='submit' name=\"{$submitVar}\" value=\"{$movepagebtn}\" />
+                       </td>
+               </tr>
+       </table>
+       <input type='hidden' name='wpEditToken' value=\"{$token}\" />
+</form>\n" );
+
+       }
+
+       function doSubmit() {
+               global $wgOut, $wgUser, $wgLang;
+               global $wgDeferredUpdateList, $wgMessageCache;
+               global  $wgUseSquid, $wgRequest;
+               $fname = "MovePageForm::doSubmit";
+               
+               if ( $wgUser->pingLimiter( 'move' ) ) {
+                       $wgOut->rateLimited();
+                       return;
+               }
+               
+               # Variables beginning with 'o' for old article 'n' for new article
+
+               $ot = Title::newFromText( $this->oldTitle );
+               $nt = Title::newFromText( $this->newTitle );
+
+               # Delete to make way if requested
+               if ( $wgUser->isAllowed( 'delete' ) && $this->deleteAndMove ) {
+                       $article = new Article( $nt );
+                       // This may output an error message and exit
+                       $article->doDelete( wfMsgForContent( 'delete_and_move_reason' ) );
+               }
+
+               # don't allow moving to pages with # in
+               if ( !$nt || $nt->getFragment() != '' ) {
+                       $this->showForm( 'badtitletext' );
+                       return;
+               }
+
+               $error = $ot->moveTo( $nt, true, $this->reason );
+               if ( $error !== true ) {
+                       $this->showForm( $error );
+                       return;
+               }
+               
+               # Move talk page if
+               # (1) the checkbox says to,
+               # (2) the namespaces are not themselves talk namespaces, and of course
+               # (3) it exists.
+               if ( ( $wgRequest->getVal('wpMovetalk') == 1 ) &&
+                    !$ot->isTalkPage() &&
+                    !$nt->isTalkPage() ) {
+                       
+                       $ott = $ot->getTalkPage();
+                       $ntt = $nt->getTalkPage();
+
+                       # Attempt the move
+                       $error = $ott->moveTo( $ntt, true, $this->reason );
+                       if ( $error === true ) {
+                               $talkmoved = 1;
+                       } else {
+                               $talkmoved = $error;
+                       }
+               } else {
+                       # Stay silent on the subject of talk.
+                       $talkmoved = '';
+               }
+               
+               # Give back result to user.
+               $titleObj = Title::makeTitle( NS_SPECIAL, 'Movepage' );
+               $success = $titleObj->getFullURL( 
+                 'action=success&oldtitle=' . wfUrlencode( $ot->getPrefixedText() ) .
+                 '&newtitle=' . wfUrlencode( $nt->getPrefixedText() ) .
+                 '&talkmoved='.$talkmoved );
+
+               $wgOut->redirect( $success );
+       }
+
+       function showSuccess() {
+               global $wgOut, $wgRequest, $wgRawHtml;
+
+               $wgOut->setPagetitle( wfMsg( 'movepage' ) );
+               $wgOut->setSubtitle( wfMsg( 'pagemovedsub' ) );
+               $oldtitle = $wgRequest->getVal('oldtitle');
+               $newtitle = $wgRequest->getVal('newtitle');
+               $talkmoved = $wgRequest->getVal('talkmoved');
+
+               $text = wfMsg( 'pagemovedtext', $oldtitle, $newtitle );
+               
+               # Temporarily disable raw html wikitext option out of XSS paranoia
+               $marchingantofdoom = $wgRawHtml;
+               $wgRawHtml = false;
+               $wgOut->addWikiText( $text );
+               $wgRawHtml = $marchingantofdoom;
+
+               if ( $talkmoved == 1 ) {
+                       $wgOut->addWikiText( wfMsg( 'talkpagemoved' ) );
+               } elseif( 'articleexists' == $talkmoved ) {
+                       $wgOut->addWikiText( wfMsg( 'talkexists' ) );
+               } else {
+                       $ot = Title::newFromURL( $oldtitle );
+                       if ( ! $ot->isTalkPage() ) {
+                               $wgOut->addWikiText( wfMsg( 'talkpagenotmoved', wfMsg( $talkmoved ) ) );
+                       }
+               }
+       }
+}
+?>
diff --git a/includes/SpecialNewimages.php b/includes/SpecialNewimages.php
new file mode 100644 (file)
index 0000000..744eb0e
--- /dev/null
@@ -0,0 +1,145 @@
+<?php
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/** */
+require_once( 'ImageGallery.php' );
+
+/**
+ *
+ */
+function wfSpecialNewimages() {
+       global $wgUser, $wgOut, $wgLang, $wgContLang, $wgRequest;
+       
+       $wpIlMatch = $wgRequest->getText( 'wpIlMatch' );
+       $dbr =& wfGetDB( DB_SLAVE );
+       $sk = $wgUser->getSkin();
+
+       /** If we were clever, we'd use this to cache. */
+       $latestTimestamp = wfTimestamp( TS_MW, $dbr->selectField(
+               'image', 'img_timestamp',
+               '', 'wfSpecialNewimages',
+               array( 'ORDER BY' => 'img_timestamp DESC',
+                      'LIMIT' => 1 ) ) );
+       
+       /** Hardcode this for now. */
+       $limit = 48;
+       
+       $where = array();
+       if ( $wpIlMatch != '' ) {
+               $nt = Title::newFromUrl( $wpIlMatch );
+               if($nt ) {
+                       $m = $dbr->strencode( strtolower( $nt->getDBkey() ) );
+                       $m = str_replace( '%', "\\%", $m );
+                       $m = str_replace( '_', "\\_", $m );
+                       $where[] = "LCASE(img_name) LIKE '%{$m}%'";
+               }
+       }       
+       
+       $invertSort = false;
+       if( $until = $wgRequest->getVal( 'until' ) ) {
+               $where[] = 'img_timestamp < ' . $dbr->timestamp( $until );
+       }
+       if( $from = $wgRequest->getVal( 'from' ) ) {
+               $where[] = 'img_timestamp >= ' . $dbr->timestamp( $from );
+               $invertSort = true;
+       }
+       
+       $res = $dbr->select( 'image',
+               array( 'img_size', 'img_name', 'img_user', 'img_user_text',
+                      'img_description', 'img_timestamp' ),
+               $where,
+               'wfSpecialNewimages',
+               array( 'LIMIT' => $limit + 1,
+                      'ORDER BY' => 'img_timestamp' . ( $invertSort ? '' : ' DESC' ) )
+       );
+
+       /**
+        * We have to flip things around to get the last N after a certain date
+        */
+       $images = array();
+       while ( $s = $dbr->fetchObject( $res ) ) {
+               if( $invertSort ) {
+                       array_unshift( $images, $s );
+               } else {
+                       array_push( $images, $s );
+               }
+       }
+       $dbr->freeResult( $res );
+       
+       $gallery = new ImageGallery();
+       $firstTimestamp = null;
+       $lastTimestamp = null;
+       $shownImages = 0;
+       foreach( $images as $s ) {
+               if( ++$shownImages > $limit ) {
+                       # One extra just to test for whether to show a page link;
+                       # don't actually show it.
+                       break;
+               }
+               
+               $name = $s->img_name;
+               $ut = $s->img_user_text;
+
+               $nt = Title::newFromText( $name, NS_IMAGE );
+               $img = Image::newFromTitle( $nt );
+               $ul = $sk->makeLinkObj( Title::makeTitle( NS_USER, $ut ), $ut );
+
+               $gallery->add( $img, "$ul<br />\n<i>".$wgLang->timeanddate( $s->img_timestamp, true )."</i><br />\n" );
+               
+               $timestamp = wfTimestamp( TS_MW, $s->img_timestamp );
+               if( empty( $firstTimestamp ) ) {
+                       $firstTimestamp = $timestamp;
+               }
+               $lastTimestamp = $timestamp;
+       }
+       
+       $bydate = wfMsg( 'bydate' );
+       $lt = $wgLang->formatNum( min( $shownImages, $limit ) );
+       $text = wfMsg( "imagelisttext",
+               "<strong>{$lt}</strong>", "<strong>{$bydate}</strong>" );
+       $wgOut->addHTML( "<p>{$text}\n</p>" );
+
+       $sub = wfMsg( 'ilsubmit' );
+       $titleObj = Title::makeTitle( NS_SPECIAL, 'Newimages' );
+       $action = $titleObj->escapeLocalURL(  "limit={$limit}" );
+
+       $wgOut->addHTML( "<form id=\"imagesearch\" method=\"post\" action=\"" .
+         "{$action}\">" .
+         "<input type='text' size='20' name=\"wpIlMatch\" value=\"" .
+         htmlspecialchars( $wpIlMatch ) . "\" /> " .
+         "<input type='submit' name=\"wpIlSubmit\" value=\"{$sub}\" /></form>" );
+       $here = $wgContLang->specialPage( 'Newimages' );
+
+       /**
+        * Paging controls...
+        */
+       $now = wfTimestampNow();
+       $date = $wgLang->timeanddate( $now );
+       $dateLink = $sk->makeKnownLinkObj( $titleObj, wfMsg( 'rclistfrom', $date ), 'from=' . $now );
+       
+       $prevLink = wfMsg( 'prevn', $wgLang->formatNum( $limit ) );
+       if( $firstTimestamp && $firstTimestamp != $latestTimestamp ) {
+               $prevLink = $sk->makeKnownLinkObj( $titleObj, $prevLink, 'from=' . $firstTimestamp );
+       }
+       
+       $nextLink = wfMsg( 'nextn', $wgLang->formatNum( $limit ) );
+       if( $shownImages > $limit && $lastTimestamp ) {
+               $nextLink = $sk->makeKnownLinkObj( $titleObj, $nextLink, 'until=' . $lastTimestamp );
+       }
+       
+       $prevnext = '<p>' . wfMsg( 'viewprevnext', $prevLink, $nextLink, $dateLink ) . '</p>';
+       $wgOut->addHTML( $prevnext );
+       
+       if( count( $images ) ) {
+               $wgOut->addHTML( $gallery->toHTML() );
+               $wgOut->addHTML( $prevnext );
+       } else {
+               $wgOut->addWikiText( wfMsg( 'noimages' ) );
+       }
+}
+
+?>
diff --git a/includes/SpecialNewpages.php b/includes/SpecialNewpages.php
new file mode 100644 (file)
index 0000000..3b24cc2
--- /dev/null
@@ -0,0 +1,137 @@
+<?php
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/**
+ *
+ */
+require_once( 'QueryPage.php' );
+
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+class NewPagesPage extends QueryPage {
+
+       function getName() {
+               return 'Newpages';
+       }
+
+       function isExpensive() {
+               # Indexed on RC, and will *not* work with querycache yet.
+               return false;
+               #return parent::isExpensive();
+       }
+
+       function getSQL() {
+               global $wgUser, $wgOnlySysopsCanPatrol, $wgUseRCPatrol;
+               $usepatrol = ( $wgUseRCPatrol && $wgUser->isLoggedIn() &&
+                              ( $wgUser->isAllowed('patrol') || !$wgOnlySysopsCanPatrol ) ) ? 1 : 0;
+               $dbr =& wfGetDB( DB_SLAVE );
+               extract( $dbr->tableNames( 'recentchanges', 'page', 'text' ) );
+
+               # FIXME: text will break with compression
+               return
+                       "SELECT 'Newpages' as type,
+                               rc_namespace AS namespace,
+                               rc_title AS title,
+                               rc_cur_id AS value,
+                               rc_user AS user,
+                               rc_user_text AS user_text,
+                               rc_comment as comment,
+                               rc_timestamp AS timestamp,
+                               '{$usepatrol}' as usepatrol,
+                               rc_patrolled AS patrolled,
+                               rc_id AS rcid,
+                               page_len as length,
+                               page_latest as rev_id
+                       FROM $recentchanges,$page
+                       WHERE rc_cur_id=page_id AND rc_new=1
+                         AND rc_namespace=".NS_MAIN." AND page_is_redirect=0";
+       }
+
+       function formatResult( $skin, $result ) {
+               global $wgLang, $wgContLang, $wgUser, $wgOnlySysopsCanPatrol, $wgUseRCPatrol;
+               $u = $result->user;
+               $ut = $result->user_text;
+
+               $length = wfMsg( 'nbytes', $wgLang->formatNum( $result->length ) );
+
+               if ( $u == 0 ) { # not by a logged-in user
+                       $userPage = Title::makeTitle( NS_SPECIAL, 'Contributions' );
+                       $linkParams = 'target=' . urlencode( $ut );
+               } else {
+                       $userPage = Title::makeTitle( NS_USER, $ut );
+                       $linkParams = '';
+               }
+               $ul = $skin->makeLinkObj( $userPage, htmlspecialchars( $ut ), $linkParams );
+
+               $d = $wgLang->timeanddate( $result->timestamp, true );
+
+               # Since there is no diff link, we need to give users a way to
+               # mark the article as patrolled if it isn't already
+               if ( $wgUseRCPatrol && !is_null ( $result->usepatrol ) && $result->usepatrol &&
+                    $result->patrolled == 0 && $wgUser->isLoggedIn() &&
+                    ( $wgUser->isAllowed('patrol') || !$wgOnlySysopsCanPatrol ) )
+                       $link = $skin->makeKnownLink( $result->title, '', "rcid={$result->rcid}" );
+               else
+                       $link = $skin->makeKnownLink( $result->title, '' );
+
+               $s = "{$d} {$link} ({$length}) . . {$ul}";
+
+               $s .= $skin->commentBlock( $result->comment );
+
+               return $s;
+       }
+       
+       function feedItemDesc( $row ) {
+               if( isset( $row->rev_id ) ) {
+                       $revision = Revision::newFromId( $row->rev_id );
+                       if( $revision ) {
+                               return '<p>' . htmlspecialchars( wfMsg( 'summary' ) ) . ': ' . $text . "</p>\n<hr />\n<div>" .
+                                       nl2br( htmlspecialchars( $revision->getText() ) ) . "</div>";
+                       }
+               }
+               return parent::feedItemDesc( $row );
+       }
+}
+
+/**
+ * constructor
+ */
+function wfSpecialNewpages($par, $specialPage)
+{
+       global $wgRequest;
+       list( $limit, $offset ) = wfCheckLimits();
+       if( $par ) {
+               $bits = preg_split( '/\s*,\s*/', trim( $par ) );
+               foreach ( $bits as $bit ) {
+                       if ( 'shownav' == $bit ) $shownavigation = 1;
+                       if ( is_numeric( $bit ) ) {
+                               $limit = $bit;
+                       }
+
+                       if ( preg_match( '/^limit=(\d+)$/', $bit, $m ) ) {
+                               $limit = intval($m[1]);
+                       }
+                       if ( preg_match( '/^offset=(\d+)$/', $bit, $m ) ) {
+                               $offset = intval($m[1]);
+                       }
+               }
+       }
+       if(!isset($shownavigation)) {
+               $shownavigation=!$specialPage->including();
+       }
+
+       $npp = new NewPagesPage();
+
+       if( !$npp->doFeed( $wgRequest->getVal( 'feed' ) ) ) {
+               $npp->doQuery( $offset, $limit, $shownavigation );
+       }
+}
+
+?>
diff --git a/includes/SpecialPage.php b/includes/SpecialPage.php
new file mode 100644 (file)
index 0000000..4fbd7b9
--- /dev/null
@@ -0,0 +1,434 @@
+<?php
+/**
+ * SpecialPage: handling special pages and lists thereof
+ * $wgSpecialPages is a list of all SpecialPage objects. These objects are
+ * either instances of SpecialPage or a sub-class thereof. They have an
+ * execute() method, which sends the HTML for the special page to $wgOut.
+ * The parent class has an execute() method which distributes the call to
+ * the historical global functions. Additionally, execute() also checks if the
+ * user has the necessary access privileges and bails out if not.
+ *
+ * To add a special page at run-time, use SpecialPage::addPage().
+ * DO NOT manipulate this array at run-time.
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+
+/**
+ * @access private
+ */
+$wgSpecialPages = array(
+       'DoubleRedirects'       => new SpecialPage ( 'DoubleRedirects' ),
+       'BrokenRedirects'       => new SpecialPage ( 'BrokenRedirects' ),
+       'Disambiguations'       => new SpecialPage ( 'Disambiguations' ),
+
+       'Userlogin'         => new SpecialPage( 'Userlogin' ),
+       'Userlogout'        => new UnlistedSpecialPage( 'Userlogout' ),
+       'Preferences'       => new SpecialPage( 'Preferences' ),
+       'Watchlist'         => new SpecialPage( 'Watchlist' ),
+
+       'Recentchanges'     => new IncludableSpecialPage( 'Recentchanges' ),
+       'Upload'            => new SpecialPage( 'Upload' ),
+       'Imagelist'         => new SpecialPage( 'Imagelist' ),
+       'Newimages'         => new SpecialPage( 'Newimages' ),
+       'Listusers'         => new SpecialPage( 'Listusers' ),
+       'Statistics'        => new SpecialPage( 'Statistics' ),
+       'Random'        => new SpecialPage( 'Randompage' ),
+       'Lonelypages'       => new SpecialPage( 'Lonelypages' ),
+       'Uncategorizedpages'=> new SpecialPage( 'Uncategorizedpages' ),
+       'Uncategorizedcategories'=> new SpecialPage( 'Uncategorizedcategories' ),
+       'Unusedcategories'      => new SpecialPage( 'Unusedcategories' ),
+       'Unusedimages'      => new SpecialPage( 'Unusedimages' ),
+       'Wantedpages'   => new SpecialPage( 'Wantedpages' ),
+       'Mostlinked'    => new SpecialPage( 'Mostlinked' ),
+       'Shortpages'    => new SpecialPage( 'Shortpages' ),
+       'Longpages'             => new SpecialPage( 'Longpages' ),
+       'Newpages'              => new IncludableSpecialPage( 'Newpages' ),
+       'Ancientpages'  => new SpecialPage( 'Ancientpages' ),
+       'Deadendpages'  => new SpecialPage( 'Deadendpages' ),
+       'Allpages'              => new IncludableSpecialPage( 'Allpages' ),
+       'Ipblocklist'   => new SpecialPage( 'Ipblocklist' ),
+       'Specialpages'  => new UnlistedSpecialPage( 'Specialpages' ),
+       'Contributions' => new UnlistedSpecialPage( 'Contributions' ),
+       'Emailuser'             => new UnlistedSpecialPage( 'Emailuser' ),
+       'Whatlinkshere' => new UnlistedSpecialPage( 'Whatlinkshere' ),
+       'Recentchangeslinked' => new UnlistedSpecialPage( 'Recentchangeslinked' ),
+       'Movepage'              => new UnlistedSpecialPage( 'Movepage' ),
+       'Blockme'       => new UnlistedSpecialPage( 'Blockme' ),
+       'Booksources'   => new SpecialPage( 'Booksources' ),
+       'Categories'    => new SpecialPage( 'Categories' ),
+       'Export'                => new SpecialPage( 'Export' ),
+       'Version'               => new SpecialPage( 'Version' ),
+       'Allmessages'   => new SpecialPage( 'Allmessages' ),
+       'Log'           => new SpecialPage( 'Log' ),
+       'Blockip'               => new SpecialPage( 'Blockip', 'block' ),
+       'Undelete'              => new SpecialPage( 'Undelete', 'delete' ),
+       "Import"                => new SpecialPage( "Import", 'import' ),
+       'Lockdb'                => new SpecialPage( 'Lockdb', 'siteadmin' ),
+       'Unlockdb'              => new SpecialPage( 'Unlockdb', 'siteadmin' ),
+       'Userrights'    => new SpecialPage( 'Userrights', 'userrights' ),
+);
+
+if ( $wgUseValidation )
+       $wgSpecialPages['Validate'] = new SpecialPage( 'Validate' );
+
+if( !$wgDisableCounters ) {
+       $wgSpecialPages['Popularpages'] = new SpecialPage( 'Popularpages' );
+}
+
+if( !$wgDisableInternalSearch ) {
+       $wgSpecialPages['Search'] = new UnlistedSpecialPage( 'Search' );
+}
+
+if( $wgEmailAuthentication ) {
+       $wgSpecialPages['Confirmemail'] = new UnlistedSpecialPage( 'Confirmemail' );
+}
+
+/**
+ * Parent special page class, also static functions for handling the special
+ * page list
+ * @package MediaWiki
+ */
+class SpecialPage
+{
+       /**#@+
+        * @access private
+        */
+       /**
+        * The name of the class, used in the URL.
+        * Also used for the default <h1> heading, @see getDescription()
+        */
+       var $mName;
+       /**
+        * Minimum user level required to access this page, or "" for anyone.
+        * Also used to categorise the pages in Special:Specialpages
+        */
+       var $mRestriction;
+       /**
+        * Listed in Special:Specialpages?
+        */
+       var $mListed;
+       /**
+        * Function name called by the default execute()
+        */
+       var $mFunction;
+       /**
+        * File which needs to be included before the function above can be called
+        */
+       var $mFile;
+       /**
+        * Whether or not this special page is being included from an article
+        */
+       var $mIncluding;
+       /**
+        * Whether the special page can be included in an article
+        */
+       var $mIncludable;
+
+
+       /**#@-*/
+
+
+       /**
+        * Add a page to the list of valid special pages
+        * $obj->execute() must send HTML to $wgOut then return
+        * Use this for a special page extension
+        * @static
+        */
+       function addPage( &$obj ) {
+               global $wgSpecialPages;
+               $wgSpecialPages[$obj->mName] = $obj;
+       }
+
+       /**
+        * Remove a special page from the list
+        * Occasionally used to disable expensive or dangerous special pages
+        * @static
+        */
+       function removePage( $name ) {
+               global $wgSpecialPages;
+               unset( $wgSpecialPages[$name] );
+       }
+
+       /**
+        * Find the object with a given name and return it (or NULL)
+        * @static
+        * @param string $name
+        */
+       function getPage( $name ) {
+               global $wgSpecialPages;
+               if ( array_key_exists( $name, $wgSpecialPages ) ) {
+                       return $wgSpecialPages[$name];
+               } else {
+                       return NULL;
+               }
+       }
+
+       /**
+        * @static
+        * @param string $name
+        * @return mixed Title object if the redirect exists, otherwise NULL
+        */
+       function getRedirect( $name ) {
+               global $wgUser;
+               switch ( $name ) {
+                       case 'Mypage':
+                               return Title::makeTitle( NS_USER, $wgUser->getName() );
+                       case 'Mytalk':
+                               return Title::makeTitle( NS_USER_TALK, $wgUser->getName() );
+                       case 'Mycontributions':
+                               return Title::makeTitle( NS_SPECIAL, 'Contributions/' . $wgUser->getName() );
+                       case 'Listadmins':
+                               return Title::makeTitle( NS_SPECIAL, 'Listusers/sysop' ); # @bug 2832
+                       case 'Randompage':
+                               return Title::makeTitle( NS_SPECIAL, 'Random' );
+                       default:
+                               return NULL;
+               }
+       }
+
+       /**
+        * Return categorised listable special pages
+        * Returns a 2d array where the first index is the restriction name
+        * @static
+        */
+       function getPages() {
+               global $wgSpecialPages;
+               $pages = array(
+                 '' => array(),
+                 'sysop' => array(),
+                 'developer' => array()
+               );
+
+               foreach ( $wgSpecialPages as $name => $page ) {
+                       if ( $page->isListed() ) {
+                               $pages[$page->getRestriction()][$page->getName()] =& $wgSpecialPages[$name];
+                       }
+               }
+               return $pages;
+       }
+
+       /**
+        * Execute a special page path.
+        * The path     may contain parameters, e.g. Special:Name/Params
+        * Extracts the special page name and call the execute method, passing the parameters
+        *
+        * Returns a title object if the page is redirected, false if there was no such special
+        * page, and true if it was successful.
+        *
+        * @param $title          a title object
+        * @param $including      output is being captured for use in {{special:whatever}}
+        */
+       function executePath( &$title, $including = false ) {
+               global $wgSpecialPages, $wgOut, $wgTitle;
+
+               $bits = split( "/", $title->getDBkey(), 2 );
+               $name = $bits[0];
+               if( !isset( $bits[1] ) ) { // bug 2087
+                       $par = NULL;
+               } else {
+                       $par = $bits[1];
+               }
+
+               $page = SpecialPage::getPage( $name );
+               if ( is_null( $page ) ) {
+                       if ( $including ) {
+                               return false;
+                       } else {
+                               $redir = SpecialPage::getRedirect( $name );
+                               if ( isset( $redir ) ) {
+                                       if ( isset( $par ) )
+                                               $wgOut->redirect( $redir->getFullURL() . '/' . $par );
+                                       else
+                                               $wgOut->redirect( $redir->getFullURL() );
+                                       $retVal = $redir;
+                               } else {
+                                       $wgOut->setArticleRelated( false );
+                                       $wgOut->setRobotpolicy( "noindex,follow" );
+                                       $wgOut->errorpage( "nosuchspecialpage", "nospecialpagetext" );
+                                       $retVal = false;
+                               }
+                       }
+               } else {
+                       if ( $including && !$page->includable() ) {
+                               return false;
+                       }
+                       if($par !== NULL) {
+                               $wgTitle = Title::makeTitle( NS_SPECIAL, $name );
+                       } else {
+                               $wgTitle = $title;
+                       }
+                       $page->including( $including );
+
+                       $page->execute( $par );
+                       $retVal = true;
+               }
+               return $retVal;
+       }
+
+       /**
+        * Just like executePath() except it returns the HTML instead of outputting it
+        * Returns false if there was no such special page, or a title object if it was
+        * a redirect.
+        * @static
+        */
+       function capturePath( &$title ) {
+               global $wgOut, $wgTitle;
+
+               $oldTitle = $wgTitle;
+               $oldOut = $wgOut;
+               $wgOut = new OutputPage;
+
+               $ret = SpecialPage::executePath( $title, true );
+               if ( $ret === true ) {
+                       $ret = $wgOut->getHTML();
+               }
+               $wgTitle = $oldTitle;
+               $wgOut = $oldOut;
+               return $ret;
+       }
+
+       /**
+        * Default constructor for special pages
+        * Derivative classes should call this from their constructor
+        *     Note that if the user does not have the required level, an error message will
+        *     be displayed by the default execute() method, without the global function ever
+        *     being called.
+        *
+        *     If you override execute(), you can recover the default behaviour with userCanExecute()
+        *     and displayRestrictionError()
+        *
+        * @param string $name Name of the special page, as seen in links and URLs
+        * @param string $restriction Minimum user level required, e.g. "sysop" or "developer".
+        * @param boolean $listed Whether the page is listed in Special:Specialpages
+        * @param string $function Function called by execute(). By default it is constructed from $name
+        * @param string $file File which is included by execute(). It is also constructed from $name by default
+        */
+       function SpecialPage( $name = '', $restriction = '', $listed = true, $function = false, $file = 'default', $includable = false ) {
+               $this->mName = $name;
+               $this->mRestriction = $restriction;
+               $this->mListed = $listed;
+               $this->mIncludable = $includable;
+               if ( $function == false ) {
+                       $this->mFunction = 'wfSpecial'.$name;
+               } else {
+                       $this->mFunction = $function;
+               }
+               if ( $file === 'default' ) {
+                       $this->mFile = "Special{$name}.php";
+               } else {
+                       $this->mFile = $file;
+               }
+       }
+
+       # Accessor functions, see the descriptions of the associated variables above
+       function getName() { return $this->mName; }
+       function getRestriction() { return $this->mRestriction; }
+       function isListed() { return $this->mListed; }
+       function getFile() { return $this->mFile; }
+       function including( $x = NULL ) { return wfSetVar( $this->mIncluding, $x ); }
+       function includable( $x = NULL ) { return wfSetVar( $this->mIncludable, $x ); }
+
+       /**
+        * Checks if the given user (identified by an object) can execute this
+        * special page (as defined by $mRestriction)
+        */
+       function userCanExecute( &$user ) {
+               if ( $this->mRestriction == "" ) {
+                       return true;
+               } else {
+                       if ( in_array( $this->mRestriction, $user->getRights() ) ) {
+                               return true;
+                       } else {
+                               return false;
+                       }
+               }
+       }
+
+       /**
+        * Output an error message telling the user what access level they have to have
+        */
+       function displayRestrictionError() {
+               global $wgOut;
+               $wgOut->permissionRequired( $this->mRestriction );
+       }
+
+       /**
+        * Sets headers - this should be called from the execute() method of all derived classes!
+        */
+       function setHeaders() {
+               global $wgOut;
+               $wgOut->setArticleRelated( false );
+               $wgOut->setRobotPolicy( "noindex,follow" );
+               $wgOut->setPageTitle( $this->getDescription() );
+       }
+
+       /**
+        * Default execute method
+        * Checks user permissions, calls the function given in mFunction
+        */
+       function execute( $par ) {
+               global $wgUser, $wgOut, $wgTitle;
+
+               $this->setHeaders();
+
+               if ( $this->userCanExecute( $wgUser ) ) {
+                       if ( $this->mFile ) {
+                               require_once( $this->mFile );
+                       }
+                       $func = $this->mFunction;
+                       $func( $par, $this );
+               } else {
+                       $this->displayRestrictionError();
+               }
+       }
+
+       # Returns the name that goes in the <h1> in the special page itself, and also the name that
+       # will be listed in Special:Specialpages
+       #
+       # Derived classes can override this, but usually it is easier to keep the default behaviour.
+       # Messages can be added at run-time, see MessageCache.php
+       function getDescription() {
+               return wfMsg( strtolower( $this->mName ) );
+       }
+
+       /**
+        * Get a self-referential title object
+        */
+       function getTitle() {
+               return Title::makeTitle( NS_SPECIAL, $this->mName );
+       }
+
+       /**
+        * Set whether this page is listed in Special:Specialpages, at run-time
+        */
+       function setListed( $listed ) {
+               return wfSetVar( $this->mListed, $listed );
+       }
+
+}
+
+/**
+ * Shortcut to construct a special page which is unlisted by default
+ * @package MediaWiki
+ */
+class UnlistedSpecialPage extends SpecialPage
+{
+       function UnlistedSpecialPage( $name, $restriction = '', $function = false, $file = 'default' ) {
+               SpecialPage::SpecialPage( $name, $restriction, false, $function, $file );
+       }
+}
+
+/**
+ * Shortcut to construct an includable special  page
+ * @package MediaWiki
+ */
+class IncludableSpecialPage extends SpecialPage
+{
+       function IncludableSpecialPage( $name, $restriction = '', $listed = true, $function = false, $file = 'default' ) {
+               SpecialPage::SpecialPage( $name, $restriction, $listed, $function, $file, true );
+       }
+}
+?>
diff --git a/includes/SpecialPopularpages.php b/includes/SpecialPopularpages.php
new file mode 100644 (file)
index 0000000..930e3e9
--- /dev/null
@@ -0,0 +1,63 @@
+<?php
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/**
+ *
+ */
+require_once( "QueryPage.php" );
+
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+class PopularPagesPage extends QueryPage {
+
+       function getName() {
+               return "Popularpages";
+       }
+
+       function isExpensive() {
+               # page_counter is not indexed
+               return true;
+       }
+       function isSyndicated() { return false; }
+
+       function getSQL() {
+               $dbr =& wfGetDB( DB_SLAVE );
+               $page = $dbr->tableName( 'page' );
+
+               return
+                       "SELECT 'Popularpages' as type,
+                               page_namespace as namespace,
+                               page_title as title,
+                               page_counter as value
+                       FROM $page
+                       WHERE page_namespace=".NS_MAIN." AND page_is_redirect=0";
+       }
+
+       function formatResult( $skin, $result ) {
+               global $wgLang, $wgContLang;
+               $title = Title::makeTitle( $result->namespace, $result->title );
+               $link = $skin->makeKnownLinkObj( $title, $wgContLang->convert( $title->getPrefixedText() ) );
+               $nv = wfMsg( "nviews", $wgLang->formatNum( $result->value ) );
+               return "{$link} ({$nv})";
+       }
+}
+
+/**
+ * Constructor
+ */
+function wfSpecialPopularpages() {
+    list( $limit, $offset ) = wfCheckLimits();
+    
+    $ppp = new PopularPagesPage();
+    
+    return $ppp->doQuery( $offset, $limit );
+}
+
+?>
diff --git a/includes/SpecialPreferences.php b/includes/SpecialPreferences.php
new file mode 100644 (file)
index 0000000..bdf9e1e
--- /dev/null
@@ -0,0 +1,815 @@
+<?php
+/**
+ * Hold things related to displaying and saving user preferences.
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+if( !defined( 'MEDIAWIKI' ) )
+       die();
+
+/**
+ * Entry point that create the "Preferences" object
+ */
+function wfSpecialPreferences() {
+       global $wgRequest;
+
+       $form = new PreferencesForm( $wgRequest );
+       $form->execute();
+}
+
+/**
+ * Preferences form handling
+ * This object will show the preferences form and can save it as well.
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+class PreferencesForm {
+       var $mQuickbar, $mOldpass, $mNewpass, $mRetypePass, $mStubs;
+       var $mRows, $mCols, $mSkin, $mMath, $mDate, $mUserEmail, $mEmailFlag, $mNick;
+       var $mUserLanguage, $mUserVariant;
+       var $mSearch, $mRecent, $mHourDiff, $mSearchLines, $mSearchChars, $mAction;
+       var $mReset, $mPosted, $mToggles, $mSearchNs, $mRealName, $mImageSize;
+       var $mUnderline;
+
+       /**
+        * Constructor
+        * Load some values
+        */
+       function PreferencesForm( &$request ) {
+               global $wgLang, $wgContLang, $wgUser, $wgAllowRealName;
+
+               $this->mQuickbar = $request->getVal( 'wpQuickbar' );
+               $this->mOldpass = $request->getVal( 'wpOldpass' );
+               $this->mNewpass = $request->getVal( 'wpNewpass' );
+               $this->mRetypePass =$request->getVal( 'wpRetypePass' );
+               $this->mStubs = $request->getVal( 'wpStubs' );
+               $this->mRows = $request->getVal( 'wpRows' );
+               $this->mCols = $request->getVal( 'wpCols' );
+               $this->mSkin = $request->getVal( 'wpSkin' );
+               $this->mMath = $request->getVal( 'wpMath' );
+               $this->mDate = $request->getVal( 'wpDate' );
+               $this->mUserEmail = $request->getVal( 'wpUserEmail' );
+               $this->mRealName = $wgAllowRealName ? $request->getVal( 'wpRealName' ) : '';
+               $this->mEmailFlag = $request->getCheck( 'wpEmailFlag' ) ? 1 : 0;
+               $this->mNick = $request->getVal( 'wpNick' );
+               $this->mUserLanguage = $request->getVal( 'wpUserLanguage' );
+               $this->mUserVariant = $request->getVal( 'wpUserVariant' );
+               $this->mSearch = $request->getVal( 'wpSearch' );
+               $this->mRecent = $request->getVal( 'wpRecent' );
+               $this->mHourDiff = $request->getVal( 'wpHourDiff' );
+               $this->mSearchLines = $request->getVal( 'wpSearchLines' );
+               $this->mSearchChars = $request->getVal( 'wpSearchChars' );
+               $this->mImageSize = $request->getVal( 'wpImageSize' );
+               $this->mThumbSize = $request->getInt( 'wpThumbSize' );
+               $this->mUnderline = $request->getInt( 'wpOpunderline' );
+               $this->mAction = $request->getVal( 'action' );
+               $this->mReset = $request->getCheck( 'wpReset' );
+               $this->mPosted = $request->wasPosted();
+               $this->mSuccess = $request->getCheck( 'success' );
+
+               $this->mSaveprefs = $request->getCheck( 'wpSaveprefs' ) &&
+                       $this->mPosted &&
+                       $wgUser->matchEditToken( $request->getVal( 'wpEditToken' ) );
+
+               # User toggles  (the big ugly unsorted list of checkboxes)
+               $this->mToggles = array();
+               if ( $this->mPosted ) {
+                       $togs = $wgLang->getUserToggles();
+                       foreach ( $togs as $tname ) {
+                               $this->mToggles[$tname] = $request->getCheck( "wpOp$tname" ) ? 1 : 0;
+                       }
+               }
+
+               $this->mUsedToggles = array();
+
+               # Search namespace options
+               # Note: namespaces don't necessarily have consecutive keys
+               $this->mSearchNs = array();
+               if ( $this->mPosted ) {
+                       $namespaces = $wgContLang->getNamespaces();
+                       foreach ( $namespaces as $i => $namespace ) {
+                               if ( $i >= 0 ) {
+                                       $this->mSearchNs[$i] = $request->getCheck( "wpNs$i" ) ? 1 : 0;
+                               }
+                       }
+               }
+
+               # Validate language
+               if ( !preg_match( '/^[a-z\-]*$/', $this->mUserLanguage ) ) {
+                       $this->mUserLanguage = 'nolanguage';
+               }
+       }
+
+       function execute() {
+               global $wgUser, $wgOut;
+
+               if ( $wgUser->isAnon() ) {
+                       $wgOut->errorpage( 'prefsnologin', 'prefsnologintext' );
+                       return;
+               }
+               if ( wfReadOnly() ) {
+                       $wgOut->readOnlyPage();
+                       return;
+               }
+               if ( $this->mReset ) {
+                       $this->resetPrefs();
+                       $this->mainPrefsForm( 'reset', wfMsg( 'prefsreset' ) );
+               } else if ( $this->mSaveprefs ) {
+                       $this->savePreferences();
+               } else {
+                       $this->resetPrefs();
+                       $this->mainPrefsForm( '' );
+               }
+       }
+       /**
+        * @access private
+        */
+       function validateInt( &$val, $min=0, $max=0x7fffffff ) {
+               $val = intval($val);
+               $val = min($val, $max);
+               $val = max($val, $min);
+               return $val;
+       }
+
+       /**
+        * @access private
+        */
+       function validateIntOrNull( &$val, $min=0, $max=0x7fffffff ) {
+               $val = trim($val);
+               if($val === '') {
+                       return $val;
+               } else {
+                       return $this->validateInt( $val, $min, $max );
+               }
+       }
+
+       /**
+        * @access private
+        */
+       function validateDate( &$val, $min = 0, $max=0x7fffffff ) {
+               if ( ( sprintf('%d', $val) === $val && $val >= $min && $val <= $max ) || $val == 'ISO 8601' )
+                       return $val;
+               else
+                       return 0;
+       }
+
+       /**
+        * Used to validate the user inputed timezone before saving it as
+        * 'timeciorrection', will return '00:00' if fed bogus data.
+        * Note: It's not a 100% correct implementation timezone-wise, it will
+        * accept stuff like '14:30',
+        * @access private
+        * @param string $s the user input
+        * @return string
+        */
+       function validateTimeZone( $s ) {
+               if ( $s !== '' ) {
+                       if ( strpos( $s, ':' ) ) {
+                               # HH:MM
+                               $array = explode( ':' , $s );
+                               $hour = intval( $array[0] );
+                               $minute = intval( $array[1] );
+                       } else {
+                               $minute = intval( $s * 60 );
+                               $hour = intval( $minute / 60 );
+                               $minute = abs( $minute ) % 60;
+                       }
+                       # Max is +14:00 and min is -12:00, see:
+                       # http://en.wikipedia.org/wiki/Timezone
+                       $hour = min( $hour, 14 );
+                       $hour = max( $hour, -12 );
+                       $minute = min( $minute, 59 );
+                       $minute = max( $minute, 0 );
+                       $s = sprintf( "%02d:%02d", $hour, $minute );
+               }
+               return $s;
+       }
+
+       /**
+        * @access private
+        */
+       function savePreferences() {
+               global $wgUser, $wgLang, $wgOut;
+               global $wgEnableUserEmail, $wgEnableEmail;
+               global $wgEmailAuthentication, $wgMinimalPasswordLength;
+               global $wgAuth;
+
+
+               if ( '' != $this->mNewpass ) {
+                       if ( $this->mNewpass != $this->mRetypePass ) {
+                               $this->mainPrefsForm( 'error', wfMsg( 'badretype' ) );
+                               return;
+                       }
+
+                       if ( strlen( $this->mNewpass ) < $wgMinimalPasswordLength ) {
+                               $this->mainPrefsForm( 'error', wfMsg( 'passwordtooshort', $wgMinimalPasswordLength ) );
+                               return;
+                       }
+
+                       if (!$wgUser->checkPassword( $this->mOldpass )) {
+                               $this->mainPrefsForm( 'error', wfMsg( 'wrongpassword' ) );
+                               return;
+                       }
+                       if (!$wgAuth->setPassword( $wgUser, $this->mNewpass )) {
+                               $this->mainPrefsForm( 'error', wfMsg( 'externaldberror' ) );
+                               return;
+                       }
+                       $wgUser->setPassword( $this->mNewpass );
+               }
+               $wgUser->setRealName( $this->mRealName );
+
+               if( $wgUser->getOption( 'language' ) !== $this->mUserLanguage ) {
+                       $needRedirect = true;
+               } else {
+                       $needRedirect = false;
+               }
+
+               $wgUser->setOption( 'language', $this->mUserLanguage );
+               $wgUser->setOption( 'variant', $this->mUserVariant );
+               $wgUser->setOption( 'nickname', $this->mNick );
+               $wgUser->setOption( 'quickbar', $this->mQuickbar );
+               $wgUser->setOption( 'skin', $this->mSkin );
+               global $wgUseTeX;
+               if( $wgUseTeX ) {
+                       $wgUser->setOption( 'math', $this->mMath );
+               }
+               $wgUser->setOption( 'date', $this->validateDate( $this->mDate, 0, 20 ) );
+               $wgUser->setOption( 'searchlimit', $this->validateIntOrNull( $this->mSearch ) );
+               $wgUser->setOption( 'contextlines', $this->validateIntOrNull( $this->mSearchLines ) );
+               $wgUser->setOption( 'contextchars', $this->validateIntOrNull( $this->mSearchChars ) );
+               $wgUser->setOption( 'rclimit', $this->validateIntOrNull( $this->mRecent ) );
+               $wgUser->setOption( 'rows', $this->validateInt( $this->mRows, 4, 1000 ) );
+               $wgUser->setOption( 'cols', $this->validateInt( $this->mCols, 4, 1000 ) );
+               $wgUser->setOption( 'stubthreshold', $this->validateIntOrNull( $this->mStubs ) );
+               $wgUser->setOption( 'timecorrection', $this->validateTimeZone( $this->mHourDiff, -12, 14 ) );
+               $wgUser->setOption( 'imagesize', $this->mImageSize );
+               $wgUser->setOption( 'thumbsize', $this->mThumbSize );
+               $wgUser->setOption( 'underline', $this->validateInt($this->mUnderline, 0, 2) );
+
+               # Set search namespace options
+               foreach( $this->mSearchNs as $i => $value ) {
+                       $wgUser->setOption( "searchNs{$i}", $value );
+               }
+
+               if( $wgEnableEmail && $wgEnableUserEmail ) {
+                       $wgUser->setOption( 'disablemail', $this->mEmailFlag );
+               }
+
+               # Set user toggles
+               foreach ( $this->mToggles as $tname => $tvalue ) {
+                       $wgUser->setOption( $tname, $tvalue );
+               }
+               if (!$wgAuth->updateExternalDB($wgUser)) {
+                       $this->mainPrefsForm( wfMsg( 'externaldberror' ) );
+                       return;
+               }
+               $wgUser->setCookies();
+               $wgUser->saveSettings();
+
+               $error = false;
+               if( $wgEnableEmail ) {
+                       $newadr = $this->mUserEmail;
+                       $oldadr = $wgUser->getEmail();
+                       if( ($newadr != '') && ($newadr != $oldadr) ) {
+                               # the user has supplied a new email address on the login page
+                               if( $wgUser->isValidEmailAddr( $newadr ) ) {
+                                       $wgUser->mEmail = $newadr; # new behaviour: set this new emailaddr from login-page into user database record
+                                       $wgUser->mEmailAuthenticated = null; # but flag as "dirty" = unauthenticated
+                                       $wgUser->saveSettings();
+                                       if ($wgEmailAuthentication) {
+                                               # Mail a temporary password to the dirty address.
+                                               # User can come back through the confirmation URL to re-enable email.
+                                               $result = $wgUser->sendConfirmationMail();
+                                               if( WikiError::isError( $result ) ) {
+                                                       $error = wfMsg( 'mailerror', htmlspecialchars( $result->getMessage() ) );
+                                               } else {
+                                                       $error = wfMsg( 'eauthentsent', $wgUser->getName() );
+                                               }
+                                       }
+                               } else {
+                                       $error = wfMsg( 'invalidemailaddress' );
+                               }
+                       } else {
+                               $wgUser->setEmail( $this->mUserEmail );
+                               $wgUser->setCookies();
+                               $wgUser->saveSettings();
+                       }
+               }
+
+               if( $needRedirect && $error === false ) {
+                       $title =& Title::makeTitle( NS_SPECIAL, "Preferences" );
+                       $wgOut->redirect($title->getFullURL('success'));
+                       return;
+               }
+
+               $wgOut->setParserOptions( ParserOptions::newFromUser( $wgUser ) );
+               $po = ParserOptions::newFromUser( $wgUser );
+               $this->mainPrefsForm( $error === false ? 'success' : 'error', $error);
+       }
+
+       /**
+        * @access private
+        */
+       function resetPrefs() {
+               global $wgUser, $wgLang, $wgContLang, $wgAllowRealName;
+
+               $this->mOldpass = $this->mNewpass = $this->mRetypePass = '';
+               $this->mUserEmail = $wgUser->getEmail();
+               $this->mUserEmailAuthenticationtimestamp = $wgUser->getEmailAuthenticationtimestamp();
+               $this->mRealName = ($wgAllowRealName) ? $wgUser->getRealName() : '';
+               $this->mUserLanguage = $wgUser->getOption( 'language' );
+               if( empty( $this->mUserLanguage ) ) {
+                       # Quick hack for conversions, where this value is blank
+                       global $wgContLanguageCode;
+                       $this->mUserLanguage = $wgContLanguageCode;
+               }
+               $this->mUserVariant = $wgUser->getOption( 'variant');
+               $this->mEmailFlag = $wgUser->getOption( 'disablemail' ) == 1 ? 1 : 0;
+               $this->mNick = $wgUser->getOption( 'nickname' );
+
+               $this->mQuickbar = $wgUser->getOption( 'quickbar' );
+               $this->mSkin = $wgUser->getOption( 'skin' );
+               $this->mMath = $wgUser->getOption( 'math' );
+               $this->mDate = $wgUser->getOption( 'date' );
+               $this->mRows = $wgUser->getOption( 'rows' );
+               $this->mCols = $wgUser->getOption( 'cols' );
+               $this->mStubs = $wgUser->getOption( 'stubthreshold' );
+               $this->mHourDiff = $wgUser->getOption( 'timecorrection' );
+               $this->mSearch = $wgUser->getOption( 'searchlimit' );
+               $this->mSearchLines = $wgUser->getOption( 'contextlines' );
+               $this->mSearchChars = $wgUser->getOption( 'contextchars' );
+               $this->mImageSize = $wgUser->getOption( 'imagesize' );
+               $this->mThumbSize = $wgUser->getOption( 'thumbsize' );
+               $this->mRecent = $wgUser->getOption( 'rclimit' );
+               $this->mUnderline = $wgUser->getOption( 'underline' );
+
+               $togs = $wgLang->getUserToggles();
+               foreach ( $togs as $tname ) {
+                       $ttext = wfMsg('tog-'.$tname);
+                       $this->mToggles[$tname] = $wgUser->getOption( $tname );
+               }
+
+               $namespaces = $wgContLang->getNamespaces();
+               foreach ( $namespaces as $i => $namespace ) {
+                       if ( $i >= NS_MAIN ) {
+                               $this->mSearchNs[$i] = $wgUser->getOption( 'searchNs'.$i );
+                       }
+               }
+       }
+
+       /**
+        * @access private
+        */
+       function namespacesCheckboxes() {
+               global $wgContLang, $wgUser;
+
+               # Determine namespace checkboxes
+               $namespaces = $wgContLang->getNamespaces();
+               $r1 = null;
+
+               foreach ( $namespaces as $i => $name ) {
+                       if ($i < 0)
+                               continue;
+                       $checked = $this->mSearchNs[$i] ? "checked='checked'" : '';
+                       $name = str_replace( '_', ' ', $namespaces[$i] );
+
+                       if ( empty($name) )
+                               $name = wfMsg( 'blanknamespace' );
+
+                       $r1 .= "<label><input type='checkbox' value='1' name='wpNs$i' {$checked}/>{$name}</label>\n";
+               }
+               return $r1;
+       }
+
+
+       function getToggle( $tname, $trailer = false) {
+               global $wgUser, $wgLang;
+
+               $this->mUsedToggles[$tname] = true;
+               $ttext = $wgLang->getUserToggle( $tname );
+
+               $checked = $wgUser->getOption( $tname ) == 1 ? ' checked="checked"' : '';
+               $trailer = $trailer ? $trailer : '';
+               return "<div class='toggle'><input type='checkbox' value='1' id=\"$tname\" name=\"wpOp$tname\"$checked />" .
+                       " <span class='toggletext'><label for=\"$tname\">$ttext</label>$trailer</span></div>\n";
+       }
+
+       function getToggles( $items ) {
+               $out = "";
+               foreach( $items as $item ) {
+                       if( $item === false )
+                               continue;
+                       if( is_array( $item ) ) {
+                               list( $key, $trailer ) = $item;
+                       } else {
+                               $key = $item;
+                               $trailer = false;
+                       }
+                       $out .= $this->getToggle( $key, $trailer );
+               }
+               return $out;
+       }
+
+       function addRow($td1, $td2) {
+               return "<tr><td align='right'>$td1</td><td align='left'>$td2</td></tr>";
+       }
+
+       /**
+        * @access private
+        */
+       function mainPrefsForm( $status , $message = '' ) {
+               global $wgUser, $wgOut, $wgLang, $wgContLang, $wgValidSkinNames;
+               global $wgAllowRealName, $wgImageLimits, $wgThumbLimits;
+               global $wgDisableLangConversion;
+               global $wgEnotifWatchlist, $wgEnotifUserTalk,$wgEnotifMinorEdits;
+               global $wgRCShowWatchingUsers, $wgEnotifRevealEditorAddress;
+               global $wgEnableEmail, $wgEnableUserEmail, $wgEmailAuthentication;
+               global $wgContLanguageCode, $wgDefaultSkin, $wgSkipSkins;
+
+               $wgOut->setPageTitle( wfMsg( 'preferences' ) );
+               $wgOut->setArticleRelated( false );
+               $wgOut->setRobotpolicy( 'noindex,nofollow' );
+
+               if ( $this->mSuccess || 'success' == $status ) {
+                       $wgOut->addWikitext( '<span class="preferences-save-success">'. wfMsg( 'savedprefs' ) . "</span>\n----" );
+               } else  if ( 'error' == $status ) {
+                       $wgOut->addWikitext( "<span class='error'>" . $message  . "</span>\n----" );
+               } else if ( '' != $status ) {
+                       $wgOut->addWikitext( $message . "\n----" );
+               }
+               $uname = $wgUser->getName();
+               $uid = $wgUser->getID();
+
+               $wgOut->addWikiText( wfMsg( 'prefslogintext', $uname, $uid ) );
+               $wgOut->addWikiText( wfMsg('clearyourcache'));
+
+               $qbs = $wgLang->getQuickbarSettings();
+               $skinNames = $wgLang->getSkinNames();
+               $mathopts = $wgLang->getMathNames();
+               $dateopts = $wgLang->getDateFormats();
+               $togs = $wgLang->getUserToggles();
+
+               $titleObj = Title::makeTitle( NS_SPECIAL, 'Preferences' );
+               $action = $titleObj->escapeLocalURL();
+
+               # Pre-expire some toggles so they won't show if disabled
+               $this->mUsedToggles[ 'shownumberswatching' ] = true;
+               $this->mUsedToggles[ 'showupdated' ] = true;
+               $this->mUsedToggles[ 'enotifwatchlistpages' ] = true;
+               $this->mUsedToggles[ 'enotifusertalkpages' ] = true;
+               $this->mUsedToggles[ 'enotifminoredits' ] = true;
+               $this->mUsedToggles[ 'enotifrevealaddr' ] = true;
+
+               # Enotif
+               # <FIXME>
+               $this->mUserEmail = htmlspecialchars( $this->mUserEmail );
+               $this->mRealName = htmlspecialchars( $this->mRealName );
+               $this->mNick = htmlspecialchars( $this->mNick );
+               if ( $this->mEmailFlag ) { $emfc = 'checked="checked"'; }
+               else { $emfc = ''; }
+
+               if ($wgEmailAuthentication && ($this->mUserEmail != '') ) {
+                       if( $wgUser->getEmailAuthenticationTimestamp() ) {
+                               $emailauthenticated = wfMsg('emailauthenticated',$wgLang->timeanddate($wgUser->getEmailAuthenticationTimestamp(), true ) ).'<br />';
+                       } else {
+                               $skin = $wgUser->getSkin();
+                               $emailauthenticated = wfMsg('emailnotauthenticated').'<br />' .
+                                       $skin->makeKnownLinkObj( Title::makeTitle( NS_SPECIAL, 'Confirmemail' ),
+                                               wfMsg( 'emailconfirmlink' ) );
+                       }
+               } else {
+                       $emailauthenticated = '';
+               }
+
+               if ($this->mUserEmail == '') {
+                       $emailauthenticated = wfMsg( 'noemailprefs' );
+               }
+
+               $ps = $this->namespacesCheckboxes();
+
+               $enotifwatchlistpages = ($wgEnotifWatchlist) ? $this->getToggle( 'enotifwatchlistpages' ) : '';
+               $enotifusertalkpages = ($wgEnotifUserTalk) ? $this->getToggle( 'enotifusertalkpages' ) : '';
+               $enotifminoredits = ($wgEnotifWatchlist && $wgEnotifMinorEdits) ? $this->getToggle( 'enotifminoredits' ) : '';
+               $enotifrevealaddr = (($wgEnotifWatchlist || $wgEnotifUserTalk) && $wgEnotifRevealEditorAddress) ? $this->getToggle( 'enotifrevealaddr' ) : '';
+               $prefs_help_email_enotif = ( $wgEnotifWatchlist || $wgEnotifUserTalk) ? ' ' . wfMsg('prefs-help-email-enotif') : '';
+               $prefs_help_realname = '';
+
+               # </FIXME>
+
+               $wgOut->addHTML( "<form id='preferences' name='preferences' action=\"$action\" method='post'>" );
+
+               # User data
+               #
+
+               $wgOut->addHTML( "<fieldset>\n<legend>" . wfMsg('prefs-personal') . "</legend>\n<table>\n");
+
+               if ($wgAllowRealName) {
+                       $wgOut->addHTML(
+                               $this->addRow(
+                                       wfMsg('yourrealname'),
+                                       "<input type='text' name='wpRealName' value=\"{$this->mRealName}\" size='25' />"
+                               )
+                       );
+               }
+               if ($wgEnableEmail) {
+                       $wgOut->addHTML(
+                               $this->addRow(
+                                       wfMsg( 'youremail' ),
+                                       "<input type='text' name='wpUserEmail' value=\"{$this->mUserEmail}\" size='25' />"
+                               )
+                       );
+               }
+
+               $wgOut->addHTML(
+                       $this->addRow(
+                               wfMsg( 'yournick' ),
+                               "<input type='text' name='wpNick' value=\"{$this->mNick}\" size='25' />"
+                       ) .
+                       # FIXME: The <input> part should be where the &nbsp; is, getToggle() needs
+                       # to be changed to out return its output in two parts. -ævar
+                       $this->addRow(
+                               '&nbsp;',
+                               $this->getToggle( 'fancysig' )
+                       )
+               );
+
+               /**
+                * If a bogus value is set, default to the content language.
+                * Otherwise, no default is selected and the user ends up
+                * with an Afrikaans interface since it's first in the list.
+                */
+               $languages = $wgLang->getLanguageNames();
+               $selectedLang = isset( $languages[$this->mUserLanguage] ) ? $this->mUserLanguage : $wgContLanguageCode;
+               $selbox = null;
+               foreach($languages as $code => $name) {
+                       global $IP;
+                       /* only add languages that have a file */
+                       $langfile="$IP/languages/Language".str_replace('-', '_', ucfirst($code)).".php";
+                       if(file_exists($langfile) || $code == $wgContLanguageCode) {
+                               $sel = ($code == $selectedLang)? ' selected="selected"' : '';
+                               $selbox .= "<option value=\"$code\"$sel>$code - $name</option>\n";
+                       }
+               }
+               $wgOut->addHTML( $this->addRow( wfMsg('yourlanguage'), "<select name='wpUserLanguage'>$selbox</select>" ));
+
+               /* see if there are multiple language variants to choose from*/
+               if(!$wgDisableLangConversion) {
+                       $variants = $wgContLang->getVariants();
+
+                       foreach($variants as $v) {
+                               $v = str_replace( '_', '-', strtolower($v));
+                               if($name = $languages[$v]) {
+                                       $variantArray[$v] = $name;
+                               }
+                       }
+
+                       $selbox = null;
+                       foreach($variantArray as $code => $name) {
+                               $sel = $code == $this->mUserVariant ? 'selected="selected"' : '';
+                               $selbox .= "<option value=\"$code\" $sel>$code - $name</option>";
+                       }
+
+                       if(count($variantArray) > 1) {
+                               $wgOut->addHtml(
+                                       $this->addRow( wfMsg( 'yourvariant' ), "<select name='wpUserVariant'>$selbox</select>" )
+                               );
+                       }
+               }
+               $wgOut->addHTML('</table>');
+
+               # Password
+               $this->mOldpass = htmlspecialchars( $this->mOldpass );
+               $this->mNewpass = htmlspecialchars( $this->mNewpass );
+               $this->mRetypePass = htmlspecialchars( $this->mRetypePass );
+
+               $wgOut->addHTML( '<fieldset><legend>' . wfMsg( 'changepassword' ) . '</legend><table>');
+               $wgOut->addHTML(
+                       $this->addRow( wfMsg( 'oldpassword' ), "<input type='password' name='wpOldpass' value=\"{$this->mOldpass}\" size='20' />" ) .
+                       $this->addRow( wfMsg( 'newpassword' ), "<input type='password' name='wpNewpass' value=\"{$this->mNewpass}\" size='20' />" ) .
+                       $this->addRow( wfMsg( 'retypenew' ), "<input type='password' name='wpRetypePass' value=\"{$this->mRetypePass}\" size='20' />" ) .
+                       "</table>\n" .
+                       $this->getToggle( "rememberpassword" ) . "</fieldset>\n\n" );
+
+               # <FIXME>
+               # Enotif
+                if ($wgEnableEmail) {
+                       $wgOut->addHTML( '<fieldset><legend>' . wfMsg( 'email' ) . '</legend>' );
+                        $wgOut->addHTML(
+                                $emailauthenticated.
+                                $enotifrevealaddr.
+                                $enotifwatchlistpages.
+                                $enotifusertalkpages.
+                                $enotifminoredits );
+                        if ($wgEnableUserEmail) {
+                               $emf = wfMsg( 'emailflag' );
+                                $wgOut->addHTML(
+                                "<div><label><input type='checkbox' $emfc value=\"1\" name=\"wpEmailFlag\" />$emf</label></div>" );
+                        }
+
+                       $wgOut->addHTML( '</fieldset>' );
+                }
+               # </FIXME>
+
+               if ($wgAllowRealName || $wgEnableEmail) {
+                       $wgOut->addHTML("<div class='prefsectiontip'>");
+                       $rn = $wgAllowRealName ? wfMsg('prefs-help-realname') : '';
+                       $em = $wgEnableEmail ? '<br />' .  wfMsg('prefs-help-email') : '';
+                       $wgOut->addHTML( $rn . $em  . '</div>');
+               }
+
+               $wgOut->addHTML( '</fieldset>' );
+
+               # Quickbar
+               #
+               if ($this->mSkin == 'cologneblue' || $this->mSkin == 'standard') {
+                       $wgOut->addHtml( "<fieldset>\n<legend>" . wfMsg( 'qbsettings' ) . "</legend>\n" );
+                       for ( $i = 0; $i < count( $qbs ); ++$i ) {
+                               if ( $i == $this->mQuickbar ) { $checked = ' checked="checked"'; }
+                               else { $checked = ""; }
+                               $wgOut->addHTML( "<div><label><input type='radio' name='wpQuickbar' value=\"$i\"$checked />{$qbs[$i]}</label></div>\n" );
+                       }
+                       $wgOut->addHtml( "</fieldset>\n\n" );
+               } else {
+                       # Need to output a hidden option even if the relevant skin is not in use,
+                       # otherwise the preference will get reset to 0 on submit
+                       $wgOut->addHTML( "<input type='hidden' name='wpQuickbar' value='{$this->mQuickbar}' />" );
+               }
+
+               # Skin
+               #
+               $wgOut->addHTML( "<fieldset>\n<legend>\n" . wfMsg('skin') . "</legend>\n" );
+               $mptitle = Title::newMainPage();
+               $previewtext = wfMsg('skinpreview');
+               # Only show members of $wgValidSkinNames rather than
+               # $skinNames (skins is all skin names from Language.php)
+               foreach ($wgValidSkinNames as $skinkey => $skinname ) {
+                       if ( in_array( $skinkey, $wgSkipSkins ) ) {
+                               continue;
+                       }
+                       $checked = $skinkey == $this->mSkin ? ' checked="checked"' : '';
+                       $sn = isset( $skinNames[$skinkey] ) ? $skinNames[$skinkey] : $skinname;
+
+                       $mplink = htmlspecialchars($mptitle->getLocalURL("useskin=$skinkey"));
+                       $previewlink = "<a target='_blank' href=\"$mplink\">$previewtext</a>";
+                       if( $skinkey == $wgDefaultSkin )
+                               $sn .= ' (' . wfMsg( 'default' ) . ')';
+                       $wgOut->addHTML( "<input type='radio' name='wpSkin' value=\"$skinkey\"$checked /> {$sn} $previewlink<br/>\n" );
+               }
+               $wgOut->addHTML( "</fieldset>\n\n" );
+
+               # Math
+               #
+               global $wgUseTeX;
+               if( $wgUseTeX ) {
+                       $wgOut->addHTML( "<fieldset>\n<legend>" . wfMsg('math') . '</legend>' );
+                       foreach ( $mathopts as $k => $v ) {
+                               $checked = $k == $this->mMath ? ' checked="checked"' : '';
+                               $wgOut->addHTML( "<div><label><input type='radio' name='wpMath' value=\"$k\"$checked /> ".wfMsg($v)."</label></div>\n" );
+                       }
+                       $wgOut->addHTML( "</fieldset>\n\n" );
+               }
+
+               # Files
+               #
+               $wgOut->addHTML("<fieldset>
+                       <legend>" . wfMsg( 'files' ) . "</legend>
+                       <div><label>" . wfMsg('imagemaxsize') . "<select name=\"wpImageSize\">");
+
+                       $imageLimitOptions = null;
+                       foreach ( $wgImageLimits as $index => $limits ) {
+                               $selected = ($index == $this->mImageSize) ? 'selected="selected"' : '';
+                               $imageLimitOptions .= "<option value=\"{$index}\" {$selected}>{$limits[0]}×{$limits[1]}". wfMsgHtml('unit-pixel') ."</option>\n";
+                       }
+
+                       $imageThumbOptions = null;
+                       $wgOut->addHTML( "{$imageLimitOptions}</select></label></div>
+                               <div><label>" . wfMsg('thumbsize') . "<select name=\"wpThumbSize\">");
+                       foreach ( $wgThumbLimits as $index => $size ) {
+                               $selected = ($index == $this->mThumbSize) ? 'selected="selected"' : '';
+                               $imageThumbOptions .= "<option value=\"{$index}\" {$selected}>{$size}". wfMsgHtml('unit-pixel') ."</option>\n";
+                       }
+                       $wgOut->addHTML( "{$imageThumbOptions}</select></label></div></fieldset>\n\n");
+
+                # Date format
+                #
+               if ($dateopts) {
+                       $wgOut->addHTML( "<fieldset>\n<legend>" . wfMsg('dateformat') . "</legend>\n" );
+                       foreach($dateopts as $key => $option) {
+                               ($key == $this->mDate) ? $checked = ' checked="checked"' : $checked = '';
+                               $wgOut->addHTML( "<div><label><input type='radio' name=\"wpDate\" ".
+                                       "value=\"$key\"$checked />$option</label></div>\n" );
+                       }
+                       $wgOut->addHTML( "</fieldset>\n\n");
+               }
+
+               # Time zone
+               #
+
+               $nowlocal = $wgLang->time( $now = wfTimestampNow(), true );
+               $nowserver = $wgLang->time( $now, false );
+
+               $wgOut->addHTML( '<fieldset><legend>' . wfMsg( 'timezonelegend' ) . '</legend><table>' .
+                       $this->addRow( wfMsg( 'servertime' ), $nowserver ) .
+                       $this->addRow( wfMsg( 'localtime' ), $nowlocal ) .
+                       $this->addRow(
+                               wfMsg( 'timezoneoffset' ),
+                               "<input type='text' name='wpHourDiff' value=\"" . htmlspecialchars( $this->mHourDiff ) . "\" size='6' />"
+                       ) . "<tr><td colspan='2'>
+                               <input type='button' value=\"" . wfMsg( 'guesstimezone' ) ."\"
+                               onclick='javascript:guessTimezone()' id='guesstimezonebutton' style='display:none;' />
+                               </td></tr></table>
+                       <div class='prefsectiontip'>¹" .  wfMsg( 'timezonetext' ) . "</div>
+               </fieldset>\n\n" );
+
+               # Editing
+               #
+               $wgOut->addHTML( '<fieldset><legend>' . wfMsg( 'textboxsize' ) . '</legend>
+                       <div>
+                               <label>' . wfMsg( 'rows' ) . ": <input type='text' name='wpRows' value=\"{$this->mRows}\" size='6' /></label>
+                               <label>" . wfMsg( 'columns' ) . ": <input type='text' name='wpCols' value=\"{$this->mCols}\" size='6' /></label>
+                       </div>" .
+                       $this->getToggles( array(
+                               'editsection',
+                               'editsectiononrightclick',
+                               'editondblclick',
+                               'editwidth',
+                               'showtoolbar',
+                               'previewonfirst',
+                               'previewontop',
+                               'watchdefault',
+                               'minordefault',
+                               'externaleditor',
+                               'externaldiff' )
+                       ) . '</fieldset>'
+               );
+
+               $wgOut->addHTML( '<fieldset><legend>' . htmlspecialchars(wfMsg('prefs-rc')) . '</legend>
+                               <table>' .
+                                       $this->addRow(
+                                               wfMsg ( 'stubthreshold' ),
+                                               "<input type='text' name=\"wpStubs\" value=\"$this->mStubs\" size='6' />"
+                                       ) .
+                                       $this->addRow(
+                                               wfMsg( 'recentchangescount' ),
+                                               "<input type='text' name='wpRecent' value=\"$this->mRecent\" size='6' />"
+                                       ) .
+                               '</table>' .
+                       $this->getToggles( array(
+                               'hideminor',
+                               $wgRCShowWatchingUsers ? 'shownumberswatching' : false,
+                               'usenewrc' )
+                       ) . '</fieldset>'
+               );
+
+               $wgOut->addHTML( '<fieldset><legend>' . wfMsg( 'searchresultshead' ) . '</legend><table>' .
+                       $this->addRow( wfMsg( 'resultsperpage' ), "<input type='text' name='wpSearch' value=\"$this->mSearch\" size='4' />" ) .
+                       $this->addRow( wfMsg( 'contextlines' ), "<input type='text' name='wpSearchLines' value=\"$this->mSearchLines\" size='4' />" ) .
+                       $this->addRow( wfMsg( 'contextchars' ), "<input type='text' name='wpSearchChars' value=\"$this->mSearchChars\" size='4' />" ) .
+               "</table><fieldset><legend>" . wfMsg( 'defaultns' ) . "</legend>$ps</fieldset></fieldset>" );
+
+               # Misc
+               #
+               $wgOut->addHTML('<fieldset><legend>' . wfMsg('prefs-misc') . '</legend>');
+
+               $msgUnderline = htmlspecialchars(wfMsg('tog-underline'));
+               $msgUnderlinenever = htmlspecialchars(wfMsg('underline-never'));
+               $msgUnderlinealways = htmlspecialchars(wfMsg('underline-always'));
+               $msgUnderlinedefault = htmlspecialchars(wfMsg('underline-default'));
+               $uopt = $wgUser->getOption('underline');
+               $s0 = $uopt == 0 ? ' selected="selected"' : '';
+               $s1 = $uopt == 1 ? ' selected="selected"' : '';
+               $s2 = $uopt == 2 ? ' selected="selected"' : '';
+               $wgOut->addHTML("
+<div class='toggle'><label>$msgUnderline
+<select name=\"wpOpunderline\">
+<option value=\"0\"$s0>$msgUnderlinenever</option>
+<option value=\"1\"$s1>$msgUnderlinealways</option>
+<option value=\"2\"$s2>$msgUnderlinedefault</option>
+</select>
+</label>
+</div>
+");
+               foreach ( $togs as $tname ) {
+                       if( !array_key_exists( $tname, $this->mUsedToggles ) ) {
+                               $wgOut->addHTML( $this->getToggle( $tname ) );
+                       }
+               }
+               $wgOut->addHTML( '</fieldset>' );
+
+               $token = $wgUser->editToken();
+               $wgOut->addHTML( "
+       <div id='prefsubmit'>
+       <div>
+               <input type='submit' name='wpSaveprefs' value=\"" . wfMsg( 'saveprefs' ) . "\" accesskey=\"".
+               wfMsg('accesskey-save')."\" title=\"[alt-".wfMsg('accesskey-save')."]\" />
+               <input type='submit' name='wpReset' value=\"" . wfMsg( 'resetprefs' ) . "\" />
+       </div>
+
+       </div>
+
+       <input type='hidden' name='wpEditToken' value='{$token}' />
+       </form>\n" );
+       }
+}
+?>
diff --git a/includes/SpecialRandompage.php b/includes/SpecialRandompage.php
new file mode 100644 (file)
index 0000000..82d580c
--- /dev/null
@@ -0,0 +1,60 @@
+<?php
+/**
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/**
+ * Constructor
+ *
+ * @param string $par the namespace to get a random page from (default NS_MAIN), 
+ *               used as e.g. Special:Randompage/Category
+ */
+function wfSpecialRandompage( $par = NS_MAIN ) {
+       global $wgOut, $wgTitle, $wgArticle, $wgExtraRandompageSQL, $wgContLang;
+       $fname = 'wfSpecialRandompage';
+
+       # Determine the namespace to get a random page from.
+       $namespace = $wgContLang->getNsIndex($par);
+       if ($namespace === false || $namespace < NS_MAIN) {
+               $namespace = NS_MAIN;
+       }
+       
+       # NOTE! We use a literal constant in the SQL instead of the RAND()
+       # function because RAND() will return a different value for every row
+       # in the table. That's both very slow and returns results heavily
+       # biased towards low values, as rows later in the table will likely
+       # never be reached for comparison.
+       #
+       # Using a literal constant means the whole thing gets optimized on
+       # the index, and the comparison is both fast and fair.
+       
+       # interpolation and sprintf() can muck up with locale-specific decimal separator
+       $randstr = wfRandom();
+       
+       $db =& wfGetDB( DB_SLAVE );
+       $use_index = $db->useIndexClause( 'page_random' );
+       $page = $db->tableName( 'page' );
+
+       $extra = $wgExtraRandompageSQL ? "AND ($wgExtraRandompageSQL)" : '';
+       $sql = "SELECT page_id,page_title
+               FROM $page $use_index
+               WHERE page_namespace=$namespace AND page_is_redirect=0 $extra
+               AND page_random>$randstr
+               ORDER BY page_random
+               LIMIT 1";
+       $res = $db->query( $sql, $fname );
+       
+       $title = null;
+       if( $s = $db->fetchObject( $res ) ) {
+               $title =& Title::makeTitle( $namespace, $s->page_title );
+       }       
+       if( is_null( $title ) ) {
+               # That's not supposed to happen :)
+               $title = Title::newFromText( wfMsg( 'mainpage' ) );
+       }
+       $wgOut->reportTime(); # for logfile
+       $wgOut->redirect( $title->getFullUrl() );
+}
+
+?>
diff --git a/includes/SpecialRecentchanges.php b/includes/SpecialRecentchanges.php
new file mode 100644 (file)
index 0000000..ae382b7
--- /dev/null
@@ -0,0 +1,566 @@
+<?php
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/**
+ *
+ */
+require_once( 'Feed.php' );
+require_once( 'ChangesList.php' );
+require_once( 'Revision.php' );
+
+/**
+ * Constructor
+ */
+function wfSpecialRecentchanges( $par, $specialPage ) {
+       global $wgUser, $wgOut, $wgLang, $wgContLang, $wgTitle, $wgMemc, $wgDBname;
+       global $wgRequest, $wgSitename, $wgLanguageCode, $wgContLanguageCode;
+       global $wgFeedClasses, $wgUseRCPatrol;
+       global $wgRCShowWatchingUsers, $wgShowUpdatedMarker;
+       global $wgLinkCache;
+       $fname = 'wfSpecialRecentchanges';
+
+       # Get query parameters
+       $feedFormat = $wgRequest->getVal( 'feed' );
+
+       $defaults = array(
+       /* int  */ 'days' => $wgUser->getDefaultOption('rcdays'),
+       /* int  */ 'limit' => $wgUser->getDefaultOption('rclimit'),
+       /* bool */ 'hideminor' => false,
+       /* bool */ 'hidebots' => true,
+       /* bool */ 'hideliu' => false,
+       /* bool */ 'hidepatrolled' => false,
+       /* bool */ 'hidemyself' => false,
+       /* text */ 'from' => '',
+       /* text */ 'namespace' => null,
+       /* bool */ 'invert' => false,
+       );
+
+       extract($defaults);
+       
+
+       $days = $wgUser->getOption( 'rcdays' );
+       if ( !$days ) { $days = $defaults['days']; }
+       $days = $wgRequest->getInt( 'days', $days );
+
+       $limit = $wgUser->getOption( 'rclimit' );
+       if ( !$limit ) { $limit = $defaults['limit']; }
+
+       #       list( $limit, $offset ) = wfCheckLimits( 100, 'rclimit' );
+       $limit = $wgRequest->getInt( 'limit', $limit );
+
+       /* order of selection: url > preferences > default */
+       $hideminor = $wgRequest->getBool( 'hideminor', $wgUser->getOption( 'hideminor') ? true : $defaults['hideminor'] );              
+       
+       # As a feed, use limited settings only
+       if( $feedFormat ) {
+               global $wgFeedLimit;
+               if( $limit > $wgFeedLimit ) {
+                       $options['limit'] = $wgFeedLimit;
+               }
+
+       } else {
+
+               $namespace = $wgRequest->getIntOrNull( 'namespace' );
+               $invert = $wgRequest->getBool( 'invert', $defaults['invert'] );
+               $hidebots = $wgRequest->getBool( 'hidebots', $defaults['hidebots'] );
+               $hideliu = $wgRequest->getBool( 'hideliu', $defaults['hideliu'] );
+               $hidepatrolled = $wgRequest->getBool( 'hidepatrolled', $defaults['hidepatrolled'] );
+               $hidemyself = $wgRequest->getBool ( 'hidemyself', $defaults['hidemyself'] );
+               $from = $wgRequest->getVal( 'from', $defaults['from'] );        
+
+               # Get query parameters from path
+               if( $par ) {
+                       $bits = preg_split( '/\s*,\s*/', trim( $par ) );
+                       foreach ( $bits as $bit ) {
+                               if ( 'hidebots' == $bit ) $hidebots = 1;
+                               if ( 'bots' == $bit ) $hidebots = 0;
+                               if ( 'hideminor' == $bit ) $hideminor = 1;
+                               if ( 'minor' == $bit ) $hideminor = 0;
+                               if ( 'hideliu' == $bit ) $hideliu = 1;
+                               if ( 'hidepatrolled' == $bit ) $hidepatrolled = 1;
+                               if ( 'hidemyself' == $bit ) $hidemyself = 1;
+
+                               if ( is_numeric( $bit ) ) {
+                                       $limit = $bit;
+                               }
+
+                               if ( preg_match( '/^limit=(\d+)$/', $bit, $m ) ) {
+                                       $limit = $m[1];
+                               }
+
+                               if ( preg_match( '/^days=(\d+)$/', $bit, $m ) ) {
+                                       $days = $m[1];
+                               }
+                       }
+               }
+       }
+
+       if ( $limit < 0 || $limit > 5000 ) $limit = $defaults['limit'];
+
+
+       # Database connection and caching
+       $dbr =& wfGetDB( DB_SLAVE );
+       extract( $dbr->tableNames( 'recentchanges', 'watchlist' ) );
+
+       
+       $cutoff_unixtime = time() - ( $days * 86400 );
+       $cutoff_unixtime = $cutoff_unixtime - ($cutoff_unixtime % 86400);
+       $cutoff = $dbr->timestamp( $cutoff_unixtime );
+       if(preg_match('/^[0-9]{14}$/', $from) and $from > wfTimestamp(TS_MW,$cutoff)) {
+               $cutoff = $dbr->timestamp($from);
+       } else {
+               $from = $defaults['from'];
+       }
+               
+       # 10 seconds server-side caching max
+       $wgOut->setSquidMaxage( 10 );
+
+       # Get last modified date, for client caching
+       # Don't use this if we are using the patrol feature, patrol changes don't update the timestamp
+       $lastmod = $dbr->selectField( 'recentchanges', 'MAX(rc_timestamp)', false, $fname );
+       if ( $feedFormat || !$wgUseRCPatrol ) {
+               if( $lastmod && $wgOut->checkLastModified( $lastmod ) ){
+                       # Client cache fresh and headers sent, nothing more to do.
+                       return;
+               }
+       }
+
+       $hidem  = $hideminor ? 'AND rc_minor=0' : '';
+       $hidem .= $hidebots ? ' AND rc_bot=0' : '';
+       $hidem .= ( $hideliu && !$hidemyself ) ? ' AND rc_user=0' : '';
+       $hidem .= $hidepatrolled ? ' AND rc_patrolled=0' : '';
+       $hidem .= $hidemyself  ? ' AND rc_user <> '.$wgUser->getID() : '';
+       $hidem .= is_null( $namespace ) ?  '' : ' AND rc_namespace' . ($invert ? '!=' : '=') . $namespace;
+
+       // This is the big thing!
+
+       $uid = $wgUser->getID();
+        $notifts = ($wgShowUpdatedMarker?",wl_notificationtimestamp":"");
+
+       // Perform query
+       $sql2 = "SELECT $recentchanges.*" . ($uid ? ",wl_user".$notifts : "") . " FROM $recentchanges " .
+         ($uid ? "LEFT OUTER JOIN $watchlist ON wl_user={$uid} AND wl_title=rc_title AND wl_namespace=rc_namespace " : "") .
+         "WHERE rc_timestamp > '{$cutoff}' {$hidem} " .
+         "ORDER BY rc_timestamp DESC LIMIT {$limit}";
+       $res = $dbr->query( $sql2, $fname );
+
+       // Fetch results, prepare a batch link existence check query
+       $rows = array();
+       $batch = new LinkBatch;
+       while( $row = $dbr->fetchObject( $res ) ){
+               $rows[] = $row;
+               // User page link
+               $title = Title::makeTitleSafe( NS_USER, $row->rc_user_text );
+               $batch->addObj( $title );
+
+               // User talk
+               $title = Title::makeTitleSafe( NS_USER_TALK, $row->rc_user_text );
+               $batch->addObj( $title );
+
+       }
+       $dbr->freeResult( $res );
+
+       // Run existence checks
+       $batch->execute( $wgLinkCache );
+
+       if( $feedFormat ) {
+               rcOutputFeed( $rows, $feedFormat, $limit, $hideminor, $lastmod );
+       } else {
+
+               # Web output...
+
+               // Output header
+               if ( !$specialPage->including() ) {
+                       $wgOut->addWikiText( wfMsgForContent( "recentchangestext" ) );
+               
+                       // Dump everything here
+                       $nondefaults = array();
+               
+                       wfAppendToArrayIfNotDefault( 'days', $days, $defaults, $nondefaults);
+                       wfAppendToArrayIfNotDefault( 'limit', $limit , $defaults, $nondefaults);
+                       wfAppendToArrayIfNotDefault( 'hideminor', $hideminor, $defaults, $nondefaults);
+                       wfAppendToArrayIfNotDefault( 'hidebots', $hidebots, $defaults, $nondefaults);
+                       wfAppendToArrayIfNotDefault( 'hideliu', $hideliu, $defaults, $nondefaults);
+                       wfAppendToArrayIfNotDefault( 'hidepatrolled', $hidepatrolled, $defaults, $nondefaults);
+                       wfAppendToArrayIfNotDefault( 'hidemyself', $hidemyself, $defaults, $nondefaults);
+                       wfAppendToArrayIfNotDefault( 'from', $from, $defaults, $nondefaults);
+                       wfAppendToArrayIfNotDefault( 'namespace', $namespace, $defaults, $nondefaults);
+                       wfAppendToArrayIfNotDefault( 'invert', $invert, $defaults, $nondefaults);
+
+                       // Add end of the texts
+                       $wgOut->addHTML( '<div class="rcoptions">' . rcOptionsPanel( $defaults, $nondefaults ) );
+                       $wgOut->addHTML( rcNamespaceForm( $namespace, $invert, $nondefaults) . '</div>');
+               }
+
+               // And now for the content
+               $sk = $wgUser->getSkin();
+               $wgOut->setSyndicated( true );
+               $list =& new ChangesList( $sk );
+               $s = $list->beginRecentChangesList();
+               $counter = 1;
+               foreach( $rows as $obj ){
+                       if( $limit == 0) {
+                               break;
+                       }
+
+                       if ( ! ( $hideminor     && $obj->rc_minor     ) &&
+                            ! ( $hidepatrolled && $obj->rc_patrolled ) ) {
+                               $rc = RecentChange::newFromRow( $obj );
+                               $rc->counter = $counter++;
+
+                               if ($wgShowUpdatedMarker
+                                       && !empty( $obj->wl_notificationtimestamp )
+                                       && ($obj->rc_timestamp >= $obj->wl_notificationtimestamp)) {
+                                               $rc->notificationtimestamp = true;
+                               } else {
+                                       $rc->notificationtimestamp = false;
+                               }
+
+                               if ($wgRCShowWatchingUsers && $wgUser->getOption( 'shownumberswatching' )) {
+                                       $sql3 = "SELECT COUNT(*) AS n FROM $watchlist WHERE wl_title='" . $dbr->strencode($obj->rc_title) ."' AND wl_namespace=$obj->rc_namespace" ;
+                                       $res3 = $dbr->query( $sql3, 'wfSpecialRecentChanges');
+                                       $x = $dbr->fetchObject( $res3 );
+                                       $rc->numberofWatchingusers = $x->n;
+                               } else {
+                                       $rc->numberofWatchingusers = 0;
+                               }
+                               $s .= $list->recentChangesLine( $rc, !empty( $obj->wl_user ) );
+                               --$limit;
+                       }
+               }
+               $s .= $list->endRecentChangesList();
+               $wgOut->addHTML( $s );
+       }
+}
+
+function rcOutputFeed( $rows, $feedFormat, $limit, $hideminor, $lastmod ) {
+       global $messageMemc, $wgDBname, $wgFeedCacheTimeout;
+       global $wgFeedClasses, $wgTitle, $wgSitename, $wgContLanguageCode;
+       
+       if( !isset( $wgFeedClasses[$feedFormat] ) ) {
+               wfHttpError( 500, "Internal Server Error", "Unsupported feed type." );
+               return false;
+       }
+       
+       $timekey = "$wgDBname:rcfeed:$feedFormat:timestamp";
+       $key = "$wgDBname:rcfeed:$feedFormat:limit:$limit:minor:$hideminor";
+       
+       $feedTitle = $wgSitename . ' - ' . wfMsgForContent( 'recentchanges' ) .
+               ' [' . $wgContLanguageCode . ']';
+       $feed = new $wgFeedClasses[$feedFormat](
+               $feedTitle,
+               htmlspecialchars( wfMsgForContent( 'recentchangestext' ) ),
+               $wgTitle->getFullUrl() );
+
+       /**
+        * Bumping around loading up diffs can be pretty slow, so where
+        * possible we want to cache the feed output so the next visitor
+        * gets it quick too.
+        */
+       $cachedFeed = false;
+       if( $feedLastmod = $messageMemc->get( $timekey ) ) {
+               /**
+                * If the cached feed was rendered very recently, we may
+                * go ahead and use it even if there have been edits made
+                * since it was rendered. This keeps a swarm of requests
+                * from being too bad on a super-frequently edited wiki.
+                */
+               if( time() - wfTimestamp( TS_UNIX, $feedLastmod )
+                               < $wgFeedCacheTimeout
+                       || wfTimestamp( TS_UNIX, $feedLastmod )
+                               > wfTimestamp( TS_UNIX, $lastmod ) ) {
+                       wfDebug( "RC: loading feed from cache ($key; $feedLastmod; $lastmod)...\n" );
+                       $cachedFeed = $messageMemc->get( $key );
+               } else {
+                       wfDebug( "RC: cached feed timestamp check failed ($feedLastmod; $lastmod)\n" );
+               }
+       }
+       if( is_string( $cachedFeed ) ) {
+               wfDebug( "RC: Outputting cached feed\n" );
+               $feed->httpHeaders();
+               echo $cachedFeed;
+       } else {
+               wfDebug( "RC: rendering new feed and caching it\n" );
+               ob_start();
+               rcDoOutputFeed( $rows, $feed );
+               $cachedFeed = ob_get_contents();
+               ob_end_flush();
+               
+               $expire = 3600 * 24; # One day
+               $messageMemc->set( $key, $cachedFeed );
+               $messageMemc->set( $timekey, wfTimestamp( TS_MW ), $expire );
+       }
+       return true;
+}
+
+function rcDoOutputFeed( $rows, &$feed ) {
+       global $wgSitename, $wgFeedClasses, $wgContLanguageCode;
+       
+       $feed->outHeader();
+       
+       # Merge adjacent edits by one user
+       $sorted = array();
+       $n = 0;
+       foreach( $rows as $obj ) {
+               if( $n > 0 &&
+                       $obj->rc_namespace >= 0 &&
+                       $obj->rc_cur_id == $sorted[$n-1]->rc_cur_id &&
+                       $obj->rc_user_text == $sorted[$n-1]->rc_user_text ) {
+                       $sorted[$n-1]->rc_last_oldid = $obj->rc_last_oldid;
+               } else {
+                       $sorted[$n] = $obj;
+                       $n++;
+               }
+               $first = false;
+       }
+       
+       foreach( $sorted as $obj ) {
+               $title = Title::makeTitle( $obj->rc_namespace, $obj->rc_title );
+               $talkpage = $title->getTalkPage();
+               $item = new FeedItem(
+                       $title->getPrefixedText(),
+                       rcFormatDiff( $obj ),
+                       $title->getFullURL(),
+                       $obj->rc_timestamp,
+                       $obj->rc_user_text,
+                       $talkpage->getFullURL()
+                       );
+               $feed->outItem( $item );
+       }
+       $feed->outFooter();
+}
+
+/**
+ *
+ */
+function rcCountLink( $lim, $d, $page='Recentchanges', $more='' ) {
+       global $wgUser, $wgLang, $wgContLang;
+       $sk = $wgUser->getSkin();
+       $s = $sk->makeKnownLink( $wgContLang->specialPage( $page ),
+         ($lim ? $wgLang->formatNum( "{$lim}" ) : wfMsg( 'recentchangesall' ) ), "{$more}" .
+         ($d ? "days={$d}&" : '') . 'limit='.$lim );
+       return $s;
+}
+
+/**
+ *
+ */
+function rcDaysLink( $lim, $d, $page='Recentchanges', $more='' ) {
+       global $wgUser, $wgLang, $wgContLang;
+       $sk = $wgUser->getSkin();
+       $s = $sk->makeKnownLink( $wgContLang->specialPage( $page ),
+         ($d ? $wgLang->formatNum( "{$d}" ) : wfMsg( 'recentchangesall' ) ), $more.'days='.$d .
+         ($lim ? '&limit='.$lim : '') );
+       return $s;
+}
+
+/**
+ * Used by Recentchangeslinked
+ */
+function rcDayLimitLinks( $days, $limit, $page='Recentchanges', $more='', $doall = false, $minorLink = '',
+       $botLink = '', $liuLink = '', $patrLink = '', $myselfLink = '' ) {
+       if ($more != '') $more .= '&';
+       $cl = rcCountLink( 50, $days, $page, $more ) . ' | ' .
+         rcCountLink( 100, $days, $page, $more  ) . ' | ' .
+         rcCountLink( 250, $days, $page, $more  ) . ' | ' .
+         rcCountLink( 500, $days, $page, $more  ) .
+         ( $doall ? ( ' | ' . rcCountLink( 0, $days, $page, $more ) ) : '' );
+       $dl = rcDaysLink( $limit, 1, $page, $more  ) . ' | ' .
+         rcDaysLink( $limit, 3, $page, $more  ) . ' | ' .
+         rcDaysLink( $limit, 7, $page, $more  ) . ' | ' .
+         rcDaysLink( $limit, 14, $page, $more  ) . ' | ' .
+         rcDaysLink( $limit, 30, $page, $more  ) .
+         ( $doall ? ( ' | ' . rcDaysLink( $limit, 0, $page, $more ) ) : '' );
+       $shm = wfMsg( 'showhideminor', $minorLink, $botLink, $liuLink, $patrLink, $myselfLink );
+       $note = wfMsg( 'rclinks', $cl, $dl, $shm );
+       return $note;
+}
+
+
+/**
+ * Makes change an option link which carries all the other options
+ */
+function makeOptionsLink( $title, $override, $options ) {
+       global $wgUser, $wgLang, $wgContLang;
+       $sk = $wgUser->getSkin();
+       return $sk->makeKnownLink( $wgContLang->specialPage( 'Recentchanges' ),
+               $title, wfArrayToCGI( $override, $options ) );
+}
+
+/**
+ * Creates the options panel
+ */
+function rcOptionsPanel( $defaults, $nondefaults ) {
+       global $wgLang;
+
+       $options = $nondefaults + $defaults;
+
+       if( $options['from'] )
+               $note = wfMsg( 'rcnotefrom', $wgLang->formatNum( $options['limit'] ), $wgLang->timeanddate( $options['from'], true ) );
+       else
+               $note = wfMsg( 'rcnote', $wgLang->formatNum( $options['limit'] ), $wgLang->formatNum( $options['days'] ) );
+
+       // limit links
+       $cl = '';
+       $options_limit = array(50, 100, 250, 500);
+       $i = 0;
+       while ( $i+1 < count($options_limit) ) {
+               $cl .=  makeOptionsLink( $options_limit[$i], array( 'limit' => $options_limit[$i] ), $nondefaults) . ' | ' ;
+               $i++;
+       }
+       $cl .=  makeOptionsLink( $options_limit[$i], array( 'limit' => $options_limit[$i] ), $nondefaults) ;
+
+       // day links, reset 'from' to none
+       $dl = '';
+       $options_days = array(1, 3, 7, 14, 30);
+       $i = 0;
+       while ( $i+1 < count($options_days) ) {
+               $dl .=  makeOptionsLink( $options_days[$i], array( 'days' => $options_days[$i], 'from' => '' ), $nondefaults) . ' | ' ;
+               $i++;
+       }
+       $dl .=  makeOptionsLink( $options_days[$i], array( 'days' => $options_days[$i], 'from' => '' ), $nondefaults) ;
+
+       // show/hide links
+       $showhide = array( wfMsg( 'show' ), wfMsg( 'hide' ));
+       $minorLink = makeOptionsLink( $showhide[1-$options['hideminor']],
+               array( 'hideminor' => 1-$options['hideminor'] ), $nondefaults);
+       $botLink = makeOptionsLink( $showhide[1-$options['hidebots']],
+               array( 'hidebots' => 1-$options['hidebots'] ), $nondefaults);
+       $liuLink   = makeOptionsLink( $showhide[1-$options['hideliu']],
+               array( 'hideliu' => 1-$options['hideliu'] ), $nondefaults);
+       $patrLink  = makeOptionsLink( $showhide[1-$options['hidepatrolled']],
+               array( 'hidepatrolled' => 1-$options['hidepatrolled'] ), $nondefaults);
+       $myselfLink = makeOptionsLink( $showhide[1-$options['hidemyself']], 
+               array( 'hidemyself' => 1-$options['hidemyself'] ), $nondefaults);
+       $hl = wfMsg( 'showhideminor', $minorLink, $botLink, $liuLink, $patrLink, $myselfLink );
+       
+       // show from this onward link
+       $now = $wgLang->timeanddate( wfTimestampNow(), true );
+       $tl =  makeOptionsLink( $now, array( 'from' => wfTimestampNow()), $nondefaults );
+       
+       $rclinks = wfMsg( 'rclinks', $cl, $dl, $hl );
+       $rclistfrom = wfMsg( 'rclistfrom', $tl );
+       return "$note<br />$rclinks<br />$rclistfrom";
+
+}
+
+/**<F2>
+ * Creates the choose namespace selection
+ *
+ * @access private
+ *
+ * @param mixed $namespace The key of the currently selected namespace, empty string
+ *              if there is none
+ * @param bool $invert Whether to invert the namespace selection
+ * @param array $nondefaults An array of non default options to be remembered
+ *
+ * @return string
+ */
+function rcNamespaceForm ( $namespace, $invert, $nondefaults ) {
+       global $wgContLang, $wgScript;
+       $t = Title::makeTitle( NS_SPECIAL, 'Recentchanges' );
+
+       $namespaceselect = HTMLnamespaceselector($namespace, '');
+       $submitbutton = '<input type="submit" value="' . wfMsgHtml( 'allpagessubmit' ) . '" />';
+       $invertbox = "<input type='checkbox' name='invert' value='1' id='nsinvert'" . ( $invert ? ' checked="checked"' : '' ) . ' />';
+
+       $out = "<div class='namespacesettings'><form method='get' action='{$wgScript}'>\n";
+
+       foreach ( $nondefaults as $key => $value ) {
+               if ($key != 'namespace' && $key != 'invert')
+                       $out .= wfElement('input', array( 'type' => 'hidden', 'name' => $key, 'value' => $value));
+       }
+
+       $out .= '<input type="hidden" name="title" value="'.$t->getPrefixedText().'" />';
+       $out .= "
+<div id='nsselect' class='recentchanges'>
+       <label for='namespace'>" . wfMsgHtml('namespace') . "</label>
+       $namespaceselect $submitbutton $invertbox <label for='nsinvert'>" . wfMsgHtml('invert') . "</label>
+</div>";
+       $out .= '</form></div>';
+       return $out;
+}
+
+
+/**
+ * Format a diff for the newsfeed
+ */
+function rcFormatDiff( $row ) {
+       $fname = 'rcFormatDiff';
+       wfProfileIn( $fname );
+       
+       require_once( 'DifferenceEngine.php' );
+       $comment = "<p>" . htmlspecialchars( $row->rc_comment ) . "</p>\n";
+       
+       if( $row->rc_namespace >= 0 ) {
+               global $wgContLang;
+               
+               #$diff =& new DifferenceEngine( $row->rc_this_oldid, $row->rc_last_oldid, $row->rc_id );
+               #$diff->showDiffPage();
+               
+               $titleObj = Title::makeTitle( $row->rc_namespace, $row->rc_title );
+               $dbr =& wfGetDB( DB_SLAVE );
+               $newrev =& Revision::newFromTitle( $titleObj, $row->rc_this_oldid );
+               if( $newrev ) {
+                       $newtext = $newrev->getText();
+               } else {
+                       $diffText = "<p>Can't load revision $row->rc_this_oldid</p>";
+                       wfProfileOut( $fname );
+                       return $comment . $diffText;
+               }
+
+               if( $row->rc_last_oldid ) {
+                       wfProfileIn( "$fname-dodiff" );
+                       $oldrev =& Revision::newFromId( $row->rc_last_oldid );
+                       if( !$oldrev ) {
+                               $diffText = "<p>Can't load old revision $row->rc_last_oldid</p>";
+                               wfProfileOut( $fname );
+                               return $comment . $diffText;
+                       }
+                       $oldtext = $oldrev->getText();
+                               
+                       # Old entries may contain illegal characters
+                       # which will damage output
+                       $oldtext = UtfNormal::cleanUp( $oldtext );
+                       
+                       global $wgFeedDiffCutoff;
+                       if( strlen( $newtext ) > $wgFeedDiffCutoff ||
+                               strlen( $oldtext ) > $wgFeedDiffCutoff ) {
+                               $diffLink = $titleObj->escapeFullUrl(
+                                       'diff=' . $row->rc_this_oldid .
+                                       '&oldid=' . $row->rc_last_oldid );
+                               $diffText = '<a href="' .
+                                       $diffLink .
+                                       '">' .
+                                       htmlspecialchars( wfMsgForContent( 'difference' ) ) .
+                                       '</a>';
+                       } else {
+                               $diffText = DifferenceEngine::getDiff( $oldtext, $newtext,
+                                 wfMsg( 'revisionasof', $wgContLang->timeanddate( $row->rc_timestamp ) ),
+                                 wfMsg( 'currentrev' ) );
+                       }
+                       wfProfileOut( "$fname-dodiff" );
+               } else {
+                       $rev = Revision::newFromId( $row->rc_this_oldid );
+                       if( is_null( $rev ) ) {
+                               $newtext = '';
+                       } else {
+                               $newtext = $rev->getText();
+                       }
+                       $diffText = '<p><b>' . wfMsg( 'newpage' ) . '</b></p>' .
+                               '<div>' . nl2br( htmlspecialchars( $newtext ) ) . '</div>';
+               }
+               
+               wfProfileOut( $fname );
+               return $comment . $diffText;
+       }
+       
+       wfProfileOut( $fname );
+       return $comment;        
+}
+
+?>
diff --git a/includes/SpecialRecentchangeslinked.php b/includes/SpecialRecentchangeslinked.php
new file mode 100644 (file)
index 0000000..5aaa490
--- /dev/null
@@ -0,0 +1,136 @@
+<?php
+/**
+ * This is to display changes made to all articles linked in an article.
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/**
+ *
+ */
+require_once( 'SpecialRecentchanges.php' );
+
+/**
+ * Entrypoint
+ * @param string $par parent page we will look at
+ */
+function wfSpecialRecentchangeslinked( $par = NULL ) {
+       global $wgUser, $wgOut, $wgLang, $wgContLang, $wgTitle, $wgRequest;
+       $fname = 'wfSpecialRecentchangeslinked';
+
+       $days = $wgRequest->getInt( 'days' );
+       $target = isset($par) ? $par : $wgRequest->getText( 'target' );
+       $hideminor = $wgRequest->getBool( 'hideminor' ) ? 1 : 0;
+       
+       $wgOut->setPagetitle( wfMsg( 'recentchangeslinked' ) );
+       $sk = $wgUser->getSkin();
+
+       if (is_null($target)) {
+               $wgOut->errorpage( 'notargettitle', 'notargettext' );
+               return;
+       }
+       $nt = Title::newFromURL( $target );
+       if( !$nt ) {
+               $wgOut->errorpage( 'notargettitle', 'notargettext' );
+               return;
+       }
+       $id = $nt->getArticleId();
+       
+       $wgOut->setSubtitle( htmlspecialchars( wfMsg( 'rclsub', $nt->getPrefixedText() ) ) );
+
+       if ( ! $days ) {
+               $days = $wgUser->getOption( 'rcdays' );
+               if ( ! $days ) { $days = 7; }
+       }
+       $days = (int)$days;
+       list( $limit, $offset ) = wfCheckLimits( 100, 'rclimit' );
+
+       $dbr =& wfGetDB( DB_SLAVE );
+       $cutoff = $dbr->timestamp( time() - ( $days * 86400 ) );
+
+       $hideminor = ($hideminor ? 1 : 0);
+       if ( $hideminor ) {
+               $mlink = $sk->makeKnownLink( $wgContLang->specialPage( 'Recentchangeslinked' ),
+                 WfMsg( 'show' ), 'target=' . htmlspecialchars( $nt->getPrefixedURL() ) .
+                 "&days={$days}&limit={$limit}&hideminor=0" );
+       } else {
+               $mlink = $sk->makeKnownLink( $wgContLang->specialPage( "Recentchangeslinked" ),
+                 WfMsg( "hide" ), "target=" . htmlspecialchars( $nt->getPrefixedURL() ) .
+                 "&days={$days}&limit={$limit}&hideminor=1" );
+       }
+       if ( $hideminor ) {
+               $cmq = 'AND rev_minor_edit=0';
+       } else { $cmq = ''; }
+
+       extract( $dbr->tableNames( 'categorylinks', 'pagelinks', 'revision', 'page' ) );
+       
+       // If target is a Category, use categorylinks and invert from and to
+       if( $nt->getNamespace() == NS_CATEGORY ) {
+               $catkey = $dbr->addQuotes( $nt->getDBKey() );
+               $sql =
+ "SELECT page_id,page_namespace,page_title,rev_id,rev_user,rev_comment,
+         rev_user_text,rev_timestamp,rev_minor_edit,
+         page_is_new
+    FROM $categorylinks, $revision, $page
+   WHERE rev_timestamp > '{$cutoff}'
+         {$cmq}
+     AND rev_page=page_id
+     AND cl_from=page_id
+     AND cl_to=$catkey
+GROUP BY page_id,page_namespace,page_title,
+         rev_user,rev_comment,rev_user_text,rev_timestamp,rev_minor_edit,
+         page_is_new
+ORDER BY rev_timestamp DESC
+   LIMIT {$limit}";
+       } else {
+               $sql =
+ "SELECT page_id,page_namespace,page_title,
+         rev_user,rev_comment,rev_user_text,rev_id,rev_timestamp,rev_minor_edit,
+         page_is_new
+    FROM $pagelinks, $revision, $page
+   WHERE rev_timestamp > '{$cutoff}'
+         {$cmq}
+     AND rev_page=page_id
+     AND pl_namespace=page_namespace
+     AND pl_title=page_title
+     AND pl_from=$id
+GROUP BY page_id,page_namespace,page_title,
+         rev_user,rev_comment,rev_user_text,rev_timestamp,rev_minor_edit,
+         page_is_new
+ORDER BY rev_timestamp DESC
+   LIMIT {$limit}";
+       }
+       $res = $dbr->query( $sql, $fname );
+
+       $wgOut->addHTML("&lt; ".$sk->makeKnownLinkObj($nt, "", "redirect=no" )."<br />\n");
+       $note = wfMsg( "rcnote", $limit, $days );
+       $wgOut->addHTML( "<hr />\n{$note}\n<br />" );
+
+       $note = rcDayLimitlinks( $days, $limit, "Recentchangeslinked",
+                                 "target=" . $nt->getPrefixedURL() . "&hideminor={$hideminor}",
+                                 false, $mlink );
+
+       $wgOut->addHTML( $note."\n" );
+
+       $list =& new ChangesList( $sk );
+       $s = $list->beginRecentChangesList();
+       $count = $dbr->numRows( $res );
+       
+       $counter = 1;
+       while ( $limit ) {
+               if ( 0 == $count ) { break; }
+               $obj = $dbr->fetchObject( $res );
+               --$count;
+
+               $rc = RecentChange::newFromCurRow( $obj );
+               $rc->counter = $counter++;
+               $s .= $list->recentChangesLine( $rc );
+               --$limit;
+       }
+       $s .= $list->endRecentChangesList();
+
+       $dbr->freeResult( $res );
+       $wgOut->addHTML( $s );
+}
+
+?>
diff --git a/includes/SpecialSearch.php b/includes/SpecialSearch.php
new file mode 100644 (file)
index 0000000..fe88387
--- /dev/null
@@ -0,0 +1,415 @@
+<?php
+# Copyright (C) 2004 Brion Vibber <brion@pobox.com>
+# http://www.mediawiki.org/
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or 
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# http://www.gnu.org/copyleft/gpl.html
+
+/**
+ * Run text & title search and display the output
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/** */
+require_once( 'SearchEngine.php' );
+require_once( 'Revision.php' );
+
+/**
+ * Entry point
+ *
+ * @param string $par (default '')
+ */
+function wfSpecialSearch( $par = '' ) {
+       global $wgRequest, $wgUser;
+       
+       $search = $wgRequest->getText( 'search', $par );
+       $searchPage = new SpecialSearch( $wgRequest, $wgUser );
+       if( $wgRequest->getVal( 'fulltext' ) ||
+               !is_null( $wgRequest->getVal( 'offset' ) ) ||
+               !is_null ($wgRequest->getVal( 'searchx' ) ) ) {
+               $searchPage->showResults( $search );
+       } else {
+               $searchPage->goResult( $search );
+       }
+}
+
+/**
+ * @todo document
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+class SpecialSearch {
+
+       /**
+        * Set up basic search parameters from the request and user settings.
+        * Typically you'll pass $wgRequest and $wgUser.
+        *
+        * @param WebRequest $request
+        * @param User $user
+        * @access public
+        */
+       function SpecialSearch( &$request, &$user ) {
+               list( $this->limit, $this->offset ) = $request->getLimitOffset( 20, 'searchlimit' );
+               
+               if( $request->getCheck( 'searchx' ) ) {
+                       $this->namespaces = $this->powerSearch( $request );
+               } else {
+                       $this->namespaces = $this->userNamespaces( $user );
+               }
+               
+               $this->searchRedirects = $request->getcheck( 'redirs' ) ? true : false;
+       }
+       
+       /**
+        * If an exact title match can be found, jump straight ahead to
+        * @param string $term
+        * @access public
+        */
+       function goResult( $term ) {
+               global $wgOut;
+               global $wgGoToEdit;
+               
+               $this->setupPage( $term );
+
+               # Try to go to page as entered.
+               #
+               $t = Title::newFromText( $term );
+
+               # If the string cannot be used to create a title
+               if( is_null( $t ) ){ 
+                       return $this->showResults( $term );
+               }
+
+               # If there's an exact or very near match, jump right there.
+               $t = SearchEngine::getNearMatch( $term );
+               if( !is_null( $t ) ) {
+                       $wgOut->redirect( $t->getFullURL() );
+                       return;
+               }
+               
+               # No match, generate an edit URL
+               $t = Title::newFromText( $term );
+               if( is_null( $t ) ) {
+                       $editurl = ''; # hrm...
+               } else {
+                       # If the feature is enabled, go straight to the edit page
+                       if ( $wgGoToEdit ) {
+                               $wgOut->redirect( $t->getFullURL( 'action=edit' ) );
+                               return;
+                       } else {
+                               $editurl = $t->escapeLocalURL( 'action=edit' );
+                       }
+               }
+               $wgOut->addWikiText( wfMsg('nogomatch', ":$term" ) );
+
+               return $this->showResults( $term );
+       }
+       
+       /**
+        * @param string $term
+        * @access public
+        */
+       function showResults( $term ) {
+               $fname = 'SpecialSearch::showResults';
+               wfProfileIn( $fname );
+               
+               $this->setupPage( $term );
+               
+               global $wgUser, $wgOut;
+               $sk = $wgUser->getSkin();
+               $wgOut->addWikiText( wfMsg( 'searchresulttext' ) );
+               
+               #if ( !$this->parseQuery() ) {
+               if( '' === trim( $term ) ) {
+                       $wgOut->setSubtitle( '' );
+                       $wgOut->addHTML( $this->powerSearchBox( $term ) );
+                       wfProfileOut( $fname );
+                       return;
+               }
+               
+               global $wgDisableTextSearch;
+               if ( $wgDisableTextSearch ) {
+                       global $wgForwardSearchUrl;
+                       if( $wgForwardSearchUrl ) {
+                               $url = str_replace( '$1', urlencode( $term ), $wgForwardSearchUrl );
+                               $wgOut->redirect( $url );
+                               return;
+                       }
+                       global $wgInputEncoding;
+                       $wgOut->addHTML( wfMsg( 'searchdisabled' ) );
+                       $wgOut->addHTML(
+                               wfMsg( 'googlesearch',
+                                       htmlspecialchars( $term ),
+                                       htmlspecialchars( $wgInputEncoding ),
+                                       htmlspecialchars( wfMsg( 'search' ) )
+                               )
+                       );
+                       wfProfileOut( $fname );
+                       return;
+               }
+
+               $search = SearchEngine::create();
+               $search->setLimitOffset( $this->limit, $this->offset );
+               $search->setNamespaces( $this->namespaces );
+               $search->showRedirects = $this->searchRedirects;
+               $titleMatches = $search->searchTitle( $term );
+               $textMatches = $search->searchText( $term );
+               
+               $num = ( $titleMatches ? $titleMatches->numRows() : 0 )
+                       + ( $textMatches ? $textMatches->numRows() : 0);
+               if ( $num >= $this->limit ) {
+                       $top = wfShowingResults( $this->offset, $this->limit );
+               } else {
+                       $top = wfShowingResultsNum( $this->offset, $this->limit, $num );
+               }
+               $wgOut->addHTML( "<p>{$top}</p>\n" );
+
+               if( $num || $this->offset ) {
+                       $prevnext = wfViewPrevNext( $this->offset, $this->limit,
+                               'Special:Search',
+                               wfArrayToCGI(
+                                       $this->powerSearchOptions(),
+                                       array( 'search' => $term ) ) );
+                       $wgOut->addHTML( "<br />{$prevnext}\n" );
+               }
+
+               if( $titleMatches ) {
+                       if( $titleMatches->numRows() ) {
+                               $wgOut->addWikiText( '==' . wfMsg( 'titlematches' ) . "==\n" );
+                               $wgOut->addHTML( $this->showMatches( $titleMatches ) );
+                       } else {
+                               $wgOut->addWikiText( '==' . wfMsg( 'notitlematches' ) . "==\n" );
+                       }
+               }
+               
+               if( $textMatches ) {
+                       if( $textMatches->numRows() ) {
+                               $wgOut->addWikiText( '==' . wfMsg( 'textmatches' ) . "==\n" );
+                               $wgOut->addHTML( $this->showMatches( $textMatches ) );
+                       } elseif( $num == 0 ) {
+                               # Don't show the 'no text matches' if we received title matches
+                               $wgOut->addWikiText( '==' . wfMsg( 'notextmatches' ) . "==\n" );
+                       }
+               }
+               
+               if ( $num == 0 ) {
+                       $wgOut->addWikiText( wfMsg( 'nonefound' ) );
+               }
+               if( $num || $this->offset ) {
+                       $wgOut->addHTML( "<p>{$prevnext}</p>\n" );
+               }
+               $wgOut->addHTML( $this->powerSearchBox( $term ) );
+               wfProfileOut( $fname );
+       }
+       
+       #------------------------------------------------------------------
+       # Private methods below this line
+       
+       /**
+        * 
+        */
+       function setupPage( $term ) {
+               global $wgOut;
+               $wgOut->setPageTitle( wfMsg( 'searchresults' ) );
+               $wgOut->setSubtitle( htmlspecialchars( wfMsg( 'searchquery', $term ) ) );
+               $wgOut->setArticleRelated( false );
+               $wgOut->setRobotpolicy( 'noindex,nofollow' );
+       }
+       
+       /**
+        * Extract default namespaces to search from the given user's
+        * settings, returning a list of index numbers.
+        *
+        * @param User $user
+        * @return array
+        * @access private
+        */
+       function userNamespaces( &$user ) {
+               $arr = array();
+               foreach( SearchEngine::searchableNamespaces() as $ns => $name ) {
+                       if( $user->getOption( 'searchNs' . $ns ) ) {
+                               $arr[] = $ns;
+                       }
+               }
+               return $arr;
+       }
+       
+       /**
+        * Extract "power search" namespace settings from the request object,
+        * returning a list of index numbers to search.
+        *
+        * @param WebRequest $request
+        * @return array
+        * @access private
+        */
+       function powerSearch( &$request ) {
+               $arr = array();
+               foreach( SearchEngine::searchableNamespaces() as $ns => $name ) {
+                       if( $request->getCheck( 'ns' . $ns ) ) {
+                               $arr[] = $ns;
+                       }
+               }
+               return $arr;
+       }
+       
+       /**
+        * Reconstruct the 'power search' options for links
+        * @return array
+        * @access private
+        */
+       function powerSearchOptions() {
+               $opt = array();
+               foreach( $this->namespaces as $n ) {
+                       $opt['ns' . $n] = 1;
+               }
+               $opt['redirs'] = $this->searchRedirects ? 1 : 0;
+               $opt['searchx'] = 1;
+               return $opt;
+       }
+       
+       /**
+        * @param SearchResultSet $matches
+        * @param string $terms partial regexp for highlighting terms
+        */
+       function showMatches( &$matches ) {
+               $fname = 'SpecialSearch::showMatches';
+               wfProfileIn( $fname );
+               
+               global $wgContLang;
+               $tm = $wgContLang->convertForSearchResult( $matches->termMatches() );
+               $terms = implode( '|', $tm );
+               
+               global $wgOut;
+               $off = $this->offset + 1;
+               $out = "<ol start='{$off}'>\n";
+
+               while( $result = $matches->next() ) {
+                       $out .= $this->showHit( $result, $terms );
+               }
+               $out .= "</ol>\n";
+
+               // convert the whole thing to desired language variant
+               global $wgContLang;
+               $out = $wgContLang->convert( $out );
+               wfProfileOut( $fname );
+               return $out;
+       }
+       
+       /**
+        * Format a single hit result
+        * @param SearchResult $result
+        * @param string $terms partial regexp for highlighting terms
+        */
+       function showHit( $result, $terms ) {
+               $fname = 'SpecialSearch::showHit';
+               wfProfileIn( $fname );
+               global $wgUser, $wgContLang;
+
+               $t = $result->getTitle();
+               if( is_null( $t ) ) {
+                       wfProfileOut( $fname );
+                       return "<!-- Broken link in search result -->\n";
+               }
+               $sk =& $wgUser->getSkin();
+
+               $contextlines = $wgUser->getOption( 'contextlines' );
+               if ( '' == $contextlines ) { $contextlines = 5; }
+               $contextchars = $wgUser->getOption( 'contextchars' );
+               if ( '' == $contextchars ) { $contextchars = 50; }
+
+               $link = $sk->makeKnownLinkObj( $t );
+               $revision = Revision::newFromTitle( $t );
+               $text = $revision->getText();
+               $size = wfMsg( 'nbytes', strlen( $text ) );
+
+               $lines = explode( "\n", $text );
+
+               $max = IntVal( $contextchars ) + 1;
+               $pat1 = "/(.*)($terms)(.{0,$max})/i";
+
+               $lineno = 0;
+               
+               $extract = '';
+               wfProfileIn( "$fname-extract" );
+               foreach ( $lines as $line ) {
+                       if ( 0 == $contextlines ) {
+                               break;
+                       }
+                       ++$lineno;
+                       if ( ! preg_match( $pat1, $line, $m ) ) {
+                               continue;
+                       }
+                       --$contextlines;
+                       $pre = $wgContLang->truncate( $m[1], -$contextchars, '...' );
+
+                       if ( count( $m ) < 3 ) {
+                               $post = '';
+                       } else {
+                               $post = $wgContLang->truncate( $m[3], $contextchars, '...' );
+                       }
+
+                       $found = $m[2];
+
+                       $line = htmlspecialchars( $pre . $found . $post );
+                       $pat2 = '/(' . $terms . ")/i";
+                       $line = preg_replace( $pat2,
+                         "<span class='searchmatch'>\\1</span>", $line );
+
+                       $extract .= "<br /><small>{$lineno}: {$line}</small>\n";
+               }
+               wfProfileOut( "$fname-extract" );
+               wfProfileOut( $fname );
+               return "<li>{$link} ({$size}){$extract}</li>\n";
+       }
+       
+       function powerSearchBox( $term ) {
+               $namespaces = '';
+               foreach( SearchEngine::searchableNamespaces() as $ns => $name ) {
+                       $checked = in_array( $ns, $this->namespaces )
+                               ? ' checked="checked"'
+                               : '';
+                       $name = str_replace( '_', ' ', $name );
+                       if( '' == $name ) {
+                               $name = wfMsg( 'blanknamespace' );
+                       }
+                       $namespaces .= " <label><input type='checkbox' value=\"1\" name=\"" .
+                         "ns{$ns}\"{$checked} />{$name}</label>\n";
+               }
+               
+               $checked = $this->searchRedirects
+                       ? ' checked="checked"'
+                       : '';
+               $redirect = "<input type='checkbox' value='1' name=\"redirs\"{$checked} />\n";
+               
+               $searchField = "<input type='text' name=\"search\" value=\"" .
+                       htmlspecialchars( $term ) ."\" width=\"80\" />\n";
+               
+               $searchButton = '<input type="submit" name="searchx" value="' .
+                 htmlspecialchars( wfMsg('powersearch') ) . "\" />\n";
+               
+               $ret = wfMsg( 'powersearchtext',
+                       $namespaces, $redirect, $searchField,
+                       '', '', '', '', '', # Dummy placeholders
+                       $searchButton );
+               
+               $title = Title::makeTitle( NS_SPECIAL, 'Search' );
+               $action = $title->escapeLocalURL();
+               return "<br /><br />\n<form id=\"powersearch\" method=\"get\" " .
+                 "action=\"$action\">\n{$ret}\n</form>\n";
+       }
+}
+
+?>
diff --git a/includes/SpecialShortpages.php b/includes/SpecialShortpages.php
new file mode 100644 (file)
index 0000000..70ca503
--- /dev/null
@@ -0,0 +1,74 @@
+<?php
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/**
+ *
+ */
+require_once("QueryPage.php");
+
+/**
+ * SpecialShortpages extends QueryPage. It is used to return the shortest
+ * pages in the database.
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+class ShortPagesPage extends QueryPage {
+
+       function getName() {
+               return "Shortpages";
+       }
+
+       /**
+        * This query is indexed as of 1.5
+        */
+       function isExpensive() {
+               return false;
+       }
+       
+       function isSyndicated() {
+               return false;
+       }
+
+       function getSQL() {
+               $dbr =& wfGetDB( DB_SLAVE );
+               $page = $dbr->tableName( 'page' );
+               $name = $dbr->addQuotes( $this->getName() );
+               
+               return
+                       "SELECT $name as type,
+                                       page_namespace as namespace,
+                               page_title as title,
+                               page_len AS value
+                       FROM $page
+                       WHERE page_namespace=".NS_MAIN." AND page_is_redirect=0";
+       }
+       
+       function sortDescending() {
+               return false;
+       }
+
+       function formatResult( $skin, $result ) {
+               global $wgLang, $wgContLang;
+               $nb = htmlspecialchars( wfMsg( "nbytes", $wgLang->formatNum( $result->value ) ) );
+               $title = Title::makeTitle( $result->namespace, $result->title );
+               $link = $skin->makeKnownLinkObj( $title, $wgContLang->convert( $title->getPrefixedText() ) );
+               return "{$link} ({$nb})";
+       }
+}
+
+/**
+ * constructor
+ */
+function wfSpecialShortpages() {
+       list( $limit, $offset ) = wfCheckLimits();
+
+       $spp = new ShortPagesPage();
+
+       return $spp->doQuery( $offset, $limit );
+}
+
+?>
diff --git a/includes/SpecialSpecialpages.php b/includes/SpecialSpecialpages.php
new file mode 100644 (file)
index 0000000..265af2f
--- /dev/null
@@ -0,0 +1,73 @@
+<?php
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/**
+ *
+ */
+function wfSpecialSpecialpages() {
+       global $wgLang, $wgOut, $wgUser, $wgAvailableRights;
+       
+       $wgOut->setRobotpolicy( 'index,nofollow' );
+       $sk = $wgUser->getSkin();       
+       
+       # Get listable pages, in a 2-d array with the first dimension being user right
+       $pages = SpecialPage::getPages();
+
+       /** Pages available to all */
+       wfSpecialSpecialpages_gen($pages[''],'spheading',$sk);
+
+       /** Restricted special pages */
+       $rpages = array();
+       foreach($wgAvailableRights as $right) {
+               /** only show pages a user can access */
+               if( $wgUser->isAllowed($right) ) {
+                       /** some rights might not have any special page associated */
+                       if(isset($pages[$right])) {
+                               $rpages = array_merge( $rpages, $pages[$right] );
+                       }
+               }
+       }
+       wfSpecialSpecialpages_gen( $rpages, 'restrictedpheading', $sk );
+}
+
+/**
+ * sub function generating the list of pages
+ * @param $pages the list of pages
+ * @param $heading header to be used
+ * @param $sk skin object ???
+ */
+function wfSpecialSpecialpages_gen($pages,$heading,$sk) {
+       global $wgLang, $wgOut, $wgSortSpecialPages;
+
+       if( count( $pages ) == 0 ) {
+               # Yeah, that was pointless. Thanks for coming.
+               return;
+       }
+       
+       /** Put them into a sortable array */
+       $sortedPages = array();
+       foreach ( $pages as $name => $page ) {
+               if ( $page->isListed() ) {
+                       $sortedPages[$page->getDescription()] = $page->getTitle();
+               }
+       }
+       
+       /** Sort */
+       if ( $wgSortSpecialPages ) {
+               ksort( $sortedPages );
+       }
+
+       /** Now output the HTML */
+       $wgOut->addHTML( '<h2>' . wfMsg( $heading ) . "</h2>\n<ul>" );
+       foreach ( $sortedPages as $desc => $title ) {
+               $link = $sk->makeKnownLinkObj( $title, $desc );
+               $wgOut->addHTML( "<li>{$link}</li>\n" );
+       }
+       $wgOut->addHTML( "</ul>\n" );
+}
+
+?>
diff --git a/includes/SpecialStatistics.php b/includes/SpecialStatistics.php
new file mode 100644 (file)
index 0000000..5e45cc0
--- /dev/null
@@ -0,0 +1,84 @@
+<?php
+/**
+*
+* @package MediaWiki
+* @subpackage SpecialPage
+*/
+
+/**
+* constructor
+*/
+function wfSpecialStatistics() {
+       global $wgUser, $wgOut, $wgLang, $wgRequest;
+       $fname = 'wfSpecialStatistics';
+
+       $action = $wgRequest->getVal( 'action' );
+
+       $dbr =& wfGetDB( DB_SLAVE );
+       extract( $dbr->tableNames( 'page', 'site_stats', 'user', 'user_groups' ) );
+
+       $row = $dbr->selectRow( 'site_stats', '*', false, $fname );
+       $views = $row->ss_total_views;
+       $edits = $row->ss_total_edits;
+       $good = $row->ss_good_articles;
+
+       # This code is somewhat schema-agnostic, because I'm changing it in a minor release -- TS
+       if ( isset( $row->ss_total_pages ) && $row->ss_total_pages == -1 ) {
+               # Update schema
+               $u = new SiteStatsUpdate( 0, 0, 0 );
+               $u->doUpdate();
+               $row = $dbr->selectRow( 'site_stats', '*', false, $fname );
+       }
+
+       if ( isset( $row->ss_total_pages ) ) {
+               $total = $row->ss_total_pages;
+       } else {
+               $sql = "SELECT COUNT(page_namespace) AS total FROM $page";
+               $res = $dbr->query( $sql, $fname );
+               $pageRow = $dbr->fetchObject( $res );
+               $total = $pageRow->total;
+       }
+
+       if ( isset( $row->ss_users ) ) {
+               $users = $row->ss_users;
+       } else {
+               $sql = "SELECT MAX(user_id) AS total FROM $user";
+               $res = $dbr->query( $sql, $fname );
+               $userRow = $dbr->fetchObject( $res );
+               $users = $userRow->total;
+       }       
+
+       $sql = "SELECT COUNT(*) AS total FROM $user_groups WHERE ug_group='sysop'";
+       $res = $dbr->query( $sql, $fname );
+       $row = $dbr->fetchObject( $res );
+       $admins = $row->total;
+       
+       if ($action == 'raw') {
+               $wgOut->disable();
+               header( 'Pragma: nocache' );
+               echo "total=$total;good=$good;views=$views;edits=$edits;users=$users;admins=$admins\n";
+               return;
+       } else {
+               $text = '==' . wfMsg( 'sitestats' ) . "==\n" ;
+               $text .= wfMsg( 'sitestatstext',
+                       $wgLang->formatNum( $total ),
+                       $wgLang->formatNum( $good ),
+                       $wgLang->formatNum( $views ),
+                       $wgLang->formatNum( $edits ),
+                       $wgLang->formatNum( sprintf( '%.2f', $total ? $edits / $total : 0 ) ),
+                       $wgLang->formatNum( sprintf( '%.2f', $edits ? $views / $edits : 0 ) ) );
+       
+               $text .= "\n==" . wfMsg( 'userstats' ) . "==\n";
+       
+               $text .= wfMsg( 'userstatstext',
+                       $wgLang->formatNum( $users ),
+                       $wgLang->formatNum( $admins ),
+                       '[[' . wfMsg( 'administrators' ) . ']]',
+                       // should logically be after #admins, danm backwards compatability!
+                       $wgLang->formatNum( sprintf( '%.2f', $admins / $users * 100 ) )
+               );
+               
+               $wgOut->addWikiText( $text );
+       }
+}
+?>
diff --git a/includes/SpecialUncategorizedcategories.php b/includes/SpecialUncategorizedcategories.php
new file mode 100644 (file)
index 0000000..ba399f0
--- /dev/null
@@ -0,0 +1,39 @@
+<?php
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/**
+ *
+ */
+require_once( "SpecialUncategorizedpages.php" );
+
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+class UncategorizedCategoriesPage extends UncategorizedPagesPage {
+       function UncategorizedCategoriesPage() {
+               $this->requestedNamespace = NS_CATEGORY;
+       }
+
+       function getName() {
+               return "Uncategorizedcategories";
+       }
+}
+
+/**
+ * constructor
+ */
+function wfSpecialUncategorizedcategories() {
+       list( $limit, $offset ) = wfCheckLimits();
+
+       $lpp = new UncategorizedCategoriesPage();
+
+       return $lpp->doQuery( $offset, $limit );
+}
+
+?>
diff --git a/includes/SpecialUncategorizedpages.php b/includes/SpecialUncategorizedpages.php
new file mode 100644 (file)
index 0000000..5011835
--- /dev/null
@@ -0,0 +1,56 @@
+<?php
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/**
+ *
+ */
+require_once( "QueryPage.php" );
+
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+class UncategorizedPagesPage extends PageQueryPage {
+       var $requestedNamespace = NS_MAIN;
+       
+       function getName() {
+               return "Uncategorizedpages";
+       }
+
+       function sortDescending() {
+               return false;
+       }
+
+       function isExpensive() {
+               return true;
+       }
+       function isSyndicated() { return false; }
+       
+       function getSQL() {
+               $dbr =& wfGetDB( DB_SLAVE );
+               extract( $dbr->tableNames( 'page', 'categorylinks' ) );
+               $name = $dbr->addQuotes( $this->getName() );
+
+               return "SELECT $name as type, page_namespace AS namespace, page_title AS title, page_title AS value " .
+                       "FROM $page LEFT JOIN $categorylinks ON page_id=cl_from ".
+                       "WHERE cl_from IS NULL AND page_namespace=$this->requestedNamespace AND page_is_redirect=0";
+       }
+}
+
+/**
+ * constructor
+ */
+function wfSpecialUncategorizedpages() {
+       list( $limit, $offset ) = wfCheckLimits();
+
+       $lpp = new UncategorizedPagesPage();
+
+       return $lpp->doQuery( $offset, $limit );
+}
+
+?>
diff --git a/includes/SpecialUndelete.php b/includes/SpecialUndelete.php
new file mode 100644 (file)
index 0000000..5613b28
--- /dev/null
@@ -0,0 +1,477 @@
+<?php
+/**
+ * @todo document
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/** */
+require_once( 'Revision.php' );
+
+/**
+ *
+ */
+function wfSpecialUndelete( $par ) {
+    global $wgRequest;
+
+       $form = new UndeleteForm( $wgRequest, $par );
+       $form->execute();
+}
+
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+class PageArchive {
+       var $title;
+       
+       function PageArchive( &$title ) {
+               if( is_null( $title ) ) {
+                       wfDebugDieBacktrace( 'Archiver() given a null title.');
+               }
+               $this->title =& $title;
+       }
+       
+       /**
+        * List all deleted pages recorded in the archive table. Returns result
+        * wrapper with (ar_namespace, ar_title, count) fields, ordered by page
+        * namespace/title. Can be called staticaly.
+        *
+        * @return ResultWrapper
+        */
+       /* static */ function listAllPages() {
+               $dbr =& wfGetDB( DB_SLAVE );
+               $archive = $dbr->tableName( 'archive' );
+
+               $sql = "SELECT ar_namespace,ar_title, COUNT(*) AS count FROM $archive " . 
+                 "GROUP BY ar_namespace,ar_title ORDER BY ar_namespace,ar_title";
+
+               return $dbr->resultObject( $dbr->query( $sql, 'PageArchive::listAllPages' ) );
+       }
+       
+       /**
+        * List the revisions of the given page. Returns result wrapper with
+        * (ar_minor_edit, ar_timestamp, ar_user, ar_user_text, ar_comment) fields.
+        *
+        * @return ResultWrapper
+        */
+       function listRevisions() {
+               $dbr =& wfGetDB( DB_SLAVE );
+               return $dbr->resultObject( $dbr->select( 'archive',
+                       array( 'ar_minor_edit', 'ar_timestamp', 'ar_user', 'ar_user_text', 'ar_comment' ),
+                       array( 'ar_namespace' => $this->title->getNamespace(),
+                              'ar_title' => $this->title->getDBkey() ),
+                       'PageArchive::listRevisions',
+                       array( 'ORDER BY' => 'ar_timestamp DESC' ) ) );
+       }
+       
+       /**
+        * Fetch (and decompress if necessary) the stored text for the deleted
+        * revision of the page with the given timestamp.
+        *
+        * @return string
+        */
+       function getRevisionText( $timestamp ) {
+               $fname = 'PageArchive::getRevisionText';
+               $dbr =& wfGetDB( DB_SLAVE );
+               $row = $dbr->selectRow( 'archive',
+                       array( 'ar_text', 'ar_flags', 'ar_text_id' ),
+                       array( 'ar_namespace' => $this->title->getNamespace(),
+                              'ar_title' => $this->title->getDbkey(),
+                              'ar_timestamp' => $dbr->timestamp( $timestamp ) ),
+                       $fname );
+               if( is_null( $row->ar_text_id ) ) {
+                       // An old row from MediaWiki 1.4 or previous.
+                       // Text is embedded in this row in classic compression format.
+                       return Revision::getRevisionText( $row, "ar_" );
+               } else {
+                       // New-style: keyed to the text storage backend.
+                       $text = $dbr->selectRow( 'text',
+                               array( 'old_text', 'old_flags' ),
+                               array( 'old_id' => $row->ar_text_id ),
+                               $fname );
+                       return Revision::getRevisionText( $text );
+               }
+       }
+       
+       /**
+        * Fetch (and decompress if necessary) the stored text of the most
+        * recently edited deleted revision of the page.
+        *
+        * If there are no archived revisions for the page, returns NULL.
+        *
+        * @return string
+        */
+       function getLastRevisionText() {
+               $dbr =& wfGetDB( DB_SLAVE );
+               $row = $dbr->selectRow( 'archive',
+                       array( 'ar_text', 'ar_flags' ),
+                       array( 'ar_namespace' => $this->title->getNamespace(),
+                              'ar_title' => $this->title->getDBkey() ),
+                       'PageArchive::getLastRevisionText',
+                       array( 'ORDER BY' => 'ar_timestamp DESC' ) );
+               if( $row ) {
+                       return Revision::getRevisionText( $row, "ar_" );
+               } else {
+                       return NULL;
+               }
+       }
+       
+       /**
+        * Quick check if any archived revisions are present for the page.
+        * @return bool
+        */
+       function isDeleted() {
+               $dbr =& wfGetDB( DB_SLAVE );
+               $n = $dbr->selectField( 'archive', 'COUNT(ar_title)',
+                       array( 'ar_namespace' => $this->title->getNamespace(),
+                              'ar_title' => $this->title->getDBkey() ) );
+               return ($n > 0);
+       }
+       
+       /**
+        * This is the meaty bit -- restores archived revisions of the given page
+        * to the cur/old tables. If the page currently exists, all revisions will
+        * be stuffed into old, otherwise the most recent will go into cur.
+        * The deletion log will be updated with an undeletion notice.
+        *
+        * Returns true on success.
+        *
+        * @param array $timestamps Pass an empty array to restore all revisions, otherwise list the ones to undelete.
+        * @return bool
+        */
+       function undelete( $timestamps ) {
+               global $wgUser, $wgOut, $wgLang, $wgDeferredUpdateList;
+               global $wgUseSquid, $wgInternalServer, $wgLinkCache;
+               global $wgDBtype;
+
+               $fname = "doUndeleteArticle";
+               $restoreAll = empty( $timestamps );
+               $restoreRevisions = count( $timestamps );
+
+               $dbw =& wfGetDB( DB_MASTER );
+               extract( $dbw->tableNames( 'page', 'archive' ) );
+
+               # Does this page already exist? We'll have to update it...
+               $article = new Article( $this->title );
+               $options = ( $wgDBtype == 'PostgreSQL' )
+                       ? '' // pg doesn't support this?
+                       : 'FOR UPDATE';
+               $page = $dbw->selectRow( 'page',
+                       array( 'page_id', 'page_latest' ),
+                       array( 'page_namespace' => $this->title->getNamespace(),
+                              'page_title'     => $this->title->getDBkey() ),
+                       $fname,
+                       $options );
+               if( $page ) {
+                       # Page already exists. Import the history, and if necessary
+                       # we'll update the latest revision field in the record.
+                       $newid             = 0;
+                       $pageId            = $page->page_id;
+                       $previousRevId     = $page->page_latest;
+                       $previousTimestamp = $page->rev_timestamp;
+               } else {
+                       # Have to create a new article...
+                       $newid  = $article->insertOn( $dbw );
+                       $pageId = $newid;
+                       $previousRevId = 0;
+                       $previousTimestamp = 0;
+               }
+               
+               if( $restoreAll ) {
+                       $oldones = '1'; # All revisions...
+               } else {
+                       $oldts = implode( ',',
+                               array_map( array( &$dbw, 'addQuotes' ),
+                                       array_map( array( &$dbw, 'timestamp' ),
+                                               $timestamps ) ) );
+                       
+                       $oldones = "ar_timestamp IN ( {$oldts} )";
+               }
+               
+               /**
+                * Restore each revision...
+                */
+               $result = $dbw->select( 'archive',
+                       /* fields */ array(
+                               'ar_rev_id',
+                               'ar_text',
+                               'ar_comment',
+                               'ar_user',
+                               'ar_user_text',
+                               'ar_timestamp',
+                               'ar_minor_edit',
+                               'ar_flags',
+                               'ar_text_id' ),
+                       /* WHERE */ array(
+                               'ar_namespace' => $this->title->getNamespace(),
+                               'ar_title'     => $this->title->getDBkey(),
+                               $oldones ),
+                       $fname,
+                       /* options */ array(
+                               'ORDER BY' => 'ar_timestamp' )
+                       );
+               $revision = null;
+               while( $row = $dbw->fetchObject( $result ) ) {
+                       if( $row->ar_text_id ) {
+                               // Revision was deleted in 1.5+; text is in
+                               // the regular text table, use the reference.
+                               // Specify null here so the so the text is
+                               // dereferenced for page length info if needed.
+                               $revText = null;
+                       } else {
+                               // Revision was deleted in 1.4 or earlier.
+                               // Text is squashed into the archive row, and
+                               // a new text table entry will be created for it.
+                               $revText = Revision::getRevisionText( $row, 'ar_' );
+                       }
+                       $revision = new Revision( array(
+                               'page'       => $pageId,
+                               'id'         => $row->ar_rev_id,
+                               'text'       => $revText,
+                               'comment'    => $row->ar_comment,
+                               'user'       => $row->ar_user,
+                               'user_text'  => $row->ar_user_text,
+                               'timestamp'  => $row->ar_timestamp,
+                               'minor_edit' => $row->ar_minor_edit,
+                               'text_id'    => $row->ar_text_id,
+                               ) );
+                       $revision->insertOn( $dbw );
+               }
+               
+               if( $revision ) {
+                       # FIXME: Update latest if newer as well...
+                       if( $newid ) {
+                               # FIXME: update article count if changed...
+                               $article->updateRevisionOn( $dbw, $revision, $previousRevId );
+                               
+                               # Finally, clean up the link tables
+                               $wgLinkCache = new LinkCache();
+                               # Select for update
+                               $wgLinkCache->forUpdate( true );
+                               
+                               # Create a dummy OutputPage to update the outgoing links
+                               $dummyOut = new OutputPage();
+                               $dummyOut->addWikiText( $revision->getText() );
+
+                               $u = new LinksUpdate( $newid, $this->title->getPrefixedDBkey() );
+                               array_push( $wgDeferredUpdateList, $u );
+                               
+                               #TODO: SearchUpdate, etc.
+                       }
+                               
+                       if( $newid ) {
+                               Article::onArticleCreate( $this->title );
+                       } else {
+                               Article::onArticleEdit( $this->title );
+                       }
+               } else {
+                       # Something went terribly worong!
+               }
+
+               # Now that it's safely stored, take it out of the archive
+               $dbw->delete( 'archive',
+                       /* WHERE */ array(
+                               'ar_namespace' => $this->title->getNamespace(),
+                               'ar_title' => $this->title->getDBkey(),
+                               $oldones ),
+                       $fname );
+               
+               # Touch the log!
+               $log = new LogPage( 'delete' );
+               if( $restoreAll ) {
+                       $reason = '';
+               } else {
+                       $reason = wfMsgForContent( 'undeletedrevisions', $restoreRevisions );
+               }
+               $log->addEntry( 'restore', $this->title, $reason );
+
+               return true;
+       }
+}
+
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+class UndeleteForm {
+       var $mAction, $mTarget, $mTimestamp, $mRestore, $mTargetObj;
+       var $mTargetTimestamp;
+
+       function UndeleteForm( &$request, $par = "" ) {
+               global $wgUser;
+               $this->mAction = $request->getText( 'action' );
+               $this->mTarget = $request->getText( 'target' );
+               $this->mTimestamp = $request->getText( 'timestamp' );
+               $this->mRestore = $request->getCheck( 'restore' ) &&
+                       $request->wasPosted() &&
+                       $wgUser->matchEditToken( $request->getVal( 'wpEditToken' ) );
+               if( $par != "" ) {
+                       $this->mTarget = $par;
+               }
+               if ( $this->mTarget !== "" ) {
+                       $this->mTargetObj = Title::newFromURL( $this->mTarget );
+               } else {
+                       $this->mTargetObj = NULL;
+               }
+               if( $this->mRestore ) {
+                       $timestamps = array();
+                       foreach( $_REQUEST as $key => $val ) {
+                               if( preg_match( '/^ts(\d{14})$/', $key, $matches ) ) {
+                                       array_push( $timestamps, $matches[1] );
+                               }
+                       }
+                       rsort( $timestamps );
+                       $this->mTargetTimestamp = $timestamps;
+               }
+       }
+
+       function execute() {
+               if( is_null( $this->mTargetObj ) ) {
+                       return $this->showList();
+               }
+               if( $this->mTimestamp !== "" ) {
+                       return $this->showRevision( $this->mTimestamp );
+               }
+               if( $this->mRestore && $this->mAction == "submit" ) {
+                       return $this->undelete();
+               }
+               return $this->showHistory();
+       }
+
+       /* private */ function showList() {
+               global $wgLang, $wgContLang, $wgUser, $wgOut;
+               $fname = "UndeleteForm::showList";
+               
+               # List undeletable articles    
+               $result = PageArchive::listAllPages();
+               
+               $wgOut->setPagetitle( wfMsg( "undeletepage" ) );
+               $wgOut->addWikiText( wfMsg( "undeletepagetext" ) );
+
+               $sk = $wgUser->getSkin();
+               $undelete =& Title::makeTitle( NS_SPECIAL, 'Undelete' );
+               $wgOut->addHTML( "<ul>\n" );
+               while( $row = $result->fetchObject() ) {
+                       $n = ($row->ar_namespace ? 
+                               ($wgContLang->getNsText( $row->ar_namespace ) . ":") : "").
+                               $row->ar_title;
+                       $link = $sk->makeKnownLinkObj( $undelete,
+                               htmlspecialchars( $n ), "target=" . urlencode( $n ) );
+                       $revisions = htmlspecialchars( wfMsg( "undeleterevisions",
+                               $wgLang->formatNum( $row->count ) ) );
+                       $wgOut->addHTML( "<li>$link $revisions</li>\n" );
+               }
+               $result->free();
+               $wgOut->addHTML( "</ul>\n" );
+               
+               return true;
+       }
+       
+       /* private */ function showRevision( $timestamp ) {
+               global $wgLang, $wgUser, $wgOut;
+               $fname = "UndeleteForm::showRevision";
+
+               if(!preg_match("/[0-9]{14}/",$timestamp)) return 0;
+
+               $archive =& new PageArchive( $this->mTargetObj );
+               $text = $archive->getRevisionText( $timestamp );
+               
+               $wgOut->setPagetitle( wfMsg( "undeletepage" ) );
+               $wgOut->addWikiText( "(" . wfMsg( "undeleterevision",
+                       $wgLang->date( $timestamp ) ) . ")\n<hr />\n" . $text );
+       }
+
+       /* private */ function showHistory() {
+               global $wgLang, $wgUser, $wgOut;
+               
+               $sk = $wgUser->getSkin();
+               $wgOut->setPagetitle( wfMsg( "undeletepage" ) );
+
+               $archive = new PageArchive( $this->mTargetObj );
+               $text = $archive->getLastRevisionText();
+               if( is_null( $text ) ) {
+                       $wgOut->addWikiText( wfMsg( "nohistory" ) );
+                       return;
+               }
+               $wgOut->addWikiText( wfMsg( "undeletehistory" ) . "\n----\n" . $text );
+
+               # List all stored revisions
+               $revisions = $archive->listRevisions();
+               
+               $titleObj = Title::makeTitle( NS_SPECIAL, "Undelete" );
+               $action = $titleObj->escapeLocalURL( "action=submit" );
+               $encTarget = htmlspecialchars( $this->mTarget );
+               $button = htmlspecialchars( wfMsg("undeletebtn") );
+               $token = htmlspecialchars( $wgUser->editToken() );
+               
+               $wgOut->addHTML("
+       <form id=\"undelete\" method=\"post\" action=\"{$action}\">
+       <input type=\"hidden\" name=\"target\" value=\"{$encTarget}\" />
+       <input type=\"submit\" name=\"restore\" value=\"{$button}\" />
+       <input type='hidden' name='wpEditToken' value=\"{$token}\" />
+       ");
+
+               # Show relevant lines from the deletion log:
+               $wgOut->addHTML( "<h2>" . htmlspecialchars( LogPage::logName( 'delete' ) ) . "</h2>\n" );
+               require_once( 'SpecialLog.php' );
+               $logViewer =& new LogViewer(
+                       new LogReader(
+                               new FauxRequest(
+                                       array( 'page' => $this->mTargetObj->getPrefixedText(),
+                                              'type' => 'delete' ) ) ) );
+               $logViewer->showList( $wgOut );
+               
+               # The page's stored (deleted) history:
+               $wgOut->addHTML( "<h2>" . htmlspecialchars( wfMsg( "history" ) ) . "</h2>\n" );
+               $wgOut->addHTML("<ul>");
+               $target = urlencode( $this->mTarget );
+               while( $row = $revisions->fetchObject() ) {
+                       $ts = wfTimestamp( TS_MW, $row->ar_timestamp );
+                       $checkBox = "<input type=\"checkbox\" name=\"ts$ts\" value=\"1\" />";
+                       $pageLink = $sk->makeKnownLinkObj( $titleObj,
+                               $wgLang->timeanddate( $row->ar_timestamp, true ),
+                               "target=$target&timestamp=$ts" );
+                       $userLink = htmlspecialchars( $row->ar_user_text );
+                       if( $row->ar_user ) {
+                               $userLink = $sk->makeKnownLinkObj(
+                                       Title::makeTitle( NS_USER, $row->ar_user_text ),
+                                       $userLink );
+                       } else {
+                               $userLink = $sk->makeKnownLinkObj(
+                                       Title::makeTitle( NS_SPECIAL, 'Contributions' ),
+                                       $userLink, 'target=' . $row->ar_user_text );
+                       }
+                       $comment = $sk->commentBlock( $row->ar_comment );
+                       $wgOut->addHTML( "<li>$checkBox $pageLink . . $userLink $comment</li>\n" );
+
+               }
+               $revisions->free();
+               $wgOut->addHTML("</ul>\n</form>");
+               
+               return true;
+       }
+
+       function undelete() {
+               global $wgOut;
+               if( !is_null( $this->mTargetObj ) ) {
+                       $archive = new PageArchive( $this->mTargetObj );
+                       if( $archive->undelete( $this->mTargetTimestamp ) ) {
+                               $wgOut->addWikiText( wfMsg( "undeletedtext", $this->mTarget ) );
+
+                               if (NS_IMAGE == $this->mTargetObj->getNamespace()) {
+                                       /* refresh image metadata cache */
+                                       new Image( $this->mTargetObj );
+                               }
+
+                               return true;
+                       }
+               }
+               $wgOut->fatalError( wfMsg( "cannotundelete" ) );
+               return false;
+       }
+}
+
+?>
diff --git a/includes/SpecialUnlockdb.php b/includes/SpecialUnlockdb.php
new file mode 100644 (file)
index 0000000..9184ab0
--- /dev/null
@@ -0,0 +1,106 @@
+<?php
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/**
+ *
+ */
+function wfSpecialUnlockdb() {
+       global $wgUser, $wgOut, $wgRequest;
+
+       if ( ! $wgUser->isAllowed('siteadmin') ) {
+               $wgOut->developerRequired();
+               return;
+       }
+       $action = $wgRequest->getVal( 'action' );
+       $f = new DBUnlockForm();
+
+       if ( "success" == $action ) {
+               $f->showSuccess();
+       } else if ( "submit" == $action && $wgRequest->wasPosted() &&
+               $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) ) ) {
+               $f->doSubmit();
+       } else {
+               $f->showForm( "" );
+       }
+}
+
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+class DBUnlockForm {
+       function showForm( $err )
+       {
+               global $wgOut, $wgUser, $wgLang;
+
+               $wgOut->setPagetitle( wfMsg( "unlockdb" ) );
+               $wgOut->addWikiText( wfMsg( "unlockdbtext" ) );
+
+               if ( "" != $err ) {
+                       $wgOut->setSubtitle( wfMsg( "formerror" ) );
+                       $wgOut->addHTML( '<p class="error">' . htmlspecialchars( $err ) . "</p>\n" );
+               }
+               $lc = htmlspecialchars( wfMsg( "unlockconfirm" ) );
+               $lb = htmlspecialchars( wfMsg( "unlockbtn" ) );
+               $titleObj = Title::makeTitle( NS_SPECIAL, "Unlockdb" );
+               $action = $titleObj->escapeLocalURL( "action=submit" );
+               $token = htmlspecialchars( $wgUser->editToken() );
+
+               $wgOut->addHTML( <<<END
+
+<form id="unlockdb" method="post" action="{$action}">
+<table border="0">
+       <tr>
+               <td align="right">
+                       <input type="checkbox" name="wpLockConfirm" />
+               </td>
+               <td align="left">{$lc}</td>
+       </tr>
+       <tr>
+               <td>&nbsp;</td>
+               <td align="left">
+                       <input type="submit" name="wpLock" value="{$lb}" />
+               </td>
+       </tr>
+</table>
+<input type="hidden" name="wpEditToken" value="{$token}" />
+</form>
+END
+);
+
+       }
+
+       function doSubmit() {
+               global $wgOut, $wgUser, $wgLang;
+               global $wgRequest, $wgReadOnlyFile;
+
+               $wpLockConfirm = $wgRequest->getCheck( 'wpLockConfirm' );
+               if ( ! $wpLockConfirm ) {
+                       $this->showForm( wfMsg( "locknoconfirm" ) );
+                       return;
+               }
+               if ( @! unlink( $wgReadOnlyFile ) ) {
+                       $wgOut->fileDeleteError( $wgReadOnlyFile );
+                       return;
+               }
+               $titleObj = Title::makeTitle( NS_SPECIAL, "Unlockdb" );
+               $success = $titleObj->getFullURL( "action=success" );
+               $wgOut->redirect( $success );
+       }
+
+       function showSuccess() {
+               global $wgOut, $wgUser;
+               global $ip;
+
+               $wgOut->setPagetitle( wfMsg( "unlockdb" ) );
+               $wgOut->setSubtitle( wfMsg( "unlockdbsuccesssub" ) );
+               $wgOut->addWikiText( wfMsg( "unlockdbsuccesstext", $ip ) );
+       }
+}
+
+?>
diff --git a/includes/SpecialUnusedcategories.php b/includes/SpecialUnusedcategories.php
new file mode 100644 (file)
index 0000000..9ab9505
--- /dev/null
@@ -0,0 +1,52 @@
+<?php
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/** */
+require_once('QueryPage.php');
+
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+class UnusedCategoriesPage extends QueryPage {
+
+       function getName() {
+               return 'Unusedcategories';
+       }
+
+       function getPageHeader() {
+               return '<p>' . wfMsg('unusedcategoriestext') . '</p>';
+       }
+
+       function getSQL() {
+               $NScat = NS_CATEGORY;
+               $dbr =& wfGetDB( DB_SLAVE );
+               extract( $dbr->tableNames( 'categorylinks','page' ));
+               return "SELECT 'Unusedcategories' as type,
+                               {$NScat} as namespace, page_title as title, 1 as value
+                               FROM $page
+                               LEFT JOIN $categorylinks ON page_title=cl_to
+                               WHERE cl_from IS NULL
+                               AND page_namespace = {$NScat}
+                               AND page_is_redirect = 0";
+       }
+
+       function formatResult( $skin, $result ) {
+               global $wgLang;
+               $title = Title::makeTitle( NS_CATEGORY, $result->title );
+               return $skin->makeLinkObj( $title, $title->getText() );
+       }
+}
+
+/** constructor */
+function wfSpecialUnusedCategories() {
+       list( $limit, $offset ) = wfCheckLimits();
+       $uc = new UnusedCategoriesPage();
+       return $uc->doQuery( $offset, $limit );
+}
+?>
diff --git a/includes/SpecialUnusedimages.php b/includes/SpecialUnusedimages.php
new file mode 100644 (file)
index 0000000..c4d7d2a
--- /dev/null
@@ -0,0 +1,81 @@
+<?php
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/** */
+require_once("QueryPage.php");
+
+/**
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+class UnusedimagesPage extends QueryPage {
+
+       function getName() {
+               return 'Unusedimages';
+       }
+       
+       function sortDescending() {
+               return false;
+       }
+       function isSyndicated() { return false; }
+
+       function getSQL() {
+               global $wgCountCategorizedImagesAsUsed;
+               $dbr =& wfGetDB( DB_SLAVE );
+               
+               if ( $wgCountCategorizedImagesAsUsed ) {
+                       extract( $dbr->tableNames( 'page', 'image', 'imagelinks', 'categorylinks' ) );
+               
+                       return 'SELECT img_name as title, img_user, img_user_text, img_timestamp as value, img_description
+                                       FROM ((('.$page.' AS I LEFT JOIN '.$categorylinks.' AS L ON I.page_id = L.cl_from) 
+                                               LEFT JOIN '.$imagelinks.' AS P ON I.page_title = P.il_to)
+                                               INNER JOIN '.$image.' AS G ON I.page_title = G.img_name)
+                                       WHERE I.page_namespace = '.NS_IMAGE.' AND L.cl_from IS NULL AND P.il_to IS NULL';
+               } else {
+                       extract( $dbr->tableNames( 'image','imagelinks' ) );
+               
+                       return 'SELECT img_name as title, img_user, img_user_text, img_timestamp as value, img_description' .
+                       ' FROM '.$image.' LEFT JOIN '.$imagelinks.' ON img_name=il_to WHERE il_to IS NULL ';
+               }
+       }
+       
+       function formatResult( $skin, $result ) {
+               global $wgLang, $wgContLang;
+               $title = Title::makeTitle( NS_IMAGE, $result->title );
+               
+               $imageUrl = htmlspecialchars( Image::imageUrl( $result->title ) );
+               $return =
+               # The 'desc' linking to the image page
+               '('.$skin->makeKnownLinkObj( $title, wfMsg('imgdesc') ).') '
+               # Link to the image itself
+               . '<a href="' . $imageUrl . '">' . htmlspecialchars( $title->getText() ) . '</a>'
+               # Last modified date
+               . ' . . '.$wgLang->timeanddate($result->value)
+               # Link to username
+               . ' . . '.$skin->makeLinkObj( Title::makeTitle( NS_USER, $result->img_user_text ), $result->img_user_text)
+               # If there is a description, show it
+               . $skin->commentBlock( $wgContLang->convert( $result->img_description ) );
+               
+               return $return;
+       }
+       
+       function getPageHeader() {
+               return wfMsg( "unusedimagestext" );
+       }
+
+}
+
+/**
+ * Entry point
+ */
+function wfSpecialUnusedimages() {
+       list( $limit, $offset ) = wfCheckLimits();
+       $uip = new UnusedimagesPage();
+
+       return $uip->doQuery( $offset, $limit );
+}
+?>
diff --git a/includes/SpecialUpload.php b/includes/SpecialUpload.php
new file mode 100644 (file)
index 0000000..52d145b
--- /dev/null
@@ -0,0 +1,911 @@
+<?php
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/**
+ *
+ */
+require_once( 'Image.php' );
+
+/**
+ * Entry point
+ */
+function wfSpecialUpload() {
+       global $wgRequest;
+       $form = new UploadForm( $wgRequest );
+       $form->execute();
+}
+
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+class UploadForm {
+       /**#@+
+        * @access private
+        */
+       var $mUploadFile, $mUploadDescription, $mIgnoreWarning;
+       var $mUploadSaveName, $mUploadTempName, $mUploadSize, $mUploadOldVersion;
+       var $mUploadCopyStatus, $mUploadSource, $mReUpload, $mAction, $mUpload;
+       var $mOname, $mSessionKey, $mStashed, $mDestFile;
+       /**#@-*/
+
+       /**
+        * Constructor : initialise object
+        * Get data POSTed through the form and assign them to the object
+        * @param $request Data posted.
+        */
+       function UploadForm( &$request ) {
+               $this->mDestFile          = $request->getText( 'wpDestFile' );
+               
+               if( !$request->wasPosted() ) {
+                       # GET requests just give the main form; no data except wpDestfile.
+                       return;
+               }
+
+               $this->mIgnoreWarning     = $request->getCheck( 'wpIgnoreWarning');
+               $this->mReUpload          = $request->getCheck( 'wpReUpload' );
+               $this->mUpload            = $request->getCheck( 'wpUpload' );
+               
+               $this->mUploadDescription = $request->getText( 'wpUploadDescription' );
+               $this->mUploadCopyStatus  = $request->getText( 'wpUploadCopyStatus' );
+               $this->mUploadSource      = $request->getText( 'wpUploadSource' );
+               $this->mWatchthis         = $request->getBool( 'wpWatchthis' );
+               wfDebug( "UploadForm: watchthis is: '$this->mWatchthis'\n" );
+
+               $this->mAction            = $request->getVal( 'action' );
+               
+               $this->mSessionKey        = $request->getInt( 'wpSessionKey' );
+               if( !empty( $this->mSessionKey ) &&
+                       isset( $_SESSION['wsUploadData'][$this->mSessionKey] ) ) {
+                       /**
+                        * Confirming a temporarily stashed upload.
+                        * We don't want path names to be forged, so we keep
+                        * them in the session on the server and just give
+                        * an opaque key to the user agent.
+                        */
+                       $data = $_SESSION['wsUploadData'][$this->mSessionKey];
+                       $this->mUploadTempName   = $data['mUploadTempName'];
+                       $this->mUploadSize       = $data['mUploadSize'];
+                       $this->mOname            = $data['mOname'];
+                       $this->mStashed          = true;
+               } else {
+                       /**
+                        *Check for a newly uploaded file.
+                        */
+                       $this->mUploadTempName = $request->getFileTempName( 'wpUploadFile' );
+                       $this->mUploadSize     = $request->getFileSize( 'wpUploadFile' );
+                       $this->mOname          = $request->getFileName( 'wpUploadFile' );
+                       $this->mSessionKey     = false;
+                       $this->mStashed        = false;
+               }
+       }
+
+       /**
+        * Start doing stuff
+        * @access public
+        */
+       function execute() {
+               global $wgUser, $wgOut;
+               global $wgEnableUploads, $wgUploadDirectory;
+
+               /** Show an error message if file upload is disabled */ 
+               if( ! $wgEnableUploads ) {
+                       $wgOut->addWikiText( wfMsg( 'uploaddisabled' ) );
+                       return;
+               }
+
+               /** Various rights checks */
+               if( !$wgUser->isAllowed( 'upload' ) || $wgUser->isBlocked() ) {
+                       $wgOut->errorpage( 'uploadnologin', 'uploadnologintext' );
+                       return;
+               }
+               if( wfReadOnly() ) {
+                       $wgOut->readOnlyPage();
+                       return;
+               }
+               
+               /** Check if the image directory is writeable, this is a common mistake */
+               if ( !is_writeable( $wgUploadDirectory ) ) {
+                       $wgOut->addWikiText( wfMsg( 'upload_directory_read_only', $wgUploadDirectory ) );
+                       return;
+               }
+
+               if( $this->mReUpload ) {
+                       $this->unsaveUploadedFile();
+                       $this->mainUploadForm();
+               } else if ( 'submit' == $this->mAction || $this->mUpload ) {
+                       $this->processUpload();
+               } else {
+                       $this->mainUploadForm();
+               }
+       }
+
+       /* -------------------------------------------------------------- */
+
+       /**
+        * Really do the upload
+        * Checks are made in SpecialUpload::execute()
+        * @access private
+        */
+       function processUpload() {
+               global $wgUser, $wgOut, $wgLang, $wgContLang;
+               global $wgUploadDirectory;
+               global $wgUseCopyrightUpload, $wgCheckCopyrightUpload;
+
+               /**
+                * If there was no filename or a zero size given, give up quick.
+                */
+               if( trim( $this->mOname ) == '' || empty( $this->mUploadSize ) ) {
+                       return $this->mainUploadForm('<li>'.wfMsg( 'emptyfile' ).'</li>');
+               }
+
+               # Chop off any directories in the given filename
+               if ( $this->mDestFile ) {
+                       $basename = basename( $this->mDestFile );
+               } else {
+                       $basename = basename( $this->mOname );
+               }
+
+               /**
+                * We'll want to blacklist against *any* 'extension', and use
+                * only the final one for the whitelist.
+                */
+               list( $partname, $ext ) = $this->splitExtensions( $basename );
+               if( count( $ext ) ) {
+                       $finalExt = $ext[count( $ext ) - 1];
+               } else {
+                       $finalExt = '';
+               }
+               $fullExt = implode( '.', $ext );
+               
+               if ( strlen( $partname ) < 3 ) {
+                       $this->mainUploadForm( wfMsg( 'minlength' ) );
+                       return;
+               }
+
+               /**
+                * Filter out illegal characters, and try to make a legible name
+                * out of it. We'll strip some silently that Title would die on.
+                */
+               $filtered = preg_replace ( "/[^".Title::legalChars()."]|:/", '-', $basename );
+               $nt = Title::newFromText( $filtered );
+               if( is_null( $nt ) ) {
+                       return $this->uploadError( wfMsg( 'illegalfilename', htmlspecialchars( $filtered ) ) );
+               }
+               $nt =& Title::makeTitle( NS_IMAGE, $nt->getDBkey() );
+               $this->mUploadSaveName = $nt->getDBkey();
+               
+               /**
+                * If the image is protected, non-sysop users won't be able
+                * to modify it by uploading a new revision.
+                */
+               if( !$nt->userCanEdit() ) {
+                       return $this->uploadError( wfMsg( 'protectedpage' ) );
+               }
+               
+               /* Don't allow users to override the blacklist (check file extension) */
+               global $wgStrictFileExtensions;
+               global $wgFileExtensions, $wgFileBlacklist;
+               if( $this->checkFileExtensionList( $ext, $wgFileBlacklist ) ||
+                       ($wgStrictFileExtensions &&
+                               !$this->checkFileExtension( $finalExt, $wgFileExtensions ) ) ) {
+                       return $this->uploadError( wfMsg( 'badfiletype', htmlspecialchars( $fullExt ) ) );
+               }
+               
+               /**
+                * Look at the contents of the file; if we can recognize the
+                * type but it's corrupt or data of the wrong type, we should
+                * probably not accept it.
+                */
+               if( !$this->mStashed ) {
+                       $veri= $this->verify($this->mUploadTempName, $finalExt);
+                       
+                       if( $veri !== true ) { //it's a wiki error...
+                               return $this->uploadError( $veri->toString() );
+                       }
+               }
+               
+               /**
+                * Check for non-fatal conditions
+                */
+               if ( ! $this->mIgnoreWarning ) {
+                       $warning = '';
+                       
+                       global $wgCapitalLinks;
+                       if( $wgCapitalLinks ) {
+                               $filtered = ucfirst( $filtered );
+                       }
+                       if( $this->mUploadSaveName != $filtered ) {
+                               $warning .=  '<li>'.wfMsg( 'badfilename', htmlspecialchars( $this->mUploadSaveName ) ).'</li>';
+                       }
+       
+                       global $wgCheckFileExtensions;
+                       if ( $wgCheckFileExtensions ) {
+                               if ( ! $this->checkFileExtension( $finalExt, $wgFileExtensions ) ) {
+                                       $warning .= '<li>'.wfMsg( 'badfiletype', htmlspecialchars( $fullExt ) ).'</li>';
+                               }
+                       }
+       
+                       global $wgUploadSizeWarning;
+                       if ( $wgUploadSizeWarning && ( $this->mUploadSize > $wgUploadSizeWarning ) ) {
+                               # TODO: Format $wgUploadSizeWarning to something that looks better than the raw byte
+                               # value, perhaps add GB,MB and KB suffixes?
+                               $warning .= '<li>'.wfMsg( 'largefile', $wgUploadSizeWarning, $this->mUploadSize ).'</li>';
+                       }
+                       if ( $this->mUploadSize == 0 ) {
+                               $warning .= '<li>'.wfMsg( 'emptyfile' ).'</li>';
+                       }
+                       
+                       if( $nt->getArticleID() ) {
+                               global $wgUser;
+                               $sk = $wgUser->getSkin();
+                               $dlink = $sk->makeKnownLinkObj( $nt );
+                               $warning .= '<li>'.wfMsg( 'fileexists', $dlink ).'</li>';
+                       }
+                       
+                       if( $warning != '' ) {
+                               /**
+                                * Stash the file in a temporary location; the user can choose
+                                * to let it through and we'll complete the upload then.
+                                */
+                               return $this->uploadWarning($warning);
+                       }
+               }
+               
+               /**
+                * Try actually saving the thing...
+                * It will show an error form on failure.
+                */
+               if( $this->saveUploadedFile( $this->mUploadSaveName,
+                                            $this->mUploadTempName,
+                                            !empty( $this->mSessionKey ) ) ) {
+                       /**
+                        * Update the upload log and create the description page
+                        * if it's a new file.
+                        */
+                       $img = Image::newFromName( $this->mUploadSaveName );
+                       $success = $img->recordUpload( $this->mUploadOldVersion,
+                                                       $this->mUploadDescription,
+                                                       $this->mUploadCopyStatus,
+                                                       $this->mUploadSource,
+                                                       $this->mWatchthis );
+
+                       if ( $success ) {
+                               $this->showSuccess();
+                       } else {
+                               // Image::recordUpload() fails if the image went missing, which is 
+                               // unlikely, hence the lack of a specialised message
+                               $wgOut->fileNotFoundError( $this->mUploadSaveName );
+                       }
+               }
+       }
+
+       /**
+        * Move the uploaded file from its temporary location to the final
+        * destination. If a previous version of the file exists, move
+        * it into the archive subdirectory.
+        *
+        * @todo If the later save fails, we may have disappeared the original file.
+        *
+        * @param string $saveName
+        * @param string $tempName full path to the temporary file
+        * @param bool $useRename if true, doesn't check that the source file
+        *                        is a PHP-managed upload temporary
+        */
+       function saveUploadedFile( $saveName, $tempName, $useRename = false ) {
+               global $wgUploadDirectory, $wgOut;
+
+               $fname= "SpecialUpload::saveUploadedFile";
+               
+               $dest = wfImageDir( $saveName );
+               $archive = wfImageArchiveDir( $saveName );
+               $this->mSavedFile = "{$dest}/{$saveName}";
+
+               if( is_file( $this->mSavedFile ) ) {
+                       $this->mUploadOldVersion = gmdate( 'YmdHis' ) . "!{$saveName}";
+                       wfSuppressWarnings();
+                       $success = rename( $this->mSavedFile, "${archive}/{$this->mUploadOldVersion}" );
+                       wfRestoreWarnings();
+
+                       if( ! $success ) { 
+                               $wgOut->fileRenameError( $this->mSavedFile,
+                                 "${archive}/{$this->mUploadOldVersion}" );
+                               return false;
+                       }
+                       else wfDebug("$fname: moved file ".$this->mSavedFile." to ${archive}/{$this->mUploadOldVersion}\n");
+               } 
+               else {
+                       $this->mUploadOldVersion = '';
+               }
+               
+               if( $useRename ) {
+                       wfSuppressWarnings();
+                       $success = rename( $tempName, $this->mSavedFile );
+                       wfRestoreWarnings();
+
+                       if( ! $success ) {
+                               $wgOut->fileCopyError( $tempName, $this->mSavedFile );
+                               return false;
+                       } else {
+                               wfDebug("$fname: wrote tempfile $tempName to ".$this->mSavedFile."\n");
+                       }
+               } else {
+                       wfSuppressWarnings();
+                       $success = move_uploaded_file( $tempName, $this->mSavedFile );
+                       wfRestoreWarnings();
+
+                       if( ! $success ) {
+                               $wgOut->fileCopyError( $tempName, $this->mSavedFile );
+                               return false;
+                       }
+                       else wfDebug("$fname: wrote tempfile $tempName to ".$this->mSavedFile."\n");
+               }
+               
+               chmod( $this->mSavedFile, 0644 );
+               return true;
+       }
+
+       /**
+        * Stash a file in a temporary directory for later processing
+        * after the user has confirmed it.
+        *
+        * If the user doesn't explicitly cancel or accept, these files
+        * can accumulate in the temp directory.
+        *
+        * @param string $saveName - the destination filename
+        * @param string $tempName - the source temporary file to save
+        * @return string - full path the stashed file, or false on failure
+        * @access private
+        */
+       function saveTempUploadedFile( $saveName, $tempName ) {
+               global $wgOut;          
+               $archive = wfImageArchiveDir( $saveName, 'temp' );
+               $stash = $archive . '/' . gmdate( "YmdHis" ) . '!' . $saveName;
+
+               if ( !move_uploaded_file( $tempName, $stash ) ) {
+                       $wgOut->fileCopyError( $tempName, $stash );
+                       return false;
+               }
+               
+               return $stash;
+       }
+       
+       /**
+        * Stash a file in a temporary directory for later processing,
+        * and save the necessary descriptive info into the session.
+        * Returns a key value which will be passed through a form
+        * to pick up the path info on a later invocation.
+        *
+        * @return int
+        * @access private
+        */
+       function stashSession() {               
+               $stash = $this->saveTempUploadedFile(
+                       $this->mUploadSaveName, $this->mUploadTempName );
+
+               if( !$stash ) {
+                       # Couldn't save the file.
+                       return false;
+               }
+               
+               $key = mt_rand( 0, 0x7fffffff );
+               $_SESSION['wsUploadData'][$key] = array(
+                       'mUploadTempName' => $stash,
+                       'mUploadSize'     => $this->mUploadSize,
+                       'mOname'          => $this->mOname );
+               return $key;
+       }
+
+       /**
+        * Remove a temporarily kept file stashed by saveTempUploadedFile().
+        * @access private
+        */
+       function unsaveUploadedFile() {
+               wfSuppressWarnings();
+               $success = unlink( $this->mUploadTempName );
+               wfRestoreWarnings();
+               if ( ! $success ) {
+                       $wgOut->fileDeleteError( $this->mUploadTempName );
+               }
+       }
+
+       /* -------------------------------------------------------------- */
+
+       /**
+        * Show some text and linkage on successful upload.
+        * @access private
+        */
+       function showSuccess() {
+               global $wgUser, $wgOut, $wgContLang;
+               
+               $sk = $wgUser->getSkin();
+               $ilink = $sk->makeMediaLink( $this->mUploadSaveName, Image::imageUrl( $this->mUploadSaveName ) );
+               $dname = $wgContLang->getNsText( NS_IMAGE ) . ':'.$this->mUploadSaveName;
+               $dlink = $sk->makeKnownLink( $dname, $dname );
+
+               $wgOut->addHTML( '<h2>' . wfMsg( 'successfulupload' ) . "</h2>\n" );
+               $text = wfMsg( 'fileuploaded', $ilink, $dlink );
+               $wgOut->addHTML( $text );
+               $wgOut->returnToMain( false );
+       }
+
+       /**
+        * @param string $error as HTML
+        * @access private
+        */
+       function uploadError( $error ) {
+               global $wgOut;
+               $sub = wfMsg( 'uploadwarning' );
+               $wgOut->addHTML( "<h2>{$sub}</h2>\n" );
+               $wgOut->addHTML( "<h4 class='error'>{$error}</h4>\n" );
+       }
+
+       /**
+        * There's something wrong with this file, not enough to reject it
+        * totally but we require manual intervention to save it for real.
+        * Stash it away, then present a form asking to confirm or cancel.
+        *
+        * @param string $warning as HTML
+        * @access private
+        */
+       function uploadWarning( $warning ) {
+               global $wgOut, $wgUser, $wgLang, $wgUploadDirectory, $wgRequest;
+               global $wgUseCopyrightUpload;
+
+               $this->mSessionKey = $this->stashSession();
+               if( !$this->mSessionKey ) {
+                       # Couldn't save file; an error has been displayed so let's go.
+                       return;
+               }
+
+               $sub = wfMsg( 'uploadwarning' );
+               $wgOut->addHTML( "<h2>{$sub}</h2>\n" );
+               $wgOut->addHTML( "<ul class='warning'>{$warning}</ul><br />\n" );
+
+               $save = wfMsg( 'savefile' );
+               $reupload = wfMsg( 'reupload' );
+               $iw = wfMsg( 'ignorewarning' );
+               $reup = wfMsg( 'reuploaddesc' );
+               $titleObj = Title::makeTitle( NS_SPECIAL, 'Upload' );
+               $action = $titleObj->escapeLocalURL( 'action=submit' );
+
+               if ( $wgUseCopyrightUpload )
+               {
+                       $copyright =  "
+       <input type='hidden' name='wpUploadCopyStatus' value=\"" . htmlspecialchars( $this->mUploadCopyStatus ) . "\" />
+       <input type='hidden' name='wpUploadSource' value=\"" . htmlspecialchars( $this->mUploadSource ) . "\" />
+       ";
+               } else {
+                       $copyright = "";
+               }
+
+               $wgOut->addHTML( "
+       <form id='uploadwarning' method='post' enctype='multipart/form-data' action='$action'>
+               <input type='hidden' name='wpIgnoreWarning' value='1' />
+               <input type='hidden' name='wpSessionKey' value=\"" . htmlspecialchars( $this->mSessionKey ) . "\" />
+               <input type='hidden' name='wpUploadDescription' value=\"" . htmlspecialchars( $this->mUploadDescription ) . "\" />
+               <input type='hidden' name='wpDestFile' value=\"" . htmlspecialchars( $this->mDestFile ) . "\" />
+               <input type='hidden' name='wpWatchthis' value=\"" . htmlspecialchars( intval( $this->mWatchthis ) ) . "\" />
+       {$copyright}
+       <table border='0'>
+               <tr>
+                       <tr>
+                               <td align='right'>
+                                       <input tabindex='2' type='submit' name='wpUpload' value='$save' />
+                               </td>
+                               <td align='left'>$iw</td>
+                       </tr>
+                       <tr>
+                               <td align='right'>
+                                       <input tabindex='2' type='submit' name='wpReUpload' value='{$reupload}' />
+                               </td>
+                               <td align='left'>$reup</td>
+                       </tr>
+               </tr>
+       </table></form>\n" );
+       }
+
+       /**
+        * Displays the main upload form, optionally with a highlighted
+        * error message up at the top.
+        *
+        * @param string $msg as HTML
+        * @access private
+        */
+       function mainUploadForm( $msg='' ) {
+               global $wgOut, $wgUser, $wgLang, $wgUploadDirectory, $wgRequest;
+               global $wgUseCopyrightUpload;
+               
+               $cols = intval($wgUser->getOption( 'cols' ));
+               $ew = $wgUser->getOption( 'editwidth' );
+               if ( $ew ) $ew = " style=\"width:100%\"";
+               else $ew = '';
+
+               if ( '' != $msg ) {
+                       $sub = wfMsg( 'uploaderror' );
+                       $wgOut->addHTML( "<h2>{$sub}</h2>\n" .
+                         "<h4 class='error'>{$msg}</h4>\n" );
+               }
+               $wgOut->addWikiText( wfMsg( 'uploadtext' ) );
+               $sk = $wgUser->getSkin();
+
+
+               $sourcefilename = wfMsg( 'sourcefilename' );
+               $destfilename = wfMsg( 'destfilename' );
+               
+               $fd = wfMsg( 'filedesc' );
+               $ulb = wfMsg( 'uploadbtn' );
+
+               $iw = wfMsg( 'ignorewarning' );
+
+               $titleObj = Title::makeTitle( NS_SPECIAL, 'Upload' );
+               $action = $titleObj->escapeLocalURL();
+
+               $encDestFile = htmlspecialchars( $this->mDestFile );
+               $source = null;
+
+               if ( $wgUseCopyrightUpload )
+                 {
+                       $source = "
+       <td align='right' nowrap='nowrap'>" . wfMsg ( 'filestatus' ) . ":</td>
+       <td><input tabindex='3' type='text' name=\"wpUploadCopyStatus\" value=\"" .
+       htmlspecialchars($this->mUploadCopyStatus). "\" size='40' /></td>
+       </tr><tr>
+       <td align='right'>". wfMsg ( 'filesource' ) . ":</td>
+       <td><input tabindex='4' type='text' name='wpUploadSource' value=\"" .
+       htmlspecialchars($this->mUploadSource). "\" size='40' /></td>
+       " ;
+                 }
+
+               $watchChecked = $wgUser->getOption( 'watchdefault' )
+                       ? 'checked="checked"'
+                       : '';
+               
+               $wgOut->addHTML( "
+       <form id='upload' method='post' enctype='multipart/form-data' action=\"$action\">
+       <table border='0'><tr>
+
+       <td align='right'>{$sourcefilename}:</td><td align='left'>
+       <input tabindex='1' type='file' name='wpUploadFile' id='wpUploadFile' " . ($this->mDestFile?"":"onchange='fillDestFilename()' ") . "size='40' />
+       </td></tr><tr>
+
+       <td align='right'>{$destfilename}:</td><td align='left'>
+       <input tabindex='1' type='text' name='wpDestFile' id='wpDestFile' size='40' value=\"$encDestFile\" />
+       </td></tr><tr>
+       
+       <td align='right'>{$fd}:</td><td align='left'>
+       <textarea tabindex='2' name='wpUploadDescription' rows='6' cols='{$cols}'{$ew}>"        
+         . htmlspecialchars( $this->mUploadDescription ) .
+       "</textarea>
+       </td></tr><tr>
+       
+       <td></td><td align='left'>
+       <input type='checkbox' name='wpWatchthis' id='wpWatchthis' $watchChecked value='true' />
+       <label for='wpWatchthis'>" . wfMsgHtml( 'watchthis' ) . "</label>
+       </td></tr><tr>
+       {$source}
+       </tr>
+       <tr><td></td><td align='left'>
+       <input tabindex='5' type='submit' name='wpUpload' value=\"{$ulb}\" />
+       </td></tr></table></form>\n" );
+       }
+       
+       /* -------------------------------------------------------------- */
+
+       /**
+        * Split a file into a base name and all dot-delimited 'extensions'
+        * on the end. Some web server configurations will fall back to
+        * earlier pseudo-'extensions' to determine type and execute
+        * scripts, so the blacklist needs to check them all.
+        *
+        * @return array
+        */
+       function splitExtensions( $filename ) {
+               $bits = explode( '.', $filename );
+               $basename = array_shift( $bits );
+               return array( $basename, $bits );
+       }
+       
+       /**
+        * Perform case-insensitive match against a list of file extensions.
+        * Returns true if the extension is in the list.
+        *
+        * @param string $ext
+        * @param array $list
+        * @return bool
+        */
+       function checkFileExtension( $ext, $list ) {
+               return in_array( strtolower( $ext ), $list );
+       }
+
+       /**
+        * Perform case-insensitive match against a list of file extensions.
+        * Returns true if any of the extensions are in the list.
+        *
+        * @param array $ext
+        * @param array $list
+        * @return bool
+        */
+       function checkFileExtensionList( $ext, $list ) {
+               foreach( $ext as $e ) {
+                       if( in_array( strtolower( $e ), $list ) ) {
+                               return true;
+                       }
+               }
+               return false;
+       }
+       
+       /**
+        * Verifies that it's ok to include the uploaded file
+        *
+        * @param string $tmpfile the full path opf the temporary file to verify
+        * @param string $extension The filename extension that the file is to be served with
+        * @return mixed true of the file is verified, a WikiError object otherwise.
+        */
+       function verify( $tmpfile, $extension ) {
+               #magically determine mime type
+               $magic=& wfGetMimeMagic();
+               $mime= $magic->guessMimeType($tmpfile,false);
+               
+               $fname= "SpecialUpload::verify";
+               
+               #check mime type, if desired
+               global $wgVerifyMimeType;
+               if ($wgVerifyMimeType) {
+
+                       #check mime type against file extension
+                       if( !$this->verifyExtension( $mime, $extension ) ) {
+                               return new WikiErrorMsg( 'uploadcorrupt' );
+                       }
+               
+                       #check mime type blacklist
+                       global $wgMimeTypeBlacklist;
+                       if( isset($wgMimeTypeBlacklist) && !is_null($wgMimeTypeBlacklist) 
+                               && $this->checkFileExtension( $mime, $wgMimeTypeBlacklist ) ) {
+                               return new WikiErrorMsg( 'badfiletype', htmlspecialchars( $mime ) );
+                       }
+               }
+       
+               #check for htmlish code and javascript
+               if( $this->detectScript ( $tmpfile, $mime ) ) {
+                       return new WikiErrorMsg( 'uploadscripted' );
+               }
+               
+               /**
+               * Scan the uploaded file for viruses
+               */
+               $virus= $this->detectVirus($tmpfile);
+               if ( $virus ) {
+                       return new WikiErrorMsg( 'uploadvirus', htmlspecialchars($virus) );
+               }
+               
+               wfDebug( "$fname: all clear; passing.\n" );
+               return true;
+       }
+       
+       /**
+        * Checks if the mime type of the uploaded file matches the file extension.
+        *
+        * @param string $mime the mime type of the uploaded file
+        * @param string $extension The filename extension that the file is to be served with
+        * @return bool
+        */
+       function verifyExtension( $mime, $extension ) {
+               $fname = 'SpecialUpload::verifyExtension';
+
+               $magic =& wfGetMimeMagic();
+
+               if ( ! $mime || $mime == 'unknown' || $mime == 'unknown/unknown' )
+                       if ( ! $magic->isRecognizableExtension( $extension ) ) {
+                               wfDebug( "$fname: passing file with unknown detected mime type; unrecognized extension '$extension', can't verify\n" );
+                               return true;
+                       } else {
+                               wfDebug( "$fname: rejecting file with unknown detected mime type; recognized extension '$extension', so probably invalid file\n" );
+                               return false;
+                       }
+
+               $match= $magic->isMatchingExtension($extension,$mime);
+               
+               if ($match===NULL) {
+                       wfDebug( "$fname: no file extension known for mime type $mime, passing file\n" );
+                       return true; 
+               } elseif ($match===true) {
+                       wfDebug( "$fname: mime type $mime matches extension $extension, passing file\n" );
+                       
+                       #TODO: if it's a bitmap, make sure PHP or ImageMagic resp. can handle it!
+                       return true;
+                       
+               } else {
+                       wfDebug( "$fname: mime type $mime mismatches file extension $extension, rejecting file\n" );
+                       return false; 
+               }
+       }
+       
+       /** Heuristig for detecting files that *could* contain JavaScript instructions or 
+       * things that may look like HTML to a browser and are thus
+       * potentially harmful. The present implementation will produce false positives in some situations.
+       *
+       * @param string $file Pathname to the temporary upload file
+       * @param string $mime The mime type of the file
+       * @return bool true if the file contains something looking like embedded scripts
+       */
+       function detectScript($file,$mime) {
+               
+               #ugly hack: for text files, always look at the entire file.
+               #For binarie field, just check the first K.
+               
+               if (strpos($mime,'text/')===0) $chunk = file_get_contents( $file );
+               else {
+                       $fp = fopen( $file, 'rb' );
+                       $chunk = fread( $fp, 1024 );
+                       fclose( $fp );
+               }
+               
+               $chunk= strtolower( $chunk );
+               
+               if (!$chunk) return false;
+               
+               #decode from UTF-16 if needed (could be used for obfuscation).
+               if (substr($chunk,0,2)=="\xfe\xff") $enc= "UTF-16BE"; 
+               elseif (substr($chunk,0,2)=="\xff\xfe") $enc= "UTF-16LE"; 
+               else $enc= NULL;
+                       
+               if ($enc) $chunk= iconv($enc,"ASCII//IGNORE",$chunk);
+               
+               $chunk= trim($chunk);
+               
+               #FIXME: convert from UTF-16 if necessarry!
+               
+               wfDebug("SpecialUpload::detectScript: checking for embedded scripts and HTML stuff\n");
+               
+               #check for HTML doctype
+               if (eregi("<!DOCTYPE *X?HTML",$chunk)) return true;
+               
+               /**
+               * Internet Explorer for Windows performs some really stupid file type
+               * autodetection which can cause it to interpret valid image files as HTML
+               * and potentially execute JavaScript, creating a cross-site scripting
+               * attack vectors.
+               *
+               * Apple's Safari browser also performs some unsafe file type autodetection
+               * which can cause legitimate files to be interpreted as HTML if the
+               * web server is not correctly configured to send the right content-type
+               * (or if you're really uploading plain text and octet streams!)
+               *
+               * Returns true if IE is likely to mistake the given file for HTML.
+               * Also returns true if Safari would mistake the given file for HTML
+               * when served with a generic content-type.
+               */
+               
+               $tags = array(
+                       '<body',
+                       '<head',
+                       '<html',   #also in safari
+                       '<img',
+                       '<pre',
+                       '<script', #also in safari
+                       '<table',
+                       '<title'   #also in safari
+                       );
+                       
+               foreach( $tags as $tag ) {
+                       if( false !== strpos( $chunk, $tag ) ) {
+                               return true;
+                       }
+               }
+               
+               /*
+               * look for javascript 
+               */
+               
+               #resolve entity-refs to look at attributes. may be harsh on big files... cache result?
+               $chunk = Sanitizer::decodeCharReferences( $chunk );
+               
+               #look for script-types
+               if (preg_match("!type\s*=\s*['\"]?\s*(\w*/)?(ecma|java)!sim",$chunk)) return true;
+               
+               #look for html-style script-urls
+               if (preg_match("!(href|src|data)\s*=\s*['\"]?\s*(ecma|java)script:!sim",$chunk)) return true;
+               
+               #look for css-style script-urls
+               if (preg_match("!url\s*\(\s*['\"]?\s*(ecma|java)script:!sim",$chunk)) return true;
+               
+               wfDebug("SpecialUpload::detectScript: no scripts found\n");
+               return false;
+       }
+       
+       /** Generic wrapper function for a virus scanner program.
+       * This relies on the $wgAntivirus and $wgAntivirusSetup variables.
+       * $wgAntivirusRequired may be used to deny upload if the scan fails.
+       *
+       * @param string $file Pathname to the temporary upload file
+       * @return mixed false if not virus is found, NULL if the scan fails or is disabled,
+       *         or a string containing feedback from the virus scanner if a virus was found.
+       *         If textual feedback is missing but a virus was found, this function returns true.
+       */
+       function detectVirus($file) {
+               global $wgAntivirus, $wgAntivirusSetup, $wgAntivirusRequired;
+               
+               $fname= "SpecialUpload::detectVirus";
+               
+               if (!$wgAntivirus) { #disabled?
+                       wfDebug("$fname: virus scanner disabled\n");
+                       
+                       return NULL;
+               }
+               
+               if (!$wgAntivirusSetup[$wgAntivirus]) { 
+                       wfDebug("$fname: unknown virus scanner: $wgAntivirus\n"); 
+
+                       $wgOut->addHTML( "<div class='error'>Bad configuration: unknown virus scanner: <i>$wgAntivirus</i></div>\n" ); #LOCALIZE
+                       
+                       return "unknown antivirus: $wgAntivirus";
+               }
+               
+               #look up scanner configuration
+               $virus_scanner= $wgAntivirusSetup[$wgAntivirus]["command"]; #command pattern
+               $virus_scanner_codes= $wgAntivirusSetup[$wgAntivirus]["codemap"]; #exit-code map
+               $msg_pattern= $wgAntivirusSetup[$wgAntivirus]["messagepattern"]; #message pattern
+               
+               $scanner= $virus_scanner; #copy, so we can resolve the pattern
+               
+               if (strpos($scanner,"%f")===false) $scanner.= " ".wfEscapeShellArg($file); #simple pattern: append file to scan
+               else $scanner= str_replace("%f",wfEscapeShellArg($file),$scanner); #complex pattern: replace "%f" with file to scan
+               
+               wfDebug("$fname: running virus scan: $scanner \n");
+               
+               #execute virus scanner
+               $code= false;
+               
+               #NOTE: there's a 50 line workaround to make stderr redirection work on windows, too.
+               #      that does not seem to be worth the pain. 
+               #      Ask me (Duesentrieb) about it if it's ever needed.
+               if (wfIsWindows()) exec("$scanner",$output,$code); 
+               else exec("$scanner 2>&1",$output,$code); 
+               
+               $exit_code= $code; #remeber for user feedback
+               
+               if ($virus_scanner_codes) { #map exit code to AV_xxx constants.
+                       if (isset($virus_scanner_codes[$code])) $code= $virus_scanner_codes[$code]; #explicite mapping
+                       else if (isset($virus_scanner_codes["*"])) $code= $virus_scanner_codes["*"]; #fallback mapping
+               }
+               
+               if ($code===AV_SCAN_FAILED) { #scan failed (code was mapped to false by $virus_scanner_codes)
+                       wfDebug("$fname: failed to scan $file (code $exit_code).\n");
+                       
+                       if ($wgAntivirusRequired) return "scan failed (code $exit_code)";
+                       else return NULL; 
+               }
+               else if ($code===AV_SCAN_ABORTED) { #scan failed because filetype is unknown (probably imune)
+                       wfDebug("$fname: unsupported file type $file (code $exit_code).\n");
+                       return NULL; 
+               }
+               else if ($code===AV_NO_VIRUS) {
+                       wfDebug("$fname: file passed virus scan.\n");
+                       return false; #no virus found
+               }
+               else { 
+                       $output= join("\n",$output);
+                       $output= trim($output);
+                       
+                       if (!$output) $output= true; #if ther's no output, return true
+                       else if ($msg_pattern) {
+                               $groups= array();
+                               if (preg_match($msg_pattern,$output,$groups)) {
+                                       if ($groups[1]) $output= $groups[1];
+                               }
+                       }
+                       
+                       wfDebug("$fname: FOUND VIRUS! scanner feedback: $output");
+                       return $output;
+               }
+       }
+       
+       
+}
+?>
diff --git a/includes/SpecialUploadMogile.php b/includes/SpecialUploadMogile.php
new file mode 100644 (file)
index 0000000..6519d51
--- /dev/null
@@ -0,0 +1,131 @@
+<?php
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/**
+ *
+ */
+require_once( 'SpecialUpload.php' );
+require_once( 'MogileFS.php' );
+
+/**
+ * Entry point
+ */
+function wfSpecialUploadMogile() {
+        global $wgRequest;
+        $form = new UploadFormMogile( $wgRequest );
+        $form->execute();
+}
+
+/** @package MediaWiki */
+class UploadFormMogile extends UploadForm {
+       /**
+        * Move the uploaded file from its temporary location to the final
+        * destination. If a previous version of the file exists, move
+        * it into the archive subdirectory.
+        *
+        * @todo If the later save fails, we may have disappeared the original file.
+        *
+        * @param string $saveName
+        * @param string $tempName full path to the temporary file
+        * @param bool $useRename  Not used in this implementation
+        */
+       function saveUploadedFile( $saveName, $tempName, $useRename = false ) {
+               global $wgUploadDirectory, $wgOut;
+               $mfs = MogileFS::NewMogileFS();
+
+               $this->mSavedFile = "image!{$saveName}";
+
+               if( $mfs->getPaths( $this->mSavedFile )) {
+                       $this->mUploadOldVersion = gmdate( 'YmdHis' ) . "!{$saveName}";
+                       if( !$mfs->rename( $this->mSavedFile, "archive!{$this->mUploadOldVersion}" ) ) { 
+                               $wgOut->fileRenameError( $this->mSavedFile,
+                                 "archive!{$this->mUploadOldVersion}" );
+                               return false;
+                       }
+               } else {
+                       $this->mUploadOldVersion = '';
+               }
+               
+               if ( $this->mStashed ) {
+                       if (!$mfs->rename($tempName,$this->mSavedFile)) {
+                               $wgOut->fileRenameError($tempName, $this->mSavedFile );
+                               return false;
+                       }
+               } else {
+                       if ( !$mfs->saveFile($this->mSavedFile,'normal',$tempName )) {
+                               $wgOut->fileCopyError( $tempName, $this->mSavedFile );
+                               return false;
+                       }
+                       unlink($tempName);
+               }
+               return true;
+       }
+
+       /**
+        * Stash a file in a temporary directory for later processing
+        * after the user has confirmed it.
+        *
+        * If the user doesn't explicitly cancel or accept, these files
+        * can accumulate in the temp directory.
+        *
+        * @param string $saveName - the destination filename
+        * @param string $tempName - the source temporary file to save
+        * @return string - full path the stashed file, or false on failure
+        * @access private
+        */
+       function saveTempUploadedFile( $saveName, $tempName ) {
+               global $wgOut;
+
+               $stash = 'stash!' . gmdate( "YmdHis" ) . '!' . $saveName;
+               $mfs = MogileFS::NewMogileFS();
+               if ( !$mfs->saveFile( $stash, 'normal', $tempName ) ) {
+                       $wgOut->fileCopyError( $tempName, $stash );
+                       return false;
+               }
+               unlink($tempName);
+               return $stash;
+       }
+       
+       /**
+        * Stash a file in a temporary directory for later processing,
+        * and save the necessary descriptive info into the session.
+        * Returns a key value which will be passed through a form
+        * to pick up the path info on a later invocation.
+        *
+        * @return int
+        * @access private
+        */
+       function stashSession() {
+               $stash = $this->saveTempUploadedFile(
+                       $this->mUploadSaveName, $this->mUploadTempName );
+
+               if( !$stash ) {
+                       # Couldn't save the file.
+                       return false;
+               }
+               
+               $key = mt_rand( 0, 0x7fffffff );
+               $_SESSION['wsUploadData'][$key] = array(
+                       'mUploadTempName' => $stash,
+                       'mUploadSize'     => $this->mUploadSize,
+                       'mOname'          => $this->mOname );
+               return $key;
+       }
+
+       /**
+        * Remove a temporarily kept file stashed by saveTempUploadedFile().
+        * @access private
+        */
+       function unsaveUploadedFile() {
+               global $wgOut;
+               $mfs = MogileFS::NewMogileFS();
+               if ( ! $mfs->delete( $this->mUploadTempName ) ) {
+                       $wgOut->fileDeleteError( $this->mUploadTempName );
+               }
+       }
+}
+?>
diff --git a/includes/SpecialUserlogin.php b/includes/SpecialUserlogin.php
new file mode 100644 (file)
index 0000000..b91bd5a
--- /dev/null
@@ -0,0 +1,539 @@
+<?php
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/**
+ * constructor
+ */
+function wfSpecialUserlogin() {
+       global $wgCommandLineMode;
+       global $wgRequest;
+       if( !$wgCommandLineMode && !isset( $_COOKIE[session_name()] )  ) {
+               User::SetupSession();
+       }
+       
+       $form = new LoginForm( $wgRequest );
+       $form->execute();
+}
+
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+class LoginForm {
+       var $mName, $mPassword, $mRetype, $mReturnto, $mCookieCheck, $mPosted;
+       var $mAction, $mCreateaccount, $mCreateaccountMail, $mMailmypassword;
+       var $mLoginattempt, $mRemember, $mEmail, $mDomain;
+       
+       /**
+        * Constructor
+        * @param webrequest $request A webrequest object passed by reference
+        */
+       function LoginForm( &$request ) {
+               global $wgLang, $wgAllowRealName, $wgEnableEmail;
+               global $wgAuth;
+
+               $this->mName = $request->getText( 'wpName' );
+               $this->mPassword = $request->getText( 'wpPassword' );
+               $this->mRetype = $request->getText( 'wpRetype' );
+               $this->mDomain = $request->getText( 'wpDomain' );
+               $this->mReturnto = $request->getVal( 'returnto' );
+               $this->mCookieCheck = $request->getVal( 'wpCookieCheck' );
+               $this->mPosted = $request->wasPosted();
+               $this->mCreateaccount = $request->getCheck( 'wpCreateaccount' );
+               $this->mCreateaccountMail = $request->getCheck( 'wpCreateaccountMail' )
+                                           && $wgEnableEmail;
+               $this->mMailmypassword = $request->getCheck( 'wpMailmypassword' )
+                                        && $wgEnableEmail;
+               $this->mLoginattempt = $request->getCheck( 'wpLoginattempt' );
+               $this->mAction = $request->getVal( 'action' );
+               $this->mRemember = $request->getCheck( 'wpRemember' );
+               
+               if( $wgEnableEmail ) {
+                       $this->mEmail = $request->getText( 'wpEmail' );
+               } else {
+                       $this->mEmail = '';
+               }
+               if( $wgAllowRealName ) {
+                   $this->mRealName = $request->getText( 'wpRealName' );
+               } else {
+                   $this->mRealName = '';
+               }
+               
+               if( !$wgAuth->validDomain( $this->mDomain ) ) {
+                       $this->mDomain = 'invaliddomain';
+               }
+               $wgAuth->setDomain( $this->mDomain );
+               # When switching accounts, it sucks to get automatically logged out
+               if( $this->mReturnto == $wgLang->specialPage( 'Userlogout' ) ) {
+                       $this->mReturnto = '';
+               }
+       }
+
+       function execute() {
+               if ( !is_null( $this->mCookieCheck ) ) {
+                       $this->onCookieRedirectCheck( $this->mCookieCheck );
+                       return;
+               } else if( $this->mPosted ) {
+                       if( $this->mCreateaccount ) {
+                               return $this->addNewAccount();
+                       } else if ( $this->mCreateaccountMail ) {
+                               return $this->addNewAccountMailPassword();
+                       } else if ( $this->mMailmypassword ) {
+                               return $this->mailPassword();
+                       } else if ( ( 'submitlogin' == $this->mAction ) || $this->mLoginattempt ) {
+                               return $this->processLogin();
+                       }
+               }
+               $this->mainLoginForm( '' );
+       }
+
+       /**
+        * @access private
+        */
+       function addNewAccountMailPassword() {
+               global $wgOut;
+               
+               if ('' == $this->mEmail) {
+                       $this->mainLoginForm( wfMsg( 'noemail', htmlspecialchars( $this->mName ) ) );
+                       return;
+               }
+
+               $u = $this->addNewaccountInternal();
+
+               if ($u == NULL) {
+                       return;
+               }
+
+               $u->saveSettings();
+               $result = $this->mailPasswordInternal($u);
+               
+               $wgOut->setPageTitle( wfMsg( 'accmailtitle' ) );
+               $wgOut->setRobotpolicy( 'noindex,nofollow' );
+               $wgOut->setArticleRelated( false );
+       
+               if( WikiError::isError( $result ) ) {
+                       $this->mainLoginForm( wfMsg( 'mailerror', $result->getMessage() ) );
+               } else {
+                       $wgOut->addWikiText( wfMsg( 'accmailtext', $u->getName(), $u->getEmail() ) );
+                       $wgOut->returnToMain( false );
+               }
+               $u = 0;
+       }
+
+
+       /**
+        * @access private
+        */
+       function addNewAccount() {
+               global $wgUser, $wgOut, $wgEmailAuthentication;
+
+               $u = $this->addNewAccountInternal();
+
+               if ($u == NULL) {
+                       return;
+               }
+
+               $wgUser = $u;
+               $wgUser->setCookies();
+
+               $wgUser->saveSettings();
+               if( $wgEmailAuthentication && $wgUser->isValidEmailAddr( $wgUser->getEmail() ) ) {
+                       $wgUser->sendConfirmationMail();
+               }
+               
+               wfRunHooks( 'AddNewAccount' );
+
+               if( $this->hasSessionCookie() ) {
+                       return $this->successfulLogin( wfMsg( 'welcomecreation', $wgUser->getName() ) );
+               } else {
+                       return $this->cookieRedirectCheck( 'new' );
+               }
+       }
+
+       /**
+        * @access private
+        */
+       function addNewAccountInternal() {
+               global $wgUser, $wgOut;
+               global $wgUseLatin1, $wgEnableSorbs, $wgProxyWhitelist;
+               global $wgMemc, $wgAccountCreationThrottle, $wgDBname, $wgIP;
+               global $wgAuth;
+
+               // If the user passes an invalid domain, something is fishy
+               if( !$wgAuth->validDomain( $this->mDomain ) ) {
+                       $this->mainLoginForm( wfMsg( 'wrongpassword' ) );
+                       return false;
+               }
+
+               // If we are not allowing users to login locally, we should
+               // be checking to see if the user is actually able to
+               // authenticate to the authentication server before they
+               // create an account (otherwise, they can create a local account
+               // and login as any domain user). We only need to check this for
+               // domains that aren't local.
+               if( 'local' != $this->mDomain && '' != $this->mDomain ) {
+                       if( !$wgAuth->canCreateAccounts() && ( !$wgAuth->userExists( $this->mName ) || !$wgAuth->authenticate( $this->mName, $this->mPassword ) ) ) {
+                               $this->mainLoginForm( wfMsg( 'wrongpassword' ) );
+                               return false;
+                       }
+               }
+
+               if (!$wgUser->isAllowedToCreateAccount()) {
+                       $this->userNotPrivilegedMessage();
+                       return false;
+               }
+
+               if ( $wgEnableSorbs && !in_array( $wgIP, $wgProxyWhitelist ) && 
+                 $wgUser->inSorbsBlacklist( $wgIP ) ) 
+               {
+                       $this->mainLoginForm( wfMsg( 'sorbs_create_account_reason' ) . ' (' . htmlspecialchars( $wgIP ) . ')' );
+                       return;
+               }
+
+
+               if ( 0 != strcmp( $this->mPassword, $this->mRetype ) ) {
+                       $this->mainLoginForm( wfMsg( 'badretype' ) );
+                       return false;
+               }
+               
+               $name = trim( $this->mName );
+               $u = User::newFromName( $name );
+               if ( is_null( $u ) ) {
+                       $this->mainLoginForm( wfMsg( 'noname' ) );
+                       return false;
+               }
+               
+               if ( wfReadOnly() ) {
+                       $wgOut->readOnlyPage();
+                       return false;
+               }
+               
+               if ( 0 != $u->idForName() ) {
+                       $this->mainLoginForm( wfMsg( 'userexists' ) );
+                       return false;
+               }
+
+               if ( !$wgUser->isValidPassword( $this->mPassword ) ) {
+                       $this->mainLoginForm( wfMsg( 'passwordtooshort', $wgMinimalPasswordLength ) );
+                       return false;
+               }
+
+               if ( $wgAccountCreationThrottle ) {
+                       $key = $wgDBname.':acctcreate:ip:'.$wgIP;
+                       $value = $wgMemc->incr( $key );
+                       if ( !$value ) {
+                               $wgMemc->set( $key, 1, 86400 );
+                       }
+                       if ( $value > $wgAccountCreationThrottle ) {
+                               $this->throttleHit( $wgAccountCreationThrottle );
+                               return false;
+                       }
+               }
+
+               $abortError = '';
+               if( !wfRunHooks( 'AbortNewAccount', array( $u, &$abortError ) ) ) {
+                       wfDebug( "LoginForm::addNewAccountInternal: a hook blocked creation\n" );
+                       $this->mainLoginForm( $abortError );
+                       return false;
+               }
+
+               if( !$wgAuth->addUser( $u, $this->mPassword ) ) {
+                       $this->mainLoginForm( wfMsg( 'externaldberror' ) );
+                       return false;
+               }
+
+               # Update user count
+               $ssUpdate = new SiteStatsUpdate( 0, 0, 0, 0, 1 );
+               $ssUpdate->doUpdate();
+
+               return $this->initUser( $u );
+       }
+       
+       /**
+        * Actually add a user to the database.
+        * Give it a User object that has been initialised with a name.
+        *
+        * @param User $u
+        * @return User
+        * @access private
+        */
+       function &initUser( &$u ) {
+               $u->addToDatabase();
+               $u->setPassword( $this->mPassword );
+               $u->setEmail( $this->mEmail );
+               $u->setRealName( $this->mRealName );
+               $u->setToken();
+               
+               global $wgAuth;
+               $wgAuth->initUser( $u );
+
+               if ( $this->mRemember ) { $r = 1; }
+               else { $r = 0; }
+               $u->setOption( 'rememberpassword', $r );
+               
+               return $u;
+       }
+
+       /**
+        * @access private
+        */
+       function processLogin() {
+               global $wgUser;
+               global $wgAuth;
+
+               if ( '' == $this->mName ) {
+                       $this->mainLoginForm( wfMsg( 'noname' ) );
+                       return;
+               }
+               $u = User::newFromName( $this->mName );
+               if( is_null( $u ) ) {
+                       $this->mainLoginForm( wfMsg( 'noname' ) );
+                       return;
+               }
+               if ( 0 == $u->getID() ) {
+                       global $wgAuth;
+                       /**
+                        * If the external authentication plugin allows it,
+                        * automatically create a new account for users that
+                        * are externally defined but have not yet logged in.
+                        */
+                       if ( $wgAuth->autoCreate() && $wgAuth->userExists( $u->getName() ) ) {
+                               if ( $wgAuth->authenticate( $u->getName(), $this->mPassword ) ) {
+                                       $u =& $this->initUser( $u );
+                               } else {
+                                       $this->mainLoginForm( wfMsg( 'wrongpassword' ) );
+                                       return;
+                               }
+                       } else {
+                               $this->mainLoginForm( wfMsg( 'nosuchuser', $u->getName() ) );
+                               return;
+                       }
+               } else {
+                       $u->loadFromDatabase();
+               }
+
+               if (!$u->checkPassword( $this->mPassword )) {
+                       $this->mainLoginForm( wfMsg( 'wrongpassword' ) );
+                       return;
+               }
+
+               # We've verified now, update the real record
+               #
+               if ( $this->mRemember ) {
+                       $r = 1;
+               } else {
+                       $r = 0;
+               }
+               $u->setOption( 'rememberpassword', $r );
+
+               $wgAuth->updateUser( $u );
+
+               $wgUser = $u;
+               $wgUser->setCookies();
+
+               $wgUser->saveSettings();
+               
+               if( $this->hasSessionCookie() ) {
+                       return $this->successfulLogin( wfMsg( 'loginsuccess', $wgUser->getName() ) );
+               } else {
+                       return $this->cookieRedirectCheck( 'login' );
+               }
+       }
+
+       /**
+        * @access private
+        */
+       function mailPassword() {
+               global $wgUser, $wgDeferredUpdateList, $wgOutputEncoding;
+               global $wgCookiePath, $wgCookieDomain, $wgDBname;
+
+               if ( '' == $this->mName ) {
+                       $this->mainLoginForm( wfMsg( 'noname' ) );
+                       return;
+               }
+               $u = User::newFromName( $this->mName );
+               if( is_null( $u ) ) {
+                       $this->mainLoginForm( wfMsg( 'noname' ) );
+                       return;
+               }
+               if ( 0 == $u->getID() ) {
+                       $this->mainLoginForm( wfMsg( 'nosuchuser', $u->getName() ) );
+                       return;
+               }
+
+               $u->loadFromDatabase();
+
+               $result = $this->mailPasswordInternal( $u );
+               if( WikiError::isError( $result ) ) {
+                       $this->mainLoginForm( wfMsg( 'mailerror', $result->getMessage() ) );
+               } else {
+                       $this->mainLoginForm( wfMsg( 'passwordsent', $u->getName() ) );
+               }
+       }
+
+
+       /**
+        * @return mixed true on success, WikiError on failure
+        * @access private
+        */
+       function mailPasswordInternal( $u ) {
+               global $wgPasswordSender, $wgIP;
+               global $wgCookiePath, $wgCookieDomain, $wgCookiePrefix;
+
+               if ( '' == $u->getEmail() ) {
+                       return wfMsg( 'noemail', $u->getName() );
+               }
+
+               $np = $u->randomPassword();
+               $u->setNewpassword( $np );
+
+               setcookie( "{$wgCookiePrefix}Token", '', time() - 3600, $wgCookiePath, $wgCookieDomain );
+
+               $u->saveSettings();
+
+               $ip = $wgIP;
+               if ( '' == $ip ) { $ip = '(Unknown)'; }
+
+               $m = wfMsg( 'passwordremindertext', $ip, $u->getName(), $np );
+
+               $result = $u->sendMail( wfMsg( 'passwordremindertitle' ), $m );
+               return $result;
+       }
+
+
+       /**
+        * @param string $msg Message that will be shown on success.
+        * @access private
+        */
+       function successfulLogin( $msg ) {
+               global $wgUser;
+               global $wgOut;
+
+               # Run any hooks; ignore results
+               
+               wfRunHooks('UserLoginComplete', array(&$wgUser));
+               
+               $wgOut->setPageTitle( wfMsg( 'loginsuccesstitle' ) );
+               $wgOut->setRobotpolicy( 'noindex,nofollow' );
+               $wgOut->setArticleRelated( false );
+               $wgOut->addWikiText( $msg );
+               $wgOut->returnToMain();
+       }
+
+       /** */
+       function userNotPrivilegedMessage() {
+               global $wgOut;
+               
+               $wgOut->setPageTitle( wfMsg( 'whitelistacctitle' ) );
+               $wgOut->setRobotpolicy( 'noindex,nofollow' );
+               $wgOut->setArticleRelated( false );
+
+               $wgOut->addWikiText( wfMsg( 'whitelistacctext' ) );
+               
+               $wgOut->returnToMain( false );
+       }
+
+       /**
+        * @access private
+        */
+       function mainLoginForm( $err ) {
+               global $wgUser, $wgOut, $wgLang;
+               global $wgAllowRealName, $wgEnableEmail;
+               global $wgCookiePrefix;
+               global $wgAuth;
+
+               if ( '' == $this->mName ) {
+                       if ( $wgUser->isLoggedIn() ) {
+                               $this->mName = $wgUser->getName();
+                       } else {
+                               $this->mName = @$_COOKIE[$wgCookiePrefix.'UserName'];
+                       }
+               }
+
+               $q = 'action=submitlogin';
+               if ( !empty( $this->mReturnto ) ) {
+                       $q .= '&returnto=' . wfUrlencode( $this->mReturnto );
+               }
+               $titleObj = Title::makeTitle( NS_SPECIAL, 'Userlogin' );
+
+               require_once( 'templates/Userlogin.php' );
+               $template =& new UserloginTemplate();
+               
+               $template->set( 'name', $this->mName );
+               $template->set( 'password', $this->mPassword );
+               $template->set( 'retype', $this->mRetype );
+               $template->set( 'email', $this->mEmail );
+               $template->set( 'realname', $this->mRealName );
+               $template->set( 'domain', $this->mDomain );
+
+               $template->set( 'action', $titleObj->getLocalUrl( $q ) );
+               $template->set( 'error', $err );
+               $template->set( 'create', $wgUser->isAllowedToCreateAccount() );
+               $template->set( 'createemail', $wgEnableEmail && $wgUser->isLoggedIn() );
+               $template->set( 'userealname', $wgAllowRealName );
+               $template->set( 'useemail', $wgEnableEmail );
+               $template->set( 'remember', $wgUser->getOption( 'rememberpassword' ) or $this->mRemember  );
+               $wgAuth->modifyUITemplate( $template );
+               
+               $wgOut->setPageTitle( wfMsg( 'userlogin' ) );
+               $wgOut->setRobotpolicy( 'noindex,nofollow' );
+               $wgOut->setArticleRelated( false );
+               $wgOut->addTemplate( $template );
+       }
+
+       /**
+        * @access private
+        */
+       function hasSessionCookie() {
+               global $wgDisableCookieCheck;
+               return ( $wgDisableCookieCheck ) ? true : ( isset( $_COOKIE[session_name()] ) );
+       }
+         
+       /**
+        * @access private
+        */
+       function cookieRedirectCheck( $type ) {
+               global $wgOut, $wgLang;
+
+               $titleObj = Title::makeTitle( NS_SPECIAL, 'Userlogin' );
+               $check = $titleObj->getFullURL( 'wpCookieCheck='.$type );
+
+               return $wgOut->redirect( $check );
+       }
+
+       /**
+        * @access private
+        */
+       function onCookieRedirectCheck( $type ) {
+               global $wgUser;
+
+               if ( !$this->hasSessionCookie() ) {
+                       if ( $type == 'new' ) {
+                               return $this->mainLoginForm( wfMsg( 'nocookiesnew' ) );
+                       } else if ( $type == 'login' ) {
+                               return $this->mainLoginForm( wfMsg( 'nocookieslogin' ) );
+                       } else {
+                               # shouldn't happen
+                               return $this->mainLoginForm( wfMsg( 'error' ) );
+                       }
+               } else {
+                       return $this->successfulLogin( wfMsg( 'loginsuccess', $wgUser->getName() ) );
+               }
+       }
+
+       /**
+        * @access private
+        */
+       function throttleHit( $limit ) {
+               global $wgOut;
+
+               $wgOut->addWikiText( wfMsg( 'acct_creation_throttle_hit', $limit ) );
+       }
+}
+?>
diff --git a/includes/SpecialUserlogout.php b/includes/SpecialUserlogout.php
new file mode 100644 (file)
index 0000000..0a34a8e
--- /dev/null
@@ -0,0 +1,28 @@
+<?php
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/**
+ * constructor
+ */
+function wfSpecialUserlogout() {
+       global $wgUser, $wgOut, $returnto;
+
+       if (wfRunHooks('UserLogout', array(&$wgUser))) {
+               
+               $wgUser->logout();
+
+               wfRunHooks('UserLogoutComplete', array(&$wgUser));
+               
+               $wgOut->mCookies = array();
+               $wgOut->setRobotpolicy( 'noindex,nofollow' );
+               $wgOut->addHTML( wfMsg( 'logouttext' ) );
+               $wgOut->returnToMain();
+               
+       }
+}
+
+?>
diff --git a/includes/SpecialUserrights.php b/includes/SpecialUserrights.php
new file mode 100644 (file)
index 0000000..704db31
--- /dev/null
@@ -0,0 +1,178 @@
+<?php
+/**
+ * Provide an administration interface
+ * DO NOT USE: INSECURE.
+ * 
+ * TODO : remove everything related to group editing (SpecialGrouplevels.php)
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/** */
+require_once('HTMLForm.php');
+
+/** Entry point */
+function wfSpecialUserrights() {
+       global $wgRequest;
+       $form = new UserrightsForm($wgRequest);
+       $form->execute();
+}
+
+/**
+ * A class to manage user levels rights.
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+class UserrightsForm extends HTMLForm {
+       var $mPosted, $mRequest, $mSaveprefs;
+       /** Escaped local url name*/
+       var $action;
+
+       /** Constructor*/
+       function UserrightsForm ( &$request ) {
+               $this->mPosted = $request->wasPosted();
+               $this->mRequest =& $request;
+               $this->mName = 'userrights';
+               
+               $titleObj = Title::makeTitle( NS_SPECIAL, 'Userrights' );
+               $this->action = $titleObj->escapeLocalURL();
+       }
+
+       /**
+        * Manage forms to be shown according to posted data.
+        * Depending on the submit button used, call a form or a save function.
+        */
+       function execute() {
+               // show the general form
+               $this->switchForm();
+               if( $this->mPosted ) {
+                       // show some more forms
+                       if( $this->mRequest->getCheck( 'ssearchuser' ) ) {
+                               $this->editUserGroupsForm( $this->mRequest->getVal( 'user-editname' ) );
+                       }
+
+                       // save settings
+                       if( $this->mRequest->getCheck( 'saveusergroups' ) ) {
+                               global $wgUser;
+                               $username = $this->mRequest->getVal( 'user-editname' );
+                               if( $wgUser->matchEditToken( $this->mRequest->getVal( 'wpEditToken' ), $username ) ) {
+                                       $this->saveUserGroups( $username,
+                                               $this->mRequest->getArray( 'member' ),
+                                               $this->mRequest->getArray( 'available' ) );
+                               }
+                       }
+               }
+       }
+
+       /**
+        * Save user groups changes in the database.
+        * Data comes from the editUserGroupsForm() form function
+        *
+        * @param string $username Username to apply changes to.
+        * @param array $removegroup id of groups to be removed.
+        * @param array $addgroup id of groups to be added.
+        *
+        */
+       function saveUserGroups( $username, $removegroup, $addgroup) {
+               $u = User::newFromName($username);
+
+               if(is_null($u)) {
+                       $wgOut->addWikiText( wfMsg( 'nosuchusershort', htmlspecialchars( $username ) ) );
+                       return;
+               }
+
+               if($u->getID() == 0) {
+                       $wgOut->addWikiText( wfMsg( 'nosuchusershort', htmlspecialchars( $username ) ) );
+                       return;
+               }               
+
+               $oldGroups = $u->getGroups();
+               $newGroups = $oldGroups;
+               $logcomment = ' ';
+               // remove then add groups               
+               if(isset($removegroup)) {
+                       $newGroups = array_diff($newGroups, $removegroup);
+                       foreach( $removegroup as $group ) {
+                               $u->removeGroup( $group );
+                       }
+               }
+               if(isset($addgroup)) {
+                       $newGroups = array_merge($newGroups, $addgroup);
+                       foreach( $addgroup as $group ) {
+                               $u->addGroup( $group );
+                       }
+               }
+               $newGroups = array_unique( $newGroups );
+               
+               wfDebug( 'oldGroups: ' . print_r( $oldGroups, true ) );
+               wfDebug( 'newGroups: ' . print_r( $newGroups, true ) );
+
+               $log = new LogPage( 'rights' );
+               $log->addEntry( 'rights', Title::makeTitle( NS_USER, $u->getName() ), '', array( $this->makeGroupNameList( $oldGroups ),
+                       $this->makeGroupNameList( $newGroups ) ) );
+       }
+
+       function makeGroupNameList( $ids ) {
+               return implode( ', ', $ids );
+       }
+
+       /**
+        * The entry form
+        * It allows a user to look for a username and edit its groups membership
+        */
+       function switchForm() {
+               global $wgOut;
+               
+               // user selection
+               $wgOut->addHTML( "<form name=\"uluser\" action=\"$this->action\" method=\"post\">\n" );
+               $wgOut->addHTML( $this->fieldset( 'lookup-user',
+                               $this->textbox( 'user-editname' ) .
+                               wfElement( 'input', array(
+                                       'type'  => 'submit',
+                                       'name'  => 'ssearchuser',
+                                       'value' => wfMsg( 'editusergroup' ) ) )
+               ));
+               $wgOut->addHTML( "</form>\n" );
+       }
+
+       /**
+        * Edit user groups membership
+        * @param string $username Name of the user.
+        */
+       function editUserGroupsForm($username) {
+               global $wgOut, $wgUser;
+               
+               $user = User::newFromName($username);
+               if( is_null( $user ) || $user->getID() == 0 ) {
+                       $wgOut->addWikiText( wfMsg( 'nosuchusershort', wfEscapeWikiText( $username ) ) );
+                       return;
+               }
+               
+               $groups = $user->getGroups();
+
+               $wgOut->addHTML( "<form name=\"editGroup\" action=\"$this->action\" method=\"post\">\n".
+                       wfElement( 'input', array(
+                               'type'  => 'hidden',
+                               'name'  => 'user-editname',
+                               'value' => $username ) ) .
+                       wfElement( 'input', array(
+                               'type'  => 'hidden',
+                               'name'  => 'wpEditToken',
+                               'value' => $wgUser->editToken( $username ) ) ) .
+                       $this->fieldset( 'editusergroup',
+                       $wgOut->parse( wfMsg('editing', $username ) ) .
+                       '<table border="0" align="center"><tr><td>'.
+                       HTMLSelectGroups('member', $this->mName.'-groupsmember', $groups,true,6).
+                       '</td><td>'.
+                       HTMLSelectGroups('available', $this->mName.'-groupsavailable', $groups,true,6,true).
+                       '</td></tr></table>'."\n".
+                       $wgOut->parse( wfMsg('userrights-groupshelp') ) .
+                       wfElement( 'input', array(
+                               'type'  => 'submit',
+                               'name'  => 'saveusergroups',
+                               'value' => wfMsg( 'saveusergroups' ) ) )
+                       ));
+               $wgOut->addHTML( "</form>\n" );
+       }
+} // end class UserrightsForm
+?>
diff --git a/includes/SpecialValidate.php b/includes/SpecialValidate.php
new file mode 100644 (file)
index 0000000..1c43c98
--- /dev/null
@@ -0,0 +1,775 @@
+<?php
+# Copyright (C) 2004 Magnus Manske <magnus.manske@web.de>
+# http://www.mediawiki.org/
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or 
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# http://www.gnu.org/copyleft/gpl.html
+
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+class Validation {
+       var $topicList;
+       var $voteCache;
+       var $page_id;
+
+       function getRevisionFromId( $rev_id ) {
+               if( isset( $this->id2rev[$rev_id] ) ) return $this->id2rev[$rev_id];
+
+               $db =& wfGetDB( DB_SLAVE );
+               $fname = 'SpecialValidate::getRevisionFromId';
+               $res = $db->select( 'revision', '*', array( 'rev_id' => $rev_id ), $fname, array( 'LIMIT' => 1 ) );
+               $rev = $db->fetchObject($res);
+               $db->freeResult($res);
+
+               $this->id2rev[$rev->rev_id] = $rev;
+               $this->ts2rev[$rev->rev_timestamp] = $rev;
+
+               return $rev;
+       }
+
+       function getRevisionFromTimestamp( $timestamp ) {
+               if( isset( $this->ts2rev[$timestamp] ) ) return $this->ts2rev[$timestamp];
+
+               $db =& wfGetDB( DB_SLAVE );
+               $fname = 'SpecialValidate::getRevisionFromTimestamp';
+               $res = $db->select( 'revision', '*',
+                       array( 'rev_page' => $this->page_id, 'rev_timestamp' => $timestamp ),
+                       $fname, array( 'LIMIT' => 1 )
+               );
+               $rev = $db->fetchObject($res);
+               $db->freeResult($res);
+
+               $this->id2rev[$rev->rev_id] = $rev;
+               $this->ts2rev[$rev->rev_timestamp] = $rev;
+
+               return $rev;
+       }
+
+       # Returns a HTML link to the specified article revision
+       function getRevisionLink( &$article, $revision, $text = "" ) {
+               global $wgUser;
+               $sk = $wgUser->getSkin();
+               $t = $article->getTitle();
+               if( $text == "" ) $text = wfMsg("val_view_version");
+               return $sk->makeKnownLinkObj( $t, $this->getParsedWiki($text), 'oldid='.urlencode($revision) );
+       }
+
+       # Returns an array containing all topics you can vote on
+       function getTopicList() {
+               $db =& wfGetDB( DB_SLAVE );
+
+               $topics = array();
+               $res = $db->select( 'validate', '*', array( 'val_page' => 0 ), 'SpecialValidate::getTopicList' );
+               while( $topic = $db->fetchObject($res) ) {
+                       $topics[$topic->val_type] = $topic;
+               }
+               $db->freeResult($res);
+
+               ksort( $topics );
+               return $topics;
+       }
+       
+       # Merges one dataset into another
+       function mergeInto( &$source, &$dest ) {
+               $ret = false;
+               foreach( $source as $x => $y ) {
+                       $doit = false;
+                       if( !isset( $dest[$x] ) ) {
+                               $doit = true;
+                       } elseif( $dest[$x]->value == 0 ) {
+                               $doit = true;
+                       }
+                       if( $doit ) {
+                               $dest[$x] = $y;
+                               $ret = true;
+                       }
+               }
+               if( $ret ) {
+                       ksort ( $dest );
+               }
+               return $ret;
+       }
+
+       # Merges all votes prior to the given revision into it
+       function mergeOldRevisions( &$article, $revision ) {
+               $tmp = $this->voteCache;
+               krsort( $tmp );
+               $update = false;
+               $ts = $this->getRevisionTimestamp( $revision );
+               $data = $this->voteCache[$ts];
+               foreach( $tmp as $x => $y ) {
+                       if( $x < $ts ) {
+                               if( $this->mergeInto( $y, $data ) ) {
+                                       $update = true;
+                               }
+                       }
+               }
+               if( $update ) {
+                       $this->setRevision( $article, $revision, $data );
+               }
+       }
+       
+       # Clears all votes prior to the given revision
+       function clearOldRevisions( &$article, $revision ) {
+               $tmp = $this->voteCache;
+               $ts = $this->getRevisionTimestamp( $revision );
+               foreach( $tmp as $x => $y ) {
+                       if( $x < $ts ) {
+                               $this->deleteRevisionVote ( $article, $this->getRevisionId( $x ) );
+                       }
+               }
+       }
+       
+       # Updates the votes for the given revision from the FORM data
+       function updateRevision( &$article, $revision ) {
+               global $wgRequest;
+               
+               if( isset( $this->voteCache[$this->getRevisionTimestamp( $revision )] ) ) {
+                       $data = $this->voteCache[$this->getRevisionTimestamp( $revision )];
+               } else {
+                       $data = array();
+               }
+               $nv = $wgRequest->getArray( "re_v_{$revision}", array() );
+               $nc = $wgRequest->getArray( "re_c_{$revision}", array() );
+               
+               foreach( $nv as $x => $y ) {
+                       $data[$x]->value = $y;
+                       $data[$x]->comment = $nc[$x];
+               }
+               krsort( $data );
+               
+               $this->setRevision( $article, $revision, $data );
+       }
+       
+       # Sets a specific revision to both cache and database
+       function setRevision( &$article, $revision, &$data ) {
+               global $wgUser;
+               $this->deleteRevisionVote( $article, $revision );
+               $this->voteCache[ $this->getRevisionTimestamp($revision) ] = $data;
+               foreach( $data as $x => $y ) {
+                       if( $y->value > 0 ) {
+                               $ip = $wgUser->isAnon() ? $wgUser->getName() : '';
+                               $dbw =& wfGetDB( DB_MASTER );
+                               $dbw->insert( 'validate',
+                                       array(
+                                               'val_user'     => $wgUser->getId(),
+                                               'val_page'     => $article->getId(),
+                                               'val_revision' => $revision,
+                                               'val_type'     => $x,
+                                               'val_value'    => $y->value,
+                                               'val_comment'  => $y->comment,
+                                               'val_ip'       => $ip ),
+                                       'SpecialValidate::setRevision'
+                               );
+                       }
+               }
+       }
+       
+       # Returns a map identifying the current user
+       function identifyUser( $user = "" ) {
+               global $wgUser;
+               if( $user == "" ) $user = $wgUser->getID();
+               return User::isIP($user)
+                       ? array( 'val_user' => 0, 'val_ip' => $user )
+                       : array( 'val_user' => $user );
+       }
+       
+       # Deletes a specific vote set in both cache and database
+       function deleteRevisionVote( &$article, $revision ) {
+               $ts = $this->getRevisionTimestamp( $revision );
+               if( !isset ( $this->voteCache[$ts] ) ) return;
+
+               $db =& wfGetDB( DB_MASTER );
+               $db->delete(
+                       'validate',
+                       array_merge(
+                               $this->identifyUser(),
+                               array(
+                                       'val_page' => $article->getID(),
+                                       'val_revision' => $revision
+                               )
+                       ),
+                       'SpecialValidate::deleteRevisionVote'
+               );
+
+               unset( $this->voteCache[$ts] );
+       }
+       
+       # Reads the entire vote list for this user for the given article
+       function getVoteList( $id, $user = "" ) {
+               $db =& wfGetDB( DB_SLAVE );
+               $res = $db->select( 'validate', '*', array_merge( array( 'val_page' => $id ), $this->identifyUser($user) ) );
+
+               $revisions = array();
+               while( $vote = $db->fetchObject($res) ) {
+                       $ts = $this->getRevisionTimestamp( $vote->val_revision );
+                       if( ! isset( $revisions[$ts] ) ) {
+                               $revisions[$ts] = array();
+                       }
+                       $revisions[$ts][$vote->val_type]->value = $vote->val_value;
+                       $revisions[$ts][$vote->val_type]->comment = $vote->val_comment;
+               }
+               $db->freeResult($res);
+
+               return $revisions;
+       }
+       
+       # Reads the entire vote list for this user for all articles
+       # XXX Should be paged
+       function getAllVoteLists( $user ) {
+               $db =& wfGetDB( DB_SLAVE );
+               $res = $db->select( 'validate', '*', $this->identifyUser($user) );
+
+               $votes = array();
+               while( $vote = $db->fetchObject($res) ) {
+                       $votes[$vote->val_page][$vote->val_revision][$vote->val_type] = $vote;
+               }
+               $db->freeResult($res);
+
+               return $votes;
+       }
+       
+       # This functions adds a topic to the database
+       function addTopic( $topic, $limit ) {
+               $db =& wfGetDB( DB_MASTER );
+
+               $next_idx = 1;
+               while( isset( $this->topicList[$next_idx] ) ) {
+                      $next_idx++;
+               }
+
+               $db->insert(
+                       'validate',
+                       array(
+                               'val_user' => 0,
+                               'val_page' => 0,
+                               'val_revision' => 0,
+                               'val_type' => $next_idx,
+                               'val_value' => $limit,
+                               'val_comment' => $topic,
+                               'val_ip' => ''
+                       ),
+                       'SpecialValidate::addTopic'
+               );
+
+               $t->val_user = $t->val_page = $t->val_revision = 0;
+               $t->val_type = $next_idx;
+               $t->val_value = $limit;
+               $t->val_comment = $topic;
+               $t->val_ip = "";
+               $this->topicList[$next_idx] = $t;
+
+               ksort( $this->topicList );
+       }
+
+       function deleteTopic( $id ) {
+               $db =& wfGetDB( DB_MASTER );
+               $db->delete( 'validate', array( 'val_type' => $id ), 'SpecialValidate::deleteTopic' );
+               unset( $this->topicList[$id] );
+       }
+       
+       # This function returns a link text to the page validation statistics
+       function getStatisticsLink( &$article ) {
+               global $wgUser;
+               $sk = $wgUser->getSkin();
+               $nt = $article->getTitle();
+               return $sk->makeKnownLinkObj( $nt, wfMsg( 'val_rev_stats', $nt->getPrefixedText() ), 'action=validate&mode=list' );
+       }
+
+       # This function returns a link text to the page validation statistics of a single revision
+       function getRevisionStatsLink( &$article, $revision ) {
+               global $wgUser;
+               $sk = $wgUser->getSkin();
+               $nt = $article->getTitle();
+               $text = $this->getParsedWiki( wfMsg('val_revision_stats_link') );
+               $query = "action=validate&mode=details&revision={$revision}";
+               return '(' . $sk->makeKnownLinkObj( $nt, $text, $query ) . ')';
+       }
+
+       # This function returns a link text to the user rating statistics page
+       function getUserRatingsLink( $user, $text ) {
+               global $wgUser;
+               $sk = $wgUser->getSkin();
+               if( $user == 0 ) $user = $wgUser->getName();
+               $nt = Title::newFromText( 'Special:Validate' );
+               return $sk->makeKnownLinkObj( $nt, $text, 'mode=userstats&user='.urlencode($user) );
+       }
+
+       # Returns the timestamp of a revision based on the revision number
+       function getRevisionTimestamp( $rev_id ) {
+               $rev = $this->getRevisionFromId( $rev_id );
+               return $rev->rev_timestamp;
+       }
+
+       # Returns the revision number of a revision based on the timestamp
+       function getRevisionId( $ts ) {
+               $rev = $this->getRevisionFromTimestamp( $ts );
+               return $rev->rev_id;
+       }
+
+
+       # HTML generation functions from this point on
+       
+       # Returns the metadata string for a revision
+       function getMetadata( $rev_id, &$article ) {
+               global $wgUser;
+               $sk = $wgUser->getSkin();
+
+               $metadata = "";
+               $x = $this->getRevisionFromId($rev_id);
+               $metadata .= wfTimestamp( TS_DB, $x->rev_timestamp );
+               $metadata .= " by ";
+               if( $x->rev_user == 0 ) {
+                       $metadata .= $x->rev_user_text;
+               } else {
+                       $u = new User;
+                       $u->setId( $x->rev_user );
+                       $u->setName( $x->rev_user_text );
+                       $nt = $u->getUserPage();
+                       $metadata .= $sk->makeKnownLinkObj( $nt, htmlspecialchars( $nt->getText() ) );
+               }
+               $metadata .= ': '. $sk->commentBlock( $x->rev_comment, $article->getTitle() );
+               return $metadata;
+       }
+       
+       # Generates a link to the topic description
+       function getTopicLink($s) {
+               $t = Title::newFromText ( wfMsg ( 'val_topic_desc_page' ) ) ;
+               # FIXME: Why doesn't this use standard linking code?
+               $r = "<a href=\"" ;
+               $r .= $t->escapeLocalURL () ;
+               $r .= "#" . urlencode ( $s ) ;
+               $r .= "\">{$s}</a>" ;
+               return $r ;
+       }
+               
+       # Generates HTML from a wiki text, e.g., a wfMsg
+       function getParsedWiki ( $text ) {
+               global $wgOut, $wgTitle, $wgParser ;
+               $parserOutput = $wgParser->parse( $text , $wgTitle, $wgOut->mParserOptions,false);
+               return $parserOutput->getText() ;
+       }
+
+       # Generates a form for a single revision
+       function getRevisionForm( &$article, $idx, &$data, $focus = false ) {
+               # Fill data with blank values
+               $ts = $idx;
+               $revision = $this->getRevisionId( $ts );
+               foreach( $this->topicList as $x => $y ) {
+                       if( !isset( $data[$x] ) ) {
+                               $data[$x]->value = 0;
+                               $data[$x]->comment = "";
+                       }
+               }
+               ksort( $data ) ;                
+       
+               # Generate form
+               $table_class = $focus ? 'revisionform_focus' : 'revisionform_default';
+               $ret = "<form method='post'><table class='{$table_class}'>\n";
+               $head = "Revision #" . $revision;
+               $link = $this->getRevisionLink( $article, $revision );
+               $metadata = $this->getMetadata( $revision, $article );
+               $ret .= "<tr><th colspan='3'>" . $head . " ({$link}) {$metadata}</th></tr>\n";
+               $line = 0;
+               foreach( $data as $x => $y ) {
+                       $line = 1 - $line;
+                       $trclass = $line == 1 ? "revision_tr_first" : "revision_tr_default";
+                       $idx = "_{$revision}[{$x}]";
+                       $ret .= "<tr class='{$trclass}'>\n";
+                       $ret .= "<th>\n";
+                       $ret .= $this->getTopicLink ( $this->topicList[$x]->val_comment ) ;
+                       $ret .= "</th>\n";
+                       
+                       $tlx = $this->topicList[$x];
+                       $vote = "";
+                       $max = $tlx->val_value;
+                       for( $a = 0 ; $a <= $max ; $a++ ) {
+                               if( $a == 0 ) {
+                                       $vote .= wfMsg ( "val_noop" );
+                               }
+                               $vote .= "<input type='radio' name='re_v{$idx}' value='{$a}'";
+                               if( $a == $y->value ) {
+                                       $vote .= " checked='checked'";
+                               }
+                               $vote .= " />";
+                               if( $max == 2 && $a == 1 ) {
+                                       $vote .= wfMsg( "val_no" ) . " ";
+                               } elseif( $max == 2 && $a == 2 ) {
+                                       $vote .= wfMsg( "val_yes" );
+                               } elseif( $a != 0 ) {
+                                       $vote .= $a . " ";
+                               }
+                               if ( $a == 0 ) {
+                                       $vote .= " &nbsp; ";
+                               }
+                       }                       
+                       $ret .= "<td>{$vote}</td>\n";
+                       
+                       $ret .= "<td><input size='50' style='width:98%' maxlength='250' type='text' name='re_c{$idx}' value='{$y->comment}'/>";
+                       $ret .= "</td></tr>\n";
+               }
+               $checked = $focus ? " checked='checked'" : "";
+               $ret .= "<tr><td colspan='3'>\n";
+               $ret .= "<input type='checkbox' name='re_merge_{$revision}' value='1'{$checked} />" . $this->getParsedWiki( wfMsg( 'val_merge_old' ) ) . " \n";
+               $ret .= "<input type='checkbox' name='re_clear_{$revision}' value='1'{$checked} />" . $this->getParsedWiki( wfMsg( 'val_clear_old' ) ) . " \n";
+               $ret .= "<input type='submit' name='re_submit[{$revision}]' value=\"" . wfMsgHtml( "ok" ) . "\" />\n";
+               
+               if( $focus ) $ret .= "<br/>\n<small>" . $this->getParsedWiki ( wfMsg( "val_form_note" ) ) . "</small>";
+               $ret .= "</td></tr>\n";
+               $ret .= "</table></form>\n\n";
+               return $ret;
+       }
+       
+
+       # Generates the page from the validation tab
+       function validatePageForm( &$article, $revision ) {
+               global $wgOut, $wgRequest, $wgUser;
+               
+               $ret = "";
+               $this->page_id = $article->getID();
+               $this->topicList = $this->getTopicList();
+               $this->voteCache = $this->getVoteList( $article->getID() );
+               
+               # Check for POST data
+               $re = $wgRequest->getArray( 're_submit' );
+               if ( isset( $re ) ) {
+                       $id = array_keys( $re );
+                       $id = $id[0] ; # $id is now the revision number the user clicked "OK" for
+                       $clearOldRev = $wgRequest->getVal( "re_clear_{$id}", 0 );
+                       $mergeOldRev = $wgRequest->getVal( "re_merge_{$id}", 0 );
+                       $this->updateRevision( $article, $id );
+                       if( $mergeOldRev ) {
+                               $this->mergeOldRevisions( $article, $id );
+                       }
+                       if( $clearOldRev ) {
+                               $this->clearOldRevisions( $article, $id );
+                       }
+                       $ret .= '<p class="revision_saved">' . $this->getParsedWiki( wfMsg( 'val_revision_changes_ok' ) ) . "</p>";
+               } else {
+                       $ret .= $this->getParsedWiki( wfMsg ('val_votepage_intro') );
+               }
+               
+               # Make sure the requested revision exists
+               $rev = $this->getRevisionFromId($revision);
+               $ts = $rev->rev_timestamp;
+               if( !isset( $this->voteCache[$ts] ) ) {
+                       $this->voteCache[$ts] = array();
+               }
+               
+               # Sort revisions list, newest first
+               krsort( $this->voteCache );
+               
+               # Output
+               $title = $article->getTitle();
+               $title = $title->getPrefixedText();
+               $wgOut->setPageTitle( wfMsg( 'val_rev_for', $title ) );
+               foreach( $this->voteCache as $x => $y ) {
+                       $ret .= $this->getRevisionForm( $article, $x, $y, $x == $ts );
+                       $ret .= "<br/>\n";
+               }
+               $ret .= $this->getStatisticsLink( $article );
+               $ret .= "<p>" . $this->getUserRatingsLink( $wgUser->getID(), wfMsg( 'val_show_my_ratings' ) ) . "</p>";
+               return $ret ;   
+       }
+       
+       # This function performs the "management" mode on Special:Validate
+       function manageTopics() {
+               global $wgRequest;
+               $this->topicList = $this->getTopicList();
+               
+               $iamsure = $wgRequest->getVal( "iamsure", "0" ) == 1;
+               
+               if( $iamsure && $wgRequest->getVal( "m_add", "--" ) != "--" ) {
+                       $new_topic = $wgRequest->getVal( "m_topic" );
+                       $new_limit = $wgRequest->getVal( "m_limit" );
+                       if( $new_topic != "" && $new_limit > 1 ) {
+                               $this->addTopic( $new_topic, $new_limit );
+                       }
+               }
+
+               $da = $wgRequest->getArray( "m_del" );
+               if( $iamsure && isset( $da ) && count( $da ) > 0 ) {
+                       $id = array_keys( $da );
+                       $id = array_shift( $id );
+                       $this->deleteTopic( $id );
+               }
+               
+               # FIXME: Wikitext this
+               $r = "<p>" . $this->getParsedWiki( wfMsg( 'val_warning' ) ) . "</p>\n";
+               $r .= "<form method='post'>\n";
+               $r .= "<table>\n";
+               $r .= "<tr>" . wfMsg( 'val_list_header' ) . "</tr>\n";
+               foreach( $this->topicList as $x => $y ) {
+                       $r .= "<tr>\n";
+                       $r .= "<th>{$y->val_type}</th>\n";
+                       $r .= "<td>" . $this->getTopicLink ( $y->val_comment ) . "</td>\n";
+                       $r .= "<td>1 .. <b>" . intval( $y->val_value ) . "</b></td>\n";
+                       $r .= "<td><input type='submit' name='m_del[" . intval( $x ) . "]' value='" . htmlspecialchars( wfMsg( 'val_del' ) ) . "'/></td>\n";
+                       $r .= "</tr>\n";
+               }
+               $r .= "<tr>\n";
+               $r .= "<td></td>\n";
+               $r .= '<td><input type="text" name="m_topic" value=""/></td>' . "\n";
+               $r .= '<td>1 .. <input type="text" name="m_limit" value="" size="4"/></td>' . "\n";
+               $r .= '<td><input type="submit" name="m_add" value="' . htmlspecialchars( wfMsg( 'val_add' ) ) . '"/></td>' . "\n";
+               $r .= "</tr></table>\n";
+               $r .= '<p><input type="checkbox" name="iamsure" id="iamsure" value="1"/>';
+               $r .= '<label for="iamsure">' . $this->getParsedWiki( wfMsg( 'val_iamsure' ) ) . "</label></p>\n";
+               $r .= "</form>\n";
+               return $r;
+       }
+       
+       # Generates an ID for both logged-in users and anons; $res is an object from an SQL query
+       function make_user_id( &$res ) {
+               return $res->val_user == 0 ? $res->val_ip : $res->val_user;
+       }
+
+       function showDetails( &$article, $revision ) {
+               global $wgOut, $wgUser;
+               $this->page_id = $article->getID();
+               $this->topicList = $this->getTopicList();
+
+               $sk = $wgUser->getSkin();
+               $title = $article->getTitle();
+               $wgOut->setPageTitle( str_replace( '$1', $title->getPrefixedText(), wfMsg( 'val_validation_of' ) ) );
+               
+               $data = array();
+               $users = array();
+               $topics = array();
+
+               # Collecting statistic data
+               $db =& wfGetDB( DB_SLAVE );
+               $res = $db->select( 'validate', '*', array( 'val_page' => $this->page_id, 'val_revision' => $revision ), 'SpecialValidate::showDetails' );
+               while( $x = $db->fetchObject($res) ) {
+                       $data[$this->make_user_id($x)][$x->val_type] = $x;
+                       $users[$this->make_user_id($x)] = true;
+                       $topics[$x->val_type] = true;
+               }
+               $db->freeResult($res);
+               
+               # Sorting lists of topics and users
+               ksort( $users );
+               ksort( $topics );
+               
+               $ts = $this->getRevisionTimestamp( $revision );
+               $url = $this->getRevisionLink( $article, $revision, wfTimestamp( TS_DB, $ts ) );
+
+               # Table headers
+               $ret = "" ;                     
+               $ret .= "<p><b>" . str_replace( '$1', $url, wfMsg( 'val_revision_of' ) ) . "</b></p>\n";
+               $ret .= "<table>\n";
+               $ret .= "<tr><th>" . $this->getParsedWiki ( wfMsg('val_details_th') ) . "</th>" ;
+               
+               foreach( $topics as $t => $dummy ) {
+                       $ret .= '<th>' . $sk->commentBlock( $this->topicList[$t]->val_comment, $article->getTitle() ) . '</th>';
+               }
+               $ret .= "</tr>\n";
+
+               # Table data
+               foreach( $users as $u => $dummy ) { # Every row a user
+                       $ret .= "<tr>";
+                       $ret .= "<th>";
+                       if( !User::IsIP( $u ) ) { # Logged-in user rating
+                               $ret .= $this->getUserRatingsLink( $u, User::whoIs( $u ) );
+                       } else { # Anon rating
+                               $ret .= $this->getUserRatingsLink( $u, $u );
+                       }
+                       $ret .= "</th>";
+                       foreach( $topics as $t => $dummy ) { # Every column a topic
+                               if( !isset( $data[$u][$t] ) ) {
+                                       $ret .= "<td/>";
+                               } else {
+                                       $ret .= "<td>";
+                                       $ret .= $data[$u][$t]->val_value;
+                                       if( $data[$u][$t]->val_comment != "" ) {
+                                               $ret .= ' ' . $sk->commentBlock( $data[$u][$t]->val_comment, $article->getTitle() );
+                                       }
+                                       $ret .= "</td>";
+                               }
+                       }
+                       $ret .= "</tr>";
+               }
+               $ret .= "</table>";
+               $ret .= "<p>" . $this->getStatisticsLink( $article ) . "</p>";
+               $ret .= "<p>" . $this->getUserRatingsLink( $wgUser->getID(), wfMsg( 'val_show_my_ratings' ) ) . "</p>";
+               
+               return $ret;
+       }
+       
+       # XXX This should be paged
+       function showList( &$article ) {
+               global $wgOut, $wgUser;
+               $this->page_id = $article->getID();
+               $this->topicList = $this->getTopicList();
+
+               $title = $article->getTitle();
+               $wgOut->setPageTitle( str_replace( '$1', $title->getPrefixedText(), wfMsg( 'val_validation_of' ) ) );
+               
+               # Collecting statistic data
+               $db =& wfGetDB( DB_SLAVE );
+               $res = $db->select( 'validate', '*', array( "val_page" => $this->page_id ), 'SpecialValidate::showList' );
+
+               $statistics = array();
+               while( $vote = $db->fetchObject($res) ) {
+                       $ts = $this->getRevisionTimestamp($vote->val_revision);
+                       if ( !isset ( $statistics[$ts] ) ) $statistics[$ts] = array () ;
+                       if ( !isset ( $statistics[$ts][$vote->val_type]->count ) ) $statistics[$ts][$vote->val_type]->count = 0 ;
+                       if ( !isset ( $statistics[$ts][$vote->val_type]->sum ) ) $statistics[$ts][$vote->val_type]->sum = 0 ;
+                       $statistics[$ts][$vote->val_type]->count++;
+                       $statistics[$ts][$vote->val_type]->sum += $vote->val_value;
+               }
+               $db->freeResult($res);
+
+               krsort( $statistics );
+               
+               $ret = "<table><tr>\n";
+               $ret .= "<th>" . $this->getParsedWiki( wfMsg( "val_revision" ) ) . "</th>\n";
+               foreach( $this->topicList as $topic ) {
+                       $ret .= "<th>" . $this->getTopicLink($topic->val_comment) . "</th>";
+               }
+               $ret .= "</tr>\n";
+
+               foreach( $statistics as $ts => $data ) {
+                       $rev_id = $this->getRevisionId( $ts );
+                       $revision_link = $this->getRevisionLink( $article, $rev_id, wfTimestamp( TS_DB, $ts ) );
+                       $details_link = $this->getRevisionStatsLink( $article, $rev_id );
+                       $ret .= "<tr><td>{$revision_link} {$details_link}</td>";
+                       foreach( $this->topicList as $topicType => $topic ) {
+                               if( isset( $data[$topicType] ) ) {
+                                       $stats = $data[$topicType];
+                                       $average = $stats->count == 0 ? 0 : $stats->sum / $stats->count;
+                                       $ret .= sprintf( "<td><b>%1.1f</b> (%d)</td>", $average, $stats->count );
+                               } else {
+                                       $ret .= "<td></td>";
+                               }
+                       }
+                       $ret .= "</tr>\n";
+               }
+               $ret .= "</table>\n";
+               $ret .= "<p>" . $this->getUserRatingsLink( $wgUser->getID(), wfMsg( 'val_show_my_ratings' ) ) . "</p>";
+               return $ret;
+       }
+       
+       function getRatingText( $value, $max ) {
+               if( $max == 2 && $value == 1 ) {
+                       $ret = wfMsg ( "val_no" ) . " ";
+               } elseif( $max == 2 && $value == 2 ) {
+                       $ret = wfMsg( "val_yes" );
+               } elseif( $value != 0 ) {
+                       $ret = wfMsg( "val_of", $value, $max ) . " ";
+               } else {
+                       $ret = "";
+               }
+               return $ret;
+       }
+
+       # XXX This should be paged
+       function showUserStats( $user ) {
+               global $wgOut, $wgUser;
+               $this->topicList = $this->getTopicList();
+               $data = $this->getAllVoteLists( $user );
+               $sk = $wgUser->getSkin();
+               
+               if( $user == $wgUser->getID() ) {
+                       $wgOut->setPageTitle ( wfMsg ( 'val_my_stats_title' ) );
+               } elseif( !User::IsIP( $user ) ) {
+                       $wgOut->setPageTitle( wfMsg( 'val_user_stats_title', User::whoIs( $user ) ) );
+               } else {
+                       $wgOut->setPageTitle( wfMsg( 'val_user_stats_title', $user ) );
+               }
+               
+               $ret = "<table>\n";
+               foreach( $data as $articleid => $revisions ) {
+                       $title = Title::newFromID( $articleid );
+                       $ret .= "<tr><th colspan='4'>";
+                       $ret .= $sk->makeKnownLinkObj( $title, $title->getEscapedText() );
+                       $ret .= "</th></tr>";
+                       krsort( $revisions );
+                       foreach( $revisions as $revid => $revision ) {
+                               $url = $title->getLocalURL( "oldid={$revid}" );
+                               $ret .= "<tr><th>";
+                               $ret .= $sk->makeKnownLinkObj( $title, wfMsg('val_revision_number', $revid ), "oldid={$revid}" );
+                               $ret .= "</th>";
+                               ksort( $revision );
+                               $initial = true;
+                               foreach( $revision as $topic => $rating ) {
+                                       if( !$initial ) {
+                                               $ret .= "<tr><td/>";
+                                       }
+                                       $initial = false;
+                                       $ret .= "<td>" . $this->getTopicLink ( $this->topicList[$topic]->val_comment ) . "</td>";
+                                       $ret .= "<td>" . $this->getRatingText( $rating->val_value, $this->topicList[$topic]->val_value ) . "</td>";
+                                       $ret .= "<td>" . $sk->commentBlock( $rating->val_comment ) . "</td>";
+                                       $ret .= "</tr>";
+                               }
+                       }
+                       $ret .= "</tr>";
+               }
+               $ret .= "</table>";
+               
+               return $ret;
+       }
+
+}
+
+/**
+ * constructor
+ */
+function wfSpecialValidate( $page = '' ) {
+       global $wgOut, $wgRequest, $wgUseValidation, $wgUser, $wgContLang;
+       
+       if( !$wgUseValidation ) {
+               $wgOut->errorpage( "nosuchspecialpage", "nospecialpagetext" );
+               return;
+       }
+
+/*
+       # Can do?
+       if( ! $wgUser->isAllowed('change_validation') ) {
+               $wgOut->sysopRequired();
+               return;
+       }
+*/     
+
+       $mode = $wgRequest->getVal( "mode" );
+       $skin = $wgUser->getSkin();
+
+       
+       if( $mode == "manage" ) {
+               $v = new Validation();
+               $html = $v->manageTopics();
+       } elseif( $mode == "userstats" ) {
+               $v = new Validation();
+               $user = $wgRequest->getVal( "user" );
+               $html = $v->showUserStats( $user );
+       } else {
+               $html = "$mode";
+               $html .= "<ul>\n";
+
+               $t = Title::newFromText( "Special:Validate" );
+               $url = $t->escapeLocalURL( "mode=manage" );
+               $html .= "<li><a href=\"" . $url . "\">Manage</a></li>\n";
+
+               $html .= "</ul>\n";
+       }
+
+       $wgOut->addHTML( $html );
+}
+
+?>
diff --git a/includes/SpecialVersion.php b/includes/SpecialVersion.php
new file mode 100644 (file)
index 0000000..313505a
--- /dev/null
@@ -0,0 +1,147 @@
+<?php
+/**
+ * Give information about the version of MediaWiki, PHP, the DB and extensions
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ *
+ * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
+ * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
+ */
+
+/**
+ * constructor
+ */
+function wfSpecialVersion() {
+       $version = new SpecialVersion;
+       $version->execute();
+}
+
+class SpecialVersion {
+       /**
+        * @var object
+        */
+       var $langObj;
+       
+       /**
+        * Constructor
+        */
+       function SpecialVersion() {
+               // English motherfucker, do you speak it?
+               $this->langObj = setupLangObj( 'LanguageEn' );
+               $this->langObj->initEncoding();
+       }
+       
+       function execute() {
+               global $wgOut;
+               
+               $wgOut->addWikiText( $this->MediaWikiCredits() . $this->extensionCredits() );
+               $wgOut->addHTML( $this->IPInfo() );
+       }
+
+       function MediaWikiCredits() {
+               global $wgVersion;
+               
+               $dbr =& wfGetDB( DB_SLAVE );
+               
+               $ret =
+               "__NOTOC__
+               <div dir='ltr'>
+               This wiki is powered by '''[http://www.mediawiki.org/ MediaWiki]''',  
+               copyright (C) 2001-2006 Magnus Manske, Brion Vibber, Lee Daniel Crocker,
+               Tim Starling, Erik Möller, and others.
+                
+               MediaWiki is free software; you can redistribute it and/or modify
+               it under the terms of the GNU General Public License as published by
+               the Free Software Foundation; either version 2 of the License, or
+               (at your option) any later version.
+                
+               MediaWiki is distributed in the hope that it will be useful,
+               but WITHOUT ANY WARRANTY; without even the implied warranty of
+               MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+               GNU General Public License for more details.
+               
+               You should have received [{{SERVER}}{{SCRIPTPATH}}/COPYING a copy of the GNU General Public License]
+               along with this program; if not, write to the Free Software
+               Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+               or [http://www.gnu.org/copyleft/gpl.html read it online]
+               
+               * [http://www.mediawiki.org/ MediaWiki]: $wgVersion
+               * [http://www.php.net/ PHP]: " . phpversion() . " (" . php_sapi_name() . ")
+               * " . $dbr->getSoftwareLink() . ": " . $dbr->getServerVersion() . "
+               </div>";
+
+               return str_replace( "\t\t", '', $ret );
+       }
+
+       function extensionCredits() {
+               global $wgExtensionCredits, $wgExtensionFunctions, $wgSkinExtensionFunction;
+               
+               if ( ! count( $wgExtensionCredits ) && ! count( $wgExtensionFunctions ) && ! count( $wgSkinExtensionFunction ) )
+                       return '';
+
+               $extensionTypes = array(
+                       'specialpage' => 'Special pages',
+                       'parserhook' => 'Parser hooks',
+                       'other' => 'Other',
+               );
+               
+               $out = "\n* Extensions:\n";
+               foreach ( $extensionTypes as $type => $text ) {
+                       if ( count( @$wgExtensionCredits[$type] ) ) {
+                               $out .= "** $text:\n";
+                               foreach ( $wgExtensionCredits[$type] as $extension ) {
+                                       wfSuppressWarnings();
+                                       $out .= $this->formatCredits(
+                                               $extension['name'],
+                                               $extension['version'],
+                                               $extension['author'],
+                                               $extension['url'],
+                                               $extension['description']
+                                       );
+                                       wfRestoreWarnings();
+                               }
+                       }
+               }
+
+               if ( count( $wgExtensionFunctions ) ) {
+                       $out .= "** Extension functions:\n";
+                       $out .= '***' . $this->langObj->listToText( $wgExtensionFunctions ) . "\n";
+               }
+
+               if ( count( $wgSkinExtensionFunction ) ) {
+                       $out .= "** Skin extension functions:\n";
+                       $out .= '***' . $this->langObj->listToText( $wgSkinExtensionFunction ) . "\n";
+               }
+
+               return $out;
+       }
+
+       function formatCredits( $name, $version = null, $author = null, $url = null, $description = null) {
+               $ret = '*** ';
+               if ( isset( $url ) )
+                       $ret .= "[$url ";
+               $ret .= "''$name";
+               if ( isset( $version ) )
+                       $ret .= " (version $version)";
+               $ret .= "''";
+               if ( isset( $url ) )
+                       $ret .= ']';
+               if ( isset( $description ) )
+                       $ret .= ', ' . $description;
+               if ( isset( $description ) && isset( $author ) )
+                       $ret .= ', ';
+               if ( isset( $author ) )
+                       $ret .= ' by ' . $this->langObj->listToText( (array)$author );
+
+               return "$ret\n";
+       }
+
+       function IPInfo() {
+               global $wgIP;
+               
+               $ip =  str_replace( '--', ' - - ', htmlspecialchars( $wgIP ) );
+               return "<!-- visited from $ip -->\n";
+       }
+}
+?>
diff --git a/includes/SpecialWantedpages.php b/includes/SpecialWantedpages.php
new file mode 100644 (file)
index 0000000..d55925e
--- /dev/null
@@ -0,0 +1,74 @@
+<?php
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/**
+ *
+ */
+require_once ( 'QueryPage.php' ) ;
+
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+class WantedPagesPage extends QueryPage {
+
+       function getName() {
+               return 'Wantedpages';
+       }
+
+       function isExpensive() {
+               return true;
+       }
+       function isSyndicated() { return false; }
+
+       function getSQL() {
+               global $wgWantedPagesThreshold;
+               $count = $wgWantedPagesThreshold - 1;
+               $dbr =& wfGetDB( DB_SLAVE );
+               $pagelinks = $dbr->tableName( 'pagelinks' );
+               $page      = $dbr->tableName( 'page' );
+               return
+                       "SELECT 'Wantedpages' AS type,
+                               pl_namespace AS namespace,
+                               pl_title AS title,
+                               COUNT(*) AS value
+                        FROM $pagelinks
+                        LEFT JOIN $page
+                        ON pl_namespace=page_namespace AND pl_title=page_title
+                        WHERE page_namespace IS NULL
+                        GROUP BY pl_namespace,pl_title
+                        HAVING COUNT(*) > $count";
+       }
+
+       function formatResult( $skin, $result ) {
+               global $wgContLang;
+
+               $nt = Title::makeTitle( $result->namespace, $result->title );
+               $text = $wgContLang->convert( $nt->getPrefixedText() );
+               $plink = $skin->makeBrokenLink( $nt->getPrefixedText(), $text );
+               
+               $nl = wfMsg( "nlinks", $result->value );
+               $nlink = $skin->makeKnownLink( $wgContLang->specialPage( "Whatlinkshere" ), $nl,
+                 "target=" . $nt->getPrefixedURL() );
+
+               return "{$plink} ({$nlink})";
+       }
+}
+
+/**
+ * constructor
+ */
+function wfSpecialWantedpages() {
+       list( $limit, $offset ) = wfCheckLimits();
+
+       $wpp = new WantedPagesPage();
+
+       $wpp->doQuery( $offset, $limit );
+}
+
+?>
diff --git a/includes/SpecialWatchlist.php b/includes/SpecialWatchlist.php
new file mode 100644 (file)
index 0000000..c0accda
--- /dev/null
@@ -0,0 +1,356 @@
+<?php
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/**
+ *
+ */
+require_once( 'SpecialRecentchanges.php' );
+require_once( 'WatchedItem.php' );
+
+/**
+ * constructor
+ */
+function wfSpecialWatchlist( $par ) {
+       global $wgUser, $wgOut, $wgLang, $wgTitle, $wgMemc, $wgRequest, $wgContLang;
+       global $wgUseWatchlistCache, $wgWLCacheTimeout, $wgDBname;
+       global $wgRCShowWatchingUsers, $wgEnotifWatchlist, $wgShowUpdatedMarker;
+       global $wgEnotifWatchlist;
+       $fname = 'wfSpecialWatchlist';
+
+       $wgOut->setPagetitle( wfMsg( 'watchlist' ) );
+       $sub = htmlspecialchars( wfMsg( 'watchlistsub', $wgUser->getName() ) );
+       $wgOut->setSubtitle( $sub );
+       $wgOut->setRobotpolicy( 'noindex,nofollow' );
+
+       $specialTitle = Title::makeTitle( NS_SPECIAL, 'Watchlist' );
+
+       if( $wgUser->isAnon() ) {
+               $wgOut->addWikiText( wfMsg( 'nowatchlist' ) );
+               return;
+       }
+
+       $defaults = array(
+       /* float */ 'days' => 3.0, /* or 0.5, watch further below */
+       /* bool  */ 'hideOwn' => false,
+       );
+
+       extract($defaults);
+
+       # Get query variables
+       $days = $wgRequest->getVal( 'days' );
+       $hideOwn = $wgRequest->getBool( 'hideOwn' );
+
+       # Watchlist editing
+       $action = $wgRequest->getVal( 'action' );
+       $remove = $wgRequest->getVal( 'remove' );
+       $id = $wgRequest->getArray( 'id' );
+
+       $uid = $wgUser->getID();
+       if( $wgEnotifWatchlist && $wgRequest->getVal( 'reset' ) && $wgRequest->wasPosted() ) {
+               $wgUser->clearAllNotifications( $uid );
+       }
+
+  # Deleting items from watchlist
+       if(($action == 'submit') && isset($remove) && is_array($id)) {
+               $wgOut->addWikiText( wfMsg( 'removingchecked' ) );
+               $wgOut->addHTML( '<p>' );
+               foreach($id as $one) {
+                       $t = Title::newFromURL( $one );
+                       if( !is_null( $t ) ) {
+                               $wl = WatchedItem::fromUserTitle( $wgUser, $t );
+                               if( $wl->removeWatch() === false ) {
+                                       $wgOut->addHTML( "<br />\n" . wfMsg( 'couldntremove', htmlspecialchars($one) ) );
+                               } else {
+                                       $wgOut->addHTML( ' (' . htmlspecialchars($one) . ')' );
+                               }
+                       } else {
+                               $wgOut->addHTML( "<br />\n" . wfMsg( 'iteminvalidname', htmlspecialchars($one) ) );
+                       }
+               }
+               $wgOut->addHTML( "done.</p>\n" );
+       }
+
+       if ( $wgUseWatchlistCache ) {
+               $memckey = "$wgDBname:watchlist:id:" . $wgUser->getId();
+               $cache_s = @$wgMemc->get( $memckey );
+               if( $cache_s ){
+                       $wgOut->addWikiText( wfMsg('wlsaved') );
+                       $wgOut->addHTML( $cache_s );
+                       return;
+               }
+       }
+
+       $dbr =& wfGetDB( DB_SLAVE );
+       extract( $dbr->tableNames( 'page', 'revision', 'watchlist', 'recentchanges' ) );
+
+                       $sql = "SELECT COUNT(*) AS n FROM $watchlist WHERE wl_user=$uid";
+               $res = $dbr->query( $sql, $fname );
+               $s = $dbr->fetchObject( $res );
+
+        #      Patch *** A1 *** (see A2 below)
+#      adjust for page X, talk:page X, which are both stored separately, but treated together
+       $nitems = floor($s->n / 2);
+#      $nitems = $s->n;
+
+       if($nitems == 0) {
+               $wgOut->addWikiText( wfMsg( 'nowatchlist' ) );
+               return;
+       }
+
+       if( is_null($days) || !is_numeric($days) ) {
+               $big = 1000; /* The magical big */
+               if($nitems > $big) {
+                       # Set default cutoff shorter
+                       $days = $defaults['days'] = (12.0 / 24.0); # 12 hours...
+               } else {
+                       $days = $defaults['days']; # default cutoff for shortlisters
+               }
+       } else {
+               $days = floatval($days);
+       }
+
+       // Dump everything here
+       $nondefaults = array();
+
+       wfAppendToArrayIfNotDefault( 'days', $days, $defaults, $nondefaults);
+       wfAppendToArrayIfNotDefault( 'hideOwn', $hideOwn, $defaults, $nondefaults);
+
+       if ( $days <= 0 ) {
+               $docutoff = '';
+               $cutoff = false;
+               $npages = wfMsg( 'watchlistall1' );
+       } else {
+               $docutoff = "AND rev_timestamp > '" .
+                 ( $cutoff = $dbr->timestamp( time() - intval( $days * 86400 ) ) )
+                 . "'";
+                  /* 
+                  $sql = "SELECT COUNT(*) AS n FROM $page, $revision  WHERE rev_timestamp>'$cutoff' AND page_id=rev_page";
+                  $res = $dbr->query( $sql, $fname );
+                  $s = $dbr->fetchObject( $res );
+                  $npages = $s->n;
+                  */
+                  $npages = 40000 * $days;
+
+       }
+
+       /* Edit watchlist form */
+       if($wgRequest->getBool('edit') || $par == 'edit' ) {
+               $wgOut->addWikiText( wfMsg( 'watchlistcontains', $wgLang->formatNum( $nitems ) ) .
+                       "\n\n" . wfMsg( 'watcheditlist' ) );
+
+               $wgOut->addHTML( '<form action=\'' .
+                       $specialTitle->escapeLocalUrl( 'action=submit' ) .
+                       "' method='post'>\n" );
+
+#              Patch A2
+#              The following was proposed by KTurner 07.11.2004 to T.Gries
+#              $sql = "SELECT distinct (wl_namespace & ~1),wl_title FROM $watchlist WHERE wl_user=$uid";
+               $sql = "SELECT wl_namespace,wl_title FROM $watchlist WHERE wl_user=$uid";
+
+               $res = $dbr->query( $sql, $fname );
+               $sk = $wgUser->getSkin();
+
+               $list = array();
+               while( $s = $dbr->fetchObject( $res ) ) {
+                       $list[$s->wl_namespace][] = $s->wl_title;
+               }
+
+               // TODO: Display a TOC
+               foreach($list as $ns => $titles) {
+                       if (Namespace::isTalk($ns))
+                               continue;
+                       if ($ns != NS_MAIN)
+                               $wgOut->addHTML( '<h2>' . $wgContLang->getFormattedNsText( $ns ) . '</h2>' );
+                       $wgOut->addHTML( '<ul>' );
+                       foreach($titles as $title) {
+                               $t = Title::makeTitle( $ns, $title );
+                               if( is_null( $t ) ) {
+                                       $wgOut->addHTML(
+                                               '<!-- bad title "' .
+                                               htmlspecialchars( $s->wl_title ) . '" in namespace ' . $s->wl_namespace . " -->\n"
+                                       );
+                               } else {
+                                       $t = $t->getPrefixedText();
+                                       $wgOut->addHTML(
+                                               '<li><input type="checkbox" name="id[]" value="' . htmlspecialchars($t) . '" />' .
+                                               $sk->makeLink( $t, $t ) .
+                                               "</li>\n"
+                                       );
+                               }
+                       }
+                       $wgOut->addHTML( '</ul>' );
+               }
+               $wgOut->addHTML(
+                       "<input type='submit' name='remove' value=\"" .
+                       htmlspecialchars( wfMsg( "removechecked" ) ) . "\" />\n" .
+                       "</form>\n"
+               );
+
+               return;
+       }
+
+       # If the watchlist is relatively short, it's simplest to zip
+       # down its entirety and then sort the results.
+
+       # If it's relatively long, it may be worth our while to zip
+       # through the time-sorted page list checking for watched items.
+
+       # Up estimate of watched items by 15% to compensate for talk pages...
+
+       $andHideOwn = $hideOwn ? "AND (rc_user <> $uid)" : '';
+
+       # Show watchlist header
+       $header = '';
+       if( $wgUser->getOption( 'enotifwatchlistpages' ) && $wgEnotifWatchlist) {
+               $header .= wfMsg( 'wlheader-enotif' ) . "\n";
+       }
+       if ( $wgEnotifWatchlist && $wgShowUpdatedMarker ) {
+               $header .= wfMsg( 'wlheader-showupdated' ) . "\n";
+       }
+
+       # TODO: Consider removing the third parameter
+       $header .= wfMsg( 'watchdetails', $wgLang->formatNum( $nitems ), 
+               $wgLang->formatNum( $npages ), '',
+               $specialTitle->getFullUrl( 'edit=yes' ) );
+       $wgOut->addWikiText( $header );
+       
+       if ( $wgEnotifWatchlist && $wgShowUpdatedMarker ) {
+               $wgOut->addHTML( '<form action="' .
+                       $specialTitle->escapeLocalUrl() .
+                       '" method="post"><input type="submit" name="dummy" value="' .
+                       htmlspecialchars( wfMsg( 'enotif_reset' ) ) .
+                       '" /><input type="hidden" name="reset" value="all" /></form>' .
+                       "\n\n" );
+       }
+
+        $sql = "SELECT
+          rc_namespace page_namespace,rc_title page_title,
+          rc_comment rev_comment, rc_cur_id page_id,
+          rc_user rev_user,rc_user_text rev_user_text,
+          rc_timestamp rev_timestamp,rc_minor rev_minor_edit,
+          rc_this_oldid rev_id,
+          rc_last_oldid,
+          rc_new page_is_new,wl_notificationtimestamp
+          FROM $watchlist,$recentchanges,$page
+          WHERE wl_user=$uid
+          AND wl_namespace=rc_namespace
+          AND wl_title=rc_title
+          AND rc_timestamp > '$cutoff'
+          AND rc_cur_id=page_id
+          AND rc_this_oldid=page_latest
+          $andHideOwn
+          ORDER BY rc_timestamp DESC";
+
+       $res = $dbr->query( $sql, $fname );
+       $numRows = $dbr->numRows( $res );
+
+       /* Start bottom header */
+       $wgOut->addHTML( "<hr />\n<p>" );
+
+       if($days >= 1)
+               $wgOut->addWikiText( wfMsg( 'rcnote', $wgLang->formatNum( $numRows ),
+                       $wgLang->formatNum( $days ) ) . '<br />' , false );
+       elseif($days > 0)
+               $wgOut->addWikiText( wfMsg( 'wlnote', $wgLang->formatNum( $numRows ),
+                       $wgLang->formatNum( round($days*24) ) ) . '<br />' , false );
+
+       $wgOut->addHTML( "\n" . wlCutoffLinks( $days, 'Watchlist', $nondefaults ) . "<br />\n" );
+       
+       $sk = $wgUser->getSkin();
+       $s = $sk->makeKnownLink(
+               $wgContLang->specialPage( 'Watchlist' ),
+               (0 == $hideOwn) ? wfMsgHtml( 'wlhide' ) : wfMsgHtml( 'wlshow' ),
+               wfArrayToCGI( array('hideOwn' => 1-$hideOwn ), $nondefaults ) );
+
+       $wgOut->addHTML( wfMsgHtml( "wlhideshowown", $s ) );
+       
+       if ( $numRows == 0 ) {
+               $wgOut->addWikitext( "<br />" . wfMsg( 'watchnochange' ), false );
+               $wgOut->addHTML( "</p>\n" );
+               return;
+       }
+
+       $wgOut->addHTML( "</p>\n" );
+       /* End bottom header */
+
+       $sk = $wgUser->getSkin();
+       $list =& new ChangesList( $sk );
+       $s = $list->beginRecentChangesList();
+       $counter = 1;
+       while ( $obj = $dbr->fetchObject( $res ) ) {
+               # Make fake RC entry
+               $rc = RecentChange::newFromCurRow( $obj, $obj->rc_last_oldid );
+               $rc->counter = $counter++;
+
+               if ( $wgShowUpdatedMarker ) {
+                       $updated = $obj->wl_notificationtimestamp;
+               } else {
+                       // Same visual appearance as MW 1.4
+                       $updated = true;
+               }
+
+               if ($wgRCShowWatchingUsers && $wgUser->getOption( 'shownumberswatching' )) {
+                       $sql3 = "SELECT COUNT(*) AS n FROM $watchlist WHERE wl_title='" .wfStrencode($obj->page_title). "' AND wl_namespace='{$obj->page_namespace}'" ;
+                       $res3 = $dbr->query( $sql3, DB_READ, $fname );
+                       $x = $dbr->fetchObject( $res3 );
+                       $rc->numberofWatchingusers = $x->n;
+               } else {
+                       $rc->numberofWatchingusers = 0;
+               }
+
+               $s .= $list->recentChangesLine( $rc, $updated );
+       }
+       $s .= $list->endRecentChangesList();
+
+       $dbr->freeResult( $res );
+       $wgOut->addHTML( $s );
+
+       if ( $wgUseWatchlistCache ) {
+               $wgMemc->set( $memckey, $s, $wgWLCacheTimeout);
+       }
+
+}
+
+function wlHoursLink( $h, $page, $options = array() ) {
+       global $wgUser, $wgLang, $wgContLang;
+       $sk = $wgUser->getSkin();
+       $s = $sk->makeKnownLink(
+         $wgContLang->specialPage( $page ),
+         $wgLang->formatNum( $h ),
+         wfArrayToCGI( array('days' => ($h / 24.0)), $options ) );
+       return $s;
+}
+
+function wlDaysLink( $d, $page, $options = array() ) {
+       global $wgUser, $wgLang, $wgContLang;
+       $sk = $wgUser->getSkin();
+       $s = $sk->makeKnownLink(
+         $wgContLang->specialPage( $page ),
+         ($d ? $wgLang->formatNum( $d ) : wfMsgHtml( 'watchlistall2' ) ),
+         wfArrayToCGI( array('days' => $d), $options ) );
+       return $s;
+}
+
+function wlCutoffLinks( $days, $page = 'Watchlist', $options = array() ) {
+       $hours = array( 1, 2, 6, 12 );
+       $days = array( 1, 3, 7 );
+       $cl = '';
+       $i = 0;
+       foreach( $hours as $h ) {
+               $hours[$i++] = wlHoursLink( $h, $page, $options );
+       }
+       $i = 0;
+       foreach( $days as $d ) {
+               $days[$i++] = wlDaysLink( $d, $page, $options );
+       }
+       return wfMsg ('wlshowlast',
+               implode(' | ', $hours),
+               implode(' | ', $days),
+               wlDaysLink( 0, $page, $options ) );
+}
+
+?>
diff --git a/includes/SpecialWhatlinkshere.php b/includes/SpecialWhatlinkshere.php
new file mode 100644 (file)
index 0000000..087b517
--- /dev/null
@@ -0,0 +1,127 @@
+<?php
+/**
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+/**
+ * Entry point
+ * @param string $par An article name ??
+ */
+function wfSpecialWhatlinkshere($par = NULL) {
+       global $wgUser, $wgOut, $wgRequest;
+       $fname = 'wfSpecialWhatlinkshere';
+
+       $target = isset($par) ? $par : $wgRequest->getVal( 'target' );
+       list( $limit, $offset ) = $wgRequest->getLimitOffset(); 
+
+       if (is_null($target)) {
+               $wgOut->errorpage( 'notargettitle', 'notargettext' );
+               return;
+       }
+
+       $nt = Title::newFromURL( $target );
+       if( !$nt ) {
+               $wgOut->errorpage( 'notargettitle', 'notargettext' );
+               return;
+       }
+       $wgOut->setPagetitle( $nt->getPrefixedText() );
+       $wgOut->setSubtitle( wfMsg( 'linklistsub' ) );
+
+       $sk = $wgUser->getSkin();
+       $isredir = ' (' . wfMsg( 'isredirect' ) . ")\n";
+
+       $wgOut->addHTML('&lt; '.$sk->makeLinkObj($nt, '', 'redirect=no' )."<br />\n");
+
+       wfShowIndirectLinks( 0, $nt, $limit, $offset );
+}
+
+/**
+ * @param int   $level
+ * @param Title $target
+ * @param int   $limit
+ * @param int   $offset
+ * @access private
+ */
+function wfShowIndirectLinks( $level, $target, $limit, $offset = 0 ) {
+       global $wgOut, $wgUser;
+       $fname = 'wfShowIndirectLinks';
+
+       $dbr =& wfGetDB( DB_READ );
+       
+       // Read one extra row as an at-end check
+       $queryLimit = $limit + 1; 
+       $limitSql = ( $level == 0 )
+               ? "$offset,$queryLimit"
+               : $queryLimit;
+
+       $res = $dbr->select( array( 'pagelinks', 'page' ),
+               array( 'page_id', 'page_namespace', 'page_title', 'page_is_redirect' ),
+               array(
+                       'pl_from=page_id',
+                       'pl_namespace' => $target->getNamespace(),
+                       'pl_title'     => $target->getDbKey() ),
+               $fname,
+               array( 'LIMIT' => $limitSql ) );
+
+       if ( 0 == $dbr->numRows( $res ) ) {
+               if ( 0 == $level ) {
+                       $wgOut->addWikiText( wfMsg( 'nolinkshere' ) );
+               }
+               return;
+       }
+       if ( 0 == $level ) {
+               $wgOut->addWikiText( wfMsg( 'linkshere' ) );
+       }
+       $sk = $wgUser->getSkin();
+       $isredir = ' (' . wfMsg( 'isredirect' ) . ")\n";
+
+       if( $dbr->numRows( $res ) == 0 ) {
+               return;
+       }
+       $atend = ( $dbr->numRows( $res ) <= $limit );
+       
+       if( $level == 0 ) {
+               $specialTitle = Title::makeTitle( NS_SPECIAL, 'Whatlinkshere' );
+               $prevnext = wfViewPrevNext( $offset, $limit, $specialTitle,
+                       'target=' . urlencode( $target->getPrefixedDbKey() ),
+                       $atend );
+               $wgOut->addHTML( $prevnext );
+       }
+       
+       $wgOut->addHTML( '<ul>' );
+       $linksShown = 0;
+       while ( $row = $dbr->fetchObject( $res ) ) {
+               if( ++$linksShown > $limit ) {
+                       // Last row is for checks only; don't display it.
+                       break;
+               }
+               
+               $nt = Title::makeTitle( $row->page_namespace, $row->page_title );
+
+               if ( $row->page_is_redirect ) {
+                       $extra = 'redirect=no';
+               } else {
+                       $extra = '';
+               }
+
+               $link = $sk->makeKnownLinkObj( $nt, '', $extra );
+               $wgOut->addHTML( '<li>'.$link );
+
+               if ( $row->page_is_redirect ) {
+                       $wgOut->addHTML( $isredir );
+                       if ( $level < 2 ) {
+                               wfShowIndirectLinks( $level + 1, $nt, 500 );
+                       }
+               }
+               $wgOut->addHTML( "</li>\n" );
+       }
+       $wgOut->addHTML( "</ul>\n" );
+       
+       if( $level == 0 ) {
+               $wgOut->addHTML( $prevnext );
+       }
+}
+
+?>
diff --git a/includes/SquidUpdate.php b/includes/SquidUpdate.php
new file mode 100644 (file)
index 0000000..91769b2
--- /dev/null
@@ -0,0 +1,253 @@
+<?php
+/**
+ * See deferred.txt
+ * @package MediaWiki
+ */
+
+/**
+ *
+ * @package MediaWiki
+ */
+class SquidUpdate {
+       var $urlArr, $mMaxTitles;
+
+       function SquidUpdate( $urlArr = Array(), $maxTitles = false ) {
+               global $wgMaxSquidPurgeTitles;
+               if ( $maxTitles === false ) {
+                       $this->mMaxTitles = $wgMaxSquidPurgeTitles;
+               } else {
+                       $this->mMaxTitles = $maxTitles;
+               }
+               if ( count( $urlArr ) > $this->mMaxTitles ) {
+                       $urlArr = array_slice( $urlArr, 0, $this->mMaxTitles );
+               }
+               $this->urlArr = $urlArr;
+       }
+
+       /* static */ function newFromLinksTo( &$title ) {
+               $fname = 'SquidUpdate::newFromLinksTo';
+               wfProfileIn( $fname );
+
+               # Get a list of URLs linking to this page
+               $id = $title->getArticleID();
+
+               $dbr =& wfGetDB( DB_SLAVE );
+               $links = $dbr->tableName( 'links' );
+               $page = $dbr->tableName( 'page' );
+
+               $res = $dbr->select( array( 'links', 'page' ),
+                       array( 'page_namespace', 'page_title' ),
+                       array(
+                               'pl_namespace' => $title->getNamespace(),
+                               'pl_title'     => $title->getDbKey(),
+                               'pl_from=page_id' ),
+                       $fname );
+               $blurlArr = $title->getSquidURLs();
+               if ( $dbr->numRows( $res ) <= $this->mMaxTitles ) {
+                       while ( $BL = $dbr->fetchObject ( $res ) )
+                       {
+                               $tobj = Title::makeTitle( $BL->page_namespace, $BL->page_title ) ; 
+                               $blurlArr[] = $tobj->getInternalURL();
+                       }
+               }
+               $dbr->freeResult ( $res ) ;
+
+               wfProfileOut( $fname );
+               return new SquidUpdate( $blurlArr );
+       }
+
+       /* static */ function newFromTitles( &$titles, $urlArr = array() ) {
+               foreach ( $titles as $title ) {
+                       $urlArr[] = $title->getInternalURL();
+               }
+               return new SquidUpdate( $urlArr );
+       }
+
+       /* static */ function newSimplePurge( &$title ) {
+               $urlArr = $title->getSquidURLs();
+               return new SquidUpdate( $blurlArr );
+       }
+
+       function doUpdate() {
+               SquidUpdate::purge( $this->urlArr );
+       }
+
+       /* Purges a list of Squids defined in $wgSquidServers.
+       $urlArr should contain the full URLs to purge as values 
+       (example: $urlArr[] = 'http://my.host/something')
+       XXX report broken Squids per mail or log */
+
+       /* static */ function purge( $urlArr ) {
+               global $wgSquidServers, $wgHTCPMulticastAddress, $wgHTCPPort;
+
+               if ( $wgSquidServers == 'echo' ) {
+                       echo implode("<br />\n", $urlArr);
+                       return;
+               }
+
+               if ( $wgHTCPMulticastAddress && $wgHTCPPort )
+                       SquidUpdate::HTCPPurge( $urlArr );
+
+               $fname = 'SquidUpdate::purge';
+               wfProfileIn( $fname );
+               
+               $maxsocketspersquid = 8; //  socket cap per Squid
+               $urlspersocket = 400; // 400 seems to be a good tradeoff, opening a socket takes a while
+               $firsturl = $urlArr[0];
+               unset($urlArr[0]);
+               $urlArr = array_values($urlArr);
+               $sockspersq =  max(ceil(count($urlArr) / $urlspersocket ),1);
+               if ($sockspersq == 1) {
+                       /* the most common case */
+                       $urlspersocket = count($urlArr);
+               } else if ($sockspersq > $maxsocketspersquid ) {
+                       $urlspersocket = ceil(count($urlArr) / $maxsocketspersquid);
+                       $sockspersq = $maxsocketspersquid;
+               }
+               $totalsockets = count($wgSquidServers) * $sockspersq;
+               $sockets = Array();
+
+               /* this sets up the sockets and tests the first socket for each server. */
+               for ($ss=0;$ss < count($wgSquidServers);$ss++) {
+                       $failed = false;
+                       $so = 0;
+                       while ($so < $sockspersq && !$failed) {
+                               if ($so == 0) {
+                                       /* first socket for this server, do the tests */
+                                       @list($server, $port) = explode(':', $wgSquidServers[$ss]);
+                                       if(!isset($port)) $port = 80;
+                                       #$this->debug("Opening socket to $server:$port");
+                                       $socket = @fsockopen($server, $port, $error, $errstr, 3);
+                                       #$this->debug("\n");
+                                       if (!$socket) {
+                                               $failed = true;
+                                               $totalsockets -= $sockspersq;
+                                       } else {
+                                               $msg = 'PURGE ' . $firsturl . " HTTP/1.0\r\n".
+                                               "Connection: Keep-Alive\r\n\r\n";
+                                               #$this->debug($msg);
+                                               @fputs($socket,$msg);
+                                               #$this->debug("...");
+                                               $res = @fread($socket,512);
+                                               #$this->debug("\n");
+                                               /* Squid only returns http headers with 200 or 404 status, 
+                                               if there's more returned something's wrong */
+                                               if (strlen($res) > 250) {
+                                                       fclose($socket);
+                                                       $failed = true;
+                                                       $totalsockets -= $sockspersq;
+                                               } else {
+                                                       @stream_set_blocking($socket,false);
+                                                       $sockets[] = $socket;
+                                               }
+                                       } 
+                               } else {
+                                       /* open the remaining sockets for this server */
+                                       list($server, $port) = explode(':', $wgSquidServers[$ss]);
+                                       if(!isset($port)) $port = 80;
+                                       $sockets[] = @fsockopen($server, $port, $error, $errstr, 2);
+                                       @stream_set_blocking($sockets[$s],false);
+                               }
+                               $so++;
+                       }
+               }
+
+               if ($urlspersocket > 0) {
+                       /* now do the heavy lifting. The fread() relies on Squid returning only the headers */
+                       for ($r=0;$r < $urlspersocket;$r++) {
+                               for ($s=0;$s < $totalsockets;$s++) {
+                                       if($r != 0) {
+                                               $res = '';
+                                               $esc = 0;
+                                               while (strlen($res) < 100 && $esc < 200  ) {
+                                                       $res .= @fread($sockets[$s],512);
+                                                       $esc++;
+                                                       usleep(20);
+                                               }
+                                       }
+                                       $urindex = $r + $urlspersocket * ($s - $sockspersq * floor($s / $sockspersq));
+                                       $msg = 'PURGE ' . $urlArr[$urindex] . " HTTP/1.0\r\n".
+                                       "Connection: Keep-Alive\r\n\r\n";
+                                       #$this->debug($msg);
+                                       @fputs($sockets[$s],$msg);
+                                       #$this->debug("\n");
+                               }
+                       }
+               }
+               #$this->debug("Reading response...");
+               foreach ($sockets as $socket) {
+                       $res = '';
+                       $esc = 0;
+                       while (strlen($res) < 100 && $esc < 200  ) {
+                               $res .= @fread($socket,1024);
+                               $esc++;
+                               usleep(20);
+                       }
+
+                       @fclose($socket);
+               }
+               #$this->debug("\n");
+               wfProfileOut( $fname );
+       }
+
+       /* static */ function HTCPPurge( $urlArr ) {
+               global $wgHTCPMulticastAddress, $wgHTCPMulticastTTL, $wgHTCPPort;
+               $fname = 'SquidUpdate::HTCPPurge';
+               wfProfileIn( $fname );
+
+               $htcpOpCLR = 4;                 // HTCP CLR
+
+               // FIXME PHP doesn't support these socket constants (include/linux/in.h)
+               define( "IPPROTO_IP", 0 );
+               define( "IP_MULTICAST_LOOP", 34 );
+               define( "IP_MULTICAST_TTL", 33 );
+
+               // pfsockopen doesn't work because we need set_sock_opt
+               $conn = socket_create( AF_INET, SOCK_DGRAM, SOL_UDP );
+               if ( $conn ) {
+                       // Set socket options
+                       socket_set_option( $conn, IPPROTO_IP, IP_MULTICAST_LOOP, 0 );
+                       if ( $wgHTCPMulticastTTL != 1 )
+                               socket_set_option( $conn, IPPROTO_IP, IP_MULTICAST_TTL,
+                                       $wgHTCPMulticastTTL );
+
+                       foreach ( $urlArr as $url ) {
+                               // Construct a minimal HTCP request diagram
+                               // as per RFC 2756
+                               // Opcode 'CLR', no response desired, no auth
+                               $htcpTransID = rand();
+
+                               $htcpSpecifier = pack( 'na4na*na8n',
+                                       4, 'NONE', strlen( $url ), $url,
+                                       8, 'HTTP/1.0', 0 );
+
+                               $htcpDataLen = 8 + 2 + strlen( $htcpSpecifier );
+                               $htcpLen = 4 + $htcpDataLen + 2;
+
+                               // Note! Squid gets the bit order of the first
+                               // word wrong, wrt the RFC. Apparently no other
+                               // implementation exists, so adapt to Squid
+                               $htcpPacket = pack( 'nxxnCxNxxa*n',
+                                       $htcpLen, $htcpDataLen, $htcpOpCLR,
+                                       $htcpTransID, $htcpSpecifier, 2);
+
+                               // Send out
+                               wfDebug( "Purging URL $url via HTCP\n" );
+                               socket_sendto( $conn, $htcpPacket, $htcpLen, 0,
+                                       $wgHTCPMulticastAddress, $wgHTCPPort );
+                       }
+               } else {
+                       $errstr = socket_strerror( socket_last_error() );
+                       wfDebug( "SquidUpdate::HTCPPurge(): Error opening UDP socket: $errstr\n" );
+               }
+               wfProfileOut( $fname );
+       }
+
+       function debug( $text ) {
+               global $wgDebugSquid;
+               if ( $wgDebugSquid ) {
+                       wfDebug( $text );
+               }
+       }
+}
+?>
diff --git a/includes/StreamFile.php b/includes/StreamFile.php
new file mode 100644 (file)
index 0000000..0c44bb9
--- /dev/null
@@ -0,0 +1,65 @@
+<?php
+/** */
+
+/** */
+function wfStreamFile( $fname ) {
+       global $wgSquidMaxage;
+       $stat = @stat( $fname );
+       if ( !$stat ) {
+               header( 'HTTP/1.0 404 Not Found' );
+               echo "<html><body>
+<h1>File not found</h1>
+<p>Although this PHP script ({$_SERVER['SCRIPT_NAME']}) exists, the file requested for output 
+does not.</p>
+</body></html>";
+               return;
+       }
+
+       header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s', $stat['mtime'] ) . ' GMT' );
+
+       if ( !empty( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) ) {
+               $modsince = preg_replace( '/;.*$/', '', $_SERVER['HTTP_IF_MODIFIED_SINCE'] );
+               $sinceTime = strtotime( $modsince );
+               if ( $stat['mtime'] <= $sinceTime ) {
+                       header( "HTTP/1.0 304 Not Modified" );
+                       return;
+               }
+       }
+       
+       header( 'Content-Length: ' . $stat['size'] );
+       
+       $type = wfGetType( $fname );
+       if ( $type and $type!="unknown/unknown") {
+               header("Content-type: $type");
+       } else {
+               header('Content-type: application/x-wiki');
+       }
+       
+       readfile( $fname );
+}
+
+/** */
+function wfGetType( $filename ) {
+       global $wgTrivialMimeDetection;
+
+       # trivial detection by file extension,
+       # used for thumbnails (thumb.php)
+       if ($wgTrivialMimeDetection) {
+               $ext= strtolower(strrchr($filename, '.'));
+               
+               switch ($ext) {
+                       case '.gif': return 'image/gif';
+                       case '.png': return 'image/png';
+                       case '.jpg': return 'image/jpeg';
+                       case '.jpeg': return 'image/jpeg';
+               }
+               
+               return 'unknown/unknown';
+       }
+       else {
+               $magic=& wfGetMimeMagic();
+               return $magic->guessMimeType($filename); //full fancy mime detection
+       }
+}
+
+?>
diff --git a/includes/Title.php b/includes/Title.php
new file mode 100644 (file)
index 0000000..e147b28
--- /dev/null
@@ -0,0 +1,2127 @@
+<?php
+/**
+ * See title.txt
+ *
+ * @package MediaWiki
+ */
+
+/** */
+require_once( 'normal/UtfNormal.php' );
+
+$wgTitleInterwikiCache = array();
+define ( 'GAID_FOR_UPDATE', 1 );
+
+# Title::newFromTitle maintains a cache to avoid
+# expensive re-normalization of commonly used titles.
+# On a batch operation this can become a memory leak
+# if not bounded. After hitting this many titles,
+# reset the cache.
+define( 'MW_TITLECACHE_MAX', 1000 );
+
+/**
+ * Title class
+ * - Represents a title, which may contain an interwiki designation or namespace
+ * - Can fetch various kinds of data from the database, albeit inefficiently.
+ *
+ * @package MediaWiki
+ */
+class Title {
+       /**
+        * All member variables should be considered private
+        * Please use the accessor functions
+        */
+
+        /**#@+
+        * @access private
+        */
+
+       var $mTextform;           # Text form (spaces not underscores) of the main part
+       var $mUrlform;            # URL-encoded form of the main part
+       var $mDbkeyform;          # Main part with underscores
+       var $mNamespace;          # Namespace index, i.e. one of the NS_xxxx constants
+       var $mInterwiki;          # Interwiki prefix (or null string)
+       var $mFragment;           # Title fragment (i.e. the bit after the #)
+       var $mArticleID;          # Article ID, fetched from the link cache on demand
+       var $mLatestID;         # ID of most recent revision
+       var $mRestrictions;       # Array of groups allowed to edit this article
+                              # Only null or "sysop" are supported
+       var $mRestrictionsLoaded; # Boolean for initialisation on demand
+       var $mPrefixedText;       # Text form including namespace/interwiki, initialised on demand
+       var $mDefaultNamespace;   # Namespace index when there is no namespace
+                              # Zero except in {{transclusion}} tags
+       var $mWatched;            # Is $wgUser watching this page? NULL if unfilled, accessed through userIsWatching()
+       /**#@-*/
+
+
+       /**
+        * Constructor
+        * @access private
+        */
+       /* private */ function Title() {
+               $this->mInterwiki = $this->mUrlform =
+               $this->mTextform = $this->mDbkeyform = '';
+               $this->mArticleID = -1;
+               $this->mNamespace = NS_MAIN;
+               $this->mRestrictionsLoaded = false;
+               $this->mRestrictions = array();
+               # Dont change the following, NS_MAIN is hardcoded in several place
+               # See bug #696
+               $this->mDefaultNamespace = NS_MAIN;
+               $this->mWatched = NULL;
+               $this->mLatestID = false;
+       }
+
+       /**
+        * Create a new Title from a prefixed DB key
+        * @param string $key The database key, which has underscores
+        *      instead of spaces, possibly including namespace and
+        *      interwiki prefixes
+        * @return Title the new object, or NULL on an error
+        * @static
+        * @access public
+        */
+       /* static */ function newFromDBkey( $key ) {
+               $t = new Title();
+               $t->mDbkeyform = $key;
+               if( $t->secureAndSplit() )
+                       return $t;
+               else
+                       return NULL;
+       }
+
+       /**
+        * Create a new Title from text, such as what one would
+        * find in a link. Decodes any HTML entities in the text.
+        *
+        * @param string $text the link text; spaces, prefixes,
+        *      and an initial ':' indicating the main namespace
+        *      are accepted
+        * @param int $defaultNamespace the namespace to use if
+        *      none is specified by a prefix
+        * @return Title the new object, or NULL on an error
+        * @static
+        * @access public
+        */
+       function newFromText( $text, $defaultNamespace = NS_MAIN ) {
+               $fname = 'Title::newFromText';
+               wfProfileIn( $fname );
+
+               if( is_object( $text ) ) {
+                       wfDebugDieBacktrace( 'Title::newFromText given an object' );
+               }
+
+               /**
+                * Wiki pages often contain multiple links to the same page.
+                * Title normalization and parsing can become expensive on
+                * pages with many links, so we can save a little time by
+                * caching them.
+                *
+                * In theory these are value objects and won't get changed...
+                */
+               static $titleCache = array();
+               if( $defaultNamespace == NS_MAIN && isset( $titleCache[$text] ) ) {
+                       wfProfileOut( $fname );
+                       return $titleCache[$text];
+               }
+
+               /**
+                * Convert things like &eacute; &#257; or &#x3017; into real text...
+                */
+               $filteredText = Sanitizer::decodeCharReferences( $text );
+
+               $t =& new Title();
+               $t->mDbkeyform = str_replace( ' ', '_', $filteredText );
+               $t->mDefaultNamespace = $defaultNamespace;
+
+               if( $t->secureAndSplit() ) {
+                       if( $defaultNamespace == NS_MAIN ) {
+                               if( count( $titleCache ) >= MW_TITLECACHE_MAX ) {
+                                       # Avoid memory leaks on mass operations...
+                                       $titleCache = array();
+                               }
+                               $titleCache[$text] =& $t;
+                       }
+                       wfProfileOut( $fname );
+                       return $t;
+               } else {
+                       wfProfileOut( $fname );
+                       return NULL;
+               }
+       }
+
+       /**
+        * Create a new Title from URL-encoded text. Ensures that
+        * the given title's length does not exceed the maximum.
+        * @param string $url the title, as might be taken from a URL
+        * @return Title the new object, or NULL on an error
+        * @static
+        * @access public
+        */
+       function newFromURL( $url ) {
+               global $wgLang, $wgServer;
+               $t = new Title();
+
+               # For compatibility with old buggy URLs. "+" is not valid in titles,
+               # but some URLs used it as a space replacement and they still come
+               # from some external search tools.
+               $s = str_replace( '+', ' ', $url );
+
+               $t->mDbkeyform = str_replace( ' ', '_', $s );
+               if( $t->secureAndSplit() ) {
+                       return $t;
+               } else {
+                       return NULL;
+               }
+       }
+
+       /**
+        * Create a new Title from an article ID
+        *
+        * @todo This is inefficiently implemented, the page row is requested
+        *       but not used for anything else
+        *
+        * @param int $id the page_id corresponding to the Title to create
+        * @return Title the new object, or NULL on an error
+        * @access public
+        * @static
+        */
+       function newFromID( $id ) {
+               $fname = 'Title::newFromID';
+               $dbr =& wfGetDB( DB_SLAVE );
+               $row = $dbr->selectRow( 'page', array( 'page_namespace', 'page_title' ),
+                       array( 'page_id' => $id ), $fname );
+               if ( $row !== false ) {
+                       $title = Title::makeTitle( $row->page_namespace, $row->page_title );
+               } else {
+                       $title = NULL;
+               }
+               return $title;
+       }
+
+       /**
+        * Create a new Title from a namespace index and a DB key.
+        * It's assumed that $ns and $title are *valid*, for instance when
+        * they came directly from the database or a special page name.
+        * For convenience, spaces are converted to underscores so that
+        * eg user_text fields can be used directly.
+        *
+        * @param int $ns the namespace of the article
+        * @param string $title the unprefixed database key form
+        * @return Title the new object
+        * @static
+        * @access public
+        */
+       function &makeTitle( $ns, $title ) {
+               $t =& new Title();
+               $t->mInterwiki = '';
+               $t->mFragment = '';
+               $t->mNamespace = IntVal( $ns );
+               $t->mDbkeyform = str_replace( ' ', '_', $title );
+               $t->mArticleID = ( $ns >= 0 ) ? -1 : 0;
+               $t->mUrlform = wfUrlencode( $t->mDbkeyform );
+               $t->mTextform = str_replace( '_', ' ', $title );
+               return $t;
+       }
+
+       /**
+        * Create a new Title frrom a namespace index and a DB key.
+        * The parameters will be checked for validity, which is a bit slower
+        * than makeTitle() but safer for user-provided data.
+        *
+        * @param int $ns the namespace of the article
+        * @param string $title the database key form
+        * @return Title the new object, or NULL on an error
+        * @static
+        * @access public
+        */
+       function makeTitleSafe( $ns, $title ) {
+               $t = new Title();
+               $t->mDbkeyform = Title::makeName( $ns, $title );
+               if( $t->secureAndSplit() ) {
+                       return $t;
+               } else {
+                       return NULL;
+               }
+       }
+
+       /**
+        * Create a new Title for the Main Page
+        *
+        * @static
+        * @return Title the new object
+        * @access public
+        */
+       function newMainPage() {
+               return Title::newFromText( wfMsgForContent( 'mainpage' ) );
+       }
+
+       /**
+        * Create a new Title for a redirect
+        * @param string $text the redirect title text
+        * @return Title the new object, or NULL if the text is not a
+        *      valid redirect
+        * @static
+        * @access public
+        */
+       function newFromRedirect( $text ) {
+               global $wgMwRedir;
+               $rt = NULL;
+               if ( $wgMwRedir->matchStart( $text ) ) {
+                       if ( preg_match( '/\[{2}(.*?)(?:\||\]{2})/', $text, $m ) ) {
+                               # categories are escaped using : for example one can enter:
+                               # #REDIRECT [[:Category:Music]]. Need to remove it.
+                               if ( substr($m[1],0,1) == ':') {
+                                       # We don't want to keep the ':'
+                                       $m[1] = substr( $m[1], 1 );
+                               }
+
+                               $rt = Title::newFromText( $m[1] );
+                               # Disallow redirects to Special:Userlogout
+                               if ( !is_null($rt) && $rt->getNamespace() == NS_SPECIAL && preg_match( '/^Userlogout/i', $rt->getText() ) ) {
+                                       $rt = NULL;
+                               }
+                       }
+               }
+               return $rt;
+       }
+
+#----------------------------------------------------------------------------
+#      Static functions
+#----------------------------------------------------------------------------
+
+       /**
+        * Get the prefixed DB key associated with an ID
+        * @param int $id the page_id of the article
+        * @return Title an object representing the article, or NULL
+        *      if no such article was found
+        * @static
+        * @access public
+        */
+       function nameOf( $id ) {
+               $fname = 'Title::nameOf';
+               $dbr =& wfGetDB( DB_SLAVE );
+
+               $s = $dbr->selectRow( 'page', array( 'page_namespace','page_title' ),  array( 'page_id' => $id ), $fname );
+               if ( $s === false ) { return NULL; }
+
+               $n = Title::makeName( $s->page_namespace, $s->page_title );
+               return $n;
+       }
+
+       /**
+        * Get a regex character class describing the legal characters in a link
+        * @return string the list of characters, not delimited
+        * @static
+        * @access public
+        */
+       function legalChars() {
+               # Missing characters:
+               #  * []|# Needed for link syntax
+               #  * % and + are corrupted by Apache when they appear in the path
+               #
+               # % seems to work though
+               #
+               # The problem with % is that URLs are double-unescaped: once by Apache's
+               # path conversion code, and again by PHP. So %253F, for example, becomes "?".
+               # Our code does not double-escape to compensate for this, indeed double escaping
+               # would break if the double-escaped title was passed in the query string
+               # rather than the path. This is a minor security issue because articles can be
+               # created such that they are hard to view or edit. -- TS
+               #
+               # Theoretically 0x80-0x9F of ISO 8859-1 should be disallowed, but
+               # this breaks interlanguage links
+
+               $set = " %!\"$&'()*,\\-.\\/0-9:;=?@A-Z\\\\^_`a-z~\\x80-\\xFF";
+               return $set;
+       }
+
+       /**
+        * Get a string representation of a title suitable for
+        * including in a search index
+        *
+        * @param int $ns a namespace index
+        * @param string $title text-form main part
+        * @return string a stripped-down title string ready for the
+        *      search index
+        */
+       /* static */ function indexTitle( $ns, $title ) {
+               global $wgDBminWordLen, $wgContLang;
+               require_once( 'SearchEngine.php' );
+
+               $lc = SearchEngine::legalSearchChars() . '&#;';
+               $t = $wgContLang->stripForSearch( $title );
+               $t = preg_replace( "/[^{$lc}]+/", ' ', $t );
+               $t = strtolower( $t );
+
+               # Handle 's, s'
+               $t = preg_replace( "/([{$lc}]+)'s( |$)/", "\\1 \\1's ", $t );
+               $t = preg_replace( "/([{$lc}]+)s'( |$)/", "\\1s ", $t );
+
+               $t = preg_replace( "/\\s+/", ' ', $t );
+
+               if ( $ns == NS_IMAGE ) {
+                       $t = preg_replace( "/ (png|gif|jpg|jpeg|ogg)$/", "", $t );
+               }
+               return trim( $t );
+       }
+
+       /*
+        * Make a prefixed DB key from a DB key and a namespace index
+        * @param int $ns numerical representation of the namespace
+        * @param string $title the DB key form the title
+        * @return string the prefixed form of the title
+        */
+       /* static */ function makeName( $ns, $title ) {
+               global $wgContLang;
+
+               $n = $wgContLang->getNsText( $ns );
+               return $n == '' ? $title : "$n:$title";
+       }
+
+       /**
+        * Returns the URL associated with an interwiki prefix
+        * @param string $key the interwiki prefix (e.g. "MeatBall")
+        * @return the associated URL, containing "$1", which should be
+        *      replaced by an article title
+        * @static (arguably)
+        * @access public
+        */
+       function getInterwikiLink( $key, $transludeonly = false ) {
+               global $wgMemc, $wgDBname, $wgInterwikiExpiry, $wgTitleInterwikiCache;
+               $fname = 'Title::getInterwikiLink';
+
+               wfProfileIn( $fname );
+
+               $k = $wgDBname.':interwiki:'.$key;
+               if( array_key_exists( $k, $wgTitleInterwikiCache ) ) {
+                       wfProfileOut( $fname );
+                       return $wgTitleInterwikiCache[$k]->iw_url;
+               }
+
+               $s = $wgMemc->get( $k );
+               # Ignore old keys with no iw_local
+               if( $s && isset( $s->iw_local ) && isset($s->iw_trans)) {
+                       $wgTitleInterwikiCache[$k] = $s;
+                       wfProfileOut( $fname );
+                       return $s->iw_url;
+               }
+
+               $dbr =& wfGetDB( DB_SLAVE );
+               $res = $dbr->select( 'interwiki',
+                       array( 'iw_url', 'iw_local', 'iw_trans' ),
+                       array( 'iw_prefix' => $key ), $fname );
+               if( !$res ) {
+                       wfProfileOut( $fname );
+                       return '';
+               }
+
+               $s = $dbr->fetchObject( $res );
+               if( !$s ) {
+                       # Cache non-existence: create a blank object and save it to memcached
+                       $s = (object)false;
+                       $s->iw_url = '';
+                       $s->iw_local = 0;
+                       $s->iw_trans = 0;
+               }
+               $wgMemc->set( $k, $s, $wgInterwikiExpiry );
+               $wgTitleInterwikiCache[$k] = $s;
+
+               wfProfileOut( $fname );
+               return $s->iw_url;
+       }
+
+       /**
+        * Determine whether the object refers to a page within
+        * this project.
+        *
+        * @return bool TRUE if this is an in-project interwiki link
+        *      or a wikilink, FALSE otherwise
+        * @access public
+        */
+       function isLocal() {
+               global $wgTitleInterwikiCache, $wgDBname;
+
+               if ( $this->mInterwiki != '' ) {
+                       # Make sure key is loaded into cache
+                       $this->getInterwikiLink( $this->mInterwiki );
+                       $k = $wgDBname.':interwiki:' . $this->mInterwiki;
+                       return (bool)($wgTitleInterwikiCache[$k]->iw_local);
+               } else {
+                       return true;
+               }
+       }
+
+       /**
+        * Determine whether the object refers to a page within
+        * this project and is transcludable.
+        *
+        * @return bool TRUE if this is transcludable
+        * @access public
+        */
+       function isTrans() {
+               global $wgTitleInterwikiCache, $wgDBname;
+
+               if ($this->mInterwiki == '' || !$this->isLocal())
+                       return false;
+               # Make sure key is loaded into cache
+               $this->getInterwikiLink( $this->mInterwiki );
+               $k = $wgDBname.':interwiki:' . $this->mInterwiki;
+               return (bool)($wgTitleInterwikiCache[$k]->iw_trans);
+       }
+
+       /**
+        * Update the page_touched field for an array of title objects
+        * @todo Inefficient unless the IDs are already loaded into the
+        *      link cache
+        * @param array $titles an array of Title objects to be touched
+        * @param string $timestamp the timestamp to use instead of the
+        *      default current time
+        * @static
+        * @access public
+        */
+       function touchArray( $titles, $timestamp = '' ) {
+               global $wgUseFileCache;
+
+               if ( count( $titles ) == 0 ) {
+                       return;
+               }
+               $dbw =& wfGetDB( DB_MASTER );
+               if ( $timestamp == '' ) {
+                       $timestamp = $dbw->timestamp();
+               }
+               $page = $dbw->tableName( 'page' );
+               /*
+               $sql = "UPDATE $page SET page_touched='{$timestamp}' WHERE page_id IN (";
+               $first = true;
+
+               foreach ( $titles as $title ) {
+                       if ( $wgUseFileCache ) {
+                               $cm = new CacheManager($title);
+                               @unlink($cm->fileCacheName());
+                       }
+
+                       if ( ! $first ) {
+                               $sql .= ',';
+                       }
+                       $first = false;
+                       $sql .= $title->getArticleID();
+               }
+               $sql .= ')';
+               if ( ! $first ) {
+                       $dbw->query( $sql, 'Title::touchArray' );
+               }
+               */
+               // hack hack hack -- brion 2005-07-11. this was unfriendly to db.
+               // do them in small chunks:
+               $fname = 'Title::touchArray';
+               foreach( $titles as $title ) {
+                       $dbw->update( 'page',
+                               array( 'page_touched' => $timestamp ),
+                               array(
+                                       'page_namespace' => $title->getNamespace(),
+                                       'page_title'     => $title->getDBkey() ),
+                               $fname );
+               }
+       }
+
+#----------------------------------------------------------------------------
+#      Other stuff
+#----------------------------------------------------------------------------
+
+       /** Simple accessors */
+       /**
+        * Get the text form (spaces not underscores) of the main part
+        * @return string
+        * @access public
+        */
+       function getText() { return $this->mTextform; }
+       /**
+        * Get the URL-encoded form of the main part
+        * @return string
+        * @access public
+        */
+       function getPartialURL() { return $this->mUrlform; }
+       /**
+        * Get the main part with underscores
+        * @return string
+        * @access public
+        */
+       function getDBkey() { return $this->mDbkeyform; }
+       /**
+        * Get the namespace index, i.e. one of the NS_xxxx constants
+        * @return int
+        * @access public
+        */
+       function getNamespace() { return $this->mNamespace; }
+       /**
+        * Get the interwiki prefix (or null string)
+        * @return string
+        * @access public
+        */
+       function getInterwiki() { return $this->mInterwiki; }
+       /**
+        * Get the Title fragment (i.e. the bit after the #)
+        * @return string
+        * @access public
+        */
+       function getFragment() { return $this->mFragment; }
+       /**
+        * Get the default namespace index, for when there is no namespace
+        * @return int
+        * @access public
+        */
+       function getDefaultNamespace() { return $this->mDefaultNamespace; }
+
+       /**
+        * Get title for search index
+        * @return string a stripped-down title string ready for the
+        *      search index
+        */
+       function getIndexTitle() {
+               return Title::indexTitle( $this->mNamespace, $this->mTextform );
+       }
+
+       /**
+        * Get the prefixed database key form
+        * @return string the prefixed title, with underscores and
+        *      any interwiki and namespace prefixes
+        * @access public
+        */
+       function getPrefixedDBkey() {
+               $s = $this->prefix( $this->mDbkeyform );
+               $s = str_replace( ' ', '_', $s );
+               return $s;
+       }
+
+       /**
+        * Get the prefixed title with spaces.
+        * This is the form usually used for display
+        * @return string the prefixed title, with spaces
+        * @access public
+        */
+       function getPrefixedText() {
+               global $wgContLang;
+               if ( empty( $this->mPrefixedText ) ) {
+                       $s = $this->prefix( $this->mTextform );
+                       $s = str_replace( '_', ' ', $s );
+                       $this->mPrefixedText = $s;
+               }
+               return $this->mPrefixedText;
+       }
+
+       /**
+        * Get the prefixed title with spaces, plus any fragment
+        * (part beginning with '#')
+        * @return string the prefixed title, with spaces and
+        *      the fragment, including '#'
+        * @access public
+        */
+       function getFullText() {
+               global $wgContLang;
+               $text = $this->getPrefixedText();
+               if( '' != $this->mFragment ) {
+                       $text .= '#' . $this->mFragment;
+               }
+               return $text;
+       }
+
+       /**
+        * Get a URL-encoded title (not an actual URL) including interwiki
+        * @return string the URL-encoded form
+        * @access public
+        */
+       function getPrefixedURL() {
+               $s = $this->prefix( $this->mDbkeyform );
+               $s = str_replace( ' ', '_', $s );
+
+               $s = wfUrlencode ( $s ) ;
+
+               # Cleaning up URL to make it look nice -- is this safe?
+               $s = str_replace( '%28', '(', $s );
+               $s = str_replace( '%29', ')', $s );
+
+               return $s;
+       }
+
+       /**
+        * Get a real URL referring to this title, with interwiki link and
+        * fragment
+        *
+        * @param string $query an optional query string, not used
+        *      for interwiki links
+        * @return string the URL
+        * @access public
+        */
+       function getFullURL( $query = '' ) {
+               global $wgContLang, $wgServer, $wgScript, $wgMakeDumpLinks, $wgArticlePath;
+
+               if ( '' == $this->mInterwiki ) {
+                       return $wgServer . $this->getLocalUrl( $query );
+               } elseif ( $wgMakeDumpLinks && $wgContLang->getLanguageName( $this->mInterwiki ) ) {
+                       $baseUrl = str_replace( '$1', "../../{$this->mInterwiki}/$1", $wgArticlePath );
+                       $baseUrl = str_replace( '$1', $this->getHashedDirectory() . '/$1', $baseUrl );
+               } else {
+                       $baseUrl = $this->getInterwikiLink( $this->mInterwiki );
+               }
+
+               $namespace = $wgContLang->getNsText( $this->mNamespace );
+               if ( '' != $namespace ) {
+                       # Can this actually happen? Interwikis shouldn't be parsed.
+                       $namespace .= ':';
+               }
+               $url = str_replace( '$1', $namespace . $this->mUrlform, $baseUrl );
+               if( $query != '' ) {
+                       if( false === strpos( $url, '?' ) ) {
+                               $url .= '?';
+                       } else {
+                               $url .= '&';
+                       }
+                       $url .= $query;
+               }
+               if ( '' != $this->mFragment ) {
+                       $url .= '#' . $this->mFragment;
+               }
+               return $url;
+       }
+
+       /**
+        * Get a relative directory for putting an HTML version of this article into
+        */
+       function getHashedDirectory() {
+               global $wgMakeDumpLinks, $wgInputEncoding;
+               $dbkey = $this->getDBkey();
+
+               # Split into characters
+               if ( $wgInputEncoding == 'UTF-8' ) {
+                       preg_match_all( '/./us', $dbkey, $m );
+               } else {
+                       preg_match_all( '/./s', $dbkey, $m );
+               }
+               $chars = $m[0];
+               $length = count( $chars );
+               $dir = '';
+
+               for ( $i = 0; $i < $wgMakeDumpLinks; $i++ ) {
+                       if ( $i ) {
+                               $dir .= '/';
+                       }
+                       if ( $i >= $length ) {
+                               $dir .= '_';
+                       } elseif ( ord( $chars[$i] ) > 32 ) {
+                               $dir .= strtolower( $chars[$i] );
+                       } else {
+                               $dir .= sprintf( "%02X", ord( $chars[$i] ) );
+                       }
+               }
+               return $dir;
+       }
+
+       function getHashedFilename() {
+               $dbkey = $this->getPrefixedDBkey();
+               $mainPage = Title::newMainPage();
+               if ( $mainPage->getPrefixedDBkey() == $dbkey ) {
+                       return 'index.html';
+               }
+
+               $dir = $this->getHashedDirectory();
+
+               # Replace illegal charcters for Windows paths with underscores
+               $friendlyName = strtr( $dbkey, '/\\*?"<>|~', '_________' );
+
+               # Work out lower case form. We assume we're on a system with case-insensitive
+               # filenames, so unless the case is of a special form, we have to disambiguate
+               $lowerCase = $this->prefix( ucfirst( strtolower( $this->getDBkey() ) ) );
+
+               # Make it mostly unique
+               if ( $lowerCase != $friendlyName  ) {
+                       $friendlyName .= '_' . substr(md5( $dbkey ), 0, 4);
+               }
+               # Handle colon specially by replacing it with tilde
+               # Thus we reduce the number of paths with hashes appended
+               $friendlyName = str_replace( ':', '~', $friendlyName );
+               return "$dir/$friendlyName.html";
+       }
+
+       /**
+        * Get a URL with no fragment or server name.  If this page is generated
+        * with action=render, $wgServer is prepended.
+        * @param string $query an optional query string; if not specified,
+        *      $wgArticlePath will be used.
+        * @return string the URL
+        * @access public
+        */
+       function getLocalURL( $query = '' ) {
+               global $wgLang, $wgArticlePath, $wgScript, $wgMakeDumpLinks, $wgServer, $action;
+
+               if ( $this->isExternal() ) {
+                       return $this->getFullURL();
+               }
+
+               $dbkey = wfUrlencode( $this->getPrefixedDBkey() );
+               if ( $wgMakeDumpLinks ) {
+                       $url = str_replace( '$1', wfUrlencode( $this->getHashedFilename() ), $wgArticlePath );
+               } elseif ( $query == '' ) {
+                       $url = str_replace( '$1', $dbkey, $wgArticlePath );
+               } else {
+                       global $wgActionPaths;
+                       if( !empty( $wgActionPaths ) &&
+                               preg_match( '/^(.*&|)action=([^&]*)(&(.*)|)$/', $query, $matches ) ) {
+                               $action = urldecode( $matches[2] );
+                               if( isset( $wgActionPaths[$action] ) ) {
+                                       $query = $matches[1];
+                                       if( isset( $matches[4] ) ) $query .= $matches[4];
+                                       $url = str_replace( '$1', $dbkey, $wgActionPaths[$action] );
+                                       if( $query != '' ) $url .= '?' . $query;
+                                       return $url;
+                               }
+                       }
+                       if ( $query == '-' ) {
+                               $query = '';
+                       }
+                       $url = "{$wgScript}?title={$dbkey}&{$query}";
+               }
+
+               if ($action == 'render')
+                       return $wgServer . $url;
+               else
+                       return $url;
+       }
+
+       /**
+        * Get an HTML-escaped version of the URL form, suitable for
+        * using in a link, without a server name or fragment
+        * @param string $query an optional query string
+        * @return string the URL
+        * @access public
+        */
+       function escapeLocalURL( $query = '' ) {
+               return htmlspecialchars( $this->getLocalURL( $query ) );
+       }
+
+       /**
+        * Get an HTML-escaped version of the URL form, suitable for
+        * using in a link, including the server name and fragment
+        *
+        * @return string the URL
+        * @param string $query an optional query string
+        * @access public
+        */
+       function escapeFullURL( $query = '' ) {
+               return htmlspecialchars( $this->getFullURL( $query ) );
+       }
+
+       /**
+        * Get the URL form for an internal link.
+        * - Used in various Squid-related code, in case we have a different
+        * internal hostname for the server from the exposed one.
+        *
+        * @param string $query an optional query string
+        * @return string the URL
+        * @access public
+        */
+       function getInternalURL( $query = '' ) {
+               global $wgInternalServer;
+               return $wgInternalServer . $this->getLocalURL( $query );
+       }
+
+       /**
+        * Get the edit URL for this Title
+        * @return string the URL, or a null string if this is an
+        *      interwiki link
+        * @access public
+        */
+       function getEditURL() {
+               global $wgServer, $wgScript;
+
+               if ( '' != $this->mInterwiki ) { return ''; }
+               $s = $this->getLocalURL( 'action=edit' );
+
+               return $s;
+       }
+
+       /**
+        * Get the HTML-escaped displayable text form.
+        * Used for the title field in <a> tags.
+        * @return string the text, including any prefixes
+        * @access public
+        */
+       function getEscapedText() {
+               return htmlspecialchars( $this->getPrefixedText() );
+       }
+
+       /**
+        * Is this Title interwiki?
+        * @return boolean
+        * @access public
+        */
+       function isExternal() { return ( '' != $this->mInterwiki ); }
+
+       /**
+        * Does the title correspond to a protected article?
+        * @param string $what the action the page is protected from,
+        *      by default checks move and edit
+        * @return boolean
+        * @access public
+        */
+       function isProtected($action = '') {
+               if ( -1 == $this->mNamespace ) { return true; }
+               if($action == 'edit' || $action == '') {
+                       $a = $this->getRestrictions("edit");
+                       if ( in_array( 'sysop', $a ) ) { return true; }
+               }
+               if($action == 'move' || $action == '') {
+                       $a = $this->getRestrictions("move");
+                       if ( in_array( 'sysop', $a ) ) { return true; }
+               }
+               return false;
+       }
+
+       /**
+        * Is $wgUser is watching this page?
+        * @return boolean
+        * @access public
+        */
+       function userIsWatching() {
+               global $wgUser;
+
+               if ( is_null( $this->mWatched ) ) {
+                       if ( -1 == $this->mNamespace || 0 == $wgUser->getID()) {
+                               $this->mWatched = false;
+                       } else {
+                               $this->mWatched = $wgUser->isWatched( $this );
+                       }
+               }
+               return $this->mWatched;
+       }
+
+       /**
+        * Is $wgUser perform $action this page?
+        * @param string $action action that permission needs to be checked for
+        * @return boolean
+        * @access private
+        */
+       function userCan($action) {
+               $fname = 'Title::userCanEdit';
+               wfProfileIn( $fname );
+
+               global $wgUser;
+               if( NS_SPECIAL == $this->mNamespace ) {
+                       wfProfileOut( $fname );
+                       return false;
+               }
+               if( NS_MEDIAWIKI == $this->mNamespace &&
+                   !$wgUser->isAllowed('editinterface') ) {
+                       wfProfileOut( $fname );
+                       return false;
+               }
+               if( $this->mDbkeyform == '_' ) {
+                       # FIXME: Is this necessary? Shouldn't be allowed anyway...
+                       wfProfileOut( $fname );
+                       return false;
+               }
+
+               # protect global styles and js
+               if ( NS_MEDIAWIKI == $this->mNamespace
+                && preg_match("/\\.(css|js)$/", $this->mTextform )
+                    && !$wgUser->isAllowed('editinterface') ) {
+                       wfProfileOut( $fname );
+                       return false;
+               }
+
+               # protect css/js subpages of user pages
+               # XXX: this might be better using restrictions
+               # XXX: Find a way to work around the php bug that prevents using $this->userCanEditCssJsSubpage() from working
+               if( NS_USER == $this->mNamespace
+                       && preg_match("/\\.(css|js)$/", $this->mTextform )
+                       && !$wgUser->isAllowed('editinterface')
+                       && !preg_match('/^'.preg_quote($wgUser->getName(), '/').'\//', $this->mTextform) ) {
+                       wfProfileOut( $fname );
+                       return false;
+               }
+
+               foreach( $this->getRestrictions($action) as $right ) {
+                       // Backwards compatibility, rewrite sysop -> protect
+                       if ( $right == 'sysop' ) {
+                               $right = 'protect';
+                       }
+                       if( '' != $right && !$wgUser->isAllowed( $right ) ) {
+                               wfProfileOut( $fname );
+                               return false;
+                       }
+               }
+
+               if( $action == 'move' &&
+                       !( $this->isMovable() && $wgUser->isAllowed( 'move' ) ) ) {
+                       wfProfileOut( $fname );
+                       return false;
+               }
+
+               wfProfileOut( $fname );
+               return true;
+       }
+
+       /**
+        * Can $wgUser edit this page?
+        * @return boolean
+        * @access public
+        */
+       function userCanEdit() {
+               return $this->userCan('edit');
+       }
+
+       /**
+        * Can $wgUser move this page?
+        * @return boolean
+        * @access public
+        */
+       function userCanMove() {
+               return $this->userCan('move');
+       }
+
+       /**
+        * Would anybody with sufficient privileges be able to move this page?
+        * Some pages just aren't movable.
+        *
+        * @return boolean
+        * @access public
+        */
+       function isMovable() {
+               return Namespace::isMovable( $this->getNamespace() )
+                       && $this->getInterwiki() == '';
+       }
+
+       /**
+        * Can $wgUser read this page?
+        * @return boolean
+        * @access public
+        */
+       function userCanRead() {
+               global $wgUser;
+
+               if( $wgUser->isAllowed('read') ) {
+                       return true;
+               } else {
+                       global $wgWhitelistRead;
+
+                       /** If anon users can create an account,
+                           they need to reach the login page first! */
+                       if( $wgUser->isAllowed( 'createaccount' )
+                           && $this->getNamespace() == NS_SPECIAL
+                           && $this->getText() == 'Userlogin' ) {
+                               return true;
+                       }
+
+                       /** some pages are explicitly allowed */
+                       $name = $this->getPrefixedText();
+                       if( $wgWhitelistRead && in_array( $name, $wgWhitelistRead ) ) {
+                               return true;
+                       }
+
+                       # Compatibility with old settings
+                       if( $wgWhitelistRead && $this->getNamespace() == NS_MAIN ) {
+                               if( in_array( ':' . $name, $wgWhitelistRead ) ) {
+                                       return true;
+                               }
+                       }
+               }
+               return false;
+       }
+
+       /**
+        * Is this a talk page of some sort?
+        * @return bool
+        * @access public
+        */
+       function isTalkPage() {
+               return Namespace::isTalk( $this->getNamespace() );
+       }
+
+       /**
+        * Is this a .css or .js subpage of a user page?
+        * @return bool
+        * @access public
+        */
+       function isCssJsSubpage() {
+               return ( NS_USER == $this->mNamespace and preg_match("/\\.(css|js)$/", $this->mTextform ) );
+       }
+       /**
+        * Is this a .css subpage of a user page?
+        * @return bool
+        * @access public
+        */
+       function isCssSubpage() {
+               return ( NS_USER == $this->mNamespace and preg_match("/\\.css$/", $this->mTextform ) );
+       }
+       /**
+        * Is this a .js subpage of a user page?
+        * @return bool
+        * @access public
+        */
+       function isJsSubpage() {
+               return ( NS_USER == $this->mNamespace and preg_match("/\\.js$/", $this->mTextform ) );
+       }
+       /**
+        * Protect css/js subpages of user pages: can $wgUser edit
+        * this page?
+        *
+        * @return boolean
+        * @todo XXX: this might be better using restrictions
+        * @access public
+        */
+       function userCanEditCssJsSubpage() {
+               global $wgUser;
+               return ( $wgUser->isAllowed('editinterface') or preg_match('/^'.preg_quote($wgUser->getName(), '/').'\//', $this->mTextform) );
+       }
+
+       /**
+        * Loads a string into mRestrictions array
+        * @param string $res restrictions in string format
+        * @access public
+        */
+       function loadRestrictions( $res ) {
+               foreach( explode( ':', trim( $res ) ) as $restrict ) {
+                       $temp = explode( '=', trim( $restrict ) );
+                       if(count($temp) == 1) {
+                               // old format should be treated as edit/move restriction
+                               $this->mRestrictions["edit"] = explode( ',', trim( $temp[0] ) );
+                               $this->mRestrictions["move"] = explode( ',', trim( $temp[0] ) );
+                       } else {
+                               $this->mRestrictions[$temp[0]] = explode( ',', trim( $temp[1] ) );
+                       }
+               }
+               $this->mRestrictionsLoaded = true;
+       }
+
+       /**
+        * Accessor/initialisation for mRestrictions
+        * @param string $action action that permission needs to be checked for
+        * @return array the array of groups allowed to edit this article
+        * @access public
+        */
+       function getRestrictions($action) {
+               $id = $this->getArticleID();
+               if ( 0 == $id ) { return array(); }
+
+               if ( ! $this->mRestrictionsLoaded ) {
+                       $dbr =& wfGetDB( DB_SLAVE );
+                       $res = $dbr->selectField( 'page', 'page_restrictions', 'page_id='.$id );
+                       $this->loadRestrictions( $res );
+               }
+               if( isset( $this->mRestrictions[$action] ) ) {
+                       return $this->mRestrictions[$action];
+               }
+               return array();
+       }
+
+       /**
+        * Is there a version of this page in the deletion archive?
+        * @return int the number of archived revisions
+        * @access public
+        */
+       function isDeleted() {
+               $fname = 'Title::isDeleted';
+               if ( $this->getNamespace() < 0 ) {
+                       $n = 0;
+               } else {
+                       $dbr =& wfGetDB( DB_SLAVE );
+                       $n = $dbr->selectField( 'archive', 'COUNT(*)', array( 'ar_namespace' => $this->getNamespace(),
+                               'ar_title' => $this->getDBkey() ), $fname );
+               }
+               return (int)$n;
+       }
+
+       /**
+        * Get the article ID for this Title from the link cache,
+        * adding it if necessary
+        * @param int $flags a bit field; may be GAID_FOR_UPDATE to select
+        *      for update
+        * @return int the ID
+        * @access public
+        */
+       function getArticleID( $flags = 0 ) {
+               global $wgLinkCache;
+
+               if ( $flags & GAID_FOR_UPDATE ) {
+                       $oldUpdate = $wgLinkCache->forUpdate( true );
+                       $this->mArticleID = $wgLinkCache->addLinkObj( $this );
+                       $wgLinkCache->forUpdate( $oldUpdate );
+               } else {
+                       if ( -1 == $this->mArticleID ) {
+                               $this->mArticleID = $wgLinkCache->addLinkObj( $this );
+                       }
+               }
+               return $this->mArticleID;
+       }
+
+       function getLatestRevID() {
+               if ($this->mLatestID !== false)
+                       return $this->mLatestID;
+
+               $db =& wfGetDB(DB_SLAVE);
+               return $this->mLatestID = $db->selectField( 'revision',
+                       "max(rev_id)",
+                       array('rev_page' => $this->getArticleID()),
+                       'Title::getLatestRevID' );
+       }
+
+       /**
+        * This clears some fields in this object, and clears any associated
+        * keys in the "bad links" section of $wgLinkCache.
+        *
+        * - This is called from Article::insertNewArticle() to allow
+        * loading of the new page_id. It's also called from
+        * Article::doDeleteArticle()
+        *
+        * @param int $newid the new Article ID
+        * @access public
+        */
+       function resetArticleID( $newid ) {
+               global $wgLinkCache;
+               $wgLinkCache->clearBadLink( $this->getPrefixedDBkey() );
+
+               if ( 0 == $newid ) { $this->mArticleID = -1; }
+               else { $this->mArticleID = $newid; }
+               $this->mRestrictionsLoaded = false;
+               $this->mRestrictions = array();
+       }
+
+       /**
+        * Updates page_touched for this page; called from LinksUpdate.php
+        * @return bool true if the update succeded
+        * @access public
+        */
+       function invalidateCache() {
+               global $wgUseFileCache;
+
+               if ( wfReadOnly() ) {
+                       return;
+               }
+
+               $now = wfTimestampNow();
+               $dbw =& wfGetDB( DB_MASTER );
+               $success = $dbw->update( 'page',
+                       array( /* SET */
+                               'page_touched' => $dbw->timestamp()
+                       ), array( /* WHERE */
+                               'page_namespace' => $this->getNamespace() ,
+                               'page_title' => $this->getDBkey()
+                       ), 'Title::invalidateCache'
+               );
+
+               if ($wgUseFileCache) {
+                       $cache = new CacheManager($this);
+                       @unlink($cache->fileCacheName());
+               }
+
+               return $success;
+       }
+
+       /**
+        * Prefix some arbitrary text with the namespace or interwiki prefix
+        * of this object
+        *
+        * @param string $name the text
+        * @return string the prefixed text
+        * @access private
+        */
+       /* private */ function prefix( $name ) {
+               global $wgContLang;
+
+               $p = '';
+               if ( '' != $this->mInterwiki ) {
+                       $p = $this->mInterwiki . ':';
+               }
+               if ( 0 != $this->mNamespace ) {
+                       $p .= $wgContLang->getNsText( $this->mNamespace ) . ':';
+               }
+               return $p . $name;
+       }
+
+       /**
+        * Secure and split - main initialisation function for this object
+        *
+        * Assumes that mDbkeyform has been set, and is urldecoded
+        * and uses underscores, but not otherwise munged.  This function
+        * removes illegal characters, splits off the interwiki and
+        * namespace prefixes, sets the other forms, and canonicalizes
+        * everything.
+        * @return bool true on success
+        * @access private
+        */
+       /* private */ function secureAndSplit() {
+               global $wgContLang, $wgLocalInterwiki, $wgCapitalLinks;
+               $fname = 'Title::secureAndSplit';
+               wfProfileIn( $fname );
+
+               # Initialisation
+               static $rxTc = false;
+               if( !$rxTc ) {
+                       # % is needed as well
+                       $rxTc = '/[^' . Title::legalChars() . ']|%[0-9A-Fa-f]{2}/S';
+               }
+
+               $this->mInterwiki = $this->mFragment = '';
+               $this->mNamespace = $this->mDefaultNamespace; # Usually NS_MAIN
+
+               # Clean up whitespace
+               #
+               $t = preg_replace( '/[ _]+/', '_', $this->mDbkeyform );
+               $t = trim( $t, '_' );
+
+               if ( '' == $t ) {
+                       wfProfileOut( $fname );
+                       return false;
+               }
+
+               if( false !== strpos( $t, UTF8_REPLACEMENT ) ) {
+                       # Contained illegal UTF-8 sequences or forbidden Unicode chars.
+                       wfProfileOut( $fname );
+                       return false;
+               }
+
+               $this->mDbkeyform = $t;
+
+               # Initial colon indicates main namespace rather than specified default
+               # but should not create invalid {ns,title} pairs such as {0,Project:Foo}
+               if ( ':' == $t{0} ) {
+                       $this->mNamespace = NS_MAIN;
+                       $t = substr( $t, 1 ); # remove the colon but continue processing
+               }
+
+               # Namespace or interwiki prefix
+               $firstPass = true;
+               do {
+                       if ( preg_match( "/^(.+?)_*:_*(.*)$/S", $t, $m ) ) {
+                               $p = $m[1];
+                               $lowerNs = strtolower( $p );
+                               if ( $ns = Namespace::getCanonicalIndex( $lowerNs ) ) {
+                                       # Canonical namespace
+                                       $t = $m[2];
+                                       $this->mNamespace = $ns;
+                               } elseif ( $ns = $wgContLang->getNsIndex( $lowerNs )) {
+                                       # Ordinary namespace
+                                       $t = $m[2];
+                                       $this->mNamespace = $ns;
+                               } elseif( $this->getInterwikiLink( $p ) ) {
+                                       if( !$firstPass ) {
+                                               # Can't make a local interwiki link to an interwiki link.
+                                               # That's just crazy!
+                                               wfProfileOut( $fname );
+                                               return false;
+                                       }
+
+                                       # Interwiki link
+                                       $t = $m[2];
+                                       $this->mInterwiki = $p;
+
+                                       # Redundant interwiki prefix to the local wiki
+                                       if ( 0 == strcasecmp( $this->mInterwiki, $wgLocalInterwiki ) ) {
+                                               if( $t == '' ) {
+                                                       # Can't have an empty self-link
+                                                       wfProfileOut( $fname );
+                                                       return false;
+                                               }
+                                               $this->mInterwiki = '';
+                                               $firstPass = false;
+                                               # Do another namespace split...
+                                               continue;
+                                       }
+                               }
+                               # If there's no recognized interwiki or namespace,
+                               # then let the colon expression be part of the title.
+                       }
+                       break;
+               } while( true );
+               $r = $t;
+
+               # We already know that some pages won't be in the database!
+               #
+               if ( '' != $this->mInterwiki || -1 == $this->mNamespace ) {
+                       $this->mArticleID = 0;
+               }
+               $f = strstr( $r, '#' );
+               if ( false !== $f ) {
+                       $this->mFragment = substr( $f, 1 );
+                       $r = substr( $r, 0, strlen( $r ) - strlen( $f ) );
+                       # remove whitespace again: prevents "Foo_bar_#"
+                       # becoming "Foo_bar_"
+                       $r = preg_replace( '/_*$/', '', $r );
+               }
+
+               # Reject illegal characters.
+               #
+               if( preg_match( $rxTc, $r ) ) {
+                       wfProfileOut( $fname );
+                       return false;
+               }
+
+               /**
+                * Pages with "/./" or "/../" appearing in the URLs will
+                * often be unreachable due to the way web browsers deal
+                * with 'relative' URLs. Forbid them explicitly.
+                */
+               if ( strpos( $r, '.' ) !== false &&
+                    ( $r === '.' || $r === '..' ||
+                      strpos( $r, './' ) === 0  ||
+                      strpos( $r, '../' ) === 0 ||
+                      strpos( $r, '/./' ) !== false ||
+                      strpos( $r, '/../' ) !== false ) )
+               {
+                       wfProfileOut( $fname );
+                       return false;
+               }
+
+               # We shouldn't need to query the DB for the size.
+               #$maxSize = $dbr->textFieldSize( 'page', 'page_title' );
+               if ( strlen( $r ) > 255 ) {
+                       wfProfileOut( $fname );
+                       return false;
+               }
+
+               /**
+                * Normally, all wiki links are forced to have
+                * an initial capital letter so [[foo]] and [[Foo]]
+                * point to the same place.
+                *
+                * Don't force it for interwikis, since the other
+                * site might be case-sensitive.
+                */
+               if( $wgCapitalLinks && $this->mInterwiki == '') {
+                       $t = $wgContLang->ucfirst( $r );
+               } else {
+                       $t = $r;
+               }
+
+               /**
+                * Can't make a link to a namespace alone...
+                * "empty" local links can only be self-links
+                * with a fragment identifier.
+                */
+               if( $t == '' &&
+                       $this->mInterwiki == '' &&
+                       $this->mNamespace != NS_MAIN ) {
+                       wfProfileOut( $fname );
+                       return false;
+               }
+
+               # Fill fields
+               $this->mDbkeyform = $t;
+               $this->mUrlform = wfUrlencode( $t );
+
+               $this->mTextform = str_replace( '_', ' ', $t );
+
+               wfProfileOut( $fname );
+               return true;
+       }
+
+       /**
+        * Get a Title object associated with the talk page of this article
+        * @return Title the object for the talk page
+        * @access public
+        */
+       function getTalkPage() {
+               return Title::makeTitle( Namespace::getTalk( $this->getNamespace() ), $this->getDBkey() );
+       }
+
+       /**
+        * Get a title object associated with the subject page of this
+        * talk page
+        *
+        * @return Title the object for the subject page
+        * @access public
+        */
+       function getSubjectPage() {
+               return Title::makeTitle( Namespace::getSubject( $this->getNamespace() ), $this->getDBkey() );
+       }
+
+       /**
+        * Get an array of Title objects linking to this Title
+        * Also stores the IDs in the link cache.
+        *
+        * @param string $options may be FOR UPDATE
+        * @return array the Title objects linking here
+        * @access public
+        */
+       function getLinksTo( $options = '' ) {
+               global $wgLinkCache;
+               $id = $this->getArticleID();
+
+               if ( $options ) {
+                       $db =& wfGetDB( DB_MASTER );
+               } else {
+                       $db =& wfGetDB( DB_SLAVE );
+               }
+
+               $res = $db->select( array( 'page', 'pagelinks' ),
+                       array( 'page_namespace', 'page_title', 'page_id' ),
+                       array(
+                               'pl_from=page_id',
+                               'pl_namespace' => $this->getNamespace(),
+                               'pl_title'     => $this->getDbKey() ),
+                       'Title::getLinksTo',
+                       $options );
+
+               $retVal = array();
+               if ( $db->numRows( $res ) ) {
+                       while ( $row = $db->fetchObject( $res ) ) {
+                               if ( $titleObj = Title::makeTitle( $row->page_namespace, $row->page_title ) ) {
+                                       $wgLinkCache->addGoodLinkObj( $row->page_id, $titleObj );
+                                       $retVal[] = $titleObj;
+                               }
+                       }
+               }
+               $db->freeResult( $res );
+               return $retVal;
+       }
+
+       /**
+        * Get an array of Title objects referring to non-existent articles linked from this page
+        *
+        * @param string $options may be FOR UPDATE
+        * @return array the Title objects
+        * @access public
+        */
+       function getBrokenLinksFrom( $options = '' ) {
+               global $wgLinkCache;
+
+               if ( $options ) {
+                       $db =& wfGetDB( DB_MASTER );
+               } else {
+                       $db =& wfGetDB( DB_SLAVE );
+               }
+
+               $res = $db->safeQuery(
+                         "SELECT pl_namespace, pl_title
+                            FROM !
+                       LEFT JOIN !
+                              ON pl_namespace=page_namespace
+                             AND pl_title=page_title
+                           WHERE pl_from=?
+                             AND page_namespace IS NULL
+                                 !",
+                       $db->tableName( 'pagelinks' ),
+                       $db->tableName( 'page' ),
+                       $this->getArticleId(),
+                       $options );
+
+               $retVal = array();
+               if ( $db->numRows( $res ) ) {
+                       while ( $row = $db->fetchObject( $res ) ) {
+                               $retVal[] = Title::makeTitle( $row->pl_namespace, $row->pl_title );
+                       }
+               }
+               $db->freeResult( $res );
+               return $retVal;
+       }
+
+
+       /**
+        * Get a list of URLs to purge from the Squid cache when this
+        * page changes
+        *
+        * @return array the URLs
+        * @access public
+        */
+       function getSquidURLs() {
+               return array(
+                       $this->getInternalURL(),
+                       $this->getInternalURL( 'action=history' )
+               );
+       }
+
+       /**
+        * Move this page without authentication
+        * @param Title &$nt the new page Title
+        * @access public
+        */
+       function moveNoAuth( &$nt ) {
+               return $this->moveTo( $nt, false );
+       }
+
+       /**
+        * Check whether a given move operation would be valid.
+        * Returns true if ok, or a message key string for an error message
+        * if invalid. (Scarrrrry ugly interface this.)
+        * @param Title &$nt the new title
+        * @param bool $auth indicates whether $wgUser's permissions
+        *      should be checked
+        * @return mixed true on success, message name on failure
+        * @access public
+        */
+       function isValidMoveOperation( &$nt, $auth = true, $reason = '' ) {
+               global $wgUser;
+               if( !$this or !$nt ) {
+                       return 'badtitletext';
+               }
+               if( $this->equals( $nt ) ) {
+                       return 'selfmove';
+               }
+               if( !$this->isMovable() || !$nt->isMovable() ) {
+                       return 'immobile_namespace';
+               }
+
+               $fname = 'Title::move';
+               $oldid = $this->getArticleID();
+               $newid = $nt->getArticleID();
+
+               if ( strlen( $nt->getDBkey() ) < 1 ) {
+                       return 'articleexists';
+               }
+               if ( ( '' == $this->getDBkey() ) ||
+                        ( !$oldid ) ||
+                    ( '' == $nt->getDBkey() ) ) {
+                       return 'badarticleerror';
+               }
+
+               if ( $auth && (
+                               !$this->userCanEdit() || !$nt->userCanEdit() ||
+                               !$this->userCanMove() || !$nt->userCanMove() ) ) {
+                       return 'protectedpage';
+               }
+
+               # The move is allowed only if (1) the target doesn't exist, or
+               # (2) the target is a redirect to the source, and has no history
+               # (so we can undo bad moves right after they're done).
+
+               if ( 0 != $newid ) { # Target exists; check for validity
+                       if ( ! $this->isValidMoveTarget( $nt ) ) {
+                               return 'articleexists';
+                       }
+               }
+               return true;
+       }
+
+       /**
+        * Move a title to a new location
+        * @param Title &$nt the new title
+        * @param bool $auth indicates whether $wgUser's permissions
+        *      should be checked
+        * @return mixed true on success, message name on failure
+        * @access public
+        */
+       function moveTo( &$nt, $auth = true, $reason = '' ) {
+               $err = $this->isValidMoveOperation( $nt, $auth, $reason );
+               if( is_string( $err ) ) {
+                       return $err;
+               }
+
+               $pageid = $this->getArticleID();
+               if( $nt->exists() ) {
+                       $this->moveOverExistingRedirect( $nt, $reason );
+                       $pageCountChange = 0;
+               } else { # Target didn't exist, do normal move.
+                       $this->moveToNewTitle( $nt, $newid, $reason );
+                       $pageCountChange = 1;
+               }
+               $redirid = $this->getArticleID();
+
+               # Fixing category links (those without piped 'alternate' names) to be sorted under the new title
+               $dbw =& wfGetDB( DB_MASTER );
+               $categorylinks = $dbw->tableName( 'categorylinks' );
+               $sql = "UPDATE $categorylinks SET cl_sortkey=" . $dbw->addQuotes( $nt->getPrefixedText() ) .
+                       " WHERE cl_from=" . $dbw->addQuotes( $pageid ) .
+                       " AND cl_sortkey=" . $dbw->addQuotes( $this->getPrefixedText() );
+               $dbw->query( $sql, 'SpecialMovepage::doSubmit' );
+
+               # Update watchlists
+
+               $oldnamespace = $this->getNamespace() & ~1;
+               $newnamespace = $nt->getNamespace() & ~1;
+               $oldtitle = $this->getDBkey();
+               $newtitle = $nt->getDBkey();
+
+               if( $oldnamespace != $newnamespace || $oldtitle != $newtitle ) {
+                       WatchedItem::duplicateEntries( $this, $nt );
+               }
+
+               # Update search engine
+               $u = new SearchUpdate( $pageid, $nt->getPrefixedDBkey() );
+               $u->doUpdate();
+               $u = new SearchUpdate( $redirid, $this->getPrefixedDBkey(), '' );
+               $u->doUpdate();
+
+               # Update site_stats
+               if ( $this->getNamespace() == NS_MAIN and $nt->getNamespace() != NS_MAIN ) {
+                       # Moved out of main namespace
+                       # not viewed, edited, removing
+                       $u = new SiteStatsUpdate( 0, 1, -1, $pageCountChange);
+               } elseif ( $this->getNamespace() != NS_MAIN and $nt->getNamespace() == NS_MAIN ) {
+                       # Moved into main namespace
+                       # not viewed, edited, adding
+                       $u = new SiteStatsUpdate( 0, 1, +1, $pageCountChange );
+               } elseif ( $pageCountChange ) {
+                       # Added redirect
+                       $u = new SiteStatsUpdate( 0, 0, 0, 1 );
+               } else{
+                       $u = false;
+               }
+               if ( $u ) {
+                       $u->doUpdate();
+               }
+
+               global $wgUser;
+               wfRunHooks( 'TitleMoveComplete', array( &$this, &$nt, &$wgUser, $pageid, $redirid ) );
+               return true;
+       }
+
+       /**
+        * Move page to a title which is at present a redirect to the
+        * source page
+        *
+        * @param Title &$nt the page to move to, which should currently
+        *      be a redirect
+        * @access private
+        */
+       function moveOverExistingRedirect( &$nt, $reason = '' ) {
+               global $wgUser, $wgLinkCache, $wgUseSquid, $wgMwRedir;
+               $fname = 'Title::moveOverExistingRedirect';
+               $comment = wfMsgForContent( '1movedto2', $this->getPrefixedText(), $nt->getPrefixedText() );
+
+               if ( $reason ) {
+                       $comment .= ": $reason";
+               }
+
+               $now = wfTimestampNow();
+               $rand = wfRandom();
+               $newid = $nt->getArticleID();
+               $oldid = $this->getArticleID();
+               $dbw =& wfGetDB( DB_MASTER );
+               $links = $dbw->tableName( 'links' );
+
+               # Delete the old redirect. We don't save it to history since
+               # by definition if we've got here it's rather uninteresting.
+               # We have to remove it so that the next step doesn't trigger
+               # a conflict on the unique namespace+title index...
+               $dbw->delete( 'page', array( 'page_id' => $newid ), $fname );
+
+               # Save a null revision in the page's history notifying of the move
+               $nullRevision = Revision::newNullRevision( $dbw, $oldid,
+                       wfMsgForContent( '1movedto2', $this->getPrefixedText(), $nt->getPrefixedText() ),
+                       true );
+               $nullRevId = $nullRevision->insertOn( $dbw );
+
+               # Change the name of the target page:
+               $dbw->update( 'page',
+                       /* SET */ array(
+                               'page_touched'   => $dbw->timestamp($now),
+                               'page_namespace' => $nt->getNamespace(),
+                               'page_title'     => $nt->getDBkey(),
+                               'page_latest'    => $nullRevId,
+                       ),
+                       /* WHERE */ array( 'page_id' => $oldid ),
+                       $fname
+               );
+               $wgLinkCache->clearLink( $nt->getPrefixedDBkey() );
+
+               # Recreate the redirect, this time in the other direction.
+               $redirectText = $wgMwRedir->getSynonym( 0 ) . ' [[' . $nt->getPrefixedText() . "]]\n";
+               $redirectArticle = new Article( $this );
+               $newid = $redirectArticle->insertOn( $dbw );
+               $redirectRevision = new Revision( array(
+                       'page'    => $newid,
+                       'comment' => $comment,
+                       'text'    => $redirectText ) );
+               $revid = $redirectRevision->insertOn( $dbw );
+               $redirectArticle->updateRevisionOn( $dbw, $redirectRevision, 0 );
+               $wgLinkCache->clearLink( $this->getPrefixedDBkey() );
+
+               # Log the move
+               $log = new LogPage( 'move' );
+               $log->addEntry( 'move_redir', $this, $reason, array( 1 => $nt->getPrefixedText() ) );
+
+               # Now, we record the link from the redirect to the new title.
+               # It should have no other outgoing links...
+               $dbw->delete( 'pagelinks', array( 'pl_from' => $newid ), $fname );
+               $dbw->insert( 'pagelinks',
+                       array(
+                               'pl_from'      => $newid,
+                               'pl_namespace' => $nt->getNamespace(),
+                               'pl_title'     => $nt->getDbKey() ),
+                       $fname );
+
+               # Purge squid
+               if ( $wgUseSquid ) {
+                       $urls = array_merge( $nt->getSquidURLs(), $this->getSquidURLs() );
+                       $u = new SquidUpdate( $urls );
+                       $u->doUpdate();
+               }
+       }
+
+       /**
+        * Move page to non-existing title.
+        * @param Title &$nt the new Title
+        * @param int &$newid set to be the new article ID
+        * @access private
+        */
+       function moveToNewTitle( &$nt, &$newid, $reason = '' ) {
+               global $wgUser, $wgLinkCache, $wgUseSquid;
+               global $wgMwRedir;
+               $fname = 'MovePageForm::moveToNewTitle';
+               $comment = wfMsgForContent( '1movedto2', $this->getPrefixedText(), $nt->getPrefixedText() );
+               if ( $reason ) {
+                       $comment .= ": $reason";
+               }
+
+               $newid = $nt->getArticleID();
+               $oldid = $this->getArticleID();
+               $dbw =& wfGetDB( DB_MASTER );
+               $now = $dbw->timestamp();
+               wfSeedRandom();
+               $rand = wfRandom();
+
+               # Save a null revision in the page's history notifying of the move
+               $nullRevision = Revision::newNullRevision( $dbw, $oldid,
+                       wfMsgForContent( '1movedto2', $this->getPrefixedText(), $nt->getPrefixedText() ),
+                       true );
+               $nullRevId = $nullRevision->insertOn( $dbw );
+
+               # Rename cur entry
+               $dbw->update( 'page',
+                       /* SET */ array(
+                               'page_touched'   => $now,
+                               'page_namespace' => $nt->getNamespace(),
+                               'page_title'     => $nt->getDBkey(),
+                               'page_latest'    => $nullRevId,
+                       ),
+                       /* WHERE */ array( 'page_id' => $oldid ),
+                       $fname
+               );
+
+               $wgLinkCache->clearLink( $nt->getPrefixedDBkey() );
+
+               # Insert redirect
+               $redirectText = $wgMwRedir->getSynonym( 0 ) . ' [[' . $nt->getPrefixedText() . "]]\n";
+               $redirectArticle = new Article( $this );
+               $newid = $redirectArticle->insertOn( $dbw );
+               $redirectRevision = new Revision( array(
+                       'page'    => $newid,
+                       'comment' => $comment,
+                       'text'    => $redirectText ) );
+               $revid = $redirectRevision->insertOn( $dbw );
+               $redirectArticle->updateRevisionOn( $dbw, $redirectRevision, 0 );
+               $wgLinkCache->clearLink( $this->getPrefixedDBkey() );
+
+               # Log the move
+               $log = new LogPage( 'move' );
+               $log->addEntry( 'move', $this, $reason, array( 1 => $nt->getPrefixedText()) );
+
+               # Purge caches as per article creation
+               Article::onArticleCreate( $nt );
+
+               # Record the just-created redirect's linking to the page
+               $dbw->insert( 'pagelinks',
+                       array(
+                               'pl_from'      => $newid,
+                               'pl_namespace' => $nt->getNamespace(),
+                               'pl_title'     => $nt->getDBkey() ),
+                       $fname );
+
+               # Non-existent target may have had broken links to it; these must
+               # now be touched to update link coloring.
+               $nt->touchLinks();
+
+               # Purge old title from squid
+               # The new title, and links to the new title, are purged in Article::onArticleCreate()
+               $titles = $nt->getLinksTo();
+               if ( $wgUseSquid ) {
+                       $urls = $this->getSquidURLs();
+                       foreach ( $titles as $linkTitle ) {
+                               $urls[] = $linkTitle->getInternalURL();
+                       }
+                       $u = new SquidUpdate( $urls );
+                       $u->doUpdate();
+               }
+       }
+
+       /**
+        * Checks if $this can be moved to a given Title
+        * - Selects for update, so don't call it unless you mean business
+        *
+        * @param Title &$nt the new title to check
+        * @access public
+        */
+       function isValidMoveTarget( $nt ) {
+
+               $fname = 'Title::isValidMoveTarget';
+               $dbw =& wfGetDB( DB_MASTER );
+
+               # Is it a redirect?
+               $id  = $nt->getArticleID();
+               $obj = $dbw->selectRow( array( 'page', 'revision', 'text'),
+                       array( 'page_is_redirect','old_text','old_flags' ),
+                       array( 'page_id' => $id, 'page_latest=rev_id', 'rev_text_id=old_id' ),
+                       $fname, 'FOR UPDATE' );
+
+               if ( !$obj || 0 == $obj->page_is_redirect ) {
+                       # Not a redirect
+                       return false;
+               }
+               $text = Revision::getRevisionText( $obj );
+
+               # Does the redirect point to the source?
+               if ( preg_match( "/\\[\\[\\s*([^\\]\\|]*)]]/", $text, $m ) ) {
+                       $redirTitle = Title::newFromText( $m[1] );
+                       if( !is_object( $redirTitle ) ||
+                               $redirTitle->getPrefixedDBkey() != $this->getPrefixedDBkey() ) {
+                               return false;
+                       }
+               } else {
+                       # Fail safe
+                       return false;
+               }
+
+               # Does the article have a history?
+               $row = $dbw->selectRow( array( 'page', 'revision'),
+                       array( 'rev_id' ),
+                       array( 'page_namespace' => $nt->getNamespace(),
+                               'page_title' => $nt->getDBkey(),
+                               'page_id=rev_page AND page_latest != rev_id'
+                       ), $fname, 'FOR UPDATE'
+               );
+
+               # Return true if there was no history
+               return $row === false;
+       }
+
+       /**
+        * Create a redirect; fails if the title already exists; does
+        * not notify RC
+        *
+        * @param Title $dest the destination of the redirect
+        * @param string $comment the comment string describing the move
+        * @return bool true on success
+        * @access public
+        */
+       function createRedirect( $dest, $comment ) {
+               global $wgUser;
+               if ( $this->getArticleID() ) {
+                       return false;
+               }
+
+               $fname = 'Title::createRedirect';
+               $dbw =& wfGetDB( DB_MASTER );
+
+               $article = new Article( $this );
+               $newid = $article->insertOn( $dbw );
+               $revision = new Revision( array(
+                       'page'      => $newid,
+                       'comment'   => $comment,
+                       'text'      => "#REDIRECT [[" . $dest->getPrefixedText() . "]]\n",
+                       ) );
+               $revisionId = $revision->insertOn( $dbw );
+               $article->updateRevisionOn( $dbw, $revision, 0 );
+
+               # Link table
+               $dbw->insert( 'pagelinks',
+                       array(
+                               'pl_from'      => $newid,
+                               'pl_namespace' => $dest->getNamespace(),
+                               'pl_title'     => $dest->getDbKey()
+                       ), $fname
+               );
+
+               Article::onArticleCreate( $this );
+               return true;
+       }
+
+       /**
+        * Get categories to which this Title belongs and return an array of
+        * categories' names.
+        *
+        * @return array an array of parents in the form:
+        *      $parent => $currentarticle
+        * @access public
+        */
+       function getParentCategories() {
+               global $wgContLang,$wgUser;
+
+               $titlekey = $this->getArticleId();
+               $sk =& $wgUser->getSkin();
+               $parents = array();
+               $dbr =& wfGetDB( DB_SLAVE );
+               $categorylinks = $dbr->tableName( 'categorylinks' );
+
+               # NEW SQL
+               $sql = "SELECT * FROM $categorylinks"
+                    ." WHERE cl_from='$titlekey'"
+                        ." AND cl_from <> '0'"
+                        ." ORDER BY cl_sortkey";
+
+               $res = $dbr->query ( $sql ) ;
+
+               if($dbr->numRows($res) > 0) {
+                       while ( $x = $dbr->fetchObject ( $res ) )
+                               //$data[] = Title::newFromText($wgContLang->getNSText ( NS_CATEGORY ).':'.$x->cl_to);
+                               $data[$wgContLang->getNSText ( NS_CATEGORY ).':'.$x->cl_to] = $this->getFullText();
+                       $dbr->freeResult ( $res ) ;
+               } else {
+                       $data = '';
+               }
+               return $data;
+       }
+
+       /**
+        * Get a tree of parent categories
+        * @param array $children an array with the children in the keys, to check for circular refs
+        * @return array
+        * @access public
+        */
+       function getParentCategoryTree( $children = array() ) {
+               $parents = $this->getParentCategories();
+
+               if($parents != '') {
+                       foreach($parents as $parent => $current)
+                       {
+                               if ( array_key_exists( $parent, $children ) ) {
+                                       # Circular reference
+                                       $stack[$parent] = array();
+                               } else {
+                                       $nt = Title::newFromText($parent);
+                                       $stack[$parent] = $nt->getParentCategoryTree( $children + array($parent => 1) );
+                               }
+                       }
+                       return $stack;
+               } else {
+                       return array();
+               }
+       }
+
+
+       /**
+        * Get an associative array for selecting this title from
+        * the "cur" table
+        *
+        * @return array
+        * @access public
+        */
+       function curCond() {
+               wfDebugDieBacktrace( 'curCond called' );
+               return array( 'cur_namespace' => $this->mNamespace, 'cur_title' => $this->mDbkeyform );
+       }
+
+       /**
+        * Get an associative array for selecting this title from the
+        * "old" table
+        *
+        * @return array
+        * @access public
+        */
+       function oldCond() {
+               wfDebugDieBacktrace( 'oldCond called' );
+               return array( 'old_namespace' => $this->mNamespace, 'old_title' => $this->mDbkeyform );
+       }
+
+       /**
+        * Get the revision ID of the previous revision
+        *
+        * @param integer $revision  Revision ID. Get the revision that was before this one.
+        * @return interger $oldrevision|false
+        */
+       function getPreviousRevisionID( $revision ) {
+               $dbr =& wfGetDB( DB_SLAVE );
+               return $dbr->selectField( 'revision', 'rev_id',
+                       'rev_page=' . IntVal( $this->getArticleId() ) .
+                       ' AND rev_id<' . IntVal( $revision ) . ' ORDER BY rev_id DESC' );
+       }
+
+       /**
+        * Get the revision ID of the next revision
+        *
+        * @param integer $revision  Revision ID. Get the revision that was after this one.
+        * @return interger $oldrevision|false
+        */
+       function getNextRevisionID( $revision ) {
+               $dbr =& wfGetDB( DB_SLAVE );
+               return $dbr->selectField( 'revision', 'rev_id',
+                       'rev_page=' . IntVal( $this->getArticleId() ) .
+                       ' AND rev_id>' . IntVal( $revision ) . ' ORDER BY rev_id' );
+       }
+
+       /**
+        * Compare with another title.
+        *
+        * @param Title $title
+        * @return bool
+        */
+       function equals( $title ) {
+               return $this->getInterwiki() == $title->getInterwiki()
+                       && $this->getNamespace() == $title->getNamespace()
+                       && $this->getDbkey() == $title->getDbkey();
+       }
+
+       /**
+        * Check if page exists
+        * @return bool
+        */
+       function exists() {
+               return $this->getArticleId() != 0;
+       }
+
+       /**
+        * Should a link should be displayed as a known link, just based on its title?
+        *
+        * Currently, a self-link with a fragment, special pages and image pages are in
+        * this category. Special pages never exist in the database. Some images do not
+        * have description pages in the database, but the description page contains
+        * useful history information that the user may want to link to.
+        */
+       function isAlwaysKnown() {
+               return  $this->isExternal() || ( 0 == $this->mNamespace && "" == $this->mDbkeyform )
+                 || NS_SPECIAL == $this->mNamespace || NS_IMAGE == $this->mNamespace;
+       }
+
+       /**
+        * Update page_touched timestamps on pages linking to this title.
+        * In principal, this could be backgrounded and could also do squid
+        * purging.
+        */
+       function touchLinks() {
+               $fname = 'Title::touchLinks';
+
+               $dbw =& wfGetDB( DB_MASTER );
+
+               $res = $dbw->select( 'pagelinks',
+                       array( 'pl_from' ),
+                       array(
+                               'pl_namespace' => $this->getNamespace(),
+                               'pl_title'     => $this->getDbKey() ),
+                       $fname );
+               if ( 0 == $dbw->numRows( $res ) ) {
+                       return;
+               }
+
+               $arr = array();
+               $toucharr = array();
+               while( $row = $dbw->fetchObject( $res ) ) {
+                       $toucharr[] = $row->pl_from;
+               }
+
+               $dbw->update( 'page', /* SET */ array( 'page_touched' => $dbw->timestamp() ),
+                                                       /* WHERE */ array( 'page_id' => $toucharr ),$fname);
+       }
+
+       function trackbackURL() {
+               global $wgTitle, $wgScriptPath, $wgServer;
+
+               return "$wgServer$wgScriptPath/trackback.php?article="
+                       . htmlspecialchars(urlencode($wgTitle->getPrefixedDBkey()));
+       }
+
+       function trackbackRDF() {
+               $url = htmlspecialchars($this->getFullURL());
+               $title = htmlspecialchars($this->getText());
+               $tburl = $this->trackbackURL();
+
+               return "
+<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"
+         xmlns:dc=\"http://purl.org/dc/elements/1.1/\"
+         xmlns:trackback=\"http://madskills.com/public/xml/rss/module/trackback/\">
+<rdf:Description
+   rdf:about=\"$url\"
+   dc:identifier=\"$url\"
+   dc:title=\"$title\"
+   trackback:ping=\"$tburl\" />
+</rdf:RDF>";
+       }
+}
+?>
diff --git a/includes/UpdateClasses.php b/includes/UpdateClasses.php
new file mode 100644 (file)
index 0000000..e6da731
--- /dev/null
@@ -0,0 +1,17 @@
+<?php
+/**
+ * See deferred.txt
+ *
+ * @package MediaWiki
+ */
+
+/**
+ *
+ */
+
+require_once( 'SiteStatsUpdate.php' );
+require_once( 'LinksUpdate.php' );
+require_once( 'SearchUpdate.php' );
+require_once( 'SquidUpdate.php' );
+
+?>
\ No newline at end of file
diff --git a/includes/User.php b/includes/User.php
new file mode 100644 (file)
index 0000000..95ee6bd
--- /dev/null
@@ -0,0 +1,1826 @@
+<?php
+/**
+ * See user.txt
+ *
+ * @package MediaWiki
+ */
+
+/**
+ *
+ */
+require_once( 'WatchedItem.php' );
+
+# Number of characters in user_token field
+define( 'USER_TOKEN_LENGTH', 32 );
+
+# Serialized record version
+define( 'MW_USER_VERSION', 2 );
+
+/**
+ *
+ * @package MediaWiki
+ */
+class User {
+       /**#@+
+        * @access private
+        */
+       var $mId, $mName, $mPassword, $mEmail, $mNewtalk;
+       var $mEmailAuthenticated;
+       var $mRights, $mOptions;
+       var $mDataLoaded, $mNewpassword;
+       var $mSkin;
+       var $mBlockedby, $mBlockreason;
+       var $mTouched;
+       var $mToken;
+       var $mRealName;
+       var $mHash;
+       var $mGroups;
+       var $mVersion; // serialized version
+
+       /** Construct using User:loadDefaults() */
+       function User() {
+               $this->loadDefaults();
+               $this->mVersion = MW_USER_VERSION;
+       }
+
+       /**
+        * Static factory method
+        * @param string $name Username, validated by Title:newFromText()
+        * @return User
+        * @static
+        */
+       function newFromName( $name ) {
+               # Force usernames to capital
+               global $wgContLang;
+               $name = $wgContLang->ucfirst( $name );
+
+               # Clean up name according to title rules
+               $t = Title::newFromText( $name );
+               if( is_null( $t ) ) {
+                       return null;
+               }
+
+               # Reject various classes of invalid names
+               $canonicalName = $t->getText();
+               global $wgAuth;
+               $canonicalName = $wgAuth->getCanonicalName( $t->getText() );
+
+               if( !User::isValidUserName( $canonicalName ) ) {
+                       return null;
+               }
+
+               $u = new User();
+               $u->setName( $canonicalName );
+               $u->setId( $u->idFromName( $canonicalName ) );
+               return $u;
+       }
+
+       /**
+        * Factory method to fetch whichever use has a given email confirmation code.
+        * This code is generated when an account is created or its e-mail address
+        * has changed.
+        *
+        * If the code is invalid or has expired, returns NULL.
+        *
+        * @param string $code
+        * @return User
+        * @static
+        */
+       function newFromConfirmationCode( $code ) {
+               $dbr =& wfGetDB( DB_SLAVE );
+               $name = $dbr->selectField( 'user', 'user_name', array(
+                       'user_email_token' => md5( $code ),
+                       'user_email_token_expires > ' . $dbr->addQuotes( $dbr->timestamp() ),
+                       ) );
+               if( is_string( $name ) ) {
+                       return User::newFromName( $name );
+               } else {
+                       return null;
+               }
+       }
+
+       /**
+        * Serialze sleep function, for better cache efficiency and avoidance of
+        * silly "incomplete type" errors when skins are cached
+        */
+       function __sleep() {
+               return array( 'mId', 'mName', 'mPassword', 'mEmail', 'mNewtalk',
+                       'mEmailAuthenticated', 'mRights', 'mOptions', 'mDataLoaded',
+                       'mNewpassword', 'mBlockedby', 'mBlockreason', 'mTouched',
+                       'mToken', 'mRealName', 'mHash', 'mGroups' );
+       }
+
+       /**
+        * Get username given an id.
+        * @param integer $id Database user id
+        * @return string Nickname of a user
+        * @static
+        */
+       function whoIs( $id )   {
+               $dbr =& wfGetDB( DB_SLAVE );
+               return $dbr->selectField( 'user', 'user_name', array( 'user_id' => $id ) );
+       }
+
+       /**
+        * Get real username given an id.
+        * @param integer $id Database user id
+        * @return string Realname of a user
+        * @static
+        */
+       function whoIsReal( $id )       {
+               $dbr =& wfGetDB( DB_SLAVE );
+               return $dbr->selectField( 'user', 'user_real_name', array( 'user_id' => $id ) );
+       }
+
+       /**
+        * Get database id given a user name
+        * @param string $name Nickname of a user
+        * @return integer|null Database user id (null: if non existent
+        * @static
+        */
+       function idFromName( $name ) {
+               $fname = "User::idFromName";
+
+               $nt = Title::newFromText( $name );
+               if( is_null( $nt ) ) {
+                       # Illegal name
+                       return null;
+               }
+               $dbr =& wfGetDB( DB_SLAVE );
+               $s = $dbr->selectRow( 'user', array( 'user_id' ), array( 'user_name' => $nt->getText() ), $fname );
+
+               if ( $s === false ) {
+                       return 0;
+               } else {
+                       return $s->user_id;
+               }
+       }
+
+       /**
+        * does the string match an anonymous IPv4 address?
+        *
+        * @static
+        * @param string $name Nickname of a user
+        * @return bool
+        */
+       function isIP( $name ) {
+               return preg_match("/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/",$name);
+               /*return preg_match("/^
+                       (?:[01]?\d{1,2}|2(:?[0-4]\d|5[0-5]))\.
+                       (?:[01]?\d{1,2}|2(:?[0-4]\d|5[0-5]))\.
+                       (?:[01]?\d{1,2}|2(:?[0-4]\d|5[0-5]))\.
+                       (?:[01]?\d{1,2}|2(:?[0-4]\d|5[0-5]))
+               $/x", $name);*/
+       }
+
+       /**
+        * Is the input a valid username?
+        *
+        * Checks if the input is a valid username, we don't want an empty string,
+        * an IP address, anything that containins slashes (would mess up subpages),
+        * is longer than the maximum allowed username size or doesn't begin with
+        * a capital letter.
+        *
+        * @param string $name
+        * @return bool
+        * @static
+        */
+       function isValidUserName( $name ) {
+               global $wgContLang, $wgMaxNameChars;
+
+               if ( $name == ''
+               || User::isIP( $name )
+               || strpos( $name, '/' ) !== false
+               || strlen( $name ) > $wgMaxNameChars
+               || $name != $wgContLang->ucfirst( $name ) )
+                       return false;
+               else
+                       return true;
+       }
+
+       /**
+        * Is the input a valid password?
+        *
+        * @param string $password
+        * @return bool
+        * @static
+        */
+       function isValidPassword( $password ) {
+               global $wgMinimalPasswordLength;
+               return strlen( $password ) >= $wgMinimalPasswordLength;
+       }
+
+       /**
+        * does the string match roughly an email address ?
+        *
+        * @todo Check for RFC 2822 compilance
+        * @bug 959
+        *
+        * @param string $addr email address
+        * @static
+        * @return bool
+        */
+       function isValidEmailAddr ( $addr ) {
+               # There used to be a regular expression here, it got removed because it
+               # rejected valid addresses.
+               return ( trim( $addr ) != '' ) &&
+                       (false !== strpos( $addr, '@' ) );
+       }
+
+       /**
+        * Count the number of edits of a user
+        *
+        * @param int $uid The user ID to check
+        * @return int
+        */
+       function edits( $uid ) {
+               $fname = 'User::editCount';
+
+               $dbr =& wfGetDB( DB_SLAVE );
+               return $dbr->selectField(
+                       'revision', 'count(*)',
+                       array( 'rev_user' => $uid ),
+                       $fname
+               );
+       }
+
+       /**
+        * probably return a random password
+        * @return string probably a random password
+        * @static
+        * @todo Check what is doing really [AV]
+        */
+       function randomPassword() {
+               global $wgMinimalPasswordLength;
+               $pwchars = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz';
+               $l = strlen( $pwchars ) - 1;
+
+               $pwlength = max( 7, $wgMinimalPasswordLength );
+               $digit = mt_rand(0, $pwlength - 1);
+               $np = '';
+               for ( $i = 0; $i < $pwlength; $i++ ) {
+                       $np .= $i == $digit ? chr( mt_rand(48, 57) ) : $pwchars{ mt_rand(0, $l)};
+               }
+               return $np;
+       }
+
+       /**
+        * Set properties to default
+        * Used at construction. It will load per language default settings only
+        * if we have an available language object.
+        */
+       function loadDefaults() {
+               static $n=0;
+               $n++;
+               $fname = 'User::loadDefaults' . $n;
+               wfProfileIn( $fname );
+
+               global $wgContLang, $wgIP, $wgCookiePrefix;
+               global $wgNamespacesToBeSearchedDefault;
+
+               $this->mId = 0;
+               $this->mNewtalk = -1;
+               $this->mName = $wgIP;
+               $this->mRealName = $this->mEmail = '';
+               $this->mEmailAuthenticated = null;
+               $this->mPassword = $this->mNewpassword = '';
+               $this->mRights = array();
+               $this->mGroups = array();
+               $this->mOptions = User::getDefaultOptions();
+
+               foreach( $wgNamespacesToBeSearchedDefault as $nsnum => $val ) {
+                       $this->mOptions['searchNs'.$nsnum] = $val;
+               }
+               unset( $this->mSkin );
+               $this->mDataLoaded = false;
+               $this->mBlockedby = -1; # Unset
+               $this->setToken(); # Random
+               $this->mHash = false;
+
+               if ( isset( $_COOKIE[$wgCookiePrefix.'LoggedOut'] ) ) {
+                       $this->mTouched = wfTimestamp( TS_MW, $_COOKIE[$wgCookiePrefix.'LoggedOut'] );
+               }
+               else {
+                       $this->mTouched = '0'; # Allow any pages to be cached
+               }
+
+               wfProfileOut( $fname );
+       }
+
+       /**
+        * Combine the language default options with any site-specific options
+        * and add the default language variants.
+        *
+        * @return array
+        * @static
+        * @access private
+        */
+       function getDefaultOptions() {
+               /**
+                * Site defaults will override the global/language defaults
+                */
+               global $wgContLang, $wgDefaultUserOptions;
+               $defOpt = $wgDefaultUserOptions + $wgContLang->getDefaultUserOptions();
+
+               /**
+                * default language setting
+                */
+               $variant = $wgContLang->getPreferredVariant();
+               $defOpt['variant'] = $variant;
+               $defOpt['language'] = $variant;
+
+               return $defOpt;
+       }
+
+       /**
+        * Get a given default option value.
+        *
+        * @param string $opt
+        * @return string
+        * @static
+        * @access public
+        */
+       function getDefaultOption( $opt ) {
+               $defOpts = User::getDefaultOptions();
+               if( isset( $defOpts[$opt] ) ) {
+                       return $defOpts[$opt];
+               } else {
+                       return '';
+               }
+       }
+
+       /**
+        * Get blocking information
+        * @access private
+        * @param bool $bFromSlave Specify whether to check slave or master. To improve performance,
+        *  non-critical checks are done against slaves. Check when actually saving should be done against
+        *  master.
+        *
+        * Note that even if $bFromSlave is false, the check is done first against slave, then master.
+        * The logic is that if blocked on slave, we'll assume it's either blocked on master or
+        * just slightly outta sync and soon corrected - safer to block slightly more that less.
+        * And it's cheaper to check slave first, then master if needed, than master always.
+        */
+       function getBlockedStatus( $bFromSlave = true ) {
+               global $wgIP, $wgBlockCache, $wgProxyList, $wgEnableSorbs, $wgProxyWhitelist;
+
+               if ( -1 != $this->mBlockedby ) { return; }
+
+               $this->mBlockedby = 0;
+
+               # User blocking
+               if ( $this->mId ) {
+                       $block = new Block();
+                       $block->forUpdate( $bFromSlave );
+                       if ( $block->load( $wgIP , $this->mId ) ) {
+                               $this->mBlockedby = $block->mBy;
+                               $this->mBlockreason = $block->mReason;
+                               $this->spreadBlock();
+                       }
+               }
+
+               # IP/range blocking
+               if ( !$this->mBlockedby ) {
+                       # Check first against slave, and optionally from master.
+                       $block = $wgBlockCache->get( $wgIP, true );
+                       if ( !$block && !$bFromSlave )
+                               {
+                               # Not blocked: check against master, to make sure.
+                               $wgBlockCache->clearLocal( );
+                               $block = $wgBlockCache->get( $wgIP, false );
+                               }
+                       if ( $block !== false ) {
+                               $this->mBlockedby = $block->mBy;
+                               $this->mBlockreason = $block->mReason;
+                       }
+               }
+
+               # Proxy blocking
+               if ( !$this->isSysop() && !in_array( $wgIP, $wgProxyWhitelist ) ) {
+
+                       # Local list
+                       if ( array_key_exists( $wgIP, $wgProxyList ) ) {
+                               $this->mBlockedby = wfMsg( 'proxyblocker' );
+                               $this->mBlockreason = wfMsg( 'proxyblockreason' );
+                       }
+
+                       # DNSBL
+                       if ( !$this->mBlockedby && $wgEnableSorbs && !$this->getID() ) {
+                               if ( $this->inSorbsBlacklist( $wgIP ) ) {
+                                       $this->mBlockedby = wfMsg( 'sorbs' );
+                                       $this->mBlockreason = wfMsg( 'sorbsreason' );
+                               }
+                       }
+               }
+       }
+
+       function inSorbsBlacklist( $ip ) {
+               global $wgEnableSorbs;
+               return $wgEnableSorbs &&
+                       $this->inDnsBlacklist( $ip, 'http.dnsbl.sorbs.net.' );
+       }
+
+       function inOpmBlacklist( $ip ) {
+               global $wgEnableOpm;
+               return $wgEnableOpm &&
+                       $this->inDnsBlacklist( $ip, 'opm.blitzed.org.' );
+       }
+
+       function inDnsBlacklist( $ip, $base ) {
+               $fname = 'User::inDnsBlacklist';
+               wfProfileIn( $fname );
+
+               $found = false;
+               $host = '';
+
+               if ( preg_match( '/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/', $ip, $m ) ) {
+                       # Make hostname
+                       for ( $i=4; $i>=1; $i-- ) {
+                               $host .= $m[$i] . '.';
+                       }
+                       $host .= $base;
+
+                       # Send query
+                       $ipList = gethostbynamel( $host );
+
+                       if ( $ipList ) {
+                               wfDebug( "Hostname $host is {$ipList[0]}, it's a proxy says $base!\n" );
+                               $found = true;
+                       } else {
+                               wfDebug( "Requested $host, not found in $base.\n" );
+                       }
+               }
+
+               wfProfileOut( $fname );
+               return $found;
+       }
+
+       /**
+        * Primitive rate limits: enforce maximum actions per time period
+        * to put a brake on flooding.
+        *
+        * Note: when using a shared cache like memcached, IP-address
+        * last-hit counters will be shared across wikis.
+        *
+        * @return bool true if a rate limiter was tripped
+        * @access public
+        */
+       function pingLimiter( $action='edit' ) {
+               global $wgRateLimits;
+               if( !isset( $wgRateLimits[$action] ) ) {
+                       return false;
+               }
+               if( $this->isAllowed( 'delete' ) ) {
+                       // goddam cabal
+                       return false;
+               }
+
+               global $wgMemc, $wgIP, $wgDBname, $wgRateLimitLog;
+               $fname = 'User::pingLimiter';
+               $limits = $wgRateLimits[$action];
+               $keys = array();
+               $id = $this->getId();
+
+               if( isset( $limits['anon'] ) && $id == 0 ) {
+                       $keys["$wgDBname:limiter:$action:anon"] = $limits['anon'];
+               }
+
+               if( isset( $limits['user'] ) && $id != 0 ) {
+                       $keys["$wgDBname:limiter:$action:user:$id"] = $limits['user'];
+               }
+               if( $this->isNewbie() ) {
+                       if( isset( $limits['newbie'] ) && $id != 0 ) {
+                               $keys["$wgDBname:limiter:$action:user:$id"] = $limits['newbie'];
+                       }
+                       if( isset( $limits['ip'] ) ) {
+                               $keys["mediawiki:limiter:$action:ip:$wgIP"] = $limits['ip'];
+                       }
+                       if( isset( $limits['subnet'] ) && preg_match( '/^(\d+\.\d+\.\d+)\.\d+$/', $wgIP, $matches ) ) {
+                               $subnet = $matches[1];
+                               $keys["mediawiki:limiter:$action:subnet:$subnet"] = $limits['subnet'];
+                       }
+               }
+
+               $triggered = false;
+               foreach( $keys as $key => $limit ) {
+                       list( $max, $period ) = $limit;
+                       $summary = "(limit $max in {$period}s)";
+                       $count = $wgMemc->get( $key );
+                       if( $count ) {
+                               if( $count > $max ) {
+                                       wfDebug( "$fname: tripped! $key at $count $summary\n" );
+                                       if( $wgRateLimitLog ) {
+                                               @error_log( wfTimestamp( TS_MW ) . ' ' . $wgDBname . ': ' . $this->getName() . " tripped $key at $count $summary\n", 3, $wgRateLimitLog );
+                                       }
+                                       $triggered = true;
+                               } else {
+                                       wfDebug( "$fname: ok. $key at $count $summary\n" );
+                               }
+                       } else {
+                               wfDebug( "$fname: adding record for $key $summary\n" );
+                               $wgMemc->add( $key, 1, IntVal( $period ) );
+                       }
+                       $wgMemc->incr( $key );
+               }
+
+               return $triggered;
+       }
+
+       /**
+        * Check if user is blocked
+        * @return bool True if blocked, false otherwise
+        */
+       function isBlocked( $bFromSlave = true ) { // hacked from false due to horrible probs on site
+               $this->getBlockedStatus( $bFromSlave );
+               return $this->mBlockedby !== 0;
+       }
+
+       /**
+        * Check if user is blocked from editing a particular article
+        */
+       function isBlockedFrom( $title, $bFromSlave = false ) {
+               global $wgBlockAllowsUTEdit;
+               if ( $wgBlockAllowsUTEdit && $title->getText() === $this->getName() &&
+                 $title->getNamespace() == NS_USER_TALK )
+               {
+                       return false;
+               } else {
+                       return $this->isBlocked( $bFromSlave );
+               }
+       }
+
+       /**
+        * Get name of blocker
+        * @return string name of blocker
+        */
+       function blockedBy() {
+               $this->getBlockedStatus();
+               return $this->mBlockedby;
+       }
+
+       /**
+        * Get blocking reason
+        * @return string Blocking reason
+        */
+       function blockedFor() {
+               $this->getBlockedStatus();
+               return $this->mBlockreason;
+       }
+
+       /**
+        * Initialise php session
+        */
+       function SetupSession() {
+               global $wgSessionsInMemcached, $wgCookiePath, $wgCookieDomain;
+               if( $wgSessionsInMemcached ) {
+                       require_once( 'MemcachedSessions.php' );
+               } elseif( 'files' != ini_get( 'session.save_handler' ) ) {
+                       # If it's left on 'user' or another setting from another
+                       # application, it will end up failing. Try to recover.
+                       ini_set ( 'session.save_handler', 'files' );
+               }
+               session_set_cookie_params( 0, $wgCookiePath, $wgCookieDomain );
+               session_cache_limiter( 'private, must-revalidate' );
+               @session_start();
+       }
+
+       /**
+        * Read datas from session
+        * @static
+        */
+       function loadFromSession() {
+               global $wgMemc, $wgDBname, $wgCookiePrefix;
+
+               if ( isset( $_SESSION['wsUserID'] ) ) {
+                       if ( 0 != $_SESSION['wsUserID'] ) {
+                               $sId = $_SESSION['wsUserID'];
+                       } else {
+                               return new User();
+                       }
+               } else if ( isset( $_COOKIE["{$wgCookiePrefix}UserID"] ) ) {
+                       $sId = IntVal( $_COOKIE["{$wgCookiePrefix}UserID"] );
+                       $_SESSION['wsUserID'] = $sId;
+               } else {
+                       return new User();
+               }
+               if ( isset( $_SESSION['wsUserName'] ) ) {
+                       $sName = $_SESSION['wsUserName'];
+               } else if ( isset( $_COOKIE["{$wgCookiePrefix}UserName"] ) ) {
+                       $sName = $_COOKIE["{$wgCookiePrefix}UserName"];
+                       $_SESSION['wsUserName'] = $sName;
+               } else {
+                       return new User();
+               }
+
+               $passwordCorrect = FALSE;
+               $user = $wgMemc->get( $key = "$wgDBname:user:id:$sId" );
+               if( !is_object( $user ) || $user->mVersion < MW_USER_VERSION ) {
+                       # Expire old serialized objects; they may be corrupt.
+                       $user = false;
+               }
+               if($makenew = !$user) {
+                       wfDebug( "User::loadFromSession() unable to load from memcached\n" );
+                       $user = new User();
+                       $user->mId = $sId;
+                       $user->loadFromDatabase();
+               } else {
+                       wfDebug( "User::loadFromSession() got from cache!\n" );
+               }
+
+               if ( isset( $_SESSION['wsToken'] ) ) {
+                       $passwordCorrect = $_SESSION['wsToken'] == $user->mToken;
+               } else if ( isset( $_COOKIE["{$wgCookiePrefix}Token"] ) ) {
+                       $passwordCorrect = $user->mToken == $_COOKIE["{$wgCookiePrefix}Token"];
+               } else {
+                       return new User(); # Can't log in from session
+               }
+
+               if ( ( $sName == $user->mName ) && $passwordCorrect ) {
+                       if($makenew) {
+                               if($wgMemc->set( $key, $user ))
+                                       wfDebug( "User::loadFromSession() successfully saved user\n" );
+                               else
+                                       wfDebug( "User::loadFromSession() unable to save to memcached\n" );
+                       }
+                       return $user;
+               }
+               return new User(); # Can't log in from session
+       }
+
+       /**
+        * Load a user from the database
+        */
+       function loadFromDatabase() {
+               global $wgCommandLineMode;
+               $fname = "User::loadFromDatabase";
+
+               # Counter-intuitive, breaks various things, use User::setLoaded() if you want to suppress
+               # loading in a command line script, don't assume all command line scripts need it like this
+               #if ( $this->mDataLoaded || $wgCommandLineMode ) {
+               if ( $this->mDataLoaded ) {
+                       return;
+               }
+
+               # Paranoia
+               $this->mId = IntVal( $this->mId );
+
+               /** Anonymous user */
+               if( !$this->mId ) {
+                       /** Get rights */
+                       $this->mRights = $this->getGroupPermissions( array( '*' ) );
+                       $this->mDataLoaded = true;
+                       return;
+               } # the following stuff is for non-anonymous users only
+
+               $dbr =& wfGetDB( DB_SLAVE );
+               $s = $dbr->selectRow( 'user', array( 'user_name','user_password','user_newpassword','user_email',
+                 'user_email_authenticated',
+                 'user_real_name','user_options','user_touched', 'user_token' ),
+                 array( 'user_id' => $this->mId ), $fname );
+
+               if ( $s !== false ) {
+                       $this->mName = $s->user_name;
+                       $this->mEmail = $s->user_email;
+                       $this->mEmailAuthenticated = wfTimestampOrNull( TS_MW, $s->user_email_authenticated );
+                       $this->mRealName = $s->user_real_name;
+                       $this->mPassword = $s->user_password;
+                       $this->mNewpassword = $s->user_newpassword;
+                       $this->decodeOptions( $s->user_options );
+                       $this->mTouched = wfTimestamp(TS_MW,$s->user_touched);
+                       $this->mToken = $s->user_token;
+
+                       $res = $dbr->select( 'user_groups',
+                               array( 'ug_group' ),
+                               array( 'ug_user' => $this->mId ),
+                               $fname );
+                       $this->mGroups = array();
+                       while( $row = $dbr->fetchObject( $res ) ) {
+                               $this->mGroups[] = $row->ug_group;
+                       }
+                       $effectiveGroups = array_merge( array( '*', 'user' ), $this->mGroups );
+                       $this->mRights = $this->getGroupPermissions( $effectiveGroups );
+               }
+
+               $this->mDataLoaded = true;
+       }
+
+       function getID() { return $this->mId; }
+       function setID( $v ) {
+               $this->mId = $v;
+               $this->mDataLoaded = false;
+       }
+
+       function getName() {
+               $this->loadFromDatabase();
+               return $this->mName;
+       }
+
+       function setName( $str ) {
+               $this->loadFromDatabase();
+               $this->mName = $str;
+       }
+
+
+       /**
+        * Return the title dbkey form of the name, for eg user pages.
+        * @return string
+        * @access public
+        */
+       function getTitleKey() {
+               return str_replace( ' ', '_', $this->getName() );
+       }
+
+       function getNewtalk() {
+               global $wgUseEnotif;
+               $fname = 'User::getNewtalk';
+               $this->loadFromDatabase();
+
+               # Load the newtalk status if it is unloaded (mNewtalk=-1)
+               if( $this->mNewtalk == -1 ) {
+                       $this->mNewtalk = 0; # reset talk page status
+
+                       # Check memcached separately for anons, who have no
+                       # entire User object stored in there.
+                       if( !$this->mId ) {
+                               global $wgDBname, $wgMemc;
+                               $key = "$wgDBname:newtalk:ip:{$this->mName}";
+                               $newtalk = $wgMemc->get( $key );
+                               if( is_integer( $newtalk ) ) {
+                                       $this->mNewtalk = $newtalk ? 1 : 0;
+                                       return (bool)$this->mNewtalk;
+                               }
+                       }
+
+                       $dbr =& wfGetDB( DB_SLAVE );
+                       if ( $wgUseEnotif ) {
+                               $res = $dbr->select( 'watchlist',
+                                       array( 'wl_user' ),
+                                       array( 'wl_title'     => $this->getTitleKey(),
+                                                  'wl_namespace' => NS_USER_TALK,
+                                                  'wl_user'      => $this->mId,
+                                                  'wl_notificationtimestamp != 0' ),
+                                       'User::getNewtalk' );
+                               if( $dbr->numRows($res) > 0 ) {
+                                       $this->mNewtalk = 1;
+                               }
+                               $dbr->freeResult( $res );
+                       } elseif ( $this->mId ) {
+                               $res = $dbr->select( 'user_newtalk', 1, array( 'user_id' => $this->mId ), $fname );
+
+                               if ( $dbr->numRows($res)>0 ) {
+                                       $this->mNewtalk= 1;
+                               }
+                               $dbr->freeResult( $res );
+                       } else {
+                               $res = $dbr->select( 'user_newtalk', 1, array( 'user_ip' => $this->mName ), $fname );
+                               $this->mNewtalk = $dbr->numRows( $res ) > 0 ? 1 : 0;
+                               $dbr->freeResult( $res );
+                       }
+
+                       if( !$this->mId ) {
+                               $wgMemc->set( $key, $this->mNewtalk, time() ); // + 1800 );
+                       }
+               }
+
+               return ( 0 != $this->mNewtalk );
+       }
+
+       /**
+        * Return the talk page(s) this user has new messages on.
+        */
+       function getNewMessageLinks() {
+       global  $wgDBname;
+               $talks = array();
+               if (!wfRunHooks('UserRetrieveNewTalks', array(&$this, &$talks)))
+                       return $talks;
+
+               if (!$this->getNewtalk())
+                       return array();
+               $up = $this->getUserPage();
+               $utp = $up->getTalkPage();
+               return array(array("wiki" => $wgDBname, "link" => $utp->getLocalURL()));
+       }
+
+       function setNewtalk( $val ) {
+               $this->loadFromDatabase();
+               $this->mNewtalk = $val;
+               $this->invalidateCache();
+       }
+
+       function invalidateCache() {
+               global $wgClockSkewFudge;
+               $this->loadFromDatabase();
+               $this->mTouched = wfTimestamp(TS_MW, time() + $wgClockSkewFudge );
+               # Don't forget to save the options after this or
+               # it won't take effect!
+       }
+
+       function validateCache( $timestamp ) {
+               $this->loadFromDatabase();
+               return ($timestamp >= $this->mTouched);
+       }
+
+       /**
+        * Encrypt a password.
+        * It can eventuall salt a password @see User::addSalt()
+        * @param string $p clear Password.
+        * @return string Encrypted password.
+        */
+       function encryptPassword( $p ) {
+               return wfEncryptPassword( $this->mId, $p );
+       }
+
+       # Set the password and reset the random token
+       function setPassword( $str ) {
+               $this->loadFromDatabase();
+               $this->setToken();
+               $this->mPassword = $this->encryptPassword( $str );
+               $this->mNewpassword = '';
+       }
+
+       # Set the random token (used for persistent authentication)
+       function setToken( $token = false ) {
+               global $wgSecretKey, $wgProxyKey, $wgDBname;
+               if ( !$token ) {
+                       if ( $wgSecretKey ) {
+                               $key = $wgSecretKey;
+                       } elseif ( $wgProxyKey ) {
+                               $key = $wgProxyKey;
+                       } else {
+                               $key = microtime();
+                       }
+                       $this->mToken = md5( $key . mt_rand( 0, 0x7fffffff ) . $wgDBname . $this->mId );
+               } else {
+                       $this->mToken = $token;
+               }
+       }
+
+
+       function setCookiePassword( $str ) {
+               $this->loadFromDatabase();
+               $this->mCookiePassword = md5( $str );
+       }
+
+       function setNewpassword( $str ) {
+               $this->loadFromDatabase();
+               $this->mNewpassword = $this->encryptPassword( $str );
+       }
+
+       function getEmail() {
+               $this->loadFromDatabase();
+               return $this->mEmail;
+       }
+
+       function getEmailAuthenticationTimestamp() {
+               $this->loadFromDatabase();
+               return $this->mEmailAuthenticated;
+       }
+
+       function setEmail( $str ) {
+               $this->loadFromDatabase();
+               $this->mEmail = $str;
+       }
+
+       function getRealName() {
+               $this->loadFromDatabase();
+               return $this->mRealName;
+       }
+
+       function setRealName( $str ) {
+               $this->loadFromDatabase();
+               $this->mRealName = $str;
+       }
+
+       function getOption( $oname ) {
+               $this->loadFromDatabase();
+               if ( array_key_exists( $oname, $this->mOptions ) ) {
+                       return trim( $this->mOptions[$oname] );
+               } else {
+                       return '';
+               }
+       }
+
+       function setOption( $oname, $val ) {
+               $this->loadFromDatabase();
+               if ( $oname == 'skin' ) {
+                       # Clear cached skin, so the new one displays immediately in Special:Preferences
+                       unset( $this->mSkin );
+               }
+               $this->mOptions[$oname] = $val;
+               $this->invalidateCache();
+       }
+
+       function getRights() {
+               $this->loadFromDatabase();
+               return $this->mRights;
+       }
+
+       /**
+        * Get the list of explicit group memberships this user has.
+        * The implicit * and user groups are not included.
+        * @return array of strings
+        */
+       function getGroups() {
+               $this->loadFromDatabase();
+               return $this->mGroups;
+       }
+
+       /**
+        * Get the list of implicit group memberships this user has.
+        * This includes all explicit groups, plus 'user' if logged in
+        * and '*' for all accounts.
+        * @return array of strings
+        */
+       function getEffectiveGroups() {
+               $base = array( '*' );
+               if( $this->isLoggedIn() ) {
+                       $base[] = 'user';
+               }
+               return array_merge( $base, $this->getGroups() );
+       }
+
+       /**
+        * Remove the user from the given group.
+        * This takes immediate effect.
+        * @string $group
+        */
+       function addGroup( $group ) {
+               $dbw =& wfGetDB( DB_MASTER );
+               $dbw->insert( 'user_groups',
+                       array(
+                               'ug_user'  => $this->getID(),
+                               'ug_group' => $group,
+                       ),
+                       'User::addGroup',
+                       array( 'IGNORE' ) );
+
+               $this->mGroups = array_merge( $this->mGroups, array( $group ) );
+               $this->mRights = User::getGroupPermissions( $this->getEffectiveGroups() );
+
+               $this->invalidateCache();
+               $this->saveSettings();
+       }
+
+       /**
+        * Remove the user from the given group.
+        * This takes immediate effect.
+        * @string $group
+        */
+       function removeGroup( $group ) {
+               $dbw =& wfGetDB( DB_MASTER );
+               $dbw->delete( 'user_groups',
+                       array(
+                               'ug_user'  => $this->getID(),
+                               'ug_group' => $group,
+                       ),
+                       'User::removeGroup' );
+
+               $this->mGroups = array_diff( $this->mGroups, array( $group ) );
+               $this->mRights = User::getGroupPermissions( $this->getEffectiveGroups() );
+
+               $this->invalidateCache();
+               $this->saveSettings();
+       }
+
+
+       /**
+        * A more legible check for non-anonymousness.
+        * Returns true if the user is not an anonymous visitor.
+        *
+        * @return bool
+        */
+       function isLoggedIn() {
+               return( $this->getID() != 0 );
+       }
+
+       /**
+        * A more legible check for anonymousness.
+        * Returns true if the user is an anonymous visitor.
+        *
+        * @return bool
+        */
+       function isAnon() {
+               return !$this->isLoggedIn();
+       }
+
+       /**
+        * Check if a user is sysop
+        * Die with backtrace. Use User:isAllowed() instead.
+        * @deprecated
+        */
+       function isSysop() {
+               return $this->isAllowed( 'protect' );
+       }
+
+       /** @deprecated */
+       function isDeveloper() {
+               return $this->isAllowed( 'siteadmin' );
+       }
+
+       /** @deprecated */
+       function isBureaucrat() {
+               return $this->isAllowed( 'makesysop' );
+       }
+
+       /**
+        * Whether the user is a bot
+        * @todo need to be migrated to the new user level management sytem
+        */
+       function isBot() {
+               $this->loadFromDatabase();
+               return in_array( 'bot', $this->mRights );
+       }
+
+       /**
+        * Check if user is allowed to access a feature / make an action
+        * @param string $action Action to be checked (see $wgAvailableRights in Defines.php for possible actions).
+        * @return boolean True: action is allowed, False: action should not be allowed
+        */
+       function isAllowed($action='') {
+               $this->loadFromDatabase();
+               return in_array( $action , $this->mRights );
+       }
+
+       /**
+        * Load a skin if it doesn't exist or return it
+        * @todo FIXME : need to check the old failback system [AV]
+        */
+       function &getSkin() {
+               global $IP, $wgRequest, $wgStyleDirectory;
+               if ( ! isset( $this->mSkin ) ) {
+                       $fname = 'User::getSkin';
+                       wfProfileIn( $fname );
+
+                       # get all skin names available
+                       $skinNames = Skin::getSkinNames();
+
+                       # get the user skin
+                       $userSkin = $this->getOption( 'skin' );
+                       $userSkin = $wgRequest->getText('useskin', $userSkin);
+                       if ( $userSkin == '' ) { $userSkin = 'monobook'; }
+
+                       if ( !isset( $skinNames[$userSkin] ) ) {
+                               # in case the user skin could not be found find a replacement
+                               $fallback = array(
+                                       0 => 'Standard',
+                                       1 => 'Nostalgia',
+                                       2 => 'CologneBlue');
+                               # if phptal is enabled we should have monobook skin that
+                               # superseed the good old SkinStandard.
+                               if ( isset( $skinNames['monobook'] ) ) {
+                                       $fallback[0] = 'MonoBook';
+                               }
+
+                               if(is_numeric($userSkin) && isset( $fallback[$userSkin]) ){
+                                       $sn = $fallback[$userSkin];
+                               } else {
+                                       $sn = $fallback[0];
+                               }
+                       } else {
+                               # The user skin is available
+                               $sn = $skinNames[$userSkin];
+                       }
+
+                       # Grab the skin class and initialise it. Each skin checks for PHPTal
+                       # and will not load if it's not enabled.
+                       require_once( $wgStyleDirectory.'/'.$sn.'.php' );
+
+                       # Check if we got if not failback to default skin
+                       $className = 'Skin'.$sn;
+                       if( !class_exists( $className ) ) {
+                               # DO NOT die if the class isn't found. This breaks maintenance
+                               # scripts and can cause a user account to be unrecoverable
+                               # except by SQL manipulation if a previously valid skin name
+                               # is no longer valid.
+                               $className = 'SkinStandard';
+                               require_once( $wgStyleDirectory.'/Standard.php' );
+                       }
+                       $this->mSkin =& new $className;
+                       wfProfileOut( $fname );
+               }
+               return $this->mSkin;
+       }
+
+       /**#@+
+        * @param string $title Article title to look at
+        */
+
+       /**
+        * Check watched status of an article
+        * @return bool True if article is watched
+        */
+       function isWatched( $title ) {
+               $wl = WatchedItem::fromUserTitle( $this, $title );
+               return $wl->isWatched();
+       }
+
+       /**
+        * Watch an article
+        */
+       function addWatch( $title ) {
+               $wl = WatchedItem::fromUserTitle( $this, $title );
+               $wl->addWatch();
+               $this->invalidateCache();
+       }
+
+       /**
+        * Stop watching an article
+        */
+       function removeWatch( $title ) {
+               $wl = WatchedItem::fromUserTitle( $this, $title );
+               $wl->removeWatch();
+               $this->invalidateCache();
+       }
+
+       /**
+        * Clear the user's notification timestamp for the given title.
+        * If e-notif e-mails are on, they will receive notification mails on
+        * the next change of the page if it's watched etc.
+        */
+       function clearNotification( &$title ) {
+               global $wgUser, $wgUseEnotif;
+
+               if ( !$wgUseEnotif ) {
+                       return;
+               }
+
+               $userid = $this->getID();
+               if ($userid==0) {
+                       return;
+               }
+
+               // Only update the timestamp if the page is being watched.
+               // The query to find out if it is watched is cached both in memcached and per-invocation,
+               // and when it does have to be executed, it can be on a slave
+               // If this is the user's newtalk page, we always update the timestamp
+               if ($title->getNamespace() == NS_USER_TALK &&
+                       $title->getText() == $wgUser->getName())
+               {
+                       $watched = true;
+               } elseif ( $this->getID() == $wgUser->getID() ) {
+                       $watched = $title->userIsWatching();
+               } else {
+                       $watched = true;
+               }
+
+               // If the page is watched by the user (or may be watched), update the timestamp on any
+               // any matching rows
+               if ( $watched ) {
+                       $dbw =& wfGetDB( DB_MASTER );
+                       $success = $dbw->update( 'watchlist',
+                                       array( /* SET */
+                                               'wl_notificationtimestamp' => 0
+                                       ), array( /* WHERE */
+                                               'wl_title' => $title->getDBkey(),
+                                               'wl_namespace' => $title->getNamespace(),
+                                               'wl_user' => $this->getID()
+                                       ), 'User::clearLastVisited'
+                       );
+               }
+       }
+
+       /**#@-*/
+
+       /**
+        * Resets all of the given user's page-change notification timestamps.
+        * If e-notif e-mails are on, they will receive notification mails on
+        * the next change of any watched page.
+        *
+        * @param int $currentUser user ID number
+        * @access public
+        */
+       function clearAllNotifications( $currentUser ) {
+               global $wgUseEnotif;
+               if ( !$wgUseEnotif ) {
+                       return;
+               }
+               if( $currentUser != 0 )  {
+
+                       $dbw =& wfGetDB( DB_MASTER );
+                       $success = $dbw->update( 'watchlist',
+                               array( /* SET */
+                                       'wl_notificationtimestamp' => 0
+                               ), array( /* WHERE */
+                                       'wl_user' => $currentUser
+                               ), 'UserMailer::clearAll'
+                       );
+
+               #       we also need to clear here the "you have new message" notification for the own user_talk page
+               #       This is cleared one page view later in Article::viewUpdates();
+               }
+       }
+
+       /**
+        * @access private
+        * @return string Encoding options
+        */
+       function encodeOptions() {
+               $a = array();
+               foreach ( $this->mOptions as $oname => $oval ) {
+                       array_push( $a, $oname.'='.$oval );
+               }
+               $s = implode( "\n", $a );
+               return $s;
+       }
+
+       /**
+        * @access private
+        */
+       function decodeOptions( $str ) {
+               $a = explode( "\n", $str );
+               foreach ( $a as $s ) {
+                       if ( preg_match( "/^(.[^=]*)=(.*)$/", $s, $m ) ) {
+                               $this->mOptions[$m[1]] = $m[2];
+                       }
+               }
+       }
+
+       function setCookies() {
+               global $wgCookieExpiration, $wgCookiePath, $wgCookieDomain, $wgCookiePrefix;
+               if ( 0 == $this->mId ) return;
+               $this->loadFromDatabase();
+               $exp = time() + $wgCookieExpiration;
+
+               $_SESSION['wsUserID'] = $this->mId;
+               setcookie( $wgCookiePrefix.'UserID', $this->mId, $exp, $wgCookiePath, $wgCookieDomain );
+
+               $_SESSION['wsUserName'] = $this->mName;
+               setcookie( $wgCookiePrefix.'UserName', $this->mName, $exp, $wgCookiePath, $wgCookieDomain );
+       
+               $_SESSION['wsToken'] = $this->mToken;
+                 global $wgOut;
+               if ( 1 == $this->getOption( 'rememberpassword' ) ) {
+                       setcookie( $wgCookiePrefix.'Token', $this->mToken, $exp, $wgCookiePath, $wgCookieDomain );
+               } else {
+                       setcookie( $wgCookiePrefix.'Token', '', time() - 3600 );
+               }
+       }
+
+       /**
+        * Logout user
+        * It will clean the session cookie
+        */
+       function logout() {
+               global $wgCookiePath, $wgCookieDomain, $wgIP, $wgCookiePrefix;
+               $this->loadDefaults();
+               $this->setLoaded( true );
+
+               $_SESSION['wsUserID'] = 0;
+
+               setcookie( $wgCookiePrefix.'UserID', '', time() - 3600, $wgCookiePath, $wgCookieDomain );
+               setcookie( $wgCookiePrefix.'Token', '', time() - 3600, $wgCookiePath, $wgCookieDomain );
+
+               # Remember when user logged out, to prevent seeing cached pages
+               setcookie( $wgCookiePrefix.'LoggedOut', wfTimestampNow(), time() + 86400, $wgCookiePath, $wgCookieDomain );
+       }
+
+       /**
+        * Save object settings into database
+        */
+       function saveSettings() {
+               global $wgMemc, $wgDBname, $wgUseEnotif;
+               $fname = 'User::saveSettings';
+
+               if ( wfReadOnly() ) { return; }
+               $this->saveNewtalk();
+               if ( 0 == $this->mId ) { return; }
+
+               $dbw =& wfGetDB( DB_MASTER );
+               $dbw->update( 'user',
+                       array( /* SET */
+                               'user_name' => $this->mName,
+                               'user_password' => $this->mPassword,
+                               'user_newpassword' => $this->mNewpassword,
+                               'user_real_name' => $this->mRealName,
+                               'user_email' => $this->mEmail,
+                               'user_email_authenticated' => $dbw->timestampOrNull( $this->mEmailAuthenticated ),
+                               'user_options' => $this->encodeOptions(),
+                               'user_touched' => $dbw->timestamp($this->mTouched),
+                               'user_token' => $this->mToken
+                       ), array( /* WHERE */
+                               'user_id' => $this->mId
+                       ), $fname
+               );
+               $wgMemc->delete( "$wgDBname:user:id:$this->mId" );
+       }
+
+       /**
+        * Save value of new talk flag.
+        */
+       function saveNewtalk() {
+               global $wgDBname, $wgMemc, $wgUseEnotif;
+
+               $fname = 'User::saveNewtalk';
+
+               $changed = false;
+
+               if ( wfReadOnly() ) { return ; }
+               $dbr =& wfGetDB( DB_SLAVE );
+               $dbw =& wfGetDB( DB_MASTER );
+               $changed = false;
+               if ( $wgUseEnotif ) {
+                       if ( ! $this->getNewtalk() ) {
+                               # Delete the watchlist entry for user_talk page X watched by user X
+                               $dbw->delete( 'watchlist',
+                                       array( 'wl_user'      => $this->mId,
+                                                  'wl_title'     => $this->getTitleKey(),
+                                                  'wl_namespace' => NS_USER_TALK ),
+                                       $fname );
+                               if ( $dbw->affectedRows() ) {
+                                       $changed = true;
+                               }
+                               if( !$this->mId ) {
+                                       # Anon users have a separate memcache space for newtalk
+                                       # since they don't store their own info. Trim...
+                                       $wgMemc->delete( "$wgDBname:newtalk:ip:{$this->mName}" );
+                               }
+                       }
+               } else {
+                       if ($this->getID() != 0) {
+                               $field = 'user_id';
+                               $value = $this->getID();
+                               $key = false;
+                       } else {
+                               $field = 'user_ip';
+                               $value = $this->mName;
+                               $key = "$wgDBname:newtalk:ip:$this->mName";
+                       }
+
+                       $dbr =& wfGetDB( DB_SLAVE );
+                       $dbw =& wfGetDB( DB_MASTER );
+
+                       $res = $dbr->selectField('user_newtalk', $field,
+                                                                        array($field => $value), $fname);
+
+                       $changed = true;
+                       if ($res !== false && $this->mNewtalk == 0) {
+                               $dbw->delete('user_newtalk', array($field => $value), $fname);
+                               if ( $key ) {
+                                       $wgMemc->set( $key, 0 );
+                               }
+                       } else if ($res === false && $this->mNewtalk == 1) {
+                               $dbw->insert('user_newtalk', array($field => $value), $fname);
+                               if ( $key ) {
+                                       $wgMemc->set( $key, 1 );
+                               }
+                       } else {
+                               $changed = false;
+                       }
+               }
+
+               # Update user_touched, so that newtalk notifications in the client cache are invalidated
+               if ( $changed && $this->getID() ) {
+                       $dbw->update('user',
+                               /*SET*/ array( 'user_touched' => $this->mTouched ),
+                               /*WHERE*/ array( 'user_id' => $this->getID() ),
+                               $fname);
+                       $wgMemc->set( "$wgDBname:user:id:{$this->mId}", $this, 86400 );
+               }
+       }
+
+       /**
+        * Checks if a user with the given name exists, returns the ID
+        */
+       function idForName() {
+               $fname = 'User::idForName';
+
+               $gotid = 0;
+               $s = trim( $this->mName );
+               if ( 0 == strcmp( '', $s ) ) return 0;
+
+               $dbr =& wfGetDB( DB_SLAVE );
+               $id = $dbr->selectField( 'user', 'user_id', array( 'user_name' => $s ), $fname );
+               if ( $id === false ) {
+                       $id = 0;
+               }
+               return $id;
+       }
+
+       /**
+        * Add user object to the database
+        */
+       function addToDatabase() {
+               $fname = 'User::addToDatabase';
+               $dbw =& wfGetDB( DB_MASTER );
+               $seqVal = $dbw->nextSequenceValue( 'user_user_id_seq' );
+               $dbw->insert( 'user',
+                       array(
+                               'user_id' => $seqVal,
+                               'user_name' => $this->mName,
+                               'user_password' => $this->mPassword,
+                               'user_newpassword' => $this->mNewpassword,
+                               'user_email' => $this->mEmail,
+                               'user_email_authenticated' => $dbw->timestampOrNull( $this->mEmailAuthenticated ),
+                               'user_real_name' => $this->mRealName,
+                               'user_options' => $this->encodeOptions(),
+                               'user_token' => $this->mToken
+                       ), $fname
+               );
+               $this->mId = $dbw->insertId();
+       }
+
+       function spreadBlock() {
+               global $wgIP;
+               # If the (non-anonymous) user is blocked, this function will block any IP address
+               # that they successfully log on from.
+               $fname = 'User::spreadBlock';
+
+               wfDebug( "User:spreadBlock()\n" );
+               if ( $this->mId == 0 ) {
+                       return;
+               }
+
+               $userblock = Block::newFromDB( '', $this->mId );
+               if ( !$userblock->isValid() ) {
+                       return;
+               }
+
+               # Check if this IP address is already blocked
+               $ipblock = Block::newFromDB( $wgIP );
+               if ( $ipblock->isValid() ) {
+                       # Just update the timestamp
+                       $ipblock->updateTimestamp();
+                       return;
+               }
+
+               # Make a new block object with the desired properties
+               wfDebug( "Autoblocking {$this->mName}@{$wgIP}\n" );
+               $ipblock->mAddress = $wgIP;
+               $ipblock->mUser = 0;
+               $ipblock->mBy = $userblock->mBy;
+               $ipblock->mReason = wfMsg( 'autoblocker', $this->getName(), $userblock->mReason );
+               $ipblock->mTimestamp = wfTimestampNow();
+               $ipblock->mAuto = 1;
+               # If the user is already blocked with an expiry date, we don't
+               # want to pile on top of that!
+               if($userblock->mExpiry) {
+                       $ipblock->mExpiry = min ( $userblock->mExpiry, Block::getAutoblockExpiry( $ipblock->mTimestamp ));
+               } else {
+                       $ipblock->mExpiry = Block::getAutoblockExpiry( $ipblock->mTimestamp );
+               }
+
+               # Insert it
+               $ipblock->insert();
+
+       }
+
+       function getPageRenderingHash() {
+               global $wgContLang;
+               if( $this->mHash ){
+                       return $this->mHash;
+               }
+
+               // stubthreshold is only included below for completeness,
+               // it will always be 0 when this function is called by parsercache.
+
+               $confstr =        $this->getOption( 'math' );
+               $confstr .= '!' . $this->getOption( 'stubthreshold' );
+               $confstr .= '!' . $this->getOption( 'date' );
+               $confstr .= '!' . $this->getOption( 'numberheadings' );
+               $confstr .= '!' . $this->getOption( 'language' );
+               $confstr .= '!' . $this->getOption( 'thumbsize' );
+               // add in language specific options, if any
+               $extra = $wgContLang->getExtraHashOptions();
+               $confstr .= $extra;
+
+               $this->mHash = $confstr;
+               return $confstr ;
+       }
+
+       function isAllowedToCreateAccount() {
+               return $this->isAllowed( 'createaccount' );
+       }
+
+       /**
+        * Set mDataLoaded, return previous value
+        * Use this to prevent DB access in command-line scripts or similar situations
+        */
+       function setLoaded( $loaded ) {
+               return wfSetVar( $this->mDataLoaded, $loaded );
+       }
+
+       /**
+        * Get this user's personal page title.
+        *
+        * @return Title
+        * @access public
+        */
+       function getUserPage() {
+               return Title::makeTitle( NS_USER, $this->mName );
+       }
+
+       /**
+        * Get this user's talk page title.
+        *
+        * @return Title
+        * @access public
+        */
+       function getTalkPage() {
+               $title = $this->getUserPage();
+               return $title->getTalkPage();
+       }
+
+       /**
+        * @static
+        */
+       function getMaxID() {
+               $dbr =& wfGetDB( DB_SLAVE );
+               return $dbr->selectField( 'user', 'max(user_id)', false );
+       }
+
+       /**
+        * Determine whether the user is a newbie. Newbies are either
+        * anonymous IPs, or the 1% most recently created accounts.
+        * Bots and sysops are excluded.
+        * @return bool True if it is a newbie.
+        */
+       function isNewbie() {
+               return $this->isAnon() || $this->mId > User::getMaxID() * 0.99 && !$this->isAllowed( 'delete' ) && !$this->isBot();
+       }
+
+       /**
+        * Check to see if the given clear-text password is one of the accepted passwords
+        * @param string $password User password.
+        * @return bool True if the given password is correct otherwise False.
+        */
+       function checkPassword( $password ) {
+               global $wgAuth, $wgMinimalPasswordLength;
+               $this->loadFromDatabase();
+
+               // Even though we stop people from creating passwords that
+               // are shorter than this, doesn't mean people wont be able
+               // to. Certain authentication plugins do NOT want to save
+               // domain passwords in a mysql database, so we should
+               // check this (incase $wgAuth->strict() is false).
+               if( strlen( $password ) < $wgMinimalPasswordLength ) {
+                       return false;
+               }
+
+               if( $wgAuth->authenticate( $this->getName(), $password ) ) {
+                       return true;
+               } elseif( $wgAuth->strict() ) {
+                       /* Auth plugin doesn't allow local authentication */
+                       return false;
+               }
+               $ep = $this->encryptPassword( $password );
+               if ( 0 == strcmp( $ep, $this->mPassword ) ) {
+                       return true;
+               } elseif ( ($this->mNewpassword != '') && (0 == strcmp( $ep, $this->mNewpassword )) ) {
+                       return true;
+               } elseif ( function_exists( 'iconv' ) ) {
+                       # Some wikis were converted from ISO 8859-1 to UTF-8, the passwords can't be converted
+                       # Check for this with iconv
+                       $cp1252hash = $this->encryptPassword( iconv( 'UTF-8', 'WINDOWS-1252', $password ) );
+                       if ( 0 == strcmp( $cp1252hash, $this->mPassword ) ) {
+                               return true;
+                       }
+               }
+               return false;
+       }
+
+       /**
+        * Initialize (if necessary) and return a session token value
+        * which can be used in edit forms to show that the user's
+        * login credentials aren't being hijacked with a foreign form
+        * submission.
+        *
+        * @param mixed $salt - Optional function-specific data for hash.
+        *                      Use a string or an array of strings.
+        * @return string
+        * @access public
+        */
+       function editToken( $salt = '' ) {
+               if( !isset( $_SESSION['wsEditToken'] ) ) {
+                       $token = $this->generateToken();
+                       $_SESSION['wsEditToken'] = $token;
+               } else {
+                       $token = $_SESSION['wsEditToken'];
+               }
+               if( is_array( $salt ) ) {
+                       $salt = implode( '|', $salt );
+               }
+               return md5( $token . $salt );
+       }
+
+       /**
+        * Generate a hex-y looking random token for various uses.
+        * Could be made more cryptographically sure if someone cares.
+        * @return string
+        */
+       function generateToken( $salt = '' ) {
+               $token = dechex( mt_rand() ) . dechex( mt_rand() );
+               return md5( $token . $salt );
+       }
+
+       /**
+        * Check given value against the token value stored in the session.
+        * A match should confirm that the form was submitted from the
+        * user's own login session, not a form submission from a third-party
+        * site.
+        *
+        * @param string $val - the input value to compare
+        * @param string $salt - Optional function-specific data for hash
+        * @return bool
+        * @access public
+        */
+       function matchEditToken( $val, $salt = '' ) {
+               global $wgMemc;
+
+/*
+               if ( !isset( $_SESSION['wsEditToken'] ) ) {
+                       $logfile = '/home/wikipedia/logs/session_debug/session.log';
+                       $mckey = memsess_key( session_id() );
+                       $uname = @posix_uname();
+                       $msg = "wsEditToken not set!\n" .
+                       'apache server=' . $uname['nodename'] . "\n" .
+                       'session_id = ' . session_id() . "\n" .
+                       '$_SESSION=' . var_export( $_SESSION, true ) . "\n" .
+                       '$_COOKIE=' . var_export( $_COOKIE, true ) . "\n" .
+                       "mc get($mckey) = " . var_export( $wgMemc->get( $mckey ), true ) . "\n\n\n";
+
+                       @error_log( $msg, 3, $logfile );
+               }
+*/
+               return ( $val == $this->editToken( $salt ) );
+       }
+
+       /**
+        * Generate a new e-mail confirmation token and send a confirmation
+        * mail to the user's given address.
+        *
+        * @return mixed True on success, a WikiError object on failure.
+        */
+       function sendConfirmationMail() {
+               global $wgIP, $wgContLang;
+               $url = $this->confirmationTokenUrl( $expiration );
+               return $this->sendMail( wfMsg( 'confirmemail_subject' ),
+                       wfMsg( 'confirmemail_body',
+                               $wgIP,
+                               $this->getName(),
+                               $url,
+                               $wgContLang->timeanddate( $expiration, false ) ) );
+       }
+
+       /**
+        * Send an e-mail to this user's account. Does not check for
+        * confirmed status or validity.
+        *
+        * @param string $subject
+        * @param string $body
+        * @param strong $from Optional from address; default $wgPasswordSender will be used otherwise.
+        * @return mixed True on success, a WikiError object on failure.
+        */
+       function sendMail( $subject, $body, $from = null ) {
+               if( is_null( $from ) ) {
+                       global $wgPasswordSender;
+                       $from = $wgPasswordSender;
+               }
+
+               require_once( 'UserMailer.php' );
+               $error = userMailer( $this->getEmail(), $from, $subject, $body );
+
+               if( $error == '' ) {
+                       return true;
+               } else {
+                       return new WikiError( $error );
+               }
+       }
+
+       /**
+        * Generate, store, and return a new e-mail confirmation code.
+        * A hash (unsalted since it's used as a key) is stored.
+        * @param &$expiration mixed output: accepts the expiration time
+        * @return string
+        * @access private
+        */
+       function confirmationToken( &$expiration ) {
+               $fname = 'User::confirmationToken';
+
+               $now = time();
+               $expires = $now + 7 * 24 * 60 * 60;
+               $expiration = wfTimestamp( TS_MW, $expires );
+
+               $token = $this->generateToken( $this->mId . $this->mEmail . $expires );
+               $hash = md5( $token );
+
+               $dbw =& wfGetDB( DB_MASTER );
+               $dbw->update( 'user',
+                       array( 'user_email_token'         => $hash,
+                              'user_email_token_expires' => $dbw->timestamp( $expires ) ),
+                       array( 'user_id'                  => $this->mId ),
+                       $fname );
+
+               return $token;
+       }
+
+       /**
+        * Generate and store a new e-mail confirmation token, and return
+        * the URL the user can use to confirm.
+        * @param &$expiration mixed output: accepts the expiration time
+        * @return string
+        * @access private
+        */
+       function confirmationTokenUrl( &$expiration ) {
+               $token = $this->confirmationToken( $expiration );
+               $title = Title::makeTitle( NS_SPECIAL, 'Confirmemail/' . $token );
+               return $title->getFullUrl();
+       }
+
+       /**
+        * Mark the e-mail address confirmed and save.
+        */
+       function confirmEmail() {
+               $this->loadFromDatabase();
+               $this->mEmailAuthenticated = wfTimestampNow();
+               $this->saveSettings();
+               return true;
+       }
+
+       /**
+        * Is this user allowed to send e-mails within limits of current
+        * site configuration?
+        * @return bool
+        */
+       function canSendEmail() {
+               return $this->isEmailConfirmed();
+       }
+
+       /**
+        * Is this user allowed to receive e-mails within limits of current
+        * site configuration?
+        * @return bool
+        */
+       function canReceiveEmail() {
+               return $this->canSendEmail() && !$this->getOption( 'disablemail' );
+       }
+
+       /**
+        * Is this user's e-mail address valid-looking and confirmed within
+        * limits of the current site configuration?
+        *
+        * If $wgEmailAuthentication is on, this may require the user to have
+        * confirmed their address by returning a code or using a password
+        * sent to the address from the wiki.
+        *
+        * @return bool
+        */
+       function isEmailConfirmed() {
+               global $wgEmailAuthentication;
+               $this->loadFromDatabase();
+               if( $this->isAnon() )
+                       return false;
+               if( !$this->isValidEmailAddr( $this->mEmail ) )
+                       return false;
+               if( $wgEmailAuthentication && !$this->getEmailAuthenticationTimestamp() )
+                       return false;
+               return true;
+       }
+
+       /**
+        * @param array $groups list of groups
+        * @return array list of permission key names for given groups combined
+        * @static
+        */
+       function getGroupPermissions( $groups ) {
+               global $wgGroupPermissions;
+               $rights = array();
+               foreach( $groups as $group ) {
+                       if( isset( $wgGroupPermissions[$group] ) ) {
+                               $rights = array_merge( $rights,
+                                       array_keys( array_filter( $wgGroupPermissions[$group] ) ) );
+                       }
+               }
+               return $rights;
+       }
+
+       /**
+        * @param string $group key name
+        * @return string localized descriptive name, if provided
+        * @static
+        */
+       function getGroupName( $group ) {
+               $key = "group-$group-name";
+               $name = wfMsg( $key );
+               if( $name == '' || $name == "&lt;$key&gt;" ) {
+                       return $group;
+               } else {
+                       return $name;
+               }
+       }
+
+       /**
+        * Return the set of defined explicit groups.
+        * The * and 'user' groups are not included.
+        * @return array
+        * @static
+        */
+       function getAllGroups() {
+               global $wgGroupPermissions;
+               return array_diff(
+                       array_keys( $wgGroupPermissions ),
+                       array( '*', 'user' ) );
+       }
+
+}
+
+?>
diff --git a/includes/UserMailer.php b/includes/UserMailer.php
new file mode 100644 (file)
index 0000000..274c066
--- /dev/null
@@ -0,0 +1,368 @@
+<?php
+/**
+ * UserMailer.php
+ *  Copyright (C) 2004 Thomas Gries <mail@tgries.de>
+ * http://www.mediawiki.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ * 
+ * @author <brion@pobox.com>
+ * @author <mail@tgries.de>
+ * 
+ * @package MediaWiki
+ */
+
+require_once( 'WikiError.php' );
+
+/**
+ * Converts a string into a valid RFC 822 "phrase", such as is used for the sender name
+ */
+function wfRFC822Phrase( $phrase ) {
+       $phrase = strtr( $phrase, array( "\r" => '', "\n" => '', '"' => '' ) );
+       return '"' . $phrase . '"';
+}
+
+/**
+ * This function will perform a direct (authenticated) login to
+ * a SMTP Server to use for mail relaying if 'wgSMTP' specifies an
+ * array of parameters. It requires PEAR:Mail to do that.
+ * Otherwise it just uses the standard PHP 'mail' function.
+ *
+ * @param string $to recipient's email
+ * @param string $from sender's email
+ * @param string $subject email's subject
+ * @param string $body email's text
+ * @param string $replyto optional reply-to email (default : false)
+ */
+function userMailer( $to, $from, $subject, $body, $replyto=false ) {
+       global $wgUser, $wgSMTP, $wgOutputEncoding, $wgErrorString, $wgEmergencyContact;
+       
+       if (is_array( $wgSMTP )) {
+               require_once( 'Mail.php' );
+               
+               $timestamp = time();
+       
+               $headers['From'] = $from;
+               if ( $replyto ) {
+                       $headers['Reply-To'] = $replyto;
+               }
+               $headers['Subject'] = $subject;
+               $headers['MIME-Version'] = '1.0';
+               $headers['Content-type'] = 'text/plain; charset='.$wgOutputEncoding;
+               $headers['Content-transfer-encoding'] = '8bit';
+               $headers['Message-ID'] = "<{$timestamp}" . $wgUser->getName() . '@' . $wgSMTP['IDHost'] . '>';
+               $headers['X-Mailer'] = 'MediaWiki mailer';
+       
+               // Create the mail object using the Mail::factory method
+               $mail_object =& Mail::factory('smtp', $wgSMTP);
+               wfDebug( "Sending mail via PEAR::Mail\n" );
+               $mailResult =& $mail_object->send($to, $headers, $body);
+               
+               # Based on the result return an error string, 
+               if ($mailResult === true)
+                       return '';
+               else if (is_object($mailResult))
+                       return $mailResult->getMessage();
+               else
+                       return 'Mail object return unknown error.';
+       } else  {
+               # In the following $headers = expression we removed "Reply-To: {$from}\r\n" , because it is treated differently
+               # (fifth parameter of the PHP mail function, see some lines below)
+               $headers =
+                       "MIME-Version: 1.0\n" .
+                       "Content-type: text/plain; charset={$wgOutputEncoding}\n" .
+                       "Content-Transfer-Encoding: 8bit\n" .
+                       "X-Mailer: MediaWiki mailer\n".
+                       'From: ' . $from . "\n";
+               if ($replyto) {
+                       $headers .= "Reply-To: $replyto\n";
+               }
+
+               $wgErrorString = '';
+               set_error_handler( 'mailErrorHandler' );
+               wfDebug( "Sending mail via internal mail() function\n" );
+               mail( $to, $subject, $body, $headers );
+               restore_error_handler();
+
+               if ( $wgErrorString ) {
+                       wfDebug( "Error sending mail: $wgErrorString\n" );
+               }
+               return $wgErrorString;
+       }
+}
+
+/**
+ * @todo document
+ */
+function mailErrorHandler( $code, $string ) {
+       global $wgErrorString;
+       $wgErrorString = preg_replace( "/^mail\(\): /", "", $string );
+}
+
+
+/**
+ * This module processes the email notifications when the current page is
+ * changed. It looks up the table watchlist to find out which users are watching
+ * that page.
+ *
+ * The current implementation sends independent emails to each watching user for
+ * the following reason:
+ *
+ * - Each watching user will be notified about the page edit time expressed in
+ * his/her local time (UTC is shown additionally). To achieve this, we need to
+ * find the individual timeoffset of each watching user from the preferences..
+ *
+ * Suggested improvement to slack down the number of sent emails: We could think
+ * of sending out bulk mails (bcc:user1,user2...) for all these users having the
+ * same timeoffset in their preferences.
+ *
+ * Visit the documentation pages under http://meta.wikipedia.com/Enotif
+ * 
+ * @package MediaWiki
+ * 
+ */
+class EmailNotification {
+       /**#@+
+        * @access private
+        */
+       var $to, $subject, $body, $replyto, $from;
+       var $user, $title, $timestamp, $summary, $minorEdit, $oldid;
+       
+       /**#@-*/
+       
+       /**
+        * @todo document
+        * @param $currentPage
+        * @param $currentNs
+        * @param $timestamp
+        * @param $currentSummary
+        * @param $currentMinorEdit
+        * @param $oldid (default: false)
+        */
+       function notifyOnPageChange(&$title, $timestamp, $summary, $minorEdit, $oldid=false) {
+       
+               # we use $wgEmergencyContact as sender's address
+               global $wgUser, $wgLang, $wgEmergencyContact;
+               global $wgEnotifWatchlist, $wgEnotifMinorEdits;
+               global $wgEnotifUserTalk;
+               global $wgEnotifRevealEditorAddress;
+               global $wgEnotifFromEditor;
+               global $wgEmailAuthentication;
+               global $wgShowUpdatedMarker;
+
+               $fname = 'UserMailer::notifyOnPageChange';
+               wfProfileIn( $fname );
+               
+               # The following code is only run, if several conditions are met:
+               # 1. EmailNotification for pages (other than user_talk pages) must be enabled
+               # 2. minor edits (changes) are only regarded if the global flag indicates so
+       
+               $isUserTalkPage = ($title->getNamespace() == NS_USER_TALK);
+               $enotifusertalkpage = ($isUserTalkPage && $wgEnotifUserTalk);
+               $enotifwatchlistpage = (!$isUserTalkPage && $wgEnotifWatchlist);        
+
+
+               if ( ($enotifusertalkpage || $enotifwatchlistpage) && (!$minorEdit || $wgEnotifMinorEdits) ) {
+                       $dbr =& wfGetDB( DB_MASTER );
+                       extract( $dbr->tableNames( 'watchlist' ) );
+                       $res = $dbr->select( 'watchlist', array( 'wl_user' ), 
+                               array(
+                                       'wl_title' => $title->getDBkey(),
+                                       'wl_namespace' => $title->getNamespace(),
+                                       'wl_user <> ' . $wgUser->getID(),
+                                       'wl_notificationtimestamp <= 1',
+                               ), $fname );
+
+                       # if anyone is watching ... set up the email message text which is
+                       # common for all receipients ...
+                       if ( $dbr->numRows( $res ) > 0 ) { 
+                               $this->user &= $wgUser;
+                               $this->title =& $title;
+                               $this->timestamp = $timestamp;
+                               $this->summary = $summary;
+                               $this->minorEdit = $minorEdit;
+                               $this->oldid = $oldid;
+
+                               $this->composeCommonMailtext();
+                               $watchingUser = new User();
+       
+                               # ... now do for all watching users ... if the options fit
+                               for ($i = 1; $i <= $dbr->numRows( $res ); $i++) { 
+
+                                       $wuser = $dbr->fetchObject( $res );
+                                       $watchingUser->setID($wuser->wl_user);
+                                       if ( ( $enotifwatchlistpage && $watchingUser->getOption('enotifwatchlistpages') ) ||
+                                               ( $enotifusertalkpage && $watchingUser->getOption('enotifusertalkpages') )
+                                       && (!$minorEdit || ($wgEnotifMinorEdits && $watchingUser->getOption('enotifminoredits') ) )
+                                       && ($watchingUser->isEmailConfirmed() ) ) {
+                                               # ... adjust remaining text and page edit time placeholders
+                                               # which needs to be personalized for each user
+                                               $this->composeAndSendPersonalisedMail( $watchingUser );
+
+                                       } # if the watching user has an email address in the preferences
+                               }
+                       } # if anyone is watching
+               } # if $wgEnotifWatchlist = true
+
+               if ( $wgShowUpdatedMarker || $wgEnotifWatchlist ) {
+                       # mark the changed watch-listed page with a timestamp, so that the page is 
+                       # listed with an "updated since your last visit" icon in the watch list, ...
+                       $dbw =& wfGetDB( DB_MASTER );
+                       $success = $dbw->update( 'watchlist',
+                               array( /* SET */
+                                       'wl_notificationtimestamp' => $timestamp
+                               ), array( /* WHERE */
+                                       'wl_title' => $title->getDBkey(),
+                                       'wl_namespace' => $title->getNamespace(),
+                               ), 'UserMailer::NotifyOnChange'
+                       );
+               }
+
+       } # function NotifyOnChange
+       
+       /**
+        * @access private
+        */
+       function composeCommonMailtext() {
+               global $wgLang, $wgUser, $wgEmergencyContact;
+               global $wgEnotifRevealEditorAddress;
+               global $wgEnotifFromEditor;
+               global $wgNoReplyAddress;
+               
+               $summary = ($this->summary == '') ? ' - ' : $this->summary;
+               $medit   = ($this->minorEdit) ? wfMsg( 'minoredit' ) : '';
+               
+               # You as the WikiAdmin and Sysops can make use of plenty of
+               # named variables when composing your notification emails while
+               # simply editing the Meta pages
+               
+               $subject = wfMsgForContent( 'enotif_subject' );
+               $body    = wfMsgForContent( 'enotif_body' );
+               $from    = ''; /* fail safe */
+               $replyto = ''; /* fail safe */
+               $keys    = array();
+               
+               # regarding the use of oldid as an indicator for the last visited version, see also
+               # http://bugzilla.wikipeda.org/show_bug.cgi?id=603 "Delete + undelete cycle doesn't preserve old_id"
+               # However, in the case of a new page which is already watched, we have no previous version to compare
+               if( $this->oldid ) {
+                       $difflink = $this->title->getFullUrl( 'diff=0&oldid=' . $this->oldid );
+                       $keys['$NEWPAGE'] = wfMsgForContent( 'enotif_lastvisited', $difflink );
+                       $keys['$OLDID']   = $this->oldid;
+                       $keys['$CHANGEDORCREATED'] = wfMsgForContent( 'changed' );
+               } else {
+                       $keys['$NEWPAGE'] = wfMsgForContent( 'enotif_newpagetext' );
+                       # clear $OLDID placeholder in the message template
+                       $keys['$OLDID']   = '';
+                       $keys['$CHANGEDORCREATED'] = wfMsgForContent( 'created' );
+               }
+               
+               $body = strtr( $body, $keys ); 
+               $pagetitle = $this->title->getPrefixedText();
+               
+               $keys['$PAGETITLE']          = $pagetitle;
+               $keys['$PAGETITLE_URL']      = $this->title->getFullUrl();
+               
+               $keys['$PAGEMINOREDIT']      = $medit;
+               $keys['$PAGESUMMARY']        = $summary;
+       
+               $subject = strtr( $subject, $keys );
+
+               # Reveal the page editor's address as REPLY-TO address only if
+               # the user has not opted-out and the option is enabled at the
+               # global configuration level.
+               $name    = $wgUser->getName();
+               $adminAddress = 'WikiAdmin <' . $wgEmergencyContact . '>';
+               $editorAddress = wfRFC822Phrase( $name ) . ' <' . $wgUser->getEmail() . '>';
+               if( $wgEnotifRevealEditorAddress
+                   && ( $wgUser->getEmail() != '' )
+                   && $wgUser->getOption( 'enotifrevealaddr' ) ) {
+                       if( $wgEnotifFromEditor ) {
+                               $from    = $editorAddress;
+                       } else {
+                               $from    = $adminAddress;
+                               $replyto = $editorAddress;
+                       }
+               } else {
+                       $from    = $adminAddress;
+                       $replyto = $wgNoReplyAddress;
+               }
+       
+               if( $wgUser->isIP( $name ) ) {
+                       #real anon (user:xxx.xxx.xxx.xxx)
+                       $anon    = $name . ' (anonymous user)';
+                       $anonUrl = wfUrlencode( $name ) . ' (anonymous user)';
+                       $subject = str_replace('$PAGEEDITOR', 'anonymous user '. $name, $subject);
+                       
+                       $keys['$PAGEEDITOR']       = 'anonymous user ' . $name;
+                       $keys['$PAGEEDITOR_EMAIL'] = wfMsgForContent( 'noemailtitle' );
+               } else {
+                       $subject = str_replace('$PAGEEDITOR', $name, $subject);
+                       $keys['$PAGEEDITOR']          = $name;
+                       $emailPage = Title::makeTitle( NS_SPECIAL, 'Emailuser/' . $name );
+                       $keys['$PAGEEDITOR_EMAIL'] = $emailPage->getFullUrl();
+               }
+               $userPage = $wgUser->getUserPage();
+               $keys['$PAGEEDITOR_WIKI'] = $userPage->getFullUrl();
+               $body = strtr( $body, $keys );
+               
+               $body = wordwrap( $body, 72 );
+
+               # now save this as the constant user-independent part of the message
+               $this->from    = $from;
+               $this->replyto = $replyto;
+               $this->subject = $subject;
+               $this->body    = $body;
+       }
+
+
+       
+       /**
+        * Does the per-user customizations to a notification e-mail (name,
+        * timestamp in proper timezone, etc) and sends it out.
+        * Returns true if the mail was sent successfully.
+        *
+        * @param User $watchingUser
+        * @param object $mail
+        * @return bool
+        * @access private
+        */
+       function composeAndSendPersonalisedMail( $watchingUser ) {
+               global $wgLang;
+               // From the PHP manual:
+               //     Note:  The to parameter cannot be an address in the form of "Something <someone@example.com>". 
+               //     The mail command will not parse this properly while talking with the MTA.
+               $to = $watchingUser->getEmail();
+               $body = str_replace( '$WATCHINGUSERNAME', $watchingUser->getName() , $this->body );
+       
+               $timecorrection = $watchingUser->getOption( 'timecorrection' );
+               if( !$timecorrection ) {
+                       # fail safe - I prefer it. TomGries
+                       $timecorrection = '00:00';
+               }
+               # $PAGEEDITDATE is the time and date of the page change
+               # expressed in terms of individual local time of the notification
+               # recipient, i.e. watching user
+               $body = str_replace('$PAGEEDITDATE',
+                       $wgLang->timeanddate( $this->timestamp, true, false, $timecorrection ),
+                       $body);
+               
+               $error = userMailer( $to, $this->from, $this->subject, $body, $this->replyto );
+               return ($error == '');
+       }
+
+} # end of class EmailNotification
+?>
diff --git a/includes/UserTalkUpdate.php b/includes/UserTalkUpdate.php
new file mode 100644 (file)
index 0000000..10bf915
--- /dev/null
@@ -0,0 +1,117 @@
+<?php
+/** Copyright (C) 2004 Thomas Gries <mail@tgries.de>
+ * http://www.mediawiki.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ * 
+ * See deferred.txt
+ *
+ * @package MediaWiki
+ * @author <mail@tgries.de>
+ */
+
+/**
+ *
+ * @package MediaWiki
+ */
+class UserTalkUpdate {
+
+       /**#@+
+        * @access private
+        */
+       var $mAction, $mNamespace, $mTitle, $mSummary, $mMinorEdit, $mTimestamp;
+       /**#@-*/
+
+       /**
+        * @todo document
+        * @param string $action
+        * @param integer $ns
+        * @param $title
+        * @param $summary
+        * @param $minoredit
+        * @param $timestamp
+        */
+       function UserTalkUpdate( $action, $ns, $title, $summary, $minoredit, $timestamp) {
+               global $wgUser, $wgLang, $wgMemc, $wgDBname;
+               $fname = 'UserTalkUpdate::UserTalkUpdate';
+
+               $this->mAction = $action;
+               $this->mNamespace = $ns;
+               $this->mTitle = $title;
+               $this->mSummary = $summary;
+               $this->mMinorEdit = $minoredit;
+               $this->mTimestamp = $timestamp;
+
+               # If namespace isn't User_talk:, do nothing.
+               if ( $this->mNamespace != NS_USER_TALK ) {
+                       return;
+               }
+
+               # If the user talk page is our own, clear the flag
+               # when we are reading it or writing it.
+               if ( 0 == strcmp( str_replace( '_', ' ', $this->mTitle ), $wgUser->getName() ) ) {
+                       $wgUser->setNewtalk( 0 );
+                       $wgUser->saveSettings();
+               } else {
+                       # Not ours.  If writing, then mark it as modified.
+                       $sql = false;
+                       if ( 1 == $this->mAction ) {
+                               $user = new User();
+                               $user->setID(User::idFromName($this->mTitle));
+
+                               if ($id=$user->getID()) {
+                                       $sql = true;
+                                       $wgMemc->delete( "$wgDBname:user:id:$id" );
+                               } else {
+                                       if ( $wgUser->isIP($this->mTitle) ) { # anonymous
+                                               $dbw =& wfGetDB( DB_MASTER );
+                                               $dbw->replace( 'watchlist',
+                                                       array(array('wl_user','wl_namespace', 'wl_title', 'wl_notificationtimestamp')),
+                                                         array('wl_user'                       => 0,
+                                                               'wl_namespace'                  => NS_USER_TALK,
+                                                               'wl_title'                      => $this->mTitle,
+                                                               'wl_notificationtimestamp'      => 1
+                                                               ), 'UserTalkUpdate'
+                                                       );
+                                               $sql = true;
+                                               $wgMemc->delete( "$wgDBname:newtalk:ip:$this->mTitle" );
+                                       }
+                               }
+
+                               if($sql && !$user->getNewtalk() ) {
+                                       # create an artificial watchlist table entry for the owner X of the user_talk page X
+                                       # only insert if X is a real user and the page is not yet watched
+                                       # mark the changed watch-listed page with a timestamp, so that the page is listed with
+                                       # an "updated since your last visit" icon in the watch list, ...
+                                       # ... no matter, if the watching user has or has not indicated an email address in his/her preferences.
+                                       # We memorise the event of sending out a notification and use this as a flag to suppress
+                                       # further mails for changes on the same page for that watching user
+                                       $dbw =& wfGetDB( DB_MASTER );
+                                       $dbw->replace( 'watchlist',
+                                               array(array('wl_user','wl_namespace', 'wl_title', 'wl_notificationtimestamp')),
+                                                 array('wl_user' => $id,
+                                                       'wl_namespace' => NS_USER_TALK,
+                                                       'wl_title' => $this->mTitle,
+                                                       'wl_notificationtimestamp' => 1
+                                                       ), 'UserTalkUpdate'
+                                               );
+                               }
+                       }
+               }
+       }
+}
+
+?>
diff --git a/includes/Utf8Case.php b/includes/Utf8Case.php
new file mode 100644 (file)
index 0000000..9a2c730
--- /dev/null
@@ -0,0 +1,1506 @@
+<?php
+/**
+ * Simple 1:1 upper/lowercase switching arrays for utf-8 text
+ * Won't get context-sensitive things yet
+ *
+ * Hack for bugs in ucfirst() and company
+ *
+ * These are pulled from memcached if possible, as this is faster than filling
+ * up a big array manually. See also languages/LanguageUtf8.php
+ * @package MediaWiki
+ * @subpackage Language
+ */
+
+/*
+ * Translation array to get upper case character
+ */
+$wikiUpperChars = array(
+       "a" => "A",
+       "b" => "B",
+       "c" => "C",
+       "d" => "D",
+       "e" => "E",
+       "f" => "F",
+       "g" => "G",
+       "h" => "H",
+       "i" => "I",
+       "j" => "J",
+       "k" => "K",
+       "l" => "L",
+       "m" => "M",
+       "n" => "N",
+       "o" => "O",
+       "p" => "P",
+       "q" => "Q",
+       "r" => "R",
+       "s" => "S",
+       "t" => "T",
+       "u" => "U",
+       "v" => "V",
+       "w" => "W",
+       "x" => "X",
+       "y" => "Y",
+       "z" => "Z",
+       "\xc2\xb5" => "\xce\x9c",
+       "\xc3\xa0" => "\xc3\x80",
+       "\xc3\xa1" => "\xc3\x81",
+       "\xc3\xa2" => "\xc3\x82",
+       "\xc3\xa3" => "\xc3\x83",
+       "\xc3\xa4" => "\xc3\x84",
+       "\xc3\xa5" => "\xc3\x85",
+       "\xc3\xa6" => "\xc3\x86",
+       "\xc3\xa7" => "\xc3\x87",
+       "\xc3\xa8" => "\xc3\x88",
+       "\xc3\xa9" => "\xc3\x89",
+       "\xc3\xaa" => "\xc3\x8a",
+       "\xc3\xab" => "\xc3\x8b",
+       "\xc3\xac" => "\xc3\x8c",
+       "\xc3\xad" => "\xc3\x8d",
+       "\xc3\xae" => "\xc3\x8e",
+       "\xc3\xaf" => "\xc3\x8f",
+       "\xc3\xb0" => "\xc3\x90",
+       "\xc3\xb1" => "\xc3\x91",
+       "\xc3\xb2" => "\xc3\x92",
+       "\xc3\xb3" => "\xc3\x93",
+       "\xc3\xb4" => "\xc3\x94",
+       "\xc3\xb5" => "\xc3\x95",
+       "\xc3\xb6" => "\xc3\x96",
+       "\xc3\xb8" => "\xc3\x98",
+       "\xc3\xb9" => "\xc3\x99",
+       "\xc3\xba" => "\xc3\x9a",
+       "\xc3\xbb" => "\xc3\x9b",
+       "\xc3\xbc" => "\xc3\x9c",
+       "\xc3\xbd" => "\xc3\x9d",
+       "\xc3\xbe" => "\xc3\x9e",
+       "\xc3\xbf" => "\xc5\xb8",
+       "\xc4\x81" => "\xc4\x80",
+       "\xc4\x83" => "\xc4\x82",
+       "\xc4\x85" => "\xc4\x84",
+       "\xc4\x87" => "\xc4\x86",
+       "\xc4\x89" => "\xc4\x88",
+       "\xc4\x8b" => "\xc4\x8a",
+       "\xc4\x8d" => "\xc4\x8c",
+       "\xc4\x8f" => "\xc4\x8e",
+       "\xc4\x91" => "\xc4\x90",
+       "\xc4\x93" => "\xc4\x92",
+       "\xc4\x95" => "\xc4\x94",
+       "\xc4\x97" => "\xc4\x96",
+       "\xc4\x99" => "\xc4\x98",
+       "\xc4\x9b" => "\xc4\x9a",
+       "\xc4\x9d" => "\xc4\x9c",
+       "\xc4\x9f" => "\xc4\x9e",
+       "\xc4\xa1" => "\xc4\xa0",
+       "\xc4\xa3" => "\xc4\xa2",
+       "\xc4\xa5" => "\xc4\xa4",
+       "\xc4\xa7" => "\xc4\xa6",
+       "\xc4\xa9" => "\xc4\xa8",
+       "\xc4\xab" => "\xc4\xaa",
+       "\xc4\xad" => "\xc4\xac",
+       "\xc4\xaf" => "\xc4\xae",
+       "\xc4\xb1" => "I",
+       "\xc4\xb3" => "\xc4\xb2",
+       "\xc4\xb5" => "\xc4\xb4",
+       "\xc4\xb7" => "\xc4\xb6",
+       "\xc4\xba" => "\xc4\xb9",
+       "\xc4\xbc" => "\xc4\xbb",
+       "\xc4\xbe" => "\xc4\xbd",
+       "\xc5\x80" => "\xc4\xbf",
+       "\xc5\x82" => "\xc5\x81",
+       "\xc5\x84" => "\xc5\x83",
+       "\xc5\x86" => "\xc5\x85",
+       "\xc5\x88" => "\xc5\x87",
+       "\xc5\x8b" => "\xc5\x8a",
+       "\xc5\x8d" => "\xc5\x8c",
+       "\xc5\x8f" => "\xc5\x8e",
+       "\xc5\x91" => "\xc5\x90",
+       "\xc5\x93" => "\xc5\x92",
+       "\xc5\x95" => "\xc5\x94",
+       "\xc5\x97" => "\xc5\x96",
+       "\xc5\x99" => "\xc5\x98",
+       "\xc5\x9b" => "\xc5\x9a",
+       "\xc5\x9d" => "\xc5\x9c",
+       "\xc5\x9f" => "\xc5\x9e",
+       "\xc5\xa1" => "\xc5\xa0",
+       "\xc5\xa3" => "\xc5\xa2",
+       "\xc5\xa5" => "\xc5\xa4",
+       "\xc5\xa7" => "\xc5\xa6",
+       "\xc5\xa9" => "\xc5\xa8",
+       "\xc5\xab" => "\xc5\xaa",
+       "\xc5\xad" => "\xc5\xac",
+       "\xc5\xaf" => "\xc5\xae",
+       "\xc5\xb1" => "\xc5\xb0",
+       "\xc5\xb3" => "\xc5\xb2",
+       "\xc5\xb5" => "\xc5\xb4",
+       "\xc5\xb7" => "\xc5\xb6",
+       "\xc5\xba" => "\xc5\xb9",
+       "\xc5\xbc" => "\xc5\xbb",
+       "\xc5\xbe" => "\xc5\xbd",
+       "\xc5\xbf" => "S",
+       "\xc6\x83" => "\xc6\x82",
+       "\xc6\x85" => "\xc6\x84",
+       "\xc6\x88" => "\xc6\x87",
+       "\xc6\x8c" => "\xc6\x8b",
+       "\xc6\x92" => "\xc6\x91",
+       "\xc6\x95" => "\xc7\xb6",
+       "\xc6\x99" => "\xc6\x98",
+       "\xc6\xa1" => "\xc6\xa0",
+       "\xc6\xa3" => "\xc6\xa2",
+       "\xc6\xa5" => "\xc6\xa4",
+       "\xc6\xa8" => "\xc6\xa7",
+       "\xc6\xad" => "\xc6\xac",
+       "\xc6\xb0" => "\xc6\xaf",
+       "\xc6\xb4" => "\xc6\xb3",
+       "\xc6\xb6" => "\xc6\xb5",
+       "\xc6\xb9" => "\xc6\xb8",
+       "\xc6\xbd" => "\xc6\xbc",
+       "\xc6\xbf" => "\xc7\xb7",
+       "\xc7\x85" => "\xc7\x84",
+       "\xc7\x86" => "\xc7\x84",
+       "\xc7\x88" => "\xc7\x87",
+       "\xc7\x89" => "\xc7\x87",
+       "\xc7\x8b" => "\xc7\x8a",
+       "\xc7\x8c" => "\xc7\x8a",
+       "\xc7\x8e" => "\xc7\x8d",
+       "\xc7\x90" => "\xc7\x8f",
+       "\xc7\x92" => "\xc7\x91",
+       "\xc7\x94" => "\xc7\x93",
+       "\xc7\x96" => "\xc7\x95",
+       "\xc7\x98" => "\xc7\x97",
+       "\xc7\x9a" => "\xc7\x99",
+       "\xc7\x9c" => "\xc7\x9b",
+       "\xc7\x9d" => "\xc6\x8e",
+       "\xc7\x9f" => "\xc7\x9e",
+       "\xc7\xa1" => "\xc7\xa0",
+       "\xc7\xa3" => "\xc7\xa2",
+       "\xc7\xa5" => "\xc7\xa4",
+       "\xc7\xa7" => "\xc7\xa6",
+       "\xc7\xa9" => "\xc7\xa8",
+       "\xc7\xab" => "\xc7\xaa",
+       "\xc7\xad" => "\xc7\xac",
+       "\xc7\xaf" => "\xc7\xae",
+       "\xc7\xb2" => "\xc7\xb1",
+       "\xc7\xb3" => "\xc7\xb1",
+       "\xc7\xb5" => "\xc7\xb4",
+       "\xc7\xb9" => "\xc7\xb8",
+       "\xc7\xbb" => "\xc7\xba",
+       "\xc7\xbd" => "\xc7\xbc",
+       "\xc7\xbf" => "\xc7\xbe",
+       "\xc8\x81" => "\xc8\x80",
+       "\xc8\x83" => "\xc8\x82",
+       "\xc8\x85" => "\xc8\x84",
+       "\xc8\x87" => "\xc8\x86",
+       "\xc8\x89" => "\xc8\x88",
+       "\xc8\x8b" => "\xc8\x8a",
+       "\xc8\x8d" => "\xc8\x8c",
+       "\xc8\x8f" => "\xc8\x8e",
+       "\xc8\x91" => "\xc8\x90",
+       "\xc8\x93" => "\xc8\x92",
+       "\xc8\x95" => "\xc8\x94",
+       "\xc8\x97" => "\xc8\x96",
+       "\xc8\x99" => "\xc8\x98",
+       "\xc8\x9b" => "\xc8\x9a",
+       "\xc8\x9d" => "\xc8\x9c",
+       "\xc8\x9f" => "\xc8\x9e",
+       "\xc8\xa3" => "\xc8\xa2",
+       "\xc8\xa5" => "\xc8\xa4",
+       "\xc8\xa7" => "\xc8\xa6",
+       "\xc8\xa9" => "\xc8\xa8",
+       "\xc8\xab" => "\xc8\xaa",
+       "\xc8\xad" => "\xc8\xac",
+       "\xc8\xaf" => "\xc8\xae",
+       "\xc8\xb1" => "\xc8\xb0",
+       "\xc8\xb3" => "\xc8\xb2",
+       "\xc9\x93" => "\xc6\x81",
+       "\xc9\x94" => "\xc6\x86",
+       "\xc9\x96" => "\xc6\x89",
+       "\xc9\x97" => "\xc6\x8a",
+       "\xc9\x99" => "\xc6\x8f",
+       "\xc9\x9b" => "\xc6\x90",
+       "\xc9\xa0" => "\xc6\x93",
+       "\xc9\xa3" => "\xc6\x94",
+       "\xc9\xa8" => "\xc6\x97",
+       "\xc9\xa9" => "\xc6\x96",
+       "\xc9\xaf" => "\xc6\x9c",
+       "\xc9\xb2" => "\xc6\x9d",
+       "\xc9\xb5" => "\xc6\x9f",
+       "\xca\x80" => "\xc6\xa6",
+       "\xca\x83" => "\xc6\xa9",
+       "\xca\x88" => "\xc6\xae",
+       "\xca\x8a" => "\xc6\xb1",
+       "\xca\x8b" => "\xc6\xb2",
+       "\xca\x92" => "\xc6\xb7",
+       "\xcd\x85" => "\xce\x99",
+       "\xce\xac" => "\xce\x86",
+       "\xce\xad" => "\xce\x88",
+       "\xce\xae" => "\xce\x89",
+       "\xce\xaf" => "\xce\x8a",
+       "\xce\xb1" => "\xce\x91",
+       "\xce\xb2" => "\xce\x92",
+       "\xce\xb3" => "\xce\x93",
+       "\xce\xb4" => "\xce\x94",
+       "\xce\xb5" => "\xce\x95",
+       "\xce\xb6" => "\xce\x96",
+       "\xce\xb7" => "\xce\x97",
+       "\xce\xb8" => "\xce\x98",
+       "\xce\xb9" => "\xce\x99",
+       "\xce\xba" => "\xce\x9a",
+       "\xce\xbb" => "\xce\x9b",
+       "\xce\xbc" => "\xce\x9c",
+       "\xce\xbd" => "\xce\x9d",
+       "\xce\xbe" => "\xce\x9e",
+       "\xce\xbf" => "\xce\x9f",
+       "\xcf\x80" => "\xce\xa0",
+       "\xcf\x81" => "\xce\xa1",
+       "\xcf\x82" => "\xce\xa3",
+       "\xcf\x83" => "\xce\xa3",
+       "\xcf\x84" => "\xce\xa4",
+       "\xcf\x85" => "\xce\xa5",
+       "\xcf\x86" => "\xce\xa6",
+       "\xcf\x87" => "\xce\xa7",
+       "\xcf\x88" => "\xce\xa8",
+       "\xcf\x89" => "\xce\xa9",
+       "\xcf\x8a" => "\xce\xaa",
+       "\xcf\x8b" => "\xce\xab",
+       "\xcf\x8c" => "\xce\x8c",
+       "\xcf\x8d" => "\xce\x8e",
+       "\xcf\x8e" => "\xce\x8f",
+       "\xcf\x90" => "\xce\x92",
+       "\xcf\x91" => "\xce\x98",
+       "\xcf\x95" => "\xce\xa6",
+       "\xcf\x96" => "\xce\xa0",
+       "\xcf\x9b" => "\xcf\x9a",
+       "\xcf\x9d" => "\xcf\x9c",
+       "\xcf\x9f" => "\xcf\x9e",
+       "\xcf\xa1" => "\xcf\xa0",
+       "\xcf\xa3" => "\xcf\xa2",
+       "\xcf\xa5" => "\xcf\xa4",
+       "\xcf\xa7" => "\xcf\xa6",
+       "\xcf\xa9" => "\xcf\xa8",
+       "\xcf\xab" => "\xcf\xaa",
+       "\xcf\xad" => "\xcf\xac",
+       "\xcf\xaf" => "\xcf\xae",
+       "\xcf\xb0" => "\xce\x9a",
+       "\xcf\xb1" => "\xce\xa1",
+       "\xcf\xb2" => "\xce\xa3",
+       "\xcf\xb5" => "\xce\x95",
+       "\xd0\xb0" => "\xd0\x90",
+       "\xd0\xb1" => "\xd0\x91",
+       "\xd0\xb2" => "\xd0\x92",
+       "\xd0\xb3" => "\xd0\x93",
+       "\xd0\xb4" => "\xd0\x94",
+       "\xd0\xb5" => "\xd0\x95",
+       "\xd0\xb6" => "\xd0\x96",
+       "\xd0\xb7" => "\xd0\x97",
+       "\xd0\xb8" => "\xd0\x98",
+       "\xd0\xb9" => "\xd0\x99",
+       "\xd0\xba" => "\xd0\x9a",
+       "\xd0\xbb" => "\xd0\x9b",
+       "\xd0\xbc" => "\xd0\x9c",
+       "\xd0\xbd" => "\xd0\x9d",
+       "\xd0\xbe" => "\xd0\x9e",
+       "\xd0\xbf" => "\xd0\x9f",
+       "\xd1\x80" => "\xd0\xa0",
+       "\xd1\x81" => "\xd0\xa1",
+       "\xd1\x82" => "\xd0\xa2",
+       "\xd1\x83" => "\xd0\xa3",
+       "\xd1\x84" => "\xd0\xa4",
+       "\xd1\x85" => "\xd0\xa5",
+       "\xd1\x86" => "\xd0\xa6",
+       "\xd1\x87" => "\xd0\xa7",
+       "\xd1\x88" => "\xd0\xa8",
+       "\xd1\x89" => "\xd0\xa9",
+       "\xd1\x8a" => "\xd0\xaa",
+       "\xd1\x8b" => "\xd0\xab",
+       "\xd1\x8c" => "\xd0\xac",
+       "\xd1\x8d" => "\xd0\xad",
+       "\xd1\x8e" => "\xd0\xae",
+       "\xd1\x8f" => "\xd0\xaf",
+       "\xd1\x90" => "\xd0\x80",
+       "\xd1\x91" => "\xd0\x81",
+       "\xd1\x92" => "\xd0\x82",
+       "\xd1\x93" => "\xd0\x83",
+       "\xd1\x94" => "\xd0\x84",
+       "\xd1\x95" => "\xd0\x85",
+       "\xd1\x96" => "\xd0\x86",
+       "\xd1\x97" => "\xd0\x87",
+       "\xd1\x98" => "\xd0\x88",
+       "\xd1\x99" => "\xd0\x89",
+       "\xd1\x9a" => "\xd0\x8a",
+       "\xd1\x9b" => "\xd0\x8b",
+       "\xd1\x9c" => "\xd0\x8c",
+       "\xd1\x9d" => "\xd0\x8d",
+       "\xd1\x9e" => "\xd0\x8e",
+       "\xd1\x9f" => "\xd0\x8f",
+       "\xd1\xa1" => "\xd1\xa0",
+       "\xd1\xa3" => "\xd1\xa2",
+       "\xd1\xa5" => "\xd1\xa4",
+       "\xd1\xa7" => "\xd1\xa6",
+       "\xd1\xa9" => "\xd1\xa8",
+       "\xd1\xab" => "\xd1\xaa",
+       "\xd1\xad" => "\xd1\xac",
+       "\xd1\xaf" => "\xd1\xae",
+       "\xd1\xb1" => "\xd1\xb0",
+       "\xd1\xb3" => "\xd1\xb2",
+       "\xd1\xb5" => "\xd1\xb4",
+       "\xd1\xb7" => "\xd1\xb6",
+       "\xd1\xb9" => "\xd1\xb8",
+       "\xd1\xbb" => "\xd1\xba",
+       "\xd1\xbd" => "\xd1\xbc",
+       "\xd1\xbf" => "\xd1\xbe",
+       "\xd2\x81" => "\xd2\x80",
+       "\xd2\x8d" => "\xd2\x8c",
+       "\xd2\x8f" => "\xd2\x8e",
+       "\xd2\x91" => "\xd2\x90",
+       "\xd2\x93" => "\xd2\x92",
+       "\xd2\x95" => "\xd2\x94",
+       "\xd2\x97" => "\xd2\x96",
+       "\xd2\x99" => "\xd2\x98",
+       "\xd2\x9b" => "\xd2\x9a",
+       "\xd2\x9d" => "\xd2\x9c",
+       "\xd2\x9f" => "\xd2\x9e",
+       "\xd2\xa1" => "\xd2\xa0",
+       "\xd2\xa3" => "\xd2\xa2",
+       "\xd2\xa5" => "\xd2\xa4",
+       "\xd2\xa7" => "\xd2\xa6",
+       "\xd2\xa9" => "\xd2\xa8",
+       "\xd2\xab" => "\xd2\xaa",
+       "\xd2\xad" => "\xd2\xac",
+       "\xd2\xaf" => "\xd2\xae",
+       "\xd2\xb1" => "\xd2\xb0",
+       "\xd2\xb3" => "\xd2\xb2",
+       "\xd2\xb5" => "\xd2\xb4",
+       "\xd2\xb7" => "\xd2\xb6",
+       "\xd2\xb9" => "\xd2\xb8",
+       "\xd2\xbb" => "\xd2\xba",
+       "\xd2\xbd" => "\xd2\xbc",
+       "\xd2\xbf" => "\xd2\xbe",
+       "\xd3\x82" => "\xd3\x81",
+       "\xd3\x84" => "\xd3\x83",
+       "\xd3\x88" => "\xd3\x87",
+       "\xd3\x8c" => "\xd3\x8b",
+       "\xd3\x91" => "\xd3\x90",
+       "\xd3\x93" => "\xd3\x92",
+       "\xd3\x95" => "\xd3\x94",
+       "\xd3\x97" => "\xd3\x96",
+       "\xd3\x99" => "\xd3\x98",
+       "\xd3\x9b" => "\xd3\x9a",
+       "\xd3\x9d" => "\xd3\x9c",
+       "\xd3\x9f" => "\xd3\x9e",
+       "\xd3\xa1" => "\xd3\xa0",
+       "\xd3\xa3" => "\xd3\xa2",
+       "\xd3\xa5" => "\xd3\xa4",
+       "\xd3\xa7" => "\xd3\xa6",
+       "\xd3\xa9" => "\xd3\xa8",
+       "\xd3\xab" => "\xd3\xaa",
+       "\xd3\xad" => "\xd3\xac",
+       "\xd3\xaf" => "\xd3\xae",
+       "\xd3\xb1" => "\xd3\xb0",
+       "\xd3\xb3" => "\xd3\xb2",
+       "\xd3\xb5" => "\xd3\xb4",
+       "\xd3\xb9" => "\xd3\xb8",
+       "\xd5\xa1" => "\xd4\xb1",
+       "\xd5\xa2" => "\xd4\xb2",
+       "\xd5\xa3" => "\xd4\xb3",
+       "\xd5\xa4" => "\xd4\xb4",
+       "\xd5\xa5" => "\xd4\xb5",
+       "\xd5\xa6" => "\xd4\xb6",
+       "\xd5\xa7" => "\xd4\xb7",
+       "\xd5\xa8" => "\xd4\xb8",
+       "\xd5\xa9" => "\xd4\xb9",
+       "\xd5\xaa" => "\xd4\xba",
+       "\xd5\xab" => "\xd4\xbb",
+       "\xd5\xac" => "\xd4\xbc",
+       "\xd5\xad" => "\xd4\xbd",
+       "\xd5\xae" => "\xd4\xbe",
+       "\xd5\xaf" => "\xd4\xbf",
+       "\xd5\xb0" => "\xd5\x80",
+       "\xd5\xb1" => "\xd5\x81",
+       "\xd5\xb2" => "\xd5\x82",
+       "\xd5\xb3" => "\xd5\x83",
+       "\xd5\xb4" => "\xd5\x84",
+       "\xd5\xb5" => "\xd5\x85",
+       "\xd5\xb6" => "\xd5\x86",
+       "\xd5\xb7" => "\xd5\x87",
+       "\xd5\xb8" => "\xd5\x88",
+       "\xd5\xb9" => "\xd5\x89",
+       "\xd5\xba" => "\xd5\x8a",
+       "\xd5\xbb" => "\xd5\x8b",
+       "\xd5\xbc" => "\xd5\x8c",
+       "\xd5\xbd" => "\xd5\x8d",
+       "\xd5\xbe" => "\xd5\x8e",
+       "\xd5\xbf" => "\xd5\x8f",
+       "\xd6\x80" => "\xd5\x90",
+       "\xd6\x81" => "\xd5\x91",
+       "\xd6\x82" => "\xd5\x92",
+       "\xd6\x83" => "\xd5\x93",
+       "\xd6\x84" => "\xd5\x94",
+       "\xd6\x85" => "\xd5\x95",
+       "\xd6\x86" => "\xd5\x96",
+       "\xe1\xb8\x81" => "\xe1\xb8\x80",
+       "\xe1\xb8\x83" => "\xe1\xb8\x82",
+       "\xe1\xb8\x85" => "\xe1\xb8\x84",
+       "\xe1\xb8\x87" => "\xe1\xb8\x86",
+       "\xe1\xb8\x89" => "\xe1\xb8\x88",
+       "\xe1\xb8\x8b" => "\xe1\xb8\x8a",
+       "\xe1\xb8\x8d" => "\xe1\xb8\x8c",
+       "\xe1\xb8\x8f" => "\xe1\xb8\x8e",
+       "\xe1\xb8\x91" => "\xe1\xb8\x90",
+       "\xe1\xb8\x93" => "\xe1\xb8\x92",
+       "\xe1\xb8\x95" => "\xe1\xb8\x94",
+       "\xe1\xb8\x97" => "\xe1\xb8\x96",
+       "\xe1\xb8\x99" => "\xe1\xb8\x98",
+       "\xe1\xb8\x9b" => "\xe1\xb8\x9a",
+       "\xe1\xb8\x9d" => "\xe1\xb8\x9c",
+       "\xe1\xb8\x9f" => "\xe1\xb8\x9e",
+       "\xe1\xb8\xa1" => "\xe1\xb8\xa0",
+       "\xe1\xb8\xa3" => "\xe1\xb8\xa2",
+       "\xe1\xb8\xa5" => "\xe1\xb8\xa4",
+       "\xe1\xb8\xa7" => "\xe1\xb8\xa6",
+       "\xe1\xb8\xa9" => "\xe1\xb8\xa8",
+       "\xe1\xb8\xab" => "\xe1\xb8\xaa",
+       "\xe1\xb8\xad" => "\xe1\xb8\xac",
+       "\xe1\xb8\xaf" => "\xe1\xb8\xae",
+       "\xe1\xb8\xb1" => "\xe1\xb8\xb0",
+       "\xe1\xb8\xb3" => "\xe1\xb8\xb2",
+       "\xe1\xb8\xb5" => "\xe1\xb8\xb4",
+       "\xe1\xb8\xb7" => "\xe1\xb8\xb6",
+       "\xe1\xb8\xb9" => "\xe1\xb8\xb8",
+       "\xe1\xb8\xbb" => "\xe1\xb8\xba",
+       "\xe1\xb8\xbd" => "\xe1\xb8\xbc",
+       "\xe1\xb8\xbf" => "\xe1\xb8\xbe",
+       "\xe1\xb9\x81" => "\xe1\xb9\x80",
+       "\xe1\xb9\x83" => "\xe1\xb9\x82",
+       "\xe1\xb9\x85" => "\xe1\xb9\x84",
+       "\xe1\xb9\x87" => "\xe1\xb9\x86",
+       "\xe1\xb9\x89" => "\xe1\xb9\x88",
+       "\xe1\xb9\x8b" => "\xe1\xb9\x8a",
+       "\xe1\xb9\x8d" => "\xe1\xb9\x8c",
+       "\xe1\xb9\x8f" => "\xe1\xb9\x8e",
+       "\xe1\xb9\x91" => "\xe1\xb9\x90",
+       "\xe1\xb9\x93" => "\xe1\xb9\x92",
+       "\xe1\xb9\x95" => "\xe1\xb9\x94",
+       "\xe1\xb9\x97" => "\xe1\xb9\x96",
+       "\xe1\xb9\x99" => "\xe1\xb9\x98",
+       "\xe1\xb9\x9b" => "\xe1\xb9\x9a",
+       "\xe1\xb9\x9d" => "\xe1\xb9\x9c",
+       "\xe1\xb9\x9f" => "\xe1\xb9\x9e",
+       "\xe1\xb9\xa1" => "\xe1\xb9\xa0",
+       "\xe1\xb9\xa3" => "\xe1\xb9\xa2",
+       "\xe1\xb9\xa5" => "\xe1\xb9\xa4",
+       "\xe1\xb9\xa7" => "\xe1\xb9\xa6",
+       "\xe1\xb9\xa9" => "\xe1\xb9\xa8",
+       "\xe1\xb9\xab" => "\xe1\xb9\xaa",
+       "\xe1\xb9\xad" => "\xe1\xb9\xac",
+       "\xe1\xb9\xaf" => "\xe1\xb9\xae",
+       "\xe1\xb9\xb1" => "\xe1\xb9\xb0",
+       "\xe1\xb9\xb3" => "\xe1\xb9\xb2",
+       "\xe1\xb9\xb5" => "\xe1\xb9\xb4",
+       "\xe1\xb9\xb7" => "\xe1\xb9\xb6",
+       "\xe1\xb9\xb9" => "\xe1\xb9\xb8",
+       "\xe1\xb9\xbb" => "\xe1\xb9\xba",
+       "\xe1\xb9\xbd" => "\xe1\xb9\xbc",
+       "\xe1\xb9\xbf" => "\xe1\xb9\xbe",
+       "\xe1\xba\x81" => "\xe1\xba\x80",
+       "\xe1\xba\x83" => "\xe1\xba\x82",
+       "\xe1\xba\x85" => "\xe1\xba\x84",
+       "\xe1\xba\x87" => "\xe1\xba\x86",
+       "\xe1\xba\x89" => "\xe1\xba\x88",
+       "\xe1\xba\x8b" => "\xe1\xba\x8a",
+       "\xe1\xba\x8d" => "\xe1\xba\x8c",
+       "\xe1\xba\x8f" => "\xe1\xba\x8e",
+       "\xe1\xba\x91" => "\xe1\xba\x90",
+       "\xe1\xba\x93" => "\xe1\xba\x92",
+       "\xe1\xba\x95" => "\xe1\xba\x94",
+       "\xe1\xba\x9b" => "\xe1\xb9\xa0",
+       "\xe1\xba\xa1" => "\xe1\xba\xa0",
+       "\xe1\xba\xa3" => "\xe1\xba\xa2",
+       "\xe1\xba\xa5" => "\xe1\xba\xa4",
+       "\xe1\xba\xa7" => "\xe1\xba\xa6",
+       "\xe1\xba\xa9" => "\xe1\xba\xa8",
+       "\xe1\xba\xab" => "\xe1\xba\xaa",
+       "\xe1\xba\xad" => "\xe1\xba\xac",
+       "\xe1\xba\xaf" => "\xe1\xba\xae",
+       "\xe1\xba\xb1" => "\xe1\xba\xb0",
+       "\xe1\xba\xb3" => "\xe1\xba\xb2",
+       "\xe1\xba\xb5" => "\xe1\xba\xb4",
+       "\xe1\xba\xb7" => "\xe1\xba\xb6",
+       "\xe1\xba\xb9" => "\xe1\xba\xb8",
+       "\xe1\xba\xbb" => "\xe1\xba\xba",
+       "\xe1\xba\xbd" => "\xe1\xba\xbc",
+       "\xe1\xba\xbf" => "\xe1\xba\xbe",
+       "\xe1\xbb\x81" => "\xe1\xbb\x80",
+       "\xe1\xbb\x83" => "\xe1\xbb\x82",
+       "\xe1\xbb\x85" => "\xe1\xbb\x84",
+       "\xe1\xbb\x87" => "\xe1\xbb\x86",
+       "\xe1\xbb\x89" => "\xe1\xbb\x88",
+       "\xe1\xbb\x8b" => "\xe1\xbb\x8a",
+       "\xe1\xbb\x8d" => "\xe1\xbb\x8c",
+       "\xe1\xbb\x8f" => "\xe1\xbb\x8e",
+       "\xe1\xbb\x91" => "\xe1\xbb\x90",
+       "\xe1\xbb\x93" => "\xe1\xbb\x92",
+       "\xe1\xbb\x95" => "\xe1\xbb\x94",
+       "\xe1\xbb\x97" => "\xe1\xbb\x96",
+       "\xe1\xbb\x99" => "\xe1\xbb\x98",
+       "\xe1\xbb\x9b" => "\xe1\xbb\x9a",
+       "\xe1\xbb\x9d" => "\xe1\xbb\x9c",
+       "\xe1\xbb\x9f" => "\xe1\xbb\x9e",
+       "\xe1\xbb\xa1" => "\xe1\xbb\xa0",
+       "\xe1\xbb\xa3" => "\xe1\xbb\xa2",
+       "\xe1\xbb\xa5" => "\xe1\xbb\xa4",
+       "\xe1\xbb\xa7" => "\xe1\xbb\xa6",
+       "\xe1\xbb\xa9" => "\xe1\xbb\xa8",
+       "\xe1\xbb\xab" => "\xe1\xbb\xaa",
+       "\xe1\xbb\xad" => "\xe1\xbb\xac",
+       "\xe1\xbb\xaf" => "\xe1\xbb\xae",
+       "\xe1\xbb\xb1" => "\xe1\xbb\xb0",
+       "\xe1\xbb\xb3" => "\xe1\xbb\xb2",
+       "\xe1\xbb\xb5" => "\xe1\xbb\xb4",
+       "\xe1\xbb\xb7" => "\xe1\xbb\xb6",
+       "\xe1\xbb\xb9" => "\xe1\xbb\xb8",
+       "\xe1\xbc\x80" => "\xe1\xbc\x88",
+       "\xe1\xbc\x81" => "\xe1\xbc\x89",
+       "\xe1\xbc\x82" => "\xe1\xbc\x8a",
+       "\xe1\xbc\x83" => "\xe1\xbc\x8b",
+       "\xe1\xbc\x84" => "\xe1\xbc\x8c",
+       "\xe1\xbc\x85" => "\xe1\xbc\x8d",
+       "\xe1\xbc\x86" => "\xe1\xbc\x8e",
+       "\xe1\xbc\x87" => "\xe1\xbc\x8f",
+       "\xe1\xbc\x90" => "\xe1\xbc\x98",
+       "\xe1\xbc\x91" => "\xe1\xbc\x99",
+       "\xe1\xbc\x92" => "\xe1\xbc\x9a",
+       "\xe1\xbc\x93" => "\xe1\xbc\x9b",
+       "\xe1\xbc\x94" => "\xe1\xbc\x9c",
+       "\xe1\xbc\x95" => "\xe1\xbc\x9d",
+       "\xe1\xbc\xa0" => "\xe1\xbc\xa8",
+       "\xe1\xbc\xa1" => "\xe1\xbc\xa9",
+       "\xe1\xbc\xa2" => "\xe1\xbc\xaa",
+       "\xe1\xbc\xa3" => "\xe1\xbc\xab",
+       "\xe1\xbc\xa4" => "\xe1\xbc\xac",
+       "\xe1\xbc\xa5" => "\xe1\xbc\xad",
+       "\xe1\xbc\xa6" => "\xe1\xbc\xae",
+       "\xe1\xbc\xa7" => "\xe1\xbc\xaf",
+       "\xe1\xbc\xb0" => "\xe1\xbc\xb8",
+       "\xe1\xbc\xb1" => "\xe1\xbc\xb9",
+       "\xe1\xbc\xb2" => "\xe1\xbc\xba",
+       "\xe1\xbc\xb3" => "\xe1\xbc\xbb",
+       "\xe1\xbc\xb4" => "\xe1\xbc\xbc",
+       "\xe1\xbc\xb5" => "\xe1\xbc\xbd",
+       "\xe1\xbc\xb6" => "\xe1\xbc\xbe",
+       "\xe1\xbc\xb7" => "\xe1\xbc\xbf",
+       "\xe1\xbd\x80" => "\xe1\xbd\x88",
+       "\xe1\xbd\x81" => "\xe1\xbd\x89",
+       "\xe1\xbd\x82" => "\xe1\xbd\x8a",
+       "\xe1\xbd\x83" => "\xe1\xbd\x8b",
+       "\xe1\xbd\x84" => "\xe1\xbd\x8c",
+       "\xe1\xbd\x85" => "\xe1\xbd\x8d",
+       "\xe1\xbd\x91" => "\xe1\xbd\x99",
+       "\xe1\xbd\x93" => "\xe1\xbd\x9b",
+       "\xe1\xbd\x95" => "\xe1\xbd\x9d",
+       "\xe1\xbd\x97" => "\xe1\xbd\x9f",
+       "\xe1\xbd\xa0" => "\xe1\xbd\xa8",
+       "\xe1\xbd\xa1" => "\xe1\xbd\xa9",
+       "\xe1\xbd\xa2" => "\xe1\xbd\xaa",
+       "\xe1\xbd\xa3" => "\xe1\xbd\xab",
+       "\xe1\xbd\xa4" => "\xe1\xbd\xac",
+       "\xe1\xbd\xa5" => "\xe1\xbd\xad",
+       "\xe1\xbd\xa6" => "\xe1\xbd\xae",
+       "\xe1\xbd\xa7" => "\xe1\xbd\xaf",
+       "\xe1\xbd\xb0" => "\xe1\xbe\xba",
+       "\xe1\xbd\xb1" => "\xe1\xbe\xbb",
+       "\xe1\xbd\xb2" => "\xe1\xbf\x88",
+       "\xe1\xbd\xb3" => "\xe1\xbf\x89",
+       "\xe1\xbd\xb4" => "\xe1\xbf\x8a",
+       "\xe1\xbd\xb5" => "\xe1\xbf\x8b",
+       "\xe1\xbd\xb6" => "\xe1\xbf\x9a",
+       "\xe1\xbd\xb7" => "\xe1\xbf\x9b",
+       "\xe1\xbd\xb8" => "\xe1\xbf\xb8",
+       "\xe1\xbd\xb9" => "\xe1\xbf\xb9",
+       "\xe1\xbd\xba" => "\xe1\xbf\xaa",
+       "\xe1\xbd\xbb" => "\xe1\xbf\xab",
+       "\xe1\xbd\xbc" => "\xe1\xbf\xba",
+       "\xe1\xbd\xbd" => "\xe1\xbf\xbb",
+       "\xe1\xbe\x80" => "\xe1\xbe\x88",
+       "\xe1\xbe\x81" => "\xe1\xbe\x89",
+       "\xe1\xbe\x82" => "\xe1\xbe\x8a",
+       "\xe1\xbe\x83" => "\xe1\xbe\x8b",
+       "\xe1\xbe\x84" => "\xe1\xbe\x8c",
+       "\xe1\xbe\x85" => "\xe1\xbe\x8d",
+       "\xe1\xbe\x86" => "\xe1\xbe\x8e",
+       "\xe1\xbe\x87" => "\xe1\xbe\x8f",
+       "\xe1\xbe\x90" => "\xe1\xbe\x98",
+       "\xe1\xbe\x91" => "\xe1\xbe\x99",
+       "\xe1\xbe\x92" => "\xe1\xbe\x9a",
+       "\xe1\xbe\x93" => "\xe1\xbe\x9b",
+       "\xe1\xbe\x94" => "\xe1\xbe\x9c",
+       "\xe1\xbe\x95" => "\xe1\xbe\x9d",
+       "\xe1\xbe\x96" => "\xe1\xbe\x9e",
+       "\xe1\xbe\x97" => "\xe1\xbe\x9f",
+       "\xe1\xbe\xa0" => "\xe1\xbe\xa8",
+       "\xe1\xbe\xa1" => "\xe1\xbe\xa9",
+       "\xe1\xbe\xa2" => "\xe1\xbe\xaa",
+       "\xe1\xbe\xa3" => "\xe1\xbe\xab",
+       "\xe1\xbe\xa4" => "\xe1\xbe\xac",
+       "\xe1\xbe\xa5" => "\xe1\xbe\xad",
+       "\xe1\xbe\xa6" => "\xe1\xbe\xae",
+       "\xe1\xbe\xa7" => "\xe1\xbe\xaf",
+       "\xe1\xbe\xb0" => "\xe1\xbe\xb8",
+       "\xe1\xbe\xb1" => "\xe1\xbe\xb9",
+       "\xe1\xbe\xb3" => "\xe1\xbe\xbc",
+       "\xe1\xbe\xbe" => "\xce\x99",
+       "\xe1\xbf\x83" => "\xe1\xbf\x8c",
+       "\xe1\xbf\x90" => "\xe1\xbf\x98",
+       "\xe1\xbf\x91" => "\xe1\xbf\x99",
+       "\xe1\xbf\xa0" => "\xe1\xbf\xa8",
+       "\xe1\xbf\xa1" => "\xe1\xbf\xa9",
+       "\xe1\xbf\xa5" => "\xe1\xbf\xac",
+       "\xe1\xbf\xb3" => "\xe1\xbf\xbc",
+       "\xe2\x85\xb0" => "\xe2\x85\xa0",
+       "\xe2\x85\xb1" => "\xe2\x85\xa1",
+       "\xe2\x85\xb2" => "\xe2\x85\xa2",
+       "\xe2\x85\xb3" => "\xe2\x85\xa3",
+       "\xe2\x85\xb4" => "\xe2\x85\xa4",
+       "\xe2\x85\xb5" => "\xe2\x85\xa5",
+       "\xe2\x85\xb6" => "\xe2\x85\xa6",
+       "\xe2\x85\xb7" => "\xe2\x85\xa7",
+       "\xe2\x85\xb8" => "\xe2\x85\xa8",
+       "\xe2\x85\xb9" => "\xe2\x85\xa9",
+       "\xe2\x85\xba" => "\xe2\x85\xaa",
+       "\xe2\x85\xbb" => "\xe2\x85\xab",
+       "\xe2\x85\xbc" => "\xe2\x85\xac",
+       "\xe2\x85\xbd" => "\xe2\x85\xad",
+       "\xe2\x85\xbe" => "\xe2\x85\xae",
+       "\xe2\x85\xbf" => "\xe2\x85\xaf",
+       "\xe2\x93\x90" => "\xe2\x92\xb6",
+       "\xe2\x93\x91" => "\xe2\x92\xb7",
+       "\xe2\x93\x92" => "\xe2\x92\xb8",
+       "\xe2\x93\x93" => "\xe2\x92\xb9",
+       "\xe2\x93\x94" => "\xe2\x92\xba",
+       "\xe2\x93\x95" => "\xe2\x92\xbb",
+       "\xe2\x93\x96" => "\xe2\x92\xbc",
+       "\xe2\x93\x97" => "\xe2\x92\xbd",
+       "\xe2\x93\x98" => "\xe2\x92\xbe",
+       "\xe2\x93\x99" => "\xe2\x92\xbf",
+       "\xe2\x93\x9a" => "\xe2\x93\x80",
+       "\xe2\x93\x9b" => "\xe2\x93\x81",
+       "\xe2\x93\x9c" => "\xe2\x93\x82",
+       "\xe2\x93\x9d" => "\xe2\x93\x83",
+       "\xe2\x93\x9e" => "\xe2\x93\x84",
+       "\xe2\x93\x9f" => "\xe2\x93\x85",
+       "\xe2\x93\xa0" => "\xe2\x93\x86",
+       "\xe2\x93\xa1" => "\xe2\x93\x87",
+       "\xe2\x93\xa2" => "\xe2\x93\x88",
+       "\xe2\x93\xa3" => "\xe2\x93\x89",
+       "\xe2\x93\xa4" => "\xe2\x93\x8a",
+       "\xe2\x93\xa5" => "\xe2\x93\x8b",
+       "\xe2\x93\xa6" => "\xe2\x93\x8c",
+       "\xe2\x93\xa7" => "\xe2\x93\x8d",
+       "\xe2\x93\xa8" => "\xe2\x93\x8e",
+       "\xe2\x93\xa9" => "\xe2\x93\x8f",
+       "\xef\xbd\x81" => "\xef\xbc\xa1",
+       "\xef\xbd\x82" => "\xef\xbc\xa2",
+       "\xef\xbd\x83" => "\xef\xbc\xa3",
+       "\xef\xbd\x84" => "\xef\xbc\xa4",
+       "\xef\xbd\x85" => "\xef\xbc\xa5",
+       "\xef\xbd\x86" => "\xef\xbc\xa6",
+       "\xef\xbd\x87" => "\xef\xbc\xa7",
+       "\xef\xbd\x88" => "\xef\xbc\xa8",
+       "\xef\xbd\x89" => "\xef\xbc\xa9",
+       "\xef\xbd\x8a" => "\xef\xbc\xaa",
+       "\xef\xbd\x8b" => "\xef\xbc\xab",
+       "\xef\xbd\x8c" => "\xef\xbc\xac",
+       "\xef\xbd\x8d" => "\xef\xbc\xad",
+       "\xef\xbd\x8e" => "\xef\xbc\xae",
+       "\xef\xbd\x8f" => "\xef\xbc\xaf",
+       "\xef\xbd\x90" => "\xef\xbc\xb0",
+       "\xef\xbd\x91" => "\xef\xbc\xb1",
+       "\xef\xbd\x92" => "\xef\xbc\xb2",
+       "\xef\xbd\x93" => "\xef\xbc\xb3",
+       "\xef\xbd\x94" => "\xef\xbc\xb4",
+       "\xef\xbd\x95" => "\xef\xbc\xb5",
+       "\xef\xbd\x96" => "\xef\xbc\xb6",
+       "\xef\xbd\x97" => "\xef\xbc\xb7",
+       "\xef\xbd\x98" => "\xef\xbc\xb8",
+       "\xef\xbd\x99" => "\xef\xbc\xb9",
+       "\xef\xbd\x9a" => "\xef\xbc\xba",
+       "\xf0\x90\x90\xa8" => "\xf0\x90\x90\x80",
+       "\xf0\x90\x90\xa9" => "\xf0\x90\x90\x81",
+       "\xf0\x90\x90\xaa" => "\xf0\x90\x90\x82",
+       "\xf0\x90\x90\xab" => "\xf0\x90\x90\x83",
+       "\xf0\x90\x90\xac" => "\xf0\x90\x90\x84",
+       "\xf0\x90\x90\xad" => "\xf0\x90\x90\x85",
+       "\xf0\x90\x90\xae" => "\xf0\x90\x90\x86",
+       "\xf0\x90\x90\xaf" => "\xf0\x90\x90\x87",
+       "\xf0\x90\x90\xb0" => "\xf0\x90\x90\x88",
+       "\xf0\x90\x90\xb1" => "\xf0\x90\x90\x89",
+       "\xf0\x90\x90\xb2" => "\xf0\x90\x90\x8a",
+       "\xf0\x90\x90\xb3" => "\xf0\x90\x90\x8b",
+       "\xf0\x90\x90\xb4" => "\xf0\x90\x90\x8c",
+       "\xf0\x90\x90\xb5" => "\xf0\x90\x90\x8d",
+       "\xf0\x90\x90\xb6" => "\xf0\x90\x90\x8e",
+       "\xf0\x90\x90\xb7" => "\xf0\x90\x90\x8f",
+       "\xf0\x90\x90\xb8" => "\xf0\x90\x90\x90",
+       "\xf0\x90\x90\xb9" => "\xf0\x90\x90\x91",
+       "\xf0\x90\x90\xba" => "\xf0\x90\x90\x92",
+       "\xf0\x90\x90\xbb" => "\xf0\x90\x90\x93",
+       "\xf0\x90\x90\xbc" => "\xf0\x90\x90\x94",
+       "\xf0\x90\x90\xbd" => "\xf0\x90\x90\x95",
+       "\xf0\x90\x90\xbe" => "\xf0\x90\x90\x96",
+       "\xf0\x90\x90\xbf" => "\xf0\x90\x90\x97",
+       "\xf0\x90\x91\x80" => "\xf0\x90\x90\x98",
+       "\xf0\x90\x91\x81" => "\xf0\x90\x90\x99",
+       "\xf0\x90\x91\x82" => "\xf0\x90\x90\x9a",
+       "\xf0\x90\x91\x83" => "\xf0\x90\x90\x9b",
+       "\xf0\x90\x91\x84" => "\xf0\x90\x90\x9c",
+       "\xf0\x90\x91\x85" => "\xf0\x90\x90\x9d",
+       "\xf0\x90\x91\x86" => "\xf0\x90\x90\x9e",
+       "\xf0\x90\x91\x87" => "\xf0\x90\x90\x9f",
+       "\xf0\x90\x91\x88" => "\xf0\x90\x90\xa0",
+       "\xf0\x90\x91\x89" => "\xf0\x90\x90\xa1",
+       "\xf0\x90\x91\x8a" => "\xf0\x90\x90\xa2",
+       "\xf0\x90\x91\x8b" => "\xf0\x90\x90\xa3",
+       "\xf0\x90\x91\x8c" => "\xf0\x90\x90\xa4",
+       "\xf0\x90\x91\x8d" => "\xf0\x90\x90\xa5"
+);
+
+/*
+ * Translation array to get lower case character
+ */
+$wikiLowerChars = array (
+       "A" => "a",
+       "B" => "b",
+       "C" => "c",
+       "D" => "d",
+       "E" => "e",
+       "F" => "f",
+       "G" => "g",
+       "H" => "h",
+       "I" => "i",
+       "J" => "j",
+       "K" => "k",
+       "L" => "l",
+       "M" => "m",
+       "N" => "n",
+       "O" => "o",
+       "P" => "p",
+       "Q" => "q",
+       "R" => "r",
+       "S" => "s",
+       "T" => "t",
+       "U" => "u",
+       "V" => "v",
+       "W" => "w",
+       "X" => "x",
+       "Y" => "y",
+       "Z" => "z",
+       "\xc3\x80" => "\xc3\xa0",
+       "\xc3\x81" => "\xc3\xa1",
+       "\xc3\x82" => "\xc3\xa2",
+       "\xc3\x83" => "\xc3\xa3",
+       "\xc3\x84" => "\xc3\xa4",
+       "\xc3\x85" => "\xc3\xa5",
+       "\xc3\x86" => "\xc3\xa6",
+       "\xc3\x87" => "\xc3\xa7",
+       "\xc3\x88" => "\xc3\xa8",
+       "\xc3\x89" => "\xc3\xa9",
+       "\xc3\x8a" => "\xc3\xaa",
+       "\xc3\x8b" => "\xc3\xab",
+       "\xc3\x8c" => "\xc3\xac",
+       "\xc3\x8d" => "\xc3\xad",
+       "\xc3\x8e" => "\xc3\xae",
+       "\xc3\x8f" => "\xc3\xaf",
+       "\xc3\x90" => "\xc3\xb0",
+       "\xc3\x91" => "\xc3\xb1",
+       "\xc3\x92" => "\xc3\xb2",
+       "\xc3\x93" => "\xc3\xb3",
+       "\xc3\x94" => "\xc3\xb4",
+       "\xc3\x95" => "\xc3\xb5",
+       "\xc3\x96" => "\xc3\xb6",
+       "\xc3\x98" => "\xc3\xb8",
+       "\xc3\x99" => "\xc3\xb9",
+       "\xc3\x9a" => "\xc3\xba",
+       "\xc3\x9b" => "\xc3\xbb",
+       "\xc3\x9c" => "\xc3\xbc",
+       "\xc3\x9d" => "\xc3\xbd",
+       "\xc3\x9e" => "\xc3\xbe",
+       "\xc4\x80" => "\xc4\x81",
+       "\xc4\x82" => "\xc4\x83",
+       "\xc4\x84" => "\xc4\x85",
+       "\xc4\x86" => "\xc4\x87",
+       "\xc4\x88" => "\xc4\x89",
+       "\xc4\x8a" => "\xc4\x8b",
+       "\xc4\x8c" => "\xc4\x8d",
+       "\xc4\x8e" => "\xc4\x8f",
+       "\xc4\x90" => "\xc4\x91",
+       "\xc4\x92" => "\xc4\x93",
+       "\xc4\x94" => "\xc4\x95",
+       "\xc4\x96" => "\xc4\x97",
+       "\xc4\x98" => "\xc4\x99",
+       "\xc4\x9a" => "\xc4\x9b",
+       "\xc4\x9c" => "\xc4\x9d",
+       "\xc4\x9e" => "\xc4\x9f",
+       "\xc4\xa0" => "\xc4\xa1",
+       "\xc4\xa2" => "\xc4\xa3",
+       "\xc4\xa4" => "\xc4\xa5",
+       "\xc4\xa6" => "\xc4\xa7",
+       "\xc4\xa8" => "\xc4\xa9",
+       "\xc4\xaa" => "\xc4\xab",
+       "\xc4\xac" => "\xc4\xad",
+       "\xc4\xae" => "\xc4\xaf",
+       "\xc4\xb0" => "i",
+       "\xc4\xb2" => "\xc4\xb3",
+       "\xc4\xb4" => "\xc4\xb5",
+       "\xc4\xb6" => "\xc4\xb7",
+       "\xc4\xb9" => "\xc4\xba",
+       "\xc4\xbb" => "\xc4\xbc",
+       "\xc4\xbd" => "\xc4\xbe",
+       "\xc4\xbf" => "\xc5\x80",
+       "\xc5\x81" => "\xc5\x82",
+       "\xc5\x83" => "\xc5\x84",
+       "\xc5\x85" => "\xc5\x86",
+       "\xc5\x87" => "\xc5\x88",
+       "\xc5\x8a" => "\xc5\x8b",
+       "\xc5\x8c" => "\xc5\x8d",
+       "\xc5\x8e" => "\xc5\x8f",
+       "\xc5\x90" => "\xc5\x91",
+       "\xc5\x92" => "\xc5\x93",
+       "\xc5\x94" => "\xc5\x95",
+       "\xc5\x96" => "\xc5\x97",
+       "\xc5\x98" => "\xc5\x99",
+       "\xc5\x9a" => "\xc5\x9b",
+       "\xc5\x9c" => "\xc5\x9d",
+       "\xc5\x9e" => "\xc5\x9f",
+       "\xc5\xa0" => "\xc5\xa1",
+       "\xc5\xa2" => "\xc5\xa3",
+       "\xc5\xa4" => "\xc5\xa5",
+       "\xc5\xa6" => "\xc5\xa7",
+       "\xc5\xa8" => "\xc5\xa9",
+       "\xc5\xaa" => "\xc5\xab",
+       "\xc5\xac" => "\xc5\xad",
+       "\xc5\xae" => "\xc5\xaf",
+       "\xc5\xb0" => "\xc5\xb1",
+       "\xc5\xb2" => "\xc5\xb3",
+       "\xc5\xb4" => "\xc5\xb5",
+       "\xc5\xb6" => "\xc5\xb7",
+       "\xc5\xb8" => "\xc3\xbf",
+       "\xc5\xb9" => "\xc5\xba",
+       "\xc5\xbb" => "\xc5\xbc",
+       "\xc5\xbd" => "\xc5\xbe",
+       "\xc6\x81" => "\xc9\x93",
+       "\xc6\x82" => "\xc6\x83",
+       "\xc6\x84" => "\xc6\x85",
+       "\xc6\x86" => "\xc9\x94",
+       "\xc6\x87" => "\xc6\x88",
+       "\xc6\x89" => "\xc9\x96",
+       "\xc6\x8a" => "\xc9\x97",
+       "\xc6\x8b" => "\xc6\x8c",
+       "\xc6\x8e" => "\xc7\x9d",
+       "\xc6\x8f" => "\xc9\x99",
+       "\xc6\x90" => "\xc9\x9b",
+       "\xc6\x91" => "\xc6\x92",
+       "\xc6\x93" => "\xc9\xa0",
+       "\xc6\x94" => "\xc9\xa3",
+       "\xc6\x96" => "\xc9\xa9",
+       "\xc6\x97" => "\xc9\xa8",
+       "\xc6\x98" => "\xc6\x99",
+       "\xc6\x9c" => "\xc9\xaf",
+       "\xc6\x9d" => "\xc9\xb2",
+       "\xc6\x9f" => "\xc9\xb5",
+       "\xc6\xa0" => "\xc6\xa1",
+       "\xc6\xa2" => "\xc6\xa3",
+       "\xc6\xa4" => "\xc6\xa5",
+       "\xc6\xa6" => "\xca\x80",
+       "\xc6\xa7" => "\xc6\xa8",
+       "\xc6\xa9" => "\xca\x83",
+       "\xc6\xac" => "\xc6\xad",
+       "\xc6\xae" => "\xca\x88",
+       "\xc6\xaf" => "\xc6\xb0",
+       "\xc6\xb1" => "\xca\x8a",
+       "\xc6\xb2" => "\xca\x8b",
+       "\xc6\xb3" => "\xc6\xb4",
+       "\xc6\xb5" => "\xc6\xb6",
+       "\xc6\xb7" => "\xca\x92",
+       "\xc6\xb8" => "\xc6\xb9",
+       "\xc6\xbc" => "\xc6\xbd",
+       "\xc7\x84" => "\xc7\x86",
+       "\xc7\x85" => "\xc7\x86",
+       "\xc7\x87" => "\xc7\x89",
+       "\xc7\x88" => "\xc7\x89",
+       "\xc7\x8a" => "\xc7\x8c",
+       "\xc7\x8b" => "\xc7\x8c",
+       "\xc7\x8d" => "\xc7\x8e",
+       "\xc7\x8f" => "\xc7\x90",
+       "\xc7\x91" => "\xc7\x92",
+       "\xc7\x93" => "\xc7\x94",
+       "\xc7\x95" => "\xc7\x96",
+       "\xc7\x97" => "\xc7\x98",
+       "\xc7\x99" => "\xc7\x9a",
+       "\xc7\x9b" => "\xc7\x9c",
+       "\xc7\x9e" => "\xc7\x9f",
+       "\xc7\xa0" => "\xc7\xa1",
+       "\xc7\xa2" => "\xc7\xa3",
+       "\xc7\xa4" => "\xc7\xa5",
+       "\xc7\xa6" => "\xc7\xa7",
+       "\xc7\xa8" => "\xc7\xa9",
+       "\xc7\xaa" => "\xc7\xab",
+       "\xc7\xac" => "\xc7\xad",
+       "\xc7\xae" => "\xc7\xaf",
+       "\xc7\xb1" => "\xc7\xb3",
+       "\xc7\xb2" => "\xc7\xb3",
+       "\xc7\xb4" => "\xc7\xb5",
+       "\xc7\xb6" => "\xc6\x95",
+       "\xc7\xb7" => "\xc6\xbf",
+       "\xc7\xb8" => "\xc7\xb9",
+       "\xc7\xba" => "\xc7\xbb",
+       "\xc7\xbc" => "\xc7\xbd",
+       "\xc7\xbe" => "\xc7\xbf",
+       "\xc8\x80" => "\xc8\x81",
+       "\xc8\x82" => "\xc8\x83",
+       "\xc8\x84" => "\xc8\x85",
+       "\xc8\x86" => "\xc8\x87",
+       "\xc8\x88" => "\xc8\x89",
+       "\xc8\x8a" => "\xc8\x8b",
+       "\xc8\x8c" => "\xc8\x8d",
+       "\xc8\x8e" => "\xc8\x8f",
+       "\xc8\x90" => "\xc8\x91",
+       "\xc8\x92" => "\xc8\x93",
+       "\xc8\x94" => "\xc8\x95",
+       "\xc8\x96" => "\xc8\x97",
+       "\xc8\x98" => "\xc8\x99",
+       "\xc8\x9a" => "\xc8\x9b",
+       "\xc8\x9c" => "\xc8\x9d",
+       "\xc8\x9e" => "\xc8\x9f",
+       "\xc8\xa2" => "\xc8\xa3",
+       "\xc8\xa4" => "\xc8\xa5",
+       "\xc8\xa6" => "\xc8\xa7",
+       "\xc8\xa8" => "\xc8\xa9",
+       "\xc8\xaa" => "\xc8\xab",
+       "\xc8\xac" => "\xc8\xad",
+       "\xc8\xae" => "\xc8\xaf",
+       "\xc8\xb0" => "\xc8\xb1",
+       "\xc8\xb2" => "\xc8\xb3",
+       "\xce\x86" => "\xce\xac",
+       "\xce\x88" => "\xce\xad",
+       "\xce\x89" => "\xce\xae",
+       "\xce\x8a" => "\xce\xaf",
+       "\xce\x8c" => "\xcf\x8c",
+       "\xce\x8e" => "\xcf\x8d",
+       "\xce\x8f" => "\xcf\x8e",
+       "\xce\x91" => "\xce\xb1",
+       "\xce\x92" => "\xce\xb2",
+       "\xce\x93" => "\xce\xb3",
+       "\xce\x94" => "\xce\xb4",
+       "\xce\x95" => "\xce\xb5",
+       "\xce\x96" => "\xce\xb6",
+       "\xce\x97" => "\xce\xb7",
+       "\xce\x98" => "\xce\xb8",
+       "\xce\x99" => "\xce\xb9",
+       "\xce\x9a" => "\xce\xba",
+       "\xce\x9b" => "\xce\xbb",
+       "\xce\x9c" => "\xce\xbc",
+       "\xce\x9d" => "\xce\xbd",
+       "\xce\x9e" => "\xce\xbe",
+       "\xce\x9f" => "\xce\xbf",
+       "\xce\xa0" => "\xcf\x80",
+       "\xce\xa1" => "\xcf\x81",
+       "\xce\xa3" => "\xcf\x83",
+       "\xce\xa4" => "\xcf\x84",
+       "\xce\xa5" => "\xcf\x85",
+       "\xce\xa6" => "\xcf\x86",
+       "\xce\xa7" => "\xcf\x87",
+       "\xce\xa8" => "\xcf\x88",
+       "\xce\xa9" => "\xcf\x89",
+       "\xce\xaa" => "\xcf\x8a",
+       "\xce\xab" => "\xcf\x8b",
+       "\xcf\x9a" => "\xcf\x9b",
+       "\xcf\x9c" => "\xcf\x9d",
+       "\xcf\x9e" => "\xcf\x9f",
+       "\xcf\xa0" => "\xcf\xa1",
+       "\xcf\xa2" => "\xcf\xa3",
+       "\xcf\xa4" => "\xcf\xa5",
+       "\xcf\xa6" => "\xcf\xa7",
+       "\xcf\xa8" => "\xcf\xa9",
+       "\xcf\xaa" => "\xcf\xab",
+       "\xcf\xac" => "\xcf\xad",
+       "\xcf\xae" => "\xcf\xaf",
+       "\xcf\xb4" => "\xce\xb8",
+       "\xd0\x80" => "\xd1\x90",
+       "\xd0\x81" => "\xd1\x91",
+       "\xd0\x82" => "\xd1\x92",
+       "\xd0\x83" => "\xd1\x93",
+       "\xd0\x84" => "\xd1\x94",
+       "\xd0\x85" => "\xd1\x95",
+       "\xd0\x86" => "\xd1\x96",
+       "\xd0\x87" => "\xd1\x97",
+       "\xd0\x88" => "\xd1\x98",
+       "\xd0\x89" => "\xd1\x99",
+       "\xd0\x8a" => "\xd1\x9a",
+       "\xd0\x8b" => "\xd1\x9b",
+       "\xd0\x8c" => "\xd1\x9c",
+       "\xd0\x8d" => "\xd1\x9d",
+       "\xd0\x8e" => "\xd1\x9e",
+       "\xd0\x8f" => "\xd1\x9f",
+       "\xd0\x90" => "\xd0\xb0",
+       "\xd0\x91" => "\xd0\xb1",
+       "\xd0\x92" => "\xd0\xb2",
+       "\xd0\x93" => "\xd0\xb3",
+       "\xd0\x94" => "\xd0\xb4",
+       "\xd0\x95" => "\xd0\xb5",
+       "\xd0\x96" => "\xd0\xb6",
+       "\xd0\x97" => "\xd0\xb7",
+       "\xd0\x98" => "\xd0\xb8",
+       "\xd0\x99" => "\xd0\xb9",
+       "\xd0\x9a" => "\xd0\xba",
+       "\xd0\x9b" => "\xd0\xbb",
+       "\xd0\x9c" => "\xd0\xbc",
+       "\xd0\x9d" => "\xd0\xbd",
+       "\xd0\x9e" => "\xd0\xbe",
+       "\xd0\x9f" => "\xd0\xbf",
+       "\xd0\xa0" => "\xd1\x80",
+       "\xd0\xa1" => "\xd1\x81",
+       "\xd0\xa2" => "\xd1\x82",
+       "\xd0\xa3" => "\xd1\x83",
+       "\xd0\xa4" => "\xd1\x84",
+       "\xd0\xa5" => "\xd1\x85",
+       "\xd0\xa6" => "\xd1\x86",
+       "\xd0\xa7" => "\xd1\x87",
+       "\xd0\xa8" => "\xd1\x88",
+       "\xd0\xa9" => "\xd1\x89",
+       "\xd0\xaa" => "\xd1\x8a",
+       "\xd0\xab" => "\xd1\x8b",
+       "\xd0\xac" => "\xd1\x8c",
+       "\xd0\xad" => "\xd1\x8d",
+       "\xd0\xae" => "\xd1\x8e",
+       "\xd0\xaf" => "\xd1\x8f",
+       "\xd1\xa0" => "\xd1\xa1",
+       "\xd1\xa2" => "\xd1\xa3",
+       "\xd1\xa4" => "\xd1\xa5",
+       "\xd1\xa6" => "\xd1\xa7",
+       "\xd1\xa8" => "\xd1\xa9",
+       "\xd1\xaa" => "\xd1\xab",
+       "\xd1\xac" => "\xd1\xad",
+       "\xd1\xae" => "\xd1\xaf",
+       "\xd1\xb0" => "\xd1\xb1",
+       "\xd1\xb2" => "\xd1\xb3",
+       "\xd1\xb4" => "\xd1\xb5",
+       "\xd1\xb6" => "\xd1\xb7",
+       "\xd1\xb8" => "\xd1\xb9",
+       "\xd1\xba" => "\xd1\xbb",
+       "\xd1\xbc" => "\xd1\xbd",
+       "\xd1\xbe" => "\xd1\xbf",
+       "\xd2\x80" => "\xd2\x81",
+       "\xd2\x8c" => "\xd2\x8d",
+       "\xd2\x8e" => "\xd2\x8f",
+       "\xd2\x90" => "\xd2\x91",
+       "\xd2\x92" => "\xd2\x93",
+       "\xd2\x94" => "\xd2\x95",
+       "\xd2\x96" => "\xd2\x97",
+       "\xd2\x98" => "\xd2\x99",
+       "\xd2\x9a" => "\xd2\x9b",
+       "\xd2\x9c" => "\xd2\x9d",
+       "\xd2\x9e" => "\xd2\x9f",
+       "\xd2\xa0" => "\xd2\xa1",
+       "\xd2\xa2" => "\xd2\xa3",
+       "\xd2\xa4" => "\xd2\xa5",
+       "\xd2\xa6" => "\xd2\xa7",
+       "\xd2\xa8" => "\xd2\xa9",
+       "\xd2\xaa" => "\xd2\xab",
+       "\xd2\xac" => "\xd2\xad",
+       "\xd2\xae" => "\xd2\xaf",
+       "\xd2\xb0" => "\xd2\xb1",
+       "\xd2\xb2" => "\xd2\xb3",
+       "\xd2\xb4" => "\xd2\xb5",
+       "\xd2\xb6" => "\xd2\xb7",
+       "\xd2\xb8" => "\xd2\xb9",
+       "\xd2\xba" => "\xd2\xbb",
+       "\xd2\xbc" => "\xd2\xbd",
+       "\xd2\xbe" => "\xd2\xbf",
+       "\xd3\x81" => "\xd3\x82",
+       "\xd3\x83" => "\xd3\x84",
+       "\xd3\x87" => "\xd3\x88",
+       "\xd3\x8b" => "\xd3\x8c",
+       "\xd3\x90" => "\xd3\x91",
+       "\xd3\x92" => "\xd3\x93",
+       "\xd3\x94" => "\xd3\x95",
+       "\xd3\x96" => "\xd3\x97",
+       "\xd3\x98" => "\xd3\x99",
+       "\xd3\x9a" => "\xd3\x9b",
+       "\xd3\x9c" => "\xd3\x9d",
+       "\xd3\x9e" => "\xd3\x9f",
+       "\xd3\xa0" => "\xd3\xa1",
+       "\xd3\xa2" => "\xd3\xa3",
+       "\xd3\xa4" => "\xd3\xa5",
+       "\xd3\xa6" => "\xd3\xa7",
+       "\xd3\xa8" => "\xd3\xa9",
+       "\xd3\xaa" => "\xd3\xab",
+       "\xd3\xac" => "\xd3\xad",
+       "\xd3\xae" => "\xd3\xaf",
+       "\xd3\xb0" => "\xd3\xb1",
+       "\xd3\xb2" => "\xd3\xb3",
+       "\xd3\xb4" => "\xd3\xb5",
+       "\xd3\xb8" => "\xd3\xb9",
+       "\xd4\xb1" => "\xd5\xa1",
+       "\xd4\xb2" => "\xd5\xa2",
+       "\xd4\xb3" => "\xd5\xa3",
+       "\xd4\xb4" => "\xd5\xa4",
+       "\xd4\xb5" => "\xd5\xa5",
+       "\xd4\xb6" => "\xd5\xa6",
+       "\xd4\xb7" => "\xd5\xa7",
+       "\xd4\xb8" => "\xd5\xa8",
+       "\xd4\xb9" => "\xd5\xa9",
+       "\xd4\xba" => "\xd5\xaa",
+       "\xd4\xbb" => "\xd5\xab",
+       "\xd4\xbc" => "\xd5\xac",
+       "\xd4\xbd" => "\xd5\xad",
+       "\xd4\xbe" => "\xd5\xae",
+       "\xd4\xbf" => "\xd5\xaf",
+       "\xd5\x80" => "\xd5\xb0",
+       "\xd5\x81" => "\xd5\xb1",
+       "\xd5\x82" => "\xd5\xb2",
+       "\xd5\x83" => "\xd5\xb3",
+       "\xd5\x84" => "\xd5\xb4",
+       "\xd5\x85" => "\xd5\xb5",
+       "\xd5\x86" => "\xd5\xb6",
+       "\xd5\x87" => "\xd5\xb7",
+       "\xd5\x88" => "\xd5\xb8",
+       "\xd5\x89" => "\xd5\xb9",
+       "\xd5\x8a" => "\xd5\xba",
+       "\xd5\x8b" => "\xd5\xbb",
+       "\xd5\x8c" => "\xd5\xbc",
+       "\xd5\x8d" => "\xd5\xbd",
+       "\xd5\x8e" => "\xd5\xbe",
+       "\xd5\x8f" => "\xd5\xbf",
+       "\xd5\x90" => "\xd6\x80",
+       "\xd5\x91" => "\xd6\x81",
+       "\xd5\x92" => "\xd6\x82",
+       "\xd5\x93" => "\xd6\x83",
+       "\xd5\x94" => "\xd6\x84",
+       "\xd5\x95" => "\xd6\x85",
+       "\xd5\x96" => "\xd6\x86",
+       "\xe1\xb8\x80" => "\xe1\xb8\x81",
+       "\xe1\xb8\x82" => "\xe1\xb8\x83",
+       "\xe1\xb8\x84" => "\xe1\xb8\x85",
+       "\xe1\xb8\x86" => "\xe1\xb8\x87",
+       "\xe1\xb8\x88" => "\xe1\xb8\x89",
+       "\xe1\xb8\x8a" => "\xe1\xb8\x8b",
+       "\xe1\xb8\x8c" => "\xe1\xb8\x8d",
+       "\xe1\xb8\x8e" => "\xe1\xb8\x8f",
+       "\xe1\xb8\x90" => "\xe1\xb8\x91",
+       "\xe1\xb8\x92" => "\xe1\xb8\x93",
+       "\xe1\xb8\x94" => "\xe1\xb8\x95",
+       "\xe1\xb8\x96" => "\xe1\xb8\x97",
+       "\xe1\xb8\x98" => "\xe1\xb8\x99",
+       "\xe1\xb8\x9a" => "\xe1\xb8\x9b",
+       "\xe1\xb8\x9c" => "\xe1\xb8\x9d",
+       "\xe1\xb8\x9e" => "\xe1\xb8\x9f",
+       "\xe1\xb8\xa0" => "\xe1\xb8\xa1",
+       "\xe1\xb8\xa2" => "\xe1\xb8\xa3",
+       "\xe1\xb8\xa4" => "\xe1\xb8\xa5",
+       "\xe1\xb8\xa6" => "\xe1\xb8\xa7",
+       "\xe1\xb8\xa8" => "\xe1\xb8\xa9",
+       "\xe1\xb8\xaa" => "\xe1\xb8\xab",
+       "\xe1\xb8\xac" => "\xe1\xb8\xad",
+       "\xe1\xb8\xae" => "\xe1\xb8\xaf",
+       "\xe1\xb8\xb0" => "\xe1\xb8\xb1",
+       "\xe1\xb8\xb2" => "\xe1\xb8\xb3",
+       "\xe1\xb8\xb4" => "\xe1\xb8\xb5",
+       "\xe1\xb8\xb6" => "\xe1\xb8\xb7",
+       "\xe1\xb8\xb8" => "\xe1\xb8\xb9",
+       "\xe1\xb8\xba" => "\xe1\xb8\xbb",
+       "\xe1\xb8\xbc" => "\xe1\xb8\xbd",
+       "\xe1\xb8\xbe" => "\xe1\xb8\xbf",
+       "\xe1\xb9\x80" => "\xe1\xb9\x81",
+       "\xe1\xb9\x82" => "\xe1\xb9\x83",
+       "\xe1\xb9\x84" => "\xe1\xb9\x85",
+       "\xe1\xb9\x86" => "\xe1\xb9\x87",
+       "\xe1\xb9\x88" => "\xe1\xb9\x89",
+       "\xe1\xb9\x8a" => "\xe1\xb9\x8b",
+       "\xe1\xb9\x8c" => "\xe1\xb9\x8d",
+       "\xe1\xb9\x8e" => "\xe1\xb9\x8f",
+       "\xe1\xb9\x90" => "\xe1\xb9\x91",
+       "\xe1\xb9\x92" => "\xe1\xb9\x93",
+       "\xe1\xb9\x94" => "\xe1\xb9\x95",
+       "\xe1\xb9\x96" => "\xe1\xb9\x97",
+       "\xe1\xb9\x98" => "\xe1\xb9\x99",
+       "\xe1\xb9\x9a" => "\xe1\xb9\x9b",
+       "\xe1\xb9\x9c" => "\xe1\xb9\x9d",
+       "\xe1\xb9\x9e" => "\xe1\xb9\x9f",
+       "\xe1\xb9\xa0" => "\xe1\xb9\xa1",
+       "\xe1\xb9\xa2" => "\xe1\xb9\xa3",
+       "\xe1\xb9\xa4" => "\xe1\xb9\xa5",
+       "\xe1\xb9\xa6" => "\xe1\xb9\xa7",
+       "\xe1\xb9\xa8" => "\xe1\xb9\xa9",
+       "\xe1\xb9\xaa" => "\xe1\xb9\xab",
+       "\xe1\xb9\xac" => "\xe1\xb9\xad",
+       "\xe1\xb9\xae" => "\xe1\xb9\xaf",
+       "\xe1\xb9\xb0" => "\xe1\xb9\xb1",
+       "\xe1\xb9\xb2" => "\xe1\xb9\xb3",
+       "\xe1\xb9\xb4" => "\xe1\xb9\xb5",
+       "\xe1\xb9\xb6" => "\xe1\xb9\xb7",
+       "\xe1\xb9\xb8" => "\xe1\xb9\xb9",
+       "\xe1\xb9\xba" => "\xe1\xb9\xbb",
+       "\xe1\xb9\xbc" => "\xe1\xb9\xbd",
+       "\xe1\xb9\xbe" => "\xe1\xb9\xbf",
+       "\xe1\xba\x80" => "\xe1\xba\x81",
+       "\xe1\xba\x82" => "\xe1\xba\x83",
+       "\xe1\xba\x84" => "\xe1\xba\x85",
+       "\xe1\xba\x86" => "\xe1\xba\x87",
+       "\xe1\xba\x88" => "\xe1\xba\x89",
+       "\xe1\xba\x8a" => "\xe1\xba\x8b",
+       "\xe1\xba\x8c" => "\xe1\xba\x8d",
+       "\xe1\xba\x8e" => "\xe1\xba\x8f",
+       "\xe1\xba\x90" => "\xe1\xba\x91",
+       "\xe1\xba\x92" => "\xe1\xba\x93",
+       "\xe1\xba\x94" => "\xe1\xba\x95",
+       "\xe1\xba\xa0" => "\xe1\xba\xa1",
+       "\xe1\xba\xa2" => "\xe1\xba\xa3",
+       "\xe1\xba\xa4" => "\xe1\xba\xa5",
+       "\xe1\xba\xa6" => "\xe1\xba\xa7",
+       "\xe1\xba\xa8" => "\xe1\xba\xa9",
+       "\xe1\xba\xaa" => "\xe1\xba\xab",
+       "\xe1\xba\xac" => "\xe1\xba\xad",
+       "\xe1\xba\xae" => "\xe1\xba\xaf",
+       "\xe1\xba\xb0" => "\xe1\xba\xb1",
+       "\xe1\xba\xb2" => "\xe1\xba\xb3",
+       "\xe1\xba\xb4" => "\xe1\xba\xb5",
+       "\xe1\xba\xb6" => "\xe1\xba\xb7",
+       "\xe1\xba\xb8" => "\xe1\xba\xb9",
+       "\xe1\xba\xba" => "\xe1\xba\xbb",
+       "\xe1\xba\xbc" => "\xe1\xba\xbd",
+       "\xe1\xba\xbe" => "\xe1\xba\xbf",
+       "\xe1\xbb\x80" => "\xe1\xbb\x81",
+       "\xe1\xbb\x82" => "\xe1\xbb\x83",
+       "\xe1\xbb\x84" => "\xe1\xbb\x85",
+       "\xe1\xbb\x86" => "\xe1\xbb\x87",
+       "\xe1\xbb\x88" => "\xe1\xbb\x89",
+       "\xe1\xbb\x8a" => "\xe1\xbb\x8b",
+       "\xe1\xbb\x8c" => "\xe1\xbb\x8d",
+       "\xe1\xbb\x8e" => "\xe1\xbb\x8f",
+       "\xe1\xbb\x90" => "\xe1\xbb\x91",
+       "\xe1\xbb\x92" => "\xe1\xbb\x93",
+       "\xe1\xbb\x94" => "\xe1\xbb\x95",
+       "\xe1\xbb\x96" => "\xe1\xbb\x97",
+       "\xe1\xbb\x98" => "\xe1\xbb\x99",
+       "\xe1\xbb\x9a" => "\xe1\xbb\x9b",
+       "\xe1\xbb\x9c" => "\xe1\xbb\x9d",
+       "\xe1\xbb\x9e" => "\xe1\xbb\x9f",
+       "\xe1\xbb\xa0" => "\xe1\xbb\xa1",
+       "\xe1\xbb\xa2" => "\xe1\xbb\xa3",
+       "\xe1\xbb\xa4" => "\xe1\xbb\xa5",
+       "\xe1\xbb\xa6" => "\xe1\xbb\xa7",
+       "\xe1\xbb\xa8" => "\xe1\xbb\xa9",
+       "\xe1\xbb\xaa" => "\xe1\xbb\xab",
+       "\xe1\xbb\xac" => "\xe1\xbb\xad",
+       "\xe1\xbb\xae" => "\xe1\xbb\xaf",
+       "\xe1\xbb\xb0" => "\xe1\xbb\xb1",
+       "\xe1\xbb\xb2" => "\xe1\xbb\xb3",
+       "\xe1\xbb\xb4" => "\xe1\xbb\xb5",
+       "\xe1\xbb\xb6" => "\xe1\xbb\xb7",
+       "\xe1\xbb\xb8" => "\xe1\xbb\xb9",
+       "\xe1\xbc\x88" => "\xe1\xbc\x80",
+       "\xe1\xbc\x89" => "\xe1\xbc\x81",
+       "\xe1\xbc\x8a" => "\xe1\xbc\x82",
+       "\xe1\xbc\x8b" => "\xe1\xbc\x83",
+       "\xe1\xbc\x8c" => "\xe1\xbc\x84",
+       "\xe1\xbc\x8d" => "\xe1\xbc\x85",
+       "\xe1\xbc\x8e" => "\xe1\xbc\x86",
+       "\xe1\xbc\x8f" => "\xe1\xbc\x87",
+       "\xe1\xbc\x98" => "\xe1\xbc\x90",
+       "\xe1\xbc\x99" => "\xe1\xbc\x91",
+       "\xe1\xbc\x9a" => "\xe1\xbc\x92",
+       "\xe1\xbc\x9b" => "\xe1\xbc\x93",
+       "\xe1\xbc\x9c" => "\xe1\xbc\x94",
+       "\xe1\xbc\x9d" => "\xe1\xbc\x95",
+       "\xe1\xbc\xa8" => "\xe1\xbc\xa0",
+       "\xe1\xbc\xa9" => "\xe1\xbc\xa1",
+       "\xe1\xbc\xaa" => "\xe1\xbc\xa2",
+       "\xe1\xbc\xab" => "\xe1\xbc\xa3",
+       "\xe1\xbc\xac" => "\xe1\xbc\xa4",
+       "\xe1\xbc\xad" => "\xe1\xbc\xa5",
+       "\xe1\xbc\xae" => "\xe1\xbc\xa6",
+       "\xe1\xbc\xaf" => "\xe1\xbc\xa7",
+       "\xe1\xbc\xb8" => "\xe1\xbc\xb0",
+       "\xe1\xbc\xb9" => "\xe1\xbc\xb1",
+       "\xe1\xbc\xba" => "\xe1\xbc\xb2",
+       "\xe1\xbc\xbb" => "\xe1\xbc\xb3",
+       "\xe1\xbc\xbc" => "\xe1\xbc\xb4",
+       "\xe1\xbc\xbd" => "\xe1\xbc\xb5",
+       "\xe1\xbc\xbe" => "\xe1\xbc\xb6",
+       "\xe1\xbc\xbf" => "\xe1\xbc\xb7",
+       "\xe1\xbd\x88" => "\xe1\xbd\x80",
+       "\xe1\xbd\x89" => "\xe1\xbd\x81",
+       "\xe1\xbd\x8a" => "\xe1\xbd\x82",
+       "\xe1\xbd\x8b" => "\xe1\xbd\x83",
+       "\xe1\xbd\x8c" => "\xe1\xbd\x84",
+       "\xe1\xbd\x8d" => "\xe1\xbd\x85",
+       "\xe1\xbd\x99" => "\xe1\xbd\x91",
+       "\xe1\xbd\x9b" => "\xe1\xbd\x93",
+       "\xe1\xbd\x9d" => "\xe1\xbd\x95",
+       "\xe1\xbd\x9f" => "\xe1\xbd\x97",
+       "\xe1\xbd\xa8" => "\xe1\xbd\xa0",
+       "\xe1\xbd\xa9" => "\xe1\xbd\xa1",
+       "\xe1\xbd\xaa" => "\xe1\xbd\xa2",
+       "\xe1\xbd\xab" => "\xe1\xbd\xa3",
+       "\xe1\xbd\xac" => "\xe1\xbd\xa4",
+       "\xe1\xbd\xad" => "\xe1\xbd\xa5",
+       "\xe1\xbd\xae" => "\xe1\xbd\xa6",
+       "\xe1\xbd\xaf" => "\xe1\xbd\xa7",
+       "\xe1\xbe\x88" => "\xe1\xbe\x80",
+       "\xe1\xbe\x89" => "\xe1\xbe\x81",
+       "\xe1\xbe\x8a" => "\xe1\xbe\x82",
+       "\xe1\xbe\x8b" => "\xe1\xbe\x83",
+       "\xe1\xbe\x8c" => "\xe1\xbe\x84",
+       "\xe1\xbe\x8d" => "\xe1\xbe\x85",
+       "\xe1\xbe\x8e" => "\xe1\xbe\x86",
+       "\xe1\xbe\x8f" => "\xe1\xbe\x87",
+       "\xe1\xbe\x98" => "\xe1\xbe\x90",
+       "\xe1\xbe\x99" => "\xe1\xbe\x91",
+       "\xe1\xbe\x9a" => "\xe1\xbe\x92",
+       "\xe1\xbe\x9b" => "\xe1\xbe\x93",
+       "\xe1\xbe\x9c" => "\xe1\xbe\x94",
+       "\xe1\xbe\x9d" => "\xe1\xbe\x95",
+       "\xe1\xbe\x9e" => "\xe1\xbe\x96",
+       "\xe1\xbe\x9f" => "\xe1\xbe\x97",
+       "\xe1\xbe\xa8" => "\xe1\xbe\xa0",
+       "\xe1\xbe\xa9" => "\xe1\xbe\xa1",
+       "\xe1\xbe\xaa" => "\xe1\xbe\xa2",
+       "\xe1\xbe\xab" => "\xe1\xbe\xa3",
+       "\xe1\xbe\xac" => "\xe1\xbe\xa4",
+       "\xe1\xbe\xad" => "\xe1\xbe\xa5",
+       "\xe1\xbe\xae" => "\xe1\xbe\xa6",
+       "\xe1\xbe\xaf" => "\xe1\xbe\xa7",
+       "\xe1\xbe\xb8" => "\xe1\xbe\xb0",
+       "\xe1\xbe\xb9" => "\xe1\xbe\xb1",
+       "\xe1\xbe\xba" => "\xe1\xbd\xb0",
+       "\xe1\xbe\xbb" => "\xe1\xbd\xb1",
+       "\xe1\xbe\xbc" => "\xe1\xbe\xb3",
+       "\xe1\xbf\x88" => "\xe1\xbd\xb2",
+       "\xe1\xbf\x89" => "\xe1\xbd\xb3",
+       "\xe1\xbf\x8a" => "\xe1\xbd\xb4",
+       "\xe1\xbf\x8b" => "\xe1\xbd\xb5",
+       "\xe1\xbf\x8c" => "\xe1\xbf\x83",
+       "\xe1\xbf\x98" => "\xe1\xbf\x90",
+       "\xe1\xbf\x99" => "\xe1\xbf\x91",
+       "\xe1\xbf\x9a" => "\xe1\xbd\xb6",
+       "\xe1\xbf\x9b" => "\xe1\xbd\xb7",
+       "\xe1\xbf\xa8" => "\xe1\xbf\xa0",
+       "\xe1\xbf\xa9" => "\xe1\xbf\xa1",
+       "\xe1\xbf\xaa" => "\xe1\xbd\xba",
+       "\xe1\xbf\xab" => "\xe1\xbd\xbb",
+       "\xe1\xbf\xac" => "\xe1\xbf\xa5",
+       "\xe1\xbf\xb8" => "\xe1\xbd\xb8",
+       "\xe1\xbf\xb9" => "\xe1\xbd\xb9",
+       "\xe1\xbf\xba" => "\xe1\xbd\xbc",
+       "\xe1\xbf\xbb" => "\xe1\xbd\xbd",
+       "\xe1\xbf\xbc" => "\xe1\xbf\xb3",
+       "\xe2\x84\xa6" => "\xcf\x89",
+       "\xe2\x84\xaa" => "k",
+       "\xe2\x84\xab" => "\xc3\xa5",
+       "\xe2\x85\xa0" => "\xe2\x85\xb0",
+       "\xe2\x85\xa1" => "\xe2\x85\xb1",
+       "\xe2\x85\xa2" => "\xe2\x85\xb2",
+       "\xe2\x85\xa3" => "\xe2\x85\xb3",
+       "\xe2\x85\xa4" => "\xe2\x85\xb4",
+       "\xe2\x85\xa5" => "\xe2\x85\xb5",
+       "\xe2\x85\xa6" => "\xe2\x85\xb6",
+       "\xe2\x85\xa7" => "\xe2\x85\xb7",
+       "\xe2\x85\xa8" => "\xe2\x85\xb8",
+       "\xe2\x85\xa9" => "\xe2\x85\xb9",
+       "\xe2\x85\xaa" => "\xe2\x85\xba",
+       "\xe2\x85\xab" => "\xe2\x85\xbb",
+       "\xe2\x85\xac" => "\xe2\x85\xbc",
+       "\xe2\x85\xad" => "\xe2\x85\xbd",
+       "\xe2\x85\xae" => "\xe2\x85\xbe",
+       "\xe2\x85\xaf" => "\xe2\x85\xbf",
+       "\xe2\x92\xb6" => "\xe2\x93\x90",
+       "\xe2\x92\xb7" => "\xe2\x93\x91",
+       "\xe2\x92\xb8" => "\xe2\x93\x92",
+       "\xe2\x92\xb9" => "\xe2\x93\x93",
+       "\xe2\x92\xba" => "\xe2\x93\x94",
+       "\xe2\x92\xbb" => "\xe2\x93\x95",
+       "\xe2\x92\xbc" => "\xe2\x93\x96",
+       "\xe2\x92\xbd" => "\xe2\x93\x97",
+       "\xe2\x92\xbe" => "\xe2\x93\x98",
+       "\xe2\x92\xbf" => "\xe2\x93\x99",
+       "\xe2\x93\x80" => "\xe2\x93\x9a",
+       "\xe2\x93\x81" => "\xe2\x93\x9b",
+       "\xe2\x93\x82" => "\xe2\x93\x9c",
+       "\xe2\x93\x83" => "\xe2\x93\x9d",
+       "\xe2\x93\x84" => "\xe2\x93\x9e",
+       "\xe2\x93\x85" => "\xe2\x93\x9f",
+       "\xe2\x93\x86" => "\xe2\x93\xa0",
+       "\xe2\x93\x87" => "\xe2\x93\xa1",
+       "\xe2\x93\x88" => "\xe2\x93\xa2",
+       "\xe2\x93\x89" => "\xe2\x93\xa3",
+       "\xe2\x93\x8a" => "\xe2\x93\xa4",
+       "\xe2\x93\x8b" => "\xe2\x93\xa5",
+       "\xe2\x93\x8c" => "\xe2\x93\xa6",
+       "\xe2\x93\x8d" => "\xe2\x93\xa7",
+       "\xe2\x93\x8e" => "\xe2\x93\xa8",
+       "\xe2\x93\x8f" => "\xe2\x93\xa9",
+       "\xef\xbc\xa1" => "\xef\xbd\x81",
+       "\xef\xbc\xa2" => "\xef\xbd\x82",
+       "\xef\xbc\xa3" => "\xef\xbd\x83",
+       "\xef\xbc\xa4" => "\xef\xbd\x84",
+       "\xef\xbc\xa5" => "\xef\xbd\x85",
+       "\xef\xbc\xa6" => "\xef\xbd\x86",
+       "\xef\xbc\xa7" => "\xef\xbd\x87",
+       "\xef\xbc\xa8" => "\xef\xbd\x88",
+       "\xef\xbc\xa9" => "\xef\xbd\x89",
+       "\xef\xbc\xaa" => "\xef\xbd\x8a",
+       "\xef\xbc\xab" => "\xef\xbd\x8b",
+       "\xef\xbc\xac" => "\xef\xbd\x8c",
+       "\xef\xbc\xad" => "\xef\xbd\x8d",
+       "\xef\xbc\xae" => "\xef\xbd\x8e",
+       "\xef\xbc\xaf" => "\xef\xbd\x8f",
+       "\xef\xbc\xb0" => "\xef\xbd\x90",
+       "\xef\xbc\xb1" => "\xef\xbd\x91",
+       "\xef\xbc\xb2" => "\xef\xbd\x92",
+       "\xef\xbc\xb3" => "\xef\xbd\x93",
+       "\xef\xbc\xb4" => "\xef\xbd\x94",
+       "\xef\xbc\xb5" => "\xef\xbd\x95",
+       "\xef\xbc\xb6" => "\xef\xbd\x96",
+       "\xef\xbc\xb7" => "\xef\xbd\x97",
+       "\xef\xbc\xb8" => "\xef\xbd\x98",
+       "\xef\xbc\xb9" => "\xef\xbd\x99",
+       "\xef\xbc\xba" => "\xef\xbd\x9a",
+       "\xf0\x90\x90\x80" => "\xf0\x90\x90\xa8",
+       "\xf0\x90\x90\x81" => "\xf0\x90\x90\xa9",
+       "\xf0\x90\x90\x82" => "\xf0\x90\x90\xaa",
+       "\xf0\x90\x90\x83" => "\xf0\x90\x90\xab",
+       "\xf0\x90\x90\x84" => "\xf0\x90\x90\xac",
+       "\xf0\x90\x90\x85" => "\xf0\x90\x90\xad",
+       "\xf0\x90\x90\x86" => "\xf0\x90\x90\xae",
+       "\xf0\x90\x90\x87" => "\xf0\x90\x90\xaf",
+       "\xf0\x90\x90\x88" => "\xf0\x90\x90\xb0",
+       "\xf0\x90\x90\x89" => "\xf0\x90\x90\xb1",
+       "\xf0\x90\x90\x8a" => "\xf0\x90\x90\xb2",
+       "\xf0\x90\x90\x8b" => "\xf0\x90\x90\xb3",
+       "\xf0\x90\x90\x8c" => "\xf0\x90\x90\xb4",
+       "\xf0\x90\x90\x8d" => "\xf0\x90\x90\xb5",
+       "\xf0\x90\x90\x8e" => "\xf0\x90\x90\xb6",
+       "\xf0\x90\x90\x8f" => "\xf0\x90\x90\xb7",
+       "\xf0\x90\x90\x90" => "\xf0\x90\x90\xb8",
+       "\xf0\x90\x90\x91" => "\xf0\x90\x90\xb9",
+       "\xf0\x90\x90\x92" => "\xf0\x90\x90\xba",
+       "\xf0\x90\x90\x93" => "\xf0\x90\x90\xbb",
+       "\xf0\x90\x90\x94" => "\xf0\x90\x90\xbc",
+       "\xf0\x90\x90\x95" => "\xf0\x90\x90\xbd",
+       "\xf0\x90\x90\x96" => "\xf0\x90\x90\xbe",
+       "\xf0\x90\x90\x97" => "\xf0\x90\x90\xbf",
+       "\xf0\x90\x90\x98" => "\xf0\x90\x91\x80",
+       "\xf0\x90\x90\x99" => "\xf0\x90\x91\x81",
+       "\xf0\x90\x90\x9a" => "\xf0\x90\x91\x82",
+       "\xf0\x90\x90\x9b" => "\xf0\x90\x91\x83",
+       "\xf0\x90\x90\x9c" => "\xf0\x90\x91\x84",
+       "\xf0\x90\x90\x9d" => "\xf0\x90\x91\x85",
+       "\xf0\x90\x90\x9e" => "\xf0\x90\x91\x86",
+       "\xf0\x90\x90\x9f" => "\xf0\x90\x91\x87",
+       "\xf0\x90\x90\xa0" => "\xf0\x90\x91\x88",
+       "\xf0\x90\x90\xa1" => "\xf0\x90\x91\x89",
+       "\xf0\x90\x90\xa2" => "\xf0\x90\x91\x8a",
+       "\xf0\x90\x90\xa3" => "\xf0\x90\x91\x8b",
+       "\xf0\x90\x90\xa4" => "\xf0\x90\x91\x8c",
+       "\xf0\x90\x90\xa5" => "\xf0\x90\x91\x8d"
+);
+
+?>
diff --git a/includes/WatchedItem.php b/includes/WatchedItem.php
new file mode 100644 (file)
index 0000000..1912f54
--- /dev/null
@@ -0,0 +1,193 @@
+<?php
+/**
+ *
+ * @package MediaWiki
+ */
+
+/**
+ *
+ * @package MediaWiki
+ */
+class WatchedItem {
+       var $mTitle, $mUser;
+
+       /**
+        * Create a WatchedItem object with the given user and title
+        * @todo document
+        * @private
+        */
+       function &fromUserTitle( &$user, &$title ) {
+               $wl = new WatchedItem;
+               $wl->mUser =& $user;
+               $wl->mTitle =& $title;
+               $wl->id = $user->getId();
+# Patch (also) for email notification on page changes T.Gries/M.Arndt 11.09.2004
+# TG patch: here we do not consider pages and their talk pages equivalent - why should we ?
+# The change results in talk-pages not automatically included in watchlists, when their parent page is included
+#              $wl->ns = $title->getNamespace() & ~1;
+               $wl->ns = $title->getNamespace();
+
+               $wl->ti = $title->getDBkey();
+               return $wl;
+       }
+
+       /**
+        * Returns the memcached key for this item
+        */
+       function watchKey() {
+               global $wgDBname;
+               return "$wgDBname:watchlist:user:$this->id:page:$this->ns:$this->ti";
+       }
+       
+       /**
+        * Is mTitle being watched by mUser?
+        */
+       function isWatched() {
+               # Pages and their talk pages are considered equivalent for watching;
+               # remember that talk namespaces are numbered as page namespace+1.
+               global $wgMemc;
+               $fname = 'WatchedItem::isWatched';
+
+               $key = $this->watchKey();
+               $iswatched = $wgMemc->get( $key );
+               if( is_integer( $iswatched ) ) return $iswatched;
+               
+               $dbr =& wfGetDB( DB_SLAVE );
+               $res = $dbr->select( 'watchlist', 1, array( 'wl_user' => $this->id, 'wl_namespace' => $this->ns, 
+                       'wl_title' => $this->ti ), $fname );
+               $iswatched = ($dbr->numRows( $res ) > 0) ? 1 : 0;
+               $wgMemc->set( $key, $iswatched );
+               return $iswatched;
+       }
+
+       /**
+        * @todo document
+        */
+       function addWatch() {
+               $fname = 'WatchedItem::addWatch';
+               wfProfileIn( $fname );
+               # REPLACE instead of INSERT because occasionally someone
+               # accidentally reloads a watch-add operation.
+               $dbw =& wfGetDB( DB_MASTER );
+               $dbw->replace( 'watchlist', array(array('wl_user', 'wl_namespace', 'wl_title', 'wl_notificationtimestamp')),
+                 array( 
+                   'wl_user' => $this->id,
+                       'wl_namespace' => ($this->ns & ~1),
+                       'wl_title' => $this->ti,
+                       'wl_notificationtimestamp' => '0'
+                 ), $fname );
+
+               # the following code compensates the new behaviour, introduced by the enotif patch,
+               # that every single watched page needs now to be listed in watchlist
+               # namespace:page and namespace_talk:page need separate entries: create them
+               $dbw->replace( 'watchlist', array(array('wl_user', 'wl_namespace', 'wl_title', 'wl_notificationtimestamp')),
+                 array(
+                       'wl_user' => $this->id,
+                       'wl_namespace' => ($this->ns | 1 ),
+                       'wl_title' => $this->ti,
+                       'wl_notificationtimestamp' => '0'
+                 ), $fname );
+
+               global $wgMemc;
+               $wgMemc->set( $this->watchkey(), 1 );
+               wfProfileOut( $fname );
+               return true;
+       }
+
+       function removeWatch() {
+               global $wgMemc;
+               $fname = 'WatchedItem::removeWatch';
+
+               $success = false;
+               $dbw =& wfGetDB( DB_MASTER );
+               $dbw->delete( 'watchlist', 
+                       array( 
+                               'wl_user' => $this->id, 
+                               'wl_namespace' => ($this->ns & ~1),
+                               'wl_title' => $this->ti
+                       ), $fname
+               );
+               if ( $dbw->affectedRows() ) {
+                       $success = true;
+               }
+
+               # the following code compensates the new behaviour, introduced by the
+               # enotif patch, that every single watched page needs now to be listed
+               # in watchlist namespace:page and namespace_talk:page had separate
+               # entries: clear them
+               $dbw->delete( 'watchlist',
+                       array(
+                               'wl_user' => $this->id,
+                               'wl_namespace' => ($this->ns | 1),
+                               'wl_title' => $this->ti
+                       ), $fname
+               );
+               
+               if ( $dbw->affectedRows() ) {
+                       $success = true;
+               }
+               if ( $success ) {
+                       $wgMemc->set( $this->watchkey(), 0 );
+               }
+               return $success;
+       }
+
+       /**
+        * Check if the given title already is watched by the user, and if so
+        * add watches on a new title. To be used for page renames and such.
+        *
+        * @param Title $ot Page title to duplicate entries from, if present
+        * @param Title $nt Page title to add watches on
+        * @static
+        */
+       function duplicateEntries( $ot, $nt ) {
+               WatchedItem::doDuplicateEntries( $ot->getSubjectPage(), $nt->getSubjectPage() );
+               WatchedItem::doDuplicateEntries( $ot->getTalkPage(), $nt->getTalkPage() );
+       }
+       
+       /**
+        * @static
+        * @access private
+        */
+       function doDuplicateEntries( $ot, $nt ) {
+               $fname = "WatchedItem::duplicateEntries";
+               global $wgMemc, $wgDBname;
+               $oldnamespace = $ot->getNamespace();
+               $newnamespace = $nt->getNamespace();
+               $oldtitle = $ot->getDBkey();
+               $newtitle = $nt->getDBkey();
+
+               $dbw =& wfGetDB( DB_MASTER );
+               $watchlist = $dbw->tableName( 'watchlist' );
+               
+               $res = $dbw->select( 'watchlist', 'wl_user', 
+                       array( 'wl_namespace' => $oldnamespace, 'wl_title' => $oldtitle ),
+                       $fname, 'FOR UPDATE'
+               );
+               # Construct array to replace into the watchlist
+               $values = array();
+               while ( $s = $dbw->fetchObject( $res ) ) {
+                       $values[] = array(
+                               'wl_user' => $s->wl_user,
+                               'wl_namespace' => $newnamespace,
+                               'wl_title' => $newtitle
+                       );
+               }
+               $dbw->freeResult( $res );
+               
+               if( empty( $values ) ) {
+                       // Nothing to do
+                       return true;
+               }
+
+               # Perform replace
+               # Note that multi-row replace is very efficient for MySQL but may be inefficient for
+               # some other DBMSes, mostly due to poor simulation by us
+               $dbw->replace( 'watchlist', array(array( 'wl_user', 'wl_namespace', 'wl_title')), $values, $fname );
+               return true;
+       }
+
+
+}
+
+?>
diff --git a/includes/WebRequest.php b/includes/WebRequest.php
new file mode 100644 (file)
index 0000000..31195eb
--- /dev/null
@@ -0,0 +1,449 @@
+<?php
+/**
+ * Deal with importing all those nasssty globals and things
+ * @package MediaWiki
+ */
+
+# Copyright (C) 2003 Brion Vibber <brion@pobox.com>
+# http://www.mediawiki.org/
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or 
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# http://www.gnu.org/copyleft/gpl.html
+
+/**
+ * The WebRequest class encapsulates getting at data passed in the
+ * URL or via a POSTed form, handling remove of "magic quotes" slashes,
+ * stripping illegal input characters and normalizing Unicode sequences.
+ *
+ * Usually this is used via a global singleton, $wgRequest. You should
+ * not create a second WebRequest object; make a FauxRequest object if
+ * you want to pass arbitrary data to some function in place of the web
+ * input.
+ *
+ * @package MediaWiki
+ */
+class WebRequest {
+       function WebRequest() {
+               $this->checkMagicQuotes();
+               global $wgUsePathInfo;
+               if( isset( $_SERVER['PATH_INFO'] ) && ($_SERVER['PATH_INFO'] != '') && $wgUsePathInfo ) {
+                       # Stuff it!
+                       $_GET['title'] = $_REQUEST['title'] =
+                               substr( $_SERVER['PATH_INFO'], 1 );
+               }
+       }
+
+       /**
+        * Recursively strips slashes from the given array;
+        * used for undoing the evil that is magic_quotes_gpc.
+        * @param array &$arr will be modified
+        * @return array the original array
+        * @private
+        */
+       function &fix_magic_quotes( &$arr ) {
+               foreach( $arr as $key => $val ) {
+                       if( is_array( $val ) ) {
+                               $this->fix_magic_quotes( $arr[$key] );
+                       } else {
+                               $arr[$key] = stripslashes( $val );
+                       }
+               }
+               return $arr;
+       }
+       
+       /**
+        * If magic_quotes_gpc option is on, run the global arrays
+        * through fix_magic_quotes to strip out the stupid slashes.
+        * WARNING: This should only be done once! Running a second
+        * time could damage the values.
+        * @private
+        */
+       function checkMagicQuotes() {
+               if ( get_magic_quotes_gpc() ) {
+                       $this->fix_magic_quotes( $_COOKIE );
+                       $this->fix_magic_quotes( $_ENV );
+                       $this->fix_magic_quotes( $_GET );
+                       $this->fix_magic_quotes( $_POST );
+                       $this->fix_magic_quotes( $_REQUEST );
+                       $this->fix_magic_quotes( $_SERVER );
+               }
+       }
+       
+       /**
+        * Recursively normalizes UTF-8 strings in the given array.
+        * @param array $data string or array
+        * @return cleaned-up version of the given
+        * @private
+        */
+       function normalizeUnicode( $data ) {
+               if( is_array( $data ) ) {
+                       foreach( $data as $key => $val ) {
+                               $data[$key] = $this->normalizeUnicode( $val );
+                       }
+               } else {
+                       $data = UtfNormal::cleanUp( $data );
+               }
+               return $data;
+       }
+       
+       /**
+        * Fetch a value from the given array or return $default if it's not set.
+        *
+        * @param array &$arr
+        * @param string $name
+        * @param mixed $default
+        * @return mixed
+        * @private
+        */
+       function getGPCVal( &$arr, $name, $default ) {
+               if( isset( $arr[$name] ) ) {
+                       global $wgServer, $wgContLang;
+                       $data = $arr[$name];
+                       if( isset( $_GET[$name] ) && !is_array( $data ) ) {
+                               # Check for alternate/legacy character encoding.
+                               if( isset( $wgContLang ) ) {
+                                       $data = $wgContLang->checkTitleEncoding( $data );
+                               }
+                       }
+                       require_once( 'normal/UtfNormal.php' );
+                       $data = $this->normalizeUnicode( $data );
+                       return $data;
+               } else {
+                       return $default;
+               }
+       }
+
+       /**
+        * Fetch a scalar from the input or return $default if it's not set.
+        * Returns a string. Arrays are discarded.
+        *
+        * @param string $name
+        * @param string $default optional default (or NULL)
+        * @return string
+        */
+       function getVal( $name, $default = NULL ) {
+               $val = $this->getGPCVal( $_REQUEST, $name, $default );
+               if( is_array( $val ) ) {
+                       $val = $default;
+               }
+               if( is_null( $val ) ) {
+                       return null;
+               } else {
+                       return (string)$val;
+               }
+       }
+       
+       /**
+        * Fetch an array from the input or return $default if it's not set.
+        * If source was scalar, will return an array with a single element.
+        * If no source and no default, returns NULL.
+        *
+        * @param string $name
+        * @param array $default optional default (or NULL)
+        * @return array
+        */
+       function getArray( $name, $default = NULL ) {
+               $val = $this->getGPCVal( $_REQUEST, $name, $default );
+               if( is_null( $val ) ) {
+                       return null;
+               } else {
+                       return (array)$val;
+               }
+       }
+
+       /**
+        * Fetch an integer value from the input or return $default if not set.
+        * Guaranteed to return an integer; non-numeric input will typically
+        * return 0.
+        * @param string $name
+        * @param int $default
+        * @return int
+        */
+       function getInt( $name, $default = 0 ) {
+               return IntVal( $this->getVal( $name, $default ) );
+       }
+       
+       /**
+        * Fetch an integer value from the input or return null if empty.
+        * Guaranteed to return an integer or null; non-numeric input will
+        * typically return null.
+        * @param string $name
+        * @return int
+        */
+       function getIntOrNull( $name ) {
+               $val = $this->getVal( $name );
+               return is_numeric( $val )
+                       ? IntVal( $val )
+                       : null;
+       }
+       
+       /**
+        * Fetch a boolean value from the input or return $default if not set.
+        * Guaranteed to return true or false, with normal PHP semantics for
+        * boolean interpretation of strings.
+        * @param string $name
+        * @param bool $default
+        * @return bool
+        */
+       function getBool( $name, $default = false ) {
+               return $this->getVal( $name, $default ) ? true : false;
+       }
+       
+       /**
+        * Return true if the named value is set in the input, whatever that
+        * value is (even "0"). Return false if the named value is not set.
+        * Example use is checking for the presence of check boxes in forms.
+        * @param string $name
+        * @return bool
+        */
+       function getCheck( $name ) {
+               # Checkboxes and buttons are only present when clicked
+               # Presence connotes truth, abscense false
+               $val = $this->getVal( $name, NULL );
+               return isset( $val );
+       }
+       
+       /**
+        * Fetch a text string from the given array or return $default if it's not
+        * set. \r is stripped from the text, and with some language modules there 
+        * is an input transliteration applied. This should generally be used for
+        * form <textarea> and <input> fields.
+        *
+        * @param string $name
+        * @param string $default optional
+        * @return string
+        */
+       function getText( $name, $default = '' ) {
+               global $wgContLang;
+               $val = $this->getVal( $name, $default );
+               return str_replace( "\r\n", "\n",
+                       $wgContLang->recodeInput( $val ) );
+       }
+       
+       /**
+        * Extracts the given named values into an array.
+        * If no arguments are given, returns all input values.
+        * No transformation is performed on the values.
+        */
+       function getValues() {  
+               $names = func_get_args();
+               if ( count( $names ) == 0 ) {
+                       $names = array_keys( $_REQUEST );
+               }
+
+               $retVal = array();
+               foreach ( $names as $name ) { 
+                       $value = $this->getVal( $name );
+                       if ( !is_null( $value ) ) {
+                               $retVal[$name] = $value;
+                       }
+               }
+               return $retVal;
+       }
+
+       /**
+        * Returns true if the present request was reached by a POST operation,
+        * false otherwise (GET, HEAD, or command-line).
+        *
+        * Note that values retrieved by the object may come from the
+        * GET URL etc even on a POST request.
+        *
+        * @return bool
+        */
+       function wasPosted() {
+               return $_SERVER['REQUEST_METHOD'] == 'POST';
+       }
+       
+       /**
+        * Returns true if there is a session cookie set.
+        * This does not necessarily mean that the user is logged in!
+        *
+        * @return bool
+        */
+       function checkSessionCookie() {
+               return isset( $_COOKIE[ini_get('session.name')] );
+       }
+       
+       /**
+        * Return the path portion of the request URI.
+        * @return string
+        */
+       function getRequestURL() {
+               return $_SERVER['REQUEST_URI'];
+       }
+       
+       /**
+        * Return the request URI with the canonical service and hostname.
+        * @return string
+        */
+       function getFullRequestURL() {
+               global $wgServer;
+               return $wgServer . $this->getRequestURL();
+       }
+       
+       /**
+        * Take an arbitrary query and rewrite the present URL to include it
+        * @param string $query Query string fragment; do not include initial '?'
+        * @return string
+        */
+       function appendQuery( $query ) {
+               global $wgTitle;
+               $basequery = '';
+               foreach( $_GET as $var => $val ) {
+                       if( $var == 'title' ) continue;
+                       $basequery .= '&' . urlencode( $var ) . '=' . urlencode( $val );
+               }
+               $basequery .= '&' . $query;
+               
+               # Trim the extra &
+               $basequery = substr( $basequery, 1 );
+               return $wgTitle->getLocalURL( $basequery );
+       }
+       
+       /**
+        * HTML-safe version of appendQuery().
+        * @param string $query Query string fragment; do not include initial '?'
+        * @return string
+        */
+       function escapeAppendQuery( $query ) {
+               return htmlspecialchars( $this->appendQuery( $query ) );
+       }
+       
+       /**
+        * Check for limit and offset parameters on the input, and return sensible
+        * defaults if not given. The limit must be positive and is capped at 5000.
+        * Offset must be positive but is not capped.
+        *
+        * @param int $deflimit Limit to use if no input and the user hasn't set the option.
+        * @param string $optionname To specify an option other than rclimit to pull from.
+        * @return array first element is limit, second is offset
+        */
+       function getLimitOffset( $deflimit = 50, $optionname = 'rclimit' ) {
+               global $wgUser;
+       
+               $limit = $this->getInt( 'limit', 0 );
+               if( $limit < 0 ) $limit = 0;
+               if( ( $limit == 0 ) && ( $optionname != '' ) ) {
+                       $limit = (int)$wgUser->getOption( $optionname );
+               }
+               if( $limit <= 0 ) $limit = $deflimit;
+               if( $limit > 5000 ) $limit = 5000; # We have *some* limits...
+       
+               $offset = $this->getInt( 'offset', 0 );
+               if( $offset < 0 ) $offset = 0;
+       
+               return array( $limit, $offset );
+       }
+       
+       /**
+        * Return the path to the temporary file where PHP has stored the upload.
+        * @param string $key
+        * @return string or NULL if no such file.
+        */
+       function getFileTempname( $key ) {
+               if( !isset( $_FILES[$key] ) ) {
+                       return NULL;
+               }
+               return $_FILES[$key]['tmp_name'];
+       }
+       
+       /**
+        * Return the size of the upload, or 0.
+        * @param string $key
+        * @return integer
+        */
+       function getFileSize( $key ) {
+               if( !isset( $_FILES[$key] ) ) {
+                       return 0;
+               }
+               return $_FILES[$key]['size'];
+       }
+       
+       /**
+        * Return the original filename of the uploaded file, as reported by
+        * the submitting user agent. HTML-style character entities are
+        * interpreted and normalized to Unicode normalization form C, in part
+        * to deal with weird input from Safari with non-ASCII filenames.
+        *
+        * Other than this the name is not verified for being a safe filename.
+        *
+        * @param string $key
+        * @return string or NULL if no such file.
+        */
+       function getFileName( $key ) {
+               if( !isset( $_FILES[$key] ) ) {
+                       return NULL;
+               }
+               $name = $_FILES[$key]['name'];
+               
+               # Safari sends filenames in HTML-encoded Unicode form D...
+               # Horrid and evil! Let's try to make some kind of sense of it.
+               $name = Sanitizer::decodeCharReferences( $name );
+               $name = UtfNormal::cleanUp( $name );
+               wfDebug( "WebRequest::getFileName() '" . $_FILES[$key]['name'] . "' normalized to '$name'\n" );
+               return $name;
+       }
+}
+
+/**
+ * WebRequest clone which takes values from a provided array.
+ *
+ * @package MediaWiki
+ */
+class FauxRequest extends WebRequest {
+       var $data = null;
+       var $wasPosted = false;
+       
+       function FauxRequest( $data, $wasPosted = false ) {
+               if( is_array( $data ) ) {
+                       $this->data = $data;
+               } else {
+                       wfDebugDieBacktrace( "FauxRequest() got bogus data" );
+               }
+               $this->wasPosted = $wasPosted;
+       }
+
+       function getVal( $name, $default = NULL ) {
+               return $this->getGPCVal( $this->data, $name, $default );
+       }
+       
+       function getText( $name, $default = '' ) {
+               # Override; don't recode since we're using internal data
+               return $this->getVal( $name, $default );
+       }
+       
+       function getValues() {  
+               return $this->data;
+       }
+
+       function wasPosted() {
+               return $this->wasPosted;
+       }
+       
+       function checkSessionCookie() {
+               return false;
+       }
+       
+       function getRequestURL() {
+               wfDebugDieBacktrace( 'FauxRequest::getRequestURL() not implemented' );
+       }
+       
+       function appendQuery( $query ) {
+               wfDebugDieBacktrace( 'FauxRequest::appendQuery() not implemented' );
+       }
+       
+}
+
+?>
diff --git a/includes/WikiError.php b/includes/WikiError.php
new file mode 100644 (file)
index 0000000..46738fc
--- /dev/null
@@ -0,0 +1,125 @@
+<?php
+/**
+ * MediaWiki error classes
+ * Copyright (C) 2005 Brion Vibber <brion@pobox.com>
+ * http://www.mediawiki.org/
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or 
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @package MediaWiki
+ */
+
+/**
+ * Since PHP4 doesn't have exceptions, here's some error objects
+ * loosely modeled on the standard PEAR_Error model...
+ * @package MediaWiki
+ */
+class WikiError {
+       /**
+        * @param string $message
+        */
+       function WikiError( $message ) {
+               $this->mMessage = $message;
+       }
+       
+       /**
+        * @return string Plaintext error message to display
+        */
+       function getMessage() {
+               return $this->mMessage;
+       }
+       
+       /**
+        * In following PEAR_Error model this could be formatted differently,
+        * but so far it's not.
+        * @return string
+        */
+       function toString() {
+               return $this->getMessage();
+       }
+       
+       /**
+        * Returns true if the given object is a WikiError-descended
+        * error object, false otherwise.
+        *
+        * @param mixed $object
+        * @return bool
+        * @static
+        */
+       function isError( &$object ) {
+               return is_a( $object, 'WikiError' );
+       }
+}
+
+/**
+ * Localized error message object
+ * @package MediaWiki
+ */
+class WikiErrorMsg extends WikiError {
+       /**
+        * @param string $message Wiki message name
+        * @param ... parameters to pass to wfMsg()
+        */
+       function WikiErrorMsg( $message/*, ... */ ) {
+               $args = func_get_args();
+               array_shift( $args );
+               $this->mMessage = wfMsgReal( $message, $args, true );
+       }
+}
+
+/**
+ * @package MediaWiki
+ * @todo document
+ */
+class WikiXmlError extends WikiError {
+       /**
+        * @param resource $parser
+        * @param string $message
+        */
+       function WikiXmlError( $parser, $message = 'XML parsing error', $context = null, $offset = 0 ) {
+               $this->mXmlError = xml_get_error_code( $parser );
+               $this->mColumn = xml_get_current_column_number( $parser );
+               $this->mLine = xml_get_current_line_number( $parser );
+               $this->mByte = xml_get_current_byte_index( $parser );
+               $this->mContext = $this->_extractContext( $context, $offset );
+               $this->mMessage = $message;
+               xml_parser_free( $parser );
+               wfDebug( "WikiXmlError: " . $this->getMessage() . "\n" );
+       }
+
+       /** @return string */   
+       function getMessage() {
+               return sprintf( '%s at line %d, col %d (byte %d%s): %s',
+                       $this->mMessage,
+                       $this->mLine,
+                       $this->mColumn,
+                       $this->mByte,
+                       $this->mContext,
+                       xml_error_string( $this->mXmlError ) );
+       }
+       
+       function _extractContext( $context, $offset ) {
+               if( is_null( $context ) ) {
+                       return null;
+               } else {
+                       // Hopefully integer overflow will be handled transparently here
+                       $inlineOffset = $this->mByte - $offset;
+                       return '; "' . substr( $context, $inlineOffset, 16 ) . '"';
+               }
+       }
+}
+
+?>
diff --git a/includes/ZhClient.php b/includes/ZhClient.php
new file mode 100644 (file)
index 0000000..6dacdc5
--- /dev/null
@@ -0,0 +1,149 @@
+<?php
+/**
+ * @package MediaWiki
+ */
+
+/**
+ * Client for querying zhdaemon
+ *
+ * @package MediaWiki
+ */
+class ZhClient {
+       var $mHost, $mPort, $mFP, $mConnected;
+
+       /**
+        * Constructor
+        *
+        * @access private
+        */
+       function ZhClient($host, $port) {
+               $this->mHost = $host;
+               $this->mPort = $port;
+               $this->mConnected = $this->connect();
+       }
+
+       /**
+        * Check if connection to zhdaemon is successful
+        *
+        * @access public
+        */
+       function isconnected() {
+               return $this->mConnected;
+       }
+
+       /**
+        * Establish conncetion
+        *
+        * @access private
+        */
+       function connect() {
+               wfSuppressWarnings();
+               $this->mFP = fsockopen($this->mHost, $this->mPort, $errno, $errstr, 30);
+               wfRestoreWarnings();
+               if(!$this->mFP) {
+                       return false;
+               }
+               return true;
+       }
+
+       /**
+        * Query the daemon and return the result
+        *
+        * @access private
+        */
+       function query($request) {
+               if(!$this->mConnected)
+                       return false;
+
+               fwrite($this->mFP, $request);
+
+               $result=fgets($this->mFP, 1024);
+
+               list($status, $len) = explode(" ", $result);
+               if($status == 'ERROR') {
+                       //$len is actually the error code...
+                       print "zhdaemon error $len<br />\n";
+                       return false;
+               }
+               $bytesread=0;
+               $data='';
+               while(!feof($this->mFP) && $bytesread<$len) {
+                       $str= fread($this->mFP, $len-$bytesread);
+                       $bytesread += strlen($str);
+                       $data .= $str;
+               }
+               //data should be of length $len. otherwise something is wrong
+               if(strlen($data) != $len)
+                       return false;
+               return $data;
+       }
+
+       /**
+        * Convert the input to a different language variant
+        *
+        * @param string $text input text
+        * @param string $tolang language variant
+        * @return string the converted text
+        * @access public
+        */
+       function convert($text, $tolang) {
+               $len = strlen($text);
+               $q = "CONV $tolang $len\n$text";
+               $result = $this->query($q);
+               if(!$result)
+                       $result = $text;
+               return $result;
+       }
+
+       /**
+        * Convert the input to all possible variants 
+        *
+        * @param string $text input text
+        * @return array langcode => converted_string
+        * @access public
+        */     
+       function convertToAllVariants($text) {
+               $len = strlen($text);
+               $q = "CONV ALL $len\n$text";
+               $result = $this->query($q);
+               if(!$result)
+                       return false;
+               list($infoline, $data) = explode('|', $result, 2);
+               $info = explode(";", $infoline);
+               $ret = array();
+               $i=0;
+               foreach($info as $variant) {
+                       list($code, $len) = explode(' ', $variant);
+                       $ret[strtolower($code)] = substr($data, $i, $len);
+                       $r = $ret[strtolower($code)];
+                       $i+=$len;
+               }
+               return $ret;
+    }
+       /**
+        * Perform word segmentation
+        *
+        * @param string $text input text
+        * @return string segmented text
+        * @access public
+        */
+       function segment($text) {
+               $len = strlen($text);
+               $q = "SEG $len\n$text";
+               $result = $this->query($q);
+               if(!$result) {// fallback to character based segmentation
+                       $result = ZhClientFake::segment($text);
+               }
+               return $result;
+       }
+
+       /**
+        * Close the connection
+        *
+        * @access public
+        */
+       function close() {
+               fclose($this->mFP);
+       }
+}
+?>
\ No newline at end of file
diff --git a/includes/ZhConversion.php b/includes/ZhConversion.php
new file mode 100644 (file)
index 0000000..dd0cd42
--- /dev/null
@@ -0,0 +1,8457 @@
+<?php
+/**
+ * Simplified/Traditional Chinese conversion tables
+ *
+ * Automatically generated using code and data in includes/zhtable/
+ * Do not modify directly! 
+ *
+ * @package MediaWiki
+*/
+
+$zh2TW=array(
+"画"=>"畫",
+"板"=>"板",
+"表"=>"表",
+"才"=>"才",
+"丑"=>"醜",
+"出"=>"出",
+"淀"=>"澱",
+"冬"=>"冬",
+"范"=>"範",
+"丰"=>"豐",
+"刮"=>"刮",
+"后"=>"後",
+"胡"=>"胡",
+"回"=>"回",
+"伙"=>"夥",
+"姜"=>"薑",
+"借"=>"借",
+"克"=>"克",
+"困"=>"困",
+"漓"=>"漓",
+"里"=>"里",
+"帘"=>"簾",
+"霉"=>"霉",
+"面"=>"面",
+"蔑"=>"蔑",
+"千"=>"千",
+"秋"=>"秋",
+"松"=>"松",
+"咸"=>"咸",
+"向"=>"向",
+"余"=>"餘",
+"郁"=>"鬱",
+"御"=>"御",
+"愿"=>"願",
+"云"=>"雲",
+"芸"=>"芸",
+"沄"=>"沄",
+"致"=>"致",
+"制"=>"制",
+"朱"=>"朱",
+"筑"=>"築",
+"准"=>"準",
+"厂"=>"廠",
+"广"=>"廣",
+"辟"=>"闢",
+"别"=>"別",
+"卜"=>"卜",
+"沈"=>"沈",
+"冲"=>"沖",
+"种"=>"種",
+"虫"=>"蟲",
+"担"=>"擔",
+"党"=>"黨",
+"斗"=>"鬥",
+"儿"=>"兒",
+"干"=>"乾",
+"谷"=>"谷",
+"柜"=>"櫃",
+"合"=>"合",
+"划"=>"劃",
+"坏"=>"壞",
+"几"=>"幾",
+"系"=>"系",
+"家"=>"家",
+"价"=>"價",
+"据"=>"據",
+"卷"=>"捲",
+"适"=>"適",
+"蜡"=>"蠟",
+"腊"=>"臘",
+"了"=>"了",
+"累"=>"累",
+"么"=>"麽",
+"蒙"=>"蒙",
+"万"=>"萬",
+"宁"=>"寧",
+"朴"=>"樸",
+"苹"=>"蘋",
+"仆"=>"僕",
+"曲"=>"曲",
+"确"=>"確",
+"舍"=>"舍",
+"胜"=>"勝",
+"术"=>"術",
+"台"=>"台",
+"体"=>"體",
+"涂"=>"塗",
+"叶"=>"葉",
+"吁"=>"吁",
+"旋"=>"旋",
+"佣"=>"傭",
+"与"=>"與",
+"折"=>"折",
+"征"=>"徵",
+"症"=>"症",
+"恶"=>"惡",
+"发"=>"發",
+"复"=>"復",
+"汇"=>"匯",
+"获"=>"獲",
+"饥"=>"飢",
+"尽"=>"盡",
+"历"=>"歷",
+"卤"=>"滷",
+"弥"=>"彌",
+"签"=>"簽",
+"纤"=>"纖",
+"苏"=>"蘇",
+"坛"=>"壇",
+"团"=>"團",
+"须"=>"須",
+"脏"=>"臟",
+"只"=>"只",
+"钟"=>"鐘",
+"药"=>"藥",
+"同"=>"同",
+"志"=>"志",
+"杯"=>"杯",
+"岳"=>"岳",
+"布"=>"布",
+"当"=>"當",
+"吊"=>"弔",
+"仇"=>"仇",
+"蕴"=>"蘊",
+"线"=>"線",
+"为"=>"為",
+"产"=>"產",
+"众"=>"眾",
+"伪"=>"偽",
+"凫"=>"鳧",
+"厕"=>"廁",
+"启"=>"啟",
+"墙"=>"牆",
+"壳"=>"殼",
+"奖"=>"獎",
+"妫"=>"媯",
+"并"=>"並",
+"录"=>"錄",
+"悫"=>"愨",
+"极"=>"極",
+"沩"=>"溈",
+"瘘"=>"瘺",
+"硷"=>"鹼",
+"竖"=>"豎",
+"绝"=>"絕",
+"绣"=>"繡",
+"绦"=>"絛",
+"绱"=>"緔",
+"绷"=>"綳",
+"绿"=>"綠",
+"缰"=>"韁",
+"苧"=>"苎",
+"莼"=>"蒓",
+"说"=>"說",
+"谣"=>"謠",
+"谫"=>"譾",
+"赃"=>"贓",
+"赍"=>"齎",
+"赝"=>"贗",
+"酝"=>"醞",
+"采"=>"採",
+"钩"=>"鉤",
+"钵"=>"缽",
+"锈"=>"銹",
+"锐"=>"銳",
+"锨"=>"杴",
+"镌"=>"鐫",
+"镢"=>"钁",
+"阅"=>"閱",
+"颓"=>"頹",
+"颜"=>"顏",
+"骂"=>"罵",
+"鲇"=>"鯰",
+"鲞"=>"鯗",
+"鳄"=>"鱷",
+"鸡"=>"雞",
+"鹚"=>"鶿",
+"䌶"=>"䊷",
+"䜥"=>"𧩙",
+"专"=>"專",
+"业"=>"業",
+"丛"=>"叢",
+"东"=>"東",
+"丝"=>"絲",
+"丢"=>"丟",
+"两"=>"兩",
+"严"=>"嚴",
+"丧"=>"喪",
+"个"=>"個",
+"临"=>"臨",
+"丽"=>"麗",
+"举"=>"舉",
+"义"=>"義",
+"乌"=>"烏",
+"乐"=>"樂",
+"乔"=>"喬",
+"习"=>"習",
+"乡"=>"鄉",
+"书"=>"書",
+"买"=>"買",
+"乱"=>"亂",
+"争"=>"爭",
+"于"=>"於",
+"亏"=>"虧",
+"亚"=>"亞",
+"亩"=>"畝",
+"亲"=>"親",
+"亵"=>"褻",
+"亸"=>"嚲",
+"亿"=>"億",
+"仅"=>"僅",
+"从"=>"從",
+"仑"=>"侖",
+"仓"=>"倉",
+"仪"=>"儀",
+"们"=>"們",
+"优"=>"優",
+"会"=>"會",
+"伛"=>"傴",
+"伞"=>"傘",
+"伟"=>"偉",
+"传"=>"傳",
+"伣"=>"俔",
+"伤"=>"傷",
+"伥"=>"倀",
+"伦"=>"倫",
+"伧"=>"傖",
+"伫"=>"佇",
+"佥"=>"僉",
+"侠"=>"俠",
+"侣"=>"侶",
+"侥"=>"僥",
+"侦"=>"偵",
+"侧"=>"側",
+"侨"=>"僑",
+"侩"=>"儈",
+"侪"=>"儕",
+"侬"=>"儂",
+"俣"=>"俁",
+"俦"=>"儔",
+"俨"=>"儼",
+"俩"=>"倆",
+"俪"=>"儷",
+"俫"=>"倈",
+"俭"=>"儉",
+"债"=>"債",
+"倾"=>"傾",
+"偬"=>"傯",
+"偻"=>"僂",
+"偾"=>"僨",
+"偿"=>"償",
+"傥"=>"儻",
+"傧"=>"儐",
+"储"=>"儲",
+"傩"=>"儺",
+"兑"=>"兌",
+"兖"=>"兗",
+"兰"=>"蘭",
+"关"=>"關",
+"兴"=>"興",
+"兹"=>"茲",
+"养"=>"養",
+"兽"=>"獸",
+"冁"=>"囅",
+"内"=>"內",
+"冈"=>"岡",
+"册"=>"冊",
+"写"=>"寫",
+"军"=>"軍",
+"农"=>"農",
+"冯"=>"馮",
+"决"=>"決",
+"况"=>"況",
+"冻"=>"凍",
+"净"=>"凈",
+"凉"=>"涼",
+"减"=>"減",
+"凑"=>"湊",
+"凛"=>"凜",
+"凤"=>"鳳",
+"凭"=>"憑",
+"凯"=>"凱",
+"击"=>"擊",
+"凿"=>"鑿",
+"刍"=>"芻",
+"刘"=>"劉",
+"则"=>"則",
+"刚"=>"剛",
+"创"=>"創",
+"删"=>"刪",
+"刬"=>"剗",
+"刭"=>"剄",
+"刹"=>"剎",
+"刽"=>"劊",
+"刿"=>"劌",
+"剀"=>"剴",
+"剂"=>"劑",
+"剐"=>"剮",
+"剑"=>"劍",
+"剥"=>"剝",
+"剧"=>"劇",
+"劝"=>"勸",
+"办"=>"辦",
+"务"=>"務",
+"劢"=>"勱",
+"动"=>"動",
+"励"=>"勵",
+"劲"=>"勁",
+"劳"=>"勞",
+"势"=>"勢",
+"勋"=>"勛",
+"勚"=>"勩",
+"匀"=>"勻",
+"匦"=>"匭",
+"匮"=>"匱",
+"区"=>"區",
+"医"=>"醫",
+"华"=>"華",
+"协"=>"協",
+"单"=>"單",
+"卖"=>"賣",
+"卢"=>"盧",
+"卫"=>"衛",
+"却"=>"卻",
+"厅"=>"廳",
+"厉"=>"厲",
+"压"=>"壓",
+"厌"=>"厭",
+"厍"=>"厙",
+"厐"=>"龎",
+"厘"=>"釐",
+"厢"=>"廂",
+"厣"=>"厴",
+"厦"=>"廈",
+"厨"=>"廚",
+"厩"=>"廄",
+"厮"=>"廝",
+"县"=>"縣",
+"叁"=>"叄",
+"参"=>"參",
+"双"=>"雙",
+"变"=>"變",
+"叙"=>"敘",
+"叠"=>"疊",
+"号"=>"號",
+"叹"=>"嘆",
+"叽"=>"嘰",
+"吓"=>"嚇",
+"吕"=>"呂",
+"吗"=>"嗎",
+"吣"=>"唚",
+"吨"=>"噸",
+"听"=>"聽",
+"吴"=>"吳",
+"呐"=>"吶",
+"呒"=>"嘸",
+"呓"=>"囈",
+"呕"=>"嘔",
+"呖"=>"嚦",
+"呗"=>"唄",
+"员"=>"員",
+"呙"=>"咼",
+"呛"=>"嗆",
+"呜"=>"嗚",
+"咏"=>"詠",
+"咙"=>"嚨",
+"咛"=>"嚀",
+"咝"=>"噝",
+"咤"=>"吒",
+"响"=>"響",
+"哑"=>"啞",
+"哒"=>"噠",
+"哓"=>"嘵",
+"哔"=>"嗶",
+"哕"=>"噦",
+"哗"=>"嘩",
+"哙"=>"噲",
+"哜"=>"嚌",
+"哝"=>"噥",
+"哟"=>"喲",
+"唛"=>"嘜",
+"唝"=>"嗊",
+"唠"=>"嘮",
+"唡"=>"啢",
+"唢"=>"嗩",
+"唤"=>"喚",
+"啧"=>"嘖",
+"啬"=>"嗇",
+"啭"=>"囀",
+"啮"=>"嚙",
+"啴"=>"嘽",
+"啸"=>"嘯",
+"㖞"=>"喎",
+"喷"=>"噴",
+"喽"=>"嘍",
+"喾"=>"嚳",
+"嗫"=>"囁",
+"嗳"=>"噯",
+"嘘"=>"噓",
+"嘤"=>"嚶",
+"嘱"=>"囑",
+"噜"=>"嚕",
+"嚣"=>"囂",
+"园"=>"園",
+"囱"=>"囪",
+"围"=>"圍",
+"囵"=>"圇",
+"国"=>"國",
+"图"=>"圖",
+"圆"=>"圓",
+"圣"=>"聖",
+"圹"=>"壙",
+"场"=>"場",
+"坂"=>"阪",
+"块"=>"塊",
+"坚"=>"堅",
+"坜"=>"壢",
+"坝"=>"壩",
+"坞"=>"塢",
+"坟"=>"墳",
+"坠"=>"墜",
+"垄"=>"壟",
+"垅"=>"壠",
+"垆"=>"壚",
+"垒"=>"壘",
+"垦"=>"墾",
+"垩"=>"堊",
+"垫"=>"墊",
+"垭"=>"埡",
+"垱"=>"壋",
+"垲"=>"塏",
+"垴"=>"堖",
+"埘"=>"塒",
+"埙"=>"塤",
+"埚"=>"堝",
+"埯"=>"垵",
+"堑"=>"塹",
+"堕"=>"墮",
+"𡒄"=>"壈",
+"壮"=>"壯",
+"声"=>"聲",
+"壶"=>"壺",
+"壸"=>"壼",
+"处"=>"處",
+"备"=>"備",
+"够"=>"夠",
+"头"=>"頭",
+"夸"=>"誇",
+"夹"=>"夾",
+"夺"=>"奪",
+"奁"=>"奩",
+"奂"=>"奐",
+"奋"=>"奮",
+"奥"=>"奧",
+"奸"=>"姦",
+"妆"=>"妝",
+"妇"=>"婦",
+"妈"=>"媽",
+"妩"=>"嫵",
+"妪"=>"嫗",
+"姗"=>"姍",
+"姹"=>"奼",
+"娄"=>"婁",
+"娅"=>"婭",
+"娆"=>"嬈",
+"娇"=>"嬌",
+"娈"=>"孌",
+"娱"=>"娛",
+"娲"=>"媧",
+"娴"=>"嫻",
+"婳"=>"嫿",
+"婴"=>"嬰",
+"婵"=>"嬋",
+"婶"=>"嬸",
+"媪"=>"媼",
+"嫒"=>"嬡",
+"嫔"=>"嬪",
+"嫱"=>"嬙",
+"嬷"=>"嬤",
+"孙"=>"孫",
+"学"=>"學",
+"孪"=>"孿",
+"宝"=>"寶",
+"实"=>"實",
+"宠"=>"寵",
+"审"=>"審",
+"宪"=>"憲",
+"宫"=>"宮",
+"宽"=>"寬",
+"宾"=>"賓",
+"寝"=>"寢",
+"对"=>"對",
+"寻"=>"尋",
+"导"=>"導",
+"寿"=>"壽",
+"将"=>"將",
+"尔"=>"爾",
+"尘"=>"塵",
+"尝"=>"嘗",
+"尧"=>"堯",
+"尴"=>"尷",
+"尸"=>"屍",
+"层"=>"層",
+"屃"=>"屓",
+"屉"=>"屜",
+"届"=>"屆",
+"属"=>"屬",
+"屡"=>"屢",
+"屦"=>"屨",
+"屿"=>"嶼",
+"岁"=>"歲",
+"岂"=>"豈",
+"岖"=>"嶇",
+"岗"=>"崗",
+"岘"=>"峴",
+"岙"=>"嶴",
+"岚"=>"嵐",
+"岛"=>"島",
+"岭"=>"嶺",
+"岽"=>"崬",
+"岿"=>"巋",
+"峄"=>"嶧",
+"峡"=>"峽",
+"峣"=>"嶢",
+"峤"=>"嶠",
+"峥"=>"崢",
+"峦"=>"巒",
+"崂"=>"嶗",
+"崃"=>"崍",
+"崄"=>"嶮",
+"崭"=>"嶄",
+"嵘"=>"嶸",
+"嵚"=>"嶔",
+"嵝"=>"嶁",
+"巅"=>"巔",
+"巩"=>"鞏",
+"巯"=>"巰",
+"币"=>"幣",
+"帅"=>"帥",
+"师"=>"師",
+"帏"=>"幃",
+"帐"=>"帳",
+"帜"=>"幟",
+"带"=>"帶",
+"帧"=>"幀",
+"帮"=>"幫",
+"帱"=>"幬",
+"帻"=>"幘",
+"帼"=>"幗",
+"幂"=>"冪",
+"幺"=>"么",
+"庄"=>"莊",
+"庆"=>"慶",
+"庐"=>"廬",
+"庑"=>"廡",
+"库"=>"庫",
+"应"=>"應",
+"庙"=>"廟",
+"庞"=>"龐",
+"废"=>"廢",
+"廪"=>"廩",
+"开"=>"開",
+"异"=>"異",
+"弃"=>"棄",
+"弑"=>"弒",
+"张"=>"張",
+"弪"=>"弳",
+"弯"=>"彎",
+"弹"=>"彈",
+"强"=>"強",
+"归"=>"歸",
+"彝"=>"彞",
+"彦"=>"彥",
+"彻"=>"徹",
+"径"=>"徑",
+"徕"=>"徠",
+"忆"=>"憶",
+"忏"=>"懺",
+"忧"=>"憂",
+"忾"=>"愾",
+"怀"=>"懷",
+"态"=>"態",
+"怂"=>"慫",
+"怃"=>"憮",
+"怄"=>"慪",
+"怅"=>"悵",
+"怆"=>"愴",
+"怜"=>"憐",
+"总"=>"總",
+"怼"=>"懟",
+"怿"=>"懌",
+"恋"=>"戀",
+"恒"=>"恆",
+"恳"=>"懇",
+"恸"=>"慟",
+"恹"=>"懨",
+"恺"=>"愷",
+"恻"=>"惻",
+"恼"=>"惱",
+"恽"=>"惲",
+"悦"=>"悅",
+"悬"=>"懸",
+"悭"=>"慳",
+"悮"=>"悞",
+"悯"=>"憫",
+"惊"=>"驚",
+"惧"=>"懼",
+"惨"=>"慘",
+"惩"=>"懲",
+"惫"=>"憊",
+"惬"=>"愜",
+"惭"=>"慚",
+"惮"=>"憚",
+"惯"=>"慣",
+"愠"=>"慍",
+"愤"=>"憤",
+"愦"=>"憒",
+"慑"=>"懾",
+"懑"=>"懣",
+"懒"=>"懶",
+"懔"=>"懍",
+"戆"=>"戇",
+"戋"=>"戔",
+"戏"=>"戲",
+"戗"=>"戧",
+"战"=>"戰",
+"戬"=>"戩",
+"戯"=>"戱",
+"户"=>"戶",
+"扑"=>"撲",
+"执"=>"執",
+"扩"=>"擴",
+"扪"=>"捫",
+"扫"=>"掃",
+"扬"=>"揚",
+"扰"=>"擾",
+"抚"=>"撫",
+"抛"=>"拋",
+"抟"=>"摶",
+"抠"=>"摳",
+"抡"=>"掄",
+"抢"=>"搶",
+"护"=>"護",
+"报"=>"報",
+"拟"=>"擬",
+"拢"=>"攏",
+"拣"=>"揀",
+"拥"=>"擁",
+"拦"=>"攔",
+"拧"=>"擰",
+"拨"=>"撥",
+"择"=>"擇",
+"挂"=>"掛",
+"挚"=>"摯",
+"挛"=>"攣",
+"挜"=>"掗",
+"挝"=>"撾",
+"挞"=>"撻",
+"挟"=>"挾",
+"挠"=>"撓",
+"挡"=>"擋",
+"挢"=>"撟",
+"挣"=>"掙",
+"挤"=>"擠",
+"挥"=>"揮",
+"挦"=>"撏",
+"挽"=>"輓",
+"捝"=>"挩",
+"捞"=>"撈",
+"损"=>"損",
+"捡"=>"撿",
+"换"=>"換",
+"捣"=>"搗",
+"掳"=>"擄",
+"掴"=>"摑",
+"掷"=>"擲",
+"掸"=>"撣",
+"掺"=>"摻",
+"掼"=>"摜",
+"揽"=>"攬",
+"揾"=>"搵",
+"揿"=>"撳",
+"搀"=>"攙",
+"搁"=>"擱",
+"搂"=>"摟",
+"搅"=>"攪",
+"携"=>"攜",
+"摄"=>"攝",
+"摅"=>"攄",
+"摆"=>"擺",
+"摇"=>"搖",
+"摈"=>"擯",
+"摊"=>"攤",
+"撄"=>"攖",
+"撑"=>"撐",
+"㧑"=>"撝",
+"撵"=>"攆",
+"撷"=>"擷",
+"撸"=>"擼",
+"撺"=>"攛",
+"㧟"=>"擓",
+"擞"=>"擻",
+"攒"=>"攢",
+"敌"=>"敵",
+"敛"=>"斂",
+"数"=>"數",
+"斋"=>"齋",
+"斓"=>"斕",
+"斩"=>"斬",
+"断"=>"斷",
+"无"=>"無",
+"旧"=>"舊",
+"时"=>"時",
+"旷"=>"曠",
+"旸"=>"暘",
+"昙"=>"曇",
+"昼"=>"晝",
+"昽"=>"曨",
+"显"=>"顯",
+"晋"=>"晉",
+"晒"=>"曬",
+"晓"=>"曉",
+"晔"=>"曄",
+"晕"=>"暈",
+"晖"=>"暉",
+"暂"=>"暫",
+"暧"=>"曖",
+"机"=>"機",
+"杀"=>"殺",
+"杂"=>"雜",
+"权"=>"權",
+"杆"=>"桿",
+"条"=>"條",
+"来"=>"來",
+"杨"=>"楊",
+"杩"=>"榪",
+"杰"=>"傑",
+"构"=>"構",
+"枞"=>"樅",
+"枢"=>"樞",
+"枣"=>"棗",
+"枥"=>"櫪",
+"枧"=>"梘",
+"枨"=>"棖",
+"枪"=>"槍",
+"枫"=>"楓",
+"枭"=>"梟",
+"柠"=>"檸",
+"柽"=>"檉",
+"栀"=>"梔",
+"栅"=>"柵",
+"标"=>"標",
+"栈"=>"棧",
+"栉"=>"櫛",
+"栊"=>"櫳",
+"栋"=>"棟",
+"栌"=>"櫨",
+"栎"=>"櫟",
+"栏"=>"欄",
+"树"=>"樹",
+"栖"=>"棲",
+"栗"=>"慄",
+"样"=>"樣",
+"栾"=>"欒",
+"桠"=>"椏",
+"桡"=>"橈",
+"桢"=>"楨",
+"档"=>"檔",
+"桤"=>"榿",
+"桥"=>"橋",
+"桦"=>"樺",
+"桧"=>"檜",
+"桨"=>"槳",
+"桩"=>"樁",
+"梦"=>"夢",
+"梼"=>"檮",
+"梾"=>"棶",
+"梿"=>"槤",
+"检"=>"檢",
+"棁"=>"梲",
+"棂"=>"欞",
+"椁"=>"槨",
+"椟"=>"櫝",
+"椠"=>"槧",
+"椤"=>"欏",
+"椭"=>"橢",
+"楼"=>"樓",
+"榄"=>"欖",
+"榅"=>"榲",
+"榇"=>"櫬",
+"榈"=>"櫚",
+"榉"=>"櫸",
+"槚"=>"檟",
+"槛"=>"檻",
+"槟"=>"檳",
+"槠"=>"櫧",
+"横"=>"橫",
+"樯"=>"檣",
+"樱"=>"櫻",
+"橥"=>"櫫",
+"橱"=>"櫥",
+"橹"=>"櫓",
+"橼"=>"櫞",
+"檩"=>"檁",
+"欢"=>"歡",
+"欤"=>"歟",
+"欧"=>"歐",
+"歼"=>"殲",
+"殁"=>"歿",
+"殇"=>"殤",
+"残"=>"殘",
+"殒"=>"殞",
+"殓"=>"殮",
+"殚"=>"殫",
+"殡"=>"殯",
+"㱮"=>"殨",
+"殴"=>"毆",
+"毁"=>"毀",
+"毂"=>"轂",
+"毕"=>"畢",
+"毙"=>"斃",
+"毡"=>"氈",
+"毵"=>"毿",
+"氇"=>"氌",
+"气"=>"氣",
+"氢"=>"氫",
+"氩"=>"氬",
+"氲"=>"氳",
+"汉"=>"漢",
+"汤"=>"湯",
+"汹"=>"洶",
+"沟"=>"溝",
+"没"=>"沒",
+"沣"=>"灃",
+"沤"=>"漚",
+"沥"=>"瀝",
+"沦"=>"淪",
+"沧"=>"滄",
+"沪"=>"滬",
+"泞"=>"濘",
+"注"=>"註",
+"泪"=>"淚",
+"泶"=>"澩",
+"泷"=>"瀧",
+"泸"=>"瀘",
+"泺"=>"濼",
+"泻"=>"瀉",
+"泼"=>"潑",
+"泽"=>"澤",
+"泾"=>"涇",
+"洁"=>"潔",
+"洒"=>"灑",
+"洼"=>"窪",
+"浃"=>"浹",
+"浅"=>"淺",
+"浆"=>"漿",
+"浇"=>"澆",
+"浈"=>"湞",
+"浊"=>"濁",
+"测"=>"測",
+"浍"=>"澮",
+"济"=>"濟",
+"浏"=>"瀏",
+"浐"=>"滻",
+"浑"=>"渾",
+"浒"=>"滸",
+"浓"=>"濃",
+"浔"=>"潯",
+"涛"=>"濤",
+"涝"=>"澇",
+"涞"=>"淶",
+"涟"=>"漣",
+"涠"=>"潿",
+"涡"=>"渦",
+"涣"=>"渙",
+"涤"=>"滌",
+"润"=>"潤",
+"涧"=>"澗",
+"涨"=>"漲",
+"涩"=>"澀",
+"渊"=>"淵",
+"渌"=>"淥",
+"渍"=>"漬",
+"渎"=>"瀆",
+"渐"=>"漸",
+"渑"=>"澠",
+"渔"=>"漁",
+"渖"=>"瀋",
+"渗"=>"滲",
+"温"=>"溫",
+"湾"=>"灣",
+"湿"=>"濕",
+"溃"=>"潰",
+"溅"=>"濺",
+"溆"=>"漵",
+"滗"=>"潷",
+"滚"=>"滾",
+"滞"=>"滯",
+"滟"=>"灧",
+"滠"=>"灄",
+"满"=>"滿",
+"滢"=>"瀅",
+"滤"=>"濾",
+"滥"=>"濫",
+"滦"=>"灤",
+"滨"=>"濱",
+"滩"=>"灘",
+"滪"=>"澦",
+"漤"=>"灠",
+"潆"=>"瀠",
+"潇"=>"瀟",
+"潋"=>"瀲",
+"潍"=>"濰",
+"潜"=>"潛",
+"潴"=>"瀦",
+"澜"=>"瀾",
+"濑"=>"瀨",
+"濒"=>"瀕",
+"灏"=>"灝",
+"灭"=>"滅",
+"灯"=>"燈",
+"灵"=>"靈",
+"灶"=>"竈",
+"灾"=>"災",
+"灿"=>"燦",
+"炀"=>"煬",
+"炉"=>"爐",
+"炖"=>"燉",
+"炜"=>"煒",
+"炝"=>"熗",
+"点"=>"點",
+"炼"=>"煉",
+"炽"=>"熾",
+"烁"=>"爍",
+"烂"=>"爛",
+"烃"=>"烴",
+"烛"=>"燭",
+"烟"=>"煙",
+"烦"=>"煩",
+"烧"=>"燒",
+"烨"=>"燁",
+"烩"=>"燴",
+"烫"=>"燙",
+"烬"=>"燼",
+"热"=>"熱",
+"焕"=>"煥",
+"焖"=>"燜",
+"焘"=>"燾",
+"煴"=>"熅",
+"爱"=>"愛",
+"爷"=>"爺",
+"牍"=>"牘",
+"牦"=>"氂",
+"牵"=>"牽",
+"牺"=>"犧",
+"犊"=>"犢",
+"状"=>"狀",
+"犷"=>"獷",
+"犸"=>"獁",
+"犹"=>"猶",
+"狈"=>"狽",
+"狝"=>"獮",
+"狞"=>"獰",
+"独"=>"獨",
+"狭"=>"狹",
+"狮"=>"獅",
+"狯"=>"獪",
+"狰"=>"猙",
+"狱"=>"獄",
+"狲"=>"猻",
+"猃"=>"獫",
+"猎"=>"獵",
+"猕"=>"獼",
+"猡"=>"玀",
+"猪"=>"豬",
+"猫"=>"貓",
+"猬"=>"蝟",
+"献"=>"獻",
+"獭"=>"獺",
+"玑"=>"璣",
+"玚"=>"瑒",
+"玛"=>"瑪",
+"玮"=>"瑋",
+"环"=>"環",
+"现"=>"現",
+"玱"=>"瑲",
+"玺"=>"璽",
+"珐"=>"琺",
+"珑"=>"瓏",
+"珰"=>"璫",
+"珲"=>"琿",
+"琏"=>"璉",
+"琐"=>"瑣",
+"琼"=>"瓊",
+"瑶"=>"瑤",
+"瑷"=>"璦",
+"璎"=>"瓔",
+"瓒"=>"瓚",
+"瓯"=>"甌",
+"电"=>"電",
+"画"=>"畫",
+"畅"=>"暢",
+"畴"=>"疇",
+"疖"=>"癤",
+"疗"=>"療",
+"疟"=>"瘧",
+"疠"=>"癘",
+"疡"=>"瘍",
+"疬"=>"癧",
+"疭"=>"瘲",
+"疮"=>"瘡",
+"疯"=>"瘋",
+"疱"=>"皰",
+"疴"=>"痾",
+"痈"=>"癰",
+"痉"=>"痙",
+"痒"=>"癢",
+"痖"=>"瘂",
+"痨"=>"癆",
+"痪"=>"瘓",
+"痫"=>"癇",
+"瘅"=>"癉",
+"瘆"=>"瘮",
+"瘗"=>"瘞",
+"瘪"=>"癟",
+"瘫"=>"癱",
+"瘾"=>"癮",
+"瘿"=>"癭",
+"癞"=>"癩",
+"癣"=>"癬",
+"癫"=>"癲",
+"皑"=>"皚",
+"皱"=>"皺",
+"皲"=>"皸",
+"盏"=>"盞",
+"盐"=>"鹽",
+"监"=>"監",
+"盖"=>"蓋",
+"盗"=>"盜",
+"盘"=>"盤",
+"眍"=>"瞘",
+"眦"=>"眥",
+"眬"=>"矓",
+"着"=>"著",
+"睁"=>"睜",
+"睐"=>"睞",
+"睑"=>"瞼",
+"瞆"=>"瞶",
+"瞒"=>"瞞",
+"䁖"=>"瞜",
+"瞩"=>"矚",
+"矫"=>"矯",
+"矶"=>"磯",
+"矾"=>"礬",
+"矿"=>"礦",
+"砀"=>"碭",
+"码"=>"碼",
+"砖"=>"磚",
+"砗"=>"硨",
+"砚"=>"硯",
+"砜"=>"碸",
+"砺"=>"礪",
+"砻"=>"礱",
+"砾"=>"礫",
+"础"=>"礎",
+"硁"=>"硜",
+"硕"=>"碩",
+"硖"=>"硤",
+"硗"=>"磽",
+"硙"=>"磑",
+"碍"=>"礙",
+"碛"=>"磧",
+"碜"=>"磣",
+"碱"=>"鹼",
+"礼"=>"禮",
+"祃"=>"禡",
+"祎"=>"禕",
+"祢"=>"禰",
+"祯"=>"禎",
+"祷"=>"禱",
+"祸"=>"禍",
+"禀"=>"稟",
+"禄"=>"祿",
+"禅"=>"禪",
+"离"=>"離",
+"秃"=>"禿",
+"秆"=>"稈",
+"积"=>"積",
+"称"=>"稱",
+"秽"=>"穢",
+"秾"=>"穠",
+"稆"=>"穭",
+"税"=>"稅",
+"稣"=>"穌",
+"稳"=>"穩",
+"穑"=>"穡",
+"穷"=>"窮",
+"窃"=>"竊",
+"窍"=>"竅",
+"窎"=>"窵",
+"窑"=>"窯",
+"窜"=>"竄",
+"窝"=>"窩",
+"窥"=>"窺",
+"窦"=>"竇",
+"窭"=>"窶",
+"竞"=>"競",
+"笃"=>"篤",
+"笋"=>"筍",
+"笔"=>"筆",
+"笕"=>"筧",
+"笺"=>"箋",
+"笼"=>"籠",
+"笾"=>"籩",
+"筚"=>"篳",
+"筛"=>"篩",
+"筜"=>"簹",
+"筝"=>"箏",
+"䇲"=>"筴",
+"筹"=>"籌",
+"筼"=>"篔",
+"简"=>"簡",
+"箓"=>"籙",
+"箦"=>"簀",
+"箧"=>"篋",
+"箨"=>"籜",
+"箩"=>"籮",
+"箪"=>"簞",
+"箫"=>"簫",
+"篑"=>"簣",
+"篓"=>"簍",
+"篮"=>"籃",
+"篱"=>"籬",
+"簖"=>"籪",
+"籁"=>"籟",
+"籴"=>"糴",
+"类"=>"類",
+"籼"=>"秈",
+"粜"=>"糶",
+"粝"=>"糲",
+"粤"=>"粵",
+"粪"=>"糞",
+"粮"=>"糧",
+"糁"=>"糝",
+"糇"=>"餱",
+"紧"=>"緊",
+"䌷"=>"紬",
+"䌹"=>"絅",
+"絷"=>"縶",
+"䌸"=>"縳",
+"䍁"=>"繸",
+"纟"=>"糹",
+"纠"=>"糾",
+"纡"=>"紆",
+"红"=>"紅",
+"纣"=>"紂",
+"纥"=>"紇",
+"约"=>"約",
+"级"=>"級",
+"纨"=>"紈",
+"纩"=>"纊",
+"纪"=>"紀",
+"纫"=>"紉",
+"纬"=>"緯",
+"纭"=>"紜",
+"纮"=>"紘",
+"纯"=>"純",
+"纰"=>"紕",
+"纱"=>"紗",
+"纲"=>"綱",
+"纳"=>"納",
+"纴"=>"紝",
+"纵"=>"縱",
+"纶"=>"綸",
+"纷"=>"紛",
+"纸"=>"紙",
+"纹"=>"紋",
+"纺"=>"紡",
+"纻"=>"紵",
+"纼"=>"紖",
+"纽"=>"紐",
+"纾"=>"紓",
+"绀"=>"紺",
+"绁"=>"紲",
+"绂"=>"紱",
+"练"=>"練",
+"组"=>"組",
+"绅"=>"紳",
+"细"=>"細",
+"织"=>"織",
+"终"=>"終",
+"绉"=>"縐",
+"绊"=>"絆",
+"绋"=>"紼",
+"绌"=>"絀",
+"绍"=>"紹",
+"绎"=>"繹",
+"经"=>"經",
+"绐"=>"紿",
+"绑"=>"綁",
+"绒"=>"絨",
+"结"=>"結",
+"绔"=>"絝",
+"绕"=>"繞",
+"绖"=>"絰",
+"绗"=>"絎",
+"绘"=>"繪",
+"给"=>"給",
+"绚"=>"絢",
+"绛"=>"絳",
+"络"=>"絡",
+"绞"=>"絞",
+"统"=>"統",
+"绠"=>"綆",
+"绡"=>"綃",
+"绢"=>"絹",
+"绤"=>"綌",
+"绥"=>"綏",
+"继"=>"繼",
+"绨"=>"綈",
+"绩"=>"績",
+"绪"=>"緒",
+"绫"=>"綾",
+"绬"=>"緓",
+"续"=>"續",
+"绮"=>"綺",
+"绯"=>"緋",
+"绰"=>"綽",
+"绲"=>"緄",
+"绳"=>"繩",
+"维"=>"維",
+"绵"=>"綿",
+"绶"=>"綬",
+"绸"=>"綢",
+"绹"=>"綯",
+"绺"=>"綹",
+"绻"=>"綣",
+"综"=>"綜",
+"绽"=>"綻",
+"绾"=>"綰",
+"缀"=>"綴",
+"缁"=>"緇",
+"缂"=>"緙",
+"缃"=>"緗",
+"缄"=>"緘",
+"缅"=>"緬",
+"缆"=>"纜",
+"缇"=>"緹",
+"缈"=>"緲",
+"缉"=>"緝",
+"缊"=>"縕",
+"缋"=>"繢",
+"缌"=>"緦",
+"缍"=>"綞",
+"缎"=>"緞",
+"缏"=>"緶",
+"缑"=>"緱",
+"缒"=>"縋",
+"缓"=>"緩",
+"缔"=>"締",
+"缕"=>"縷",
+"编"=>"編",
+"缗"=>"緡",
+"缘"=>"緣",
+"缙"=>"縉",
+"缚"=>"縛",
+"缛"=>"縟",
+"缜"=>"縝",
+"缝"=>"縫",
+"缞"=>"縗",
+"缟"=>"縞",
+"缠"=>"纏",
+"缡"=>"縭",
+"缢"=>"縊",
+"缣"=>"縑",
+"缤"=>"繽",
+"缥"=>"縹",
+"缦"=>"縵",
+"缧"=>"縲",
+"缨"=>"纓",
+"缩"=>"縮",
+"缪"=>"繆",
+"缫"=>"繅",
+"缬"=>"纈",
+"缭"=>"繚",
+"缮"=>"繕",
+"缯"=>"繒",
+"缱"=>"繾",
+"缲"=>"繰",
+"缳"=>"繯",
+"缴"=>"繳",
+"缵"=>"纘",
+"罂"=>"罌",
+"网"=>"網",
+"罗"=>"羅",
+"罚"=>"罰",
+"罢"=>"罷",
+"罴"=>"羆",
+"羁"=>"羈",
+"羟"=>"羥",
+"翘"=>"翹",
+"耢"=>"耮",
+"耧"=>"耬",
+"耸"=>"聳",
+"耻"=>"恥",
+"聂"=>"聶",
+"聋"=>"聾",
+"职"=>"職",
+"聍"=>"聹",
+"联"=>"聯",
+"聩"=>"聵",
+"聪"=>"聰",
+"肃"=>"肅",
+"肠"=>"腸",
+"肤"=>"膚",
+"肮"=>"骯",
+"肴"=>"餚",
+"肾"=>"腎",
+"肿"=>"腫",
+"胀"=>"脹",
+"胁"=>"脅",
+"胆"=>"膽",
+"胧"=>"朧",
+"胨"=>"腖",
+"胪"=>"臚",
+"胫"=>"脛",
+"胶"=>"膠",
+"脉"=>"脈",
+"脍"=>"膾",
+"脐"=>"臍",
+"脑"=>"腦",
+"脓"=>"膿",
+"脔"=>"臠",
+"脚"=>"腳",
+"脱"=>"脫",
+"脶"=>"腡",
+"脸"=>"臉",
+"腭"=>"齶",
+"腻"=>"膩",
+"腼"=>"靦",
+"腽"=>"膃",
+"腾"=>"騰",
+"膑"=>"臏",
+"臜"=>"臢",
+"舆"=>"輿",
+"舣"=>"艤",
+"舰"=>"艦",
+"舱"=>"艙",
+"舻"=>"艫",
+"艰"=>"艱",
+"艳"=>"艷",
+"艺"=>"藝",
+"节"=>"節",
+"芈"=>"羋",
+"芗"=>"薌",
+"芜"=>"蕪",
+"芦"=>"蘆",
+"苁"=>"蓯",
+"苇"=>"葦",
+"苈"=>"藶",
+"苋"=>"莧",
+"苌"=>"萇",
+"苍"=>"蒼",
+"苎"=>"苧",
+"茎"=>"莖",
+"茏"=>"蘢",
+"茑"=>"蔦",
+"茔"=>"塋",
+"茕"=>"煢",
+"茧"=>"繭",
+"荆"=>"荊",
+"荐"=>"薦",
+"荙"=>"薘",
+"荚"=>"莢",
+"荛"=>"蕘",
+"荜"=>"蓽",
+"荞"=>"蕎",
+"荟"=>"薈",
+"荠"=>"薺",
+"荡"=>"蕩",
+"荣"=>"榮",
+"荤"=>"葷",
+"荥"=>"滎",
+"荦"=>"犖",
+"荧"=>"熒",
+"荨"=>"蕁",
+"荩"=>"藎",
+"荪"=>"蓀",
+"荫"=>"蔭",
+"荬"=>"蕒",
+"荭"=>"葒",
+"荮"=>"葤",
+"莅"=>"蒞",
+"莱"=>"萊",
+"莲"=>"蓮",
+"莳"=>"蒔",
+"莴"=>"萵",
+"莶"=>"薟",
+"莸"=>"蕕",
+"莹"=>"瑩",
+"莺"=>"鶯",
+"萝"=>"蘿",
+"萤"=>"螢",
+"营"=>"營",
+"萦"=>"縈",
+"萧"=>"蕭",
+"萨"=>"薩",
+"葱"=>"蔥",
+"蒇"=>"蕆",
+"蒉"=>"蕢",
+"蒋"=>"蔣",
+"蒌"=>"蔞",
+"蓝"=>"藍",
+"蓟"=>"薊",
+"蓠"=>"蘺",
+"蓣"=>"蕷",
+"蓥"=>"鎣",
+"蓦"=>"驀",
+"蔂"=>"虆",
+"蔷"=>"薔",
+"蔹"=>"蘞",
+"蔺"=>"藺",
+"蔼"=>"藹",
+"蕰"=>"薀",
+"蕲"=>"蘄",
+"薮"=>"藪",
+"藓"=>"蘚",
+"蘖"=>"櫱",
+"虏"=>"虜",
+"虑"=>"慮",
+"虚"=>"虛",
+"虬"=>"虯",
+"虮"=>"蟣",
+"虽"=>"雖",
+"虾"=>"蝦",
+"虿"=>"蠆",
+"蚀"=>"蝕",
+"蚁"=>"蟻",
+"蚂"=>"螞",
+"蚕"=>"蠶",
+"蚬"=>"蜆",
+"蛊"=>"蠱",
+"蛎"=>"蠣",
+"蛏"=>"蟶",
+"蛮"=>"蠻",
+"蛰"=>"蟄",
+"蛱"=>"蛺",
+"蛲"=>"蟯",
+"蛳"=>"螄",
+"蛴"=>"蠐",
+"蜕"=>"蛻",
+"蜗"=>"蝸",
+"蝇"=>"蠅",
+"蝈"=>"蟈",
+"蝉"=>"蟬",
+"蝼"=>"螻",
+"蝾"=>"蠑",
+"螀"=>"螿",
+"螨"=>"蟎",
+"蟏"=>"蠨",
+"衅"=>"釁",
+"衔"=>"銜",
+"补"=>"補",
+"衬"=>"襯",
+"衮"=>"袞",
+"袄"=>"襖",
+"袅"=>"裊",
+"袆"=>"褘",
+"袜"=>"襪",
+"袭"=>"襲",
+"袯"=>"襏",
+"装"=>"裝",
+"裆"=>"襠",
+"裈"=>"褌",
+"裢"=>"褳",
+"裣"=>"襝",
+"裤"=>"褲",
+"裥"=>"襇",
+"褛"=>"褸",
+"褴"=>"襤",
+"见"=>"見",
+"观"=>"觀",
+"觃"=>"覎",
+"规"=>"規",
+"觅"=>"覓",
+"视"=>"視",
+"觇"=>"覘",
+"览"=>"覽",
+"觉"=>"覺",
+"觊"=>"覬",
+"觋"=>"覡",
+"觌"=>"覿",
+"觍"=>"覥",
+"觎"=>"覦",
+"觏"=>"覯",
+"觐"=>"覲",
+"觑"=>"覷",
+"觞"=>"觴",
+"触"=>"觸",
+"觯"=>"觶",
+"訚"=>"誾",
+"䜣"=>"訢",
+"誉"=>"譽",
+"誊"=>"謄",
+"讠"=>"訁",
+"计"=>"計",
+"订"=>"訂",
+"讣"=>"訃",
+"认"=>"認",
+"讥"=>"譏",
+"讦"=>"訐",
+"讧"=>"訌",
+"讨"=>"討",
+"让"=>"讓",
+"讪"=>"訕",
+"讫"=>"訖",
+"讬"=>"託",
+"训"=>"訓",
+"议"=>"議",
+"讯"=>"訊",
+"记"=>"記",
+"讱"=>"訒",
+"讲"=>"講",
+"讳"=>"諱",
+"讴"=>"謳",
+"讵"=>"詎",
+"讶"=>"訝",
+"讷"=>"訥",
+"许"=>"許",
+"讹"=>"訛",
+"论"=>"論",
+"讻"=>"訩",
+"讼"=>"訟",
+"讽"=>"諷",
+"设"=>"設",
+"访"=>"訪",
+"诀"=>"訣",
+"证"=>"證",
+"诂"=>"詁",
+"诃"=>"訶",
+"评"=>"評",
+"诅"=>"詛",
+"识"=>"識",
+"诇"=>"詗",
+"诈"=>"詐",
+"诉"=>"訴",
+"诊"=>"診",
+"诋"=>"詆",
+"诌"=>"謅",
+"词"=>"詞",
+"诎"=>"詘",
+"诏"=>"詔",
+"诐"=>"詖",
+"译"=>"譯",
+"诒"=>"詒",
+"诓"=>"誆",
+"诔"=>"誄",
+"试"=>"試",
+"诖"=>"詿",
+"诗"=>"詩",
+"诘"=>"詰",
+"诙"=>"詼",
+"诚"=>"誠",
+"诛"=>"誅",
+"诜"=>"詵",
+"话"=>"話",
+"诞"=>"誕",
+"诟"=>"詬",
+"诠"=>"詮",
+"诡"=>"詭",
+"询"=>"詢",
+"诣"=>"詣",
+"诤"=>"諍",
+"该"=>"該",
+"详"=>"詳",
+"诧"=>"詫",
+"诨"=>"諢",
+"诩"=>"詡",
+"诪"=>"譸",
+"诫"=>"誡",
+"诬"=>"誣",
+"语"=>"語",
+"诮"=>"誚",
+"误"=>"誤",
+"诰"=>"誥",
+"诱"=>"誘",
+"诲"=>"誨",
+"诳"=>"誑",
+"诵"=>"誦",
+"诶"=>"誒",
+"请"=>"請",
+"诸"=>"諸",
+"诹"=>"諏",
+"诺"=>"諾",
+"读"=>"讀",
+"诼"=>"諑",
+"诽"=>"誹",
+"课"=>"課",
+"诿"=>"諉",
+"谀"=>"諛",
+"谁"=>"誰",
+"谂"=>"諗",
+"调"=>"調",
+"谄"=>"諂",
+"谅"=>"諒",
+"谆"=>"諄",
+"谇"=>"誶",
+"谈"=>"談",
+"谊"=>"誼",
+"谋"=>"謀",
+"谌"=>"諶",
+"谍"=>"諜",
+"谎"=>"謊",
+"谏"=>"諫",
+"谐"=>"諧",
+"谑"=>"謔",
+"谒"=>"謁",
+"谓"=>"謂",
+"谔"=>"諤",
+"谕"=>"諭",
+"谖"=>"諼",
+"谗"=>"讒",
+"谘"=>"諮",
+"谙"=>"諳",
+"谚"=>"諺",
+"谛"=>"諦",
+"谜"=>"謎",
+"谝"=>"諞",
+"谞"=>"諝",
+"谟"=>"謨",
+"谠"=>"讜",
+"谡"=>"謖",
+"谢"=>"謝",
+"谤"=>"謗",
+"谥"=>"謚",
+"谦"=>"謙",
+"谧"=>"謐",
+"谨"=>"謹",
+"谩"=>"謾",
+"谪"=>"謫",
+"谬"=>"謬",
+"谭"=>"譚",
+"谮"=>"譖",
+"谯"=>"譙",
+"谰"=>"讕",
+"谱"=>"譜",
+"谲"=>"譎",
+"谳"=>"讞",
+"谴"=>"譴",
+"谵"=>"譫",
+"谶"=>"讖",
+"豮"=>"豶",
+"贝"=>"貝",
+"贞"=>"貞",
+"负"=>"負",
+"贠"=>"貟",
+"贡"=>"貢",
+"财"=>"財",
+"责"=>"責",
+"贤"=>"賢",
+"败"=>"敗",
+"账"=>"賬",
+"货"=>"貨",
+"质"=>"質",
+"贩"=>"販",
+"贪"=>"貪",
+"贫"=>"貧",
+"贬"=>"貶",
+"购"=>"購",
+"贮"=>"貯",
+"贯"=>"貫",
+"贰"=>"貳",
+"贱"=>"賤",
+"贲"=>"賁",
+"贳"=>"貰",
+"贴"=>"貼",
+"贵"=>"貴",
+"贶"=>"貺",
+"贷"=>"貸",
+"贸"=>"貿",
+"费"=>"費",
+"贺"=>"賀",
+"贻"=>"貽",
+"贼"=>"賊",
+"贽"=>"贄",
+"贾"=>"賈",
+"贿"=>"賄",
+"赀"=>"貲",
+"赁"=>"賃",
+"赂"=>"賂",
+"资"=>"資",
+"赅"=>"賅",
+"赆"=>"贐",
+"赇"=>"賕",
+"赈"=>"賑",
+"赉"=>"賚",
+"赊"=>"賒",
+"赋"=>"賦",
+"赌"=>"賭",
+"赎"=>"贖",
+"赏"=>"賞",
+"赐"=>"賜",
+"赑"=>"贔",
+"赒"=>"賙",
+"赓"=>"賡",
+"赔"=>"賠",
+"赕"=>"賧",
+"赖"=>"賴",
+"赗"=>"賵",
+"赘"=>"贅",
+"赙"=>"賻",
+"赚"=>"賺",
+"赛"=>"賽",
+"赜"=>"賾",
+"赞"=>"贊",
+"赟"=>"贇",
+"赠"=>"贈",
+"赡"=>"贍",
+"赢"=>"贏",
+"赣"=>"贛",
+"赪"=>"赬",
+"赵"=>"趙",
+"赶"=>"趕",
+"趋"=>"趨",
+"趱"=>"趲",
+"趸"=>"躉",
+"跃"=>"躍",
+"跄"=>"蹌",
+"跞"=>"躒",
+"践"=>"踐",
+"跶"=>"躂",
+"跷"=>"蹺",
+"跸"=>"蹕",
+"跹"=>"躚",
+"跻"=>"躋",
+"踊"=>"踴",
+"踌"=>"躊",
+"踪"=>"蹤",
+"踬"=>"躓",
+"踯"=>"躑",
+"蹑"=>"躡",
+"蹒"=>"蹣",
+"蹰"=>"躕",
+"蹿"=>"躥",
+"躏"=>"躪",
+"躜"=>"躦",
+"躯"=>"軀",
+"车"=>"車",
+"轧"=>"軋",
+"轨"=>"軌",
+"轩"=>"軒",
+"轪"=>"軑",
+"轫"=>"軔",
+"转"=>"轉",
+"轭"=>"軛",
+"轮"=>"輪",
+"软"=>"軟",
+"轰"=>"轟",
+"轱"=>"軲",
+"轲"=>"軻",
+"轳"=>"轤",
+"轴"=>"軸",
+"轵"=>"軹",
+"轶"=>"軼",
+"轷"=>"軤",
+"轸"=>"軫",
+"轹"=>"轢",
+"轺"=>"軺",
+"轻"=>"輕",
+"轼"=>"軾",
+"载"=>"載",
+"轾"=>"輊",
+"轿"=>"轎",
+"辀"=>"輈",
+"辁"=>"輇",
+"辂"=>"輅",
+"较"=>"較",
+"辄"=>"輒",
+"辅"=>"輔",
+"辆"=>"輛",
+"辇"=>"輦",
+"辈"=>"輩",
+"辉"=>"輝",
+"辊"=>"輥",
+"辋"=>"輞",
+"辌"=>"輬",
+"辍"=>"輟",
+"辎"=>"輜",
+"辏"=>"輳",
+"辐"=>"輻",
+"辑"=>"輯",
+"辒"=>"轀",
+"输"=>"輸",
+"辔"=>"轡",
+"辕"=>"轅",
+"辖"=>"轄",
+"辗"=>"輾",
+"辘"=>"轆",
+"辙"=>"轍",
+"辚"=>"轔",
+"辞"=>"辭",
+"辩"=>"辯",
+"辫"=>"辮",
+"边"=>"邊",
+"辽"=>"遼",
+"达"=>"達",
+"迁"=>"遷",
+"过"=>"過",
+"迈"=>"邁",
+"运"=>"運",
+"还"=>"還",
+"这"=>"這",
+"进"=>"進",
+"远"=>"遠",
+"违"=>"違",
+"连"=>"連",
+"迟"=>"遲",
+"迩"=>"邇",
+"迳"=>"逕",
+"迹"=>"跡",
+"选"=>"選",
+"逊"=>"遜",
+"递"=>"遞",
+"逦"=>"邐",
+"逻"=>"邏",
+"遗"=>"遺",
+"遥"=>"遙",
+"邓"=>"鄧",
+"邝"=>"鄺",
+"邬"=>"鄔",
+"邮"=>"郵",
+"邹"=>"鄒",
+"邺"=>"鄴",
+"邻"=>"鄰",
+"郏"=>"郟",
+"郐"=>"鄶",
+"郑"=>"鄭",
+"郓"=>"鄆",
+"郦"=>"酈",
+"郧"=>"鄖",
+"郸"=>"鄲",
+"酂"=>"酇",
+"酦"=>"醱",
+"酱"=>"醬",
+"酽"=>"釅",
+"酾"=>"釃",
+"酿"=>"釀",
+"释"=>"釋",
+"鉴"=>"鑒",
+"銮"=>"鑾",
+"錾"=>"鏨",
+"钅"=>"釒",
+"钆"=>"釓",
+"钇"=>"釔",
+"针"=>"針",
+"钉"=>"釘",
+"钊"=>"釗",
+"钋"=>"釙",
+"钌"=>"釕",
+"钍"=>"釷",
+"钎"=>"釺",
+"钏"=>"釧",
+"钐"=>"釤",
+"钑"=>"鈒",
+"钒"=>"釩",
+"钓"=>"釣",
+"钔"=>"鍆",
+"钕"=>"釹",
+"钖"=>"鍚",
+"钗"=>"釵",
+"钘"=>"鈃",
+"钙"=>"鈣",
+"钚"=>"鈈",
+"钛"=>"鈦",
+"钜"=>"鉅",
+"钝"=>"鈍",
+"钞"=>"鈔",
+"钠"=>"鈉",
+"钡"=>"鋇",
+"钢"=>"鋼",
+"钣"=>"鈑",
+"钤"=>"鈐",
+"钥"=>"鑰",
+"钦"=>"欽",
+"钧"=>"鈞",
+"钨"=>"鎢",
+"钪"=>"鈧",
+"钫"=>"鈁",
+"钬"=>"鈥",
+"钭"=>"鈄",
+"钮"=>"鈕",
+"钯"=>"鈀",
+"钰"=>"鈺",
+"钱"=>"錢",
+"钲"=>"鉦",
+"钳"=>"鉗",
+"钴"=>"鈷",
+"钶"=>"鈳",
+"钷"=>"鉕",
+"钸"=>"鈽",
+"钹"=>"鈸",
+"钺"=>"鉞",
+"钻"=>"鑽",
+"钼"=>"鉬",
+"钽"=>"鉭",
+"钾"=>"鉀",
+"钿"=>"鈿",
+"铀"=>"鈾",
+"铁"=>"鐵",
+"铂"=>"鉑",
+"铃"=>"鈴",
+"铄"=>"鑠",
+"铅"=>"鉛",
+"铆"=>"鉚",
+"铇"=>"鉋",
+"铈"=>"鈰",
+"铉"=>"鉉",
+"铊"=>"鉈",
+"铋"=>"鉍",
+"铌"=>"鈮",
+"铍"=>"鈹",
+"铎"=>"鐸",
+"铏"=>"鉶",
+"铐"=>"銬",
+"铑"=>"銠",
+"铒"=>"鉺",
+"铓"=>"鋩",
+"铔"=>"錏",
+"铕"=>"銪",
+"铖"=>"鋮",
+"铗"=>"鋏",
+"铘"=>"鋣",
+"铙"=>"鐃",
+"铚"=>"銍",
+"铛"=>"鐺",
+"铜"=>"銅",
+"铝"=>"鋁",
+"铞"=>"銱",
+"铟"=>"銦",
+"铠"=>"鎧",
+"铡"=>"鍘",
+"铢"=>"銖",
+"铣"=>"銑",
+"铤"=>"鋌",
+"铥"=>"銩",
+"铦"=>"銛",
+"铧"=>"鏵",
+"铨"=>"銓",
+"铩"=>"鎩",
+"铪"=>"鉿",
+"铫"=>"銚",
+"铬"=>"鉻",
+"铭"=>"銘",
+"铮"=>"錚",
+"铯"=>"銫",
+"铰"=>"鉸",
+"铱"=>"銥",
+"铲"=>"鏟",
+"铳"=>"銃",
+"铴"=>"鐋",
+"铵"=>"銨",
+"银"=>"銀",
+"铷"=>"銣",
+"铸"=>"鑄",
+"铹"=>"鐒",
+"铺"=>"鋪",
+"铻"=>"鋙",
+"铼"=>"錸",
+"铽"=>"鋱",
+"链"=>"鏈",
+"铿"=>"鏗",
+"销"=>"銷",
+"锁"=>"鎖",
+"锂"=>"鋰",
+"锃"=>"鋥",
+"锄"=>"鋤",
+"锅"=>"鍋",
+"锆"=>"鋯",
+"锇"=>"鋨",
+"锉"=>"銼",
+"锊"=>"鋝",
+"锋"=>"鋒",
+"锌"=>"鋅",
+"锍"=>"鋶",
+"锎"=>"鐦",
+"锏"=>"鐧",
+"锑"=>"銻",
+"锒"=>"鋃",
+"锓"=>"鋟",
+"锔"=>"鋦",
+"锕"=>"錒",
+"锖"=>"錆",
+"锗"=>"鍺",
+"锘"=>"鍩",
+"错"=>"錯",
+"锚"=>"錨",
+"锛"=>"錛",
+"锜"=>"錡",
+"锝"=>"鍀",
+"锞"=>"錁",
+"锟"=>"錕",
+"锠"=>"錩",
+"锡"=>"錫",
+"锢"=>"錮",
+"锣"=>"鑼",
+"锤"=>"錘",
+"锥"=>"錐",
+"锦"=>"錦",
+"锧"=>"鑕",
+"锩"=>"錈",
+"锪"=>"鍃",
+"锫"=>"錇",
+"锬"=>"錟",
+"锭"=>"錠",
+"键"=>"鍵",
+"锯"=>"鋸",
+"锰"=>"錳",
+"锱"=>"錙",
+"锲"=>"鍥",
+"锳"=>"鍈",
+"锴"=>"鍇",
+"锵"=>"鏘",
+"锶"=>"鍶",
+"锷"=>"鍔",
+"锸"=>"鍤",
+"锹"=>"鍬",
+"锺"=>"鍾",
+"锻"=>"鍛",
+"锼"=>"鎪",
+"锽"=>"鍠",
+"锾"=>"鍰",
+"锿"=>"鎄",
+"镀"=>"鍍",
+"镁"=>"鎂",
+"镂"=>"鏤",
+"镃"=>"鎡",
+"镄"=>"鐨",
+"镅"=>"鎇",
+"镆"=>"鏌",
+"镇"=>"鎮",
+"镈"=>"鎛",
+"镉"=>"鎘",
+"镊"=>"鑷",
+"镋"=>"鎲",
+"镍"=>"鎳",
+"镎"=>"鎿",
+"镏"=>"鎦",
+"镐"=>"鎬",
+"镑"=>"鎊",
+"镒"=>"鎰",
+"镓"=>"鎵",
+"镔"=>"鑌",
+"镕"=>"鎔",
+"镖"=>"鏢",
+"镗"=>"鏜",
+"镘"=>"鏝",
+"镙"=>"鏍",
+"镚"=>"鏰",
+"镛"=>"鏞",
+"镜"=>"鏡",
+"镝"=>"鏑",
+"镞"=>"鏃",
+"镟"=>"鏇",
+"镠"=>"鏐",
+"镡"=>"鐔",
+"镣"=>"鐐",
+"镤"=>"鏷",
+"镥"=>"鑥",
+"镦"=>"鐓",
+"镧"=>"鑭",
+"镨"=>"鐠",
+"镩"=>"鑹",
+"镪"=>"鏹",
+"镫"=>"鐙",
+"镬"=>"鑊",
+"镭"=>"鐳",
+"镮"=>"鐶",
+"镯"=>"鐲",
+"镰"=>"鐮",
+"镱"=>"鐿",
+"镲"=>"鑔",
+"镳"=>"鑣",
+"镴"=>"鑞",
+"镵"=>"鑱",
+"镶"=>"鑲",
+"长"=>"長",
+"门"=>"門",
+"闩"=>"閂",
+"闪"=>"閃",
+"闫"=>"閆",
+"闬"=>"閈",
+"闭"=>"閉",
+"问"=>"問",
+"闯"=>"闖",
+"闰"=>"閏",
+"闱"=>"闈",
+"闲"=>"閑",
+"闳"=>"閎",
+"间"=>"間",
+"闵"=>"閔",
+"闶"=>"閌",
+"闷"=>"悶",
+"闸"=>"閘",
+"闹"=>"鬧",
+"闺"=>"閨",
+"闻"=>"聞",
+"闼"=>"闥",
+"闽"=>"閩",
+"闾"=>"閭",
+"闿"=>"闓",
+"阀"=>"閥",
+"阁"=>"閣",
+"阂"=>"閡",
+"阃"=>"閫",
+"阄"=>"鬮",
+"阆"=>"閬",
+"阇"=>"闍",
+"阈"=>"閾",
+"阉"=>"閹",
+"阊"=>"閶",
+"阋"=>"鬩",
+"阌"=>"閿",
+"阍"=>"閽",
+"阎"=>"閻",
+"阏"=>"閼",
+"阐"=>"闡",
+"阑"=>"闌",
+"阒"=>"闃",
+"阓"=>"闠",
+"阔"=>"闊",
+"阕"=>"闋",
+"阖"=>"闔",
+"阗"=>"闐",
+"阘"=>"闒",
+"阙"=>"闕",
+"阚"=>"闞",
+"阛"=>"闤",
+"队"=>"隊",
+"阳"=>"陽",
+"阴"=>"陰",
+"阵"=>"陣",
+"阶"=>"階",
+"际"=>"際",
+"陆"=>"陸",
+"陇"=>"隴",
+"陈"=>"陳",
+"陉"=>"陘",
+"陕"=>"陝",
+"陧"=>"隉",
+"陨"=>"隕",
+"险"=>"險",
+"随"=>"隨",
+"隐"=>"隱",
+"隶"=>"隸",
+"隽"=>"雋",
+"难"=>"難",
+"雏"=>"雛",
+"雠"=>"讎",
+"雳"=>"靂",
+"雾"=>"霧",
+"霁"=>"霽",
+"霡"=>"霢",
+"霭"=>"靄",
+"靓"=>"靚",
+"静"=>"靜",
+"靥"=>"靨",
+"鞑"=>"韃",
+"鞒"=>"鞽",
+"鞯"=>"韉",
+"韦"=>"韋",
+"韧"=>"韌",
+"韨"=>"韍",
+"韩"=>"韓",
+"韪"=>"韙",
+"韫"=>"韞",
+"韬"=>"韜",
+"韵"=>"韻",
+"页"=>"頁",
+"顶"=>"頂",
+"顷"=>"頃",
+"顸"=>"頇",
+"项"=>"項",
+"顺"=>"順",
+"顼"=>"頊",
+"顽"=>"頑",
+"顾"=>"顧",
+"顿"=>"頓",
+"颀"=>"頎",
+"颁"=>"頒",
+"颂"=>"頌",
+"颃"=>"頏",
+"预"=>"預",
+"颅"=>"顱",
+"领"=>"領",
+"颇"=>"頗",
+"颈"=>"頸",
+"颉"=>"頡",
+"颊"=>"頰",
+"颋"=>"頲",
+"颌"=>"頜",
+"颍"=>"潁",
+"颎"=>"熲",
+"颏"=>"頦",
+"颐"=>"頤",
+"频"=>"頻",
+"颒"=>"頮",
+"颔"=>"頷",
+"颕"=>"頴",
+"颖"=>"穎",
+"颗"=>"顆",
+"题"=>"題",
+"颙"=>"顒",
+"颚"=>"顎",
+"颛"=>"顓",
+"额"=>"額",
+"颞"=>"顳",
+"颟"=>"顢",
+"颠"=>"顛",
+"颡"=>"顙",
+"颢"=>"顥",
+"颤"=>"顫",
+"颥"=>"顬",
+"颦"=>"顰",
+"颧"=>"顴",
+"风"=>"風",
+"飏"=>"颺",
+"飐"=>"颭",
+"飑"=>"颮",
+"飒"=>"颯",
+"飓"=>"颶",
+"飔"=>"颸",
+"飕"=>"颼",
+"飖"=>"颻",
+"飗"=>"飀",
+"飘"=>"飄",
+"飙"=>"飆",
+"飚"=>"飈",
+"飞"=>"飛",
+"飨"=>"饗",
+"餍"=>"饜",
+"饣"=>"飠",
+"饤"=>"飣",
+"饦"=>"飥",
+"饧"=>"餳",
+"饨"=>"飩",
+"饩"=>"餼",
+"饪"=>"飪",
+"饫"=>"飫",
+"饬"=>"飭",
+"饭"=>"飯",
+"饮"=>"飲",
+"饯"=>"餞",
+"饰"=>"飾",
+"饱"=>"飽",
+"饲"=>"飼",
+"饳"=>"飿",
+"饴"=>"飴",
+"饵"=>"餌",
+"饶"=>"饒",
+"饷"=>"餉",
+"饸"=>"餄",
+"饹"=>"餎",
+"饺"=>"餃",
+"饻"=>"餏",
+"饼"=>"餅",
+"饽"=>"餑",
+"饾"=>"餖",
+"饿"=>"餓",
+"馀"=>"餘",
+"馁"=>"餒",
+"馂"=>"餕",
+"馃"=>"餜",
+"馄"=>"餛",
+"馅"=>"餡",
+"馆"=>"館",
+"馇"=>"餷",
+"馈"=>"饋",
+"馉"=>"餶",
+"馊"=>"餿",
+"馋"=>"饞",
+"馌"=>"饁",
+"馍"=>"饃",
+"馎"=>"餺",
+"馏"=>"餾",
+"馐"=>"饈",
+"馑"=>"饉",
+"馒"=>"饅",
+"馓"=>"饊",
+"馔"=>"饌",
+"馕"=>"饢",
+"马"=>"馬",
+"驭"=>"馭",
+"驮"=>"馱",
+"驯"=>"馴",
+"驰"=>"馳",
+"驱"=>"驅",
+"驲"=>"馹",
+"驳"=>"駁",
+"驴"=>"驢",
+"驵"=>"駔",
+"驶"=>"駛",
+"驷"=>"駟",
+"驸"=>"駙",
+"驹"=>"駒",
+"驺"=>"騶",
+"驻"=>"駐",
+"驼"=>"駝",
+"驽"=>"駑",
+"驾"=>"駕",
+"驿"=>"驛",
+"骀"=>"駘",
+"骁"=>"驍",
+"骃"=>"駰",
+"骄"=>"驕",
+"骅"=>"驊",
+"骆"=>"駱",
+"骇"=>"駭",
+"骈"=>"駢",
+"骉"=>"驫",
+"骊"=>"驪",
+"骋"=>"騁",
+"验"=>"驗",
+"骍"=>"騂",
+"骎"=>"駸",
+"骏"=>"駿",
+"骐"=>"騏",
+"骑"=>"騎",
+"骒"=>"騍",
+"骓"=>"騅",
+"骔"=>"騌",
+"骕"=>"驌",
+"骖"=>"驂",
+"骗"=>"騙",
+"骘"=>"騭",
+"骙"=>"騤",
+"骚"=>"騷",
+"骛"=>"騖",
+"骜"=>"驁",
+"骝"=>"騮",
+"骞"=>"騫",
+"骟"=>"騸",
+"骠"=>"驃",
+"骡"=>"騾",
+"骢"=>"驄",
+"骣"=>"驏",
+"骤"=>"驟",
+"骥"=>"驥",
+"骦"=>"驦",
+"骧"=>"驤",
+"髅"=>"髏",
+"髋"=>"髖",
+"髌"=>"髕",
+"鬓"=>"鬢",
+"魇"=>"魘",
+"魉"=>"魎",
+"鱼"=>"魚",
+"鱽"=>"魛",
+"鱾"=>"魢",
+"鱿"=>"魷",
+"鲀"=>"魨",
+"鲁"=>"魯",
+"鲂"=>"魴",
+"鲃"=>"䰾",
+"鲄"=>"魺",
+"鲅"=>"鮁",
+"鲆"=>"鮃",
+"鲈"=>"鱸",
+"鲉"=>"鮋",
+"鲊"=>"鮓",
+"鲋"=>"鮒",
+"鲌"=>"鮊",
+"鲍"=>"鮑",
+"鲎"=>"鱟",
+"鲏"=>"鮍",
+"鲐"=>"鮐",
+"鲑"=>"鮭",
+"鲒"=>"鮚",
+"鲓"=>"鮳",
+"鲔"=>"鮪",
+"鲕"=>"鮞",
+"鲖"=>"鮦",
+"鲗"=>"鰂",
+"鲘"=>"鮜",
+"鲙"=>"鱠",
+"鲚"=>"鱭",
+"鲛"=>"鮫",
+"鲜"=>"鮮",
+"鲝"=>"鮺",
+"鲟"=>"鱘",
+"鲠"=>"鯁",
+"鲡"=>"鱺",
+"鲢"=>"鰱",
+"鲣"=>"鰹",
+"鲤"=>"鯉",
+"鲥"=>"鰣",
+"鲦"=>"鰷",
+"鲧"=>"鯀",
+"鲨"=>"鯊",
+"鲩"=>"鯇",
+"鲪"=>"鮶",
+"鲫"=>"鯽",
+"鲬"=>"鯒",
+"鲭"=>"鯖",
+"鲮"=>"鯪",
+"鲯"=>"鯕",
+"鲰"=>"鯫",
+"鲱"=>"鯡",
+"鲲"=>"鯤",
+"鲳"=>"鯧",
+"鲴"=>"鯝",
+"鲵"=>"鯢",
+"鲶"=>"鯰",
+"鲷"=>"鯛",
+"鲸"=>"鯨",
+"鲹"=>"鰺",
+"鲺"=>"鯴",
+"鲻"=>"鯔",
+"鲼"=>"鱝",
+"鲽"=>"鰈",
+"鲾"=>"鰏",
+"鲿"=>"鱨",
+"鳀"=>"鯷",
+"鳁"=>"鰮",
+"鳂"=>"鰃",
+"鳃"=>"鰓",
+"鳅"=>"鰍",
+"鳆"=>"鰒",
+"鳇"=>"鰉",
+"鳈"=>"鰁",
+"鳉"=>"鱂",
+"鳊"=>"鯿",
+"鳋"=>"鰠",
+"鳌"=>"鰲",
+"鳍"=>"鰭",
+"鳎"=>"鰨",
+"鳏"=>"鰥",
+"鳐"=>"鰩",
+"鳑"=>"鰟",
+"鳒"=>"鰜",
+"鳓"=>"鰳",
+"鳔"=>"鰾",
+"鳕"=>"鱈",
+"鳖"=>"鱉",
+"鳗"=>"鰻",
+"鳘"=>"鰵",
+"鳙"=>"鱅",
+"鳚"=>"䲁",
+"鳛"=>"鰼",
+"鳜"=>"鱖",
+"鳝"=>"鱔",
+"鳞"=>"鱗",
+"鳟"=>"鱒",
+"鳠"=>"鱯",
+"鳡"=>"鱤",
+"鳢"=>"鱧",
+"鳣"=>"鱣",
+"䴓"=>"鳾",
+"䴕"=>"鴷",
+"䴔"=>"鵁",
+"䴖"=>"鶄",
+"䴗"=>"鶪",
+"䴘"=>"鷈",
+"䴙"=>"鷿",
+"鸟"=>"鳥",
+"鸠"=>"鳩",
+"鸢"=>"鳶",
+"鸣"=>"鳴",
+"鸤"=>"鳲",
+"鸥"=>"鷗",
+"鸦"=>"鴉",
+"鸧"=>"鶬",
+"鸨"=>"鴇",
+"鸩"=>"鴆",
+"鸪"=>"鴣",
+"鸫"=>"鶇",
+"鸬"=>"鸕",
+"鸭"=>"鴨",
+"鸮"=>"鴞",
+"鸯"=>"鴦",
+"鸰"=>"鴒",
+"鸱"=>"鴟",
+"鸲"=>"鴝",
+"鸳"=>"鴛",
+"鸴"=>"鷽",
+"鸵"=>"鴕",
+"鸶"=>"鷥",
+"鸷"=>"鷙",
+"鸸"=>"鴯",
+"鸹"=>"鴰",
+"鸺"=>"鵂",
+"鸻"=>"鴴",
+"鸼"=>"鵃",
+"鸽"=>"鴿",
+"鸾"=>"鸞",
+"鸿"=>"鴻",
+"鹀"=>"鵐",
+"鹁"=>"鵓",
+"鹂"=>"鸝",
+"鹃"=>"鵑",
+"鹄"=>"鵠",
+"鹅"=>"鵝",
+"鹆"=>"鵒",
+"鹇"=>"鷳",
+"鹈"=>"鵜",
+"鹉"=>"鵡",
+"鹊"=>"鵲",
+"鹋"=>"鶓",
+"鹌"=>"鵪",
+"鹍"=>"鵾",
+"鹎"=>"鵯",
+"鹏"=>"鵬",
+"鹐"=>"鵮",
+"鹑"=>"鶉",
+"鹒"=>"鶊",
+"鹓"=>"鵷",
+"鹔"=>"鷫",
+"鹕"=>"鶘",
+"鹖"=>"鶡",
+"鹗"=>"鶚",
+"鹘"=>"鶻",
+"鹙"=>"鶖",
+"鹛"=>"鶥",
+"鹜"=>"鶩",
+"鹝"=>"鷊",
+"鹞"=>"鷂",
+"鹟"=>"鶲",
+"鹠"=>"鶹",
+"鹡"=>"鶺",
+"鹢"=>"鷁",
+"鹣"=>"鶼",
+"鹤"=>"鶴",
+"鹥"=>"鷖",
+"鹦"=>"鸚",
+"鹧"=>"鷓",
+"鹨"=>"鷚",
+"鹩"=>"鷯",
+"鹪"=>"鷦",
+"鹫"=>"鷲",
+"鹬"=>"鷸",
+"鹭"=>"鷺",
+"鹯"=>"鸇",
+"鹰"=>"鷹",
+"鹱"=>"鸌",
+"鹲"=>"鸏",
+"鹳"=>"鸛",
+"鹴"=>"鸘",
+"鹾"=>"鹺",
+"麦"=>"麥",
+"麸"=>"麩",
+"麽"=>"麼",
+"黄"=>"黃",
+"黉"=>"黌",
+"黡"=>"黶",
+"黩"=>"黷",
+"黪"=>"黲",
+"黾"=>"黽",
+"鼋"=>"黿",
+"鼍"=>"鼉",
+"鼗"=>"鞀",
+"鼹"=>"鼴",
+"齐"=>"齊",
+"齑"=>"齏",
+"齿"=>"齒",
+"龀"=>"齔",
+"龁"=>"齕",
+"龂"=>"齗",
+"龃"=>"齟",
+"龄"=>"齡",
+"龅"=>"齙",
+"龆"=>"齠",
+"龇"=>"齜",
+"龈"=>"齦",
+"龉"=>"齬",
+"龊"=>"齪",
+"龋"=>"齲",
+"龌"=>"齷",
+"龙"=>"龍",
+"龚"=>"龔",
+"龛"=>"龕",
+"龟"=>"龜",
+
+"BIG-" =>      "BIG-",
+".PRG" =>      ".PRG",
+"一伙" =>    "一伙",
+"一并" =>    "一併",
+"一准" =>    "一准",
+"一划" =>    "一划",
+"一地里" =>         "一地裡",
+"一干" =>    "一干",
+"一树百获" =>      "一樹百穫",
+"一台" =>    "一臺",
+"一冲" =>    "一衝",
+"一只" =>    "一隻",
+"一发千钧" =>      "一髮千鈞",
+"一出" =>    "一齣",
+"七只" =>    "七隻",
+"三元里" =>         "三元裡",
+"三国志" =>         "三國誌",
+"三复" =>    "三複",
+"三只" =>    "三隻",
+"上吊" =>    "上吊",
+"上台" =>    "上臺",
+"下不了台" =>      "下不了臺",
+"下台" =>    "下臺",
+"下面" =>    "下麵",
+"不准" =>    "不准",
+"不吊" =>    "不吊",
+"不干" =>    "不幹",
+"不舍" =>    "不捨",
+"不知所云" =>      "不知所云",
+"不识台举" =>      "不識檯舉",
+"不锈钢" =>         "不鏽鋼",
+"丑剧" =>    "丑劇",
+"丑旦" =>    "丑旦",
+"丑角" =>    "丑角",
+"世界杯" =>         "世界盃",
+"并存着" =>         "並存著",
+"中岳" =>    "中嶽",
+"中台路" =>         "中臺路",
+"中台医专" =>      "中臺醫專",
+"丰南" =>    "丰南",
+"丰台" =>    "丰台",
+"丰姿" =>    "丰姿",
+"丰神俊朗" =>      "丰神俊朗",
+"丰采" =>    "丰采",
+"丰韵" =>    "丰韻",
+"主干" =>    "主幹",
+"九世之雠" =>      "九世之讎",
+"九只" =>    "九隻",
+"干丝" =>    "乾絲",
+"干着急" =>         "乾著急",
+"干面" =>    "乾麵",
+"乱发" =>    "亂髮",
+"云云" =>    "云云",
+"云何" =>    "云何",
+"云尔" =>    "云爾",
+"五岳" =>    "五嶽",
+"五斗柜" =>         "五斗櫃",
+"五斗橱" =>         "五斗櫥",
+"五斗米" =>         "五斗米",
+"五谷" =>    "五穀",
+"五行生克" =>      "五行生剋",
+"五只" =>    "五隻",
+"五出" =>    "五齣",
+"井里" =>    "井裡",
+"交卷" =>    "交卷",
+"人云亦云" =>      "人云亦云",
+"人物志" =>         "人物誌",
+"什锦面" =>         "什錦麵",
+"什么" =>    "什麼",
+"仆倒" =>    "仆倒",
+"仇雠" =>    "仇讎",
+"介系词" =>         "介係詞",
+"介系词" =>         "介繫詞",
+"仿制" =>    "仿製",
+"伙伕" =>    "伙伕",
+"伙伴" =>    "伙伴",
+"伙同" =>    "伙同",
+"伙夫" =>    "伙夫",
+"伙房" =>    "伙房",
+"伙计" =>    "伙計",
+"伙食" =>    "伙食",
+"布下" =>    "佈下",
+"布告" =>    "佈告",
+"布哨" =>    "佈哨",
+"布局" =>    "佈局",
+"布岗" =>    "佈崗",
+"布施" =>    "佈施",
+"布景" =>    "佈景",
+"布有" =>    "佈有",
+"布满" =>    "佈滿",
+"布线" =>    "佈線",
+"布置" =>    "佈置",
+"布署" =>    "佈署",
+"布道" =>    "佈道",
+"布达" =>    "佈達",
+"布防" =>    "佈防",
+"布阵" =>    "佈陣",
+"布雷" =>    "佈雷",
+"体育锻鍊" =>      "体育鍛鍊",
+"何干" =>    "何干",
+"作准" =>    "作准",
+"佣人" =>    "佣人",
+"佣工" =>    "佣工",
+"佣金" =>    "佣金",
+"并入" =>    "併入",
+"并列" =>    "併列",
+"并到" =>    "併到",
+"并合" =>    "併合",
+"并吞" =>    "併吞",
+"并在" =>    "併在",
+"并成" =>    "併成",
+"并排" =>    "併排",
+"并拢" =>    "併攏",
+"并案" =>    "併案",
+"并为" =>    "併為",
+"并发" =>    "併發",
+"并科" =>    "併科",
+"并购" =>    "併購",
+"并进" =>    "併進",
+"来复" =>    "來複",
+"供制" =>    "供製",
+"侵并" =>    "侵併",
+"便辟" =>    "便辟",
+"系数" =>    "係數",
+"系为" =>    "係為",
+"保险柜" =>         "保險柜",
+"信号台" =>         "信號臺",
+"修复" =>    "修複",
+"修胡刀" =>         "修鬍刀",
+"俯冲" =>    "俯衝",
+"个里" =>    "個裡",
+"倒绷孩儿" =>      "倒繃孩兒",
+"借着" =>    "借著",
+"偃仆" =>    "偃仆",
+"假发" =>    "假髮",
+"停制" =>    "停製",
+"偷鸡不着" =>      "偷雞不著",
+"家伙" =>    "傢伙",
+"家俱" =>    "傢俱",
+"家具" =>    "傢具",
+"传布" =>    "傳佈",
+"债台高筑" =>      "債臺高築",
+"傻里傻气" =>      "傻裡傻氣",
+"倾复" =>    "傾複",
+"倾复" =>    "傾覆",
+"僱佣" =>    "僱佣",
+"仪表" =>    "儀錶",
+"亿只" =>    "億隻",
+"尽尽" =>    "儘儘",
+"尽先" =>    "儘先",
+"尽其所有" =>      "儘其所有",
+"尽力" =>    "儘力",
+"尽可能" =>         "儘可能",
+"尽快" =>    "儘快",
+"尽早" =>    "儘早",
+"尽是" =>    "儘是",
+"尽管" =>    "儘管",
+"尽速" =>    "儘速",
+"尽量" =>    "儘量",
+"允准" =>    "允准",
+"兄台" =>    "兄臺",
+"充饥" =>    "充饑",
+"光采" =>    "光采",
+"克里" =>    "克裡",
+"克复" =>    "克複",
+"入伙" =>    "入伙",
+"内制" =>    "內製",
+"两只" =>    "兩隻",
+"八字胡" =>         "八字鬍",
+"八只" =>    "八隻",
+"公布" =>    "公佈",
+"公干" =>    "公幹",
+"公斗" =>    "公斗",
+"公历" =>    "公曆",
+"公里" =>    "公裡",
+"六谷" =>    "六穀",
+"六只" =>    "六隻",
+"六出" =>    "六齣",
+"兼并" =>    "兼併",
+"册卷" =>    "冊卷",
+"冤雠" =>    "冤讎",
+"准予" =>    "准予",
+"准假" =>    "准假",
+"准定" =>    "准定",
+"准将" =>    "准將",
+"准尉" =>    "准尉",
+"准此" =>    "准此",
+"准考证" =>         "准考證",
+"准许" =>    "准許",
+"几几" =>    "几几",
+"几杖" =>    "几杖",
+"几案" =>    "几案",
+"几筵" =>    "几筵",
+"几丝" =>    "几絲",
+"凹洞里" =>         "凹洞裡",
+"出征" =>    "出征",
+"函复" =>    "函覆",
+"刀削面" =>         "刀削麵",
+"刁斗" =>    "刁斗",
+"分布" =>    "分佈",
+"切面" =>    "切麵",
+"刊布" =>    "刊佈",
+"划上" =>    "划上",
+"划下" =>    "划下",
+"划不来" =>         "划不來",
+"划了" =>    "划了",
+"划具" =>    "划具",
+"划出" =>    "划出",
+"划到" =>    "划到",
+"划动" =>    "划動",
+"划去" =>    "划去",
+"划子" =>    "划子",
+"划得来" =>         "划得來",
+"划拳" =>    "划拳",
+"划桨" =>    "划槳",
+"划水" =>    "划水",
+"划算" =>    "划算",
+"划船" =>    "划船",
+"划艇" =>    "划艇",
+"划着" =>    "划著",
+"划着走" =>         "划著走",
+"划行" =>    "划行",
+"划走" =>    "划走",
+"划起" =>    "划起",
+"划进" =>    "划進",
+"划过" =>    "划過",
+"初征" =>    "初征",
+"别致" =>    "別緻",
+"别着" =>    "別著",
+"别只" =>    "別隻",
+"利比里亚" =>      "利比裡亞",
+"刮着" =>    "刮著",
+"刮胡刀" =>         "刮鬍刀",
+"剃发" =>    "剃髮",
+"剃须" =>    "剃鬚",
+"削发" =>    "削髮",
+"克制" =>    "剋制",
+"克扣" =>    "剋扣",
+"克日" =>    "剋日",
+"克星" =>    "剋星",
+"克服" =>    "剋服",
+"克期" =>    "剋期",
+"克死" =>    "剋死",
+"克薄" =>    "剋薄",
+"前仆后仰" =>      "前仆後仰",
+"前仆后继" =>      "前仆後繼",
+"前台" =>    "前臺",
+"前车之复" =>      "前車之覆",
+"刚才" =>    "剛纔",
+"剥制" =>    "剝製",
+"剪发" =>    "剪髮",
+"割舍" =>    "割捨",
+"创获" =>    "創穫",
+"创制" =>    "創製",
+"加里宁" =>         "加裡寧",
+"劳力士表" =>      "勞力士錶",
+"包准" =>    "包准",
+"包谷" =>    "包穀",
+"匏系" =>    "匏繫",
+"北岳" =>    "北嶽",
+"北斗" =>    "北斗",
+"北回" =>    "北迴",
+"匡复" =>    "匡複",
+"匪干" =>    "匪幹",
+"十卷" =>    "十卷",
+"十干" =>    "十干",
+"十台" =>    "十臺",
+"十只" =>    "十隻",
+"十出" =>    "十齣",
+"千百只" =>         "千百隻",
+"千丝万缕" =>      "千絲萬縷",
+"千回百折" =>      "千迴百折",
+"千回百转" =>      "千迴百轉",
+"千钧一发" =>      "千鈞一髮",
+"千只" =>    "千隻",
+"升斗小民" =>      "升斗小民",
+"半只" =>    "半隻",
+"南岳" =>    "南嶽",
+"南征" =>    "南征",
+"南斗" =>    "南斗",
+"南台" =>    "南臺",
+"南回" =>    "南迴",
+"卡里" =>    "卡裡",
+"印制" =>    "印製",
+"卷入" =>    "卷入",
+"卷取" =>    "卷取",
+"卷土重来" =>      "卷土重來",
+"卷子" =>    "卷子",
+"卷宗" =>    "卷宗",
+"卷尺" =>    "卷尺",
+"卷层云" =>         "卷層雲",
+"卷帙" =>    "卷帙",
+"卷扬机" =>         "卷揚機",
+"卷曲" =>    "卷曲",
+"卷染" =>    "卷染",
+"卷烟" =>    "卷煙",
+"卷筒" =>    "卷筒",
+"卷纬" =>    "卷緯",
+"卷绕" =>    "卷繞",
+"卷舌" =>    "卷舌",
+"卷装" =>    "卷裝",
+"卷轴" =>    "卷軸",
+"卷云" =>    "卷雲",
+"卷领" =>    "卷領",
+"卷发" =>    "卷髮",
+"卷须" =>    "卷鬚",
+"厚朴" =>    "厚朴",
+"参与" =>    "參与",
+"参与者" =>         "參与者",
+"参合" =>    "參合",
+"参考价值" =>      "參考價值",
+"参与" =>    "參與",
+"参与人员" =>      "參與人員",
+"参与制" =>         "參與制",
+"参与感" =>         "參與感",
+"参与者" =>         "參與者",
+"参观团" =>         "參觀團",
+"参观团体" =>      "參觀團體",
+"参阅" =>    "參閱",
+"反冲" =>    "反衝",
+"反复" =>    "反複",
+"反复" =>    "反覆",
+"取舍" =>    "取捨",
+"口里" =>    "口裡",
+"古柯咸" =>         "古柯鹹",
+"只准" =>    "只准",
+"只冲" =>    "只衝",
+"叮当" =>    "叮噹",
+"可怜虫" =>         "可憐虫",
+"可紧可松" =>      "可緊可鬆",
+"台制" =>    "台製",
+"司令台" =>         "司令臺",
+"吃着不尽" =>      "吃著不盡",
+"吃里扒外" =>      "吃裡扒外",
+"吃里爬外" =>      "吃裡爬外",
+"各吊" =>    "各吊",
+"合伙" =>    "合伙",
+"合并" =>    "合併",
+"合着" =>    "合著",
+"合着者" =>         "合著者",
+"吊上" =>    "吊上",
+"吊下" =>    "吊下",
+"吊了" =>    "吊了",
+"吊个" =>    "吊個",
+"吊儿郎当" =>      "吊兒郎當",
+"吊到" =>    "吊到",
+"吊去" =>    "吊去",
+"吊取" =>    "吊取",
+"吊吊" =>    "吊吊",
+"吊嗓" =>    "吊嗓",
+"吊好" =>    "吊好",
+"吊子" =>    "吊子",
+"吊带" =>    "吊帶",
+"吊带裤" =>         "吊帶褲",
+"吊床" =>    "吊床",
+"吊得" =>    "吊得",
+"吊挂" =>    "吊掛",
+"吊挂着" =>         "吊掛著",
+"吊杆" =>    "吊杆",
+"吊架" =>    "吊架",
+"吊桶" =>    "吊桶",
+"吊杆" =>    "吊桿",
+"吊桥" =>    "吊橋",
+"吊死" =>    "吊死",
+"吊灯" =>    "吊燈",
+"吊环" =>    "吊環",
+"吊盘" =>    "吊盤",
+"吊索" =>    "吊索",
+"吊着" =>    "吊著",
+"吊装" =>    "吊裝",
+"吊裤" =>    "吊褲",
+"吊裤带" =>         "吊褲帶",
+"吊袜" =>    "吊襪",
+"吊走" =>    "吊走",
+"吊起" =>    "吊起",
+"吊车" =>    "吊車",
+"吊钩" =>    "吊鉤",
+"吊销" =>    "吊銷",
+"吊钟" =>    "吊鐘",
+"同伙" =>    "同伙",
+"名表" =>    "名錶",
+"後冠" =>    "后冠",
+"後北街" =>         "后北街",
+"後土" =>    "后土",
+"後妃" =>    "后妃",
+"後安路" =>         "后安路",
+"後平路" =>         "后平路",
+"後座" =>    "后座",
+"後稷" =>    "后稷",
+"後羿" =>    "后羿",
+"後街" =>    "后街",
+"後里" =>    "后里",
+"向着" =>    "向著",
+"吞并" =>    "吞併",
+"吹发" =>    "吹髮",
+"吕後" =>    "呂后",
+"呆里呆气" =>      "呆裡呆氣",
+"呈准" =>    "呈准",
+"周而复始" =>      "周而複始",
+"呼吁" =>    "呼籲",
+"和面" =>    "和麵",
+"哪里" =>    "哪裡",
+"哭脏" =>    "哭髒",
+"问卷" =>    "問卷",
+"喝采" =>    "喝采",
+"乔岳" =>    "喬嶽",
+"单干" =>    "單干",
+"单只" =>    "單隻",
+"嘴里" =>    "嘴裏",
+"嘴里" =>    "嘴裡",
+"恶心" =>    "噁心",
+"当啷" =>    "噹啷",
+"当当" =>    "噹噹",
+"噜苏" =>    "嚕囌",
+"向导" =>    "嚮導",
+"向往" =>    "嚮往",
+"向应" =>    "嚮應",
+"向日" =>    "嚮日",
+"向迩" =>    "嚮邇",
+"严丝合缝" =>      "嚴絲合縫",
+"严复" =>    "嚴複",
+"囉苏" =>    "囉囌",
+"四舍五入" =>      "四捨五入",
+"四只" =>    "四隻",
+"四出" =>    "四齣",
+"回历新年" =>      "回曆新年",
+"回丝" =>    "回絲",
+"回着" =>    "回著",
+"回复" =>    "回覆",
+"回采" =>    "回采",
+"圈子里" =>         "圈子裡",
+"圈里" =>    "圈裡",
+"国历" =>    "國曆",
+"国雠" =>    "國讎",
+"园里" =>    "園裡",
+"圆台" =>    "圓臺",
+"图里" =>    "圖裡",
+"土里" =>    "土裡",
+"土制" =>    "土製",
+"地志" =>    "地誌",
+"坍台" =>    "坍臺",
+"坑里" =>    "坑裡",
+"垂发" =>    "垂髮",
+"垮台" =>    "垮臺",
+"埃及豔後" =>      "埃及豔后",
+"埃荣冲" =>         "埃榮衝",
+"埋布" =>    "埋佈",
+"城里" =>    "城裡",
+"基干" =>    "基幹",
+"报复" =>    "報複",
+"塌台" =>    "塌臺",
+"塔台" =>    "塔臺",
+"涂着" =>    "塗著",
+"墓志" =>    "墓誌",
+"墨斗" =>    "墨斗",
+"墨索里尼" =>      "墨索裡尼",
+"垦复" =>    "墾複",
+"压卷" =>    "壓卷",
+"垄断价格" =>      "壟斷價格",
+"垄断资产" =>      "壟斷資產",
+"垄断集团" =>      "壟斷集團",
+"壶里" =>    "壺裡",
+"寿面" =>    "壽麵",
+"夏天里" =>         "夏天裡",
+"夏历" =>    "夏曆",
+"外制" =>    "外製",
+"多冲" =>    "多衝",
+"多采多姿" =>      "多采多姿",
+"多么" =>    "多麼",
+"夜光表" =>         "夜光錶",
+"夜里" =>    "夜裡",
+"梦里" =>    "夢裡",
+"大伙" =>    "大伙",
+"大卷" =>    "大卷",
+"大干" =>    "大干",
+"大干" =>    "大幹",
+"大辟" =>    "大辟",
+"大只" =>    "大隻",
+"天後" =>    "天后",
+"天干" =>    "天干",
+"天文台" =>         "天文臺",
+"天翻地复" =>      "天翻地覆",
+"太後" =>    "太后",
+"奏折" =>    "奏摺",
+"女丑" =>    "女丑",
+"女佣" =>    "女佣",
+"好家夥" =>         "好傢夥",
+"好戏连台" =>      "好戲連臺",
+"好困" =>    "好睏",
+"如饥似渴" =>      "如饑似渴",
+"妆台" =>    "妝臺",
+"姜太公" =>         "姜太公",
+"姜子牙" =>         "姜子牙",
+"姜丝" =>    "姜絲",
+"字汇" =>    "字彙",
+"字里行间" =>      "字裡行間",
+"存折" =>    "存摺",
+"孟姜女" =>         "孟姜女",
+"宇宙志" =>         "宇宙誌",
+"宋皇台道" =>      "宋皇臺道",
+"定准" =>    "定准",
+"定制" =>    "定製",
+"宣布" =>    "宣佈",
+"宫里" =>    "宮裡",
+"家伙" =>    "家伙",
+"家里" =>    "家裏",
+"家里" =>    "家裡",
+"密布" =>    "密佈",
+"密致" =>    "密緻",
+"寇雠" =>    "寇讎",
+"富台街" =>         "富臺街",
+"寓禁于征" =>      "寓禁於征",
+"实干" =>    "實幹",
+"写字台" =>         "寫字檯",
+"写字台" =>         "寫字臺",
+"宽松" =>    "寬鬆",
+"宝卷" =>    "寶卷",
+"宝里宝气" =>      "寶裡寶氣",
+"封後" =>    "封后",
+"封面里" =>         "封面裡",
+"射干" =>    "射干",
+"对表" =>    "對錶",
+"小丑" =>    "小丑",
+"小伙" =>    "小伙",
+"小只" =>    "小隻",
+"少吊" =>    "少吊",
+"就里" =>    "就裡",
+"尺布斗粟" =>      "尺布斗粟",
+"尼克松" =>         "尼克鬆",
+"尼采" =>    "尼采",
+"尿斗" =>    "尿斗",
+"局里" =>    "局裡",
+"居里" =>    "居裡",
+"屋子里" =>         "屋子裡",
+"屋里" =>    "屋裡",
+"展布" =>    "展佈",
+"展卷" =>    "展卷",
+"屡仆屡起" =>      "屢仆屢起",
+"屯里" =>    "屯裡",
+"山岳" =>    "山嶽",
+"山斗" =>    "山斗",
+"山里" =>    "山裡",
+"山重水复" =>      "山重水複",
+"岱岳" =>    "岱嶽",
+"峰回" =>    "峰迴",
+"岳岳" =>    "嶽嶽",
+"巅复" =>    "巔覆",
+"巡回" =>    "巡迴",
+"巧干" =>    "巧幹",
+"巴尔干" =>         "巴爾幹",
+"巴里" =>    "巴裡",
+"巷里" =>    "巷裡",
+"市里" =>    "市裡",
+"布谷" =>    "布穀",
+"希腊" =>    "希腊",
+"帘子" =>    "帘子",
+"帘布" =>    "帘布",
+"席卷" =>    "席卷",
+"带团参加" =>      "帶團參加",
+"带发修行" =>      "帶髮修行",
+"干世" =>    "干世",
+"干休" =>    "干休",
+"干系" =>    "干係",
+"干冒" =>    "干冒",
+"干卿何事" =>      "干卿何事",
+"干卿底事" =>      "干卿底事",
+"干城" =>    "干城",
+"干将" =>    "干將",
+"干德道" =>         "干德道",
+"干戈" =>    "干戈",
+"干挠" =>    "干撓",
+"干扰" =>    "干擾",
+"干支" =>    "干支",
+"干政" =>    "干政",
+"干时" =>    "干時",
+"干没" =>    "干沒",
+"干涉" =>    "干涉",
+"干犯" =>    "干犯",
+"干禄" =>    "干祿",
+"干与" =>    "干與",
+"干着急" =>         "干著急",
+"干诺道中" =>      "干諾道中",
+"干诺道西" =>      "干諾道西",
+"干谒" =>    "干謁",
+"干证" =>    "干證",
+"干誉" =>    "干譽",
+"干贝" =>    "干貝",
+"干连" =>    "干連",
+"干云蔽日" =>      "干雲蔽日",
+"干预" =>    "干預",
+"平台" =>    "平臺",
+"年历" =>    "年曆",
+"年里" =>    "年裡",
+"干上" =>    "幹上",
+"干下去" =>         "幹下去",
+"干不了" =>         "幹不了",
+"干不成" =>         "幹不成",
+"干了" =>    "幹了",
+"干事" =>    "幹事",
+"干些" =>    "幹些",
+"干个" =>    "幹個",
+"干劲" =>    "幹勁",
+"干员" =>    "幹員",
+"干啥" =>    "幹啥",
+"干吗" =>    "幹嗎",
+"干嘛" =>    "幹嘛",
+"干坏事" =>         "幹壞事",
+"干完" =>    "幹完",
+"干将" =>    "幹將",
+"干得" =>    "幹得",
+"干性油" =>         "幹性油",
+"干才" =>    "幹才",
+"干掉" =>    "幹掉",
+"干校" =>    "幹校",
+"干活" =>    "幹活",
+"干流" =>    "幹流",
+"干球温度" =>      "幹球溫度",
+"干略" =>    "幹略",
+"干线" =>    "幹線",
+"干练" =>    "幹練",
+"干警" =>    "幹警",
+"干起来" =>         "幹起來",
+"干路" =>    "幹路",
+"干办" =>    "幹辦",
+"干这一行" =>      "幹這一行",
+"干这种事" =>      "幹這種事",
+"干道" =>    "幹道",
+"干部" =>    "幹部",
+"干么" =>    "幹麼",
+"几丝" =>    "幾絲",
+"几只" =>    "幾隻",
+"几出" =>    "幾齣",
+"底里" =>    "底裡",
+"店里" =>    "店裡",
+"康采恩" =>         "康采恩",
+"庙里" =>    "廟裡",
+"建台" =>    "建臺",
+"弄脏" =>    "弄髒",
+"弔卷" =>    "弔卷",
+"弘历" =>    "弘曆",
+"强干弱枝" =>      "強幹弱枝",
+"别扭" =>    "彆扭",
+"别拗" =>    "彆拗",
+"别气" =>    "彆氣",
+"别脚" =>    "彆腳",
+"别着" =>    "彆著",
+"弹子台" =>         "彈子檯",
+"弹珠台" =>         "彈珠檯",
+"弹药" =>    "彈葯",
+"汇刊" =>    "彙刊",
+"汇报" =>    "彙報",
+"汇整" =>    "彙整",
+"汇算" =>    "彙算",
+"汇编" =>    "彙編",
+"汇总" =>    "彙總",
+"汇纂" =>    "彙纂",
+"汇辑" =>    "彙輯",
+"汇集" =>    "彙集",
+"形单影只" =>      "形單影隻",
+"影後" =>    "影后",
+"往里" =>    "往裡",
+"往复" =>    "往複",
+"征伐" =>    "征伐",
+"征兵" =>    "征兵",
+"征利" =>    "征利",
+"征尘" =>    "征塵",
+"征夫" =>    "征夫",
+"征属" =>    "征屬",
+"征帆" =>    "征帆",
+"征戌" =>    "征戌",
+"征战" =>    "征戰",
+"征收" =>    "征收",
+"征服" =>    "征服",
+"征求" =>    "征求",
+"征发" =>    "征發",
+"征衣" =>    "征衣",
+"征讨" =>    "征討",
+"征途" =>    "征途",
+"后台" =>    "後臺",
+"从里到外" =>      "從裡到外",
+"从里向外" =>      "從裡向外",
+"复雠" =>    "復讎",
+"复辟" =>    "復辟",
+"德干高原" =>      "德干高原",
+"心愿" =>    "心愿",
+"心里" =>    "心裏",
+"心里" =>    "心裡",
+"忙里" =>    "忙裡",
+"快干" =>    "快幹",
+"快冲" =>    "快衝",
+"怎么" =>    "怎麼",
+"怎么着" =>         "怎麼著",
+"急冲而下" =>      "急衝而下",
+"怪里怪气" =>      "怪裡怪氣",
+"恩准" =>    "恩准",
+"情有所钟" =>      "情有所鍾",
+"情有独钟" =>      "情有獨鍾",
+"意面" =>    "意麵",
+"慌里慌张" =>      "慌裡慌張",
+"慰借" =>    "慰藉",
+"忧郁" =>    "憂郁",
+"凭吊" =>    "憑吊",
+"凭借" =>    "憑藉",
+"凭借着" =>         "憑藉著",
+"蒙懂" =>    "懞懂",
+"怀里" =>    "懷裡",
+"怀表" =>    "懷錶",
+"悬吊" =>    "懸吊",
+"悬心吊胆" =>      "懸心吊膽",
+"戏台" =>    "戲臺",
+"戴表" =>    "戴錶",
+"戽斗" =>    "戽斗",
+"房里" =>    "房裡",
+"手不释卷" =>      "手不釋卷",
+"手卷" =>    "手卷",
+"手折" =>    "手摺",
+"手里" =>    "手裏",
+"手里" =>    "手裡",
+"手表" =>    "手錶",
+"手松" =>    "手鬆",
+"才干" =>    "才幹",
+"才高八斗" =>      "才高八斗",
+"打谷" =>    "打穀",
+"扞御" =>    "扞禦",
+"批准" =>    "批准",
+"批复" =>    "批複",
+"批复" =>    "批覆",
+"承制" =>    "承製",
+"抗御" =>    "抗禦",
+"折冲" =>    "折衝",
+"披复" =>    "披覆",
+"披发" =>    "披髮",
+"抱朴" =>    "抱朴",
+"抵御" =>    "抵禦",
+"拆伙" =>    "拆伙",
+"拆台" =>    "拆臺",
+"拈须" =>    "拈鬚",
+"拉纤" =>    "拉縴",
+"拉面" =>    "拉麵",
+"拖吊" =>    "拖吊",
+"拗别" =>    "拗彆",
+"拮据" =>    "拮据",
+"捍御" =>    "捍禦",
+"舍不得" =>         "捨不得",
+"舍出" =>    "捨出",
+"舍去" =>    "捨去",
+"舍命" =>    "捨命",
+"舍己从人" =>      "捨己從人",
+"舍己救人" =>      "捨己救人",
+"舍己为人" =>      "捨己為人",
+"舍己为公" =>      "捨己為公",
+"舍己为国" =>      "捨己為國",
+"舍得" =>    "捨得",
+"舍我其谁" =>      "捨我其誰",
+"舍本逐末" =>      "捨本逐末",
+"舍弃" =>    "捨棄",
+"舍死忘生" =>      "捨死忘生",
+"舍生" =>    "捨生",
+"舍短取长" =>      "捨短取長",
+"舍身" =>    "捨身",
+"舍车保帅" =>      "捨車保帥",
+"舍近求远" =>      "捨近求遠",
+"捲发" =>    "捲髮",
+"捵面" =>    "捵麵",
+"掌柜" =>    "掌柜",
+"排骨面" =>         "排骨麵",
+"挂帘" =>    "掛帘",
+"挂面" =>    "掛麵",
+"接着说" =>         "接著說",
+"掩卷" =>    "掩卷",
+"提心吊胆" =>      "提心吊膽",
+"插图卷" =>         "插圖卷",
+"换吊" =>    "換吊",
+"换只" =>    "換隻",
+"换发" =>    "換髮",
+"握发" =>    "握髮",
+"搭伙" =>    "搭伙",
+"折合" =>    "摺合",
+"折奏" =>    "摺奏",
+"折子" =>    "摺子",
+"折尺" =>    "摺尺",
+"折扇" =>    "摺扇",
+"折梯" =>    "摺梯",
+"折椅" =>    "摺椅",
+"折叠" =>    "摺疊",
+"折痕" =>    "摺痕",
+"折篷" =>    "摺篷",
+"折纸" =>    "摺紙",
+"折裙" =>    "摺裙",
+"撒布" =>    "撒佈",
+"撚须" =>    "撚鬚",
+"撞球台" =>         "撞球檯",
+"擂台" =>    "擂臺",
+"担仔面" =>         "擔仔麵",
+"担担面" =>         "擔擔麵",
+"担着" =>    "擔著",
+"担负着" =>         "擔負著",
+"据云" =>    "據云",
+"擢发难数" =>      "擢髮難數",
+"拟准" =>    "擬准",
+"摆布" =>    "擺佈",
+"摄制" =>    "攝製",
+"支干" =>    "支幹",
+"收获" =>    "收穫",
+"改制" =>    "改製",
+"攻克" =>    "攻剋",
+"放松" =>    "放鬆",
+"故布疑阵" =>      "故佈疑陣",
+"叙说着" =>         "敘說著",
+"散伙" =>    "散伙",
+"散布" =>    "散佈",
+"散发" =>    "散髮",
+"整只" =>    "整隻",
+"整出" =>    "整齣",
+"敌忾同雠" =>      "敵愾同讎",
+"文借" =>    "文藉",
+"文采" =>    "文采",
+"斗亚兰路" =>      "斗亞蘭路",
+"斗六" =>    "斗六",
+"斗南" =>    "斗南",
+"斗大" =>    "斗大",
+"斗子" =>    "斗子",
+"斗室" =>    "斗室",
+"斗宿" =>    "斗宿",
+"斗方" =>    "斗方",
+"斗栱" =>    "斗栱",
+"斗笠" =>    "斗笠",
+"斗筲" =>    "斗筲",
+"斗箕" =>    "斗箕",
+"斗篷" =>    "斗篷",
+"斗胆" =>    "斗膽",
+"斗蓬" =>    "斗蓬",
+"斗转参横" =>      "斗轉參橫",
+"斗量" =>    "斗量",
+"斗门" =>    "斗門",
+"料斗" =>    "料斗",
+"斤斗" =>    "斤斗",
+"斯里兰卡" =>      "斯裡蘭卡",
+"新历" =>    "新曆",
+"断头台" =>         "斷頭臺",
+"断发文身" =>      "斷髮文身",
+"方才" =>    "方纔",
+"方志" =>    "方誌",
+"施舍" =>    "施捨",
+"旋绕着" =>         "旋繞著",
+"旋回" =>    "旋迴",
+"族里" =>    "族裡",
+"日历" =>    "日曆",
+"日志" =>    "日誌",
+"日进斗金" =>      "日進斗金",
+"明了" =>    "明瞭",
+"明窗净几" =>      "明窗淨几",
+"明里" =>    "明裡",
+"星斗" =>    "星斗",
+"星历" =>    "星曆",
+"星移斗换" =>      "星移斗換",
+"星移斗转" =>      "星移斗轉",
+"星罗棋布" =>      "星羅棋佈",
+"星辰表" =>         "星辰錶",
+"春假里" =>         "春假裡",
+"春天里" =>         "春天裡",
+"景致" =>    "景緻",
+"暗地里" =>         "暗地裡",
+"暗沟里" =>         "暗溝裡",
+"暗里" =>    "暗裡",
+"暴敛横征" =>      "暴斂橫征",
+"历数" =>    "曆數",
+"历书" =>    "曆書",
+"历法" =>    "曆法",
+"历象" =>    "曆象",
+"书卷" =>    "書卷",
+"会干" =>    "會幹",
+"会里" =>    "會裡",
+"月历" =>    "月曆",
+"月台" =>    "月臺",
+"有只" =>    "有隻",
+"木制" =>    "木製",
+"本台" =>    "本臺",
+"朴子" =>    "朴子",
+"朴实" =>    "朴實",
+"朴忠" =>    "朴忠",
+"朴直" =>    "朴直",
+"朴硝" =>    "朴硝",
+"朴素" =>    "朴素",
+"朴茂" =>    "朴茂",
+"朴资茅斯" =>      "朴資茅斯",
+"朴钝" =>    "朴鈍",
+"材干" =>    "材幹",
+"村里" =>    "村裡",
+"杜老志道" =>      "杜老誌道",
+"束发" =>    "束髮",
+"杯面" =>    "杯麵",
+"东岳" =>    "東嶽",
+"东征" =>    "東征",
+"松赞干布" =>      "松贊干布",
+"板着脸" =>         "板著臉",
+"枕借" =>    "枕藉",
+"林宏岳" =>         "林宏嶽",
+"枝干" =>    "枝幹",
+"枯干" =>    "枯幹",
+"某只" =>    "某隻",
+"染发" =>    "染髮",
+"柜上" =>    "柜上",
+"柜台" =>    "柜台",
+"柜子" =>    "柜子",
+"柜柳" =>    "柜柳",
+"查卷" =>    "查卷",
+"查号台" =>         "查號臺",
+"校雠学" =>         "校讎學",
+"核准" =>    "核准",
+"核复" =>    "核覆",
+"格里" =>    "格裡",
+"案准" =>    "案准",
+"案卷" =>    "案卷",
+"条干" =>    "條幹",
+"梯冲" =>    "梯衝",
+"械系" =>    "械繫",
+"棉卷" =>    "棉卷",
+"棉制" =>    "棉製",
+"植发" =>    "植髮",
+"楼台" =>    "樓臺",
+"标志着" =>         "標志著",
+"标致" =>    "標緻",
+"标志" =>    "標誌",
+"模制" =>    "模製",
+"树干" =>    "樹幹",
+"横征暴敛" =>      "橫征暴斂",
+"横冲" =>    "橫衝",
+"档卷" =>    "檔卷",
+"检复" =>    "檢覆",
+"台子" =>    "檯子",
+"台布" =>    "檯布",
+"台灯" =>    "檯燈",
+"台球" =>    "檯球",
+"台面" =>    "檯面",
+"柜台" =>    "櫃檯",
+"柜台" =>    "櫃臺",
+"栏干" =>    "欄干",
+"欺蒙" =>    "欺矇",
+"歌後" =>    "歌后",
+"歌台舞榭" =>      "歌臺舞榭",
+"欧几里得" =>      "歐幾裡得",
+"正当着" =>         "正當著",
+"此仆彼起" =>      "此仆彼起",
+"武後" =>    "武后",
+"武松" =>    "武鬆",
+"归并" =>    "歸併",
+"死里求生" =>      "死裡求生",
+"死里逃生" =>      "死裡逃生",
+"残卷" =>    "殘卷",
+"杀虫药" =>         "殺虫藥",
+"壳里" =>    "殼裡",
+"母後" =>    "母后",
+"每只" =>    "每隻",
+"比干" =>    "比干",
+"毛卷" =>    "毛卷",
+"毛坏" =>    "毛坏",
+"毛发" =>    "毛髮",
+"毫发" =>    "毫髮",
+"气冲斗牛" =>      "氣沖斗牛",
+"气冲牛斗" =>      "氣沖牛斗",
+"气象台" =>         "氣象臺",
+"水斗" =>    "水斗",
+"水里" =>    "水裡",
+"水表" =>    "水錶",
+"永历" =>    "永曆",
+"永志不忘" =>      "永誌不忘",
+"污蔑" =>    "汙衊",
+"江干" =>    "江干",
+"池里" =>    "池裡",
+"污蔑" =>    "污衊",
+"沈着" =>    "沈著",
+"没事干" =>         "沒事幹",
+"没精打采" =>      "沒精打采",
+"冲着" =>    "沖著",
+"沙里淘金" =>      "沙裡淘金",
+"河岳" =>    "河嶽",
+"河里" =>    "河裡",
+"油面" =>    "油麵",
+"泡制" =>    "泡製",
+"泡面" =>    "泡麵",
+"泰斗" =>    "泰斗",
+"洗发" =>    "洗髮",
+"派团参加" =>      "派團參加",
+"浪琴表" =>         "浪琴錶",
+"浮吊" =>    "浮吊",
+"海里" =>    "海裡",
+"涂着" =>    "涂著",
+"液晶表" =>         "液晶錶",
+"凉面" =>    "涼麵",
+"淡朱" =>    "淡硃",
+"渊淳岳峙" =>      "淵淳嶽峙",
+"渠冲" =>    "渠衝",
+"测验卷" =>         "測驗卷",
+"港制" =>    "港製",
+"凑合着" =>         "湊合著",
+"湖里" =>    "湖裡",
+"汤团" =>    "湯糰",
+"汤面" =>    "湯麵",
+"温郁" =>    "溫郁",
+"卤制" =>    "滷製",
+"卤面" =>    "滷麵",
+"满布" =>    "滿佈",
+"漏斗" =>    "漏斗",
+"演奏台" =>         "演奏臺",
+"潜意识里" =>      "潛意識裡",
+"潭里" =>    "潭裡",
+"浓郁" =>    "濃郁",
+"浓发" =>    "濃髮",
+"湿地松" =>         "濕地鬆",
+"蒙蒙" =>    "濛濛",
+"蒙雾" =>    "濛霧",
+"蒙鸿" =>    "濛鴻",
+"瀛台" =>    "瀛臺",
+"弥漫" =>    "瀰漫",
+"弥漫着" =>         "瀰漫著",
+"漓江" =>    "灕江",
+"火并" =>    "火併",
+"灰蒙" =>    "灰濛",
+"炒面" =>    "炒麵",
+"炮制" =>    "炮製",
+"炸药" =>    "炸葯",
+"炸酱面" =>         "炸醬麵",
+"为着" =>    "為著",
+"乌干达" =>         "烏干達",
+"乌苏里江" =>      "烏蘇裡江",
+"乌发" =>    "烏髮",
+"乌龙面" =>         "烏龍麵",
+"烘制" =>    "烘製",
+"烽火台" =>         "烽火臺",
+"无干" =>    "無干",
+"无精打采" =>      "無精打采",
+"炼制" =>    "煉製",
+"烟卷儿" =>         "煙卷兒",
+"烟斗" =>    "煙斗",
+"烟斗丝" =>         "煙斗絲",
+"烟台" =>    "煙臺",
+"照准" =>    "照准",
+"熨斗" =>    "熨斗",
+"灯台" =>    "燈臺",
+"燎发" =>    "燎髮",
+"烫发" =>    "燙髮",
+"烫面" =>    "燙麵",
+"烛台" =>    "燭臺",
+"炉台" =>    "爐臺",
+"墙里" =>    "牆裡",
+"片言只语" =>      "片言隻語",
+"牛肉面" =>         "牛肉麵",
+"牛只" =>    "牛隻",
+"特准" =>    "特准",
+"特征" =>    "特征",
+"特里" =>    "特裡",
+"特制" =>    "特製",
+"牵系" =>    "牽繫",
+"狼借" =>    "狼藉",
+"猛冲" =>    "猛衝",
+"奖杯" =>    "獎盃",
+"获准" =>    "獲准",
+"率团参加" =>      "率團參加",
+"王侯後" =>         "王侯后",
+"王後" =>    "王后",
+"班里" =>    "班裡",
+"理发" =>    "理髮",
+"瑶台" =>    "瑤臺",
+"甚么" =>    "甚麼",
+"甜面酱" =>         "甜麵醬",
+"生力面" =>         "生力麵",
+"生锈" =>    "生鏽",
+"生发" =>    "生髮",
+"田里" =>    "田裡",
+"由馀" =>    "由余",
+"由表及里" =>      "由表及裡",
+"男佣" =>    "男佣",
+"男用表" =>         "男用錶",
+"留发" =>    "留髮",
+"畚斗" =>    "畚斗",
+"当着" =>    "當著",
+"疏松" =>    "疏鬆",
+"疑系" =>    "疑係",
+"疲困" =>    "疲睏",
+"病症" =>    "病癥",
+"症候" =>    "癥候",
+"症状" =>    "癥狀",
+"症结" =>    "癥結",
+"登台" =>    "登臺",
+"发布" =>    "發佈",
+"发蒙" =>    "發矇",
+"发着" =>    "發著",
+"发面" =>    "發麵",
+"发霉" =>    "發黴",
+"白卷" =>    "白卷",
+"白干儿" =>         "白干兒",
+"白里透红" =>      "白裡透紅",
+"白发" =>    "白髮",
+"白面" =>    "白麵",
+"百谷" =>    "百穀",
+"百里" =>    "百裡",
+"百只" =>    "百隻",
+"皇後" =>    "皇后",
+"皇历" =>    "皇曆",
+"皓发" =>    "皓髮",
+"皮里阳秋" =>      "皮裏陽秋",
+"皮里春秋" =>      "皮裡春秋",
+"皮制" =>    "皮製",
+"皱折" =>    "皺摺",
+"盒里" =>    "盒裡",
+"监制" =>    "監製",
+"盘里" =>    "盤裡",
+"盘回" =>    "盤迴",
+"直接参与" =>      "直接參与",
+"直冲" =>    "直衝",
+"相克" =>    "相剋",
+"相干" =>    "相干",
+"相冲" =>    "相衝",
+"看台" =>    "看臺",
+"眼帘" =>    "眼帘",
+"眼眶里" =>         "眼眶裡",
+"眼里" =>    "眼裡",
+"困乏" =>    "睏乏",
+"困倦" =>    "睏倦",
+"睡着了" =>         "睡著了",
+"了如" =>    "瞭如",
+"了望" =>    "瞭望",
+"了然" =>    "瞭然",
+"了若指掌" =>      "瞭若指掌",
+"了解" =>    "瞭解",
+"瞳蒙" =>    "瞳矇",
+"蒙住" =>    "矇住",
+"蒙昧无知" =>      "矇昧無知",
+"蒙混" =>    "矇混",
+"蒙蒙" =>    "矇矇",
+"蒙眬" =>    "矇矓",
+"蒙蔽" =>    "矇蔽",
+"蒙骗" =>    "矇騙",
+"短发" =>    "短髮",
+"矮几" =>    "矮几",
+"石英表" =>         "石英錶",
+"石莼" =>    "石蓴",
+"研制" =>    "研製",
+"砰当" =>    "砰噹",
+"砲台" =>    "砲臺",
+"朱唇皓齿" =>      "硃唇皓齒",
+"朱批" =>    "硃批",
+"朱砂" =>    "硃砂",
+"朱笔" =>    "硃筆",
+"朱红色" =>         "硃紅色",
+"朱色" =>    "硃色",
+"朱谕" =>    "硃諭",
+"硬干" =>    "硬幹",
+"砚台" =>    "硯臺",
+"碑志" =>    "碑誌",
+"磁制" =>    "磁製",
+"磨制" =>    "磨製",
+"示复" =>    "示覆",
+"社里" =>    "社裡",
+"神采" =>    "神采",
+"御侮" =>    "禦侮",
+"御寇" =>    "禦寇",
+"御寒" =>    "禦寒",
+"御敌" =>    "禦敵",
+"礼义干橹" =>      "禮義干櫓",
+"秃发" =>    "禿髮",
+"秀斗" =>    "秀斗",
+"秀发" =>    "秀髮",
+"私下里" =>         "私下裡",
+"秋天里" =>         "秋天裡",
+"秋裤" =>    "秋褲",
+"秒表" =>    "秒錶",
+"稀松" =>    "稀鬆",
+"禀复" =>    "稟覆",
+"稻谷" =>    "稻穀",
+"稽征" =>    "稽征",
+"谷人" =>    "穀人",
+"谷保家商" =>      "穀保家商",
+"谷仓" =>    "穀倉",
+"谷场" =>    "穀場",
+"谷子" =>    "穀子",
+"谷梁" =>    "穀梁",
+"谷壳" =>    "穀殼",
+"谷物" =>    "穀物",
+"谷皮" =>    "穀皮",
+"谷神" =>    "穀神",
+"谷谷" =>    "穀穀",
+"谷粒" =>    "穀粒",
+"谷舱" =>    "穀艙",
+"谷苗" =>    "穀苗",
+"谷草" =>    "穀草",
+"谷贱伤农" =>      "穀賤傷農",
+"谷道" =>    "穀道",
+"谷雨" =>    "穀雨",
+"谷类" =>    "穀類",
+"谷风" =>    "穀風",
+"积极参与" =>      "積极參与",
+"积极参加" =>      "積极參加",
+"积谷防饥" =>      "積穀防饑",
+"空蒙" =>    "空濛",
+"窗帘" =>    "窗帘",
+"窗明几净" =>      "窗明几淨",
+"窗台" =>    "窗檯",
+"窗台" =>    "窗臺",
+"窝里" =>    "窩裡",
+"窝阔台" =>         "窩闊臺",
+"穷发" =>    "窮髮",
+"站台" =>    "站臺",
+"笆斗" =>    "笆斗",
+"笑里藏刀" =>      "笑裡藏刀",
+"第一卷" =>         "第一卷",
+"筋斗" =>    "筋斗",
+"答卷" =>    "答卷",
+"答复" =>    "答複",
+"答复" =>    "答覆",
+"筵几" =>    "筵几",
+"箕斗" =>    "箕斗",
+"算历" =>    "算曆",
+"签着" =>    "簽著",
+"吁求" =>    "籲求",
+"吁请" =>    "籲請",
+"粗制" =>    "粗製",
+"粗卤" =>    "粗鹵",
+"精干" =>    "精幹",
+"精明强干" =>      "精明強幹",
+"精致" =>    "精緻",
+"精制" =>    "精製",
+"精辟" =>    "精辟",
+"精采" =>    "精采",
+"糊里糊涂" =>      "糊裡糊塗",
+"团子" =>    "糰子",
+"系着" =>    "系著",
+"系里" =>    "系裡",
+"纪历" =>    "紀曆",
+"红绳系足" =>      "紅繩繫足",
+"红发" =>    "紅髮",
+"纡回" =>    "紆迴",
+"纳采" =>    "納采",
+"素食面" =>         "素食麵",
+"素发" =>    "素髮",
+"素面" =>    "素麵",
+"紫微斗数" =>      "紫微斗數",
+"细致" =>    "細緻",
+"组里" =>    "組裡",
+"结发" =>    "結髮",
+"绝对参照" =>      "絕對參照",
+"丝来线去" =>      "絲來線去",
+"丝布" =>    "絲布",
+"丝板" =>    "絲板",
+"丝瓜布" =>         "絲瓜布",
+"丝绒布" =>         "絲絨布",
+"丝线" =>    "絲線",
+"丝织厂" =>         "絲織廠",
+"丝虫" =>    "絲蟲",
+"綑吊" =>    "綑吊",
+"经卷" =>    "經卷",
+"维系" =>    "維繫",
+"绾发" =>    "綰髮",
+"网里" =>    "網裡",
+"紧绷" =>    "緊繃",
+"紧绷着" =>         "緊繃著",
+"编制" =>    "編製",
+"编发" =>    "編髮",
+"缓冲" =>    "緩衝",
+"致密" =>    "緻密",
+"萦回" =>    "縈迴",
+"县里" =>    "縣裡",
+"县志" =>    "縣誌",
+"缝里" =>    "縫裡",
+"缝制" =>    "縫製",
+"纤夫" =>    "縴夫",
+"纤手" =>    "縴手",
+"繁复" =>    "繁複",
+"绷住" =>    "繃住",
+"绷子" =>    "繃子",
+"绷带" =>    "繃帶",
+"绷紧" =>    "繃緊",
+"绷脸" =>    "繃臉",
+"绷着" =>    "繃著",
+"绷着脸" =>         "繃著臉",
+"绷着脸儿" =>      "繃著臉兒",
+"绷开" =>    "繃開",
+"绘制" =>    "繪製",
+"系上" =>    "繫上",
+"系世" =>    "繫世",
+"系到" =>    "繫到",
+"系囚" =>    "繫囚",
+"系心" =>    "繫心",
+"系念" =>    "繫念",
+"系怀" =>    "繫懷",
+"系恋" =>    "繫戀",
+"系数" =>    "繫數",
+"系于" =>    "繫於",
+"系系" =>    "繫系",
+"系结" =>    "繫結",
+"系紧" =>    "繫緊",
+"系绳" =>    "繫繩",
+"系累" =>    "繫纍",
+"系着" =>    "繫著",
+"系辞" =>    "繫辭",
+"系风捕影" =>      "繫風捕影",
+"缴卷" =>    "繳卷",
+"累囚" =>    "纍囚",
+"累累" =>    "纍纍",
+"坛子" =>    "罈子",
+"坛坛罐罐" =>      "罈罈罐罐",
+"骂着" =>    "罵著",
+"羁系" =>    "羈繫",
+"美制" =>    "美製",
+"美发" =>    "美髮",
+"翻来复去" =>      "翻來覆去",
+"翻天复地" =>      "翻天覆地",
+"翻复" =>    "翻覆",
+"翻云复雨" =>      "翻雲覆雨",
+"老么" =>    "老么",
+"老板" =>    "老闆",
+"考卷" =>    "考卷",
+"耕获" =>    "耕穫",
+"聊斋志异" =>      "聊齋誌異",
+"联系" =>    "聯係",
+"联系" =>    "聯繫",
+"肉丝面" =>         "肉絲麵",
+"肉羹面" =>         "肉羹麵",
+"肉松" =>    "肉鬆",
+"肚里" =>    "肚裏",
+"肚里" =>    "肚裡",
+"肢体" =>    "肢体",
+"胃里" =>    "胃裡",
+"背向着" =>         "背向著",
+"背地里" =>         "背地裡",
+"胡里胡涂" =>      "胡裡胡塗",
+"能干" =>    "能幹",
+"脉冲" =>    "脈衝",
+"脱发" =>    "脫髮",
+"腊味" =>    "腊味",
+"腊笔" =>    "腊筆",
+"腊肉" =>    "腊肉",
+"脑子里" =>         "腦子裡",
+"腰里" =>    "腰裡",
+"胶卷" =>    "膠卷",
+"膨松" =>    "膨鬆",
+"自制" =>    "自製",
+"自觉自愿" =>      "自覺自愿",
+"台上" =>    "臺上",
+"台下" =>    "臺下",
+"台中" =>    "臺中",
+"台儿庄" =>         "臺兒莊",
+"台北" =>    "臺北",
+"台南" =>    "臺南",
+"台地" =>    "臺地",
+"台塑" =>    "臺塑",
+"台大" =>    "臺大",
+"台币" =>    "臺幣",
+"台座" =>    "臺座",
+"台东" =>    "臺東",
+"台柱" =>    "臺柱",
+"台榭" =>    "臺榭",
+"台机路" =>         "臺機路",
+"台步" =>    "臺步",
+"台汽" =>    "臺汽",
+"台海" =>    "臺海",
+"台澎金马" =>      "臺澎金馬",
+"台湾" =>    "臺灣",
+"台灯" =>    "臺燈",
+"台球" =>    "臺球",
+"台省" =>    "臺省",
+"台端" =>    "臺端",
+"台糖" =>    "臺糖",
+"台肥" =>    "臺肥",
+"台航" =>    "臺航",
+"台西" =>    "臺西",
+"台视" =>    "臺視",
+"台词" =>    "臺詞",
+"台车" =>    "臺車",
+"台铁" =>    "臺鐵",
+"台阶" =>    "臺階",
+"台电" =>    "臺電",
+"台面" =>    "臺面",
+"舂谷" =>    "舂穀",
+"兴致" =>    "興緻",
+"兴高采烈" =>      "興高采烈",
+"旧历" =>    "舊曆",
+"舒卷" =>    "舒卷",
+"舞榭歌台" =>      "舞榭歌臺",
+"舞台" =>    "舞臺",
+"航海历" =>         "航海曆",
+"船只" =>    "船隻",
+"舰只" =>    "艦隻",
+"芬郁" =>    "芬郁",
+"花卷" =>    "花卷",
+"花盆里" =>         "花盆裡",
+"花采" =>    "花采",
+"苑里" =>    "苑裡",
+"若干" =>    "若干",
+"若干" =>    "若幹",
+"苦干" =>    "苦幹",
+"苦里" =>    "苦裏",
+"苦卤" =>    "苦鹵",
+"范仲淹" =>         "范仲淹",
+"范蠡" =>    "范蠡",
+"范阳" =>    "范陽",
+"茅台" =>    "茅臺",
+"茶几" =>    "茶几",
+"草丛里" =>         "草叢裡",
+"庄里" =>    "莊裡",
+"茎干" =>    "莖幹",
+"菌丝体" =>         "菌絲体",
+"菌丝体" =>         "菌絲體",
+"华里" =>    "華裡",
+"华发" =>    "華髮",
+"万卷" =>    "萬卷",
+"万历" =>    "萬曆",
+"万只" =>    "萬隻",
+"落发" =>    "落髮",
+"着儿" =>    "著兒",
+"着书立说" =>      "著書立說",
+"着色软体" =>      "著色軟體",
+"着重指出" =>      "著重指出",
+"着录" =>    "著錄",
+"着录规则" =>      "著錄規則",
+"蓄发" =>    "蓄髮",
+"蓄须" =>    "蓄鬚",
+"蓬发" =>    "蓬髮",
+"蓬松" =>    "蓬鬆",
+"莲台" =>    "蓮臺",
+"薑丝" =>    "薑絲",
+"薙发" =>    "薙髮",
+"借以" =>    "藉以",
+"借助" =>    "藉助",
+"借口" =>    "藉口",
+"借故" =>    "藉故",
+"借机" =>    "藉機",
+"借此" =>    "藉此",
+"借由" =>    "藉由",
+"借端" =>    "藉端",
+"借着" =>    "藉著",
+"借借" =>    "藉藉",
+"借词" =>    "藉詞",
+"借资" =>    "藉資",
+"借酒浇愁" =>      "藉酒澆愁",
+"藤制" =>    "藤製",
+"蕴含着" =>         "蘊含著",
+"蕴涵着" =>         "蘊涵著",
+"蕴借" =>    "蘊藉",
+"萝卜" =>    "蘿蔔",
+"虎须" =>    "虎鬚",
+"号志" =>    "號誌",
+"蜂後" =>    "蜂后",
+"蜜里调油" =>      "蜜裡調油",
+"蠁干" =>    "蠁幹",
+"蛮干" =>    "蠻幹",
+"行事历" =>         "行事曆",
+"胡同" =>    "衚衕",
+"冲上" =>    "衝上",
+"冲下" =>    "衝下",
+"冲来" =>    "衝來",
+"冲倒" =>    "衝倒",
+"冲冠" =>    "衝冠",
+"冲出" =>    "衝出",
+"冲到" =>    "衝到",
+"冲刺" =>    "衝刺",
+"冲克" =>    "衝剋",
+"冲力" =>    "衝力",
+"冲劲" =>    "衝勁",
+"冲动" =>    "衝動",
+"冲去" =>    "衝去",
+"冲口" =>    "衝口",
+"冲垮" =>    "衝垮",
+"冲堂" =>    "衝堂",
+"冲压" =>    "衝壓",
+"冲天" =>    "衝天",
+"冲掉" =>    "衝掉",
+"冲撞" =>    "衝撞",
+"冲击" =>    "衝擊",
+"冲散" =>    "衝散",
+"冲决" =>    "衝決",
+"冲浪" =>    "衝浪",
+"冲激" =>    "衝激",
+"冲破" =>    "衝破",
+"冲程" =>    "衝程",
+"冲突" =>    "衝突",
+"冲线" =>    "衝線",
+"冲着" =>    "衝著",
+"冲冲" =>    "衝衝",
+"冲要" =>    "衝要",
+"冲起" =>    "衝起",
+"冲进" =>    "衝進",
+"冲过" =>    "衝過",
+"冲锋" =>    "衝鋒",
+"表里" =>    "表裡",
+"袋里" =>    "袋裡",
+"袖里" =>    "袖裡",
+"被里" =>    "被裡",
+"被复" =>    "被複",
+"被复" =>    "被覆",
+"被复着" =>         "被覆著",
+"被发" =>    "被髮",
+"裁并" =>    "裁併",
+"裁制" =>    "裁製",
+"里面" =>    "裏面",
+"里人" =>    "裡人",
+"里加" =>    "裡加",
+"里外" =>    "裡外",
+"里子" =>    "裡子",
+"里屋" =>    "裡屋",
+"里层" =>    "裡層",
+"里布" =>    "裡布",
+"里带" =>    "裡帶",
+"里弦" =>    "裡弦",
+"里应外合" =>      "裡應外合",
+"里拉" =>    "裡拉",
+"里斯" =>    "裡斯",
+"里海" =>    "裡海",
+"里脊" =>    "裡脊",
+"里衣" =>    "裡衣",
+"里里" =>    "裡裡",
+"里通外国" =>      "裡通外國",
+"里通外敌" =>      "裡通外敵",
+"里边" =>    "裡邊",
+"里间" =>    "裡間",
+"里面" =>    "裡面",
+"里头" =>    "裡頭",
+"制件" =>    "製件",
+"制作" =>    "製作",
+"制做" =>    "製做",
+"制备" =>    "製備",
+"制冰" =>    "製冰",
+"制冷" =>    "製冷",
+"制剂" =>    "製劑",
+"制品" =>    "製品",
+"制图" =>    "製圖",
+"制成" =>    "製成",
+"制法" =>    "製法",
+"制为" =>    "製為",
+"制片" =>    "製片",
+"制版" =>    "製版",
+"制程" =>    "製程",
+"制糖" =>    "製糖",
+"制纸" =>    "製紙",
+"制药" =>    "製藥",
+"制表" =>    "製表",
+"制裁" =>    "製裁",
+"制造" =>    "製造",
+"制革" =>    "製革",
+"制鞋" =>    "製鞋",
+"制盐" =>    "製鹽",
+"复仞年如" =>      "複仞年如",
+"复以百万" =>      "複以百萬",
+"复位" =>    "複位",
+"复信" =>    "複信",
+"复分数" =>         "複分數",
+"复列" =>    "複列",
+"复利" =>    "複利",
+"复印" =>    "複印",
+"复原" =>    "複原",
+"复句" =>    "複句",
+"复合" =>    "複合",
+"复名" =>    "複名",
+"复员" =>    "複員",
+"复壁" =>    "複壁",
+"复壮" =>    "複壯",
+"复姓" =>    "複姓",
+"复字键" =>         "複字鍵",
+"复审" =>    "複審",
+"复写" =>    "複寫",
+"复式" =>    "複式",
+"复复" =>    "複復",
+"复数" =>    "複數",
+"复本" =>    "複本",
+"复查" =>    "複查",
+"复核" =>    "複核",
+"复检" =>    "複檢",
+"复次" =>    "複次",
+"复比" =>    "複比",
+"复决" =>    "複決",
+"复活" =>    "複活",
+"复测" =>    "複測",
+"复亩珍" =>         "複畝珍",
+"复发" =>    "複發",
+"复目" =>    "複目",
+"复眼" =>    "複眼",
+"复种" =>    "複種",
+"复线" =>    "複線",
+"复习" =>    "複習",
+"复兴社" =>         "複興社",
+"复旧" =>    "複舊",
+"复色" =>    "複色",
+"复叶" =>    "複葉",
+"复盖" =>    "複蓋",
+"复苏" =>    "複蘇",
+"复制" =>    "複製",
+"复诊" =>    "複診",
+"复评" =>    "複評",
+"复词" =>    "複詞",
+"复试" =>    "複試",
+"复课" =>    "複課",
+"复议" =>    "複議",
+"复变函数" =>      "複變函數",
+"复赛" =>    "複賽",
+"复述" =>    "複述",
+"复选" =>    "複選",
+"复钱" =>    "複錢",
+"复阅" =>    "複閱",
+"复杂" =>    "複雜",
+"复电" =>    "複電",
+"复音" =>    "複音",
+"复韵" =>    "複韻",
+"衬里" =>    "襯裡",
+"西岳" =>    "西嶽",
+"西征" =>    "西征",
+"西历" =>    "西曆",
+"要冲" =>    "要衝",
+"要么" =>    "要麼",
+"复上" =>    "覆上",
+"复亡" =>    "覆亡",
+"复住" =>    "覆住",
+"复信" =>    "覆信",
+"复冒" =>    "覆冒",
+"复判" =>    "覆判",
+"复命" =>    "覆命",
+"复在" =>    "覆在",
+"复审" =>    "覆審",
+"复写" =>    "覆寫",
+"复巢" =>    "覆巢",
+"复成" =>    "覆成",
+"复败" =>    "覆敗",
+"复文" =>    "覆文",
+"复校" =>    "覆校",
+"复核" =>    "覆核",
+"复水难收" =>      "覆水難收",
+"复没" =>    "覆沒",
+"复灭" =>    "覆滅",
+"复叠" =>    "覆疊",
+"复盆" =>    "覆盆",
+"复舟" =>    "覆舟",
+"复着" =>    "覆著",
+"复盖" =>    "覆蓋",
+"复盖着" =>         "覆蓋著",
+"复试" =>    "覆試",
+"复诵" =>    "覆誦",
+"复议" =>    "覆議",
+"复车" =>    "覆車",
+"复载" =>    "覆載",
+"复辙" =>    "覆轍",
+"复述" =>    "覆述",
+"复选" =>    "覆選",
+"复电" =>    "覆電",
+"复鼎金" =>         "覆鼎金",
+"见复" =>    "見覆",
+"亲征" =>    "親征",
+"观众台" =>         "觀眾臺",
+"观台" =>    "觀臺",
+"观象台" =>         "觀象臺",
+"角落里" =>         "角落裡",
+"觔斗" =>    "觔斗",
+"触须" =>    "觸鬚",
+"订制" =>    "訂製",
+"诉说着" =>         "訴說著",
+"词汇" =>    "詞彙",
+"词采" =>    "詞采",
+"试卷" =>    "試卷",
+"试制" =>    "試製",
+"诗卷" =>    "詩卷",
+"话里有话" =>      "話裡有話",
+"志哀" =>    "誌哀",
+"志喜" =>    "誌喜",
+"志庆" =>    "誌慶",
+"语云" =>    "語云",
+"语汇" =>    "語彙",
+"诬蔑" =>    "誣衊",
+"诵经台" =>         "誦經臺",
+"说着" =>    "說著",
+"课征" =>    "課征",
+"调制" =>    "調製",
+"调频台" =>         "調頻臺",
+"请参阅" =>         "請參閱",
+"讲台" =>    "講臺",
+"谢绝参观" =>      "謝絕參觀",
+"护发" =>    "護髮",
+"雠正" =>    "讎正",
+"雠隙" =>    "讎隙",
+"豆腐干" =>         "豆腐干",
+"竖着" =>    "豎著",
+"丰富多采" =>      "豐富多采",
+"丰滨" =>    "豐濱",
+"丰滨乡" =>         "豐濱鄉",
+"丰采" =>    "豐采",
+"象征着" =>         "象徵著",
+"贵干" =>    "貴幹",
+"贾後" =>    "賈后",
+"赈饥" =>    "賑饑",
+"赐复" =>    "賜覆",
+"贤後" =>    "賢后",
+"质朴" =>    "質朴",
+"赌台" =>    "賭檯",
+"购并" =>    "購併",
+"赤绳系足" =>      "赤繩繫足",
+"赤松" =>    "赤鬆",
+"起吊" =>    "起吊",
+"起复" =>    "起複",
+"超级杯" =>         "超級盃",
+"赶制" =>    "趕製",
+"跟斗" =>    "跟斗",
+"跳表" =>    "跳錶",
+"蹈借" =>    "蹈藉",
+"踬仆" =>    "躓仆",
+"躯干" =>    "軀幹",
+"车库里" =>         "車庫裡",
+"车站里" =>         "車站裡",
+"车里" =>    "車裡",
+"轻松" =>    "輕鬆",
+"轮回" =>    "輪迴",
+"转台" =>    "轉檯",
+"辛丑" =>    "辛丑",
+"辟易" =>    "辟易",
+"辟邪" =>    "辟邪",
+"办伙" =>    "辦伙",
+"办公台" =>         "辦公檯",
+"辞汇" =>    "辭彙",
+"农历" =>    "農曆",
+"迂回" =>    "迂迴",
+"近日里" =>         "近日裡",
+"迥然回异" =>      "迥然迴異",
+"回光返照" =>      "迴光返照",
+"回向" =>    "迴向",
+"回圈" =>    "迴圈",
+"回廊" =>    "迴廊",
+"回形夹" =>         "迴形夾",
+"回文" =>    "迴文",
+"回旋" =>    "迴旋",
+"回流" =>    "迴流",
+"回环" =>    "迴環",
+"回盪" =>    "迴盪",
+"回纹针" =>         "迴紋針",
+"回绕" =>    "迴繞",
+"回翔" =>    "迴翔",
+"回肠" =>    "迴腸",
+"回荡" =>    "迴蕩",
+"回诵" =>    "迴誦",
+"回路" =>    "迴路",
+"回转" =>    "迴轉",
+"回递性" =>         "迴遞性",
+"回避" =>    "迴避",
+"回銮" =>    "迴鑾",
+"回音" =>    "迴音",
+"回响" =>    "迴響",
+"回风" =>    "迴風",
+"回首" =>    "迴首",
+"迷蒙" =>    "迷濛",
+"退伙" =>    "退伙",
+"这么着" =>         "這么著",
+"这里" =>    "這裏",
+"这里" =>    "這裡",
+"这只" =>    "這隻",
+"这么" =>    "這麼",
+"这么着" =>         "這麼著",
+"通心面" =>         "通心麵",
+"速食面" =>         "速食麵",
+"连系" =>    "連繫",
+"连台好戏" =>      "連臺好戲",
+"遍布" =>    "遍佈",
+"递回" =>    "遞迴",
+"远征" =>    "遠征",
+"适才" =>    "適纔",
+"遮复" =>    "遮覆",
+"还冲" =>    "還衝",
+"邋里邋遢" =>      "邋裡邋遢",
+"那里" =>    "那裏",
+"那里" =>    "那裡",
+"那只" =>    "那隻",
+"那么" =>    "那麼",
+"那么着" =>         "那麼著",
+"邪辟" =>    "邪辟",
+"郁烈" =>    "郁烈",
+"郁穆" =>    "郁穆",
+"郁郁" =>    "郁郁",
+"郁闭" =>    "郁閉",
+"郁馥" =>    "郁馥",
+"乡愿" =>    "鄉愿",
+"乡里" =>    "鄉裡",
+"邻里" =>    "鄰裡",
+"配合着" =>         "配合著",
+"配制" =>    "配製",
+"酒杯" =>    "酒盃",
+"酒坛" =>    "酒罈",
+"酥松" =>    "酥鬆",
+"醋坛" =>    "醋罈",
+"酝借" =>    "醞藉",
+"酝酿着" =>         "醞釀著",
+"医药" =>    "醫葯",
+"醲郁" =>    "醲郁",
+"酿制" =>    "釀製",
+"采地" =>    "采地",
+"采女" =>    "采女",
+"采声" =>    "采聲",
+"采色" =>    "采色",
+"采薇" =>    "采薇",
+"采薪之忧" =>      "采薪之憂",
+"采兰赠药" =>      "采蘭贈藥",
+"采邑" =>    "采邑",
+"采采" =>    "采采",
+"采风" =>    "采風",
+"里程表" =>         "里程錶",
+"重折" =>    "重摺",
+"重制" =>    "重製",
+"重复" =>    "重複",
+"重复" =>    "重覆",
+"野台戏" =>         "野臺戲",
+"金斗" =>    "金斗",
+"金装玉里" =>      "金裝玉裡",
+"金表" =>    "金錶",
+"金发" =>    "金髮",
+"银朱" =>    "銀硃",
+"银发" =>    "銀髮",
+"铜制" =>    "銅製",
+"铝制" =>    "鋁製",
+"钢制" =>    "鋼製",
+"录着" =>    "錄著",
+"录制" =>    "錄製",
+"表带" =>    "錶帶",
+"表店" =>    "錶店",
+"表厂" =>    "錶廠",
+"表壳" =>    "錶殼",
+"表链" =>    "錶鏈",
+"表面" =>    "錶面",
+"锅台" =>    "鍋臺",
+"锻鍊出" =>         "鍛鍊出",
+"锻鍊身体" =>      "鍛鍊身体",
+"镜台" =>    "鏡臺",
+"锈病" =>    "鏽病",
+"锈菌" =>    "鏽菌",
+"锈蚀" =>    "鏽蝕",
+"钟表" =>    "鐘錶",
+"铁锈" =>    "鐵鏽",
+"长征" =>    "長征",
+"长发" =>    "長髮",
+"长须鲸" =>         "長鬚鯨",
+"门帘" =>    "門帘",
+"门斗" =>    "門斗",
+"门里" =>    "門裡",
+"开伙" =>    "開伙",
+"开卷" =>    "開卷",
+"开诚布公" =>      "開誠佈公",
+"开采" =>    "開采",
+"閒情逸致" =>      "閒情逸緻",
+"间不容发" =>      "間不容髮",
+"闵采尔" =>         "閔采爾",
+"阅卷" =>    "閱卷",
+"阑干" =>    "闌干",
+"关系" =>    "關係",
+"关系着" =>         "關係著",
+"防御" =>    "防禦",
+"防锈" =>    "防鏽",
+"防台" =>    "防颱",
+"阿斗" =>    "阿斗",
+"阿里" =>    "阿裡",
+"除旧布新" =>      "除舊佈新",
+"阴干" =>    "陰干",
+"阴历" =>    "陰曆",
+"阴郁" =>    "陰郁",
+"陆征祥" =>         "陸征祥",
+"阳春面" =>         "陽春麵",
+"阳历" =>    "陽曆",
+"阳台" =>    "陽臺",
+"只字" =>    "隻字",
+"只影" =>    "隻影",
+"只手遮天" =>      "隻手遮天",
+"只眼" =>    "隻眼",
+"只言片语" =>      "隻言片語",
+"只身" =>    "隻身",
+"雅致" =>    "雅緻",
+"雇佣" =>    "雇佣",
+"双折" =>    "雙摺",
+"杂志" =>    "雜誌",
+"鸡丝" =>    "雞絲",
+"鸡丝面" =>         "雞絲麵",
+"鸡腿面" =>         "雞腿麵",
+"鸡只" =>    "雞隻",
+"难舍" =>    "難捨",
+"雨花台" =>         "雨花臺",
+"雪里" =>    "雪裡",
+"云须" =>    "雲鬚",
+"电子表" =>         "電子錶",
+"电台" =>    "電臺",
+"电冲" =>    "電衝",
+"电复" =>    "電覆",
+"电视台" =>         "電視臺",
+"电表" =>    "電錶",
+"雾台" =>    "霧臺",
+"雾里" =>    "霧裡",
+"露台" =>    "露臺",
+"灵台" =>    "靈臺",
+"青瓦台" =>         "青瓦臺",
+"青霉" =>    "青黴",
+"面朝着" =>         "面朝著",
+"面临着" =>         "面臨著",
+"鞋里" =>    "鞋裡",
+"鞣制" =>    "鞣製",
+"秋千" =>    "鞦韆",
+"鞭辟入里" =>      "鞭辟入裡",
+"韩国制" =>         "韓國製",
+"韩制" =>    "韓製",
+"颂系" =>    "頌繫",
+"预制" =>    "預製",
+"颁布" =>    "頒佈",
+"头里" =>    "頭裡",
+"头发" =>    "頭髮",
+"颊须" =>    "頰鬚",
+"颠仆" =>    "顛仆",
+"颠复" =>    "顛複",
+"颠复" =>    "顛覆",
+"显着标志" =>      "顯著標志",
+"风土志" =>         "風土誌",
+"风斗" =>    "風斗",
+"风物志" =>         "風物誌",
+"风里" =>    "風裡",
+"风采" =>    "風采",
+"台风" =>    "颱風",
+"刮了" =>    "颳了",
+"刮倒" =>    "颳倒",
+"刮去" =>    "颳去",
+"刮得" =>    "颳得",
+"刮着" =>    "颳著",
+"刮走" =>    "颳走",
+"刮起" =>    "颳起",
+"刮风" =>    "颳風",
+"饭团" =>    "飯糰",
+"饼干" =>    "餅干",
+"馄饨面" =>         "餛飩麵",
+"饥不择食" =>      "饑不擇食",
+"饥寒" =>    "饑寒",
+"饥民" =>    "饑民",
+"饥渴" =>    "饑渴",
+"饥溺" =>    "饑溺",
+"饥荒" =>    "饑荒",
+"饥饱" =>    "饑飽",
+"饥饿" =>    "饑餓",
+"饥馑" =>    "饑饉",
+"首当其冲" =>      "首當其衝",
+"香郁" =>    "香郁",
+"馥郁" =>    "馥郁",
+"马里" =>    "馬裡",
+"马表" =>    "馬錶",
+"腾冲" =>    "騰衝",
+"骨子里" =>         "骨子裡",
+"骨干" =>    "骨幹",
+"骨灰坛" =>         "骨灰罈",
+"肮脏" =>    "骯髒",
+"脏乱" =>    "髒亂",
+"脏了" =>    "髒了",
+"脏兮兮" =>         "髒兮兮",
+"脏字" =>    "髒字",
+"脏得" =>    "髒得",
+"脏东西" =>         "髒東西",
+"脏水" =>    "髒水",
+"脏的" =>    "髒的",
+"脏话" =>    "髒話",
+"脏钱" =>    "髒錢",
+"高干" =>    "高幹",
+"高台" =>    "高臺",
+"髭须" =>    "髭鬚",
+"发型" =>    "髮型",
+"发夹" =>    "髮夾",
+"发妻" =>    "髮妻",
+"发姐" =>    "髮姐",
+"发带" =>    "髮帶",
+"发廊" =>    "髮廊",
+"发式" =>    "髮式",
+"发指" =>    "髮指",
+"发捲" =>    "髮捲",
+"发根" =>    "髮根",
+"发毛" =>    "髮毛",
+"发油" =>    "髮油",
+"发状" =>    "髮狀",
+"发短心长" =>      "髮短心長",
+"发端" =>    "髮端",
+"发结" =>    "髮結",
+"发丝" =>    "髮絲",
+"发网" =>    "髮網",
+"发肤" =>    "髮膚",
+"发胶" =>    "髮膠",
+"发菜" =>    "髮菜",
+"发蜡" =>    "髮蠟",
+"发辫" =>    "髮辮",
+"发针" =>    "髮針",
+"发长" =>    "髮長",
+"发际" =>    "髮際",
+"发雕" =>    "髮雕",
+"发霜" =>    "髮霜",
+"发髻" =>    "髮髻",
+"发鬓" =>    "髮鬢",
+"鬅松" =>    "鬅鬆",
+"松了" =>    "鬆了",
+"松些" =>    "鬆些",
+"松劲" =>    "鬆勁",
+"松动" =>    "鬆動",
+"松口" =>    "鬆口",
+"松土" =>    "鬆土",
+"松弛" =>    "鬆弛",
+"松快" =>    "鬆快",
+"松懈" =>    "鬆懈",
+"松手" =>    "鬆手",
+"松掉" =>    "鬆掉",
+"松散" =>    "鬆散",
+"松林" =>    "鬆林",
+"松柔" =>    "鬆柔",
+"松毛虫" =>         "鬆毛蟲",
+"松浮" =>    "鬆浮",
+"松涛" =>    "鬆濤",
+"松科" =>    "鬆科",
+"松节油" =>         "鬆節油",
+"松绑" =>    "鬆綁",
+"松紧" =>    "鬆緊",
+"松缓" =>    "鬆緩",
+"松脆" =>    "鬆脆",
+"松脱" =>    "鬆脫",
+"松起" =>    "鬆起",
+"松软" =>    "鬆軟",
+"松通" =>    "鬆通",
+"松开" =>    "鬆開",
+"松饼" =>    "鬆餅",
+"松松" =>    "鬆鬆",
+"鬈发" =>    "鬈髮",
+"胡子" =>    "鬍子",
+"胡梢" =>    "鬍梢",
+"胡渣" =>    "鬍渣",
+"胡髭" =>    "鬍髭",
+"胡须" =>    "鬍鬚",
+"须根" =>    "鬚根",
+"须毛" =>    "鬚毛",
+"须生" =>    "鬚生",
+"须眉" =>    "鬚眉",
+"须发" =>    "鬚髮",
+"须须" =>    "鬚鬚",
+"鬓发" =>    "鬢髮",
+"斗着" =>    "鬥著",
+"闹着玩儿" =>      "鬧著玩儿",
+"闹着玩儿" =>      "鬧著玩兒",
+"郁郁" =>    "鬱郁",
+"魂牵梦系" =>      "魂牽夢繫",
+"鱼松" =>    "魚鬆",
+"鲸须" =>    "鯨鬚",
+"鲇鱼" =>    "鯰魚",
+"鸿篇巨制" =>      "鴻篇巨製",
+"鹤发" =>    "鶴髮",
+"卤化" =>    "鹵化",
+"卤味" =>    "鹵味",
+"卤族" =>    "鹵族",
+"卤水" =>    "鹵水",
+"卤汁" =>    "鹵汁",
+"卤簿" =>    "鹵簿",
+"卤素" =>    "鹵素",
+"卤莽" =>    "鹵莽",
+"卤钝" =>    "鹵鈍",
+"咸味" =>    "鹹味",
+"咸土" =>    "鹹土",
+"咸度" =>    "鹹度",
+"咸得" =>    "鹹得",
+"咸水" =>    "鹹水",
+"咸海" =>    "鹹海",
+"咸淡" =>    "鹹淡",
+"咸湖" =>    "鹹湖",
+"咸汤" =>    "鹹湯",
+"咸的" =>    "鹹的",
+"咸肉" =>    "鹹肉",
+"咸菜" =>    "鹹菜",
+"咸蛋" =>    "鹹蛋",
+"咸猪肉" =>         "鹹豬肉",
+"咸类" =>    "鹹類",
+"咸鱼" =>    "鹹魚",
+"咸鸭蛋" =>         "鹹鴨蛋",
+"咸卤" =>    "鹹鹵",
+"咸咸" =>    "鹹鹹",
+"盐卤" =>    "鹽鹵",
+"面价" =>    "麵價",
+"面包" =>    "麵包",
+"面团" =>    "麵團",
+"面店" =>    "麵店",
+"面厂" =>    "麵廠",
+"面摊" =>    "麵攤",
+"面杖" =>    "麵杖",
+"面条" =>    "麵條",
+"面灰" =>    "麵灰",
+"面皮" =>    "麵皮",
+"面筋" =>    "麵筋",
+"面粉" =>    "麵粉",
+"面糊" =>    "麵糊",
+"面线" =>    "麵線",
+"面茶" =>    "麵茶",
+"面食" =>    "麵食",
+"面饺" =>    "麵餃",
+"面饼" =>    "麵餅",
+"麻酱面" =>         "麻醬麵",
+"黄卷" =>    "黃卷",
+"黄历" =>    "黃曆",
+"黄发" =>    "黃髮",
+"黑发" =>    "黑髮",
+"黑松" =>    "黑鬆",
+"霉毒" =>    "黴毒",
+"霉素" =>    "黴素",
+"霉菌" =>    "黴菌",
+"鼓里" =>    "鼓裡",
+"冬冬" =>    "鼕鼕",
+"龙卷" =>    "龍卷",
+"龙须" =>    "龍鬚",
+"内存"=>"記憶體",
+"默认"=>"預設",
+"缺省"=>"預設",
+"串行"=>"串列",
+"以太网"=>"乙太網",
+"位图"=>"點陣圖",
+"例程"=>"常式",
+"信道"=>"通道",
+"光标"=>"游標",
+"光盘"=>"光碟",
+"光驱"=>"光碟機",
+"全角"=>"全形",
+"共享"=>"共用",
+"兼容"=>"相容",
+"前缀"=>"首碼",
+"后缀"=>"尾碼",
+"加载"=>"載入",
+"半角"=>"半形",
+"变量"=>"變數",
+"噪声"=>"雜訊",
+"因子"=>"因數",
+"在线"=>"線上",
+"脱机"=>"離線",
+"域名"=>"功能變數名稱",
+"声卡"=>"音效卡",
+"字号"=>"字型大小",
+"字库"=>"字型檔",
+"字段"=>"欄位",
+"字符"=>"字元",
+"存盘"=>"存檔",
+"寻址"=>"定址",
+"尾注"=>"章節附註",
+"异步"=>"非同步",
+"总线"=>"匯流排",
+"括号"=>"括弧",
+"接口"=>"介面",
+"控件"=>"控制項",
+"权限"=>"許可權",
+"盘片"=>"碟片",
+"硅片"=>"矽片",
+"硅谷"=>"矽谷",
+"硬盘"=>"硬碟",
+"磁盘"=>"磁碟",
+"磁道"=>"磁軌",
+"程控"=>"程式控制",
+"端口"=>"埠",
+"算子"=>"運算元",
+"算法"=>"演算法",
+"芯片"=>"晶片",
+"芯片"=>"晶元",
+"词组"=>"片語",
+"译码"=>"解碼",
+"软驱"=>"軟碟機",
+"闪存"=>"快閃記憶體",
+"鼠标"=>"滑鼠",
+"进制"=>"進位",
+"交互式"=>"互動式",
+"仿真"=>"模擬",
+"优先级"=>"優先順序",
+"传感"=>"感測",
+"便携式"=>"攜帶型",
+"信息论"=>"資訊理論",
+"循环"=>"迴圈",
+"写保护"=>"防寫",
+"分布式"=>"分散式",
+"分辨率"=>"解析度",
+"程序"=>"程式",
+"服务器"=>"伺服器",
+"等于"=>"等於",
+"局域网"=>"區域網",
+"上载"=>"上傳",
+"计算机"=>"電腦",
+"宏"=>"巨集",
+"扫瞄仪"=>"掃瞄器",
+"宽带"=>"寬頻",
+"窗口"=>"視窗",
+"数据库"=>"資料庫",
+"公历"=>"西曆",
+"奶酪"=>"乳酪",
+"巨商"=>"鉅賈",
+"手电"=>"手電筒",
+"万历"=>"萬曆",
+"永历"=>"永曆",
+"词汇"=>"辭彙",
+"保安"=>"保全",
+"习用"=>"慣用",
+"元音"=>"母音",
+"任意球"=>"自由球",
+"头球"=>"頭槌",
+"入球"=>"進球",
+"粒入球"=>"顆進球",
+"打门"=>"射門",
+"火锅盖帽"=>"蓋火鍋",
+"打印机"=>"印表機",
+"打印機"=>"印表機",
+"字节"=>"位元組",
+"字節"=>"位元組",
+"打印"=>"列印",
+"打印"=>"列印",
+"硬件"=>"硬體",
+"硬件"=>"硬體",
+"二极管"=>"二極體",
+"二極管"=>"二極體",
+"三极管"=>"三極體",
+"三極管"=>"三極體",
+"数码"=>"數位",
+"數碼"=>"數位",
+"软件"=>"軟體",
+"軟件"=>"軟體",
+"网络"=>"網路",
+"網絡"=>"網路",
+"人工智能"=>"人工智慧",
+"航天飞机"=>"太空梭",
+"穿梭機"=>"太空梭",
+"因特网"=>"網際網路",
+"互聯網"=>"網際網路",
+"机器人"=>"機器人",
+"機械人"=>"機器人",
+"移动电话"=>"行動電話",
+"流動電話"=>"行動電話",
+"调制解调器"=>"數據機",
+"調制解調器"=>"數據機",
+"短信"=>"簡訊",
+"短訊"=>"簡訊",
+"乌兹别克斯坦"=>"烏茲別克",
+"乍得"=>"查德",
+"乍得"=>"查德",
+"也门"=>"葉門",
+"也門"=>"葉門",
+"伯利兹"=>"貝里斯",
+"伯利茲"=>"貝里斯",
+"佛得角"=>"維德角",
+"佛得角"=>"維德角",
+"克罗地亚"=>"克羅埃西亞",
+"克羅地亞"=>"克羅埃西亞",
+"冈比亚"=>"甘比亞",
+"岡比亞"=>"甘比亞",
+"几内亚比绍"=>"幾內亞比索",
+"幾內亞比紹"=>"幾內亞比索",
+"列支敦士登"=>"列支敦斯登",
+"列支敦士登"=>"列支敦斯登",
+"利比里亚"=>"賴比瑞亞",
+"利比里亞"=>"賴比瑞亞",
+"加纳"=>"迦納",
+"加納"=>"迦納",
+"加蓬"=>"加彭",
+"加蓬"=>"加彭",
+"博茨瓦纳"=>"波札那",
+"博茨瓦納"=>"波札那",
+"卡塔尔"=>"卡達",
+"卡塔爾"=>"卡達",
+"卢旺达"=>"盧安達",
+"盧旺達"=>"盧安達",
+"危地马拉"=>"瓜地馬拉",
+"危地馬拉"=>"瓜地馬拉",
+"厄瓜多尔"=>"厄瓜多",
+"厄瓜多爾"=>"厄瓜多",
+"厄立特里亚"=>"厄利垂亞",
+"厄立特里亞"=>"厄利垂亞",
+"吉布提"=>"吉布地",
+"吉布堤"=>"吉布地",
+"哈萨克斯坦"=>"哈薩克",
+"哥斯达黎加"=>"哥斯大黎加",
+"哥斯達黎加"=>"哥斯大黎加",
+"图瓦卢"=>"吐瓦魯",
+"圖瓦盧"=>"吐瓦魯",
+"土库曼斯坦"=>"土庫曼",
+"圣卢西亚"=>"聖露西亞",
+"聖盧西亞"=>"聖露西亞",
+"圣基茨和尼维斯"=>"聖克里斯多福及尼維斯",
+"聖吉斯納域斯"=>"聖克里斯多福及尼維斯",
+"圣文森特和格林纳丁斯"=>"聖文森及格瑞那丁",
+"聖文森特和格林納丁斯"=>"聖文森及格瑞那丁",
+"圣马力诺"=>"聖馬利諾",
+"聖馬力諾"=>"聖馬利諾",
+"圭亚那"=>"蓋亞那",
+"圭亞那"=>"蓋亞那",
+"坦桑尼亚"=>"坦尚尼亞",
+"坦桑尼亞"=>"坦尚尼亞",
+"埃塞俄比亚"=>"衣索比亞",
+"埃塞俄比亞"=>"衣索比亞",
+"基里巴斯"=>"吉里巴斯",
+"基里巴斯"=>"吉里巴斯",
+"塔吉克斯坦"=>"塔吉克",
+"塞拉利昂"=>"獅子山",
+"塞拉利昂"=>"獅子山",
+"塞浦路斯"=>"塞普勒斯",
+"塞浦路斯"=>"塞普勒斯",
+"塞舌尔"=>"塞席爾",
+"塞舌爾"=>"塞席爾",
+"多米尼加"=>"多明尼加",
+"多明尼加共和國"=>"多明尼加",
+"多米尼加联邦"=>"多米尼克",
+"多明尼加聯邦"=>"多米尼克",
+"安提瓜和巴布达"=>"安地卡及巴布達",
+"安提瓜和巴布達"=>"安地卡及巴布達",
+"尼日利亚"=>"奈及利亞",
+"尼日利亞"=>"奈及利亞",
+"尼日尔"=>"尼日",
+"尼日爾"=>"尼日",
+"巴巴多斯"=>"巴貝多",
+"巴巴多斯"=>"巴貝多",
+"巴布亚新几内亚"=>"巴布亞紐幾內亞",
+"巴布亞新畿內亞"=>"巴布亞紐幾內亞",
+"布基纳法索"=>"布吉納法索",
+"布基納法索"=>"布吉納法索",
+"布隆迪"=>"蒲隆地",
+"布隆迪"=>"蒲隆地",
+"希腊"=>"希臘",
+"帕劳"=>"帛琉",
+"意大利"=>"義大利",
+"意大利"=>"義大利",
+"所罗门群岛"=>"索羅門群島",
+"所羅門群島"=>"索羅門群島",
+"文莱"=>"汶萊",
+"斯威士兰"=>"史瓦濟蘭",
+"斯威士蘭"=>"史瓦濟蘭",
+"斯洛文尼亚"=>"斯洛維尼亞",
+"斯洛文尼亞"=>"斯洛維尼亞",
+"新西兰"=>"紐西蘭",
+"新西蘭"=>"紐西蘭",
+"朝鲜"=>"北韓",
+"格林纳达"=>"格瑞那達",
+"格林納達"=>"格瑞那達",
+"格鲁吉亚"=>"喬治亞",
+"格魯吉亞"=>"喬治亞",
+"梵蒂冈"=>"教廷",
+"梵蒂岡"=>"教廷",
+"毛里塔尼亚"=>"茅利塔尼亞",
+"毛里塔尼亞"=>"茅利塔尼亞",
+"毛里求斯"=>"模里西斯",
+"毛里裘斯"=>"模里西斯",
+"沙特阿拉伯"=>"沙烏地阿拉伯",
+"沙地阿拉伯"=>"沙烏地阿拉伯",
+"波斯尼亚和黑塞哥维那"=>"波士尼亞赫塞哥維納",
+"波斯尼亞黑塞哥維那"=>"波士尼亞赫塞哥維納",
+"津巴布韦"=>"辛巴威",
+"津巴布韋"=>"辛巴威",
+"洪都拉斯"=>"宏都拉斯",
+"洪都拉斯"=>"宏都拉斯",
+"特立尼达和托巴哥"=>"千里達托貝哥",
+"特立尼達和多巴哥"=>"千里達托貝哥",
+"瑙鲁"=>"諾魯",
+"瑙魯"=>"諾魯",
+"瓦努阿图"=>"萬那杜",
+"瓦努阿圖"=>"萬那杜",
+"溫納圖萬"=>"那杜",
+"科摩罗"=>"葛摩",
+"科摩羅"=>"葛摩",
+"科特迪瓦"=>"象牙海岸",
+"突尼斯"=>"突尼西亞",
+"索马里"=>"索馬利亞",
+"索馬里"=>"索馬利亞",
+"老挝"=>"寮國",
+"老撾"=>"寮國",
+"肯尼亚"=>"肯亞",
+"肯雅"=>"肯亞",
+"苏里南"=>"蘇利南",
+"莫桑比克"=>"莫三比克",
+"莱索托"=>"賴索托",
+"萊索托"=>"賴索托",
+"贝宁"=>"貝南",
+"貝寧"=>"貝南",
+"赞比亚"=>"尚比亞",
+"贊比亞"=>"尚比亞",
+"阿塞拜疆"=>"亞塞拜然",
+"阿塞拜疆"=>"亞塞拜然",
+"阿拉伯联合酋长国"=>"阿拉伯聯合大公國",
+"阿拉伯聯合酋長國"=>"阿拉伯聯合大公國",
+"韩国"=>"南韓",
+"马尔代夫"=>"馬爾地夫",
+"馬爾代夫"=>"馬爾地夫",
+"马耳他"=>"馬爾他",
+"马里"=>"馬利",
+"馬里"=>"馬利",
+"方便面"=>"速食麵",
+"快速面"=>"速食麵",
+"即食麵"=>"速食麵",
+"薯仔"=>"土豆",
+"蹦极跳"=>"笨豬跳",
+"绑紧跳"=>"笨豬跳",
+"冷菜"=>"冷盤",
+"凉菜"=>"冷盤",
+"的士"=>"計程車",
+"出租车"=>"計程車",
+"巴士"=>"公車",
+"公共汽车"=>"公車",
+"台球"=>"撞球",
+"桌球"=>"撞球",
+"雪糕"=>"冰淇淋",
+"卫生"=>"衛生",
+"衞生"=>"衛生",
+"平治"=>"賓士",
+"奔驰"=>"賓士",
+"積架"=>"捷豹",
+"福士"=>"福斯",
+"雪铁龙"=>"雪鐵龍",
+"马自达"=>"馬自達",
+"萬事得"=>"馬自達",
+"布什"=>"布希",
+"布殊"=>"布希",
+"克林顿"=>"柯林頓",
+"克林頓"=>"柯林頓",
+"萨达姆"=>"海珊",
+"薩達姆"=>"海珊",
+"凡高"=>"梵谷",
+"狄安娜"=>"黛安娜",
+"戴安娜"=>"黛安娜",
+"赫拉"=>"希拉",
+);
+
+
+$zh2CN=array(
+"么"=>"么",
+"瀋"=>"沈",
+"畫"=>"划",
+"鍾"=>"钟",
+"餘"=>"余",
+"鯰"=>"鲇",
+"鹼"=>"硷",
+"麼"=>"么",
+"䊷"=>"䌶",
+"𧩙"=>"䜥",
+"万"=>"万",
+"与"=>"与",
+"丑"=>"丑",
+"丟"=>"丢",
+"並"=>"并",
+"丰"=>"丰",
+"么"=>"么",
+"乾"=>"干",
+"亂"=>"乱",
+"云"=>"云",
+"亙"=>"亘",
+"亞"=>"亚",
+"仆"=>"仆",
+"价"=>"价",
+"伙"=>"伙",
+"佇"=>"伫",
+"佈"=>"布",
+"体"=>"体",
+"余"=>"余",
+"余"=>"馀",
+"佣"=>"佣",
+"併"=>"并",
+"來"=>"来",
+"侖"=>"仑",
+"侶"=>"侣",
+"俁"=>"俣",
+"係"=>"系",
+"俔"=>"伣",
+"俠"=>"侠",
+"倀"=>"伥",
+"倆"=>"俩",
+"倈"=>"俫",
+"倉"=>"仓",
+"個"=>"个",
+"們"=>"们",
+"倫"=>"伦",
+"偉"=>"伟",
+"側"=>"侧",
+"偵"=>"侦",
+"偽"=>"伪",
+"傑"=>"杰",
+"傖"=>"伧",
+"傘"=>"伞",
+"備"=>"备",
+"傢"=>"家",
+"傭"=>"佣",
+"傯"=>"偬",
+"傳"=>"传",
+"傴"=>"伛",
+"債"=>"债",
+"傷"=>"伤",
+"傾"=>"倾",
+"僂"=>"偻",
+"僅"=>"仅",
+"僉"=>"佥",
+"僑"=>"侨",
+"僕"=>"仆",
+"僞"=>"伪",
+"僥"=>"侥",
+"僨"=>"偾",
+"價"=>"价",
+"儀"=>"仪",
+"儂"=>"侬",
+"億"=>"亿",
+"儈"=>"侩",
+"儉"=>"俭",
+"儐"=>"傧",
+"儔"=>"俦",
+"儕"=>"侪",
+"儘"=>"尽",
+"償"=>"偿",
+"優"=>"优",
+"儲"=>"储",
+"儷"=>"俪",
+"儺"=>"傩",
+"儻"=>"傥",
+"儼"=>"俨",
+"儿"=>"儿",
+"兇"=>"凶",
+"兌"=>"兑",
+"兒"=>"儿",
+"兗"=>"兖",
+"党"=>"党",
+"內"=>"内",
+"兩"=>"两",
+"冊"=>"册",
+"冪"=>"幂",
+"准"=>"准",
+"凈"=>"净",
+"凍"=>"冻",
+"凜"=>"凛",
+"几"=>"几",
+"凱"=>"凯",
+"划"=>"划",
+"別"=>"别",
+"刪"=>"删",
+"剄"=>"刭",
+"則"=>"则",
+"剋"=>"克",
+"剎"=>"刹",
+"剗"=>"刬",
+"剛"=>"刚",
+"剝"=>"剥",
+"剮"=>"剐",
+"剴"=>"剀",
+"創"=>"创",
+"劃"=>"划",
+"劇"=>"剧",
+"劉"=>"刘",
+"劊"=>"刽",
+"劌"=>"刿",
+"劍"=>"剑",
+"劑"=>"剂",
+"勁"=>"劲",
+"動"=>"动",
+"務"=>"务",
+"勛"=>"勋",
+"勝"=>"胜",
+"勞"=>"劳",
+"勢"=>"势",
+"勩"=>"勚",
+"勱"=>"劢",
+"勵"=>"励",
+"勸"=>"劝",
+"勻"=>"匀",
+"匭"=>"匦",
+"匯"=>"汇",
+"匱"=>"匮",
+"區"=>"区",
+"協"=>"协",
+"卷"=>"卷",
+"卻"=>"却",
+"厂"=>"厂",
+"厙"=>"厍",
+"厠"=>"厕",
+"厭"=>"厌",
+"厲"=>"厉",
+"厴"=>"厣",
+"參"=>"参",
+"叄"=>"叁",
+"叢"=>"丛",
+"台"=>"台",
+"叶"=>"叶",
+"吊"=>"吊",
+"后"=>"后",
+"后"=>"後",
+"吒"=>"咤",
+"吳"=>"吴",
+"吶"=>"呐",
+"呂"=>"吕",
+"咼"=>"呙",
+"員"=>"员",
+"唄"=>"呗",
+"唚"=>"吣",
+"問"=>"问",
+"啓"=>"启",
+"啞"=>"哑",
+"啟"=>"启",
+"啢"=>"唡",
+"喎"=>"㖞",
+"喚"=>"唤",
+"喪"=>"丧",
+"喬"=>"乔",
+"單"=>"单",
+"喲"=>"哟",
+"嗆"=>"呛",
+"嗇"=>"啬",
+"嗊"=>"唝",
+"嗎"=>"吗",
+"嗚"=>"呜",
+"嗩"=>"唢",
+"嗶"=>"哔",
+"嘆"=>"叹",
+"嘍"=>"喽",
+"嘔"=>"呕",
+"嘖"=>"啧",
+"嘗"=>"尝",
+"嘜"=>"唛",
+"嘩"=>"哗",
+"嘮"=>"唠",
+"嘯"=>"啸",
+"嘰"=>"叽",
+"嘵"=>"哓",
+"嘸"=>"呒",
+"嘽"=>"啴",
+"噁"=>"恶",
+"噓"=>"嘘",
+"噝"=>"咝",
+"噠"=>"哒",
+"噥"=>"哝",
+"噦"=>"哕",
+"噯"=>"嗳",
+"噲"=>"哙",
+"噴"=>"喷",
+"噸"=>"吨",
+"噹"=>"当",
+"嚀"=>"咛",
+"嚇"=>"吓",
+"嚌"=>"哜",
+"嚕"=>"噜",
+"嚙"=>"啮",
+"嚥"=>"咽",
+"嚦"=>"呖",
+"嚨"=>"咙",
+"嚮"=>"向",
+"嚲"=>"亸",
+"嚳"=>"喾",
+"嚴"=>"严",
+"嚶"=>"嘤",
+"囀"=>"啭",
+"囁"=>"嗫",
+"囂"=>"嚣",
+"囅"=>"冁",
+"囈"=>"呓",
+"囌"=>"苏",
+"囑"=>"嘱",
+"囪"=>"囱",
+"圇"=>"囵",
+"國"=>"国",
+"圍"=>"围",
+"園"=>"园",
+"圓"=>"圆",
+"圖"=>"图",
+"團"=>"团",
+"坏"=>"坏",
+"垵"=>"埯",
+"埡"=>"垭",
+"埰"=>"采",
+"執"=>"执",
+"堅"=>"坚",
+"堊"=>"垩",
+"堖"=>"垴",
+"堝"=>"埚",
+"堯"=>"尧",
+"報"=>"报",
+"場"=>"场",
+"塊"=>"块",
+"塋"=>"茔",
+"塏"=>"垲",
+"塒"=>"埘",
+"塗"=>"涂",
+"塚"=>"冢",
+"塢"=>"坞",
+"塤"=>"埙",
+"塵"=>"尘",
+"塹"=>"堑",
+"墊"=>"垫",
+"墜"=>"坠",
+"墮"=>"堕",
+"墳"=>"坟",
+"墻"=>"墙",
+"墾"=>"垦",
+"壇"=>"坛",
+"壈"=>"𡒄",
+"壋"=>"垱",
+"壓"=>"压",
+"壘"=>"垒",
+"壙"=>"圹",
+"壚"=>"垆",
+"壞"=>"坏",
+"壟"=>"垄",
+"壠"=>"垅",
+"壢"=>"坜",
+"壩"=>"坝",
+"壯"=>"壮",
+"壺"=>"壶",
+"壼"=>"壸",
+"壽"=>"寿",
+"夠"=>"够",
+"夢"=>"梦",
+"夾"=>"夹",
+"奐"=>"奂",
+"奧"=>"奥",
+"奩"=>"奁",
+"奪"=>"夺",
+"奬"=>"奖",
+"奮"=>"奋",
+"奼"=>"姹",
+"妝"=>"妆",
+"姍"=>"姗",
+"姜"=>"姜",
+"姦"=>"奸",
+"娛"=>"娱",
+"婁"=>"娄",
+"婦"=>"妇",
+"婭"=>"娅",
+"媧"=>"娲",
+"媯"=>"妫",
+"媼"=>"媪",
+"媽"=>"妈",
+"嫗"=>"妪",
+"嫵"=>"妩",
+"嫻"=>"娴",
+"嫿"=>"婳",
+"嬀"=>"妫",
+"嬈"=>"娆",
+"嬋"=>"婵",
+"嬌"=>"娇",
+"嬙"=>"嫱",
+"嬡"=>"嫒",
+"嬤"=>"嬷",
+"嬪"=>"嫔",
+"嬰"=>"婴",
+"嬸"=>"婶",
+"孌"=>"娈",
+"孫"=>"孙",
+"學"=>"学",
+"孿"=>"孪",
+"宁"=>"宁",
+"宮"=>"宫",
+"寢"=>"寝",
+"實"=>"实",
+"寧"=>"宁",
+"審"=>"审",
+"寫"=>"写",
+"寬"=>"宽",
+"寵"=>"宠",
+"寶"=>"宝",
+"將"=>"将",
+"專"=>"专",
+"尋"=>"寻",
+"對"=>"对",
+"導"=>"导",
+"尷"=>"尴",
+"屆"=>"届",
+"屍"=>"尸",
+"屓"=>"屃",
+"屜"=>"屉",
+"屢"=>"屡",
+"層"=>"层",
+"屨"=>"屦",
+"屬"=>"属",
+"岡"=>"冈",
+"峴"=>"岘",
+"島"=>"岛",
+"峽"=>"峡",
+"崍"=>"崃",
+"崗"=>"岗",
+"崢"=>"峥",
+"崬"=>"岽",
+"嵐"=>"岚",
+"嶁"=>"嵝",
+"嶄"=>"崭",
+"嶇"=>"岖",
+"嶔"=>"嵚",
+"嶗"=>"崂",
+"嶠"=>"峤",
+"嶢"=>"峣",
+"嶧"=>"峄",
+"嶮"=>"崄",
+"嶴"=>"岙",
+"嶸"=>"嵘",
+"嶺"=>"岭",
+"嶼"=>"屿",
+"嶽"=>"岳",
+"巋"=>"岿",
+"巒"=>"峦",
+"巔"=>"巅",
+"巰"=>"巯",
+"帘"=>"帘",
+"帥"=>"帅",
+"師"=>"师",
+"帳"=>"帐",
+"帶"=>"带",
+"幀"=>"帧",
+"幃"=>"帏",
+"幗"=>"帼",
+"幘"=>"帻",
+"幟"=>"帜",
+"幣"=>"币",
+"幫"=>"帮",
+"幬"=>"帱",
+"幹"=>"干",
+"幺"=>"么",
+"幾"=>"几",
+"广"=>"广",
+"庫"=>"库",
+"廁"=>"厕",
+"廂"=>"厢",
+"廄"=>"厩",
+"廈"=>"厦",
+"廚"=>"厨",
+"廝"=>"厮",
+"廟"=>"庙",
+"廠"=>"厂",
+"廡"=>"庑",
+"廢"=>"废",
+"廣"=>"广",
+"廩"=>"廪",
+"廬"=>"庐",
+"廳"=>"厅",
+"弒"=>"弑",
+"弳"=>"弪",
+"張"=>"张",
+"強"=>"强",
+"彆"=>"别",
+"彈"=>"弹",
+"彌"=>"弥",
+"彎"=>"弯",
+"彙"=>"汇",
+"彞"=>"彝",
+"彥"=>"彦",
+"征"=>"征",
+"後"=>"后",
+"徑"=>"径",
+"從"=>"从",
+"徠"=>"徕",
+"復"=>"复",
+"徵"=>"征",
+"徹"=>"彻",
+"恆"=>"恒",
+"恥"=>"耻",
+"悅"=>"悦",
+"悞"=>"悮",
+"悵"=>"怅",
+"悶"=>"闷",
+"惡"=>"恶",
+"惱"=>"恼",
+"惲"=>"恽",
+"惻"=>"恻",
+"愛"=>"爱",
+"愜"=>"惬",
+"愨"=>"悫",
+"愴"=>"怆",
+"愷"=>"恺",
+"愾"=>"忾",
+"愿"=>"愿",
+"慄"=>"栗",
+"態"=>"态",
+"慍"=>"愠",
+"慘"=>"惨",
+"慚"=>"惭",
+"慟"=>"恸",
+"慣"=>"惯",
+"慤"=>"悫",
+"慪"=>"怄",
+"慫"=>"怂",
+"慮"=>"虑",
+"慳"=>"悭",
+"慶"=>"庆",
+"憂"=>"忧",
+"憊"=>"惫",
+"憐"=>"怜",
+"憑"=>"凭",
+"憒"=>"愦",
+"憚"=>"惮",
+"憤"=>"愤",
+"憫"=>"悯",
+"憮"=>"怃",
+"憲"=>"宪",
+"憶"=>"忆",
+"懇"=>"恳",
+"應"=>"应",
+"懌"=>"怿",
+"懍"=>"懔",
+"懞"=>"蒙",
+"懟"=>"怼",
+"懣"=>"懑",
+"懨"=>"恹",
+"懲"=>"惩",
+"懶"=>"懒",
+"懷"=>"怀",
+"懸"=>"悬",
+"懺"=>"忏",
+"懼"=>"惧",
+"懾"=>"慑",
+"戀"=>"恋",
+"戇"=>"戆",
+"戔"=>"戋",
+"戧"=>"戗",
+"戩"=>"戬",
+"戰"=>"战",
+"戱"=>"戯",
+"戲"=>"戏",
+"戶"=>"户",
+"担"=>"担",
+"拋"=>"抛",
+"拾"=>"十",
+"挩"=>"捝",
+"挾"=>"挟",
+"捨"=>"舍",
+"捫"=>"扪",
+"据"=>"据",
+"掃"=>"扫",
+"掄"=>"抡",
+"掗"=>"挜",
+"掙"=>"挣",
+"掛"=>"挂",
+"採"=>"采",
+"揀"=>"拣",
+"揚"=>"扬",
+"換"=>"换",
+"揮"=>"挥",
+"損"=>"损",
+"搖"=>"摇",
+"搗"=>"捣",
+"搵"=>"揾",
+"搶"=>"抢",
+"摑"=>"掴",
+"摜"=>"掼",
+"摟"=>"搂",
+"摯"=>"挚",
+"摳"=>"抠",
+"摶"=>"抟",
+"摺"=>"折",
+"摻"=>"掺",
+"撈"=>"捞",
+"撏"=>"挦",
+"撐"=>"撑",
+"撓"=>"挠",
+"撝"=>"㧑",
+"撟"=>"挢",
+"撣"=>"掸",
+"撥"=>"拨",
+"撫"=>"抚",
+"撲"=>"扑",
+"撳"=>"揿",
+"撻"=>"挞",
+"撾"=>"挝",
+"撿"=>"捡",
+"擁"=>"拥",
+"擄"=>"掳",
+"擇"=>"择",
+"擊"=>"击",
+"擋"=>"挡",
+"擓"=>"㧟",
+"擔"=>"担",
+"據"=>"据",
+"擠"=>"挤",
+"擬"=>"拟",
+"擯"=>"摈",
+"擰"=>"拧",
+"擱"=>"搁",
+"擲"=>"掷",
+"擴"=>"扩",
+"擷"=>"撷",
+"擺"=>"摆",
+"擻"=>"擞",
+"擼"=>"撸",
+"擾"=>"扰",
+"攄"=>"摅",
+"攆"=>"撵",
+"攏"=>"拢",
+"攔"=>"拦",
+"攖"=>"撄",
+"攙"=>"搀",
+"攛"=>"撺",
+"攜"=>"携",
+"攝"=>"摄",
+"攢"=>"攒",
+"攣"=>"挛",
+"攤"=>"摊",
+"攪"=>"搅",
+"攬"=>"揽",
+"敗"=>"败",
+"敘"=>"叙",
+"敵"=>"敌",
+"數"=>"数",
+"斂"=>"敛",
+"斃"=>"毙",
+"斕"=>"斓",
+"斗"=>"斗",
+"斬"=>"斩",
+"斷"=>"断",
+"於"=>"于",
+"時"=>"时",
+"晉"=>"晋",
+"晝"=>"昼",
+"暈"=>"晕",
+"暉"=>"晖",
+"暘"=>"旸",
+"暢"=>"畅",
+"暫"=>"暂",
+"曄"=>"晔",
+"曆"=>"历",
+"曇"=>"昙",
+"曉"=>"晓",
+"曏"=>"向",
+"曖"=>"暧",
+"曠"=>"旷",
+"曨"=>"昽",
+"曬"=>"晒",
+"書"=>"书",
+"會"=>"会",
+"朧"=>"胧",
+"朮"=>"术",
+"术"=>"术",
+"朴"=>"朴",
+"東"=>"东",
+"杴"=>"锨",
+"极"=>"极",
+"柜"=>"柜",
+"柵"=>"栅",
+"桿"=>"杆",
+"梔"=>"栀",
+"梘"=>"枧",
+"條"=>"条",
+"梟"=>"枭",
+"梲"=>"棁",
+"棄"=>"弃",
+"棖"=>"枨",
+"棗"=>"枣",
+"棟"=>"栋",
+"棧"=>"栈",
+"棲"=>"栖",
+"棶"=>"梾",
+"椏"=>"桠",
+"楊"=>"杨",
+"楓"=>"枫",
+"楨"=>"桢",
+"業"=>"业",
+"極"=>"极",
+"榪"=>"杩",
+"榮"=>"荣",
+"榲"=>"榅",
+"榿"=>"桤",
+"構"=>"构",
+"槍"=>"枪",
+"槤"=>"梿",
+"槧"=>"椠",
+"槨"=>"椁",
+"槳"=>"桨",
+"樁"=>"桩",
+"樂"=>"乐",
+"樅"=>"枞",
+"樓"=>"楼",
+"標"=>"标",
+"樞"=>"枢",
+"樣"=>"样",
+"樸"=>"朴",
+"樹"=>"树",
+"樺"=>"桦",
+"橈"=>"桡",
+"橋"=>"桥",
+"機"=>"机",
+"橢"=>"椭",
+"橫"=>"横",
+"檁"=>"檩",
+"檉"=>"柽",
+"檔"=>"档",
+"檜"=>"桧",
+"檟"=>"槚",
+"檢"=>"检",
+"檣"=>"樯",
+"檮"=>"梼",
+"檯"=>"台",
+"檳"=>"槟",
+"檸"=>"柠",
+"檻"=>"槛",
+"櫃"=>"柜",
+"櫓"=>"橹",
+"櫚"=>"榈",
+"櫛"=>"栉",
+"櫝"=>"椟",
+"櫞"=>"橼",
+"櫟"=>"栎",
+"櫥"=>"橱",
+"櫧"=>"槠",
+"櫨"=>"栌",
+"櫪"=>"枥",
+"櫫"=>"橥",
+"櫬"=>"榇",
+"櫱"=>"蘖",
+"櫳"=>"栊",
+"櫸"=>"榉",
+"櫻"=>"樱",
+"欄"=>"栏",
+"權"=>"权",
+"欏"=>"椤",
+"欒"=>"栾",
+"欖"=>"榄",
+"欞"=>"棂",
+"欽"=>"钦",
+"歐"=>"欧",
+"歟"=>"欤",
+"歡"=>"欢",
+"歲"=>"岁",
+"歷"=>"历",
+"歸"=>"归",
+"歿"=>"殁",
+"殘"=>"残",
+"殞"=>"殒",
+"殤"=>"殇",
+"殨"=>"㱮",
+"殫"=>"殚",
+"殮"=>"殓",
+"殯"=>"殡",
+"殲"=>"歼",
+"殺"=>"杀",
+"殻"=>"壳",
+"殼"=>"壳",
+"毀"=>"毁",
+"毆"=>"殴",
+"毿"=>"毵",
+"氂"=>"牦",
+"氈"=>"毡",
+"氌"=>"氇",
+"氣"=>"气",
+"氫"=>"氢",
+"氬"=>"氩",
+"氳"=>"氲",
+"汙"=>"污",
+"決"=>"决",
+"沒"=>"没",
+"沖"=>"冲",
+"況"=>"况",
+"洶"=>"汹",
+"浹"=>"浃",
+"涂"=>"涂",
+"涇"=>"泾",
+"涼"=>"凉",
+"淀"=>"淀",
+"淒"=>"凄",
+"淚"=>"泪",
+"淥"=>"渌",
+"淨"=>"净",
+"淩"=>"凌",
+"淪"=>"沦",
+"淵"=>"渊",
+"淶"=>"涞",
+"淺"=>"浅",
+"渙"=>"涣",
+"減"=>"减",
+"渦"=>"涡",
+"測"=>"测",
+"渾"=>"浑",
+"湊"=>"凑",
+"湞"=>"浈",
+"湯"=>"汤",
+"溈"=>"沩",
+"準"=>"准",
+"溝"=>"沟",
+"溫"=>"温",
+"滄"=>"沧",
+"滅"=>"灭",
+"滌"=>"涤",
+"滎"=>"荥",
+"滬"=>"沪",
+"滯"=>"滞",
+"滲"=>"渗",
+"滷"=>"卤",
+"滸"=>"浒",
+"滻"=>"浐",
+"滾"=>"滚",
+"滿"=>"满",
+"漁"=>"渔",
+"漚"=>"沤",
+"漢"=>"汉",
+"漣"=>"涟",
+"漬"=>"渍",
+"漲"=>"涨",
+"漵"=>"溆",
+"漸"=>"渐",
+"漿"=>"浆",
+"潁"=>"颍",
+"潑"=>"泼",
+"潔"=>"洁",
+"潙"=>"沩",
+"潛"=>"潜",
+"潤"=>"润",
+"潯"=>"浔",
+"潰"=>"溃",
+"潷"=>"滗",
+"潿"=>"涠",
+"澀"=>"涩",
+"澆"=>"浇",
+"澇"=>"涝",
+"澐"=>"沄",
+"澗"=>"涧",
+"澠"=>"渑",
+"澤"=>"泽",
+"澦"=>"滪",
+"澩"=>"泶",
+"澮"=>"浍",
+"澱"=>"淀",
+"濁"=>"浊",
+"濃"=>"浓",
+"濕"=>"湿",
+"濘"=>"泞",
+"濛"=>"蒙",
+"濟"=>"济",
+"濤"=>"涛",
+"濫"=>"滥",
+"濰"=>"潍",
+"濱"=>"滨",
+"濺"=>"溅",
+"濼"=>"泺",
+"濾"=>"滤",
+"瀅"=>"滢",
+"瀆"=>"渎",
+"瀉"=>"泻",
+"瀋"=>"沈",
+"瀏"=>"浏",
+"瀕"=>"濒",
+"瀘"=>"泸",
+"瀝"=>"沥",
+"瀟"=>"潇",
+"瀠"=>"潆",
+"瀦"=>"潴",
+"瀧"=>"泷",
+"瀨"=>"濑",
+"瀰"=>"弥",
+"瀲"=>"潋",
+"瀾"=>"澜",
+"灃"=>"沣",
+"灄"=>"滠",
+"灑"=>"洒",
+"灕"=>"漓",
+"灘"=>"滩",
+"灝"=>"灏",
+"灠"=>"漤",
+"灣"=>"湾",
+"灤"=>"滦",
+"灧"=>"滟",
+"災"=>"灾",
+"為"=>"为",
+"烏"=>"乌",
+"烴"=>"烃",
+"無"=>"无",
+"煉"=>"炼",
+"煒"=>"炜",
+"煙"=>"烟",
+"煢"=>"茕",
+"煥"=>"焕",
+"煩"=>"烦",
+"煬"=>"炀",
+"熅"=>"煴",
+"熒"=>"荧",
+"熗"=>"炝",
+"熱"=>"热",
+"熲"=>"颎",
+"熾"=>"炽",
+"燁"=>"烨",
+"燈"=>"灯",
+"燉"=>"炖",
+"燒"=>"烧",
+"燙"=>"烫",
+"燜"=>"焖",
+"營"=>"营",
+"燦"=>"灿",
+"燭"=>"烛",
+"燴"=>"烩",
+"燼"=>"烬",
+"燾"=>"焘",
+"爍"=>"烁",
+"爐"=>"炉",
+"爛"=>"烂",
+"爭"=>"争",
+"爲"=>"为",
+"爺"=>"爷",
+"爾"=>"尔",
+"牆"=>"墙",
+"牘"=>"牍",
+"牽"=>"牵",
+"犖"=>"荦",
+"犢"=>"犊",
+"犧"=>"牺",
+"狀"=>"状",
+"狹"=>"狭",
+"狽"=>"狈",
+"猙"=>"狰",
+"猶"=>"犹",
+"猻"=>"狲",
+"獁"=>"犸",
+"獄"=>"狱",
+"獅"=>"狮",
+"獎"=>"奖",
+"獨"=>"独",
+"獪"=>"狯",
+"獫"=>"猃",
+"獮"=>"狝",
+"獰"=>"狞",
+"獲"=>"获",
+"獵"=>"猎",
+"獷"=>"犷",
+"獸"=>"兽",
+"獺"=>"獭",
+"獻"=>"献",
+"獼"=>"猕",
+"玀"=>"猡",
+"現"=>"现",
+"琺"=>"珐",
+"琿"=>"珲",
+"瑋"=>"玮",
+"瑒"=>"玚",
+"瑣"=>"琐",
+"瑤"=>"瑶",
+"瑩"=>"莹",
+"瑪"=>"玛",
+"瑲"=>"玱",
+"璉"=>"琏",
+"璣"=>"玑",
+"璦"=>"瑷",
+"璫"=>"珰",
+"環"=>"环",
+"璽"=>"玺",
+"瓊"=>"琼",
+"瓏"=>"珑",
+"瓔"=>"璎",
+"瓚"=>"瓒",
+"甌"=>"瓯",
+"產"=>"产",
+"産"=>"产",
+"畝"=>"亩",
+"畢"=>"毕",
+"異"=>"异",
+"畵"=>"画",
+"當"=>"当",
+"疇"=>"畴",
+"疊"=>"叠",
+"痙"=>"痉",
+"痾"=>"疴",
+"瘂"=>"痖",
+"瘋"=>"疯",
+"瘍"=>"疡",
+"瘓"=>"痪",
+"瘞"=>"瘗",
+"瘡"=>"疮",
+"瘧"=>"疟",
+"瘮"=>"瘆",
+"瘲"=>"疭",
+"瘺"=>"瘘",
+"瘻"=>"瘘",
+"療"=>"疗",
+"癆"=>"痨",
+"癇"=>"痫",
+"癉"=>"瘅",
+"癘"=>"疠",
+"癟"=>"瘪",
+"癢"=>"痒",
+"癤"=>"疖",
+"癥"=>"症",
+"癧"=>"疬",
+"癩"=>"癞",
+"癬"=>"癣",
+"癭"=>"瘿",
+"癮"=>"瘾",
+"癰"=>"痈",
+"癱"=>"瘫",
+"癲"=>"癫",
+"發"=>"发",
+"皚"=>"皑",
+"皰"=>"疱",
+"皸"=>"皲",
+"皺"=>"皱",
+"盃"=>"杯",
+"盜"=>"盗",
+"盞"=>"盏",
+"盡"=>"尽",
+"監"=>"监",
+"盤"=>"盘",
+"盧"=>"卢",
+"眥"=>"眦",
+"眾"=>"众",
+"睏"=>"困",
+"睜"=>"睁",
+"睞"=>"睐",
+"瞘"=>"眍",
+"瞜"=>"䁖",
+"瞞"=>"瞒",
+"瞭"=>"了",
+"瞶"=>"瞆",
+"瞼"=>"睑",
+"矇"=>"蒙",
+"矓"=>"眬",
+"矚"=>"瞩",
+"矯"=>"矫",
+"硃"=>"朱",
+"硜"=>"硁",
+"硤"=>"硖",
+"硨"=>"砗",
+"确"=>"确",
+"硯"=>"砚",
+"碩"=>"硕",
+"碭"=>"砀",
+"碸"=>"砜",
+"確"=>"确",
+"碼"=>"码",
+"磑"=>"硙",
+"磚"=>"砖",
+"磣"=>"碜",
+"磧"=>"碛",
+"磯"=>"矶",
+"磽"=>"硗",
+"礆"=>"硷",
+"礎"=>"础",
+"礙"=>"碍",
+"礦"=>"矿",
+"礪"=>"砺",
+"礫"=>"砾",
+"礬"=>"矾",
+"礱"=>"砻",
+"祿"=>"禄",
+"禍"=>"祸",
+"禎"=>"祯",
+"禕"=>"祎",
+"禡"=>"祃",
+"禦"=>"御",
+"禪"=>"禅",
+"禮"=>"礼",
+"禰"=>"祢",
+"禱"=>"祷",
+"禿"=>"秃",
+"秈"=>"籼",
+"种"=>"种",
+"稅"=>"税",
+"稈"=>"秆",
+"稟"=>"禀",
+"種"=>"种",
+"稱"=>"称",
+"穀"=>"谷",
+"穌"=>"稣",
+"積"=>"积",
+"穎"=>"颖",
+"穠"=>"秾",
+"穡"=>"穑",
+"穢"=>"秽",
+"穩"=>"稳",
+"穫"=>"获",
+"穭"=>"稆",
+"窩"=>"窝",
+"窪"=>"洼",
+"窮"=>"穷",
+"窯"=>"窑",
+"窵"=>"窎",
+"窶"=>"窭",
+"窺"=>"窥",
+"竄"=>"窜",
+"竅"=>"窍",
+"竇"=>"窦",
+"竈"=>"灶",
+"竊"=>"窃",
+"竪"=>"竖",
+"競"=>"竞",
+"筆"=>"笔",
+"筍"=>"笋",
+"筑"=>"筑",
+"筧"=>"笕",
+"筴"=>"䇲",
+"箋"=>"笺",
+"箏"=>"筝",
+"節"=>"节",
+"範"=>"范",
+"築"=>"筑",
+"篋"=>"箧",
+"篔"=>"筼",
+"篤"=>"笃",
+"篩"=>"筛",
+"篳"=>"筚",
+"簀"=>"箦",
+"簍"=>"篓",
+"簞"=>"箪",
+"簡"=>"简",
+"簣"=>"篑",
+"簫"=>"箫",
+"簹"=>"筜",
+"簽"=>"签",
+"簾"=>"帘",
+"籃"=>"篮",
+"籌"=>"筹",
+"籖"=>"签",
+"籙"=>"箓",
+"籜"=>"箨",
+"籟"=>"籁",
+"籠"=>"笼",
+"籩"=>"笾",
+"籪"=>"簖",
+"籬"=>"篱",
+"籮"=>"箩",
+"籲"=>"吁",
+"粵"=>"粤",
+"糝"=>"糁",
+"糞"=>"粪",
+"糧"=>"粮",
+"糰"=>"团",
+"糲"=>"粝",
+"糴"=>"籴",
+"糶"=>"粜",
+"糹"=>"纟",
+"糾"=>"纠",
+"紀"=>"纪",
+"紂"=>"纣",
+"約"=>"约",
+"紅"=>"红",
+"紆"=>"纡",
+"紇"=>"纥",
+"紈"=>"纨",
+"紉"=>"纫",
+"紋"=>"纹",
+"納"=>"纳",
+"紐"=>"纽",
+"紓"=>"纾",
+"純"=>"纯",
+"紕"=>"纰",
+"紖"=>"纼",
+"紗"=>"纱",
+"紘"=>"纮",
+"紙"=>"纸",
+"級"=>"级",
+"紛"=>"纷",
+"紜"=>"纭",
+"紝"=>"纴",
+"紡"=>"纺",
+"紬"=>"䌷",
+"細"=>"细",
+"紱"=>"绂",
+"紲"=>"绁",
+"紳"=>"绅",
+"紵"=>"纻",
+"紹"=>"绍",
+"紺"=>"绀",
+"紼"=>"绋",
+"紿"=>"绐",
+"絀"=>"绌",
+"終"=>"终",
+"組"=>"组",
+"絅"=>"䌹",
+"絆"=>"绊",
+"絎"=>"绗",
+"結"=>"结",
+"絕"=>"绝",
+"絛"=>"绦",
+"絝"=>"绔",
+"絞"=>"绞",
+"絡"=>"络",
+"絢"=>"绚",
+"給"=>"给",
+"絨"=>"绒",
+"絰"=>"绖",
+"統"=>"统",
+"絲"=>"丝",
+"絳"=>"绛",
+"絶"=>"绝",
+"絹"=>"绢",
+"綁"=>"绑",
+"綃"=>"绡",
+"綆"=>"绠",
+"綈"=>"绨",
+"綉"=>"绣",
+"綌"=>"绤",
+"綏"=>"绥",
+"經"=>"经",
+"綜"=>"综",
+"綞"=>"缍",
+"綠"=>"绿",
+"綢"=>"绸",
+"綣"=>"绻",
+"綫"=>"线",
+"綬"=>"绶",
+"維"=>"维",
+"綯"=>"绹",
+"綰"=>"绾",
+"綱"=>"纲",
+"網"=>"网",
+"綳"=>"绷",
+"綴"=>"缀",
+"綸"=>"纶",
+"綹"=>"绺",
+"綺"=>"绮",
+"綻"=>"绽",
+"綽"=>"绰",
+"綾"=>"绫",
+"綿"=>"绵",
+"緄"=>"绲",
+"緇"=>"缁",
+"緊"=>"紧",
+"緋"=>"绯",
+"緑"=>"绿",
+"緒"=>"绪",
+"緓"=>"绬",
+"緔"=>"绱",
+"緗"=>"缃",
+"緘"=>"缄",
+"緙"=>"缂",
+"線"=>"线",
+"緝"=>"缉",
+"緞"=>"缎",
+"締"=>"缔",
+"緡"=>"缗",
+"緣"=>"缘",
+"緦"=>"缌",
+"編"=>"编",
+"緩"=>"缓",
+"緬"=>"缅",
+"緯"=>"纬",
+"緱"=>"缑",
+"緲"=>"缈",
+"練"=>"练",
+"緶"=>"缏",
+"緹"=>"缇",
+"緻"=>"致",
+"縈"=>"萦",
+"縉"=>"缙",
+"縊"=>"缢",
+"縋"=>"缒",
+"縐"=>"绉",
+"縑"=>"缣",
+"縕"=>"缊",
+"縗"=>"缞",
+"縛"=>"缚",
+"縝"=>"缜",
+"縞"=>"缟",
+"縟"=>"缛",
+"縣"=>"县",
+"縧"=>"绦",
+"縫"=>"缝",
+"縭"=>"缡",
+"縮"=>"缩",
+"縱"=>"纵",
+"縲"=>"缧",
+"縳"=>"䌸",
+"縴"=>"纤",
+"縵"=>"缦",
+"縶"=>"絷",
+"縷"=>"缕",
+"縹"=>"缥",
+"總"=>"总",
+"績"=>"绩",
+"繃"=>"绷",
+"繅"=>"缫",
+"繆"=>"缪",
+"繒"=>"缯",
+"織"=>"织",
+"繕"=>"缮",
+"繚"=>"缭",
+"繞"=>"绕",
+"繡"=>"绣",
+"繢"=>"缋",
+"繩"=>"绳",
+"繪"=>"绘",
+"繫"=>"系",
+"繭"=>"茧",
+"繮"=>"缰",
+"繯"=>"缳",
+"繰"=>"缲",
+"繳"=>"缴",
+"繸"=>"䍁",
+"繹"=>"绎",
+"繼"=>"继",
+"繽"=>"缤",
+"繾"=>"缱",
+"纈"=>"缬",
+"纊"=>"纩",
+"續"=>"续",
+"纍"=>"累",
+"纏"=>"缠",
+"纓"=>"缨",
+"纔"=>"才",
+"纖"=>"纤",
+"纘"=>"缵",
+"纜"=>"缆",
+"缽"=>"钵",
+"罈"=>"坛",
+"罌"=>"罂",
+"罰"=>"罚",
+"罵"=>"骂",
+"罷"=>"罢",
+"羅"=>"罗",
+"羆"=>"罴",
+"羈"=>"羁",
+"羋"=>"芈",
+"羥"=>"羟",
+"義"=>"义",
+"習"=>"习",
+"翹"=>"翘",
+"耬"=>"耧",
+"耮"=>"耢",
+"聖"=>"圣",
+"聞"=>"闻",
+"聯"=>"联",
+"聰"=>"聪",
+"聲"=>"声",
+"聳"=>"耸",
+"聵"=>"聩",
+"聶"=>"聂",
+"職"=>"职",
+"聹"=>"聍",
+"聽"=>"听",
+"聾"=>"聋",
+"肅"=>"肃",
+"胜"=>"胜",
+"脅"=>"胁",
+"脈"=>"脉",
+"脛"=>"胫",
+"脫"=>"脱",
+"脹"=>"胀",
+"腊"=>"腊",
+"腎"=>"肾",
+"腖"=>"胨",
+"腡"=>"脶",
+"腦"=>"脑",
+"腫"=>"肿",
+"腳"=>"脚",
+"腸"=>"肠",
+"膃"=>"腽",
+"膚"=>"肤",
+"膠"=>"胶",
+"膩"=>"腻",
+"膽"=>"胆",
+"膾"=>"脍",
+"膿"=>"脓",
+"臉"=>"脸",
+"臍"=>"脐",
+"臏"=>"膑",
+"臘"=>"腊",
+"臚"=>"胪",
+"臟"=>"脏",
+"臠"=>"脔",
+"臢"=>"臜",
+"臥"=>"卧",
+"臨"=>"临",
+"臺"=>"台",
+"與"=>"与",
+"興"=>"兴",
+"舉"=>"举",
+"舊"=>"旧",
+"艙"=>"舱",
+"艤"=>"舣",
+"艦"=>"舰",
+"艫"=>"舻",
+"艱"=>"艰",
+"艷"=>"艳",
+"芻"=>"刍",
+"苎"=>"苧",
+"苧"=>"苎",
+"苹"=>"苹",
+"范"=>"范",
+"茲"=>"兹",
+"荊"=>"荆",
+"莊"=>"庄",
+"莖"=>"茎",
+"莢"=>"荚",
+"莧"=>"苋",
+"華"=>"华",
+"萇"=>"苌",
+"萊"=>"莱",
+"萬"=>"万",
+"萵"=>"莴",
+"葉"=>"叶",
+"葒"=>"荭",
+"著"=>"着",
+"葤"=>"荮",
+"葦"=>"苇",
+"葯"=>"药",
+"葷"=>"荤",
+"蒓"=>"莼",
+"蒔"=>"莳",
+"蒞"=>"莅",
+"蒼"=>"苍",
+"蓀"=>"荪",
+"蓋"=>"盖",
+"蓮"=>"莲",
+"蓯"=>"苁",
+"蓴"=>"莼",
+"蓽"=>"荜",
+"蔔"=>"卜",
+"蔞"=>"蒌",
+"蔣"=>"蒋",
+"蔥"=>"葱",
+"蔦"=>"茑",
+"蔭"=>"荫",
+"蕁"=>"荨",
+"蕆"=>"蒇",
+"蕎"=>"荞",
+"蕒"=>"荬",
+"蕓"=>"芸",
+"蕕"=>"莸",
+"蕘"=>"荛",
+"蕢"=>"蒉",
+"蕩"=>"荡",
+"蕪"=>"芜",
+"蕭"=>"萧",
+"蕷"=>"蓣",
+"薀"=>"蕰",
+"薈"=>"荟",
+"薊"=>"蓟",
+"薌"=>"芗",
+"薔"=>"蔷",
+"薘"=>"荙",
+"薟"=>"莶",
+"薦"=>"荐",
+"薩"=>"萨",
+"薴"=>"苧",
+"薺"=>"荠",
+"藉"=>"借",
+"藍"=>"蓝",
+"藎"=>"荩",
+"藝"=>"艺",
+"藥"=>"药",
+"藪"=>"薮",
+"藴"=>"蕴",
+"藶"=>"苈",
+"藹"=>"蔼",
+"藺"=>"蔺",
+"蘄"=>"蕲",
+"蘆"=>"芦",
+"蘇"=>"苏",
+"蘊"=>"蕴",
+"蘋"=>"苹",
+"蘚"=>"藓",
+"蘞"=>"蔹",
+"蘢"=>"茏",
+"蘭"=>"兰",
+"蘺"=>"蓠",
+"蘿"=>"萝",
+"虆"=>"蔂",
+"處"=>"处",
+"虛"=>"虚",
+"虜"=>"虏",
+"號"=>"号",
+"虧"=>"亏",
+"虫"=>"虫",
+"虯"=>"虬",
+"蛺"=>"蛱",
+"蛻"=>"蜕",
+"蜆"=>"蚬",
+"蜡"=>"蜡",
+"蝕"=>"蚀",
+"蝟"=>"猬",
+"蝦"=>"虾",
+"蝸"=>"蜗",
+"螄"=>"蛳",
+"螞"=>"蚂",
+"螢"=>"萤",
+"螻"=>"蝼",
+"螿"=>"螀",
+"蟄"=>"蛰",
+"蟈"=>"蝈",
+"蟎"=>"螨",
+"蟣"=>"虮",
+"蟬"=>"蝉",
+"蟯"=>"蛲",
+"蟲"=>"虫",
+"蟶"=>"蛏",
+"蟻"=>"蚁",
+"蠅"=>"蝇",
+"蠆"=>"虿",
+"蠐"=>"蛴",
+"蠑"=>"蝾",
+"蠟"=>"蜡",
+"蠣"=>"蛎",
+"蠨"=>"蟏",
+"蠱"=>"蛊",
+"蠶"=>"蚕",
+"蠻"=>"蛮",
+"衆"=>"众",
+"衊"=>"蔑",
+"術"=>"术",
+"衕"=>"同",
+"衚"=>"胡",
+"衛"=>"卫",
+"衝"=>"冲",
+"衹"=>"只",
+"袞"=>"衮",
+"裊"=>"袅",
+"裏"=>"里",
+"補"=>"补",
+"裝"=>"装",
+"裡"=>"里",
+"製"=>"制",
+"複"=>"复",
+"褌"=>"裈",
+"褘"=>"袆",
+"褲"=>"裤",
+"褳"=>"裢",
+"褸"=>"褛",
+"褻"=>"亵",
+"襇"=>"裥",
+"襏"=>"袯",
+"襖"=>"袄",
+"襝"=>"裣",
+"襠"=>"裆",
+"襤"=>"褴",
+"襪"=>"袜",
+"襯"=>"衬",
+"襲"=>"袭",
+"覆"=>"复",
+"見"=>"见",
+"覎"=>"觃",
+"規"=>"规",
+"覓"=>"觅",
+"視"=>"视",
+"覘"=>"觇",
+"覡"=>"觋",
+"覥"=>"觍",
+"覦"=>"觎",
+"親"=>"亲",
+"覬"=>"觊",
+"覯"=>"觏",
+"覲"=>"觐",
+"覷"=>"觑",
+"覺"=>"觉",
+"覽"=>"览",
+"覿"=>"觌",
+"觀"=>"观",
+"觴"=>"觞",
+"觶"=>"觯",
+"觸"=>"触",
+"訁"=>"讠",
+"訂"=>"订",
+"訃"=>"讣",
+"計"=>"计",
+"訊"=>"讯",
+"訌"=>"讧",
+"討"=>"讨",
+"訐"=>"讦",
+"訒"=>"讱",
+"訓"=>"训",
+"訕"=>"讪",
+"訖"=>"讫",
+"託"=>"讬",
+"記"=>"记",
+"訛"=>"讹",
+"訝"=>"讶",
+"訟"=>"讼",
+"訢"=>"䜣",
+"訣"=>"诀",
+"訥"=>"讷",
+"訩"=>"讻",
+"訪"=>"访",
+"設"=>"设",
+"許"=>"许",
+"訴"=>"诉",
+"訶"=>"诃",
+"診"=>"诊",
+"註"=>"注",
+"詁"=>"诂",
+"詆"=>"诋",
+"詎"=>"讵",
+"詐"=>"诈",
+"詒"=>"诒",
+"詔"=>"诏",
+"評"=>"评",
+"詖"=>"诐",
+"詗"=>"诇",
+"詘"=>"诎",
+"詛"=>"诅",
+"詞"=>"词",
+"詠"=>"咏",
+"詡"=>"诩",
+"詢"=>"询",
+"詣"=>"诣",
+"試"=>"试",
+"詩"=>"诗",
+"詫"=>"诧",
+"詬"=>"诟",
+"詭"=>"诡",
+"詮"=>"诠",
+"詰"=>"诘",
+"話"=>"话",
+"該"=>"该",
+"詳"=>"详",
+"詵"=>"诜",
+"詼"=>"诙",
+"詿"=>"诖",
+"誄"=>"诔",
+"誅"=>"诛",
+"誆"=>"诓",
+"誇"=>"夸",
+"誌"=>"志",
+"認"=>"认",
+"誑"=>"诳",
+"誒"=>"诶",
+"誕"=>"诞",
+"誘"=>"诱",
+"誚"=>"诮",
+"語"=>"语",
+"誠"=>"诚",
+"誡"=>"诫",
+"誣"=>"诬",
+"誤"=>"误",
+"誥"=>"诰",
+"誦"=>"诵",
+"誨"=>"诲",
+"說"=>"说",
+"説"=>"说",
+"誰"=>"谁",
+"課"=>"课",
+"誶"=>"谇",
+"誹"=>"诽",
+"誼"=>"谊",
+"誾"=>"訚",
+"調"=>"调",
+"諂"=>"谄",
+"諄"=>"谆",
+"談"=>"谈",
+"諉"=>"诿",
+"請"=>"请",
+"諍"=>"诤",
+"諏"=>"诹",
+"諑"=>"诼",
+"諒"=>"谅",
+"論"=>"论",
+"諗"=>"谂",
+"諛"=>"谀",
+"諜"=>"谍",
+"諝"=>"谞",
+"諞"=>"谝",
+"諢"=>"诨",
+"諤"=>"谔",
+"諦"=>"谛",
+"諧"=>"谐",
+"諫"=>"谏",
+"諭"=>"谕",
+"諮"=>"谘",
+"諱"=>"讳",
+"諳"=>"谙",
+"諶"=>"谌",
+"諷"=>"讽",
+"諸"=>"诸",
+"諺"=>"谚",
+"諼"=>"谖",
+"諾"=>"诺",
+"謀"=>"谋",
+"謁"=>"谒",
+"謂"=>"谓",
+"謄"=>"誊",
+"謅"=>"诌",
+"謊"=>"谎",
+"謎"=>"谜",
+"謐"=>"谧",
+"謔"=>"谑",
+"謖"=>"谡",
+"謗"=>"谤",
+"謙"=>"谦",
+"謚"=>"谥",
+"講"=>"讲",
+"謝"=>"谢",
+"謠"=>"谣",
+"謡"=>"谣",
+"謨"=>"谟",
+"謫"=>"谪",
+"謬"=>"谬",
+"謭"=>"谫",
+"謳"=>"讴",
+"謹"=>"谨",
+"謾"=>"谩",
+"證"=>"证",
+"譎"=>"谲",
+"譏"=>"讥",
+"譖"=>"谮",
+"識"=>"识",
+"譙"=>"谯",
+"譚"=>"谭",
+"譜"=>"谱",
+"譫"=>"谵",
+"譯"=>"译",
+"議"=>"议",
+"譴"=>"谴",
+"護"=>"护",
+"譸"=>"诪",
+"譽"=>"誉",
+"譾"=>"谫",
+"讀"=>"读",
+"變"=>"变",
+"讎"=>"仇",
+"讎"=>"雠",
+"讒"=>"谗",
+"讓"=>"让",
+"讕"=>"谰",
+"讖"=>"谶",
+"讜"=>"谠",
+"讞"=>"谳",
+"豈"=>"岂",
+"豎"=>"竖",
+"豐"=>"丰",
+"豬"=>"猪",
+"豶"=>"豮",
+"貓"=>"猫",
+"貝"=>"贝",
+"貞"=>"贞",
+"貟"=>"贠",
+"負"=>"负",
+"財"=>"财",
+"貢"=>"贡",
+"貧"=>"贫",
+"貨"=>"货",
+"販"=>"贩",
+"貪"=>"贪",
+"貫"=>"贯",
+"責"=>"责",
+"貯"=>"贮",
+"貰"=>"贳",
+"貲"=>"赀",
+"貳"=>"贰",
+"貴"=>"贵",
+"貶"=>"贬",
+"買"=>"买",
+"貸"=>"贷",
+"貺"=>"贶",
+"費"=>"费",
+"貼"=>"贴",
+"貽"=>"贻",
+"貿"=>"贸",
+"賀"=>"贺",
+"賁"=>"贲",
+"賂"=>"赂",
+"賃"=>"赁",
+"賄"=>"贿",
+"賅"=>"赅",
+"資"=>"资",
+"賈"=>"贾",
+"賊"=>"贼",
+"賑"=>"赈",
+"賒"=>"赊",
+"賓"=>"宾",
+"賕"=>"赇",
+"賙"=>"赒",
+"賚"=>"赉",
+"賜"=>"赐",
+"賞"=>"赏",
+"賠"=>"赔",
+"賡"=>"赓",
+"賢"=>"贤",
+"賣"=>"卖",
+"賤"=>"贱",
+"賦"=>"赋",
+"賧"=>"赕",
+"質"=>"质",
+"賫"=>"赍",
+"賬"=>"账",
+"賭"=>"赌",
+"賴"=>"赖",
+"賵"=>"赗",
+"賺"=>"赚",
+"賻"=>"赙",
+"購"=>"购",
+"賽"=>"赛",
+"賾"=>"赜",
+"贄"=>"贽",
+"贅"=>"赘",
+"贇"=>"赟",
+"贈"=>"赠",
+"贊"=>"赞",
+"贋"=>"赝",
+"贍"=>"赡",
+"贏"=>"赢",
+"贐"=>"赆",
+"贓"=>"赃",
+"贔"=>"赑",
+"贖"=>"赎",
+"贗"=>"赝",
+"贛"=>"赣",
+"贜"=>"赃",
+"赬"=>"赪",
+"趕"=>"赶",
+"趙"=>"赵",
+"趨"=>"趋",
+"趲"=>"趱",
+"跡"=>"迹",
+"踐"=>"践",
+"踴"=>"踊",
+"蹌"=>"跄",
+"蹕"=>"跸",
+"蹣"=>"蹒",
+"蹤"=>"踪",
+"蹺"=>"跷",
+"躂"=>"跶",
+"躉"=>"趸",
+"躊"=>"踌",
+"躋"=>"跻",
+"躍"=>"跃",
+"躑"=>"踯",
+"躒"=>"跞",
+"躓"=>"踬",
+"躕"=>"蹰",
+"躚"=>"跹",
+"躡"=>"蹑",
+"躥"=>"蹿",
+"躦"=>"躜",
+"躪"=>"躏",
+"軀"=>"躯",
+"車"=>"车",
+"軋"=>"轧",
+"軌"=>"轨",
+"軍"=>"军",
+"軑"=>"轪",
+"軒"=>"轩",
+"軔"=>"轫",
+"軛"=>"轭",
+"軟"=>"软",
+"軤"=>"轷",
+"軫"=>"轸",
+"軲"=>"轱",
+"軸"=>"轴",
+"軹"=>"轵",
+"軺"=>"轺",
+"軻"=>"轲",
+"軼"=>"轶",
+"軾"=>"轼",
+"較"=>"较",
+"輅"=>"辂",
+"輇"=>"辁",
+"輈"=>"辀",
+"載"=>"载",
+"輊"=>"轾",
+"輒"=>"辄",
+"輓"=>"挽",
+"輔"=>"辅",
+"輕"=>"轻",
+"輛"=>"辆",
+"輜"=>"辎",
+"輝"=>"辉",
+"輞"=>"辋",
+"輟"=>"辍",
+"輥"=>"辊",
+"輦"=>"辇",
+"輩"=>"辈",
+"輪"=>"轮",
+"輬"=>"辌",
+"輯"=>"辑",
+"輳"=>"辏",
+"輸"=>"输",
+"輻"=>"辐",
+"輾"=>"辗",
+"輿"=>"舆",
+"轀"=>"辒",
+"轂"=>"毂",
+"轄"=>"辖",
+"轅"=>"辕",
+"轆"=>"辘",
+"轉"=>"转",
+"轍"=>"辙",
+"轎"=>"轿",
+"轔"=>"辚",
+"轟"=>"轰",
+"轡"=>"辔",
+"轢"=>"轹",
+"轤"=>"轳",
+"辟"=>"辟",
+"辦"=>"办",
+"辭"=>"辞",
+"辮"=>"辫",
+"辯"=>"辩",
+"農"=>"农",
+"迴"=>"回",
+"适"=>"适",
+"逕"=>"迳",
+"這"=>"这",
+"連"=>"连",
+"週"=>"周",
+"進"=>"进",
+"遊"=>"游",
+"運"=>"运",
+"過"=>"过",
+"達"=>"达",
+"違"=>"违",
+"遙"=>"遥",
+"遜"=>"逊",
+"遞"=>"递",
+"遠"=>"远",
+"適"=>"适",
+"遲"=>"迟",
+"遷"=>"迁",
+"選"=>"选",
+"遺"=>"遗",
+"遼"=>"辽",
+"邁"=>"迈",
+"還"=>"还",
+"邇"=>"迩",
+"邊"=>"边",
+"邏"=>"逻",
+"邐"=>"逦",
+"郁"=>"郁",
+"郟"=>"郏",
+"郵"=>"邮",
+"鄆"=>"郓",
+"鄉"=>"乡",
+"鄒"=>"邹",
+"鄔"=>"邬",
+"鄖"=>"郧",
+"鄧"=>"邓",
+"鄭"=>"郑",
+"鄰"=>"邻",
+"鄲"=>"郸",
+"鄴"=>"邺",
+"鄶"=>"郐",
+"鄺"=>"邝",
+"酇"=>"酂",
+"酈"=>"郦",
+"醖"=>"酝",
+"醜"=>"丑",
+"醞"=>"酝",
+"醫"=>"医",
+"醬"=>"酱",
+"醱"=>"酦",
+"釀"=>"酿",
+"釁"=>"衅",
+"釃"=>"酾",
+"釅"=>"酽",
+"采"=>"采",
+"釋"=>"释",
+"釐"=>"厘",
+"釒"=>"钅",
+"釓"=>"钆",
+"釔"=>"钇",
+"釕"=>"钌",
+"釗"=>"钊",
+"釘"=>"钉",
+"釙"=>"钋",
+"針"=>"针",
+"釣"=>"钓",
+"釤"=>"钐",
+"釧"=>"钏",
+"釩"=>"钒",
+"釵"=>"钗",
+"釷"=>"钍",
+"釹"=>"钕",
+"釺"=>"钎",
+"鈀"=>"钯",
+"鈁"=>"钫",
+"鈃"=>"钘",
+"鈄"=>"钭",
+"鈈"=>"钚",
+"鈉"=>"钠",
+"鈍"=>"钝",
+"鈎"=>"钩",
+"鈐"=>"钤",
+"鈑"=>"钣",
+"鈒"=>"钑",
+"鈔"=>"钞",
+"鈕"=>"钮",
+"鈞"=>"钧",
+"鈣"=>"钙",
+"鈥"=>"钬",
+"鈦"=>"钛",
+"鈧"=>"钪",
+"鈮"=>"铌",
+"鈰"=>"铈",
+"鈳"=>"钶",
+"鈴"=>"铃",
+"鈷"=>"钴",
+"鈸"=>"钹",
+"鈹"=>"铍",
+"鈺"=>"钰",
+"鈽"=>"钸",
+"鈾"=>"铀",
+"鈿"=>"钿",
+"鉀"=>"钾",
+"鉅"=>"钜",
+"鉈"=>"铊",
+"鉉"=>"铉",
+"鉋"=>"铇",
+"鉍"=>"铋",
+"鉑"=>"铂",
+"鉕"=>"钷",
+"鉗"=>"钳",
+"鉚"=>"铆",
+"鉛"=>"铅",
+"鉞"=>"钺",
+"鉢"=>"钵",
+"鉤"=>"钩",
+"鉦"=>"钲",
+"鉬"=>"钼",
+"鉭"=>"钽",
+"鉶"=>"铏",
+"鉸"=>"铰",
+"鉺"=>"铒",
+"鉻"=>"铬",
+"鉿"=>"铪",
+"銀"=>"银",
+"銃"=>"铳",
+"銅"=>"铜",
+"銍"=>"铚",
+"銑"=>"铣",
+"銓"=>"铨",
+"銖"=>"铢",
+"銘"=>"铭",
+"銚"=>"铫",
+"銛"=>"铦",
+"銜"=>"衔",
+"銠"=>"铑",
+"銣"=>"铷",
+"銥"=>"铱",
+"銦"=>"铟",
+"銨"=>"铵",
+"銩"=>"铥",
+"銪"=>"铕",
+"銫"=>"铯",
+"銬"=>"铐",
+"銱"=>"铞",
+"銳"=>"锐",
+"銷"=>"销",
+"銹"=>"锈",
+"銻"=>"锑",
+"銼"=>"锉",
+"鋁"=>"铝",
+"鋃"=>"锒",
+"鋅"=>"锌",
+"鋇"=>"钡",
+"鋌"=>"铤",
+"鋏"=>"铗",
+"鋒"=>"锋",
+"鋙"=>"铻",
+"鋝"=>"锊",
+"鋟"=>"锓",
+"鋣"=>"铘",
+"鋤"=>"锄",
+"鋥"=>"锃",
+"鋦"=>"锔",
+"鋨"=>"锇",
+"鋩"=>"铓",
+"鋪"=>"铺",
+"鋭"=>"锐",
+"鋮"=>"铖",
+"鋯"=>"锆",
+"鋰"=>"锂",
+"鋱"=>"铽",
+"鋶"=>"锍",
+"鋸"=>"锯",
+"鋼"=>"钢",
+"錁"=>"锞",
+"錄"=>"录",
+"錆"=>"锖",
+"錇"=>"锫",
+"錈"=>"锩",
+"錏"=>"铔",
+"錐"=>"锥",
+"錒"=>"锕",
+"錕"=>"锟",
+"錘"=>"锤",
+"錙"=>"锱",
+"錚"=>"铮",
+"錛"=>"锛",
+"錟"=>"锬",
+"錠"=>"锭",
+"錡"=>"锜",
+"錢"=>"钱",
+"錦"=>"锦",
+"錨"=>"锚",
+"錩"=>"锠",
+"錫"=>"锡",
+"錮"=>"锢",
+"錯"=>"错",
+"録"=>"录",
+"錳"=>"锰",
+"錶"=>"表",
+"錸"=>"铼",
+"鍀"=>"锝",
+"鍁"=>"锨",
+"鍃"=>"锪",
+"鍆"=>"钔",
+"鍇"=>"锴",
+"鍈"=>"锳",
+"鍋"=>"锅",
+"鍍"=>"镀",
+"鍔"=>"锷",
+"鍘"=>"铡",
+"鍚"=>"钖",
+"鍛"=>"锻",
+"鍠"=>"锽",
+"鍤"=>"锸",
+"鍥"=>"锲",
+"鍩"=>"锘",
+"鍬"=>"锹",
+"鍰"=>"锾",
+"鍵"=>"键",
+"鍶"=>"锶",
+"鍺"=>"锗",
+"鍾"=>"钟",
+"鎂"=>"镁",
+"鎄"=>"锿",
+"鎇"=>"镅",
+"鎊"=>"镑",
+"鎔"=>"镕",
+"鎖"=>"锁",
+"鎘"=>"镉",
+"鎛"=>"镈",
+"鎡"=>"镃",
+"鎢"=>"钨",
+"鎣"=>"蓥",
+"鎦"=>"镏",
+"鎧"=>"铠",
+"鎩"=>"铩",
+"鎪"=>"锼",
+"鎬"=>"镐",
+"鎮"=>"镇",
+"鎰"=>"镒",
+"鎲"=>"镋",
+"鎳"=>"镍",
+"鎵"=>"镓",
+"鎸"=>"镌",
+"鎿"=>"镎",
+"鏃"=>"镞",
+"鏇"=>"镟",
+"鏈"=>"链",
+"鏌"=>"镆",
+"鏍"=>"镙",
+"鏐"=>"镠",
+"鏑"=>"镝",
+"鏗"=>"铿",
+"鏘"=>"锵",
+"鏜"=>"镗",
+"鏝"=>"镘",
+"鏞"=>"镛",
+"鏟"=>"铲",
+"鏡"=>"镜",
+"鏢"=>"镖",
+"鏤"=>"镂",
+"鏨"=>"錾",
+"鏰"=>"镚",
+"鏵"=>"铧",
+"鏷"=>"镤",
+"鏹"=>"镪",
+"鏽"=>"锈",
+"鐃"=>"铙",
+"鐋"=>"铴",
+"鐐"=>"镣",
+"鐒"=>"铹",
+"鐓"=>"镦",
+"鐔"=>"镡",
+"鐘"=>"钟",
+"鐙"=>"镫",
+"鐝"=>"镢",
+"鐠"=>"镨",
+"鐦"=>"锎",
+"鐧"=>"锏",
+"鐨"=>"镄",
+"鐫"=>"镌",
+"鐮"=>"镰",
+"鐲"=>"镯",
+"鐳"=>"镭",
+"鐵"=>"铁",
+"鐶"=>"镮",
+"鐸"=>"铎",
+"鐺"=>"铛",
+"鐿"=>"镱",
+"鑄"=>"铸",
+"鑊"=>"镬",
+"鑌"=>"镔",
+"鑒"=>"鉴",
+"鑔"=>"镲",
+"鑕"=>"锧",
+"鑞"=>"镴",
+"鑠"=>"铄",
+"鑣"=>"镳",
+"鑥"=>"镥",
+"鑭"=>"镧",
+"鑰"=>"钥",
+"鑱"=>"镵",
+"鑲"=>"镶",
+"鑷"=>"镊",
+"鑹"=>"镩",
+"鑼"=>"锣",
+"鑽"=>"钻",
+"鑾"=>"銮",
+"鑿"=>"凿",
+"钁"=>"镢",
+"镟"=>"旋",
+"長"=>"长",
+"門"=>"门",
+"閂"=>"闩",
+"閃"=>"闪",
+"閆"=>"闫",
+"閈"=>"闬",
+"閉"=>"闭",
+"開"=>"开",
+"閌"=>"闶",
+"閎"=>"闳",
+"閏"=>"闰",
+"閑"=>"闲",
+"間"=>"间",
+"閔"=>"闵",
+"閘"=>"闸",
+"閡"=>"阂",
+"閣"=>"阁",
+"閤"=>"合",
+"閥"=>"阀",
+"閨"=>"闺",
+"閩"=>"闽",
+"閫"=>"阃",
+"閬"=>"阆",
+"閭"=>"闾",
+"閱"=>"阅",
+"閲"=>"阅",
+"閶"=>"阊",
+"閹"=>"阉",
+"閻"=>"阎",
+"閼"=>"阏",
+"閽"=>"阍",
+"閾"=>"阈",
+"閿"=>"阌",
+"闃"=>"阒",
+"闆"=>"板",
+"闈"=>"闱",
+"闊"=>"阔",
+"闋"=>"阕",
+"闌"=>"阑",
+"闍"=>"阇",
+"闐"=>"阗",
+"闒"=>"阘",
+"闓"=>"闿",
+"闔"=>"阖",
+"闕"=>"阙",
+"闖"=>"闯",
+"關"=>"关",
+"闞"=>"阚",
+"闠"=>"阓",
+"闡"=>"阐",
+"闤"=>"阛",
+"闥"=>"闼",
+"阪"=>"坂",
+"陘"=>"陉",
+"陝"=>"陕",
+"陣"=>"阵",
+"陰"=>"阴",
+"陳"=>"陈",
+"陸"=>"陆",
+"陽"=>"阳",
+"隉"=>"陧",
+"隊"=>"队",
+"階"=>"阶",
+"隕"=>"陨",
+"際"=>"际",
+"隨"=>"随",
+"險"=>"险",
+"隱"=>"隐",
+"隴"=>"陇",
+"隸"=>"隶",
+"隻"=>"只",
+"雋"=>"隽",
+"雖"=>"虽",
+"雙"=>"双",
+"雛"=>"雏",
+"雜"=>"杂",
+"雞"=>"鸡",
+"離"=>"离",
+"難"=>"难",
+"雲"=>"云",
+"電"=>"电",
+"霢"=>"霡",
+"霧"=>"雾",
+"霽"=>"霁",
+"靂"=>"雳",
+"靄"=>"霭",
+"靈"=>"灵",
+"靚"=>"靓",
+"靜"=>"静",
+"靦"=>"腼",
+"靨"=>"靥",
+"鞀"=>"鼗",
+"鞏"=>"巩",
+"鞝"=>"绱",
+"鞦"=>"秋",
+"鞽"=>"鞒",
+"韁"=>"缰",
+"韃"=>"鞑",
+"韆"=>"千",
+"韉"=>"鞯",
+"韋"=>"韦",
+"韌"=>"韧",
+"韍"=>"韨",
+"韓"=>"韩",
+"韙"=>"韪",
+"韜"=>"韬",
+"韞"=>"韫",
+"韻"=>"韵",
+"響"=>"响",
+"頁"=>"页",
+"頂"=>"顶",
+"頃"=>"顷",
+"項"=>"项",
+"順"=>"顺",
+"頇"=>"顸",
+"須"=>"须",
+"頊"=>"顼",
+"頌"=>"颂",
+"頎"=>"颀",
+"頏"=>"颃",
+"預"=>"预",
+"頑"=>"顽",
+"頒"=>"颁",
+"頓"=>"顿",
+"頗"=>"颇",
+"領"=>"领",
+"頜"=>"颌",
+"頡"=>"颉",
+"頤"=>"颐",
+"頦"=>"颏",
+"頭"=>"头",
+"頮"=>"颒",
+"頰"=>"颊",
+"頲"=>"颋",
+"頴"=>"颕",
+"頷"=>"颔",
+"頸"=>"颈",
+"頹"=>"颓",
+"頻"=>"频",
+"頽"=>"颓",
+"顆"=>"颗",
+"題"=>"题",
+"額"=>"额",
+"顎"=>"颚",
+"顏"=>"颜",
+"顒"=>"颙",
+"顓"=>"颛",
+"顔"=>"颜",
+"願"=>"愿",
+"顙"=>"颡",
+"顛"=>"颠",
+"類"=>"类",
+"顢"=>"颟",
+"顥"=>"颢",
+"顧"=>"顾",
+"顫"=>"颤",
+"顬"=>"颥",
+"顯"=>"显",
+"顰"=>"颦",
+"顱"=>"颅",
+"顳"=>"颞",
+"顴"=>"颧",
+"風"=>"风",
+"颭"=>"飐",
+"颮"=>"飑",
+"颯"=>"飒",
+"颱"=>"台",
+"颳"=>"刮",
+"颶"=>"飓",
+"颸"=>"飔",
+"颺"=>"飏",
+"颻"=>"飖",
+"颼"=>"飕",
+"飀"=>"飗",
+"飄"=>"飘",
+"飆"=>"飙",
+"飈"=>"飚",
+"飛"=>"飞",
+"飠"=>"饣",
+"飢"=>"饥",
+"飣"=>"饤",
+"飥"=>"饦",
+"飩"=>"饨",
+"飪"=>"饪",
+"飫"=>"饫",
+"飭"=>"饬",
+"飯"=>"饭",
+"飲"=>"饮",
+"飴"=>"饴",
+"飼"=>"饲",
+"飽"=>"饱",
+"飾"=>"饰",
+"飿"=>"饳",
+"餃"=>"饺",
+"餄"=>"饸",
+"餅"=>"饼",
+"餉"=>"饷",
+"養"=>"养",
+"餌"=>"饵",
+"餎"=>"饹",
+"餏"=>"饻",
+"餑"=>"饽",
+"餒"=>"馁",
+"餓"=>"饿",
+"餕"=>"馂",
+"餖"=>"饾",
+"餚"=>"肴",
+"餛"=>"馄",
+"餜"=>"馃",
+"餞"=>"饯",
+"餡"=>"馅",
+"館"=>"馆",
+"餱"=>"糇",
+"餳"=>"饧",
+"餶"=>"馉",
+"餷"=>"馇",
+"餺"=>"馎",
+"餼"=>"饩",
+"餾"=>"馏",
+"餿"=>"馊",
+"饁"=>"馌",
+"饃"=>"馍",
+"饅"=>"馒",
+"饈"=>"馐",
+"饉"=>"馑",
+"饊"=>"馓",
+"饋"=>"馈",
+"饌"=>"馔",
+"饑"=>"饥",
+"饒"=>"饶",
+"饗"=>"飨",
+"饜"=>"餍",
+"饞"=>"馋",
+"饢"=>"馕",
+"馬"=>"马",
+"馭"=>"驭",
+"馮"=>"冯",
+"馱"=>"驮",
+"馳"=>"驰",
+"馴"=>"驯",
+"馹"=>"驲",
+"駁"=>"驳",
+"駐"=>"驻",
+"駑"=>"驽",
+"駒"=>"驹",
+"駔"=>"驵",
+"駕"=>"驾",
+"駘"=>"骀",
+"駙"=>"驸",
+"駛"=>"驶",
+"駝"=>"驼",
+"駟"=>"驷",
+"駡"=>"骂",
+"駢"=>"骈",
+"駭"=>"骇",
+"駰"=>"骃",
+"駱"=>"骆",
+"駸"=>"骎",
+"駿"=>"骏",
+"騁"=>"骋",
+"騂"=>"骍",
+"騅"=>"骓",
+"騌"=>"骔",
+"騍"=>"骒",
+"騎"=>"骑",
+"騏"=>"骐",
+"騖"=>"骛",
+"騙"=>"骗",
+"騤"=>"骙",
+"騫"=>"骞",
+"騭"=>"骘",
+"騮"=>"骝",
+"騰"=>"腾",
+"騶"=>"驺",
+"騷"=>"骚",
+"騸"=>"骟",
+"騾"=>"骡",
+"驀"=>"蓦",
+"驁"=>"骜",
+"驂"=>"骖",
+"驃"=>"骠",
+"驄"=>"骢",
+"驅"=>"驱",
+"驊"=>"骅",
+"驌"=>"骕",
+"驍"=>"骁",
+"驏"=>"骣",
+"驕"=>"骄",
+"驗"=>"验",
+"驚"=>"惊",
+"驛"=>"驿",
+"驟"=>"骤",
+"驢"=>"驴",
+"驤"=>"骧",
+"驥"=>"骥",
+"驦"=>"骦",
+"驪"=>"骊",
+"驫"=>"骉",
+"骯"=>"肮",
+"髏"=>"髅",
+"髒"=>"脏",
+"體"=>"体",
+"髕"=>"髌",
+"髖"=>"髋",
+"髮"=>"发",
+"鬆"=>"松",
+"鬍"=>"胡",
+"鬚"=>"须",
+"鬢"=>"鬓",
+"鬥"=>"斗",
+"鬧"=>"闹",
+"鬩"=>"阋",
+"鬮"=>"阄",
+"鬱"=>"郁",
+"魎"=>"魉",
+"魘"=>"魇",
+"魚"=>"鱼",
+"魛"=>"鱽",
+"魢"=>"鱾",
+"魨"=>"鲀",
+"魯"=>"鲁",
+"魴"=>"鲂",
+"魷"=>"鱿",
+"魺"=>"鲄",
+"鮁"=>"鲅",
+"鮃"=>"鲆",
+"鮊"=>"鲌",
+"鮋"=>"鲉",
+"鮍"=>"鲏",
+"鮎"=>"鲇",
+"鮐"=>"鲐",
+"鮑"=>"鲍",
+"鮒"=>"鲋",
+"鮓"=>"鲊",
+"鮚"=>"鲒",
+"鮜"=>"鲘",
+"鮝"=>"鲞",
+"鮞"=>"鲕",
+"鮦"=>"鲖",
+"鮪"=>"鲔",
+"鮫"=>"鲛",
+"鮭"=>"鲑",
+"鮮"=>"鲜",
+"鮳"=>"鲓",
+"鮶"=>"鲪",
+"鮺"=>"鲝",
+"鯀"=>"鲧",
+"鯁"=>"鲠",
+"鯇"=>"鲩",
+"鯉"=>"鲤",
+"鯊"=>"鲨",
+"鯒"=>"鲬",
+"鯔"=>"鲻",
+"鯕"=>"鲯",
+"鯖"=>"鲭",
+"鯗"=>"鲞",
+"鯛"=>"鲷",
+"鯝"=>"鲴",
+"鯡"=>"鲱",
+"鯢"=>"鲵",
+"鯤"=>"鲲",
+"鯧"=>"鲳",
+"鯨"=>"鲸",
+"鯪"=>"鲮",
+"鯫"=>"鲰",
+"鯴"=>"鲺",
+"鯷"=>"鳀",
+"鯽"=>"鲫",
+"鯿"=>"鳊",
+"鰁"=>"鳈",
+"鰂"=>"鲗",
+"鰃"=>"鳂",
+"鰈"=>"鲽",
+"鰉"=>"鳇",
+"鰍"=>"鳅",
+"鰏"=>"鲾",
+"鰐"=>"鳄",
+"鰒"=>"鳆",
+"鰓"=>"鳃",
+"鰜"=>"鳒",
+"鰟"=>"鳑",
+"鰠"=>"鳋",
+"鰣"=>"鲥",
+"鰥"=>"鳏",
+"鰨"=>"鳎",
+"鰩"=>"鳐",
+"鰭"=>"鳍",
+"鰮"=>"鳁",
+"鰱"=>"鲢",
+"鰲"=>"鳌",
+"鰳"=>"鳓",
+"鰵"=>"鳘",
+"鰷"=>"鲦",
+"鰹"=>"鲣",
+"鰺"=>"鲹",
+"鰻"=>"鳗",
+"鰼"=>"鳛",
+"鰾"=>"鳔",
+"鱂"=>"鳉",
+"鱅"=>"鳙",
+"鱈"=>"鳕",
+"鱉"=>"鳖",
+"鱒"=>"鳟",
+"鱔"=>"鳝",
+"鱖"=>"鳜",
+"鱗"=>"鳞",
+"鱘"=>"鲟",
+"鱝"=>"鲼",
+"鱟"=>"鲎",
+"鱠"=>"鲙",
+"鱣"=>"鳣",
+"鱤"=>"鳡",
+"鱧"=>"鳢",
+"鱨"=>"鲿",
+"鱭"=>"鲚",
+"鱯"=>"鳠",
+"鱷"=>"鳄",
+"鱸"=>"鲈",
+"鱺"=>"鲡",
+"䰾"=>"鲃",
+"䲁"=>"鳚",
+"鳥"=>"鸟",
+"鳧"=>"凫",
+"鳩"=>"鸠",
+"鳬"=>"凫",
+"鳲"=>"鸤",
+"鳳"=>"凤",
+"鳴"=>"鸣",
+"鳶"=>"鸢",
+"鳾"=>"䴓",
+"鴆"=>"鸩",
+"鴇"=>"鸨",
+"鴉"=>"鸦",
+"鴒"=>"鸰",
+"鴕"=>"鸵",
+"鴛"=>"鸳",
+"鴝"=>"鸲",
+"鴞"=>"鸮",
+"鴟"=>"鸱",
+"鴣"=>"鸪",
+"鴦"=>"鸯",
+"鴨"=>"鸭",
+"鴯"=>"鸸",
+"鴰"=>"鸹",
+"鴴"=>"鸻",
+"鴷"=>"䴕",
+"鴻"=>"鸿",
+"鴿"=>"鸽",
+"鵁"=>"䴔",
+"鵂"=>"鸺",
+"鵃"=>"鸼",
+"鵐"=>"鹀",
+"鵑"=>"鹃",
+"鵒"=>"鹆",
+"鵓"=>"鹁",
+"鵜"=>"鹈",
+"鵝"=>"鹅",
+"鵠"=>"鹄",
+"鵡"=>"鹉",
+"鵪"=>"鹌",
+"鵬"=>"鹏",
+"鵮"=>"鹐",
+"鵯"=>"鹎",
+"鵲"=>"鹊",
+"鵷"=>"鹓",
+"鵾"=>"鹍",
+"鶄"=>"䴖",
+"鶇"=>"鸫",
+"鶉"=>"鹑",
+"鶊"=>"鹒",
+"鶓"=>"鹋",
+"鶖"=>"鹙",
+"鶘"=>"鹕",
+"鶚"=>"鹗",
+"鶡"=>"鹖",
+"鶥"=>"鹛",
+"鶩"=>"鹜",
+"鶪"=>"䴗",
+"鶬"=>"鸧",
+"鶯"=>"莺",
+"鶲"=>"鹟",
+"鶴"=>"鹤",
+"鶹"=>"鹠",
+"鶺"=>"鹡",
+"鶻"=>"鹘",
+"鶼"=>"鹣",
+"鶿"=>"鹚",
+"鷀"=>"鹚",
+"鷁"=>"鹢",
+"鷂"=>"鹞",
+"鷄"=>"鸡",
+"鷈"=>"䴘",
+"鷊"=>"鹝",
+"鷓"=>"鹧",
+"鷖"=>"鹥",
+"鷗"=>"鸥",
+"鷙"=>"鸷",
+"鷚"=>"鹨",
+"鷥"=>"鸶",
+"鷦"=>"鹪",
+"鷫"=>"鹔",
+"鷯"=>"鹩",
+"鷲"=>"鹫",
+"鷳"=>"鹇",
+"鷸"=>"鹬",
+"鷹"=>"鹰",
+"鷺"=>"鹭",
+"鷽"=>"鸴",
+"鷿"=>"䴙",
+"鸇"=>"鹯",
+"鸌"=>"鹱",
+"鸏"=>"鹲",
+"鸕"=>"鸬",
+"鸘"=>"鹴",
+"鸚"=>"鹦",
+"鸛"=>"鹳",
+"鸝"=>"鹂",
+"鸞"=>"鸾",
+"鹵"=>"卤",
+"鹹"=>"咸",
+"鹺"=>"鹾",
+"鹽"=>"盐",
+"麗"=>"丽",
+"麥"=>"麦",
+"麩"=>"麸",
+"麯"=>"曲",
+"麵"=>"面",
+"麼"=>"么",
+"麽"=>"么",
+"黃"=>"黄",
+"黌"=>"黉",
+"點"=>"点",
+"黨"=>"党",
+"黲"=>"黪",
+"黴"=>"霉",
+"黶"=>"黡",
+"黷"=>"黩",
+"黽"=>"黾",
+"黿"=>"鼋",
+"鼉"=>"鼍",
+"鼕"=>"冬",
+"鼴"=>"鼹",
+"齊"=>"齐",
+"齋"=>"斋",
+"齎"=>"赍",
+"齏"=>"齑",
+"齒"=>"齿",
+"齔"=>"龀",
+"齕"=>"龁",
+"齗"=>"龂",
+"齙"=>"龅",
+"齜"=>"龇",
+"齟"=>"龃",
+"齠"=>"龆",
+"齡"=>"龄",
+"齣"=>"出",
+"齦"=>"龈",
+"齪"=>"龊",
+"齬"=>"龉",
+"齲"=>"龋",
+"齶"=>"腭",
+"齷"=>"龌",
+"龍"=>"龙",
+"龎"=>"厐",
+"龐"=>"庞",
+"龔"=>"龚",
+"龕"=>"龛",
+"龜"=>"龟",
+
+"幾畫" =>    "几画",
+"賣畫" =>    "卖画",
+"滷鹼" =>    "卤碱",
+"原畫" =>    "原画",
+"口鹼" =>    "口碱",
+"古畫" =>    "古画",
+"名畫" =>    "名画",
+"奇畫" =>    "奇画",
+"如畫" =>    "如画",
+"么 " =>      "幺 ",
+"么廝" =>    "幺厮",
+"么爹" =>    "幺爹",
+"弱鹼" =>    "弱碱",
+"彩畫" =>    "彩画",
+"所畫" =>    "所画",
+"扉畫" =>    "扉画",
+"教畫" =>    "教画",
+"楊么" =>    "杨幺",
+"水鹼" =>    "水碱",
+"洋鹼" =>    "洋碱",
+"炭畫" =>    "炭画",
+"畫一" =>    "画一",
+"畫上" =>    "画上",
+"畫下" =>    "画下",
+"畫中" =>    "画中",
+"畫供" =>    "画供",
+"畫兒" =>    "画儿",
+"畫具" =>    "画具",
+"畫出" =>    "画出",
+"畫史" =>    "画史",
+"畫品" =>    "画品",
+"畫商" =>    "画商",
+"畫圈" =>    "画圈",
+"畫境" =>    "画境",
+"畫工" =>    "画工",
+"畫帖" =>    "画帖",
+"畫幅" =>    "画幅",
+"畫意" =>    "画意",
+"畫成" =>    "画成",
+"畫景" =>    "画景",
+"畫本" =>    "画本",
+"畫架" =>    "画架",
+"畫框" =>    "画框",
+"畫法" =>    "画法",
+"畫王" =>    "画王",
+"畫界" =>    "画界",
+"畫符" =>    "画符",
+"畫紙" =>    "画纸",
+"畫線" =>    "画线",
+"畫航" =>    "画航",
+"畫舫" =>    "画舫",
+"畫虎" =>    "画虎",
+"畫論" =>    "画论",
+"畫譜" =>    "画谱",
+"畫象" =>    "画象",
+"畫質" =>    "画质",
+"畫貼" =>    "画贴",
+"畫軸" =>    "画轴",
+"畫頁" =>    "画页",
+"鹽鹼" =>    "盐碱",
+"鹼 " =>      "碱 ",
+"鹼基" =>    "碱基",
+"鹼度" =>    "碱度",
+"鹼水" =>    "碱水",
+"鹼熔" =>    "碱熔",
+"磁畫" =>    "磁画",
+"策畫" =>    "策画",
+"組畫" =>    "组画",
+"絹畫" =>    "绢画",
+"老么" =>    "老幺",
+"耐鹼" =>    "耐碱",
+"肉鹼" =>    "肉碱",
+"膠畫" =>    "胶画",
+"茶鹼" =>    "茶碱",
+"西畫" =>    "西画",
+"貼畫" =>    "贴画",
+"返鹼" =>    "返碱",
+"那麼" =>    "那麽",
+"鍾鍛" =>    "锺锻",
+"鍛鍾" =>    "锻锺",
+"雕畫" =>    "雕画",
+"鯰 " =>      "鲶 ",
+"麼 " =>      "麽 ",
+"三聯畫" =>         "三联画",
+"中國畫" =>         "中国画",
+"書畫 " =>   "书画 ",
+"書畫社" =>         "书画社",
+"五筆畫" =>         "五笔画",
+"作畫 " =>   "作画 ",
+"入畫 " =>   "入画 ",
+"寫生畫" =>         "写生画",
+"刻畫 " =>   "刻画 ",
+"動畫 " =>   "动画 ",
+"勾畫 " =>   "勾画 ",
+"單色畫" =>         "单色画",
+"卡通畫" =>         "卡通画",
+"國畫 " =>   "国画 ",
+"圖畫 " =>   "图画 ",
+"壁畫 " =>   "壁画 ",
+"字畫 " =>   "字画 ",
+"宣傳畫" =>         "宣传画",
+"工筆畫" =>         "工笔画",
+"年畫 " =>   "年画 ",
+"幽默畫" =>         "幽默画",
+"指畫 " =>   "指画 ",
+"描畫 " =>   "描画 ",
+"插畫 " =>   "插画 ",
+"擘畫 " =>   "擘画 ",
+"春畫 " =>   "春画 ",
+"木刻畫" =>         "木刻画",
+"機械畫" =>         "机械画",
+"比畫 " =>   "比画 ",
+"毛筆畫" =>         "毛笔画",
+"水粉畫" =>         "水粉画",
+"油畫 " =>   "油画 ",
+"海景畫" =>         "海景画",
+"漫畫 " =>   "漫画 ",
+"點畫 " =>   "点画 ",
+"版畫 " =>   "版画 ",
+"畫  " =>     "画  ",
+"畫像 " =>   "画像 ",
+"畫冊 " =>   "画册 ",
+"畫刊 " =>   "画刊 ",
+"畫匠 " =>   "画匠 ",
+"畫捲 " =>   "画卷 ",
+"畫圖 " =>   "画图 ",
+"畫壇 " =>   "画坛 ",
+"畫室 " =>   "画室 ",
+"畫家 " =>   "画家 ",
+"畫屏 " =>   "画屏 ",
+"畫展 " =>   "画展 ",
+"畫布 " =>   "画布 ",
+"畫師 " =>   "画师 ",
+"畫廊 " =>   "画廊 ",
+"畫報 " =>   "画报 ",
+"畫押 " =>   "画押 ",
+"畫板 " =>   "画板 ",
+"畫片 " =>   "画片 ",
+"畫畫 " =>   "画画 ",
+"畫皮 " =>   "画皮 ",
+"畫眉鳥" =>         "画眉鸟",
+"畫稿 " =>   "画稿 ",
+"畫筆 " =>   "画笔 ",
+"畫院 " =>   "画院 ",
+"畫集 " =>   "画集 ",
+"畫面 " =>   "画面 ",
+"筆畫 " =>   "笔画 ",
+"細密畫" =>         "细密画",
+"繪畫 " =>   "绘画 ",
+"自畫像" =>         "自画像",
+"蠟筆畫" =>         "蜡笔画",
+"裸體畫" =>         "裸体画",
+"西洋畫" =>         "西洋画",
+"透視畫" =>         "透视画",
+"銅版畫" =>         "铜版画",
+"鍾  " =>     "锺  ",
+"靜物畫" =>         "静物画",
+"餘  " =>     "馀  ",
+"記憶體"=>"内存",
+"預設"=>"默认",
+"預設"=>"缺省",
+"串列"=>"串行",
+"乙太網"=>"以太网",
+"點陣圖"=>"位图",
+"常式"=>"例程",
+"通道"=>"信道",
+"游標"=>"光标",
+"光碟"=>"光盘",
+"光碟機"=>"光驱",
+"全形"=>"全角",
+"共用"=>"共享",
+"相容"=>"兼容",
+"首碼"=>"前缀",
+"尾碼"=>"后缀",
+"載入"=>"加载",
+"半形"=>"半角",
+"變數"=>"变量",
+"雜訊"=>"噪声",
+"因數"=>"因子",
+"線上"=>"在线",
+"離線"=>"脱机",
+"功能變數名稱"=>"域名",
+"音效卡"=>"声卡",
+"字型大小"=>"字号",
+"字型檔"=>"字库",
+"欄位"=>"字段",
+"字元"=>"字符",
+"存檔"=>"存盘",
+"定址"=>"寻址",
+"章節附註"=>"尾注",
+"非同步"=>"异步",
+"匯流排"=>"总线",
+"括弧"=>"括号",
+"介面"=>"接口",
+"控制項"=>"控件",
+"許可權"=>"权限",
+"碟片"=>"盘片",
+"矽片"=>"硅片",
+"矽谷"=>"硅谷",
+"硬碟"=>"硬盘",
+"磁碟"=>"磁盘",
+"磁軌"=>"磁道",
+"程式控制"=>"程控",
+"埠"=>"端口",
+"運算元"=>"算子",
+"演算法"=>"算法",
+"晶片"=>"芯片",
+"晶元"=>"芯片",
+"片語"=>"词组",
+"解碼"=>"译码",
+"軟碟機"=>"软驱",
+"快閃記憶體"=>"闪存",
+"滑鼠"=>"鼠标",
+"進位"=>"进制",
+"互動式"=>"交互式",
+"模擬"=>"仿真",
+"優先順序"=>"优先级",
+"感測"=>"传感",
+"攜帶型"=>"便携式",
+"資訊理論"=>"信息论",
+"迴圈"=>"循环",
+"防寫"=>"写保护",
+"分散式"=>"分布式",
+"解析度"=>"分辨率",
+"程式"=>"程序",
+"伺服器"=>"服务器",
+"等於"=>"等于",
+"區域網"=>"局域网",
+"上傳"=>"上载",
+"電腦"=>"计算机",
+"巨集"=>"宏",
+"掃瞄器"=>"扫瞄仪",
+"寬頻"=>"宽带",
+"視窗"=>"窗口",
+"資料庫"=>"数据库",
+"西曆"=>"公历",
+"乳酪"=>"奶酪",
+"鉅賈"=>"巨商",
+"手電筒"=>"手电",
+"萬曆"=>"万历",
+"永曆"=>"永历",
+"辭彙"=>"词汇",
+"保全"=>"保安",
+"慣用"=>"习用",
+"母音"=>"元音",
+"自由球"=>"任意球",
+"頭槌"=>"头球",
+"進球"=>"入球",
+"顆進球"=>"粒入球",
+"射門"=>"打门",
+"蓋火鍋"=>"火锅盖帽",
+"印表機"=>"打印机",
+"打印機"=>"打印机",
+"位元組"=>"字节",
+"字節"=>"字节",
+"列印"=>"打印",
+"打印"=>"打印",
+"硬體"=>"硬件",
+"二極體"=>"二极管",
+"二極管"=>"二极管",
+"三極體"=>"三极管",
+"三極管"=>"三极管",
+"數位"=>"数码",
+"數碼"=>"数码",
+"軟體"=>"软件",
+"軟件"=>"软件",
+"網路"=>"网络",
+"網絡"=>"网络",
+"人工智慧"=>"人工智能",
+"太空梭"=>"航天飞机",
+"穿梭機"=>"航天飞机",
+"網際網路"=>"因特网",
+"互聯網"=>"因特网",
+"機械人"=>"机器人",
+"機器人"=>"机器人",
+"行動電話"=>"移动电话",
+"流動電話"=>"移动电话",
+"調制解調器"=>"调制解调器",
+"數據機"=>"调制解调器",
+"短訊"=>"短信",
+"簡訊"=>"短信",
+"烏茲別克"=>"乌兹别克斯坦",
+"查德"=>"乍得",
+"乍得"=>"乍得",
+"也門"=>"",
+"葉門"=>"也门",
+"伯利茲"=>"伯利兹",
+"貝里斯"=>"伯利兹",
+"維德角"=>"佛得角",
+"佛得角"=>"佛得角",
+"克羅地亞"=>"克罗地亚",
+"克羅埃西亞"=>"克罗地亚",
+"岡比亞"=>"冈比亚",
+"甘比亞"=>"冈比亚",
+"幾內亞比紹"=>"几内亚比绍",
+"幾內亞比索"=>"几内亚比绍",
+"列支敦斯登"=>"列支敦士登",
+"列支敦士登"=>"列支敦士登",
+"利比里亞"=>"利比里亚",
+"賴比瑞亞"=>"利比里亚",
+"加納"=>"加纳",
+"迦納"=>"加纳",
+"加彭"=>"加蓬",
+"加蓬"=>"加蓬",
+"博茨瓦納"=>"博茨瓦纳",
+"波札那"=>"博茨瓦纳",
+"卡塔爾"=>"卡塔尔",
+"卡達"=>"卡塔尔",
+"盧旺達"=>"卢旺达",
+"盧安達"=>"卢旺达",
+"危地馬拉"=>"危地马拉",
+"瓜地馬拉"=>"危地马拉",
+"厄瓜多爾"=>"厄瓜多尔",
+"厄瓜多"=>"厄瓜多尔",
+"厄立特里亞"=>"厄立特里亚",
+"厄利垂亞"=>"厄立特里亚",
+"吉布堤"=>"吉布提",
+"吉布地"=>"吉布提",
+"哈薩克"=>"哈萨克斯坦",
+"哥斯達黎加"=>"哥斯达黎加",
+"哥斯大黎加"=>"哥斯达黎加",
+"圖瓦盧"=>"图瓦卢",
+"吐瓦魯"=>"图瓦卢",
+"土庫曼"=>"土库曼斯坦",
+"聖盧西亞"=>"圣卢西亚",
+"聖露西亞"=>"圣卢西亚",
+"聖吉斯納域斯"=>"圣基茨和尼维斯",
+"聖克里斯多福及尼維斯"=>"圣基茨和尼维斯",
+"聖文森特和格林納丁斯"=>"圣文森特和格林纳丁斯",
+"聖文森及格瑞那丁"=>"圣文森特和格林纳丁斯",
+"聖馬力諾"=>"圣马力诺",
+"聖馬利諾"=>"圣马力诺",
+"圭亞那"=>"圭亚那",
+"蓋亞那"=>"圭亚那",
+"坦桑尼亞"=>"坦桑尼亚",
+"坦尚尼亞"=>"坦桑尼亚",
+"埃塞俄比亞"=>"埃塞俄比亚",
+"衣索比亞"=>"埃塞俄比亚",
+"吉里巴斯"=>"基里巴斯",
+"基里巴斯"=>"基里巴斯",
+"塔吉克"=>"塔吉克斯坦",
+"獅子山"=>"塞拉利昂",
+"塞拉利昂"=>"塞拉利昂",
+"塞普勒斯"=>"塞浦路斯",
+"塞浦路斯"=>"塞浦路斯",
+"塞舌爾"=>"塞舌尔",
+"塞席爾"=>"塞舌尔",
+"多明尼加共和國"=>"多米尼加",
+"多明尼加"=>"多米尼加",
+"多明尼加聯邦"=>"多米尼加联邦",
+"多米尼克"=>"多米尼加联邦",
+"安提瓜和巴布達"=>"安提瓜和巴布达",
+"安地卡及巴布達"=>"安提瓜和巴布达",
+"尼日利亞"=>"尼日利亚",
+"奈及利亞"=>"尼日利亚",
+"尼日爾"=>"尼日尔",
+"尼日"=>"尼日尔",
+"巴貝多"=>"巴巴多斯",
+"巴巴多斯"=>"巴巴多斯",
+"巴布亞新畿內亞"=>"巴布亚新几内亚",
+"巴布亞紐幾內亞"=>"巴布亚新几内亚",
+"布基納法索"=>"布基纳法索",
+"布吉納法索"=>"布基纳法索",
+"蒲隆地"=>"布隆迪",
+"布隆迪"=>"布隆迪",
+"希臘"=>"希腊",
+"帛琉"=>"帕劳",
+"義大利"=>"意大利",
+"意大利"=>"意大利",
+"所羅門群島"=>"所罗门群岛",
+"索羅門群島"=>"所罗门群岛",
+"汶萊"=>"文莱",
+"斯威士蘭"=>"斯威士兰",
+"史瓦濟蘭"=>"斯威士兰",
+"斯洛文尼亞"=>"斯洛文尼亚",
+"斯洛維尼亞"=>"斯洛文尼亚",
+"新西蘭"=>"新西兰",
+"紐西蘭"=>"新西兰",
+"北韓"=>"朝鲜",
+"格林納達"=>"格林纳达",
+"格瑞那達"=>"格林纳达",
+"格魯吉亞"=>"格鲁吉亚",
+"喬治亞"=>"格鲁吉亚",
+"梵蒂岡"=>"梵蒂冈",
+"教廷"=>"梵蒂冈",
+"毛里塔尼亞"=>"毛里塔尼亚",
+"茅利塔尼亞"=>"毛里塔尼亚",
+"毛里裘斯"=>"毛里求斯",
+"模里西斯"=>"毛里求斯",
+"沙地阿拉伯"=>"沙特阿拉伯",
+"沙烏地阿拉伯"=>"沙特阿拉伯",
+"波斯尼亞黑塞哥維那"=>"波斯尼亚和黑塞哥维那",
+"波士尼亞赫塞哥維納"=>"波斯尼亚和黑塞哥维那",
+"津巴布韋"=>"津巴布韦",
+"辛巴威"=>"津巴布韦",
+"宏都拉斯"=>"洪都拉斯",
+"洪都拉斯"=>"洪都拉斯",
+"特立尼達和多巴哥"=>"特立尼达和托巴哥",
+"千里達托貝哥"=>"特立尼达和托巴哥",
+"瑙魯"=>"瑙鲁",
+"諾魯"=>"瑙鲁",
+"瓦努阿圖"=>"瓦努阿图",
+"萬那杜"=>"瓦努阿图",
+"溫納圖"=>"瓦努阿图",
+"科摩羅"=>"科摩罗",
+"葛摩"=>"科摩罗",
+"象牙海岸"=>"科特迪瓦",
+"突尼西亞"=>"突尼斯",
+"索馬里"=>"索马里",
+"索馬利亞"=>"索马里",
+"老撾"=>"老挝",
+"寮國"=>"老挝",
+"肯雅"=>"肯尼亚",
+"肯亞"=>"肯尼亚",
+"蘇利南"=>"苏里南",
+"莫三比克"=>"莫桑比克",
+"莫桑比克"=>"莫桑比克",
+"萊索托"=>"莱索托",
+"賴索托"=>"莱索托",
+"貝寧"=>"贝宁",
+"貝南"=>"贝宁",
+"贊比亞"=>"赞比亚",
+"尚比亞"=>"赞比亚",
+"亞塞拜然"=>"阿塞拜疆",
+"阿塞拜疆"=>"阿塞拜疆",
+"阿拉伯聯合酋長國"=>"阿拉伯联合酋长国",
+"阿拉伯聯合大公國"=>"阿拉伯联合酋长国",
+"南韓"=>"韩国",
+"馬爾代夫"=>"马尔代夫",
+"馬爾地夫"=>"马尔代夫",
+"馬爾他"=>"马耳他",
+"馬里"=>"马里",
+"馬利"=>"马里",
+"即食麵"=>"方便面",
+"快速面"=>"方便面",
+"速食麵"=>"方便面",
+"泡麵"=>"方便面",
+"笨豬跳"=>"蹦极跳",
+"绑紧跳"=>"蹦极跳",
+"冷盤  "=>"凉菜",
+"冷菜"=>"凉菜",
+"散钱"=>"零钱",
+"谐星"=>"笑星    ",
+"夜学"=>"夜校",
+"华乐"=>"民乐",
+"中樂"=>"民乐",
+"住屋"=>"住房",
+"屋价"=>"房价",
+"的士"=>"出租车",
+"計程車"=>"出租车",
+"巴士"=>"公共汽车",
+"公車"=>"公共汽车",
+"單車"=>"自行车",
+"節慶"=>"节日",
+"芝士"=>"乾酪",
+"狗隻"=>"犬只",
+"士多啤梨"=>"草莓",
+"忌廉"=>"奶油",
+"桌球"=>"台球",
+"撞球"=>"台球",
+"雪糕"=>"冰淇淋",
+"衞生"=>"卫生",
+"衛生"=>"卫生",
+"賓士"=>"奔驰",
+"平治"=>"奔驰",
+"捷豹"=>"美洲虎",
+"積架"=>"美洲虎",
+"福斯"=>"大众",
+"福士"=>"大众",
+"雪鐵龍"=>"雪铁龙",
+"萬事得"=>"马自达",
+"馬自達"=>"马自达",
+"寶獅"=>"标志",
+"布殊"=>"布什",
+"布希"=>"布什",
+"柯林頓"=>"克林顿",
+"克林頓"=>"克林顿",
+"薩達姆"=>"萨达姆",
+"海珊"=>"萨达姆",
+"梵谷"=>"凡高",
+"大衛碧咸"=>"大卫·贝克汉姆",
+"米高奧雲"=>"迈克尔·欧文",
+"卡佩雅蒂"=>"珍妮弗·卡普里亚蒂",
+"沙芬"=>"马拉特·萨芬",
+"舒麥加"=>"迈克尔·舒马赫",
+"希特拉"=>"希特勒",
+"戴安娜"=>"狄安娜",
+"黛安娜"=>"狄安娜",
+"希拉"=>"赫拉",
+);
+
+$zh2HK=array(
+"打印机" => "打印機",
+"印表機" => "打印機",
+"字节" => "字節",
+"位元組" => "字節",
+"打印" => "打印",
+"列印" => "打印",
+"硬件" => "硬件",
+"硬體" => "硬件",
+"二极管" => "二極管",
+"二極體" => "二極管",
+"三极管" => "三極管",
+"三極體" => "三極管",
+"数码" => "數碼",
+"數位" => "數碼",
+"软件" => "軟件",
+"軟體" => "軟件",
+"网络" => "網絡",
+"網路" => "網絡",
+"人工智能" => "人工智能",
+"人工智慧" => "人工智能",
+"航天飞机" => "穿梭機",
+"太空梭" => "穿梭機",
+"因特网" => "互聯網",
+"網際網路" => "互聯網",
+"机器人" => "機械人",
+"機器人" => "機械人",
+"移动电话" => "流動電話",
+"行動電話" => "流動電話",
+"调制解调器" => "調制解調器",
+"數據機" => "調制解調器",
+"短信" => "短訊",
+"簡訊" => "短訊",
+"乍得" => "乍得",
+"查德" => "乍得",
+"也门" => "也門",
+"葉門" => "也門",
+"伯利兹" => "伯利茲",
+"貝里斯" => "伯利茲",
+"佛得角" => "佛得角",
+"維德角" => "佛得角",
+"克罗地亚" => "克羅地亞",
+"克羅埃西亞" => "克羅地亞",
+"冈比亚" => "岡比亞",
+"甘比亞" => "岡比亞",
+"几内亚比绍" => "幾內亞比紹",
+"幾內亞比索" => "幾內亞比紹",
+"列支敦士登" => "列支敦士登",
+"列支敦斯登" => "列支敦士登",
+"利比里亚" => "利比里亞",
+"賴比瑞亞" => "利比里亞",
+"加纳" => "加納",
+"迦納" => "加納",
+"加蓬" => "加蓬",
+"加彭" => "加蓬",
+"博茨瓦纳" => "博茨瓦納",
+"波札那" => "博茨瓦納",
+"卡塔尔" => "卡塔爾",
+"卡達" => "卡塔爾",
+"卢旺达" => "盧旺達",
+"盧安達" => "盧旺達",
+"危地马拉" => "危地馬拉",
+"瓜地馬拉" => "危地馬拉",
+"厄瓜多尔" => "厄瓜多爾",
+"厄瓜多" => "厄瓜多爾",
+"厄立特里亚" => "厄立特里亞",
+"厄利垂亞" => "厄立特里亞",
+"吉布提" => "吉布堤",
+"吉布地" => "吉布堤",
+"哥斯达黎加" => "哥斯達黎加",
+"哥斯大黎加" => "哥斯達黎加",
+"图瓦卢" => "圖瓦盧",
+"吐瓦魯" => "圖瓦盧",
+"圣卢西亚" => "聖盧西亞",
+"聖露西亞" => "聖盧西亞",
+"圣基茨和尼维斯" => "聖吉斯納域斯",
+"聖克里斯多福及尼維斯" => "聖吉斯納域斯",
+"圣文森特和格林纳丁斯" => "聖文森特和格林納丁斯",
+"聖文森及格瑞那丁" => "聖文森特和格林納丁斯",
+"圣马力诺" => "聖馬力諾",
+"聖馬利諾" => "聖馬力諾",
+"圭亚那" => "圭亞那",
+"蓋亞那" => "圭亞那",
+"坦桑尼亚" => "坦桑尼亞",
+"坦尚尼亞" => "坦桑尼亞",
+"埃塞俄比亚" => "埃塞俄比亞",
+"衣索比亞" => "埃塞俄比亞",
+"基里巴斯" => "基里巴斯",
+"吉里巴斯" => "基里巴斯",
+"獅子山" => "塞拉利昂",
+"塞普勒斯" => "塞浦路斯",
+"塞舌尔" => "塞舌爾",
+"塞席爾" => "塞舌爾",
+"多米尼加" => "多明尼加共和國",
+"多明尼加" => "多明尼加共和國",
+"多米尼加联邦" => "多明尼加聯邦",
+"多米尼克" => "多明尼加聯邦",
+"安提瓜和巴布达" => "安提瓜和巴布達",
+"安地卡及巴布達" => "安提瓜和巴布達",
+"尼日利亚" => "尼日利亞",
+"奈及利亞" => "尼日利亞",
+"尼日尔" => "尼日爾",
+"尼日" => "尼日爾",
+"巴巴多斯" => "巴巴多斯",
+"巴貝多" => "巴巴多斯",
+"巴布亚新几内亚" => "巴布亞新畿內亞",
+"巴布亞紐幾內亞" => "巴布亞新畿內亞",
+"布基纳法索" => "布基納法索",
+"布吉納法索" => "布基納法索",
+"布隆迪" => "布隆迪",
+"蒲隆地" => "布隆迪",
+"義大利" => "意大利",
+"所罗门群岛" => "所羅門群島",
+"索羅門群島" => "所羅門群島",
+"斯威士兰" => "斯威士蘭",
+"史瓦濟蘭" => "斯威士蘭",
+"斯洛文尼亚" => "斯洛文尼亞",
+"斯洛維尼亞" => "斯洛文尼亞",
+"新西兰" => "新西蘭",
+"紐西蘭" => "新西蘭",
+"格林纳达" => "格林納達",
+"格瑞那達" => "格林納達",
+"格鲁吉亚" => "格魯吉亞",
+"喬治亞" => "格魯吉亞",
+"梵蒂冈" => "梵蒂岡",
+"教廷" => "梵蒂岡",
+"毛里塔尼亚" => "毛里塔尼亞",
+"茅利塔尼亞" => "毛里塔尼亞",
+"毛里求斯" => "毛里裘斯",
+"模里西斯" => "毛里裘斯",
+"沙特阿拉伯" => "沙地阿拉伯",
+"沙烏地阿拉伯" => "沙地阿拉伯",
+"波斯尼亚和黑塞哥维那" => "波斯尼亞黑塞哥維那",
+"波士尼亞赫塞哥維納" => "波斯尼亞黑塞哥維那",
+"津巴布韦" => "津巴布韋",
+"辛巴威" => "津巴布韋",
+"洪都拉斯" => "洪都拉斯",
+"宏都拉斯" => "洪都拉斯",
+"特立尼达和托巴哥" => "特立尼達和多巴哥",
+"千里達托貝哥" => "特立尼達和多巴哥",
+"瑙鲁" => "瑙魯",
+"諾魯" => "瑙魯",
+"瓦努阿图" => "瓦努阿圖",
+"萬那杜" => "瓦努阿圖",
+"科摩罗" => "科摩羅",
+"葛摩" => "科摩羅",
+"索马里" => "索馬里",
+"索馬利亞" => "索馬里",
+"老挝" => "老撾",
+"寮國" => "老撾",
+"肯尼亚" => "肯雅",
+"肯亞" => "肯雅",
+"莫桑比克" => "莫桑比克",
+"莫三比克" => "莫桑比克",
+"莱索托" => "萊索托",
+"賴索托" => "萊索托",
+"贝宁" => "貝寧",
+"貝南" => "貝寧",
+"赞比亚" => "贊比亞",
+"尚比亞" => "贊比亞",
+"阿塞拜疆" => "阿塞拜疆",
+"亞塞拜然" => "阿塞拜疆",
+"阿拉伯联合酋长国" => "阿拉伯聯合酋長國",
+"阿拉伯聯合大公國" => "阿拉伯聯合酋長國",
+"马尔代夫" => "馬爾代夫",
+"馬爾地夫" => "馬爾代夫",
+"马里" => "馬里",
+"馬利" => "馬里",
+"方便面" => "即食麵",
+"快速面" => "即食麵",
+"速食麵" => "即食麵",
+"泡麵" => "即食麵",
+"土豆" => "薯仔",
+"华乐" => "中樂",
+"民乐" => "中樂",
+"計程車     " => "的士",
+"出租车" => "的士",
+"公車" => "巴士",
+"公共汽车" => "巴士",
+"自行车" => "單車",
+"节日" => "節慶",
+"犬只" => "狗隻",
+"台球" => "桌球",
+"撞球" => "桌球",
+"冰淇淋" => "雪糕",
+"冰淇淋" => "雪糕",
+"卫生" => "衞生",
+"衛生" => "衞生",
+"老人" => "長者",
+"賓士" => "平治",
+"捷豹" => "積架",
+"福斯" => "福士",
+"雪铁龙" => "先進",
+"雪鐵龍" => "先進",
+"沃尓沃" => "富豪",
+"马自达" => "萬事得",
+"馬自達" => "萬事得",
+"寶獅" => "標致",
+"布什" => "布殊",
+"布希" => "布殊",
+"克林顿" => "克林頓",
+"柯林頓" => "克林頓",
+"萨达姆" => "薩達姆",
+"海珊" => "薩達姆",
+"大卫·贝克汉姆" => "大衛碧咸",
+"迈克尔·欧文" => "米高奧雲",
+"珍妮弗·卡普里亚蒂" => "卡佩雅蒂",
+"马拉特·萨芬" => "沙芬",
+"迈克尔·舒马赫" => "舒麥加",
+"希特勒" => "希特拉",
+"狄安娜" => "戴安娜",
+"黛安娜" => "戴安娜",
+);
+
+$zh2SG=array(
+"方便面" => "快速面",
+"速食麵" => "快速面",
+"即食麵" => "快速面",
+"蹦极跳" => "绑紧跳",
+"笨豬跳" => "绑紧跳",
+"凉菜" => "冷菜",
+"冷盤" => "冷菜",
+"零钱" => "散钱",
+"散紙" => "散钱",
+"笑星" => "谐星",
+"夜校" => "夜学",
+"民乐" => "华乐",
+"住房" => "住屋",
+"房价" => "屋价",
+"泡麵" => "快速面",
+);
+?>
\ No newline at end of file
diff --git a/includes/killthread.php b/includes/killthread.php
new file mode 100644 (file)
index 0000000..b12eccb
--- /dev/null
@@ -0,0 +1,47 @@
+<?php
+/**
+ * Script to kill a MySQL thread after a specified timeout
+ * @package MediaWiki
+ * @subpackage Database
+ */
+
+/**
+ *
+ */
+if( php_sapi_name() != 'cli' ) {
+       die('');
+}
+
+define( 'MEDIAWIKI', 1 );
+$wgCommandLineMode = true;
+
+unset( $IP );
+ini_set( 'allow_url_fopen', 0 ); # For security...
+require_once( '../LocalSettings.php' );
+
+if( !$wgAllowSysopQueries ) {
+       die( "Queries disabled.\n" );
+}
+
+require_once( 'Setup.php' );
+
+$wgTitle = Title::newFromText( wfMsgForContent( 'badtitle' ) );
+$wgArticle = new Article($wgTitle);
+
+if ( !$argv[1] || !$argv[2] ) {
+       exit();
+}
+
+$tid = (int)$argv[2];
+
+# Wait for timeout (this process may be killed during this time)
+$us = floor( $argv[1] * 1000000 ) % 1000000;
+$s = floor( $argv[1] );
+usleep( $us );
+sleep( $s );
+
+# Kill DB thread
+$conn = Database::newFromParams( $wgDBserver, $wgDBsqluser, $wgDBsqlpassword, $wgDBname );
+$conn->query( 'KILL '.$tid );
+
+?>
diff --git a/includes/memcached-client.php b/includes/memcached-client.php
new file mode 100644 (file)
index 0000000..4ff0da9
--- /dev/null
@@ -0,0 +1,994 @@
+<?php
+//
+// +---------------------------------------------------------------------------+
+// | memcached client, PHP                                                     |
+// +---------------------------------------------------------------------------+
+// | Copyright (c) 2003 Ryan T. Dean <rtdean@cytherianage.net>                 |
+// | All rights reserved.                                                      |
+// |                                                                           |
+// | Redistribution and use in source and binary forms, with or without        |
+// | modification, are permitted provided that the following conditions        |
+// | are met:                                                                  |
+// |                                                                           |
+// | 1. Redistributions of source code must retain the above copyright         |
+// |    notice, this list of conditions and the following disclaimer.          |
+// | 2. Redistributions in binary form must reproduce the above copyright      |
+// |    notice, this list of conditions and the following disclaimer in the    |
+// |    documentation and/or other materials provided with the distribution.   |
+// |                                                                           |
+// | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR      |
+// | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
+// | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.   |
+// | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,          |
+// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT  |
+// | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
+// | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY     |
+// | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT       |
+// | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF  |
+// | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.         |
+// +---------------------------------------------------------------------------+
+// | Author: Ryan T. Dean <rtdean@cytherianage.net>                            |
+// | Heavily influenced by the Perl memcached client by Brad Fitzpatrick.      |
+// |   Permission granted by Brad Fitzpatrick for relicense of ported Perl     |
+// |   client logic under 2-clause BSD license.                                |
+// +---------------------------------------------------------------------------+
+//
+// $TCAnet$
+//
+
+/**
+ * This is the PHP client for memcached - a distributed memory cache daemon.
+ * More information is available at http://www.danga.com/memcached/
+ *
+ * Usage example:
+ *
+ * require_once 'memcached.php';
+ * 
+ * $mc = new memcached(array(
+ *              'servers' => array('127.0.0.1:10000', 
+ *                                 array('192.0.0.1:10010', 2),
+ *                                 '127.0.0.1:10020'),
+ *              'debug'   => false,
+ *              'compress_threshold' => 10240,
+ *              'persistant' => true));
+ *
+ * $mc->add('key', array('some', 'array'));
+ * $mc->replace('key', 'some random string');
+ * $val = $mc->get('key');
+ *
+ * @author  Ryan T. Dean <rtdean@cytherianage.net>
+ * @package memcached-client
+ * @version 0.1.2
+ */
+
+// {{{ requirements
+// }}}
+
+// {{{ constants
+// {{{ flags
+
+/**
+ * Flag: indicates data is serialized
+ */
+define("MEMCACHE_SERIALIZED", 1<<0);
+
+/**
+ * Flag: indicates data is compressed
+ */
+define("MEMCACHE_COMPRESSED", 1<<1);
+
+// }}}
+
+/**
+ * Minimum savings to store data compressed
+ */
+define("COMPRESSION_SAVINGS", 0.20);
+
+// }}}
+
+// {{{ class memcached
+/**
+ * memcached client class implemented using (p)fsockopen()
+ *
+ * @author  Ryan T. Dean <rtdean@cytherianage.net>
+ * @package memcached-client
+ */
+class memcached
+{
+   // {{{ properties
+   // {{{ public
+
+   /**
+    * Command statistics
+    *
+    * @var     array
+    * @access  public
+    */
+   var $stats;
+   
+   // }}}
+   // {{{ private
+
+   /**
+    * Cached Sockets that are connected
+    *
+    * @var     array
+    * @access  private
+    */
+   var $_cache_sock;
+   
+   /**
+    * Current debug status; 0 - none to 9 - profiling
+    *
+    * @var     boolean
+    * @access  private
+    */
+   var $_debug;
+   
+   /**
+    * Dead hosts, assoc array, 'host'=>'unixtime when ok to check again'
+    *
+    * @var     array
+    * @access  private
+    */
+   var $_host_dead;
+   
+   /**
+    * Is compression available?
+    *
+    * @var     boolean
+    * @access  private
+    */
+   var $_have_zlib;
+   
+   /**
+    * Do we want to use compression?
+    *
+    * @var     boolean
+    * @access  private
+    */
+   var $_compress_enable;
+   
+   /**
+    * At how many bytes should we compress?
+    *
+    * @var     interger
+    * @access  private
+    */
+   var $_compress_threshold;
+   
+   /**
+    * Are we using persistant links?
+    *
+    * @var     boolean
+    * @access  private
+    */
+   var $_persistant;
+   
+   /**
+    * If only using one server; contains ip:port to connect to
+    *
+    * @var     string
+    * @access  private
+    */
+   var $_single_sock;
+   
+   /**
+    * Array containing ip:port or array(ip:port, weight)
+    *
+    * @var     array
+    * @access  private
+    */
+   var $_servers;
+   
+   /**
+    * Our bit buckets
+    *
+    * @var     array
+    * @access  private
+    */
+   var $_buckets;
+   
+   /**
+    * Total # of bit buckets we have
+    *
+    * @var     interger
+    * @access  private
+    */
+   var $_bucketcount;
+   
+   /**
+    * # of total servers we have
+    *
+    * @var     interger
+    * @access  private
+    */
+   var $_active;
+
+   /**
+    * Stream timeout in seconds. Applies for example to fread()
+    *
+    * @var     integer
+    * @access  private
+    */
+   var $_timeout_seconds;
+
+   /**
+    * Stream timeout in microseconds
+    *
+    * @var     integer
+    * @access  private
+    */
+   var $_timeout_microseconds;
+
+   // }}}
+   // }}}
+   // {{{ methods
+   // {{{ public functions
+   // {{{ memcached()
+
+   /**
+    * Memcache initializer
+    *
+    * @param   array    $args    Associative array of settings
+    *
+    * @return  mixed
+    * @access  public
+    */
+   function memcached ($args)
+   {
+      $this->set_servers(@$args['servers']);
+      $this->_debug = @$args['debug'];
+      $this->stats = array();
+      $this->_compress_threshold = @$args['compress_threshold'];
+      $this->_persistant = array_key_exists('persistant', $args) ? (@$args['persistant']) : false;
+      $this->_compress_enable = true;
+      $this->_have_zlib = function_exists("gzcompress");
+      
+      $this->_cache_sock = array();
+      $this->_host_dead = array();
+
+      $this->_timeout_seconds = 1;
+      $this->_timeout_microseconds = 0;
+   }
+
+   // }}}
+   // {{{ add()
+
+   /**
+    * Adds a key/value to the memcache server if one isn't already set with 
+    * that key
+    *
+    * @param   string   $key     Key to set with data
+    * @param   mixed    $val     Value to store
+    * @param   interger $exp     (optional) Time to expire data at
+    *
+    * @return  boolean
+    * @access  public
+    */
+   function add ($key, $val, $exp = 0)
+   {
+      return $this->_set('add', $key, $val, $exp);
+   }
+
+   // }}}
+   // {{{ decr()
+
+   /**
+    * Decriment a value stored on the memcache server
+    *
+    * @param   string   $key     Key to decriment
+    * @param   interger $amt     (optional) Amount to decriment
+    *
+    * @return  mixed    FALSE on failure, value on success
+    * @access  public
+    */
+   function decr ($key, $amt=1)
+   {
+      return $this->_incrdecr('decr', $key, $amt);
+   }
+
+   // }}}
+   // {{{ delete()
+
+   /**
+    * Deletes a key from the server, optionally after $time
+    *
+    * @param   string   $key     Key to delete
+    * @param   interger $time    (optional) How long to wait before deleting
+    *
+    * @return  boolean  TRUE on success, FALSE on failure
+    * @access  public
+    */
+   function delete ($key, $time = 0)
+   {
+      if (!$this->_active)
+         return false;
+         
+      $sock = $this->get_sock($key);
+      if (!is_resource($sock))
+         return false;
+      
+      $key = is_array($key) ? $key[1] : $key;
+      
+      @$this->stats['delete']++;
+      $cmd = "delete $key $time\r\n";
+      if(!fwrite($sock, $cmd, strlen($cmd)))
+      {
+         $this->_dead_sock($sock);
+         return false;
+      }
+      $res = trim(fgets($sock));
+      
+      if ($this->_debug)
+         $this->_debugprint(sprintf("MemCache: delete %s (%s)\n", $key, $res));
+      
+      if ($res == "DELETED")
+         return true;
+      return false;
+   }
+
+   // }}}
+   // {{{ disconnect_all()
+
+   /**
+    * Disconnects all connected sockets
+    *
+    * @access  public
+    */
+   function disconnect_all ()
+   {
+      foreach ($this->_cache_sock as $sock)
+         fclose($sock);
+
+      $this->_cache_sock = array();
+   }
+
+   // }}}
+   // {{{ enable_compress()
+
+   /**
+    * Enable / Disable compression
+    *
+    * @param   boolean  $enable  TRUE to enable, FALSE to disable
+    *
+    * @access  public
+    */
+   function enable_compress ($enable)
+   {
+      $this->_compress_enable = $enable;
+   }
+
+   // }}}
+   // {{{ forget_dead_hosts()
+
+   /**
+    * Forget about all of the dead hosts
+    *
+    * @access  public
+    */
+   function forget_dead_hosts ()
+   {
+      $this->_host_dead = array();
+   }
+
+   // }}}
+   // {{{ get()
+
+   /**
+    * Retrieves the value associated with the key from the memcache server
+    *
+    * @param  string   $key     Key to retrieve
+    *
+    * @return  mixed
+    * @access  public
+    */
+   function get ($key)
+   {
+      if (!$this->_active)
+         return false;
+         
+      $sock = $this->get_sock($key);
+      
+      if (!is_resource($sock))
+         return false;
+         
+      @$this->stats['get']++;
+      
+      $cmd = "get $key\r\n";
+      if (!fwrite($sock, $cmd, strlen($cmd)))
+      {
+         $this->_dead_sock($sock);
+         return false;
+      }
+      
+      $val = array();
+      $this->_load_items($sock, $val);
+      
+      if ($this->_debug)
+         foreach ($val as $k => $v)
+            $this->_debugprint(@sprintf("MemCache: sock %s got %s => %s\r\n", serialize($sock), $k, $v));
+
+      return @$val[$key];
+   }
+
+   // }}}
+   // {{{ get_multi()
+
+   /**
+    * Get multiple keys from the server(s)
+    *
+    * @param   array    $keys    Keys to retrieve
+    *
+    * @return  array
+    * @access  public
+    */
+   function get_multi ($keys)
+   {
+      if (!$this->_active)
+         return false;
+         
+      $this->stats['get_multi']++;
+      
+      foreach ($keys as $key)
+      {
+         $sock = $this->get_sock($key);
+         if (!is_resource($sock)) continue;
+         $key = is_array($key) ? $key[1] : $key;
+         if (!isset($sock_keys[$sock]))
+         {
+            $sock_keys[$sock] = array();
+            $socks[] = $sock;
+         }
+         $sock_keys[$sock][] = $key;
+      }
+      
+      // Send out the requests
+      foreach ($socks as $sock)
+      {
+         $cmd = "get";
+         foreach ($sock_keys[$sock] as $key)
+         {
+            $cmd .= " ". $key;
+         }
+         $cmd .= "\r\n";
+         
+         if (fwrite($sock, $cmd, strlen($cmd)))
+         {
+            $gather[] = $sock;
+         } else
+         {
+            $this->_dead_sock($sock);
+         }
+      }
+      
+      // Parse responses
+      $val = array();
+      foreach ($gather as $sock)
+      {
+         $this->_load_items($sock, $val);
+      }
+      
+      if ($this->_debug)
+         foreach ($val as $k => $v)
+            $this->_debugprint(sprintf("MemCache: got %s => %s\r\n", $k, $v));
+            
+      return $val;
+   }
+
+   // }}}
+   // {{{ incr()
+
+   /**
+    * Increments $key (optionally) by $amt
+    *
+    * @param   string   $key     Key to increment
+    * @param   interger $amt     (optional) amount to increment
+    *
+    * @return  interger New key value?
+    * @access  public
+    */
+   function incr ($key, $amt=1)
+   {
+      return $this->_incrdecr('incr', $key, $amt);
+   }
+
+   // }}}
+   // {{{ replace()
+
+   /**
+    * Overwrites an existing value for key; only works if key is already set
+    *
+    * @param   string   $key     Key to set value as
+    * @param   mixed    $value   Value to store
+    * @param   interger $exp     (optional) Experiation time
+    *
+    * @return  boolean
+    * @access  public
+    */
+   function replace ($key, $value, $exp=0)
+   {
+      return $this->_set('replace', $key, $value, $exp);
+   }
+
+   // }}}
+   // {{{ run_command()
+
+   /**
+    * Passes through $cmd to the memcache server connected by $sock; returns 
+    * output as an array (null array if no output)
+    *
+    * NOTE: due to a possible bug in how PHP reads while using fgets(), each
+    *       line may not be terminated by a \r\n.  More specifically, my testing
+    *       has shown that, on FreeBSD at least, each line is terminated only
+    *       with a \n.  This is with the PHP flag auto_detect_line_endings set
+    *       to falase (the default).
+    *
+    * @param   resource $sock    Socket to send command on
+    * @param   string   $cmd     Command to run
+    *
+    * @return  array    Output array
+    * @access  public
+    */
+   function run_command ($sock, $cmd)
+   {
+      if (!is_resource($sock))
+         return array();
+      
+      if (!fwrite($sock, $cmd, strlen($cmd)))
+         return array();
+         
+      while (true)
+      {
+         $res = fgets($sock);
+         $ret[] = $res;
+         if (preg_match('/^END/', $res))
+            break;
+         if (strlen($res) == 0)
+            break;
+      }
+      return $ret;
+   }
+
+   // }}}
+   // {{{ set()
+
+   /**
+    * Unconditionally sets a key to a given value in the memcache.  Returns true
+    * if set successfully.
+    *
+    * @param   string   $key     Key to set value as
+    * @param   mixed    $value   Value to set
+    * @param   interger $exp     (optional) Experiation time
+    *
+    * @return  boolean  TRUE on success
+    * @access  public
+    */
+   function set ($key, $value, $exp=0)
+   {
+      return $this->_set('set', $key, $value, $exp);
+   }
+
+   // }}}
+   // {{{ set_compress_threshold()
+
+   /**
+    * Sets the compression threshold
+    *
+    * @param   interger $thresh  Threshold to compress if larger than
+    *
+    * @access  public
+    */
+   function set_compress_threshold ($thresh)
+   {
+      $this->_compress_threshold = $thresh;
+   }
+
+   // }}}
+   // {{{ set_debug()
+
+   /**
+    * Sets the debug flag
+    *
+    * @param   boolean  $dbg     TRUE for debugging, FALSE otherwise
+    *
+    * @access  public
+    *
+    * @see     memcahced::memcached
+    */
+   function set_debug ($dbg)
+   {
+      $this->_debug = $dbg;
+   }
+
+   // }}}
+   // {{{ set_servers()
+
+   /**
+    * Sets the server list to distribute key gets and puts between
+    *
+    * @param   array    $list    Array of servers to connect to
+    *
+    * @access  public
+    *
+    * @see     memcached::memcached()
+    */
+   function set_servers ($list)
+   {
+      $this->_servers = $list;
+      $this->_active = count($list);
+      $this->_buckets = null;
+      $this->_bucketcount = 0;
+      
+      $this->_single_sock = null;
+      if ($this->_active == 1)
+         $this->_single_sock = $this->_servers[0];
+   }
+
+   /**
+    * Sets the timeout for new connections
+    *
+    * @param   integer  $seconds Number of seconds
+    * @param   integer  $microseconds  Number of microseconds
+    * 
+    * @access  public
+    */
+   function set_timeout ($seconds, $microseconds)
+   {
+      $this->_timeout_seconds = $seconds;
+      $this->_timeout_microseconds = $microseconds;
+   }
+   
+   // }}}
+   // }}}
+   // {{{ private methods
+   // {{{ _close_sock()
+
+   /**
+    * Close the specified socket
+    *
+    * @param   string   $sock    Socket to close
+    *
+    * @access  private
+    */
+   function _close_sock ($sock)
+   {
+      $host = array_search($sock, $this->_cache_sock);
+      fclose($this->_cache_sock[$host]);
+      unset($this->_cache_sock[$host]);
+   }
+
+   // }}}
+   // {{{ _connect_sock()
+
+   /**
+    * Connects $sock to $host, timing out after $timeout
+    *
+    * @param   interger $sock    Socket to connect
+    * @param   string   $host    Host:IP to connect to
+    * @param   float    $timeout (optional) Timeout value, defaults to 0.25s
+    *
+    * @return  boolean
+    * @access  private
+    */
+   function _connect_sock (&$sock, $host, $timeout = 0.25)
+   {
+      list ($ip, $port) = explode(":", $host);
+      if ($this->_persistant == 1)
+      {
+         $sock = @pfsockopen($ip, $port, $errno, $errstr, $timeout);
+      } else
+      {
+         $sock = @fsockopen($ip, $port, $errno, $errstr, $timeout);
+      }
+      
+      if (!$sock) {
+         if ($this->_debug)
+            $this->_debugprint( "Error connecting to $host: $errstr\n" );
+         return false;
+      }
+
+      // Initialise timeout
+      stream_set_timeout($sock, $this->_timeout_seconds, $this->_timeout_microseconds);
+
+      return true;
+   }
+
+   // }}}
+   // {{{ _dead_sock()
+
+   /**
+    * Marks a host as dead until 30-40 seconds in the future
+    *
+    * @param   string   $sock    Socket to mark as dead
+    *
+    * @access  private
+    */
+   function _dead_sock ($sock)
+   {
+      $host = array_search($sock, $this->_cache_sock);
+      @list ($ip, $port) = explode(":", $host);
+      $this->_host_dead[$ip] = time() + 30 + intval(rand(0, 10));
+      $this->_host_dead[$host] = $this->_host_dead[$ip];
+      unset($this->_cache_sock[$host]);
+   }
+
+   // }}}
+   // {{{ get_sock()
+
+   /**
+    * get_sock
+    *
+    * @param   string   $key     Key to retrieve value for;
+    *
+    * @return  mixed    resource on success, false on failure
+    * @access  private
+    */
+   function get_sock ($key)
+   {
+      if (!$this->_active)
+         return false;
+
+      if ($this->_single_sock !== null)
+         return $this->sock_to_host($this->_single_sock);
+      
+      $hv = is_array($key) ? intval($key[0]) : $this->_hashfunc($key);
+      
+      if ($this->_buckets === null)
+      {
+         foreach ($this->_servers as $v)
+         {
+            if (is_array($v))
+            {
+               for ($i=0; $i<$v[1]; $i++)
+                  $bu[] = $v[0];
+            } else
+            {
+               $bu[] = $v;
+            }
+         }
+         $this->_buckets = $bu;
+         $this->_bucketcount = count($bu);
+      }
+      
+      $realkey = is_array($key) ? $key[1] : $key;
+      for ($tries = 0; $tries<20; $tries++)
+      {
+         $host = $this->_buckets[$hv % $this->_bucketcount];
+         $sock = $this->sock_to_host($host);
+         if (is_resource($sock))
+            return $sock;
+         $hv += $this->_hashfunc($tries . $realkey);
+      }
+      
+      return false;
+   }
+
+   // }}}
+   // {{{ _hashfunc()
+
+   /**
+    * Creates a hash interger based on the $key
+    *
+    * @param   string   $key     Key to hash
+    *
+    * @return  interger Hash value
+    * @access  private
+    */
+   function _hashfunc ($key)
+   {
+      # Hash function must on [0,0x7ffffff]
+      # We take the first 31 bits of the MD5 hash, which unlike the hash 
+      # function used in a previous version of this client, works
+      return hexdec(substr(md5($key),0,8)) & 0x7fffffff;
+   }
+
+   // }}}
+   // {{{ _incrdecr()
+
+   /**
+    * Perform increment/decriment on $key
+    *
+    * @param   string   $cmd     Command to perform
+    * @param   string   $key     Key to perform it on
+    * @param   interger $amt     Amount to adjust
+    *
+    * @return  interger    New value of $key
+    * @access  private
+    */
+   function _incrdecr ($cmd, $key, $amt=1)
+   {
+      if (!$this->_active)
+         return null;
+         
+      $sock = $this->get_sock($key);
+      if (!is_resource($sock))
+         return null;
+         
+      $key = is_array($key) ? $key[1] : $key;
+      @$this->stats[$cmd]++;
+      if (!fwrite($sock, "$cmd $key $amt\r\n"))
+         return $this->_dead_sock($sock);
+         
+      stream_set_timeout($sock, 1, 0);
+      $line = fgets($sock);
+      if (!preg_match('/^(\d+)/', $line, $match))
+         return null;
+      return $match[1];
+   }
+
+   // }}}
+   // {{{ _load_items()
+
+   /**
+    * Load items into $ret from $sock
+    *
+    * @param   resource $sock    Socket to read from
+    * @param   array    $ret     Returned values
+    *
+    * @access  private
+    */
+   function _load_items ($sock, &$ret)
+   {
+      while (1)
+      {
+         $decl = fgets($sock);
+         if ($decl == "END\r\n")
+         {
+            return true;
+         } elseif (preg_match('/^VALUE (\S+) (\d+) (\d+)\r\n$/', $decl, $match))
+         {
+            list($rkey, $flags, $len) = array($match[1], $match[2], $match[3]);
+            $bneed = $len+2;
+            $offset = 0;
+            
+            while ($bneed > 0)
+            {
+               $data = fread($sock, $bneed);
+               $n = strlen($data);
+               if ($n == 0)
+                  break;
+               $offset += $n;
+               $bneed -= $n;
+               @$ret[$rkey] .= $data;
+            }
+            
+            if ($offset != $len+2)
+            {
+               // Something is borked!
+               if ($this->_debug)
+                  $this->_debugprint(sprintf("Something is borked!  key %s expecting %d got %d length\n", $rkey, $len+2, $offset));
+
+               unset($ret[$rkey]);
+               $this->_close_sock($sock);
+               return false;
+            }
+            
+            if ($this->_have_zlib && $flags & MEMCACHE_COMPRESSED)
+               $ret[$rkey] = gzuncompress($ret[$rkey]);
+
+            $ret[$rkey] = rtrim($ret[$rkey]);
+
+            if ($flags & MEMCACHE_SERIALIZED)
+               $ret[$rkey] = unserialize($ret[$rkey]);
+
+         } else 
+         {
+            $this->_debugprint("Error parsing memcached response\n");
+            return 0;
+         }
+      }
+   }
+
+   // }}}
+   // {{{ _set()
+
+   /**
+    * Performs the requested storage operation to the memcache server
+    *
+    * @param   string   $cmd     Command to perform
+    * @param   string   $key     Key to act on
+    * @param   mixed    $val     What we need to store
+    * @param   interger $exp     When it should expire
+    *
+    * @return  boolean
+    * @access  private
+    */
+   function _set ($cmd, $key, $val, $exp)
+   {
+      if (!$this->_active)
+         return false;
+         
+      $sock = $this->get_sock($key);
+      if (!is_resource($sock))
+         return false;
+         
+      @$this->stats[$cmd]++;
+      
+      $flags = 0;
+      
+      if (!is_scalar($val))
+      {
+         $val = serialize($val);
+         $flags |= MEMCACHE_SERIALIZED;
+         if ($this->_debug)
+            $this->_debugprint(sprintf("client: serializing data as it is not scalar\n"));
+      }
+      
+      $len = strlen($val);
+      
+      if ($this->_have_zlib && $this->_compress_enable && 
+          $this->_compress_threshold && $len >= $this->_compress_threshold)
+      {
+         $c_val = gzcompress($val, 9);
+         $c_len = strlen($c_val);
+         
+         if ($c_len < $len*(1 - COMPRESSION_SAVINGS))
+         {
+            if ($this->_debug)
+               $this->_debugprint(sprintf("client: compressing data; was %d bytes is now %d bytes\n", $len, $c_len));
+            $val = $c_val;
+            $len = $c_len;
+            $flags |= MEMCACHE_COMPRESSED;
+         }
+      }
+      if (!fwrite($sock, "$cmd $key $flags $exp $len\r\n$val\r\n"))
+         return $this->_dead_sock($sock);
+         
+      $line = trim(fgets($sock));
+      
+      if ($this->_debug)
+      {
+         if ($flags & MEMCACHE_COMPRESSED)
+            $val = 'compressed data';
+         $this->_debugprint(sprintf("MemCache: %s %s => %s (%s)\n", $cmd, $key, $val, $line));
+      }
+      if ($line == "STORED")
+         return true;
+      return false;
+   }
+
+   // }}}
+   // {{{ sock_to_host()
+
+   /**
+    * Returns the socket for the host
+    *
+    * @param   string   $host    Host:IP to get socket for
+    *
+    * @return  mixed    IO Stream or false
+    * @access  private
+    */
+   function sock_to_host ($host)
+   {
+      if (isset($this->_cache_sock[$host]))
+         return $this->_cache_sock[$host];
+      
+      $now = time();
+      list ($ip, $port) = explode (":", $host);
+      if (isset($this->_host_dead[$host]) && $this->_host_dead[$host] > $now ||
+          isset($this->_host_dead[$ip]) && $this->_host_dead[$ip] > $now)
+         return null;
+         
+      if (!$this->_connect_sock($sock, $host))
+         return $this->_dead_sock($host);
+         
+      // Do not buffer writes
+      stream_set_write_buffer($sock, 0);
+      
+      $this->_cache_sock[$host] = $sock;
+      
+      return $this->_cache_sock[$host];
+   }
+
+   function _debugprint($str){
+      print($str);
+   }
+
+   // }}}
+   // }}}
+   // }}}
+}
+
+// }}}
+?>
diff --git a/includes/mime.info b/includes/mime.info
new file mode 100644 (file)
index 0000000..b314be0
--- /dev/null
@@ -0,0 +1,76 @@
+#Mime type info file.
+#the first mime type in each line is the "main" mime type,
+#the others are aliases for this type
+#the media type is given in upper case and square brackets, 
+#like [BITMAP], and must indicate a media type as defined by
+#the MEDIATYPE_xxx constants in Defines.php
+
+
+image/gif      [BITMAP]
+image/png      [BITMAP]
+image/ief      [BITMAP]
+image/jpeg     [BITMAP]
+image/xbm      [BITMAP]
+image/tiff     [BITMAP]
+image/x-icon   [BITMAP]
+image/x-rgb    [BITMAP]
+image/x-portable-pixmap                [BITMAP]
+image/x-portable-graymap image/x-portable-greymap      [BITMAP]
+image/x-bmp image/bmp application/x-bmp application/bmp        [BITMAP]
+image/x-photoshop image/psd image/x-psd image/photoshop        [BITMAP]
+image/svg image/svg+xml application/svg+xml application/svg    [DRAWING]
+application/postscript [DRAWING]
+application/x-latex    [DRAWING]
+application/x-tex      [DRAWING]
+
+
+audio/mp3 audio/mpeg3 audio/mpeg       [AUDIO]
+audio/wav audio/x-wav audio/wave       [AUDIO]
+audio/mid audio/midi   [AUDIO]
+audio/basic            [AUDIO]
+audio/x-aiff           [AUDIO]
+audio/x-pn-realaudio   [AUDIO]
+audio/x-realaudio      [AUDIO]
+
+video/mpeg application/mpeg    [VIDEO]
+video/ogg                      [VIDEO]
+video/x-sgi-video              [VIDEO]
+
+application/ogg application/x-ogg audio/ogg audio/x-ogg video/ogg video/x-ogg          [MULTIMEDIA]
+
+application/x-shockwave-flash  [MULTIMEDIA]
+audio/x-pn-realaudio-plugin    [MULTIMEDIA]
+model/iges     [MULTIMEDIA]
+model/mesh     [MULTIMEDIA]
+model/vrml     [MULTIMEDIA]
+video/quicktime        [MULTIMEDIA]
+video/x-msvideo        [MULTIMEDIA]
+
+text/plain     [TEXT]
+text/html application/xhtml+xml        [TEXT]
+application/xml text/xml       [TEXT]
+text   [TEXT]
+
+application/zip application/x-zip      [ARCHIVE]
+application/x-gzip     [ARCHIVE]
+application/x-bzip     [ARCHIVE]
+application/x-tar      [ARCHIVE]
+application/x-stuffit  [ARCHIVE]
+
+
+text/javascript application/x-javascript application/x-ecmascript text/ecmascript      [EXECUTABLE]
+application/x-bash     [EXECUTABLE]
+application/x-sh       [EXECUTABLE]
+application/x-csh      [EXECUTABLE]
+application/x-tcsh     [EXECUTABLE]
+application/x-tcl      [EXECUTABLE]
+application/x-perl     [EXECUTABLE]
+application/x-python   [EXECUTABLE]
+
+application/pdf application/acrobat    [OFFICE]
+application/msword             [OFFICE]
+application/vnd.ms-excel       [OFFICE]
+application/vnd.ms-powerpoint  [OFFICE]
+application/x-director         [OFFICE]
+text/rtf                       [OFFICE]
diff --git a/includes/mime.types b/includes/mime.types
new file mode 100644 (file)
index 0000000..3a7fa39
--- /dev/null
@@ -0,0 +1,117 @@
+application/andrew-inset ez
+application/mac-binhex40 hqx
+application/mac-compactpro cpt
+application/mathml+xml mathml
+application/msword doc
+application/octet-stream bin dms lha lzh exe class so dll
+application/oda oda
+application/ogg ogg ogm
+application/pdf pdf
+application/postscript ai eps ps
+application/rdf+xml rdf
+application/smil smi smil
+application/srgs gram
+application/srgs+xml grxml
+application/vnd.mif mif
+application/vnd.ms-excel xls
+application/vnd.ms-powerpoint ppt
+application/vnd.wap.wbxml wbxml
+application/vnd.wap.wmlc wmlc
+application/vnd.wap.wmlscriptc wmlsc
+application/voicexml+xml vxml
+application/x-bcpio bcpio
+application/x-bzip gz bz2
+application/x-cdlink vcd
+application/x-chess-pgn pgn
+application/x-cpio cpio
+application/x-csh csh
+application/x-director dcr dir dxr
+application/x-dvi dvi
+application/x-futuresplash spl
+application/x-gtar gtar tar
+application/x-gzip gz
+application/x-hdf hdf
+application/x-jar jar
+application/x-javascript js
+application/x-koan skp skd skt skm
+application/x-latex latex
+application/x-netcdf nc cdf
+application/x-sh sh
+application/x-shar shar
+application/x-shockwave-flash swf
+application/x-stuffit sit
+application/x-sv4cpio sv4cpio
+application/x-sv4crc sv4crc
+application/x-tar tar
+application/x-tcl tcl
+application/x-tex tex
+application/x-texinfo texinfo texi
+application/x-troff t tr roff
+application/x-troff-man man
+application/x-troff-me me
+application/x-troff-ms ms
+application/x-ustar ustar
+application/x-wais-source src
+application/x-xpinstall xpi
+application/xhtml+xml xhtml xht
+application/xslt+xml xslt
+application/xml xml xsl
+application/xml-dtd dtd
+application/zip zip jar xpi  sxc stc  sxd std   sxi sti   sxm stm   sxw stw  
+audio/basic au snd
+audio/midi mid midi kar
+audio/mpeg mpga mp2 mp3
+audio/ogg ogg 
+audio/x-aiff aif aiff aifc
+audio/x-mpegurl m3u
+audio/x-ogg ogg 
+audio/x-pn-realaudio ram rm
+audio/x-pn-realaudio-plugin rpm
+audio/x-realaudio ra
+audio/x-wav wav
+chemical/x-pdb pdb
+chemical/x-xyz xyz
+image/bmp bmp
+image/cgm cgm
+image/gif gif
+image/ief ief
+image/jpeg jpeg jpg jpe
+image/png png
+image/svg+xml svg
+image/tiff tiff tif
+image/vnd.djvu djvu djv
+image/vnd.wap.wbmp wbmp
+image/x-cmu-raster ras
+image/x-icon ico
+image/x-portable-anymap pnm
+image/x-portable-bitmap pbm
+image/x-portable-graymap pgm
+image/x-portable-pixmap ppm
+image/x-rgb rgb
+image/x-photoshop psd
+image/x-xbitmap xbm
+image/x-xpixmap xpm
+image/x-xwindowdump xwd
+model/iges igs iges
+model/mesh msh mesh silo
+model/vrml wrl vrml
+text/calendar ics ifb
+text/css css
+text/html html htm
+text/plain txt
+text/richtext rtx
+text/rtf rtf
+text/sgml sgml sgm
+text/tab-separated-values tsv
+text/vnd.wap.wml wml
+text/vnd.wap.wmlscript wmls
+text/xml xml xsl xslt rss rdf
+text/x-setext etx
+video/mpeg mpeg mpg mpe
+video/ogg ogm ogg
+video/quicktime qt mov
+video/vnd.mpegurl mxu
+video/x-msvideo avi
+video/x-ogg ogm ogg
+video/x-sgi-movie movie
+x-conference/x-cooltalk ice
\ No newline at end of file
diff --git a/includes/normal/.cvsignore b/includes/normal/.cvsignore
new file mode 100644 (file)
index 0000000..097f749
--- /dev/null
@@ -0,0 +1,10 @@
+CompositionExclusions.txt
+DerivedNormalizationProps.txt
+NormalizationCorrections.txt
+NormalizationTest.txt
+testdata
+UnicodeData.txt
+UTF-8-test.txt
+*~
+._*
+.DS_Store
diff --git a/includes/normal/CleanUpTest.php b/includes/normal/CleanUpTest.php
new file mode 100644 (file)
index 0000000..527c5ff
--- /dev/null
@@ -0,0 +1,423 @@
+<?php
+# Copyright (C) 2004 Brion Vibber <brion@pobox.com>
+# http://www.mediawiki.org/
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or 
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# http://www.gnu.org/copyleft/gpl.html
+
+/**
+ * Additional tests for UtfNormal::cleanUp() function, inclusion
+ * regression checks for known problems.
+ *
+ * Requires PHPUnit.
+ * 
+ * @package UtfNormal
+ * @access private
+ */
+
+if( php_sapi_name() != 'cli' ) {
+       die( "Run me from the command line please.\n" );
+}
+
+/** */
+if( isset( $_SERVER['argv'] ) && in_array( '--icu', $_SERVER['argv'] ) ) {
+       dl( 'php_utfnormal.so' );
+}
+
+#ini_set( 'memory_limit', '40M' );
+
+require_once( 'PHPUnit.php' );
+require_once( 'UtfNormal.php' );
+
+/**
+ * @package UtfNormal
+ */
+class CleanUpTest extends PHPUnit_TestCase {
+       /**
+        * @param string $name ???
+        */
+       function CleanUpTest( $name ) {
+               $this->PHPUnit_TestCase( $name );
+       }
+
+       /** @todo document */
+       function setUp() {
+       }
+
+       /** @todo document */
+       function tearDown() {
+       }
+
+       /** @todo document */
+       function testAscii() {
+               $text = 'This is plain ASCII text.';
+               $this->assertEquals( $text, UtfNormal::cleanUp( $text ) );
+       }
+
+       /** @todo document */
+       function testNull() {
+               $text = "a \x00 null";
+               $expect = "a \xef\xbf\xbd null";
+               $this->assertEquals(
+                       bin2hex( $expect ),
+                       bin2hex( UtfNormal::cleanUp( $text ) ) );
+       }
+
+       /** @todo document */
+       function testLatin() {
+               $text = "L'\xc3\xa9cole";
+               $this->assertEquals( $text, UtfNormal::cleanUp( $text ) );
+       }
+
+       /** @todo document */
+       function testLatinNormal() {
+               $text = "L'e\xcc\x81cole";
+               $expect = "L'\xc3\xa9cole";
+               $this->assertEquals( $expect, UtfNormal::cleanUp( $text ) );
+       }
+
+       /**
+        * This test is *very* expensive!
+        * @todo document
+        */
+       function XtestAllChars() {
+               $rep = UTF8_REPLACEMENT;
+               global $utfCanonicalComp, $utfCanonicalDecomp;
+               for( $i = 0x0; $i < UNICODE_MAX; $i++ ) {
+                       $char = codepointToUtf8( $i );
+                       $clean = UtfNormal::cleanUp( $char );
+                       $x = sprintf( "%04X", $i );
+                       if( $i % 0x1000 == 0 ) echo "U+$x\n";
+                       if( $i == 0x0009 ||
+                           $i == 0x000a ||
+                           $i == 0x000d ||
+                           ($i > 0x001f && $i < UNICODE_SURROGATE_FIRST) ||
+                           ($i > UNICODE_SURROGATE_LAST && $i < 0xfffe ) ||
+                           ($i > 0xffff && $i <= UNICODE_MAX ) ) {
+                               if( isset( $utfCanonicalComp[$char] ) || isset( $utfCanonicalDecomp[$char] ) ) {
+                                   $comp = UtfNormal::NFC( $char );
+                                       $this->assertEquals(
+                                               bin2hex( $comp ),
+                                               bin2hex( $clean ),
+                                               "U+$x should be decomposed" );
+                               } else {
+                                       $this->assertEquals(
+                                               bin2hex( $char ), 
+                                               bin2hex( $clean ),
+                                               "U+$x should be intact" );
+                               }
+                       } else {
+                               $this->assertEquals( bin2hex( $rep ), bin2hex( $clean ), $x );
+                       }
+               }
+       }
+
+       /** @todo document */
+       function testAllBytes() {
+               $this->doTestBytes( '', '' );
+               $this->doTestBytes( 'x', '' );
+               $this->doTestBytes( '', 'x' );
+               $this->doTestBytes( 'x', 'x' );
+       }
+
+       /** @todo document */
+       function doTestBytes( $head, $tail ) {
+               for( $i = 0x0; $i < 256; $i++ ) {
+                       $char = $head . chr( $i ) . $tail;
+                       $clean = UtfNormal::cleanUp( $char );
+                       $x = sprintf( "%02X", $i );
+                       if( $i == 0x0009 ||
+                           $i == 0x000a ||
+                           $i == 0x000d ||
+                           ($i > 0x001f && $i < 0x80) ) {
+                               $this->assertEquals(
+                                       bin2hex( $char ), 
+                                       bin2hex( $clean ),
+                                       "ASCII byte $x should be intact" );
+                               if( $char != $clean ) return;
+                       } else {
+                               $norm = $head . UTF8_REPLACEMENT . $tail;
+                               $this->assertEquals(
+                                       bin2hex( $norm ),
+                                       bin2hex( $clean ),
+                                       "Forbidden byte $x should be rejected" );
+                               if( $norm != $clean ) return;
+                       }
+               }
+       }
+
+       /** @todo document */
+       function testDoubleBytes() {
+               $this->doTestDoubleBytes( '', '' );
+               $this->doTestDoubleBytes( 'x', '' );
+               $this->doTestDoubleBytes( '', 'x' );
+               $this->doTestDoubleBytes( 'x', 'x' );
+       }
+
+       /**
+        * @todo document
+        */
+       function doTestDoubleBytes( $head, $tail ) {
+               for( $first = 0xc0; $first < 0x100; $first++ ) {
+                       for( $second = 0x80; $second < 0x100; $second++ ) {
+                               $char = $head . chr( $first ) . chr( $second ) . $tail;
+                               $clean = UtfNormal::cleanUp( $char );
+                               $x = sprintf( "%02X,%02X", $first, $second );
+                               if( $first > 0xc1 &&
+                                   $first < 0xe0 &&
+                                   $second < 0xc0 ) {
+                                   $norm = UtfNormal::NFC( $char );
+                                       $this->assertEquals(
+                                               bin2hex( $norm ), 
+                                               bin2hex( $clean ),
+                                               "Pair $x should be intact" );
+                                   if( $norm != $clean ) return;
+                               } elseif( $first > 0xfd || $second > 0xbf ) {
+                                       # fe and ff are not legal head bytes -- expect two replacement chars
+                                       $norm = $head . UTF8_REPLACEMENT . UTF8_REPLACEMENT . $tail;
+                                       $this->assertEquals(
+                                               bin2hex( $norm ),
+                                               bin2hex( $clean ),
+                                               "Forbidden pair $x should be rejected" );
+                                       if( $norm != $clean ) return;
+                               } else {
+                                       $norm = $head . UTF8_REPLACEMENT . $tail;
+                                       $this->assertEquals(
+                                               bin2hex( $norm ),
+                                               bin2hex( $clean ),
+                                               "Forbidden pair $x should be rejected" );
+                                       if( $norm != $clean ) return;
+                               }
+                       }
+               }
+       }
+
+       /** @todo document */
+       function testTripleBytes() {
+               $this->doTestTripleBytes( '', '' );
+               $this->doTestTripleBytes( 'x', '' );
+               $this->doTestTripleBytes( '', 'x' );
+               $this->doTestTripleBytes( 'x', 'x' );
+       }
+
+       /** @todo document */
+       function doTestTripleBytes( $head, $tail ) {
+               for( $first = 0xc0; $first < 0x100; $first++ ) {
+                       for( $second = 0x80; $second < 0x100; $second++ ) {
+                               #for( $third = 0x80; $third < 0x100; $third++ ) {
+                               for( $third = 0x80; $third < 0x81; $third++ ) {
+                                       $char = $head . chr( $first ) . chr( $second ) . chr( $third ) . $tail;
+                                       $clean = UtfNormal::cleanUp( $char );
+                                       $x = sprintf( "%02X,%02X,%02X", $first, $second, $third );
+                                       if( $first >= 0xe0 &&
+                                               $first < 0xf0 &&
+                                               $second < 0xc0 &&
+                                               $third < 0xc0 ) {
+                                               if( $first == 0xe0 && $second < 0xa0 ) {
+                                                       $this->assertEquals(
+                                                               bin2hex( $head . UTF8_REPLACEMENT . $tail ), 
+                                                               bin2hex( $clean ),
+                                                               "Overlong triplet $x should be rejected" );
+                                               } elseif( $first == 0xed && 
+                                                       ( chr( $first ) . chr( $second ) . chr( $third ))  >= UTF8_SURROGATE_FIRST ) {
+                                                       $this->assertEquals(
+                                                               bin2hex( $head . UTF8_REPLACEMENT . $tail ), 
+                                                               bin2hex( $clean ),
+                                                               "Surrogate triplet $x should be rejected" );
+                                               } else {
+                                                       $this->assertEquals(
+                                                               bin2hex( UtfNormal::NFC( $char ) ), 
+                                                               bin2hex( $clean ),
+                                                               "Triplet $x should be intact" );
+                                               }
+                                       } elseif( $first > 0xc1 && $first < 0xe0 && $second < 0xc0 ) {
+                                               $this->assertEquals(
+                                                       bin2hex( UtfNormal::NFC( $head . chr( $first ) . chr( $second ) ) . UTF8_REPLACEMENT . $tail ),
+                                                       bin2hex( $clean ),
+                                                       "Valid 2-byte $x + broken tail" );
+                                       } elseif( $second > 0xc1 && $second < 0xe0 && $third < 0xc0 ) {
+                                               $this->assertEquals(
+                                                       bin2hex( $head . UTF8_REPLACEMENT . UtfNormal::NFC( chr( $second ) . chr( $third ) . $tail ) ),
+                                                       bin2hex( $clean ),
+                                                       "Broken head + valid 2-byte $x" );
+                                       } elseif( ( $first > 0xfd || $second > 0xfd ) &&
+                                                   ( ( $second > 0xbf && $third > 0xbf ) ||
+                                                     ( $second < 0xc0 && $third < 0xc0 ) ||
+                                                     ( $second > 0xfd ) ||
+                                                     ( $third > 0xfd ) ) ) {
+                                               # fe and ff are not legal head bytes -- expect three replacement chars
+                                               $this->assertEquals(
+                                                       bin2hex( $head . UTF8_REPLACEMENT . UTF8_REPLACEMENT . UTF8_REPLACEMENT . $tail ),
+                                                       bin2hex( $clean ),
+                                                       "Forbidden triplet $x should be rejected" );
+                                       } elseif( $first > 0xc2 && $second < 0xc0 && $third < 0xc0 ) {
+                                               $this->assertEquals(
+                                                       bin2hex( $head . UTF8_REPLACEMENT . $tail ),
+                                                       bin2hex( $clean ),
+                                                       "Forbidden triplet $x should be rejected" );
+                                       } else {
+                                               $this->assertEquals(
+                                                       bin2hex( $head . UTF8_REPLACEMENT . UTF8_REPLACEMENT . $tail ),
+                                                       bin2hex( $clean ),
+                                                       "Forbidden triplet $x should be rejected" );
+                                       }
+                               }
+                       }
+               }
+       }
+
+       /** @todo document */   
+       function testChunkRegression() {
+               # Check for regression against a chunking bug
+               $text   = "\x46\x55\xb8" .
+                         "\xdc\x96" . 
+                         "\xee" .
+                         "\xe7" .
+                         "\x44" .
+                         "\xaa" .
+                         "\x2f\x25";
+               $expect = "\x46\x55\xef\xbf\xbd" .
+                         "\xdc\x96" . 
+                         "\xef\xbf\xbd" .
+                         "\xef\xbf\xbd" .
+                         "\x44" .
+                         "\xef\xbf\xbd" .
+                         "\x2f\x25";
+
+               $this->assertEquals(
+                       bin2hex( $expect ),
+                       bin2hex( UtfNormal::cleanUp( $text ) ) );
+       }
+
+       /** @todo document */
+       function testInterposeRegression() {
+               $text   = "\x4e\x30" .
+                         "\xb1" .              # bad tail
+                         "\x3a" .
+                         "\x92" .              # bad tail
+                         "\x62\x3a" .
+                         "\x84" .              # bad tail
+                         "\x43" .
+                         "\xc6" .              # bad head
+                         "\x3f" .
+                         "\x92" .              # bad tail
+                         "\xad" .              # bad tail
+                         "\x7d" .
+                         "\xd9\x95";
+       
+               $expect = "\x4e\x30" .
+                         "\xef\xbf\xbd" .
+                         "\x3a" .
+                         "\xef\xbf\xbd" .
+                         "\x62\x3a" .
+                         "\xef\xbf\xbd" .
+                         "\x43" .
+                         "\xef\xbf\xbd" .
+                         "\x3f" .
+                         "\xef\xbf\xbd" .
+                         "\xef\xbf\xbd" .
+                         "\x7d" .
+                         "\xd9\x95";
+               
+               $this->assertEquals(
+                       bin2hex( $expect ),
+                       bin2hex( UtfNormal::cleanUp( $text ) ) );
+       }
+
+       /** @todo document */   
+       function testOverlongRegression() {
+               $text   = "\x67" .
+                         "\x1a" . # forbidden ascii
+                         "\xea" . # bad head
+                         "\xc1\xa6" . # overlong sequence
+                         "\xad" . # bad tail
+                         "\x1c" . # forbidden ascii
+                         "\xb0" . # bad tail
+                         "\x3c" .
+                         "\x9e";  # bad tail
+               $expect = "\x67" .
+                         "\xef\xbf\xbd" .
+                         "\xef\xbf\xbd" .
+                         "\xef\xbf\xbd" .
+                         "\xef\xbf\xbd" .
+                         "\xef\xbf\xbd" .
+                         "\xef\xbf\xbd" .
+                         "\x3c" .
+                         "\xef\xbf\xbd";
+               $this->assertEquals(
+                       bin2hex( $expect ),
+                       bin2hex( UtfNormal::cleanUp( $text ) ) );
+       }
+
+       /** @todo document */   
+       function testSurrogateRegression() {
+               $text   = "\xed\xb4\x96" . # surrogate 0xDD16
+                         "\x83" . # bad tail
+                         "\xb4" . # bad tail
+                         "\xac";  # bad head
+               $expect = "\xef\xbf\xbd" .
+                         "\xef\xbf\xbd" .
+                         "\xef\xbf\xbd" .
+                         "\xef\xbf\xbd";
+               $this->assertEquals(
+                       bin2hex( $expect ),
+                       bin2hex( UtfNormal::cleanUp( $text ) ) );
+       }
+
+       /** @todo document */
+       function testBomRegression() {
+               $text   = "\xef\xbf\xbe" . # U+FFFE, illegal char
+                         "\xb2" . # bad tail
+                         "\xef" . # bad head
+                         "\x59";
+               $expect = "\xef\xbf\xbd" .
+                         "\xef\xbf\xbd" .
+                         "\xef\xbf\xbd" .
+                         "\x59";
+               $this->assertEquals(
+                       bin2hex( $expect ),
+                       bin2hex( UtfNormal::cleanUp( $text ) ) );
+       }
+
+       /** @todo document */
+       function testForbiddenRegression() {
+               $text   = "\xef\xbf\xbf"; # U+FFFF, illegal char
+               $expect = "\xef\xbf\xbd";
+               $this->assertEquals(
+                       bin2hex( $expect ),
+                       bin2hex( UtfNormal::cleanUp( $text ) ) );
+       }
+
+       /** @todo document */
+       function testHangulRegression() {
+               $text = "\xed\x9c\xaf" . # Hangul char
+                               "\xe1\x87\x81";  # followed by another final jamo
+               $expect = $text;         # Should *not* change.
+               $this->assertEquals(
+                       bin2hex( $expect ),
+                       bin2hex( UtfNormal::cleanUp( $text ) ) );
+       }
+}
+
+
+$suite =& new PHPUnit_TestSuite( 'CleanUpTest' );
+$result = PHPUnit::run( $suite );
+echo $result->toString();
+
+if( !$result->wasSuccessful() ) {
+       exit( -1 );
+}
+exit( 0 );
+?>
\ No newline at end of file
diff --git a/includes/normal/Makefile b/includes/normal/Makefile
new file mode 100644 (file)
index 0000000..fcdf238
--- /dev/null
@@ -0,0 +1,72 @@
+.PHONY : all test testutf8 testclean icutest bench icubench clean distclean
+
+FETCH=wget
+#FETCH=fetch
+BASE=http://www.unicode.org/Public/UNIDATA
+PHP=php
+#PHP=php-cli
+
+all : UtfNormalData.inc
+
+UtfNormalData.inc : UtfNormalGenerate.php UtfNormalUtil.php UnicodeData.txt CompositionExclusions.txt NormalizationCorrections.txt DerivedNormalizationProps.txt
+       $(PHP) UtfNormalGenerate.php
+
+test : testutf8 testclean UtfNormalTest.php UtfNormalData.inc NormalizationTest.txt
+       $(PHP) UtfNormalTest.php
+
+testutf8 : Utf8Test.php UTF-8-test.txt
+       $(PHP) Utf8Test.php
+
+testclean : CleanUpTest.php
+       $(PHP) CleanUpTest.php
+
+bench : UtfNormalData.inc testdata/washington.txt testdata/berlin.txt testdata/tokyo.txt testdata/sociology.txt testdata/bulgakov.txt
+       $(PHP) UtfNormalBench.php
+
+icutest : UtfNormalData.inc NormalizationTest.txt
+       $(PHP) Utf8Test.php --icu
+       $(PHP) CleanUpTest.php --icu
+       $(PHP) UtfNormalTest.php --icu
+
+icubench : UtfNormalData.inc testdata/washington.txt testdata/berlin.txt testdata/tokyo.txt testdata/sociology.txt testdata/bulgakov.txt
+       $(PHP) UtfNormalBench.php --icu
+
+clean :
+       rm -f UtfNormalData.inc
+
+distclean : clean
+       rm -f CompositionExclusions.txt NormalizationTest.txt NormalizationCorrections.txt UnicodeData.txt DerivedNormalizationProps.txt
+
+# The Unicode data files...
+CompositionExclusions.txt :
+       $(FETCH) $(BASE)/CompositionExclusions.txt
+
+NormalizationTest.txt :
+       $(FETCH) $(BASE)/NormalizationTest.txt
+
+NormalizationCorrections.txt :
+       $(FETCH) $(BASE)/NormalizationCorrections.txt
+
+DerivedNormalizationProps.txt :
+       $(FETCH) $(BASE)/DerivedNormalizationProps.txt
+
+UnicodeData.txt :
+       $(FETCH) $(BASE)/UnicodeData.txt
+
+UTF-8-test.txt :
+       $(FETCH) http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
+
+testdata/berlin.txt :
+       mkdir -p testdata && wget -U MediaWiki/test -O testdata/berlin.txt "http://de.wikipedia.org/w/wiki.phtml?title=Berlin&oldid=2775712&action=raw"
+
+testdata/washington.txt :
+       mkdir -p testdata && wget -U MediaWiki/test -O testdata/washington.txt "http://en.wikipedia.org/w/wiki.phtml?title=Washington%2C_DC&oldid=6370218&action=raw"
+
+testdata/tokyo.txt :
+       mkdir -p testdata && wget -U MediaWiki/test -O testdata/tokyo.txt "http://ja.wikipedia.org/w/wiki.phtml?title=%E6%9D%B1%E4%BA%AC%E9%83%BD&oldid=940880&action=raw"
+
+testdata/sociology.txt :
+       mkdir -p testdata && wget -U MediaWiki/test -O testdata/sociology.txt "http://ko.wikipedia.org/w/wiki.phtml?title=%EC%82%AC%ED%9A%8C%ED%95%99&oldid=16409&action=raw"
+
+testdata/bulgakov.txt :
+       mkdir -p testdata && wget -U MediaWiki/test -O testdata/bulgakov.txt "http://ru.wikipedia.org/w/wiki.phtml?title=%D0%91%D1%83%D0%BB%D0%B3%D0%B0%D0%BA%D0%BE%D0%B2%2C_%D0%A1%D0%B5%D1%80%D0%B3%D0%B5%D0%B9_%D0%9D%D0%B8%D0%BA%D0%BE%D0%BB%D0%B0%D0%B5%D0%B2%D0%B8%D1%87&oldid=17704&action=raw"
diff --git a/includes/normal/README b/includes/normal/README
new file mode 100644 (file)
index 0000000..f8207a1
--- /dev/null
@@ -0,0 +1,55 @@
+This directory contains some Unicode normalization routines. These routines
+are meant to be reusable in other projects, so I'm not tying them to the
+MediaWiki utility functions.
+
+The main function to care about is UtfNormal::toNFC(); this will convert
+a given UTF-8 string to Normalization Form C if it's not already such.
+The function assumes that the input string is already valid UTF-8; if there
+are corrupt characters this may produce erroneous results.
+
+To also check for illegal characters, use UtfNormal::cleanUp(). This will
+strip illegal UTF-8 sequences and characters that are illegal in XML, and
+if necessary convert to normalization form C.
+
+Performance is kind of stinky in absolute terms, though it should be speedy
+on pure ASCII text. ;) On text that can be determined quickly to already be
+in NFC it's not too awful but it can quickly get uncomfortably slow,
+particularly for Korean text (the hangul decomposition/composition code is
+extra slow).
+
+
+== Regenerating data tables ==
+
+UtfNormalData.inc and UtfNormalDataK.inc are generated from the Unicode
+Character Database by the script UtfNormalGenerate.php. On a *nix system
+'make' should fetch the necessary files and regenerate it if the scripts
+have been changed or you remove it.
+
+
+== Testing ==
+
+'make test' will run the conformance test (UtfNormalTest.php), fetching the
+data from from the net if necessary. If it reports failure, something is
+going wrong!
+
+
+== Benchmarks ==
+
+Run 'make bench' to download some sample texts from Wikipedia and run some
+cheap benchmarks of some of the functions. Take all numbers with large
+grains of salt.
+
+
+== PHP module extension ==
+
+There's an experimental PHP extension module which wraps the ICU library's
+normalization functions. This is *MUCH* faster than doing this work in pure
+PHP code. This is in the 'normal' directory in MediaWiki's CVS extensions
+module. It is known to work with PHP 4.3.8 and 5.0.2 on Linux/x86 but hasn't
+been thoroughly tested on other configurations.
+
+If the php_normal.so module is loaded in php.ini, the normalization functions
+will automatically use it. If you can't (or don't want to) load it in php.ini,
+you may be able to load it using the dl() function before include()ing or
+require()ing UtfNormal.php, and it will be picked up.
+
diff --git a/includes/normal/RandomTest.php b/includes/normal/RandomTest.php
new file mode 100644 (file)
index 0000000..e85ec42
--- /dev/null
@@ -0,0 +1,107 @@
+<?php
+# Copyright (C) 2004 Brion Vibber <brion@pobox.com>
+# http://www.mediawiki.org/
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or 
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# http://www.gnu.org/copyleft/gpl.html
+
+/**
+ * Test feeds random 16-byte strings to both the pure PHP and ICU-based
+ * UtfNormal::cleanUp() code paths, and checks to see if there's a
+ * difference. Will run forever until it finds one or you kill it.
+ * 
+ * @package UtfNormal
+ * @access private
+ */
+
+if( php_sapi_name() != 'cli' ) {
+       die( "Run me from the command line please.\n" );
+}
+
+/** */
+require_once( 'UtfNormal.php' );
+require_once( '../DifferenceEngine.php' );
+
+dl('php_utfnormal.so' );
+
+# mt_srand( 99999 );
+
+function randomString( $length, $nullOk, $ascii = false ) {
+       $out = '';
+       for( $i = 0; $i < $length; $i++ )
+               $out .= chr( mt_rand( $nullOk ? 0 : 1, $ascii ? 127 : 255 ) );
+       return $out;
+}
+
+/* Duplicate of the cleanUp() path for ICU usage */
+function donorm( $str ) {
+       # We exclude a few chars that ICU would not.
+       $str = preg_replace( '/[\x00-\x08\x0b\x0c\x0e-\x1f]/', UTF8_REPLACEMENT, $str );
+       $str = str_replace( UTF8_FFFE, UTF8_REPLACEMENT, $str );
+       $str = str_replace( UTF8_FFFF, UTF8_REPLACEMENT, $str );
+       
+       # UnicodeString constructor fails if the string ends with a head byte.
+       # Add a junk char at the end, we'll strip it off
+       return rtrim( utf8_normalize( $str . "\x01", UNORM_NFC ), "\x01" );
+}
+
+function wfMsg($x) {
+       return $x;
+}
+
+function showDiffs( $a, $b ) {
+       $ota = explode( "\n", str_replace( "\r\n", "\n", $a ) );
+       $nta = explode( "\n", str_replace( "\r\n", "\n", $b ) );
+       
+       $diffs =& new Diff( $ota, $nta );
+       $formatter =& new TableDiffFormatter();
+       $funky = $formatter->format( $diffs );
+       preg_match_all( '/<span class="diffchange">(.*?)<\/span>/', $funky, $matches );
+       foreach( $matches[1] as $bit ) {
+               $hex = bin2hex( $bit );
+               echo "\t$hex\n";
+       }
+}
+
+$size = 16;
+$n = 0;
+while( true ) {
+       $n++;
+       echo "$n\n";
+       
+       $str = randomString( $size, true);
+       $clean = UtfNormal::cleanUp( $str );
+       $norm = donorm( $str );
+
+       echo strlen( $clean ) . ", " . strlen( $norm );
+       if( $clean == $norm ) {
+               echo " (match)\n";
+       } else {
+               echo " (FAIL)\n";
+               echo "\traw: " . bin2hex( $str ) . "\n" .
+                        "\tphp: " . bin2hex( $clean ) . "\n" .
+                        "\ticu: " . bin2hex( $norm ) . "\n";
+               echo "\n\tdiffs:\n";
+               showDiffs( $clean, $norm );
+               die();
+       }
+       
+       
+       $str = '';
+       $clean = '';
+       $norm = '';
+}
+
+?>
\ No newline at end of file
diff --git a/includes/normal/Utf8Test.php b/includes/normal/Utf8Test.php
new file mode 100644 (file)
index 0000000..ba3555e
--- /dev/null
@@ -0,0 +1,151 @@
+<?php
+# Copyright (C) 2004 Brion Vibber <brion@pobox.com>
+# http://www.mediawiki.org/
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or 
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# http://www.gnu.org/copyleft/gpl.html
+
+/**
+ * Runs the UTF-8 decoder test at:
+ * http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
+ *
+ * @package UtfNormal
+ * @access private
+ */
+
+/** */
+require_once 'UtfNormalUtil.php';
+require_once 'UtfNormal.php';
+mb_internal_encoding( "utf-8" );
+
+#$verbose = true;
+if( php_sapi_name() != 'cli' ) {
+       die( "Run me from the command line please.\n" );
+}
+
+$in = fopen( "UTF-8-test.txt", "rt" );
+if( !$in ) {
+       print "Couldn't open UTF-8-test.txt -- can't run tests.\n";
+       print "If necessary, manually download this file. It can be obtained at\n";
+       print "http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt";
+       exit(-1);
+}
+
+$columns = 0;
+while( false !== ( $line = fgets( $in ) ) ) {
+       if( preg_match( '/^(Here come the tests:\s*)\|$/', $line, $matches ) ) {
+               $columns = strpos( $line, '|' );
+               break;
+       }
+}
+
+if( !$columns ) {
+       print "Something seems to be wrong; couldn't extract line length.\n";
+       print "Check that UTF-8-test.txt was downloaded correctly from\n";
+       print "http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt";
+       exit(-1);
+}
+
+# print "$columns\n";
+
+$ignore = array(
+       # These two lines actually seem to be corrupt
+       '2.1.1', '2.2.1' );
+
+$exceptions = array(
+       # Tests that should mark invalid characters due to using long
+       # sequences beyond what is now considered legal.
+       '2.1.5', '2.1.6', '2.2.4', '2.2.5', '2.2.6', '2.3.5',
+       
+       # Literal 0xffff, which is illegal
+       '2.2.3' );
+
+$longTests = array(
+       # These tests span multiple lines
+       '3.1.9', '3.2.1', '3.2.2', '3.2.3', '3.2.4', '3.2.5',
+       '3.4' );
+
+# These tests are not in proper subsections
+$sectionTests = array( '3.4' );
+
+$section = NULL;
+$test = '';
+$failed = 0;
+$success = 0;
+$total = 0;
+while( false !== ( $line = fgets( $in ) ) ) {
+       if( preg_match( '/^(\d+)\s+(.*?)\s*\|/', $line, $matches ) ) {
+               $section = $matches[1];
+               print $line;
+               continue;
+       }
+       if( preg_match( '/^(\d+\.\d+\.\d+)\s*/', $line, $matches ) ) {
+               $test = $matches[1];
+
+               if( in_array( $test, $ignore ) ) {
+                       continue;
+               }
+               if( in_array( $test, $longTests ) ) {
+                       $line = fgets( $in );
+                       for( $line = fgets( $in ); !preg_match( '/^\s+\|/', $line ); $line = fgets( $in ) ) {
+                               testLine( $test, $line, $total, $success, $failed );
+                       }
+               } else {
+                       testLine( $test, $line, $total, $success, $failed );
+               }
+       }
+}
+
+if( $failed ) {
+       echo "\nFailed $failed tests.\n";
+       echo "UTF-8 DECODER TEST FAILED\n";
+       exit (-1);
+}
+
+echo "UTF-8 DECODER TEST SUCCESS!\n";
+exit (0);
+
+
+function testLine( $test, $line, &$total, &$success, &$failed ) {
+       $stripped = $line;
+       UtfNormal::quickisNFCVerify( $stripped );
+
+       $same = ( $line == $stripped );
+       $len = mb_strlen( substr( $stripped, 0, strpos( $stripped, '|' ) ) );
+       if( $len == 0 ) {
+               $len = strlen( substr( $stripped, 0, strpos( $stripped, '|' ) ) );
+       }
+       
+       global $columns;
+       $ok = $same ^ ($test >= 3 );
+
+       global $exceptions;
+       $ok ^= in_array( $test, $exceptions );
+       
+       $ok &= ($columns == $len);
+       
+       $total++;
+       if( $ok ) {
+               $success++;
+       } else {
+               $failed++;
+       }
+       global $verbose;
+       if( $verbose || !$ok ) {
+               print str_replace( "\n", "$len\n", $stripped );
+       }
+}
+
+?>
diff --git a/includes/normal/UtfNormal.php b/includes/normal/UtfNormal.php
new file mode 100644 (file)
index 0000000..55f420e
--- /dev/null
@@ -0,0 +1,791 @@
+<?php
+# Copyright (C) 2004 Brion Vibber <brion@pobox.com>
+# http://www.mediawiki.org/
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or 
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# http://www.gnu.org/copyleft/gpl.html
+
+/**
+ * Unicode normalization routines for working with UTF-8 strings.
+ * Currently assumes that input strings are valid UTF-8!
+ *
+ * Not as fast as I'd like, but should be usable for most purposes.
+ * UtfNormal::toNFC() will bail early if given ASCII text or text
+ * it can quickly deterimine is already normalized.
+ *
+ * All functions can be called static.
+ *
+ * See description of forms at http://www.unicode.org/reports/tr15/
+ *
+ * @package UtfNormal
+ */
+
+/** */
+require_once 'UtfNormalUtil.php';
+
+global $utfCombiningClass, $utfCanonicalComp, $utfCanonicalDecomp;
+$utfCombiningClass = NULL;
+$utfCanonicalComp = NULL;
+$utfCanonicalDecomp = NULL;
+
+# Load compatibility decompositions on demand if they are needed.
+global $utfCompatibilityDecomp;
+$utfCompatibilityDecomp = NULL;
+
+define( 'UNICODE_HANGUL_FIRST', 0xac00 );
+define( 'UNICODE_HANGUL_LAST',  0xd7a3 );
+
+define( 'UNICODE_HANGUL_LBASE', 0x1100 );
+define( 'UNICODE_HANGUL_VBASE', 0x1161 );
+define( 'UNICODE_HANGUL_TBASE', 0x11a7 );
+
+define( 'UNICODE_HANGUL_LCOUNT', 19 );
+define( 'UNICODE_HANGUL_VCOUNT', 21 );
+define( 'UNICODE_HANGUL_TCOUNT', 28 );
+define( 'UNICODE_HANGUL_NCOUNT', UNICODE_HANGUL_VCOUNT * UNICODE_HANGUL_TCOUNT );
+
+define( 'UNICODE_HANGUL_LEND', UNICODE_HANGUL_LBASE + UNICODE_HANGUL_LCOUNT - 1 );
+define( 'UNICODE_HANGUL_VEND', UNICODE_HANGUL_VBASE + UNICODE_HANGUL_VCOUNT - 1 );
+define( 'UNICODE_HANGUL_TEND', UNICODE_HANGUL_TBASE + UNICODE_HANGUL_TCOUNT - 1 );
+
+define( 'UNICODE_SURROGATE_FIRST', 0xd800 );
+define( 'UNICODE_SURROGATE_LAST', 0xdfff );
+define( 'UNICODE_MAX', 0x10ffff );
+define( 'UNICODE_REPLACEMENT', 0xfffd );
+
+
+define( 'UTF8_HANGUL_FIRST', codepointToUtf8( UNICODE_HANGUL_FIRST ) );
+define( 'UTF8_HANGUL_LAST', codepointToUtf8( UNICODE_HANGUL_LAST ) );
+
+define( 'UTF8_HANGUL_LBASE', codepointToUtf8( UNICODE_HANGUL_LBASE ) );
+define( 'UTF8_HANGUL_VBASE', codepointToUtf8( UNICODE_HANGUL_VBASE ) );
+define( 'UTF8_HANGUL_TBASE', codepointToUtf8( UNICODE_HANGUL_TBASE ) );
+
+define( 'UTF8_HANGUL_LEND', codepointToUtf8( UNICODE_HANGUL_LEND ) );
+define( 'UTF8_HANGUL_VEND', codepointToUtf8( UNICODE_HANGUL_VEND ) );
+define( 'UTF8_HANGUL_TEND', codepointToUtf8( UNICODE_HANGUL_TEND ) );
+
+define( 'UTF8_SURROGATE_FIRST', codepointToUtf8( UNICODE_SURROGATE_FIRST ) );
+define( 'UTF8_SURROGATE_LAST', codepointToUtf8( UNICODE_SURROGATE_LAST ) );
+define( 'UTF8_MAX', codepointToUtf8( UNICODE_MAX ) );
+define( 'UTF8_REPLACEMENT', codepointToUtf8( UNICODE_REPLACEMENT ) );
+#define( 'UTF8_REPLACEMENT', '!' );
+
+define( 'UTF8_OVERLONG_A', "\xc1\xbf" );
+define( 'UTF8_OVERLONG_B', "\xe0\x9f\xbf" );
+define( 'UTF8_OVERLONG_C', "\xf0\x8f\xbf\xbf" );
+
+# These two ranges are illegal
+define( 'UTF8_FDD0', codepointToUtf8( 0xfdd0 ) );
+define( 'UTF8_FDEF', codepointToUtf8( 0xfdef ) );
+define( 'UTF8_FFFE', codepointToUtf8( 0xfffe ) );
+define( 'UTF8_FFFF', codepointToUtf8( 0xffff ) );
+
+define( 'UTF8_HEAD', false );
+define( 'UTF8_TAIL', true );
+
+
+/**
+ * For using the ICU wrapper
+ */
+define( 'UNORM_NONE', 1 );
+define( 'UNORM_NFD',  2 );
+define( 'UNORM_NFKD', 3 );
+define( 'UNORM_NFC',  4 );
+define( 'UNORM_DEFAULT', UNORM_NFC );
+define( 'UNORM_NFKC', 5 );
+define( 'UNORM_FCD',  6 );
+
+define( 'NORMALIZE_ICU', function_exists( 'utf8_normalize' ) );
+
+/**
+ *
+ * @package MediaWiki
+ */
+class UtfNormal {
+       /**
+        * The ultimate convenience function! Clean up invalid UTF-8 sequences,
+        * and convert to normal form C, canonical composition.
+        *
+        * Fast return for pure ASCII strings; some lesser optimizations for
+        * strings containing only known-good characters. Not as fast as toNFC().
+        *
+        * @param string $string a UTF-8 string
+        * @return string a clean, shiny, normalized UTF-8 string
+        */
+       function cleanUp( $string ) {
+               if( NORMALIZE_ICU ) {
+                       # We exclude a few chars that ICU would not.
+                       $string = preg_replace(
+                               '/[\x00-\x08\x0b\x0c\x0e-\x1f]/',
+                               UTF8_REPLACEMENT,
+                               $string );
+                       $string = str_replace( UTF8_FFFE, UTF8_REPLACEMENT, $string );
+                       $string = str_replace( UTF8_FFFF, UTF8_REPLACEMENT, $string );
+                       
+                       # UnicodeString constructor fails if the string ends with a
+                       # head byte. Add a junk char at the end, we'll strip it off.
+                       return rtrim( utf8_normalize( $string . "\x01", UNORM_NFC ), "\x01" );
+               } elseif( UtfNormal::quickIsNFCVerify( $string ) ) {
+                       # Side effect -- $string has had UTF-8 errors cleaned up.
+                       return $string;
+               } else {
+                       return UtfNormal::NFC( $string );
+               }
+       }
+
+       /**
+        * Convert a UTF-8 string to normal form C, canonical composition.
+        * Fast return for pure ASCII strings; some lesser optimizations for
+        * strings containing only known-good characters.
+        *
+        * @param string $string a valid UTF-8 string. Input is not validated.
+        * @return string a UTF-8 string in normal form C
+        */
+       function toNFC( $string ) {
+               if( NORMALIZE_ICU )
+                       return utf8_normalize( $string, UNORM_NFC );
+               elseif( UtfNormal::quickIsNFC( $string ) )
+                       return $string;
+               else
+                       return UtfNormal::NFC( $string );
+       }
+       
+       /**
+        * Convert a UTF-8 string to normal form D, canonical decomposition.
+        * Fast return for pure ASCII strings.
+        *
+        * @param string $string a valid UTF-8 string. Input is not validated.
+        * @return string a UTF-8 string in normal form D
+        */
+       function toNFD( $string ) {
+               if( NORMALIZE_ICU )
+                       return utf8_normalize( $string, UNORM_NFD );
+               elseif( preg_match( '/[\x80-\xff]/', $string ) )
+                       return UtfNormal::NFD( $string );
+               else
+                       return $string;
+       }
+       
+       /**
+        * Convert a UTF-8 string to normal form KC, compatibility composition.
+        * This may cause irreversible information loss, use judiciously.
+        * Fast return for pure ASCII strings.
+        *
+        * @param string $string a valid UTF-8 string. Input is not validated.
+        * @return string a UTF-8 string in normal form KC
+        */
+       function toNFKC( $string ) {
+               if( NORMALIZE_ICU )
+                       return utf8_normalize( $string, UNORM_NFKC );
+               elseif( preg_match( '/[\x80-\xff]/', $string ) )
+                       return UtfNormal::NFKC( $string );
+               else
+                       return $string;
+       }
+       
+       /**
+        * Convert a UTF-8 string to normal form KD, compatibility decomposition.
+        * This may cause irreversible information loss, use judiciously.
+        * Fast return for pure ASCII strings.
+        *
+        * @param string $string a valid UTF-8 string. Input is not validated.
+        * @return string a UTF-8 string in normal form KD
+        */
+       function toNFKD( $string ) {
+               if( NORMALIZE_ICU )
+                       return utf8_normalize( $string, UNORM_NFKD );
+               elseif( preg_match( '/[\x80-\xff]/', $string ) )
+                       return UtfNormal::NFKD( $string );
+               else
+                       return $string;
+       }
+       
+       /**
+        * Load the basic composition data if necessary
+        * @access private
+        */
+       function loadData() {
+               global $utfCombiningClass, $utfCanonicalComp, $utfCanonicalDecomp;
+               if( !isset( $utfCombiningClass ) ) {
+                       require_once( 'UtfNormalData.inc' );
+               }
+       }
+       
+       /**
+        * Returns true if the string is _definitely_ in NFC.
+        * Returns false if not or uncertain.
+        * @param string $string a valid UTF-8 string. Input is not validated.
+        * @return bool
+        */
+       function quickIsNFC( $string ) {
+               # ASCII is always valid NFC!
+               # If it's pure ASCII, let it through.
+               if( !preg_match( '/[\x80-\xff]/', $string ) ) return true;
+               
+               UtfNormal::loadData();
+               global $utfCheckNFC, $utfCombiningClass;
+               $len = strlen( $string );
+               for( $i = 0; $i < $len; $i++ ) {
+                       $c = $string{$i};
+                       $n = ord( $c );
+                       if( $n < 0x80 ) {
+                               continue;
+                       } elseif( $n >= 0xf0 ) {
+                               $c = substr( $string, $i, 4 );
+                               $i += 3;
+                       } elseif( $n >= 0xe0 ) {
+                               $c = substr( $string, $i, 3 );
+                               $i += 2;
+                       } elseif( $n >= 0xc0 ) {
+                               $c = substr( $string, $i, 2 );
+                               $i++;
+                       }
+                       if( isset( $utfCheckNFC[$c] ) ) {
+                               # If it's NO or MAYBE, bail and do the slow check.
+                               return false;
+                       }
+                       if( isset( $utfCombiningClass[$c] ) ) {
+                               # Combining character? We might have to do sorting, at least.
+                               return false;
+                       }
+               }
+               return true;
+       }
+
+       /**
+        * Returns true if the string is _definitely_ in NFC.
+        * Returns false if not or uncertain.
+        * @param string $string a UTF-8 string, altered on output to be valid UTF-8 safe for XML.
+        */
+       function quickIsNFCVerify( &$string ) {
+               # Screen out some characters that eg won't be allowed in XML
+               $string = preg_replace( '/[\x00-\x08\x0b\x0c\x0e-\x1f]/', UTF8_REPLACEMENT, $string );
+               
+               # ASCII is always valid NFC!
+               # If we're only ever given plain ASCII, we can avoid the overhead
+               # of initializing the decomposition tables by skipping out early.
+               if( !preg_match( '/[\x80-\xff]/', $string ) ) return true;
+               
+               static $checkit = null, $tailBytes = null, $utfCheckOrCombining = null;
+               if( !isset( $checkit ) ) {
+                       # Load/build some scary lookup tables...
+                       UtfNormal::loadData();
+                       global $utfCheckNFC, $utfCombiningClass;
+                       
+                       $utfCheckOrCombining = array_merge( $utfCheckNFC, $utfCombiningClass );
+
+                       # Head bytes for sequences which we should do further validity checks
+                       $checkit = array_flip( array_map( 'chr',
+                                       array( 0xc0, 0xc1, 0xe0, 0xed, 0xef,
+                                                  0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+                                                  0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff ) ) );
+                       
+                       # Each UTF-8 head byte is followed by a certain
+                       # number of tail bytes.
+                       $tailBytes = array();
+                       for( $n = 0; $n < 256; $n++ ) {
+                               if( $n < 0xc0 ) {
+                                       $remaining = 0;
+                               } elseif( $n < 0xe0 ) {
+                                       $remaining = 1;
+                               } elseif( $n < 0xf0 ) {
+                                       $remaining = 2;
+                               } elseif( $n < 0xf8 ) {
+                                       $remaining = 3;
+                               } elseif( $n < 0xfc ) {
+                                       $remaining = 4;
+                               } elseif( $n < 0xfe ) {
+                                       $remaining = 5;
+                               } else {
+                                       $remaining = 0;
+                               }
+                               $tailBytes[chr($n)] = $remaining;
+                       }
+               }
+               
+               # Chop the text into pure-ASCII and non-ASCII areas;
+               # large ASCII parts can be handled much more quickly.
+               # Don't chop up Unicode areas for punctuation, though,
+               # that wastes energy.
+               preg_match_all(
+                       '/([\x00-\x7f]+|[\x80-\xff][\x00-\x40\x5b-\x5f\x7b-\xff]*)/',
+                       $string, $matches );
+               
+               $looksNormal = true;
+               $base = 0;
+               $replace = array();
+               foreach( $matches[1] as $str ) {
+                       $chunk = strlen( $str );
+                       
+                       if( $str{0} < "\x80" ) {
+                               # ASCII chunk: guaranteed to be valid UTF-8
+                               # and in normal form C, so skip over it.
+                               $base += $chunk;
+                               continue;
+                       }
+                       
+                       # We'll have to examine the chunk byte by byte to ensure
+                       # that it consists of valid UTF-8 sequences, and to see
+                       # if any of them might not be normalized.
+                       #
+                       # Since PHP is not the fastest language on earth, some of
+                       # this code is a little ugly with inner loop optimizations.
+                       
+                       $head = '';
+                       $len = $chunk + 1; # Counting down is faster. I'm *so* sorry.
+                       
+                       for( $i = -1; --$len; ) {
+                               if( $remaining = $tailBytes[$c = $str{++$i}] ) {
+                                       # UTF-8 head byte!
+                                       $sequence = $head = $c;
+                                       do {
+                                               # Look for the defined number of tail bytes...
+                                               if( --$len && ( $c = $str{++$i} ) >= "\x80" && $c < "\xc0" ) {
+                                                       # Legal tail bytes are nice.
+                                                       $sequence .= $c;
+                                               } else {
+                                                       if( 0 == $len ) {
+                                                               # Premature end of string!
+                                                               # Drop a replacement character into output to
+                                                               # represent the invalid UTF-8 sequence.
+                                                               $replace[] = array( UTF8_REPLACEMENT,
+                                                                                                       $base + $i + 1 - strlen( $sequence ),
+                                                                                                       strlen( $sequence ) );
+                                                               break 2;
+                                                       } else {
+                                                               # Illegal tail byte; abandon the sequence.
+                                                               $replace[] = array( UTF8_REPLACEMENT,
+                                                                                                       $base + $i - strlen( $sequence ),
+                                                                                                       strlen( $sequence ) );
+                                                               # Back up and reprocess this byte; it may itself
+                                                               # be a legal ASCII or UTF-8 sequence head.
+                                                               --$i;
+                                                               ++$len;
+                                                               continue 2;
+                                                       }
+                                               }
+                                       } while( --$remaining );
+
+                                       if( isset( $checkit[$head] ) ) {
+                                               # Do some more detailed validity checks, for
+                                               # invalid characters and illegal sequences.
+                                               if( $head == "\xed" ) {
+                                                       # 0xed is relatively frequent in Korean, which
+                                                       # abuts the surrogate area, so we're doing
+                                                       # this check separately to speed things up.
+                                                       
+                                                       if( $sequence >= UTF8_SURROGATE_FIRST ) {
+                                                               # Surrogates are legal only in UTF-16 code.
+                                                               # They are totally forbidden here in UTF-8
+                                                               # utopia.
+                                                               $replace[] = array( UTF8_REPLACEMENT,
+                                                                            $base + $i + 1 - strlen( $sequence ),
+                                                                            strlen( $sequence ) );
+                                                               $head = '';
+                                                               continue;
+                                                       }
+                                               } else {
+                                                       # Slower, but rarer checks...
+                                                       $n = ord( $head );
+                                                       if(
+                                                               # "Overlong sequences" are those that are syntactically
+                                                               # correct but use more UTF-8 bytes than are necessary to
+                                                               # encode a character. Naïve string comparisons can be
+                                                               # tricked into failing to see a match for an ASCII
+                                                               # character, for instance, which can be a security hole
+                                                               # if blacklist checks are being used.
+                                                              ($n  < 0xc2 && $sequence <= UTF8_OVERLONG_A)
+                                                               || ($n == 0xe0 && $sequence <= UTF8_OVERLONG_B)
+                                                               || ($n == 0xf0 && $sequence <= UTF8_OVERLONG_C)
+                                                               
+                                                               # U+FFFE and U+FFFF are explicitly forbidden in Unicode.
+                                                               || ($n == 0xef && 
+                                                                          ($sequence == UTF8_FFFE)
+                                                                       || ($sequence == UTF8_FFFF) )
+                                                               
+                                                               # Unicode has been limited to 21 bits; longer
+                                                               # sequences are not allowed.
+                                                               || ($n >= 0xf0 && $sequence > UTF8_MAX) ) {
+                                                               
+                                                               $replace[] = array( UTF8_REPLACEMENT,
+                                                                                   $base + $i + 1 - strlen( $sequence ), 
+                                                                                   strlen( $sequence ) );
+                                                               $head = '';
+                                                               continue;
+                                                       }
+                                               }
+                                       }
+                                       
+                                       if( isset( $utfCheckOrCombining[$sequence] ) ) {
+                                               # If it's NO or MAYBE, we'll have to rip
+                                               # the string apart and put it back together.
+                                               # That's going to be mighty slow.
+                                               $looksNormal = false;
+                                       }
+                                       
+                                       # The sequence is legal!
+                                       $head = '';
+                               } elseif( $c < "\x80" ) {
+                                       # ASCII byte.
+                                       $head = '';
+                               } elseif( $c < "\xc0" ) {
+                                       # Illegal tail bytes
+                                       if( $head == '' ) {
+                                               # Out of the blue!
+                                               $replace[] = array( UTF8_REPLACEMENT, $base + $i, 1 );
+                                       } else {
+                                               # Don't add if we're continuing a broken sequence;
+                                               # we already put a replacement character when we looked
+                                               # at the broken sequence.
+                                               $replace[] = array( '', $base + $i, 1 );
+                                       }
+                               } else {
+                                       # Miscellaneous freaks.
+                                       $replace[] = array( UTF8_REPLACEMENT, $base + $i, 1 );
+                                       $head = '';
+                               }
+                       }
+                       $base += $chunk;
+               }
+               if( count( $replace ) ) {
+                       # There were illegal UTF-8 sequences we need to fix up.
+                       $out = '';
+                       $last = 0;
+                       foreach( $replace as $rep ) {
+                               list( $replacement, $start, $length ) = $rep;
+                               if( $last < $start ) {
+                                       $out .= substr( $string, $last, $start - $last );
+                               }
+                               $out .= $replacement;
+                               $last = $start + $length;
+                       }
+                       if( $last < strlen( $string ) ) {
+                               $out .= substr( $string, $last );
+                       }
+                       $string = $out;
+               }
+               return $looksNormal;
+       }
+       
+       # These take a string and run the normalization on them, without
+       # checking for validity or any optimization etc. Input must be
+       # VALID UTF-8!
+       /**
+        * @param string $string
+        * @return string
+        * @access private
+        */
+       function NFC( $string ) {
+               return UtfNormal::fastCompose( UtfNormal::NFD( $string ) );
+       }
+       
+       /**
+        * @param string $string
+        * @return string
+        * @access private
+        */
+       function NFD( $string ) {
+               UtfNormal::loadData();
+               global $utfCanonicalDecomp;
+               return UtfNormal::fastCombiningSort(
+                       UtfNormal::fastDecompose( $string, $utfCanonicalDecomp ) );
+       }
+       
+       /**
+        * @param string $string
+        * @return string
+        * @access private
+        */
+       function NFKC( $string ) {
+               return UtfNormal::fastCompose( UtfNormal::NFKD( $string ) );
+       }
+       
+       /**
+        * @param string $string
+        * @return string
+        * @access private
+        */
+       function NFKD( $string ) {
+               global $utfCompatibilityDecomp;
+               if( !isset( $utfCompatibilityDecomp ) ) {
+                       require_once( 'UtfNormalDataK.inc' );
+               }
+               return UtfNormal::fastCombiningSort(
+                       UtfNormal::fastDecompose( $string, $utfCompatibilityDecomp ) );
+       }
+       
+       
+       /**
+        * Perform decomposition of a UTF-8 string into either D or KD form
+        * (depending on which decomposition map is passed to us).
+        * Input is assumed to be *valid* UTF-8. Invalid code will break.
+        * @access private
+        * @param string $string Valid UTF-8 string
+        * @param array $map hash of expanded decomposition map
+        * @return string a UTF-8 string decomposed, not yet normalized (needs sorting)
+        */
+       function fastDecompose( $string, &$map ) {
+               UtfNormal::loadData();
+               $len = strlen( $string );
+               $out = '';
+               for( $i = 0; $i < $len; $i++ ) {
+                       $c = $string{$i};
+                       $n = ord( $c );
+                       if( $n < 0x80 ) {
+                               # ASCII chars never decompose
+                               # THEY ARE IMMORTAL
+                               $out .= $c;
+                               continue;
+                       } elseif( $n >= 0xf0 ) {
+                               $c = substr( $string, $i, 4 );
+                               $i += 3;
+                       } elseif( $n >= 0xe0 ) {
+                               $c = substr( $string, $i, 3 );
+                               $i += 2;
+                       } elseif( $n >= 0xc0 ) {
+                               $c = substr( $string, $i, 2 );
+                               $i++;
+                       }
+                       if( isset( $map[$c] ) ) {
+                               $out .= $map[$c];
+                               continue;
+                       } else {
+                               if( $c >= UTF8_HANGUL_FIRST && $c <= UTF8_HANGUL_LAST ) {
+                                       # Decompose a hangul syllable into jamo;
+                                       # hardcoded for three-byte UTF-8 sequence.
+                                       # A lookup table would be slightly faster,
+                                       # but adds a lot of memory & disk needs.
+                                       #
+                                       $index = ( (ord( $c{0} ) & 0x0f) << 12
+                                                | (ord( $c{1} ) & 0x3f) <<  6
+                                                | (ord( $c{2} ) & 0x3f) )
+                                              - UNICODE_HANGUL_FIRST;
+                                       $l = IntVal( $index / UNICODE_HANGUL_NCOUNT );
+                                       $v = IntVal( ($index % UNICODE_HANGUL_NCOUNT) / UNICODE_HANGUL_TCOUNT);
+                                       $t = $index % UNICODE_HANGUL_TCOUNT;
+                                       $out .= "\xe1\x84" . chr( 0x80 + $l ) . "\xe1\x85" . chr( 0xa1 + $v );
+                                       if( $t >= 25 ) {
+                                               $out .= "\xe1\x87" . chr( 0x80 + $t - 25 );
+                                       } elseif( $t ) {
+                                               $out .= "\xe1\x86" . chr( 0xa7 + $t );
+                                       }
+                                       continue;
+                               }
+                       }
+                       $out .= $c;
+               }
+               return $out;
+       }
+
+       /**
+        * Sorts combining characters into canonical order. This is the
+        * final step in creating decomposed normal forms D and KD.
+        * @access private
+        * @param string $string a valid, decomposed UTF-8 string. Input is not validated.
+        * @return string a UTF-8 string with combining characters sorted in canonical order
+        */
+       function fastCombiningSort( $string ) {
+               UtfNormal::loadData();
+               global $utfCombiningClass;
+               $len = strlen( $string );
+               $out = '';
+               $combiners = array();
+               $lastClass = -1;
+               for( $i = 0; $i < $len; $i++ ) {
+                       $c = $string{$i};
+                       $n = ord( $c );
+                       if( $n >= 0x80 ) {
+                               if( $n >= 0xf0 ) {
+                                       $c = substr( $string, $i, 4 );
+                                       $i += 3;
+                               } elseif( $n >= 0xe0 ) {
+                                       $c = substr( $string, $i, 3 );
+                                       $i += 2;
+                               } elseif( $n >= 0xc0 ) {
+                                       $c = substr( $string, $i, 2 );
+                                       $i++;
+                               }
+                               if( isset( $utfCombiningClass[$c] ) ) {
+                                       $lastClass = $utfCombiningClass[$c];
+                                       @$combiners[$lastClass] .= $c;
+                                       continue;
+                               }
+                       }
+                       if( $lastClass ) {
+                               ksort( $combiners );
+                               $out .= implode( '', $combiners );
+                               $combiners = array();
+                       }
+                       $out .= $c;
+                       $lastClass = 0;
+               }
+               if( $lastClass ) {
+                       ksort( $combiners );
+                       $out .= implode( '', $combiners );
+               }
+               return $out;
+       }
+
+       /**
+        * Produces canonically composed sequences, i.e. normal form C or KC.
+        *
+        * @access private
+        * @param string $string a valid UTF-8 string in sorted normal form D or KD. Input is not validated.
+        * @return string a UTF-8 string with canonical precomposed characters used where possible
+        */
+       function fastCompose( $string ) {
+               UtfNormal::loadData();
+               global $utfCanonicalComp, $utfCombiningClass;
+               $len = strlen( $string );
+               $out = '';
+               $lastClass = -1;
+               $lastHangul = 0;
+               $startChar = '';
+               $combining = '';
+               $x1 = ord(substr(UTF8_HANGUL_VBASE,0,1));
+               $x2 = ord(substr(UTF8_HANGUL_TEND,0,1));
+               for( $i = 0; $i < $len; $i++ ) {
+                       $c = $string{$i};
+                       $n = ord( $c );
+                       if( $n < 0x80 ) {
+                               # No combining characters here...
+                               $out .= $startChar;
+                               $out .= $combining;
+                               $startChar = $c;
+                               $combining = '';
+                               $lastClass = 0;
+                               continue;
+                       } elseif( $n >= 0xf0 ) {
+                               $c = substr( $string, $i, 4 );
+                               $i += 3;
+                       } elseif( $n >= 0xe0 ) {
+                               $c = substr( $string, $i, 3 );
+                               $i += 2;
+                       } elseif( $n >= 0xc0 ) {
+                               $c = substr( $string, $i, 2 );
+                               $i++;
+                       }
+                       $pair = $startChar . $c;
+                       if( $n > 0x80 ) {
+                               if( isset( $utfCombiningClass[$c] ) ) {
+                                       # A combining char; see what we can do with it
+                                       $class = $utfCombiningClass[$c];
+                                       if( !empty( $startChar ) &&
+                                               $lastClass < $class &&
+                                               $class > 0 &&
+                                               isset( $utfCanonicalComp[$pair] ) ) {
+                                               $startChar = $utfCanonicalComp[$pair];
+                                               $class = 0;
+                                       } else {
+                                               $combining .= $c;
+                                       }
+                                       $lastClass = $class;
+                                       $lastHangul = 0;
+                                       continue;
+                               }
+                       }
+                       # New start char
+                       if( $lastClass == 0 ) {
+                               if( isset( $utfCanonicalComp[$pair] ) ) {
+                                       $startChar = $utfCanonicalComp[$pair];
+                                       $lastHangul = 0;
+                                       continue;
+                               }
+                               if( $n >= $x1 && $n <= $x2 ) {
+                                       # WARNING: Hangul code is painfully slow.
+                                       # I apologize for this ugly, ugly code; however
+                                       # performance is even more teh suck if we call
+                                       # out to nice clean functions. Lookup tables are
+                                       # marginally faster, but require a lot of space.
+                                       #
+                                       if( $c >= UTF8_HANGUL_VBASE &&
+                                               $c <= UTF8_HANGUL_VEND &&
+                                               $startChar >= UTF8_HANGUL_LBASE &&
+                                               $startChar <= UTF8_HANGUL_LEND ) {
+                                               #
+                                               #$lIndex = utf8ToCodepoint( $startChar ) - UNICODE_HANGUL_LBASE;
+                                               #$vIndex = utf8ToCodepoint( $c ) - UNICODE_HANGUL_VBASE;
+                                               $lIndex = ord( $startChar{2} ) - 0x80;
+                                               $vIndex = ord( $c{2}         ) - 0xa1;
+
+                                               $hangulPoint = UNICODE_HANGUL_FIRST +
+                                                       UNICODE_HANGUL_TCOUNT *
+                                                       (UNICODE_HANGUL_VCOUNT * $lIndex + $vIndex);
+                                               
+                                               # Hardcode the limited-range UTF-8 conversion:
+                                               $startChar = chr( $hangulPoint >> 12 & 0x0f | 0xe0 ) .
+                                                                        chr( $hangulPoint >>  6 & 0x3f | 0x80 ) .
+                                                                        chr( $hangulPoint       & 0x3f | 0x80 );
+                                               $lastHangul = 0;
+                                               continue;
+                                       } elseif( $c >= UTF8_HANGUL_TBASE &&
+                                                         $c <= UTF8_HANGUL_TEND &&
+                                                         $startChar >= UTF8_HANGUL_FIRST &&
+                                                         $startChar <= UTF8_HANGUL_LAST &&
+                                                         !$lastHangul ) {
+                                               # $tIndex = utf8ToCodepoint( $c ) - UNICODE_HANGUL_TBASE;
+                                               $tIndex = ord( $c{2} ) - 0xa7;
+                                               if( $tIndex < 0 ) $tIndex = ord( $c{2} ) - 0x80 + (0x11c0 - 0x11a7);
+                                               
+                                               # Increment the code point by $tIndex, without
+                                               # the function overhead of decoding and recoding UTF-8
+                                               #
+                                               $tail = ord( $startChar{2} ) + $tIndex;
+                                               if( $tail > 0xbf ) {
+                                                       $tail -= 0x40;
+                                                       $mid = ord( $startChar{1} ) + 1;
+                                                       if( $mid > 0xbf ) {
+                                                               $startChar{0} = chr( ord( $startChar{0} ) + 1 );
+                                                               $mid -= 0x40;
+                                                       }
+                                                       $startChar{1} = chr( $mid );
+                                               }
+                                               $startChar{2} = chr( $tail );
+                                               
+                                               # If there's another jamo char after this, *don't* try to merge it.
+                                               $lastHangul = 1;
+                                               continue;
+                                       }
+                               }
+                       }
+                       $out .= $startChar;
+                       $out .= $combining;
+                       $startChar = $c;
+                       $combining = '';
+                       $lastClass = 0;
+                       $lastHangul = 0;
+               }
+               $out .= $startChar . $combining;
+               return $out;
+       }
+       
+       /**
+        * This is just used for the benchmark, comparing how long it takes to
+        * interate through a string without really doing anything of substance.
+        * @param string $string
+        * @return string
+        */
+       function placebo( $string ) {
+               $len = strlen( $string );
+               $out = '';
+               for( $i = 0; $i < $len; $i++ ) {
+                       $out .= $string{$i};
+               }
+               return $out;
+       }
+}
+
+?>
diff --git a/includes/normal/UtfNormalBench.php b/includes/normal/UtfNormalBench.php
new file mode 100644 (file)
index 0000000..dbf69f4
--- /dev/null
@@ -0,0 +1,107 @@
+<?php
+# Copyright (C) 2004 Brion Vibber <brion@pobox.com>
+# http://www.mediawiki.org/
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or 
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# http://www.gnu.org/copyleft/gpl.html
+
+/**
+ * Approximate benchmark for some basic operations.
+ * 
+ * @package UtfNormal
+ * @access private
+ */
+
+/** */
+if( isset( $_SERVER['argv'] ) && in_array( '--icu', $_SERVER['argv'] ) ) {
+       dl( 'php_utfnormal.so' );
+}
+
+require_once 'UtfNormalUtil.php';
+require_once 'UtfNormal.php';
+
+define( 'BENCH_CYCLES', 5 );
+
+if( php_sapi_name() != 'cli' ) {
+       die( "Run me from the command line please.\n" );
+}
+
+$testfiles = array(
+       'testdata/washington.txt' => 'English text',
+       'testdata/berlin.txt' => 'German text',
+       'testdata/bulgakov.txt' => 'Russian text',
+       'testdata/tokyo.txt' => 'Japanese text',
+       'testdata/sociology.txt' => 'Korean text'
+);
+$normalizer = new UtfNormal;
+UtfNormal::loadData();
+foreach( $testfiles as $file => $desc ) {
+       benchmarkTest( $normalizer, $file, $desc );
+}
+
+# -------
+
+function benchmarkTest( &$u, $filename, $desc ) {
+       print "Testing $filename ($desc)...\n";
+       $data = file_get_contents( $filename );
+       $forms = array(
+#              'placebo',
+               'cleanUp',
+               'toNFC',
+#              'toNFKC',
+#              'toNFD', 'toNFKD',
+               'NFC',
+#              'NFKC',
+#              'NFD', 'NFKD',
+               array( 'fastDecompose', 'fastCombiningSort', 'fastCompose' ),
+#              'quickIsNFC', 'quickIsNFCVerify',
+               );
+       foreach( $forms as $form ) {
+               if( is_array( $form ) ) {
+                       $str = $data;
+                       foreach( $form as $step ) {
+                               $str = benchmarkForm( $u, $str, $step );
+                       }
+               } else {
+                       benchmarkForm( $u, $data, $form );
+               }
+       }
+}
+
+function benchTime(){
+       $st = explode( ' ', microtime() );
+       return (float)$st[0] + (float)$st[1];
+}
+
+function benchmarkForm( &$u, &$data, $form ) {
+       global $utfCanonicalDecomp;
+       #$start = benchTime();
+       for( $i = 0; $i < BENCH_CYCLES; $i++ ) {
+               $start = benchTime();
+               $out = $u->$form( $data, $utfCanonicalDecomp );
+               $deltas[] = (benchTime() - $start);
+       }
+       #$delta = (benchTime() - $start) / BENCH_CYCLES;
+       sort( $deltas );
+       $delta = $deltas[0]; # Take shortest time
+       
+       $rate = IntVal( strlen( $data ) / $delta );
+       $same = (0 == strcmp( $data, $out ) );
+       
+       printf( " %20s %6.1fms %8d bytes/s (%s)\n", $form, $delta*1000.0, $rate, ($same ? 'no change' : 'changed' ) );
+       return $out;
+}
+
+?>
diff --git a/includes/normal/UtfNormalData.inc b/includes/normal/UtfNormalData.inc
new file mode 100644 (file)
index 0000000..6216d1a
--- /dev/null
@@ -0,0 +1,13 @@
+<?php
+/**
+ * This file was automatically generated -- do not edit!
+ * Run UtfNormalGenerate.php to create this file again (make clean && make)
+ * @package MediaWiki
+ */
+/** */
+global $utfCombiningClass, $utfCanonicalComp, $utfCanonicalDecomp, $utfCheckNFC;
+$utfCombiningClass = unserialize( 'a:384:{s:2:"̀";i:230;s:2:"́";i:230;s:2:"̂";i:230;s:2:"̃";i:230;s:2:"̄";i:230;s:2:"̅";i:230;s:2:"̆";i:230;s:2:"̇";i:230;s:2:"̈";i:230;s:2:"̉";i:230;s:2:"̊";i:230;s:2:"̋";i:230;s:2:"̌";i:230;s:2:"̍";i:230;s:2:"̎";i:230;s:2:"̏";i:230;s:2:"̐";i:230;s:2:"̑";i:230;s:2:"̒";i:230;s:2:"̓";i:230;s:2:"̔";i:230;s:2:"̕";i:232;s:2:"̖";i:220;s:2:"̗";i:220;s:2:"̘";i:220;s:2:"̙";i:220;s:2:"̚";i:232;s:2:"̛";i:216;s:2:"̜";i:220;s:2:"̝";i:220;s:2:"̞";i:220;s:2:"̟";i:220;s:2:"̠";i:220;s:2:"̡";i:202;s:2:"̢";i:202;s:2:"̣";i:220;s:2:"̤";i:220;s:2:"̥";i:220;s:2:"̦";i:220;s:2:"̧";i:202;s:2:"̨";i:202;s:2:"̩";i:220;s:2:"̪";i:220;s:2:"̫";i:220;s:2:"̬";i:220;s:2:"̭";i:220;s:2:"̮";i:220;s:2:"̯";i:220;s:2:"̰";i:220;s:2:"̱";i:220;s:2:"̲";i:220;s:2:"̳";i:220;s:2:"̴";i:1;s:2:"̵";i:1;s:2:"̶";i:1;s:2:"̷";i:1;s:2:"̸";i:1;s:2:"̹";i:220;s:2:"̺";i:220;s:2:"̻";i:220;s:2:"̼";i:220;s:2:"̽";i:230;s:2:"̾";i:230;s:2:"̿";i:230;s:2:"̀";i:230;s:2:"́";i:230;s:2:"͂";i:230;s:2:"̓";i:230;s:2:"̈́";i:230;s:2:"ͅ";i:240;s:2:"͆";i:230;s:2:"͇";i:220;s:2:"͈";i:220;s:2:"͉";i:220;s:2:"͊";i:230;s:2:"͋";i:230;s:2:"͌";i:230;s:2:"͍";i:220;s:2:"͎";i:220;s:2:"͐";i:230;s:2:"͑";i:230;s:2:"͒";i:230;s:2:"͓";i:220;s:2:"͔";i:220;s:2:"͕";i:220;s:2:"͖";i:220;s:2:"͗";i:230;s:2:"͘";i:232;s:2:"͙";i:220;s:2:"͚";i:220;s:2:"͛";i:230;s:2:"͜";i:233;s:2:"͝";i:234;s:2:"͞";i:234;s:2:"͟";i:233;s:2:"͠";i:234;s:2:"͡";i:234;s:2:"͢";i:233;s:2:"ͣ";i:230;s:2:"ͤ";i:230;s:2:"ͥ";i:230;s:2:"ͦ";i:230;s:2:"ͧ";i:230;s:2:"ͨ";i:230;s:2:"ͩ";i:230;s:2:"ͪ";i:230;s:2:"ͫ";i:230;s:2:"ͬ";i:230;s:2:"ͭ";i:230;s:2:"ͮ";i:230;s:2:"ͯ";i:230;s:2:"҃";i:230;s:2:"҄";i:230;s:2:"҅";i:230;s:2:"҆";i:230;s:2:"֑";i:220;s:2:"֒";i:230;s:2:"֓";i:230;s:2:"֔";i:230;s:2:"֕";i:230;s:2:"֖";i:220;s:2:"֗";i:230;s:2:"֘";i:230;s:2:"֙";i:230;s:2:"֚";i:222;s:2:"֛";i:220;s:2:"֜";i:230;s:2:"֝";i:230;s:2:"֞";i:230;s:2:"֟";i:230;s:2:"֠";i:230;s:2:"֡";i:230;s:2:"֢";i:220;s:2:"֣";i:220;s:2:"֤";i:220;s:2:"֥";i:220;s:2:"֦";i:220;s:2:"֧";i:220;s:2:"֨";i:230;s:2:"֩";i:230;s:2:"֪";i:220;s:2:"֫";i:230;s:2:"֬";i:230;s:2:"֭";i:222;s:2:"֮";i:228;s:2:"֯";i:230;s:2:"ְ";i:10;s:2:"ֱ";i:11;s:2:"ֲ";i:12;s:2:"ֳ";i:13;s:2:"ִ";i:14;s:2:"ֵ";i:15;s:2:"ֶ";i:16;s:2:"ַ";i:17;s:2:"ָ";i:18;s:2:"ֹ";i:19;s:2:"ֻ";i:20;s:2:"ּ";i:21;s:2:"ֽ";i:22;s:2:"ֿ";i:23;s:2:"ׁ";i:24;s:2:"ׂ";i:25;s:2:"ׄ";i:230;s:2:"ׅ";i:220;s:2:"ׇ";i:18;s:2:"ؐ";i:230;s:2:"ؑ";i:230;s:2:"ؒ";i:230;s:2:"ؓ";i:230;s:2:"ؔ";i:230;s:2:"ؕ";i:230;s:2:"ً";i:27;s:2:"ٌ";i:28;s:2:"ٍ";i:29;s:2:"َ";i:30;s:2:"ُ";i:31;s:2:"ِ";i:32;s:2:"ّ";i:33;s:2:"ْ";i:34;s:2:"ٓ";i:230;s:2:"ٔ";i:230;s:2:"ٕ";i:220;s:2:"ٖ";i:220;s:2:"ٗ";i:230;s:2:"٘";i:230;s:2:"ٙ";i:230;s:2:"ٚ";i:230;s:2:"ٛ";i:230;s:2:"ٜ";i:220;s:2:"ٝ";i:230;s:2:"ٞ";i:230;s:2:"ٰ";i:35;s:2:"ۖ";i:230;s:2:"ۗ";i:230;s:2:"ۘ";i:230;s:2:"ۙ";i:230;s:2:"ۚ";i:230;s:2:"ۛ";i:230;s:2:"ۜ";i:230;s:2:"۟";i:230;s:2:"۠";i:230;s:2:"ۡ";i:230;s:2:"ۢ";i:230;s:2:"ۣ";i:220;s:2:"ۤ";i:230;s:2:"ۧ";i:230;s:2:"ۨ";i:230;s:2:"۪";i:220;s:2:"۫";i:230;s:2:"۬";i:230;s:2:"ۭ";i:220;s:2:"ܑ";i:36;s:2:"ܰ";i:230;s:2:"ܱ";i:220;s:2:"ܲ";i:230;s:2:"ܳ";i:230;s:2:"ܴ";i:220;s:2:"ܵ";i:230;s:2:"ܶ";i:230;s:2:"ܷ";i:220;s:2:"ܸ";i:220;s:2:"ܹ";i:220;s:2:"ܺ";i:230;s:2:"ܻ";i:220;s:2:"ܼ";i:220;s:2:"ܽ";i:230;s:2:"ܾ";i:220;s:2:"ܿ";i:230;s:2:"݀";i:230;s:2:"݁";i:230;s:2:"݂";i:220;s:2:"݃";i:230;s:2:"݄";i:220;s:2:"݅";i:230;s:2:"݆";i:220;s:2:"݇";i:230;s:2:"݈";i:220;s:2:"݉";i:230;s:2:"݊";i:230;s:3:"़";i:7;s:3:"्";i:9;s:3:"॑";i:230;s:3:"॒";i:220;s:3:"॓";i:230;s:3:"॔";i:230;s:3:"়";i:7;s:3:"্";i:9;s:3:"਼";i:7;s:3:"੍";i:9;s:3:"઼";i:7;s:3:"્";i:9;s:3:"଼";i:7;s:3:"୍";i:9;s:3:"்";i:9;s:3:"్";i:9;s:3:"ౕ";i:84;s:3:"ౖ";i:91;s:3:"಼";i:7;s:3:"್";i:9;s:3:"്";i:9;s:3:"්";i:9;s:3:"ุ";i:103;s:3:"ู";i:103;s:3:"ฺ";i:9;s:3:"่";i:107;s:3:"้";i:107;s:3:"๊";i:107;s:3:"๋";i:107;s:3:"ຸ";i:118;s:3:"ູ";i:118;s:3:"່";i:122;s:3:"້";i:122;s:3:"໊";i:122;s:3:"໋";i:122;s:3:"༘";i:220;s:3:"༙";i:220;s:3:"༵";i:220;s:3:"༷";i:220;s:3:"༹";i:216;s:3:"ཱ";i:129;s:3:"ི";i:130;s:3:"ུ";i:132;s:3:"ེ";i:130;s:3:"ཻ";i:130;s:3:"ོ";i:130;s:3:"ཽ";i:130;s:3:"ྀ";i:130;s:3:"ྂ";i:230;s:3:"ྃ";i:230;s:3:"྄";i:9;s:3:"྆";i:230;s:3:"྇";i:230;s:3:"࿆";i:220;s:3:"့";i:7;s:3:"္";i:9;s:3:"፟";i:230;s:3:"᜔";i:9;s:3:"᜴";i:9;s:3:"្";i:9;s:3:"៝";i:230;s:3:"ᢩ";i:228;s:3:"᤹";i:222;s:3:"᤺";i:230;s:3:"᤻";i:220;s:3:"ᨗ";i:230;s:3:"ᨘ";i:220;s:3:"᷀";i:230;s:3:"᷁";i:230;s:3:"᷂";i:220;s:3:"᷃";i:230;s:3:"⃐";i:230;s:3:"⃑";i:230;s:3:"⃒";i:1;s:3:"⃓";i:1;s:3:"⃔";i:230;s:3:"⃕";i:230;s:3:"⃖";i:230;s:3:"⃗";i:230;s:3:"⃘";i:1;s:3:"⃙";i:1;s:3:"⃚";i:1;s:3:"⃛";i:230;s:3:"⃜";i:230;s:3:"⃡";i:230;s:3:"⃥";i:1;s:3:"⃦";i:1;s:3:"⃧";i:230;s:3:"⃨";i:220;s:3:"⃩";i:230;s:3:"⃪";i:1;s:3:"⃫";i:1;s:3:"〪";i:218;s:3:"〫";i:228;s:3:"〬";i:232;s:3:"〭";i:222;s:3:"〮";i:224;s:3:"〯";i:224;s:3:"゙";i:8;s:3:"゚";i:8;s:3:"꠆";i:9;s:3:"ﬞ";i:26;s:3:"︠";i:230;s:3:"︡";i:230;s:3:"︢";i:230;s:3:"︣";i:230;s:4:"𐨍";i:220;s:4:"𐨏";i:230;s:4:"𐨸";i:230;s:4:"𐨹";i:1;s:4:"𐨺";i:220;s:4:"𐨿";i:9;s:4:"𝅥";i:216;s:4:"𝅦";i:216;s:4:"𝅧";i:1;s:4:"𝅨";i:1;s:4:"𝅩";i:1;s:4:"𝅭";i:226;s:4:"𝅮";i:216;s:4:"𝅯";i:216;s:4:"𝅰";i:216;s:4:"𝅱";i:216;s:4:"𝅲";i:216;s:4:"𝅻";i:220;s:4:"𝅼";i:220;s:4:"𝅽";i:220;s:4:"𝅾";i:220;s:4:"𝅿";i:220;s:4:"𝆀";i:220;s:4:"𝆁";i:220;s:4:"𝆂";i:220;s:4:"𝆅";i:230;s:4:"𝆆";i:230;s:4:"𝆇";i:230;s:4:"𝆈";i:230;s:4:"𝆉";i:230;s:4:"𝆊";i:220;s:4:"𝆋";i:220;s:4:"𝆪";i:230;s:4:"𝆫";i:230;s:4:"𝆬";i:230;s:4:"𝆭";i:230;s:4:"𝉂";i:230;s:4:"𝉃";i:230;s:4:"𝉄";i:230;}' );
+$utfCanonicalComp = unserialize( 'a:1851:{s:3:"À";s:2:"À";s:3:"Á";s:2:"Á";s:3:"Â";s:2:"Â";s:3:"Ã";s:2:"Ã";s:3:"Ä";s:2:"Ä";s:3:"Å";s:2:"Å";s:3:"Ç";s:2:"Ç";s:3:"È";s:2:"È";s:3:"É";s:2:"É";s:3:"Ê";s:2:"Ê";s:3:"Ë";s:2:"Ë";s:3:"Ì";s:2:"Ì";s:3:"Í";s:2:"Í";s:3:"Î";s:2:"Î";s:3:"Ï";s:2:"Ï";s:3:"Ñ";s:2:"Ñ";s:3:"Ò";s:2:"Ò";s:3:"Ó";s:2:"Ó";s:3:"Ô";s:2:"Ô";s:3:"Õ";s:2:"Õ";s:3:"Ö";s:2:"Ö";s:3:"Ù";s:2:"Ù";s:3:"Ú";s:2:"Ú";s:3:"Û";s:2:"Û";s:3:"Ü";s:2:"Ü";s:3:"Ý";s:2:"Ý";s:3:"à";s:2:"à";s:3:"á";s:2:"á";s:3:"â";s:2:"â";s:3:"ã";s:2:"ã";s:3:"ä";s:2:"ä";s:3:"å";s:2:"å";s:3:"ç";s:2:"ç";s:3:"è";s:2:"è";s:3:"é";s:2:"é";s:3:"ê";s:2:"ê";s:3:"ë";s:2:"ë";s:3:"ì";s:2:"ì";s:3:"í";s:2:"í";s:3:"î";s:2:"î";s:3:"ï";s:2:"ï";s:3:"ñ";s:2:"ñ";s:3:"ò";s:2:"ò";s:3:"ó";s:2:"ó";s:3:"ô";s:2:"ô";s:3:"õ";s:2:"õ";s:3:"ö";s:2:"ö";s:3:"ù";s:2:"ù";s:3:"ú";s:2:"ú";s:3:"û";s:2:"û";s:3:"ü";s:2:"ü";s:3:"ý";s:2:"ý";s:3:"ÿ";s:2:"ÿ";s:3:"Ā";s:2:"Ā";s:3:"ā";s:2:"ā";s:3:"Ă";s:2:"Ă";s:3:"ă";s:2:"ă";s:3:"Ą";s:2:"Ą";s:3:"ą";s:2:"ą";s:3:"Ć";s:2:"Ć";s:3:"ć";s:2:"ć";s:3:"Ĉ";s:2:"Ĉ";s:3:"ĉ";s:2:"ĉ";s:3:"Ċ";s:2:"Ċ";s:3:"ċ";s:2:"ċ";s:3:"Č";s:2:"Č";s:3:"č";s:2:"č";s:3:"Ď";s:2:"Ď";s:3:"ď";s:2:"ď";s:3:"Ē";s:2:"Ē";s:3:"ē";s:2:"ē";s:3:"Ĕ";s:2:"Ĕ";s:3:"ĕ";s:2:"ĕ";s:3:"Ė";s:2:"Ė";s:3:"ė";s:2:"ė";s:3:"Ę";s:2:"Ę";s:3:"ę";s:2:"ę";s:3:"Ě";s:2:"Ě";s:3:"ě";s:2:"ě";s:3:"Ĝ";s:2:"Ĝ";s:3:"ĝ";s:2:"ĝ";s:3:"Ğ";s:2:"Ğ";s:3:"ğ";s:2:"ğ";s:3:"Ġ";s:2:"Ġ";s:3:"ġ";s:2:"ġ";s:3:"Ģ";s:2:"Ģ";s:3:"ģ";s:2:"ģ";s:3:"Ĥ";s:2:"Ĥ";s:3:"ĥ";s:2:"ĥ";s:3:"Ĩ";s:2:"Ĩ";s:3:"ĩ";s:2:"ĩ";s:3:"Ī";s:2:"Ī";s:3:"ī";s:2:"ī";s:3:"Ĭ";s:2:"Ĭ";s:3:"ĭ";s:2:"ĭ";s:3:"Į";s:2:"Į";s:3:"į";s:2:"į";s:3:"İ";s:2:"İ";s:3:"Ĵ";s:2:"Ĵ";s:3:"ĵ";s:2:"ĵ";s:3:"Ķ";s:2:"Ķ";s:3:"ķ";s:2:"ķ";s:3:"Ĺ";s:2:"Ĺ";s:3:"ĺ";s:2:"ĺ";s:3:"Ļ";s:2:"Ļ";s:3:"ļ";s:2:"ļ";s:3:"Ľ";s:2:"Ľ";s:3:"ľ";s:2:"ľ";s:3:"Ń";s:2:"Ń";s:3:"ń";s:2:"ń";s:3:"Ņ";s:2:"Ņ";s:3:"ņ";s:2:"ņ";s:3:"Ň";s:2:"Ň";s:3:"ň";s:2:"ň";s:3:"Ō";s:2:"Ō";s:3:"ō";s:2:"ō";s:3:"Ŏ";s:2:"Ŏ";s:3:"ŏ";s:2:"ŏ";s:3:"Ő";s:2:"Ő";s:3:"ő";s:2:"ő";s:3:"Ŕ";s:2:"Ŕ";s:3:"ŕ";s:2:"ŕ";s:3:"Ŗ";s:2:"Ŗ";s:3:"ŗ";s:2:"ŗ";s:3:"Ř";s:2:"Ř";s:3:"ř";s:2:"ř";s:3:"Ś";s:2:"Ś";s:3:"ś";s:2:"ś";s:3:"Ŝ";s:2:"Ŝ";s:3:"ŝ";s:2:"ŝ";s:3:"Ş";s:2:"Ş";s:3:"ş";s:2:"ş";s:3:"Š";s:2:"Š";s:3:"š";s:2:"š";s:3:"Ţ";s:2:"Ţ";s:3:"ţ";s:2:"ţ";s:3:"Ť";s:2:"Ť";s:3:"ť";s:2:"ť";s:3:"Ũ";s:2:"Ũ";s:3:"ũ";s:2:"ũ";s:3:"Ū";s:2:"Ū";s:3:"ū";s:2:"ū";s:3:"Ŭ";s:2:"Ŭ";s:3:"ŭ";s:2:"ŭ";s:3:"Ů";s:2:"Ů";s:3:"ů";s:2:"ů";s:3:"Ű";s:2:"Ű";s:3:"ű";s:2:"ű";s:3:"Ų";s:2:"Ų";s:3:"ų";s:2:"ų";s:3:"Ŵ";s:2:"Ŵ";s:3:"ŵ";s:2:"ŵ";s:3:"Ŷ";s:2:"Ŷ";s:3:"ŷ";s:2:"ŷ";s:3:"Ÿ";s:2:"Ÿ";s:3:"Ź";s:2:"Ź";s:3:"ź";s:2:"ź";s:3:"Ż";s:2:"Ż";s:3:"ż";s:2:"ż";s:3:"Ž";s:2:"Ž";s:3:"ž";s:2:"ž";s:3:"Ơ";s:2:"Ơ";s:3:"ơ";s:2:"ơ";s:3:"Ư";s:2:"Ư";s:3:"ư";s:2:"ư";s:3:"Ǎ";s:2:"Ǎ";s:3:"ǎ";s:2:"ǎ";s:3:"Ǐ";s:2:"Ǐ";s:3:"ǐ";s:2:"ǐ";s:3:"Ǒ";s:2:"Ǒ";s:3:"ǒ";s:2:"ǒ";s:3:"Ǔ";s:2:"Ǔ";s:3:"ǔ";s:2:"ǔ";s:4:"Ǖ";s:2:"Ǖ";s:4:"ǖ";s:2:"ǖ";s:4:"Ǘ";s:2:"Ǘ";s:4:"ǘ";s:2:"ǘ";s:4:"Ǚ";s:2:"Ǚ";s:4:"ǚ";s:2:"ǚ";s:4:"Ǜ";s:2:"Ǜ";s:4:"ǜ";s:2:"ǜ";s:4:"Ǟ";s:2:"Ǟ";s:4:"ǟ";s:2:"ǟ";s:4:"Ǡ";s:2:"Ǡ";s:4:"ǡ";s:2:"ǡ";s:4:"Ǣ";s:2:"Ǣ";s:4:"ǣ";s:2:"ǣ";s:3:"Ǧ";s:2:"Ǧ";s:3:"ǧ";s:2:"ǧ";s:3:"Ǩ";s:2:"Ǩ";s:3:"ǩ";s:2:"ǩ";s:3:"Ǫ";s:2:"Ǫ";s:3:"ǫ";s:2:"ǫ";s:4:"Ǭ";s:2:"Ǭ";s:4:"ǭ";s:2:"ǭ";s:4:"Ǯ";s:2:"Ǯ";s:4:"ǯ";s:2:"ǯ";s:3:"ǰ";s:2:"ǰ";s:3:"Ǵ";s:2:"Ǵ";s:3:"ǵ";s:2:"ǵ";s:3:"Ǹ";s:2:"Ǹ";s:3:"ǹ";s:2:"ǹ";s:4:"Ǻ";s:2:"Ǻ";s:4:"ǻ";s:2:"ǻ";s:4:"Ǽ";s:2:"Ǽ";s:4:"ǽ";s:2:"ǽ";s:4:"Ǿ";s:2:"Ǿ";s:4:"ǿ";s:2:"ǿ";s:3:"Ȁ";s:2:"Ȁ";s:3:"ȁ";s:2:"ȁ";s:3:"Ȃ";s:2:"Ȃ";s:3:"ȃ";s:2:"ȃ";s:3:"Ȅ";s:2:"Ȅ";s:3:"ȅ";s:2:"ȅ";s:3:"Ȇ";s:2:"Ȇ";s:3:"ȇ";s:2:"ȇ";s:3:"Ȉ";s:2:"Ȉ";s:3:"ȉ";s:2:"ȉ";s:3:"Ȋ";s:2:"Ȋ";s:3:"ȋ";s:2:"ȋ";s:3:"Ȍ";s:2:"Ȍ";s:3:"ȍ";s:2:"ȍ";s:3:"Ȏ";s:2:"Ȏ";s:3:"ȏ";s:2:"ȏ";s:3:"Ȑ";s:2:"Ȑ";s:3:"ȑ";s:2:"ȑ";s:3:"Ȓ";s:2:"Ȓ";s:3:"ȓ";s:2:"ȓ";s:3:"Ȕ";s:2:"Ȕ";s:3:"ȕ";s:2:"ȕ";s:3:"Ȗ";s:2:"Ȗ";s:3:"ȗ";s:2:"ȗ";s:3:"Ș";s:2:"Ș";s:3:"ș";s:2:"ș";s:3:"Ț";s:2:"Ț";s:3:"ț";s:2:"ț";s:3:"Ȟ";s:2:"Ȟ";s:3:"ȟ";s:2:"ȟ";s:3:"Ȧ";s:2:"Ȧ";s:3:"ȧ";s:2:"ȧ";s:3:"Ȩ";s:2:"Ȩ";s:3:"ȩ";s:2:"ȩ";s:4:"Ȫ";s:2:"Ȫ";s:4:"ȫ";s:2:"ȫ";s:4:"Ȭ";s:2:"Ȭ";s:4:"ȭ";s:2:"ȭ";s:3:"Ȯ";s:2:"Ȯ";s:3:"ȯ";s:2:"ȯ";s:4:"Ȱ";s:2:"Ȱ";s:4:"ȱ";s:2:"ȱ";s:3:"Ȳ";s:2:"Ȳ";s:3:"ȳ";s:2:"ȳ";s:2:"̀";s:2:"̀";s:2:"́";s:2:"́";s:2:"̓";s:2:"̓";s:4:"̈́";s:2:"̈́";s:2:"ʹ";s:2:"ʹ";s:1:";";s:2:";";s:4:"΅";s:2:"΅";s:4:"Ά";s:2:"Ά";s:2:"·";s:2:"·";s:4:"Έ";s:2:"Έ";s:4:"Ή";s:2:"Ή";s:4:"Ί";s:2:"Ί";s:4:"Ό";s:2:"Ό";s:4:"Ύ";s:2:"Ύ";s:4:"Ώ";s:2:"Ώ";s:4:"ΐ";s:2:"ΐ";s:4:"Ϊ";s:2:"Ϊ";s:4:"Ϋ";s:2:"Ϋ";s:4:"ά";s:2:"ά";s:4:"έ";s:2:"έ";s:4:"ή";s:2:"ή";s:4:"ί";s:2:"ί";s:4:"ΰ";s:2:"ΰ";s:4:"ϊ";s:2:"ϊ";s:4:"ϋ";s:2:"ϋ";s:4:"ό";s:2:"ό";s:4:"ύ";s:2:"ύ";s:4:"ώ";s:2:"ώ";s:4:"ϓ";s:2:"ϓ";s:4:"ϔ";s:2:"ϔ";s:4:"Ѐ";s:2:"Ѐ";s:4:"Ё";s:2:"Ё";s:4:"Ѓ";s:2:"Ѓ";s:4:"Ї";s:2:"Ї";s:4:"Ќ";s:2:"Ќ";s:4:"Ѝ";s:2:"Ѝ";s:4:"Ў";s:2:"Ў";s:4:"Й";s:2:"Й";s:4:"й";s:2:"й";s:4:"ѐ";s:2:"ѐ";s:4:"ё";s:2:"ё";s:4:"ѓ";s:2:"ѓ";s:4:"ї";s:2:"ї";s:4:"ќ";s:2:"ќ";s:4:"ѝ";s:2:"ѝ";s:4:"ў";s:2:"ў";s:4:"Ѷ";s:2:"Ѷ";s:4:"ѷ";s:2:"ѷ";s:4:"Ӂ";s:2:"Ӂ";s:4:"ӂ";s:2:"ӂ";s:4:"Ӑ";s:2:"Ӑ";s:4:"ӑ";s:2:"ӑ";s:4:"Ӓ";s:2:"Ӓ";s:4:"ӓ";s:2:"ӓ";s:4:"Ӗ";s:2:"Ӗ";s:4:"ӗ";s:2:"ӗ";s:4:"Ӛ";s:2:"Ӛ";s:4:"ӛ";s:2:"ӛ";s:4:"Ӝ";s:2:"Ӝ";s:4:"ӝ";s:2:"ӝ";s:4:"Ӟ";s:2:"Ӟ";s:4:"ӟ";s:2:"ӟ";s:4:"Ӣ";s:2:"Ӣ";s:4:"ӣ";s:2:"ӣ";s:4:"Ӥ";s:2:"Ӥ";s:4:"ӥ";s:2:"ӥ";s:4:"Ӧ";s:2:"Ӧ";s:4:"ӧ";s:2:"ӧ";s:4:"Ӫ";s:2:"Ӫ";s:4:"ӫ";s:2:"ӫ";s:4:"Ӭ";s:2:"Ӭ";s:4:"ӭ";s:2:"ӭ";s:4:"Ӯ";s:2:"Ӯ";s:4:"ӯ";s:2:"ӯ";s:4:"Ӱ";s:2:"Ӱ";s:4:"ӱ";s:2:"ӱ";s:4:"Ӳ";s:2:"Ӳ";s:4:"ӳ";s:2:"ӳ";s:4:"Ӵ";s:2:"Ӵ";s:4:"ӵ";s:2:"ӵ";s:4:"Ӹ";s:2:"Ӹ";s:4:"ӹ";s:2:"ӹ";s:4:"آ";s:2:"آ";s:4:"أ";s:2:"أ";s:4:"ؤ";s:2:"ؤ";s:4:"إ";s:2:"إ";s:4:"ئ";s:2:"ئ";s:4:"ۀ";s:2:"ۀ";s:4:"ۂ";s:2:"ۂ";s:4:"ۓ";s:2:"ۓ";s:6:"ऩ";s:3:"ऩ";s:6:"ऱ";s:3:"ऱ";s:6:"ऴ";s:3:"ऴ";s:6:"ো";s:3:"ো";s:6:"ৌ";s:3:"ৌ";s:6:"ୈ";s:3:"ୈ";s:6:"ୋ";s:3:"ୋ";s:6:"ୌ";s:3:"ୌ";s:6:"ஔ";s:3:"ஔ";s:6:"ொ";s:3:"ொ";s:6:"ோ";s:3:"ோ";s:6:"ௌ";s:3:"ௌ";s:6:"ై";s:3:"ై";s:6:"ೀ";s:3:"ೀ";s:6:"ೇ";s:3:"ೇ";s:6:"ೈ";s:3:"ೈ";s:6:"ೊ";s:3:"ೊ";s:6:"ೋ";s:3:"ೋ";s:6:"ൊ";s:3:"ൊ";s:6:"ോ";s:3:"ോ";s:6:"ൌ";s:3:"ൌ";s:6:"ේ";s:3:"ේ";s:6:"ො";s:3:"ො";s:6:"ෝ";s:3:"ෝ";s:6:"ෞ";s:3:"ෞ";s:6:"ཱི";s:3:"ཱི";s:6:"ཱུ";s:3:"ཱུ";s:6:"ཱྀ";s:3:"ཱྀ";s:6:"ဦ";s:3:"ဦ";s:3:"Ḁ";s:3:"Ḁ";s:3:"ḁ";s:3:"ḁ";s:3:"Ḃ";s:3:"Ḃ";s:3:"ḃ";s:3:"ḃ";s:3:"Ḅ";s:3:"Ḅ";s:3:"ḅ";s:3:"ḅ";s:3:"Ḇ";s:3:"Ḇ";s:3:"ḇ";s:3:"ḇ";s:4:"Ḉ";s:3:"Ḉ";s:4:"ḉ";s:3:"ḉ";s:3:"Ḋ";s:3:"Ḋ";s:3:"ḋ";s:3:"ḋ";s:3:"Ḍ";s:3:"Ḍ";s:3:"ḍ";s:3:"ḍ";s:3:"Ḏ";s:3:"Ḏ";s:3:"ḏ";s:3:"ḏ";s:3:"Ḑ";s:3:"Ḑ";s:3:"ḑ";s:3:"ḑ";s:3:"Ḓ";s:3:"Ḓ";s:3:"ḓ";s:3:"ḓ";s:4:"Ḕ";s:3:"Ḕ";s:4:"ḕ";s:3:"ḕ";s:4:"Ḗ";s:3:"Ḗ";s:4:"ḗ";s:3:"ḗ";s:3:"Ḙ";s:3:"Ḙ";s:3:"ḙ";s:3:"ḙ";s:3:"Ḛ";s:3:"Ḛ";s:3:"ḛ";s:3:"ḛ";s:4:"Ḝ";s:3:"Ḝ";s:4:"ḝ";s:3:"ḝ";s:3:"Ḟ";s:3:"Ḟ";s:3:"ḟ";s:3:"ḟ";s:3:"Ḡ";s:3:"Ḡ";s:3:"ḡ";s:3:"ḡ";s:3:"Ḣ";s:3:"Ḣ";s:3:"ḣ";s:3:"ḣ";s:3:"Ḥ";s:3:"Ḥ";s:3:"ḥ";s:3:"ḥ";s:3:"Ḧ";s:3:"Ḧ";s:3:"ḧ";s:3:"ḧ";s:3:"Ḩ";s:3:"Ḩ";s:3:"ḩ";s:3:"ḩ";s:3:"Ḫ";s:3:"Ḫ";s:3:"ḫ";s:3:"ḫ";s:3:"Ḭ";s:3:"Ḭ";s:3:"ḭ";s:3:"ḭ";s:4:"Ḯ";s:3:"Ḯ";s:4:"ḯ";s:3:"ḯ";s:3:"Ḱ";s:3:"Ḱ";s:3:"ḱ";s:3:"ḱ";s:3:"Ḳ";s:3:"Ḳ";s:3:"ḳ";s:3:"ḳ";s:3:"Ḵ";s:3:"Ḵ";s:3:"ḵ";s:3:"ḵ";s:3:"Ḷ";s:3:"Ḷ";s:3:"ḷ";s:3:"ḷ";s:5:"Ḹ";s:3:"Ḹ";s:5:"ḹ";s:3:"ḹ";s:3:"Ḻ";s:3:"Ḻ";s:3:"ḻ";s:3:"ḻ";s:3:"Ḽ";s:3:"Ḽ";s:3:"ḽ";s:3:"ḽ";s:3:"Ḿ";s:3:"Ḿ";s:3:"ḿ";s:3:"ḿ";s:3:"Ṁ";s:3:"Ṁ";s:3:"ṁ";s:3:"ṁ";s:3:"Ṃ";s:3:"Ṃ";s:3:"ṃ";s:3:"ṃ";s:3:"Ṅ";s:3:"Ṅ";s:3:"ṅ";s:3:"ṅ";s:3:"Ṇ";s:3:"Ṇ";s:3:"ṇ";s:3:"ṇ";s:3:"Ṉ";s:3:"Ṉ";s:3:"ṉ";s:3:"ṉ";s:3:"Ṋ";s:3:"Ṋ";s:3:"ṋ";s:3:"ṋ";s:4:"Ṍ";s:3:"Ṍ";s:4:"ṍ";s:3:"ṍ";s:4:"Ṏ";s:3:"Ṏ";s:4:"ṏ";s:3:"ṏ";s:4:"Ṑ";s:3:"Ṑ";s:4:"ṑ";s:3:"ṑ";s:4:"Ṓ";s:3:"Ṓ";s:4:"ṓ";s:3:"ṓ";s:3:"Ṕ";s:3:"Ṕ";s:3:"ṕ";s:3:"ṕ";s:3:"Ṗ";s:3:"Ṗ";s:3:"ṗ";s:3:"ṗ";s:3:"Ṙ";s:3:"Ṙ";s:3:"ṙ";s:3:"ṙ";s:3:"Ṛ";s:3:"Ṛ";s:3:"ṛ";s:3:"ṛ";s:5:"Ṝ";s:3:"Ṝ";s:5:"ṝ";s:3:"ṝ";s:3:"Ṟ";s:3:"Ṟ";s:3:"ṟ";s:3:"ṟ";s:3:"Ṡ";s:3:"Ṡ";s:3:"ṡ";s:3:"ṡ";s:3:"Ṣ";s:3:"Ṣ";s:3:"ṣ";s:3:"ṣ";s:4:"Ṥ";s:3:"Ṥ";s:4:"ṥ";s:3:"ṥ";s:4:"Ṧ";s:3:"Ṧ";s:4:"ṧ";s:3:"ṧ";s:5:"Ṩ";s:3:"Ṩ";s:5:"ṩ";s:3:"ṩ";s:3:"Ṫ";s:3:"Ṫ";s:3:"ṫ";s:3:"ṫ";s:3:"Ṭ";s:3:"Ṭ";s:3:"ṭ";s:3:"ṭ";s:3:"Ṯ";s:3:"Ṯ";s:3:"ṯ";s:3:"ṯ";s:3:"Ṱ";s:3:"Ṱ";s:3:"ṱ";s:3:"ṱ";s:3:"Ṳ";s:3:"Ṳ";s:3:"ṳ";s:3:"ṳ";s:3:"Ṵ";s:3:"Ṵ";s:3:"ṵ";s:3:"ṵ";s:3:"Ṷ";s:3:"Ṷ";s:3:"ṷ";s:3:"ṷ";s:4:"Ṹ";s:3:"Ṹ";s:4:"ṹ";s:3:"ṹ";s:4:"Ṻ";s:3:"Ṻ";s:4:"ṻ";s:3:"ṻ";s:3:"Ṽ";s:3:"Ṽ";s:3:"ṽ";s:3:"ṽ";s:3:"Ṿ";s:3:"Ṿ";s:3:"ṿ";s:3:"ṿ";s:3:"Ẁ";s:3:"Ẁ";s:3:"ẁ";s:3:"ẁ";s:3:"Ẃ";s:3:"Ẃ";s:3:"ẃ";s:3:"ẃ";s:3:"Ẅ";s:3:"Ẅ";s:3:"ẅ";s:3:"ẅ";s:3:"Ẇ";s:3:"Ẇ";s:3:"ẇ";s:3:"ẇ";s:3:"Ẉ";s:3:"Ẉ";s:3:"ẉ";s:3:"ẉ";s:3:"Ẋ";s:3:"Ẋ";s:3:"ẋ";s:3:"ẋ";s:3:"Ẍ";s:3:"Ẍ";s:3:"ẍ";s:3:"ẍ";s:3:"Ẏ";s:3:"Ẏ";s:3:"ẏ";s:3:"ẏ";s:3:"Ẑ";s:3:"Ẑ";s:3:"ẑ";s:3:"ẑ";s:3:"Ẓ";s:3:"Ẓ";s:3:"ẓ";s:3:"ẓ";s:3:"Ẕ";s:3:"Ẕ";s:3:"ẕ";s:3:"ẕ";s:3:"ẖ";s:3:"ẖ";s:3:"ẗ";s:3:"ẗ";s:3:"ẘ";s:3:"ẘ";s:3:"ẙ";s:3:"ẙ";s:4:"ẛ";s:3:"ẛ";s:3:"Ạ";s:3:"Ạ";s:3:"ạ";s:3:"ạ";s:3:"Ả";s:3:"Ả";s:3:"ả";s:3:"ả";s:4:"Ấ";s:3:"Ấ";s:4:"ấ";s:3:"ấ";s:4:"Ầ";s:3:"Ầ";s:4:"ầ";s:3:"ầ";s:4:"Ẩ";s:3:"Ẩ";s:4:"ẩ";s:3:"ẩ";s:4:"Ẫ";s:3:"Ẫ";s:4:"ẫ";s:3:"ẫ";s:5:"Ậ";s:3:"Ậ";s:5:"ậ";s:3:"ậ";s:4:"Ắ";s:3:"Ắ";s:4:"ắ";s:3:"ắ";s:4:"Ằ";s:3:"Ằ";s:4:"ằ";s:3:"ằ";s:4:"Ẳ";s:3:"Ẳ";s:4:"ẳ";s:3:"ẳ";s:4:"Ẵ";s:3:"Ẵ";s:4:"ẵ";s:3:"ẵ";s:5:"Ặ";s:3:"Ặ";s:5:"ặ";s:3:"ặ";s:3:"Ẹ";s:3:"Ẹ";s:3:"ẹ";s:3:"ẹ";s:3:"Ẻ";s:3:"Ẻ";s:3:"ẻ";s:3:"ẻ";s:3:"Ẽ";s:3:"Ẽ";s:3:"ẽ";s:3:"ẽ";s:4:"Ế";s:3:"Ế";s:4:"ế";s:3:"ế";s:4:"Ề";s:3:"Ề";s:4:"ề";s:3:"ề";s:4:"Ể";s:3:"Ể";s:4:"ể";s:3:"ể";s:4:"Ễ";s:3:"Ễ";s:4:"ễ";s:3:"ễ";s:5:"Ệ";s:3:"Ệ";s:5:"ệ";s:3:"ệ";s:3:"Ỉ";s:3:"Ỉ";s:3:"ỉ";s:3:"ỉ";s:3:"Ị";s:3:"Ị";s:3:"ị";s:3:"ị";s:3:"Ọ";s:3:"Ọ";s:3:"ọ";s:3:"ọ";s:3:"Ỏ";s:3:"Ỏ";s:3:"ỏ";s:3:"ỏ";s:4:"Ố";s:3:"Ố";s:4:"ố";s:3:"ố";s:4:"Ồ";s:3:"Ồ";s:4:"ồ";s:3:"ồ";s:4:"Ổ";s:3:"Ổ";s:4:"ổ";s:3:"ổ";s:4:"Ỗ";s:3:"Ỗ";s:4:"ỗ";s:3:"ỗ";s:5:"Ộ";s:3:"Ộ";s:5:"ộ";s:3:"ộ";s:4:"Ớ";s:3:"Ớ";s:4:"ớ";s:3:"ớ";s:4:"Ờ";s:3:"Ờ";s:4:"ờ";s:3:"ờ";s:4:"Ở";s:3:"Ở";s:4:"ở";s:3:"ở";s:4:"Ỡ";s:3:"Ỡ";s:4:"ỡ";s:3:"ỡ";s:4:"Ợ";s:3:"Ợ";s:4:"ợ";s:3:"ợ";s:3:"Ụ";s:3:"Ụ";s:3:"ụ";s:3:"ụ";s:3:"Ủ";s:3:"Ủ";s:3:"ủ";s:3:"ủ";s:4:"Ứ";s:3:"Ứ";s:4:"ứ";s:3:"ứ";s:4:"Ừ";s:3:"Ừ";s:4:"ừ";s:3:"ừ";s:4:"Ử";s:3:"Ử";s:4:"ử";s:3:"ử";s:4:"Ữ";s:3:"Ữ";s:4:"ữ";s:3:"ữ";s:4:"Ự";s:3:"Ự";s:4:"ự";s:3:"ự";s:3:"Ỳ";s:3:"Ỳ";s:3:"ỳ";s:3:"ỳ";s:3:"Ỵ";s:3:"Ỵ";s:3:"ỵ";s:3:"ỵ";s:3:"Ỷ";s:3:"Ỷ";s:3:"ỷ";s:3:"ỷ";s:3:"Ỹ";s:3:"Ỹ";s:3:"ỹ";s:3:"ỹ";s:4:"ἀ";s:3:"ἀ";s:4:"ἁ";s:3:"ἁ";s:5:"ἂ";s:3:"ἂ";s:5:"ἃ";s:3:"ἃ";s:5:"ἄ";s:3:"ἄ";s:5:"ἅ";s:3:"ἅ";s:5:"ἆ";s:3:"ἆ";s:5:"ἇ";s:3:"ἇ";s:4:"Ἀ";s:3:"Ἀ";s:4:"Ἁ";s:3:"Ἁ";s:5:"Ἂ";s:3:"Ἂ";s:5:"Ἃ";s:3:"Ἃ";s:5:"Ἄ";s:3:"Ἄ";s:5:"Ἅ";s:3:"Ἅ";s:5:"Ἆ";s:3:"Ἆ";s:5:"Ἇ";s:3:"Ἇ";s:4:"ἐ";s:3:"ἐ";s:4:"ἑ";s:3:"ἑ";s:5:"ἒ";s:3:"ἒ";s:5:"ἓ";s:3:"ἓ";s:5:"ἔ";s:3:"ἔ";s:5:"ἕ";s:3:"ἕ";s:4:"Ἐ";s:3:"Ἐ";s:4:"Ἑ";s:3:"Ἑ";s:5:"Ἒ";s:3:"Ἒ";s:5:"Ἓ";s:3:"Ἓ";s:5:"Ἔ";s:3:"Ἔ";s:5:"Ἕ";s:3:"Ἕ";s:4:"ἠ";s:3:"ἠ";s:4:"ἡ";s:3:"ἡ";s:5:"ἢ";s:3:"ἢ";s:5:"ἣ";s:3:"ἣ";s:5:"ἤ";s:3:"ἤ";s:5:"ἥ";s:3:"ἥ";s:5:"ἦ";s:3:"ἦ";s:5:"ἧ";s:3:"ἧ";s:4:"Ἠ";s:3:"Ἠ";s:4:"Ἡ";s:3:"Ἡ";s:5:"Ἢ";s:3:"Ἢ";s:5:"Ἣ";s:3:"Ἣ";s:5:"Ἤ";s:3:"Ἤ";s:5:"Ἥ";s:3:"Ἥ";s:5:"Ἦ";s:3:"Ἦ";s:5:"Ἧ";s:3:"Ἧ";s:4:"ἰ";s:3:"ἰ";s:4:"ἱ";s:3:"ἱ";s:5:"ἲ";s:3:"ἲ";s:5:"ἳ";s:3:"ἳ";s:5:"ἴ";s:3:"ἴ";s:5:"ἵ";s:3:"ἵ";s:5:"ἶ";s:3:"ἶ";s:5:"ἷ";s:3:"ἷ";s:4:"Ἰ";s:3:"Ἰ";s:4:"Ἱ";s:3:"Ἱ";s:5:"Ἲ";s:3:"Ἲ";s:5:"Ἳ";s:3:"Ἳ";s:5:"Ἴ";s:3:"Ἴ";s:5:"Ἵ";s:3:"Ἵ";s:5:"Ἶ";s:3:"Ἶ";s:5:"Ἷ";s:3:"Ἷ";s:4:"ὀ";s:3:"ὀ";s:4:"ὁ";s:3:"ὁ";s:5:"ὂ";s:3:"ὂ";s:5:"ὃ";s:3:"ὃ";s:5:"ὄ";s:3:"ὄ";s:5:"ὅ";s:3:"ὅ";s:4:"Ὀ";s:3:"Ὀ";s:4:"Ὁ";s:3:"Ὁ";s:5:"Ὂ";s:3:"Ὂ";s:5:"Ὃ";s:3:"Ὃ";s:5:"Ὄ";s:3:"Ὄ";s:5:"Ὅ";s:3:"Ὅ";s:4:"ὐ";s:3:"ὐ";s:4:"ὑ";s:3:"ὑ";s:5:"ὒ";s:3:"ὒ";s:5:"ὓ";s:3:"ὓ";s:5:"ὔ";s:3:"ὔ";s:5:"ὕ";s:3:"ὕ";s:5:"ὖ";s:3:"ὖ";s:5:"ὗ";s:3:"ὗ";s:4:"Ὑ";s:3:"Ὑ";s:5:"Ὓ";s:3:"Ὓ";s:5:"Ὕ";s:3:"Ὕ";s:5:"Ὗ";s:3:"Ὗ";s:4:"ὠ";s:3:"ὠ";s:4:"ὡ";s:3:"ὡ";s:5:"ὢ";s:3:"ὢ";s:5:"ὣ";s:3:"ὣ";s:5:"ὤ";s:3:"ὤ";s:5:"ὥ";s:3:"ὥ";s:5:"ὦ";s:3:"ὦ";s:5:"ὧ";s:3:"ὧ";s:4:"Ὠ";s:3:"Ὠ";s:4:"Ὡ";s:3:"Ὡ";s:5:"Ὢ";s:3:"Ὢ";s:5:"Ὣ";s:3:"Ὣ";s:5:"Ὤ";s:3:"Ὤ";s:5:"Ὥ";s:3:"Ὥ";s:5:"Ὦ";s:3:"Ὦ";s:5:"Ὧ";s:3:"Ὧ";s:4:"ὰ";s:3:"ὰ";s:2:"ά";s:3:"ά";s:4:"ὲ";s:3:"ὲ";s:2:"έ";s:3:"έ";s:4:"ὴ";s:3:"ὴ";s:2:"ή";s:3:"ή";s:4:"ὶ";s:3:"ὶ";s:2:"ί";s:3:"ί";s:4:"ὸ";s:3:"ὸ";s:2:"ό";s:3:"ό";s:4:"ὺ";s:3:"ὺ";s:2:"ύ";s:3:"ύ";s:4:"ὼ";s:3:"ὼ";s:2:"ώ";s:3:"ώ";s:5:"ᾀ";s:3:"ᾀ";s:5:"ᾁ";s:3:"ᾁ";s:5:"ᾂ";s:3:"ᾂ";s:5:"ᾃ";s:3:"ᾃ";s:5:"ᾄ";s:3:"ᾄ";s:5:"ᾅ";s:3:"ᾅ";s:5:"ᾆ";s:3:"ᾆ";s:5:"ᾇ";s:3:"ᾇ";s:5:"ᾈ";s:3:"ᾈ";s:5:"ᾉ";s:3:"ᾉ";s:5:"ᾊ";s:3:"ᾊ";s:5:"ᾋ";s:3:"ᾋ";s:5:"ᾌ";s:3:"ᾌ";s:5:"ᾍ";s:3:"ᾍ";s:5:"ᾎ";s:3:"ᾎ";s:5:"ᾏ";s:3:"ᾏ";s:5:"ᾐ";s:3:"ᾐ";s:5:"ᾑ";s:3:"ᾑ";s:5:"ᾒ";s:3:"ᾒ";s:5:"ᾓ";s:3:"ᾓ";s:5:"ᾔ";s:3:"ᾔ";s:5:"ᾕ";s:3:"ᾕ";s:5:"ᾖ";s:3:"ᾖ";s:5:"ᾗ";s:3:"ᾗ";s:5:"ᾘ";s:3:"ᾘ";s:5:"ᾙ";s:3:"ᾙ";s:5:"ᾚ";s:3:"ᾚ";s:5:"ᾛ";s:3:"ᾛ";s:5:"ᾜ";s:3:"ᾜ";s:5:"ᾝ";s:3:"ᾝ";s:5:"ᾞ";s:3:"ᾞ";s:5:"ᾟ";s:3:"ᾟ";s:5:"ᾠ";s:3:"ᾠ";s:5:"ᾡ";s:3:"ᾡ";s:5:"ᾢ";s:3:"ᾢ";s:5:"ᾣ";s:3:"ᾣ";s:5:"ᾤ";s:3:"ᾤ";s:5:"ᾥ";s:3:"ᾥ";s:5:"ᾦ";s:3:"ᾦ";s:5:"ᾧ";s:3:"ᾧ";s:5:"ᾨ";s:3:"ᾨ";s:5:"ᾩ";s:3:"ᾩ";s:5:"ᾪ";s:3:"ᾪ";s:5:"ᾫ";s:3:"ᾫ";s:5:"ᾬ";s:3:"ᾬ";s:5:"ᾭ";s:3:"ᾭ";s:5:"ᾮ";s:3:"ᾮ";s:5:"ᾯ";s:3:"ᾯ";s:4:"ᾰ";s:3:"ᾰ";s:4:"ᾱ";s:3:"ᾱ";s:5:"ᾲ";s:3:"ᾲ";s:4:"ᾳ";s:3:"ᾳ";s:4:"ᾴ";s:3:"ᾴ";s:4:"ᾶ";s:3:"ᾶ";s:5:"ᾷ";s:3:"ᾷ";s:4:"Ᾰ";s:3:"Ᾰ";s:4:"Ᾱ";s:3:"Ᾱ";s:4:"Ὰ";s:3:"Ὰ";s:2:"Ά";s:3:"Ά";s:4:"ᾼ";s:3:"ᾼ";s:2:"ι";s:3:"ι";s:4:"῁";s:3:"῁";s:5:"ῂ";s:3:"ῂ";s:4:"ῃ";s:3:"ῃ";s:4:"ῄ";s:3:"ῄ";s:4:"ῆ";s:3:"ῆ";s:5:"ῇ";s:3:"ῇ";s:4:"Ὲ";s:3:"Ὲ";s:2:"Έ";s:3:"Έ";s:4:"Ὴ";s:3:"Ὴ";s:2:"Ή";s:3:"Ή";s:4:"ῌ";s:3:"ῌ";s:5:"῍";s:3:"῍";s:5:"῎";s:3:"῎";s:5:"῏";s:3:"῏";s:4:"ῐ";s:3:"ῐ";s:4:"ῑ";s:3:"ῑ";s:4:"ῒ";s:3:"ῒ";s:2:"ΐ";s:3:"ΐ";s:4:"ῖ";s:3:"ῖ";s:4:"ῗ";s:3:"ῗ";s:4:"Ῐ";s:3:"Ῐ";s:4:"Ῑ";s:3:"Ῑ";s:4:"Ὶ";s:3:"Ὶ";s:2:"Ί";s:3:"Ί";s:5:"῝";s:3:"῝";s:5:"῞";s:3:"῞";s:5:"῟";s:3:"῟";s:4:"ῠ";s:3:"ῠ";s:4:"ῡ";s:3:"ῡ";s:4:"ῢ";s:3:"ῢ";s:2:"ΰ";s:3:"ΰ";s:4:"ῤ";s:3:"ῤ";s:4:"ῥ";s:3:"ῥ";s:4:"ῦ";s:3:"ῦ";s:4:"ῧ";s:3:"ῧ";s:4:"Ῠ";s:3:"Ῠ";s:4:"Ῡ";s:3:"Ῡ";s:4:"Ὺ";s:3:"Ὺ";s:2:"Ύ";s:3:"Ύ";s:4:"Ῥ";s:3:"Ῥ";s:4:"῭";s:3:"῭";s:2:"΅";s:3:"΅";s:1:"`";s:3:"`";s:5:"ῲ";s:3:"ῲ";s:4:"ῳ";s:3:"ῳ";s:4:"ῴ";s:3:"ῴ";s:4:"ῶ";s:3:"ῶ";s:5:"ῷ";s:3:"ῷ";s:4:"Ὸ";s:3:"Ὸ";s:2:"Ό";s:3:"Ό";s:4:"Ὼ";s:3:"Ὼ";s:2:"Ώ";s:3:"Ώ";s:4:"ῼ";s:3:"ῼ";s:2:"´";s:3:"´";s:3:" ";s:3:" ";s:3:" ";s:3:" ";s:2:"Ω";s:3:"Ω";s:1:"K";s:3:"K";s:2:"Å";s:3:"Å";s:5:"↚";s:3:"↚";s:5:"↛";s:3:"↛";s:5:"↮";s:3:"↮";s:5:"⇍";s:3:"⇍";s:5:"⇎";s:3:"⇎";s:5:"⇏";s:3:"⇏";s:5:"∄";s:3:"∄";s:5:"∉";s:3:"∉";s:5:"∌";s:3:"∌";s:5:"∤";s:3:"∤";s:5:"∦";s:3:"∦";s:5:"≁";s:3:"≁";s:5:"≄";s:3:"≄";s:5:"≇";s:3:"≇";s:5:"≉";s:3:"≉";s:3:"≠";s:3:"≠";s:5:"≢";s:3:"≢";s:5:"≭";s:3:"≭";s:3:"≮";s:3:"≮";s:3:"≯";s:3:"≯";s:5:"≰";s:3:"≰";s:5:"≱";s:3:"≱";s:5:"≴";s:3:"≴";s:5:"≵";s:3:"≵";s:5:"≸";s:3:"≸";s:5:"≹";s:3:"≹";s:5:"⊀";s:3:"⊀";s:5:"⊁";s:3:"⊁";s:5:"⊄";s:3:"⊄";s:5:"⊅";s:3:"⊅";s:5:"⊈";s:3:"⊈";s:5:"⊉";s:3:"⊉";s:5:"⊬";s:3:"⊬";s:5:"⊭";s:3:"⊭";s:5:"⊮";s:3:"⊮";s:5:"⊯";s:3:"⊯";s:5:"⋠";s:3:"⋠";s:5:"⋡";s:3:"⋡";s:5:"⋢";s:3:"⋢";s:5:"⋣";s:3:"⋣";s:5:"⋪";s:3:"⋪";s:5:"⋫";s:3:"⋫";s:5:"⋬";s:3:"⋬";s:5:"⋭";s:3:"⋭";s:3:"〈";s:3:"〈";s:3:"〉";s:3:"〉";s:6:"が";s:3:"が";s:6:"ぎ";s:3:"ぎ";s:6:"ぐ";s:3:"ぐ";s:6:"げ";s:3:"げ";s:6:"ご";s:3:"ご";s:6:"ざ";s:3:"ざ";s:6:"じ";s:3:"じ";s:6:"ず";s:3:"ず";s:6:"ぜ";s:3:"ぜ";s:6:"ぞ";s:3:"ぞ";s:6:"だ";s:3:"だ";s:6:"ぢ";s:3:"ぢ";s:6:"づ";s:3:"づ";s:6:"で";s:3:"で";s:6:"ど";s:3:"ど";s:6:"ば";s:3:"ば";s:6:"ぱ";s:3:"ぱ";s:6:"び";s:3:"び";s:6:"ぴ";s:3:"ぴ";s:6:"ぶ";s:3:"ぶ";s:6:"ぷ";s:3:"ぷ";s:6:"べ";s:3:"べ";s:6:"ぺ";s:3:"ぺ";s:6:"ぼ";s:3:"ぼ";s:6:"ぽ";s:3:"ぽ";s:6:"ゔ";s:3:"ゔ";s:6:"ゞ";s:3:"ゞ";s:6:"ガ";s:3:"ガ";s:6:"ギ";s:3:"ギ";s:6:"グ";s:3:"グ";s:6:"ゲ";s:3:"ゲ";s:6:"ゴ";s:3:"ゴ";s:6:"ザ";s:3:"ザ";s:6:"ジ";s:3:"ジ";s:6:"ズ";s:3:"ズ";s:6:"ゼ";s:3:"ゼ";s:6:"ゾ";s:3:"ゾ";s:6:"ダ";s:3:"ダ";s:6:"ヂ";s:3:"ヂ";s:6:"ヅ";s:3:"ヅ";s:6:"デ";s:3:"デ";s:6:"ド";s:3:"ド";s:6:"バ";s:3:"バ";s:6:"パ";s:3:"パ";s:6:"ビ";s:3:"ビ";s:6:"ピ";s:3:"ピ";s:6:"ブ";s:3:"ブ";s:6:"プ";s:3:"プ";s:6:"ベ";s:3:"ベ";s:6:"ペ";s:3:"ペ";s:6:"ボ";s:3:"ボ";s:6:"ポ";s:3:"ポ";s:6:"ヴ";s:3:"ヴ";s:6:"ヷ";s:3:"ヷ";s:6:"ヸ";s:3:"ヸ";s:6:"ヹ";s:3:"ヹ";s:6:"ヺ";s:3:"ヺ";s:6:"ヾ";s:3:"ヾ";s:3:"豈";s:3:"豈";s:3:"更";s:3:"更";s:3:"車";s:3:"車";s:3:"賈";s:3:"賈";s:3:"滑";s:3:"滑";s:3:"串";s:3:"串";s:3:"句";s:3:"句";s:3:"龜";s:3:"龜";s:3:"契";s:3:"契";s:3:"金";s:3:"金";s:3:"喇";s:3:"喇";s:3:"奈";s:3:"奈";s:3:"懶";s:4:"懶";s:3:"癩";s:3:"癩";s:3:"羅";s:3:"羅";s:3:"蘿";s:3:"蘿";s:3:"螺";s:3:"螺";s:3:"裸";s:3:"裸";s:3:"邏";s:3:"邏";s:3:"樂";s:3:"樂";s:3:"洛";s:3:"洛";s:3:"烙";s:3:"烙";s:3:"珞";s:3:"珞";s:3:"落";s:3:"落";s:3:"酪";s:3:"酪";s:3:"駱";s:3:"駱";s:3:"亂";s:3:"亂";s:3:"卵";s:3:"卵";s:3:"欄";s:3:"欄";s:3:"爛";s:3:"爛";s:3:"蘭";s:3:"蘭";s:3:"鸞";s:3:"鸞";s:3:"嵐";s:3:"嵐";s:3:"濫";s:3:"濫";s:3:"藍";s:3:"藍";s:3:"襤";s:3:"襤";s:3:"拉";s:3:"拉";s:3:"臘";s:3:"臘";s:3:"蠟";s:3:"蠟";s:3:"廊";s:4:"廊";s:3:"朗";s:4:"朗";s:3:"浪";s:3:"浪";s:3:"狼";s:3:"狼";s:3:"郎";s:3:"郎";s:3:"來";s:3:"來";s:3:"冷";s:3:"冷";s:3:"勞";s:3:"勞";s:3:"擄";s:3:"擄";s:3:"櫓";s:3:"櫓";s:3:"爐";s:3:"爐";s:3:"盧";s:3:"盧";s:3:"老";s:3:"老";s:3:"蘆";s:3:"蘆";s:3:"虜";s:4:"虜";s:3:"路";s:3:"路";s:3:"露";s:3:"露";s:3:"魯";s:3:"魯";s:3:"鷺";s:3:"鷺";s:3:"碌";s:4:"碌";s:3:"祿";s:3:"祿";s:3:"綠";s:3:"綠";s:3:"菉";s:3:"菉";s:3:"錄";s:3:"錄";s:3:"鹿";s:3:"鹿";s:3:"論";s:3:"論";s:3:"壟";s:3:"壟";s:3:"弄";s:3:"弄";s:3:"籠";s:3:"籠";s:3:"聾";s:3:"聾";s:3:"牢";s:3:"牢";s:3:"磊";s:3:"磊";s:3:"賂";s:3:"賂";s:3:"雷";s:3:"雷";s:3:"壘";s:3:"壘";s:3:"屢";s:3:"屢";s:3:"樓";s:3:"樓";s:3:"淚";s:3:"淚";s:3:"漏";s:3:"漏";s:3:"累";s:3:"累";s:3:"縷";s:3:"縷";s:3:"陋";s:3:"陋";s:3:"勒";s:3:"勒";s:3:"肋";s:3:"肋";s:3:"凜";s:3:"凜";s:3:"凌";s:3:"凌";s:3:"稜";s:3:"稜";s:3:"綾";s:3:"綾";s:3:"菱";s:3:"菱";s:3:"陵";s:3:"陵";s:3:"讀";s:3:"讀";s:3:"拏";s:3:"拏";s:3:"諾";s:3:"諾";s:3:"丹";s:3:"丹";s:3:"寧";s:4:"寧";s:3:"怒";s:3:"怒";s:3:"率";s:3:"率";s:3:"異";s:4:"異";s:3:"北";s:4:"北";s:3:"磻";s:3:"磻";s:3:"便";s:3:"便";s:3:"復";s:3:"復";s:3:"不";s:3:"不";s:3:"泌";s:3:"泌";s:3:"數";s:3:"數";s:3:"索";s:3:"索";s:3:"參";s:3:"參";s:3:"塞";s:3:"塞";s:3:"省";s:3:"省";s:3:"葉";s:3:"葉";s:3:"說";s:3:"說";s:3:"殺";s:4:"殺";s:3:"辰";s:3:"辰";s:3:"沈";s:3:"沈";s:3:"拾";s:3:"拾";s:3:"若";s:4:"若";s:3:"掠";s:3:"掠";s:3:"略";s:3:"略";s:3:"亮";s:3:"亮";s:3:"兩";s:3:"兩";s:3:"凉";s:3:"凉";s:3:"梁";s:3:"梁";s:3:"糧";s:3:"糧";s:3:"良";s:3:"良";s:3:"諒";s:3:"諒";s:3:"量";s:3:"量";s:3:"勵";s:3:"勵";s:3:"呂";s:3:"呂";s:3:"女";s:3:"女";s:3:"廬";s:3:"廬";s:3:"旅";s:3:"旅";s:3:"濾";s:3:"濾";s:3:"礪";s:3:"礪";s:3:"閭";s:3:"閭";s:3:"驪";s:3:"驪";s:3:"麗";s:3:"麗";s:3:"黎";s:3:"黎";s:3:"力";s:3:"力";s:3:"曆";s:3:"曆";s:3:"歷";s:3:"歷";s:3:"轢";s:3:"轢";s:3:"年";s:3:"年";s:3:"憐";s:3:"憐";s:3:"戀";s:3:"戀";s:3:"撚";s:3:"撚";s:3:"漣";s:3:"漣";s:3:"煉";s:3:"煉";s:3:"璉";s:3:"璉";s:3:"秊";s:3:"秊";s:3:"練";s:3:"練";s:3:"聯";s:3:"聯";s:3:"輦";s:3:"輦";s:3:"蓮";s:3:"蓮";s:3:"連";s:3:"連";s:3:"鍊";s:3:"鍊";s:3:"列";s:3:"列";s:3:"劣";s:3:"劣";s:3:"咽";s:3:"咽";s:3:"烈";s:3:"烈";s:3:"裂";s:3:"裂";s:3:"廉";s:3:"廉";s:3:"念";s:3:"念";s:3:"捻";s:3:"捻";s:3:"殮";s:3:"殮";s:3:"簾";s:3:"簾";s:3:"獵";s:3:"獵";s:3:"令";s:3:"令";s:3:"囹";s:3:"囹";s:3:"嶺";s:3:"嶺";s:3:"怜";s:3:"怜";s:3:"玲";s:3:"玲";s:3:"瑩";s:3:"瑩";s:3:"羚";s:3:"羚";s:3:"聆";s:3:"聆";s:3:"鈴";s:3:"鈴";s:3:"零";s:3:"零";s:3:"靈";s:3:"靈";s:3:"領";s:3:"領";s:3:"例";s:3:"例";s:3:"禮";s:3:"禮";s:3:"醴";s:3:"醴";s:3:"隸";s:3:"隸";s:3:"惡";s:3:"惡";s:3:"了";s:3:"了";s:3:"僚";s:3:"僚";s:3:"寮";s:3:"寮";s:3:"尿";s:3:"尿";s:3:"料";s:3:"料";s:3:"燎";s:3:"燎";s:3:"療";s:3:"療";s:3:"蓼";s:3:"蓼";s:3:"遼";s:3:"遼";s:3:"龍";s:3:"龍";s:3:"暈";s:3:"暈";s:3:"阮";s:3:"阮";s:3:"劉";s:3:"劉";s:3:"杻";s:3:"杻";s:3:"柳";s:3:"柳";s:3:"流";s:4:"流";s:3:"溜";s:3:"溜";s:3:"琉";s:3:"琉";s:3:"留";s:3:"留";s:3:"硫";s:3:"硫";s:3:"紐";s:3:"紐";s:3:"類";s:3:"類";s:3:"六";s:3:"六";s:3:"戮";s:3:"戮";s:3:"陸";s:3:"陸";s:3:"倫";s:3:"倫";s:3:"崙";s:3:"崙";s:3:"淪";s:3:"淪";s:3:"輪";s:3:"輪";s:3:"律";s:3:"律";s:3:"慄";s:3:"慄";s:3:"栗";s:3:"栗";s:3:"隆";s:3:"隆";s:3:"利";s:3:"利";s:3:"吏";s:3:"吏";s:3:"履";s:3:"履";s:3:"易";s:3:"易";s:3:"李";s:3:"李";s:3:"梨";s:3:"梨";s:3:"泥";s:3:"泥";s:3:"理";s:3:"理";s:3:"痢";s:3:"痢";s:3:"罹";s:3:"罹";s:3:"裏";s:3:"裏";s:3:"裡";s:3:"裡";s:3:"里";s:3:"里";s:3:"離";s:3:"離";s:3:"匿";s:3:"匿";s:3:"溺";s:3:"溺";s:3:"吝";s:3:"吝";s:3:"燐";s:3:"燐";s:3:"璘";s:3:"璘";s:3:"藺";s:3:"藺";s:3:"隣";s:3:"隣";s:3:"鱗";s:3:"鱗";s:3:"麟";s:3:"麟";s:3:"林";s:3:"林";s:3:"淋";s:3:"淋";s:3:"臨";s:3:"臨";s:3:"立";s:3:"立";s:3:"笠";s:3:"笠";s:3:"粒";s:3:"粒";s:3:"狀";s:3:"狀";s:3:"炙";s:3:"炙";s:3:"識";s:3:"識";s:3:"什";s:3:"什";s:3:"茶";s:3:"茶";s:3:"刺";s:3:"刺";s:3:"切";s:4:"切";s:3:"度";s:3:"度";s:3:"拓";s:3:"拓";s:3:"糖";s:3:"糖";s:3:"宅";s:3:"宅";s:3:"洞";s:3:"洞";s:3:"暴";s:3:"暴";s:3:"輻";s:3:"輻";s:3:"行";s:3:"行";s:3:"降";s:3:"降";s:3:"見";s:3:"見";s:3:"廓";s:3:"廓";s:3:"兀";s:3:"兀";s:3:"嗀";s:3:"嗀";s:3:"塚";s:3:"塚";s:3:"晴";s:3:"晴";s:3:"凞";s:3:"凞";s:3:"猪";s:3:"猪";s:3:"益";s:3:"益";s:3:"礼";s:3:"礼";s:3:"神";s:3:"神";s:3:"祥";s:3:"祥";s:3:"福";s:4:"福";s:3:"靖";s:3:"靖";s:3:"精";s:3:"精";s:3:"羽";s:3:"羽";s:3:"蘒";s:3:"蘒";s:3:"諸";s:3:"諸";s:3:"逸";s:3:"逸";s:3:"都";s:3:"都";s:3:"飯";s:3:"飯";s:3:"飼";s:3:"飼";s:3:"館";s:3:"館";s:3:"鶴";s:3:"鶴";s:3:"侮";s:4:"侮";s:3:"僧";s:4:"僧";s:3:"免";s:4:"免";s:3:"勉";s:4:"勉";s:3:"勤";s:4:"勤";s:3:"卑";s:4:"卑";s:3:"喝";s:3:"喝";s:3:"嘆";s:4:"嘆";s:3:"器";s:3:"器";s:3:"塀";s:3:"塀";s:3:"墨";s:3:"墨";s:3:"層";s:3:"層";s:3:"屮";s:4:"屮";s:3:"悔";s:4:"悔";s:3:"慨";s:3:"慨";s:3:"憎";s:4:"憎";s:3:"懲";s:4:"懲";s:3:"敏";s:4:"敏";s:3:"既";s:3:"既";s:3:"暑";s:4:"暑";s:3:"梅";s:4:"梅";s:3:"海";s:4:"海";s:3:"渚";s:3:"渚";s:3:"漢";s:3:"漢";s:3:"煮";s:3:"煮";s:3:"爫";s:3:"爫";s:3:"琢";s:3:"琢";s:3:"碑";s:3:"碑";s:3:"社";s:3:"社";s:3:"祉";s:3:"祉";s:3:"祈";s:3:"祈";s:3:"祐";s:3:"祐";s:3:"祖";s:4:"祖";s:3:"祝";s:3:"祝";s:3:"禍";s:3:"禍";s:3:"禎";s:3:"禎";s:3:"穀";s:4:"穀";s:3:"突";s:3:"突";s:3:"節";s:3:"節";s:3:"縉";s:3:"縉";s:3:"繁";s:3:"繁";s:3:"署";s:3:"署";s:3:"者";s:4:"者";s:3:"臭";s:3:"臭";s:3:"艹";s:3:"艹";s:3:"著";s:4:"著";s:3:"褐";s:3:"褐";s:3:"視";s:3:"視";s:3:"謁";s:3:"謁";s:3:"謹";s:3:"謹";s:3:"賓";s:3:"賓";s:3:"贈";s:3:"贈";s:3:"辶";s:3:"辶";s:3:"難";s:3:"難";s:3:"響";s:3:"響";s:3:"頻";s:3:"頻";s:3:"並";s:3:"並";s:3:"况";s:4:"况";s:3:"全";s:3:"全";s:3:"侀";s:3:"侀";s:3:"充";s:3:"充";s:3:"冀";s:3:"冀";s:3:"勇";s:4:"勇";s:3:"勺";s:4:"勺";s:3:"啕";s:3:"啕";s:3:"喙";s:4:"喙";s:3:"嗢";s:3:"嗢";s:3:"墳";s:3:"墳";s:3:"奄";s:3:"奄";s:3:"奔";s:3:"奔";s:3:"婢";s:3:"婢";s:3:"嬨";s:3:"嬨";s:3:"廒";s:3:"廒";s:3:"廙";s:3:"廙";s:3:"彩";s:3:"彩";s:3:"徭";s:3:"徭";s:3:"惘";s:3:"惘";s:3:"慎";s:4:"慎";s:3:"愈";s:3:"愈";s:3:"慠";s:3:"慠";s:3:"戴";s:3:"戴";s:3:"揄";s:3:"揄";s:3:"搜";s:3:"搜";s:3:"摒";s:3:"摒";s:3:"敖";s:3:"敖";s:3:"望";s:4:"望";s:3:"杖";s:3:"杖";s:3:"歹";s:3:"歹";s:3:"滛";s:3:"滛";s:3:"滋";s:4:"滋";s:3:"瀞";s:4:"瀞";s:3:"瞧";s:3:"瞧";s:3:"爵";s:4:"爵";s:3:"犯";s:3:"犯";s:3:"瑱";s:4:"瑱";s:3:"甆";s:3:"甆";s:3:"画";s:3:"画";s:3:"瘝";s:3:"瘝";s:3:"瘟";s:3:"瘟";s:3:"盛";s:3:"盛";s:3:"直";s:4:"直";s:3:"睊";s:4:"睊";s:3:"着";s:3:"着";s:3:"磌";s:4:"磌";s:3:"窱";s:3:"窱";s:3:"类";s:3:"类";s:3:"絛";s:3:"絛";s:3:"缾";s:3:"缾";s:3:"荒";s:3:"荒";s:3:"華";s:3:"華";s:3:"蝹";s:4:"蝹";s:3:"襁";s:3:"襁";s:3:"覆";s:3:"覆";s:3:"調";s:3:"調";s:3:"請";s:3:"請";s:3:"諭";s:4:"諭";s:3:"變";s:4:"變";s:3:"輸";s:4:"輸";s:3:"遲";s:3:"遲";s:3:"醙";s:3:"醙";s:3:"鉶";s:3:"鉶";s:3:"陼";s:3:"陼";s:3:"韛";s:3:"韛";s:3:"頋";s:4:"頋";s:3:"鬒";s:4:"鬒";s:4:"𢡊";s:3:"𢡊";s:4:"𢡄";s:3:"𢡄";s:4:"𣏕";s:3:"𣏕";s:3:"㮝";s:4:"㮝";s:3:"䀘";s:3:"䀘";s:3:"䀹";s:4:"䀹";s:4:"𥉉";s:3:"𥉉";s:4:"𥳐";s:3:"𥳐";s:4:"𧻓";s:3:"𧻓";s:3:"齃";s:3:"齃";s:3:"龎";s:3:"龎";s:3:"丽";s:4:"丽";s:3:"丸";s:4:"丸";s:3:"乁";s:4:"乁";s:4:"𠄢";s:4:"𠄢";s:3:"你";s:4:"你";s:3:"侻";s:4:"侻";s:3:"倂";s:4:"倂";s:3:"偺";s:4:"偺";s:3:"備";s:4:"備";s:3:"像";s:4:"像";s:3:"㒞";s:4:"㒞";s:4:"𠘺";s:4:"𠘺";s:3:"兔";s:4:"兔";s:3:"兤";s:4:"兤";s:3:"具";s:4:"具";s:4:"𠔜";s:4:"𠔜";s:3:"㒹";s:4:"㒹";s:3:"內";s:4:"內";s:3:"再";s:4:"再";s:4:"𠕋";s:4:"𠕋";s:3:"冗";s:4:"冗";s:3:"冤";s:4:"冤";s:3:"仌";s:4:"仌";s:3:"冬";s:4:"冬";s:4:"𩇟";s:4:"𩇟";s:3:"凵";s:4:"凵";s:3:"刃";s:4:"刃";s:3:"㓟";s:4:"㓟";s:3:"刻";s:4:"刻";s:3:"剆";s:4:"剆";s:3:"割";s:4:"割";s:3:"剷";s:4:"剷";s:3:"㔕";s:4:"㔕";s:3:"包";s:4:"包";s:3:"匆";s:4:"匆";s:3:"卉";s:4:"卉";s:3:"博";s:4:"博";s:3:"即";s:4:"即";s:3:"卽";s:4:"卽";s:3:"卿";s:4:"卿";s:4:"𠨬";s:4:"𠨬";s:3:"灰";s:4:"灰";s:3:"及";s:4:"及";s:3:"叟";s:4:"叟";s:4:"𠭣";s:4:"𠭣";s:3:"叫";s:4:"叫";s:3:"叱";s:4:"叱";s:3:"吆";s:4:"吆";s:3:"咞";s:4:"咞";s:3:"吸";s:4:"吸";s:3:"呈";s:4:"呈";s:3:"周";s:4:"周";s:3:"咢";s:4:"咢";s:3:"哶";s:4:"哶";s:3:"唐";s:4:"唐";s:3:"啓";s:4:"啓";s:3:"啣";s:4:"啣";s:3:"善";s:4:"善";s:3:"喫";s:4:"喫";s:3:"喳";s:4:"喳";s:3:"嗂";s:4:"嗂";s:3:"圖";s:4:"圖";s:3:"圗";s:4:"圗";s:3:"噑";s:4:"噑";s:3:"噴";s:4:"噴";s:3:"壮";s:4:"壮";s:3:"城";s:4:"城";s:3:"埴";s:4:"埴";s:3:"堍";s:4:"堍";s:3:"型";s:4:"型";s:3:"堲";s:4:"堲";s:3:"報";s:4:"報";s:3:"墬";s:4:"墬";s:4:"𡓤";s:4:"𡓤";s:3:"売";s:4:"売";s:3:"壷";s:4:"壷";s:3:"夆";s:4:"夆";s:3:"多";s:4:"多";s:3:"夢";s:4:"夢";s:3:"奢";s:4:"奢";s:4:"𡚨";s:4:"𡚨";s:4:"𡛪";s:4:"𡛪";s:3:"姬";s:4:"姬";s:3:"娛";s:4:"娛";s:3:"娧";s:4:"娧";s:3:"姘";s:4:"姘";s:3:"婦";s:4:"婦";s:3:"㛮";s:4:"㛮";s:3:"㛼";s:4:"㛼";s:3:"嬈";s:4:"嬈";s:3:"嬾";s:4:"嬾";s:4:"𡧈";s:4:"𡧈";s:3:"寃";s:4:"寃";s:3:"寘";s:4:"寘";s:3:"寳";s:4:"寳";s:4:"𡬘";s:4:"𡬘";s:3:"寿";s:4:"寿";s:3:"将";s:4:"将";s:3:"当";s:4:"当";s:3:"尢";s:4:"尢";s:3:"㞁";s:4:"㞁";s:3:"屠";s:4:"屠";s:3:"峀";s:4:"峀";s:3:"岍";s:4:"岍";s:4:"𡷤";s:4:"𡷤";s:3:"嵃";s:4:"嵃";s:4:"𡷦";s:4:"𡷦";s:3:"嵮";s:4:"嵮";s:3:"嵫";s:4:"嵫";s:3:"嵼";s:4:"嵼";s:3:"巡";s:4:"巡";s:3:"巢";s:4:"巢";s:3:"㠯";s:4:"㠯";s:3:"巽";s:4:"巽";s:3:"帨";s:4:"帨";s:3:"帽";s:4:"帽";s:3:"幩";s:4:"幩";s:3:"㡢";s:4:"㡢";s:4:"𢆃";s:4:"𢆃";s:3:"㡼";s:4:"㡼";s:3:"庰";s:4:"庰";s:3:"庳";s:4:"庳";s:3:"庶";s:4:"庶";s:4:"𪎒";s:4:"𪎒";s:3:"廾";s:4:"廾";s:4:"𢌱";s:4:"𢌱";s:3:"舁";s:4:"舁";s:3:"弢";s:4:"弢";s:3:"㣇";s:4:"㣇";s:4:"𣊸";s:4:"𣊸";s:4:"𦇚";s:4:"𦇚";s:3:"形";s:4:"形";s:3:"彫";s:4:"彫";s:3:"㣣";s:4:"㣣";s:3:"徚";s:4:"徚";s:3:"忍";s:4:"忍";s:3:"志";s:4:"志";s:3:"忹";s:4:"忹";s:3:"悁";s:4:"悁";s:3:"㤺";s:4:"㤺";s:3:"㤜";s:4:"㤜";s:4:"𢛔";s:4:"𢛔";s:3:"惇";s:4:"惇";s:3:"慈";s:4:"慈";s:3:"慌";s:4:"慌";s:3:"慺";s:4:"慺";s:3:"憲";s:4:"憲";s:3:"憤";s:4:"憤";s:3:"憯";s:4:"憯";s:3:"懞";s:4:"懞";s:3:"成";s:4:"成";s:3:"戛";s:4:"戛";s:3:"扝";s:4:"扝";s:3:"抱";s:4:"抱";s:3:"拔";s:4:"拔";s:3:"捐";s:4:"捐";s:4:"𢬌";s:4:"𢬌";s:3:"挽";s:4:"挽";s:3:"拼";s:4:"拼";s:3:"捨";s:4:"捨";s:3:"掃";s:4:"掃";s:3:"揤";s:4:"揤";s:4:"𢯱";s:4:"𢯱";s:3:"搢";s:4:"搢";s:3:"揅";s:4:"揅";s:3:"掩";s:4:"掩";s:3:"㨮";s:4:"㨮";s:3:"摩";s:4:"摩";s:3:"摾";s:4:"摾";s:3:"撝";s:4:"撝";s:3:"摷";s:4:"摷";s:3:"㩬";s:4:"㩬";s:3:"敬";s:4:"敬";s:4:"𣀊";s:4:"𣀊";s:3:"旣";s:4:"旣";s:3:"書";s:4:"書";s:3:"晉";s:4:"晉";s:3:"㬙";s:4:"㬙";s:3:"㬈";s:4:"㬈";s:3:"㫤";s:4:"㫤";s:3:"冒";s:4:"冒";s:3:"冕";s:4:"冕";s:3:"最";s:4:"最";s:3:"暜";s:4:"暜";s:3:"肭";s:4:"肭";s:3:"䏙";s:4:"䏙";s:3:"朡";s:4:"朡";s:3:"杞";s:4:"杞";s:3:"杓";s:4:"杓";s:4:"𣏃";s:4:"𣏃";s:3:"㭉";s:4:"㭉";s:3:"柺";s:4:"柺";s:3:"枅";s:4:"枅";s:3:"桒";s:4:"桒";s:4:"𣑭";s:4:"𣑭";s:3:"梎";s:4:"梎";s:3:"栟";s:4:"栟";s:3:"椔";s:4:"椔";s:3:"楂";s:4:"楂";s:3:"榣";s:4:"榣";s:3:"槪";s:4:"槪";s:3:"檨";s:4:"檨";s:4:"𣚣";s:4:"𣚣";s:3:"櫛";s:4:"櫛";s:3:"㰘";s:4:"㰘";s:3:"次";s:4:"次";s:4:"𣢧";s:4:"𣢧";s:3:"歔";s:4:"歔";s:3:"㱎";s:4:"㱎";s:3:"歲";s:4:"歲";s:3:"殟";s:4:"殟";s:3:"殻";s:4:"殻";s:4:"𣪍";s:4:"𣪍";s:4:"𡴋";s:4:"𡴋";s:4:"𣫺";s:4:"𣫺";s:3:"汎";s:4:"汎";s:4:"𣲼";s:4:"𣲼";s:3:"沿";s:4:"沿";s:3:"泍";s:4:"泍";s:3:"汧";s:4:"汧";s:3:"洖";s:4:"洖";s:3:"派";s:4:"派";s:3:"浩";s:4:"浩";s:3:"浸";s:4:"浸";s:3:"涅";s:4:"涅";s:4:"𣴞";s:4:"𣴞";s:3:"洴";s:4:"洴";s:3:"港";s:4:"港";s:3:"湮";s:4:"湮";s:3:"㴳";s:4:"㴳";s:3:"滇";s:4:"滇";s:4:"𣻑";s:4:"𣻑";s:3:"淹";s:4:"淹";s:3:"潮";s:4:"潮";s:4:"𣽞";s:4:"𣽞";s:4:"𣾎";s:4:"𣾎";s:3:"濆";s:4:"濆";s:3:"瀹";s:4:"瀹";s:3:"瀛";s:4:"瀛";s:3:"㶖";s:4:"㶖";s:3:"灊";s:4:"灊";s:3:"災";s:4:"災";s:3:"灷";s:4:"灷";s:3:"炭";s:4:"炭";s:4:"𠔥";s:4:"𠔥";s:3:"煅";s:4:"煅";s:4:"𤉣";s:4:"𤉣";s:3:"熜";s:4:"熜";s:4:"𤎫";s:4:"𤎫";s:3:"爨";s:4:"爨";s:3:"牐";s:4:"牐";s:4:"𤘈";s:4:"𤘈";s:3:"犀";s:4:"犀";s:3:"犕";s:4:"犕";s:4:"𤜵";s:4:"𤜵";s:4:"𤠔";s:4:"𤠔";s:3:"獺";s:4:"獺";s:3:"王";s:4:"王";s:3:"㺬";s:4:"㺬";s:3:"玥";s:4:"玥";s:3:"㺸";s:4:"㺸";s:3:"瑇";s:4:"瑇";s:3:"瑜";s:4:"瑜";s:3:"璅";s:4:"璅";s:3:"瓊";s:4:"瓊";s:3:"㼛";s:4:"㼛";s:3:"甤";s:4:"甤";s:4:"𤰶";s:4:"𤰶";s:3:"甾";s:4:"甾";s:4:"𤲒";s:4:"𤲒";s:4:"𢆟";s:4:"𢆟";s:3:"瘐";s:4:"瘐";s:4:"𤾡";s:4:"𤾡";s:4:"𤾸";s:4:"𤾸";s:4:"𥁄";s:4:"𥁄";s:3:"㿼";s:4:"㿼";s:3:"䀈";s:4:"䀈";s:4:"𥃳";s:4:"𥃳";s:4:"𥃲";s:4:"𥃲";s:4:"𥄙";s:4:"𥄙";s:4:"𥄳";s:4:"𥄳";s:3:"眞";s:4:"眞";s:3:"真";s:4:"真";s:3:"瞋";s:4:"瞋";s:3:"䁆";s:4:"䁆";s:3:"䂖";s:4:"䂖";s:4:"𥐝";s:4:"𥐝";s:3:"硎";s:4:"硎";s:3:"䃣";s:4:"䃣";s:4:"𥘦";s:4:"𥘦";s:4:"𥚚";s:4:"𥚚";s:4:"𥛅";s:4:"𥛅";s:3:"秫";s:4:"秫";s:3:"䄯";s:4:"䄯";s:3:"穊";s:4:"穊";s:3:"穏";s:4:"穏";s:4:"𥥼";s:4:"𥥼";s:4:"𥪧";s:4:"𥪧";s:3:"竮";s:4:"竮";s:3:"䈂";s:4:"䈂";s:4:"𥮫";s:4:"𥮫";s:3:"篆";s:4:"篆";s:3:"築";s:4:"築";s:3:"䈧";s:4:"䈧";s:4:"𥲀";s:4:"𥲀";s:3:"糒";s:4:"糒";s:3:"䊠";s:4:"䊠";s:3:"糨";s:4:"糨";s:3:"糣";s:4:"糣";s:3:"紀";s:4:"紀";s:4:"𥾆";s:4:"𥾆";s:3:"絣";s:4:"絣";s:3:"䌁";s:4:"䌁";s:3:"緇";s:4:"緇";s:3:"縂";s:4:"縂";s:3:"繅";s:4:"繅";s:3:"䌴";s:4:"䌴";s:4:"𦈨";s:4:"𦈨";s:4:"𦉇";s:4:"𦉇";s:3:"䍙";s:4:"䍙";s:4:"𦋙";s:4:"𦋙";s:3:"罺";s:4:"罺";s:4:"𦌾";s:4:"𦌾";s:3:"羕";s:4:"羕";s:3:"翺";s:4:"翺";s:4:"𦓚";s:4:"𦓚";s:4:"𦔣";s:4:"𦔣";s:3:"聠";s:4:"聠";s:4:"𦖨";s:4:"𦖨";s:3:"聰";s:4:"聰";s:4:"𣍟";s:4:"𣍟";s:3:"䏕";s:4:"䏕";s:3:"育";s:4:"育";s:3:"脃";s:4:"脃";s:3:"䐋";s:4:"䐋";s:3:"脾";s:4:"脾";s:3:"媵";s:4:"媵";s:4:"𦞧";s:4:"𦞧";s:4:"𦞵";s:4:"𦞵";s:4:"𣎓";s:4:"𣎓";s:4:"𣎜";s:4:"𣎜";s:3:"舄";s:4:"舄";s:3:"辞";s:4:"辞";s:3:"䑫";s:4:"䑫";s:3:"芑";s:4:"芑";s:3:"芋";s:4:"芋";s:3:"芝";s:4:"芝";s:3:"劳";s:4:"劳";s:3:"花";s:4:"花";s:3:"芳";s:4:"芳";s:3:"芽";s:4:"芽";s:3:"苦";s:4:"苦";s:4:"𦬼";s:4:"𦬼";s:3:"茝";s:4:"茝";s:3:"荣";s:4:"荣";s:3:"莭";s:4:"莭";s:3:"茣";s:4:"茣";s:3:"莽";s:4:"莽";s:3:"菧";s:4:"菧";s:3:"荓";s:4:"荓";s:3:"菊";s:4:"菊";s:3:"菌";s:4:"菌";s:3:"菜";s:4:"菜";s:4:"𦰶";s:4:"𦰶";s:4:"𦵫";s:4:"𦵫";s:4:"𦳕";s:4:"𦳕";s:3:"䔫";s:4:"䔫";s:3:"蓱";s:4:"蓱";s:3:"蓳";s:4:"蓳";s:3:"蔖";s:4:"蔖";s:4:"𧏊";s:4:"𧏊";s:3:"蕤";s:4:"蕤";s:4:"𦼬";s:4:"𦼬";s:3:"䕝";s:4:"䕝";s:3:"䕡";s:4:"䕡";s:4:"𦾱";s:4:"𦾱";s:4:"𧃒";s:4:"𧃒";s:3:"䕫";s:4:"䕫";s:3:"虐";s:4:"虐";s:3:"虧";s:4:"虧";s:3:"虩";s:4:"虩";s:3:"蚩";s:4:"蚩";s:3:"蚈";s:4:"蚈";s:3:"蜎";s:4:"蜎";s:3:"蛢";s:4:"蛢";s:3:"蜨";s:4:"蜨";s:3:"蝫";s:4:"蝫";s:3:"螆";s:4:"螆";s:3:"䗗";s:4:"䗗";s:3:"蟡";s:4:"蟡";s:3:"蠁";s:4:"蠁";s:3:"䗹";s:4:"䗹";s:3:"衠";s:4:"衠";s:3:"衣";s:4:"衣";s:4:"𧙧";s:4:"𧙧";s:3:"裗";s:4:"裗";s:3:"裞";s:4:"裞";s:3:"䘵";s:4:"䘵";s:3:"裺";s:4:"裺";s:3:"㒻";s:4:"㒻";s:4:"𧢮";s:4:"𧢮";s:4:"𧥦";s:4:"𧥦";s:3:"䚾";s:4:"䚾";s:3:"䛇";s:4:"䛇";s:3:"誠";s:4:"誠";s:3:"豕";s:4:"豕";s:4:"𧲨";s:4:"𧲨";s:3:"貫";s:4:"貫";s:3:"賁";s:4:"賁";s:3:"贛";s:4:"贛";s:3:"起";s:4:"起";s:4:"𧼯";s:4:"𧼯";s:4:"𠠄";s:4:"𠠄";s:3:"跋";s:4:"跋";s:3:"趼";s:4:"趼";s:3:"跰";s:4:"跰";s:4:"𠣞";s:4:"𠣞";s:3:"軔";s:4:"軔";s:4:"𨗒";s:4:"𨗒";s:4:"𨗭";s:4:"𨗭";s:3:"邔";s:4:"邔";s:3:"郱";s:4:"郱";s:3:"鄑";s:4:"鄑";s:4:"𨜮";s:4:"𨜮";s:3:"鄛";s:4:"鄛";s:3:"鈸";s:4:"鈸";s:3:"鋗";s:4:"鋗";s:3:"鋘";s:4:"鋘";s:3:"鉼";s:4:"鉼";s:3:"鏹";s:4:"鏹";s:3:"鐕";s:4:"鐕";s:4:"𨯺";s:4:"𨯺";s:3:"開";s:4:"開";s:3:"䦕";s:4:"䦕";s:3:"閷";s:4:"閷";s:4:"𨵷";s:4:"𨵷";s:3:"䧦";s:4:"䧦";s:3:"雃";s:4:"雃";s:3:"嶲";s:4:"嶲";s:3:"霣";s:4:"霣";s:4:"𩅅";s:4:"𩅅";s:4:"𩈚";s:4:"𩈚";s:3:"䩮";s:4:"䩮";s:3:"䩶";s:4:"䩶";s:3:"韠";s:4:"韠";s:4:"𩐊";s:4:"𩐊";s:3:"䪲";s:4:"䪲";s:4:"𩒖";s:4:"𩒖";s:3:"頩";s:4:"頩";s:4:"𩖶";s:4:"𩖶";s:3:"飢";s:4:"飢";s:3:"䬳";s:4:"䬳";s:3:"餩";s:4:"餩";s:3:"馧";s:4:"馧";s:3:"駂";s:4:"駂";s:3:"駾";s:4:"駾";s:3:"䯎";s:4:"䯎";s:4:"𩬰";s:4:"𩬰";s:3:"鱀";s:4:"鱀";s:3:"鳽";s:4:"鳽";s:3:"䳎";s:4:"䳎";s:3:"䳭";s:4:"䳭";s:3:"鵧";s:4:"鵧";s:4:"𪃎";s:4:"𪃎";s:3:"䳸";s:4:"䳸";s:4:"𪄅";s:4:"𪄅";s:4:"𪈎";s:4:"𪈎";s:4:"𪊑";s:4:"𪊑";s:3:"麻";s:4:"麻";s:3:"䵖";s:4:"䵖";s:3:"黹";s:4:"黹";s:3:"黾";s:4:"黾";s:3:"鼅";s:4:"鼅";s:3:"鼏";s:4:"鼏";s:3:"鼖";s:4:"鼖";s:3:"鼻";s:4:"鼻";s:4:"𪘀";s:4:"𪘀";}' );
+$utfCanonicalDecomp = unserialize( 'a:2032:{s:2:"À";s:3:"À";s:2:"Á";s:3:"Á";s:2:"Â";s:3:"Â";s:2:"Ã";s:3:"Ã";s:2:"Ä";s:3:"Ä";s:2:"Å";s:3:"Å";s:2:"Ç";s:3:"Ç";s:2:"È";s:3:"È";s:2:"É";s:3:"É";s:2:"Ê";s:3:"Ê";s:2:"Ë";s:3:"Ë";s:2:"Ì";s:3:"Ì";s:2:"Í";s:3:"Í";s:2:"Î";s:3:"Î";s:2:"Ï";s:3:"Ï";s:2:"Ñ";s:3:"Ñ";s:2:"Ò";s:3:"Ò";s:2:"Ó";s:3:"Ó";s:2:"Ô";s:3:"Ô";s:2:"Õ";s:3:"Õ";s:2:"Ö";s:3:"Ö";s:2:"Ù";s:3:"Ù";s:2:"Ú";s:3:"Ú";s:2:"Û";s:3:"Û";s:2:"Ü";s:3:"Ü";s:2:"Ý";s:3:"Ý";s:2:"à";s:3:"à";s:2:"á";s:3:"á";s:2:"â";s:3:"â";s:2:"ã";s:3:"ã";s:2:"ä";s:3:"ä";s:2:"å";s:3:"å";s:2:"ç";s:3:"ç";s:2:"è";s:3:"è";s:2:"é";s:3:"é";s:2:"ê";s:3:"ê";s:2:"ë";s:3:"ë";s:2:"ì";s:3:"ì";s:2:"í";s:3:"í";s:2:"î";s:3:"î";s:2:"ï";s:3:"ï";s:2:"ñ";s:3:"ñ";s:2:"ò";s:3:"ò";s:2:"ó";s:3:"ó";s:2:"ô";s:3:"ô";s:2:"õ";s:3:"õ";s:2:"ö";s:3:"ö";s:2:"ù";s:3:"ù";s:2:"ú";s:3:"ú";s:2:"û";s:3:"û";s:2:"ü";s:3:"ü";s:2:"ý";s:3:"ý";s:2:"ÿ";s:3:"ÿ";s:2:"Ā";s:3:"Ā";s:2:"ā";s:3:"ā";s:2:"Ă";s:3:"Ă";s:2:"ă";s:3:"ă";s:2:"Ą";s:3:"Ą";s:2:"ą";s:3:"ą";s:2:"Ć";s:3:"Ć";s:2:"ć";s:3:"ć";s:2:"Ĉ";s:3:"Ĉ";s:2:"ĉ";s:3:"ĉ";s:2:"Ċ";s:3:"Ċ";s:2:"ċ";s:3:"ċ";s:2:"Č";s:3:"Č";s:2:"č";s:3:"č";s:2:"Ď";s:3:"Ď";s:2:"ď";s:3:"ď";s:2:"Ē";s:3:"Ē";s:2:"ē";s:3:"ē";s:2:"Ĕ";s:3:"Ĕ";s:2:"ĕ";s:3:"ĕ";s:2:"Ė";s:3:"Ė";s:2:"ė";s:3:"ė";s:2:"Ę";s:3:"Ę";s:2:"ę";s:3:"ę";s:2:"Ě";s:3:"Ě";s:2:"ě";s:3:"ě";s:2:"Ĝ";s:3:"Ĝ";s:2:"ĝ";s:3:"ĝ";s:2:"Ğ";s:3:"Ğ";s:2:"ğ";s:3:"ğ";s:2:"Ġ";s:3:"Ġ";s:2:"ġ";s:3:"ġ";s:2:"Ģ";s:3:"Ģ";s:2:"ģ";s:3:"ģ";s:2:"Ĥ";s:3:"Ĥ";s:2:"ĥ";s:3:"ĥ";s:2:"Ĩ";s:3:"Ĩ";s:2:"ĩ";s:3:"ĩ";s:2:"Ī";s:3:"Ī";s:2:"ī";s:3:"ī";s:2:"Ĭ";s:3:"Ĭ";s:2:"ĭ";s:3:"ĭ";s:2:"Į";s:3:"Į";s:2:"į";s:3:"į";s:2:"İ";s:3:"İ";s:2:"Ĵ";s:3:"Ĵ";s:2:"ĵ";s:3:"ĵ";s:2:"Ķ";s:3:"Ķ";s:2:"ķ";s:3:"ķ";s:2:"Ĺ";s:3:"Ĺ";s:2:"ĺ";s:3:"ĺ";s:2:"Ļ";s:3:"Ļ";s:2:"ļ";s:3:"ļ";s:2:"Ľ";s:3:"Ľ";s:2:"ľ";s:3:"ľ";s:2:"Ń";s:3:"Ń";s:2:"ń";s:3:"ń";s:2:"Ņ";s:3:"Ņ";s:2:"ņ";s:3:"ņ";s:2:"Ň";s:3:"Ň";s:2:"ň";s:3:"ň";s:2:"Ō";s:3:"Ō";s:2:"ō";s:3:"ō";s:2:"Ŏ";s:3:"Ŏ";s:2:"ŏ";s:3:"ŏ";s:2:"Ő";s:3:"Ő";s:2:"ő";s:3:"ő";s:2:"Ŕ";s:3:"Ŕ";s:2:"ŕ";s:3:"ŕ";s:2:"Ŗ";s:3:"Ŗ";s:2:"ŗ";s:3:"ŗ";s:2:"Ř";s:3:"Ř";s:2:"ř";s:3:"ř";s:2:"Ś";s:3:"Ś";s:2:"ś";s:3:"ś";s:2:"Ŝ";s:3:"Ŝ";s:2:"ŝ";s:3:"ŝ";s:2:"Ş";s:3:"Ş";s:2:"ş";s:3:"ş";s:2:"Š";s:3:"Š";s:2:"š";s:3:"š";s:2:"Ţ";s:3:"Ţ";s:2:"ţ";s:3:"ţ";s:2:"Ť";s:3:"Ť";s:2:"ť";s:3:"ť";s:2:"Ũ";s:3:"Ũ";s:2:"ũ";s:3:"ũ";s:2:"Ū";s:3:"Ū";s:2:"ū";s:3:"ū";s:2:"Ŭ";s:3:"Ŭ";s:2:"ŭ";s:3:"ŭ";s:2:"Ů";s:3:"Ů";s:2:"ů";s:3:"ů";s:2:"Ű";s:3:"Ű";s:2:"ű";s:3:"ű";s:2:"Ų";s:3:"Ų";s:2:"ų";s:3:"ų";s:2:"Ŵ";s:3:"Ŵ";s:2:"ŵ";s:3:"ŵ";s:2:"Ŷ";s:3:"Ŷ";s:2:"ŷ";s:3:"ŷ";s:2:"Ÿ";s:3:"Ÿ";s:2:"Ź";s:3:"Ź";s:2:"ź";s:3:"ź";s:2:"Ż";s:3:"Ż";s:2:"ż";s:3:"ż";s:2:"Ž";s:3:"Ž";s:2:"ž";s:3:"ž";s:2:"Ơ";s:3:"Ơ";s:2:"ơ";s:3:"ơ";s:2:"Ư";s:3:"Ư";s:2:"ư";s:3:"ư";s:2:"Ǎ";s:3:"Ǎ";s:2:"ǎ";s:3:"ǎ";s:2:"Ǐ";s:3:"Ǐ";s:2:"ǐ";s:3:"ǐ";s:2:"Ǒ";s:3:"Ǒ";s:2:"ǒ";s:3:"ǒ";s:2:"Ǔ";s:3:"Ǔ";s:2:"ǔ";s:3:"ǔ";s:2:"Ǖ";s:5:"Ǖ";s:2:"ǖ";s:5:"ǖ";s:2:"Ǘ";s:5:"Ǘ";s:2:"ǘ";s:5:"ǘ";s:2:"Ǚ";s:5:"Ǚ";s:2:"ǚ";s:5:"ǚ";s:2:"Ǜ";s:5:"Ǜ";s:2:"ǜ";s:5:"ǜ";s:2:"Ǟ";s:5:"Ǟ";s:2:"ǟ";s:5:"ǟ";s:2:"Ǡ";s:5:"Ǡ";s:2:"ǡ";s:5:"ǡ";s:2:"Ǣ";s:4:"Ǣ";s:2:"ǣ";s:4:"ǣ";s:2:"Ǧ";s:3:"Ǧ";s:2:"ǧ";s:3:"ǧ";s:2:"Ǩ";s:3:"Ǩ";s:2:"ǩ";s:3:"ǩ";s:2:"Ǫ";s:3:"Ǫ";s:2:"ǫ";s:3:"ǫ";s:2:"Ǭ";s:5:"Ǭ";s:2:"ǭ";s:5:"ǭ";s:2:"Ǯ";s:4:"Ǯ";s:2:"ǯ";s:4:"ǯ";s:2:"ǰ";s:3:"ǰ";s:2:"Ǵ";s:3:"Ǵ";s:2:"ǵ";s:3:"ǵ";s:2:"Ǹ";s:3:"Ǹ";s:2:"ǹ";s:3:"ǹ";s:2:"Ǻ";s:5:"Ǻ";s:2:"ǻ";s:5:"ǻ";s:2:"Ǽ";s:4:"Ǽ";s:2:"ǽ";s:4:"ǽ";s:2:"Ǿ";s:4:"Ǿ";s:2:"ǿ";s:4:"ǿ";s:2:"Ȁ";s:3:"Ȁ";s:2:"ȁ";s:3:"ȁ";s:2:"Ȃ";s:3:"Ȃ";s:2:"ȃ";s:3:"ȃ";s:2:"Ȅ";s:3:"Ȅ";s:2:"ȅ";s:3:"ȅ";s:2:"Ȇ";s:3:"Ȇ";s:2:"ȇ";s:3:"ȇ";s:2:"Ȉ";s:3:"Ȉ";s:2:"ȉ";s:3:"ȉ";s:2:"Ȋ";s:3:"Ȋ";s:2:"ȋ";s:3:"ȋ";s:2:"Ȍ";s:3:"Ȍ";s:2:"ȍ";s:3:"ȍ";s:2:"Ȏ";s:3:"Ȏ";s:2:"ȏ";s:3:"ȏ";s:2:"Ȑ";s:3:"Ȑ";s:2:"ȑ";s:3:"ȑ";s:2:"Ȓ";s:3:"Ȓ";s:2:"ȓ";s:3:"ȓ";s:2:"Ȕ";s:3:"Ȕ";s:2:"ȕ";s:3:"ȕ";s:2:"Ȗ";s:3:"Ȗ";s:2:"ȗ";s:3:"ȗ";s:2:"Ș";s:3:"Ș";s:2:"ș";s:3:"ș";s:2:"Ț";s:3:"Ț";s:2:"ț";s:3:"ț";s:2:"Ȟ";s:3:"Ȟ";s:2:"ȟ";s:3:"ȟ";s:2:"Ȧ";s:3:"Ȧ";s:2:"ȧ";s:3:"ȧ";s:2:"Ȩ";s:3:"Ȩ";s:2:"ȩ";s:3:"ȩ";s:2:"Ȫ";s:5:"Ȫ";s:2:"ȫ";s:5:"ȫ";s:2:"Ȭ";s:5:"Ȭ";s:2:"ȭ";s:5:"ȭ";s:2:"Ȯ";s:3:"Ȯ";s:2:"ȯ";s:3:"ȯ";s:2:"Ȱ";s:5:"Ȱ";s:2:"ȱ";s:5:"ȱ";s:2:"Ȳ";s:3:"Ȳ";s:2:"ȳ";s:3:"ȳ";s:2:"̀";s:2:"̀";s:2:"́";s:2:"́";s:2:"̓";s:2:"̓";s:2:"̈́";s:4:"̈́";s:2:"ʹ";s:2:"ʹ";s:2:";";s:1:";";s:2:"΅";s:4:"΅";s:2:"Ά";s:4:"Ά";s:2:"·";s:2:"·";s:2:"Έ";s:4:"Έ";s:2:"Ή";s:4:"Ή";s:2:"Ί";s:4:"Ί";s:2:"Ό";s:4:"Ό";s:2:"Ύ";s:4:"Ύ";s:2:"Ώ";s:4:"Ώ";s:2:"ΐ";s:6:"ΐ";s:2:"Ϊ";s:4:"Ϊ";s:2:"Ϋ";s:4:"Ϋ";s:2:"ά";s:4:"ά";s:2:"έ";s:4:"έ";s:2:"ή";s:4:"ή";s:2:"ί";s:4:"ί";s:2:"ΰ";s:6:"ΰ";s:2:"ϊ";s:4:"ϊ";s:2:"ϋ";s:4:"ϋ";s:2:"ό";s:4:"ό";s:2:"ύ";s:4:"ύ";s:2:"ώ";s:4:"ώ";s:2:"ϓ";s:4:"ϓ";s:2:"ϔ";s:4:"ϔ";s:2:"Ѐ";s:4:"Ѐ";s:2:"Ё";s:4:"Ё";s:2:"Ѓ";s:4:"Ѓ";s:2:"Ї";s:4:"Ї";s:2:"Ќ";s:4:"Ќ";s:2:"Ѝ";s:4:"Ѝ";s:2:"Ў";s:4:"Ў";s:2:"Й";s:4:"Й";s:2:"й";s:4:"й";s:2:"ѐ";s:4:"ѐ";s:2:"ё";s:4:"ё";s:2:"ѓ";s:4:"ѓ";s:2:"ї";s:4:"ї";s:2:"ќ";s:4:"ќ";s:2:"ѝ";s:4:"ѝ";s:2:"ў";s:4:"ў";s:2:"Ѷ";s:4:"Ѷ";s:2:"ѷ";s:4:"ѷ";s:2:"Ӂ";s:4:"Ӂ";s:2:"ӂ";s:4:"ӂ";s:2:"Ӑ";s:4:"Ӑ";s:2:"ӑ";s:4:"ӑ";s:2:"Ӓ";s:4:"Ӓ";s:2:"ӓ";s:4:"ӓ";s:2:"Ӗ";s:4:"Ӗ";s:2:"ӗ";s:4:"ӗ";s:2:"Ӛ";s:4:"Ӛ";s:2:"ӛ";s:4:"ӛ";s:2:"Ӝ";s:4:"Ӝ";s:2:"ӝ";s:4:"ӝ";s:2:"Ӟ";s:4:"Ӟ";s:2:"ӟ";s:4:"ӟ";s:2:"Ӣ";s:4:"Ӣ";s:2:"ӣ";s:4:"ӣ";s:2:"Ӥ";s:4:"Ӥ";s:2:"ӥ";s:4:"ӥ";s:2:"Ӧ";s:4:"Ӧ";s:2:"ӧ";s:4:"ӧ";s:2:"Ӫ";s:4:"Ӫ";s:2:"ӫ";s:4:"ӫ";s:2:"Ӭ";s:4:"Ӭ";s:2:"ӭ";s:4:"ӭ";s:2:"Ӯ";s:4:"Ӯ";s:2:"ӯ";s:4:"ӯ";s:2:"Ӱ";s:4:"Ӱ";s:2:"ӱ";s:4:"ӱ";s:2:"Ӳ";s:4:"Ӳ";s:2:"ӳ";s:4:"ӳ";s:2:"Ӵ";s:4:"Ӵ";s:2:"ӵ";s:4:"ӵ";s:2:"Ӹ";s:4:"Ӹ";s:2:"ӹ";s:4:"ӹ";s:2:"آ";s:4:"آ";s:2:"أ";s:4:"أ";s:2:"ؤ";s:4:"ؤ";s:2:"إ";s:4:"إ";s:2:"ئ";s:4:"ئ";s:2:"ۀ";s:4:"ۀ";s:2:"ۂ";s:4:"ۂ";s:2:"ۓ";s:4:"ۓ";s:3:"ऩ";s:6:"ऩ";s:3:"ऱ";s:6:"ऱ";s:3:"ऴ";s:6:"ऴ";s:3:"क़";s:6:"क़";s:3:"ख़";s:6:"ख़";s:3:"ग़";s:6:"ग़";s:3:"ज़";s:6:"ज़";s:3:"ड़";s:6:"ड़";s:3:"ढ़";s:6:"ढ़";s:3:"फ़";s:6:"फ़";s:3:"य़";s:6:"य़";s:3:"ো";s:6:"ো";s:3:"ৌ";s:6:"ৌ";s:3:"ড়";s:6:"ড়";s:3:"ঢ়";s:6:"ঢ়";s:3:"য়";s:6:"য়";s:3:"ਲ਼";s:6:"ਲ਼";s:3:"ਸ਼";s:6:"ਸ਼";s:3:"ਖ਼";s:6:"ਖ਼";s:3:"ਗ਼";s:6:"ਗ਼";s:3:"ਜ਼";s:6:"ਜ਼";s:3:"ਫ਼";s:6:"ਫ਼";s:3:"ୈ";s:6:"ୈ";s:3:"ୋ";s:6:"ୋ";s:3:"ୌ";s:6:"ୌ";s:3:"ଡ଼";s:6:"ଡ଼";s:3:"ଢ଼";s:6:"ଢ଼";s:3:"ஔ";s:6:"ஔ";s:3:"ொ";s:6:"ொ";s:3:"ோ";s:6:"ோ";s:3:"ௌ";s:6:"ௌ";s:3:"ై";s:6:"ై";s:3:"ೀ";s:6:"ೀ";s:3:"ೇ";s:6:"ೇ";s:3:"ೈ";s:6:"ೈ";s:3:"ೊ";s:6:"ೊ";s:3:"ೋ";s:9:"ೋ";s:3:"ൊ";s:6:"ൊ";s:3:"ോ";s:6:"ോ";s:3:"ൌ";s:6:"ൌ";s:3:"ේ";s:6:"ේ";s:3:"ො";s:6:"ො";s:3:"ෝ";s:9:"ෝ";s:3:"ෞ";s:6:"ෞ";s:3:"གྷ";s:6:"གྷ";s:3:"ཌྷ";s:6:"ཌྷ";s:3:"དྷ";s:6:"དྷ";s:3:"བྷ";s:6:"བྷ";s:3:"ཛྷ";s:6:"ཛྷ";s:3:"ཀྵ";s:6:"ཀྵ";s:3:"ཱི";s:6:"ཱི";s:3:"ཱུ";s:6:"ཱུ";s:3:"ྲྀ";s:6:"ྲྀ";s:3:"ླྀ";s:6:"ླྀ";s:3:"ཱྀ";s:6:"ཱྀ";s:3:"ྒྷ";s:6:"ྒྷ";s:3:"ྜྷ";s:6:"ྜྷ";s:3:"ྡྷ";s:6:"ྡྷ";s:3:"ྦྷ";s:6:"ྦྷ";s:3:"ྫྷ";s:6:"ྫྷ";s:3:"ྐྵ";s:6:"ྐྵ";s:3:"ဦ";s:6:"ဦ";s:3:"Ḁ";s:3:"Ḁ";s:3:"ḁ";s:3:"ḁ";s:3:"Ḃ";s:3:"Ḃ";s:3:"ḃ";s:3:"ḃ";s:3:"Ḅ";s:3:"Ḅ";s:3:"ḅ";s:3:"ḅ";s:3:"Ḇ";s:3:"Ḇ";s:3:"ḇ";s:3:"ḇ";s:3:"Ḉ";s:5:"Ḉ";s:3:"ḉ";s:5:"ḉ";s:3:"Ḋ";s:3:"Ḋ";s:3:"ḋ";s:3:"ḋ";s:3:"Ḍ";s:3:"Ḍ";s:3:"ḍ";s:3:"ḍ";s:3:"Ḏ";s:3:"Ḏ";s:3:"ḏ";s:3:"ḏ";s:3:"Ḑ";s:3:"Ḑ";s:3:"ḑ";s:3:"ḑ";s:3:"Ḓ";s:3:"Ḓ";s:3:"ḓ";s:3:"ḓ";s:3:"Ḕ";s:5:"Ḕ";s:3:"ḕ";s:5:"ḕ";s:3:"Ḗ";s:5:"Ḗ";s:3:"ḗ";s:5:"ḗ";s:3:"Ḙ";s:3:"Ḙ";s:3:"ḙ";s:3:"ḙ";s:3:"Ḛ";s:3:"Ḛ";s:3:"ḛ";s:3:"ḛ";s:3:"Ḝ";s:5:"Ḝ";s:3:"ḝ";s:5:"ḝ";s:3:"Ḟ";s:3:"Ḟ";s:3:"ḟ";s:3:"ḟ";s:3:"Ḡ";s:3:"Ḡ";s:3:"ḡ";s:3:"ḡ";s:3:"Ḣ";s:3:"Ḣ";s:3:"ḣ";s:3:"ḣ";s:3:"Ḥ";s:3:"Ḥ";s:3:"ḥ";s:3:"ḥ";s:3:"Ḧ";s:3:"Ḧ";s:3:"ḧ";s:3:"ḧ";s:3:"Ḩ";s:3:"Ḩ";s:3:"ḩ";s:3:"ḩ";s:3:"Ḫ";s:3:"Ḫ";s:3:"ḫ";s:3:"ḫ";s:3:"Ḭ";s:3:"Ḭ";s:3:"ḭ";s:3:"ḭ";s:3:"Ḯ";s:5:"Ḯ";s:3:"ḯ";s:5:"ḯ";s:3:"Ḱ";s:3:"Ḱ";s:3:"ḱ";s:3:"ḱ";s:3:"Ḳ";s:3:"Ḳ";s:3:"ḳ";s:3:"ḳ";s:3:"Ḵ";s:3:"Ḵ";s:3:"ḵ";s:3:"ḵ";s:3:"Ḷ";s:3:"Ḷ";s:3:"ḷ";s:3:"ḷ";s:3:"Ḹ";s:5:"Ḹ";s:3:"ḹ";s:5:"ḹ";s:3:"Ḻ";s:3:"Ḻ";s:3:"ḻ";s:3:"ḻ";s:3:"Ḽ";s:3:"Ḽ";s:3:"ḽ";s:3:"ḽ";s:3:"Ḿ";s:3:"Ḿ";s:3:"ḿ";s:3:"ḿ";s:3:"Ṁ";s:3:"Ṁ";s:3:"ṁ";s:3:"ṁ";s:3:"Ṃ";s:3:"Ṃ";s:3:"ṃ";s:3:"ṃ";s:3:"Ṅ";s:3:"Ṅ";s:3:"ṅ";s:3:"ṅ";s:3:"Ṇ";s:3:"Ṇ";s:3:"ṇ";s:3:"ṇ";s:3:"Ṉ";s:3:"Ṉ";s:3:"ṉ";s:3:"ṉ";s:3:"Ṋ";s:3:"Ṋ";s:3:"ṋ";s:3:"ṋ";s:3:"Ṍ";s:5:"Ṍ";s:3:"ṍ";s:5:"ṍ";s:3:"Ṏ";s:5:"Ṏ";s:3:"ṏ";s:5:"ṏ";s:3:"Ṑ";s:5:"Ṑ";s:3:"ṑ";s:5:"ṑ";s:3:"Ṓ";s:5:"Ṓ";s:3:"ṓ";s:5:"ṓ";s:3:"Ṕ";s:3:"Ṕ";s:3:"ṕ";s:3:"ṕ";s:3:"Ṗ";s:3:"Ṗ";s:3:"ṗ";s:3:"ṗ";s:3:"Ṙ";s:3:"Ṙ";s:3:"ṙ";s:3:"ṙ";s:3:"Ṛ";s:3:"Ṛ";s:3:"ṛ";s:3:"ṛ";s:3:"Ṝ";s:5:"Ṝ";s:3:"ṝ";s:5:"ṝ";s:3:"Ṟ";s:3:"Ṟ";s:3:"ṟ";s:3:"ṟ";s:3:"Ṡ";s:3:"Ṡ";s:3:"ṡ";s:3:"ṡ";s:3:"Ṣ";s:3:"Ṣ";s:3:"ṣ";s:3:"ṣ";s:3:"Ṥ";s:5:"Ṥ";s:3:"ṥ";s:5:"ṥ";s:3:"Ṧ";s:5:"Ṧ";s:3:"ṧ";s:5:"ṧ";s:3:"Ṩ";s:5:"Ṩ";s:3:"ṩ";s:5:"ṩ";s:3:"Ṫ";s:3:"Ṫ";s:3:"ṫ";s:3:"ṫ";s:3:"Ṭ";s:3:"Ṭ";s:3:"ṭ";s:3:"ṭ";s:3:"Ṯ";s:3:"Ṯ";s:3:"ṯ";s:3:"ṯ";s:3:"Ṱ";s:3:"Ṱ";s:3:"ṱ";s:3:"ṱ";s:3:"Ṳ";s:3:"Ṳ";s:3:"ṳ";s:3:"ṳ";s:3:"Ṵ";s:3:"Ṵ";s:3:"ṵ";s:3:"ṵ";s:3:"Ṷ";s:3:"Ṷ";s:3:"ṷ";s:3:"ṷ";s:3:"Ṹ";s:5:"Ṹ";s:3:"ṹ";s:5:"ṹ";s:3:"Ṻ";s:5:"Ṻ";s:3:"ṻ";s:5:"ṻ";s:3:"Ṽ";s:3:"Ṽ";s:3:"ṽ";s:3:"ṽ";s:3:"Ṿ";s:3:"Ṿ";s:3:"ṿ";s:3:"ṿ";s:3:"Ẁ";s:3:"Ẁ";s:3:"ẁ";s:3:"ẁ";s:3:"Ẃ";s:3:"Ẃ";s:3:"ẃ";s:3:"ẃ";s:3:"Ẅ";s:3:"Ẅ";s:3:"ẅ";s:3:"ẅ";s:3:"Ẇ";s:3:"Ẇ";s:3:"ẇ";s:3:"ẇ";s:3:"Ẉ";s:3:"Ẉ";s:3:"ẉ";s:3:"ẉ";s:3:"Ẋ";s:3:"Ẋ";s:3:"ẋ";s:3:"ẋ";s:3:"Ẍ";s:3:"Ẍ";s:3:"ẍ";s:3:"ẍ";s:3:"Ẏ";s:3:"Ẏ";s:3:"ẏ";s:3:"ẏ";s:3:"Ẑ";s:3:"Ẑ";s:3:"ẑ";s:3:"ẑ";s:3:"Ẓ";s:3:"Ẓ";s:3:"ẓ";s:3:"ẓ";s:3:"Ẕ";s:3:"Ẕ";s:3:"ẕ";s:3:"ẕ";s:3:"ẖ";s:3:"ẖ";s:3:"ẗ";s:3:"ẗ";s:3:"ẘ";s:3:"ẘ";s:3:"ẙ";s:3:"ẙ";s:3:"ẛ";s:4:"ẛ";s:3:"Ạ";s:3:"Ạ";s:3:"ạ";s:3:"ạ";s:3:"Ả";s:3:"Ả";s:3:"ả";s:3:"ả";s:3:"Ấ";s:5:"Ấ";s:3:"ấ";s:5:"ấ";s:3:"Ầ";s:5:"Ầ";s:3:"ầ";s:5:"ầ";s:3:"Ẩ";s:5:"Ẩ";s:3:"ẩ";s:5:"ẩ";s:3:"Ẫ";s:5:"Ẫ";s:3:"ẫ";s:5:"ẫ";s:3:"Ậ";s:5:"Ậ";s:3:"ậ";s:5:"ậ";s:3:"Ắ";s:5:"Ắ";s:3:"ắ";s:5:"ắ";s:3:"Ằ";s:5:"Ằ";s:3:"ằ";s:5:"ằ";s:3:"Ẳ";s:5:"Ẳ";s:3:"ẳ";s:5:"ẳ";s:3:"Ẵ";s:5:"Ẵ";s:3:"ẵ";s:5:"ẵ";s:3:"Ặ";s:5:"Ặ";s:3:"ặ";s:5:"ặ";s:3:"Ẹ";s:3:"Ẹ";s:3:"ẹ";s:3:"ẹ";s:3:"Ẻ";s:3:"Ẻ";s:3:"ẻ";s:3:"ẻ";s:3:"Ẽ";s:3:"Ẽ";s:3:"ẽ";s:3:"ẽ";s:3:"Ế";s:5:"Ế";s:3:"ế";s:5:"ế";s:3:"Ề";s:5:"Ề";s:3:"ề";s:5:"ề";s:3:"Ể";s:5:"Ể";s:3:"ể";s:5:"ể";s:3:"Ễ";s:5:"Ễ";s:3:"ễ";s:5:"ễ";s:3:"Ệ";s:5:"Ệ";s:3:"ệ";s:5:"ệ";s:3:"Ỉ";s:3:"Ỉ";s:3:"ỉ";s:3:"ỉ";s:3:"Ị";s:3:"Ị";s:3:"ị";s:3:"ị";s:3:"Ọ";s:3:"Ọ";s:3:"ọ";s:3:"ọ";s:3:"Ỏ";s:3:"Ỏ";s:3:"ỏ";s:3:"ỏ";s:3:"Ố";s:5:"Ố";s:3:"ố";s:5:"ố";s:3:"Ồ";s:5:"Ồ";s:3:"ồ";s:5:"ồ";s:3:"Ổ";s:5:"Ổ";s:3:"ổ";s:5:"ổ";s:3:"Ỗ";s:5:"Ỗ";s:3:"ỗ";s:5:"ỗ";s:3:"Ộ";s:5:"Ộ";s:3:"ộ";s:5:"ộ";s:3:"Ớ";s:5:"Ớ";s:3:"ớ";s:5:"ớ";s:3:"Ờ";s:5:"Ờ";s:3:"ờ";s:5:"ờ";s:3:"Ở";s:5:"Ở";s:3:"ở";s:5:"ở";s:3:"Ỡ";s:5:"Ỡ";s:3:"ỡ";s:5:"ỡ";s:3:"Ợ";s:5:"Ợ";s:3:"ợ";s:5:"ợ";s:3:"Ụ";s:3:"Ụ";s:3:"ụ";s:3:"ụ";s:3:"Ủ";s:3:"Ủ";s:3:"ủ";s:3:"ủ";s:3:"Ứ";s:5:"Ứ";s:3:"ứ";s:5:"ứ";s:3:"Ừ";s:5:"Ừ";s:3:"ừ";s:5:"ừ";s:3:"Ử";s:5:"Ử";s:3:"ử";s:5:"ử";s:3:"Ữ";s:5:"Ữ";s:3:"ữ";s:5:"ữ";s:3:"Ự";s:5:"Ự";s:3:"ự";s:5:"ự";s:3:"Ỳ";s:3:"Ỳ";s:3:"ỳ";s:3:"ỳ";s:3:"Ỵ";s:3:"Ỵ";s:3:"ỵ";s:3:"ỵ";s:3:"Ỷ";s:3:"Ỷ";s:3:"ỷ";s:3:"ỷ";s:3:"Ỹ";s:3:"Ỹ";s:3:"ỹ";s:3:"ỹ";s:3:"ἀ";s:4:"ἀ";s:3:"ἁ";s:4:"ἁ";s:3:"ἂ";s:6:"ἂ";s:3:"ἃ";s:6:"ἃ";s:3:"ἄ";s:6:"ἄ";s:3:"ἅ";s:6:"ἅ";s:3:"ἆ";s:6:"ἆ";s:3:"ἇ";s:6:"ἇ";s:3:"Ἀ";s:4:"Ἀ";s:3:"Ἁ";s:4:"Ἁ";s:3:"Ἂ";s:6:"Ἂ";s:3:"Ἃ";s:6:"Ἃ";s:3:"Ἄ";s:6:"Ἄ";s:3:"Ἅ";s:6:"Ἅ";s:3:"Ἆ";s:6:"Ἆ";s:3:"Ἇ";s:6:"Ἇ";s:3:"ἐ";s:4:"ἐ";s:3:"ἑ";s:4:"ἑ";s:3:"ἒ";s:6:"ἒ";s:3:"ἓ";s:6:"ἓ";s:3:"ἔ";s:6:"ἔ";s:3:"ἕ";s:6:"ἕ";s:3:"Ἐ";s:4:"Ἐ";s:3:"Ἑ";s:4:"Ἑ";s:3:"Ἒ";s:6:"Ἒ";s:3:"Ἓ";s:6:"Ἓ";s:3:"Ἔ";s:6:"Ἔ";s:3:"Ἕ";s:6:"Ἕ";s:3:"ἠ";s:4:"ἠ";s:3:"ἡ";s:4:"ἡ";s:3:"ἢ";s:6:"ἢ";s:3:"ἣ";s:6:"ἣ";s:3:"ἤ";s:6:"ἤ";s:3:"ἥ";s:6:"ἥ";s:3:"ἦ";s:6:"ἦ";s:3:"ἧ";s:6:"ἧ";s:3:"Ἠ";s:4:"Ἠ";s:3:"Ἡ";s:4:"Ἡ";s:3:"Ἢ";s:6:"Ἢ";s:3:"Ἣ";s:6:"Ἣ";s:3:"Ἤ";s:6:"Ἤ";s:3:"Ἥ";s:6:"Ἥ";s:3:"Ἦ";s:6:"Ἦ";s:3:"Ἧ";s:6:"Ἧ";s:3:"ἰ";s:4:"ἰ";s:3:"ἱ";s:4:"ἱ";s:3:"ἲ";s:6:"ἲ";s:3:"ἳ";s:6:"ἳ";s:3:"ἴ";s:6:"ἴ";s:3:"ἵ";s:6:"ἵ";s:3:"ἶ";s:6:"ἶ";s:3:"ἷ";s:6:"ἷ";s:3:"Ἰ";s:4:"Ἰ";s:3:"Ἱ";s:4:"Ἱ";s:3:"Ἲ";s:6:"Ἲ";s:3:"Ἳ";s:6:"Ἳ";s:3:"Ἴ";s:6:"Ἴ";s:3:"Ἵ";s:6:"Ἵ";s:3:"Ἶ";s:6:"Ἶ";s:3:"Ἷ";s:6:"Ἷ";s:3:"ὀ";s:4:"ὀ";s:3:"ὁ";s:4:"ὁ";s:3:"ὂ";s:6:"ὂ";s:3:"ὃ";s:6:"ὃ";s:3:"ὄ";s:6:"ὄ";s:3:"ὅ";s:6:"ὅ";s:3:"Ὀ";s:4:"Ὀ";s:3:"Ὁ";s:4:"Ὁ";s:3:"Ὂ";s:6:"Ὂ";s:3:"Ὃ";s:6:"Ὃ";s:3:"Ὄ";s:6:"Ὄ";s:3:"Ὅ";s:6:"Ὅ";s:3:"ὐ";s:4:"ὐ";s:3:"ὑ";s:4:"ὑ";s:3:"ὒ";s:6:"ὒ";s:3:"ὓ";s:6:"ὓ";s:3:"ὔ";s:6:"ὔ";s:3:"ὕ";s:6:"ὕ";s:3:"ὖ";s:6:"ὖ";s:3:"ὗ";s:6:"ὗ";s:3:"Ὑ";s:4:"Ὑ";s:3:"Ὓ";s:6:"Ὓ";s:3:"Ὕ";s:6:"Ὕ";s:3:"Ὗ";s:6:"Ὗ";s:3:"ὠ";s:4:"ὠ";s:3:"ὡ";s:4:"ὡ";s:3:"ὢ";s:6:"ὢ";s:3:"ὣ";s:6:"ὣ";s:3:"ὤ";s:6:"ὤ";s:3:"ὥ";s:6:"ὥ";s:3:"ὦ";s:6:"ὦ";s:3:"ὧ";s:6:"ὧ";s:3:"Ὠ";s:4:"Ὠ";s:3:"Ὡ";s:4:"Ὡ";s:3:"Ὢ";s:6:"Ὢ";s:3:"Ὣ";s:6:"Ὣ";s:3:"Ὤ";s:6:"Ὤ";s:3:"Ὥ";s:6:"Ὥ";s:3:"Ὦ";s:6:"Ὦ";s:3:"Ὧ";s:6:"Ὧ";s:3:"ὰ";s:4:"ὰ";s:3:"ά";s:4:"ά";s:3:"ὲ";s:4:"ὲ";s:3:"έ";s:4:"έ";s:3:"ὴ";s:4:"ὴ";s:3:"ή";s:4:"ή";s:3:"ὶ";s:4:"ὶ";s:3:"ί";s:4:"ί";s:3:"ὸ";s:4:"ὸ";s:3:"ό";s:4:"ό";s:3:"ὺ";s:4:"ὺ";s:3:"ύ";s:4:"ύ";s:3:"ὼ";s:4:"ὼ";s:3:"ώ";s:4:"ώ";s:3:"ᾀ";s:6:"ᾀ";s:3:"ᾁ";s:6:"ᾁ";s:3:"ᾂ";s:8:"ᾂ";s:3:"ᾃ";s:8:"ᾃ";s:3:"ᾄ";s:8:"ᾄ";s:3:"ᾅ";s:8:"ᾅ";s:3:"ᾆ";s:8:"ᾆ";s:3:"ᾇ";s:8:"ᾇ";s:3:"ᾈ";s:6:"ᾈ";s:3:"ᾉ";s:6:"ᾉ";s:3:"ᾊ";s:8:"ᾊ";s:3:"ᾋ";s:8:"ᾋ";s:3:"ᾌ";s:8:"ᾌ";s:3:"ᾍ";s:8:"ᾍ";s:3:"ᾎ";s:8:"ᾎ";s:3:"ᾏ";s:8:"ᾏ";s:3:"ᾐ";s:6:"ᾐ";s:3:"ᾑ";s:6:"ᾑ";s:3:"ᾒ";s:8:"ᾒ";s:3:"ᾓ";s:8:"ᾓ";s:3:"ᾔ";s:8:"ᾔ";s:3:"ᾕ";s:8:"ᾕ";s:3:"ᾖ";s:8:"ᾖ";s:3:"ᾗ";s:8:"ᾗ";s:3:"ᾘ";s:6:"ᾘ";s:3:"ᾙ";s:6:"ᾙ";s:3:"ᾚ";s:8:"ᾚ";s:3:"ᾛ";s:8:"ᾛ";s:3:"ᾜ";s:8:"ᾜ";s:3:"ᾝ";s:8:"ᾝ";s:3:"ᾞ";s:8:"ᾞ";s:3:"ᾟ";s:8:"ᾟ";s:3:"ᾠ";s:6:"ᾠ";s:3:"ᾡ";s:6:"ᾡ";s:3:"ᾢ";s:8:"ᾢ";s:3:"ᾣ";s:8:"ᾣ";s:3:"ᾤ";s:8:"ᾤ";s:3:"ᾥ";s:8:"ᾥ";s:3:"ᾦ";s:8:"ᾦ";s:3:"ᾧ";s:8:"ᾧ";s:3:"ᾨ";s:6:"ᾨ";s:3:"ᾩ";s:6:"ᾩ";s:3:"ᾪ";s:8:"ᾪ";s:3:"ᾫ";s:8:"ᾫ";s:3:"ᾬ";s:8:"ᾬ";s:3:"ᾭ";s:8:"ᾭ";s:3:"ᾮ";s:8:"ᾮ";s:3:"ᾯ";s:8:"ᾯ";s:3:"ᾰ";s:4:"ᾰ";s:3:"ᾱ";s:4:"ᾱ";s:3:"ᾲ";s:6:"ᾲ";s:3:"ᾳ";s:4:"ᾳ";s:3:"ᾴ";s:6:"ᾴ";s:3:"ᾶ";s:4:"ᾶ";s:3:"ᾷ";s:6:"ᾷ";s:3:"Ᾰ";s:4:"Ᾰ";s:3:"Ᾱ";s:4:"Ᾱ";s:3:"Ὰ";s:4:"Ὰ";s:3:"Ά";s:4:"Ά";s:3:"ᾼ";s:4:"ᾼ";s:3:"ι";s:2:"ι";s:3:"῁";s:4:"῁";s:3:"ῂ";s:6:"ῂ";s:3:"ῃ";s:4:"ῃ";s:3:"ῄ";s:6:"ῄ";s:3:"ῆ";s:4:"ῆ";s:3:"ῇ";s:6:"ῇ";s:3:"Ὲ";s:4:"Ὲ";s:3:"Έ";s:4:"Έ";s:3:"Ὴ";s:4:"Ὴ";s:3:"Ή";s:4:"Ή";s:3:"ῌ";s:4:"ῌ";s:3:"῍";s:5:"῍";s:3:"῎";s:5:"῎";s:3:"῏";s:5:"῏";s:3:"ῐ";s:4:"ῐ";s:3:"ῑ";s:4:"ῑ";s:3:"ῒ";s:6:"ῒ";s:3:"ΐ";s:6:"ΐ";s:3:"ῖ";s:4:"ῖ";s:3:"ῗ";s:6:"ῗ";s:3:"Ῐ";s:4:"Ῐ";s:3:"Ῑ";s:4:"Ῑ";s:3:"Ὶ";s:4:"Ὶ";s:3:"Ί";s:4:"Ί";s:3:"῝";s:5:"῝";s:3:"῞";s:5:"῞";s:3:"῟";s:5:"῟";s:3:"ῠ";s:4:"ῠ";s:3:"ῡ";s:4:"ῡ";s:3:"ῢ";s:6:"ῢ";s:3:"ΰ";s:6:"ΰ";s:3:"ῤ";s:4:"ῤ";s:3:"ῥ";s:4:"ῥ";s:3:"ῦ";s:4:"ῦ";s:3:"ῧ";s:6:"ῧ";s:3:"Ῠ";s:4:"Ῠ";s:3:"Ῡ";s:4:"Ῡ";s:3:"Ὺ";s:4:"Ὺ";s:3:"Ύ";s:4:"Ύ";s:3:"Ῥ";s:4:"Ῥ";s:3:"῭";s:4:"῭";s:3:"΅";s:4:"΅";s:3:"`";s:1:"`";s:3:"ῲ";s:6:"ῲ";s:3:"ῳ";s:4:"ῳ";s:3:"ῴ";s:6:"ῴ";s:3:"ῶ";s:4:"ῶ";s:3:"ῷ";s:6:"ῷ";s:3:"Ὸ";s:4:"Ὸ";s:3:"Ό";s:4:"Ό";s:3:"Ὼ";s:4:"Ὼ";s:3:"Ώ";s:4:"Ώ";s:3:"ῼ";s:4:"ῼ";s:3:"´";s:2:"´";s:3:" ";s:3:" ";s:3:" ";s:3:" ";s:3:"Ω";s:2:"Ω";s:3:"K";s:1:"K";s:3:"Å";s:3:"Å";s:3:"↚";s:5:"↚";s:3:"↛";s:5:"↛";s:3:"↮";s:5:"↮";s:3:"⇍";s:5:"⇍";s:3:"⇎";s:5:"⇎";s:3:"⇏";s:5:"⇏";s:3:"∄";s:5:"∄";s:3:"∉";s:5:"∉";s:3:"∌";s:5:"∌";s:3:"∤";s:5:"∤";s:3:"∦";s:5:"∦";s:3:"≁";s:5:"≁";s:3:"≄";s:5:"≄";s:3:"≇";s:5:"≇";s:3:"≉";s:5:"≉";s:3:"≠";s:3:"≠";s:3:"≢";s:5:"≢";s:3:"≭";s:5:"≭";s:3:"≮";s:3:"≮";s:3:"≯";s:3:"≯";s:3:"≰";s:5:"≰";s:3:"≱";s:5:"≱";s:3:"≴";s:5:"≴";s:3:"≵";s:5:"≵";s:3:"≸";s:5:"≸";s:3:"≹";s:5:"≹";s:3:"⊀";s:5:"⊀";s:3:"⊁";s:5:"⊁";s:3:"⊄";s:5:"⊄";s:3:"⊅";s:5:"⊅";s:3:"⊈";s:5:"⊈";s:3:"⊉";s:5:"⊉";s:3:"⊬";s:5:"⊬";s:3:"⊭";s:5:"⊭";s:3:"⊮";s:5:"⊮";s:3:"⊯";s:5:"⊯";s:3:"⋠";s:5:"⋠";s:3:"⋡";s:5:"⋡";s:3:"⋢";s:5:"⋢";s:3:"⋣";s:5:"⋣";s:3:"⋪";s:5:"⋪";s:3:"⋫";s:5:"⋫";s:3:"⋬";s:5:"⋬";s:3:"⋭";s:5:"⋭";s:3:"〈";s:3:"〈";s:3:"〉";s:3:"〉";s:3:"⫝̸";s:5:"⫝̸";s:3:"が";s:6:"が";s:3:"ぎ";s:6:"ぎ";s:3:"ぐ";s:6:"ぐ";s:3:"げ";s:6:"げ";s:3:"ご";s:6:"ご";s:3:"ざ";s:6:"ざ";s:3:"じ";s:6:"じ";s:3:"ず";s:6:"ず";s:3:"ぜ";s:6:"ぜ";s:3:"ぞ";s:6:"ぞ";s:3:"だ";s:6:"だ";s:3:"ぢ";s:6:"ぢ";s:3:"づ";s:6:"づ";s:3:"で";s:6:"で";s:3:"ど";s:6:"ど";s:3:"ば";s:6:"ば";s:3:"ぱ";s:6:"ぱ";s:3:"び";s:6:"び";s:3:"ぴ";s:6:"ぴ";s:3:"ぶ";s:6:"ぶ";s:3:"ぷ";s:6:"ぷ";s:3:"べ";s:6:"べ";s:3:"ぺ";s:6:"ぺ";s:3:"ぼ";s:6:"ぼ";s:3:"ぽ";s:6:"ぽ";s:3:"ゔ";s:6:"ゔ";s:3:"ゞ";s:6:"ゞ";s:3:"ガ";s:6:"ガ";s:3:"ギ";s:6:"ギ";s:3:"グ";s:6:"グ";s:3:"ゲ";s:6:"ゲ";s:3:"ゴ";s:6:"ゴ";s:3:"ザ";s:6:"ザ";s:3:"ジ";s:6:"ジ";s:3:"ズ";s:6:"ズ";s:3:"ゼ";s:6:"ゼ";s:3:"ゾ";s:6:"ゾ";s:3:"ダ";s:6:"ダ";s:3:"ヂ";s:6:"ヂ";s:3:"ヅ";s:6:"ヅ";s:3:"デ";s:6:"デ";s:3:"ド";s:6:"ド";s:3:"バ";s:6:"バ";s:3:"パ";s:6:"パ";s:3:"ビ";s:6:"ビ";s:3:"ピ";s:6:"ピ";s:3:"ブ";s:6:"ブ";s:3:"プ";s:6:"プ";s:3:"ベ";s:6:"ベ";s:3:"ペ";s:6:"ペ";s:3:"ボ";s:6:"ボ";s:3:"ポ";s:6:"ポ";s:3:"ヴ";s:6:"ヴ";s:3:"ヷ";s:6:"ヷ";s:3:"ヸ";s:6:"ヸ";s:3:"ヹ";s:6:"ヹ";s:3:"ヺ";s:6:"ヺ";s:3:"ヾ";s:6:"ヾ";s:3:"豈";s:3:"豈";s:3:"更";s:3:"更";s:3:"車";s:3:"車";s:3:"賈";s:3:"賈";s:3:"滑";s:3:"滑";s:3:"串";s:3:"串";s:3:"句";s:3:"句";s:3:"龜";s:3:"龜";s:3:"龜";s:3:"龜";s:3:"契";s:3:"契";s:3:"金";s:3:"金";s:3:"喇";s:3:"喇";s:3:"奈";s:3:"奈";s:3:"懶";s:3:"懶";s:3:"癩";s:3:"癩";s:3:"羅";s:3:"羅";s:3:"蘿";s:3:"蘿";s:3:"螺";s:3:"螺";s:3:"裸";s:3:"裸";s:3:"邏";s:3:"邏";s:3:"樂";s:3:"樂";s:3:"洛";s:3:"洛";s:3:"烙";s:3:"烙";s:3:"珞";s:3:"珞";s:3:"落";s:3:"落";s:3:"酪";s:3:"酪";s:3:"駱";s:3:"駱";s:3:"亂";s:3:"亂";s:3:"卵";s:3:"卵";s:3:"欄";s:3:"欄";s:3:"爛";s:3:"爛";s:3:"蘭";s:3:"蘭";s:3:"鸞";s:3:"鸞";s:3:"嵐";s:3:"嵐";s:3:"濫";s:3:"濫";s:3:"藍";s:3:"藍";s:3:"襤";s:3:"襤";s:3:"拉";s:3:"拉";s:3:"臘";s:3:"臘";s:3:"蠟";s:3:"蠟";s:3:"廊";s:3:"廊";s:3:"朗";s:3:"朗";s:3:"浪";s:3:"浪";s:3:"狼";s:3:"狼";s:3:"郎";s:3:"郎";s:3:"來";s:3:"來";s:3:"冷";s:3:"冷";s:3:"勞";s:3:"勞";s:3:"擄";s:3:"擄";s:3:"櫓";s:3:"櫓";s:3:"爐";s:3:"爐";s:3:"盧";s:3:"盧";s:3:"老";s:3:"老";s:3:"蘆";s:3:"蘆";s:3:"虜";s:3:"虜";s:3:"路";s:3:"路";s:3:"露";s:3:"露";s:3:"魯";s:3:"魯";s:3:"鷺";s:3:"鷺";s:3:"碌";s:3:"碌";s:3:"祿";s:3:"祿";s:3:"綠";s:3:"綠";s:3:"菉";s:3:"菉";s:3:"錄";s:3:"錄";s:3:"鹿";s:3:"鹿";s:3:"論";s:3:"論";s:3:"壟";s:3:"壟";s:3:"弄";s:3:"弄";s:3:"籠";s:3:"籠";s:3:"聾";s:3:"聾";s:3:"牢";s:3:"牢";s:3:"磊";s:3:"磊";s:3:"賂";s:3:"賂";s:3:"雷";s:3:"雷";s:3:"壘";s:3:"壘";s:3:"屢";s:3:"屢";s:3:"樓";s:3:"樓";s:3:"淚";s:3:"淚";s:3:"漏";s:3:"漏";s:3:"累";s:3:"累";s:3:"縷";s:3:"縷";s:3:"陋";s:3:"陋";s:3:"勒";s:3:"勒";s:3:"肋";s:3:"肋";s:3:"凜";s:3:"凜";s:3:"凌";s:3:"凌";s:3:"稜";s:3:"稜";s:3:"綾";s:3:"綾";s:3:"菱";s:3:"菱";s:3:"陵";s:3:"陵";s:3:"讀";s:3:"讀";s:3:"拏";s:3:"拏";s:3:"樂";s:3:"樂";s:3:"諾";s:3:"諾";s:3:"丹";s:3:"丹";s:3:"寧";s:3:"寧";s:3:"怒";s:3:"怒";s:3:"率";s:3:"率";s:3:"異";s:3:"異";s:3:"北";s:3:"北";s:3:"磻";s:3:"磻";s:3:"便";s:3:"便";s:3:"復";s:3:"復";s:3:"不";s:3:"不";s:3:"泌";s:3:"泌";s:3:"數";s:3:"數";s:3:"索";s:3:"索";s:3:"參";s:3:"參";s:3:"塞";s:3:"塞";s:3:"省";s:3:"省";s:3:"葉";s:3:"葉";s:3:"說";s:3:"說";s:3:"殺";s:3:"殺";s:3:"辰";s:3:"辰";s:3:"沈";s:3:"沈";s:3:"拾";s:3:"拾";s:3:"若";s:3:"若";s:3:"掠";s:3:"掠";s:3:"略";s:3:"略";s:3:"亮";s:3:"亮";s:3:"兩";s:3:"兩";s:3:"凉";s:3:"凉";s:3:"梁";s:3:"梁";s:3:"糧";s:3:"糧";s:3:"良";s:3:"良";s:3:"諒";s:3:"諒";s:3:"量";s:3:"量";s:3:"勵";s:3:"勵";s:3:"呂";s:3:"呂";s:3:"女";s:3:"女";s:3:"廬";s:3:"廬";s:3:"旅";s:3:"旅";s:3:"濾";s:3:"濾";s:3:"礪";s:3:"礪";s:3:"閭";s:3:"閭";s:3:"驪";s:3:"驪";s:3:"麗";s:3:"麗";s:3:"黎";s:3:"黎";s:3:"力";s:3:"力";s:3:"曆";s:3:"曆";s:3:"歷";s:3:"歷";s:3:"轢";s:3:"轢";s:3:"年";s:3:"年";s:3:"憐";s:3:"憐";s:3:"戀";s:3:"戀";s:3:"撚";s:3:"撚";s:3:"漣";s:3:"漣";s:3:"煉";s:3:"煉";s:3:"璉";s:3:"璉";s:3:"秊";s:3:"秊";s:3:"練";s:3:"練";s:3:"聯";s:3:"聯";s:3:"輦";s:3:"輦";s:3:"蓮";s:3:"蓮";s:3:"連";s:3:"連";s:3:"鍊";s:3:"鍊";s:3:"列";s:3:"列";s:3:"劣";s:3:"劣";s:3:"咽";s:3:"咽";s:3:"烈";s:3:"烈";s:3:"裂";s:3:"裂";s:3:"說";s:3:"說";s:3:"廉";s:3:"廉";s:3:"念";s:3:"念";s:3:"捻";s:3:"捻";s:3:"殮";s:3:"殮";s:3:"簾";s:3:"簾";s:3:"獵";s:3:"獵";s:3:"令";s:3:"令";s:3:"囹";s:3:"囹";s:3:"寧";s:3:"寧";s:3:"嶺";s:3:"嶺";s:3:"怜";s:3:"怜";s:3:"玲";s:3:"玲";s:3:"瑩";s:3:"瑩";s:3:"羚";s:3:"羚";s:3:"聆";s:3:"聆";s:3:"鈴";s:3:"鈴";s:3:"零";s:3:"零";s:3:"靈";s:3:"靈";s:3:"領";s:3:"領";s:3:"例";s:3:"例";s:3:"禮";s:3:"禮";s:3:"醴";s:3:"醴";s:3:"隸";s:3:"隸";s:3:"惡";s:3:"惡";s:3:"了";s:3:"了";s:3:"僚";s:3:"僚";s:3:"寮";s:3:"寮";s:3:"尿";s:3:"尿";s:3:"料";s:3:"料";s:3:"樂";s:3:"樂";s:3:"燎";s:3:"燎";s:3:"療";s:3:"療";s:3:"蓼";s:3:"蓼";s:3:"遼";s:3:"遼";s:3:"龍";s:3:"龍";s:3:"暈";s:3:"暈";s:3:"阮";s:3:"阮";s:3:"劉";s:3:"劉";s:3:"杻";s:3:"杻";s:3:"柳";s:3:"柳";s:3:"流";s:3:"流";s:3:"溜";s:3:"溜";s:3:"琉";s:3:"琉";s:3:"留";s:3:"留";s:3:"硫";s:3:"硫";s:3:"紐";s:3:"紐";s:3:"類";s:3:"類";s:3:"六";s:3:"六";s:3:"戮";s:3:"戮";s:3:"陸";s:3:"陸";s:3:"倫";s:3:"倫";s:3:"崙";s:3:"崙";s:3:"淪";s:3:"淪";s:3:"輪";s:3:"輪";s:3:"律";s:3:"律";s:3:"慄";s:3:"慄";s:3:"栗";s:3:"栗";s:3:"率";s:3:"率";s:3:"隆";s:3:"隆";s:3:"利";s:3:"利";s:3:"吏";s:3:"吏";s:3:"履";s:3:"履";s:3:"易";s:3:"易";s:3:"李";s:3:"李";s:3:"梨";s:3:"梨";s:3:"泥";s:3:"泥";s:3:"理";s:3:"理";s:3:"痢";s:3:"痢";s:3:"罹";s:3:"罹";s:3:"裏";s:3:"裏";s:3:"裡";s:3:"裡";s:3:"里";s:3:"里";s:3:"離";s:3:"離";s:3:"匿";s:3:"匿";s:3:"溺";s:3:"溺";s:3:"吝";s:3:"吝";s:3:"燐";s:3:"燐";s:3:"璘";s:3:"璘";s:3:"藺";s:3:"藺";s:3:"隣";s:3:"隣";s:3:"鱗";s:3:"鱗";s:3:"麟";s:3:"麟";s:3:"林";s:3:"林";s:3:"淋";s:3:"淋";s:3:"臨";s:3:"臨";s:3:"立";s:3:"立";s:3:"笠";s:3:"笠";s:3:"粒";s:3:"粒";s:3:"狀";s:3:"狀";s:3:"炙";s:3:"炙";s:3:"識";s:3:"識";s:3:"什";s:3:"什";s:3:"茶";s:3:"茶";s:3:"刺";s:3:"刺";s:3:"切";s:3:"切";s:3:"度";s:3:"度";s:3:"拓";s:3:"拓";s:3:"糖";s:3:"糖";s:3:"宅";s:3:"宅";s:3:"洞";s:3:"洞";s:3:"暴";s:3:"暴";s:3:"輻";s:3:"輻";s:3:"行";s:3:"行";s:3:"降";s:3:"降";s:3:"見";s:3:"見";s:3:"廓";s:3:"廓";s:3:"兀";s:3:"兀";s:3:"嗀";s:3:"嗀";s:3:"塚";s:3:"塚";s:3:"晴";s:3:"晴";s:3:"凞";s:3:"凞";s:3:"猪";s:3:"猪";s:3:"益";s:3:"益";s:3:"礼";s:3:"礼";s:3:"神";s:3:"神";s:3:"祥";s:3:"祥";s:3:"福";s:3:"福";s:3:"靖";s:3:"靖";s:3:"精";s:3:"精";s:3:"羽";s:3:"羽";s:3:"蘒";s:3:"蘒";s:3:"諸";s:3:"諸";s:3:"逸";s:3:"逸";s:3:"都";s:3:"都";s:3:"飯";s:3:"飯";s:3:"飼";s:3:"飼";s:3:"館";s:3:"館";s:3:"鶴";s:3:"鶴";s:3:"侮";s:3:"侮";s:3:"僧";s:3:"僧";s:3:"免";s:3:"免";s:3:"勉";s:3:"勉";s:3:"勤";s:3:"勤";s:3:"卑";s:3:"卑";s:3:"喝";s:3:"喝";s:3:"嘆";s:3:"嘆";s:3:"器";s:3:"器";s:3:"塀";s:3:"塀";s:3:"墨";s:3:"墨";s:3:"層";s:3:"層";s:3:"屮";s:3:"屮";s:3:"悔";s:3:"悔";s:3:"慨";s:3:"慨";s:3:"憎";s:3:"憎";s:3:"懲";s:3:"懲";s:3:"敏";s:3:"敏";s:3:"既";s:3:"既";s:3:"暑";s:3:"暑";s:3:"梅";s:3:"梅";s:3:"海";s:3:"海";s:3:"渚";s:3:"渚";s:3:"漢";s:3:"漢";s:3:"煮";s:3:"煮";s:3:"爫";s:3:"爫";s:3:"琢";s:3:"琢";s:3:"碑";s:3:"碑";s:3:"社";s:3:"社";s:3:"祉";s:3:"祉";s:3:"祈";s:3:"祈";s:3:"祐";s:3:"祐";s:3:"祖";s:3:"祖";s:3:"祝";s:3:"祝";s:3:"禍";s:3:"禍";s:3:"禎";s:3:"禎";s:3:"穀";s:3:"穀";s:3:"突";s:3:"突";s:3:"節";s:3:"節";s:3:"練";s:3:"練";s:3:"縉";s:3:"縉";s:3:"繁";s:3:"繁";s:3:"署";s:3:"署";s:3:"者";s:3:"者";s:3:"臭";s:3:"臭";s:3:"艹";s:3:"艹";s:3:"艹";s:3:"艹";s:3:"著";s:3:"著";s:3:"褐";s:3:"褐";s:3:"視";s:3:"視";s:3:"謁";s:3:"謁";s:3:"謹";s:3:"謹";s:3:"賓";s:3:"賓";s:3:"贈";s:3:"贈";s:3:"辶";s:3:"辶";s:3:"逸";s:3:"逸";s:3:"難";s:3:"難";s:3:"響";s:3:"響";s:3:"頻";s:3:"頻";s:3:"並";s:3:"並";s:3:"况";s:3:"况";s:3:"全";s:3:"全";s:3:"侀";s:3:"侀";s:3:"充";s:3:"充";s:3:"冀";s:3:"冀";s:3:"勇";s:3:"勇";s:3:"勺";s:3:"勺";s:3:"喝";s:3:"喝";s:3:"啕";s:3:"啕";s:3:"喙";s:3:"喙";s:3:"嗢";s:3:"嗢";s:3:"塚";s:3:"塚";s:3:"墳";s:3:"墳";s:3:"奄";s:3:"奄";s:3:"奔";s:3:"奔";s:3:"婢";s:3:"婢";s:3:"嬨";s:3:"嬨";s:3:"廒";s:3:"廒";s:3:"廙";s:3:"廙";s:3:"彩";s:3:"彩";s:3:"徭";s:3:"徭";s:3:"惘";s:3:"惘";s:3:"慎";s:3:"慎";s:3:"愈";s:3:"愈";s:3:"憎";s:3:"憎";s:3:"慠";s:3:"慠";s:3:"懲";s:3:"懲";s:3:"戴";s:3:"戴";s:3:"揄";s:3:"揄";s:3:"搜";s:3:"搜";s:3:"摒";s:3:"摒";s:3:"敖";s:3:"敖";s:3:"晴";s:3:"晴";s:3:"朗";s:3:"朗";s:3:"望";s:3:"望";s:3:"杖";s:3:"杖";s:3:"歹";s:3:"歹";s:3:"殺";s:3:"殺";s:3:"流";s:3:"流";s:3:"滛";s:3:"滛";s:3:"滋";s:3:"滋";s:3:"漢";s:3:"漢";s:3:"瀞";s:3:"瀞";s:3:"煮";s:3:"煮";s:3:"瞧";s:3:"瞧";s:3:"爵";s:3:"爵";s:3:"犯";s:3:"犯";s:3:"猪";s:3:"猪";s:3:"瑱";s:3:"瑱";s:3:"甆";s:3:"甆";s:3:"画";s:3:"画";s:3:"瘝";s:3:"瘝";s:3:"瘟";s:3:"瘟";s:3:"益";s:3:"益";s:3:"盛";s:3:"盛";s:3:"直";s:3:"直";s:3:"睊";s:3:"睊";s:3:"着";s:3:"着";s:3:"磌";s:3:"磌";s:3:"窱";s:3:"窱";s:3:"節";s:3:"節";s:3:"类";s:3:"类";s:3:"絛";s:3:"絛";s:3:"練";s:3:"練";s:3:"缾";s:3:"缾";s:3:"者";s:3:"者";s:3:"荒";s:3:"荒";s:3:"華";s:3:"華";s:3:"蝹";s:3:"蝹";s:3:"襁";s:3:"襁";s:3:"覆";s:3:"覆";s:3:"視";s:3:"視";s:3:"調";s:3:"調";s:3:"諸";s:3:"諸";s:3:"請";s:3:"請";s:3:"謁";s:3:"謁";s:3:"諾";s:3:"諾";s:3:"諭";s:3:"諭";s:3:"謹";s:3:"謹";s:3:"變";s:3:"變";s:3:"贈";s:3:"贈";s:3:"輸";s:3:"輸";s:3:"遲";s:3:"遲";s:3:"醙";s:3:"醙";s:3:"鉶";s:3:"鉶";s:3:"陼";s:3:"陼";s:3:"難";s:3:"難";s:3:"靖";s:3:"靖";s:3:"韛";s:3:"韛";s:3:"響";s:3:"響";s:3:"頋";s:3:"頋";s:3:"頻";s:3:"頻";s:3:"鬒";s:3:"鬒";s:3:"龜";s:3:"龜";s:3:"𢡊";s:4:"𢡊";s:3:"𢡄";s:4:"𢡄";s:3:"𣏕";s:4:"𣏕";s:3:"㮝";s:3:"㮝";s:3:"䀘";s:3:"䀘";s:3:"䀹";s:3:"䀹";s:3:"𥉉";s:4:"𥉉";s:3:"𥳐";s:4:"𥳐";s:3:"𧻓";s:4:"𧻓";s:3:"齃";s:3:"齃";s:3:"龎";s:3:"龎";s:3:"יִ";s:4:"יִ";s:3:"ײַ";s:4:"ײַ";s:3:"שׁ";s:4:"שׁ";s:3:"שׂ";s:4:"שׂ";s:3:"שּׁ";s:6:"שּׁ";s:3:"שּׂ";s:6:"שּׂ";s:3:"אַ";s:4:"אַ";s:3:"אָ";s:4:"אָ";s:3:"אּ";s:4:"אּ";s:3:"בּ";s:4:"בּ";s:3:"גּ";s:4:"גּ";s:3:"דּ";s:4:"דּ";s:3:"הּ";s:4:"הּ";s:3:"וּ";s:4:"וּ";s:3:"זּ";s:4:"זּ";s:3:"טּ";s:4:"טּ";s:3:"יּ";s:4:"יּ";s:3:"ךּ";s:4:"ךּ";s:3:"כּ";s:4:"כּ";s:3:"לּ";s:4:"לּ";s:3:"מּ";s:4:"מּ";s:3:"נּ";s:4:"נּ";s:3:"סּ";s:4:"סּ";s:3:"ףּ";s:4:"ףּ";s:3:"פּ";s:4:"פּ";s:3:"צּ";s:4:"צּ";s:3:"קּ";s:4:"קּ";s:3:"רּ";s:4:"רּ";s:3:"שּ";s:4:"שּ";s:3:"תּ";s:4:"תּ";s:3:"וֹ";s:4:"וֹ";s:3:"בֿ";s:4:"בֿ";s:3:"כֿ";s:4:"כֿ";s:3:"פֿ";s:4:"פֿ";s:4:"𝅗𝅥";s:8:"𝅗𝅥";s:4:"𝅘𝅥";s:8:"𝅘𝅥";s:4:"𝅘𝅥𝅮";s:12:"𝅘𝅥𝅮";s:4:"𝅘𝅥𝅯";s:12:"𝅘𝅥𝅯";s:4:"𝅘𝅥𝅰";s:12:"𝅘𝅥𝅰";s:4:"𝅘𝅥𝅱";s:12:"𝅘𝅥𝅱";s:4:"𝅘𝅥𝅲";s:12:"𝅘𝅥𝅲";s:4:"𝆹𝅥";s:8:"𝆹𝅥";s:4:"𝆺𝅥";s:8:"𝆺𝅥";s:4:"𝆹𝅥𝅮";s:12:"𝆹𝅥𝅮";s:4:"𝆺𝅥𝅮";s:12:"𝆺𝅥𝅮";s:4:"𝆹𝅥𝅯";s:12:"𝆹𝅥𝅯";s:4:"𝆺𝅥𝅯";s:12:"𝆺𝅥𝅯";s:4:"丽";s:3:"丽";s:4:"丸";s:3:"丸";s:4:"乁";s:3:"乁";s:4:"𠄢";s:4:"𠄢";s:4:"你";s:3:"你";s:4:"侮";s:3:"侮";s:4:"侻";s:3:"侻";s:4:"倂";s:3:"倂";s:4:"偺";s:3:"偺";s:4:"備";s:3:"備";s:4:"僧";s:3:"僧";s:4:"像";s:3:"像";s:4:"㒞";s:3:"㒞";s:4:"𠘺";s:4:"𠘺";s:4:"免";s:3:"免";s:4:"兔";s:3:"兔";s:4:"兤";s:3:"兤";s:4:"具";s:3:"具";s:4:"𠔜";s:4:"𠔜";s:4:"㒹";s:3:"㒹";s:4:"內";s:3:"內";s:4:"再";s:3:"再";s:4:"𠕋";s:4:"𠕋";s:4:"冗";s:3:"冗";s:4:"冤";s:3:"冤";s:4:"仌";s:3:"仌";s:4:"冬";s:3:"冬";s:4:"况";s:3:"况";s:4:"𩇟";s:4:"𩇟";s:4:"凵";s:3:"凵";s:4:"刃";s:3:"刃";s:4:"㓟";s:3:"㓟";s:4:"刻";s:3:"刻";s:4:"剆";s:3:"剆";s:4:"割";s:3:"割";s:4:"剷";s:3:"剷";s:4:"㔕";s:3:"㔕";s:4:"勇";s:3:"勇";s:4:"勉";s:3:"勉";s:4:"勤";s:3:"勤";s:4:"勺";s:3:"勺";s:4:"包";s:3:"包";s:4:"匆";s:3:"匆";s:4:"北";s:3:"北";s:4:"卉";s:3:"卉";s:4:"卑";s:3:"卑";s:4:"博";s:3:"博";s:4:"即";s:3:"即";s:4:"卽";s:3:"卽";s:4:"卿";s:3:"卿";s:4:"卿";s:3:"卿";s:4:"卿";s:3:"卿";s:4:"𠨬";s:4:"𠨬";s:4:"灰";s:3:"灰";s:4:"及";s:3:"及";s:4:"叟";s:3:"叟";s:4:"𠭣";s:4:"𠭣";s:4:"叫";s:3:"叫";s:4:"叱";s:3:"叱";s:4:"吆";s:3:"吆";s:4:"咞";s:3:"咞";s:4:"吸";s:3:"吸";s:4:"呈";s:3:"呈";s:4:"周";s:3:"周";s:4:"咢";s:3:"咢";s:4:"哶";s:3:"哶";s:4:"唐";s:3:"唐";s:4:"啓";s:3:"啓";s:4:"啣";s:3:"啣";s:4:"善";s:3:"善";s:4:"善";s:3:"善";s:4:"喙";s:3:"喙";s:4:"喫";s:3:"喫";s:4:"喳";s:3:"喳";s:4:"嗂";s:3:"嗂";s:4:"圖";s:3:"圖";s:4:"嘆";s:3:"嘆";s:4:"圗";s:3:"圗";s:4:"噑";s:3:"噑";s:4:"噴";s:3:"噴";s:4:"切";s:3:"切";s:4:"壮";s:3:"壮";s:4:"城";s:3:"城";s:4:"埴";s:3:"埴";s:4:"堍";s:3:"堍";s:4:"型";s:3:"型";s:4:"堲";s:3:"堲";s:4:"報";s:3:"報";s:4:"墬";s:3:"墬";s:4:"𡓤";s:4:"𡓤";s:4:"売";s:3:"売";s:4:"壷";s:3:"壷";s:4:"夆";s:3:"夆";s:4:"多";s:3:"多";s:4:"夢";s:3:"夢";s:4:"奢";s:3:"奢";s:4:"𡚨";s:4:"𡚨";s:4:"𡛪";s:4:"𡛪";s:4:"姬";s:3:"姬";s:4:"娛";s:3:"娛";s:4:"娧";s:3:"娧";s:4:"姘";s:3:"姘";s:4:"婦";s:3:"婦";s:4:"㛮";s:3:"㛮";s:4:"㛼";s:3:"㛼";s:4:"嬈";s:3:"嬈";s:4:"嬾";s:3:"嬾";s:4:"嬾";s:3:"嬾";s:4:"𡧈";s:4:"𡧈";s:4:"寃";s:3:"寃";s:4:"寘";s:3:"寘";s:4:"寧";s:3:"寧";s:4:"寳";s:3:"寳";s:4:"𡬘";s:4:"𡬘";s:4:"寿";s:3:"寿";s:4:"将";s:3:"将";s:4:"当";s:3:"当";s:4:"尢";s:3:"尢";s:4:"㞁";s:3:"㞁";s:4:"屠";s:3:"屠";s:4:"屮";s:3:"屮";s:4:"峀";s:3:"峀";s:4:"岍";s:3:"岍";s:4:"𡷤";s:4:"𡷤";s:4:"嵃";s:3:"嵃";s:4:"𡷦";s:4:"𡷦";s:4:"嵮";s:3:"嵮";s:4:"嵫";s:3:"嵫";s:4:"嵼";s:3:"嵼";s:4:"巡";s:3:"巡";s:4:"巢";s:3:"巢";s:4:"㠯";s:3:"㠯";s:4:"巽";s:3:"巽";s:4:"帨";s:3:"帨";s:4:"帽";s:3:"帽";s:4:"幩";s:3:"幩";s:4:"㡢";s:3:"㡢";s:4:"𢆃";s:4:"𢆃";s:4:"㡼";s:3:"㡼";s:4:"庰";s:3:"庰";s:4:"庳";s:3:"庳";s:4:"庶";s:3:"庶";s:4:"廊";s:3:"廊";s:4:"𪎒";s:4:"𪎒";s:4:"廾";s:3:"廾";s:4:"𢌱";s:4:"𢌱";s:4:"𢌱";s:4:"𢌱";s:4:"舁";s:3:"舁";s:4:"弢";s:3:"弢";s:4:"弢";s:3:"弢";s:4:"㣇";s:3:"㣇";s:4:"𣊸";s:4:"𣊸";s:4:"𦇚";s:4:"𦇚";s:4:"形";s:3:"形";s:4:"彫";s:3:"彫";s:4:"㣣";s:3:"㣣";s:4:"徚";s:3:"徚";s:4:"忍";s:3:"忍";s:4:"志";s:3:"志";s:4:"忹";s:3:"忹";s:4:"悁";s:3:"悁";s:4:"㤺";s:3:"㤺";s:4:"㤜";s:3:"㤜";s:4:"悔";s:3:"悔";s:4:"𢛔";s:4:"𢛔";s:4:"惇";s:3:"惇";s:4:"慈";s:3:"慈";s:4:"慌";s:3:"慌";s:4:"慎";s:3:"慎";s:4:"慌";s:3:"慌";s:4:"慺";s:3:"慺";s:4:"憎";s:3:"憎";s:4:"憲";s:3:"憲";s:4:"憤";s:3:"憤";s:4:"憯";s:3:"憯";s:4:"懞";s:3:"懞";s:4:"懲";s:3:"懲";s:4:"懶";s:3:"懶";s:4:"成";s:3:"成";s:4:"戛";s:3:"戛";s:4:"扝";s:3:"扝";s:4:"抱";s:3:"抱";s:4:"拔";s:3:"拔";s:4:"捐";s:3:"捐";s:4:"𢬌";s:4:"𢬌";s:4:"挽";s:3:"挽";s:4:"拼";s:3:"拼";s:4:"捨";s:3:"捨";s:4:"掃";s:3:"掃";s:4:"揤";s:3:"揤";s:4:"𢯱";s:4:"𢯱";s:4:"搢";s:3:"搢";s:4:"揅";s:3:"揅";s:4:"掩";s:3:"掩";s:4:"㨮";s:3:"㨮";s:4:"摩";s:3:"摩";s:4:"摾";s:3:"摾";s:4:"撝";s:3:"撝";s:4:"摷";s:3:"摷";s:4:"㩬";s:3:"㩬";s:4:"敏";s:3:"敏";s:4:"敬";s:3:"敬";s:4:"𣀊";s:4:"𣀊";s:4:"旣";s:3:"旣";s:4:"書";s:3:"書";s:4:"晉";s:3:"晉";s:4:"㬙";s:3:"㬙";s:4:"暑";s:3:"暑";s:4:"㬈";s:3:"㬈";s:4:"㫤";s:3:"㫤";s:4:"冒";s:3:"冒";s:4:"冕";s:3:"冕";s:4:"最";s:3:"最";s:4:"暜";s:3:"暜";s:4:"肭";s:3:"肭";s:4:"䏙";s:3:"䏙";s:4:"朗";s:3:"朗";s:4:"望";s:3:"望";s:4:"朡";s:3:"朡";s:4:"杞";s:3:"杞";s:4:"杓";s:3:"杓";s:4:"𣏃";s:4:"𣏃";s:4:"㭉";s:3:"㭉";s:4:"柺";s:3:"柺";s:4:"枅";s:3:"枅";s:4:"桒";s:3:"桒";s:4:"梅";s:3:"梅";s:4:"𣑭";s:4:"𣑭";s:4:"梎";s:3:"梎";s:4:"栟";s:3:"栟";s:4:"椔";s:3:"椔";s:4:"㮝";s:3:"㮝";s:4:"楂";s:3:"楂";s:4:"榣";s:3:"榣";s:4:"槪";s:3:"槪";s:4:"檨";s:3:"檨";s:4:"𣚣";s:4:"𣚣";s:4:"櫛";s:3:"櫛";s:4:"㰘";s:3:"㰘";s:4:"次";s:3:"次";s:4:"𣢧";s:4:"𣢧";s:4:"歔";s:3:"歔";s:4:"㱎";s:3:"㱎";s:4:"歲";s:3:"歲";s:4:"殟";s:3:"殟";s:4:"殺";s:3:"殺";s:4:"殻";s:3:"殻";s:4:"𣪍";s:4:"𣪍";s:4:"𡴋";s:4:"𡴋";s:4:"𣫺";s:4:"𣫺";s:4:"汎";s:3:"汎";s:4:"𣲼";s:4:"𣲼";s:4:"沿";s:3:"沿";s:4:"泍";s:3:"泍";s:4:"汧";s:3:"汧";s:4:"洖";s:3:"洖";s:4:"派";s:3:"派";s:4:"海";s:3:"海";s:4:"流";s:3:"流";s:4:"浩";s:3:"浩";s:4:"浸";s:3:"浸";s:4:"涅";s:3:"涅";s:4:"𣴞";s:4:"𣴞";s:4:"洴";s:3:"洴";s:4:"港";s:3:"港";s:4:"湮";s:3:"湮";s:4:"㴳";s:3:"㴳";s:4:"滋";s:3:"滋";s:4:"滇";s:3:"滇";s:4:"𣻑";s:4:"𣻑";s:4:"淹";s:3:"淹";s:4:"潮";s:3:"潮";s:4:"𣽞";s:4:"𣽞";s:4:"𣾎";s:4:"𣾎";s:4:"濆";s:3:"濆";s:4:"瀹";s:3:"瀹";s:4:"瀞";s:3:"瀞";s:4:"瀛";s:3:"瀛";s:4:"㶖";s:3:"㶖";s:4:"灊";s:3:"灊";s:4:"災";s:3:"災";s:4:"灷";s:3:"灷";s:4:"炭";s:3:"炭";s:4:"𠔥";s:4:"𠔥";s:4:"煅";s:3:"煅";s:4:"𤉣";s:4:"𤉣";s:4:"熜";s:3:"熜";s:4:"𤎫";s:4:"𤎫";s:4:"爨";s:3:"爨";s:4:"爵";s:3:"爵";s:4:"牐";s:3:"牐";s:4:"𤘈";s:4:"𤘈";s:4:"犀";s:3:"犀";s:4:"犕";s:3:"犕";s:4:"𤜵";s:4:"𤜵";s:4:"𤠔";s:4:"𤠔";s:4:"獺";s:3:"獺";s:4:"王";s:3:"王";s:4:"㺬";s:3:"㺬";s:4:"玥";s:3:"玥";s:4:"㺸";s:3:"㺸";s:4:"㺸";s:3:"㺸";s:4:"瑇";s:3:"瑇";s:4:"瑜";s:3:"瑜";s:4:"瑱";s:3:"瑱";s:4:"璅";s:3:"璅";s:4:"瓊";s:3:"瓊";s:4:"㼛";s:3:"㼛";s:4:"甤";s:3:"甤";s:4:"𤰶";s:4:"𤰶";s:4:"甾";s:3:"甾";s:4:"𤲒";s:4:"𤲒";s:4:"異";s:3:"異";s:4:"𢆟";s:4:"𢆟";s:4:"瘐";s:3:"瘐";s:4:"𤾡";s:4:"𤾡";s:4:"𤾸";s:4:"𤾸";s:4:"𥁄";s:4:"𥁄";s:4:"㿼";s:3:"㿼";s:4:"䀈";s:3:"䀈";s:4:"直";s:3:"直";s:4:"𥃳";s:4:"𥃳";s:4:"𥃲";s:4:"𥃲";s:4:"𥄙";s:4:"𥄙";s:4:"𥄳";s:4:"𥄳";s:4:"眞";s:3:"眞";s:4:"真";s:3:"真";s:4:"真";s:3:"真";s:4:"睊";s:3:"睊";s:4:"䀹";s:3:"䀹";s:4:"瞋";s:3:"瞋";s:4:"䁆";s:3:"䁆";s:4:"䂖";s:3:"䂖";s:4:"𥐝";s:4:"𥐝";s:4:"硎";s:3:"硎";s:4:"碌";s:3:"碌";s:4:"磌";s:3:"磌";s:4:"䃣";s:3:"䃣";s:4:"𥘦";s:4:"𥘦";s:4:"祖";s:3:"祖";s:4:"𥚚";s:4:"𥚚";s:4:"𥛅";s:4:"𥛅";s:4:"福";s:3:"福";s:4:"秫";s:3:"秫";s:4:"䄯";s:3:"䄯";s:4:"穀";s:3:"穀";s:4:"穊";s:3:"穊";s:4:"穏";s:3:"穏";s:4:"𥥼";s:4:"𥥼";s:4:"𥪧";s:4:"𥪧";s:4:"𥪧";s:4:"𥪧";s:4:"竮";s:3:"竮";s:4:"䈂";s:3:"䈂";s:4:"𥮫";s:4:"𥮫";s:4:"篆";s:3:"篆";s:4:"築";s:3:"築";s:4:"䈧";s:3:"䈧";s:4:"𥲀";s:4:"𥲀";s:4:"糒";s:3:"糒";s:4:"䊠";s:3:"䊠";s:4:"糨";s:3:"糨";s:4:"糣";s:3:"糣";s:4:"紀";s:3:"紀";s:4:"𥾆";s:4:"𥾆";s:4:"絣";s:3:"絣";s:4:"䌁";s:3:"䌁";s:4:"緇";s:3:"緇";s:4:"縂";s:3:"縂";s:4:"繅";s:3:"繅";s:4:"䌴";s:3:"䌴";s:4:"𦈨";s:4:"𦈨";s:4:"𦉇";s:4:"𦉇";s:4:"䍙";s:3:"䍙";s:4:"𦋙";s:4:"𦋙";s:4:"罺";s:3:"罺";s:4:"𦌾";s:4:"𦌾";s:4:"羕";s:3:"羕";s:4:"翺";s:3:"翺";s:4:"者";s:3:"者";s:4:"𦓚";s:4:"𦓚";s:4:"𦔣";s:4:"𦔣";s:4:"聠";s:3:"聠";s:4:"𦖨";s:4:"𦖨";s:4:"聰";s:3:"聰";s:4:"𣍟";s:4:"𣍟";s:4:"䏕";s:3:"䏕";s:4:"育";s:3:"育";s:4:"脃";s:3:"脃";s:4:"䐋";s:3:"䐋";s:4:"脾";s:3:"脾";s:4:"媵";s:3:"媵";s:4:"𦞧";s:4:"𦞧";s:4:"𦞵";s:4:"𦞵";s:4:"𣎓";s:4:"𣎓";s:4:"𣎜";s:4:"𣎜";s:4:"舁";s:3:"舁";s:4:"舄";s:3:"舄";s:4:"辞";s:3:"辞";s:4:"䑫";s:3:"䑫";s:4:"芑";s:3:"芑";s:4:"芋";s:3:"芋";s:4:"芝";s:3:"芝";s:4:"劳";s:3:"劳";s:4:"花";s:3:"花";s:4:"芳";s:3:"芳";s:4:"芽";s:3:"芽";s:4:"苦";s:3:"苦";s:4:"𦬼";s:4:"𦬼";s:4:"若";s:3:"若";s:4:"茝";s:3:"茝";s:4:"荣";s:3:"荣";s:4:"莭";s:3:"莭";s:4:"茣";s:3:"茣";s:4:"莽";s:3:"莽";s:4:"菧";s:3:"菧";s:4:"著";s:3:"著";s:4:"荓";s:3:"荓";s:4:"菊";s:3:"菊";s:4:"菌";s:3:"菌";s:4:"菜";s:3:"菜";s:4:"𦰶";s:4:"𦰶";s:4:"𦵫";s:4:"𦵫";s:4:"𦳕";s:4:"𦳕";s:4:"䔫";s:3:"䔫";s:4:"蓱";s:3:"蓱";s:4:"蓳";s:3:"蓳";s:4:"蔖";s:3:"蔖";s:4:"𧏊";s:4:"𧏊";s:4:"蕤";s:3:"蕤";s:4:"𦼬";s:4:"𦼬";s:4:"䕝";s:3:"䕝";s:4:"䕡";s:3:"䕡";s:4:"𦾱";s:4:"𦾱";s:4:"𧃒";s:4:"𧃒";s:4:"䕫";s:3:"䕫";s:4:"虐";s:3:"虐";s:4:"虜";s:3:"虜";s:4:"虧";s:3:"虧";s:4:"虩";s:3:"虩";s:4:"蚩";s:3:"蚩";s:4:"蚈";s:3:"蚈";s:4:"蜎";s:3:"蜎";s:4:"蛢";s:3:"蛢";s:4:"蝹";s:3:"蝹";s:4:"蜨";s:3:"蜨";s:4:"蝫";s:3:"蝫";s:4:"螆";s:3:"螆";s:4:"䗗";s:3:"䗗";s:4:"蟡";s:3:"蟡";s:4:"蠁";s:3:"蠁";s:4:"䗹";s:3:"䗹";s:4:"衠";s:3:"衠";s:4:"衣";s:3:"衣";s:4:"𧙧";s:4:"𧙧";s:4:"裗";s:3:"裗";s:4:"裞";s:3:"裞";s:4:"䘵";s:3:"䘵";s:4:"裺";s:3:"裺";s:4:"㒻";s:3:"㒻";s:4:"𧢮";s:4:"𧢮";s:4:"𧥦";s:4:"𧥦";s:4:"䚾";s:3:"䚾";s:4:"䛇";s:3:"䛇";s:4:"誠";s:3:"誠";s:4:"諭";s:3:"諭";s:4:"變";s:3:"變";s:4:"豕";s:3:"豕";s:4:"𧲨";s:4:"𧲨";s:4:"貫";s:3:"貫";s:4:"賁";s:3:"賁";s:4:"贛";s:3:"贛";s:4:"起";s:3:"起";s:4:"𧼯";s:4:"𧼯";s:4:"𠠄";s:4:"𠠄";s:4:"跋";s:3:"跋";s:4:"趼";s:3:"趼";s:4:"跰";s:3:"跰";s:4:"𠣞";s:4:"𠣞";s:4:"軔";s:3:"軔";s:4:"輸";s:3:"輸";s:4:"𨗒";s:4:"𨗒";s:4:"𨗭";s:4:"𨗭";s:4:"邔";s:3:"邔";s:4:"郱";s:3:"郱";s:4:"鄑";s:3:"鄑";s:4:"𨜮";s:4:"𨜮";s:4:"鄛";s:3:"鄛";s:4:"鈸";s:3:"鈸";s:4:"鋗";s:3:"鋗";s:4:"鋘";s:3:"鋘";s:4:"鉼";s:3:"鉼";s:4:"鏹";s:3:"鏹";s:4:"鐕";s:3:"鐕";s:4:"𨯺";s:4:"𨯺";s:4:"開";s:3:"開";s:4:"䦕";s:3:"䦕";s:4:"閷";s:3:"閷";s:4:"𨵷";s:4:"𨵷";s:4:"䧦";s:3:"䧦";s:4:"雃";s:3:"雃";s:4:"嶲";s:3:"嶲";s:4:"霣";s:3:"霣";s:4:"𩅅";s:4:"𩅅";s:4:"𩈚";s:4:"𩈚";s:4:"䩮";s:3:"䩮";s:4:"䩶";s:3:"䩶";s:4:"韠";s:3:"韠";s:4:"𩐊";s:4:"𩐊";s:4:"䪲";s:3:"䪲";s:4:"𩒖";s:4:"𩒖";s:4:"頋";s:3:"頋";s:4:"頋";s:3:"頋";s:4:"頩";s:3:"頩";s:4:"𩖶";s:4:"𩖶";s:4:"飢";s:3:"飢";s:4:"䬳";s:3:"䬳";s:4:"餩";s:3:"餩";s:4:"馧";s:3:"馧";s:4:"駂";s:3:"駂";s:4:"駾";s:3:"駾";s:4:"䯎";s:3:"䯎";s:4:"𩬰";s:4:"𩬰";s:4:"鬒";s:3:"鬒";s:4:"鱀";s:3:"鱀";s:4:"鳽";s:3:"鳽";s:4:"䳎";s:3:"䳎";s:4:"䳭";s:3:"䳭";s:4:"鵧";s:3:"鵧";s:4:"𪃎";s:4:"𪃎";s:4:"䳸";s:3:"䳸";s:4:"𪄅";s:4:"𪄅";s:4:"𪈎";s:4:"𪈎";s:4:"𪊑";s:4:"𪊑";s:4:"麻";s:3:"麻";s:4:"䵖";s:3:"䵖";s:4:"黹";s:3:"黹";s:4:"黾";s:3:"黾";s:4:"鼅";s:3:"鼅";s:4:"鼏";s:3:"鼏";s:4:"鼖";s:3:"鼖";s:4:"鼻";s:3:"鼻";s:4:"𪘀";s:4:"𪘀";}' );
+$utfCheckNFC = unserialize( 'a:1216:{s:2:"̀";s:1:"N";s:2:"́";s:1:"N";s:2:"̓";s:1:"N";s:2:"̈́";s:1:"N";s:2:"ʹ";s:1:"N";s:2:";";s:1:"N";s:2:"·";s:1:"N";s:3:"क़";s:1:"N";s:3:"ख़";s:1:"N";s:3:"ग़";s:1:"N";s:3:"ज़";s:1:"N";s:3:"ड़";s:1:"N";s:3:"ढ़";s:1:"N";s:3:"फ़";s:1:"N";s:3:"य़";s:1:"N";s:3:"ড়";s:1:"N";s:3:"ঢ়";s:1:"N";s:3:"য়";s:1:"N";s:3:"ਲ਼";s:1:"N";s:3:"ਸ਼";s:1:"N";s:3:"ਖ਼";s:1:"N";s:3:"ਗ਼";s:1:"N";s:3:"ਜ਼";s:1:"N";s:3:"ਫ਼";s:1:"N";s:3:"ଡ଼";s:1:"N";s:3:"ଢ଼";s:1:"N";s:3:"གྷ";s:1:"N";s:3:"ཌྷ";s:1:"N";s:3:"དྷ";s:1:"N";s:3:"བྷ";s:1:"N";s:3:"ཛྷ";s:1:"N";s:3:"ཀྵ";s:1:"N";s:3:"ཱི";s:1:"N";s:3:"ཱུ";s:1:"N";s:3:"ྲྀ";s:1:"N";s:3:"ླྀ";s:1:"N";s:3:"ཱྀ";s:1:"N";s:3:"ྒྷ";s:1:"N";s:3:"ྜྷ";s:1:"N";s:3:"ྡྷ";s:1:"N";s:3:"ྦྷ";s:1:"N";s:3:"ྫྷ";s:1:"N";s:3:"ྐྵ";s:1:"N";s:3:"ά";s:1:"N";s:3:"έ";s:1:"N";s:3:"ή";s:1:"N";s:3:"ί";s:1:"N";s:3:"ό";s:1:"N";s:3:"ύ";s:1:"N";s:3:"ώ";s:1:"N";s:3:"Ά";s:1:"N";s:3:"ι";s:1:"N";s:3:"Έ";s:1:"N";s:3:"Ή";s:1:"N";s:3:"ΐ";s:1:"N";s:3:"Ί";s:1:"N";s:3:"ΰ";s:1:"N";s:3:"Ύ";s:1:"N";s:3:"΅";s:1:"N";s:3:"`";s:1:"N";s:3:"Ό";s:1:"N";s:3:"Ώ";s:1:"N";s:3:"´";s:1:"N";s:3:" ";s:1:"N";s:3:" ";s:1:"N";s:3:"Ω";s:1:"N";s:3:"K";s:1:"N";s:3:"Å";s:1:"N";s:3:"〈";s:1:"N";s:3:"〉";s:1:"N";s:3:"⫝̸";s:1:"N";s:3:"豈";s:1:"N";s:3:"更";s:1:"N";s:3:"車";s:1:"N";s:3:"賈";s:1:"N";s:3:"滑";s:1:"N";s:3:"串";s:1:"N";s:3:"句";s:1:"N";s:3:"龜";s:1:"N";s:3:"龜";s:1:"N";s:3:"契";s:1:"N";s:3:"金";s:1:"N";s:3:"喇";s:1:"N";s:3:"奈";s:1:"N";s:3:"懶";s:1:"N";s:3:"癩";s:1:"N";s:3:"羅";s:1:"N";s:3:"蘿";s:1:"N";s:3:"螺";s:1:"N";s:3:"裸";s:1:"N";s:3:"邏";s:1:"N";s:3:"樂";s:1:"N";s:3:"洛";s:1:"N";s:3:"烙";s:1:"N";s:3:"珞";s:1:"N";s:3:"落";s:1:"N";s:3:"酪";s:1:"N";s:3:"駱";s:1:"N";s:3:"亂";s:1:"N";s:3:"卵";s:1:"N";s:3:"欄";s:1:"N";s:3:"爛";s:1:"N";s:3:"蘭";s:1:"N";s:3:"鸞";s:1:"N";s:3:"嵐";s:1:"N";s:3:"濫";s:1:"N";s:3:"藍";s:1:"N";s:3:"襤";s:1:"N";s:3:"拉";s:1:"N";s:3:"臘";s:1:"N";s:3:"蠟";s:1:"N";s:3:"廊";s:1:"N";s:3:"朗";s:1:"N";s:3:"浪";s:1:"N";s:3:"狼";s:1:"N";s:3:"郎";s:1:"N";s:3:"來";s:1:"N";s:3:"冷";s:1:"N";s:3:"勞";s:1:"N";s:3:"擄";s:1:"N";s:3:"櫓";s:1:"N";s:3:"爐";s:1:"N";s:3:"盧";s:1:"N";s:3:"老";s:1:"N";s:3:"蘆";s:1:"N";s:3:"虜";s:1:"N";s:3:"路";s:1:"N";s:3:"露";s:1:"N";s:3:"魯";s:1:"N";s:3:"鷺";s:1:"N";s:3:"碌";s:1:"N";s:3:"祿";s:1:"N";s:3:"綠";s:1:"N";s:3:"菉";s:1:"N";s:3:"錄";s:1:"N";s:3:"鹿";s:1:"N";s:3:"論";s:1:"N";s:3:"壟";s:1:"N";s:3:"弄";s:1:"N";s:3:"籠";s:1:"N";s:3:"聾";s:1:"N";s:3:"牢";s:1:"N";s:3:"磊";s:1:"N";s:3:"賂";s:1:"N";s:3:"雷";s:1:"N";s:3:"壘";s:1:"N";s:3:"屢";s:1:"N";s:3:"樓";s:1:"N";s:3:"淚";s:1:"N";s:3:"漏";s:1:"N";s:3:"累";s:1:"N";s:3:"縷";s:1:"N";s:3:"陋";s:1:"N";s:3:"勒";s:1:"N";s:3:"肋";s:1:"N";s:3:"凜";s:1:"N";s:3:"凌";s:1:"N";s:3:"稜";s:1:"N";s:3:"綾";s:1:"N";s:3:"菱";s:1:"N";s:3:"陵";s:1:"N";s:3:"讀";s:1:"N";s:3:"拏";s:1:"N";s:3:"樂";s:1:"N";s:3:"諾";s:1:"N";s:3:"丹";s:1:"N";s:3:"寧";s:1:"N";s:3:"怒";s:1:"N";s:3:"率";s:1:"N";s:3:"異";s:1:"N";s:3:"北";s:1:"N";s:3:"磻";s:1:"N";s:3:"便";s:1:"N";s:3:"復";s:1:"N";s:3:"不";s:1:"N";s:3:"泌";s:1:"N";s:3:"數";s:1:"N";s:3:"索";s:1:"N";s:3:"參";s:1:"N";s:3:"塞";s:1:"N";s:3:"省";s:1:"N";s:3:"葉";s:1:"N";s:3:"說";s:1:"N";s:3:"殺";s:1:"N";s:3:"辰";s:1:"N";s:3:"沈";s:1:"N";s:3:"拾";s:1:"N";s:3:"若";s:1:"N";s:3:"掠";s:1:"N";s:3:"略";s:1:"N";s:3:"亮";s:1:"N";s:3:"兩";s:1:"N";s:3:"凉";s:1:"N";s:3:"梁";s:1:"N";s:3:"糧";s:1:"N";s:3:"良";s:1:"N";s:3:"諒";s:1:"N";s:3:"量";s:1:"N";s:3:"勵";s:1:"N";s:3:"呂";s:1:"N";s:3:"女";s:1:"N";s:3:"廬";s:1:"N";s:3:"旅";s:1:"N";s:3:"濾";s:1:"N";s:3:"礪";s:1:"N";s:3:"閭";s:1:"N";s:3:"驪";s:1:"N";s:3:"麗";s:1:"N";s:3:"黎";s:1:"N";s:3:"力";s:1:"N";s:3:"曆";s:1:"N";s:3:"歷";s:1:"N";s:3:"轢";s:1:"N";s:3:"年";s:1:"N";s:3:"憐";s:1:"N";s:3:"戀";s:1:"N";s:3:"撚";s:1:"N";s:3:"漣";s:1:"N";s:3:"煉";s:1:"N";s:3:"璉";s:1:"N";s:3:"秊";s:1:"N";s:3:"練";s:1:"N";s:3:"聯";s:1:"N";s:3:"輦";s:1:"N";s:3:"蓮";s:1:"N";s:3:"連";s:1:"N";s:3:"鍊";s:1:"N";s:3:"列";s:1:"N";s:3:"劣";s:1:"N";s:3:"咽";s:1:"N";s:3:"烈";s:1:"N";s:3:"裂";s:1:"N";s:3:"說";s:1:"N";s:3:"廉";s:1:"N";s:3:"念";s:1:"N";s:3:"捻";s:1:"N";s:3:"殮";s:1:"N";s:3:"簾";s:1:"N";s:3:"獵";s:1:"N";s:3:"令";s:1:"N";s:3:"囹";s:1:"N";s:3:"寧";s:1:"N";s:3:"嶺";s:1:"N";s:3:"怜";s:1:"N";s:3:"玲";s:1:"N";s:3:"瑩";s:1:"N";s:3:"羚";s:1:"N";s:3:"聆";s:1:"N";s:3:"鈴";s:1:"N";s:3:"零";s:1:"N";s:3:"靈";s:1:"N";s:3:"領";s:1:"N";s:3:"例";s:1:"N";s:3:"禮";s:1:"N";s:3:"醴";s:1:"N";s:3:"隸";s:1:"N";s:3:"惡";s:1:"N";s:3:"了";s:1:"N";s:3:"僚";s:1:"N";s:3:"寮";s:1:"N";s:3:"尿";s:1:"N";s:3:"料";s:1:"N";s:3:"樂";s:1:"N";s:3:"燎";s:1:"N";s:3:"療";s:1:"N";s:3:"蓼";s:1:"N";s:3:"遼";s:1:"N";s:3:"龍";s:1:"N";s:3:"暈";s:1:"N";s:3:"阮";s:1:"N";s:3:"劉";s:1:"N";s:3:"杻";s:1:"N";s:3:"柳";s:1:"N";s:3:"流";s:1:"N";s:3:"溜";s:1:"N";s:3:"琉";s:1:"N";s:3:"留";s:1:"N";s:3:"硫";s:1:"N";s:3:"紐";s:1:"N";s:3:"類";s:1:"N";s:3:"六";s:1:"N";s:3:"戮";s:1:"N";s:3:"陸";s:1:"N";s:3:"倫";s:1:"N";s:3:"崙";s:1:"N";s:3:"淪";s:1:"N";s:3:"輪";s:1:"N";s:3:"律";s:1:"N";s:3:"慄";s:1:"N";s:3:"栗";s:1:"N";s:3:"率";s:1:"N";s:3:"隆";s:1:"N";s:3:"利";s:1:"N";s:3:"吏";s:1:"N";s:3:"履";s:1:"N";s:3:"易";s:1:"N";s:3:"李";s:1:"N";s:3:"梨";s:1:"N";s:3:"泥";s:1:"N";s:3:"理";s:1:"N";s:3:"痢";s:1:"N";s:3:"罹";s:1:"N";s:3:"裏";s:1:"N";s:3:"裡";s:1:"N";s:3:"里";s:1:"N";s:3:"離";s:1:"N";s:3:"匿";s:1:"N";s:3:"溺";s:1:"N";s:3:"吝";s:1:"N";s:3:"燐";s:1:"N";s:3:"璘";s:1:"N";s:3:"藺";s:1:"N";s:3:"隣";s:1:"N";s:3:"鱗";s:1:"N";s:3:"麟";s:1:"N";s:3:"林";s:1:"N";s:3:"淋";s:1:"N";s:3:"臨";s:1:"N";s:3:"立";s:1:"N";s:3:"笠";s:1:"N";s:3:"粒";s:1:"N";s:3:"狀";s:1:"N";s:3:"炙";s:1:"N";s:3:"識";s:1:"N";s:3:"什";s:1:"N";s:3:"茶";s:1:"N";s:3:"刺";s:1:"N";s:3:"切";s:1:"N";s:3:"度";s:1:"N";s:3:"拓";s:1:"N";s:3:"糖";s:1:"N";s:3:"宅";s:1:"N";s:3:"洞";s:1:"N";s:3:"暴";s:1:"N";s:3:"輻";s:1:"N";s:3:"行";s:1:"N";s:3:"降";s:1:"N";s:3:"見";s:1:"N";s:3:"廓";s:1:"N";s:3:"兀";s:1:"N";s:3:"嗀";s:1:"N";s:3:"塚";s:1:"N";s:3:"晴";s:1:"N";s:3:"凞";s:1:"N";s:3:"猪";s:1:"N";s:3:"益";s:1:"N";s:3:"礼";s:1:"N";s:3:"神";s:1:"N";s:3:"祥";s:1:"N";s:3:"福";s:1:"N";s:3:"靖";s:1:"N";s:3:"精";s:1:"N";s:3:"羽";s:1:"N";s:3:"蘒";s:1:"N";s:3:"諸";s:1:"N";s:3:"逸";s:1:"N";s:3:"都";s:1:"N";s:3:"飯";s:1:"N";s:3:"飼";s:1:"N";s:3:"館";s:1:"N";s:3:"鶴";s:1:"N";s:3:"侮";s:1:"N";s:3:"僧";s:1:"N";s:3:"免";s:1:"N";s:3:"勉";s:1:"N";s:3:"勤";s:1:"N";s:3:"卑";s:1:"N";s:3:"喝";s:1:"N";s:3:"嘆";s:1:"N";s:3:"器";s:1:"N";s:3:"塀";s:1:"N";s:3:"墨";s:1:"N";s:3:"層";s:1:"N";s:3:"屮";s:1:"N";s:3:"悔";s:1:"N";s:3:"慨";s:1:"N";s:3:"憎";s:1:"N";s:3:"懲";s:1:"N";s:3:"敏";s:1:"N";s:3:"既";s:1:"N";s:3:"暑";s:1:"N";s:3:"梅";s:1:"N";s:3:"海";s:1:"N";s:3:"渚";s:1:"N";s:3:"漢";s:1:"N";s:3:"煮";s:1:"N";s:3:"爫";s:1:"N";s:3:"琢";s:1:"N";s:3:"碑";s:1:"N";s:3:"社";s:1:"N";s:3:"祉";s:1:"N";s:3:"祈";s:1:"N";s:3:"祐";s:1:"N";s:3:"祖";s:1:"N";s:3:"祝";s:1:"N";s:3:"禍";s:1:"N";s:3:"禎";s:1:"N";s:3:"穀";s:1:"N";s:3:"突";s:1:"N";s:3:"節";s:1:"N";s:3:"練";s:1:"N";s:3:"縉";s:1:"N";s:3:"繁";s:1:"N";s:3:"署";s:1:"N";s:3:"者";s:1:"N";s:3:"臭";s:1:"N";s:3:"艹";s:1:"N";s:3:"艹";s:1:"N";s:3:"著";s:1:"N";s:3:"褐";s:1:"N";s:3:"視";s:1:"N";s:3:"謁";s:1:"N";s:3:"謹";s:1:"N";s:3:"賓";s:1:"N";s:3:"贈";s:1:"N";s:3:"辶";s:1:"N";s:3:"逸";s:1:"N";s:3:"難";s:1:"N";s:3:"響";s:1:"N";s:3:"頻";s:1:"N";s:3:"並";s:1:"N";s:3:"况";s:1:"N";s:3:"全";s:1:"N";s:3:"侀";s:1:"N";s:3:"充";s:1:"N";s:3:"冀";s:1:"N";s:3:"勇";s:1:"N";s:3:"勺";s:1:"N";s:3:"喝";s:1:"N";s:3:"啕";s:1:"N";s:3:"喙";s:1:"N";s:3:"嗢";s:1:"N";s:3:"塚";s:1:"N";s:3:"墳";s:1:"N";s:3:"奄";s:1:"N";s:3:"奔";s:1:"N";s:3:"婢";s:1:"N";s:3:"嬨";s:1:"N";s:3:"廒";s:1:"N";s:3:"廙";s:1:"N";s:3:"彩";s:1:"N";s:3:"徭";s:1:"N";s:3:"惘";s:1:"N";s:3:"慎";s:1:"N";s:3:"愈";s:1:"N";s:3:"憎";s:1:"N";s:3:"慠";s:1:"N";s:3:"懲";s:1:"N";s:3:"戴";s:1:"N";s:3:"揄";s:1:"N";s:3:"搜";s:1:"N";s:3:"摒";s:1:"N";s:3:"敖";s:1:"N";s:3:"晴";s:1:"N";s:3:"朗";s:1:"N";s:3:"望";s:1:"N";s:3:"杖";s:1:"N";s:3:"歹";s:1:"N";s:3:"殺";s:1:"N";s:3:"流";s:1:"N";s:3:"滛";s:1:"N";s:3:"滋";s:1:"N";s:3:"漢";s:1:"N";s:3:"瀞";s:1:"N";s:3:"煮";s:1:"N";s:3:"瞧";s:1:"N";s:3:"爵";s:1:"N";s:3:"犯";s:1:"N";s:3:"猪";s:1:"N";s:3:"瑱";s:1:"N";s:3:"甆";s:1:"N";s:3:"画";s:1:"N";s:3:"瘝";s:1:"N";s:3:"瘟";s:1:"N";s:3:"益";s:1:"N";s:3:"盛";s:1:"N";s:3:"直";s:1:"N";s:3:"睊";s:1:"N";s:3:"着";s:1:"N";s:3:"磌";s:1:"N";s:3:"窱";s:1:"N";s:3:"節";s:1:"N";s:3:"类";s:1:"N";s:3:"絛";s:1:"N";s:3:"練";s:1:"N";s:3:"缾";s:1:"N";s:3:"者";s:1:"N";s:3:"荒";s:1:"N";s:3:"華";s:1:"N";s:3:"蝹";s:1:"N";s:3:"襁";s:1:"N";s:3:"覆";s:1:"N";s:3:"視";s:1:"N";s:3:"調";s:1:"N";s:3:"諸";s:1:"N";s:3:"請";s:1:"N";s:3:"謁";s:1:"N";s:3:"諾";s:1:"N";s:3:"諭";s:1:"N";s:3:"謹";s:1:"N";s:3:"變";s:1:"N";s:3:"贈";s:1:"N";s:3:"輸";s:1:"N";s:3:"遲";s:1:"N";s:3:"醙";s:1:"N";s:3:"鉶";s:1:"N";s:3:"陼";s:1:"N";s:3:"難";s:1:"N";s:3:"靖";s:1:"N";s:3:"韛";s:1:"N";s:3:"響";s:1:"N";s:3:"頋";s:1:"N";s:3:"頻";s:1:"N";s:3:"鬒";s:1:"N";s:3:"龜";s:1:"N";s:3:"𢡊";s:1:"N";s:3:"𢡄";s:1:"N";s:3:"𣏕";s:1:"N";s:3:"㮝";s:1:"N";s:3:"䀘";s:1:"N";s:3:"䀹";s:1:"N";s:3:"𥉉";s:1:"N";s:3:"𥳐";s:1:"N";s:3:"𧻓";s:1:"N";s:3:"齃";s:1:"N";s:3:"龎";s:1:"N";s:3:"יִ";s:1:"N";s:3:"ײַ";s:1:"N";s:3:"שׁ";s:1:"N";s:3:"שׂ";s:1:"N";s:3:"שּׁ";s:1:"N";s:3:"שּׂ";s:1:"N";s:3:"אַ";s:1:"N";s:3:"אָ";s:1:"N";s:3:"אּ";s:1:"N";s:3:"בּ";s:1:"N";s:3:"גּ";s:1:"N";s:3:"דּ";s:1:"N";s:3:"הּ";s:1:"N";s:3:"וּ";s:1:"N";s:3:"זּ";s:1:"N";s:3:"טּ";s:1:"N";s:3:"יּ";s:1:"N";s:3:"ךּ";s:1:"N";s:3:"כּ";s:1:"N";s:3:"לּ";s:1:"N";s:3:"מּ";s:1:"N";s:3:"נּ";s:1:"N";s:3:"סּ";s:1:"N";s:3:"ףּ";s:1:"N";s:3:"פּ";s:1:"N";s:3:"צּ";s:1:"N";s:3:"קּ";s:1:"N";s:3:"רּ";s:1:"N";s:3:"שּ";s:1:"N";s:3:"תּ";s:1:"N";s:3:"וֹ";s:1:"N";s:3:"בֿ";s:1:"N";s:3:"כֿ";s:1:"N";s:3:"פֿ";s:1:"N";s:4:"𝅗𝅥";s:1:"N";s:4:"𝅘𝅥";s:1:"N";s:4:"𝅘𝅥𝅮";s:1:"N";s:4:"𝅘𝅥𝅯";s:1:"N";s:4:"𝅘𝅥𝅰";s:1:"N";s:4:"𝅘𝅥𝅱";s:1:"N";s:4:"𝅘𝅥𝅲";s:1:"N";s:4:"𝆹𝅥";s:1:"N";s:4:"𝆺𝅥";s:1:"N";s:4:"𝆹𝅥𝅮";s:1:"N";s:4:"𝆺𝅥𝅮";s:1:"N";s:4:"𝆹𝅥𝅯";s:1:"N";s:4:"𝆺𝅥𝅯";s:1:"N";s:4:"丽";s:1:"N";s:4:"丸";s:1:"N";s:4:"乁";s:1:"N";s:4:"𠄢";s:1:"N";s:4:"你";s:1:"N";s:4:"侮";s:1:"N";s:4:"侻";s:1:"N";s:4:"倂";s:1:"N";s:4:"偺";s:1:"N";s:4:"備";s:1:"N";s:4:"僧";s:1:"N";s:4:"像";s:1:"N";s:4:"㒞";s:1:"N";s:4:"𠘺";s:1:"N";s:4:"免";s:1:"N";s:4:"兔";s:1:"N";s:4:"兤";s:1:"N";s:4:"具";s:1:"N";s:4:"𠔜";s:1:"N";s:4:"㒹";s:1:"N";s:4:"內";s:1:"N";s:4:"再";s:1:"N";s:4:"𠕋";s:1:"N";s:4:"冗";s:1:"N";s:4:"冤";s:1:"N";s:4:"仌";s:1:"N";s:4:"冬";s:1:"N";s:4:"况";s:1:"N";s:4:"𩇟";s:1:"N";s:4:"凵";s:1:"N";s:4:"刃";s:1:"N";s:4:"㓟";s:1:"N";s:4:"刻";s:1:"N";s:4:"剆";s:1:"N";s:4:"割";s:1:"N";s:4:"剷";s:1:"N";s:4:"㔕";s:1:"N";s:4:"勇";s:1:"N";s:4:"勉";s:1:"N";s:4:"勤";s:1:"N";s:4:"勺";s:1:"N";s:4:"包";s:1:"N";s:4:"匆";s:1:"N";s:4:"北";s:1:"N";s:4:"卉";s:1:"N";s:4:"卑";s:1:"N";s:4:"博";s:1:"N";s:4:"即";s:1:"N";s:4:"卽";s:1:"N";s:4:"卿";s:1:"N";s:4:"卿";s:1:"N";s:4:"卿";s:1:"N";s:4:"𠨬";s:1:"N";s:4:"灰";s:1:"N";s:4:"及";s:1:"N";s:4:"叟";s:1:"N";s:4:"𠭣";s:1:"N";s:4:"叫";s:1:"N";s:4:"叱";s:1:"N";s:4:"吆";s:1:"N";s:4:"咞";s:1:"N";s:4:"吸";s:1:"N";s:4:"呈";s:1:"N";s:4:"周";s:1:"N";s:4:"咢";s:1:"N";s:4:"哶";s:1:"N";s:4:"唐";s:1:"N";s:4:"啓";s:1:"N";s:4:"啣";s:1:"N";s:4:"善";s:1:"N";s:4:"善";s:1:"N";s:4:"喙";s:1:"N";s:4:"喫";s:1:"N";s:4:"喳";s:1:"N";s:4:"嗂";s:1:"N";s:4:"圖";s:1:"N";s:4:"嘆";s:1:"N";s:4:"圗";s:1:"N";s:4:"噑";s:1:"N";s:4:"噴";s:1:"N";s:4:"切";s:1:"N";s:4:"壮";s:1:"N";s:4:"城";s:1:"N";s:4:"埴";s:1:"N";s:4:"堍";s:1:"N";s:4:"型";s:1:"N";s:4:"堲";s:1:"N";s:4:"報";s:1:"N";s:4:"墬";s:1:"N";s:4:"𡓤";s:1:"N";s:4:"売";s:1:"N";s:4:"壷";s:1:"N";s:4:"夆";s:1:"N";s:4:"多";s:1:"N";s:4:"夢";s:1:"N";s:4:"奢";s:1:"N";s:4:"𡚨";s:1:"N";s:4:"𡛪";s:1:"N";s:4:"姬";s:1:"N";s:4:"娛";s:1:"N";s:4:"娧";s:1:"N";s:4:"姘";s:1:"N";s:4:"婦";s:1:"N";s:4:"㛮";s:1:"N";s:4:"㛼";s:1:"N";s:4:"嬈";s:1:"N";s:4:"嬾";s:1:"N";s:4:"嬾";s:1:"N";s:4:"𡧈";s:1:"N";s:4:"寃";s:1:"N";s:4:"寘";s:1:"N";s:4:"寧";s:1:"N";s:4:"寳";s:1:"N";s:4:"𡬘";s:1:"N";s:4:"寿";s:1:"N";s:4:"将";s:1:"N";s:4:"当";s:1:"N";s:4:"尢";s:1:"N";s:4:"㞁";s:1:"N";s:4:"屠";s:1:"N";s:4:"屮";s:1:"N";s:4:"峀";s:1:"N";s:4:"岍";s:1:"N";s:4:"𡷤";s:1:"N";s:4:"嵃";s:1:"N";s:4:"𡷦";s:1:"N";s:4:"嵮";s:1:"N";s:4:"嵫";s:1:"N";s:4:"嵼";s:1:"N";s:4:"巡";s:1:"N";s:4:"巢";s:1:"N";s:4:"㠯";s:1:"N";s:4:"巽";s:1:"N";s:4:"帨";s:1:"N";s:4:"帽";s:1:"N";s:4:"幩";s:1:"N";s:4:"㡢";s:1:"N";s:4:"𢆃";s:1:"N";s:4:"㡼";s:1:"N";s:4:"庰";s:1:"N";s:4:"庳";s:1:"N";s:4:"庶";s:1:"N";s:4:"廊";s:1:"N";s:4:"𪎒";s:1:"N";s:4:"廾";s:1:"N";s:4:"𢌱";s:1:"N";s:4:"𢌱";s:1:"N";s:4:"舁";s:1:"N";s:4:"弢";s:1:"N";s:4:"弢";s:1:"N";s:4:"㣇";s:1:"N";s:4:"𣊸";s:1:"N";s:4:"𦇚";s:1:"N";s:4:"形";s:1:"N";s:4:"彫";s:1:"N";s:4:"㣣";s:1:"N";s:4:"徚";s:1:"N";s:4:"忍";s:1:"N";s:4:"志";s:1:"N";s:4:"忹";s:1:"N";s:4:"悁";s:1:"N";s:4:"㤺";s:1:"N";s:4:"㤜";s:1:"N";s:4:"悔";s:1:"N";s:4:"𢛔";s:1:"N";s:4:"惇";s:1:"N";s:4:"慈";s:1:"N";s:4:"慌";s:1:"N";s:4:"慎";s:1:"N";s:4:"慌";s:1:"N";s:4:"慺";s:1:"N";s:4:"憎";s:1:"N";s:4:"憲";s:1:"N";s:4:"憤";s:1:"N";s:4:"憯";s:1:"N";s:4:"懞";s:1:"N";s:4:"懲";s:1:"N";s:4:"懶";s:1:"N";s:4:"成";s:1:"N";s:4:"戛";s:1:"N";s:4:"扝";s:1:"N";s:4:"抱";s:1:"N";s:4:"拔";s:1:"N";s:4:"捐";s:1:"N";s:4:"𢬌";s:1:"N";s:4:"挽";s:1:"N";s:4:"拼";s:1:"N";s:4:"捨";s:1:"N";s:4:"掃";s:1:"N";s:4:"揤";s:1:"N";s:4:"𢯱";s:1:"N";s:4:"搢";s:1:"N";s:4:"揅";s:1:"N";s:4:"掩";s:1:"N";s:4:"㨮";s:1:"N";s:4:"摩";s:1:"N";s:4:"摾";s:1:"N";s:4:"撝";s:1:"N";s:4:"摷";s:1:"N";s:4:"㩬";s:1:"N";s:4:"敏";s:1:"N";s:4:"敬";s:1:"N";s:4:"𣀊";s:1:"N";s:4:"旣";s:1:"N";s:4:"書";s:1:"N";s:4:"晉";s:1:"N";s:4:"㬙";s:1:"N";s:4:"暑";s:1:"N";s:4:"㬈";s:1:"N";s:4:"㫤";s:1:"N";s:4:"冒";s:1:"N";s:4:"冕";s:1:"N";s:4:"最";s:1:"N";s:4:"暜";s:1:"N";s:4:"肭";s:1:"N";s:4:"䏙";s:1:"N";s:4:"朗";s:1:"N";s:4:"望";s:1:"N";s:4:"朡";s:1:"N";s:4:"杞";s:1:"N";s:4:"杓";s:1:"N";s:4:"𣏃";s:1:"N";s:4:"㭉";s:1:"N";s:4:"柺";s:1:"N";s:4:"枅";s:1:"N";s:4:"桒";s:1:"N";s:4:"梅";s:1:"N";s:4:"𣑭";s:1:"N";s:4:"梎";s:1:"N";s:4:"栟";s:1:"N";s:4:"椔";s:1:"N";s:4:"㮝";s:1:"N";s:4:"楂";s:1:"N";s:4:"榣";s:1:"N";s:4:"槪";s:1:"N";s:4:"檨";s:1:"N";s:4:"𣚣";s:1:"N";s:4:"櫛";s:1:"N";s:4:"㰘";s:1:"N";s:4:"次";s:1:"N";s:4:"𣢧";s:1:"N";s:4:"歔";s:1:"N";s:4:"㱎";s:1:"N";s:4:"歲";s:1:"N";s:4:"殟";s:1:"N";s:4:"殺";s:1:"N";s:4:"殻";s:1:"N";s:4:"𣪍";s:1:"N";s:4:"𡴋";s:1:"N";s:4:"𣫺";s:1:"N";s:4:"汎";s:1:"N";s:4:"𣲼";s:1:"N";s:4:"沿";s:1:"N";s:4:"泍";s:1:"N";s:4:"汧";s:1:"N";s:4:"洖";s:1:"N";s:4:"派";s:1:"N";s:4:"海";s:1:"N";s:4:"流";s:1:"N";s:4:"浩";s:1:"N";s:4:"浸";s:1:"N";s:4:"涅";s:1:"N";s:4:"𣴞";s:1:"N";s:4:"洴";s:1:"N";s:4:"港";s:1:"N";s:4:"湮";s:1:"N";s:4:"㴳";s:1:"N";s:4:"滋";s:1:"N";s:4:"滇";s:1:"N";s:4:"𣻑";s:1:"N";s:4:"淹";s:1:"N";s:4:"潮";s:1:"N";s:4:"𣽞";s:1:"N";s:4:"𣾎";s:1:"N";s:4:"濆";s:1:"N";s:4:"瀹";s:1:"N";s:4:"瀞";s:1:"N";s:4:"瀛";s:1:"N";s:4:"㶖";s:1:"N";s:4:"灊";s:1:"N";s:4:"災";s:1:"N";s:4:"灷";s:1:"N";s:4:"炭";s:1:"N";s:4:"𠔥";s:1:"N";s:4:"煅";s:1:"N";s:4:"𤉣";s:1:"N";s:4:"熜";s:1:"N";s:4:"𤎫";s:1:"N";s:4:"爨";s:1:"N";s:4:"爵";s:1:"N";s:4:"牐";s:1:"N";s:4:"𤘈";s:1:"N";s:4:"犀";s:1:"N";s:4:"犕";s:1:"N";s:4:"𤜵";s:1:"N";s:4:"𤠔";s:1:"N";s:4:"獺";s:1:"N";s:4:"王";s:1:"N";s:4:"㺬";s:1:"N";s:4:"玥";s:1:"N";s:4:"㺸";s:1:"N";s:4:"㺸";s:1:"N";s:4:"瑇";s:1:"N";s:4:"瑜";s:1:"N";s:4:"瑱";s:1:"N";s:4:"璅";s:1:"N";s:4:"瓊";s:1:"N";s:4:"㼛";s:1:"N";s:4:"甤";s:1:"N";s:4:"𤰶";s:1:"N";s:4:"甾";s:1:"N";s:4:"𤲒";s:1:"N";s:4:"異";s:1:"N";s:4:"𢆟";s:1:"N";s:4:"瘐";s:1:"N";s:4:"𤾡";s:1:"N";s:4:"𤾸";s:1:"N";s:4:"𥁄";s:1:"N";s:4:"㿼";s:1:"N";s:4:"䀈";s:1:"N";s:4:"直";s:1:"N";s:4:"𥃳";s:1:"N";s:4:"𥃲";s:1:"N";s:4:"𥄙";s:1:"N";s:4:"𥄳";s:1:"N";s:4:"眞";s:1:"N";s:4:"真";s:1:"N";s:4:"真";s:1:"N";s:4:"睊";s:1:"N";s:4:"䀹";s:1:"N";s:4:"瞋";s:1:"N";s:4:"䁆";s:1:"N";s:4:"䂖";s:1:"N";s:4:"𥐝";s:1:"N";s:4:"硎";s:1:"N";s:4:"碌";s:1:"N";s:4:"磌";s:1:"N";s:4:"䃣";s:1:"N";s:4:"𥘦";s:1:"N";s:4:"祖";s:1:"N";s:4:"𥚚";s:1:"N";s:4:"𥛅";s:1:"N";s:4:"福";s:1:"N";s:4:"秫";s:1:"N";s:4:"䄯";s:1:"N";s:4:"穀";s:1:"N";s:4:"穊";s:1:"N";s:4:"穏";s:1:"N";s:4:"𥥼";s:1:"N";s:4:"𥪧";s:1:"N";s:4:"𥪧";s:1:"N";s:4:"竮";s:1:"N";s:4:"䈂";s:1:"N";s:4:"𥮫";s:1:"N";s:4:"篆";s:1:"N";s:4:"築";s:1:"N";s:4:"䈧";s:1:"N";s:4:"𥲀";s:1:"N";s:4:"糒";s:1:"N";s:4:"䊠";s:1:"N";s:4:"糨";s:1:"N";s:4:"糣";s:1:"N";s:4:"紀";s:1:"N";s:4:"𥾆";s:1:"N";s:4:"絣";s:1:"N";s:4:"䌁";s:1:"N";s:4:"緇";s:1:"N";s:4:"縂";s:1:"N";s:4:"繅";s:1:"N";s:4:"䌴";s:1:"N";s:4:"𦈨";s:1:"N";s:4:"𦉇";s:1:"N";s:4:"䍙";s:1:"N";s:4:"𦋙";s:1:"N";s:4:"罺";s:1:"N";s:4:"𦌾";s:1:"N";s:4:"羕";s:1:"N";s:4:"翺";s:1:"N";s:4:"者";s:1:"N";s:4:"𦓚";s:1:"N";s:4:"𦔣";s:1:"N";s:4:"聠";s:1:"N";s:4:"𦖨";s:1:"N";s:4:"聰";s:1:"N";s:4:"𣍟";s:1:"N";s:4:"䏕";s:1:"N";s:4:"育";s:1:"N";s:4:"脃";s:1:"N";s:4:"䐋";s:1:"N";s:4:"脾";s:1:"N";s:4:"媵";s:1:"N";s:4:"𦞧";s:1:"N";s:4:"𦞵";s:1:"N";s:4:"𣎓";s:1:"N";s:4:"𣎜";s:1:"N";s:4:"舁";s:1:"N";s:4:"舄";s:1:"N";s:4:"辞";s:1:"N";s:4:"䑫";s:1:"N";s:4:"芑";s:1:"N";s:4:"芋";s:1:"N";s:4:"芝";s:1:"N";s:4:"劳";s:1:"N";s:4:"花";s:1:"N";s:4:"芳";s:1:"N";s:4:"芽";s:1:"N";s:4:"苦";s:1:"N";s:4:"𦬼";s:1:"N";s:4:"若";s:1:"N";s:4:"茝";s:1:"N";s:4:"荣";s:1:"N";s:4:"莭";s:1:"N";s:4:"茣";s:1:"N";s:4:"莽";s:1:"N";s:4:"菧";s:1:"N";s:4:"著";s:1:"N";s:4:"荓";s:1:"N";s:4:"菊";s:1:"N";s:4:"菌";s:1:"N";s:4:"菜";s:1:"N";s:4:"𦰶";s:1:"N";s:4:"𦵫";s:1:"N";s:4:"𦳕";s:1:"N";s:4:"䔫";s:1:"N";s:4:"蓱";s:1:"N";s:4:"蓳";s:1:"N";s:4:"蔖";s:1:"N";s:4:"𧏊";s:1:"N";s:4:"蕤";s:1:"N";s:4:"𦼬";s:1:"N";s:4:"䕝";s:1:"N";s:4:"䕡";s:1:"N";s:4:"𦾱";s:1:"N";s:4:"𧃒";s:1:"N";s:4:"䕫";s:1:"N";s:4:"虐";s:1:"N";s:4:"虜";s:1:"N";s:4:"虧";s:1:"N";s:4:"虩";s:1:"N";s:4:"蚩";s:1:"N";s:4:"蚈";s:1:"N";s:4:"蜎";s:1:"N";s:4:"蛢";s:1:"N";s:4:"蝹";s:1:"N";s:4:"蜨";s:1:"N";s:4:"蝫";s:1:"N";s:4:"螆";s:1:"N";s:4:"䗗";s:1:"N";s:4:"蟡";s:1:"N";s:4:"蠁";s:1:"N";s:4:"䗹";s:1:"N";s:4:"衠";s:1:"N";s:4:"衣";s:1:"N";s:4:"𧙧";s:1:"N";s:4:"裗";s:1:"N";s:4:"裞";s:1:"N";s:4:"䘵";s:1:"N";s:4:"裺";s:1:"N";s:4:"㒻";s:1:"N";s:4:"𧢮";s:1:"N";s:4:"𧥦";s:1:"N";s:4:"䚾";s:1:"N";s:4:"䛇";s:1:"N";s:4:"誠";s:1:"N";s:4:"諭";s:1:"N";s:4:"變";s:1:"N";s:4:"豕";s:1:"N";s:4:"𧲨";s:1:"N";s:4:"貫";s:1:"N";s:4:"賁";s:1:"N";s:4:"贛";s:1:"N";s:4:"起";s:1:"N";s:4:"𧼯";s:1:"N";s:4:"𠠄";s:1:"N";s:4:"跋";s:1:"N";s:4:"趼";s:1:"N";s:4:"跰";s:1:"N";s:4:"𠣞";s:1:"N";s:4:"軔";s:1:"N";s:4:"輸";s:1:"N";s:4:"𨗒";s:1:"N";s:4:"𨗭";s:1:"N";s:4:"邔";s:1:"N";s:4:"郱";s:1:"N";s:4:"鄑";s:1:"N";s:4:"𨜮";s:1:"N";s:4:"鄛";s:1:"N";s:4:"鈸";s:1:"N";s:4:"鋗";s:1:"N";s:4:"鋘";s:1:"N";s:4:"鉼";s:1:"N";s:4:"鏹";s:1:"N";s:4:"鐕";s:1:"N";s:4:"𨯺";s:1:"N";s:4:"開";s:1:"N";s:4:"䦕";s:1:"N";s:4:"閷";s:1:"N";s:4:"𨵷";s:1:"N";s:4:"䧦";s:1:"N";s:4:"雃";s:1:"N";s:4:"嶲";s:1:"N";s:4:"霣";s:1:"N";s:4:"𩅅";s:1:"N";s:4:"𩈚";s:1:"N";s:4:"䩮";s:1:"N";s:4:"䩶";s:1:"N";s:4:"韠";s:1:"N";s:4:"𩐊";s:1:"N";s:4:"䪲";s:1:"N";s:4:"𩒖";s:1:"N";s:4:"頋";s:1:"N";s:4:"頋";s:1:"N";s:4:"頩";s:1:"N";s:4:"𩖶";s:1:"N";s:4:"飢";s:1:"N";s:4:"䬳";s:1:"N";s:4:"餩";s:1:"N";s:4:"馧";s:1:"N";s:4:"駂";s:1:"N";s:4:"駾";s:1:"N";s:4:"䯎";s:1:"N";s:4:"𩬰";s:1:"N";s:4:"鬒";s:1:"N";s:4:"鱀";s:1:"N";s:4:"鳽";s:1:"N";s:4:"䳎";s:1:"N";s:4:"䳭";s:1:"N";s:4:"鵧";s:1:"N";s:4:"𪃎";s:1:"N";s:4:"䳸";s:1:"N";s:4:"𪄅";s:1:"N";s:4:"𪈎";s:1:"N";s:4:"𪊑";s:1:"N";s:4:"麻";s:1:"N";s:4:"䵖";s:1:"N";s:4:"黹";s:1:"N";s:4:"黾";s:1:"N";s:4:"鼅";s:1:"N";s:4:"鼏";s:1:"N";s:4:"鼖";s:1:"N";s:4:"鼻";s:1:"N";s:4:"𪘀";s:1:"N";s:2:"̀";s:1:"M";s:2:"́";s:1:"M";s:2:"̂";s:1:"M";s:2:"̃";s:1:"M";s:2:"̄";s:1:"M";s:2:"̆";s:1:"M";s:2:"̇";s:1:"M";s:2:"̈";s:1:"M";s:2:"̉";s:1:"M";s:2:"̊";s:1:"M";s:2:"̋";s:1:"M";s:2:"̌";s:1:"M";s:2:"̏";s:1:"M";s:2:"̑";s:1:"M";s:2:"̓";s:1:"M";s:2:"̔";s:1:"M";s:2:"̛";s:1:"M";s:2:"̣";s:1:"M";s:2:"̤";s:1:"M";s:2:"̥";s:1:"M";s:2:"̦";s:1:"M";s:2:"̧";s:1:"M";s:2:"̨";s:1:"M";s:2:"̭";s:1:"M";s:2:"̮";s:1:"M";s:2:"̰";s:1:"M";s:2:"̱";s:1:"M";s:2:"̸";s:1:"M";s:2:"͂";s:1:"M";s:2:"ͅ";s:1:"M";s:2:"ٓ";s:1:"M";s:2:"ٔ";s:1:"M";s:2:"ٕ";s:1:"M";s:3:"़";s:1:"M";s:3:"া";s:1:"M";s:3:"ৗ";s:1:"M";s:3:"ା";s:1:"M";s:3:"ୖ";s:1:"M";s:3:"ୗ";s:1:"M";s:3:"ா";s:1:"M";s:3:"ௗ";s:1:"M";s:3:"ౖ";s:1:"M";s:3:"ೂ";s:1:"M";s:3:"ೕ";s:1:"M";s:3:"ೖ";s:1:"M";s:3:"ാ";s:1:"M";s:3:"ൗ";s:1:"M";s:3:"්";s:1:"M";s:3:"ා";s:1:"M";s:3:"ෟ";s:1:"M";s:3:"ီ";s:1:"M";s:3:"ᅡ";s:1:"M";s:3:"ᅢ";s:1:"M";s:3:"ᅣ";s:1:"M";s:3:"ᅤ";s:1:"M";s:3:"ᅥ";s:1:"M";s:3:"ᅦ";s:1:"M";s:3:"ᅧ";s:1:"M";s:3:"ᅨ";s:1:"M";s:3:"ᅩ";s:1:"M";s:3:"ᅪ";s:1:"M";s:3:"ᅫ";s:1:"M";s:3:"ᅬ";s:1:"M";s:3:"ᅭ";s:1:"M";s:3:"ᅮ";s:1:"M";s:3:"ᅯ";s:1:"M";s:3:"ᅰ";s:1:"M";s:3:"ᅱ";s:1:"M";s:3:"ᅲ";s:1:"M";s:3:"ᅳ";s:1:"M";s:3:"ᅴ";s:1:"M";s:3:"ᅵ";s:1:"M";s:3:"ᆨ";s:1:"M";s:3:"ᆩ";s:1:"M";s:3:"ᆪ";s:1:"M";s:3:"ᆫ";s:1:"M";s:3:"ᆬ";s:1:"M";s:3:"ᆭ";s:1:"M";s:3:"ᆮ";s:1:"M";s:3:"ᆯ";s:1:"M";s:3:"ᆰ";s:1:"M";s:3:"ᆱ";s:1:"M";s:3:"ᆲ";s:1:"M";s:3:"ᆳ";s:1:"M";s:3:"ᆴ";s:1:"M";s:3:"ᆵ";s:1:"M";s:3:"ᆶ";s:1:"M";s:3:"ᆷ";s:1:"M";s:3:"ᆸ";s:1:"M";s:3:"ᆹ";s:1:"M";s:3:"ᆺ";s:1:"M";s:3:"ᆻ";s:1:"M";s:3:"ᆼ";s:1:"M";s:3:"ᆽ";s:1:"M";s:3:"ᆾ";s:1:"M";s:3:"ᆿ";s:1:"M";s:3:"ᇀ";s:1:"M";s:3:"ᇁ";s:1:"M";s:3:"ᇂ";s:1:"M";s:3:"゙";s:1:"M";s:3:"゚";s:1:"M";}' );
+?>
diff --git a/includes/normal/UtfNormalDataK.inc b/includes/normal/UtfNormalDataK.inc
new file mode 100644 (file)
index 0000000..0f4cd7a
--- /dev/null
@@ -0,0 +1,10 @@
+<?php
+/**
+ * This file was automatically generated -- do not edit!
+ * Run UtfNormalGenerate.php to create this file again (make clean && make)
+ * @package MediaWiki
+ */
+/** */
+global $utfCompatibilityDecomp;
+$utfCompatibilityDecomp = unserialize( 'a:5389:{s:2:" ";s:1:" ";s:2:"¨";s:3:" ̈";s:2:"ª";s:1:"a";s:2:"¯";s:3:" ̄";s:2:"²";s:1:"2";s:2:"³";s:1:"3";s:2:"´";s:3:" ́";s:2:"µ";s:2:"μ";s:2:"¸";s:3:" ̧";s:2:"¹";s:1:"1";s:2:"º";s:1:"o";s:2:"¼";s:5:"1⁄4";s:2:"½";s:5:"1⁄2";s:2:"¾";s:5:"3⁄4";s:2:"À";s:3:"À";s:2:"Á";s:3:"Á";s:2:"Â";s:3:"Â";s:2:"Ã";s:3:"Ã";s:2:"Ä";s:3:"Ä";s:2:"Å";s:3:"Å";s:2:"Ç";s:3:"Ç";s:2:"È";s:3:"È";s:2:"É";s:3:"É";s:2:"Ê";s:3:"Ê";s:2:"Ë";s:3:"Ë";s:2:"Ì";s:3:"Ì";s:2:"Í";s:3:"Í";s:2:"Î";s:3:"Î";s:2:"Ï";s:3:"Ï";s:2:"Ñ";s:3:"Ñ";s:2:"Ò";s:3:"Ò";s:2:"Ó";s:3:"Ó";s:2:"Ô";s:3:"Ô";s:2:"Õ";s:3:"Õ";s:2:"Ö";s:3:"Ö";s:2:"Ù";s:3:"Ù";s:2:"Ú";s:3:"Ú";s:2:"Û";s:3:"Û";s:2:"Ü";s:3:"Ü";s:2:"Ý";s:3:"Ý";s:2:"à";s:3:"à";s:2:"á";s:3:"á";s:2:"â";s:3:"â";s:2:"ã";s:3:"ã";s:2:"ä";s:3:"ä";s:2:"å";s:3:"å";s:2:"ç";s:3:"ç";s:2:"è";s:3:"è";s:2:"é";s:3:"é";s:2:"ê";s:3:"ê";s:2:"ë";s:3:"ë";s:2:"ì";s:3:"ì";s:2:"í";s:3:"í";s:2:"î";s:3:"î";s:2:"ï";s:3:"ï";s:2:"ñ";s:3:"ñ";s:2:"ò";s:3:"ò";s:2:"ó";s:3:"ó";s:2:"ô";s:3:"ô";s:2:"õ";s:3:"õ";s:2:"ö";s:3:"ö";s:2:"ù";s:3:"ù";s:2:"ú";s:3:"ú";s:2:"û";s:3:"û";s:2:"ü";s:3:"ü";s:2:"ý";s:3:"ý";s:2:"ÿ";s:3:"ÿ";s:2:"Ā";s:3:"Ā";s:2:"ā";s:3:"ā";s:2:"Ă";s:3:"Ă";s:2:"ă";s:3:"ă";s:2:"Ą";s:3:"Ą";s:2:"ą";s:3:"ą";s:2:"Ć";s:3:"Ć";s:2:"ć";s:3:"ć";s:2:"Ĉ";s:3:"Ĉ";s:2:"ĉ";s:3:"ĉ";s:2:"Ċ";s:3:"Ċ";s:2:"ċ";s:3:"ċ";s:2:"Č";s:3:"Č";s:2:"č";s:3:"č";s:2:"Ď";s:3:"Ď";s:2:"ď";s:3:"ď";s:2:"Ē";s:3:"Ē";s:2:"ē";s:3:"ē";s:2:"Ĕ";s:3:"Ĕ";s:2:"ĕ";s:3:"ĕ";s:2:"Ė";s:3:"Ė";s:2:"ė";s:3:"ė";s:2:"Ę";s:3:"Ę";s:2:"ę";s:3:"ę";s:2:"Ě";s:3:"Ě";s:2:"ě";s:3:"ě";s:2:"Ĝ";s:3:"Ĝ";s:2:"ĝ";s:3:"ĝ";s:2:"Ğ";s:3:"Ğ";s:2:"ğ";s:3:"ğ";s:2:"Ġ";s:3:"Ġ";s:2:"ġ";s:3:"ġ";s:2:"Ģ";s:3:"Ģ";s:2:"ģ";s:3:"ģ";s:2:"Ĥ";s:3:"Ĥ";s:2:"ĥ";s:3:"ĥ";s:2:"Ĩ";s:3:"Ĩ";s:2:"ĩ";s:3:"ĩ";s:2:"Ī";s:3:"Ī";s:2:"ī";s:3:"ī";s:2:"Ĭ";s:3:"Ĭ";s:2:"ĭ";s:3:"ĭ";s:2:"Į";s:3:"Į";s:2:"į";s:3:"į";s:2:"İ";s:3:"İ";s:2:"IJ";s:2:"IJ";s:2:"ij";s:2:"ij";s:2:"Ĵ";s:3:"Ĵ";s:2:"ĵ";s:3:"ĵ";s:2:"Ķ";s:3:"Ķ";s:2:"ķ";s:3:"ķ";s:2:"Ĺ";s:3:"Ĺ";s:2:"ĺ";s:3:"ĺ";s:2:"Ļ";s:3:"Ļ";s:2:"ļ";s:3:"ļ";s:2:"Ľ";s:3:"Ľ";s:2:"ľ";s:3:"ľ";s:2:"Ŀ";s:3:"L·";s:2:"ŀ";s:3:"l·";s:2:"Ń";s:3:"Ń";s:2:"ń";s:3:"ń";s:2:"Ņ";s:3:"Ņ";s:2:"ņ";s:3:"ņ";s:2:"Ň";s:3:"Ň";s:2:"ň";s:3:"ň";s:2:"ʼn";s:3:"ʼn";s:2:"Ō";s:3:"Ō";s:2:"ō";s:3:"ō";s:2:"Ŏ";s:3:"Ŏ";s:2:"ŏ";s:3:"ŏ";s:2:"Ő";s:3:"Ő";s:2:"ő";s:3:"ő";s:2:"Ŕ";s:3:"Ŕ";s:2:"ŕ";s:3:"ŕ";s:2:"Ŗ";s:3:"Ŗ";s:2:"ŗ";s:3:"ŗ";s:2:"Ř";s:3:"Ř";s:2:"ř";s:3:"ř";s:2:"Ś";s:3:"Ś";s:2:"ś";s:3:"ś";s:2:"Ŝ";s:3:"Ŝ";s:2:"ŝ";s:3:"ŝ";s:2:"Ş";s:3:"Ş";s:2:"ş";s:3:"ş";s:2:"Š";s:3:"Š";s:2:"š";s:3:"š";s:2:"Ţ";s:3:"Ţ";s:2:"ţ";s:3:"ţ";s:2:"Ť";s:3:"Ť";s:2:"ť";s:3:"ť";s:2:"Ũ";s:3:"Ũ";s:2:"ũ";s:3:"ũ";s:2:"Ū";s:3:"Ū";s:2:"ū";s:3:"ū";s:2:"Ŭ";s:3:"Ŭ";s:2:"ŭ";s:3:"ŭ";s:2:"Ů";s:3:"Ů";s:2:"ů";s:3:"ů";s:2:"Ű";s:3:"Ű";s:2:"ű";s:3:"ű";s:2:"Ų";s:3:"Ų";s:2:"ų";s:3:"ų";s:2:"Ŵ";s:3:"Ŵ";s:2:"ŵ";s:3:"ŵ";s:2:"Ŷ";s:3:"Ŷ";s:2:"ŷ";s:3:"ŷ";s:2:"Ÿ";s:3:"Ÿ";s:2:"Ź";s:3:"Ź";s:2:"ź";s:3:"ź";s:2:"Ż";s:3:"Ż";s:2:"ż";s:3:"ż";s:2:"Ž";s:3:"Ž";s:2:"ž";s:3:"ž";s:2:"ſ";s:1:"s";s:2:"Ơ";s:3:"Ơ";s:2:"ơ";s:3:"ơ";s:2:"Ư";s:3:"Ư";s:2:"ư";s:3:"ư";s:2:"DŽ";s:4:"DŽ";s:2:"Dž";s:4:"Dž";s:2:"dž";s:4:"dž";s:2:"LJ";s:2:"LJ";s:2:"Lj";s:2:"Lj";s:2:"lj";s:2:"lj";s:2:"NJ";s:2:"NJ";s:2:"Nj";s:2:"Nj";s:2:"nj";s:2:"nj";s:2:"Ǎ";s:3:"Ǎ";s:2:"ǎ";s:3:"ǎ";s:2:"Ǐ";s:3:"Ǐ";s:2:"ǐ";s:3:"ǐ";s:2:"Ǒ";s:3:"Ǒ";s:2:"ǒ";s:3:"ǒ";s:2:"Ǔ";s:3:"Ǔ";s:2:"ǔ";s:3:"ǔ";s:2:"Ǖ";s:5:"Ǖ";s:2:"ǖ";s:5:"ǖ";s:2:"Ǘ";s:5:"Ǘ";s:2:"ǘ";s:5:"ǘ";s:2:"Ǚ";s:5:"Ǚ";s:2:"ǚ";s:5:"ǚ";s:2:"Ǜ";s:5:"Ǜ";s:2:"ǜ";s:5:"ǜ";s:2:"Ǟ";s:5:"Ǟ";s:2:"ǟ";s:5:"ǟ";s:2:"Ǡ";s:5:"Ǡ";s:2:"ǡ";s:5:"ǡ";s:2:"Ǣ";s:4:"Ǣ";s:2:"ǣ";s:4:"ǣ";s:2:"Ǧ";s:3:"Ǧ";s:2:"ǧ";s:3:"ǧ";s:2:"Ǩ";s:3:"Ǩ";s:2:"ǩ";s:3:"ǩ";s:2:"Ǫ";s:3:"Ǫ";s:2:"ǫ";s:3:"ǫ";s:2:"Ǭ";s:5:"Ǭ";s:2:"ǭ";s:5:"ǭ";s:2:"Ǯ";s:4:"Ǯ";s:2:"ǯ";s:4:"ǯ";s:2:"ǰ";s:3:"ǰ";s:2:"DZ";s:2:"DZ";s:2:"Dz";s:2:"Dz";s:2:"dz";s:2:"dz";s:2:"Ǵ";s:3:"Ǵ";s:2:"ǵ";s:3:"ǵ";s:2:"Ǹ";s:3:"Ǹ";s:2:"ǹ";s:3:"ǹ";s:2:"Ǻ";s:5:"Ǻ";s:2:"ǻ";s:5:"ǻ";s:2:"Ǽ";s:4:"Ǽ";s:2:"ǽ";s:4:"ǽ";s:2:"Ǿ";s:4:"Ǿ";s:2:"ǿ";s:4:"ǿ";s:2:"Ȁ";s:3:"Ȁ";s:2:"ȁ";s:3:"ȁ";s:2:"Ȃ";s:3:"Ȃ";s:2:"ȃ";s:3:"ȃ";s:2:"Ȅ";s:3:"Ȅ";s:2:"ȅ";s:3:"ȅ";s:2:"Ȇ";s:3:"Ȇ";s:2:"ȇ";s:3:"ȇ";s:2:"Ȉ";s:3:"Ȉ";s:2:"ȉ";s:3:"ȉ";s:2:"Ȋ";s:3:"Ȋ";s:2:"ȋ";s:3:"ȋ";s:2:"Ȍ";s:3:"Ȍ";s:2:"ȍ";s:3:"ȍ";s:2:"Ȏ";s:3:"Ȏ";s:2:"ȏ";s:3:"ȏ";s:2:"Ȑ";s:3:"Ȑ";s:2:"ȑ";s:3:"ȑ";s:2:"Ȓ";s:3:"Ȓ";s:2:"ȓ";s:3:"ȓ";s:2:"Ȕ";s:3:"Ȕ";s:2:"ȕ";s:3:"ȕ";s:2:"Ȗ";s:3:"Ȗ";s:2:"ȗ";s:3:"ȗ";s:2:"Ș";s:3:"Ș";s:2:"ș";s:3:"ș";s:2:"Ț";s:3:"Ț";s:2:"ț";s:3:"ț";s:2:"Ȟ";s:3:"Ȟ";s:2:"ȟ";s:3:"ȟ";s:2:"Ȧ";s:3:"Ȧ";s:2:"ȧ";s:3:"ȧ";s:2:"Ȩ";s:3:"Ȩ";s:2:"ȩ";s:3:"ȩ";s:2:"Ȫ";s:5:"Ȫ";s:2:"ȫ";s:5:"ȫ";s:2:"Ȭ";s:5:"Ȭ";s:2:"ȭ";s:5:"ȭ";s:2:"Ȯ";s:3:"Ȯ";s:2:"ȯ";s:3:"ȯ";s:2:"Ȱ";s:5:"Ȱ";s:2:"ȱ";s:5:"ȱ";s:2:"Ȳ";s:3:"Ȳ";s:2:"ȳ";s:3:"ȳ";s:2:"ʰ";s:1:"h";s:2:"ʱ";s:2:"ɦ";s:2:"ʲ";s:1:"j";s:2:"ʳ";s:1:"r";s:2:"ʴ";s:2:"ɹ";s:2:"ʵ";s:2:"ɻ";s:2:"ʶ";s:2:"ʁ";s:2:"ʷ";s:1:"w";s:2:"ʸ";s:1:"y";s:2:"˘";s:3:" ̆";s:2:"˙";s:3:" ̇";s:2:"˚";s:3:" ̊";s:2:"˛";s:3:" ̨";s:2:"˜";s:3:" ̃";s:2:"˝";s:3:" ̋";s:2:"ˠ";s:2:"ɣ";s:2:"ˡ";s:1:"l";s:2:"ˢ";s:1:"s";s:2:"ˣ";s:1:"x";s:2:"ˤ";s:2:"ʕ";s:2:"̀";s:2:"̀";s:2:"́";s:2:"́";s:2:"̓";s:2:"̓";s:2:"̈́";s:4:"̈́";s:2:"ʹ";s:2:"ʹ";s:2:"ͺ";s:3:" ͅ";s:2:";";s:1:";";s:2:"΄";s:3:" ́";s:2:"΅";s:5:" ̈́";s:2:"Ά";s:4:"Ά";s:2:"·";s:2:"·";s:2:"Έ";s:4:"Έ";s:2:"Ή";s:4:"Ή";s:2:"Ί";s:4:"Ί";s:2:"Ό";s:4:"Ό";s:2:"Ύ";s:4:"Ύ";s:2:"Ώ";s:4:"Ώ";s:2:"ΐ";s:6:"ΐ";s:2:"Ϊ";s:4:"Ϊ";s:2:"Ϋ";s:4:"Ϋ";s:2:"ά";s:4:"ά";s:2:"έ";s:4:"έ";s:2:"ή";s:4:"ή";s:2:"ί";s:4:"ί";s:2:"ΰ";s:6:"ΰ";s:2:"ϊ";s:4:"ϊ";s:2:"ϋ";s:4:"ϋ";s:2:"ό";s:4:"ό";s:2:"ύ";s:4:"ύ";s:2:"ώ";s:4:"ώ";s:2:"ϐ";s:2:"β";s:2:"ϑ";s:2:"θ";s:2:"ϒ";s:2:"Υ";s:2:"ϓ";s:4:"Ύ";s:2:"ϔ";s:4:"Ϋ";s:2:"ϕ";s:2:"φ";s:2:"ϖ";s:2:"π";s:2:"ϰ";s:2:"κ";s:2:"ϱ";s:2:"ρ";s:2:"ϲ";s:2:"ς";s:2:"ϴ";s:2:"Θ";s:2:"ϵ";s:2:"ε";s:2:"Ϲ";s:2:"Σ";s:2:"Ѐ";s:4:"Ѐ";s:2:"Ё";s:4:"Ё";s:2:"Ѓ";s:4:"Ѓ";s:2:"Ї";s:4:"Ї";s:2:"Ќ";s:4:"Ќ";s:2:"Ѝ";s:4:"Ѝ";s:2:"Ў";s:4:"Ў";s:2:"Й";s:4:"Й";s:2:"й";s:4:"й";s:2:"ѐ";s:4:"ѐ";s:2:"ё";s:4:"ё";s:2:"ѓ";s:4:"ѓ";s:2:"ї";s:4:"ї";s:2:"ќ";s:4:"ќ";s:2:"ѝ";s:4:"ѝ";s:2:"ў";s:4:"ў";s:2:"Ѷ";s:4:"Ѷ";s:2:"ѷ";s:4:"ѷ";s:2:"Ӂ";s:4:"Ӂ";s:2:"ӂ";s:4:"ӂ";s:2:"Ӑ";s:4:"Ӑ";s:2:"ӑ";s:4:"ӑ";s:2:"Ӓ";s:4:"Ӓ";s:2:"ӓ";s:4:"ӓ";s:2:"Ӗ";s:4:"Ӗ";s:2:"ӗ";s:4:"ӗ";s:2:"Ӛ";s:4:"Ӛ";s:2:"ӛ";s:4:"ӛ";s:2:"Ӝ";s:4:"Ӝ";s:2:"ӝ";s:4:"ӝ";s:2:"Ӟ";s:4:"Ӟ";s:2:"ӟ";s:4:"ӟ";s:2:"Ӣ";s:4:"Ӣ";s:2:"ӣ";s:4:"ӣ";s:2:"Ӥ";s:4:"Ӥ";s:2:"ӥ";s:4:"ӥ";s:2:"Ӧ";s:4:"Ӧ";s:2:"ӧ";s:4:"ӧ";s:2:"Ӫ";s:4:"Ӫ";s:2:"ӫ";s:4:"ӫ";s:2:"Ӭ";s:4:"Ӭ";s:2:"ӭ";s:4:"ӭ";s:2:"Ӯ";s:4:"Ӯ";s:2:"ӯ";s:4:"ӯ";s:2:"Ӱ";s:4:"Ӱ";s:2:"ӱ";s:4:"ӱ";s:2:"Ӳ";s:4:"Ӳ";s:2:"ӳ";s:4:"ӳ";s:2:"Ӵ";s:4:"Ӵ";s:2:"ӵ";s:4:"ӵ";s:2:"Ӹ";s:4:"Ӹ";s:2:"ӹ";s:4:"ӹ";s:2:"և";s:4:"եւ";s:2:"آ";s:4:"آ";s:2:"أ";s:4:"أ";s:2:"ؤ";s:4:"ؤ";s:2:"إ";s:4:"إ";s:2:"ئ";s:4:"ئ";s:2:"ٵ";s:4:"اٴ";s:2:"ٶ";s:4:"وٴ";s:2:"ٷ";s:4:"ۇٴ";s:2:"ٸ";s:4:"يٴ";s:2:"ۀ";s:4:"ۀ";s:2:"ۂ";s:4:"ۂ";s:2:"ۓ";s:4:"ۓ";s:3:"ऩ";s:6:"ऩ";s:3:"ऱ";s:6:"ऱ";s:3:"ऴ";s:6:"ऴ";s:3:"क़";s:6:"क़";s:3:"ख़";s:6:"ख़";s:3:"ग़";s:6:"ग़";s:3:"ज़";s:6:"ज़";s:3:"ड़";s:6:"ड़";s:3:"ढ़";s:6:"ढ़";s:3:"फ़";s:6:"फ़";s:3:"य़";s:6:"य़";s:3:"ো";s:6:"ো";s:3:"ৌ";s:6:"ৌ";s:3:"ড়";s:6:"ড়";s:3:"ঢ়";s:6:"ঢ়";s:3:"য়";s:6:"য়";s:3:"ਲ਼";s:6:"ਲ਼";s:3:"ਸ਼";s:6:"ਸ਼";s:3:"ਖ਼";s:6:"ਖ਼";s:3:"ਗ਼";s:6:"ਗ਼";s:3:"ਜ਼";s:6:"ਜ਼";s:3:"ਫ਼";s:6:"ਫ਼";s:3:"ୈ";s:6:"ୈ";s:3:"ୋ";s:6:"ୋ";s:3:"ୌ";s:6:"ୌ";s:3:"ଡ଼";s:6:"ଡ଼";s:3:"ଢ଼";s:6:"ଢ଼";s:3:"ஔ";s:6:"ஔ";s:3:"ொ";s:6:"ொ";s:3:"ோ";s:6:"ோ";s:3:"ௌ";s:6:"ௌ";s:3:"ై";s:6:"ై";s:3:"ೀ";s:6:"ೀ";s:3:"ೇ";s:6:"ೇ";s:3:"ೈ";s:6:"ೈ";s:3:"ೊ";s:6:"ೊ";s:3:"ೋ";s:9:"ೋ";s:3:"ൊ";s:6:"ൊ";s:3:"ോ";s:6:"ോ";s:3:"ൌ";s:6:"ൌ";s:3:"ේ";s:6:"ේ";s:3:"ො";s:6:"ො";s:3:"ෝ";s:9:"ෝ";s:3:"ෞ";s:6:"ෞ";s:3:"ำ";s:6:"ํา";s:3:"ຳ";s:6:"ໍາ";s:3:"ໜ";s:6:"ຫນ";s:3:"ໝ";s:6:"ຫມ";s:3:"༌";s:3:"་";s:3:"གྷ";s:6:"གྷ";s:3:"ཌྷ";s:6:"ཌྷ";s:3:"དྷ";s:6:"དྷ";s:3:"བྷ";s:6:"བྷ";s:3:"ཛྷ";s:6:"ཛྷ";s:3:"ཀྵ";s:6:"ཀྵ";s:3:"ཱི";s:6:"ཱི";s:3:"ཱུ";s:6:"ཱུ";s:3:"ྲྀ";s:6:"ྲྀ";s:3:"ཷ";s:9:"ྲཱྀ";s:3:"ླྀ";s:6:"ླྀ";s:3:"ཹ";s:9:"ླཱྀ";s:3:"ཱྀ";s:6:"ཱྀ";s:3:"ྒྷ";s:6:"ྒྷ";s:3:"ྜྷ";s:6:"ྜྷ";s:3:"ྡྷ";s:6:"ྡྷ";s:3:"ྦྷ";s:6:"ྦྷ";s:3:"ྫྷ";s:6:"ྫྷ";s:3:"ྐྵ";s:6:"ྐྵ";s:3:"ဦ";s:6:"ဦ";s:3:"ჼ";s:3:"ნ";s:3:"ᴬ";s:1:"A";s:3:"ᴭ";s:2:"Æ";s:3:"ᴮ";s:1:"B";s:3:"ᴰ";s:1:"D";s:3:"ᴱ";s:1:"E";s:3:"ᴲ";s:2:"Ǝ";s:3:"ᴳ";s:1:"G";s:3:"ᴴ";s:1:"H";s:3:"ᴵ";s:1:"I";s:3:"ᴶ";s:1:"J";s:3:"ᴷ";s:1:"K";s:3:"ᴸ";s:1:"L";s:3:"ᴹ";s:1:"M";s:3:"ᴺ";s:1:"N";s:3:"ᴼ";s:1:"O";s:3:"ᴽ";s:2:"Ȣ";s:3:"ᴾ";s:1:"P";s:3:"ᴿ";s:1:"R";s:3:"ᵀ";s:1:"T";s:3:"ᵁ";s:1:"U";s:3:"ᵂ";s:1:"W";s:3:"ᵃ";s:1:"a";s:3:"ᵄ";s:2:"ɐ";s:3:"ᵅ";s:2:"ɑ";s:3:"ᵆ";s:3:"ᴂ";s:3:"ᵇ";s:1:"b";s:3:"ᵈ";s:1:"d";s:3:"ᵉ";s:1:"e";s:3:"ᵊ";s:2:"ə";s:3:"ᵋ";s:2:"ɛ";s:3:"ᵌ";s:2:"ɜ";s:3:"ᵍ";s:1:"g";s:3:"ᵏ";s:1:"k";s:3:"ᵐ";s:1:"m";s:3:"ᵑ";s:2:"ŋ";s:3:"ᵒ";s:1:"o";s:3:"ᵓ";s:2:"ɔ";s:3:"ᵔ";s:3:"ᴖ";s:3:"ᵕ";s:3:"ᴗ";s:3:"ᵖ";s:1:"p";s:3:"ᵗ";s:1:"t";s:3:"ᵘ";s:1:"u";s:3:"ᵙ";s:3:"ᴝ";s:3:"ᵚ";s:2:"ɯ";s:3:"ᵛ";s:1:"v";s:3:"ᵜ";s:3:"ᴥ";s:3:"ᵝ";s:2:"β";s:3:"ᵞ";s:2:"γ";s:3:"ᵟ";s:2:"δ";s:3:"ᵠ";s:2:"φ";s:3:"ᵡ";s:2:"χ";s:3:"ᵢ";s:1:"i";s:3:"ᵣ";s:1:"r";s:3:"ᵤ";s:1:"u";s:3:"ᵥ";s:1:"v";s:3:"ᵦ";s:2:"β";s:3:"ᵧ";s:2:"γ";s:3:"ᵨ";s:2:"ρ";s:3:"ᵩ";s:2:"φ";s:3:"ᵪ";s:2:"χ";s:3:"ᵸ";s:2:"н";s:3:"ᶛ";s:2:"ɒ";s:3:"ᶜ";s:1:"c";s:3:"ᶝ";s:2:"ɕ";s:3:"ᶞ";s:2:"ð";s:3:"ᶟ";s:2:"ɜ";s:3:"ᶠ";s:1:"f";s:3:"ᶡ";s:2:"ɟ";s:3:"ᶢ";s:2:"ɡ";s:3:"ᶣ";s:2:"ɥ";s:3:"ᶤ";s:2:"ɨ";s:3:"ᶥ";s:2:"ɩ";s:3:"ᶦ";s:2:"ɪ";s:3:"ᶧ";s:3:"ᵻ";s:3:"ᶨ";s:2:"ʝ";s:3:"ᶩ";s:2:"ɭ";s:3:"ᶪ";s:3:"ᶅ";s:3:"ᶫ";s:2:"ʟ";s:3:"ᶬ";s:2:"ɱ";s:3:"ᶭ";s:2:"ɰ";s:3:"ᶮ";s:2:"ɲ";s:3:"ᶯ";s:2:"ɳ";s:3:"ᶰ";s:2:"ɴ";s:3:"ᶱ";s:2:"ɵ";s:3:"ᶲ";s:2:"ɸ";s:3:"ᶳ";s:2:"ʂ";s:3:"ᶴ";s:2:"ʃ";s:3:"ᶵ";s:2:"ƫ";s:3:"ᶶ";s:2:"ʉ";s:3:"ᶷ";s:2:"ʊ";s:3:"ᶸ";s:3:"ᴜ";s:3:"ᶹ";s:2:"ʋ";s:3:"ᶺ";s:2:"ʌ";s:3:"ᶻ";s:1:"z";s:3:"ᶼ";s:2:"ʐ";s:3:"ᶽ";s:2:"ʑ";s:3:"ᶾ";s:2:"ʒ";s:3:"ᶿ";s:2:"θ";s:3:"Ḁ";s:3:"Ḁ";s:3:"ḁ";s:3:"ḁ";s:3:"Ḃ";s:3:"Ḃ";s:3:"ḃ";s:3:"ḃ";s:3:"Ḅ";s:3:"Ḅ";s:3:"ḅ";s:3:"ḅ";s:3:"Ḇ";s:3:"Ḇ";s:3:"ḇ";s:3:"ḇ";s:3:"Ḉ";s:5:"Ḉ";s:3:"ḉ";s:5:"ḉ";s:3:"Ḋ";s:3:"Ḋ";s:3:"ḋ";s:3:"ḋ";s:3:"Ḍ";s:3:"Ḍ";s:3:"ḍ";s:3:"ḍ";s:3:"Ḏ";s:3:"Ḏ";s:3:"ḏ";s:3:"ḏ";s:3:"Ḑ";s:3:"Ḑ";s:3:"ḑ";s:3:"ḑ";s:3:"Ḓ";s:3:"Ḓ";s:3:"ḓ";s:3:"ḓ";s:3:"Ḕ";s:5:"Ḕ";s:3:"ḕ";s:5:"ḕ";s:3:"Ḗ";s:5:"Ḗ";s:3:"ḗ";s:5:"ḗ";s:3:"Ḙ";s:3:"Ḙ";s:3:"ḙ";s:3:"ḙ";s:3:"Ḛ";s:3:"Ḛ";s:3:"ḛ";s:3:"ḛ";s:3:"Ḝ";s:5:"Ḝ";s:3:"ḝ";s:5:"ḝ";s:3:"Ḟ";s:3:"Ḟ";s:3:"ḟ";s:3:"ḟ";s:3:"Ḡ";s:3:"Ḡ";s:3:"ḡ";s:3:"ḡ";s:3:"Ḣ";s:3:"Ḣ";s:3:"ḣ";s:3:"ḣ";s:3:"Ḥ";s:3:"Ḥ";s:3:"ḥ";s:3:"ḥ";s:3:"Ḧ";s:3:"Ḧ";s:3:"ḧ";s:3:"ḧ";s:3:"Ḩ";s:3:"Ḩ";s:3:"ḩ";s:3:"ḩ";s:3:"Ḫ";s:3:"Ḫ";s:3:"ḫ";s:3:"ḫ";s:3:"Ḭ";s:3:"Ḭ";s:3:"ḭ";s:3:"ḭ";s:3:"Ḯ";s:5:"Ḯ";s:3:"ḯ";s:5:"ḯ";s:3:"Ḱ";s:3:"Ḱ";s:3:"ḱ";s:3:"ḱ";s:3:"Ḳ";s:3:"Ḳ";s:3:"ḳ";s:3:"ḳ";s:3:"Ḵ";s:3:"Ḵ";s:3:"ḵ";s:3:"ḵ";s:3:"Ḷ";s:3:"Ḷ";s:3:"ḷ";s:3:"ḷ";s:3:"Ḹ";s:5:"Ḹ";s:3:"ḹ";s:5:"ḹ";s:3:"Ḻ";s:3:"Ḻ";s:3:"ḻ";s:3:"ḻ";s:3:"Ḽ";s:3:"Ḽ";s:3:"ḽ";s:3:"ḽ";s:3:"Ḿ";s:3:"Ḿ";s:3:"ḿ";s:3:"ḿ";s:3:"Ṁ";s:3:"Ṁ";s:3:"ṁ";s:3:"ṁ";s:3:"Ṃ";s:3:"Ṃ";s:3:"ṃ";s:3:"ṃ";s:3:"Ṅ";s:3:"Ṅ";s:3:"ṅ";s:3:"ṅ";s:3:"Ṇ";s:3:"Ṇ";s:3:"ṇ";s:3:"ṇ";s:3:"Ṉ";s:3:"Ṉ";s:3:"ṉ";s:3:"ṉ";s:3:"Ṋ";s:3:"Ṋ";s:3:"ṋ";s:3:"ṋ";s:3:"Ṍ";s:5:"Ṍ";s:3:"ṍ";s:5:"ṍ";s:3:"Ṏ";s:5:"Ṏ";s:3:"ṏ";s:5:"ṏ";s:3:"Ṑ";s:5:"Ṑ";s:3:"ṑ";s:5:"ṑ";s:3:"Ṓ";s:5:"Ṓ";s:3:"ṓ";s:5:"ṓ";s:3:"Ṕ";s:3:"Ṕ";s:3:"ṕ";s:3:"ṕ";s:3:"Ṗ";s:3:"Ṗ";s:3:"ṗ";s:3:"ṗ";s:3:"Ṙ";s:3:"Ṙ";s:3:"ṙ";s:3:"ṙ";s:3:"Ṛ";s:3:"Ṛ";s:3:"ṛ";s:3:"ṛ";s:3:"Ṝ";s:5:"Ṝ";s:3:"ṝ";s:5:"ṝ";s:3:"Ṟ";s:3:"Ṟ";s:3:"ṟ";s:3:"ṟ";s:3:"Ṡ";s:3:"Ṡ";s:3:"ṡ";s:3:"ṡ";s:3:"Ṣ";s:3:"Ṣ";s:3:"ṣ";s:3:"ṣ";s:3:"Ṥ";s:5:"Ṥ";s:3:"ṥ";s:5:"ṥ";s:3:"Ṧ";s:5:"Ṧ";s:3:"ṧ";s:5:"ṧ";s:3:"Ṩ";s:5:"Ṩ";s:3:"ṩ";s:5:"ṩ";s:3:"Ṫ";s:3:"Ṫ";s:3:"ṫ";s:3:"ṫ";s:3:"Ṭ";s:3:"Ṭ";s:3:"ṭ";s:3:"ṭ";s:3:"Ṯ";s:3:"Ṯ";s:3:"ṯ";s:3:"ṯ";s:3:"Ṱ";s:3:"Ṱ";s:3:"ṱ";s:3:"ṱ";s:3:"Ṳ";s:3:"Ṳ";s:3:"ṳ";s:3:"ṳ";s:3:"Ṵ";s:3:"Ṵ";s:3:"ṵ";s:3:"ṵ";s:3:"Ṷ";s:3:"Ṷ";s:3:"ṷ";s:3:"ṷ";s:3:"Ṹ";s:5:"Ṹ";s:3:"ṹ";s:5:"ṹ";s:3:"Ṻ";s:5:"Ṻ";s:3:"ṻ";s:5:"ṻ";s:3:"Ṽ";s:3:"Ṽ";s:3:"ṽ";s:3:"ṽ";s:3:"Ṿ";s:3:"Ṿ";s:3:"ṿ";s:3:"ṿ";s:3:"Ẁ";s:3:"Ẁ";s:3:"ẁ";s:3:"ẁ";s:3:"Ẃ";s:3:"Ẃ";s:3:"ẃ";s:3:"ẃ";s:3:"Ẅ";s:3:"Ẅ";s:3:"ẅ";s:3:"ẅ";s:3:"Ẇ";s:3:"Ẇ";s:3:"ẇ";s:3:"ẇ";s:3:"Ẉ";s:3:"Ẉ";s:3:"ẉ";s:3:"ẉ";s:3:"Ẋ";s:3:"Ẋ";s:3:"ẋ";s:3:"ẋ";s:3:"Ẍ";s:3:"Ẍ";s:3:"ẍ";s:3:"ẍ";s:3:"Ẏ";s:3:"Ẏ";s:3:"ẏ";s:3:"ẏ";s:3:"Ẑ";s:3:"Ẑ";s:3:"ẑ";s:3:"ẑ";s:3:"Ẓ";s:3:"Ẓ";s:3:"ẓ";s:3:"ẓ";s:3:"Ẕ";s:3:"Ẕ";s:3:"ẕ";s:3:"ẕ";s:3:"ẖ";s:3:"ẖ";s:3:"ẗ";s:3:"ẗ";s:3:"ẘ";s:3:"ẘ";s:3:"ẙ";s:3:"ẙ";s:3:"ẚ";s:3:"aʾ";s:3:"ẛ";s:3:"ṡ";s:3:"Ạ";s:3:"Ạ";s:3:"ạ";s:3:"ạ";s:3:"Ả";s:3:"Ả";s:3:"ả";s:3:"ả";s:3:"Ấ";s:5:"Ấ";s:3:"ấ";s:5:"ấ";s:3:"Ầ";s:5:"Ầ";s:3:"ầ";s:5:"ầ";s:3:"Ẩ";s:5:"Ẩ";s:3:"ẩ";s:5:"ẩ";s:3:"Ẫ";s:5:"Ẫ";s:3:"ẫ";s:5:"ẫ";s:3:"Ậ";s:5:"Ậ";s:3:"ậ";s:5:"ậ";s:3:"Ắ";s:5:"Ắ";s:3:"ắ";s:5:"ắ";s:3:"Ằ";s:5:"Ằ";s:3:"ằ";s:5:"ằ";s:3:"Ẳ";s:5:"Ẳ";s:3:"ẳ";s:5:"ẳ";s:3:"Ẵ";s:5:"Ẵ";s:3:"ẵ";s:5:"ẵ";s:3:"Ặ";s:5:"Ặ";s:3:"ặ";s:5:"ặ";s:3:"Ẹ";s:3:"Ẹ";s:3:"ẹ";s:3:"ẹ";s:3:"Ẻ";s:3:"Ẻ";s:3:"ẻ";s:3:"ẻ";s:3:"Ẽ";s:3:"Ẽ";s:3:"ẽ";s:3:"ẽ";s:3:"Ế";s:5:"Ế";s:3:"ế";s:5:"ế";s:3:"Ề";s:5:"Ề";s:3:"ề";s:5:"ề";s:3:"Ể";s:5:"Ể";s:3:"ể";s:5:"ể";s:3:"Ễ";s:5:"Ễ";s:3:"ễ";s:5:"ễ";s:3:"Ệ";s:5:"Ệ";s:3:"ệ";s:5:"ệ";s:3:"Ỉ";s:3:"Ỉ";s:3:"ỉ";s:3:"ỉ";s:3:"Ị";s:3:"Ị";s:3:"ị";s:3:"ị";s:3:"Ọ";s:3:"Ọ";s:3:"ọ";s:3:"ọ";s:3:"Ỏ";s:3:"Ỏ";s:3:"ỏ";s:3:"ỏ";s:3:"Ố";s:5:"Ố";s:3:"ố";s:5:"ố";s:3:"Ồ";s:5:"Ồ";s:3:"ồ";s:5:"ồ";s:3:"Ổ";s:5:"Ổ";s:3:"ổ";s:5:"ổ";s:3:"Ỗ";s:5:"Ỗ";s:3:"ỗ";s:5:"ỗ";s:3:"Ộ";s:5:"Ộ";s:3:"ộ";s:5:"ộ";s:3:"Ớ";s:5:"Ớ";s:3:"ớ";s:5:"ớ";s:3:"Ờ";s:5:"Ờ";s:3:"ờ";s:5:"ờ";s:3:"Ở";s:5:"Ở";s:3:"ở";s:5:"ở";s:3:"Ỡ";s:5:"Ỡ";s:3:"ỡ";s:5:"ỡ";s:3:"Ợ";s:5:"Ợ";s:3:"ợ";s:5:"ợ";s:3:"Ụ";s:3:"Ụ";s:3:"ụ";s:3:"ụ";s:3:"Ủ";s:3:"Ủ";s:3:"ủ";s:3:"ủ";s:3:"Ứ";s:5:"Ứ";s:3:"ứ";s:5:"ứ";s:3:"Ừ";s:5:"Ừ";s:3:"ừ";s:5:"ừ";s:3:"Ử";s:5:"Ử";s:3:"ử";s:5:"ử";s:3:"Ữ";s:5:"Ữ";s:3:"ữ";s:5:"ữ";s:3:"Ự";s:5:"Ự";s:3:"ự";s:5:"ự";s:3:"Ỳ";s:3:"Ỳ";s:3:"ỳ";s:3:"ỳ";s:3:"Ỵ";s:3:"Ỵ";s:3:"ỵ";s:3:"ỵ";s:3:"Ỷ";s:3:"Ỷ";s:3:"ỷ";s:3:"ỷ";s:3:"Ỹ";s:3:"Ỹ";s:3:"ỹ";s:3:"ỹ";s:3:"ἀ";s:4:"ἀ";s:3:"ἁ";s:4:"ἁ";s:3:"ἂ";s:6:"ἂ";s:3:"ἃ";s:6:"ἃ";s:3:"ἄ";s:6:"ἄ";s:3:"ἅ";s:6:"ἅ";s:3:"ἆ";s:6:"ἆ";s:3:"ἇ";s:6:"ἇ";s:3:"Ἀ";s:4:"Ἀ";s:3:"Ἁ";s:4:"Ἁ";s:3:"Ἂ";s:6:"Ἂ";s:3:"Ἃ";s:6:"Ἃ";s:3:"Ἄ";s:6:"Ἄ";s:3:"Ἅ";s:6:"Ἅ";s:3:"Ἆ";s:6:"Ἆ";s:3:"Ἇ";s:6:"Ἇ";s:3:"ἐ";s:4:"ἐ";s:3:"ἑ";s:4:"ἑ";s:3:"ἒ";s:6:"ἒ";s:3:"ἓ";s:6:"ἓ";s:3:"ἔ";s:6:"ἔ";s:3:"ἕ";s:6:"ἕ";s:3:"Ἐ";s:4:"Ἐ";s:3:"Ἑ";s:4:"Ἑ";s:3:"Ἒ";s:6:"Ἒ";s:3:"Ἓ";s:6:"Ἓ";s:3:"Ἔ";s:6:"Ἔ";s:3:"Ἕ";s:6:"Ἕ";s:3:"ἠ";s:4:"ἠ";s:3:"ἡ";s:4:"ἡ";s:3:"ἢ";s:6:"ἢ";s:3:"ἣ";s:6:"ἣ";s:3:"ἤ";s:6:"ἤ";s:3:"ἥ";s:6:"ἥ";s:3:"ἦ";s:6:"ἦ";s:3:"ἧ";s:6:"ἧ";s:3:"Ἠ";s:4:"Ἠ";s:3:"Ἡ";s:4:"Ἡ";s:3:"Ἢ";s:6:"Ἢ";s:3:"Ἣ";s:6:"Ἣ";s:3:"Ἤ";s:6:"Ἤ";s:3:"Ἥ";s:6:"Ἥ";s:3:"Ἦ";s:6:"Ἦ";s:3:"Ἧ";s:6:"Ἧ";s:3:"ἰ";s:4:"ἰ";s:3:"ἱ";s:4:"ἱ";s:3:"ἲ";s:6:"ἲ";s:3:"ἳ";s:6:"ἳ";s:3:"ἴ";s:6:"ἴ";s:3:"ἵ";s:6:"ἵ";s:3:"ἶ";s:6:"ἶ";s:3:"ἷ";s:6:"ἷ";s:3:"Ἰ";s:4:"Ἰ";s:3:"Ἱ";s:4:"Ἱ";s:3:"Ἲ";s:6:"Ἲ";s:3:"Ἳ";s:6:"Ἳ";s:3:"Ἴ";s:6:"Ἴ";s:3:"Ἵ";s:6:"Ἵ";s:3:"Ἶ";s:6:"Ἶ";s:3:"Ἷ";s:6:"Ἷ";s:3:"ὀ";s:4:"ὀ";s:3:"ὁ";s:4:"ὁ";s:3:"ὂ";s:6:"ὂ";s:3:"ὃ";s:6:"ὃ";s:3:"ὄ";s:6:"ὄ";s:3:"ὅ";s:6:"ὅ";s:3:"Ὀ";s:4:"Ὀ";s:3:"Ὁ";s:4:"Ὁ";s:3:"Ὂ";s:6:"Ὂ";s:3:"Ὃ";s:6:"Ὃ";s:3:"Ὄ";s:6:"Ὄ";s:3:"Ὅ";s:6:"Ὅ";s:3:"ὐ";s:4:"ὐ";s:3:"ὑ";s:4:"ὑ";s:3:"ὒ";s:6:"ὒ";s:3:"ὓ";s:6:"ὓ";s:3:"ὔ";s:6:"ὔ";s:3:"ὕ";s:6:"ὕ";s:3:"ὖ";s:6:"ὖ";s:3:"ὗ";s:6:"ὗ";s:3:"Ὑ";s:4:"Ὑ";s:3:"Ὓ";s:6:"Ὓ";s:3:"Ὕ";s:6:"Ὕ";s:3:"Ὗ";s:6:"Ὗ";s:3:"ὠ";s:4:"ὠ";s:3:"ὡ";s:4:"ὡ";s:3:"ὢ";s:6:"ὢ";s:3:"ὣ";s:6:"ὣ";s:3:"ὤ";s:6:"ὤ";s:3:"ὥ";s:6:"ὥ";s:3:"ὦ";s:6:"ὦ";s:3:"ὧ";s:6:"ὧ";s:3:"Ὠ";s:4:"Ὠ";s:3:"Ὡ";s:4:"Ὡ";s:3:"Ὢ";s:6:"Ὢ";s:3:"Ὣ";s:6:"Ὣ";s:3:"Ὤ";s:6:"Ὤ";s:3:"Ὥ";s:6:"Ὥ";s:3:"Ὦ";s:6:"Ὦ";s:3:"Ὧ";s:6:"Ὧ";s:3:"ὰ";s:4:"ὰ";s:3:"ά";s:4:"ά";s:3:"ὲ";s:4:"ὲ";s:3:"έ";s:4:"έ";s:3:"ὴ";s:4:"ὴ";s:3:"ή";s:4:"ή";s:3:"ὶ";s:4:"ὶ";s:3:"ί";s:4:"ί";s:3:"ὸ";s:4:"ὸ";s:3:"ό";s:4:"ό";s:3:"ὺ";s:4:"ὺ";s:3:"ύ";s:4:"ύ";s:3:"ὼ";s:4:"ὼ";s:3:"ώ";s:4:"ώ";s:3:"ᾀ";s:6:"ᾀ";s:3:"ᾁ";s:6:"ᾁ";s:3:"ᾂ";s:8:"ᾂ";s:3:"ᾃ";s:8:"ᾃ";s:3:"ᾄ";s:8:"ᾄ";s:3:"ᾅ";s:8:"ᾅ";s:3:"ᾆ";s:8:"ᾆ";s:3:"ᾇ";s:8:"ᾇ";s:3:"ᾈ";s:6:"ᾈ";s:3:"ᾉ";s:6:"ᾉ";s:3:"ᾊ";s:8:"ᾊ";s:3:"ᾋ";s:8:"ᾋ";s:3:"ᾌ";s:8:"ᾌ";s:3:"ᾍ";s:8:"ᾍ";s:3:"ᾎ";s:8:"ᾎ";s:3:"ᾏ";s:8:"ᾏ";s:3:"ᾐ";s:6:"ᾐ";s:3:"ᾑ";s:6:"ᾑ";s:3:"ᾒ";s:8:"ᾒ";s:3:"ᾓ";s:8:"ᾓ";s:3:"ᾔ";s:8:"ᾔ";s:3:"ᾕ";s:8:"ᾕ";s:3:"ᾖ";s:8:"ᾖ";s:3:"ᾗ";s:8:"ᾗ";s:3:"ᾘ";s:6:"ᾘ";s:3:"ᾙ";s:6:"ᾙ";s:3:"ᾚ";s:8:"ᾚ";s:3:"ᾛ";s:8:"ᾛ";s:3:"ᾜ";s:8:"ᾜ";s:3:"ᾝ";s:8:"ᾝ";s:3:"ᾞ";s:8:"ᾞ";s:3:"ᾟ";s:8:"ᾟ";s:3:"ᾠ";s:6:"ᾠ";s:3:"ᾡ";s:6:"ᾡ";s:3:"ᾢ";s:8:"ᾢ";s:3:"ᾣ";s:8:"ᾣ";s:3:"ᾤ";s:8:"ᾤ";s:3:"ᾥ";s:8:"ᾥ";s:3:"ᾦ";s:8:"ᾦ";s:3:"ᾧ";s:8:"ᾧ";s:3:"ᾨ";s:6:"ᾨ";s:3:"ᾩ";s:6:"ᾩ";s:3:"ᾪ";s:8:"ᾪ";s:3:"ᾫ";s:8:"ᾫ";s:3:"ᾬ";s:8:"ᾬ";s:3:"ᾭ";s:8:"ᾭ";s:3:"ᾮ";s:8:"ᾮ";s:3:"ᾯ";s:8:"ᾯ";s:3:"ᾰ";s:4:"ᾰ";s:3:"ᾱ";s:4:"ᾱ";s:3:"ᾲ";s:6:"ᾲ";s:3:"ᾳ";s:4:"ᾳ";s:3:"ᾴ";s:6:"ᾴ";s:3:"ᾶ";s:4:"ᾶ";s:3:"ᾷ";s:6:"ᾷ";s:3:"Ᾰ";s:4:"Ᾰ";s:3:"Ᾱ";s:4:"Ᾱ";s:3:"Ὰ";s:4:"Ὰ";s:3:"Ά";s:4:"Ά";s:3:"ᾼ";s:4:"ᾼ";s:3:"᾽";s:3:" ̓";s:3:"ι";s:2:"ι";s:3:"᾿";s:3:" ̓";s:3:"῀";s:3:" ͂";s:3:"῁";s:5:" ̈͂";s:3:"ῂ";s:6:"ῂ";s:3:"ῃ";s:4:"ῃ";s:3:"ῄ";s:6:"ῄ";s:3:"ῆ";s:4:"ῆ";s:3:"ῇ";s:6:"ῇ";s:3:"Ὲ";s:4:"Ὲ";s:3:"Έ";s:4:"Έ";s:3:"Ὴ";s:4:"Ὴ";s:3:"Ή";s:4:"Ή";s:3:"ῌ";s:4:"ῌ";s:3:"῍";s:5:" ̓̀";s:3:"῎";s:5:" ̓́";s:3:"῏";s:5:" ̓͂";s:3:"ῐ";s:4:"ῐ";s:3:"ῑ";s:4:"ῑ";s:3:"ῒ";s:6:"ῒ";s:3:"ΐ";s:6:"ΐ";s:3:"ῖ";s:4:"ῖ";s:3:"ῗ";s:6:"ῗ";s:3:"Ῐ";s:4:"Ῐ";s:3:"Ῑ";s:4:"Ῑ";s:3:"Ὶ";s:4:"Ὶ";s:3:"Ί";s:4:"Ί";s:3:"῝";s:5:" ̔̀";s:3:"῞";s:5:" ̔́";s:3:"῟";s:5:" ̔͂";s:3:"ῠ";s:4:"ῠ";s:3:"ῡ";s:4:"ῡ";s:3:"ῢ";s:6:"ῢ";s:3:"ΰ";s:6:"ΰ";s:3:"ῤ";s:4:"ῤ";s:3:"ῥ";s:4:"ῥ";s:3:"ῦ";s:4:"ῦ";s:3:"ῧ";s:6:"ῧ";s:3:"Ῠ";s:4:"Ῠ";s:3:"Ῡ";s:4:"Ῡ";s:3:"Ὺ";s:4:"Ὺ";s:3:"Ύ";s:4:"Ύ";s:3:"Ῥ";s:4:"Ῥ";s:3:"῭";s:5:" ̈̀";s:3:"΅";s:5:" ̈́";s:3:"`";s:1:"`";s:3:"ῲ";s:6:"ῲ";s:3:"ῳ";s:4:"ῳ";s:3:"ῴ";s:6:"ῴ";s:3:"ῶ";s:4:"ῶ";s:3:"ῷ";s:6:"ῷ";s:3:"Ὸ";s:4:"Ὸ";s:3:"Ό";s:4:"Ό";s:3:"Ὼ";s:4:"Ὼ";s:3:"Ώ";s:4:"Ώ";s:3:"ῼ";s:4:"ῼ";s:3:"´";s:3:" ́";s:3:"῾";s:3:" ̔";s:3:" ";s:1:" ";s:3:" ";s:1:" ";s:3:" ";s:1:" ";s:3:" ";s:1:" ";s:3:" ";s:1:" ";s:3:" ";s:1:" ";s:3:" ";s:1:" ";s:3:" ";s:1:" ";s:3:" ";s:1:" ";s:3:" ";s:1:" ";s:3:" ";s:1:" ";s:3:"‑";s:3:"‐";s:3:"‗";s:3:" ̳";s:3:"․";s:1:".";s:3:"‥";s:2:"..";s:3:"…";s:3:"...";s:3:" ";s:1:" ";s:3:"″";s:6:"′′";s:3:"‴";s:9:"′′′";s:3:"‶";s:6:"‵‵";s:3:"‷";s:9:"‵‵‵";s:3:"‼";s:2:"!!";s:3:"‾";s:3:" ̅";s:3:"⁇";s:2:"??";s:3:"⁈";s:2:"?!";s:3:"⁉";s:2:"!?";s:3:"⁗";s:12:"′′′′";s:3:" ";s:1:" ";s:3:"⁰";s:1:"0";s:3:"ⁱ";s:1:"i";s:3:"⁴";s:1:"4";s:3:"⁵";s:1:"5";s:3:"⁶";s:1:"6";s:3:"⁷";s:1:"7";s:3:"⁸";s:1:"8";s:3:"⁹";s:1:"9";s:3:"⁺";s:1:"+";s:3:"⁻";s:3:"−";s:3:"⁼";s:1:"=";s:3:"⁽";s:1:"(";s:3:"⁾";s:1:")";s:3:"ⁿ";s:1:"n";s:3:"₀";s:1:"0";s:3:"₁";s:1:"1";s:3:"₂";s:1:"2";s:3:"₃";s:1:"3";s:3:"₄";s:1:"4";s:3:"₅";s:1:"5";s:3:"₆";s:1:"6";s:3:"₇";s:1:"7";s:3:"₈";s:1:"8";s:3:"₉";s:1:"9";s:3:"₊";s:1:"+";s:3:"₋";s:3:"−";s:3:"₌";s:1:"=";s:3:"₍";s:1:"(";s:3:"₎";s:1:")";s:3:"ₐ";s:1:"a";s:3:"ₑ";s:1:"e";s:3:"ₒ";s:1:"o";s:3:"ₓ";s:1:"x";s:3:"ₔ";s:2:"ə";s:3:"₨";s:2:"Rs";s:3:"℀";s:3:"a/c";s:3:"℁";s:3:"a/s";s:3:"ℂ";s:1:"C";s:3:"℃";s:3:"°C";s:3:"℅";s:3:"c/o";s:3:"℆";s:3:"c/u";s:3:"ℇ";s:2:"Ɛ";s:3:"℉";s:3:"°F";s:3:"ℊ";s:1:"g";s:3:"ℋ";s:1:"H";s:3:"ℌ";s:1:"H";s:3:"ℍ";s:1:"H";s:3:"ℎ";s:1:"h";s:3:"ℏ";s:2:"ħ";s:3:"ℐ";s:1:"I";s:3:"ℑ";s:1:"I";s:3:"ℒ";s:1:"L";s:3:"ℓ";s:1:"l";s:3:"ℕ";s:1:"N";s:3:"№";s:2:"No";s:3:"ℙ";s:1:"P";s:3:"ℚ";s:1:"Q";s:3:"ℛ";s:1:"R";s:3:"ℜ";s:1:"R";s:3:"ℝ";s:1:"R";s:3:"℠";s:2:"SM";s:3:"℡";s:3:"TEL";s:3:"™";s:2:"TM";s:3:"ℤ";s:1:"Z";s:3:"Ω";s:2:"Ω";s:3:"ℨ";s:1:"Z";s:3:"K";s:1:"K";s:3:"Å";s:3:"Å";s:3:"ℬ";s:1:"B";s:3:"ℭ";s:1:"C";s:3:"ℯ";s:1:"e";s:3:"ℰ";s:1:"E";s:3:"ℱ";s:1:"F";s:3:"ℳ";s:1:"M";s:3:"ℴ";s:1:"o";s:3:"ℵ";s:2:"א";s:3:"ℶ";s:2:"ב";s:3:"ℷ";s:2:"ג";s:3:"ℸ";s:2:"ד";s:3:"ℹ";s:1:"i";s:3:"℻";s:3:"FAX";s:3:"ℼ";s:2:"π";s:3:"ℽ";s:2:"γ";s:3:"ℾ";s:2:"Γ";s:3:"ℿ";s:2:"Π";s:3:"⅀";s:3:"∑";s:3:"ⅅ";s:1:"D";s:3:"ⅆ";s:1:"d";s:3:"ⅇ";s:1:"e";s:3:"ⅈ";s:1:"i";s:3:"ⅉ";s:1:"j";s:3:"⅓";s:5:"1⁄3";s:3:"⅔";s:5:"2⁄3";s:3:"⅕";s:5:"1⁄5";s:3:"⅖";s:5:"2⁄5";s:3:"⅗";s:5:"3⁄5";s:3:"⅘";s:5:"4⁄5";s:3:"⅙";s:5:"1⁄6";s:3:"⅚";s:5:"5⁄6";s:3:"⅛";s:5:"1⁄8";s:3:"⅜";s:5:"3⁄8";s:3:"⅝";s:5:"5⁄8";s:3:"⅞";s:5:"7⁄8";s:3:"⅟";s:4:"1⁄";s:3:"Ⅰ";s:1:"I";s:3:"Ⅱ";s:2:"II";s:3:"Ⅲ";s:3:"III";s:3:"Ⅳ";s:2:"IV";s:3:"Ⅴ";s:1:"V";s:3:"Ⅵ";s:2:"VI";s:3:"Ⅶ";s:3:"VII";s:3:"Ⅷ";s:4:"VIII";s:3:"Ⅸ";s:2:"IX";s:3:"Ⅹ";s:1:"X";s:3:"Ⅺ";s:2:"XI";s:3:"Ⅻ";s:3:"XII";s:3:"Ⅼ";s:1:"L";s:3:"Ⅽ";s:1:"C";s:3:"Ⅾ";s:1:"D";s:3:"Ⅿ";s:1:"M";s:3:"ⅰ";s:1:"i";s:3:"ⅱ";s:2:"ii";s:3:"ⅲ";s:3:"iii";s:3:"ⅳ";s:2:"iv";s:3:"ⅴ";s:1:"v";s:3:"ⅵ";s:2:"vi";s:3:"ⅶ";s:3:"vii";s:3:"ⅷ";s:4:"viii";s:3:"ⅸ";s:2:"ix";s:3:"ⅹ";s:1:"x";s:3:"ⅺ";s:2:"xi";s:3:"ⅻ";s:3:"xii";s:3:"ⅼ";s:1:"l";s:3:"ⅽ";s:1:"c";s:3:"ⅾ";s:1:"d";s:3:"ⅿ";s:1:"m";s:3:"↚";s:5:"↚";s:3:"↛";s:5:"↛";s:3:"↮";s:5:"↮";s:3:"⇍";s:5:"⇍";s:3:"⇎";s:5:"⇎";s:3:"⇏";s:5:"⇏";s:3:"∄";s:5:"∄";s:3:"∉";s:5:"∉";s:3:"∌";s:5:"∌";s:3:"∤";s:5:"∤";s:3:"∦";s:5:"∦";s:3:"∬";s:6:"∫∫";s:3:"∭";s:9:"∫∫∫";s:3:"∯";s:6:"∮∮";s:3:"∰";s:9:"∮∮∮";s:3:"≁";s:5:"≁";s:3:"≄";s:5:"≄";s:3:"≇";s:5:"≇";s:3:"≉";s:5:"≉";s:3:"≠";s:3:"≠";s:3:"≢";s:5:"≢";s:3:"≭";s:5:"≭";s:3:"≮";s:3:"≮";s:3:"≯";s:3:"≯";s:3:"≰";s:5:"≰";s:3:"≱";s:5:"≱";s:3:"≴";s:5:"≴";s:3:"≵";s:5:"≵";s:3:"≸";s:5:"≸";s:3:"≹";s:5:"≹";s:3:"⊀";s:5:"⊀";s:3:"⊁";s:5:"⊁";s:3:"⊄";s:5:"⊄";s:3:"⊅";s:5:"⊅";s:3:"⊈";s:5:"⊈";s:3:"⊉";s:5:"⊉";s:3:"⊬";s:5:"⊬";s:3:"⊭";s:5:"⊭";s:3:"⊮";s:5:"⊮";s:3:"⊯";s:5:"⊯";s:3:"⋠";s:5:"⋠";s:3:"⋡";s:5:"⋡";s:3:"⋢";s:5:"⋢";s:3:"⋣";s:5:"⋣";s:3:"⋪";s:5:"⋪";s:3:"⋫";s:5:"⋫";s:3:"⋬";s:5:"⋬";s:3:"⋭";s:5:"⋭";s:3:"〈";s:3:"〈";s:3:"〉";s:3:"〉";s:3:"①";s:1:"1";s:3:"②";s:1:"2";s:3:"③";s:1:"3";s:3:"④";s:1:"4";s:3:"⑤";s:1:"5";s:3:"⑥";s:1:"6";s:3:"⑦";s:1:"7";s:3:"⑧";s:1:"8";s:3:"⑨";s:1:"9";s:3:"⑩";s:2:"10";s:3:"⑪";s:2:"11";s:3:"⑫";s:2:"12";s:3:"⑬";s:2:"13";s:3:"⑭";s:2:"14";s:3:"⑮";s:2:"15";s:3:"⑯";s:2:"16";s:3:"⑰";s:2:"17";s:3:"⑱";s:2:"18";s:3:"⑲";s:2:"19";s:3:"⑳";s:2:"20";s:3:"⑴";s:3:"(1)";s:3:"⑵";s:3:"(2)";s:3:"⑶";s:3:"(3)";s:3:"⑷";s:3:"(4)";s:3:"⑸";s:3:"(5)";s:3:"⑹";s:3:"(6)";s:3:"⑺";s:3:"(7)";s:3:"⑻";s:3:"(8)";s:3:"⑼";s:3:"(9)";s:3:"⑽";s:4:"(10)";s:3:"⑾";s:4:"(11)";s:3:"⑿";s:4:"(12)";s:3:"⒀";s:4:"(13)";s:3:"⒁";s:4:"(14)";s:3:"⒂";s:4:"(15)";s:3:"⒃";s:4:"(16)";s:3:"⒄";s:4:"(17)";s:3:"⒅";s:4:"(18)";s:3:"⒆";s:4:"(19)";s:3:"⒇";s:4:"(20)";s:3:"⒈";s:2:"1.";s:3:"⒉";s:2:"2.";s:3:"⒊";s:2:"3.";s:3:"⒋";s:2:"4.";s:3:"⒌";s:2:"5.";s:3:"⒍";s:2:"6.";s:3:"⒎";s:2:"7.";s:3:"⒏";s:2:"8.";s:3:"⒐";s:2:"9.";s:3:"⒑";s:3:"10.";s:3:"⒒";s:3:"11.";s:3:"⒓";s:3:"12.";s:3:"⒔";s:3:"13.";s:3:"⒕";s:3:"14.";s:3:"⒖";s:3:"15.";s:3:"⒗";s:3:"16.";s:3:"⒘";s:3:"17.";s:3:"⒙";s:3:"18.";s:3:"⒚";s:3:"19.";s:3:"⒛";s:3:"20.";s:3:"⒜";s:3:"(a)";s:3:"⒝";s:3:"(b)";s:3:"⒞";s:3:"(c)";s:3:"⒟";s:3:"(d)";s:3:"⒠";s:3:"(e)";s:3:"⒡";s:3:"(f)";s:3:"⒢";s:3:"(g)";s:3:"⒣";s:3:"(h)";s:3:"⒤";s:3:"(i)";s:3:"⒥";s:3:"(j)";s:3:"⒦";s:3:"(k)";s:3:"⒧";s:3:"(l)";s:3:"⒨";s:3:"(m)";s:3:"⒩";s:3:"(n)";s:3:"⒪";s:3:"(o)";s:3:"⒫";s:3:"(p)";s:3:"⒬";s:3:"(q)";s:3:"⒭";s:3:"(r)";s:3:"⒮";s:3:"(s)";s:3:"⒯";s:3:"(t)";s:3:"⒰";s:3:"(u)";s:3:"⒱";s:3:"(v)";s:3:"⒲";s:3:"(w)";s:3:"⒳";s:3:"(x)";s:3:"⒴";s:3:"(y)";s:3:"⒵";s:3:"(z)";s:3:"Ⓐ";s:1:"A";s:3:"Ⓑ";s:1:"B";s:3:"Ⓒ";s:1:"C";s:3:"Ⓓ";s:1:"D";s:3:"Ⓔ";s:1:"E";s:3:"Ⓕ";s:1:"F";s:3:"Ⓖ";s:1:"G";s:3:"Ⓗ";s:1:"H";s:3:"Ⓘ";s:1:"I";s:3:"Ⓙ";s:1:"J";s:3:"Ⓚ";s:1:"K";s:3:"Ⓛ";s:1:"L";s:3:"Ⓜ";s:1:"M";s:3:"Ⓝ";s:1:"N";s:3:"Ⓞ";s:1:"O";s:3:"Ⓟ";s:1:"P";s:3:"Ⓠ";s:1:"Q";s:3:"Ⓡ";s:1:"R";s:3:"Ⓢ";s:1:"S";s:3:"Ⓣ";s:1:"T";s:3:"Ⓤ";s:1:"U";s:3:"Ⓥ";s:1:"V";s:3:"Ⓦ";s:1:"W";s:3:"Ⓧ";s:1:"X";s:3:"Ⓨ";s:1:"Y";s:3:"Ⓩ";s:1:"Z";s:3:"ⓐ";s:1:"a";s:3:"ⓑ";s:1:"b";s:3:"ⓒ";s:1:"c";s:3:"ⓓ";s:1:"d";s:3:"ⓔ";s:1:"e";s:3:"ⓕ";s:1:"f";s:3:"ⓖ";s:1:"g";s:3:"ⓗ";s:1:"h";s:3:"ⓘ";s:1:"i";s:3:"ⓙ";s:1:"j";s:3:"ⓚ";s:1:"k";s:3:"ⓛ";s:1:"l";s:3:"ⓜ";s:1:"m";s:3:"ⓝ";s:1:"n";s:3:"ⓞ";s:1:"o";s:3:"ⓟ";s:1:"p";s:3:"ⓠ";s:1:"q";s:3:"ⓡ";s:1:"r";s:3:"ⓢ";s:1:"s";s:3:"ⓣ";s:1:"t";s:3:"ⓤ";s:1:"u";s:3:"ⓥ";s:1:"v";s:3:"ⓦ";s:1:"w";s:3:"ⓧ";s:1:"x";s:3:"ⓨ";s:1:"y";s:3:"ⓩ";s:1:"z";s:3:"⓪";s:1:"0";s:3:"⨌";s:12:"∫∫∫∫";s:3:"⩴";s:3:"::=";s:3:"⩵";s:2:"==";s:3:"⩶";s:3:"===";s:3:"⫝̸";s:5:"⫝̸";s:3:"ⵯ";s:3:"ⵡ";s:3:"⺟";s:3:"母";s:3:"⻳";s:3:"龟";s:3:"⼀";s:3:"一";s:3:"⼁";s:3:"丨";s:3:"⼂";s:3:"丶";s:3:"⼃";s:3:"丿";s:3:"⼄";s:3:"乙";s:3:"⼅";s:3:"亅";s:3:"⼆";s:3:"二";s:3:"⼇";s:3:"亠";s:3:"⼈";s:3:"人";s:3:"⼉";s:3:"儿";s:3:"⼊";s:3:"入";s:3:"⼋";s:3:"八";s:3:"⼌";s:3:"冂";s:3:"⼍";s:3:"冖";s:3:"⼎";s:3:"冫";s:3:"⼏";s:3:"几";s:3:"⼐";s:3:"凵";s:3:"⼑";s:3:"刀";s:3:"⼒";s:3:"力";s:3:"⼓";s:3:"勹";s:3:"⼔";s:3:"匕";s:3:"⼕";s:3:"匚";s:3:"⼖";s:3:"匸";s:3:"⼗";s:3:"十";s:3:"⼘";s:3:"卜";s:3:"⼙";s:3:"卩";s:3:"⼚";s:3:"厂";s:3:"⼛";s:3:"厶";s:3:"⼜";s:3:"又";s:3:"⼝";s:3:"口";s:3:"⼞";s:3:"囗";s:3:"⼟";s:3:"土";s:3:"⼠";s:3:"士";s:3:"⼡";s:3:"夂";s:3:"⼢";s:3:"夊";s:3:"⼣";s:3:"夕";s:3:"⼤";s:3:"大";s:3:"⼥";s:3:"女";s:3:"⼦";s:3:"子";s:3:"⼧";s:3:"宀";s:3:"⼨";s:3:"寸";s:3:"⼩";s:3:"小";s:3:"⼪";s:3:"尢";s:3:"⼫";s:3:"尸";s:3:"⼬";s:3:"屮";s:3:"⼭";s:3:"山";s:3:"⼮";s:3:"巛";s:3:"⼯";s:3:"工";s:3:"⼰";s:3:"己";s:3:"⼱";s:3:"巾";s:3:"⼲";s:3:"干";s:3:"⼳";s:3:"幺";s:3:"⼴";s:3:"广";s:3:"⼵";s:3:"廴";s:3:"⼶";s:3:"廾";s:3:"⼷";s:3:"弋";s:3:"⼸";s:3:"弓";s:3:"⼹";s:3:"彐";s:3:"⼺";s:3:"彡";s:3:"⼻";s:3:"彳";s:3:"⼼";s:3:"心";s:3:"⼽";s:3:"戈";s:3:"⼾";s:3:"戶";s:3:"⼿";s:3:"手";s:3:"⽀";s:3:"支";s:3:"⽁";s:3:"攴";s:3:"⽂";s:3:"文";s:3:"⽃";s:3:"斗";s:3:"⽄";s:3:"斤";s:3:"⽅";s:3:"方";s:3:"⽆";s:3:"无";s:3:"⽇";s:3:"日";s:3:"⽈";s:3:"曰";s:3:"⽉";s:3:"月";s:3:"⽊";s:3:"木";s:3:"⽋";s:3:"欠";s:3:"⽌";s:3:"止";s:3:"⽍";s:3:"歹";s:3:"⽎";s:3:"殳";s:3:"⽏";s:3:"毋";s:3:"⽐";s:3:"比";s:3:"⽑";s:3:"毛";s:3:"⽒";s:3:"氏";s:3:"⽓";s:3:"气";s:3:"⽔";s:3:"水";s:3:"⽕";s:3:"火";s:3:"⽖";s:3:"爪";s:3:"⽗";s:3:"父";s:3:"⽘";s:3:"爻";s:3:"⽙";s:3:"爿";s:3:"⽚";s:3:"片";s:3:"⽛";s:3:"牙";s:3:"⽜";s:3:"牛";s:3:"⽝";s:3:"犬";s:3:"⽞";s:3:"玄";s:3:"⽟";s:3:"玉";s:3:"⽠";s:3:"瓜";s:3:"⽡";s:3:"瓦";s:3:"⽢";s:3:"甘";s:3:"⽣";s:3:"生";s:3:"⽤";s:3:"用";s:3:"⽥";s:3:"田";s:3:"⽦";s:3:"疋";s:3:"⽧";s:3:"疒";s:3:"⽨";s:3:"癶";s:3:"⽩";s:3:"白";s:3:"⽪";s:3:"皮";s:3:"⽫";s:3:"皿";s:3:"⽬";s:3:"目";s:3:"⽭";s:3:"矛";s:3:"⽮";s:3:"矢";s:3:"⽯";s:3:"石";s:3:"⽰";s:3:"示";s:3:"⽱";s:3:"禸";s:3:"⽲";s:3:"禾";s:3:"⽳";s:3:"穴";s:3:"⽴";s:3:"立";s:3:"⽵";s:3:"竹";s:3:"⽶";s:3:"米";s:3:"⽷";s:3:"糸";s:3:"⽸";s:3:"缶";s:3:"⽹";s:3:"网";s:3:"⽺";s:3:"羊";s:3:"⽻";s:3:"羽";s:3:"⽼";s:3:"老";s:3:"⽽";s:3:"而";s:3:"⽾";s:3:"耒";s:3:"⽿";s:3:"耳";s:3:"⾀";s:3:"聿";s:3:"⾁";s:3:"肉";s:3:"⾂";s:3:"臣";s:3:"⾃";s:3:"自";s:3:"⾄";s:3:"至";s:3:"⾅";s:3:"臼";s:3:"⾆";s:3:"舌";s:3:"⾇";s:3:"舛";s:3:"⾈";s:3:"舟";s:3:"⾉";s:3:"艮";s:3:"⾊";s:3:"色";s:3:"⾋";s:3:"艸";s:3:"⾌";s:3:"虍";s:3:"⾍";s:3:"虫";s:3:"⾎";s:3:"血";s:3:"⾏";s:3:"行";s:3:"⾐";s:3:"衣";s:3:"⾑";s:3:"襾";s:3:"⾒";s:3:"見";s:3:"⾓";s:3:"角";s:3:"⾔";s:3:"言";s:3:"⾕";s:3:"谷";s:3:"⾖";s:3:"豆";s:3:"⾗";s:3:"豕";s:3:"⾘";s:3:"豸";s:3:"⾙";s:3:"貝";s:3:"⾚";s:3:"赤";s:3:"⾛";s:3:"走";s:3:"⾜";s:3:"足";s:3:"⾝";s:3:"身";s:3:"⾞";s:3:"車";s:3:"⾟";s:3:"辛";s:3:"⾠";s:3:"辰";s:3:"⾡";s:3:"辵";s:3:"⾢";s:3:"邑";s:3:"⾣";s:3:"酉";s:3:"⾤";s:3:"釆";s:3:"⾥";s:3:"里";s:3:"⾦";s:3:"金";s:3:"⾧";s:3:"長";s:3:"⾨";s:3:"門";s:3:"⾩";s:3:"阜";s:3:"⾪";s:3:"隶";s:3:"⾫";s:3:"隹";s:3:"⾬";s:3:"雨";s:3:"⾭";s:3:"靑";s:3:"⾮";s:3:"非";s:3:"⾯";s:3:"面";s:3:"⾰";s:3:"革";s:3:"⾱";s:3:"韋";s:3:"⾲";s:3:"韭";s:3:"⾳";s:3:"音";s:3:"⾴";s:3:"頁";s:3:"⾵";s:3:"風";s:3:"⾶";s:3:"飛";s:3:"⾷";s:3:"食";s:3:"⾸";s:3:"首";s:3:"⾹";s:3:"香";s:3:"⾺";s:3:"馬";s:3:"⾻";s:3:"骨";s:3:"⾼";s:3:"高";s:3:"⾽";s:3:"髟";s:3:"⾾";s:3:"鬥";s:3:"⾿";s:3:"鬯";s:3:"⿀";s:3:"鬲";s:3:"⿁";s:3:"鬼";s:3:"⿂";s:3:"魚";s:3:"⿃";s:3:"鳥";s:3:"⿄";s:3:"鹵";s:3:"⿅";s:3:"鹿";s:3:"⿆";s:3:"麥";s:3:"⿇";s:3:"麻";s:3:"⿈";s:3:"黃";s:3:"⿉";s:3:"黍";s:3:"⿊";s:3:"黑";s:3:"⿋";s:3:"黹";s:3:"⿌";s:3:"黽";s:3:"⿍";s:3:"鼎";s:3:"⿎";s:3:"鼓";s:3:"⿏";s:3:"鼠";s:3:"⿐";s:3:"鼻";s:3:"⿑";s:3:"齊";s:3:"⿒";s:3:"齒";s:3:"⿓";s:3:"龍";s:3:"⿔";s:3:"龜";s:3:"⿕";s:3:"龠";s:3:" ";s:1:" ";s:3:"〶";s:3:"〒";s:3:"〸";s:3:"十";s:3:"〹";s:3:"卄";s:3:"〺";s:3:"卅";s:3:"が";s:6:"が";s:3:"ぎ";s:6:"ぎ";s:3:"ぐ";s:6:"ぐ";s:3:"げ";s:6:"げ";s:3:"ご";s:6:"ご";s:3:"ざ";s:6:"ざ";s:3:"じ";s:6:"じ";s:3:"ず";s:6:"ず";s:3:"ぜ";s:6:"ぜ";s:3:"ぞ";s:6:"ぞ";s:3:"だ";s:6:"だ";s:3:"ぢ";s:6:"ぢ";s:3:"づ";s:6:"づ";s:3:"で";s:6:"で";s:3:"ど";s:6:"ど";s:3:"ば";s:6:"ば";s:3:"ぱ";s:6:"ぱ";s:3:"び";s:6:"び";s:3:"ぴ";s:6:"ぴ";s:3:"ぶ";s:6:"ぶ";s:3:"ぷ";s:6:"ぷ";s:3:"べ";s:6:"べ";s:3:"ぺ";s:6:"ぺ";s:3:"ぼ";s:6:"ぼ";s:3:"ぽ";s:6:"ぽ";s:3:"ゔ";s:6:"ゔ";s:3:"゛";s:4:" ゙";s:3:"゜";s:4:" ゚";s:3:"ゞ";s:6:"ゞ";s:3:"ゟ";s:6:"より";s:3:"ガ";s:6:"ガ";s:3:"ギ";s:6:"ギ";s:3:"グ";s:6:"グ";s:3:"ゲ";s:6:"ゲ";s:3:"ゴ";s:6:"ゴ";s:3:"ザ";s:6:"ザ";s:3:"ジ";s:6:"ジ";s:3:"ズ";s:6:"ズ";s:3:"ゼ";s:6:"ゼ";s:3:"ゾ";s:6:"ゾ";s:3:"ダ";s:6:"ダ";s:3:"ヂ";s:6:"ヂ";s:3:"ヅ";s:6:"ヅ";s:3:"デ";s:6:"デ";s:3:"ド";s:6:"ド";s:3:"バ";s:6:"バ";s:3:"パ";s:6:"パ";s:3:"ビ";s:6:"ビ";s:3:"ピ";s:6:"ピ";s:3:"ブ";s:6:"ブ";s:3:"プ";s:6:"プ";s:3:"ベ";s:6:"ベ";s:3:"ペ";s:6:"ペ";s:3:"ボ";s:6:"ボ";s:3:"ポ";s:6:"ポ";s:3:"ヴ";s:6:"ヴ";s:3:"ヷ";s:6:"ヷ";s:3:"ヸ";s:6:"ヸ";s:3:"ヹ";s:6:"ヹ";s:3:"ヺ";s:6:"ヺ";s:3:"ヾ";s:6:"ヾ";s:3:"ヿ";s:6:"コト";s:3:"ㄱ";s:3:"ᄀ";s:3:"ㄲ";s:3:"ᄁ";s:3:"ㄳ";s:3:"ᆪ";s:3:"ㄴ";s:3:"ᄂ";s:3:"ㄵ";s:3:"ᆬ";s:3:"ㄶ";s:3:"ᆭ";s:3:"ㄷ";s:3:"ᄃ";s:3:"ㄸ";s:3:"ᄄ";s:3:"ㄹ";s:3:"ᄅ";s:3:"ㄺ";s:3:"ᆰ";s:3:"ㄻ";s:3:"ᆱ";s:3:"ㄼ";s:3:"ᆲ";s:3:"ㄽ";s:3:"ᆳ";s:3:"ㄾ";s:3:"ᆴ";s:3:"ㄿ";s:3:"ᆵ";s:3:"ㅀ";s:3:"ᄚ";s:3:"ㅁ";s:3:"ᄆ";s:3:"ㅂ";s:3:"ᄇ";s:3:"ㅃ";s:3:"ᄈ";s:3:"ㅄ";s:3:"ᄡ";s:3:"ㅅ";s:3:"ᄉ";s:3:"ㅆ";s:3:"ᄊ";s:3:"ㅇ";s:3:"ᄋ";s:3:"ㅈ";s:3:"ᄌ";s:3:"ㅉ";s:3:"ᄍ";s:3:"ㅊ";s:3:"ᄎ";s:3:"ㅋ";s:3:"ᄏ";s:3:"ㅌ";s:3:"ᄐ";s:3:"ㅍ";s:3:"ᄑ";s:3:"ㅎ";s:3:"ᄒ";s:3:"ㅏ";s:3:"ᅡ";s:3:"ㅐ";s:3:"ᅢ";s:3:"ㅑ";s:3:"ᅣ";s:3:"ㅒ";s:3:"ᅤ";s:3:"ㅓ";s:3:"ᅥ";s:3:"ㅔ";s:3:"ᅦ";s:3:"ㅕ";s:3:"ᅧ";s:3:"ㅖ";s:3:"ᅨ";s:3:"ㅗ";s:3:"ᅩ";s:3:"ㅘ";s:3:"ᅪ";s:3:"ㅙ";s:3:"ᅫ";s:3:"ㅚ";s:3:"ᅬ";s:3:"ㅛ";s:3:"ᅭ";s:3:"ㅜ";s:3:"ᅮ";s:3:"ㅝ";s:3:"ᅯ";s:3:"ㅞ";s:3:"ᅰ";s:3:"ㅟ";s:3:"ᅱ";s:3:"ㅠ";s:3:"ᅲ";s:3:"ㅡ";s:3:"ᅳ";s:3:"ㅢ";s:3:"ᅴ";s:3:"ㅣ";s:3:"ᅵ";s:3:"ㅤ";s:3:"ᅠ";s:3:"ㅥ";s:3:"ᄔ";s:3:"ㅦ";s:3:"ᄕ";s:3:"ㅧ";s:3:"ᇇ";s:3:"ㅨ";s:3:"ᇈ";s:3:"ㅩ";s:3:"ᇌ";s:3:"ㅪ";s:3:"ᇎ";s:3:"ㅫ";s:3:"ᇓ";s:3:"ㅬ";s:3:"ᇗ";s:3:"ㅭ";s:3:"ᇙ";s:3:"ㅮ";s:3:"ᄜ";s:3:"ㅯ";s:3:"ᇝ";s:3:"ㅰ";s:3:"ᇟ";s:3:"ㅱ";s:3:"ᄝ";s:3:"ㅲ";s:3:"ᄞ";s:3:"ㅳ";s:3:"ᄠ";s:3:"ㅴ";s:3:"ᄢ";s:3:"ㅵ";s:3:"ᄣ";s:3:"ㅶ";s:3:"ᄧ";s:3:"ㅷ";s:3:"ᄩ";s:3:"ㅸ";s:3:"ᄫ";s:3:"ㅹ";s:3:"ᄬ";s:3:"ㅺ";s:3:"ᄭ";s:3:"ㅻ";s:3:"ᄮ";s:3:"ㅼ";s:3:"ᄯ";s:3:"ㅽ";s:3:"ᄲ";s:3:"ㅾ";s:3:"ᄶ";s:3:"ㅿ";s:3:"ᅀ";s:3:"ㆀ";s:3:"ᅇ";s:3:"ㆁ";s:3:"ᅌ";s:3:"ㆂ";s:3:"ᇱ";s:3:"ㆃ";s:3:"ᇲ";s:3:"ㆄ";s:3:"ᅗ";s:3:"ㆅ";s:3:"ᅘ";s:3:"ㆆ";s:3:"ᅙ";s:3:"ㆇ";s:3:"ᆄ";s:3:"ㆈ";s:3:"ᆅ";s:3:"ㆉ";s:3:"ᆈ";s:3:"ㆊ";s:3:"ᆑ";s:3:"ㆋ";s:3:"ᆒ";s:3:"ㆌ";s:3:"ᆔ";s:3:"ㆍ";s:3:"ᆞ";s:3:"ㆎ";s:3:"ᆡ";s:3:"㆒";s:3:"一";s:3:"㆓";s:3:"二";s:3:"㆔";s:3:"三";s:3:"㆕";s:3:"四";s:3:"㆖";s:3:"上";s:3:"㆗";s:3:"中";s:3:"㆘";s:3:"下";s:3:"㆙";s:3:"甲";s:3:"㆚";s:3:"乙";s:3:"㆛";s:3:"丙";s:3:"㆜";s:3:"丁";s:3:"㆝";s:3:"天";s:3:"㆞";s:3:"地";s:3:"㆟";s:3:"人";s:3:"㈀";s:5:"(ᄀ)";s:3:"㈁";s:5:"(ᄂ)";s:3:"㈂";s:5:"(ᄃ)";s:3:"㈃";s:5:"(ᄅ)";s:3:"㈄";s:5:"(ᄆ)";s:3:"㈅";s:5:"(ᄇ)";s:3:"㈆";s:5:"(ᄉ)";s:3:"㈇";s:5:"(ᄋ)";s:3:"㈈";s:5:"(ᄌ)";s:3:"㈉";s:5:"(ᄎ)";s:3:"㈊";s:5:"(ᄏ)";s:3:"㈋";s:5:"(ᄐ)";s:3:"㈌";s:5:"(ᄑ)";s:3:"㈍";s:5:"(ᄒ)";s:3:"㈎";s:8:"(가)";s:3:"㈏";s:8:"(나)";s:3:"㈐";s:8:"(다)";s:3:"㈑";s:8:"(라)";s:3:"㈒";s:8:"(마)";s:3:"㈓";s:8:"(바)";s:3:"㈔";s:8:"(사)";s:3:"㈕";s:8:"(아)";s:3:"㈖";s:8:"(자)";s:3:"㈗";s:8:"(차)";s:3:"㈘";s:8:"(카)";s:3:"㈙";s:8:"(타)";s:3:"㈚";s:8:"(파)";s:3:"㈛";s:8:"(하)";s:3:"㈜";s:8:"(주)";s:3:"㈝";s:17:"(오전)";s:3:"㈞";s:14:"(오후)";s:3:"㈠";s:5:"(一)";s:3:"㈡";s:5:"(二)";s:3:"㈢";s:5:"(三)";s:3:"㈣";s:5:"(四)";s:3:"㈤";s:5:"(五)";s:3:"㈥";s:5:"(六)";s:3:"㈦";s:5:"(七)";s:3:"㈧";s:5:"(八)";s:3:"㈨";s:5:"(九)";s:3:"㈩";s:5:"(十)";s:3:"㈪";s:5:"(月)";s:3:"㈫";s:5:"(火)";s:3:"㈬";s:5:"(水)";s:3:"㈭";s:5:"(木)";s:3:"㈮";s:5:"(金)";s:3:"㈯";s:5:"(土)";s:3:"㈰";s:5:"(日)";s:3:"㈱";s:5:"(株)";s:3:"㈲";s:5:"(有)";s:3:"㈳";s:5:"(社)";s:3:"㈴";s:5:"(名)";s:3:"㈵";s:5:"(特)";s:3:"㈶";s:5:"(財)";s:3:"㈷";s:5:"(祝)";s:3:"㈸";s:5:"(労)";s:3:"㈹";s:5:"(代)";s:3:"㈺";s:5:"(呼)";s:3:"㈻";s:5:"(学)";s:3:"㈼";s:5:"(監)";s:3:"㈽";s:5:"(企)";s:3:"㈾";s:5:"(資)";s:3:"㈿";s:5:"(協)";s:3:"㉀";s:5:"(祭)";s:3:"㉁";s:5:"(休)";s:3:"㉂";s:5:"(自)";s:3:"㉃";s:5:"(至)";s:3:"㉐";s:3:"PTE";s:3:"㉑";s:2:"21";s:3:"㉒";s:2:"22";s:3:"㉓";s:2:"23";s:3:"㉔";s:2:"24";s:3:"㉕";s:2:"25";s:3:"㉖";s:2:"26";s:3:"㉗";s:2:"27";s:3:"㉘";s:2:"28";s:3:"㉙";s:2:"29";s:3:"㉚";s:2:"30";s:3:"㉛";s:2:"31";s:3:"㉜";s:2:"32";s:3:"㉝";s:2:"33";s:3:"㉞";s:2:"34";s:3:"㉟";s:2:"35";s:3:"㉠";s:3:"ᄀ";s:3:"㉡";s:3:"ᄂ";s:3:"㉢";s:3:"ᄃ";s:3:"㉣";s:3:"ᄅ";s:3:"㉤";s:3:"ᄆ";s:3:"㉥";s:3:"ᄇ";s:3:"㉦";s:3:"ᄉ";s:3:"㉧";s:3:"ᄋ";s:3:"㉨";s:3:"ᄌ";s:3:"㉩";s:3:"ᄎ";s:3:"㉪";s:3:"ᄏ";s:3:"㉫";s:3:"ᄐ";s:3:"㉬";s:3:"ᄑ";s:3:"㉭";s:3:"ᄒ";s:3:"㉮";s:6:"가";s:3:"㉯";s:6:"나";s:3:"㉰";s:6:"다";s:3:"㉱";s:6:"라";s:3:"㉲";s:6:"마";s:3:"㉳";s:6:"바";s:3:"㉴";s:6:"사";s:3:"㉵";s:6:"아";s:3:"㉶";s:6:"자";s:3:"㉷";s:6:"차";s:3:"㉸";s:6:"카";s:3:"㉹";s:6:"타";s:3:"㉺";s:6:"파";s:3:"㉻";s:6:"하";s:3:"㉼";s:15:"참고";s:3:"㉽";s:12:"주의";s:3:"㉾";s:6:"우";s:3:"㊀";s:3:"一";s:3:"㊁";s:3:"二";s:3:"㊂";s:3:"三";s:3:"㊃";s:3:"四";s:3:"㊄";s:3:"五";s:3:"㊅";s:3:"六";s:3:"㊆";s:3:"七";s:3:"㊇";s:3:"八";s:3:"㊈";s:3:"九";s:3:"㊉";s:3:"十";s:3:"㊊";s:3:"月";s:3:"㊋";s:3:"火";s:3:"㊌";s:3:"水";s:3:"㊍";s:3:"木";s:3:"㊎";s:3:"金";s:3:"㊏";s:3:"土";s:3:"㊐";s:3:"日";s:3:"㊑";s:3:"株";s:3:"㊒";s:3:"有";s:3:"㊓";s:3:"社";s:3:"㊔";s:3:"名";s:3:"㊕";s:3:"特";s:3:"㊖";s:3:"財";s:3:"㊗";s:3:"祝";s:3:"㊘";s:3:"労";s:3:"㊙";s:3:"秘";s:3:"㊚";s:3:"男";s:3:"㊛";s:3:"女";s:3:"㊜";s:3:"適";s:3:"㊝";s:3:"優";s:3:"㊞";s:3:"印";s:3:"㊟";s:3:"注";s:3:"㊠";s:3:"項";s:3:"㊡";s:3:"休";s:3:"㊢";s:3:"写";s:3:"㊣";s:3:"正";s:3:"㊤";s:3:"上";s:3:"㊥";s:3:"中";s:3:"㊦";s:3:"下";s:3:"㊧";s:3:"左";s:3:"㊨";s:3:"右";s:3:"㊩";s:3:"医";s:3:"㊪";s:3:"宗";s:3:"㊫";s:3:"学";s:3:"㊬";s:3:"監";s:3:"㊭";s:3:"企";s:3:"㊮";s:3:"資";s:3:"㊯";s:3:"協";s:3:"㊰";s:3:"夜";s:3:"㊱";s:2:"36";s:3:"㊲";s:2:"37";s:3:"㊳";s:2:"38";s:3:"㊴";s:2:"39";s:3:"㊵";s:2:"40";s:3:"㊶";s:2:"41";s:3:"㊷";s:2:"42";s:3:"㊸";s:2:"43";s:3:"㊹";s:2:"44";s:3:"㊺";s:2:"45";s:3:"㊻";s:2:"46";s:3:"㊼";s:2:"47";s:3:"㊽";s:2:"48";s:3:"㊾";s:2:"49";s:3:"㊿";s:2:"50";s:3:"㋀";s:4:"1月";s:3:"㋁";s:4:"2月";s:3:"㋂";s:4:"3月";s:3:"㋃";s:4:"4月";s:3:"㋄";s:4:"5月";s:3:"㋅";s:4:"6月";s:3:"㋆";s:4:"7月";s:3:"㋇";s:4:"8月";s:3:"㋈";s:4:"9月";s:3:"㋉";s:5:"10月";s:3:"㋊";s:5:"11月";s:3:"㋋";s:5:"12月";s:3:"㋌";s:2:"Hg";s:3:"㋍";s:3:"erg";s:3:"㋎";s:2:"eV";s:3:"㋏";s:3:"LTD";s:3:"㋐";s:3:"ア";s:3:"㋑";s:3:"イ";s:3:"㋒";s:3:"ウ";s:3:"㋓";s:3:"エ";s:3:"㋔";s:3:"オ";s:3:"㋕";s:3:"カ";s:3:"㋖";s:3:"キ";s:3:"㋗";s:3:"ク";s:3:"㋘";s:3:"ケ";s:3:"㋙";s:3:"コ";s:3:"㋚";s:3:"サ";s:3:"㋛";s:3:"シ";s:3:"㋜";s:3:"ス";s:3:"㋝";s:3:"セ";s:3:"㋞";s:3:"ソ";s:3:"㋟";s:3:"タ";s:3:"㋠";s:3:"チ";s:3:"㋡";s:3:"ツ";s:3:"㋢";s:3:"テ";s:3:"㋣";s:3:"ト";s:3:"㋤";s:3:"ナ";s:3:"㋥";s:3:"ニ";s:3:"㋦";s:3:"ヌ";s:3:"㋧";s:3:"ネ";s:3:"㋨";s:3:"ノ";s:3:"㋩";s:3:"ハ";s:3:"㋪";s:3:"ヒ";s:3:"㋫";s:3:"フ";s:3:"㋬";s:3:"ヘ";s:3:"㋭";s:3:"ホ";s:3:"㋮";s:3:"マ";s:3:"㋯";s:3:"ミ";s:3:"㋰";s:3:"ム";s:3:"㋱";s:3:"メ";s:3:"㋲";s:3:"モ";s:3:"㋳";s:3:"ヤ";s:3:"㋴";s:3:"ユ";s:3:"㋵";s:3:"ヨ";s:3:"㋶";s:3:"ラ";s:3:"㋷";s:3:"リ";s:3:"㋸";s:3:"ル";s:3:"㋹";s:3:"レ";s:3:"㋺";s:3:"ロ";s:3:"㋻";s:3:"ワ";s:3:"㋼";s:3:"ヰ";s:3:"㋽";s:3:"ヱ";s:3:"㋾";s:3:"ヲ";s:3:"㌀";s:15:"アパート";s:3:"㌁";s:12:"アルファ";s:3:"㌂";s:15:"アンペア";s:3:"㌃";s:9:"アール";s:3:"㌄";s:15:"イニング";s:3:"㌅";s:9:"インチ";s:3:"㌆";s:9:"ウォン";s:3:"㌇";s:18:"エスクード";s:3:"㌈";s:12:"エーカー";s:3:"㌉";s:9:"オンス";s:3:"㌊";s:9:"オーム";s:3:"㌋";s:9:"カイリ";s:3:"㌌";s:12:"カラット";s:3:"㌍";s:12:"カロリー";s:3:"㌎";s:12:"ガロン";s:3:"㌏";s:12:"ガンマ";s:3:"㌐";s:12:"ギガ";s:3:"㌑";s:12:"ギニー";s:3:"㌒";s:12:"キュリー";s:3:"㌓";s:18:"ギルダー";s:3:"㌔";s:6:"キロ";s:3:"㌕";s:18:"キログラム";s:3:"㌖";s:18:"キロメートル";s:3:"㌗";s:15:"キロワット";s:3:"㌘";s:12:"グラム";s:3:"㌙";s:18:"グラムトン";s:3:"㌚";s:18:"クルゼイロ";s:3:"㌛";s:12:"クローネ";s:3:"㌜";s:9:"ケース";s:3:"㌝";s:9:"コルナ";s:3:"㌞";s:12:"コーポ";s:3:"㌟";s:12:"サイクル";s:3:"㌠";s:15:"サンチーム";s:3:"㌡";s:15:"シリング";s:3:"㌢";s:9:"センチ";s:3:"㌣";s:9:"セント";s:3:"㌤";s:12:"ダース";s:3:"㌥";s:9:"デシ";s:3:"㌦";s:9:"ドル";s:3:"㌧";s:6:"トン";s:3:"㌨";s:6:"ナノ";s:3:"㌩";s:9:"ノット";s:3:"㌪";s:9:"ハイツ";s:3:"㌫";s:18:"パーセント";s:3:"㌬";s:12:"パーツ";s:3:"㌭";s:15:"バーレル";s:3:"㌮";s:18:"ピアストル";s:3:"㌯";s:12:"ピクル";s:3:"㌰";s:9:"ピコ";s:3:"㌱";s:9:"ビル";s:3:"㌲";s:18:"ファラッド";s:3:"㌳";s:12:"フィート";s:3:"㌴";s:18:"ブッシェル";s:3:"㌵";s:9:"フラン";s:3:"㌶";s:15:"ヘクタール";s:3:"㌷";s:9:"ペソ";s:3:"㌸";s:12:"ペニヒ";s:3:"㌹";s:9:"ヘルツ";s:3:"㌺";s:12:"ペンス";s:3:"㌻";s:15:"ページ";s:3:"㌼";s:12:"ベータ";s:3:"㌽";s:15:"ポイント";s:3:"㌾";s:12:"ボルト";s:3:"㌿";s:6:"ホン";s:3:"㍀";s:15:"ポンド";s:3:"㍁";s:9:"ホール";s:3:"㍂";s:9:"ホーン";s:3:"㍃";s:12:"マイクロ";s:3:"㍄";s:9:"マイル";s:3:"㍅";s:9:"マッハ";s:3:"㍆";s:9:"マルク";s:3:"㍇";s:15:"マンション";s:3:"㍈";s:12:"ミクロン";s:3:"㍉";s:6:"ミリ";s:3:"㍊";s:18:"ミリバール";s:3:"㍋";s:9:"メガ";s:3:"㍌";s:15:"メガトン";s:3:"㍍";s:12:"メートル";s:3:"㍎";s:12:"ヤード";s:3:"㍏";s:9:"ヤール";s:3:"㍐";s:9:"ユアン";s:3:"㍑";s:12:"リットル";s:3:"㍒";s:6:"リラ";s:3:"㍓";s:12:"ルピー";s:3:"㍔";s:15:"ルーブル";s:3:"㍕";s:6:"レム";s:3:"㍖";s:18:"レントゲン";s:3:"㍗";s:9:"ワット";s:3:"㍘";s:4:"0点";s:3:"㍙";s:4:"1点";s:3:"㍚";s:4:"2点";s:3:"㍛";s:4:"3点";s:3:"㍜";s:4:"4点";s:3:"㍝";s:4:"5点";s:3:"㍞";s:4:"6点";s:3:"㍟";s:4:"7点";s:3:"㍠";s:4:"8点";s:3:"㍡";s:4:"9点";s:3:"㍢";s:5:"10点";s:3:"㍣";s:5:"11点";s:3:"㍤";s:5:"12点";s:3:"㍥";s:5:"13点";s:3:"㍦";s:5:"14点";s:3:"㍧";s:5:"15点";s:3:"㍨";s:5:"16点";s:3:"㍩";s:5:"17点";s:3:"㍪";s:5:"18点";s:3:"㍫";s:5:"19点";s:3:"㍬";s:5:"20点";s:3:"㍭";s:5:"21点";s:3:"㍮";s:5:"22点";s:3:"㍯";s:5:"23点";s:3:"㍰";s:5:"24点";s:3:"㍱";s:3:"hPa";s:3:"㍲";s:2:"da";s:3:"㍳";s:2:"AU";s:3:"㍴";s:3:"bar";s:3:"㍵";s:2:"oV";s:3:"㍶";s:2:"pc";s:3:"㍷";s:2:"dm";s:3:"㍸";s:3:"dm2";s:3:"㍹";s:3:"dm3";s:3:"㍺";s:2:"IU";s:3:"㍻";s:6:"平成";s:3:"㍼";s:6:"昭和";s:3:"㍽";s:6:"大正";s:3:"㍾";s:6:"明治";s:3:"㍿";s:12:"株式会社";s:3:"㎀";s:2:"pA";s:3:"㎁";s:2:"nA";s:3:"㎂";s:3:"μA";s:3:"㎃";s:2:"mA";s:3:"㎄";s:2:"kA";s:3:"㎅";s:2:"KB";s:3:"㎆";s:2:"MB";s:3:"㎇";s:2:"GB";s:3:"㎈";s:3:"cal";s:3:"㎉";s:4:"kcal";s:3:"㎊";s:2:"pF";s:3:"㎋";s:2:"nF";s:3:"㎌";s:3:"μF";s:3:"㎍";s:3:"μg";s:3:"㎎";s:2:"mg";s:3:"㎏";s:2:"kg";s:3:"㎐";s:2:"Hz";s:3:"㎑";s:3:"kHz";s:3:"㎒";s:3:"MHz";s:3:"㎓";s:3:"GHz";s:3:"㎔";s:3:"THz";s:3:"㎕";s:3:"μl";s:3:"㎖";s:2:"ml";s:3:"㎗";s:2:"dl";s:3:"㎘";s:2:"kl";s:3:"㎙";s:2:"fm";s:3:"㎚";s:2:"nm";s:3:"㎛";s:3:"μm";s:3:"㎜";s:2:"mm";s:3:"㎝";s:2:"cm";s:3:"㎞";s:2:"km";s:3:"㎟";s:3:"mm2";s:3:"㎠";s:3:"cm2";s:3:"㎡";s:2:"m2";s:3:"㎢";s:3:"km2";s:3:"㎣";s:3:"mm3";s:3:"㎤";s:3:"cm3";s:3:"㎥";s:2:"m3";s:3:"㎦";s:3:"km3";s:3:"㎧";s:5:"m∕s";s:3:"㎨";s:6:"m∕s2";s:3:"㎩";s:2:"Pa";s:3:"㎪";s:3:"kPa";s:3:"㎫";s:3:"MPa";s:3:"㎬";s:3:"GPa";s:3:"㎭";s:3:"rad";s:3:"㎮";s:7:"rad∕s";s:3:"㎯";s:8:"rad∕s2";s:3:"㎰";s:2:"ps";s:3:"㎱";s:2:"ns";s:3:"㎲";s:3:"μs";s:3:"㎳";s:2:"ms";s:3:"㎴";s:2:"pV";s:3:"㎵";s:2:"nV";s:3:"㎶";s:3:"μV";s:3:"㎷";s:2:"mV";s:3:"㎸";s:2:"kV";s:3:"㎹";s:2:"MV";s:3:"㎺";s:2:"pW";s:3:"㎻";s:2:"nW";s:3:"㎼";s:3:"μW";s:3:"㎽";s:2:"mW";s:3:"㎾";s:2:"kW";s:3:"㎿";s:2:"MW";s:3:"㏀";s:3:"kΩ";s:3:"㏁";s:3:"MΩ";s:3:"㏂";s:4:"a.m.";s:3:"㏃";s:2:"Bq";s:3:"㏄";s:2:"cc";s:3:"㏅";s:2:"cd";s:3:"㏆";s:6:"C∕kg";s:3:"㏇";s:3:"Co.";s:3:"㏈";s:2:"dB";s:3:"㏉";s:2:"Gy";s:3:"㏊";s:2:"ha";s:3:"㏋";s:2:"HP";s:3:"㏌";s:2:"in";s:3:"㏍";s:2:"KK";s:3:"㏎";s:2:"KM";s:3:"㏏";s:2:"kt";s:3:"㏐";s:2:"lm";s:3:"㏑";s:2:"ln";s:3:"㏒";s:3:"log";s:3:"㏓";s:2:"lx";s:3:"㏔";s:2:"mb";s:3:"㏕";s:3:"mil";s:3:"㏖";s:3:"mol";s:3:"㏗";s:2:"PH";s:3:"㏘";s:4:"p.m.";s:3:"㏙";s:3:"PPM";s:3:"㏚";s:2:"PR";s:3:"㏛";s:2:"sr";s:3:"㏜";s:2:"Sv";s:3:"㏝";s:2:"Wb";s:3:"㏞";s:5:"V∕m";s:3:"㏟";s:5:"A∕m";s:3:"㏠";s:4:"1日";s:3:"㏡";s:4:"2日";s:3:"㏢";s:4:"3日";s:3:"㏣";s:4:"4日";s:3:"㏤";s:4:"5日";s:3:"㏥";s:4:"6日";s:3:"㏦";s:4:"7日";s:3:"㏧";s:4:"8日";s:3:"㏨";s:4:"9日";s:3:"㏩";s:5:"10日";s:3:"㏪";s:5:"11日";s:3:"㏫";s:5:"12日";s:3:"㏬";s:5:"13日";s:3:"㏭";s:5:"14日";s:3:"㏮";s:5:"15日";s:3:"㏯";s:5:"16日";s:3:"㏰";s:5:"17日";s:3:"㏱";s:5:"18日";s:3:"㏲";s:5:"19日";s:3:"㏳";s:5:"20日";s:3:"㏴";s:5:"21日";s:3:"㏵";s:5:"22日";s:3:"㏶";s:5:"23日";s:3:"㏷";s:5:"24日";s:3:"㏸";s:5:"25日";s:3:"㏹";s:5:"26日";s:3:"㏺";s:5:"27日";s:3:"㏻";s:5:"28日";s:3:"㏼";s:5:"29日";s:3:"㏽";s:5:"30日";s:3:"㏾";s:5:"31日";s:3:"㏿";s:3:"gal";s:3:"豈";s:3:"豈";s:3:"更";s:3:"更";s:3:"車";s:3:"車";s:3:"賈";s:3:"賈";s:3:"滑";s:3:"滑";s:3:"串";s:3:"串";s:3:"句";s:3:"句";s:3:"龜";s:3:"龜";s:3:"龜";s:3:"龜";s:3:"契";s:3:"契";s:3:"金";s:3:"金";s:3:"喇";s:3:"喇";s:3:"奈";s:3:"奈";s:3:"懶";s:3:"懶";s:3:"癩";s:3:"癩";s:3:"羅";s:3:"羅";s:3:"蘿";s:3:"蘿";s:3:"螺";s:3:"螺";s:3:"裸";s:3:"裸";s:3:"邏";s:3:"邏";s:3:"樂";s:3:"樂";s:3:"洛";s:3:"洛";s:3:"烙";s:3:"烙";s:3:"珞";s:3:"珞";s:3:"落";s:3:"落";s:3:"酪";s:3:"酪";s:3:"駱";s:3:"駱";s:3:"亂";s:3:"亂";s:3:"卵";s:3:"卵";s:3:"欄";s:3:"欄";s:3:"爛";s:3:"爛";s:3:"蘭";s:3:"蘭";s:3:"鸞";s:3:"鸞";s:3:"嵐";s:3:"嵐";s:3:"濫";s:3:"濫";s:3:"藍";s:3:"藍";s:3:"襤";s:3:"襤";s:3:"拉";s:3:"拉";s:3:"臘";s:3:"臘";s:3:"蠟";s:3:"蠟";s:3:"廊";s:3:"廊";s:3:"朗";s:3:"朗";s:3:"浪";s:3:"浪";s:3:"狼";s:3:"狼";s:3:"郎";s:3:"郎";s:3:"來";s:3:"來";s:3:"冷";s:3:"冷";s:3:"勞";s:3:"勞";s:3:"擄";s:3:"擄";s:3:"櫓";s:3:"櫓";s:3:"爐";s:3:"爐";s:3:"盧";s:3:"盧";s:3:"老";s:3:"老";s:3:"蘆";s:3:"蘆";s:3:"虜";s:3:"虜";s:3:"路";s:3:"路";s:3:"露";s:3:"露";s:3:"魯";s:3:"魯";s:3:"鷺";s:3:"鷺";s:3:"碌";s:3:"碌";s:3:"祿";s:3:"祿";s:3:"綠";s:3:"綠";s:3:"菉";s:3:"菉";s:3:"錄";s:3:"錄";s:3:"鹿";s:3:"鹿";s:3:"論";s:3:"論";s:3:"壟";s:3:"壟";s:3:"弄";s:3:"弄";s:3:"籠";s:3:"籠";s:3:"聾";s:3:"聾";s:3:"牢";s:3:"牢";s:3:"磊";s:3:"磊";s:3:"賂";s:3:"賂";s:3:"雷";s:3:"雷";s:3:"壘";s:3:"壘";s:3:"屢";s:3:"屢";s:3:"樓";s:3:"樓";s:3:"淚";s:3:"淚";s:3:"漏";s:3:"漏";s:3:"累";s:3:"累";s:3:"縷";s:3:"縷";s:3:"陋";s:3:"陋";s:3:"勒";s:3:"勒";s:3:"肋";s:3:"肋";s:3:"凜";s:3:"凜";s:3:"凌";s:3:"凌";s:3:"稜";s:3:"稜";s:3:"綾";s:3:"綾";s:3:"菱";s:3:"菱";s:3:"陵";s:3:"陵";s:3:"讀";s:3:"讀";s:3:"拏";s:3:"拏";s:3:"樂";s:3:"樂";s:3:"諾";s:3:"諾";s:3:"丹";s:3:"丹";s:3:"寧";s:3:"寧";s:3:"怒";s:3:"怒";s:3:"率";s:3:"率";s:3:"異";s:3:"異";s:3:"北";s:3:"北";s:3:"磻";s:3:"磻";s:3:"便";s:3:"便";s:3:"復";s:3:"復";s:3:"不";s:3:"不";s:3:"泌";s:3:"泌";s:3:"數";s:3:"數";s:3:"索";s:3:"索";s:3:"參";s:3:"參";s:3:"塞";s:3:"塞";s:3:"省";s:3:"省";s:3:"葉";s:3:"葉";s:3:"說";s:3:"說";s:3:"殺";s:3:"殺";s:3:"辰";s:3:"辰";s:3:"沈";s:3:"沈";s:3:"拾";s:3:"拾";s:3:"若";s:3:"若";s:3:"掠";s:3:"掠";s:3:"略";s:3:"略";s:3:"亮";s:3:"亮";s:3:"兩";s:3:"兩";s:3:"凉";s:3:"凉";s:3:"梁";s:3:"梁";s:3:"糧";s:3:"糧";s:3:"良";s:3:"良";s:3:"諒";s:3:"諒";s:3:"量";s:3:"量";s:3:"勵";s:3:"勵";s:3:"呂";s:3:"呂";s:3:"女";s:3:"女";s:3:"廬";s:3:"廬";s:3:"旅";s:3:"旅";s:3:"濾";s:3:"濾";s:3:"礪";s:3:"礪";s:3:"閭";s:3:"閭";s:3:"驪";s:3:"驪";s:3:"麗";s:3:"麗";s:3:"黎";s:3:"黎";s:3:"力";s:3:"力";s:3:"曆";s:3:"曆";s:3:"歷";s:3:"歷";s:3:"轢";s:3:"轢";s:3:"年";s:3:"年";s:3:"憐";s:3:"憐";s:3:"戀";s:3:"戀";s:3:"撚";s:3:"撚";s:3:"漣";s:3:"漣";s:3:"煉";s:3:"煉";s:3:"璉";s:3:"璉";s:3:"秊";s:3:"秊";s:3:"練";s:3:"練";s:3:"聯";s:3:"聯";s:3:"輦";s:3:"輦";s:3:"蓮";s:3:"蓮";s:3:"連";s:3:"連";s:3:"鍊";s:3:"鍊";s:3:"列";s:3:"列";s:3:"劣";s:3:"劣";s:3:"咽";s:3:"咽";s:3:"烈";s:3:"烈";s:3:"裂";s:3:"裂";s:3:"說";s:3:"說";s:3:"廉";s:3:"廉";s:3:"念";s:3:"念";s:3:"捻";s:3:"捻";s:3:"殮";s:3:"殮";s:3:"簾";s:3:"簾";s:3:"獵";s:3:"獵";s:3:"令";s:3:"令";s:3:"囹";s:3:"囹";s:3:"寧";s:3:"寧";s:3:"嶺";s:3:"嶺";s:3:"怜";s:3:"怜";s:3:"玲";s:3:"玲";s:3:"瑩";s:3:"瑩";s:3:"羚";s:3:"羚";s:3:"聆";s:3:"聆";s:3:"鈴";s:3:"鈴";s:3:"零";s:3:"零";s:3:"靈";s:3:"靈";s:3:"領";s:3:"領";s:3:"例";s:3:"例";s:3:"禮";s:3:"禮";s:3:"醴";s:3:"醴";s:3:"隸";s:3:"隸";s:3:"惡";s:3:"惡";s:3:"了";s:3:"了";s:3:"僚";s:3:"僚";s:3:"寮";s:3:"寮";s:3:"尿";s:3:"尿";s:3:"料";s:3:"料";s:3:"樂";s:3:"樂";s:3:"燎";s:3:"燎";s:3:"療";s:3:"療";s:3:"蓼";s:3:"蓼";s:3:"遼";s:3:"遼";s:3:"龍";s:3:"龍";s:3:"暈";s:3:"暈";s:3:"阮";s:3:"阮";s:3:"劉";s:3:"劉";s:3:"杻";s:3:"杻";s:3:"柳";s:3:"柳";s:3:"流";s:3:"流";s:3:"溜";s:3:"溜";s:3:"琉";s:3:"琉";s:3:"留";s:3:"留";s:3:"硫";s:3:"硫";s:3:"紐";s:3:"紐";s:3:"類";s:3:"類";s:3:"六";s:3:"六";s:3:"戮";s:3:"戮";s:3:"陸";s:3:"陸";s:3:"倫";s:3:"倫";s:3:"崙";s:3:"崙";s:3:"淪";s:3:"淪";s:3:"輪";s:3:"輪";s:3:"律";s:3:"律";s:3:"慄";s:3:"慄";s:3:"栗";s:3:"栗";s:3:"率";s:3:"率";s:3:"隆";s:3:"隆";s:3:"利";s:3:"利";s:3:"吏";s:3:"吏";s:3:"履";s:3:"履";s:3:"易";s:3:"易";s:3:"李";s:3:"李";s:3:"梨";s:3:"梨";s:3:"泥";s:3:"泥";s:3:"理";s:3:"理";s:3:"痢";s:3:"痢";s:3:"罹";s:3:"罹";s:3:"裏";s:3:"裏";s:3:"裡";s:3:"裡";s:3:"里";s:3:"里";s:3:"離";s:3:"離";s:3:"匿";s:3:"匿";s:3:"溺";s:3:"溺";s:3:"吝";s:3:"吝";s:3:"燐";s:3:"燐";s:3:"璘";s:3:"璘";s:3:"藺";s:3:"藺";s:3:"隣";s:3:"隣";s:3:"鱗";s:3:"鱗";s:3:"麟";s:3:"麟";s:3:"林";s:3:"林";s:3:"淋";s:3:"淋";s:3:"臨";s:3:"臨";s:3:"立";s:3:"立";s:3:"笠";s:3:"笠";s:3:"粒";s:3:"粒";s:3:"狀";s:3:"狀";s:3:"炙";s:3:"炙";s:3:"識";s:3:"識";s:3:"什";s:3:"什";s:3:"茶";s:3:"茶";s:3:"刺";s:3:"刺";s:3:"切";s:3:"切";s:3:"度";s:3:"度";s:3:"拓";s:3:"拓";s:3:"糖";s:3:"糖";s:3:"宅";s:3:"宅";s:3:"洞";s:3:"洞";s:3:"暴";s:3:"暴";s:3:"輻";s:3:"輻";s:3:"行";s:3:"行";s:3:"降";s:3:"降";s:3:"見";s:3:"見";s:3:"廓";s:3:"廓";s:3:"兀";s:3:"兀";s:3:"嗀";s:3:"嗀";s:3:"塚";s:3:"塚";s:3:"晴";s:3:"晴";s:3:"凞";s:3:"凞";s:3:"猪";s:3:"猪";s:3:"益";s:3:"益";s:3:"礼";s:3:"礼";s:3:"神";s:3:"神";s:3:"祥";s:3:"祥";s:3:"福";s:3:"福";s:3:"靖";s:3:"靖";s:3:"精";s:3:"精";s:3:"羽";s:3:"羽";s:3:"蘒";s:3:"蘒";s:3:"諸";s:3:"諸";s:3:"逸";s:3:"逸";s:3:"都";s:3:"都";s:3:"飯";s:3:"飯";s:3:"飼";s:3:"飼";s:3:"館";s:3:"館";s:3:"鶴";s:3:"鶴";s:3:"侮";s:3:"侮";s:3:"僧";s:3:"僧";s:3:"免";s:3:"免";s:3:"勉";s:3:"勉";s:3:"勤";s:3:"勤";s:3:"卑";s:3:"卑";s:3:"喝";s:3:"喝";s:3:"嘆";s:3:"嘆";s:3:"器";s:3:"器";s:3:"塀";s:3:"塀";s:3:"墨";s:3:"墨";s:3:"層";s:3:"層";s:3:"屮";s:3:"屮";s:3:"悔";s:3:"悔";s:3:"慨";s:3:"慨";s:3:"憎";s:3:"憎";s:3:"懲";s:3:"懲";s:3:"敏";s:3:"敏";s:3:"既";s:3:"既";s:3:"暑";s:3:"暑";s:3:"梅";s:3:"梅";s:3:"海";s:3:"海";s:3:"渚";s:3:"渚";s:3:"漢";s:3:"漢";s:3:"煮";s:3:"煮";s:3:"爫";s:3:"爫";s:3:"琢";s:3:"琢";s:3:"碑";s:3:"碑";s:3:"社";s:3:"社";s:3:"祉";s:3:"祉";s:3:"祈";s:3:"祈";s:3:"祐";s:3:"祐";s:3:"祖";s:3:"祖";s:3:"祝";s:3:"祝";s:3:"禍";s:3:"禍";s:3:"禎";s:3:"禎";s:3:"穀";s:3:"穀";s:3:"突";s:3:"突";s:3:"節";s:3:"節";s:3:"練";s:3:"練";s:3:"縉";s:3:"縉";s:3:"繁";s:3:"繁";s:3:"署";s:3:"署";s:3:"者";s:3:"者";s:3:"臭";s:3:"臭";s:3:"艹";s:3:"艹";s:3:"艹";s:3:"艹";s:3:"著";s:3:"著";s:3:"褐";s:3:"褐";s:3:"視";s:3:"視";s:3:"謁";s:3:"謁";s:3:"謹";s:3:"謹";s:3:"賓";s:3:"賓";s:3:"贈";s:3:"贈";s:3:"辶";s:3:"辶";s:3:"逸";s:3:"逸";s:3:"難";s:3:"難";s:3:"響";s:3:"響";s:3:"頻";s:3:"頻";s:3:"並";s:3:"並";s:3:"况";s:3:"况";s:3:"全";s:3:"全";s:3:"侀";s:3:"侀";s:3:"充";s:3:"充";s:3:"冀";s:3:"冀";s:3:"勇";s:3:"勇";s:3:"勺";s:3:"勺";s:3:"喝";s:3:"喝";s:3:"啕";s:3:"啕";s:3:"喙";s:3:"喙";s:3:"嗢";s:3:"嗢";s:3:"塚";s:3:"塚";s:3:"墳";s:3:"墳";s:3:"奄";s:3:"奄";s:3:"奔";s:3:"奔";s:3:"婢";s:3:"婢";s:3:"嬨";s:3:"嬨";s:3:"廒";s:3:"廒";s:3:"廙";s:3:"廙";s:3:"彩";s:3:"彩";s:3:"徭";s:3:"徭";s:3:"惘";s:3:"惘";s:3:"慎";s:3:"慎";s:3:"愈";s:3:"愈";s:3:"憎";s:3:"憎";s:3:"慠";s:3:"慠";s:3:"懲";s:3:"懲";s:3:"戴";s:3:"戴";s:3:"揄";s:3:"揄";s:3:"搜";s:3:"搜";s:3:"摒";s:3:"摒";s:3:"敖";s:3:"敖";s:3:"晴";s:3:"晴";s:3:"朗";s:3:"朗";s:3:"望";s:3:"望";s:3:"杖";s:3:"杖";s:3:"歹";s:3:"歹";s:3:"殺";s:3:"殺";s:3:"流";s:3:"流";s:3:"滛";s:3:"滛";s:3:"滋";s:3:"滋";s:3:"漢";s:3:"漢";s:3:"瀞";s:3:"瀞";s:3:"煮";s:3:"煮";s:3:"瞧";s:3:"瞧";s:3:"爵";s:3:"爵";s:3:"犯";s:3:"犯";s:3:"猪";s:3:"猪";s:3:"瑱";s:3:"瑱";s:3:"甆";s:3:"甆";s:3:"画";s:3:"画";s:3:"瘝";s:3:"瘝";s:3:"瘟";s:3:"瘟";s:3:"益";s:3:"益";s:3:"盛";s:3:"盛";s:3:"直";s:3:"直";s:3:"睊";s:3:"睊";s:3:"着";s:3:"着";s:3:"磌";s:3:"磌";s:3:"窱";s:3:"窱";s:3:"節";s:3:"節";s:3:"类";s:3:"类";s:3:"絛";s:3:"絛";s:3:"練";s:3:"練";s:3:"缾";s:3:"缾";s:3:"者";s:3:"者";s:3:"荒";s:3:"荒";s:3:"華";s:3:"華";s:3:"蝹";s:3:"蝹";s:3:"襁";s:3:"襁";s:3:"覆";s:3:"覆";s:3:"視";s:3:"視";s:3:"調";s:3:"調";s:3:"諸";s:3:"諸";s:3:"請";s:3:"請";s:3:"謁";s:3:"謁";s:3:"諾";s:3:"諾";s:3:"諭";s:3:"諭";s:3:"謹";s:3:"謹";s:3:"變";s:3:"變";s:3:"贈";s:3:"贈";s:3:"輸";s:3:"輸";s:3:"遲";s:3:"遲";s:3:"醙";s:3:"醙";s:3:"鉶";s:3:"鉶";s:3:"陼";s:3:"陼";s:3:"難";s:3:"難";s:3:"靖";s:3:"靖";s:3:"韛";s:3:"韛";s:3:"響";s:3:"響";s:3:"頋";s:3:"頋";s:3:"頻";s:3:"頻";s:3:"鬒";s:3:"鬒";s:3:"龜";s:3:"龜";s:3:"𢡊";s:4:"𢡊";s:3:"𢡄";s:4:"𢡄";s:3:"𣏕";s:4:"𣏕";s:3:"㮝";s:3:"㮝";s:3:"䀘";s:3:"䀘";s:3:"䀹";s:3:"䀹";s:3:"𥉉";s:4:"𥉉";s:3:"𥳐";s:4:"𥳐";s:3:"𧻓";s:4:"𧻓";s:3:"齃";s:3:"齃";s:3:"龎";s:3:"龎";s:3:"ff";s:2:"ff";s:3:"fi";s:2:"fi";s:3:"fl";s:2:"fl";s:3:"ffi";s:3:"ffi";s:3:"ffl";s:3:"ffl";s:3:"ſt";s:2:"st";s:3:"st";s:2:"st";s:3:"ﬓ";s:4:"մն";s:3:"ﬔ";s:4:"մե";s:3:"ﬕ";s:4:"մի";s:3:"ﬖ";s:4:"վն";s:3:"ﬗ";s:4:"մխ";s:3:"יִ";s:4:"יִ";s:3:"ײַ";s:4:"ײַ";s:3:"ﬠ";s:2:"ע";s:3:"ﬡ";s:2:"א";s:3:"ﬢ";s:2:"ד";s:3:"ﬣ";s:2:"ה";s:3:"ﬤ";s:2:"כ";s:3:"ﬥ";s:2:"ל";s:3:"ﬦ";s:2:"ם";s:3:"ﬧ";s:2:"ר";s:3:"ﬨ";s:2:"ת";s:3:"﬩";s:1:"+";s:3:"שׁ";s:4:"שׁ";s:3:"שׂ";s:4:"שׂ";s:3:"שּׁ";s:6:"שּׁ";s:3:"שּׂ";s:6:"שּׂ";s:3:"אַ";s:4:"אַ";s:3:"אָ";s:4:"אָ";s:3:"אּ";s:4:"אּ";s:3:"בּ";s:4:"בּ";s:3:"גּ";s:4:"גּ";s:3:"דּ";s:4:"דּ";s:3:"הּ";s:4:"הּ";s:3:"וּ";s:4:"וּ";s:3:"זּ";s:4:"זּ";s:3:"טּ";s:4:"טּ";s:3:"יּ";s:4:"יּ";s:3:"ךּ";s:4:"ךּ";s:3:"כּ";s:4:"כּ";s:3:"לּ";s:4:"לּ";s:3:"מּ";s:4:"מּ";s:3:"נּ";s:4:"נּ";s:3:"סּ";s:4:"סּ";s:3:"ףּ";s:4:"ףּ";s:3:"פּ";s:4:"פּ";s:3:"צּ";s:4:"צּ";s:3:"קּ";s:4:"קּ";s:3:"רּ";s:4:"רּ";s:3:"שּ";s:4:"שּ";s:3:"תּ";s:4:"תּ";s:3:"וֹ";s:4:"וֹ";s:3:"בֿ";s:4:"בֿ";s:3:"כֿ";s:4:"כֿ";s:3:"פֿ";s:4:"פֿ";s:3:"ﭏ";s:4:"אל";s:3:"ﭐ";s:2:"ٱ";s:3:"ﭑ";s:2:"ٱ";s:3:"ﭒ";s:2:"ٻ";s:3:"ﭓ";s:2:"ٻ";s:3:"ﭔ";s:2:"ٻ";s:3:"ﭕ";s:2:"ٻ";s:3:"ﭖ";s:2:"پ";s:3:"ﭗ";s:2:"پ";s:3:"ﭘ";s:2:"پ";s:3:"ﭙ";s:2:"پ";s:3:"ﭚ";s:2:"ڀ";s:3:"ﭛ";s:2:"ڀ";s:3:"ﭜ";s:2:"ڀ";s:3:"ﭝ";s:2:"ڀ";s:3:"ﭞ";s:2:"ٺ";s:3:"ﭟ";s:2:"ٺ";s:3:"ﭠ";s:2:"ٺ";s:3:"ﭡ";s:2:"ٺ";s:3:"ﭢ";s:2:"ٿ";s:3:"ﭣ";s:2:"ٿ";s:3:"ﭤ";s:2:"ٿ";s:3:"ﭥ";s:2:"ٿ";s:3:"ﭦ";s:2:"ٹ";s:3:"ﭧ";s:2:"ٹ";s:3:"ﭨ";s:2:"ٹ";s:3:"ﭩ";s:2:"ٹ";s:3:"ﭪ";s:2:"ڤ";s:3:"ﭫ";s:2:"ڤ";s:3:"ﭬ";s:2:"ڤ";s:3:"ﭭ";s:2:"ڤ";s:3:"ﭮ";s:2:"ڦ";s:3:"ﭯ";s:2:"ڦ";s:3:"ﭰ";s:2:"ڦ";s:3:"ﭱ";s:2:"ڦ";s:3:"ﭲ";s:2:"ڄ";s:3:"ﭳ";s:2:"ڄ";s:3:"ﭴ";s:2:"ڄ";s:3:"ﭵ";s:2:"ڄ";s:3:"ﭶ";s:2:"ڃ";s:3:"ﭷ";s:2:"ڃ";s:3:"ﭸ";s:2:"ڃ";s:3:"ﭹ";s:2:"ڃ";s:3:"ﭺ";s:2:"چ";s:3:"ﭻ";s:2:"چ";s:3:"ﭼ";s:2:"چ";s:3:"ﭽ";s:2:"چ";s:3:"ﭾ";s:2:"ڇ";s:3:"ﭿ";s:2:"ڇ";s:3:"ﮀ";s:2:"ڇ";s:3:"ﮁ";s:2:"ڇ";s:3:"ﮂ";s:2:"ڍ";s:3:"ﮃ";s:2:"ڍ";s:3:"ﮄ";s:2:"ڌ";s:3:"ﮅ";s:2:"ڌ";s:3:"ﮆ";s:2:"ڎ";s:3:"ﮇ";s:2:"ڎ";s:3:"ﮈ";s:2:"ڈ";s:3:"ﮉ";s:2:"ڈ";s:3:"ﮊ";s:2:"ژ";s:3:"ﮋ";s:2:"ژ";s:3:"ﮌ";s:2:"ڑ";s:3:"ﮍ";s:2:"ڑ";s:3:"ﮎ";s:2:"ک";s:3:"ﮏ";s:2:"ک";s:3:"ﮐ";s:2:"ک";s:3:"ﮑ";s:2:"ک";s:3:"ﮒ";s:2:"گ";s:3:"ﮓ";s:2:"گ";s:3:"ﮔ";s:2:"گ";s:3:"ﮕ";s:2:"گ";s:3:"ﮖ";s:2:"ڳ";s:3:"ﮗ";s:2:"ڳ";s:3:"ﮘ";s:2:"ڳ";s:3:"ﮙ";s:2:"ڳ";s:3:"ﮚ";s:2:"ڱ";s:3:"ﮛ";s:2:"ڱ";s:3:"ﮜ";s:2:"ڱ";s:3:"ﮝ";s:2:"ڱ";s:3:"ﮞ";s:2:"ں";s:3:"ﮟ";s:2:"ں";s:3:"ﮠ";s:2:"ڻ";s:3:"ﮡ";s:2:"ڻ";s:3:"ﮢ";s:2:"ڻ";s:3:"ﮣ";s:2:"ڻ";s:3:"ﮤ";s:4:"ۀ";s:3:"ﮥ";s:4:"ۀ";s:3:"ﮦ";s:2:"ہ";s:3:"ﮧ";s:2:"ہ";s:3:"ﮨ";s:2:"ہ";s:3:"ﮩ";s:2:"ہ";s:3:"ﮪ";s:2:"ھ";s:3:"ﮫ";s:2:"ھ";s:3:"ﮬ";s:2:"ھ";s:3:"ﮭ";s:2:"ھ";s:3:"ﮮ";s:2:"ے";s:3:"ﮯ";s:2:"ے";s:3:"ﮰ";s:4:"ۓ";s:3:"ﮱ";s:4:"ۓ";s:3:"ﯓ";s:2:"ڭ";s:3:"ﯔ";s:2:"ڭ";s:3:"ﯕ";s:2:"ڭ";s:3:"ﯖ";s:2:"ڭ";s:3:"ﯗ";s:2:"ۇ";s:3:"ﯘ";s:2:"ۇ";s:3:"ﯙ";s:2:"ۆ";s:3:"ﯚ";s:2:"ۆ";s:3:"ﯛ";s:2:"ۈ";s:3:"ﯜ";s:2:"ۈ";s:3:"ﯝ";s:4:"ۇٴ";s:3:"ﯞ";s:2:"ۋ";s:3:"ﯟ";s:2:"ۋ";s:3:"ﯠ";s:2:"ۅ";s:3:"ﯡ";s:2:"ۅ";s:3:"ﯢ";s:2:"ۉ";s:3:"ﯣ";s:2:"ۉ";s:3:"ﯤ";s:2:"ې";s:3:"ﯥ";s:2:"ې";s:3:"ﯦ";s:2:"ې";s:3:"ﯧ";s:2:"ې";s:3:"ﯨ";s:2:"ى";s:3:"ﯩ";s:2:"ى";s:3:"ﯪ";s:6:"ئا";s:3:"ﯫ";s:6:"ئا";s:3:"ﯬ";s:6:"ئە";s:3:"ﯭ";s:6:"ئە";s:3:"ﯮ";s:6:"ئو";s:3:"ﯯ";s:6:"ئو";s:3:"ﯰ";s:6:"ئۇ";s:3:"ﯱ";s:6:"ئۇ";s:3:"ﯲ";s:6:"ئۆ";s:3:"ﯳ";s:6:"ئۆ";s:3:"ﯴ";s:6:"ئۈ";s:3:"ﯵ";s:6:"ئۈ";s:3:"ﯶ";s:6:"ئې";s:3:"ﯷ";s:6:"ئې";s:3:"ﯸ";s:6:"ئې";s:3:"ﯹ";s:6:"ئى";s:3:"ﯺ";s:6:"ئى";s:3:"ﯻ";s:6:"ئى";s:3:"ﯼ";s:2:"ی";s:3:"ﯽ";s:2:"ی";s:3:"ﯾ";s:2:"ی";s:3:"ﯿ";s:2:"ی";s:3:"ﰀ";s:6:"ئج";s:3:"ﰁ";s:6:"ئح";s:3:"ﰂ";s:6:"ئم";s:3:"ﰃ";s:6:"ئى";s:3:"ﰄ";s:6:"ئي";s:3:"ﰅ";s:4:"بج";s:3:"ﰆ";s:4:"بح";s:3:"ﰇ";s:4:"بخ";s:3:"ﰈ";s:4:"بم";s:3:"ﰉ";s:4:"بى";s:3:"ﰊ";s:4:"بي";s:3:"ﰋ";s:4:"تج";s:3:"ﰌ";s:4:"تح";s:3:"ﰍ";s:4:"تخ";s:3:"ﰎ";s:4:"تم";s:3:"ﰏ";s:4:"تى";s:3:"ﰐ";s:4:"تي";s:3:"ﰑ";s:4:"ثج";s:3:"ﰒ";s:4:"ثم";s:3:"ﰓ";s:4:"ثى";s:3:"ﰔ";s:4:"ثي";s:3:"ﰕ";s:4:"جح";s:3:"ﰖ";s:4:"جم";s:3:"ﰗ";s:4:"حج";s:3:"ﰘ";s:4:"حم";s:3:"ﰙ";s:4:"خج";s:3:"ﰚ";s:4:"خح";s:3:"ﰛ";s:4:"خم";s:3:"ﰜ";s:4:"سج";s:3:"ﰝ";s:4:"سح";s:3:"ﰞ";s:4:"سخ";s:3:"ﰟ";s:4:"سم";s:3:"ﰠ";s:4:"صح";s:3:"ﰡ";s:4:"صم";s:3:"ﰢ";s:4:"ضج";s:3:"ﰣ";s:4:"ضح";s:3:"ﰤ";s:4:"ضخ";s:3:"ﰥ";s:4:"ضم";s:3:"ﰦ";s:4:"طح";s:3:"ﰧ";s:4:"طم";s:3:"ﰨ";s:4:"ظم";s:3:"ﰩ";s:4:"عج";s:3:"ﰪ";s:4:"عم";s:3:"ﰫ";s:4:"غج";s:3:"ﰬ";s:4:"غم";s:3:"ﰭ";s:4:"فج";s:3:"ﰮ";s:4:"فح";s:3:"ﰯ";s:4:"فخ";s:3:"ﰰ";s:4:"فم";s:3:"ﰱ";s:4:"فى";s:3:"ﰲ";s:4:"في";s:3:"ﰳ";s:4:"قح";s:3:"ﰴ";s:4:"قم";s:3:"ﰵ";s:4:"قى";s:3:"ﰶ";s:4:"قي";s:3:"ﰷ";s:4:"كا";s:3:"ﰸ";s:4:"كج";s:3:"ﰹ";s:4:"كح";s:3:"ﰺ";s:4:"كخ";s:3:"ﰻ";s:4:"كل";s:3:"ﰼ";s:4:"كم";s:3:"ﰽ";s:4:"كى";s:3:"ﰾ";s:4:"كي";s:3:"ﰿ";s:4:"لج";s:3:"ﱀ";s:4:"لح";s:3:"ﱁ";s:4:"لخ";s:3:"ﱂ";s:4:"لم";s:3:"ﱃ";s:4:"لى";s:3:"ﱄ";s:4:"لي";s:3:"ﱅ";s:4:"مج";s:3:"ﱆ";s:4:"مح";s:3:"ﱇ";s:4:"مخ";s:3:"ﱈ";s:4:"مم";s:3:"ﱉ";s:4:"مى";s:3:"ﱊ";s:4:"مي";s:3:"ﱋ";s:4:"نج";s:3:"ﱌ";s:4:"نح";s:3:"ﱍ";s:4:"نخ";s:3:"ﱎ";s:4:"نم";s:3:"ﱏ";s:4:"نى";s:3:"ﱐ";s:4:"ني";s:3:"ﱑ";s:4:"هج";s:3:"ﱒ";s:4:"هم";s:3:"ﱓ";s:4:"هى";s:3:"ﱔ";s:4:"هي";s:3:"ﱕ";s:4:"يج";s:3:"ﱖ";s:4:"يح";s:3:"ﱗ";s:4:"يخ";s:3:"ﱘ";s:4:"يم";s:3:"ﱙ";s:4:"يى";s:3:"ﱚ";s:4:"يي";s:3:"ﱛ";s:4:"ذٰ";s:3:"ﱜ";s:4:"رٰ";s:3:"ﱝ";s:4:"ىٰ";s:3:"ﱞ";s:5:" ٌّ";s:3:"ﱟ";s:5:" ٍّ";s:3:"ﱠ";s:5:" َّ";s:3:"ﱡ";s:5:" ُّ";s:3:"ﱢ";s:5:" ِّ";s:3:"ﱣ";s:5:" ّٰ";s:3:"ﱤ";s:6:"ئر";s:3:"ﱥ";s:6:"ئز";s:3:"ﱦ";s:6:"ئم";s:3:"ﱧ";s:6:"ئن";s:3:"ﱨ";s:6:"ئى";s:3:"ﱩ";s:6:"ئي";s:3:"ﱪ";s:4:"بر";s:3:"ﱫ";s:4:"بز";s:3:"ﱬ";s:4:"بم";s:3:"ﱭ";s:4:"بن";s:3:"ﱮ";s:4:"بى";s:3:"ﱯ";s:4:"بي";s:3:"ﱰ";s:4:"تر";s:3:"ﱱ";s:4:"تز";s:3:"ﱲ";s:4:"تم";s:3:"ﱳ";s:4:"تن";s:3:"ﱴ";s:4:"تى";s:3:"ﱵ";s:4:"تي";s:3:"ﱶ";s:4:"ثر";s:3:"ﱷ";s:4:"ثز";s:3:"ﱸ";s:4:"ثم";s:3:"ﱹ";s:4:"ثن";s:3:"ﱺ";s:4:"ثى";s:3:"ﱻ";s:4:"ثي";s:3:"ﱼ";s:4:"فى";s:3:"ﱽ";s:4:"في";s:3:"ﱾ";s:4:"قى";s:3:"ﱿ";s:4:"قي";s:3:"ﲀ";s:4:"كا";s:3:"ﲁ";s:4:"كل";s:3:"ﲂ";s:4:"كم";s:3:"ﲃ";s:4:"كى";s:3:"ﲄ";s:4:"كي";s:3:"ﲅ";s:4:"لم";s:3:"ﲆ";s:4:"لى";s:3:"ﲇ";s:4:"لي";s:3:"ﲈ";s:4:"ما";s:3:"ﲉ";s:4:"مم";s:3:"ﲊ";s:4:"نر";s:3:"ﲋ";s:4:"نز";s:3:"ﲌ";s:4:"نم";s:3:"ﲍ";s:4:"نن";s:3:"ﲎ";s:4:"نى";s:3:"ﲏ";s:4:"ني";s:3:"ﲐ";s:4:"ىٰ";s:3:"ﲑ";s:4:"ير";s:3:"ﲒ";s:4:"يز";s:3:"ﲓ";s:4:"يم";s:3:"ﲔ";s:4:"ين";s:3:"ﲕ";s:4:"يى";s:3:"ﲖ";s:4:"يي";s:3:"ﲗ";s:6:"ئج";s:3:"ﲘ";s:6:"ئح";s:3:"ﲙ";s:6:"ئخ";s:3:"ﲚ";s:6:"ئم";s:3:"ﲛ";s:6:"ئه";s:3:"ﲜ";s:4:"بج";s:3:"ﲝ";s:4:"بح";s:3:"ﲞ";s:4:"بخ";s:3:"ﲟ";s:4:"بم";s:3:"ﲠ";s:4:"به";s:3:"ﲡ";s:4:"تج";s:3:"ﲢ";s:4:"تح";s:3:"ﲣ";s:4:"تخ";s:3:"ﲤ";s:4:"تم";s:3:"ﲥ";s:4:"ته";s:3:"ﲦ";s:4:"ثم";s:3:"ﲧ";s:4:"جح";s:3:"ﲨ";s:4:"جم";s:3:"ﲩ";s:4:"حج";s:3:"ﲪ";s:4:"حم";s:3:"ﲫ";s:4:"خج";s:3:"ﲬ";s:4:"خم";s:3:"ﲭ";s:4:"سج";s:3:"ﲮ";s:4:"سح";s:3:"ﲯ";s:4:"سخ";s:3:"ﲰ";s:4:"سم";s:3:"ﲱ";s:4:"صح";s:3:"ﲲ";s:4:"صخ";s:3:"ﲳ";s:4:"صم";s:3:"ﲴ";s:4:"ضج";s:3:"ﲵ";s:4:"ضح";s:3:"ﲶ";s:4:"ضخ";s:3:"ﲷ";s:4:"ضم";s:3:"ﲸ";s:4:"طح";s:3:"ﲹ";s:4:"ظم";s:3:"ﲺ";s:4:"عج";s:3:"ﲻ";s:4:"عم";s:3:"ﲼ";s:4:"غج";s:3:"ﲽ";s:4:"غم";s:3:"ﲾ";s:4:"فج";s:3:"ﲿ";s:4:"فح";s:3:"ﳀ";s:4:"فخ";s:3:"ﳁ";s:4:"فم";s:3:"ﳂ";s:4:"قح";s:3:"ﳃ";s:4:"قم";s:3:"ﳄ";s:4:"كج";s:3:"ﳅ";s:4:"كح";s:3:"ﳆ";s:4:"كخ";s:3:"ﳇ";s:4:"كل";s:3:"ﳈ";s:4:"كم";s:3:"ﳉ";s:4:"لج";s:3:"ﳊ";s:4:"لح";s:3:"ﳋ";s:4:"لخ";s:3:"ﳌ";s:4:"لم";s:3:"ﳍ";s:4:"له";s:3:"ﳎ";s:4:"مج";s:3:"ﳏ";s:4:"مح";s:3:"ﳐ";s:4:"مخ";s:3:"ﳑ";s:4:"مم";s:3:"ﳒ";s:4:"نج";s:3:"ﳓ";s:4:"نح";s:3:"ﳔ";s:4:"نخ";s:3:"ﳕ";s:4:"نم";s:3:"ﳖ";s:4:"نه";s:3:"ﳗ";s:4:"هج";s:3:"ﳘ";s:4:"هم";s:3:"ﳙ";s:4:"هٰ";s:3:"ﳚ";s:4:"يج";s:3:"ﳛ";s:4:"يح";s:3:"ﳜ";s:4:"يخ";s:3:"ﳝ";s:4:"يم";s:3:"ﳞ";s:4:"يه";s:3:"ﳟ";s:6:"ئم";s:3:"ﳠ";s:6:"ئه";s:3:"ﳡ";s:4:"بم";s:3:"ﳢ";s:4:"به";s:3:"ﳣ";s:4:"تم";s:3:"ﳤ";s:4:"ته";s:3:"ﳥ";s:4:"ثم";s:3:"ﳦ";s:4:"ثه";s:3:"ﳧ";s:4:"سم";s:3:"ﳨ";s:4:"سه";s:3:"ﳩ";s:4:"شم";s:3:"ﳪ";s:4:"شه";s:3:"ﳫ";s:4:"كل";s:3:"ﳬ";s:4:"كم";s:3:"ﳭ";s:4:"لم";s:3:"ﳮ";s:4:"نم";s:3:"ﳯ";s:4:"نه";s:3:"ﳰ";s:4:"يم";s:3:"ﳱ";s:4:"يه";s:3:"ﳲ";s:6:"ـَّ";s:3:"ﳳ";s:6:"ـُّ";s:3:"ﳴ";s:6:"ـِّ";s:3:"ﳵ";s:4:"طى";s:3:"ﳶ";s:4:"طي";s:3:"ﳷ";s:4:"عى";s:3:"ﳸ";s:4:"عي";s:3:"ﳹ";s:4:"غى";s:3:"ﳺ";s:4:"غي";s:3:"ﳻ";s:4:"سى";s:3:"ﳼ";s:4:"سي";s:3:"ﳽ";s:4:"شى";s:3:"ﳾ";s:4:"شي";s:3:"ﳿ";s:4:"حى";s:3:"ﴀ";s:4:"حي";s:3:"ﴁ";s:4:"جى";s:3:"ﴂ";s:4:"جي";s:3:"ﴃ";s:4:"خى";s:3:"ﴄ";s:4:"خي";s:3:"ﴅ";s:4:"صى";s:3:"ﴆ";s:4:"صي";s:3:"ﴇ";s:4:"ضى";s:3:"ﴈ";s:4:"ضي";s:3:"ﴉ";s:4:"شج";s:3:"ﴊ";s:4:"شح";s:3:"ﴋ";s:4:"شخ";s:3:"ﴌ";s:4:"شم";s:3:"ﴍ";s:4:"شر";s:3:"ﴎ";s:4:"سر";s:3:"ﴏ";s:4:"صر";s:3:"ﴐ";s:4:"ضر";s:3:"ﴑ";s:4:"طى";s:3:"ﴒ";s:4:"طي";s:3:"ﴓ";s:4:"عى";s:3:"ﴔ";s:4:"عي";s:3:"ﴕ";s:4:"غى";s:3:"ﴖ";s:4:"غي";s:3:"ﴗ";s:4:"سى";s:3:"ﴘ";s:4:"سي";s:3:"ﴙ";s:4:"شى";s:3:"ﴚ";s:4:"شي";s:3:"ﴛ";s:4:"حى";s:3:"ﴜ";s:4:"حي";s:3:"ﴝ";s:4:"جى";s:3:"ﴞ";s:4:"جي";s:3:"ﴟ";s:4:"خى";s:3:"ﴠ";s:4:"خي";s:3:"ﴡ";s:4:"صى";s:3:"ﴢ";s:4:"صي";s:3:"ﴣ";s:4:"ضى";s:3:"ﴤ";s:4:"ضي";s:3:"ﴥ";s:4:"شج";s:3:"ﴦ";s:4:"شح";s:3:"ﴧ";s:4:"شخ";s:3:"ﴨ";s:4:"شم";s:3:"ﴩ";s:4:"شر";s:3:"ﴪ";s:4:"سر";s:3:"ﴫ";s:4:"صر";s:3:"ﴬ";s:4:"ضر";s:3:"ﴭ";s:4:"شج";s:3:"ﴮ";s:4:"شح";s:3:"ﴯ";s:4:"شخ";s:3:"ﴰ";s:4:"شم";s:3:"ﴱ";s:4:"سه";s:3:"ﴲ";s:4:"شه";s:3:"ﴳ";s:4:"طم";s:3:"ﴴ";s:4:"سج";s:3:"ﴵ";s:4:"سح";s:3:"ﴶ";s:4:"سخ";s:3:"ﴷ";s:4:"شج";s:3:"ﴸ";s:4:"شح";s:3:"ﴹ";s:4:"شخ";s:3:"ﴺ";s:4:"طم";s:3:"ﴻ";s:4:"ظم";s:3:"ﴼ";s:4:"اً";s:3:"ﴽ";s:4:"اً";s:3:"ﵐ";s:6:"تجم";s:3:"ﵑ";s:6:"تحج";s:3:"ﵒ";s:6:"تحج";s:3:"ﵓ";s:6:"تحم";s:3:"ﵔ";s:6:"تخم";s:3:"ﵕ";s:6:"تمج";s:3:"ﵖ";s:6:"تمح";s:3:"ﵗ";s:6:"تمخ";s:3:"ﵘ";s:6:"جمح";s:3:"ﵙ";s:6:"جمح";s:3:"ﵚ";s:6:"حمي";s:3:"ﵛ";s:6:"حمى";s:3:"ﵜ";s:6:"سحج";s:3:"ﵝ";s:6:"سجح";s:3:"ﵞ";s:6:"سجى";s:3:"ﵟ";s:6:"سمح";s:3:"ﵠ";s:6:"سمح";s:3:"ﵡ";s:6:"سمج";s:3:"ﵢ";s:6:"سمم";s:3:"ﵣ";s:6:"سمم";s:3:"ﵤ";s:6:"صحح";s:3:"ﵥ";s:6:"صحح";s:3:"ﵦ";s:6:"صمم";s:3:"ﵧ";s:6:"شحم";s:3:"ﵨ";s:6:"شحم";s:3:"ﵩ";s:6:"شجي";s:3:"ﵪ";s:6:"شمخ";s:3:"ﵫ";s:6:"شمخ";s:3:"ﵬ";s:6:"شمم";s:3:"ﵭ";s:6:"شمم";s:3:"ﵮ";s:6:"ضحى";s:3:"ﵯ";s:6:"ضخم";s:3:"ﵰ";s:6:"ضخم";s:3:"ﵱ";s:6:"طمح";s:3:"ﵲ";s:6:"طمح";s:3:"ﵳ";s:6:"طمم";s:3:"ﵴ";s:6:"طمي";s:3:"ﵵ";s:6:"عجم";s:3:"ﵶ";s:6:"عمم";s:3:"ﵷ";s:6:"عمم";s:3:"ﵸ";s:6:"عمى";s:3:"ﵹ";s:6:"غمم";s:3:"ﵺ";s:6:"غمي";s:3:"ﵻ";s:6:"غمى";s:3:"ﵼ";s:6:"فخم";s:3:"ﵽ";s:6:"فخم";s:3:"ﵾ";s:6:"قمح";s:3:"ﵿ";s:6:"قمم";s:3:"ﶀ";s:6:"لحم";s:3:"ﶁ";s:6:"لحي";s:3:"ﶂ";s:6:"لحى";s:3:"ﶃ";s:6:"لجج";s:3:"ﶄ";s:6:"لجج";s:3:"ﶅ";s:6:"لخم";s:3:"ﶆ";s:6:"لخم";s:3:"ﶇ";s:6:"لمح";s:3:"ﶈ";s:6:"لمح";s:3:"ﶉ";s:6:"محج";s:3:"ﶊ";s:6:"محم";s:3:"ﶋ";s:6:"محي";s:3:"ﶌ";s:6:"مجح";s:3:"ﶍ";s:6:"مجم";s:3:"ﶎ";s:6:"مخج";s:3:"ﶏ";s:6:"مخم";s:3:"ﶒ";s:6:"مجخ";s:3:"ﶓ";s:6:"همج";s:3:"ﶔ";s:6:"همم";s:3:"ﶕ";s:6:"نحم";s:3:"ﶖ";s:6:"نحى";s:3:"ﶗ";s:6:"نجم";s:3:"ﶘ";s:6:"نجم";s:3:"ﶙ";s:6:"نجى";s:3:"ﶚ";s:6:"نمي";s:3:"ﶛ";s:6:"نمى";s:3:"ﶜ";s:6:"يمم";s:3:"ﶝ";s:6:"يمم";s:3:"ﶞ";s:6:"بخي";s:3:"ﶟ";s:6:"تجي";s:3:"ﶠ";s:6:"تجى";s:3:"ﶡ";s:6:"تخي";s:3:"ﶢ";s:6:"تخى";s:3:"ﶣ";s:6:"تمي";s:3:"ﶤ";s:6:"تمى";s:3:"ﶥ";s:6:"جمي";s:3:"ﶦ";s:6:"جحى";s:3:"ﶧ";s:6:"جمى";s:3:"ﶨ";s:6:"سخى";s:3:"ﶩ";s:6:"صحي";s:3:"ﶪ";s:6:"شحي";s:3:"ﶫ";s:6:"ضحي";s:3:"ﶬ";s:6:"لجي";s:3:"ﶭ";s:6:"لمي";s:3:"ﶮ";s:6:"يحي";s:3:"ﶯ";s:6:"يجي";s:3:"ﶰ";s:6:"يمي";s:3:"ﶱ";s:6:"ممي";s:3:"ﶲ";s:6:"قمي";s:3:"ﶳ";s:6:"نحي";s:3:"ﶴ";s:6:"قمح";s:3:"ﶵ";s:6:"لحم";s:3:"ﶶ";s:6:"عمي";s:3:"ﶷ";s:6:"كمي";s:3:"ﶸ";s:6:"نجح";s:3:"ﶹ";s:6:"مخي";s:3:"ﶺ";s:6:"لجم";s:3:"ﶻ";s:6:"كمم";s:3:"ﶼ";s:6:"لجم";s:3:"ﶽ";s:6:"نجح";s:3:"ﶾ";s:6:"جحي";s:3:"ﶿ";s:6:"حجي";s:3:"ﷀ";s:6:"مجي";s:3:"ﷁ";s:6:"فمي";s:3:"ﷂ";s:6:"بحي";s:3:"ﷃ";s:6:"كمم";s:3:"ﷄ";s:6:"عجم";s:3:"ﷅ";s:6:"صمم";s:3:"ﷆ";s:6:"سخي";s:3:"ﷇ";s:6:"نجي";s:3:"ﷰ";s:6:"صلے";s:3:"ﷱ";s:6:"قلے";s:3:"ﷲ";s:8:"الله";s:3:"ﷳ";s:8:"اكبر";s:3:"ﷴ";s:8:"محمد";s:3:"ﷵ";s:8:"صلعم";s:3:"ﷶ";s:8:"رسول";s:3:"ﷷ";s:8:"عليه";s:3:"ﷸ";s:8:"وسلم";s:3:"ﷹ";s:6:"صلى";s:3:"ﷺ";s:33:"صلى الله عليه وسلم";s:3:"ﷻ";s:15:"جل جلاله";s:3:"﷼";s:8:"ریال";s:3:"︐";s:1:",";s:3:"︑";s:3:"、";s:3:"︒";s:3:"。";s:3:"︓";s:1:":";s:3:"︔";s:1:";";s:3:"︕";s:1:"!";s:3:"︖";s:1:"?";s:3:"︗";s:3:"〖";s:3:"︘";s:3:"〗";s:3:"︙";s:3:"...";s:3:"︰";s:2:"..";s:3:"︱";s:3:"—";s:3:"︲";s:3:"–";s:3:"︳";s:1:"_";s:3:"︴";s:1:"_";s:3:"︵";s:1:"(";s:3:"︶";s:1:")";s:3:"︷";s:1:"{";s:3:"︸";s:1:"}";s:3:"︹";s:3:"〔";s:3:"︺";s:3:"〕";s:3:"︻";s:3:"【";s:3:"︼";s:3:"】";s:3:"︽";s:3:"《";s:3:"︾";s:3:"》";s:3:"︿";s:3:"〈";s:3:"﹀";s:3:"〉";s:3:"﹁";s:3:"「";s:3:"﹂";s:3:"」";s:3:"﹃";s:3:"『";s:3:"﹄";s:3:"』";s:3:"﹇";s:1:"[";s:3:"﹈";s:1:"]";s:3:"﹉";s:3:" ̅";s:3:"﹊";s:3:" ̅";s:3:"﹋";s:3:" ̅";s:3:"﹌";s:3:" ̅";s:3:"﹍";s:1:"_";s:3:"﹎";s:1:"_";s:3:"﹏";s:1:"_";s:3:"﹐";s:1:",";s:3:"﹑";s:3:"、";s:3:"﹒";s:1:".";s:3:"﹔";s:1:";";s:3:"﹕";s:1:":";s:3:"﹖";s:1:"?";s:3:"﹗";s:1:"!";s:3:"﹘";s:3:"—";s:3:"﹙";s:1:"(";s:3:"﹚";s:1:")";s:3:"﹛";s:1:"{";s:3:"﹜";s:1:"}";s:3:"﹝";s:3:"〔";s:3:"﹞";s:3:"〕";s:3:"﹟";s:1:"#";s:3:"﹠";s:1:"&";s:3:"﹡";s:1:"*";s:3:"﹢";s:1:"+";s:3:"﹣";s:1:"-";s:3:"﹤";s:1:"<";s:3:"﹥";s:1:">";s:3:"﹦";s:1:"=";s:3:"﹨";s:1:"\\";s:3:"﹩";s:1:"$";s:3:"﹪";s:1:"%";s:3:"﹫";s:1:"@";s:3:"ﹰ";s:3:" ً";s:3:"ﹱ";s:4:"ـً";s:3:"ﹲ";s:3:" ٌ";s:3:"ﹴ";s:3:" ٍ";s:3:"ﹶ";s:3:" َ";s:3:"ﹷ";s:4:"ـَ";s:3:"ﹸ";s:3:" ُ";s:3:"ﹹ";s:4:"ـُ";s:3:"ﹺ";s:3:" ِ";s:3:"ﹻ";s:4:"ـِ";s:3:"ﹼ";s:3:" ّ";s:3:"ﹽ";s:4:"ـّ";s:3:"ﹾ";s:3:" ْ";s:3:"ﹿ";s:4:"ـْ";s:3:"ﺀ";s:2:"ء";s:3:"ﺁ";s:4:"آ";s:3:"ﺂ";s:4:"آ";s:3:"ﺃ";s:4:"أ";s:3:"ﺄ";s:4:"أ";s:3:"ﺅ";s:4:"ؤ";s:3:"ﺆ";s:4:"ؤ";s:3:"ﺇ";s:4:"إ";s:3:"ﺈ";s:4:"إ";s:3:"ﺉ";s:4:"ئ";s:3:"ﺊ";s:4:"ئ";s:3:"ﺋ";s:4:"ئ";s:3:"ﺌ";s:4:"ئ";s:3:"ﺍ";s:2:"ا";s:3:"ﺎ";s:2:"ا";s:3:"ﺏ";s:2:"ب";s:3:"ﺐ";s:2:"ب";s:3:"ﺑ";s:2:"ب";s:3:"ﺒ";s:2:"ب";s:3:"ﺓ";s:2:"ة";s:3:"ﺔ";s:2:"ة";s:3:"ﺕ";s:2:"ت";s:3:"ﺖ";s:2:"ت";s:3:"ﺗ";s:2:"ت";s:3:"ﺘ";s:2:"ت";s:3:"ﺙ";s:2:"ث";s:3:"ﺚ";s:2:"ث";s:3:"ﺛ";s:2:"ث";s:3:"ﺜ";s:2:"ث";s:3:"ﺝ";s:2:"ج";s:3:"ﺞ";s:2:"ج";s:3:"ﺟ";s:2:"ج";s:3:"ﺠ";s:2:"ج";s:3:"ﺡ";s:2:"ح";s:3:"ﺢ";s:2:"ح";s:3:"ﺣ";s:2:"ح";s:3:"ﺤ";s:2:"ح";s:3:"ﺥ";s:2:"خ";s:3:"ﺦ";s:2:"خ";s:3:"ﺧ";s:2:"خ";s:3:"ﺨ";s:2:"خ";s:3:"ﺩ";s:2:"د";s:3:"ﺪ";s:2:"د";s:3:"ﺫ";s:2:"ذ";s:3:"ﺬ";s:2:"ذ";s:3:"ﺭ";s:2:"ر";s:3:"ﺮ";s:2:"ر";s:3:"ﺯ";s:2:"ز";s:3:"ﺰ";s:2:"ز";s:3:"ﺱ";s:2:"س";s:3:"ﺲ";s:2:"س";s:3:"ﺳ";s:2:"س";s:3:"ﺴ";s:2:"س";s:3:"ﺵ";s:2:"ش";s:3:"ﺶ";s:2:"ش";s:3:"ﺷ";s:2:"ش";s:3:"ﺸ";s:2:"ش";s:3:"ﺹ";s:2:"ص";s:3:"ﺺ";s:2:"ص";s:3:"ﺻ";s:2:"ص";s:3:"ﺼ";s:2:"ص";s:3:"ﺽ";s:2:"ض";s:3:"ﺾ";s:2:"ض";s:3:"ﺿ";s:2:"ض";s:3:"ﻀ";s:2:"ض";s:3:"ﻁ";s:2:"ط";s:3:"ﻂ";s:2:"ط";s:3:"ﻃ";s:2:"ط";s:3:"ﻄ";s:2:"ط";s:3:"ﻅ";s:2:"ظ";s:3:"ﻆ";s:2:"ظ";s:3:"ﻇ";s:2:"ظ";s:3:"ﻈ";s:2:"ظ";s:3:"ﻉ";s:2:"ع";s:3:"ﻊ";s:2:"ع";s:3:"ﻋ";s:2:"ع";s:3:"ﻌ";s:2:"ع";s:3:"ﻍ";s:2:"غ";s:3:"ﻎ";s:2:"غ";s:3:"ﻏ";s:2:"غ";s:3:"ﻐ";s:2:"غ";s:3:"ﻑ";s:2:"ف";s:3:"ﻒ";s:2:"ف";s:3:"ﻓ";s:2:"ف";s:3:"ﻔ";s:2:"ف";s:3:"ﻕ";s:2:"ق";s:3:"ﻖ";s:2:"ق";s:3:"ﻗ";s:2:"ق";s:3:"ﻘ";s:2:"ق";s:3:"ﻙ";s:2:"ك";s:3:"ﻚ";s:2:"ك";s:3:"ﻛ";s:2:"ك";s:3:"ﻜ";s:2:"ك";s:3:"ﻝ";s:2:"ل";s:3:"ﻞ";s:2:"ل";s:3:"ﻟ";s:2:"ل";s:3:"ﻠ";s:2:"ل";s:3:"ﻡ";s:2:"م";s:3:"ﻢ";s:2:"م";s:3:"ﻣ";s:2:"م";s:3:"ﻤ";s:2:"م";s:3:"ﻥ";s:2:"ن";s:3:"ﻦ";s:2:"ن";s:3:"ﻧ";s:2:"ن";s:3:"ﻨ";s:2:"ن";s:3:"ﻩ";s:2:"ه";s:3:"ﻪ";s:2:"ه";s:3:"ﻫ";s:2:"ه";s:3:"ﻬ";s:2:"ه";s:3:"ﻭ";s:2:"و";s:3:"ﻮ";s:2:"و";s:3:"ﻯ";s:2:"ى";s:3:"ﻰ";s:2:"ى";s:3:"ﻱ";s:2:"ي";s:3:"ﻲ";s:2:"ي";s:3:"ﻳ";s:2:"ي";s:3:"ﻴ";s:2:"ي";s:3:"ﻵ";s:6:"لآ";s:3:"ﻶ";s:6:"لآ";s:3:"ﻷ";s:6:"لأ";s:3:"ﻸ";s:6:"لأ";s:3:"ﻹ";s:6:"لإ";s:3:"ﻺ";s:6:"لإ";s:3:"ﻻ";s:4:"لا";s:3:"ﻼ";s:4:"لا";s:3:"!";s:1:"!";s:3:""";s:1:""";s:3:"#";s:1:"#";s:3:"$";s:1:"$";s:3:"%";s:1:"%";s:3:"&";s:1:"&";s:3:"'";s:1:"\'";s:3:"(";s:1:"(";s:3:")";s:1:")";s:3:"*";s:1:"*";s:3:"+";s:1:"+";s:3:",";s:1:",";s:3:"-";s:1:"-";s:3:".";s:1:".";s:3:"/";s:1:"/";s:3:"0";s:1:"0";s:3:"1";s:1:"1";s:3:"2";s:1:"2";s:3:"3";s:1:"3";s:3:"4";s:1:"4";s:3:"5";s:1:"5";s:3:"6";s:1:"6";s:3:"7";s:1:"7";s:3:"8";s:1:"8";s:3:"9";s:1:"9";s:3:":";s:1:":";s:3:";";s:1:";";s:3:"<";s:1:"<";s:3:"=";s:1:"=";s:3:">";s:1:">";s:3:"?";s:1:"?";s:3:"@";s:1:"@";s:3:"A";s:1:"A";s:3:"B";s:1:"B";s:3:"C";s:1:"C";s:3:"D";s:1:"D";s:3:"E";s:1:"E";s:3:"F";s:1:"F";s:3:"G";s:1:"G";s:3:"H";s:1:"H";s:3:"I";s:1:"I";s:3:"J";s:1:"J";s:3:"K";s:1:"K";s:3:"L";s:1:"L";s:3:"M";s:1:"M";s:3:"N";s:1:"N";s:3:"O";s:1:"O";s:3:"P";s:1:"P";s:3:"Q";s:1:"Q";s:3:"R";s:1:"R";s:3:"S";s:1:"S";s:3:"T";s:1:"T";s:3:"U";s:1:"U";s:3:"V";s:1:"V";s:3:"W";s:1:"W";s:3:"X";s:1:"X";s:3:"Y";s:1:"Y";s:3:"Z";s:1:"Z";s:3:"[";s:1:"[";s:3:"\";s:1:"\\";s:3:"]";s:1:"]";s:3:"^";s:1:"^";s:3:"_";s:1:"_";s:3:"`";s:1:"`";s:3:"a";s:1:"a";s:3:"b";s:1:"b";s:3:"c";s:1:"c";s:3:"d";s:1:"d";s:3:"e";s:1:"e";s:3:"f";s:1:"f";s:3:"g";s:1:"g";s:3:"h";s:1:"h";s:3:"i";s:1:"i";s:3:"j";s:1:"j";s:3:"k";s:1:"k";s:3:"l";s:1:"l";s:3:"m";s:1:"m";s:3:"n";s:1:"n";s:3:"o";s:1:"o";s:3:"p";s:1:"p";s:3:"q";s:1:"q";s:3:"r";s:1:"r";s:3:"s";s:1:"s";s:3:"t";s:1:"t";s:3:"u";s:1:"u";s:3:"v";s:1:"v";s:3:"w";s:1:"w";s:3:"x";s:1:"x";s:3:"y";s:1:"y";s:3:"z";s:1:"z";s:3:"{";s:1:"{";s:3:"|";s:1:"|";s:3:"}";s:1:"}";s:3:"~";s:1:"~";s:3:"⦅";s:3:"⦅";s:3:"⦆";s:3:"⦆";s:3:"。";s:3:"。";s:3:"「";s:3:"「";s:3:"」";s:3:"」";s:3:"、";s:3:"、";s:3:"・";s:3:"・";s:3:"ヲ";s:3:"ヲ";s:3:"ァ";s:3:"ァ";s:3:"ィ";s:3:"ィ";s:3:"ゥ";s:3:"ゥ";s:3:"ェ";s:3:"ェ";s:3:"ォ";s:3:"ォ";s:3:"ャ";s:3:"ャ";s:3:"ュ";s:3:"ュ";s:3:"ョ";s:3:"ョ";s:3:"ッ";s:3:"ッ";s:3:"ー";s:3:"ー";s:3:"ア";s:3:"ア";s:3:"イ";s:3:"イ";s:3:"ウ";s:3:"ウ";s:3:"エ";s:3:"エ";s:3:"オ";s:3:"オ";s:3:"カ";s:3:"カ";s:3:"キ";s:3:"キ";s:3:"ク";s:3:"ク";s:3:"ケ";s:3:"ケ";s:3:"コ";s:3:"コ";s:3:"サ";s:3:"サ";s:3:"シ";s:3:"シ";s:3:"ス";s:3:"ス";s:3:"セ";s:3:"セ";s:3:"ソ";s:3:"ソ";s:3:"タ";s:3:"タ";s:3:"チ";s:3:"チ";s:3:"ツ";s:3:"ツ";s:3:"テ";s:3:"テ";s:3:"ト";s:3:"ト";s:3:"ナ";s:3:"ナ";s:3:"ニ";s:3:"ニ";s:3:"ヌ";s:3:"ヌ";s:3:"ネ";s:3:"ネ";s:3:"ノ";s:3:"ノ";s:3:"ハ";s:3:"ハ";s:3:"ヒ";s:3:"ヒ";s:3:"フ";s:3:"フ";s:3:"ヘ";s:3:"ヘ";s:3:"ホ";s:3:"ホ";s:3:"マ";s:3:"マ";s:3:"ミ";s:3:"ミ";s:3:"ム";s:3:"ム";s:3:"メ";s:3:"メ";s:3:"モ";s:3:"モ";s:3:"ヤ";s:3:"ヤ";s:3:"ユ";s:3:"ユ";s:3:"ヨ";s:3:"ヨ";s:3:"ラ";s:3:"ラ";s:3:"リ";s:3:"リ";s:3:"ル";s:3:"ル";s:3:"レ";s:3:"レ";s:3:"ロ";s:3:"ロ";s:3:"ワ";s:3:"ワ";s:3:"ン";s:3:"ン";s:3:"゙";s:3:"゙";s:3:"゚";s:3:"゚";s:3:"ᅠ";s:3:"ᅠ";s:3:"ᄀ";s:3:"ᄀ";s:3:"ᄁ";s:3:"ᄁ";s:3:"ᆪ";s:3:"ᆪ";s:3:"ᄂ";s:3:"ᄂ";s:3:"ᆬ";s:3:"ᆬ";s:3:"ᆭ";s:3:"ᆭ";s:3:"ᄃ";s:3:"ᄃ";s:3:"ᄄ";s:3:"ᄄ";s:3:"ᄅ";s:3:"ᄅ";s:3:"ᆰ";s:3:"ᆰ";s:3:"ᆱ";s:3:"ᆱ";s:3:"ᆲ";s:3:"ᆲ";s:3:"ᆳ";s:3:"ᆳ";s:3:"ᆴ";s:3:"ᆴ";s:3:"ᆵ";s:3:"ᆵ";s:3:"ᄚ";s:3:"ᄚ";s:3:"ᄆ";s:3:"ᄆ";s:3:"ᄇ";s:3:"ᄇ";s:3:"ᄈ";s:3:"ᄈ";s:3:"ᄡ";s:3:"ᄡ";s:3:"ᄉ";s:3:"ᄉ";s:3:"ᄊ";s:3:"ᄊ";s:3:"ᄋ";s:3:"ᄋ";s:3:"ᄌ";s:3:"ᄌ";s:3:"ᄍ";s:3:"ᄍ";s:3:"ᄎ";s:3:"ᄎ";s:3:"ᄏ";s:3:"ᄏ";s:3:"ᄐ";s:3:"ᄐ";s:3:"ᄑ";s:3:"ᄑ";s:3:"ᄒ";s:3:"ᄒ";s:3:"ᅡ";s:3:"ᅡ";s:3:"ᅢ";s:3:"ᅢ";s:3:"ᅣ";s:3:"ᅣ";s:3:"ᅤ";s:3:"ᅤ";s:3:"ᅥ";s:3:"ᅥ";s:3:"ᅦ";s:3:"ᅦ";s:3:"ᅧ";s:3:"ᅧ";s:3:"ᅨ";s:3:"ᅨ";s:3:"ᅩ";s:3:"ᅩ";s:3:"ᅪ";s:3:"ᅪ";s:3:"ᅫ";s:3:"ᅫ";s:3:"ᅬ";s:3:"ᅬ";s:3:"ᅭ";s:3:"ᅭ";s:3:"ᅮ";s:3:"ᅮ";s:3:"ᅯ";s:3:"ᅯ";s:3:"ᅰ";s:3:"ᅰ";s:3:"ᅱ";s:3:"ᅱ";s:3:"ᅲ";s:3:"ᅲ";s:3:"ᅳ";s:3:"ᅳ";s:3:"ᅴ";s:3:"ᅴ";s:3:"ᅵ";s:3:"ᅵ";s:3:"¢";s:2:"¢";s:3:"£";s:2:"£";s:3:"¬";s:2:"¬";s:3:" ̄";s:3:" ̄";s:3:"¦";s:2:"¦";s:3:"¥";s:2:"¥";s:3:"₩";s:3:"₩";s:3:"│";s:3:"│";s:3:"←";s:3:"←";s:3:"↑";s:3:"↑";s:3:"→";s:3:"→";s:3:"↓";s:3:"↓";s:3:"■";s:3:"■";s:3:"○";s:3:"○";s:4:"𝅗𝅥";s:8:"𝅗𝅥";s:4:"𝅘𝅥";s:8:"𝅘𝅥";s:4:"𝅘𝅥𝅮";s:12:"𝅘𝅥𝅮";s:4:"𝅘𝅥𝅯";s:12:"𝅘𝅥𝅯";s:4:"𝅘𝅥𝅰";s:12:"𝅘𝅥𝅰";s:4:"𝅘𝅥𝅱";s:12:"𝅘𝅥𝅱";s:4:"𝅘𝅥𝅲";s:12:"𝅘𝅥𝅲";s:4:"𝆹𝅥";s:8:"𝆹𝅥";s:4:"𝆺𝅥";s:8:"𝆺𝅥";s:4:"𝆹𝅥𝅮";s:12:"𝆹𝅥𝅮";s:4:"𝆺𝅥𝅮";s:12:"𝆺𝅥𝅮";s:4:"𝆹𝅥𝅯";s:12:"𝆹𝅥𝅯";s:4:"𝆺𝅥𝅯";s:12:"𝆺𝅥𝅯";s:4:"𝐀";s:1:"A";s:4:"𝐁";s:1:"B";s:4:"𝐂";s:1:"C";s:4:"𝐃";s:1:"D";s:4:"𝐄";s:1:"E";s:4:"𝐅";s:1:"F";s:4:"𝐆";s:1:"G";s:4:"𝐇";s:1:"H";s:4:"𝐈";s:1:"I";s:4:"𝐉";s:1:"J";s:4:"𝐊";s:1:"K";s:4:"𝐋";s:1:"L";s:4:"𝐌";s:1:"M";s:4:"𝐍";s:1:"N";s:4:"𝐎";s:1:"O";s:4:"𝐏";s:1:"P";s:4:"𝐐";s:1:"Q";s:4:"𝐑";s:1:"R";s:4:"𝐒";s:1:"S";s:4:"𝐓";s:1:"T";s:4:"𝐔";s:1:"U";s:4:"𝐕";s:1:"V";s:4:"𝐖";s:1:"W";s:4:"𝐗";s:1:"X";s:4:"𝐘";s:1:"Y";s:4:"𝐙";s:1:"Z";s:4:"𝐚";s:1:"a";s:4:"𝐛";s:1:"b";s:4:"𝐜";s:1:"c";s:4:"𝐝";s:1:"d";s:4:"𝐞";s:1:"e";s:4:"𝐟";s:1:"f";s:4:"𝐠";s:1:"g";s:4:"𝐡";s:1:"h";s:4:"𝐢";s:1:"i";s:4:"𝐣";s:1:"j";s:4:"𝐤";s:1:"k";s:4:"𝐥";s:1:"l";s:4:"𝐦";s:1:"m";s:4:"𝐧";s:1:"n";s:4:"𝐨";s:1:"o";s:4:"𝐩";s:1:"p";s:4:"𝐪";s:1:"q";s:4:"𝐫";s:1:"r";s:4:"𝐬";s:1:"s";s:4:"𝐭";s:1:"t";s:4:"𝐮";s:1:"u";s:4:"𝐯";s:1:"v";s:4:"𝐰";s:1:"w";s:4:"𝐱";s:1:"x";s:4:"𝐲";s:1:"y";s:4:"𝐳";s:1:"z";s:4:"𝐴";s:1:"A";s:4:"𝐵";s:1:"B";s:4:"𝐶";s:1:"C";s:4:"𝐷";s:1:"D";s:4:"𝐸";s:1:"E";s:4:"𝐹";s:1:"F";s:4:"𝐺";s:1:"G";s:4:"𝐻";s:1:"H";s:4:"𝐼";s:1:"I";s:4:"𝐽";s:1:"J";s:4:"𝐾";s:1:"K";s:4:"𝐿";s:1:"L";s:4:"𝑀";s:1:"M";s:4:"𝑁";s:1:"N";s:4:"𝑂";s:1:"O";s:4:"𝑃";s:1:"P";s:4:"𝑄";s:1:"Q";s:4:"𝑅";s:1:"R";s:4:"𝑆";s:1:"S";s:4:"𝑇";s:1:"T";s:4:"𝑈";s:1:"U";s:4:"𝑉";s:1:"V";s:4:"𝑊";s:1:"W";s:4:"𝑋";s:1:"X";s:4:"𝑌";s:1:"Y";s:4:"𝑍";s:1:"Z";s:4:"𝑎";s:1:"a";s:4:"𝑏";s:1:"b";s:4:"𝑐";s:1:"c";s:4:"𝑑";s:1:"d";s:4:"𝑒";s:1:"e";s:4:"𝑓";s:1:"f";s:4:"𝑔";s:1:"g";s:4:"𝑖";s:1:"i";s:4:"𝑗";s:1:"j";s:4:"𝑘";s:1:"k";s:4:"𝑙";s:1:"l";s:4:"𝑚";s:1:"m";s:4:"𝑛";s:1:"n";s:4:"𝑜";s:1:"o";s:4:"𝑝";s:1:"p";s:4:"𝑞";s:1:"q";s:4:"𝑟";s:1:"r";s:4:"𝑠";s:1:"s";s:4:"𝑡";s:1:"t";s:4:"𝑢";s:1:"u";s:4:"𝑣";s:1:"v";s:4:"𝑤";s:1:"w";s:4:"𝑥";s:1:"x";s:4:"𝑦";s:1:"y";s:4:"𝑧";s:1:"z";s:4:"𝑨";s:1:"A";s:4:"𝑩";s:1:"B";s:4:"𝑪";s:1:"C";s:4:"𝑫";s:1:"D";s:4:"𝑬";s:1:"E";s:4:"𝑭";s:1:"F";s:4:"𝑮";s:1:"G";s:4:"𝑯";s:1:"H";s:4:"𝑰";s:1:"I";s:4:"𝑱";s:1:"J";s:4:"𝑲";s:1:"K";s:4:"𝑳";s:1:"L";s:4:"𝑴";s:1:"M";s:4:"𝑵";s:1:"N";s:4:"𝑶";s:1:"O";s:4:"𝑷";s:1:"P";s:4:"𝑸";s:1:"Q";s:4:"𝑹";s:1:"R";s:4:"𝑺";s:1:"S";s:4:"𝑻";s:1:"T";s:4:"𝑼";s:1:"U";s:4:"𝑽";s:1:"V";s:4:"𝑾";s:1:"W";s:4:"𝑿";s:1:"X";s:4:"𝒀";s:1:"Y";s:4:"𝒁";s:1:"Z";s:4:"𝒂";s:1:"a";s:4:"𝒃";s:1:"b";s:4:"𝒄";s:1:"c";s:4:"𝒅";s:1:"d";s:4:"𝒆";s:1:"e";s:4:"𝒇";s:1:"f";s:4:"𝒈";s:1:"g";s:4:"𝒉";s:1:"h";s:4:"𝒊";s:1:"i";s:4:"𝒋";s:1:"j";s:4:"𝒌";s:1:"k";s:4:"𝒍";s:1:"l";s:4:"𝒎";s:1:"m";s:4:"𝒏";s:1:"n";s:4:"𝒐";s:1:"o";s:4:"𝒑";s:1:"p";s:4:"𝒒";s:1:"q";s:4:"𝒓";s:1:"r";s:4:"𝒔";s:1:"s";s:4:"𝒕";s:1:"t";s:4:"𝒖";s:1:"u";s:4:"𝒗";s:1:"v";s:4:"𝒘";s:1:"w";s:4:"𝒙";s:1:"x";s:4:"𝒚";s:1:"y";s:4:"𝒛";s:1:"z";s:4:"𝒜";s:1:"A";s:4:"𝒞";s:1:"C";s:4:"𝒟";s:1:"D";s:4:"𝒢";s:1:"G";s:4:"𝒥";s:1:"J";s:4:"𝒦";s:1:"K";s:4:"𝒩";s:1:"N";s:4:"𝒪";s:1:"O";s:4:"𝒫";s:1:"P";s:4:"𝒬";s:1:"Q";s:4:"𝒮";s:1:"S";s:4:"𝒯";s:1:"T";s:4:"𝒰";s:1:"U";s:4:"𝒱";s:1:"V";s:4:"𝒲";s:1:"W";s:4:"𝒳";s:1:"X";s:4:"𝒴";s:1:"Y";s:4:"𝒵";s:1:"Z";s:4:"𝒶";s:1:"a";s:4:"𝒷";s:1:"b";s:4:"𝒸";s:1:"c";s:4:"𝒹";s:1:"d";s:4:"𝒻";s:1:"f";s:4:"𝒽";s:1:"h";s:4:"𝒾";s:1:"i";s:4:"𝒿";s:1:"j";s:4:"𝓀";s:1:"k";s:4:"𝓁";s:1:"l";s:4:"𝓂";s:1:"m";s:4:"𝓃";s:1:"n";s:4:"𝓅";s:1:"p";s:4:"𝓆";s:1:"q";s:4:"𝓇";s:1:"r";s:4:"𝓈";s:1:"s";s:4:"𝓉";s:1:"t";s:4:"𝓊";s:1:"u";s:4:"𝓋";s:1:"v";s:4:"𝓌";s:1:"w";s:4:"𝓍";s:1:"x";s:4:"𝓎";s:1:"y";s:4:"𝓏";s:1:"z";s:4:"𝓐";s:1:"A";s:4:"𝓑";s:1:"B";s:4:"𝓒";s:1:"C";s:4:"𝓓";s:1:"D";s:4:"𝓔";s:1:"E";s:4:"𝓕";s:1:"F";s:4:"𝓖";s:1:"G";s:4:"𝓗";s:1:"H";s:4:"𝓘";s:1:"I";s:4:"𝓙";s:1:"J";s:4:"𝓚";s:1:"K";s:4:"𝓛";s:1:"L";s:4:"𝓜";s:1:"M";s:4:"𝓝";s:1:"N";s:4:"𝓞";s:1:"O";s:4:"𝓟";s:1:"P";s:4:"𝓠";s:1:"Q";s:4:"𝓡";s:1:"R";s:4:"𝓢";s:1:"S";s:4:"𝓣";s:1:"T";s:4:"𝓤";s:1:"U";s:4:"𝓥";s:1:"V";s:4:"𝓦";s:1:"W";s:4:"𝓧";s:1:"X";s:4:"𝓨";s:1:"Y";s:4:"𝓩";s:1:"Z";s:4:"𝓪";s:1:"a";s:4:"𝓫";s:1:"b";s:4:"𝓬";s:1:"c";s:4:"𝓭";s:1:"d";s:4:"𝓮";s:1:"e";s:4:"𝓯";s:1:"f";s:4:"𝓰";s:1:"g";s:4:"𝓱";s:1:"h";s:4:"𝓲";s:1:"i";s:4:"𝓳";s:1:"j";s:4:"𝓴";s:1:"k";s:4:"𝓵";s:1:"l";s:4:"𝓶";s:1:"m";s:4:"𝓷";s:1:"n";s:4:"𝓸";s:1:"o";s:4:"𝓹";s:1:"p";s:4:"𝓺";s:1:"q";s:4:"𝓻";s:1:"r";s:4:"𝓼";s:1:"s";s:4:"𝓽";s:1:"t";s:4:"𝓾";s:1:"u";s:4:"𝓿";s:1:"v";s:4:"𝔀";s:1:"w";s:4:"𝔁";s:1:"x";s:4:"𝔂";s:1:"y";s:4:"𝔃";s:1:"z";s:4:"𝔄";s:1:"A";s:4:"𝔅";s:1:"B";s:4:"𝔇";s:1:"D";s:4:"𝔈";s:1:"E";s:4:"𝔉";s:1:"F";s:4:"𝔊";s:1:"G";s:4:"𝔍";s:1:"J";s:4:"𝔎";s:1:"K";s:4:"𝔏";s:1:"L";s:4:"𝔐";s:1:"M";s:4:"𝔑";s:1:"N";s:4:"𝔒";s:1:"O";s:4:"𝔓";s:1:"P";s:4:"𝔔";s:1:"Q";s:4:"𝔖";s:1:"S";s:4:"𝔗";s:1:"T";s:4:"𝔘";s:1:"U";s:4:"𝔙";s:1:"V";s:4:"𝔚";s:1:"W";s:4:"𝔛";s:1:"X";s:4:"𝔜";s:1:"Y";s:4:"𝔞";s:1:"a";s:4:"𝔟";s:1:"b";s:4:"𝔠";s:1:"c";s:4:"𝔡";s:1:"d";s:4:"𝔢";s:1:"e";s:4:"𝔣";s:1:"f";s:4:"𝔤";s:1:"g";s:4:"𝔥";s:1:"h";s:4:"𝔦";s:1:"i";s:4:"𝔧";s:1:"j";s:4:"𝔨";s:1:"k";s:4:"𝔩";s:1:"l";s:4:"𝔪";s:1:"m";s:4:"𝔫";s:1:"n";s:4:"𝔬";s:1:"o";s:4:"𝔭";s:1:"p";s:4:"𝔮";s:1:"q";s:4:"𝔯";s:1:"r";s:4:"𝔰";s:1:"s";s:4:"𝔱";s:1:"t";s:4:"𝔲";s:1:"u";s:4:"𝔳";s:1:"v";s:4:"𝔴";s:1:"w";s:4:"𝔵";s:1:"x";s:4:"𝔶";s:1:"y";s:4:"𝔷";s:1:"z";s:4:"𝔸";s:1:"A";s:4:"𝔹";s:1:"B";s:4:"𝔻";s:1:"D";s:4:"𝔼";s:1:"E";s:4:"𝔽";s:1:"F";s:4:"𝔾";s:1:"G";s:4:"𝕀";s:1:"I";s:4:"𝕁";s:1:"J";s:4:"𝕂";s:1:"K";s:4:"𝕃";s:1:"L";s:4:"𝕄";s:1:"M";s:4:"𝕆";s:1:"O";s:4:"𝕊";s:1:"S";s:4:"𝕋";s:1:"T";s:4:"𝕌";s:1:"U";s:4:"𝕍";s:1:"V";s:4:"𝕎";s:1:"W";s:4:"𝕏";s:1:"X";s:4:"𝕐";s:1:"Y";s:4:"𝕒";s:1:"a";s:4:"𝕓";s:1:"b";s:4:"𝕔";s:1:"c";s:4:"𝕕";s:1:"d";s:4:"𝕖";s:1:"e";s:4:"𝕗";s:1:"f";s:4:"𝕘";s:1:"g";s:4:"𝕙";s:1:"h";s:4:"𝕚";s:1:"i";s:4:"𝕛";s:1:"j";s:4:"𝕜";s:1:"k";s:4:"𝕝";s:1:"l";s:4:"𝕞";s:1:"m";s:4:"𝕟";s:1:"n";s:4:"𝕠";s:1:"o";s:4:"𝕡";s:1:"p";s:4:"𝕢";s:1:"q";s:4:"𝕣";s:1:"r";s:4:"𝕤";s:1:"s";s:4:"𝕥";s:1:"t";s:4:"𝕦";s:1:"u";s:4:"𝕧";s:1:"v";s:4:"𝕨";s:1:"w";s:4:"𝕩";s:1:"x";s:4:"𝕪";s:1:"y";s:4:"𝕫";s:1:"z";s:4:"𝕬";s:1:"A";s:4:"𝕭";s:1:"B";s:4:"𝕮";s:1:"C";s:4:"𝕯";s:1:"D";s:4:"𝕰";s:1:"E";s:4:"𝕱";s:1:"F";s:4:"𝕲";s:1:"G";s:4:"𝕳";s:1:"H";s:4:"𝕴";s:1:"I";s:4:"𝕵";s:1:"J";s:4:"𝕶";s:1:"K";s:4:"𝕷";s:1:"L";s:4:"𝕸";s:1:"M";s:4:"𝕹";s:1:"N";s:4:"𝕺";s:1:"O";s:4:"𝕻";s:1:"P";s:4:"𝕼";s:1:"Q";s:4:"𝕽";s:1:"R";s:4:"𝕾";s:1:"S";s:4:"𝕿";s:1:"T";s:4:"𝖀";s:1:"U";s:4:"𝖁";s:1:"V";s:4:"𝖂";s:1:"W";s:4:"𝖃";s:1:"X";s:4:"𝖄";s:1:"Y";s:4:"𝖅";s:1:"Z";s:4:"𝖆";s:1:"a";s:4:"𝖇";s:1:"b";s:4:"𝖈";s:1:"c";s:4:"𝖉";s:1:"d";s:4:"𝖊";s:1:"e";s:4:"𝖋";s:1:"f";s:4:"𝖌";s:1:"g";s:4:"𝖍";s:1:"h";s:4:"𝖎";s:1:"i";s:4:"𝖏";s:1:"j";s:4:"𝖐";s:1:"k";s:4:"𝖑";s:1:"l";s:4:"𝖒";s:1:"m";s:4:"𝖓";s:1:"n";s:4:"𝖔";s:1:"o";s:4:"𝖕";s:1:"p";s:4:"𝖖";s:1:"q";s:4:"𝖗";s:1:"r";s:4:"𝖘";s:1:"s";s:4:"𝖙";s:1:"t";s:4:"𝖚";s:1:"u";s:4:"𝖛";s:1:"v";s:4:"𝖜";s:1:"w";s:4:"𝖝";s:1:"x";s:4:"𝖞";s:1:"y";s:4:"𝖟";s:1:"z";s:4:"𝖠";s:1:"A";s:4:"𝖡";s:1:"B";s:4:"𝖢";s:1:"C";s:4:"𝖣";s:1:"D";s:4:"𝖤";s:1:"E";s:4:"𝖥";s:1:"F";s:4:"𝖦";s:1:"G";s:4:"𝖧";s:1:"H";s:4:"𝖨";s:1:"I";s:4:"𝖩";s:1:"J";s:4:"𝖪";s:1:"K";s:4:"𝖫";s:1:"L";s:4:"𝖬";s:1:"M";s:4:"𝖭";s:1:"N";s:4:"𝖮";s:1:"O";s:4:"𝖯";s:1:"P";s:4:"𝖰";s:1:"Q";s:4:"𝖱";s:1:"R";s:4:"𝖲";s:1:"S";s:4:"𝖳";s:1:"T";s:4:"𝖴";s:1:"U";s:4:"𝖵";s:1:"V";s:4:"𝖶";s:1:"W";s:4:"𝖷";s:1:"X";s:4:"𝖸";s:1:"Y";s:4:"𝖹";s:1:"Z";s:4:"𝖺";s:1:"a";s:4:"𝖻";s:1:"b";s:4:"𝖼";s:1:"c";s:4:"𝖽";s:1:"d";s:4:"𝖾";s:1:"e";s:4:"𝖿";s:1:"f";s:4:"𝗀";s:1:"g";s:4:"𝗁";s:1:"h";s:4:"𝗂";s:1:"i";s:4:"𝗃";s:1:"j";s:4:"𝗄";s:1:"k";s:4:"𝗅";s:1:"l";s:4:"𝗆";s:1:"m";s:4:"𝗇";s:1:"n";s:4:"𝗈";s:1:"o";s:4:"𝗉";s:1:"p";s:4:"𝗊";s:1:"q";s:4:"𝗋";s:1:"r";s:4:"𝗌";s:1:"s";s:4:"𝗍";s:1:"t";s:4:"𝗎";s:1:"u";s:4:"𝗏";s:1:"v";s:4:"𝗐";s:1:"w";s:4:"𝗑";s:1:"x";s:4:"𝗒";s:1:"y";s:4:"𝗓";s:1:"z";s:4:"𝗔";s:1:"A";s:4:"𝗕";s:1:"B";s:4:"𝗖";s:1:"C";s:4:"𝗗";s:1:"D";s:4:"𝗘";s:1:"E";s:4:"𝗙";s:1:"F";s:4:"𝗚";s:1:"G";s:4:"𝗛";s:1:"H";s:4:"𝗜";s:1:"I";s:4:"𝗝";s:1:"J";s:4:"𝗞";s:1:"K";s:4:"𝗟";s:1:"L";s:4:"𝗠";s:1:"M";s:4:"𝗡";s:1:"N";s:4:"𝗢";s:1:"O";s:4:"𝗣";s:1:"P";s:4:"𝗤";s:1:"Q";s:4:"𝗥";s:1:"R";s:4:"𝗦";s:1:"S";s:4:"𝗧";s:1:"T";s:4:"𝗨";s:1:"U";s:4:"𝗩";s:1:"V";s:4:"𝗪";s:1:"W";s:4:"𝗫";s:1:"X";s:4:"𝗬";s:1:"Y";s:4:"𝗭";s:1:"Z";s:4:"𝗮";s:1:"a";s:4:"𝗯";s:1:"b";s:4:"𝗰";s:1:"c";s:4:"𝗱";s:1:"d";s:4:"𝗲";s:1:"e";s:4:"𝗳";s:1:"f";s:4:"𝗴";s:1:"g";s:4:"𝗵";s:1:"h";s:4:"𝗶";s:1:"i";s:4:"𝗷";s:1:"j";s:4:"𝗸";s:1:"k";s:4:"𝗹";s:1:"l";s:4:"𝗺";s:1:"m";s:4:"𝗻";s:1:"n";s:4:"𝗼";s:1:"o";s:4:"𝗽";s:1:"p";s:4:"𝗾";s:1:"q";s:4:"𝗿";s:1:"r";s:4:"𝘀";s:1:"s";s:4:"𝘁";s:1:"t";s:4:"𝘂";s:1:"u";s:4:"𝘃";s:1:"v";s:4:"𝘄";s:1:"w";s:4:"𝘅";s:1:"x";s:4:"𝘆";s:1:"y";s:4:"𝘇";s:1:"z";s:4:"𝘈";s:1:"A";s:4:"𝘉";s:1:"B";s:4:"𝘊";s:1:"C";s:4:"𝘋";s:1:"D";s:4:"𝘌";s:1:"E";s:4:"𝘍";s:1:"F";s:4:"𝘎";s:1:"G";s:4:"𝘏";s:1:"H";s:4:"𝘐";s:1:"I";s:4:"𝘑";s:1:"J";s:4:"𝘒";s:1:"K";s:4:"𝘓";s:1:"L";s:4:"𝘔";s:1:"M";s:4:"𝘕";s:1:"N";s:4:"𝘖";s:1:"O";s:4:"𝘗";s:1:"P";s:4:"𝘘";s:1:"Q";s:4:"𝘙";s:1:"R";s:4:"𝘚";s:1:"S";s:4:"𝘛";s:1:"T";s:4:"𝘜";s:1:"U";s:4:"𝘝";s:1:"V";s:4:"𝘞";s:1:"W";s:4:"𝘟";s:1:"X";s:4:"𝘠";s:1:"Y";s:4:"𝘡";s:1:"Z";s:4:"𝘢";s:1:"a";s:4:"𝘣";s:1:"b";s:4:"𝘤";s:1:"c";s:4:"𝘥";s:1:"d";s:4:"𝘦";s:1:"e";s:4:"𝘧";s:1:"f";s:4:"𝘨";s:1:"g";s:4:"𝘩";s:1:"h";s:4:"𝘪";s:1:"i";s:4:"𝘫";s:1:"j";s:4:"𝘬";s:1:"k";s:4:"𝘭";s:1:"l";s:4:"𝘮";s:1:"m";s:4:"𝘯";s:1:"n";s:4:"𝘰";s:1:"o";s:4:"𝘱";s:1:"p";s:4:"𝘲";s:1:"q";s:4:"𝘳";s:1:"r";s:4:"𝘴";s:1:"s";s:4:"𝘵";s:1:"t";s:4:"𝘶";s:1:"u";s:4:"𝘷";s:1:"v";s:4:"𝘸";s:1:"w";s:4:"𝘹";s:1:"x";s:4:"𝘺";s:1:"y";s:4:"𝘻";s:1:"z";s:4:"𝘼";s:1:"A";s:4:"𝘽";s:1:"B";s:4:"𝘾";s:1:"C";s:4:"𝘿";s:1:"D";s:4:"𝙀";s:1:"E";s:4:"𝙁";s:1:"F";s:4:"𝙂";s:1:"G";s:4:"𝙃";s:1:"H";s:4:"𝙄";s:1:"I";s:4:"𝙅";s:1:"J";s:4:"𝙆";s:1:"K";s:4:"𝙇";s:1:"L";s:4:"𝙈";s:1:"M";s:4:"𝙉";s:1:"N";s:4:"𝙊";s:1:"O";s:4:"𝙋";s:1:"P";s:4:"𝙌";s:1:"Q";s:4:"𝙍";s:1:"R";s:4:"𝙎";s:1:"S";s:4:"𝙏";s:1:"T";s:4:"𝙐";s:1:"U";s:4:"𝙑";s:1:"V";s:4:"𝙒";s:1:"W";s:4:"𝙓";s:1:"X";s:4:"𝙔";s:1:"Y";s:4:"𝙕";s:1:"Z";s:4:"𝙖";s:1:"a";s:4:"𝙗";s:1:"b";s:4:"𝙘";s:1:"c";s:4:"𝙙";s:1:"d";s:4:"𝙚";s:1:"e";s:4:"𝙛";s:1:"f";s:4:"𝙜";s:1:"g";s:4:"𝙝";s:1:"h";s:4:"𝙞";s:1:"i";s:4:"𝙟";s:1:"j";s:4:"𝙠";s:1:"k";s:4:"𝙡";s:1:"l";s:4:"𝙢";s:1:"m";s:4:"𝙣";s:1:"n";s:4:"𝙤";s:1:"o";s:4:"𝙥";s:1:"p";s:4:"𝙦";s:1:"q";s:4:"𝙧";s:1:"r";s:4:"𝙨";s:1:"s";s:4:"𝙩";s:1:"t";s:4:"𝙪";s:1:"u";s:4:"𝙫";s:1:"v";s:4:"𝙬";s:1:"w";s:4:"𝙭";s:1:"x";s:4:"𝙮";s:1:"y";s:4:"𝙯";s:1:"z";s:4:"𝙰";s:1:"A";s:4:"𝙱";s:1:"B";s:4:"𝙲";s:1:"C";s:4:"𝙳";s:1:"D";s:4:"𝙴";s:1:"E";s:4:"𝙵";s:1:"F";s:4:"𝙶";s:1:"G";s:4:"𝙷";s:1:"H";s:4:"𝙸";s:1:"I";s:4:"𝙹";s:1:"J";s:4:"𝙺";s:1:"K";s:4:"𝙻";s:1:"L";s:4:"𝙼";s:1:"M";s:4:"𝙽";s:1:"N";s:4:"𝙾";s:1:"O";s:4:"𝙿";s:1:"P";s:4:"𝚀";s:1:"Q";s:4:"𝚁";s:1:"R";s:4:"𝚂";s:1:"S";s:4:"𝚃";s:1:"T";s:4:"𝚄";s:1:"U";s:4:"𝚅";s:1:"V";s:4:"𝚆";s:1:"W";s:4:"𝚇";s:1:"X";s:4:"𝚈";s:1:"Y";s:4:"𝚉";s:1:"Z";s:4:"𝚊";s:1:"a";s:4:"𝚋";s:1:"b";s:4:"𝚌";s:1:"c";s:4:"𝚍";s:1:"d";s:4:"𝚎";s:1:"e";s:4:"𝚏";s:1:"f";s:4:"𝚐";s:1:"g";s:4:"𝚑";s:1:"h";s:4:"𝚒";s:1:"i";s:4:"𝚓";s:1:"j";s:4:"𝚔";s:1:"k";s:4:"𝚕";s:1:"l";s:4:"𝚖";s:1:"m";s:4:"𝚗";s:1:"n";s:4:"𝚘";s:1:"o";s:4:"𝚙";s:1:"p";s:4:"𝚚";s:1:"q";s:4:"𝚛";s:1:"r";s:4:"𝚜";s:1:"s";s:4:"𝚝";s:1:"t";s:4:"𝚞";s:1:"u";s:4:"𝚟";s:1:"v";s:4:"𝚠";s:1:"w";s:4:"𝚡";s:1:"x";s:4:"𝚢";s:1:"y";s:4:"𝚣";s:1:"z";s:4:"𝚤";s:2:"ı";s:4:"𝚥";s:2:"ȷ";s:4:"𝚨";s:2:"Α";s:4:"𝚩";s:2:"Β";s:4:"𝚪";s:2:"Γ";s:4:"𝚫";s:2:"Δ";s:4:"𝚬";s:2:"Ε";s:4:"𝚭";s:2:"Ζ";s:4:"𝚮";s:2:"Η";s:4:"𝚯";s:2:"Θ";s:4:"𝚰";s:2:"Ι";s:4:"𝚱";s:2:"Κ";s:4:"𝚲";s:2:"Λ";s:4:"𝚳";s:2:"Μ";s:4:"𝚴";s:2:"Ν";s:4:"𝚵";s:2:"Ξ";s:4:"𝚶";s:2:"Ο";s:4:"𝚷";s:2:"Π";s:4:"𝚸";s:2:"Ρ";s:4:"𝚹";s:2:"Θ";s:4:"𝚺";s:2:"Σ";s:4:"𝚻";s:2:"Τ";s:4:"𝚼";s:2:"Υ";s:4:"𝚽";s:2:"Φ";s:4:"𝚾";s:2:"Χ";s:4:"𝚿";s:2:"Ψ";s:4:"𝛀";s:2:"Ω";s:4:"𝛁";s:3:"∇";s:4:"𝛂";s:2:"α";s:4:"𝛃";s:2:"β";s:4:"𝛄";s:2:"γ";s:4:"𝛅";s:2:"δ";s:4:"𝛆";s:2:"ε";s:4:"𝛇";s:2:"ζ";s:4:"𝛈";s:2:"η";s:4:"𝛉";s:2:"θ";s:4:"𝛊";s:2:"ι";s:4:"𝛋";s:2:"κ";s:4:"𝛌";s:2:"λ";s:4:"𝛍";s:2:"μ";s:4:"𝛎";s:2:"ν";s:4:"𝛏";s:2:"ξ";s:4:"𝛐";s:2:"ο";s:4:"𝛑";s:2:"π";s:4:"𝛒";s:2:"ρ";s:4:"𝛓";s:2:"ς";s:4:"𝛔";s:2:"σ";s:4:"𝛕";s:2:"τ";s:4:"𝛖";s:2:"υ";s:4:"𝛗";s:2:"φ";s:4:"𝛘";s:2:"χ";s:4:"𝛙";s:2:"ψ";s:4:"𝛚";s:2:"ω";s:4:"𝛛";s:3:"∂";s:4:"𝛜";s:2:"ε";s:4:"𝛝";s:2:"θ";s:4:"𝛞";s:2:"κ";s:4:"𝛟";s:2:"φ";s:4:"𝛠";s:2:"ρ";s:4:"𝛡";s:2:"π";s:4:"𝛢";s:2:"Α";s:4:"𝛣";s:2:"Β";s:4:"𝛤";s:2:"Γ";s:4:"𝛥";s:2:"Δ";s:4:"𝛦";s:2:"Ε";s:4:"𝛧";s:2:"Ζ";s:4:"𝛨";s:2:"Η";s:4:"𝛩";s:2:"Θ";s:4:"𝛪";s:2:"Ι";s:4:"𝛫";s:2:"Κ";s:4:"𝛬";s:2:"Λ";s:4:"𝛭";s:2:"Μ";s:4:"𝛮";s:2:"Ν";s:4:"𝛯";s:2:"Ξ";s:4:"𝛰";s:2:"Ο";s:4:"𝛱";s:2:"Π";s:4:"𝛲";s:2:"Ρ";s:4:"𝛳";s:2:"Θ";s:4:"𝛴";s:2:"Σ";s:4:"𝛵";s:2:"Τ";s:4:"𝛶";s:2:"Υ";s:4:"𝛷";s:2:"Φ";s:4:"𝛸";s:2:"Χ";s:4:"𝛹";s:2:"Ψ";s:4:"𝛺";s:2:"Ω";s:4:"𝛻";s:3:"∇";s:4:"𝛼";s:2:"α";s:4:"𝛽";s:2:"β";s:4:"𝛾";s:2:"γ";s:4:"𝛿";s:2:"δ";s:4:"𝜀";s:2:"ε";s:4:"𝜁";s:2:"ζ";s:4:"𝜂";s:2:"η";s:4:"𝜃";s:2:"θ";s:4:"𝜄";s:2:"ι";s:4:"𝜅";s:2:"κ";s:4:"𝜆";s:2:"λ";s:4:"𝜇";s:2:"μ";s:4:"𝜈";s:2:"ν";s:4:"𝜉";s:2:"ξ";s:4:"𝜊";s:2:"ο";s:4:"𝜋";s:2:"π";s:4:"𝜌";s:2:"ρ";s:4:"𝜍";s:2:"ς";s:4:"𝜎";s:2:"σ";s:4:"𝜏";s:2:"τ";s:4:"𝜐";s:2:"υ";s:4:"𝜑";s:2:"φ";s:4:"𝜒";s:2:"χ";s:4:"𝜓";s:2:"ψ";s:4:"𝜔";s:2:"ω";s:4:"𝜕";s:3:"∂";s:4:"𝜖";s:2:"ε";s:4:"𝜗";s:2:"θ";s:4:"𝜘";s:2:"κ";s:4:"𝜙";s:2:"φ";s:4:"𝜚";s:2:"ρ";s:4:"𝜛";s:2:"π";s:4:"𝜜";s:2:"Α";s:4:"𝜝";s:2:"Β";s:4:"𝜞";s:2:"Γ";s:4:"𝜟";s:2:"Δ";s:4:"𝜠";s:2:"Ε";s:4:"𝜡";s:2:"Ζ";s:4:"𝜢";s:2:"Η";s:4:"𝜣";s:2:"Θ";s:4:"𝜤";s:2:"Ι";s:4:"𝜥";s:2:"Κ";s:4:"𝜦";s:2:"Λ";s:4:"𝜧";s:2:"Μ";s:4:"𝜨";s:2:"Ν";s:4:"𝜩";s:2:"Ξ";s:4:"𝜪";s:2:"Ο";s:4:"𝜫";s:2:"Π";s:4:"𝜬";s:2:"Ρ";s:4:"𝜭";s:2:"Θ";s:4:"𝜮";s:2:"Σ";s:4:"𝜯";s:2:"Τ";s:4:"𝜰";s:2:"Υ";s:4:"𝜱";s:2:"Φ";s:4:"𝜲";s:2:"Χ";s:4:"𝜳";s:2:"Ψ";s:4:"𝜴";s:2:"Ω";s:4:"𝜵";s:3:"∇";s:4:"𝜶";s:2:"α";s:4:"𝜷";s:2:"β";s:4:"𝜸";s:2:"γ";s:4:"𝜹";s:2:"δ";s:4:"𝜺";s:2:"ε";s:4:"𝜻";s:2:"ζ";s:4:"𝜼";s:2:"η";s:4:"𝜽";s:2:"θ";s:4:"𝜾";s:2:"ι";s:4:"𝜿";s:2:"κ";s:4:"𝝀";s:2:"λ";s:4:"𝝁";s:2:"μ";s:4:"𝝂";s:2:"ν";s:4:"𝝃";s:2:"ξ";s:4:"𝝄";s:2:"ο";s:4:"𝝅";s:2:"π";s:4:"𝝆";s:2:"ρ";s:4:"𝝇";s:2:"ς";s:4:"𝝈";s:2:"σ";s:4:"𝝉";s:2:"τ";s:4:"𝝊";s:2:"υ";s:4:"𝝋";s:2:"φ";s:4:"𝝌";s:2:"χ";s:4:"𝝍";s:2:"ψ";s:4:"𝝎";s:2:"ω";s:4:"𝝏";s:3:"∂";s:4:"𝝐";s:2:"ε";s:4:"𝝑";s:2:"θ";s:4:"𝝒";s:2:"κ";s:4:"𝝓";s:2:"φ";s:4:"𝝔";s:2:"ρ";s:4:"𝝕";s:2:"π";s:4:"𝝖";s:2:"Α";s:4:"𝝗";s:2:"Β";s:4:"𝝘";s:2:"Γ";s:4:"𝝙";s:2:"Δ";s:4:"𝝚";s:2:"Ε";s:4:"𝝛";s:2:"Ζ";s:4:"𝝜";s:2:"Η";s:4:"𝝝";s:2:"Θ";s:4:"𝝞";s:2:"Ι";s:4:"𝝟";s:2:"Κ";s:4:"𝝠";s:2:"Λ";s:4:"𝝡";s:2:"Μ";s:4:"𝝢";s:2:"Ν";s:4:"𝝣";s:2:"Ξ";s:4:"𝝤";s:2:"Ο";s:4:"𝝥";s:2:"Π";s:4:"𝝦";s:2:"Ρ";s:4:"𝝧";s:2:"Θ";s:4:"𝝨";s:2:"Σ";s:4:"𝝩";s:2:"Τ";s:4:"𝝪";s:2:"Υ";s:4:"𝝫";s:2:"Φ";s:4:"𝝬";s:2:"Χ";s:4:"𝝭";s:2:"Ψ";s:4:"𝝮";s:2:"Ω";s:4:"𝝯";s:3:"∇";s:4:"𝝰";s:2:"α";s:4:"𝝱";s:2:"β";s:4:"𝝲";s:2:"γ";s:4:"𝝳";s:2:"δ";s:4:"𝝴";s:2:"ε";s:4:"𝝵";s:2:"ζ";s:4:"𝝶";s:2:"η";s:4:"𝝷";s:2:"θ";s:4:"𝝸";s:2:"ι";s:4:"𝝹";s:2:"κ";s:4:"𝝺";s:2:"λ";s:4:"𝝻";s:2:"μ";s:4:"𝝼";s:2:"ν";s:4:"𝝽";s:2:"ξ";s:4:"𝝾";s:2:"ο";s:4:"𝝿";s:2:"π";s:4:"𝞀";s:2:"ρ";s:4:"𝞁";s:2:"ς";s:4:"𝞂";s:2:"σ";s:4:"𝞃";s:2:"τ";s:4:"𝞄";s:2:"υ";s:4:"𝞅";s:2:"φ";s:4:"𝞆";s:2:"χ";s:4:"𝞇";s:2:"ψ";s:4:"𝞈";s:2:"ω";s:4:"𝞉";s:3:"∂";s:4:"𝞊";s:2:"ε";s:4:"𝞋";s:2:"θ";s:4:"𝞌";s:2:"κ";s:4:"𝞍";s:2:"φ";s:4:"𝞎";s:2:"ρ";s:4:"𝞏";s:2:"π";s:4:"𝞐";s:2:"Α";s:4:"𝞑";s:2:"Β";s:4:"𝞒";s:2:"Γ";s:4:"𝞓";s:2:"Δ";s:4:"𝞔";s:2:"Ε";s:4:"𝞕";s:2:"Ζ";s:4:"𝞖";s:2:"Η";s:4:"𝞗";s:2:"Θ";s:4:"𝞘";s:2:"Ι";s:4:"𝞙";s:2:"Κ";s:4:"𝞚";s:2:"Λ";s:4:"𝞛";s:2:"Μ";s:4:"𝞜";s:2:"Ν";s:4:"𝞝";s:2:"Ξ";s:4:"𝞞";s:2:"Ο";s:4:"𝞟";s:2:"Π";s:4:"𝞠";s:2:"Ρ";s:4:"𝞡";s:2:"Θ";s:4:"𝞢";s:2:"Σ";s:4:"𝞣";s:2:"Τ";s:4:"𝞤";s:2:"Υ";s:4:"𝞥";s:2:"Φ";s:4:"𝞦";s:2:"Χ";s:4:"𝞧";s:2:"Ψ";s:4:"𝞨";s:2:"Ω";s:4:"𝞩";s:3:"∇";s:4:"𝞪";s:2:"α";s:4:"𝞫";s:2:"β";s:4:"𝞬";s:2:"γ";s:4:"𝞭";s:2:"δ";s:4:"𝞮";s:2:"ε";s:4:"𝞯";s:2:"ζ";s:4:"𝞰";s:2:"η";s:4:"𝞱";s:2:"θ";s:4:"𝞲";s:2:"ι";s:4:"𝞳";s:2:"κ";s:4:"𝞴";s:2:"λ";s:4:"𝞵";s:2:"μ";s:4:"𝞶";s:2:"ν";s:4:"𝞷";s:2:"ξ";s:4:"𝞸";s:2:"ο";s:4:"𝞹";s:2:"π";s:4:"𝞺";s:2:"ρ";s:4:"𝞻";s:2:"ς";s:4:"𝞼";s:2:"σ";s:4:"𝞽";s:2:"τ";s:4:"𝞾";s:2:"υ";s:4:"𝞿";s:2:"φ";s:4:"𝟀";s:2:"χ";s:4:"𝟁";s:2:"ψ";s:4:"𝟂";s:2:"ω";s:4:"𝟃";s:3:"∂";s:4:"𝟄";s:2:"ε";s:4:"𝟅";s:2:"θ";s:4:"𝟆";s:2:"κ";s:4:"𝟇";s:2:"φ";s:4:"𝟈";s:2:"ρ";s:4:"𝟉";s:2:"π";s:4:"𝟎";s:1:"0";s:4:"𝟏";s:1:"1";s:4:"𝟐";s:1:"2";s:4:"𝟑";s:1:"3";s:4:"𝟒";s:1:"4";s:4:"𝟓";s:1:"5";s:4:"𝟔";s:1:"6";s:4:"𝟕";s:1:"7";s:4:"𝟖";s:1:"8";s:4:"𝟗";s:1:"9";s:4:"𝟘";s:1:"0";s:4:"𝟙";s:1:"1";s:4:"𝟚";s:1:"2";s:4:"𝟛";s:1:"3";s:4:"𝟜";s:1:"4";s:4:"𝟝";s:1:"5";s:4:"𝟞";s:1:"6";s:4:"𝟟";s:1:"7";s:4:"𝟠";s:1:"8";s:4:"𝟡";s:1:"9";s:4:"𝟢";s:1:"0";s:4:"𝟣";s:1:"1";s:4:"𝟤";s:1:"2";s:4:"𝟥";s:1:"3";s:4:"𝟦";s:1:"4";s:4:"𝟧";s:1:"5";s:4:"𝟨";s:1:"6";s:4:"𝟩";s:1:"7";s:4:"𝟪";s:1:"8";s:4:"𝟫";s:1:"9";s:4:"𝟬";s:1:"0";s:4:"𝟭";s:1:"1";s:4:"𝟮";s:1:"2";s:4:"𝟯";s:1:"3";s:4:"𝟰";s:1:"4";s:4:"𝟱";s:1:"5";s:4:"𝟲";s:1:"6";s:4:"𝟳";s:1:"7";s:4:"𝟴";s:1:"8";s:4:"𝟵";s:1:"9";s:4:"𝟶";s:1:"0";s:4:"𝟷";s:1:"1";s:4:"𝟸";s:1:"2";s:4:"𝟹";s:1:"3";s:4:"𝟺";s:1:"4";s:4:"𝟻";s:1:"5";s:4:"𝟼";s:1:"6";s:4:"𝟽";s:1:"7";s:4:"𝟾";s:1:"8";s:4:"𝟿";s:1:"9";s:4:"丽";s:3:"丽";s:4:"丸";s:3:"丸";s:4:"乁";s:3:"乁";s:4:"𠄢";s:4:"𠄢";s:4:"你";s:3:"你";s:4:"侮";s:3:"侮";s:4:"侻";s:3:"侻";s:4:"倂";s:3:"倂";s:4:"偺";s:3:"偺";s:4:"備";s:3:"備";s:4:"僧";s:3:"僧";s:4:"像";s:3:"像";s:4:"㒞";s:3:"㒞";s:4:"𠘺";s:4:"𠘺";s:4:"免";s:3:"免";s:4:"兔";s:3:"兔";s:4:"兤";s:3:"兤";s:4:"具";s:3:"具";s:4:"𠔜";s:4:"𠔜";s:4:"㒹";s:3:"㒹";s:4:"內";s:3:"內";s:4:"再";s:3:"再";s:4:"𠕋";s:4:"𠕋";s:4:"冗";s:3:"冗";s:4:"冤";s:3:"冤";s:4:"仌";s:3:"仌";s:4:"冬";s:3:"冬";s:4:"况";s:3:"况";s:4:"𩇟";s:4:"𩇟";s:4:"凵";s:3:"凵";s:4:"刃";s:3:"刃";s:4:"㓟";s:3:"㓟";s:4:"刻";s:3:"刻";s:4:"剆";s:3:"剆";s:4:"割";s:3:"割";s:4:"剷";s:3:"剷";s:4:"㔕";s:3:"㔕";s:4:"勇";s:3:"勇";s:4:"勉";s:3:"勉";s:4:"勤";s:3:"勤";s:4:"勺";s:3:"勺";s:4:"包";s:3:"包";s:4:"匆";s:3:"匆";s:4:"北";s:3:"北";s:4:"卉";s:3:"卉";s:4:"卑";s:3:"卑";s:4:"博";s:3:"博";s:4:"即";s:3:"即";s:4:"卽";s:3:"卽";s:4:"卿";s:3:"卿";s:4:"卿";s:3:"卿";s:4:"卿";s:3:"卿";s:4:"𠨬";s:4:"𠨬";s:4:"灰";s:3:"灰";s:4:"及";s:3:"及";s:4:"叟";s:3:"叟";s:4:"𠭣";s:4:"𠭣";s:4:"叫";s:3:"叫";s:4:"叱";s:3:"叱";s:4:"吆";s:3:"吆";s:4:"咞";s:3:"咞";s:4:"吸";s:3:"吸";s:4:"呈";s:3:"呈";s:4:"周";s:3:"周";s:4:"咢";s:3:"咢";s:4:"哶";s:3:"哶";s:4:"唐";s:3:"唐";s:4:"啓";s:3:"啓";s:4:"啣";s:3:"啣";s:4:"善";s:3:"善";s:4:"善";s:3:"善";s:4:"喙";s:3:"喙";s:4:"喫";s:3:"喫";s:4:"喳";s:3:"喳";s:4:"嗂";s:3:"嗂";s:4:"圖";s:3:"圖";s:4:"嘆";s:3:"嘆";s:4:"圗";s:3:"圗";s:4:"噑";s:3:"噑";s:4:"噴";s:3:"噴";s:4:"切";s:3:"切";s:4:"壮";s:3:"壮";s:4:"城";s:3:"城";s:4:"埴";s:3:"埴";s:4:"堍";s:3:"堍";s:4:"型";s:3:"型";s:4:"堲";s:3:"堲";s:4:"報";s:3:"報";s:4:"墬";s:3:"墬";s:4:"𡓤";s:4:"𡓤";s:4:"売";s:3:"売";s:4:"壷";s:3:"壷";s:4:"夆";s:3:"夆";s:4:"多";s:3:"多";s:4:"夢";s:3:"夢";s:4:"奢";s:3:"奢";s:4:"𡚨";s:4:"𡚨";s:4:"𡛪";s:4:"𡛪";s:4:"姬";s:3:"姬";s:4:"娛";s:3:"娛";s:4:"娧";s:3:"娧";s:4:"姘";s:3:"姘";s:4:"婦";s:3:"婦";s:4:"㛮";s:3:"㛮";s:4:"㛼";s:3:"㛼";s:4:"嬈";s:3:"嬈";s:4:"嬾";s:3:"嬾";s:4:"嬾";s:3:"嬾";s:4:"𡧈";s:4:"𡧈";s:4:"寃";s:3:"寃";s:4:"寘";s:3:"寘";s:4:"寧";s:3:"寧";s:4:"寳";s:3:"寳";s:4:"𡬘";s:4:"𡬘";s:4:"寿";s:3:"寿";s:4:"将";s:3:"将";s:4:"当";s:3:"当";s:4:"尢";s:3:"尢";s:4:"㞁";s:3:"㞁";s:4:"屠";s:3:"屠";s:4:"屮";s:3:"屮";s:4:"峀";s:3:"峀";s:4:"岍";s:3:"岍";s:4:"𡷤";s:4:"𡷤";s:4:"嵃";s:3:"嵃";s:4:"𡷦";s:4:"𡷦";s:4:"嵮";s:3:"嵮";s:4:"嵫";s:3:"嵫";s:4:"嵼";s:3:"嵼";s:4:"巡";s:3:"巡";s:4:"巢";s:3:"巢";s:4:"㠯";s:3:"㠯";s:4:"巽";s:3:"巽";s:4:"帨";s:3:"帨";s:4:"帽";s:3:"帽";s:4:"幩";s:3:"幩";s:4:"㡢";s:3:"㡢";s:4:"𢆃";s:4:"𢆃";s:4:"㡼";s:3:"㡼";s:4:"庰";s:3:"庰";s:4:"庳";s:3:"庳";s:4:"庶";s:3:"庶";s:4:"廊";s:3:"廊";s:4:"𪎒";s:4:"𪎒";s:4:"廾";s:3:"廾";s:4:"𢌱";s:4:"𢌱";s:4:"𢌱";s:4:"𢌱";s:4:"舁";s:3:"舁";s:4:"弢";s:3:"弢";s:4:"弢";s:3:"弢";s:4:"㣇";s:3:"㣇";s:4:"𣊸";s:4:"𣊸";s:4:"𦇚";s:4:"𦇚";s:4:"形";s:3:"形";s:4:"彫";s:3:"彫";s:4:"㣣";s:3:"㣣";s:4:"徚";s:3:"徚";s:4:"忍";s:3:"忍";s:4:"志";s:3:"志";s:4:"忹";s:3:"忹";s:4:"悁";s:3:"悁";s:4:"㤺";s:3:"㤺";s:4:"㤜";s:3:"㤜";s:4:"悔";s:3:"悔";s:4:"𢛔";s:4:"𢛔";s:4:"惇";s:3:"惇";s:4:"慈";s:3:"慈";s:4:"慌";s:3:"慌";s:4:"慎";s:3:"慎";s:4:"慌";s:3:"慌";s:4:"慺";s:3:"慺";s:4:"憎";s:3:"憎";s:4:"憲";s:3:"憲";s:4:"憤";s:3:"憤";s:4:"憯";s:3:"憯";s:4:"懞";s:3:"懞";s:4:"懲";s:3:"懲";s:4:"懶";s:3:"懶";s:4:"成";s:3:"成";s:4:"戛";s:3:"戛";s:4:"扝";s:3:"扝";s:4:"抱";s:3:"抱";s:4:"拔";s:3:"拔";s:4:"捐";s:3:"捐";s:4:"𢬌";s:4:"𢬌";s:4:"挽";s:3:"挽";s:4:"拼";s:3:"拼";s:4:"捨";s:3:"捨";s:4:"掃";s:3:"掃";s:4:"揤";s:3:"揤";s:4:"𢯱";s:4:"𢯱";s:4:"搢";s:3:"搢";s:4:"揅";s:3:"揅";s:4:"掩";s:3:"掩";s:4:"㨮";s:3:"㨮";s:4:"摩";s:3:"摩";s:4:"摾";s:3:"摾";s:4:"撝";s:3:"撝";s:4:"摷";s:3:"摷";s:4:"㩬";s:3:"㩬";s:4:"敏";s:3:"敏";s:4:"敬";s:3:"敬";s:4:"𣀊";s:4:"𣀊";s:4:"旣";s:3:"旣";s:4:"書";s:3:"書";s:4:"晉";s:3:"晉";s:4:"㬙";s:3:"㬙";s:4:"暑";s:3:"暑";s:4:"㬈";s:3:"㬈";s:4:"㫤";s:3:"㫤";s:4:"冒";s:3:"冒";s:4:"冕";s:3:"冕";s:4:"最";s:3:"最";s:4:"暜";s:3:"暜";s:4:"肭";s:3:"肭";s:4:"䏙";s:3:"䏙";s:4:"朗";s:3:"朗";s:4:"望";s:3:"望";s:4:"朡";s:3:"朡";s:4:"杞";s:3:"杞";s:4:"杓";s:3:"杓";s:4:"𣏃";s:4:"𣏃";s:4:"㭉";s:3:"㭉";s:4:"柺";s:3:"柺";s:4:"枅";s:3:"枅";s:4:"桒";s:3:"桒";s:4:"梅";s:3:"梅";s:4:"𣑭";s:4:"𣑭";s:4:"梎";s:3:"梎";s:4:"栟";s:3:"栟";s:4:"椔";s:3:"椔";s:4:"㮝";s:3:"㮝";s:4:"楂";s:3:"楂";s:4:"榣";s:3:"榣";s:4:"槪";s:3:"槪";s:4:"檨";s:3:"檨";s:4:"𣚣";s:4:"𣚣";s:4:"櫛";s:3:"櫛";s:4:"㰘";s:3:"㰘";s:4:"次";s:3:"次";s:4:"𣢧";s:4:"𣢧";s:4:"歔";s:3:"歔";s:4:"㱎";s:3:"㱎";s:4:"歲";s:3:"歲";s:4:"殟";s:3:"殟";s:4:"殺";s:3:"殺";s:4:"殻";s:3:"殻";s:4:"𣪍";s:4:"𣪍";s:4:"𡴋";s:4:"𡴋";s:4:"𣫺";s:4:"𣫺";s:4:"汎";s:3:"汎";s:4:"𣲼";s:4:"𣲼";s:4:"沿";s:3:"沿";s:4:"泍";s:3:"泍";s:4:"汧";s:3:"汧";s:4:"洖";s:3:"洖";s:4:"派";s:3:"派";s:4:"海";s:3:"海";s:4:"流";s:3:"流";s:4:"浩";s:3:"浩";s:4:"浸";s:3:"浸";s:4:"涅";s:3:"涅";s:4:"𣴞";s:4:"𣴞";s:4:"洴";s:3:"洴";s:4:"港";s:3:"港";s:4:"湮";s:3:"湮";s:4:"㴳";s:3:"㴳";s:4:"滋";s:3:"滋";s:4:"滇";s:3:"滇";s:4:"𣻑";s:4:"𣻑";s:4:"淹";s:3:"淹";s:4:"潮";s:3:"潮";s:4:"𣽞";s:4:"𣽞";s:4:"𣾎";s:4:"𣾎";s:4:"濆";s:3:"濆";s:4:"瀹";s:3:"瀹";s:4:"瀞";s:3:"瀞";s:4:"瀛";s:3:"瀛";s:4:"㶖";s:3:"㶖";s:4:"灊";s:3:"灊";s:4:"災";s:3:"災";s:4:"灷";s:3:"灷";s:4:"炭";s:3:"炭";s:4:"𠔥";s:4:"𠔥";s:4:"煅";s:3:"煅";s:4:"𤉣";s:4:"𤉣";s:4:"熜";s:3:"熜";s:4:"𤎫";s:4:"𤎫";s:4:"爨";s:3:"爨";s:4:"爵";s:3:"爵";s:4:"牐";s:3:"牐";s:4:"𤘈";s:4:"𤘈";s:4:"犀";s:3:"犀";s:4:"犕";s:3:"犕";s:4:"𤜵";s:4:"𤜵";s:4:"𤠔";s:4:"𤠔";s:4:"獺";s:3:"獺";s:4:"王";s:3:"王";s:4:"㺬";s:3:"㺬";s:4:"玥";s:3:"玥";s:4:"㺸";s:3:"㺸";s:4:"㺸";s:3:"㺸";s:4:"瑇";s:3:"瑇";s:4:"瑜";s:3:"瑜";s:4:"瑱";s:3:"瑱";s:4:"璅";s:3:"璅";s:4:"瓊";s:3:"瓊";s:4:"㼛";s:3:"㼛";s:4:"甤";s:3:"甤";s:4:"𤰶";s:4:"𤰶";s:4:"甾";s:3:"甾";s:4:"𤲒";s:4:"𤲒";s:4:"異";s:3:"異";s:4:"𢆟";s:4:"𢆟";s:4:"瘐";s:3:"瘐";s:4:"𤾡";s:4:"𤾡";s:4:"𤾸";s:4:"𤾸";s:4:"𥁄";s:4:"𥁄";s:4:"㿼";s:3:"㿼";s:4:"䀈";s:3:"䀈";s:4:"直";s:3:"直";s:4:"𥃳";s:4:"𥃳";s:4:"𥃲";s:4:"𥃲";s:4:"𥄙";s:4:"𥄙";s:4:"𥄳";s:4:"𥄳";s:4:"眞";s:3:"眞";s:4:"真";s:3:"真";s:4:"真";s:3:"真";s:4:"睊";s:3:"睊";s:4:"䀹";s:3:"䀹";s:4:"瞋";s:3:"瞋";s:4:"䁆";s:3:"䁆";s:4:"䂖";s:3:"䂖";s:4:"𥐝";s:4:"𥐝";s:4:"硎";s:3:"硎";s:4:"碌";s:3:"碌";s:4:"磌";s:3:"磌";s:4:"䃣";s:3:"䃣";s:4:"𥘦";s:4:"𥘦";s:4:"祖";s:3:"祖";s:4:"𥚚";s:4:"𥚚";s:4:"𥛅";s:4:"𥛅";s:4:"福";s:3:"福";s:4:"秫";s:3:"秫";s:4:"䄯";s:3:"䄯";s:4:"穀";s:3:"穀";s:4:"穊";s:3:"穊";s:4:"穏";s:3:"穏";s:4:"𥥼";s:4:"𥥼";s:4:"𥪧";s:4:"𥪧";s:4:"𥪧";s:4:"𥪧";s:4:"竮";s:3:"竮";s:4:"䈂";s:3:"䈂";s:4:"𥮫";s:4:"𥮫";s:4:"篆";s:3:"篆";s:4:"築";s:3:"築";s:4:"䈧";s:3:"䈧";s:4:"𥲀";s:4:"𥲀";s:4:"糒";s:3:"糒";s:4:"䊠";s:3:"䊠";s:4:"糨";s:3:"糨";s:4:"糣";s:3:"糣";s:4:"紀";s:3:"紀";s:4:"𥾆";s:4:"𥾆";s:4:"絣";s:3:"絣";s:4:"䌁";s:3:"䌁";s:4:"緇";s:3:"緇";s:4:"縂";s:3:"縂";s:4:"繅";s:3:"繅";s:4:"䌴";s:3:"䌴";s:4:"𦈨";s:4:"𦈨";s:4:"𦉇";s:4:"𦉇";s:4:"䍙";s:3:"䍙";s:4:"𦋙";s:4:"𦋙";s:4:"罺";s:3:"罺";s:4:"𦌾";s:4:"𦌾";s:4:"羕";s:3:"羕";s:4:"翺";s:3:"翺";s:4:"者";s:3:"者";s:4:"𦓚";s:4:"𦓚";s:4:"𦔣";s:4:"𦔣";s:4:"聠";s:3:"聠";s:4:"𦖨";s:4:"𦖨";s:4:"聰";s:3:"聰";s:4:"𣍟";s:4:"𣍟";s:4:"䏕";s:3:"䏕";s:4:"育";s:3:"育";s:4:"脃";s:3:"脃";s:4:"䐋";s:3:"䐋";s:4:"脾";s:3:"脾";s:4:"媵";s:3:"媵";s:4:"𦞧";s:4:"𦞧";s:4:"𦞵";s:4:"𦞵";s:4:"𣎓";s:4:"𣎓";s:4:"𣎜";s:4:"𣎜";s:4:"舁";s:3:"舁";s:4:"舄";s:3:"舄";s:4:"辞";s:3:"辞";s:4:"䑫";s:3:"䑫";s:4:"芑";s:3:"芑";s:4:"芋";s:3:"芋";s:4:"芝";s:3:"芝";s:4:"劳";s:3:"劳";s:4:"花";s:3:"花";s:4:"芳";s:3:"芳";s:4:"芽";s:3:"芽";s:4:"苦";s:3:"苦";s:4:"𦬼";s:4:"𦬼";s:4:"若";s:3:"若";s:4:"茝";s:3:"茝";s:4:"荣";s:3:"荣";s:4:"莭";s:3:"莭";s:4:"茣";s:3:"茣";s:4:"莽";s:3:"莽";s:4:"菧";s:3:"菧";s:4:"著";s:3:"著";s:4:"荓";s:3:"荓";s:4:"菊";s:3:"菊";s:4:"菌";s:3:"菌";s:4:"菜";s:3:"菜";s:4:"𦰶";s:4:"𦰶";s:4:"𦵫";s:4:"𦵫";s:4:"𦳕";s:4:"𦳕";s:4:"䔫";s:3:"䔫";s:4:"蓱";s:3:"蓱";s:4:"蓳";s:3:"蓳";s:4:"蔖";s:3:"蔖";s:4:"𧏊";s:4:"𧏊";s:4:"蕤";s:3:"蕤";s:4:"𦼬";s:4:"𦼬";s:4:"䕝";s:3:"䕝";s:4:"䕡";s:3:"䕡";s:4:"𦾱";s:4:"𦾱";s:4:"𧃒";s:4:"𧃒";s:4:"䕫";s:3:"䕫";s:4:"虐";s:3:"虐";s:4:"虜";s:3:"虜";s:4:"虧";s:3:"虧";s:4:"虩";s:3:"虩";s:4:"蚩";s:3:"蚩";s:4:"蚈";s:3:"蚈";s:4:"蜎";s:3:"蜎";s:4:"蛢";s:3:"蛢";s:4:"蝹";s:3:"蝹";s:4:"蜨";s:3:"蜨";s:4:"蝫";s:3:"蝫";s:4:"螆";s:3:"螆";s:4:"䗗";s:3:"䗗";s:4:"蟡";s:3:"蟡";s:4:"蠁";s:3:"蠁";s:4:"䗹";s:3:"䗹";s:4:"衠";s:3:"衠";s:4:"衣";s:3:"衣";s:4:"𧙧";s:4:"𧙧";s:4:"裗";s:3:"裗";s:4:"裞";s:3:"裞";s:4:"䘵";s:3:"䘵";s:4:"裺";s:3:"裺";s:4:"㒻";s:3:"㒻";s:4:"𧢮";s:4:"𧢮";s:4:"𧥦";s:4:"𧥦";s:4:"䚾";s:3:"䚾";s:4:"䛇";s:3:"䛇";s:4:"誠";s:3:"誠";s:4:"諭";s:3:"諭";s:4:"變";s:3:"變";s:4:"豕";s:3:"豕";s:4:"𧲨";s:4:"𧲨";s:4:"貫";s:3:"貫";s:4:"賁";s:3:"賁";s:4:"贛";s:3:"贛";s:4:"起";s:3:"起";s:4:"𧼯";s:4:"𧼯";s:4:"𠠄";s:4:"𠠄";s:4:"跋";s:3:"跋";s:4:"趼";s:3:"趼";s:4:"跰";s:3:"跰";s:4:"𠣞";s:4:"𠣞";s:4:"軔";s:3:"軔";s:4:"輸";s:3:"輸";s:4:"𨗒";s:4:"𨗒";s:4:"𨗭";s:4:"𨗭";s:4:"邔";s:3:"邔";s:4:"郱";s:3:"郱";s:4:"鄑";s:3:"鄑";s:4:"𨜮";s:4:"𨜮";s:4:"鄛";s:3:"鄛";s:4:"鈸";s:3:"鈸";s:4:"鋗";s:3:"鋗";s:4:"鋘";s:3:"鋘";s:4:"鉼";s:3:"鉼";s:4:"鏹";s:3:"鏹";s:4:"鐕";s:3:"鐕";s:4:"𨯺";s:4:"𨯺";s:4:"開";s:3:"開";s:4:"䦕";s:3:"䦕";s:4:"閷";s:3:"閷";s:4:"𨵷";s:4:"𨵷";s:4:"䧦";s:3:"䧦";s:4:"雃";s:3:"雃";s:4:"嶲";s:3:"嶲";s:4:"霣";s:3:"霣";s:4:"𩅅";s:4:"𩅅";s:4:"𩈚";s:4:"𩈚";s:4:"䩮";s:3:"䩮";s:4:"䩶";s:3:"䩶";s:4:"韠";s:3:"韠";s:4:"𩐊";s:4:"𩐊";s:4:"䪲";s:3:"䪲";s:4:"𩒖";s:4:"𩒖";s:4:"頋";s:3:"頋";s:4:"頋";s:3:"頋";s:4:"頩";s:3:"頩";s:4:"𩖶";s:4:"𩖶";s:4:"飢";s:3:"飢";s:4:"䬳";s:3:"䬳";s:4:"餩";s:3:"餩";s:4:"馧";s:3:"馧";s:4:"駂";s:3:"駂";s:4:"駾";s:3:"駾";s:4:"䯎";s:3:"䯎";s:4:"𩬰";s:4:"𩬰";s:4:"鬒";s:3:"鬒";s:4:"鱀";s:3:"鱀";s:4:"鳽";s:3:"鳽";s:4:"䳎";s:3:"䳎";s:4:"䳭";s:3:"䳭";s:4:"鵧";s:3:"鵧";s:4:"𪃎";s:4:"𪃎";s:4:"䳸";s:3:"䳸";s:4:"𪄅";s:4:"𪄅";s:4:"𪈎";s:4:"𪈎";s:4:"𪊑";s:4:"𪊑";s:4:"麻";s:3:"麻";s:4:"䵖";s:3:"䵖";s:4:"黹";s:3:"黹";s:4:"黾";s:3:"黾";s:4:"鼅";s:3:"鼅";s:4:"鼏";s:3:"鼏";s:4:"鼖";s:3:"鼖";s:4:"鼻";s:3:"鼻";s:4:"𪘀";s:4:"𪘀";}' );
+?>
diff --git a/includes/normal/UtfNormalGenerate.php b/includes/normal/UtfNormalGenerate.php
new file mode 100644 (file)
index 0000000..efe25de
--- /dev/null
@@ -0,0 +1,235 @@
+<?php
+# Copyright (C) 2004 Brion Vibber <brion@pobox.com>
+# http://www.mediawiki.org/
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or 
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# http://www.gnu.org/copyleft/gpl.html
+
+/**
+ * This script generates UniNormalData.inc from the Unicode Character Database
+ * and supplementary files.
+ *
+ * @package UtfNormal
+ * @access private
+ */
+
+/** */
+
+if( php_sapi_name() != 'cli' ) {
+       die( "Run me from the command line please.\n" );
+}
+
+require_once 'UtfNormalUtil.php';
+
+$in = fopen("DerivedNormalizationProps.txt", "rt" );
+if( !$in ) {
+       print "Can't open DerivedNormalizationProps.txt for reading.\n";
+       print "If necessary, fetch this file from the internet:\n";
+       print "http://www.unicode.org/Public/UNIDATA/CompositionExclusions.txt\n";
+       exit(-1);
+}
+print "Initializing normalization quick check tables...\n";
+$checkNFC = array();
+while( false !== ($line = fgets( $in ) ) ) {
+       if( preg_match( '/^([0-9A-F]+)(?:..([0-9A-F]+))?\s*;\s*(NFC_QC)\s*;\s*([MN])/', $line, $matches ) ) {
+               list( $junk, $first, $last, $prop, $value ) = $matches;
+               #print "$first $last $prop $value\n";
+               if( !$last ) $last = $first;
+               for( $i = hexdec( $first ); $i <= hexdec( $last ); $i++) {
+                       $char = codepointToUtf8( $i );
+                       $checkNFC[$char] = $value;
+               }
+       }
+}
+fclose( $in );
+
+$in = fopen("CompositionExclusions.txt", "rt" );
+if( !$in ) {
+       print "Can't open CompositionExclusions.txt for reading.\n";
+       print "If necessary, fetch this file from the internet:\n";
+       print "http://www.unicode.org/Public/UNIDATA/CompositionExclusions.txt\n";
+       exit(-1);
+}
+$exclude = array();
+while( false !== ($line = fgets( $in ) ) ) {
+       if( preg_match( '/^([0-9A-F]+)/i', $line, $matches ) ) {
+               $codepoint = $matches[1];
+               $source = codepointToUtf8( hexdec( $codepoint ) );
+               $exclude[$source] = true;
+       }
+}
+fclose($in);
+
+$in = fopen("UnicodeData.txt", "rt" );
+if( !$in ) {
+       print "Can't open UnicodeData.txt for reading.\n";
+       print "If necessary, fetch this file from the internet:\n";
+       print "http://www.unicode.org/Public/UNIDATA/UnicodeData.txt\n";
+       exit(-1);
+}
+
+$compatibilityDecomp = array();
+$canonicalDecomp = array();
+$canonicalComp = array();
+$combiningClass = array();
+$total = 0;
+$compat = 0;
+$canon = 0;
+
+print "Reading character definitions...\n";
+while( false !== ($line = fgets( $in ) ) ) {
+       $columns = split(';', $line);
+       $codepoint = $columns[0];
+       $name = $columns[1];
+       $canonicalCombiningClass = $columns[3];
+       $decompositionMapping = $columns[5];
+       
+       $source = codepointToUtf8( hexdec( $codepoint ) );
+
+       if( $canonicalCombiningClass != 0 ) {
+               $combiningClass[$source] = IntVal( $canonicalCombiningClass );
+       }
+       
+       if( $decompositionMapping === '' ) continue;
+       if( preg_match( '/^<(.+)> (.*)$/', $decompositionMapping, $matches ) ) {
+               # Compatibility decomposition
+               $canonical = false;
+               $decompositionMapping = $matches[2];
+               $compat++;
+       } else {
+               $canonical = true;
+               $canon++;
+       }
+       $total++;
+       $dest = hexSequenceToUtf8( $decompositionMapping );
+       
+       $compatibilityDecomp[$source] = $dest;
+       if( $canonical ) {
+               $canonicalDecomp[$source] = $dest;
+               if( empty( $exclude[$source] ) ) {
+                       $canonicalComp[$dest] = $source;
+               }
+       }
+       #print "$codepoint | $canonicalCombiningClasses | $decompositionMapping\n";
+}
+fclose( $in );
+
+print "Recursively expanding canonical mappings...\n";
+$changed = 42;
+$pass = 1;
+while( $changed > 0 ) {
+       print "pass $pass\n";
+       $changed = 0;
+       foreach( $canonicalDecomp as $source => $dest ) {
+               $newDest = preg_replace_callback(
+                       '/([\xc0-\xff][\x80-\xbf]+)/',
+                       'callbackCanonical',
+                       $dest);
+               if( $newDest === $dest ) continue;
+               $changed++;
+               $canonicalDecomp[$source] = $newDest;
+       }
+       $pass++;
+}
+
+print "Recursively expanding compatibility mappings...\n";
+$changed = 42;
+$pass = 1;
+while( $changed > 0 ) {
+       print "pass $pass\n";
+       $changed = 0;
+       foreach( $compatibilityDecomp as $source => $dest ) {
+               $newDest = preg_replace_callback(
+                       '/([\xc0-\xff][\x80-\xbf]+)/',
+                       'callbackCompat',
+                       $dest);
+               if( $newDest === $dest ) continue;
+               $changed++;
+               $compatibilityDecomp[$source] = $newDest;
+       }
+       $pass++;
+}
+
+print "$total decomposition mappings ($canon canonical, $compat compatibility)\n";
+
+$out = fopen("UtfNormalData.inc", "wt");
+if( $out ) {
+       $serCombining = escapeSingleString( serialize( $combiningClass ) );
+       $serComp = escapeSingleString( serialize( $canonicalComp ) );
+       $serCanon = escapeSingleString( serialize( $canonicalDecomp ) );
+       $serCheckNFC = escapeSingleString( serialize( $checkNFC ) );
+       $outdata = "<" . "?php
+/**
+ * This file was automatically generated -- do not edit!
+ * Run UtfNormalGenerate.php to create this file again (make clean && make)
+ * @package MediaWiki
+ */
+/** */
+global \$utfCombiningClass, \$utfCanonicalComp, \$utfCanonicalDecomp, \$utfCheckNFC;
+\$utfCombiningClass = unserialize( '$serCombining' );
+\$utfCanonicalComp = unserialize( '$serComp' );
+\$utfCanonicalDecomp = unserialize( '$serCanon' );
+\$utfCheckNFC = unserialize( '$serCheckNFC' );
+?" . ">\n";
+       fputs( $out, $outdata );
+       fclose( $out );
+       print "Wrote out UtfNormalData.inc\n";
+} else {
+       print "Can't create file UtfNormalData.inc\n";
+       exit(-1);
+}
+
+
+$out = fopen("UtfNormalDataK.inc", "wt");
+if( $out ) {
+       $serCompat = escapeSingleString( serialize( $compatibilityDecomp ) );
+       $outdata = "<" . "?php
+/**
+ * This file was automatically generated -- do not edit!
+ * Run UtfNormalGenerate.php to create this file again (make clean && make)
+ * @package MediaWiki
+ */
+/** */
+global \$utfCompatibilityDecomp;
+\$utfCompatibilityDecomp = unserialize( '$serCompat' );
+?" . ">\n";
+       fputs( $out, $outdata );
+       fclose( $out );
+       print "Wrote out UtfNormalDataK.inc\n";
+       exit(0);
+} else {
+       print "Can't create file UtfNormalDataK.inc\n";
+       exit(-1);
+}
+
+# ---------------
+
+function callbackCanonical( $matches ) {
+       global $canonicalDecomp;
+       if( isset( $canonicalDecomp[$matches[1]] ) ) {
+               return $canonicalDecomp[$matches[1]];
+       }
+       return $matches[1];
+}
+
+function callbackCompat( $matches ) {
+       global $compatibilityDecomp;
+       if( isset( $compatibilityDecomp[$matches[1]] ) ) {
+               return $compatibilityDecomp[$matches[1]];
+       }
+       return $matches[1];
+}
+
+?>
diff --git a/includes/normal/UtfNormalTest.php b/includes/normal/UtfNormalTest.php
new file mode 100644 (file)
index 0000000..90c2ea1
--- /dev/null
@@ -0,0 +1,249 @@
+<?php
+# Copyright (C) 2004 Brion Vibber <brion@pobox.com>
+# http://www.mediawiki.org/
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or 
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# http://www.gnu.org/copyleft/gpl.html
+
+/**
+ * Implements the conformance test at:
+ * http://www.unicode.org/Public/UNIDATA/NormalizationTest.txt
+ * @package UtfNormal
+ */
+
+/** */
+$verbose = true;
+#define( 'PRETTY_UTF8', true );
+
+if( defined( 'PRETTY_UTF8' ) ) {
+       function pretty( $string ) {
+               return preg_replace( '/([\x00-\xff])/e',
+                       'sprintf("%02X", ord("$1"))',
+                       $string );
+       }       
+} else {
+       /**
+        * @ignore
+        */
+       function pretty( $string ) {
+               return trim( preg_replace( '/(.)/use',
+                       'sprintf("%04X ", utf8ToCodepoint("$1"))',
+                       $string ) );
+       }       
+}
+
+if( isset( $_SERVER['argv'] ) && in_array( '--icu', $_SERVER['argv'] ) ) {
+       dl( 'php_utfnormal.so' );
+}
+
+require_once 'UtfNormalUtil.php';
+require_once 'UtfNormal.php';
+
+if( php_sapi_name() != 'cli' ) {
+       die( "Run me from the command line please.\n" );
+}
+
+$in = fopen("NormalizationTest.txt", "rt");
+if( !$in ) {
+       print "Couldn't open NormalizationTest.txt -- can't run tests.\n";
+       print "If necessary, manually download this file. It can be obtained at\n";
+       print "http://www.unicode.org/Public/UNIDATA/NormalizationTest.txt";
+       exit(-1);
+}
+
+$normalizer = new UtfNormal;
+
+$total = 0;
+$success = 0;
+$failure = 0;
+$ok = true;
+$testedChars = array();
+while( false !== ( $line = fgets( $in ) ) ) {
+       list( $data, $comment ) = explode( '#', $line );
+       if( $data === '' ) continue;
+       if( preg_match( '/@Part([\d])/', $data, $matches ) ) {
+               if( $matches[1] > 0 ) {
+                       $ok = reportResults( $total, $success, $failure ) && $ok;
+               }
+               print "Part {$matches[1]}: $comment";
+               continue;
+       }
+       
+       $columns = array_map( "hexSequenceToUtf8", explode( ";", $data ) );
+       array_unshift( $columns, '' );
+       
+       $testedChars[$columns[1]] = true;
+       $total++;
+       if( testNormals( $normalizer, $columns, $comment ) ) {
+               $success++;
+       } else {
+               $failure++;
+               # print "FAILED: $comment";
+       }
+       if( $total % 100 == 0 ) print "$total ";
+}
+fclose( $in );
+
+$ok = reportResults( $total, $success, $failure ) && $ok;
+
+$in = fopen("UnicodeData.txt", "rt" );
+if( !$in ) {
+       print "Can't open UnicodeData.txt for reading.\n";
+       print "If necessary, fetch this file from the internet:\n";
+       print "http://www.unicode.org/Public/UNIDATA/UnicodeData.txt\n";
+       exit(-1);
+}
+print "Now testing invariants...\n";
+while( false !== ($line = fgets( $in ) ) ) {
+       $cols = explode( ';', $line );
+       $char = codepointToUtf8( hexdec( $cols[0] ) );
+       $desc = $cols[0] . ": " . $cols[1];
+       if( $char < "\x20" || $char >= UTF8_SURROGATE_FIRST && $char <= UTF8_SURROGATE_LAST ) {
+               # Can't check NULL with the ICU plugin, as null bytes fail in C land.
+               # Skip other control characters, as we strip them for XML safety.
+               # Surrogates are illegal on their own or in UTF-8, ignore.
+               continue;
+       }
+       if( empty( $testedChars[$char] ) ) {
+               $total++;
+               if( testInvariant( $normalizer, $char, $desc ) ) {
+                       $success++;
+               } else {
+                       $failure++;
+               }
+               if( $total % 100 == 0 ) print "$total ";
+       }
+}
+fclose( $in );
+
+$ok = reportResults( $total, $success, $failure ) && $ok;
+
+if( $ok ) {
+       print "TEST SUCCEEDED!\n";
+       exit(0);
+} else {
+       print "TEST FAILED!\n";
+       exit(-1);
+}
+
+## ------
+
+function reportResults( &$total, &$success, &$failure ) {
+       $percSucc = IntVal( $success * 100 / $total );
+       $percFail = IntVal( $failure * 100 / $total );
+       print "\n";
+       print "$success tests successful ($percSucc%)\n";
+       print "$failure tests failed ($percFail%)\n\n";
+       $ok = ($success > 0 && $failure == 0);
+       $total = 0;
+       $success = 0;
+       $failure = 0;
+       return $ok;
+}
+
+function testNormals( &$u, $c, $comment, $reportFailure = false ) {
+       $result = testNFC( $u, $c, $comment, $reportFailure );
+       $result = testNFD( $u, $c, $comment, $reportFailure ) && $result;
+       $result = testNFKC( $u, $c, $comment, $reportFailure ) && $result;
+       $result = testNFKD( $u, $c, $comment, $reportFailure ) && $result;
+       $result = testCleanUp( $u, $c, $comment, $reportFailure ) && $result;
+       
+       global $verbose;
+       if( $verbose && !$result && !$reportFailure ) {
+               print $comment;
+               testNormals( $u, $c, $comment, true );
+       }
+       return $result;
+}
+
+function verbosify( $a, $b, $col, $form, $verbose ) {
+       #$result = ($a === $b);
+       $result = (strcmp( $a, $b ) == 0);
+       if( $verbose ) {
+               $aa = pretty( $a );
+               $bb = pretty( $b );
+               $ok = $result ? "succeed" : " failed";
+               $eq = $result ? "==" : "!=";
+               print "  $ok $form c$col '$aa' $eq '$bb'\n";
+       }
+       return $result;
+}
+
+function testNFC( &$u, $c, $comment, $verbose ) {
+       $result = verbosify( $c[2], $u->toNFC( $c[1] ), 1, 'NFC', $verbose );
+       $result = verbosify( $c[2], $u->toNFC( $c[2] ), 2, 'NFC', $verbose ) && $result;
+       $result = verbosify( $c[2], $u->toNFC( $c[3] ), 3, 'NFC', $verbose ) && $result;
+       $result = verbosify( $c[4], $u->toNFC( $c[4] ), 4, 'NFC', $verbose ) && $result;
+       $result = verbosify( $c[4], $u->toNFC( $c[5] ), 5, 'NFC', $verbose ) && $result;
+       return $result;
+}
+
+function testCleanUp( &$u, $c, $comment, $verbose ) {
+       $x = $c[1];
+       $result = verbosify( $c[2], $u->cleanUp( $x ), 1, 'cleanUp', $verbose );
+       $x = $c[2];
+       $result = verbosify( $c[2], $u->cleanUp( $x ), 2, 'cleanUp', $verbose ) && $result;
+       $x = $c[3];
+       $result = verbosify( $c[2], $u->cleanUp( $x ), 3, 'cleanUp', $verbose ) && $result;
+       $x = $c[4];
+       $result = verbosify( $c[4], $u->cleanUp( $x ), 4, 'cleanUp', $verbose ) && $result;
+       $x = $c[5];
+       $result = verbosify( $c[4], $u->cleanUp( $x ), 5, 'cleanUp', $verbose ) && $result;
+       return $result;
+}
+
+function testNFD( &$u, $c, $comment, $verbose ) {
+       $result = verbosify( $c[3], $u->toNFD( $c[1] ), 1, 'NFD', $verbose );
+       $result = verbosify( $c[3], $u->toNFD( $c[2] ), 2, 'NFD', $verbose ) && $result;
+       $result = verbosify( $c[3], $u->toNFD( $c[3] ), 3, 'NFD', $verbose ) && $result;
+       $result = verbosify( $c[5], $u->toNFD( $c[4] ), 4, 'NFD', $verbose ) && $result;
+       $result = verbosify( $c[5], $u->toNFD( $c[5] ), 5, 'NFD', $verbose ) && $result;
+       return $result;
+}
+
+function testNFKC( &$u, $c, $comment, $verbose ) {
+       $result = verbosify( $c[4], $u->toNFKC( $c[1] ), 1, 'NFKC', $verbose );
+       $result = verbosify( $c[4], $u->toNFKC( $c[2] ), 2, 'NFKC', $verbose ) && $result;
+       $result = verbosify( $c[4], $u->toNFKC( $c[3] ), 3, 'NFKC', $verbose ) && $result;
+       $result = verbosify( $c[4], $u->toNFKC( $c[4] ), 4, 'NFKC', $verbose ) && $result;
+       $result = verbosify( $c[4], $u->toNFKC( $c[5] ), 5, 'NFKC', $verbose ) && $result;
+       return $result;
+}
+
+function testNFKD( &$u, $c, $comment, $verbose ) {
+       $result = verbosify( $c[5], $u->toNFKD( $c[1] ), 1, 'NFKD', $verbose );
+       $result = verbosify( $c[5], $u->toNFKD( $c[2] ), 2, 'NFKD', $verbose ) && $result;
+       $result = verbosify( $c[5], $u->toNFKD( $c[3] ), 3, 'NFKD', $verbose ) && $result;
+       $result = verbosify( $c[5], $u->toNFKD( $c[4] ), 4, 'NFKD', $verbose ) && $result;
+       $result = verbosify( $c[5], $u->toNFKD( $c[5] ), 5, 'NFKD', $verbose ) && $result;
+       return $result;
+}
+
+function testInvariant( &$u, $char, $desc, $reportFailure = false ) {
+       $result = verbosify( $char, $u->toNFC( $char ), 1, 'NFC', $reportFailure );
+       $result = verbosify( $char, $u->toNFD( $char ), 1, 'NFD', $reportFailure ) && $result;
+       $result = verbosify( $char, $u->toNFKC( $char ), 1, 'NFKC', $reportFailure ) && $result;
+       $result = verbosify( $char, $u->toNFKD( $char ), 1, 'NFKD', $reportFailure ) && $result;
+       $c = $char;
+       $result = verbosify( $char, $u->cleanUp( $char ), 1, 'cleanUp', $reportFailure ) && $result;
+       global $verbose;
+       if( $verbose && !$result && !$reportFailure ) {
+               print $desc;
+               testInvariant( $u, $char, $desc, true );
+       }
+       return $result;
+}
+
+?>
diff --git a/includes/normal/UtfNormalUtil.php b/includes/normal/UtfNormalUtil.php
new file mode 100644 (file)
index 0000000..06e0bb4
--- /dev/null
@@ -0,0 +1,141 @@
+<?php
+# Copyright (C) 2004 Brion Vibber <brion@pobox.com>
+# http://www.mediawiki.org/
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or 
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# http://www.gnu.org/copyleft/gpl.html
+
+/**
+ * Some of these functions are adapted from places in MediaWiki.
+ * Should probably merge them for consistency.
+ *
+ * @package UtfNormal
+ * @access public
+ */
+
+/** */
+
+/**
+ * Return UTF-8 sequence for a given Unicode code point.
+ * May die if fed out of range data.
+ *
+ * @param int $codepoint
+ * @return string
+ * @access public
+ */
+function codepointToUtf8( $codepoint ) {
+       if($codepoint <         0x80) return chr($codepoint);
+       if($codepoint <    0x800) return chr($codepoint >>      6 & 0x3f | 0xc0) .
+                                                                        chr($codepoint           & 0x3f | 0x80);
+       if($codepoint <  0x10000) return chr($codepoint >> 12 & 0x0f | 0xe0) .
+                                                                        chr($codepoint >>      6 & 0x3f | 0x80) .
+                                                                        chr($codepoint           & 0x3f | 0x80);
+       if($codepoint < 0x110000) return chr($codepoint >> 18 & 0x07 | 0xf0) .
+                                                                        chr($codepoint >> 12 & 0x3f | 0x80) .
+                                                                        chr($codepoint >>      6 & 0x3f | 0x80) .
+                                                                        chr($codepoint           & 0x3f | 0x80);
+
+       die("Asked for code outside of range ($codepoint)\n");
+}
+
+/**
+ * Take a series of space-separated hexadecimal numbers representing
+ * Unicode code points and return a UTF-8 string composed of those
+ * characters. Used by UTF-8 data generation and testing routines.
+ *
+ * @param string $sequence
+ * @return string
+ * @access private
+ */
+function hexSequenceToUtf8( $sequence ) {
+       $utf = '';
+       foreach( explode( ' ', $sequence ) as $hex ) {
+               $n = hexdec( $hex );
+               $utf .= codepointToUtf8( $n );
+       }
+       return $utf;
+}
+
+/**
+ * Take a UTF-8 string and return a space-separated series of hex
+ * numbers representing Unicode code points. For debugging.
+ *
+ * @param string $str
+ * @return string
+ * @access private
+ */
+function utf8ToHexSequence( $str ) {
+       return rtrim( preg_replace( '/(.)/uSe',
+                                   'sprintf("%04x ", utf8ToCodepoint("$1"))',
+                                   $str ) );
+}
+
+/**
+ * Determine the Unicode codepoint of a single-character UTF-8 sequence.
+ * Does not check for invalid input data.
+ *
+ * @param string $char
+ * @return int
+ * @access public
+ */
+function utf8ToCodepoint( $char ) {
+       # Find the length
+       $z = ord( $char{0} );
+       if ( $z & 0x80 ) {
+               $length = 0;
+               while ( $z & 0x80 ) {
+                       $length++;
+                       $z <<= 1;
+               }
+       } else {
+               $length = 1;
+       }
+
+       if ( $length != strlen( $char ) ) {
+               return false;
+       }
+       if ( $length == 1 ) {
+               return ord( $char );
+       }
+
+       # Mask off the length-determining bits and shift back to the original location
+       $z &= 0xff;
+       $z >>= $length;
+
+       # Add in the free bits from subsequent bytes
+       for ( $i=1; $i<$length; $i++ ) {
+               $z <<= 6;
+               $z |= ord( $char{$i} ) & 0x3f;
+       }
+
+       return $z;
+}
+
+/**
+ * Escape a string for inclusion in a PHP single-quoted string literal.
+ *
+ * @param string $string
+ * @return string
+ * @access public
+ */
+function escapeSingleString( $string ) {
+       return strtr( $string,
+               array(
+                       '\\' => '\\\\',
+                       '\'' => '\\\''
+               ));
+}
+
+?>
diff --git a/includes/proxy_check.php b/includes/proxy_check.php
new file mode 100644 (file)
index 0000000..583e8fd
--- /dev/null
@@ -0,0 +1,55 @@
+<?php
+/**
+ * Command line script to check for an open proxy at a specified location
+ * @package MediaWiki
+ */
+
+if( php_sapi_name() != 'cli' ) {
+       die('');
+}
+
+/**
+ *
+ */
+$output = '';
+
+/**
+ * Exit if there are not enough parameters, or if it's not command line mode
+ */
+if ( ( isset( $_REQUEST ) && array_key_exists( 'argv', $_REQUEST ) ) || count( $argv ) < 4 ) {
+       $output .= "Incorrect parameters\n";
+} else {
+       /**
+        * Get parameters
+        */
+       $ip = $argv[1];
+       $port = $argv[2];
+       $url = $argv[3];
+       $host = trim(`hostname`);
+       $output = "Connecting to $ip:$port, target $url, this hostname $host\n";
+
+       # Open socket
+       $sock = @fsockopen($ip, $port, $errno, $errstr, 5);
+       if ($errno == 0 ) {
+               $output .= "Connected\n";
+               # Send payload
+               $request = "GET $url HTTP/1.0\r\n";
+#              $request .= "Proxy-Connection: Keep-Alive\r\n";
+#              $request .= "Pragma: no-cache\r\n";
+#              $request .= "Host: ".$url."\r\n";
+#              $request .= "User-Agent: MediaWiki open proxy check\r\n";
+               $request .= "\r\n";
+               @fputs($sock, $request);
+               $response = fgets($sock, 65536);
+               $output .= $response;
+               @fclose($sock);
+       } else {
+               $output .= "No connection\n";
+       }
+}
+
+$output = escapeshellarg( $output );
+
+#`echo $output >> /home/tstarling/open/proxy.log`;
+
+?>
diff --git a/includes/templates/Confirmemail.php b/includes/templates/Confirmemail.php
new file mode 100644 (file)
index 0000000..ec1dc1f
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+/**
+ * @package MediaWiki
+ * @subpackage Templates
+ */
+if( !defined( 'MEDIAWIKI' ) ) die();
+
+/** */
+require_once( 'includes/SkinTemplate.php' );
+
+/**
+ * HTML template for Special:Confirmemail form
+ * @package MediaWiki
+ * @subpackage Templates
+ */
+class ConfirmemailTemplate extends QuickTemplate {
+       function execute() {
+               if( $this->data['error'] ) {
+?>
+       <div class='error'><?php $this->msgWiki( $this->data['error']) ?></div>
+<?php } else { ?>
+       <div>
+       <?php $this->msgWiki( 'confirmemail_text' ) ?>
+       </div>
+<?php } ?>
+<form name="confirmemail" id="confirmemail" method="post" action="<?php $this->text('action') ?>">
+       <input type="hidden" name="action" value="submit" />
+       <input type="hidden" name="wpEditToken" value="<?php $this->text('edittoken') ?>" />
+       <table border='0'>
+               <tr>
+                       <td></td>
+                       <td><input type="submit" name="wpConfirm" value="<?php $this->msg('confirmemail_send') ?>" /></td>
+               </tr>
+       </table>
+</form>
+<?php
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/includes/templates/Userlogin.php b/includes/templates/Userlogin.php
new file mode 100644 (file)
index 0000000..ff607cd
--- /dev/null
@@ -0,0 +1,127 @@
+<?php
+/**
+ * @package MediaWiki
+ * @subpackage Templates
+ */
+if( !defined( 'MEDIAWIKI' ) ) die();
+
+/** */
+require_once( 'includes/SkinTemplate.php' );
+
+/**
+ * HTML template for Special:Userlogin form
+ * @package MediaWiki
+ * @subpackage Templates
+ */
+class UserloginTemplate extends QuickTemplate {
+       function execute() {
+               if( $this->data['error'] ) {
+?>
+       <h2><?php $this->msg('loginerror') ?>:</h2>
+       <p class='error'><?php $this->html('error') ?></p>
+<?php } else { ?>
+       <h2><?php $this->msg('login'      ) ?>:</h2>
+       <?php  $this->msgWiki('loginprompt') ?>
+<?php } ?>
+<form name="userlogin" id="userlogin" method="post" action="<?php $this->text('action') ?>">
+       <table border='0'>
+               <tr>
+                       <td align='right'><label for='wpName'><?php $this->msg('yourname') ?>:</label></td>
+                       <td align='left'>
+                               <input tabindex='1' type='text' name="wpName" id="wpName"
+                                       value="<?php $this->text('name') ?>" size='20' />
+                       </td>
+                       <td align='left'>
+                               <input tabindex='3' type='checkbox' name="wpRemember"
+                                       value="1" id="wpRemember"
+                                       <?php if( $this->data['remember'] ) { ?>checked="checked"<?php } ?>
+                                       /><label for="wpRemember"><?php $this->msg('remembermypassword') ?></label>
+                       </td>
+               </tr>
+               <tr>
+                       <td align='right'><label for='wpPassword'><?php $this->msg('yourpassword') ?>:</label></td>
+                       <td align='left'>
+                               <input tabindex='2' type='password' name="wpPassword" id="wpPassword"
+                                       value="<?php $this->text('password') ?>" size='20' />
+                       </td>
+                       <td align='left'>
+                               <input tabindex='4' type='submit' name="wpLoginattempt"
+                                       value="<?php $this->msg('login') ?>" />
+                       </td>
+               </tr>
+       <?php if( $this->data['usedomain'] ) {
+               $doms = "";
+               foreach( $this->data['domainnames'] as $dom ) {
+                       $doms .= "<option>" . htmlspecialchars( $dom ) . "</option>";
+               }
+       ?>
+               <tr>
+                       <td align='right'><?php $this->msg( 'yourdomainname' ) ?>:</td>
+                       <td align='left'>
+                               <select tabindex='11' name="wpDomain" value="<?php $this->text( 'domain' ) ?>">
+                                       <?php echo $doms ?>
+                               </select>
+                       </td>
+               </tr>
+       <?php } ?>
+       <?php if( $this->data['create'] ) { ?>
+               <tr>
+                       <td colspan='3'>&nbsp;</td>
+               </tr>
+               <tr>
+                       <td align='right'><label for='wpRetype'><?php $this->msg('yourpasswordagain') ?>:</label></td>
+                       <td align='left'>
+                               <input tabindex='5' type='password' name="wpRetype" id="wpRetype"
+                                       value="<?php $this->text('retype') ?>" 
+                                       size='20' />
+                       </td>
+                       <td><?php $this->msg('newusersonly') ?></td>
+               </tr>
+               <tr>
+                       <?php if( $this->data['useemail'] ) { ?>
+                               <td align='right'><label for='wpEmail'><?php $this->msg('youremail') ?>:</label></td>
+                               <td align='left'>
+                                       <input tabindex='7' type='text' name="wpEmail" id="wpEmail"
+                                               value="<?php $this->text('email') ?>" size='20' />
+                               </td>
+                       <?php } ?>
+                       <?php if( $this->data['userealname'] ) { ?>
+                               </tr>
+                               <tr>
+                                       <td align='right'><label for='wpRealName'><?php $this->msg('yourrealname') ?>:</label></td>
+                                       <td align='left'>
+                                               <input tabindex='8' type='text' name="wpRealName" id="wpRealName"
+                                                       value="<?php $this->text('realname') ?>" size='20' />
+                                       </td>
+                       <?php } ?>
+                       <td align='left'>
+                               <input tabindex='9' type='submit' name="wpCreateaccount"
+                                       value="<?php $this->msg('createaccount') ?>" />
+                               <?php if( $this->data['createemail'] ) { ?>
+                               <input tabindex='6' type='submit' name="wpCreateaccountMail"
+                                       value="<?php $this->msg('createaccountmail') ?>" />
+                               <?php } ?>
+                       </td>
+               </tr>
+       <?php if( $this->data['useemail'] ) { ?>
+               <tr>
+                       <td colspan='3'>&nbsp;</td>
+               </tr>
+               <tr>
+                       <td colspan='3' align='left'>
+                               <p>
+                                       <?php $this->msgHtml( 'emailforlost' ) ?><br />
+                                       <input tabindex='10' type='submit' name="wpMailmypassword"
+                                               value="<?php $this->msg('mailmypassword') ?>" />
+                               </p>
+                       </td>
+               </tr>
+       <?php } } ?>
+       </table>
+</form>
+<?php
+               $this->msgWiki( 'loginend' );
+       }
+}
+
+?>
diff --git a/includes/zhtable/Makefile b/includes/zhtable/Makefile
new file mode 100644 (file)
index 0000000..30679fb
--- /dev/null
@@ -0,0 +1,268 @@
+#
+# Creating the file ZhConversion.php used for Simplified/Traditional
+# Chinese conversion. It gets the basic conversion table from the Unihan 
+# database, and construct the phrase tables using phrase libraries in
+# the SCIM packages and the libtabe package. There are also special
+# tables used to for adjustment. 
+#
+
+GREP = LANG=zh_CN.UTF8 grep
+SED = LANG=zh_CN.UTF8 sed
+DIFF = LANG=zh_CN.UTF8 diff
+CC ?= gcc
+
+#installation directory
+INSTDIR = /usr/local/share/zhdaemons/
+
+all: ZhConversion.php tradphrases.notsure simpphrases.notsure wordlist toCN.dict toTW.dict toHK.dict toSG.dict
+
+Unihan.txt:
+       wget -nc ftp://ftp.unicode.org/Public/UNIDATA/Unihan.zip
+       unzip -q Unihan.zip
+
+EZ.txt.in:
+       wget -nc http://easynews.dl.sourceforge.net/sourceforge/scim/scim-tables-0.5.1.tar.gz
+       tar -xzf scim-tables-0.5.1.tar.gz -O scim-tables-0.5.1/zh/EZ.txt.in > EZ.txt.in
+
+phrase_lib.txt:
+       wget -nc http://easynews.dl.sourceforge.net/sourceforge/scim/scim-pinyin-0.5.0.tar.gz
+       tar -xzf scim-pinyin-0.5.0.tar.gz -O scim-pinyin-0.5.0/data/phrase_lib.txt > phrase_lib.txt
+
+tsi.src:
+       wget -nc http://unc.dl.sourceforge.net/sourceforge/libtabe/libtabe-0.2.3.tgz    
+       tar -xzf libtabe-0.2.3.tgz -O libtabe/tsi-src/tsi.src > tsi.src
+
+wordlist: phrase_lib.txt EZ.txt.in tsi.src
+       iconv -c -f big5 -t utf8 tsi.src | $(SED) 's/# //g' | $(SED) 's/[ ][0-9].*//' > wordlist
+       $(SED) 's/\(.*\)\t[0-9][0-9]*.*/\1/' phrase_lib.txt | $(SED) '1,5d' >>wordlist
+       $(SED) '1,/BEGIN_TABLE/d' EZ.txt.in | colrm 1 8 | $(SED) 's/\t.*//' | $(GREP) "^...*" >> wordlist
+       sort wordlist | uniq | $(SED) 's/ //g' > t
+       mv t wordlist
+
+printutf8: printutf8.c
+       $(CC) -o printutf8 printutf8.c
+
+unihan.t2s.t: Unihan.txt printutf8
+       $(GREP) kSimplifiedVariant Unihan.txt | $(SED)  '/#/d' | $(SED)  's/kSimplifiedVariant//' | ./printutf8 > unihan.t2s.t
+
+trad2simp.t: trad2simp.manual unihan.t2s.t
+       cp unihan.t2s.t tmp1
+       for I in `colrm 11 < trad2simp.manual` ; do $(SED) "/^$$I/d" tmp1 > tmp2; mv tmp2 tmp1; done
+       cat trad2simp.manual tmp1 > trad2simp.t
+
+unihan.s2t.t: Unihan.txt printutf8
+       $(GREP) kTraditionalVariant Unihan.txt | $(SED)  '/#/d' | $(SED)  's/kTraditionalVariant//' | ./printutf8 > unihan.s2t.t
+
+simp2trad.t: unihan.s2t.t simp2trad.manual
+       cp unihan.s2t.t tmp1
+       for I in `colrm 11 < simp2trad.manual` ; do $(SED) "/^$$I/d" tmp1 > tmp2; mv tmp2 tmp1; done
+       cat simp2trad.manual tmp1 > simp2trad.t
+
+t2s_1tomany.t: trad2simp.t
+       $(GREP) -s ".\{19,\}" trad2simp.t | $(SED)  's/U+...../"/' | $(SED)  's/|U+...../"=>"/' | $(SED)  's/|U+.....//g' | $(SED)  's/|/",/'  > t2s_1tomany.t
+
+t2s_1to1.t: trad2simp.t s2t_1tomany.t
+       $(SED)  "/.*|.*|.*|.*/d" trad2simp.t | $(SED)  's/U+[0-9a-z][0-9a-z]*/"/' | $(SED)  's/|U+[0-9a-z][0-9a-z]*/"=>"/' | $(SED)  's/|/",/' > t2s_1to1.t
+       $(GREP)  '"."=>"..",' s2t_1tomany.t | $(SED) 's/\("."\)=>".\(.\)",/"\2"=>\1,/' >> t2s_1to1.t
+       $(GREP)  '"."=>"...",' s2t_1tomany.t | $(SED) 's/\("."\)=>".\(.\).",/"\2"=>\1,/' >> t2s_1to1.t
+       $(GREP)  '"."=>"...",' s2t_1tomany.t | $(SED) 's/\("."\)=>"..\(.\)",/"\2"=>\1,/' >> t2s_1to1.t
+       $(GREP)  '"."=>"....",' s2t_1tomany.t | $(SED) 's/\("."\)=>".\(.\)..",/"\2"=>\1,/' >> t2s_1to1.t
+       $(GREP)  '"."=>"....",' s2t_1tomany.t | $(SED) 's/\("."\)=>"..\(.\).",/"\2"=>\1,/' >> t2s_1to1.t
+       $(GREP)  '"."=>"....",' s2t_1tomany.t | $(SED) 's/\("."\)=>"...\(.\)",/"\2"=>\1,/' >> t2s_1to1.t
+       sort t2s_1to1.t | uniq > t
+       mv t t2s_1to1.t
+
+
+s2t_1tomany.t: simp2trad.t
+       $(GREP) -s ".\{19,\}" simp2trad.t | $(SED)  's/U+...../"/' | $(SED)  's/|U+...../"=>"/' | $(SED)  's/|U+.....//g' | $(SED)  's/|/",/' > s2t_1tomany.t
+
+s2t_1to1.t: simp2trad.t t2s_1tomany.t
+       $(SED)  "/.*|.*|.*|.*/d" simp2trad.t | $(SED)  's/U+[0-9a-z][0-9a-z]*/"/' | $(SED)  's/|U+[0-9a-z][0-9a-z]*/"=>"/' | $(SED)  's/|/",/' > s2t_1to1.t
+       $(GREP)  '"."=>"..",' t2s_1tomany.t | $(SED) 's/\("."\)=>".\(.\)",/"\2"=>\1,/' >> s2t_1to1.t
+       $(GREP)  '"."=>"...",' t2s_1tomany.t | $(SED) 's/\("."\)=>".\(.\).",/"\2"=>\1,/' >> s2t_1to1.t
+       $(GREP)  '"."=>"...",' t2s_1tomany.t | $(SED) 's/\("."\)=>"..\(.\)",/"\2"=>\1,/' >> s2t_1to1.t
+       $(GREP)  '"."=>"....",' t2s_1tomany.t | $(SED) 's/\("."\)=>".\(.\)..",/"\2"=>\1,/' >> s2t_1to1.t
+       $(GREP)  '"."=>"....",' t2s_1tomany.t | $(SED) 's/\("."\)=>"..\(.\).",/"\2"=>\1,/' >> s2t_1to1.t
+       $(GREP)  '"."=>"....",' t2s_1tomany.t | $(SED) 's/\("."\)=>"...\(.\)",/"\2"=>\1,/' >> s2t_1to1.t
+       sort s2t_1to1.t | uniq > t
+       mv t s2t_1to1.t
+
+tphrase.t: EZ.txt.in tsi.src
+       colrm 1 8 < EZ.txt.in | $(SED) 's/\t//g' | $(GREP) "^.\{2,4\}[0-9]" | $(SED) 's/[0-9]//g' > t
+       iconv -c -f big5 -t utf8 tsi.src | $(SED) 's/ [0-9].*//g' | $(SED) 's/[# ]//g'| $(GREP) "^.\{2,4\}"  >> t
+       sort t | uniq > tphrase.t
+
+alltradphrases.t: tphrase.t s2t_1tomany.t 
+       for i in `cat s2t_1tomany.t | $(SED) 's/.*=>".//' | $(SED) 's/"//g' |$(SED) 's/,/\n/' | $(SED) 's/\(.\)/\1\n/g' |sort | uniq`; do $(GREP) -s $$i tphrase.t ; done  > alltradphrases.t || true
+
+
+tradphrases_2.t: alltradphrases.t
+       cat alltradphrases.t | $(GREP)  "^..$$" | sort | uniq > tradphrases_2.t
+
+tradphrases_3.t: alltradphrases.t
+       cat alltradphrases.t | $(GREP)  "^...$$" | sort | uniq > tradphrases_3.t
+       for i in `cat tradphrases_2.t`; do $(GREP) $$i tradphrases_3.t ; done | sort | uniq > t3 || true
+       $(DIFF) t3 tradphrases_3.t | $(GREP) ">" | $(SED) 's/> //' > t
+       mv t tradphrases_3.t
+
+
+tradphrases_4.t: alltradphrases.t
+       cat alltradphrases.t | $(GREP)  "^....$$" | sort | uniq > tradphrases_4.t
+       for i in `cat tradphrases_2.t`; do $(GREP) $$i tradphrases_4.t ; done | sort | uniq > t3 || true
+       $(DIFF) t3 tradphrases_4.t | $(GREP) ">" | $(SED) 's/> //' > t
+       mv t tradphrases_4.t
+       for i in `cat tradphrases_3.t`; do $(GREP) $$i tradphrases_4.t ; done | sort | uniq > t3 || true
+       $(DIFF) t3 tradphrases_4.t | $(GREP) ">" | $(SED) 's/> //' > t
+       mv t tradphrases_4.t
+
+tradphrases.t: tradphrases.manual tradphrases_2.t tradphrases_3.t tradphrases_4.t t2s_1tomany.t
+       cat tradphrases.manual tradphrases_2.t tradphrases_3.t tradphrases_4.t |sort | uniq > tradphrases.t
+       for i in `$(SED) 's/"\(.\).*/\1/' t2s_1tomany.t ` ; do $(GREP) $$i tradphrases.t ; done | $(DIFF) tradphrases.t - | $(GREP) '<' | $(SED) 's/< //' > t
+       mv t tradphrases.t
+
+tradphrases.notsure: tradphrases_2.t tradphrases_3.t tradphrases_4.t t2s_1tomany.t
+       cat tradphrases_2.t tradphrases_3.t tradphrases_4.t |sort | uniq > t
+       for i in `$(SED) 's/"\(.\).*/\1/' t2s_1tomany.t ` ; do $(GREP) $$i t; done | $(DIFF) t - | $(GREP) '>' | $(SED) 's/> //' > tradphrases.notsure
+
+
+ph.t: phrase_lib.txt
+       $(SED) 's/[\t0-9a-zA-Z]//g' phrase_lib.txt | $(GREP) "^.\{2,4\}$$" > ph.t
+
+allsimpphrases.t: ph.t
+       rm -f allsimpphrases.t
+       for i in `cat t2s_1tomany.t | $(SED) 's/.*=>".//' | $(SED) 's/"//g' | $(SED) 's/,/\n/' | $(SED) 's/\(.\)/\1\n/g' | sort | uniq `; do $(GREP) $$i ph.t >> allsimpphrases.t; done
+
+simpphrases_2.t: allsimpphrases.t
+       cat allsimpphrases.t | $(GREP) "^..$$" | sort | uniq > simpphrases_2.t
+
+simpphrases_3.t: allsimpphrases.t
+       cat allsimpphrases.t | $(GREP) "^...$$" | sort | uniq > simpphrases_3.t
+       for i in `cat simpphrases_2.t`; do $(GREP) $$i simpphrases_3.t ; done | sort | uniq > t3 || true
+       $(DIFF) t3 simpphrases_3.t | $(GREP) ">" | $(SED) 's/> //' > t
+       mv t simpphrases_3.t
+
+simpphrases_4.t: allsimpphrases.t
+       cat allsimpphrases.t | $(GREP) "^....$$" | sort | uniq > simpphrases_4.t
+       rm -f t
+       for i in `cat simpphrases_2.t`; do $(GREP) $$i simpphrases_4.t >> t; done || true
+       sort t | uniq > t3
+       $(DIFF) t3 simpphrases_4.t | $(GREP) ">" | $(SED) 's/> //' > t
+       mv t simpphrases_4.t
+       for i in `cat simpphrases_3.t`; do $(GREP) $$i simpphrases_4.t; done | sort  | uniq > t3 || true
+       $(DIFF) t3 simpphrases_4.t | $(GREP) ">" | $(SED) 's/> //' > t
+       mv t simpphrases_4.t
+
+simpphrases.t:simpphrases_2.t simpphrases_3.t simpphrases_4.t t2s_1tomany.t
+       cat simpphrases_2.t simpphrases_3.t simpphrases_4.t > simpphrases.t
+       for i in `$(SED) 's/"\(.\).*/\1/' t2s_1tomany.t ` ; do $(GREP) $$i simpphrases.t ; done | $(DIFF) simpphrases.t - | $(GREP) '<' | $(SED) 's/< //' > t
+       mv t simpphrases.t
+
+
+simpphrases.notsure:simpphrases_2.t simpphrases_3.t simpphrases_4.t t2s_1tomany.t
+       cat simpphrases_2.t simpphrases_3.t simpphrases_4.t > t
+       for i in `$(SED) 's/"\(.\).*/\1/' t2s_1tomany.t ` ; do $(GREP) $$i t ; done | $(DIFF) t - | $(GREP) '>' | $(SED) 's/> //' > simpphrases.notsure
+
+trad2simp1to1.t: t2s_1tomany.t t2s_1to1.t
+       $(SED)  's/\(.......\).*/\1",/' t2s_1tomany.t > trad2simp1to1.t
+       cat t2s_1to1.t >> trad2simp1to1.t
+
+simp2trad1to1.t: s2t_1tomany.t s2t_1to1.t
+       $(SED)  's/\(.......\).*/\1",/' s2t_1tomany.t > simp2trad1to1.t
+       cat s2t_1to1.t >> simp2trad1to1.t
+
+trad2simp.php: trad2simp1to1.t tradphrases.t
+       printf '<?php\n$$trad2simp=array(' > trad2simp.php
+       cat trad2simp1to1.t >> trad2simp.php
+       printf ');\n$$str=\n"' >> trad2simp.php
+       cat tradphrases.t >> trad2simp.php
+       printf '";\n$$t=strtr($$str, $$trad2simp);\necho $$t;\n?>' >> trad2simp.php
+
+simp2trad.php: simp2trad1to1.t simpphrases.t
+       printf '<?php\n$$simp2trad=array(' > simp2trad.php
+       cat simp2trad1to1.t >> simp2trad.php
+       printf ');\n$$str=\n"' >> simp2trad.php
+       cat simpphrases.t >> simp2trad.php
+       printf '";\n$$t=strtr($$str, $$simp2trad);\necho $$t;\n?>' >> simp2trad.php
+
+simp2trad.phrases.t: trad2simp.php tradphrases.t toTW.manual
+       php -f trad2simp.php | $(SED)  's/\(.*\)/"\1" => /' > tmp1
+       cat tradphrases.t | $(SED)  's/\(.*\)/"\1",/' > tmp2
+       paste tmp1 tmp2 > simp2trad.phrases.t
+       $(SED) 's/\(.*\)\t\(.*\)/"\1"=>"\2",/' toTW.manual >> simp2trad.phrases.t
+
+trad2simp.phrases.t: simp2trad.php simpphrases.t toCN.manual
+       php -f simp2trad.php | $(SED)  's/\(.*\)/"\1" => /' > tmp1
+       cat simpphrases.t | $(SED)  's/\(.*\)/"\1",/' > tmp2
+       paste tmp1 tmp2 > trad2simp.phrases.t
+       $(SED) 's/\(.*\)\t\(.*\)/"\1"=>"\2",/' toCN.manual >> trad2simp.phrases.t
+
+toCN.dict: trad2simp1to1.t trad2simp.phrases.t
+       cat trad2simp1to1.t | $(SED) 's/[, \t]//g' | $(SED) 's/=>/\t/' > toCN.dict
+       cat trad2simp.phrases.t | $(SED) 's/[, \t]//g' | $(SED) 's/=>/\t/' >> toCN.dict
+
+toTW.dict: simp2trad1to1.t simp2trad.phrases.t
+       cat simp2trad1to1.t | $(SED) 's/[, \t]//g' | $(SED) 's/=>/\t/' > toTW.dict
+       cat simp2trad.phrases.t | $(SED) 's/[, \t]//g' | $(SED) 's/=>/\t/' >> toTW.dict
+
+toHK.dict: toHK.manual
+       cat toHK.manual | $(SED) 's/ //g' | $(SED) 's/\(^.*\)\t\(.*\)/"\1"\t"\2"/' > toHK.dict
+
+toSG.dict: toSG.manual
+       cat toSG.manual | $(SED) 's/ //g' | $(SED) 's/\(^.*\)\t\(.*\)/"\1"\t"\2"/' > toSG.dict
+
+
+
+ZhConversion.php: simp2trad1to1.t simp2trad.phrases.t trad2simp1to1.t trad2simp.phrases.t toHK.manual toSG.manual
+       printf '<?php\n/**\n * Simplified/Traditional Chinese conversion tables\n' > ZhConversion.php
+       printf ' *\n * Automatically generated using code and data in includes/zhtable/\n' >> ZhConversion.php
+       printf ' * Do not modify directly! \n *\n * @package MediaWiki\n*/\n\n' >> ZhConversion.php
+       printf '$$zh2TW=array(\n' >> ZhConversion.php
+       cat simp2trad1to1.t >> ZhConversion.php
+       echo >> ZhConversion.php
+       cat simp2trad.phrases.t >> ZhConversion.php
+       echo >> ZhConversion.php
+       echo ');' >> ZhConversion.php
+       echo >> ZhConversion.php
+       echo >> ZhConversion.php
+       printf '$$zh2CN=array(\n' >> ZhConversion.php
+       cat trad2simp1to1.t >> ZhConversion.php
+       echo >> ZhConversion.php
+       cat trad2simp.phrases.t >> ZhConversion.php
+       echo >> ZhConversion.php
+       printf ');' >> ZhConversion.php
+       echo >> ZhConversion.php
+       echo >> ZhConversion.php
+       printf '$$zh2HK=array(\n' >> ZhConversion.php
+       $(SED) 's/\(.*\)\t\(.*\)/"\1" => "\2",/' toHK.manual >> ZhConversion.php
+       echo >> ZhConversion.php
+       printf ');' >> ZhConversion.php
+       echo >> ZhConversion.php
+       echo >> ZhConversion.php
+       printf '$$zh2SG=array(\n' >> ZhConversion.php
+       $(SED) 's/\(.*\)\t\(.*\)/"\1" => "\2",/' toSG.manual >> ZhConversion.php
+       echo >> ZhConversion.php
+       printf ');' >> ZhConversion.php
+       echo >> ZhConversion.php
+       printf '?>' >> ZhConversion.php
+
+
+clean: cleantmp cleandl
+
+cleantmp:
+       # Stuff unpacked from the files fetched by wget
+       rm -f \
+               Unihan.txt \
+               EZ.txt.in \
+               phrase_lib.txt \
+               tsi.src
+       # Temporary files and other trash
+       rm -f ZhConversion.php tmp1 tmp2 tmp3 t3 *.t trad2simp.php simp2trad.php *.dict printutf8 *~ \
+               simpphrases.notsure tradphrases.notsure wordlist
+
+cleandl:
+       rm -f \
+               Unihan.zip \
+               scim-tables-0.5.1.tar.gz \
+               scim-pinyin-0.5.0.tar.gz \
+               libtabe-0.2.3.tgz
+
diff --git a/includes/zhtable/README b/includes/zhtable/README
new file mode 100644 (file)
index 0000000..94dd341
--- /dev/null
@@ -0,0 +1,16 @@
+The various .manual files contains special mappings not included in the
+unihan database, and phrases not included in the SCIM package. 
+
+- simp2trad.manual: Simplified to Traditional character mapping. Most
+  data adapted from
+
+   冯寿忠,“非对称繁简字”对照表, 《语文建设通讯》1997-9第53期.
+   /http://www.yywzw.com/jt/feng/fengb01.htm
+
+- tradphrases.manual: Phrases in Traditional Chinese. A portition is obtained
+  from the TongWen package (http://tongwen.mozdev.org/)
+
+- toTW.manual, toCN.manual, toSG.manual and toHK.manual: special phrase
+  mappings. 
+
+zhengzhu at gmail.com
\ No newline at end of file
diff --git a/includes/zhtable/printutf8.c b/includes/zhtable/printutf8.c
new file mode 100644 (file)
index 0000000..b6ccf17
--- /dev/null
@@ -0,0 +1,99 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+/* 
+ Unicode                   UTF8
+0x00000000 - 0x0000007F: 0xxxxxxx
+0x00000080 - 0x000007FF: 110xxx xx 10xx xxxx
+0x00000800 - 0x0000FFFF: 1110xxxx  10xxxx xx 10xx xxxx
+0x00010000 - 0x001FFFFF: 11110x xx 10xx xxxx 10xxxx xx 10xx xxxx
+0x00200000 - 0x03FFFFFF: 111110xx  10xxxx xx 10xx xxxx 10xxxx xx 10xx xxxx
+0x04000000 - 0x7FFFFFFF: 1111110x  10xx xxxx 10xxxx xx 10xx xxxx 10xxxx xx 10xx xxxx
+
+0000 0      1001 9
+0001 1      1010 A
+0010 2      1011 B
+0011 3      1100 C
+0100 4      1101 D 
+0101 5      1110 E
+0110 6      1111 F
+0111 7
+1000 8
+*/
+void printUTF8(long long u) {
+  long long m;
+  if(u<0x80) {
+    printf("%c", (unsigned char)u);
+  }
+  else if(u<0x800) {
+    m = ((u&0x7c0)>>6) | 0xc0;
+    printf("%c", (unsigned char)m);
+    m = (u&0x3f) | 0x80;
+    printf("%c", (unsigned char)m);
+  }
+  else if(u<0x10000) {
+    m = ((u&0xf000)>>12) | 0xe0;
+    printf("%c",(unsigned char)m);
+    m = ((u&0xfc0)>>6) | 0x80;
+    printf("%c",(unsigned char)m);
+    m = (u & 0x3f) | 0x80;
+    printf("%c",(unsigned char)m);
+  }
+  else if(u<0x200000) {
+    m = ((u&0x1c0000)>>18) | 0xf0;
+    printf("%c", (unsigned char)m);
+    m = ((u& 0x3f000)>>12) | 0x80;
+    printf("%c", (unsigned char)m);
+    m = ((u& 0xfc0)>>6) | 0x80;
+    printf("%c", (unsigned char)m);
+    m = (u&0x3f) | 0x80;
+    printf("%c", (unsigned char)m);
+  }
+  else if(u<0x4000000){
+    m = ((u&0x3000000)>>24) | 0xf8;
+    printf("%c", (unsigned char)m);
+    m = ((u&0xfc0000)>>18) | 0x80;
+    printf("%c", (unsigned char)m);
+    m = ((u&0x3f000)>>12) | 0x80;
+    printf("%c", (unsigned char)m);
+    m = ((u&0xfc00)>>6) | 0x80;
+    printf("%c", (unsigned char)m);
+    m = (u&0x3f) | 0x80;
+    printf("%c", (unsigned char)m);
+  }
+  else {
+    m = ((u&0x40000000)>>30) | 0xfc;
+    printf("%c", (unsigned char)m);
+    m = ((u&0x3f000000)>>24) | 0x80;
+    printf("%c", (unsigned char)m);
+    m = ((u&0xfc0000)>>18) | 0x80;
+    printf("%c", (unsigned char)m);
+    m = ((u&0x3f000)>>12) | 0x80;
+    printf("%c", (unsigned char)m);
+    m = ((u&0xfc0)>>6) | 0x80;
+    printf("%c", (unsigned char)m);
+    m = (u&0x3f)| 0x80;
+    printf("%c", (unsigned char)m);
+  }
+}
+
+int main() {
+  int i,j;
+  long long n1, n2;
+  unsigned char b1[15], b2[15];
+  unsigned char buf[1024];
+  i=0;
+  while(fgets(buf, 1024, stdin)) {
+    //    printf("read %s\n", buf);
+    for(i=0;i<strlen(buf); i++) 
+      if(buf[i]=='U') {
+       if(buf[i+1] == '+') {
+         n1 = strtoll(buf+i+2,0,16);
+         printf("U+%05x", n1);
+         printUTF8(n1);printf("|");
+       }
+      }
+    printf("\n");
+  }
+}
+
diff --git a/includes/zhtable/simp2trad.manual b/includes/zhtable/simp2trad.manual
new file mode 100644 (file)
index 0000000..b5e1c3a
--- /dev/null
@@ -0,0 +1,178 @@
+U+0753b画|U+0756b畫|U+07575畵|
+U+0677f板|U+0677f板|U+095c6闆|
+U+08868表|U+08868表|U+09336錶|
+U+0624d才|U+0624d才|U+07e94纔|
+U+04e11丑|U+0919c醜|U+04e11丑|
+U+051fa出|U+051fa出|U+09f63齣|
+U+06dc0淀|U+06fb1澱|U+06dc0淀|
+U+051ac冬|U+051ac冬|U+09f15鼕|
+U+08303范|U+07bc4範|U+08303范|
+U+04e30丰|U+08c50豐|U+04e30丰|
+U+0522e刮|U+0522e刮|U+098b3颳|
+U+0540e后|U+05f8c後|U+0540e后|
+U+080e1胡|U+080e1胡|U+09b0d鬍|U+0885a衚|
+U+056de回|U+056de回|U+08ff4迴|
+U+04f19伙|U+05925夥|U+04f19伙|
+U+059dc姜|U+08591薑|U+059dc姜|
+U+0501f借|U+0501f借|U+085c9藉|
+U+0514b克|U+0514b克|U+0524b剋|
+U+056f0困|U+056f0困|U+0774f睏|
+U+06f13漓|U+06f13漓|U+07055灕|
+U+091cc里|U+091cc里|U+088e1裡|U+088cf裏|
+U+05e18帘|U+07c3e簾|U+05e18帘|
+U+09709霉|U+09709霉|U+09ef4黴|
+U+09762面|U+09762面|U+09eb5麵|
+U+08511蔑|U+08511蔑|U+0884a衊|
+U+05343千|U+05343千|U+097c6韆|
+U+079cb秋|U+079cb秋|U+097a6鞦|
+U+0677e松|U+0677e松|U+09b06鬆|
+U+054b8咸|U+054b8咸|U+09e79鹹|
+U+05411向|U+05411向|U+056ae嚮|U+066cf曏|
+U+04f59余|U+09918餘|U+04f59余|
+U+090c1郁|U+09b31鬱|U+090c1郁|
+U+05fa1御|U+05fa1御|U+079a6禦|
+U+0613f愿|U+09858願|U+0613f愿|
+U+04e91云|U+096f2雲|U+04e91云|
+U+082b8芸|U+082b8芸|U+08553蕓|
+U+06c84沄|U+06c84沄|U+06f90澐|
+U+081f4致|U+081f4致|U+07dfb緻|
+U+05236制|U+05236制|U+088fd製|
+U+06731朱|U+06731朱|U+07843硃|
+U+07b51筑|U+07bc9築|U+07b51筑|
+U+051c6准|U+06e96準|U+051c6准|
+U+05382厂|U+05ee0廠|U+05382厂|
+U+05e7f广|U+05ee3廣|U+05e7f广|
+U+08f9f辟|U+095e2闢|U+08f9f辟|
+U+0522b别|U+05225別|U+05f46彆|
+U+0535c卜|U+0535c卜|U+08514蔔|
+U+06c88沈|U+06c88沈|U+0700b瀋|
+U+051b2冲|U+06c96沖|U+0885d衝|
+U+079cd种|U+07a2e種|U+079cd种|
+U+0866b虫|U+087f2蟲|U+0866b虫|
+U+062c5担|U+064d4擔|U+062c5担|
+U+0515a党|U+09ee8黨|U+0515a党|
+U+06597斗|U+09b25鬥|U+06597斗|
+U+0513f儿|U+05152兒|U+0513f儿|
+U+05e72干|U+04e7e乾|U+05e79幹|U+05e72干|U+069a6\e%G榦\e%@|
+U+08c37谷|U+08c37谷|U+07a40穀|
+U+067dc柜|U+06ac3櫃|U+067dc柜|
+U+05408合|U+05408合|U+095a4閤|
+U+05212划|U+05283劃|U+05212划|
+U+0574f坏|U+058de壞|U+0574f坏|
+U+051e0几|U+05e7e幾|U+051e0几|
+U+07cfb系|U+07cfb系|U+07e6b繫|U+04fc2係|
+U+05bb6家|U+05bb6家|U+050a2傢|
+U+04ef7价|U+050f9價|U+04ef7价|
+U+0636e据|U+064da據|U+0636e据|
+U+05377卷|U+06372捲|U+05377卷|
+U+09002适|U+09069適|U+09002适|
+U+08721蜡|U+0881f蠟|U+08721蜡|
+U+0814a腊|U+081d8臘|U+0814a腊|
+U+04e86了|U+04e86了|U+077ad瞭|
+U+07d2f累|U+07d2f累|U+07e8d纍|
+U+04e48么|U+09ebd麽|U+04e48么|U+05e7a幺|U+09ebc麼|
+U+08499蒙|U+08499蒙|U+077c7矇|U+06fdb濛|U+061de懞|
+U+04e07万|U+0842c萬|U+04e07万|
+U+05b81宁|U+05be7寧|U+05b81宁|
+U+06734朴|U+06a38樸|U+06734朴|
+U+082f9苹|U+0860b蘋|U+082f9苹|
+U+04ec6仆|U+050d5僕|U+04ec6仆|
+U+066f2曲|U+066f2曲|U+09eaf麯|
+U+0786e确|U+078ba確|U+0786e确|
+U+0820d舍|U+0820d舍|U+06368捨|
+U+080dc胜|U+052dd勝|U+080dc胜|
+U+0672f术|U+08853術|U+0672f术|U+0672e朮|
+U+053f0台|U+053f0台|U+081fa臺|U+06aaf檯|U+098b1颱|
+U+04f53体|U+09ad4體|U+04f53体|
+U+06d82涂|U+05857塗|U+06d82涂|
+U+053f6叶|U+08449葉|U+053f6叶|
+U+05401吁|U+05401吁|U+07c72籲|
+U+065cb旋|U+065cb旋|U+0955f镟|
+U+04f63佣|U+050ad傭|U+04f63佣|
+U+04e0e与|U+08207與|U+04e0e与|
+U+06298折|U+06298折|U+0647a摺|
+U+05f81征|U+05fb5徵|U+05f81征|
+U+075c7症|U+075c7症|U+07665癥|
+U+06076恶|U+060e1惡|U+05641噁|
+U+053d1发|U+0767c發|U+09aee髮|
+U+0590d复|U+05fa9復|U+08907複|U+08986覆|
+U+06c47汇|U+0532f匯|U+05f59彙|
+U+083b7获|U+07372獲|U+07a6b穫|
+U+09965饥|U+098e2飢|U+09951饑|
+U+05c3d尽|U+076e1盡|U+05118儘|
+U+05386历|U+06b77歷|U+066c6曆|
+U+05364卤|U+06ef7滷|U+09e75鹵|
+U+05f25弥|U+05f4c彌|U+07030瀰|
+U+07b7e签|U+07c3d簽|U+07c56籖|
+U+07ea4纤|U+07e96纖|U+07e34縴|
+U+082cf苏|U+08607蘇|U+056cc囌|
+U+0575b坛|U+058c7壇|U+07f48罈|
+U+056e2团|U+05718團|U+07cf0糰|
+U+0987b须|U+09808須|U+09b1a鬚|
+U+0810f脏|U+081df臟|U+09ad2髒|
+U+053ea只|U+053ea只|U+096bb隻|
+U+0949f钟|U+09418鐘|U+0937e鍾|
+U+0836f药|U+085e5藥|U+0846f葯|
+U+0540c同|U+0540c同|U+08855衕|
+U+05fd7志|U+05fd7志|U+08a8c誌|
+U+0676f杯|U+0676f杯|U+076c3盃|
+U+05cb3岳|U+05cb3岳|U+05dbd嶽|
+U+05e03布|U+05e03布|U+04f48佈|
+U+05f53当|U+07576當|U+05679噹|
+U+0540a吊|U+05f14弔|U+0540a吊|
+U+04ec7仇|U+04ec7仇|U+08b8e讎|
+U+08574蕴|U+0860a蘊|U+085f4藴|
+U+07ebf线|U+07dda線|U+07dab綫|
+U+04e3a为|U+070ba為|U+07232爲|
+U+04ea7产|U+07522產|U+07523産|
+U+04f17众|U+0773e眾|U+08846衆|
+U+04f2a伪|U+0507d偽|U+050de僞|
+U+051eb凫|U+09ce7鳧|U+09cec鳬|
+U+05395厕|U+05ec1廁|U+053a0厠|
+U+0542f启|U+0555f啟|U+05553啓|
+U+05899墙|U+07246牆|U+058bb墻|
+U+058f3壳|U+06bbc殼|U+06bbb殻|
+U+05956奖|U+0734e獎|U+0596c奬|
+U+059ab妫|U+05aaf媯|U+05b00嬀|
+U+05e76并|U+04e26並|U+04f75併|
+U+05f55录|U+09304錄|U+09332録|
+U+060ab悫|U+06128愨|U+06164慤|
+U+06781极|U+06975極|U+06781极|
+U+06ca9沩|U+06e88溈|U+06f59潙|
+U+07618瘘|U+0763a瘺|U+0763b瘻|
+U+07877硷|U+09e7c鹼|U+07906礆|
+U+07ad6竖|U+08c4e豎|U+07aea竪|
+U+07edd绝|U+07d55絕|U+07d76絶|
+U+07ee3绣|U+07e61繡|U+07d89綉|
+U+07ee6绦|U+07d5b絛|U+07e27縧|
+U+07ef1绱|U+07dd4緔|U+0979d鞝|
+U+07ef7绷|U+07db3綳|U+07e43繃|
+U+07eff绿|U+07da0綠|U+07dd1緑|
+U+07f30缰|U+097c1韁|U+07e6e繮|
+U+082e7苧|U+082ce苎|U+085b4薴|
+U+083bc莼|U+08493蒓|U+084f4蓴|
+U+08bf4说|U+08aaa說|U+08aac説|
+U+08c23谣|U+08b20謠|U+08b21謡|
+U+08c2b谫|U+08b7e譾|U+08b2d謭|
+U+08d43赃|U+08d13贓|U+08d1c贜|
+U+08d4d赍|U+09f4e齎|U+08ceb賫|
+U+08d5d赝|U+08d17贗|U+08d0b贋|
+U+0915d酝|U+0919e醞|U+09196醖|
+U+091c7采|U+063a1採|U+091c7采|U+057f0埰|
+U+094a9钩|U+09264鉤|U+0920e鈎|
+U+094b5钵|U+07f3d缽|U+09262鉢|
+U+09508锈|U+092b9銹|U+093fd鏽|
+U+09510锐|U+092b3銳|U+092ed鋭|
+U+09528锨|U+06774杴|U+09341鍁|
+U+0954c镌|U+0942b鐫|U+093b8鎸|
+U+09562镢|U+09481钁|U+0941d鐝|
+U+09605阅|U+095b1閱|U+095b2閲|
+U+09893颓|U+09839頹|U+0983d頽|
+U+0989c颜|U+0984f顏|U+09854顔|
+U+09980馀|U+09918餘|
+U+09a82骂|U+07f75罵|U+099e1駡|
+U+09c87鲇|U+09bf0鯰|U+09b8e鮎|
+U+09c9e鲞|U+09bd7鯗|U+09b9d鮝|
+U+09cc4鳄|U+09c77鱷|U+09c10鰐|
+U+09e21鸡|U+096de雞|U+09dc4鷄|
+U+09e5a鹚|U+09dbf鶿|U+09dc0鷀|
diff --git a/includes/zhtable/toCN.manual b/includes/zhtable/toCN.manual
new file mode 100644 (file)
index 0000000..caff9c1
--- /dev/null
@@ -0,0 +1,331 @@
+記憶體      内存
+預設 默认
+預設 缺省
+串列 串行
+乙太網      以太网
+點陣圖      位图
+常式 例程
+通道 信道
+游標 光标
+光碟 光盘
+光碟機      光驱
+全形 全角
+共用 共享
+相容 兼容
+首碼 前缀
+尾碼 后缀
+載入 加载
+半形 半角
+變數 变量
+雜訊 噪声
+因數 因子
+線上 在线
+離線 脱机
+功能變數名稱     域名
+音效卡      声卡
+字型大小   字号
+字型檔      字库
+欄位 字段
+字元 字符
+存檔 存盘
+定址 寻址
+章節附註   尾注
+非同步      异步
+匯流排      总线
+括弧 括号
+介面 接口
+控制項      控件
+許可權      权限
+碟片 盘片
+矽片 硅片
+矽谷 硅谷
+硬碟 硬盘
+磁碟 磁盘
+磁軌 磁道
+程式控制   程控
+埠    端口
+運算元      算子
+演算法      算法
+晶片 芯片
+晶元 芯片
+片語 词组
+解碼 译码
+軟碟機      软驱
+快閃記憶體        闪存
+滑鼠 鼠标
+進位 进制
+互動式      交互式
+模擬 仿真
+優先順序   优先级
+感測 传感
+攜帶型      便携式
+資訊理論   信息论
+迴圈 循环
+防寫 写保护
+分散式      分布式
+解析度      分辨率
+程式 程序
+伺服器      服务器
+等於 等于
+區域網      局域网
+上傳 上载
+電腦 计算机
+巨集 宏
+掃瞄器      扫瞄仪
+寬頻 宽带
+視窗 窗口
+資料庫      数据库
+西曆 公历
+乳酪 奶酪
+鉅賈 巨商
+手電筒      手电
+萬曆 万历
+永曆 永历
+辭彙 词汇
+保全 保安
+慣用 习用
+母音 元音
+自由球      任意球
+頭槌 头球
+進球 入球
+顆進球      粒入球
+射門 打门
+蓋火鍋      火锅盖帽
+印表機      打印机
+打印機      打印机
+位元組      字节
+字節 字节
+列印 打印
+打印 打印
+硬體 硬件
+二極體      二极管
+二極管      二极管
+三極體      三极管
+三極管      三极管
+數位 数码
+數碼 数码
+軟體 软件
+軟件 软件
+網路 网络
+網絡 网络
+人工智慧   人工智能
+太空梭      航天飞机
+穿梭機      航天飞机
+網際網路   因特网
+互聯網      因特网
+機械人      机器人
+機器人      机器人
+行動電話   移动电话
+流動電話   移动电话
+調制解調器        调制解调器
+數據機      调制解调器
+短訊 短信
+簡訊 短信
+烏茲別克   乌兹别克斯坦
+查德 乍得
+乍得 乍得
+也門 
+葉門 也门
+伯利茲      伯利兹
+貝里斯      伯利兹
+維德角      佛得角
+佛得角      佛得角
+克羅地亞   克罗地亚
+克羅埃西亞        克罗地亚
+岡比亞      冈比亚
+甘比亞      冈比亚
+幾內亞比紹        几内亚比绍
+幾內亞比索        几内亚比绍
+列支敦斯登        列支敦士登
+列支敦士登        列支敦士登
+利比里亞   利比里亚
+賴比瑞亞   利比里亚
+加納 加纳
+迦納 加纳
+加彭 加蓬
+加蓬 加蓬
+博茨瓦納   博茨瓦纳
+波札那      博茨瓦纳
+卡塔爾      卡塔尔
+卡達 卡塔尔
+盧旺達      卢旺达
+盧安達      卢旺达
+危地馬拉   危地马拉
+瓜地馬拉   危地马拉
+厄瓜多爾   厄瓜多尔
+厄瓜多      厄瓜多尔
+厄立特里亞        厄立特里亚
+厄利垂亞   厄立特里亚
+吉布堤      吉布提
+吉布地      吉布提
+哈薩克      哈萨克斯坦
+哥斯達黎加        哥斯达黎加
+哥斯大黎加        哥斯达黎加
+圖瓦盧      图瓦卢
+吐瓦魯      图瓦卢
+土庫曼      土库曼斯坦
+聖盧西亞   圣卢西亚
+聖露西亞   圣卢西亚
+聖吉斯納域斯     圣基茨和尼维斯
+聖克里斯多福及尼維斯 圣基茨和尼维斯
+聖文森特和格林納丁斯 圣文森特和格林纳丁斯
+聖文森及格瑞那丁       圣文森特和格林纳丁斯
+聖馬力諾   圣马力诺
+聖馬利諾   圣马力诺
+圭亞那      圭亚那
+蓋亞那      圭亚那
+坦桑尼亞   坦桑尼亚
+坦尚尼亞   坦桑尼亚
+埃塞俄比亞        埃塞俄比亚
+衣索比亞   埃塞俄比亚
+吉里巴斯   基里巴斯
+基里巴斯   基里巴斯
+塔吉克      塔吉克斯坦
+獅子山      塞拉利昂
+塞拉利昂   塞拉利昂
+塞普勒斯   塞浦路斯
+塞浦路斯   塞浦路斯
+塞舌爾      塞舌尔
+塞席爾      塞舌尔
+多明尼加共和國  多米尼加
+多明尼加   多米尼加
+多明尼加聯邦     多米尼加联邦
+多米尼克   多米尼加联邦
+安提瓜和巴布達  安提瓜和巴布达
+安地卡及巴布達  安提瓜和巴布达
+尼日利亞   尼日利亚
+奈及利亞   尼日利亚
+尼日爾      尼日尔
+尼日 尼日尔
+巴貝多      巴巴多斯
+巴巴多斯   巴巴多斯
+巴布亞新畿內亞  巴布亚新几内亚
+巴布亞紐幾內亞  巴布亚新几内亚
+布基納法索        布基纳法索
+布吉納法索        布基纳法索
+蒲隆地      布隆迪
+布隆迪      布隆迪
+希臘 希腊
+帛琉 帕劳
+義大利      意大利
+意大利      意大利
+所羅門群島        所罗门群岛
+索羅門群島        所罗门群岛
+汶萊 文莱
+斯威士蘭   斯威士兰
+史瓦濟蘭   斯威士兰
+斯洛文尼亞        斯洛文尼亚
+斯洛維尼亞        斯洛文尼亚
+新西蘭      新西兰
+紐西蘭      新西兰
+北韓 朝鲜
+格林納達   格林纳达
+格瑞那達   格林纳达
+格魯吉亞   格鲁吉亚
+喬治亞      格鲁吉亚
+梵蒂岡      梵蒂冈
+教廷 梵蒂冈
+毛里塔尼亞        毛里塔尼亚
+茅利塔尼亞        毛里塔尼亚
+毛里裘斯   毛里求斯
+模里西斯   毛里求斯
+沙地阿拉伯        沙特阿拉伯
+沙烏地阿拉伯     沙特阿拉伯
+波斯尼亞黑塞哥維那    波斯尼亚和黑塞哥维那
+波士尼亞赫塞哥維納    波斯尼亚和黑塞哥维那
+津巴布韋   津巴布韦
+辛巴威      津巴布韦
+宏都拉斯   洪都拉斯
+洪都拉斯   洪都拉斯
+特立尼達和多巴哥       特立尼达和托巴哥
+千里達托貝哥     特立尼达和托巴哥
+瑙魯 瑙鲁
+諾魯 瑙鲁
+瓦努阿圖   瓦努阿图
+萬那杜      瓦努阿图
+溫納圖      瓦努阿图
+科摩羅      科摩罗
+葛摩 科摩罗
+象牙海岸   科特迪瓦
+突尼西亞   突尼斯
+索馬里      索马里
+索馬利亞   索马里
+老撾 老挝
+寮國 老挝
+肯雅 肯尼亚
+肯亞 肯尼亚
+蘇利南      苏里南
+莫三比克   莫桑比克
+莫桑比克   莫桑比克
+萊索托      莱索托
+賴索托      莱索托
+貝寧 贝宁
+貝南 贝宁
+贊比亞      赞比亚
+尚比亞      赞比亚
+亞塞拜然   阿塞拜疆
+阿塞拜疆   阿塞拜疆
+阿拉伯聯合酋長國       阿拉伯联合酋长国
+阿拉伯聯合大公國       阿拉伯联合酋长国
+南韓 韩国
+馬爾代夫   马尔代夫
+馬爾地夫   马尔代夫
+馬爾他      马耳他
+馬里 马里
+馬利 马里
+即食麵      方便面
+快速面      方便面
+速食麵      方便面
+泡麵 方便面
+笨豬跳      蹦极跳
+绑紧跳      蹦极跳
+冷盤     凉菜
+冷菜 凉菜
+散钱 零钱
+谐星 笑星    
+夜学 夜校
+华乐 民乐
+中樂 民乐
+住屋 住房
+屋价 房价
+的士 出租车
+計程車      出租车
+巴士 公共汽车
+公車 公共汽车
+單車 自行车
+節慶 节日
+芝士 乾酪
+狗隻 犬只
+士多啤梨   草莓
+忌廉 奶油
+桌球 台球
+撞球 台球
+雪糕 冰淇淋
+衞生 卫生
+衛生 卫生
+賓士 奔驰
+平治 奔驰
+捷豹 美洲虎
+積架 美洲虎
+福斯 大众
+福士 大众
+雪鐵龍      雪铁龙
+萬事得      马自达
+馬自達      马自达
+寶獅 标志
+布殊 布什
+布希 布什
+柯林頓      克林顿
+克林頓      克林顿
+薩達姆      萨达姆
+海珊 萨达姆
+梵谷 凡高
+大衛碧咸   大卫·贝克汉姆
+米高奧雲   迈克尔·欧文
+卡佩雅蒂   珍妮弗·卡普里亚蒂
+沙芬 马拉特·萨芬
+舒麥加      迈克尔·舒马赫
+希特拉      希特勒
+戴安娜      狄安娜
+黛安娜      狄安娜
+希拉 赫拉
\ No newline at end of file
diff --git a/includes/zhtable/toHK.manual b/includes/zhtable/toHK.manual
new file mode 100644 (file)
index 0000000..ab62345
--- /dev/null
@@ -0,0 +1,211 @@
+打印机      打印機
+印表機      打印機
+字节 字節
+位元組      字節
+打印 打印
+列印 打印
+硬件 硬件
+硬體 硬件
+二极管      二極管
+二極體      二極管
+三极管      三極管
+三極體      三極管
+数码 數碼
+數位 數碼
+软件 軟件
+軟體 軟件
+网络 網絡
+網路 網絡
+人工智能   人工智能
+人工智慧   人工智能
+航天飞机   穿梭機
+太空梭      穿梭機
+因特网      互聯網
+網際網路   互聯網
+机器人      機械人
+機器人      機械人
+移动电话   流動電話
+行動電話   流動電話
+调制解调器        調制解調器
+數據機      調制解調器
+短信 短訊
+簡訊 短訊
+乍得 乍得
+查德 乍得
+也门 也門
+葉門 也門
+伯利兹      伯利茲
+貝里斯      伯利茲
+佛得角      佛得角
+維德角      佛得角
+克罗地亚   克羅地亞
+克羅埃西亞        克羅地亞
+冈比亚      岡比亞
+甘比亞      岡比亞
+几内亚比绍        幾內亞比紹
+幾內亞比索        幾內亞比紹
+列支敦士登        列支敦士登
+列支敦斯登        列支敦士登
+利比里亚   利比里亞
+賴比瑞亞   利比里亞
+加纳 加納
+迦納 加納
+加蓬 加蓬
+加彭 加蓬
+博茨瓦纳   博茨瓦納
+波札那      博茨瓦納
+卡塔尔      卡塔爾
+卡達 卡塔爾
+卢旺达      盧旺達
+盧安達      盧旺達
+危地马拉   危地馬拉
+瓜地馬拉   危地馬拉
+厄瓜多尔   厄瓜多爾
+厄瓜多      厄瓜多爾
+厄立特里亚        厄立特里亞
+厄利垂亞   厄立特里亞
+吉布提      吉布堤
+吉布地      吉布堤
+哥斯达黎加        哥斯達黎加
+哥斯大黎加        哥斯達黎加
+图瓦卢      圖瓦盧
+吐瓦魯      圖瓦盧
+圣卢西亚   聖盧西亞
+聖露西亞   聖盧西亞
+圣基茨和尼维斯  聖吉斯納域斯
+聖克里斯多福及尼維斯 聖吉斯納域斯
+圣文森特和格林纳丁斯 聖文森特和格林納丁斯
+聖文森及格瑞那丁       聖文森特和格林納丁斯
+圣马力诺   聖馬力諾
+聖馬利諾   聖馬力諾
+圭亚那      圭亞那
+蓋亞那      圭亞那
+坦桑尼亚   坦桑尼亞
+坦尚尼亞   坦桑尼亞
+埃塞俄比亚        埃塞俄比亞
+衣索比亞   埃塞俄比亞
+基里巴斯   基里巴斯
+吉里巴斯   基里巴斯
+獅子山      塞拉利昂
+塞普勒斯   塞浦路斯
+塞舌尔      塞舌爾
+塞席爾      塞舌爾
+多米尼加   多明尼加共和國
+多明尼加   多明尼加共和國
+多米尼加联邦     多明尼加聯邦
+多米尼克   多明尼加聯邦
+安提瓜和巴布达  安提瓜和巴布達
+安地卡及巴布達  安提瓜和巴布達
+尼日利亚   尼日利亞
+奈及利亞   尼日利亞
+尼日尔      尼日爾
+尼日 尼日爾
+巴巴多斯   巴巴多斯
+巴貝多      巴巴多斯
+巴布亚新几内亚  巴布亞新畿內亞
+巴布亞紐幾內亞  巴布亞新畿內亞
+布基纳法索        布基納法索
+布吉納法索        布基納法索
+布隆迪      布隆迪
+蒲隆地      布隆迪
+義大利      意大利
+所罗门群岛        所羅門群島
+索羅門群島        所羅門群島
+斯威士兰   斯威士蘭
+史瓦濟蘭   斯威士蘭
+斯洛文尼亚        斯洛文尼亞
+斯洛維尼亞        斯洛文尼亞
+新西兰      新西蘭
+紐西蘭      新西蘭
+格林纳达   格林納達
+格瑞那達   格林納達
+格鲁吉亚   格魯吉亞
+喬治亞      格魯吉亞
+梵蒂冈      梵蒂岡
+教廷 梵蒂岡
+毛里塔尼亚        毛里塔尼亞
+茅利塔尼亞        毛里塔尼亞
+毛里求斯   毛里裘斯
+模里西斯   毛里裘斯
+沙特阿拉伯        沙地阿拉伯
+沙烏地阿拉伯     沙地阿拉伯
+波斯尼亚和黑塞哥维那 波斯尼亞黑塞哥維那
+波士尼亞赫塞哥維納    波斯尼亞黑塞哥維那
+津巴布韦   津巴布韋
+辛巴威      津巴布韋
+洪都拉斯   洪都拉斯
+宏都拉斯   洪都拉斯
+特立尼达和托巴哥       特立尼達和多巴哥
+千里達托貝哥     特立尼達和多巴哥
+瑙鲁 瑙魯
+諾魯 瑙魯
+瓦努阿图   瓦努阿圖
+萬那杜      瓦努阿圖
+科摩罗      科摩羅
+葛摩 科摩羅
+索马里      索馬里
+索馬利亞   索馬里
+老挝 老撾
+寮國 老撾
+肯尼亚      肯雅
+肯亞 肯雅
+莫桑比克   莫桑比克
+莫三比克   莫桑比克
+莱索托      萊索托
+賴索托      萊索托
+贝宁 貝寧
+貝南 貝寧
+赞比亚      贊比亞
+尚比亞      贊比亞
+阿塞拜疆   阿塞拜疆
+亞塞拜然   阿塞拜疆
+阿拉伯联合酋长国       阿拉伯聯合酋長國
+阿拉伯聯合大公國       阿拉伯聯合酋長國
+马尔代夫   馬爾代夫
+馬爾地夫   馬爾代夫
+马里 馬里
+馬利 馬里
+方便面      即食麵
+快速面      即食麵
+速食麵      即食麵
+泡麵 即食麵
+土豆 薯仔
+华乐 中樂
+民乐 中樂
+計程車              的士
+出租车      的士
+公車 巴士
+公共汽车   巴士
+自行车      單車
+节日 節慶
+犬只 狗隻
+台球 桌球
+撞球 桌球
+冰淇淋      雪糕
+冰淇淋      雪糕
+卫生 衞生
+衛生 衞生
+老人 長者
+賓士 平治
+捷豹 積架
+福斯 福士
+雪铁龙      先進
+雪鐵龍      先進
+沃尓沃      富豪
+马自达      萬事得
+馬自達      萬事得
+寶獅 標致
+布什 布殊
+布希 布殊
+克林顿      克林頓
+柯林頓      克林頓
+萨达姆      薩達姆
+海珊 薩達姆
+大卫·贝克汉姆   大衛碧咸
+迈克尔·欧文      米高奧雲
+珍妮弗·卡普里亚蒂     卡佩雅蒂
+马拉特·萨芬      沙芬
+迈克尔·舒马赫   舒麥加
+希特勒      希特拉
+狄安娜      戴安娜
+黛安娜      戴安娜
\ No newline at end of file
diff --git a/includes/zhtable/toSG.manual b/includes/zhtable/toSG.manual
new file mode 100644 (file)
index 0000000..9a399bc
--- /dev/null
@@ -0,0 +1,15 @@
+方便面      快速面
+速食麵      快速面
+即食麵      快速面
+蹦极跳      绑紧跳
+笨豬跳      绑紧跳
+凉菜 冷菜
+冷盤 冷菜
+零钱 散钱
+散紙 散钱
+笑星 谐星
+夜校 夜学
+民乐 华乐
+住房 住屋
+房价 屋价
+泡麵 快速面
\ No newline at end of file
diff --git a/includes/zhtable/toTW.manual b/includes/zhtable/toTW.manual
new file mode 100644 (file)
index 0000000..5c90dbe
--- /dev/null
@@ -0,0 +1,309 @@
+内存 記憶體
+默认 預設
+缺省 預設
+串行 串列
+以太网      乙太網
+位图 點陣圖
+例程 常式
+信道 通道
+光标 游標
+光盘 光碟
+光驱 光碟機
+全角 全形
+共享 共用
+兼容 相容
+前缀 首碼
+后缀 尾碼
+加载 載入
+半角 半形
+变量 變數
+噪声 雜訊
+因子 因數
+在线 線上
+脱机 離線
+域名 功能變數名稱
+声卡 音效卡
+字号 字型大小
+字库 字型檔
+字段 欄位
+字符 字元
+存盘 存檔
+寻址 定址
+尾注 章節附註
+异步 非同步
+总线 匯流排
+括号 括弧
+接口 介面
+控件 控制項
+权限 許可權
+盘片 碟片
+硅片 矽片
+硅谷 矽谷
+硬盘 硬碟
+磁盘 磁碟
+磁道 磁軌
+程控 程式控制
+端口 埠
+算子 運算元
+算法 演算法
+芯片 晶片
+芯片 晶元
+词组 片語
+译码 解碼
+软驱 軟碟機
+闪存 快閃記憶體
+鼠标 滑鼠
+进制 進位
+交互式      互動式
+仿真 模擬
+优先级      優先順序
+传感 感測
+便携式      攜帶型
+信息论      資訊理論
+循环 迴圈
+写保护      防寫
+分布式      分散式
+分辨率      解析度
+程序 程式
+服务器      伺服器
+等于 等於
+局域网      區域網
+上载 上傳
+计算机      電腦
+宏    巨集
+扫瞄仪      掃瞄器
+宽带 寬頻
+窗口 視窗
+数据库      資料庫
+公历 西曆
+奶酪 乳酪
+巨商 鉅賈
+手电 手電筒
+万历 萬曆
+永历 永曆
+词汇 辭彙
+保安 保全
+习用 慣用
+元音 母音
+任意球      自由球
+头球 頭槌
+入球 進球
+粒入球      顆進球
+打门 射門
+火锅盖帽   蓋火鍋
+打印机      印表機
+打印機      印表機
+字节 位元組
+字節 位元組
+打印 列印
+打印 列印
+硬件 硬體
+硬件 硬體
+二极管      二極體
+二極管      二極體
+三极管      三極體
+三極管      三極體
+数码 數位
+數碼 數位
+软件 軟體
+軟件 軟體
+网络 網路
+網絡 網路
+人工智能   人工智慧
+航天飞机   太空梭
+穿梭機      太空梭
+因特网      網際網路
+互聯網      網際網路
+机器人      機器人
+機械人      機器人
+移动电话   行動電話
+流動電話   行動電話
+调制解调器        數據機
+調制解調器        數據機
+短信 簡訊
+短訊 簡訊
+乌兹别克斯坦     烏茲別克
+乍得 查德
+乍得 查德
+也门 葉門
+也門 葉門
+伯利兹      貝里斯
+伯利茲      貝里斯
+佛得角      維德角
+佛得角      維德角
+克罗地亚   克羅埃西亞
+克羅地亞   克羅埃西亞
+冈比亚      甘比亞
+岡比亞      甘比亞
+几内亚比绍        幾內亞比索
+幾內亞比紹        幾內亞比索
+列支敦士登        列支敦斯登
+列支敦士登        列支敦斯登
+利比里亚   賴比瑞亞
+利比里亞   賴比瑞亞
+加纳 迦納
+加納 迦納
+加蓬 加彭
+加蓬 加彭
+博茨瓦纳   波札那
+博茨瓦納   波札那
+卡塔尔      卡達
+卡塔爾      卡達
+卢旺达      盧安達
+盧旺達      盧安達
+危地马拉   瓜地馬拉
+危地馬拉   瓜地馬拉
+厄瓜多尔   厄瓜多
+厄瓜多爾   厄瓜多
+厄立特里亚        厄利垂亞
+厄立特里亞        厄利垂亞
+吉布提      吉布地
+吉布堤      吉布地
+哈萨克斯坦        哈薩克
+哥斯达黎加        哥斯大黎加
+哥斯達黎加        哥斯大黎加
+图瓦卢      吐瓦魯
+圖瓦盧      吐瓦魯
+土库曼斯坦        土庫曼
+圣卢西亚   聖露西亞
+聖盧西亞   聖露西亞
+圣基茨和尼维斯  聖克里斯多福及尼維斯
+聖吉斯納域斯     聖克里斯多福及尼維斯
+圣文森特和格林纳丁斯 聖文森及格瑞那丁
+聖文森特和格林納丁斯 聖文森及格瑞那丁
+圣马力诺   聖馬利諾
+聖馬力諾   聖馬利諾
+圭亚那      蓋亞那
+圭亞那      蓋亞那
+坦桑尼亚   坦尚尼亞
+坦桑尼亞   坦尚尼亞
+埃塞俄比亚        衣索比亞
+埃塞俄比亞        衣索比亞
+基里巴斯   吉里巴斯
+基里巴斯   吉里巴斯
+塔吉克斯坦        塔吉克
+塞拉利昂   獅子山
+塞拉利昂   獅子山
+塞浦路斯   塞普勒斯
+塞浦路斯   塞普勒斯
+塞舌尔      塞席爾
+塞舌爾      塞席爾
+多米尼加   多明尼加
+多明尼加共和國  多明尼加
+多米尼加联邦     多米尼克
+多明尼加聯邦     多米尼克
+安提瓜和巴布达  安地卡及巴布達
+安提瓜和巴布達  安地卡及巴布達
+尼日利亚   奈及利亞
+尼日利亞   奈及利亞
+尼日尔      尼日
+尼日爾      尼日
+巴巴多斯   巴貝多
+巴巴多斯   巴貝多
+巴布亚新几内亚  巴布亞紐幾內亞
+巴布亞新畿內亞  巴布亞紐幾內亞
+布基纳法索        布吉納法索
+布基納法索        布吉納法索
+布隆迪      蒲隆地
+布隆迪      蒲隆地
+希腊 希臘
+帕劳 帛琉
+意大利      義大利
+意大利      義大利
+所罗门群岛        索羅門群島
+所羅門群島        索羅門群島
+文莱 汶萊
+斯威士兰   史瓦濟蘭
+斯威士蘭   史瓦濟蘭
+斯洛文尼亚        斯洛維尼亞
+斯洛文尼亞        斯洛維尼亞
+新西兰      紐西蘭
+新西蘭      紐西蘭
+朝鲜 北韓
+格林纳达   格瑞那達
+格林納達   格瑞那達
+格鲁吉亚   喬治亞
+格魯吉亞   喬治亞
+梵蒂冈      教廷
+梵蒂岡      教廷
+毛里塔尼亚        茅利塔尼亞
+毛里塔尼亞        茅利塔尼亞
+毛里求斯   模里西斯
+毛里裘斯   模里西斯
+沙特阿拉伯        沙烏地阿拉伯
+沙地阿拉伯        沙烏地阿拉伯
+波斯尼亚和黑塞哥维那 波士尼亞赫塞哥維納
+波斯尼亞黑塞哥維那    波士尼亞赫塞哥維納
+津巴布韦   辛巴威
+津巴布韋   辛巴威
+洪都拉斯   宏都拉斯
+洪都拉斯   宏都拉斯
+特立尼达和托巴哥       千里達托貝哥
+特立尼達和多巴哥       千里達托貝哥
+瑙鲁 諾魯
+瑙魯 諾魯
+瓦努阿图   萬那杜
+瓦努阿圖   萬那杜
+溫納圖萬   那杜
+科摩罗      葛摩
+科摩羅      葛摩
+科特迪瓦   象牙海岸
+突尼斯      突尼西亞
+索马里      索馬利亞
+索馬里      索馬利亞
+老挝 寮國
+老撾 寮國
+肯尼亚      肯亞
+肯雅 肯亞
+苏里南      蘇利南
+莫桑比克   莫三比克
+莱索托      賴索托
+萊索托      賴索托
+贝宁 貝南
+貝寧 貝南
+赞比亚      尚比亞
+贊比亞      尚比亞
+阿塞拜疆   亞塞拜然
+阿塞拜疆   亞塞拜然
+阿拉伯联合酋长国       阿拉伯聯合大公國
+阿拉伯聯合酋長國       阿拉伯聯合大公國
+韩国 南韓
+马尔代夫   馬爾地夫
+馬爾代夫   馬爾地夫
+马耳他      馬爾他
+马里 馬利
+馬里 馬利
+方便面      速食麵
+快速面      速食麵
+即食麵      速食麵
+薯仔 土豆
+蹦极跳      笨豬跳
+绑紧跳      笨豬跳
+冷菜 冷盤
+凉菜 冷盤
+的士 計程車
+出租车      計程車
+巴士 公車
+公共汽车   公車
+台球 撞球
+桌球 撞球
+雪糕 冰淇淋
+卫生 衛生
+衞生 衛生
+平治 賓士
+奔驰 賓士
+積架 捷豹
+福士 福斯
+雪铁龙      雪鐵龍
+马自达      馬自達
+萬事得      馬自達
+布什 布希
+布殊 布希
+克林顿      柯林頓
+克林頓      柯林頓
+萨达姆      海珊
+薩達姆      海珊
+凡高 梵谷
+狄安娜      黛安娜
+戴安娜      黛安娜
+赫拉 希拉
\ No newline at end of file
diff --git a/includes/zhtable/trad2simp.manual b/includes/zhtable/trad2simp.manual
new file mode 100644 (file)
index 0000000..da06931
--- /dev/null
@@ -0,0 +1,15 @@
+U+056a5嚥|U+054bd咽|
+U+0585a塚|U+051a2冢|
+U+05dbd嶽|U+05cb3岳|
+U+04e99亙|U+04e98亘|
+U+081e5臥|U+05367卧|
+U+04f48佈|U+05e03布|
+U+06dd2淒|U+051c4凄|
+U+06de8淨|U+051c0净|
+U+05147兇|U+051f6凶|
+U+04f48佈|U+05e03布|
+U+06c59汙|U+06c61污|
+U+056ae嚮|U+05411向|
+U+09031週|U+05468周|
+U+0904a遊|U+06e38游|
+U+06de9淩|U+051cc凌|
diff --git a/includes/zhtable/tradphrases.manual b/includes/zhtable/tradphrases.manual
new file mode 100644 (file)
index 0000000..b2fec81
--- /dev/null
@@ -0,0 +1,149 @@
+一隻
+三隻
+四隻
+五隻
+六隻
+七隻
+八隻
+九隻
+十隻
+百隻
+千隻
+萬隻
+億隻
+並存著
+乾絲
+乾著急
+体育鍛鍊
+借著
+偷雞不著
+几絲
+划著
+划著走
+別著
+刮著
+千絲萬縷
+參与
+參与者
+參合
+參考價值
+參與
+參與人員
+參與制
+參與感
+參與者
+參觀團
+參觀團體
+參閱
+吃著不盡
+合著
+合著者
+吊帶褲
+吊掛著
+吊著
+吊褲
+吊褲帶
+向著
+嚴絲合縫
+回絲
+回著
+塗著
+壟斷價格
+壟斷資產
+壟斷集團
+姜絲
+帶團參加
+干著急
+幾絲
+彆著
+怎麼著
+憑藉著
+接著說
+擔著
+擔負著
+敘說著
+斗轉參橫
+旋繞著
+板著臉
+標志著
+正當著
+沈著
+沖著
+派團參加
+涂著
+湊合著
+瀰漫著
+為著
+煙斗絲
+率團參加
+畫著
+當著
+發著
+直接參与
+睡著了
+秋褲
+積极參与
+積极參加
+簽著
+系著
+絕對參照
+絲來線去
+絲布
+絲板
+絲瓜布
+絲絨布
+絲線
+絲織廠
+絲蟲
+緊繃著
+繃著
+繃著臉
+繃著臉兒
+繫著
+罵著
+肉絲麵
+背向著
+菌絲体
+菌絲體
+著兒
+著書立說
+著色軟體
+著重指出
+著錄
+著錄規則
+薑絲
+藉著
+蘊含著
+蘊涵著
+衝著
+被覆著
+覆著
+覆蓋著
+訴說著
+說著
+請參閱
+謝絕參觀
+豎著
+豐濱
+豐濱鄉
+象徵著
+這么著
+這麼著
+那麼著
+配合著
+醞釀著
+錄著
+鍛鍊出
+鍛鍊身体
+關係著
+雞絲
+雞絲麵
+面朝著
+面臨著
+顯著標志
+颳著
+髮絲
+鬥著
+鬧著玩儿
+鬧著玩兒
+鯰魚
diff --git a/index.php b/index.php
new file mode 100644 (file)
index 0000000..5ce265e
--- /dev/null
+++ b/index.php
@@ -0,0 +1,281 @@
+<?php
+/**
+ * Main wiki script; see docs/design.txt
+ * @package MediaWiki
+ */
+
+$wgRequestTime = microtime();
+
+unset( $IP );
+@ini_set( 'allow_url_fopen', 0 ); # For security...
+
+# Valid web server entry point, enable includes.
+# Please don't move this line to includes/Defines.php. This line essentially defines
+# a valid entry point. If you put it in includes/Defines.php, then any script that includes
+# it becomes an entry point, thereby defeating its purpose.
+define( 'MEDIAWIKI', true );
+require_once( './includes/Defines.php' );
+
+if( !file_exists( 'LocalSettings.php' ) ) {
+       $IP = "." ;
+       require_once( 'includes/DefaultSettings.php' ); # used for printing the version
+?>
+<!DOCTYPE html PUBLIC "-//W3C/DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
+       <head>
+               <title>MediaWiki <?php echo $wgVersion ?></title>
+               <meta http-equiv='Content-Type' content='text/html; charset=utf-8' />
+
+               <style type='text/css' media='screen, projection'>
+                       html, body {
+                               color: #000;
+                               background-color: #fff;
+                               font-family: serif;
+                               text-align:center;
+                       }
+
+                       h1 {
+                               font-size: 150%;
+                       }
+               </style>
+       </head>
+       <body>
+               <img src='skins/common/images/mediawiki.png' alt='The MediaWiki logo' />
+
+               <h1>MediaWiki <?php echo $wgVersion ?></h1>
+               <div class='error'>
+               <?php
+               if ( file_exists( 'config/LocalSettings.php' ) ) {
+                       echo( "To complete the installation, move <tt>config/LocalSettings.php</tt> to the parent directory." );
+               } else {
+                       echo( "You'll have to <a href='config/index.php' title='setup'>set the wiki up</a> first!" );
+               }
+               ?>
+
+               </div>
+       </body>
+</html>
+<?php
+       die();
+}
+
+require_once( './LocalSettings.php' );
+require_once( 'includes/Setup.php' );
+
+wfProfileIn( 'main-misc-setup' );
+OutputPage::setEncodings(); # Not really used yet
+
+# Query string fields
+$action = $wgRequest->getVal( 'action', 'view' );
+$title = $wgRequest->getVal( 'title' );
+
+if ($wgRequest->getVal( 'printable' ) == 'yes') {
+       $wgOut->setPrintable();
+}
+
+if ( '' == $title && 'delete' != $action ) {
+       $wgTitle = Title::newFromText( wfMsgForContent( 'mainpage' ) );
+} elseif ( $curid = $wgRequest->getInt( 'curid' ) ) {
+       # URLs like this are generated by RC, because rc_title isn't always accurate
+       $wgTitle = Title::newFromID( $curid );
+} else {
+       $wgTitle = Title::newFromURL( $title );
+       /* check variant links so that interwiki links don't have to worry about
+          the possible different language variants
+       */
+       if( !is_null($wgTitle) && $wgTitle->getArticleID() == 0 )
+               $wgContLang->findVariantLink( $title, $wgTitle );
+
+}
+wfProfileOut( 'main-misc-setup' );
+
+# Debug statement for user levels
+// print_r($wgUser);
+
+$search = $wgRequest->getText( 'search' );
+if( !is_null( $search ) && $search !== '' ) {
+       // Compatibility with old search URLs which didn't use Special:Search
+       // Do this above the read whitelist check for security...
+       $wgTitle = Title::makeTitle( NS_SPECIAL, 'Search' );
+}
+
+# If the user is not logged in, the Namespace:title of the article must be in
+# the Read array in order for the user to see it. (We have to check here to
+# catch special pages etc. We check again in Article::view())
+if ( !is_null( $wgTitle ) && !$wgTitle->userCanRead() ) {
+       $wgOut->loginToUse();
+       $wgOut->output();
+       exit;
+}
+
+wfProfileIn( 'main-action' );
+
+if( !$wgDisableInternalSearch && !is_null( $search ) && $search !== '' ) {
+       require_once( 'includes/SpecialSearch.php' );
+       $wgTitle = Title::makeTitle( NS_SPECIAL, 'Search' );
+       wfSpecialSearch();
+} else if( !$wgTitle or $wgTitle->getDBkey() == '' ) {
+       $wgTitle = Title::newFromText( wfMsgForContent( 'badtitle' ) );
+       $wgOut->errorpage( 'badtitle', 'badtitletext' );
+} else if ( $wgTitle->getInterwiki() != '' ) {
+       if( $rdfrom = $wgRequest->getVal( 'rdfrom' ) ) {
+               $url = $wgTitle->getFullURL( 'rdfrom=' . urlencode( $rdfrom ) );
+       } else {
+               $url = $wgTitle->getFullURL();
+       }
+       # Check for a redirect loop
+       if ( !preg_match( '/^' . preg_quote( $wgServer, '/' ) . '/', $url ) && $wgTitle->isLocal() ) {
+               $wgOut->redirect( $url );
+       } else {
+               $wgTitle = Title::newFromText( wfMsgForContent( 'badtitle' ) );
+               $wgOut->errorpage( 'badtitle', 'badtitletext' );
+       }
+} else if ( ( $action == 'view' ) &&
+       (!isset( $_GET['title'] ) || $wgTitle->getPrefixedDBKey() != $_GET['title'] ) &&
+       !count( array_diff( array_keys( $_GET ), array( 'action', 'title' ) ) ) )
+{
+       /* redirect to canonical url, make it a 301 to allow caching */
+       $wgOut->setSquidMaxage( 1200 );
+       $wgOut->redirect( $wgTitle->getFullURL(), '301');
+} else if ( NS_SPECIAL == $wgTitle->getNamespace() ) {
+       # actions that need to be made when we have a special pages
+       SpecialPage::executePath( $wgTitle );
+} else {
+       if ( NS_MEDIA == $wgTitle->getNamespace() ) {
+               $wgTitle = Title::makeTitle( NS_IMAGE, $wgTitle->getDBkey() );
+       }
+
+       $ns = $wgTitle->getNamespace();
+       if ( $ns == NS_IMAGE ) {
+               require_once( 'includes/ImagePage.php' );
+               $wgArticle = new ImagePage( $wgTitle );
+       } elseif ( $wgUseCategoryMagic && $ns == NS_CATEGORY ) {
+               require_once( 'includes/CategoryPage.php' );
+               $wgArticle = new CategoryPage( $wgTitle );
+       } else {
+               $wgArticle = new Article( $wgTitle );
+       }
+
+       if ( in_array( $action, $wgDisabledActions ) ) {
+               $wgOut->errorpage( 'nosuchaction', 'nosuchactiontext' );
+       } else {
+               switch( $action ) {
+                       case 'view':
+                               $wgOut->setSquidMaxage( $wgSquidMaxage );
+                               $wgArticle->view();
+                               break;
+                       case 'watch':
+                       case 'unwatch':
+                       case 'delete':
+                       case 'revert':
+                       case 'rollback':
+                       case 'protect':
+                       case 'unprotect':
+                       case 'info':
+                       case 'markpatrolled':
+                       case 'validate':
+                       case 'render':
+                       case 'deletetrackback':
+                               $wgArticle->$action();
+                               break;
+                       case 'print':
+                               $wgArticle->view();
+                               break;
+                       case 'dublincore':
+                               if( !$wgEnableDublinCoreRdf ) {
+                                       wfHttpError( 403, 'Forbidden', wfMsg( 'nodublincore' ) );
+                               } else {
+                                       require_once( 'includes/Metadata.php' );
+                                       wfDublinCoreRdf( $wgArticle );
+                               }
+                               break;
+                       case 'creativecommons':
+                               if( !$wgEnableCreativeCommonsRdf ) {
+                                       wfHttpError( 403, 'Forbidden', wfMsg('nocreativecommons') );
+                               } else {
+                                       require_once( 'includes/Metadata.php' );
+                                       wfCreativeCommonsRdf( $wgArticle );
+                               }
+                               break;
+                       case 'credits':
+                               require_once( 'includes/Credits.php' );
+                               showCreditsPage( $wgArticle );
+                               break;
+                       case 'submit':
+                               if( !$wgCommandLineMode && !$wgRequest->checkSessionCookie() ) {
+                                       # Send a cookie so anons get talk message notifications
+                                       User::SetupSession();
+                               }
+                               # Continue...
+                       case 'edit':
+                               $internal = $wgRequest->getVal( 'internaledit' );
+                               $external = $wgRequest->getVal( 'externaledit' );
+                               $section = $wgRequest->getVal( 'section' );
+                               $oldid = $wgRequest->getVal( 'oldid' );
+                               if(!$wgUseExternalEditor || $action=='submit' || $internal ||
+                                  $section || $oldid || (!$wgUser->getOption('externaleditor') && !$external)) {
+                                       require_once( 'includes/EditPage.php' );
+                                       $editor = new EditPage( $wgArticle );
+                                       $editor->submit();
+                               } elseif($wgUseExternalEditor && ($external || $wgUser->getOption('externaleditor'))) {
+                                       require_once( 'includes/ExternalEdit.php' );
+                                       $mode = $wgRequest->getVal( 'mode' );
+                                       $extedit = new ExternalEdit( $wgArticle, $mode );
+                                       $extedit->edit();
+                               }
+                               break;
+                       case 'history':
+                               if ($_SERVER['REQUEST_URI'] == $wgTitle->getInternalURL('action=history')) {
+                                       $wgOut->setSquidMaxage( $wgSquidMaxage );
+                               }
+                               require_once( 'includes/PageHistory.php' );
+                               $history = new PageHistory( $wgArticle );
+                               $history->history();
+                               break;
+                       case 'raw':
+                               require_once( 'includes/RawPage.php' );
+                               $raw = new RawPage( $wgArticle );
+                               $raw->view();
+                               break;
+                       case 'purge':
+                               wfPurgeSquidServers(array($wgTitle->getInternalURL()));
+                               $wgOut->setSquidMaxage( $wgSquidMaxage );
+                               $wgTitle->invalidateCache();
+                               $wgArticle->view();
+                               break;
+                       default:
+                               if (wfRunHooks('UnknownAction', array($action, $wgArticle))) {
+                                       $wgOut->errorpage( 'nosuchaction', 'nosuchactiontext' );
+                               }
+               }
+       }
+}
+wfProfileOut( 'main-action' );
+
+# Deferred updates aren't really deferred anymore. It's important to report errors to the
+# user, and that means doing this before OutputPage::output(). Note that for page saves,
+# the client will wait until the script exits anyway before following the redirect.
+wfProfileIn( 'main-updates' );
+foreach ( $wgDeferredUpdateList as $up ) {
+       $up->doUpdate();
+}
+wfProfileOut( 'main-updates' );
+
+wfProfileIn( 'main-cleanup' );
+$wgLoadBalancer->saveMasterPos();
+
+# Now commit any transactions, so that unreported errors after output() don't roll back the whole thing
+$wgLoadBalancer->commitAll();
+
+$wgOut->output();
+
+foreach ( $wgPostCommitUpdateList as $up ) {
+       $up->doUpdate();
+}
+
+wfProfileOut( 'main-cleanup' );
+
+logProfilingData();
+$wgLoadBalancer->closeAll();
+wfDebug( "Request ended normally\n" );
+?>
diff --git a/install-utils.inc b/install-utils.inc
new file mode 100644 (file)
index 0000000..62d35c6
--- /dev/null
@@ -0,0 +1,182 @@
+<?php
+
+function install_version_checks() {
+       # We dare not turn output buffer _off_ since this will break completely
+       # if PHP is globally configured to run through a gzip filter.
+       @ob_implicit_flush( true );
+       
+       if( !function_exists( 'version_compare' ) ) {
+               # version_compare was introduced in 4.1.0
+               die( "Your PHP version is much too old; 4.0.x will _not_ work. 4.3.2 or higher is recommended. ABORTING.\n" );
+       }
+       if( version_compare( phpversion(), '4.3.2' ) < 0 ) {
+               echo "WARNING: PHP 4.3.2 or higher is recommended. Older versions from 4.1.x up may work but are not actively supported.\n\n";
+       }
+       
+       if (!extension_loaded('mysql')) {
+               if (!dl('mysql.so')) {
+                       print 'Could not load MySQL driver! Please compile '.
+                                 "php --with-mysql or install the mysql.so module.\n";
+               exit;
+               }
+       }
+       
+       global $wgCommandLineMode;
+       $wgCommandLineMode = true;
+       umask( 000 );
+       set_time_limit( 0 );
+}
+
+function copyfile( $sdir, $name, $ddir, $perms = 0664 ) {
+       copyfileto( $sdir, $name, $ddir, $name, $perms );
+}
+
+function copyfileto( $sdir, $sname, $ddir, $dname, $perms = 0664 ) {
+       global $wgInstallOwner, $wgInstallGroup;
+
+       $d = "{$ddir}/{$dname}";
+       if ( copy( "{$sdir}/{$sname}", $d ) ) {
+               if ( isset( $wgInstallOwner ) ) { chown( $d, $wgInstallOwner ); }
+               if ( isset( $wgInstallGroup ) ) { chgrp( $d, $wgInstallGroup ); }
+               chmod( $d, $perms );
+               # print "Copied \"{$sname}\" to \"{$d}\".\n";
+       } else {
+               print "Failed to copy file \"{$sname}\" to \"{$ddir}/{$dname}\".\n";
+               exit();
+       }
+}
+
+function copydirectory( $source, $dest ) {
+       $handle = opendir( $source );
+       while ( false !== ( $f = readdir( $handle ) ) ) {
+               $fullname = "$source/$f";
+               if ( $f{0} != '.' && is_file( $fullname ) ) {
+                       copyfile( $source, $f, $dest );
+               }
+       }
+}
+
+function readconsole( $prompt = '' ) {
+       if ( function_exists( 'readline' ) ) {
+               return readline( $prompt );
+       } else {
+               print $prompt;
+               $fp = fopen( 'php://stdin', 'r' );
+               $st = fgets($fp, 1024);
+               if ($st === false) return false;
+               $resp = trim( $st );
+               fclose( $fp );
+               return $resp;
+       }
+}
+
+function replacevars( $ins ) {
+       $varnames = array(
+               'wgDBserver', 'wgDBname', 'wgDBintlname', 'wgDBuser',
+               'wgDBpassword', 'wgDBsqluser', 'wgDBsqlpassword',
+               'wgDBadminuser', 'wgDBadminpassword', 'wgDBprefix'
+       );
+
+       foreach ( $varnames as $var ) {
+               if( isset( $GLOBALS[$var] ) ) {
+                       $val = addslashes( $GLOBALS[$var] );
+                       $ins = str_replace( '{$' . $var . '}', $val, $ins );
+                       $ins = str_replace( '/*$' . $var . '*/`', '`' . $val, $ins );
+                       $ins = str_replace( '/*$' . $var . '*/', $val, $ins );
+               }
+       }
+       return $ins;
+}
+
+#
+# Read and execute SQL commands from a file
+#
+function dbsource( $fname, $database = false ) {
+       $fp = fopen( $fname, 'r' );
+       if ( false === $fp ) {
+               print "Could not open \"{$fname}\".\n";
+               exit();
+       }
+
+       $cmd = "";
+       $done = false;
+
+       while ( ! feof( $fp ) ) {
+               $line = trim( fgets( $fp, 1024 ) );
+               $sl = strlen( $line ) - 1;
+
+               if ( $sl < 0 ) { continue; }
+               if ( '-' == $line{0} && '-' == $line{1} ) { continue; }
+
+               if ( ';' == $line{$sl} ) {
+                       $done = true;
+                       $line = substr( $line, 0, $sl );
+               }
+
+               if ( '' != $cmd ) { $cmd .= ' '; }
+               $cmd .= $line;
+
+               if ( $done ) {
+                       $cmd = replacevars( $cmd );
+                       if( $database )
+                               $res = $database->query( $cmd );
+                       else
+                               $res = mysql_query( $cmd );
+
+                       if ( false === $res ) {
+                               $err = mysql_error();
+                               print "Query \"{$cmd}\" failed with error code \"$err\".\n";
+                               exit();
+                       }
+
+                       $cmd = '';
+                       $done = false;
+               }
+       }
+       fclose( $fp );
+}
+
+# Obsolete, use Database::fieldExists()
+function field_exists( $table, $field ) {
+       $fname = 'Update script: field_exists';
+       $db =& wfGetDB( DB_SLAVE );
+       $res = $db->query( "DESCRIBE $table", $fname );
+       $found = false;
+       
+       while ( $row = $db->fetchObject( $res ) ) {
+               if ( $row->Field == $field ) {
+                       $found = true;
+                       break;
+               }
+       }
+       return $found;
+}
+
+# Obsolete Database::tableExists()
+function table_exists( $db ) {
+       global $wgDBname;
+       $res = mysql_list_tables( $wgDBname );
+       if( !$res ) {
+               echo "** " . mysql_error() . "\n";
+               return false;
+       }
+       for( $i = mysql_num_rows( $res ) - 1; $i--; $i > 0 ) {
+               if( mysql_tablename( $res, $i ) == $db ) return true;
+       }
+       return false;
+}
+
+# Obsolete, use Database:fieldInfo()
+function field_info( $table, $field ) {
+       $res = mysql_query( "SELECT * FROM $table LIMIT 1" );
+       $n = mysql_num_fields( $res );
+       for( $i = 0; $i < $n; $i++ ) {
+               $meta = mysql_fetch_field( $res, $i );
+               if( $field == $meta->name ) {
+                       return $meta;
+               }
+       }
+       return false;
+}
+
+?>
diff --git a/languages/.htaccess b/languages/.htaccess
new file mode 100644 (file)
index 0000000..3a42882
--- /dev/null
@@ -0,0 +1 @@
+Deny from all
diff --git a/languages/Language.php b/languages/Language.php
new file mode 100644 (file)
index 0000000..2f79494
--- /dev/null
@@ -0,0 +1,2903 @@
+<?php
+/**
+ * @package MediaWiki
+ * @subpackage Language
+ */
+
+if( defined( 'MEDIAWIKI' ) ) {
+
+#
+# In general you should not make customizations in these language files
+# directly, but should use the MediaWiki: special namespace to customize
+# user interface messages through the wiki.
+# See http://meta.wikipedia.org/wiki/MediaWiki_namespace
+#
+# NOTE TO TRANSLATORS: Do not copy this whole file when making translations!
+# A lot of common constants and a base class with inheritable methods are
+# defined here, which should not be redefined. See the other LanguageXx.php
+# files for examples.
+#
+
+#--------------------------------------------------------------------------
+# Language-specific text
+#--------------------------------------------------------------------------
+
+if($wgMetaNamespace === FALSE)
+       $wgMetaNamespace = str_replace( ' ', '_', $wgSitename );
+
+/* private */ $wgNamespaceNamesEn = array(
+       NS_MEDIA            => 'Media',
+       NS_SPECIAL          => 'Special',
+       NS_MAIN             => '',
+       NS_TALK             => 'Talk',
+       NS_USER             => 'User',
+       NS_USER_TALK        => 'User_talk',
+       NS_PROJECT          => $wgMetaNamespace,
+       NS_PROJECT_TALK     => $wgMetaNamespace . '_talk',
+       NS_IMAGE            => 'Image',
+       NS_IMAGE_TALK       => 'Image_talk',
+       NS_MEDIAWIKI        => 'MediaWiki',
+       NS_MEDIAWIKI_TALK   => 'MediaWiki_talk',
+       NS_TEMPLATE         => 'Template',
+       NS_TEMPLATE_TALK    => 'Template_talk',
+       NS_HELP             => 'Help',
+       NS_HELP_TALK        => 'Help_talk',
+       NS_CATEGORY         => 'Category',
+       NS_CATEGORY_TALK    => 'Category_talk',
+);
+
+if(isset($wgExtraNamespaces)) {
+       $wgNamespaceNamesEn=$wgNamespaceNamesEn+$wgExtraNamespaces;
+}
+
+/* private */ $wgDefaultUserOptionsEn = array(
+       'quickbar'              => 1,
+       'underline'             => 2,
+       'cols'                  => 80,
+       'rows'                  => 25,
+       'searchlimit'           => 20,
+       'contextlines'          => 5,
+       'contextchars'          => 50,
+       'skin'                  => $wgDefaultSkin,
+       'math'                  => 1,
+       'rcdays'                => 7,
+       'rclimit'               => 50,
+       'highlightbroken'       => 1,
+       'stubthreshold'         => 0,
+       'previewontop'          => 1,
+       'editsection'           => 1,
+       'editsectiononrightclick'=> 0,
+       'showtoc'               => 1,
+       'showtoolbar'           => 1,
+       'date'                  => 0,
+       'imagesize'             => 2,
+       'thumbsize'             => 2,
+       'rememberpassword'      => 0,
+       'enotifwatchlistpages'  => 0,
+       'enotifusertalkpages'   => 1,
+       'enotifminoredits'      => 0,
+       'enotifrevealaddr'      => 0,
+       'shownumberswatching'   => 1,
+       'fancysig'              => 0,
+       'externaleditor'        => 0,
+       'externaldiff'          => 0,
+);
+
+/* private */ $wgQuickbarSettingsEn = array(
+       'None', 'Fixed left', 'Fixed right', 'Floating left', 'Floating right'
+);
+
+/* private */ $wgSkinNamesEn = array(
+       'standard' => 'Classic',
+       'nostalgia' => 'Nostalgia',
+       'cologneblue' => 'Cologne Blue',
+       'davinci' => 'DaVinci',
+       'mono' => 'Mono',
+       'monobook' => 'MonoBook',
+       'myskin' => 'MySkin',
+       'chick' => 'Chick'
+);
+
+/* private */ $wgMathNamesEn = array(
+       MW_MATH_PNG => 'mw_math_png',
+       MW_MATH_SIMPLE => 'mw_math_simple',
+       MW_MATH_HTML => 'mw_math_html',
+       MW_MATH_SOURCE => 'mw_math_source',
+       MW_MATH_MODERN => 'mw_math_modern',
+       MW_MATH_MATHML => 'mw_math_mathml'
+);
+
+# Whether to use user or default setting in Language::date()
+
+/* private */ $wgDateFormatsEn = array(
+       MW_DATE_DEFAULT => 'No preference',
+       MW_DATE_MDY => '16:12, January 15, 2001',
+       MW_DATE_DMY => '16:12, 15 January 2001',
+       MW_DATE_YMD => '16:12, 2001 January 15',
+       MW_DATE_ISO => '2001-01-15 16:12:34'
+);
+
+/* private */ $wgUserTogglesEn = array(
+       'highlightbroken',
+       'justify',
+       'hideminor',
+       'usenewrc',
+       'numberheadings',
+       'showtoolbar',
+       'editondblclick',
+       'editsection',
+       'editsectiononrightclick',
+       'showtoc',
+       'rememberpassword',
+       'editwidth',
+       'watchdefault',
+       'minordefault',
+       'previewontop',
+       'previewonfirst',
+       'nocache',
+       'enotifwatchlistpages',
+       'enotifusertalkpages',
+       'enotifminoredits',
+       'enotifrevealaddr',
+       'shownumberswatching',
+       'fancysig',
+       'externaleditor',
+       'externaldiff',
+);
+
+/* private */ $wgBookstoreListEn = array(
+       'AddALL' => 'http://www.addall.com/New/Partner.cgi?query=$1&type=ISBN',
+       'PriceSCAN' => 'http://www.pricescan.com/books/bookDetail.asp?isbn=$1',
+       'Barnes & Noble' => 'http://search.barnesandnoble.com/bookSearch/isbnInquiry.asp?isbn=$1',
+       'Amazon.com' => 'http://www.amazon.com/exec/obidos/ISBN=$1'
+);
+
+# Read language names
+global $wgLanguageNames;
+/** */
+require_once( 'Names.php' );
+
+$wgLanguageNamesEn =& $wgLanguageNames;
+
+
+/* private */ $wgWeekdayNamesEn = array(
+       'sunday', 'monday', 'tuesday', 'wednesday', 'thursday',
+       'friday', 'saturday'
+);
+
+
+/* private */ $wgMonthNamesEn = array(
+       'january', 'february', 'march', 'april', 'may_long', 'june',
+       'july', 'august', 'september', 'october', 'november',
+       'december'
+);
+/* private */ $wgMonthNamesGenEn = array(
+       'january-gen', 'february-gen', 'march-gen', 'april-gen', 'may-gen', 'june-gen',
+       'july-gen', 'august-gen', 'september-gen', 'october-gen', 'november-gen',
+       'december-gen'
+);
+
+/* private */ $wgMonthAbbreviationsEn = array(
+       'jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug',
+       'sep', 'oct', 'nov', 'dec'
+);
+
+# Note to translators:
+#   Please include the English words as synonyms.  This allows people
+#   from other wikis to contribute more easily.
+#
+/* private */ $wgMagicWordsEn = array(
+#   ID                                 CASE  SYNONYMS
+       MAG_REDIRECT             => array( 0,    '#redirect'              ),
+       MAG_NOTOC                => array( 0,    '__NOTOC__'              ),
+       MAG_FORCETOC             => array( 0,    '__FORCETOC__'           ),
+       MAG_TOC                  => array( 0,    '__TOC__'                ),
+       MAG_NOEDITSECTION        => array( 0,    '__NOEDITSECTION__'      ),
+       MAG_START                => array( 0,    '__START__'              ),
+       MAG_CURRENTMONTH         => array( 1,    'CURRENTMONTH'           ),
+       MAG_CURRENTMONTHNAME     => array( 1,    'CURRENTMONTHNAME'       ),
+       MAG_CURRENTMONTHNAMEGEN  => array( 1,    'CURRENTMONTHNAMEGEN'    ),
+       MAG_CURRENTMONTHABBREV   => array( 1,    'CURRENTMONTHABBREV'     ),
+       MAG_CURRENTDAY           => array( 1,    'CURRENTDAY'             ),
+       MAG_CURRENTDAYNAME       => array( 1,    'CURRENTDAYNAME'         ),
+       MAG_CURRENTYEAR          => array( 1,    'CURRENTYEAR'            ),
+       MAG_CURRENTTIME          => array( 1,    'CURRENTTIME'            ),
+       MAG_NUMBEROFARTICLES     => array( 1,    'NUMBEROFARTICLES'       ),
+       MAG_NUMBEROFFILES        => array( 1,    'NUMBEROFFILES'          ),
+       MAG_PAGENAME             => array( 1,    'PAGENAME'               ),
+       MAG_PAGENAMEE            => array( 1,    'PAGENAMEE'              ),
+       MAG_NAMESPACE            => array( 1,    'NAMESPACE'              ),
+       MAG_MSG                  => array( 0,    'MSG:'                   ),
+       MAG_SUBST                => array( 0,    'SUBST:'                 ),
+       MAG_MSGNW                => array( 0,    'MSGNW:'                 ),
+       MAG_END                  => array( 0,    '__END__'                ),
+       MAG_IMG_THUMBNAIL        => array( 1,    'thumbnail', 'thumb'     ),
+       MAG_IMG_RIGHT            => array( 1,    'right'                  ),
+       MAG_IMG_LEFT             => array( 1,    'left'                   ),
+       MAG_IMG_NONE             => array( 1,    'none'                   ),
+       MAG_IMG_WIDTH            => array( 1,    '$1px'                   ),
+       MAG_IMG_CENTER           => array( 1,    'center', 'centre'       ),
+       MAG_IMG_FRAMED           => array( 1,    'framed', 'enframed', 'frame' ),
+       MAG_INT                  => array( 0,    'INT:'                   ),
+       MAG_SITENAME             => array( 1,    'SITENAME'               ),
+       MAG_NS                   => array( 0,    'NS:'                    ),
+       MAG_LOCALURL             => array( 0,    'LOCALURL:'              ),
+       MAG_LOCALURLE            => array( 0,    'LOCALURLE:'             ),
+       MAG_SERVER               => array( 0,    'SERVER'                 ),
+       MAG_SERVERNAME           => array( 0,    'SERVERNAME'             ),
+       MAG_SCRIPTPATH           => array( 0,    'SCRIPTPATH'             ),
+       MAG_GRAMMAR              => array( 0,    'GRAMMAR:'               ),
+       MAG_NOTITLECONVERT       => array( 0,    '__NOTITLECONVERT__', '__NOTC__'),
+       MAG_NOCONTENTCONVERT     => array( 0,    '__NOCONTENTCONVERT__', '__NOCC__'),
+       MAG_CURRENTWEEK          => array( 1,    'CURRENTWEEK'            ),
+       MAG_CURRENTDOW           => array( 1,    'CURRENTDOW'             ),
+       MAG_REVISIONID           => array( 1,    'REVISIONID'             ),
+);
+
+#-------------------------------------------------------------------
+# Default messages
+#-------------------------------------------------------------------
+# Allowed characters in keys are: A-Z, a-z, 0-9, underscore (_) and
+# hyphen (-). If you need more characters, you may be able to change
+# the regex in MagicWord::initRegex
+
+# required for copyrightwarning
+global $wgRightsText;
+
+/* private */ $wgAllMessagesEn = array(
+
+# The navigation toolbar, int: is used here to make sure that the appropriate
+# messages are automatically pulled from the user-selected language file.
+
+/*
+The sidebar for MonoBook is generated from this message, lines that do not
+begin with * or ** are discarded, furthermore lines that do begin with ** and
+do not contain | are also discarded, but don't depend on this behaviour for
+future releases. Also note that since each list value is wrapped in a unique
+XHTML id it should only appear once and include characters that are legal
+XHTML id names.
+
+Note to translators: Do not include this message in the language files you
+submit for inclusion in MediaWiki, it should always be inherited from the
+parent class in order maintain consistency across languages.
+*/
+'sidebar' => '
+* navigation
+** mainpage|mainpage
+** portal-url|portal
+** currentevents-url|currentevents
+** recentchanges-url|recentchanges
+** randompage-url|randompage
+** helppage|help
+** sitesupport-url|sitesupport
+',
+
+# User preference toggles
+'tog-underline' => 'Underline links',
+'tog-highlightbroken' => 'Format broken links <a href="" class="new">like this</a> (alternative: like this<a href="" class="internal">?</a>).',
+'tog-justify'  => 'Justify paragraphs',
+'tog-hideminor' => 'Hide minor edits in recent changes',
+'tog-usenewrc' => 'Enhanced recent changes (JavaScript)',
+'tog-numberheadings' => 'Auto-number headings',
+'tog-showtoolbar'              => 'Show edit toolbar (JavaScript)',
+'tog-editondblclick' => 'Edit pages on double click (JavaScript)',
+'tog-editsection'              => 'Enable section editing via [edit] links',
+'tog-editsectiononrightclick'  => 'Enable section editing by right clicking<br /> on section titles (JavaScript)',
+'tog-showtoc'                  => 'Show table of contents (for pages with more than 3 headings)',
+'tog-rememberpassword' => 'Remember across sessions',
+'tog-editwidth' => 'Edit box has full width',
+'tog-watchdefault' => 'Add pages you edit to your watchlist',
+'tog-minordefault' => 'Mark all edits minor by default',
+'tog-previewontop' => 'Show preview before edit box',
+'tog-previewonfirst' => 'Show preview on first edit',
+'tog-nocache' => 'Disable page caching',
+'tog-enotifwatchlistpages'     => 'Send me an email on page changes',
+'tog-enotifusertalkpages'      => 'Send me an email when my user talk page is changed',
+'tog-enotifminoredits'                 => 'Send me an email also for minor edits of pages',
+'tog-enotifrevealaddr'                 => 'Reveal my email address in notification mails',
+'tog-shownumberswatching'      => 'Show the number of watching users',
+'tog-fancysig' => 'Raw signatures (without automatic link)',
+'tog-externaleditor' => 'Use external editor by default',
+'tog-externaldiff' => 'Use external diff by default',
+
+'underline-always' => 'Always',
+'underline-never' => 'Never',
+'underline-default' => 'Browser default',
+
+'skinpreview' => '(Preview)',
+
+# dates
+'sunday' => 'Sunday',
+'monday' => 'Monday',
+'tuesday' => 'Tuesday',
+'wednesday' => 'Wednesday',
+'thursday' => 'Thursday',
+'friday' => 'Friday',
+'saturday' => 'Saturday',
+'january' => 'January',
+'february' => 'February',
+'march' => 'March',
+'april' => 'April',
+'may_long' => 'May',
+'june' => 'June',
+'july' => 'July',
+'august' => 'August',
+'september' => 'September',
+'october' => 'October',
+'november' => 'November',
+'december' => 'December',
+'jan' => 'Jan',
+'feb' => 'Feb',
+'mar' => 'Mar',
+'apr' => 'Apr',
+'may' => 'May',
+'jun' => 'Jun',
+'jul' => 'Jul',
+'aug' => 'Aug',
+'sep' => 'Sep',
+'oct' => 'Oct',
+'nov' => 'Nov',
+'dec' => 'Dec',
+# Bits of text used by many pages:
+#
+'categories' => 'Categories',
+'category' => 'category',
+'category_header' => 'Articles in category "$1"',
+'subcategories' => 'Subcategories',
+
+
+'linktrail'            => '/^([a-z]+)(.*)$/sD',
+'linkprefix'           => '/^(.*?)([a-zA-Z\x80-\xff]+)$/sD',
+'mainpage'             => 'Main Page',
+'mainpagetext' => "<big>'''MediaWiki has been successfully installed.'''</big>",
+'mainpagedocfooter' => "Consult the [http://meta.wikipedia.org/wiki/MediaWiki_User%27s_Guide User's Guide] for information on using the wiki software.
+
+== Getting started ==
+
+* [http://www.mediawiki.org/wiki/Help:Configuration_settings Configuration settings list]
+* [http://www.mediawiki.org/wiki/Help:FAQ MediaWiki FAQ]
+* [http://mail.wikipedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list]",
+
+'portal'               => 'Community portal',
+'portal-url'   => 'Project:Community Portal',
+'about'                        => 'About',
+'aboutsite'            => 'About {{SITENAME}}',
+'aboutpage'            => 'Project:About',
+'article'              => 'Content page',
+'help'                 => 'Help',
+'helppage'             => 'Help:Contents',
+'bugreports'   => 'Bug reports',
+'bugreportspage' => 'Project:Bug_reports',
+'sitesupport'   => 'Donations',
+'sitesupport-url' => 'Project:Site support',
+'faq'                  => 'FAQ',
+'faqpage'              => 'Project:FAQ',
+'edithelp'             => 'Editing help',
+'newwindow'            => '(opens in new window)',
+'edithelppage' => 'Help:Editing',
+'cancel'               => 'Cancel',
+'qbfind'               => 'Find',
+'qbbrowse'             => 'Browse',
+'qbedit'               => 'Edit',
+'qbpageoptions' => 'This page',
+'qbpageinfo'   => 'Context',
+'qbmyoptions'  => 'My pages',
+'qbspecialpages'       => 'Special pages',
+'moredotdotdot'        => 'More...',
+'mypage'               => 'My page',
+'mytalk'               => 'My talk',
+'anontalk'             => 'Talk for this IP',
+'navigation' => 'Navigation',
+
+# Metadata in edit box
+'metadata' => '<b>Metadata</b> (for an explanation see <a href="$1">here</a>)',
+'metadata_page' => 'Wikipedia:Metadata',
+
+'currentevents' => 'Current events',
+'currentevents-url' => 'Current events',
+
+'disclaimers' => 'Disclaimers',
+'disclaimerpage' => "Project:General_disclaimer",
+'errorpagetitle' => "Error",
+'returnto'             => "Return to $1.",
+'tagline'              => "From {{SITENAME}}",
+'whatlinkshere'        => 'Pages that link here',
+'help'                 => 'Help',
+'search'               => 'Search',
+'go'           => 'Go',
+"history"              => 'Page history',
+'history_short' => 'History',
+'info_short'   => 'Information',
+'printableversion' => 'Printable version',
+'print' => 'Print',
+'edit' => 'Edit',
+'editthispage' => 'Edit this page',
+'delete' => 'Delete',
+'deletethispage' => 'Delete this page',
+'undelete_short1' => 'Undelete one edit',
+'undelete_short' => 'Undelete $1 edits',
+'protect' => 'Protect',
+'protectthispage' => 'Protect this page',
+'unprotect' => 'unprotect',
+'unprotectthispage' => 'Unprotect this page',
+'newpage' => 'New page',
+'talkpage'             => 'Discuss this page',
+'specialpage' => 'Special Page',
+'personaltools' => 'Personal tools',
+'postcomment'   => 'Post a comment',
+'addsection'   => '+',
+'articlepage'  => 'View content page',
+'subjectpage'  => 'View subject', # For compatibility
+'talk' => 'Discussion',
+'views' => 'Views',
+'toolbox' => 'Toolbox',
+'userpage' => 'View user page',
+'wikipediapage' => 'View project page',
+'imagepage' =>         'View image page',
+'viewtalkpage' => 'View discussion',
+'otherlanguages' => 'In other languages',
+'redirectedfrom' => '(Redirected from $1)',
+'lastmodified' => 'This page was last modified $1.',
+'viewcount'            => 'This page has been accessed $1 times.',
+'copyright'    => 'Content is available under $1.',
+'poweredby'    => "{{SITENAME}} is powered by [http://www.mediawiki.org/ MediaWiki], an open source wiki engine.",
+'printsubtitle' => "(From {{SERVER}})",
+'protectedpage' => 'Protected page',
+'administrators' => "Project:Administrators",
+
+'sysoptitle'   => 'Sysop access required',
+'sysoptext'            => "The action you have requested can only be
+performed by users with \"sysop\" capability.
+See $1.",
+'developertitle' => 'Developer access required',
+'developertext'        => "The action you have requested can only be
+performed by users with \"developer\" capability.
+See $1.",
+
+'badaccess'     => 'Permission error',
+'badaccesstext' => 'The action you have requested is limited
+to users with the "$2" permission assigned.
+See $1.',
+
+'versionrequired' => 'Version $1 of MediaWiki required',
+'versionrequiredtext' => 'Version $1 of MediaWiki is required to use this page. See [[Special:Version]]',
+
+'nbytes'               => '$1 bytes',
+'ok'                   => 'OK',
+'sitetitle'            => "{{SITENAME}}",
+'pagetitle'            => "$1 - {{SITENAME}}",
+'sitesubtitle' => 'The Free Encyclopedia', # FIXME
+'retrievedfrom' => "Retrieved from \"$1\"",
+'newmessages' => "You have $1.",
+'newmessageslink' => 'new messages',
+'editsection'=>'edit',
+'toc' => 'Contents',
+'showtoc' => 'show',
+'hidetoc' => 'hide',
+'thisisdeleted' => "View or restore $1?",
+'restorelink1' => 'one deleted edit',
+'restorelink' => "$1 deleted edits",
+'feedlinks' => 'Feed:',
+'sitenotice'   => '-', # the equivalent to wgSiteNotice
+
+# Short words for each namespace, by default used in the 'article' tab in monobook
+'nstab-main' => 'Article',
+'nstab-user' => 'User page',
+'nstab-media' => 'Media page',
+'nstab-special' => 'Special',
+'nstab-wp' => 'Project page',
+'nstab-image' => 'File',
+'nstab-mediawiki' => 'Message',
+'nstab-template' => 'Template',
+'nstab-help' => 'Help',
+'nstab-category' => 'Category',
+
+# Main script and global functions
+#
+'nosuchaction' => 'No such action',
+'nosuchactiontext' => 'The action specified by the URL is not
+recognized by the wiki',
+'nosuchspecialpage' => 'No such special page',
+'nospecialpagetext' => 'You have requested an invalid special page, a list of valid special pages may be found at [[{{ns:special}}:Specialpages]].',
+
+# General errors
+#
+'error'                        => 'Error',
+'databaseerror' => 'Database error',
+'dberrortext'  => "A database query syntax error has occurred.
+This may indicate a bug in the software.
+The last attempted database query was:
+<blockquote><tt>$1</tt></blockquote>
+from within function \"<tt>$2</tt>\".
+MySQL returned error \"<tt>$3: $4</tt>\".",
+'dberrortextcl' => "A database query syntax error has occurred.
+The last attempted database query was:
+\"$1\"
+from within function \"$2\".
+MySQL returned error \"$3: $4\".\n",
+'noconnect'            => 'Sorry! The wiki is experiencing some technical difficulties, and cannot contact the database server. <br />
+$1',
+'nodb'                 => "Could not select database $1",
+'cachederror'          => 'The following is a cached copy of the requested page, and may not be up to date.',
+'laggedslavemode'   => 'Warning: Page may not contain recent updates.',
+'readonly'             => 'Database locked',
+'enterlockreason' => 'Enter a reason for the lock, including an estimate
+of when the lock will be released',
+'readonlytext' => "The database is currently locked to new
+entries and other modifications, probably for routine database maintenance,
+after which it will be back to normal.
+The administrator who locked it offered this explanation:
+$1",
+'missingarticle' => "The database did not find the text of a page
+that it should have found, named \"$1\".
+
+This is usually caused by following an outdated diff or history link to a
+page that has been deleted.
+
+If this is not the case, you may have found a bug in the software.
+Please report this to an administrator, making note of the URL.",
+'readonly_lag' => "The database has been automatically locked while the slave database servers catch up to the master",
+'internalerror' => 'Internal error',
+'filecopyerror' => "Could not copy file \"$1\" to \"$2\".",
+'filerenameerror' => "Could not rename file \"$1\" to \"$2\".",
+'filedeleteerror' => "Could not delete file \"$1\".",
+'filenotfound' => "Could not find file \"$1\".",
+'unexpected'   => "Unexpected value: \"$1\"=\"$2\".",
+'formerror'            => 'Error: could not submit form',
+'badarticleerror' => 'This action cannot be performed on this page.',
+'cannotdelete' => 'Could not delete the page or file specified. (It may have already been deleted by someone else.)',
+'badtitle'             => 'Bad title',
+'badtitletext' => "The requested page title was invalid, empty, or
+an incorrectly linked inter-language or inter-wiki title.",
+'perfdisabled' => 'Sorry! This feature has been temporarily disabled
+because it slows the database down to the point that no one can use
+the wiki.',
+'perfdisabledsub' => "Here's a saved copy from $1:", # obsolete?
+'perfcached' => 'The following data is cached and may not be completely up to date:',
+'wrong_wfQuery_params' => "Incorrect parameters to wfQuery()<br />
+Function: $1<br />
+Query: $2
+",
+'viewsource' => 'View source',
+'protectedtext' => "This page has been locked to prevent editing; there are
+a number of reasons why this may be so, please see
+[[Project:Protected page]].
+
+You can view and copy the source of this page:",
+'sqlhidden' => '(SQL query hidden)',
+
+# Login and logout pages
+#
+'logouttitle'  => 'User logout',
+'logouttext'           => "You are now logged out.<br />
+You can continue to use {{SITENAME}} anonymously, or you can log in
+again as the same or as a different user. Note that some pages may
+continue to be displayed as if you were still logged in, until you clear
+your browser cache.\n",
+
+'welcomecreation' => "== Welcome, $1! ==
+
+Your account has been created. Don't forget to change your {{SITENAME}} preferences.",
+
+'loginpagetitle' => 'User login',
+'yourname'             => 'Username',
+'yourpassword' => 'Password',
+'yourpasswordagain' => 'Retype password',
+'newusersonly' => ' (new users only)',
+'remembermypassword' => 'Remember me',
+'yourdomainname'       => 'Your domain',
+'externaldberror'      => 'There was either an external authentication database error or you are not allowed to update your external account.',
+'loginproblem' => '<b>There has been a problem with your login.</b><br />Try again!',
+'alreadyloggedin' => "<strong>User $1, you are already logged in!</strong><br />\n",
+
+'login'                        => 'Log in',
+'loginprompt'           => "You must have cookies enabled to log in to {{SITENAME}}.",
+'userlogin'            => 'Create an account or log in',
+'logout'               => 'Log out',
+'userlogout'   => 'Log out',
+'notloggedin'  => 'Not logged in',
+'createaccount'        => 'Create new account',
+'createaccountmail'    => 'by email',
+'badretype'            => 'The passwords you entered do not match.',
+'userexists'   => 'The user name you entered is already in use. Please choose a different name.',
+'youremail'            => 'Email *',
+'yourrealname'         => 'Real name *',
+'yourlanguage' => 'Language',
+'yourvariant'  => 'Variant',
+'yournick'             => 'Nickname',
+'email'                        => 'Email',
+'emailforlost'         => "Fields marked with superscripts are optional.  Storing an email address enables people to contact you through the website without you having to reveal your
+email address to them, and it can be used to send you a new password if you forget it.<br /><br />Your real name, if you choose to provide it, will be used for giving you attribution for your work.",
+'prefs-help-email-enotif' => 'This address is also used to send you email notifications if you enabled the options.',
+'prefs-help-realname'  => '* Real name (optional): if you choose to provide it this will be used for giving you attribution for your work.',
+'loginerror'   => 'Login error',
+'prefs-help-email'      => '* Email (optional): Enables others to contact you through your user or user_talk page without the need of revealing your identity.',
+'nocookiesnew' => "The user account was created, but you are not logged in. {{SITENAME}} uses cookies to log in users. You have cookies disabled. Please enable them, then log in with your new username and password.",
+'nocookieslogin'       => "{{SITENAME}} uses cookies to log in users. You have cookies disabled. Please enable them and try again.",
+'noname'               => 'You have not specified a valid user name.',
+'loginsuccesstitle' => 'Login successful',
+'loginsuccess' => "You are now logged in to {{SITENAME}} as \"$1\".",
+'nosuchuser'   => "There is no user by the name \"$1\".
+Check your spelling, or use the form below to create a new user account.",
+'nosuchusershort'      => "There is no user by the name \"$1\". Check your spelling.",
+'wrongpassword'                => 'The password you entered is incorrect (or missing). Please try again.',
+'mailmypassword'       => 'Mail me a new password',
+'passwordremindertitle' => "Password reminder from {{SITENAME}}",
+'passwordremindertext' => "Someone (probably you, from IP address $1)
+requested that we send you a new {{SITENAME}} login password.
+The password for user \"$2\" is now \"$3\".
+You should log in and change your password now.",
+'noemail'                          => "There is no e-mail address recorded for user \"$1\".",
+'passwordsent' => "A new password has been sent to the e-mail address
+registered for \"$1\".
+Please log in again after you receive it.",
+'eauthentsent'             =>  "A confirmation email has been sent to the nominated email address.
+Before any other mail is sent to the account, you will have to follow the instructions in the email,
+to confirm that the account is actually yours.",
+'loginend'                         => '&nbsp;',
+'mailerror'                 => "Error sending mail: $1",
+'acct_creation_throttle_hit' => 'Sorry, you have already created $1 accounts. You can\'t make any more.',
+'emailauthenticated'        => 'Your email address was authenticated on $1.',
+'emailnotauthenticated'     => 'Your email address is <strong>not yet authenticated</strong>. No email
+will be sent for any of the following features.',
+'noemailprefs'              => '<strong>No email address has been specified</strong>, the following
+features will not work.',
+'emailconfirmlink' => 'Confirm your e-mail address',
+'invalidemailaddress'  => 'The email address cannot be accepted as it appears to have an invalid
+format. Please enter a well-formatted address or empty that field.',
+
+# Edit page toolbar
+'bold_sample'=>'Bold text',
+'bold_tip'=>'Bold text',
+'italic_sample'=>'Italic text',
+'italic_tip'=>'Italic text',
+'link_sample'=>'Link title',
+'link_tip'=>'Internal link',
+'extlink_sample'=>'http://www.example.com link title',
+'extlink_tip'=>'External link (remember http:// prefix)',
+'headline_sample'=>'Headline text',
+'headline_tip'=>'Level 2 headline',
+'math_sample'=>'Insert formula here',
+'math_tip'=>'Mathematical formula (LaTeX)',
+'nowiki_sample'=>'Insert non-formatted text here',
+'nowiki_tip'=>'Ignore wiki formatting',
+'image_sample'=>'Example.jpg',
+'image_tip'=>'Embedded image',
+'media_sample'=>'Example.ogg',
+'media_tip'=>'Media file link',
+'sig_tip'=>'Your signature with timestamp',
+'hr_tip'=>'Horizontal line (use sparingly)',
+'infobox'=>'Click a button to get an example text',
+# alert box shown in browsers where text selection does not work, test e.g. with mozilla or konqueror
+'infobox_alert'=>"Please enter the text you want to be formatted.\\n It will be shown in the infobox for copy and pasting.\\nExample:\\n$1\\nwill become:\\n$2",
+
+# Edit pages
+#
+'summary'              => 'Summary',
+'subject'              => 'Subject/headline',
+'minoredit'            => 'This is a minor edit',
+'watchthis'            => 'Watch this page',
+'savearticle'  => 'Save page',
+'preview'              => 'Preview',
+'showpreview'  => 'Show preview',
+'showdiff'     => 'Show changes',
+'blockedtitle' => 'User is blocked',
+'blockedtext'  => "Your user name or IP address has been blocked by $1.
+The reason given is this:<br />''$2''<p>You may contact $1 or one of the other
+[[Project:Administrators|administrators]] to discuss the block.
+
+Note that you may not use the \"email this user\" feature unless you have a valid email address registered in your [[Special:Preferences|user preferences]].
+
+Your IP address is $3. Please include this address in any queries you make.
+",
+'whitelistedittitle' => 'Login required to edit',
+'whitelistedittext' => 'You have to [[Special:Userlogin|login]] to edit pages.',
+'whitelistreadtitle' => 'Login required to read',
+'whitelistreadtext' => 'You have to [[Special:Userlogin|login]] to read pages.',
+'whitelistacctitle' => 'You are not allowed to create an account',
+'whitelistacctext' => 'To be allowed to create accounts in this Wiki you have to [[Special:Userlogin|log]] in and have the appropriate permissions.',
+'loginreqtitle'        => 'Login Required',
+'loginreqtext' => 'You must [[special:Userlogin|login]] to view other pages.',
+'accmailtitle' => 'Password sent.',
+'accmailtext' => "The password for '$1' has been sent to $2.",
+'newarticle'   => '(New)',
+'newarticletext' =>
+"You've followed a link to a page that doesn't exist yet.
+To create the page, start typing in the box below
+(see the [[Project:Help|help page]] for more info).
+If you are here by mistake, just click your browser's '''back''' button.",
+'talkpagetext' => '<!-- MediaWiki:talkpagetext -->',
+'anontalkpagetext' => "----''This is the discussion page for an anonymous user who has not created an account yet or who does not use it. We therefore have to use the numerical [[IP address]] to identify him/her. Such an IP address can be shared by several users. If you are an anonymous user and feel that irrelevant comments have been directed at you, please [[Special:Userlogin|create an account or log in]] to avoid future confusion with other anonymous users.'' ",
+'noarticletext' => '(There is currently no text in this page)',
+'clearyourcache' => "'''Note:''' After saving, you may have to bypass your browser's cache to see the changes. '''Mozilla / Firefox / Safari:''' hold down ''Shift'' while clicking ''Reload'', or press ''Ctrl-Shift-R'' (''Cmd-Shift-R'' on Apple Mac); '''IE:''' hold ''Ctrl'' while clicking ''Refresh'', or press ''Ctrl-F5''; '''Konqueror:''': simply click the ''Reload'' button, or press ''F5''; '''Opera''' users may need to completely clear their cache in ''Tools&rarr;Preferences''.",
+'usercssjsyoucanpreview' => "<strong>Tip:</strong> Use the 'Show preview' button to test your new CSS/JS before saving.",
+'usercsspreview' => "'''Remember that you are only previewing your user CSS, it has not yet been saved!'''",
+'userjspreview' => "'''Remember that you are only testing/previewing your user JavaScript, it has not yet been saved!'''",
+'updated'              => '(Updated)',
+'note'                 => '<strong>Note:</strong> ',
+'previewnote'  => 'Remember that this is only a preview, and has not yet been saved!',
+'previewconflict' => 'This preview reflects the text in the upper
+text editing area as it will appear if you choose to save.',
+'editing'              => "Editing $1",
+'editingsection'               => "Editing $1 (section)",
+'editingcomment'               => "Editing $1 (comment)",
+'editconflict' => 'Edit conflict: $1',
+'explainconflict' => "Someone else has changed this page since you
+started editing it.
+The upper text area contains the page text as it currently exists.
+Your changes are shown in the lower text area.
+You will have to merge your changes into the existing text.
+<b>Only</b> the text in the upper text area will be saved when you
+press \"Save page\".<br />",
+'yourtext'             => 'Your text',
+'storedversion' => 'Stored version',
+'nonunicodebrowser' => "<strong>WARNING: Your browser is not unicode compliant. A workaround is in place to allow you to safely edit articles: non-ASCII characters will appear in the edit box as hexadecimal codes.</strong>",
+'editingold'   => "<strong>WARNING: You are editing an out-of-date
+revision of this page.
+If you save it, any changes made since this revision will be lost.</strong>",
+'yourdiff'             => 'Differences',
+'copyrightwarning' => "Please note that all contributions to {{SITENAME}} are
+considered to be released under the $2 (see $1 for details).
+If you don't want your writing to be edited mercilessly and redistributed
+at will, then don't submit it here.<br />
+You are also promising us that you wrote this yourself, or copied it from a
+public domain or similar free resource.
+<strong>DO NOT SUBMIT COPYRIGHTED WORK WITHOUT PERMISSION!</strong>",
+'copyrightwarning2' => "Please note that all contributions to {{SITENAME}}
+may be edited, altered, or removed by other contributors.
+If you don't want your writing to be edited mercilessly, then don't submit it here.<br />
+You are also promising us that you wrote this yourself, or copied it from a
+public domain or similar free resource (see $1 for details).
+<strong>DO NOT SUBMIT COPYRIGHTED WORK WITHOUT PERMISSION!</strong>",
+'longpagewarning' => "<strong>WARNING: This page is $1 kilobytes long; some
+browsers may have problems editing pages approaching or longer than 32kb.
+Please consider breaking the page into smaller sections.</strong>",
+'readonlywarning' => '<strong>WARNING: The database has been locked for maintenance,
+so you will not be able to save your edits right now. You may wish to cut-n-paste
+the text into a text file and save it for later.</strong>',
+'protectedpagewarning' => "<strong>WARNING:  This page has been locked so that only users with sysop privileges can edit it. Be sure you are following the [[Project:Protected_page_guidelines|protected page guidelines]].</strong>",
+'templatesused'        => 'Templates used on this page:',
+
+# History pages
+#
+'revhistory'   => 'Revision history',
+'nohistory'            => 'There is no edit history for this page.',
+'revnotfound'  => 'Revision not found',
+'revnotfoundtext' => "The old revision of the page you asked for could not be found.
+Please check the URL you used to access this page.\n",
+'loadhist'             => 'Loading page history',
+'currentrev'   => 'Current revision',
+'revisionasof'          => 'Revision as of $1',
+'revisionasofwithlink'  => 'Revision as of $1; $2<br />$3 | $4',
+'previousrevision'     => '←Older revision',
+'nextrevision'         => 'Newer revision→',
+'currentrevisionlink'   => 'view current revision',
+'cur'                  => 'cur',
+'next'                 => 'next',
+'last'                 => 'last',
+'orig'                 => 'orig',
+'histlegend'   => 'Diff selection: mark the radio boxes of the versions to compare and hit enter or the button at the bottom.<br />
+Legend: (cur) = difference with current version,
+(last) = difference with preceding version, M = minor edit.',
+'history_copyright'    => '-',
+'deletedrev' => '[deleted]',
+'histfirst' => 'Earliest',
+'histlast' => 'Latest',
+
+# Diffs
+#
+'difference'   => '(Difference between revisions)',
+'loadingrev'   => 'loading revision for diff',
+'lineno'               => "Line $1:",
+'editcurrent'  => 'Edit the current version of this page',
+'selectnewerversionfordiff' => 'Select a newer version for comparison',
+'selectolderversionfordiff' => 'Select an older version for comparison',
+'compareselectedversions' => 'Compare selected versions',
+
+# Search results
+#
+'searchresults' => 'Search results',
+'searchresulttext' => "For more information about searching {{SITENAME}}, see [[Project:Searching|Searching {{SITENAME}}]].",
+'searchquery'  => "For query \"$1\"",
+'badquery'             => 'Badly formed search query',
+'badquerytext' => 'We could not process your query.
+This is probably because you have attempted to search for a
+word fewer than three letters long, which is not yet supported.
+It could also be that you have mistyped the expression, for
+example "fish and and scales".
+Please try another query.',
+'matchtotals'  => "The query \"$1\" matched $2 page titles
+and the text of $3 pages.",
+'nogomatch' => "'''There is no page titled \"$1\".''' You can [[$1|create this page]].",
+'titlematches' => 'Article title matches',
+'notitlematches' => 'No page title matches',
+'textmatches'  => 'Page text matches',
+'notextmatches'        => 'No page text matches',
+'prevn'                        => "previous $1",
+'nextn'                        => "next $1",
+'viewprevnext' => "View ($1) ($2) ($3).",
+'showingresults' => "Showing below up to <b>$1</b> results starting with #<b>$2</b>.",
+'showingresultsnum' => "Showing below <b>$3</b> results starting with #<b>$2</b>.",
+'nonefound'            => "'''Note''': unsuccessful searches are
+often caused by searching for common words like \"have\" and \"from\",
+which are not indexed, or by specifying more than one search term (only pages
+containing all of the search terms will appear in the result).",
+'powersearch' => 'Search',
+'powersearchtext' => "
+Search in namespaces :<br />
+$1<br />
+$2 List redirects &nbsp; Search for $3 $9",
+"searchdisabled" => '{{SITENAME}} search is disabled. You can search via Google in the meantime. Note that their indexes of {{SITENAME}} content may be out of date.',
+
+'googlesearch' => '
+<form method="get" action="http://www.google.com/search" id="googlesearch">
+    <input type="hidden" name="domains" value="{{SERVER}}" />
+    <input type="hidden" name="num" value="50" />
+    <input type="hidden" name="ie" value="$2" />
+    <input type="hidden" name="oe" value="$2" />
+
+    <input type="text" name="q" size="31" maxlength="255" value="$1" />
+    <input type="submit" name="btnG" value="$3" />
+  <div>
+    <input type="radio" name="sitesearch" id="gwiki" value="{{SERVER}}" checked="checked" /><label for="gwiki">{{SITENAME}}</label>
+    <input type="radio" name="sitesearch" id="gWWW" value="" /><label for="gWWW">WWW</label>
+  </div>
+</form>',
+'blanknamespace' => '(Main)',
+
+# Preferences page
+#
+'preferences'  => 'Preferences',
+'prefsnologin' => 'Not logged in',
+'prefsnologintext'     => "You must be [[Special:Userlogin|logged in]] to set user preferences.",
+'prefslogintext' => "You are logged in as \"$1\".
+Your internal ID number is $2.
+
+See [[Project:User preferences help]] for help deciphering the options.",
+'prefsreset'   => 'Preferences have been reset from storage.',
+'qbsettings'   => 'Quickbar',
+'changepassword' => 'Change password',
+'skin'                 => 'Skin',
+'math'                 => 'Math',
+'dateformat'           => 'Date format',
+'math_failure'         => 'Failed to parse',
+'math_unknown_error'   => 'unknown error',
+'math_unknown_function'        => 'unknown function ',
+'math_lexing_error'    => 'lexing error',
+'math_syntax_error'    => 'syntax error',
+'math_image_error'     => 'PNG conversion failed; check for correct installation of latex, dvips, gs, and convert',
+'math_bad_tmpdir'      => 'Can\'t write to or create math temp directory',
+'math_bad_output'      => 'Can\'t write to or create math output directory',
+'math_notexvc' => 'Missing texvc executable; please see math/README to configure.',
+'prefs-personal' => 'User data',
+'prefs-rc' => 'Recent changes & stubs',
+'prefs-misc' => 'Misc',
+'saveprefs'            => 'Save',
+'resetprefs'   => 'Reset',
+'oldpassword'  => 'Old password',
+'newpassword'  => 'New password',
+'retypenew'            => 'Retype new password',
+'textboxsize'  => 'Editing',
+'rows'                 => 'Rows',
+'columns'              => 'Columns',
+'searchresultshead' => 'Search',
+'resultsperpage' => 'Hits per page',
+'contextlines' => 'Lines per hit',
+'contextchars' => 'Context per line',
+'stubthreshold' => 'Threshold for stub display',
+'recentchangescount' => 'Titles in recent changes',
+'savedprefs'   => 'Your preferences have been saved.',
+'timezonelegend' => 'Time zone',
+'timezonetext' => 'The number of hours your local time differs from server time (UTC).',
+'localtime'    => 'Local time',
+'timezoneoffset' => 'Offset¹',
+'servertime'   => 'Server time',
+'guesstimezone' => 'Fill in from browser',
+'emailflag'            => 'Disable e-mail from other users',
+'defaultns'            => 'Search in these namespaces by default:',
+'default'              => 'default',
+'files'                        => 'Files',
+
+# User levels special page
+#
+
+# switching pan
+'groups-lookup-group' => 'Manage group rights',
+'groups-group-edit' => 'Existing groups:',
+'editgroup' => 'Edit Group',
+'addgroup' => 'Add Group',
+
+'userrights-lookup-user' => 'Manage user groups',
+'userrights-user-editname' => 'Enter a username: ',
+'editusergroup' => 'Edit User Groups',
+
+# group editing
+'groups-editgroup'          => 'Edit group',
+'groups-addgroup'           => 'Add group',
+'groups-editgroup-preamble' => 'If the name or description starts with a colon, the
+remainder will be treated as a message name, and hence the text will be localised
+using the MediaWiki namespace',
+'groups-editgroup-name'     => 'Group name:',
+'groups-editgroup-description' => 'Group description (max 255 characters):<br />',
+'savegroup'                 => 'Save Group',
+'groups-tableheader'        => 'ID || Name || Description || Rights',
+'groups-existing'           => 'Existing groups',
+'groups-noname'             => 'Please specify a valid group name',
+'groups-already-exists'     => 'A group of that name already exists',
+'addgrouplogentry'          => 'Added group $2',
+'changegrouplogentry'       => 'Changed group $2',
+'renamegrouplogentry'       => 'Renamed group $2 to $3',
+
+# user groups editing
+#
+'userrights-editusergroup' => 'Edit user groups',
+'saveusergroups' => 'Save User Groups',
+'userrights-groupsmember' => 'Member of:',
+'userrights-groupsavailable' => 'Available groups:',
+'userrights-groupshelp' => 'Select groups you want the user to be removed from or added to.
+Unselected groups will not be changed. You can deselect a group with CTRL + Left Click',
+'userrights-logcomment' => 'Changed group membership from $1 to $2',
+
+# Default group names and descriptions
+#
+'group-anon-name'       => 'Anonymous',
+'group-anon-desc'       => 'Anonymous users',
+'group-loggedin-name'   => 'User',
+'group-loggedin-desc'   => 'General logged in users',
+'group-admin-name'      => 'Administrator',
+'group-admin-desc'      => 'Trusted users able to block users and delete articles',
+'group-bureaucrat-name' => 'Bureaucrat',
+'group-bureaucrat-desc' => 'The bureaucrat group is able to make sysops',
+'group-steward-name'    => 'Steward',
+'group-steward-desc'    => 'Full access',
+
+
+# Recent changes
+#
+'changes' => 'changes',
+'recentchanges' => 'Recent changes',
+'recentchanges-url' => 'Special:Recentchanges',
+'recentchangestext' => 'Track the most recent changes to the wiki on this page.',
+'rcloaderr'            => 'Loading recent changes',
+'rcnote'               => "Below are the last <strong>$1</strong> changes in last <strong>$2</strong> days.",
+'rcnotefrom'   => "Below are the changes since <b>$2</b> (up to <b>$1</b> shown).",
+'rclistfrom'   => "Show new changes starting from $1",
+'showhideminor' => "$1 minor edits | $2 bots | $3 logged in users | $4 patrolled edits ",
+'rclinks'              => "Show last $1 changes in last $2 days<br />$3",
+'rchide'               => "in $4 form; $1 minor edits; $2 secondary namespaces; $3 multiple edits.",
+'rcliu'                        => "; $1 edits from logged in users",
+'diff'                 => 'diff',
+'hist'                 => 'hist',
+'hide'                 => 'Hide',
+'show'                 => 'show',
+'tableform'            => 'table',
+'listform'             => 'list',
+'nchanges'             => "$1 changes",
+'minoreditletter' => 'm',
+'newpageletter' => 'N',
+'sectionlink' => '→',
+'number_of_watching_users_RCview'      => '[$1]',
+'number_of_watching_users_pageview'    => '[$1 watching user/s]',
+
+# Upload
+#
+'upload'               => 'Upload file',
+'uploadbtn'            => 'Upload file',
+'uploadlink'   => 'Upload images',
+'reupload'             => 'Re-upload',
+'reuploaddesc' => 'Return to the upload form.',
+'uploadnologin' => 'Not logged in',
+'uploadnologintext'    => "You must be [[Special:Userlogin|logged in]]
+to upload files.",
+'upload_directory_read_only' => 'The upload directory ($1) is not writable by the webserver.',
+'uploaderror'  => 'Upload error',
+'uploadtext'   =>
+"
+Use the form below to upload new files,
+to view or search previously uploaded images
+go to the [[Special:Imagelist|list of uploaded files]],
+uploads and deletions are also logged in the [[Special:Log|project log]].
+
+You must also check the box affirming that you are not
+violating any copyrights by uploading the file.
+Press the \"Upload\" button to finish the upload.
+
+To include the image in a page, use a link in the form
+'''<nowiki>[[{{ns:6}}:file.jpg]]</nowiki>''',
+'''<nowiki>[[{{ns:6}}:file.png|alt text]]</nowiki>''' or
+'''<nowiki>[[{{ns:-2}}:file.ogg]]</nowiki>''' for directly linking to the file.
+",
+
+'uploadlog'            => 'upload log',
+'uploadlogpage' => 'Upload_log',
+'uploadlogpagetext' => 'Below is a list of the most recent file uploads.',
+'filename'             => 'Filename',
+'filedesc'             => 'Summary',
+'filestatus' => 'Copyright status',
+'filesource' => 'Source',
+'copyrightpage' => "Project:Copyrights",
+'copyrightpagename' => "{{SITENAME}} copyright",
+'uploadedfiles'        => 'Uploaded files',
+'ignorewarning'        => 'Ignore warning and save file anyway.',
+'minlength'            => 'File names must be at least three letters.',
+'illegalfilename'      => 'The filename "$1" contains characters that are not allowed in page titles. Please rename the file and try uploading it again.',
+'badfilename'  => 'File name has been changed to "$1".',
+'badfiletype'  => "\".$1\" is not a recommended image file format.",
+'largefile'            => 'It is recommended that images not exceed $1 bytes in size, this file is $2 bytes',
+'emptyfile'            => 'The file you uploaded seems to be empty. This might be due to a typo in the file name. Please check whether you really want to upload this file.',
+'fileexists'           => 'A file with this name exists already, please check $1 if you are not sure if you want to change it.',
+'successfulupload' => 'Successful upload',
+'fileuploaded' => "File $1 uploaded successfully.
+Please follow this link: $2 to the description page and fill
+in information about the file, such as where it came from, when it was
+created and by whom, and anything else you may know about it. If this is an image, you can insert it like this: <tt><nowiki>[[Image:$1|thumb|Description]]</nowiki></tt>",
+'uploadwarning' => 'Upload warning',
+'savefile'             => 'Save file',
+'uploadedimage' => "uploaded \"[[$1]]\"",
+'uploaddisabled' => 'Sorry, uploading is disabled.',
+'uploadscripted' => 'This file contains HTML or script code that may be erroneously be interpreted by a web browser.',
+'uploadcorrupt' => 'The file is corrupt or has an incorrect extension. Please check the file and upload again.',
+'uploadvirus' => 'The file contains a virus! Details: $1',
+'sourcefilename' => 'Source filename',
+'destfilename' => 'Destination filename',
+
+# Image list
+#
+'imagelist'            => 'File list',
+'imagelisttext'        => "Below is a list of $1 files sorted $2.",
+'getimagelist' => 'fetching file list',
+'ilsubmit'             => 'Search',
+'showlast'             => "Show last $1 files sorted $2.",
+'byname'               => 'by name',
+'bydate'               => 'by date',
+'bysize'               => 'by size',
+'imgdelete'            => 'del',
+'imgdesc'              => 'desc',
+'imglegend'            => 'Legend: (desc) = show/edit file description.',
+'imghistory'   => 'File history',
+'revertimg'            => 'rev',
+'deleteimg'            => 'del',
+'deleteimgcompletely'          => 'Delete all revisions of this file',
+'imghistlegend' => 'Legend: (cur) = this is the current file, (del) = delete
+this old version, (rev) = revert to this old version.
+<br /><i>Click on date to see the file uploaded on that date</i>.',
+'imagelinks'   => 'Links',
+'linkstoimage' => 'The following pages link to this file:',
+'nolinkstoimage' => 'There are no pages that link to this file.',
+'sharedupload' => 'This file is a shared upload and may be used by other projects.',
+'shareduploadwiki' => 'Please see the [$1 file description page] for further information.',
+'shareddescriptionfollows' => '-',
+'noimage'       => 'No file by this name exists, you can [$1 upload it]',
+'uploadnewversion' => '[$1 Upload a new version of this file]',
+
+# Statistics
+#
+'statistics'   => 'Statistics',
+'sitestats'            => '{{SITENAME}} statistics',
+'userstats'            => 'User statistics',
+'sitestatstext' => "There are '''$1''' total pages in the database.
+This includes \"talk\" pages, pages about {{SITENAME}}, minimal \"stub\"
+pages, redirects, and others that probably don't qualify as content pages.
+Excluding those, there are '''$2''' pages that are probably legitimate
+content pages.
+
+There have been a total of '''$3''' page views, and '''$4''' page edits
+since the wiki was setup.
+That comes to '''$5''' average edits per page, and '''$6''' views per edit.",
+'userstatstext' => "There are '''$1''' registered users, of which
+'''$2''' (or '''$4%''') are administrators (see $3).",
+
+# Maintenance Page
+#
+'maintenance'          => 'Maintenance page',
+'maintnancepagetext'   => 'This page includes several handy tools for everyday maintenance. Some of these functions tend to stress the database, so please do not hit reload after every item you fixed ;-)',
+'maintenancebacklink'  => 'Back to Maintenance Page',
+'disambiguations'      => 'Disambiguation pages',
+'disambiguationspage'  => 'Template:disambig',
+'disambiguationstext'  => "The following pages link to a <i>disambiguation page</i>. They should link to the appropriate topic instead.<br />A page is treated as disambiguation if it is linked from $1.<br />Links from other namespaces are <i>not</i> listed here.",
+'doubleredirects'      => 'Double redirects',
+'doubleredirectstext'  => "Each row contains links to the first and second redirect, as well as the first line of the second redirect text, usually giving the \"real\" target page, which the first redirect should point to.",
+'brokenredirects'      => 'Broken Redirects',
+'brokenredirectstext'  => 'The following redirects link to a non-existing pages.',
+'selflinks'            => 'Pages with Self Links',
+'selflinkstext'                    => 'The following pages contain a link to themselves, which they should not.',
+'mispeelings'           => 'Pages with misspellings',
+'mispeelingstext'               => "The following pages contain a common misspelling, which are listed on $1. The correct spelling might be given (like this).",
+'mispeelingspage'       => 'List of common misspellings',
+'missinglanguagelinks'  => 'Missing Language Links',
+'missinglanguagelinksbutton'    => 'Find missing language links for',
+'missinglanguagelinkstext'      => "These pages do <i>not</i> link to their counterpart in $1. Redirects and subpages are <i>not</i> shown.",
+
+
+# Miscellaneous special pages
+#
+'orphans'              => 'Orphaned pages',
+'geo'          => 'GEO coordinates',
+'validate'             => 'Validate page',
+'lonelypages'  => 'Orphaned pages',
+'uncategorizedpages'   => 'Uncategorized pages',
+'uncategorizedcategories'      => 'Uncategorized categories',
+'unusedcategories' => 'Unused categories',
+'unusedimages' => 'Unused files',
+'popularpages' => 'Popular pages',
+'nviews'               => '$1 views',
+'wantedpages'  => 'Wanted pages',
+'mostlinked'   => 'Most linked to pages',
+'nlinks'               => '$1 links',
+'allpages'             => 'All pages',
+'randompage'   => 'Random page',
+'randompage-url'=> 'Special:Random',
+'shortpages'   => 'Short pages',
+'longpages'            => 'Long pages',
+'deadendpages'  => 'Dead-end pages',
+'listusers'            => 'User list',
+'specialpages' => 'Special pages',
+'spheading'            => 'Special pages for all users',
+'restrictedpheading'   => 'Restricted special pages',
+'protectpage'  => 'Protect page',
+'recentchangeslinked' => 'Related changes',
+'rclsub'               => "(to pages linked from \"$1\")",
+'debug'                        => 'Debug',
+'newpages'             => 'New pages',
+'ancientpages'         => 'Oldest pages',
+'intl'         => 'Interlanguage links',
+'move' => 'Move',
+'movethispage' => 'Move this page',
+'unusedimagestext' => '<p>Please note that other web sites may link to an image with
+a direct URL, and so may still be listed here despite being
+in active use.</p>',
+'unusedcategoriestext' => 'The following category pages exist although no other article or category make use of them.',
+
+'booksources'  => 'Book sources',
+'categoriespagetext' => 'The following categories exist in the wiki.',
+'data' => 'Data',
+'userrights' => 'User rights management',
+'groups' => 'User groups',
+
+'booksourcetext' => "Below is a list of links to other sites that
+sell new and used books, and may also have further information
+about books you are looking for.",
+'isbn' => 'ISBN',
+'rfcurl' =>  'http://www.ietf.org/rfc/rfc$1.txt',
+'pubmedurl' =>  'http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?cmd=Retrieve&db=pubmed&dopt=Abstract&list_uids=$1',
+'alphaindexline' => "$1 to $2",
+'version'              => 'Version',
+'log'          => 'Logs',
+'alllogstext'  => 'Combined display of upload, deletion, protection, blocking, and sysop logs.
+You can narrow down the view by selecting a log type, the user name, or the affected page.',
+
+# Special:Allpages
+'nextpage'          => 'Next page ($1)',
+'allpagesfrom'         => 'Display pages starting at:',
+'allarticles'          => 'All articles',
+'allnonarticles'       => 'All non-articles',
+'allinnamespace'       => 'All pages ($1 namespace)',
+'allnotinnamespace'    => 'All pages (not in $1 namespace)',
+'allpagesprev'         => 'Previous',
+'allpagesnext'         => 'Next',
+'allpagessubmit'       => 'Go',
+
+# E this user
+#
+'mailnologin'  => 'No send address',
+'mailnologintext' => "You must be [[Special:Userlogin|logged in]]
+and have a valid e-mail address in your [[Special:Preferences|preferences]]
+to send e-mail to other users.",
+'emailuser'            => 'E-mail this user',
+'emailpage'            => 'E-mail user',
+'emailpagetext'        => 'If this user has entered a valid e-mail address in
+his or her user preferences, the form below will send a single message.
+The e-mail address you entered in your user preferences will appear
+as the "From" address of the mail, so the recipient will be able
+to reply.',
+'usermailererror' => 'Mail object returned error: ',
+'defemailsubject'  => "{{SITENAME}} e-mail",
+'noemailtitle' => 'No e-mail address',
+'noemailtext'  => 'This user has not specified a valid e-mail address,
+or has chosen not to receive e-mail from other users.',
+'emailfrom'            => 'From',
+'emailto'              => 'To',
+'emailsubject' => 'Subject',
+'emailmessage' => 'Message',
+'emailsend'            => 'Send',
+'emailsent'            => 'E-mail sent',
+'emailsenttext' => 'Your e-mail message has been sent.',
+
+# Watchlist
+#
+'watchlist'                    => 'My watchlist',
+'watchlistsub'         => "(for user \"$1\")",
+'nowatchlist'          => 'You have no items on your watchlist.',
+'watchnologin'         => 'Not logged in',
+'watchnologintext'     => 'You must be [[Special:Userlogin|logged in]] to modify your watchlist.',
+'addedwatch'           => 'Added to watchlist',
+'addedwatchtext'       => "The page \"$1\" has been added to your [[Special:Watchlist|watchlist]].
+Future changes to this page and its associated Talk page will be listed there,
+and the page will appear '''bolded''' in the [[Special:Recentchanges|list of recent changes]] to
+make it easier to pick out.
+
+<p>If you want to remove the page from your watchlist later, click \"Unwatch\" in the sidebar.",
+'removedwatch'         => 'Removed from watchlist',
+'removedwatchtext'     => "The page \"$1\" has been removed from your watchlist.",
+'watch' => 'Watch',
+'watchthispage'                => 'Watch this page',
+'unwatch' => 'Unwatch',
+'unwatchthispage'      => 'Stop watching',
+'notanarticle'         => 'Not a content page',
+'watchnochange'        => 'None of your watched items was edited in the time period displayed.',
+'watchdetails'         => "* $1 pages watched not counting talk pages
+* [[Special:Watchlist/edit|Show and edit complete watchlist]]
+",
+'wlheader-enotif'              => "* Email notification is enabled.",
+'wlheader-showupdated'   => "* Pages which have been changed since you last visited them are shown in '''bold'''",
+'watchmethod-recent'=> 'checking recent edits for watched pages',
+'watchmethod-list'     => 'checking watched pages for recent edits',
+'removechecked'        => 'Remove checked items from watchlist',
+'watchlistcontains' => "Your watchlist contains $1 pages.",
+'watcheditlist'                => 'Here\'s an alphabetical list of your
+watched content pages. Check the boxes of pages you want to remove from your watchlist and click the \'remove checked\' button
+at the bottom of the screen (deleting a content page also deletes the accompanying talk page and vice versa).',
+'removingchecked'      => 'Removing requested items from watchlist...',
+'couldntremove'        => "Couldn't remove item '$1'...",
+'iteminvalidname'      => "Problem with item '$1', invalid name...",
+'wlnote'               => 'Below are the last $1 changes in the last <b>$2</b> hours.',
+'wlshowlast'           => 'Show last $1 hours $2 days $3',
+'wlsaved'              => 'This is a saved version of your watchlist.',
+'wlhideshowown'        => '$1 my edits.',
+'wlshow'               => 'Show',
+'wlhide'               => 'Hide',
+
+'enotif_mailer'                => '{{SITENAME}} Notification Mailer',
+'enotif_reset'                 => 'Mark all pages visited',
+'enotif_newpagetext'=> 'This is a new page.',
+'changed'                      => 'changed',
+'created'                      => 'created',
+'enotif_subject'       => '{{SITENAME}} page $PAGETITLE has been $CHANGEDORCREATED by $PAGEEDITOR',
+'enotif_lastvisited' => 'See $1 for all changes since your last visit.',
+'enotif_body' => 'Dear $WATCHINGUSERNAME,
+
+the {{SITENAME}} page $PAGETITLE has been $CHANGEDORCREATED on $PAGEEDITDATE by $PAGEEDITOR, see $PAGETITLE_URL for the current version.
+
+$NEWPAGE
+
+Editor\'s summary: $PAGESUMMARY $PAGEMINOREDIT
+
+Contact the editor:
+mail: $PAGEEDITOR_EMAIL
+wiki: $PAGEEDITOR_WIKI
+
+There will be no other notifications in case of further changes unless you visit this page. You could also reset the notification flags for all your watched pages on your watchlist.
+
+             Your friendly {{SITENAME}} notification system
+
+--
+To change your watchlist settings, visit
+{{SERVER}}{{localurl:Special:Watchlist/edit}}
+
+Feedback and further assistance:
+{{SERVER}}{{localurl:Help:Contents}}',
+
+# Delete/protect/revert
+#
+'deletepage'   => 'Delete page',
+'confirm'              => 'Confirm',
+'excontent' => "content was: '$1'",
+'excontentauthor' => "content was: '$1' (and the only contributor was '$2')",
+'exbeforeblank' => "content before blanking was: '$1'",
+'exblank' => 'page was empty',
+'confirmdelete' => 'Confirm delete',
+'deletesub'            => "(Deleting \"$1\")",
+'historywarning' => 'Warning: The page you are about to delete has a history: ',
+'confirmdeletetext' => "You are about to permanently delete a page
+or image along with all of its history from the database.
+Please confirm that you intend to do this, that you understand the
+consequences, and that you are doing this in accordance with
+[[Project:Policy]].",
+'actioncomplete' => 'Action complete',
+'deletedtext'  => "\"$1\" has been deleted.
+See $2 for a record of recent deletions.",
+'deletedarticle' => "deleted \"[[$1]]\"",
+'dellogpage'   => 'Deletion_log',
+'dellogpagetext' => 'Below is a list of the most recent deletions.',
+'deletionlog'  => 'deletion log',
+'reverted'             => 'Reverted to earlier revision',
+'deletecomment'        => 'Reason for deletion',
+'imagereverted' => 'Revert to earlier version was successful.',
+'rollback'             => 'Roll back edits',
+'rollback_short' => 'Rollback',
+'rollbacklink' => 'rollback',
+'rollbackfailed' => 'Rollback failed',
+'cantrollback' => 'Cannot revert edit; last contributor is only author of this page.',
+'alreadyrolled'        => "Cannot rollback last edit of [[$1]]
+by [[User:$2|$2]] ([[User talk:$2|Talk]]); someone else has edited or rolled back the page already.
+
+Last edit was by [[User:$3|$3]] ([[User talk:$3|Talk]]). ",
+#   only shown if there is an edit comment
+'editcomment' => "The edit comment was: \"<i>$1</i>\".",
+'revertpage'   => "Reverted edit of $2, changed back to last version by $1",
+'sessionfailure' => 'There seems to be a problem with your login session;
+this action has been canceled as a precaution against session hijacking.
+Please hit "back" and reload the page you came from, then try again.',
+'protectlogpage' => 'Protection_log',
+'protectlogtext' => "Below is a list of page locks/unlocks.
+See [[Project:Protected page]] for more information.",
+'protectedarticle' => 'protected "[[$1]]"',
+'unprotectedarticle' => 'unprotected "[[$1]]"',
+'protectsub' => '(Protecting "$1")',
+'confirmprotecttext' => 'Do you really want to protect this page?',
+'confirmprotect' => 'Confirm protection',
+'protectmoveonly' => 'Protect from moves only',
+'protectcomment' => 'Reason for protecting',
+'unprotectsub' =>"(Unprotecting \"$1\")",
+'confirmunprotecttext' => 'Do you really want to unprotect this page?',
+'confirmunprotect' => 'Confirm unprotection',
+'unprotectcomment' => 'Reason for unprotecting',
+
+# Undelete
+'undelete' => 'Restore deleted page',
+'undeletepage' => 'View and restore deleted pages',
+'undeletepagetext' => 'The following pages have been deleted but are still in the archive and
+can be restored. The archive may be periodically cleaned out.',
+'undeletearticle' => 'Restore deleted page',
+'undeleterevisions' => "$1 revisions archived",
+'undeletehistory' => 'If you restore the page, all revisions will be restored to the history.
+If a new page with the same name has been created since the deletion, the restored
+revisions will appear in the prior history, and the current revision of the live page
+will not be automatically replaced.',
+'undeleterevision' => "Deleted revision as of $1",
+'undeletebtn' => 'Restore!',
+'undeletedarticle' => "restored \"[[$1]]\"",
+'undeletedrevisions' => "$1 revisions restored",
+'undeletedtext'   => "[[$1]] has been successfully restored.
+See [[Special:Log/delete]] for a record of recent deletions and restorations.",
+
+# Namespace form on various pages
+'namespace' => 'Namespace:',
+'invert' => 'Invert selection',
+
+# Contributions
+#
+'contributions' => 'User contributions',
+'mycontris'     => 'My contributions',
+'contribsub'    => "For $1",
+'nocontribs'    => 'No changes were found matching these criteria.',
+'ucnote'        => "Below are this user's last <b>$1</b> changes in the last <b>$2</b> days.",
+'uclinks'       => "View the last $1 changes; view the last $2 days.",
+'uctop'         => ' (top)' ,
+'newbies'       => 'newbies',
+'contribs-showhideminor' => '$1 minor edits',
+
+# What links here
+#
+'whatlinkshere'        => 'What links here',
+'notargettitle' => 'No target',
+'notargettext' => 'You have not specified a target page or user
+to perform this function on.',
+'linklistsub'  => '(List of links)',
+'linkshere'            => 'The following pages link to here:',
+'nolinkshere'  => 'No pages link to here.',
+'isredirect'   => 'redirect page',
+
+# Block/unblock IP
+#
+'blockip'              => 'Block user',
+'blockiptext'  => "Use the form below to block write access
+from a specific IP address or username.
+This should be done only only to prevent vandalism, and in
+accordance with [[Project:Policy|policy]].
+Fill in a specific reason below (for example, citing particular
+pages that were vandalized).",
+'ipaddress'            => 'IP Address',
+'ipadressorusername' => 'IP Address or username',
+'ipbexpiry'            => 'Expiry',
+'ipbreason'            => 'Reason',
+'ipbsubmit'            => 'Block this user',
+'ipbother'             => 'Other time',
+'ipboptions'           => '2 hours:2 hours,1 day:1 day,3 days:3 days,1 week:1 week,2 weeks:2 weeks,1 month:1 month,3 months:3 months,6 months:6 months,1 year:1 year,infinite:infinite',
+'ipbotheroption'       => 'other',
+'badipaddress' => 'Invalid IP address',
+'blockipsuccesssub' => 'Block succeeded',
+'blockipsuccesstext' => '[[{{ns:Special}}:Contributions/$1|$1]] has been blocked.
+<br />See[[{{ns:Special}}:Ipblocklist|IP block list]] to review blocks.',
+'unblockip'            => 'Unblock user',
+'unblockiptext'        => 'Use the form below to restore write access
+to a previously blocked IP address or username.',
+'ipusubmit'            => 'Unblock this address',
+'ipusuccess'   => "\"[[$1]]\" unblocked",
+'ipblocklist'  => 'List of blocked IP addresses and usernames',
+'blocklistline'        => "$1, $2 blocked $3 ($4)",
+'infiniteblock' => 'infinite',
+'expiringblock' => 'expires $1',
+'ipblocklistempty'     => 'The blocklist is empty.',
+'blocklink'            => 'block',
+'unblocklink'  => 'unblock',
+'contribslink' => 'contribs',
+'autoblocker'  => 'Autoblocked because your IP address has been recently used by "[[User:$1|$1]]". The reason given for $1\'s block is: "\'\'\'$2\'\'\'"',
+'blocklogpage' => 'Block_log',
+'blocklogentry'        => 'blocked "[[$1]]" with an expiry time of $2',
+'blocklogtext' => 'This is a log of user blocking and unblocking actions. Automatically
+blocked IP addresses are not listed. See the [[Special:Ipblocklist|IP block list]] for
+the list of currently operational bans and blocks.',
+'unblocklogentry'      => 'unblocked $1',
+'range_block_disabled' => 'The sysop ability to create range blocks is disabled.',
+'ipb_expiry_invalid'   => 'Expiry time invalid.',
+'ip_range_invalid'     => "Invalid IP range.\n",
+'proxyblocker' => 'Proxy blocker',
+'proxyblockreason'     => 'Your IP address has been blocked because it is an open proxy. Please contact your Internet service provider or tech support and inform them of this serious security problem.',
+'proxyblocksuccess'    => "Done.\n",
+'sorbs'         => 'SORBS DNSBL',
+'sorbsreason'   => 'Your IP address is listed as an open proxy in the [http://www.sorbs.net SORBS] DNSBL.',
+'sorbs_create_account_reason' => 'Your IP address is listed as an open proxy in the [http://www.sorbs.net SORBS] DNSBL. You cannot create an account',
+
+
+# Developer tools
+#
+'lockdb'               => 'Lock database',
+'unlockdb'             => 'Unlock database',
+'lockdbtext'   => 'Locking the database will suspend the ability of all
+users to edit pages, change their preferences, edit their watchlists, and
+other things requiring changes in the database.
+Please confirm that this is what you intend to do, and that you will
+unlock the database when your maintenance is done.',
+'unlockdbtext' => 'Unlocking the database will restore the ability of all
+users to edit pages, change their preferences, edit their watchlists, and
+other things requiring changes in the database.
+Please confirm that this is what you intend to do.',
+'lockconfirm'  => 'Yes, I really want to lock the database.',
+'unlockconfirm'        => 'Yes, I really want to unlock the database.',
+'lockbtn'              => 'Lock database',
+'unlockbtn'            => 'Unlock database',
+'locknoconfirm' => 'You did not check the confirmation box.',
+'lockdbsuccesssub' => 'Database lock succeeded',
+'unlockdbsuccesssub' => 'Database lock removed',
+'lockdbsuccesstext' => 'The database has been locked.
+<br />Remember to remove the lock after your maintenance is complete.',
+'unlockdbsuccesstext' => 'The database has been unlocked.',
+
+# Make sysop
+'makesysoptitle'       => 'Make a user into a sysop',
+'makesysoptext'                => 'This form is used by bureaucrats to turn ordinary users into administrators.
+Type the name of the user in the box and press the button to make the user an administrator',
+'makesysopname'                => 'Name of the user:',
+'makesysopsubmit'      => 'Make this user into a sysop',
+'makesysopok'          => "<b>User \"$1\" is now a sysop</b>",
+'makesysopfail'                => "<b>User \"$1\" could not be made into a sysop. (Did you enter the name correctly?)</b>",
+'setbureaucratflag' => 'Set bureaucrat flag',
+'setstewardflag'    => 'Set steward flag',
+'bureaucratlog'                => 'Bureaucrat_log',
+'rightslogtext'                => 'This is a log of changes to user rights.',
+'bureaucratlogentry'   => "Changed group membership for $1 from $2 to $3",
+'rights'                       => 'Rights:',
+'set_user_rights'      => 'Set user rights',
+'user_rights_set'      => "<b>User rights for \"$1\" updated</b>",
+'set_rights_fail'      => "<b>User rights for \"$1\" could not be set. (Did you enter the name correctly?)</b>",
+'makesysop'         => 'Make a user into a sysop',
+'already_sysop'     => 'This user is already an administrator',
+'already_bureaucrat' => 'This user is already a bureaucrat',
+'already_steward'   => 'This user is already a steward',
+
+# Validation
+'val_yes' => 'Yes',
+'val_no' => 'No',
+'val_of' => '$1 of $2',
+'val_revision' => 'Revision',
+'val_time' => 'Time',
+'val_user_stats_title' => 'Validation overview of user $1',
+'val_my_stats_title' => 'My validation overview',
+'val_list_header' => '<th>#</th><th>Topic</th><th>Range</th><th>Action</th>',
+'val_add' => 'Add',
+'val_del' => 'Delete',
+'val_show_my_ratings' => 'Show my validations',
+'val_revision_number' => 'Revision #$1',
+'val_warning' => '<b>Never, <i>ever</i>, change something here without <i>explicit</i> community consensus!</b>',
+'val_rev_for' => 'Revisions for $1',
+'val_details_th_user' => 'User $1',
+'val_validation_of' => 'Validation of "$1"',
+'val_revision_of' => 'Revision of $1',
+'val_revision_changes_ok' => 'Your ratings have been stored!',
+'val_rev_stats' => 'See the validation statistics for "$1" <a href="$2">here</a>',
+'val_revision_stats_link' => 'details',
+'val_iamsure' => 'Check this box if you really mean it!',
+'val_details_th' => '<sub>User</sub> \\ <sup>Topic</sup>',
+'val_clear_old' => 'Clear my older validation data',
+'val_merge_old' => 'Use my previous assessment where selected \'No opinion\'',
+'val_form_note' => "'''Hint:''' Merging your data means that for the article revision you select, all options where you have specified ''no opinion'' will be set to the value and comment of the most recent revision for which you have expressed an opinion. For example, if you want to change a single option for a newer revision, but also keep your other settings for this article in this revision, just select which option you intend to ''change'', and merging will fill in the other options with your previous settings.",
+'val_noop' => 'No opinion',
+'val_topic_desc_page' => 'Project:Validation topics',
+'val_votepage_intro' => 'Change this text <a href="{{SERVER}}{{localurl:MediaWiki:Val_votepage_intro}}">here</a>!',
+'val_percent' => '<b>$1%</b><br />($2 of $3 points<br />by $4 users)',
+'val_percent_single' => '<b>$1%</b><br />($2 of $3 points<br />by one user)',
+'val_total' => 'Total',
+'val_version' => 'Version',
+'val_tab' => 'Validate',
+'val_this_is_current_version' => 'this is the latest version',
+'val_version_of' => "Version of $1" ,
+'val_table_header' => "<tr><th>Class</th>$1<th colspan=4>Opinion</th>$1<th>Comment</th></tr>\n",
+'val_stat_link_text' => 'Validation statistics for this article',
+'val_view_version' => 'View this revision',
+'val_validate_version' => 'Validate this version',
+'val_user_validations' => 'This user has validated $1 pages.',
+'val_no_anon_validation' => 'You have to be logged in to validate an article.',
+'val_validate_article_namespace_only' => 'Only articles can be validated. This page is <i>not</i> in the article namespace.',
+'val_validated' => 'Validation done.',
+'val_article_lists' => 'List of validated articles',
+'val_page_validation_statistics' => 'Page validation statistics for $1',
+
+# Move page
+#
+'movepage'             => 'Move page',
+'movepagetext' => 'Using the form below will rename a page, moving all
+of its history to the new name.
+The old title will become a redirect page to the new title.
+Links to the old page title will not be changed; be sure to
+check for double or broken redirects.
+You are responsible for making sure that links continue to
+point where they are supposed to go.
+
+Note that the page will \'\'\'not\'\'\' be moved if there is already
+a page at the new title, unless it is empty or a redirect and has no
+past edit history. This means that you can rename a page back to where
+it was just renamed from if you make a mistake, and you cannot overwrite
+an existing page.
+
+<b>WARNING!</b>
+This can be a drastic and unexpected change for a popular page;
+please be sure you understand the consequences of this before
+proceeding.',
+'movepagetalktext' => 'The associated talk page, if any, will be automatically moved along with it \'\'\'unless:\'\'\'
+*You are moving the page across namespaces,
+*A non-empty talk page already exists under the new name, or
+*You uncheck the box below.
+
+In those cases, you will have to move or merge the page manually if desired.',
+'movearticle'  => 'Move page',
+'movenologin'  => 'Not logged in',
+'movenologintext' => "You must be a registered user and [[Special:Userlogin|logged in]]
+to move a page.",
+'newtitle'             => 'To new title',
+'movepagebtn'  => 'Move page',
+'pagemovedsub' => 'Move succeeded',
+'pagemovedtext' => "Page \"[[$1]]\" moved to \"[[$2]]\".",
+'articleexists' => 'A page of that name already exists, or the
+name you have chosen is not valid.
+Please choose another name.',
+'talkexists'   => "'''The page itself was moved successfully, but the
+talk page could not be moved because one already exists at the new
+title. Please merge them manually.'''",
+'movedto'              => 'moved to',
+'movetalk'             => 'Move "talk" page as well, if applicable.',
+'talkpagemoved' => 'The corresponding talk page was also moved.',
+'talkpagenotmoved' => 'The corresponding talk page was <strong>not</strong> moved.',
+'1movedto2'            => '$1 moved to $2',
+'1movedto2_redir' => '$1 moved to $2 over redirect',
+'movelogpage' => 'Move log',
+'movelogpagetext' => 'Below is a list of page moved.',
+'movereason'   => 'Reason',
+'revertmove'   => 'revert',
+'delete_and_move' => 'Delete and move',
+'delete_and_move_text' =>
+'==Deletion required==
+
+The destination article "[[$1]]" already exists. Do you want to delete it to make way for the move?',
+'delete_and_move_reason' => 'Deleted to make way for move',
+'selfmove' => "Source and destination titles are the same; can't move a page over itself.",
+'immobile_namespace' => "Destination title is of a special type; cannot move pages into that namespace.",
+
+# Export
+
+'export'               => 'Export pages',
+'exporttext'   => 'You can export the text and editing history of a particular page or
+set of pages wrapped in some XML. This can be imported into another wiki using MediaWiki
+via the Special:Import page.
+
+To export article pages, enter the titles in the text box below, one title per line, and
+select whether you want the current version as well as all old versions, with the page
+history lines, or just the current version with the info about the last edit.
+
+In the latter case you can also use a link, e.g. [[{{ns:Special}}:Export/Train]] for the
+article [[Train]].
+',
+'exportcuronly'        => 'Include only the current revision, not the full history',
+
+# Namespace 8 related
+
+'allmessages'  => 'System messages',
+'allmessagesname' => 'Name',
+'allmessagesdefault' => 'Default text',
+'allmessagescurrent' => 'Current text',
+'allmessagestext'      => 'This is a list of system messages available in the MediaWiki: namespace.',
+'allmessagesnotsupportedUI' => 'Your current interface language <b>$1</b> is not supported by Special:AllMessages at this site. ',
+'allmessagesnotsupportedDB' => 'Special:AllMessages not supported because wgUseDatabaseMessages is off.',
+
+# Thumbnails
+
+'thumbnail-more'       => 'Enlarge',
+'missingimage'         => "<b>Missing image</b><br /><i>$1</i>\n",
+'filemissing'          => 'File missing',
+
+# Special:Import
+'import'       => 'Import pages',
+'importinterwiki' => 'Transwiki import',
+'importtext'   => 'Please export the file from the source wiki using the Special:Export utility, save it to your disk and upload it here.',
+'importfailed' => "Import failed: $1",
+'importnotext' => 'Empty or no text',
+'importsuccess'        => 'Import succeeded!',
+'importhistoryconflict' => 'Conflicting history revision exists (may have imported this page before)',
+'importnosources' => 'No transwiki import sources have been defined and direct history uploads are disabled.',
+'importnofile' => 'No import file was uploaded.',
+'importuploaderror' => 'Upload of import file failed; perhaps the file is bigger than the allowed upload size.',
+
+# Keyboard access keys for power users
+'accesskey-search' => 'f',
+'accesskey-minoredit' => 'i',
+'accesskey-save' => 's',
+'accesskey-preview' => 'p',
+'accesskey-diff' => 'v',
+'accesskey-compareselectedversions' => 'v',
+
+# tooltip help for some actions, most are in Monobook.js
+'tooltip-search' => 'Search {{SITENAME}} [alt-f]',
+'tooltip-minoredit' => 'Mark this as a minor edit [alt-i]',
+'tooltip-save' => 'Save your changes [alt-s]',
+'tooltip-preview' => 'Preview your changes, please use this before saving! [alt-p]',
+'tooltip-diff' => 'Show which changes you made to the text. [alt-d]',
+'tooltip-compareselectedversions' => 'See the differences between the two selected versions of this page. [alt-v]',
+'tooltip-watch' => 'Add this page to your watchlist [alt-w]',
+
+# stylesheets
+'Monobook.css' => '/* edit this file to customize the monobook skin for the entire site */',
+#'Monobook.js' => '/* edit this file to change js things in the monobook skin */',
+
+# Metadata
+'nodublincore' => 'Dublin Core RDF metadata disabled for this server.',
+'nocreativecommons' => 'Creative Commons RDF metadata disabled for this server.',
+'notacceptable' => 'The wiki server can\'t provide data in a format your client can read.',
+
+# Attribution
+
+'anonymous' => 'Anonymous user(s) of {{SITENAME}}',
+'siteuser' => '{{SITENAME}} user $1',
+'lastmodifiedby' => 'This page was last modified $1 by $2.',
+'and' => 'and',
+'othercontribs' => 'Based on work by $1.',
+'others' => 'others',
+'siteusers' => '{{SITENAME}} user(s) $1',
+'creditspage' => 'Page credits',
+'nocredits' => 'There is no credits info available for this page.',
+
+# Spam protection
+
+'spamprotectiontitle' => 'Spam protection filter',
+'spamprotectiontext' => 'The page you wanted to save was blocked by the spam filter. This is probably caused by a link to an external site.',
+'spamprotectionmatch' => 'The following text is what triggered our spam filter: $1',
+'subcategorycount' => "There are $1 subcategories to this category.",
+'subcategorycount1' => "There is $1 subcategory to this category.",
+'categoryarticlecount' => "There are $1 articles in this category.",
+'categoryarticlecount1' => "There is $1 article in this category.",
+'usenewcategorypage' => "1\n\nSet first character to \"0\" to disable the new category page layout.",
+'listingcontinuesabbrev' => " cont.",
+
+# Info page
+'infosubtitle' => 'Information for page',
+'numedits' => 'Number of edits (article): $1',
+'numtalkedits' => 'Number of edits (discussion page): $1',
+'numwatchers' => 'Number of watchers: $1',
+'numauthors' => 'Number of distinct authors (article): $1',
+'numtalkauthors' => 'Number of distinct authors (discussion page): $1',
+
+# Math options
+'mw_math_png' => 'Always render PNG',
+'mw_math_simple' => 'HTML if very simple or else PNG',
+'mw_math_html' => 'HTML if possible or else PNG',
+'mw_math_source' => 'Leave it as TeX (for text browsers)',
+'mw_math_modern' => 'Recommended for modern browsers',
+'mw_math_mathml' => 'MathML if possible (experimental)',
+
+# Patrolling
+'markaspatrolleddiff'   => "Mark as patrolled",
+'markaspatrolledlink'   => "[$1]",
+'markaspatrolledtext'   => "Mark this article as patrolled",
+'markedaspatrolled'     => "Marked as patrolled",
+'markedaspatrolledtext' => "The selected revision has been marked as patrolled.",
+'rcpatroldisabled'      => "Recent Changes Patrol disabled",
+'rcpatroldisabledtext'  => "The Recent Changes Patrol feature is currently disabled.",
+
+# Monobook.js: tooltips and access keys for monobook
+'Monobook.js' => '/* tooltips and access keys */
+ta = new Object();
+ta[\'pt-userpage\'] = new Array(\'.\',\'My user page\');
+ta[\'pt-anonuserpage\'] = new Array(\'.\',\'The user page for the ip you\\\'re editing as\');
+ta[\'pt-mytalk\'] = new Array(\'n\',\'My talk page\');
+ta[\'pt-anontalk\'] = new Array(\'n\',\'Discussion about edits from this ip address\');
+ta[\'pt-preferences\'] = new Array(\'\',\'My preferences\');
+ta[\'pt-watchlist\'] = new Array(\'l\',\'The list of pages you\\\'re monitoring for changes.\');
+ta[\'pt-mycontris\'] = new Array(\'y\',\'List of my contributions\');
+ta[\'pt-login\'] = new Array(\'o\',\'You are encouraged to log in, it is not mandatory however.\');
+ta[\'pt-anonlogin\'] = new Array(\'o\',\'You are encouraged to log in, it is not mandatory however.\');
+ta[\'pt-logout\'] = new Array(\'o\',\'Log out\');
+ta[\'ca-talk\'] = new Array(\'t\',\'Discussion about the content page\');
+ta[\'ca-edit\'] = new Array(\'e\',\'You can edit this page. Please use the preview button before saving.\');
+ta[\'ca-addsection\'] = new Array(\'+\',\'Add a comment to this discussion.\');
+ta[\'ca-viewsource\'] = new Array(\'e\',\'This page is protected. You can view its source.\');
+ta[\'ca-history\'] = new Array(\'h\',\'Past versions of this page.\');
+ta[\'ca-protect\'] = new Array(\'=\',\'Protect this page\');
+ta[\'ca-delete\'] = new Array(\'d\',\'Delete this page\');
+ta[\'ca-undelete\'] = new Array(\'d\',\'Restore the edits done to this page before it was deleted\');
+ta[\'ca-move\'] = new Array(\'m\',\'Move this page\');
+ta[\'ca-watch\'] = new Array(\'w\',\'Add this page to your watchlist\');
+ta[\'ca-unwatch\'] = new Array(\'w\',\'Remove this page from your watchlist\');
+ta[\'search\'] = new Array(\'f\',\'Search this wiki\');
+ta[\'p-logo\'] = new Array(\'\',\'Main Page\');
+ta[\'n-mainpage\'] = new Array(\'z\',\'Visit the Main Page\');
+ta[\'n-portal\'] = new Array(\'\',\'About the project, what you can do, where to find things\');
+ta[\'n-currentevents\'] = new Array(\'\',\'Find background information on current events\');
+ta[\'n-recentchanges\'] = new Array(\'r\',\'The list of recent changes in the wiki.\');
+ta[\'n-randompage\'] = new Array(\'x\',\'Load a random page\');
+ta[\'n-help\'] = new Array(\'\',\'The place to find out.\');
+ta[\'n-sitesupport\'] = new Array(\'\',\'Support us\');
+ta[\'t-whatlinkshere\'] = new Array(\'j\',\'List of all wiki pages that link here\');
+ta[\'t-recentchangeslinked\'] = new Array(\'k\',\'Recent changes in pages linked from this page\');
+ta[\'feed-rss\'] = new Array(\'\',\'RSS feed for this page\');
+ta[\'feed-atom\'] = new Array(\'\',\'Atom feed for this page\');
+ta[\'t-contributions\'] = new Array(\'\',\'View the list of contributions of this user\');
+ta[\'t-emailuser\'] = new Array(\'\',\'Send a mail to this user\');
+ta[\'t-upload\'] = new Array(\'u\',\'Upload images or media files\');
+ta[\'t-specialpages\'] = new Array(\'q\',\'List of all special pages\');
+ta[\'ca-nstab-main\'] = new Array(\'c\',\'View the content page\');
+ta[\'ca-nstab-user\'] = new Array(\'c\',\'View the user page\');
+ta[\'ca-nstab-media\'] = new Array(\'c\',\'View the media page\');
+ta[\'ca-nstab-special\'] = new Array(\'\',\'This is a special page, you can\\\'t edit the page itself.\');
+ta[\'ca-nstab-wp\'] = new Array(\'a\',\'View the project page\');
+ta[\'ca-nstab-image\'] = new Array(\'c\',\'View the image page\');
+ta[\'ca-nstab-mediawiki\'] = new Array(\'c\',\'View the system message\');
+ta[\'ca-nstab-template\'] = new Array(\'c\',\'View the template\');
+ta[\'ca-nstab-help\'] = new Array(\'c\',\'View the help page\');
+ta[\'ca-nstab-category\'] = new Array(\'c\',\'View the category page\');
+',
+
+# image deletion
+'deletedrevision' => 'Deleted old revision $1.',
+
+# browsing diffs
+'previousdiff' => '← Previous diff',
+'nextdiff' => 'Next diff →',
+
+'imagemaxsize' => 'Limit images on image description pages to: ',
+'thumbsize'    => 'Thumbnail size: ',
+'showbigimage' => 'Download high resolution version ($1x$2, $3 KB)',
+
+'newimages' => 'Gallery of new files',
+'noimages'  => 'Nothing to see.',
+
+# short names for language variants used for language conversion links.
+# to disable showing a particular link, set it to 'disable', e.g.
+# 'variantname-zh-sg' => 'disable',
+'variantname-zh-cn' => 'cn',
+'variantname-zh-tw' => 'tw',
+'variantname-zh-hk' => 'hk',
+'variantname-zh-sg' => 'sg',
+'variantname-zh' => 'zh',
+
+# labels for User: and Title: on Special:Log pages
+'specialloguserlabel' => 'User: ',
+'speciallogtitlelabel' => 'Title: ',
+
+'passwordtooshort' => 'Your password is too short. It must have at least $1 characters.',
+
+# Media Warning
+'mediawarning' => '\'\'\'Warning\'\'\': This file may contain malicious code, by executing it your system may be compromised.
+<hr>',
+
+'fileinfo' => '$1KB, MIME type: <code>$2</code>',
+
+# Metadata
+'metadata' => 'Metadata',
+
+# Exif tags
+'exif-imagewidth' =>'Width',
+'exif-imagelength' =>'Height',
+'exif-bitspersample' =>'Bits per component',
+'exif-compression' =>'Compression scheme',
+'exif-photometricinterpretation' =>'Pixel composition',
+'exif-orientation' =>'Orientation',
+'exif-samplesperpixel' =>'Number of components',
+'exif-planarconfiguration' =>'Data arrangement',
+'exif-ycbcrsubsampling' =>'Subsampling ratio of Y to C',
+'exif-ycbcrpositioning' =>'Y and C positioning',
+'exif-xresolution' =>'Horizontal resolution',
+'exif-yresolution' =>'Vertical resolution',
+'exif-resolutionunit' =>'Unit of X and Y resolution',
+'exif-stripoffsets' =>'Image data location',
+'exif-rowsperstrip' =>'Number of rows per strip',
+'exif-stripbytecounts' =>'Bytes per compressed strip',
+'exif-jpeginterchangeformat' =>'Offset to JPEG SOI',
+'exif-jpeginterchangeformatlength' =>'Bytes of JPEG data',
+'exif-transferfunction' =>'Transfer function',
+'exif-whitepoint' =>'White point chromaticity',
+'exif-primarychromaticities' =>'Chromaticities of primarities',
+'exif-ycbcrcoefficients' =>'Color space transformation matrix coefficients',
+'exif-referenceblackwhite' =>'Pair of black and white reference values',
+'exif-datetime' =>'File change date and time',
+'exif-imagedescription' =>'Image title',
+'exif-make' =>'Camera manufacturer',
+'exif-model' =>'Camera model',
+'exif-software' =>'Software used',
+'exif-artist' =>'Author',
+'exif-copyright' =>'Copyright holder',
+'exif-exifversion' =>'Exif version',
+'exif-flashpixversion' =>'Supported Flashpix version',
+'exif-colorspace' =>'Color space',
+'exif-componentsconfiguration' =>'Meaning of each component',
+'exif-compressedbitsperpixel' =>'Image compression mode',
+'exif-pixelydimension' =>'Valid image width',
+'exif-pixelxdimension' =>'Valind image height',
+'exif-makernote' =>'Manufacturer notes',
+'exif-usercomment' =>'User comments',
+'exif-relatedsoundfile' =>'Related audio file',
+'exif-datetimeoriginal' =>'Date and time of data generation',
+'exif-datetimedigitized' =>'Date and time of digitizing',
+'exif-subsectime' =>'DateTime subseconds',
+'exif-subsectimeoriginal' =>'DateTimeOriginal subseconds',
+'exif-subsectimedigitized' =>'DateTimeDigitized subseconds',
+'exif-exposuretime' =>'Exposure time',
+'exif-fnumber' =>'F Number',
+'exif-exposureprogram' =>'Exposure Program',
+'exif-spectralsensitivity' =>'Spectral sensitivity',
+'exif-isospeedratings' =>'ISO speed rating',
+'exif-oecf' =>'Optoelectronic conversion factor',
+'exif-shutterspeedvalue' =>'Shutter speed',
+'exif-aperturevalue' =>'Aperture',
+'exif-brightnessvalue' =>'Brightness',
+'exif-exposurebiasvalue' =>'Exposure bias',
+'exif-maxaperturevalue' =>'Maximum land aperture',
+'exif-subjectdistance' =>'Subject distance',
+'exif-meteringmode' =>'Metering mode',
+'exif-lightsource' =>'Light source',
+'exif-flash' =>'Flash',
+'exif-focallength' =>'Lens focal length',
+'exif-subjectarea' =>'Subject area',
+'exif-flashenergy' =>'Flash energy',
+'exif-spatialfrequencyresponse' =>'Spatial frequency response',
+'exif-focalplanexresolution' =>'Focal plane X resolution',
+'exif-focalplaneyresolution' =>'Focal plane Y resolution',
+'exif-focalplaneresolutionunit' =>'Focal plane resolution unit',
+'exif-subjectlocation' =>'Subject location',
+'exif-exposureindex' =>'Exposure index',
+'exif-sensingmethod' =>'Sensing method',
+'exif-filesource' =>'File source',
+'exif-scenetype' =>'Scene type',
+'exif-cfapattern' =>'CFA pattern',
+'exif-customrendered' =>'Custom image processing',
+'exif-exposuremode' =>'Exposure mode',
+'exif-whitebalance' =>'White Balance',
+'exif-digitalzoomratio' =>'Digital zoom ratio',
+'exif-focallengthin35mmfilm' =>'Focal length in 35 mm film',
+'exif-scenecapturetype' =>'Scene capture type',
+'exif-gaincontrol' =>'Scene control',
+'exif-contrast' =>'Contrast',
+'exif-saturation' =>'Saturation',
+'exif-sharpness' =>'Sharpness',
+'exif-devicesettingdescription' =>'Device settings description',
+'exif-subjectdistancerange' =>'Subject distance range',
+'exif-imageuniqueid' =>'Unique image ID',
+'exif-gpsversionid' =>'GPS tag version',
+'exif-gpslatituderef' =>'North or South Latitude',
+'exif-gpslatitude' =>'Latitude',
+'exif-gpslongituderef' =>'East or West Longitude',
+'exif-gpslongitude' =>'Longitude',
+'exif-gpsaltituderef' =>'Altitude reference',
+'exif-gpsaltitude' =>'Altitude',
+'exif-gpstimestamp' =>'GPS time (atomic clock)',
+'exif-gpssatellites' =>'Satellites used for measurement',
+'exif-gpsstatus' =>'Receiver status',
+'exif-gpsmeasuremode' =>'Measurement mode',
+'exif-gpsdop' =>'Measurement precision',
+'exif-gpsspeedref' =>'Speed unit',
+'exif-gpsspeed' =>'Speed of GPS receiver',
+'exif-gpstrackref' =>'Reference for direction of movement',
+'exif-gpstrack' =>'Direction of movement',
+'exif-gpsimgdirectionref' =>'Reference for direction of image',
+'exif-gpsimgdirection' =>'Direction of image',
+'exif-gpsmapdatum' =>'Geodetic survey data used',
+'exif-gpsdestlatituderef' =>'Reference for latitude of destination',
+'exif-gpsdestlatitude' =>'Latitude destination',
+'exif-gpsdestlongituderef' =>'Reference for longitude of destination',
+'exif-gpsdestlongitude' =>'Longitude of destination',
+'exif-gpsdestbearingref' =>'Reference for bearing of destination',
+'exif-gpsdestbearing' =>'Bearing of destination',
+'exif-gpsdestdistanceref' =>'Reference for distance to destination',
+'exif-gpsdestdistance' =>'Distance to destination',
+'exif-gpsprocessingmethod' =>'Name of GPS processing method',
+'exif-gpsareainformation' =>'Name of GPS area',
+'exif-gpsdatestamp' =>'GPS date',
+'exif-gpsdifferential' =>'GPS differential correction',
+
+# Make & model, can be wikified in order to link to the camera and model name
+
+'exif-make-value' => '$1',
+'exif-model-value' =>'$1',
+'exif-software-value' => '$1',
+
+# Exif attributes
+
+'exif-compression-1' => 'Uncompressed',
+'exif-compression-6' => 'JPEG',
+
+'exif-photometricinterpretation-1' => 'RGB',
+'exif-photometricinterpretation-6' => 'YCbCr',
+
+'exif-orientation-1' => 'Normal', // 0th row: top; 0th column: left
+'exif-orientation-2' => 'Flipped horizontally', // 0th row: top; 0th column: right
+'exif-orientation-3' => 'Rotated 180°', // 0th row: bottom; 0th column: right
+'exif-orientation-4' => 'Flipped vertically', // 0th row: bottom; 0th column: left
+'exif-orientation-5' => 'Rotated 90° CCW and flipped vertically', // 0th row: left; 0th column: top
+'exif-orientation-6' => 'Rotated 90° CW', // 0th row: right; 0th column: top
+'exif-orientation-7' => 'Rotated 90° CW and flipped vertically', // 0th row: right; 0th column: bottom
+'exif-orientation-8' => 'Rotated 90° CCW', // 0th row: left; 0th column: bottom
+
+'exif-planarconfiguration-1' => 'chunky format',
+'exif-planarconfiguration-2' => 'planar format',
+
+'exif-xyresolution-i' => '$1 dpi',
+'exif-xyresolution-c' => '$1 dpc',
+
+'exif-colorspace-1' => 'sRGB',
+'exif-colorspace-ffff.h' => 'FFFF.H',
+
+'exif-componentsconfiguration-0' => 'does not exist',
+'exif-componentsconfiguration-1' => 'Y',
+'exif-componentsconfiguration-2' => 'Cb',
+'exif-componentsconfiguration-3' => 'Cr',
+'exif-componentsconfiguration-4' => 'R',
+'exif-componentsconfiguration-5' => 'G',
+'exif-componentsconfiguration-6' => 'B',
+
+'exif-exposureprogram-0' => 'Not defined',
+'exif-exposureprogram-1' => 'Manual',
+'exif-exposureprogram-2' => 'Normal program',
+'exif-exposureprogram-3' => 'Aperture priority',
+'exif-exposureprogram-4' => 'Shutter priority',
+'exif-exposureprogram-5' => 'Creative program (biased toward depth of field)',
+'exif-exposureprogram-6' => 'Action program (biased toward fast shutter speed)',
+'exif-exposureprogram-7' => 'Portrait mode (for closeup photos with the background out of focus)',
+'exif-exposureprogram-8' => 'Landscape mode (for landscape photos with the background in focus)',
+
+'exif-subjectdistance-value' => '$1 metres',
+
+'exif-meteringmode-0' => 'Unknown',
+'exif-meteringmode-1' => 'Average',
+'exif-meteringmode-2' => 'CenterWeightedAverage',
+'exif-meteringmode-3' => 'Spot',
+'exif-meteringmode-4' => 'MultiSpot',
+'exif-meteringmode-5' => 'Pattern',
+'exif-meteringmode-6' => 'Partial',
+'exif-meteringmode-255' => 'Other',
+
+'exif-lightsource-0' => 'Unknown',
+'exif-lightsource-1' => 'Daylight',
+'exif-lightsource-2' => 'Fluorescent',
+'exif-lightsource-3' => 'Tungsten (incandescent light)',
+'exif-lightsource-4' => 'Flash',
+'exif-lightsource-9' => 'Fine weather',
+'exif-lightsource-10' => 'Clody weather',
+'exif-lightsource-11' => 'Shade',
+'exif-lightsource-12' => 'Daylight fluorescent (D 5700 – 7100K)',
+'exif-lightsource-13' => 'Day white fluorescent (N 4600 – 5400K)',
+'exif-lightsource-14' => 'Cool white fluorescent (W 3900 – 4500K)',
+'exif-lightsource-15' => 'White fluorescent (WW 3200 – 3700K)',
+'exif-lightsource-17' => 'Standard light A',
+'exif-lightsource-18' => 'Standard light B',
+'exif-lightsource-19' => 'Standard light C',
+'exif-lightsource-20' => 'D55',
+'exif-lightsource-21' => 'D65',
+'exif-lightsource-22' => 'D75',
+'exif-lightsource-23' => 'D50',
+'exif-lightsource-24' => 'ISO studio tungsten',
+'exif-lightsource-255' => 'Other light source',
+
+'exif-focalplaneresolutionunit-2' => 'inches',
+
+'exif-sensingmethod-1' => 'Undefined',
+'exif-sensingmethod-2' => 'One-chip color area sensor',
+'exif-sensingmethod-3' => 'Two-chip color area sensor',
+'exif-sensingmethod-4' => 'Three-chip color area sensor',
+'exif-sensingmethod-5' => 'Color sequential area sensor',
+'exif-sensingmethod-7' => 'Trilinear sensor',
+'exif-sensingmethod-8' => 'Color sequential linear sensor',
+
+'exif-filesource-3' => 'DSC',
+
+'exif-scenetype-1' => 'A directly photographed image',
+
+'exif-customrendered-0' => 'Normal process',
+'exif-customrendered-1' => 'Custom process',
+
+'exif-exposuremode-0' => 'Auto exposure',
+'exif-exposuremode-1' => 'Manual exposure',
+'exif-exposuremode-2' => 'Auto bracket',
+
+'exif-whitebalance-0' => 'Auto white balance',
+'exif-whitebalance-1' => 'Manual white balance',
+
+'exif-scenecapturetype-0' => 'Standard',
+'exif-scenecapturetype-1' => 'Landscape',
+'exif-scenecapturetype-2' => 'Portrait',
+'exif-scenecapturetype-3' => 'Night scene',
+
+'exif-gaincontrol-0' => 'None',
+'exif-gaincontrol-1' => 'Low gain up',
+'exif-gaincontrol-2' => 'High gain up',
+'exif-gaincontrol-3' => 'Low gain down',
+'exif-gaincontrol-4' => 'High gain down',
+
+'exif-contrast-0' => 'Normal',
+'exif-contrast-1' => 'Soft',
+'exif-contrast-2' => 'Hard',
+
+'exif-saturation-0' => 'Normal',
+'exif-saturation-1' => 'Low saturation',
+'exif-saturation-2' => 'High saturation',
+
+'exif-sharpness-0' => 'Normal',
+'exif-sharpness-1' => 'Soft',
+'exif-sharpness-2' => 'Hard',
+
+'exif-subjectdistancerange-0' => 'Unknown',
+'exif-subjectdistancerange-1' => 'Macro',
+'exif-subjectdistancerange-2' => 'Close view',
+'exif-subjectdistancerange-3' => 'Distant view',
+
+// Pseudotags used for GPSLatitudeRef and GPSDestLatitudeRef
+'exif-gpslatitude-n' => 'North latitude',
+'exif-gpslatitude-s' => 'South latitude',
+
+// Pseudotags used for GPSLongitudeRef and GPSDestLongitudeRef
+'exif-gpslongitude-e' => 'East longitude',
+'exif-gpslongitude-w' => 'West longitude',
+
+'exif-gpsstatus-a' => 'Measurement in progress',
+'exif-gpsstatus-v' => 'Measurement interoperability',
+
+'exif-gpsmeasuremode-2' => '2-dimensional measurement',
+'exif-gpsmeasuremode-3' => '3-dimensional measurement',
+
+// Pseudotags used for GPSSpeedRef and GPSDestDistanceRef
+'exif-gpsspeed-k' => 'Kilometres per hour',
+'exif-gpsspeed-m' => 'Miles per hour',
+'exif-gpsspeed-n' => 'Knots',
+
+// Pseudotags used for GPSTrackRef, GPSImgDirectionRef and GPSDestBearingRef
+'exif-gpsdirection-t' => 'True direction',
+'exif-gpsdirection-m' => 'Magnetic direction',
+
+# external editor support
+'edit-externally' => 'Edit this file using an external application',
+'edit-externally-help' => 'See the [http://meta.wikimedia.org/wiki/Help:External_editors setup instructions] for more information.',
+
+# 'all' in various places, this might be different for inflected languages
+'recentchangesall' => 'all',
+'imagelistall' => 'all',
+'watchlistall1' => 'all',
+'watchlistall2' => 'all',
+'namespacesall' => 'all',
+
+# E-mail address confirmation
+'confirmemail' => 'Confirm E-mail address',
+'confirmemail_text' => "This wiki requires that you validate your e-mail address
+before using e-mail features. Activate the button below to send a confirmation
+mail to your address. The mail will include a link containing a code; load the
+link in your browser to confirm that your e-mail address is valid.",
+'confirmemail_send' => 'Mail a confirmation code',
+'confirmemail_sent' => 'Confirmation e-mail sent.',
+'confirmemail_sendfailed' => 'Could not send confirmation mail. Check address for invalid characters.',
+'confirmemail_invalid' => 'Invalid confirmation code. The code may have expired.',
+'confirmemail_success' => 'Your e-mail address has been confirmed. You may now log in and enjoy the wiki.',
+'confirmemail_loggedin' => 'Your e-mail address has now been confirmed.',
+'confirmemail_error' => 'Something went wrong saving your confirmation.',
+
+'confirmemail_subject' => '{{SITENAME}} e-mail address confirmation',
+'confirmemail_body' => "Someone, probably you from IP address $1, has registered an
+account \"$2\" with this e-mail address on {{SITENAME}}.
+
+To confirm that this account really does belong to you and activate
+e-mail features on {{SITENAME}}, open this link in your browser:
+
+$3
+
+If this is *not* you, don't follow the link. This confirmation code
+will expire at $4.
+",
+
+# Inputbox extension, may be useful in other contexts as well
+'tryexact' => 'Try exact match',
+'searchfulltext' => 'Search full text',
+'createarticle' => 'Create article',
+
+# Scary transclusion
+'scarytranscludedisabled' => '[Interwiki transcluding is disabled]',
+'scarytranscludefailed' => '[Template fetch failed for $1; sorry]',
+'scarytranscludetoolong' => '[URL is too long; sorry]',
+
+# Trackbacks
+'trackbackbox' => "<div id='mw_trackbacks'>
+Trackbacks for this article:<br />
+$1
+</div>
+",
+'trackback' => "; $4$5 : [$2 $1]\n",
+'trackbackexcerpt' => "; $4$5 : [$2 $1]: <nowiki>$3</nowiki>\n",
+'trackbackremove' => ' ([$1 Delete])',
+'trackbacklink' => 'Trackback',
+'trackbackdeleteok' => 'The trackback was successfully deleted.',
+
+'unit-pixel' => 'px',
+
+'youhavenewmessagesmulti' => "You have new messages on $1",
+'newtalkseperator' => ',_',
+);
+
+/* a fake language converter */
+class fakeConverter {
+       var $mLang;
+       function fakeConverter($langobj) {$this->mLang = $langobj;}
+       function convert($t, $i) {return $t;}
+       function getVariants() { return array( $this->mLang->getCode() ); }
+       function getPreferredVariant() {return $this->mLang->getCode(); }
+       function findVariantLink(&$l, &$n) {}
+       function getExtraHashOptions() {return '';}
+       function getParsedTitle() {return '';}
+       function markNoConversion($text) {return $text;}
+       function convertCategoryKey( $key ) {return $key; }
+
+}
+
+#--------------------------------------------------------------------------
+# Internationalisation code
+#--------------------------------------------------------------------------
+
+class Language {
+       var $mConverter;
+       function Language() {
+
+               # Copies any missing values in the specified arrays from En to the current language
+               $fillin = array( 'wgSysopSpecialPages', 'wgValidSpecialPages', 'wgDeveloperSpecialPages' );
+               $name = get_class( $this );
+
+               if( strpos( $name, 'language' ) == 0){
+                       $lang = ucfirst( substr( $name, 8 ) );
+                       foreach( $fillin as $arrname ){
+                               $langver = "{$arrname}{$lang}";
+                               $enver = "{$arrname}En";
+                               if( ! isset( $GLOBALS[$langver] ) || ! isset( $GLOBALS[$enver] ))
+                                       continue;
+                               foreach($GLOBALS[$enver] as $spage => $text){
+                                       if( ! isset( $GLOBALS[$langver][$spage] ) )
+                                               $GLOBALS[$langver][$spage] = $text;
+                               }
+                       }
+               }
+               $this->mConverter = new fakeConverter($this);
+       }
+
+       /**
+        * Exports the default user options as defined in
+        * $wgDefaultUserOptionsEn, user preferences can override some of these
+        * depending on what's in (Local|Default)Settings.php and some defines.
+        *
+        * @return array
+        */
+       function getDefaultUserOptions() {
+               global $wgDefaultUserOptionsEn ;
+               return $wgDefaultUserOptionsEn ;
+       }
+
+       /**
+        * Exports $wgBookstoreListEn
+        * @return array
+        */
+       function getBookstoreList() {
+               global $wgBookstoreListEn ;
+               return $wgBookstoreListEn ;
+       }
+
+       /**
+        * @return array
+        */
+       function getNamespaces() {
+               global $wgNamespaceNamesEn;
+               return $wgNamespaceNamesEn;
+       }
+
+       /**
+        * A convenience function that returns the same thing as
+        * getNamespaces() except with the array values changed to ' '
+        * where it found '_', useful for producing output to be displayed
+        * e.g. in <select> forms.
+        *
+        * @return array
+        */
+       function getFormattedNamespaces() {
+               $ns = $this->getNamespaces();
+               foreach($ns as $k => $v) {
+                       $ns[$k] = strtr($v, '_', ' ');
+               }
+               return $ns;
+       }
+
+       /**
+        * Get a namespace value by key
+        * <code>
+        * $mw_ns = $wgContLang->getNsText( NS_MEDIAWIKI );
+        * echo $mw_ns; // prints 'MediaWiki'
+        * </code>
+        *
+        * @param int $index the array key of the namespace to return
+        * @return mixed, string if the namespace value exists, otherwise false
+        */
+       function getNsText( $index ) {
+               $ns = $this->getNamespaces();
+               return isset( $ns[$index] ) ? $ns[$index] : false;
+       }
+
+       /**
+        * A convenience function that returns the same thing as
+        * getNsText() except with '_' changed to ' ', useful for
+        * producing output.
+        *
+        * @return array
+        */
+       function getFormattedNsText( $index ) {
+               $ns = $this->getNsText( $index );
+               return strtr($ns, '_', ' ');
+       }
+
+       /**
+        * Get a namespace key by value, case insensetive.
+        *
+        * @param string $text
+        * @return mixed An integer if $text is a valid value otherwise false
+        */
+       function getNsIndex( $text ) {
+               $ns = $this->getNamespaces();
+
+               foreach ( $ns as $i => $n ) {
+                       if ( strcasecmp( $n, $text ) == 0)
+                               return $i;
+               }
+               return false;
+       }
+
+       /**
+        * short names for language variants used for language conversion links.
+        *
+        * @param string $code
+        * @return string
+        */
+       function getVariantname( $code ) {
+               return wfMsg( "variantname-$code" );
+       }
+
+       function specialPage( $name ) {
+               return $this->getNsText(NS_SPECIAL) . ':' . $name;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsEn;
+               return $wgQuickbarSettingsEn;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesEn;
+               return $wgSkinNamesEn;
+       }
+
+       function getMathNames() {
+               global $wgMathNamesEn;
+               return $wgMathNamesEn;
+       }
+
+       function getDateFormats() {
+               global $wgDateFormatsEn;
+               return $wgDateFormatsEn;
+       }
+
+       function getValidationTypes() {
+               global $wgValidationTypesEn;
+               return $wgValidationTypesEn;
+       }
+
+       function getUserToggles() {
+               global $wgUserTogglesEn;
+               return $wgUserTogglesEn;
+       }
+
+       function getUserToggle( $tog ) {
+               return wfMsg( "tog-$tog" );
+       }
+
+       function getLanguageNames() {
+               global $wgLanguageNamesEn;
+               return $wgLanguageNamesEn;
+       }
+
+       function getLanguageName( $code ) {
+               global $wgLanguageNamesEn;
+               if ( ! array_key_exists( $code, $wgLanguageNamesEn ) ) {
+                       return '';
+               }
+               return $wgLanguageNamesEn[$code];
+       }
+
+       function getMonthName( $key ) {
+               global $wgMonthNamesEn, $wgContLang;
+               // see who called us and use the correct message function
+               if( get_class( $wgContLang->getLangObj() ) == get_class( $this ) )
+                       return wfMsgForContent($wgMonthNamesEn[$key-1]);
+               else
+                       return wfMsg($wgMonthNamesEn[$key-1]);
+       }
+
+       /* by default we just return base form */
+       function getMonthNameGen( $key ) {
+               return $this->getMonthName( $key );
+       }
+
+       function getMonthAbbreviation( $key ) {
+               global $wgMonthAbbreviationsEn, $wgContLang;
+               // see who called us and use the correct message function
+               if( get_class( $wgContLang->getLangObj() ) == get_class( $this ) )
+                       return wfMsgForContent(@$wgMonthAbbreviationsEn[$key-1]);
+               else
+                       return wfMsg(@$wgMonthAbbreviationsEn[$key-1]);
+       }
+
+       function getWeekdayName( $key ) {
+               global $wgWeekdayNamesEn, $wgContLang;
+               // see who called us and use the correct message function
+               if( get_class( $wgContLang->getLangObj() ) == get_class( $this ) )
+                       return wfMsgForContent($wgWeekdayNamesEn[$key-1]);
+               else
+                       return wfMsg($wgWeekdayNamesEn[$key-1]);
+       }
+
+       /**
+        * Used by date() and time() to adjust the time output.
+        * @access public
+        * @param int   $ts the time in date('YmdHis') format
+        * @param mixed $tz adjust the time by this amount (default false)
+        * @return int
+        */
+       function userAdjust( $ts, $tz = false ) {
+               global $wgUser, $wgLocalTZoffset;
+
+               if (!$tz) {
+                       $tz = $wgUser->getOption( 'timecorrection' );
+               }
+
+               if ( $tz === '' ) {
+                       $hrDiff = isset( $wgLocalTZoffset ) ? $wgLocalTZoffset : 0;
+                       $minDiff = 0;
+               } elseif ( strpos( $tz, ':' ) !== false ) {
+                       $tzArray = explode( ':', $tz );
+                       $hrDiff = intval($tzArray[0]);
+                       $minDiff = intval($hrDiff < 0 ? -$tzArray[1] : $tzArray[1]);
+               } else {
+                       $hrDiff = intval( $tz );
+               }
+               if ( 0 == $hrDiff && 0 == $minDiff ) { return $ts; }
+
+               $t = mktime( (
+                 (int)substr( $ts, 8, 2) ) + $hrDiff, # Hours
+                 (int)substr( $ts, 10, 2 ) + $minDiff, # Minutes
+                 (int)substr( $ts, 12, 2 ), # Seconds
+                 (int)substr( $ts, 4, 2 ), # Month
+                 (int)substr( $ts, 6, 2 ), # Day
+                 (int)substr( $ts, 0, 4 ) ); #Year
+               return date( 'YmdHis', $t );
+       }
+
+       /**
+        * This is meant to be used by time(), date(), and timeanddate() to get
+        * the date preference they're supposed to use, it should be used in
+        * all children.
+        *
+        *<code>
+        * function timeanddate([...], $format = true) {
+        *      $datePreference = $this->dateFormat($format);
+        * [...]
+        *</code>
+        *
+        * @param bool $usePrefs: if false, the site/language default is used
+        * @return string
+        */
+       function dateFormat( $usePrefs = true ) {
+               global $wgUser, $wgAmericanDates;
+
+               if( $usePrefs ) {
+                       $datePreference = $wgUser->getOption( 'date' );
+               } else {
+                       $options = $this->getDefaultUserOptions();
+                       $datePreference = (string)$options['date'];
+               }
+
+               if( $datePreference == MW_DATE_DEFAULT || $datePreference == '' ) {
+                       return $wgAmericanDates ? MW_DATE_MDY : MW_DATE_DMY;
+               }
+               return $datePreference;
+       }
+
+       /**
+        * @access public
+        * @param mixed  $ts the time format which needs to be turned into a
+        *               date('YmdHis') format with wfTimestamp(TS_MW,$ts)
+        * @param bool   $adj whether to adjust the time output according to the
+        *               user configured offset ($timecorrection)
+        * @param bool   $format true to use user's date format preference
+        * @param string $timecorrection the time offset as returned by
+        *               validateTimeZone() in Special:Preferences
+        * @return string
+        */
+       function date( $ts, $adj = false, $format = true, $timecorrection = false ) {
+               global $wgUser;
+
+               if ( $adj ) { $ts = $this->userAdjust( $ts, $timecorrection ); }
+
+               $datePreference = $this->dateFormat( $format );
+
+               $month = $this->getMonthName( substr( $ts, 4, 2 ) );
+               $day = $this->formatNum( 0 + substr( $ts, 6, 2 ) );
+               $year = $this->formatNum( substr( $ts, 0, 4 ), true );
+
+               switch( $datePreference ) {
+                       case MW_DATE_DMY: return "$day $month $year";
+                       case MW_DATE_YMD: return "$year $month $day";
+                       case MW_DATE_ISO: return substr($ts, 0, 4). '-' . substr($ts, 4, 2). '-' .substr($ts, 6, 2);
+                       default: return "$month $day, $year";
+               }
+       }
+
+       /**
+       * @access public
+       * @param mixed  $ts the time format which needs to be turned into a
+       *               date('YmdHis') format with wfTimestamp(TS_MW,$ts)
+       * @param bool   $adj whether to adjust the time output according to the
+       *               user configured offset ($timecorrection)
+       * @param bool   $format true to use user's date format preference
+       * @param string $timecorrection the time offset as returned by
+       *               validateTimeZone() in Special:Preferences
+       * @return string
+       */
+       function time( $ts, $adj = false, $format = true, $timecorrection = false ) {
+               global $wgUser;
+
+               if ( $adj ) { $ts = $this->userAdjust( $ts, $timecorrection ); }
+               $datePreference = $this->dateFormat( $format );
+
+               $t = substr( $ts, 8, 2 ) . ':' . substr( $ts, 10, 2 );
+
+               if ( $datePreference == MW_DATE_ISO ) {
+                       $t .= ':' . substr( $ts, 12, 2 );
+               }
+               return $this->formatNum( $t );
+       }
+
+       /**
+       * @access public
+       * @param mixed  $ts the time format which needs to be turned into a
+       *               date('YmdHis') format with wfTimestamp(TS_MW,$ts)
+       * @param bool   $adj whether to adjust the time output according to the
+       *               user configured offset ($timecorrection)
+       * @param bool   $format true to use user's date format preference
+       * @param string $timecorrection the time offset as returned by
+       *               validateTimeZone() in Special:Preferences
+       * @return string
+       */
+       function timeanddate( $ts, $adj = false, $format = true, $timecorrection = false) {
+               global $wgUser;
+
+               $datePreference = $this->dateFormat($format);
+               switch ( $datePreference ) {
+                       case MW_DATE_ISO: return $this->date( $ts, $adj, $format, $timecorrection ) . ' ' .
+                               $this->time( $ts, $adj, $format, $timecorrection );
+                       default: return $this->time( $ts, $adj, $format, $timecorrection ) . ', ' .
+                               $this->date( $ts, $adj, $format, $timecorrection );
+               }
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesEn;
+               return @$wgAllMessagesEn[$key];
+       }
+
+       function getAllMessages() {
+               global $wgAllMessagesEn;
+               return $wgAllMessagesEn;
+       }
+
+       function iconv( $in, $out, $string ) {
+               # For most languages, this is a wrapper for iconv
+               return iconv( $in, $out, $string );
+       }
+
+       function ucfirst( $string ) {
+               # For most languages, this is a wrapper for ucfirst()
+               return ucfirst( $string );
+       }
+
+       function lcfirst( $s ) {
+               return strtolower( $s{0} ). substr( $s, 1 );
+       }
+
+       function checkTitleEncoding( $s ) {
+               global $wgInputEncoding;
+
+               # Check for UTF-8 URLs; Internet Explorer produces these if you
+               # type non-ASCII chars in the URL bar or follow unescaped links.
+               $ishigh = preg_match( '/[\x80-\xff]/', $s);
+               $isutf = ($ishigh ? preg_match( '/^([\x00-\x7f]|[\xc0-\xdf][\x80-\xbf]|' .
+                        '[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xf7][\x80-\xbf]{3})+$/', $s ) : true );
+
+               if( ($wgInputEncoding != 'utf-8') and $ishigh and $isutf )
+                       return @iconv( 'UTF-8', $wgInputEncoding, $s );
+
+               if( ($wgInputEncoding == 'utf-8') and $ishigh and !$isutf )
+                       return utf8_encode( $s );
+
+               # Other languages can safely leave this function, or replace
+               # it with one to detect and convert another legacy encoding.
+               return $s;
+       }
+
+       /**
+        * Some languages have special punctuation to strip out
+        * or characters which need to be converted for MySQL's
+        * indexing to grok it correctly. Make such changes here.
+        *
+        * @param string $in
+        * @return string
+        */
+       function stripForSearch( $in ) {
+               return strtolower( $in );
+       }
+
+       function convertForSearchResult( $termsArray ) {
+               # some languages, e.g. Chinese, need to do a conversion
+               # in order for search results to be displayed correctly
+               return $termsArray;
+       }
+
+       /**
+        * Get the first character of a string. In ASCII, return
+        * first byte of the string. UTF8 and others have to
+        * overload this.
+        *
+        * @param string $s
+        * @return string
+        */
+       function firstChar( $s ) {
+               return $s[0];
+       }
+
+       function initEncoding() {
+               # Some languages may have an alternate char encoding option
+               # (Esperanto X-coding, Japanese furigana conversion, etc)
+               # If this language is used as the primary content language,
+               # an override to the defaults can be set here on startup.
+               #global $wgInputEncoding, $wgOutputEncoding, $wgEditEncoding;
+       }
+
+       function setAltEncoding() {
+               # Some languages may have an alternate char encoding option
+               # (Esperanto X-coding, Japanese furigana conversion, etc)
+               # If 'altencoding' is checked in user prefs, this gives a
+               # chance to swap out the default encoding settings.
+               #global $wgInputEncoding, $wgOutputEncoding, $wgEditEncoding;
+       }
+
+       function recodeForEdit( $s ) {
+               # For some languages we'll want to explicitly specify
+               # which characters make it into the edit box raw
+               # or are converted in some way or another.
+               # Note that if wgOutputEncoding is different from
+               # wgInputEncoding, this text will be further converted
+               # to wgOutputEncoding.
+               global $wgInputEncoding, $wgEditEncoding;
+               if( $wgEditEncoding == '' or
+                 $wgEditEncoding == $wgInputEncoding ) {
+                       return $s;
+               } else {
+                       return $this->iconv( $wgInputEncoding, $wgEditEncoding, $s );
+               }
+       }
+
+       function recodeInput( $s ) {
+               # Take the previous into account.
+               global $wgInputEncoding, $wgOutputEncoding, $wgEditEncoding;
+               if($wgEditEncoding != "") {
+                       $enc = $wgEditEncoding;
+               } else {
+                       $enc = $wgOutputEncoding;
+               }
+               if( $enc == $wgInputEncoding ) {
+                       return $s;
+               } else {
+                       return $this->iconv( $enc, $wgInputEncoding, $s );
+               }
+       }
+
+       /**
+        * For right-to-left language support
+        *
+        * @return bool
+        */
+       function isRTL() { return false; }
+
+       /**
+        * To allow "foo[[bar]]" to extend the link over the whole word "foobar"
+        *
+        * @return bool
+        */
+       function linkPrefixExtension() { return false; }
+
+
+       function &getMagicWords() {
+               global $wgMagicWordsEn;
+               return $wgMagicWordsEn;
+       }
+
+       # Fill a MagicWord object with data from here
+       function getMagic( &$mw ) {
+               $raw = $this->getMagicWords();
+               if( !isset( $raw[$mw->mId] ) ) {
+                       # Fall back to English if local list is incomplete
+                       $raw =& Language::getMagicWords();
+               }
+               $rawEntry = $raw[$mw->mId];
+               $mw->mCaseSensitive = $rawEntry[0];
+               $mw->mSynonyms = array_slice( $rawEntry, 1 );
+       }
+
+       /**
+        * Italic is unsuitable for some languages
+        *
+        * @access public
+        *
+        * @param string $text The text to be emphasized.
+        * @return string
+        */
+       function emphasize( $text ) {
+               return "<em>$text</em>";
+       }
+
+       /**
+        * This function enables formatting of numbers, it should only come
+        * into effect when the $wgTranslateNumerals variable is TRUE.
+        *
+        * Normally we output all numbers in plain en_US style, that is
+        * 293,291.235 for twohundredninetythreethousand-twohundredninetyone
+        * point twohundredthirtyfive. However this is not sutable for all
+        * languages, some such as Pakaran want ੨੯੩,੨੯੫.੨੩੫ and others such as
+        * Icelandic just want to use commas instead of dots, and dots instead
+        * of commas like "293.291,235".
+        *
+        * An example of this function being called:
+        * <code>
+        * wfMsg( 'message', $wgLang->formatNum( $num ) )
+        * </code>
+        *
+        * See LanguageGu.php for the Gujarati implementation and
+        * LanguageIs.php for the , => . and . => , implementation.
+        *
+        * @todo check if it's viable to use localeconv() for the decimal
+        *       seperator thing.
+        * @access public
+        * @param mixed $number the string to be formatted, should be an integer or
+        *        a floating point number.
+        * @param bool $year are we being passed a year? (turns off commafication)
+        * @return mixed whatever we're fed if it's a year, a string otherwise.
+        */
+       function formatNum( $number, $year = false ) {
+               return $year ? $number : $this->commafy($number);
+       }
+
+       /**
+        * Adds commas to a given number
+        *
+        * @param mixed $_
+        * @return string
+        */
+       function commafy($_) {
+               return strrev((string)preg_replace('/(\d{3})(?=\d)(?!\d*\.)/','$1,',strrev($_)));
+       }
+
+       /**
+        * For the credit list in includes/Credits.php (action=credits)
+        *
+        * @param array $l
+        * @return string
+        */
+       function listToText( $l ) {
+               $s = '';
+               $m = count($l) - 1;
+               for ($i = $m; $i >= 0; $i--) {
+                       if ($i == $m) {
+                               $s = $l[$i];
+                       } else if ($i == $m - 1) {
+                               $s = $l[$i] . ' ' . $this->getMessage('and') . ' ' . $s;
+                       } else {
+                               $s = $l[$i] . ', ' . $s;
+                       }
+               }
+               return $s;
+       }
+
+       # Crop a string from the beginning or end to a certain number of bytes.
+       # (Bytes are used because our storage has limited byte lengths for some
+       # columns in the database.) Multibyte charsets will need to make sure that
+       # only whole characters are included!
+       #
+       # $length does not include the optional ellipsis.
+       # If $length is negative, snip from the beginning
+       function truncate( $string, $length, $ellipsis = '' ) {
+               if( $length == 0 ) {
+                       return $ellipsis;
+               }
+               if ( strlen( $string ) <= abs( $length ) ) {
+                       return $string;
+               }
+               if( $length > 0 ) {
+                       $string = substr( $string, 0, $length );
+                       return $string . $ellipsis;
+               } else {
+                       $string = substr( $string, $length );
+                       return $ellipsis . $string;
+               }
+       }
+
+       /**
+        * Grammatical transformations, needed for inflected languages
+        * Invoked by putting {{grammar:case|word}} in a message
+        *
+        * @param string $word
+        * @param string $case
+        * @return string
+        */
+       function convertGrammar( $word, $case ) {
+               return $word;
+       }
+
+       /**
+        * languages like Chinese need to be segmented in order for the diff
+        * to be of any use
+        *
+        * @param string $text
+        * @return string
+        */
+       function segmentForDiff( $text ) {
+               return $text;
+       }
+
+       /**
+        * and unsegment to show the result
+        *
+        * @param string $text
+        * @return string
+        */
+       function unsegmentForDiff( $text ) {
+               return $text;
+       }
+
+       # convert text to different variants of a language.
+       function convert( $text, $isTitle = false) {
+               return $this->mConverter->convert($text, $isTitle);
+       }
+
+       /**
+        * Perform output conversion on a string, and encode for safe HTML output.
+        * @param string $text
+        * @param bool $isTitle -- wtf?
+        * @return string
+        * @todo this should get integrated somewhere sane
+        */
+       function convertHtml( $text, $isTitle = false ) {
+               return htmlspecialchars( $this->convert( $text, $isTitle ) );
+       }
+
+       function convertCategoryKey( $key ) {
+               return $this->mConverter->convertCategoryKey( $key );
+       }
+
+       /**
+        * get the list of variants supported by this langauge
+        * see sample implementation in LanguageZh.php
+        *
+        * @return array an array of language codes
+        */
+       function getVariants() {
+               return $this->mConverter->getVariants();
+       }
+
+
+       function getPreferredVariant() {
+               return $this->mConverter->getPreferredVariant();
+       }
+
+       /**
+        * if a language supports multiple variants, it is
+        * possible that non-existing link in one variant
+        * actually exists in another variant. this function
+        * tries to find it. See e.g. LanguageZh.php
+        *
+        * @param string $link the name of the link
+        * @param mixed $nt the title object of the link
+        * @return null the input parameters may be modified upon return
+        */
+       function findVariantLink( &$link, &$nt ) {
+               $this->mConverter->findVariantLink($link, $nt);
+       }
+
+       /**
+        * returns language specific options used by User::getPageRenderHash()
+        * for example, the preferred language variant
+        *
+        * @return string
+        * @access public
+        */
+       function getExtraHashOptions() {
+               return $this->mConverter->getExtraHashOptions();
+       }
+
+       /**
+        * for languages that support multiple variants, the title of an
+        * article may be displayed differently in different variants. this
+        * function returns the apporiate title defined in the body of the article.
+        *
+        * @return string
+        */
+       function getParsedTitle() {
+               return $this->mConverter->getParsedTitle();
+       }
+
+       /**
+        * Enclose a string with the "no conversion" tag. This is used by
+        * various functions in the Parser
+        *
+        * @param string $text text to be tagged for no conversion
+        * @return string the tagged text
+       */
+       function markNoConversion( $text ) {
+               return $this->mConverter->markNoConversion( $text );
+       }
+
+       /**
+        * A regular expression to match legal word-trailing characters
+        * which should be merged onto a link of the form [[foo]]bar.
+        *
+        * @return string
+        * @access public
+        */
+       function linkTrail() {
+               return $this->getMessage( 'linktrail' );
+       }
+
+       function getLangObj() {
+               return $this;
+       }
+
+       /**
+        * Get the RFC 3066 code for this language object
+        */
+       function getCode() {
+               return str_replace( '_', '-', strtolower( substr( get_class( $this ), 8 ) ) );
+       }
+
+
+}
+
+# This should fail gracefully if there's not a localization available
+wfSuppressWarnings();
+include_once( 'Language' . str_replace( '-', '_', ucfirst( $wgLanguageCode ) ) . '.php' );
+wfRestoreWarnings();
+
+}
+?>
diff --git a/languages/LanguageAf.php b/languages/LanguageAf.php
new file mode 100644 (file)
index 0000000..3b434ad
--- /dev/null
@@ -0,0 +1,782 @@
+<?php
+/** Afrikaans (Afrikaans)
+  *
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+require_once( 'LanguageUtf8.php' );
+
+/* private */ $wgNamespaceNamesAf = array(
+       NS_MEDIA                => "Media",
+       NS_SPECIAL              => "Spesiaal",
+       NS_MAIN                 => "",
+       NS_TALK                 => "Bespreking",
+       NS_USER                 => "Gebruiker",
+       NS_USER_TALK            => "Gebruikerbespreking",
+       NS_PROJECT              => $wgMetaNamespace,
+       NS_PROJECT_TALK         => $wgMetaNamespace."bespreking",
+       NS_IMAGE                => "Beeld",
+       NS_IMAGE_TALK           => "Beeldbespreking",
+       NS_MEDIAWIKI            => "MediaWiki",
+       NS_MEDIAWIKI_TALK       => "MediaWikibespreking",
+       NS_TEMPLATE             => 'Sjabloon',
+       NS_TEMPLATE_TALK        => 'Sjabloonbespreking',
+       NS_HELP                 => 'Hulp',
+       NS_HELP_TALK            => 'Hulpbespreking',
+       NS_CATEGORY             => 'Kategorie',
+       NS_CATEGORY_TALK        => 'Kategoriebespreking'
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgQuickbarSettingsAf = array(
+       "Geen.", "Links vas.", "Regs vas.", "Dryf links."
+);
+
+/* private */ $wgSkinNamesAf = array(
+       'standard' => "Standaard",
+       'nostalgia' => "Nostalgie",
+       'cologneblue' => "Keulen blou",
+) + $wgSkinNamesEn;
+
+/* private */ $wgAllMessagesAf = array(
+# User Toggles
+
+"tog-underline" => "Onderstreep skakels.",
+"tog-highlightbroken" => "Wys gebroke skakels <a href=\"\" class=\"new\">so</a> of so<a href=\"\" class=\"internal\">?</a>).",
+"tog-justify"  => "Justeer paragrawe.",
+"tog-hideminor" => "Moenie klein wysigings in die nuwe wysigingslys wys nie.",
+"tog-usenewrc" => "Verbeterde nuwe wysigingslys (vir moderne blaaiers).",
+"tog-numberheadings" => "Automatiese nommer opskrifte.",
+"tog-showtoolbar" => "Show edit toolbar",
+"tog-rememberpassword" => "Onthou wagwoord oor sessies.",
+"tog-editwidth" => "Wysigingsboks met volle wydte.",
+"tog-editondblclick" => "Wysig blaaie met dubbelkliek (JavaScript).",
+"tog-watchdefault" => "Lys nuwe en gewysigde bladsye.",
+"tog-minordefault" => "Merk alle wysigings automaties as klein by verstek.",
+"tog-previewontop" => "Wys voorskou bo wysigingsboks.",
+
+# Dates
+'sunday' => 'Sondag',
+'monday' => 'Maandag',
+'tuesday' => 'Dinsdag',
+'wednesday' => 'Woensdag',
+'thursday' => 'Donderdag',
+'friday' => 'Vrydag',
+'saturday' => 'Saterdag',
+'january' => 'Januarie',
+'february' => 'Februarie',
+'march' => 'Maart',
+'april' => 'April',
+'may_long' => 'Mei',
+'june' => 'Junie',
+'july' => 'Julie',
+'august' => 'Augustus',
+'september' => 'September',
+'october' => 'Oktober',
+'november' => 'November',
+'december' => 'Desember',
+'jan' => '01',
+'feb' => '02',
+'mar' => '03',
+'apr' => '04',
+'may' => '05',
+'jun' => '06',
+'jul' => '07',
+'aug' => '08',
+'sep' => '09',
+'oct' => '10',
+'nov' => '11',
+'dec' => '12',
+
+
+# Bits of text used by many pages:
+#
+"linktrail"            => "/^([a-z]+)(.*)\$/sD",
+"mainpage"             => "Tuisblad",
+"about"                        => "Omtrent",
+"aboutsite"      => "Inligting oor {{ns:4}}",
+"aboutpage"            => "{{ns:4}}:Omtrent",
+"help"                 => "Help",
+"helppage"             => "{{ns:4}}:Hulp",
+"bugreports"   => "Foutrapporte",
+"bugreportspage" => "{{ns:4}}:FoutRapporte",
+"faq"                  => "Gewilde vrae",
+"faqpage"              => "{{ns:4}}:GewildeVrae",
+"edithelp"             => "Wysighulp",
+"edithelppage" => "{{ns:4}}:Hoe_word_'n_bladsy_gewysig",
+"cancel"               => "Kanselleer",
+"qbfind"               => "Vind",
+"qbbrowse"             => "Snuffel",
+"qbedit"               => "Wysig",
+"qbpageoptions" => "Bladsy opsies",
+"qbpageinfo"   => "Bladsy inligting",
+"qbmyoptions"  => "My opsies",
+"mypage"               => "My bladsy",
+"mytalk"               => "My besprekings",
+"currentevents" => "Huidige gebeure",
+"errorpagetitle" => "Fout",
+"returnto"             => "Keer terug na $1.",
+"tagline"              => "Van {{SITENAME}} &#8212; die gratis ensiklopedie.",
+"whatlinkshere"        => "Bladsye wat hierheen skakel",
+"help"                 => "Hulp",
+"search"               => "Soek",
+"go"           => "Wys",
+"history"              => "Ouer weergawes",
+"printableversion" => "Drukbare weergawe",
+"editthispage" => "Wysig hierdie bladsy",
+"deletethispage" => "Skrap bladsy",
+"protectthispage" => "Beskerm hierdie bladsy",
+"unprotectthispage" => "Laat toe dat bladsy gewysig word",
+"newpage" => "Nuwe bladsy",
+"talkpage"             => "Bespreek hierdie bladsy",
+"articlepage"  => "Lees artikel",
+"subjectpage"  => "Lees onderwerp", # For compatibility
+"userpage" => "Lees gebruikersbladsy",
+"wikipediapage" => "Lees metabladsy",
+"imagepage" =>         "Lees bladsy oor prent",
+"viewtalkpage" => "Lees bespreking",
+"otherlanguages" => "Ander tale",
+"redirectedfrom" => "(Van $1 aangestuur.)",
+"lastmodified" => "Laaste wysiging op $1.",
+"viewcount"            => "Hierdie bladsy is al $1 keer aangevra.",
+"printsubtitle" => "(Van {{SERVER}})",
+"protectedpage" => "Beskermde bladsy",
+"administrators" => "{{ns:4}}:Administreerders",
+"sysoptitle"   => "Sisopregte verlang",
+
+
+"sysoptext"            => "Die wysiging waarvoor jy gevra het kan slegs deur iemand wat \"sisop\"regte het, gedoen word. Lees $1.",
+"developertitle" => "Ontwerperregte verlang",
+"developertext"        => "Die wysiging waarvoor jy gevra het kan slegs deur iemand wat \"progammeerder\"regte het, gedoen word. Lees $1.",
+"nbytes"               => "$1 grepe",
+"go"                   => "Doen",
+"ok"                   => "Aanvaar", #fixMe
+"sitetitle"            => "{{SITENAME}}",
+"sitesubtitle" => "Die gratis ensiklopedie", #fixme
+"retrievedfrom" => "Ontsluit van \"$1\"",
+"newmessages" => "Jy het $1.",
+"newmessageslink" => "nuwe boodskappe",
+
+# Main script and global functions
+#
+"nosuchaction" => "Ongeldige aksie",
+"nosuchactiontext" => "Onbekende aksie deur die adres gespesifeer",
+"nosuchspecialpage" => "Ongeldige spesiale bladsy",
+"nospecialpagetext" => "Ongeldige spesiale bladsy gespesifeer.",
+
+# General errors
+#
+"error"                        => "Fout",
+"databaseerror" => "Databasisfout",
+"dberrortext"  => "Sintaksisfout in databasisnavraag.
+Die laaste navraag was:
+<blockquote><tt>$1</tt></blockquote>
+van funksie \"<tt>$2</tt>\".
+MySQL foutboodskap \"<tt>$3: $4</tt>\".",
+"noconnect"            => "Kon nie met databasis op $1 konnekteer nie",
+"nodb"                 => "Kon nie databasis $1 selekteer nie",
+"readonly"             => "Databasis gesluit",
+"enterlockreason" => "Rede vir die sluiting,
+en beraming van wanneer ontsluiting sal plaas vind",
+"readonlytext" => "Die {{SITENAME}} databasis is tans gesluit vir nuwe
+artikelwysigings, waarskynlik vir roetine databasisonderhoud,
+waarna dit terug sal wees na normaal.
+Die administreerder wat dit gesluit het se verduideliking:
+<p>$1",
+"missingarticle" => "Die databasis het nie die teks van die veronderstelde bladsy \"$1\" gekry nie.
+Nie databasisfout nie, moontlik sagtewarefout.
+Raporteer die adres asseblief aan enige administrateur.",
+"internalerror" => "Interne fout",
+"filecopyerror" => "Kon nie lêer van \"$1\" na \"$2\" kopieer nie.",
+"filerenameerror" => "Kon nie lêernaam van \"$1\" na \"$2\" wysig nie.",
+"filedeleteerror" => "Kon nie lêer \"$1\" skrap nie.",
+"filenotfound" => "Kon nie lêer \"$1\" vind nie.",
+"unexpected"   => "Onverwagte waarde: \"$1\"=\"$2\".",
+"formerror"            => "Fout: kon vorm nie stuur nie",
+"badarticleerror" => "Die aksie kon nie op hierdie bladsy uitgevoer word nie.",
+"cannotdelete" => "Kon nie die bladsy of prent skrap nie, iemand anders het dit miskien reeds geskrap.",
+"badtitle"             => "Ongeldige titel",
+"badtitletext" => "Die bladsytitel waarvoor gevra is, is ongeldig, leeg, of
+'n verkeerd geskakelde tussen-taal of tussen-wiki titel.",
+"perfdisabled" => "Hierdie funksie is afgeskakel tydens spitstoegangsure vir verrigtingsredes, probeer weer tussen 02:00z en 14:00z (Universeel Gekoördineerde Tyd - UGT).",
+
+# Login and logout pages
+#
+"logouttitle"  => "Teken uit",
+"logouttext"   => "Jy is nou uitgeteken, en kan aanhou om
+{{SITENAME}} anoniem te gebruik; of jy kan inteken as dieselfde of 'n ander gebruiker.\n",
+
+"welcomecreation" => "<h2>Welkom, $1.</h2><p>Jou rekening is geskep;
+moenie vergeet om jou persoonlike voorkeure te stel nie.",
+
+"loginpagetitle" => "Teken in",
+"yourname"             => "Jou gebruikersnaam",
+"yourpassword" => "Jou wagwoord",
+"yourpasswordagain" => "Tik weer jou wagwoord in",
+"newusersonly" => " (slegs nuwe gebruikers)",
+"remembermypassword" => "Onthou my wagwoord oor sessies.",
+"loginproblem" => "<b>Daar was probleme met jou intekening.</b><br />Probeer weer.",
+"alreadyloggedin" => "<strong>Gebruiker $1, jy is reeds ingeteken.</strong><br />\n",
+
+"login"                        => "Teken in",
+"userlogin"            => "Teken in",
+"logout"               => "Teken uit",
+"userlogout"   => "Teken uit",
+"createaccount"        => "Kies nuwe wagwoord",
+"badretype"            => "Die wagwoorde wat jy ingetik het, is nie dieselfde nie.",
+"userexists"   => "Die gebruikersnaam wat jy gebruik het, is alreeds gebruik. Kies asseblief 'n ander gebruikersnaam.",
+"youremail"            => "Jou e-pos",
+"yournick"             => "Jou bynaam (vir stempel)",
+"emailforlost" => "Indien jy jou wagwoord vergeet het, kan jy 'n nuwe wagwoord na jou e-pos adres laat stuur.",
+"loginerror"   => "Intekenfout",
+"noname"               => "Ongeldige gebruikersnaam.",
+"loginsuccesstitle" => "Suksesvolle intekening",
+"loginsuccess" => "Jy is ingeteken by {{SITENAME}} as \"$1\".",
+"nosuchuser"   => "Daar is geen \"$1\" gebruikersnaam nie.
+Maak seker dit is reg gespel, of gebruik die vorm hier onder om 'n nuwe rekening te skep.",
+"wrongpassword"        => "Ongeldige wagwoord, probeer weer.",
+"mailmypassword" => "Stuur my wagwword na my e-pos adres.",
+"passwordremindertitle" => "Wagwoordwenk van {{SITENAME}}",
+"passwordremindertext" => "Iemand (waarskynlik jy, van IP-adres $1)
+het gevra dat ons vir jou 'n nuwe {{SITENAME}} wagwoord stuur.
+Die wagwoord vir gebruiker \"$2\" is nou \"$3\".
+Teken asseblief in en verander jou wagwoord.",
+"noemail"              => "Daar is geen e-pos adres vir gebruiker \"$1\" nie.",
+"passwordsent" => "Nuwe wagwoord gestuur na e-posadres vir \"$1\".
+Teken asseblief in na jy dit ontvang het.",
+
+# Edit pages
+#
+"summary"              => "Opsomming",
+"minoredit"            => "Klein wysiging",
+"watchthis"            => "Hou bladsy dop",
+"savearticle"  => "Stoor bladsy",
+"preview"              => "Voorskou",
+"showpreview"  => "Wys voorskou",
+"blockedtitle" => "Gebruiker is geblokkeer",
+"blockedtext"  => "Jou gebruikersnaam of IP-adres is deur $1 geblokkeer:
+<br />''$2''<p>Jy mag $1 of een van die ander [[{{ns:4}}:administreerders|administreerders]] kontak
+om dit te bespreek.",
+"newarticle"   => "(Nuut)",
+"newarticletext" =>
+"Die bladsy waarna geskakel is, bestaan nie.
+Om 'n nuwe bladsy te skep, tik in die invoerboks hier onder. Lees die [[{{ns:4}}:Help|hulp bladsy]]
+vir meer inligting.
+Indien jy per ongeluk hier is, gebruik jou blaaier se '''terug''' knop.",
+"anontalkpagetext" => "---- ''Dit is die besprekingsbladsy vir 'n anonieme gebruiker wat nie 'n rekening geskep het nie. Ons moet dus hul [[IP-adres]] gebruik om hulle te identifiseer. So 'n IP-adres kan deur verskeie gebruikers gedeel word. Indien jy 'n anonieme gebruiker is wat voel dat oneerbiedige komentaar aan jou gerig is, [[Special:Userlogin|skep 'n rekening of teken in]] om verwarring te voorkom met ander anonieme gebruikers.'' ",
+"noarticletext" => "(Daar is tans geen inligting vir hierdie artikel nie.)",
+"updated"              => "(Gewysig)",
+"note"                 => "<strong>Nota:</strong> ",
+"previewnote"  => "Onthou dat dit slegs 'n voorskou is en nog nie gestoor is nie!",
+"previewconflict" => "Hierdie voorskou reflekteer die teks in die boonste invoerboks soos dit sal lyk as jy dit stoor.",
+"editing"              => "Besig om $1 te wysig",
+"editconflict" => "Wysigingskonflik: $1",
+"explainconflict" => "Iemand anders het hierdie bladsy gewysig sedert jy dit begin verander het.
+Die boonste invoerboks het die teks wat tans bestaan.
+Jou wysigings word in die onderste invoerboks gewys.
+Jy sal jou wysigings moet saamsmelt met die huidige teks.
+<strong>Slegs</strong> die teks in die boonste invoerboks sal gestoor word wanneer jy \"Stoor bladsy\" druk.<br />",
+"yourtext"             => "Jou teks",
+"storedversion" => "Gestoorde weergawe",
+"editingold"   => "<strong>Waarskuwing: jy is besig om 'n ou weergawe van hierdie bladsy te wysig.
+As jy dit stoor, sal enige wysigings sedert hierdie wysiging verloor word.</strong>",
+"yourdiff"             => "Wysigings",
+"copyrightwarning" => "Alle bydraes aan {{SITENAME}} word beskou as beskikbaar gestel onder
+die ''GNU Free Documentation License'' (lees $1 vir meer inligting).
+As jy nie wil hê dat jou werk ongemagtig gewysig of versprei mag word nie, moet jy dit nie hier indien nie.<br />
+Jy belowe ons ook dat jy dit self geskryf het, of verkry het van 'n bron wat toelaat dat dit hier mag wees.<br />
+<strong>Moenie werk beskerm deur kopiereg sonder toestemming indien nie!</strong>",
+"longpagewarning" => "Waarskuwing: hierdie bladsy is $1 kilogrepe lank; sekere blaaiers
+kan probleme hê met die wysiging va blaaie langer as 32 kilogrepe. Breek asseblief die bladsy op in kleiner dele.",
+
+# History pages
+#
+"revhistory"   => "Wysigingsgeskiedenis",
+"nohistory"            => "Daar is geen wysigingsgeskiedenis vir hierdie bladsy nie.",
+"revnotfound"  => "Wysiging nie gevind nie.",
+"revnotfoundtext" => "Die ou wysiging waarvoor jy gevra het, kon nie gevind word nie. Maak asseblief seker dat die adres wat jy gebruik
+het om toegang te kry tot hierdie bladsy, reg is.\n",
+"loadhist"             => "Besig om bladsy wysigingsgeskiedenis te laai.",
+"currentrev"   => "Huidige wysiging",
+"revisionasof" => "Wysiging soos op $1",
+"cur"                  => "huidige",
+"next"                 => "volgende",
+"last"                 => "vorige",
+"orig"                 => "oorspronklike",
+"histlegend"   => "Byskrif: (huidige) = verskil van huidige weergawe,
+(vorige) = verskil van vorige weergawe, M = klein wysiging",
+
+# Diffs
+#
+"difference"   => "(Verksil tussen weergawes)",
+"loadingrev"   => "Besig om weergawe van verskil te laai.",
+"lineno"               => "Lyn $1:",
+"editcurrent"  => "Wysig die huidige weergawe van hierdie bladsy.",
+
+# Search results
+#
+"searchresults" => "soekresultate",
+"searchresulttext" => "Vir meer inligting oor {{SITENAME}} soekresultate, lees [[Project:Soek|Soek in {{SITENAME}}]].",
+"searchquery"  => "Vir navraag \"$1\"",
+"badquery"             => "Verkeerd gestelde navraag",
+"badquerytext" => "Ons kon nie jou naavraag prosesseer nie.
+Dit is miskien omdat jy gesoek het vir iets wat minder as drie letters bevat. Jy het miskien die navraag verkeerd ingetik.",
+"matchtotals"  => "Die navraag \"$1\" pas $2 artikeltitels
+en teks in $3 artikels.",
+"nogomatch" => "Geen bladsy met hierdie presiese titel bestaan nie, probeer 'n volteksnavraag. ",
+"titlematches" => "Artikeltitel resultate",
+"notitlematches" => "Geen artikeltitel resultate nie",
+"textmatches"  => "Artikelteks resultate",
+"notextmatches"        => "Geen artikelteks resultate nie",
+"prevn"                        => "vorige $1",
+"nextn"                        => "volgende $1",
+"viewprevnext" => "Kyk na ($1) ($2) ($3).",
+"showingresults" => "Onder <b>$1</b> resultate, beginende met #<b>$2</b>.",
+"nonefound"            => "<strong>Nota</strong>: onsuksesvolle navrae word gewoonlik veroorsaak deur 'n soektog met algemene
+woorde wat nie geindekseer word nie, of spesifisering van meer as een woord (slegs blaaie wat alle navraagwoorde
+bevat, word gewys).",
+"powersearch" => "Soek",
+"powersearchtext" => "
+Search in namespaces :<br />
+$1<br />
+$2 List redirects   Search for $3 $9", #fixMe
+
+
+# Preferences page
+#
+"preferences"  => "Voorkeure",
+"prefsnologin" => "Nie ingeteken nie",
+"prefsnologintext"     => "Jy moet [[Special:Userlogin|ingeteken wees]]
+om voorkeure te spesifiseer.",
+"prefslogintext" => "Jy is ingeteken as \"$1\".
+Jou internet ID-nommer is $2.",
+"prefsreset"   => "Voorkeure is herstel.",
+"qbsettings"   => "Snelbalkvoorkeure", #fixMe Quickbar settings
+"changepassword" => "Verander wagwoord",
+"skin"                 => "Omslag",
+"math"                 => "Verbeeld wiskunde",
+"math_failure"         => "Kon nie verbeeld nie",
+"math_unknown_error"   => "onbekende fout",
+"math_unknown_function"        => "onbekende funksie ",
+"math_lexing_error"    => "leksikale fout",
+"math_syntax_error"    => "sintaksfout",
+"saveprefs"            => "Stoor voorkeure",
+"resetprefs"   => "Herstel voorkeure",
+"oldpassword"  => "Ou wagwoord",
+"newpassword"  => "Nuwe wagwoord",
+"retypenew"            => "Tik nuwe wagwoord weer in",
+"textboxsize"  => "Grootte van invoerboks",
+"rows"                 => "Rye",
+"columns"              => "Kolomme",
+"searchresultshead" => "Soekresultaat voorkeure",
+"resultsperpage" => "Aantal resultate om te wys",
+"contextlines" => "Aantal lyne per resultaat",
+"contextchars" => "Karakters konteks per lyn",
+"stubthreshold" => "Drempel vir verkorte artikels",
+"recentchangescount" => "Aantal titels in onlangse wysigings",
+"savedprefs"   => "Jou voorkeure is gestoor.",
+"timezonetext" => "Aantal ure wat plaaslike tyd verskil van UGT.",
+"localtime"    => "Plaaslike tyd",
+"timezoneoffset" => "Teenrekening",
+"emailflag"            => "Keer e-pos van ander gebruikers",
+
+# Recent changes
+#
+"changes" => "wysigings",
+"recentchanges" => "Onlangse wysigings",
+"recentchangestext" => "Volg wysigings wat onlangs verander het, op
+[[{{ns:4}}:Welkom nuwelinge|Welkom nuwelinge]]!
+Kyk asb. ook na hierdie bladsye: [[{{ns:4}}:FAQ|{{ns:4}} FAQ]],
+[[{{ns:4}}:beleid|beleid]]
+(veral [[{{ns:4}}:styl|styl]],
+[[{{ns:4}}:neutrale standpunt|neutrale standpunt]]),
+en [[{{ns:4}}:mees algemene Wikipedia foute|mees algemene Wikipedia foute]].
+
+As jy wil hê dat Wikipedia suksesvol moet wees, is dit belangrik dat jy nie
+materiaal byvoeg wat deur [[{{ns:4}}:kopiereg|kopiereg]] beperk word nie.
+Die wetlike onderhewigheid kan die projek skade aandoen.", #fixMeContinue
+"rcloaderr"            => "Laai onlangse wysigings",
+"rcnote"               => "Hier onder is die laaste <strong>$1</strong> wysigings gedurende die laaste <strong>$2</strong> dae.",
+"rcnotefrom"   => "Hier onder is die wysigings sedert <b>$2</b> (tot by <b>$1</b> word gewys).",
+"rclistfrom"   => "Wys nuwe wysigings en begin by $1",
+# "rclinks"            => "Wys die laaste $1 wysigings in die laaste $2 ure / laaste $3 dae",
+"rclinks"              => "Wys die laaste $1 wysigings in die laaste $2 dae.",
+"rchide"               => "in $4 vorm; $1 klein veranderinge; $2 sekondêre naamspasies; $3 veelvuldige wysigings.",
+"diff"                 => "verskil",
+"hist"                 => "geskiedenis",
+"hide"                 => "vat weg",
+"show"                 => "wys",
+"tableform"            => "tabel",
+"listform"             => "lys",
+"nchanges"             => "$1 wysigings",
+"minoreditletter" => "K",
+"newpageletter" => "N",
+
+# Upload
+#
+"upload"               => "Laai lêer",
+"uploadbtn"            => "Laai lêer",
+"uploadlink"   => "Laai prente",
+"reupload"             => "Herlaai",
+"reuploaddesc" => "Keer terug na die laaivorm.",
+"uploadnologin" => "Nie ingeteken nie",
+"uploadnologintext"    => "Teken eers in [[Special:Userlogin|logged in]]
+om lêers te laai.",
+"uploaderror"  => "Laaifout",
+"uploadtext"   => "'''STOP!''' Voor jy hier laai, lees en volg {{SITENAME}} se
+[[Project:Image_use_policy|beleid oor prentgebruik]].
+
+Om prente wat voorheen gelaai is te sien of te soek, gaan na die
+[[Special:Imagelist|lys van gelaaide prente]].
+Laai van lêers en skrappings word aangeteken in die
+[[Project:Upload_log|laailog]].
+
+Gebruik die vorm hier onder om nuwe prente te laai wat jy ter illustrasie in jou artikels wil gebruik.
+In die meeste webblaaiers sal jy 'n \"Browse...\" knop sien, wat jou bedryfstelsel se standaard lêeroopmaak dialoogblokkie sal oopmaak.
+Deur 'n lêer in hierdie dialoogkassie te kies, vul jy die teksboks naas die knop met die naam van die lêer.
+Jy moet ook die blokkie merk om te bevestig dat jy geen kopieregte skend deur die lêer op te laai nie.
+Kliek die \"Laai\" knop om die laai af te handel.
+Dit mag dalk 'n rukkie neem as jy 'n stadige internetverbinding het.
+
+Die voorkeurformate is JPEG vir fotografiese prente, PNG vir tekeninge en ander ikoniese prente, en OGG vir klanklêers.
+Gebruik asseblief beskrywende lêername om verwarring te voorkom.
+Om die prent in 'n artikel te gebruik, gebruik 'n skakel met die formaat '''<nowiki>[[image:file.jpg]]</nowiki>''' of
+'''<nowiki>[[image:file.png|alt text]]</nowiki>''' of
+'''<nowiki>[[media:file.ogg]]</nowiki>''' vir klanklêers.
+
+Let asseblief op dat, soos met {{SITENAME}} bladsye, mag ander jou gelaaide lêers redigeer as hulle dink dit dien die ensiklopedie, en jy kan verhoed word om lêers te laai as jy die stelsel misbruik.",
+"uploadlog"            => "laailog",
+"uploadlogpage" => "laai_log",
+"uploadlogpagetext" => "Hier onder is 'n lys van die mees onlangse lêers wat gelaai is.
+Alle tye is bedienertyd (UGT).
+<ul>
+</ul>
+",
+"filename"             => "Lêernaam",
+"filedesc"             => "Opsomming",
+"copyrightpage" => "{{ns:4}}:kopiereg",
+"copyrightpagename" => "{{ns:4}} kopiereg",
+"uploadedfiles"        => "Gelaaide lêers",
+"ignorewarning"        => "Ignoreer waarskuwing en stoor lêer.",
+"minlength"            => "Prentname moet ten minste drie letters lank wees.",
+"badfilename"  => "Prentnaam is verander na \"$1\".",
+"badfiletype"  => "\".$1\" is nie 'n aanbevole lêerformaat vir prente nie.",
+"largefile"            => "Dis aanbeveel dat prente kleiner as 100k moet wees.",
+"successfulupload" => "Laai suksesvol",
+"fileuploaded" => "Lêer \"$1\" suksesvol gelaai.
+Volg asseblief hierdie skakel: ($2) na die beskrywingsbladsy en vul inligting in oor die die lêer, soos waar dit vandaan kom, wie het dit geskep en wanneer, en enige iets anders wat jy daarvan af weet.",
+"uploadwarning" => "Laaiwaarskuwing",
+"savefile"             => "Stoor lêer",
+"uploadedimage" => "Het \"[[$1]]\" gelaai",
+
+# Image list
+#
+"imagelist"            => "Prentelys",
+"imagelisttext"        => "Hier onder is a lys van $1 prente gesorteer $2.",
+"getimagelist" => "Besig om prentelys te haal",
+"ilsubmit"             => "Soek",
+"showlast"             => "Wys laaste $1 prente gesorteer $2.",
+"byname"               => "volgens naam",
+"bydate"               => "volgens datum",
+"bysize"               => "volgens grootte",
+"imgdelete"            => "skrap",
+"imgdesc"              => "beskrywing",
+"imglegend"            => "Legende: (beskrywing) = wys/verander prent se beskrywing.",
+"imghistory"   => "Prentgeskiedenis",
+"revertimg"            => "gaan terug",
+"deleteimg"            => "skrap",
+"deleteimgcompletely"          => "skrap",
+"imghistlegend" => "Legende: (huidig) = dit is die huidige prent, (skrap) = skrap hierdie ou weergawe, (gaan terug) = gaan terug na hierdie ou weergawe.
+<br /><i>Kliek die datum om die prent te sien wat op daardie datum gelaai is</i>.",
+"imagelinks"   => "Prentskakels",
+"linkstoimage" => "Die volgende bladsye gebruik hierdie prent:",
+"nolinkstoimage" => "Daar is geen bladsye wat hierdie prent gebruik nie.",
+
+# Statistics
+#
+"statistics"   => "Statistiek",
+"sitestats"            => "Werfstatistiek",
+"userstats"            => "Gebruikerstatistiek",
+"sitestatstext" => "Daar is 'n totaal van <b>$1</b> bladsye in die databasis.
+Dit sluit \"bespreek\" bladsye in, bladsye oor {{SITENAME}}, minimale \"verkorte\"
+bladsye, wegwysbladsye, en ander wat waarskynlik nie as artikels kwalifiseer nie.
+Uitsluitend bogenoemde, is daar <b>$2</b> bladsye wat waarskynlik ware artikels is.<p>
+Bladsye is al <b>$3</b> kere aangevra, en <b>$4</b> keer verander sedert die sagteware opgegradeer is (July 20, 2002).
+Dit werk uit op gemiddeld <b>$5</b> veranderings per bladsy, en bladsye word <b>$6</b> keer per verandering aangevra.",
+"userstatstext" => "Daar is <b>$1</b> geregistreerde gebruikers.
+<b>$2</b> van hulle is administrateurs (sien $3).",
+
+# Maintenance Page
+#
+"maintenance"          => "Instandhoudingsbladsy",
+"maintnancepagetext"   => "Hierdie bladsy bevat handige gereedskap vir alledaagse instandhouding. Party van hierdie funksies gebruik die databasis, so moet asseblief nie die bladsy herlaai na elke item wat jy verander het nie ;-)",
+"maintenancebacklink"  => "Terug na die instandhoudingsbladsy",
+"disambiguations"      => "Bladsye wat onduidelikhede opklaar",
+"disambiguationspage"  => "{{ns:4}}:Links_to_disambiguating_pages",
+"disambiguationstext"  => "Die volgende artikels skakel na 'n <i>bladsy wat onduidelikhede opklaar</i>. Hulle behoort eerder na die relevante onderwerp te skakel.<br />'n Bladsy word gesien as een wat onduidelikhede opklaar as $1 daarna toe skakel.<br />Skakels van ander naamkontekste is <i>nie</i> hier gelys nie.",
+"doubleredirects"      => "Dubbele aansture",
+"doubleredirectstext"  => "<b>Let op:</b> Hierdie lys bevat moontlik false positiewe. Dit beteken gewoonlik dat daar nog teks met skakels onder die eerste #REDIRECT is.<br />\nElke ry bevat skakels na die eerste en die tweede aanstuur, asook die eerste reël van van die tweede aanstuurteks, wat gewoonlik die \"regte\" teikenbladsy gee waarna die eerste aanstuur behoort te wys.",
+"brokenredirects"      => "Stukkende aansture",
+"brokenredirectstext"  => "Die volgende aansture skakel na 'n bladsy wat nie bestaan nie.",
+"selflinks"            => "Bladsye met selfskakels",
+"selflinkstext"                => "Die volgende bladsy bevat 'n skakel na hulself, en dit behoort nie te gebeur nie.",
+"mispeelings"           => "Bladsye met spelfoute",
+"mispeelingstext"               => "Die volgende bladsye bevat 'n algemene spelfout, soos gelys op $1. Die regte spelling word dalk (so) gegee.",
+"mispeelingspage"       => "Lys van algemene spelfoute",
+"missinglanguagelinks"  => "Weggelate taalskakels",
+"missinglanguagelinksbutton"    => "Het weggelate taalskakels gevind vir",
+"missinglanguagelinkstext"      => "Hierdie artikels skakel <i>nie</i> na hul eweknie in $1. Aansture en subbladsye word <i>nie</i> gewys nie.",
+
+
+# Miscellaneous special pages
+#
+"orphans"              => "Weesbladsye",
+"lonelypages"  => "Weesbladsye",
+"unusedimages" => "Ongebruikte prente",
+"popularpages" => "Populêre bladsye",
+"nviews"               => "$1 keer aangevra",
+"wantedpages"  => "Gesogte bladsye",
+"nlinks"               => "$1 skakels",
+"allpages"             => "Alle bladsye",
+"randompage"   => "Lukrake bladsy",
+"shortpages"   => "Kort bladsye",
+"longpages"            => "Lang bladsye",
+"listusers"            => "Gebruikerslys",
+"specialpages" => "Spesiale bladsye",
+"spheading"            => "Spesiale bladsye",
+"protectpage"  => "Beskerm bladsy",
+"recentchangeslinked" => "Verwante veranderings",
+"rclsub"               => "(na bladsye waarna \"$1\" skakel)",
+"debug"                        => "Ontfout",
+"newpages"             => "Nuwe bladsye",
+"movethispage" => "Skuif hierdie bladsy",
+"unusedimagestext" => "<p>Let asseblief op dat ander webwerwe, soos die internasionale Wikipedias, dalk met 'n direkte URL na 'n prent skakel, so die prent sal dus hier verskyn al word dit aktief gebruik.",
+"booksources"  => "Boekbronne",
+"booksourcetext" => "Hier onder is 'n lys van skakels na ander werwe wat nuwe en tweede handse boeke verkoop, en wat dalk ook verdere inligting het oor boeke waarna jy soek.
+{{SITENAME}} is nie geaffilieer aan enige van hierdie besighede nie en die lys moet nie as 'n aanbeveling gesien word nie.",
+
+# Email this user
+#
+"mailnologin"  => "Geen verstuuradres",
+"mailnologintext" => "Jy moet [[Special:Userlogin|ingeteken]]
+wees en 'n geldige e-posadres in jou [[Special:Preferences|voorkeure]]
+hê om e-pos aan ander gebruikers te stuur.",
+"emailuser"            => "Stuur e-pos na hierdie gebruiker",
+"emailpage"            => "Stuur e-pos na gebruiker",
+"emailpagetext"        => "As die gerbuiker 'n geldoge e-posadres in haar of sy gebruikersvoorkeure het, sal die vorm hier onder 'n enkele boodskap stuur.
+Die e-posadres wat jy in jou gebruikersvoorkeure het sal verkyn as die \"Van\" adres van die pos, so die ontvanger sal kan terug antwoord.",
+"noemailtitle" => "Geen e-posadres",
+"noemailtext"  => "Hierdie gebruiker het nie 'n geldige e-posadres gespesifiseer nie of het gekies om nie e-pos van ander gebruikers te ontvang nie.",
+"emailfrom"            => "Van",
+"emailto"              => "Aan",
+"emailsubject" => "Onderwerp",
+"emailmessage" => "Boodskap",
+"emailsend"            => "Stuur",
+"emailsent"            => "E-pos gestuur",
+"emailsenttext" => "Jou e-pos is gestuur.",
+
+# Watchlist
+#
+"watchlist"            => "My dophoulys",
+"watchlistsub" => "(vir gebruiker \"$1\")",
+"nowatchlist"  => "Jy het geen items in jou dophoulys nie.",
+"watchnologin" => "Nie ingeteken nie",
+"watchnologintext"     => "Jy moet [[Special:Userlogin|ingeteken]]
+wees om jou dophoulys te verander.",
+"addedwatch"   => "Bygevoeg tot dophoulys",
+"addedwatchtext" => "Die bladsy \"$1\" is by jou <a href=\"" .
+  "{{localurle:Special:Watchlist}}\">dophoulys</a> gevoeg.
+Toekomstige veranderinge aan hierdie bladsye en sy geassosieerde Bespreekbladsy sal hier verskyn en die bladsy sal in <b>vetdruk</b> verskyn in die <a href=\"" .
+  "{{localurle:Special:Recentchanges}}\">lys van onlangse wysigings</a> om dit makliker te maak om dit raak te sien.</p>
+
+<p>As jy die bladsy later van jou dophoulys wil verwyder, kliek \"Moenie meer dophou\" in die kantbalk.",
+"removedwatch" => "Afgehaal van dophoulys",
+"removedwatchtext" => "Die bladsy \"$1\" is van jou dophoulys afgehaal.",
+"watchthispage"        => "Hou hierdie bladsy dop",
+"unwatchthispage" => "Moenie meer dophou",
+"notanarticle" => "Nie 'n artikel",
+
+# Delete/protect/revert
+#
+"deletepage"   => "Skrap bladsy",
+"confirm"              => "Bevestig",
+"confirmdelete" => "Bevestig skrapping",
+"deletesub"            => "(Besig om \"$1\" te skrap)",
+"confirmdeletetext" => "Jy staan op die punt om 'n bladsy of prent asook al hulle geskiedenis uit die databasis te skrap.
+Bevestig asseblief dat jy dit wil doen, dat jy die gevolge verstaan en dat jy dit doen in ooreenstemming met die [[{{ns:4}}:Policy]].",
+"actioncomplete" => "Aksie uitgevoer",
+"deletedtext"  => "\"$1\" is geskrap.
+Kyk na $2 vir 'n rekord van onlangse skrappings.",
+"deletedarticle" => "\"$1\" geskrap",
+"dellogpage"   => "Skrap_log",
+"dellogpagetext" => "Hier onder is 'n lys van die mees onlangse skrappings. Alle tye is bedienertyd (UGT).
+<ul>
+</ul>
+",
+"deletionlog"  => "skrappingslog",
+"reverted"             => "Het terug gegaan na vroeëre weergawe",
+"deletecomment"        => "Rede vir skrapping",
+"imagereverted" => "Terugkeer na vorige weergawe was suksesvol.",
+"rollback"             => "Rol veranderinge terug",
+"rollbacklink" => "Rol terug",
+"cantrollback" => "Kan nie na verandering terug keer nie; die laaste bydraer is die enigste outer van hierdie bladsy.",
+"revertpage"   => "Het teruggegaan na laaste verandering wat $1 gemaak het",
+
+# Undelete
+"undelete" => "Herstel geskrapte bladsy",
+"undeletepage" => "Bekyk en herstel geskrapte bladsye",
+"undeletepagetext" => "Die volgende bladsye is geskrap, maar hulle is nog in die argief en kan herstel word. Die argief kan periodiek skoongemaak word.",
+"undeletearticle" => "Herstel geskrapte bladsy",
+"undeleterevisions" => "$1 weergawes in argief",
+"undeletehistory" => "As jy die bladsy herstel, sal alle weergawes herstel word.
+As 'n nuwe bladsy met dieselfde naam sedert die skrapping geskep is, sal die herstelde weergawes in die nuwe bladsy se voorgeskiedenis verskyn en die huidige weergawe van die lewendige bladsy sal nie outomaties vervang word nie.",
+"undeleterevision" => "Geskrape weergawes vanaf $1",
+"undeletebtn" => "Herstel!",
+"undeletedarticle" => "het \"$1\" herstel",
+"undeletedtext"   => "Die bladsy [[$1]] is sukselsvol herstel.
+Kyk na [[{{ns:4}}:Deletion_log]] vir 'n rekord van onlangse skrappings en herstellings.",
+
+# Contributions
+#
+"contributions"        => "Gebruikersbydraes",
+"mycontris" => "My bydraes",
+"contribsub"   => "Vir $1",
+
+"nocontribs"   => "Geen veranderinge wat by hierdie kriteria pas, is gevind nie.",
+"ucnote"               => "Hier onder is die gebruiker se laaste <b>$1</b> veranderings in die laaste <b>$2</b> dae.",
+"uclinks"              => "Bekyk die laaste $1 veranderings; bekyk die laaste $2 dae.",
+"uctop"                => " (boontoe)" ,
+
+# What links here
+#
+"whatlinkshere"        => "Wat skakel hierheen",
+"notargettitle" => "Geen teiken",
+"notargettext" => "Jy het nie 'n teikenbladsy of gebruiker waarmee hierdie funksie moet werk, gespesifiseer nie.",
+"linklistsub"  => "(Lys van skakels)",
+"linkshere"            => "Die volgende bladsye skakel hierheen:",
+"nolinkshere"  => "Geen bladsye skakel hierheen nie.",
+"isredirect"   => "Stuur bladsy aan",
+
+# Block/unblock IP
+#
+"blockip"              => "Blok IP-adres",
+"blockiptext"  => "Gebruik die vorm hier onder om skryftoegang van 'n sekere IP-adres te blok.
+Dit moet net gedoen word om vandalisme te voorkom en in ooreenstemming met [[{{ns:4}}:Policy|{{ns:4}} policy]].
+Vul 'n spesifieke rede hier onder in (haal byvoorbeeld spesifieke bladsye wat gevandaliseer is, aan).",
+"ipaddress"            => "IP-Adres",
+"ipbreason"            => "Rede",
+"ipbsubmit"            => "Blok hierdie adres",
+"badipaddress" => "Die IP-adres is nie in die regte formaat nie.",
+"blockipsuccesssub" => "Blokkering het geslaag",
+"blockipsuccesstext" => "Die IP-adres \"$1\" is geblok.
+<br />Kyk na [[Special:Ipblocklist|IP block list]] vir 'n oorsig van blokkerings.",
+"unblockip"            => "Maak IP-adres oop",
+"unblockiptext"        => "Gebruik die vorm hier onder om skryftoegang te herstel vir 'n voorheen geblokkeerde IP-adres.",
+"ipusubmit"            => "Maak hierdie adres oop",
+"ipusuccess"   => "IP-adres \"$1\" is oopgemaak",
+"ipblocklist"  => "Lys van geblokkeerde IP-adresse",
+'blocklistline'        => '$1, $2 het $3 geblok ($4)',
+"blocklink"            => "blok",
+"unblocklink"  => "maak oop",
+"contribslink" => "bydraes",
+
+# Developer tools
+#
+"lockdb"               => "Sluit databasis",
+"unlockdb"             => "Ontsluit databasis",
+"lockdbtext"   => "As jy die databasis sluit, kan geen gebruiker meer bladsye redigeer nie, voorkeure verander nie, dophoulyste verander nie, of ander aksies uitvoer wat veranderinge in die databasis verg nie.
+Bevestig asseblief dat dit is wat jy wil doen en dat jy die databasis sal ontsluit sodra jy jou instandhouding afgehandel het.",
+"unlockdbtext" => "As jy die databasis ontsluit, kan gebruikers weer bladsye redigeer, voorkeure verander, dophoulyste verander, of ander aksies uitvoer wat veranderinge in die databasis verg.
+Bevestig asseblief dat dit is wat jy wil doen.",
+"lockconfirm"  => "Ja, ek wil regtig die databasis sluit.",
+"unlockconfirm"        => "Ja, ek wil regtig die databasis ontsluit.",
+"lockbtn"              => "Sluit die databasis",
+"unlockbtn"            => "Ontsluit die databasis",
+"locknoconfirm" => "Jy het nie die bevestigblokkie gemerk nie.",
+"lockdbsuccesssub" => "Databasissluit het geslaag",
+"unlockdbsuccesssub" => "Databasisslot is verwyder",
+"lockdbsuccesstext" => "Die {{SITENAME}} databasis is gesluit.
+<br />Onthou om dit te ontsluit wanneer jou onderhoud afgehandel is.",
+"unlockdbsuccesstext" => "Die {{SITENAME}} databasis is ontsluit.",
+
+# Move page
+#
+"movepage"             => "Skuif bladsy",
+"movepagetext" => "Met die vorm hier onder kan jy 'n bladsy hernoem en so al sy geskiedenis na die nuwe naam skuif.
+Die ou titel sal 'n aanstuurbladsy na die nuwe titel word.
+Skakels na die ou bladsytitel sal nie verander nie; maak seker dat jy
+check vir dubbele of gebrekte aansture.
+Dis jou verantwoordelikheid om seker te maak dat skakels steeds wys waarheen hulle moet.
+
+Let op dat 'n bladsy '''nie''' geskuif sal word as daar reeds 'n bladsy met so 'n titel bestaan nie, tensy dit leeg is off 'n aanstuurbladsy is, en dit het geen veranderingsgeskiedenis nie. Dit beteken dat jy 'n bladsy kan hernoem na sy ou titel as jy 'n fout gemaak het, en jy kan nie oor 'n bestaande bladsy skryf nie.
+
+<b>WAARSKUWING!</b>
+Hierdie kan 'n drasitiese en onverwagte verandering vir 'n populêre bladsy wees;
+maak asseblief seker dat jy die gevolge verstaan voordat jy voortgaan.",
+"movepagetalktext" => "Die geassosieerde praatbladsy, indien enige, sal outomaties saam met dit geskuif word, '''behalwe as:'''
+*Jy die bladsy oor naamkontekste heen skuif,
+*'n Bespreekbladsy wat nie leeg is nie reeds onder die nuwe naam bestaan, of
+*Jy die merk uit blokkie hier onder wegneem.
+
+In hierdie gevalle, sal jy die bladsy met die hand moet skuif of saamsmelt as jy wil.",
+"movearticle"  => "Skuif bladsy",
+"movenologin"  => "Nie ingeteken nie",
+"movenologintext" => "Jy moet 'n geregistreerde gebruiker wees en [[Special:Userlogin|ingeteken]]
+wees om 'n bladsy te skuif.",
+"newtitle"             => "Na nuwe titel",
+"movepagebtn"  => "Skuif bladsy",
+"pagemovedsub" => "Verskuiwing het geslaag",
+"pagemovedtext" => "Bladsy \"[[$1]]\" geskuif na \"[[$2]]\".",
+"articleexists" => "'n Bladsy met daardie naam bestaan reeds, of die naam wat jy gekies het, is nie geldig nie.
+Kies asseblief 'n ander naam.",
+"talkexists"   => "Die bladsy self is suksesvol verskuif, maar die bespreekbladsy kon nie geskuif word nie omdat een reeds bestaan met die nuwe titel. Smelt hulle asseblief met die hand saam.",
+"movedto"              => "geskuif na",
+"movetalk"             => "Skuif \"bespreek\"bladsy ook, indien van toepassing.",
+"talkpagemoved" => "Die ooreenkomstige bespreekbladsy is ook geskuif.",
+"talkpagenotmoved" => "Die ooreenkomstige bespreekbladsy is <strong>nie</strong> geskuif nie.",
+
+#Math
+       'mw_math_png' => "Gebruik altyd PNG.",
+       'mw_math_simple' => "Gebruik HTML indien dit eenvoudig is, andersins PNG.",
+       'mw_math_html' => "Gebruik HTML wanneer moontlik, andersins PNG.",
+       'mw_math_source' => "Los as TeX (vir teks blaaiers).",
+       'mw_math_modern' => "Moderne blaaiers.",
+       'mw_math_mathml' => 'MathML',
+
+);
+
+class LanguageAf extends LanguageUtf8 {
+
+       function getNamespaces() {
+               global $wgNamespaceNamesAf;
+               return $wgNamespaceNamesAf;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsAf;
+               return $wgQuickbarSettingsAf;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesAf;
+               return $wgSkinNamesAf;
+       }
+
+       function getMessage( $key )
+       {
+               global $wgAllMessagesAf;
+               if( isset( $wgAllMessagesAf[$key] ) ) {
+                       return $wgAllMessagesAf[$key];
+               } else {
+                       return parent::getMessage( $key );
+               }
+       }
+
+       function formatNum( $number ) {
+               global $wgTranslateNumerals;
+               return $wgTranslateNumerals ? strtr($number, '.,', ',.' ) : $number;
+       }
+
+}
+
+?>
diff --git a/languages/LanguageAr.php b/languages/LanguageAr.php
new file mode 100644 (file)
index 0000000..8374987
--- /dev/null
@@ -0,0 +1,679 @@
+<?php
+/** Arabic (العربية)
+  *
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+/** This is an UTF-8 language  */
+require_once('LanguageUtf8.php');
+
+/* private */ $wgNamespaceNamesAr = array(
+       NS_MEDIA            => 'ملف',
+       NS_SPECIAL          => 'خاص',
+       NS_MAIN             => '',
+       NS_TALK             => 'نقاش',
+       NS_USER             => 'مستخدم',
+       NS_USER_TALK        => 'نقاش_المستخدم',
+       NS_PROJECT          => 'ويكيبيديا',
+       NS_PROJECT_TALK     => 'نقاش_ويكيبيديا',
+       NS_IMAGE            => 'صورة',
+       NS_IMAGE_TALK       => 'نقاش_الصورة',
+       NS_MEDIAWIKI        => 'ميدياويكي',
+       NS_MEDIAWIKI_TALK   => 'نقاش_ميدياويكي',
+       NS_TEMPLATE         => 'Template',
+       NS_TEMPLATE_TALK    => 'نقاش_Template',
+       NS_HELP             => 'مساعدة',
+       NS_HELP_TALK        => 'نقاش_المساعدة',
+       NS_CATEGORY         => 'تصنيف',
+       NS_CATEGORY_TALK    => 'نقاش_التصنيف'
+) + $wgNamespaceNamesEn;
+
+
+/* private */ $wgAllMessagesAr = array(
+# Dates
+'sunday' => 'الأحد',
+'monday' => 'الإثنين',
+'tuesday' => 'الثلاثاء',
+'wednesday' => 'الأربعاء',
+'thursday' => 'الخميس',
+'friday' => 'الجمعة',
+'saturday' => 'السبت',
+'january' => 'يناير',
+'february' => 'فبراير',
+'march' => 'مارس',
+'april' => 'ابريل',
+'may_long' => 'مايو',
+'june' => 'يونيو',
+'july' => 'يوليو',
+'august' => 'أغسطس',
+'september' => 'سبتمبر',
+'november' => 'نوفمبر',
+'december' => 'ديسمبر',
+
+# Bits of text used by many pages:
+#
+'mainpage'             => 'الصفحة الرئيسية',
+'mytalk'               => 'صفحة نقاشي',
+'history_short' => 'تاريخ الصفحة',
+'edit' => 'عدل هذه الصفحة',
+'delete' => 'حذف هذه الصفحة',
+'protect' => 'صفحة محمية',
+'talk' => 'ناقش هذه الصفحة',
+
+# Watchlist
+#
+'watch' => 'راقب هذه الصفحة',
+'watchthispage'                => 'راقب هذه الصفحة',
+'unwatch' => 'توقف عن مراقبة الصفحة',
+'unwatchthispage'      => 'توقف عن مراقبة الصفحة',
+
+
+# copy and paste from wikipedia:
+'1movedto2' => '$1 تم نقلها إلى $2',
+'1movedto2_redir' => 'تم نقل $1 فوق التحويلة $2',
+'about' => 'حول',
+'aboutpage' => 'ويكيبيديا:حول',
+'accmailtext' => 'تم إرسال كلمة السر الخاصة بـ \'$1\' إلى العنوان $2.',
+'accmailtitle' => 'تم إرسال كلمة السر.',
+'acct_creation_throttle_hit' => 'معذرة، لقد أقمت $1 حساب. لا يممكنك عمل المزيد.',
+'actioncomplete' => 'انتهاء العملية',
+'addedwatch' => 'تمت الإضافة لقائمة المراقبة',
+'addedwatchtext' => 'تمت إضافة الصفحة  "$1" إلى <a href="/wiki/Special:Watchlist">قائمة المراقبة</a> لديك. سيتم وضع التغييرات القادمة على هذه الصفحة، وصفحة النقاش الخاصة بها سيتم وضعها هناك. وسيتم إظهار إسم الصفحة بخط <b>عريض</b> في صفحة <a href="/wiki/Special:Recentchanges">أحدث التغييرات</a> لتسهيل تحديدها وإكتشافها.</p>
+
+<p>
+إذا كنت تريد إزالة الصفحة من قائمة المراقبة لديك، إضغط على "توقف عن مراقبة الصفحة" في اللوحة أسفل الصفحة.',
+'administrators' => 'ويكيبيديا:إداريين',
+'allmessages' => 'كافة رسائل النظام',
+'allpages' => 'كل الصفحات',
+'allpagessubmit' => 'اذهب',
+'alphaindexline' => '$1 إلى $2',
+'alreadyloggedin' => '<strong>المستخدم $1, انت مسجل للدخول من قبل!</strong><br />',
+'ancientpages' => 'المقالات القديمة',
+'anontalkpagetext' => '----
+هذه صفحة نقاش لمستخدم مجهول، وهو المستخدم الذي لم يقم بإنشاء حساب في ويكيبيديا، أو لا يستعمل ذلك الحساب.
+لذا يتم إستعمال رقم ال IP للتعريف به. من الممكن أن يشترك عدد من المستخدمين بنفس رقم ال IP. إذا كنت مستخدم مجهول
+وترى أن رسائل خير موجهة لك قد وصلتك، من الممكن أن تقوم [[Special:Userlogin|بإنشاء حساب أو القيام بالدخول]]
+حتى يزول الخلط بينك وبين المستخدمين المجهولين الآخرين.',
+'anonymous' => 'مستخدم مجهول لويكيبيديا',
+'article' => 'مقالة',
+'articleexists' => 'يوجد صفحة بهذا الإسم،
+أو أن الإسم الذي تم إختياره غير صالح.
+يرجى إختيار إسم آخر.',
+'articlepage' => 'عرض المقالة',
+'badfilename' => 'تم تغيير إسم الصورة إلى "$1".',
+'badipaddress' => 'لا يوجد مستخدم بهذا الإسم',
+'badquery' => 'نص بحث خاطئ',
+'badretype' => 'كلمات السر التي أدخلتها غير متطابقة.',
+'badtitle' => 'عنوان خاطئ',
+'blanknamespace' => 'مقالات',
+'blockedtext' => 'إسم المستخدم أو عنوان ال IP الخاص بك تم منعه من قبل $1.
+سبب المنع هو: <br />\'\'$2\'\' <p>
+من الممكن الإتصال مع $1 للنقاش حول المنع، أو من الممكن الإتصال مع أحد [[Wikipedia:Administrators|الإداريين]] حول ذلك.
+
+تذكر أنه لا يمكن لك إستعمال خاصية إرسال رسائل إلكترونية للمستخدمين إلا إذا كنت قد وضعت عنوان بريدي صحيح في صفحة [[Special:Preferences|التفضيلات]] الخاصة بك.
+
+عنوان ال IP الخاص بك هو $3. يرجى إضافته في أي رسالة للتساؤل حول المنع.',
+'blockedtitle' => 'المستخدم ممنوع',
+'blockip' => 'منع مستخدم',
+'blocklink' => 'منع مستخدم',
+'blocklogentry' => 'منع "$1" لفترة زمنية مدتها $2',
+'bold_sample' => 'نص عريض',
+'bold_tip' => 'نص عريض',
+'booksources' => 'مصدر كتاب',
+'brokenredirects' => 'وصلات مكسورة',
+'brokenredirectstext' => 'الوصلات التالية تشير لصفحات غير موجودة.',
+'bugreports' => 'تقارير الأخطاء',
+'bydate' => 'على التاريخ',
+'byname' => 'على الإسم',
+'bysize' => 'على الحجم',
+'cancel' => 'إلغاء العملية',
+'categories' => 'تصنيفات الصفحة',
+'categoriespagetext' => 'التصنيفات التالية موجودة في ويكيبيديا',
+'category' => 'تصنيف',
+'category_header' => 'المقالات في التصنيف "$1"',
+'categoryarticlecount' => 'يوجد $1 مقال في هذا التصنيف.',
+'categoryarticlecount1' => 'هناك $1 مقال  هذا التصنيف.',
+'changepassword' => 'غير كلمة السر',
+'changes' => 'تغييرات',
+'columns' => 'أعمدة',
+'compareselectedversions' => 'قارن بين النسخ المختارة',
+'confirm' => 'تأكيد',
+'confirmdelete' => 'تأكيد الحذف',
+'confirmprotect' => 'تأكيد الحماية',
+'confirmprotecttext' => 'هل أنت متأكد انك تريد حماية هذه الصفحة؟',
+'confirmunprotect' => 'تأكيد إزالة الحماية',
+'confirmunprotecttext' => 'هل أنت متأكد انك تريد إزالة الحماية عن هذه الصفحة؟',
+'contribslink' => 'مساهمات',
+'contribsub' => 'للمستخدم $1',
+'contributions' => 'مساهمات المستخدم',
+'copyright' => 'المحتويات تحت  $1.',
+'copyrightpage' => 'ويكيبيديا:حقوق النسخ',
+'copyrightpagename' => 'حقوق النسخ في ويكيبيديا',
+'copyrightwarning' => 'يرجى الملاحظة أن جميع المساهمات هنا خاضعة وصادرة تحت ترخيص
+جنو للوثائق الحرة (أنظر في $1 للمزيد من التفاصيل)
+إذا لم ترد أن تخضع كتابتك للتعديل والتوزيع الحر، لا تضعها هنا.
+<br />
+كما أنك تتعهد بأنك قمت بكتابة ما هو موجود بنفسك، أو قمت بنسخها
+من مصدر يخضع ضمن الملكية العامة، أو مصدر حر آخر.
+<strong>لا ترسل أي عمل ذو حقوق محفوظة بدون الإذن من صاحب الحق</strong>.',
+'createaccount' => 'إنشاء حساب جديد',
+'createaccountmail' => 'عبر البريد الإلكتروني',
+'cur' => 'الحالي',
+'currentevents' => 'احداث حالية',
+'currentrev' => 'النسخة الحالية',
+'databaseerror' => 'خطأ في قاعدة البيانات',
+'dateformat' => 'صيغة التاريخ',
+'deadendpages' => 'صفحات نهاية مسدودة',
+'defaultns' => 'أبحث في هذه النطاقات بشكل أفتراضي:',
+'defemailsubject' => 'رسالة من ويكيبيديا',
+'deletecomment' => 'سبب الحذف',
+'deletedarticle' => 'تم حذف "$1"',
+'deletedtext' => '"$1" تم حذفها.
+انظر في $2 لسجل آخر عمليات الحذف.',
+'deleteimg' => 'حذف',
+'deletepage' => 'حذف الصفحة',
+'deletesub' => '(حذف "$1")',
+'deletethispage' => 'حذف هذه الصفحة',
+'deletionlog' => 'سجل الحذف',
+'dellogpage' => 'سجل_الحذف',
+'diff' => 'فرق',
+'disclaimerpage' => 'ويكيبيديا:عدم_مسؤولية_عام',
+'disclaimers' => 'عدم مسؤولية',
+'doubleredirects' => 'وصلات مزدوجة',
+'editcurrent' => 'حرر النسخة الحالية من هذه الصفحة',
+'edithelp' => 'مساعدة التحرير',
+'edithelppage' => 'ويكيبيديا:مساعدة التحرير',
+'editing' => 'تحرير $1',
+'editingold' => '<strong> تحذير: أنت تقوم الآن بتحرير نسخة قديمة من هذه الصفحة. إذا قمت بحفظها، سيتم فقدات كافة التغييرات التي حدثت بعد هذه النسخة. </strong>',
+'editsection' => 'تحرير',
+'editthispage' => 'عدل هذه الصفحة',
+'emailflag' => 'عدم تلقي الرسائل من المستخدمين الآخرين',
+'emailforlost' => '* إدخال عنوانك البريدي أمر إختياري، لكنه يسمح لك بإرسال رسائل للأعضاء في الموقع من دون الكشف عن عنوانك لهم، كما أنه يساعدك في حال نسيانك لكلمة السر.',
+'emailfrom' => 'من',
+'emailmessage' => 'نص الرسالة',
+'emailpage' => 'أرسل رسالة للمستخدم',
+'emailpagetext' => 'لو أن هذا المستخدم قد قام بإدخال عنوان بريدي صحيح في تفضيلاته،
+فسيتم إرسال رسالة واحدة له بالنموذج أدناه.
+العنوان الذي قمت أنت بإدخاله لك في تفضيلات المستخدم،
+سيظهر في مكان المرسل في الرسالة التي سترسل له، ليتمكن من الرد عليك.',
+'emailsend' => 'إرسال',
+'emailsent' => 'تم إرسال الرسالة',
+'emailsenttext' => 'تم إرسال رسالتك الإلكترونية.',
+'emailsubject' => 'العنوان',
+'emailto' => 'إلى',
+'emailuser' => 'أرسل رسالة لهذا المستخدم',
+'error' => 'خطأ',
+'errorpagetitle' => 'خطأ',
+'excontent' => 'المحتوى كان: \'$1\'',
+'excontentauthor' => 'المحتوى كان: \'$1\' (و المساهم الوحيد كان \'$2\')',
+'explainconflict' => 'لقد قام أحد ما بتعديل الصفحة بعد أن بدأت انت بتحريرها.
+صندوق النصوص العلوي يحتوي على النص الموجود حاليا في الصفحة.
+والتغييرات التي قمت أنت بها موجودة في الصندوق في أسفل الصفحة.
+يجب أن تقوم بدمج تغييراتك في النص الموجود حاليا.
+<b>فقط</b> ما هو موجود في الصندوق العلوي هو ما سيتم حفظه وإستعاله عند الضغط على زر "حفظ الصفحة".
+<p>',
+'export' => 'صدّر صفحات',
+'faq' => 'الأسئلة الأكثر تكرارا',
+'faqpage' => 'ويكيبيديا:أسئلة متكررة',
+'filecopyerror' => 'لا يمكن نسخ الملف من  "$1" إلى "$2".',
+'filedeleteerror' => 'لا يمكن حذف الملف "$1".',
+'filedesc' => 'وصف قصير',
+'filename' => 'إسم الملف',
+'filenotfound' => 'لا يمكن إيجاد الملف "$1".',
+'filerenameerror' => 'لا يمكن غيير إسم الملف من  "$1" إلى "$2".',
+'filesource' => 'مصدر',
+'go' => 'إذهب',
+'headline_sample' => 'نص عنوان رئيسي',
+'headline_tip' => 'عنوان من المستوى الثاني',
+'help' => 'مساعدة',
+'helppage' => 'ويكيبيديا:مساعدة',
+'hide' => 'إخفاء',
+'hidetoc' => 'إخفاء',
+'hist' => 'تاريخ',
+'histlegend' => 'مفتاح: (الحالي) = الفرق مع النسخة الحالية
+(السابق) = الفروقات مع النسخة السابقة، ط = تغيير طفيف',
+'history' => 'تاريخ الصفحة',
+'ilsubmit' => 'بحث',
+'imagelist' => 'قائمة الصور',
+'imagepage' => 'عرض صفحة الصورة',
+'imgdelete' => 'حذف',
+'imgdesc' => 'وصف',
+'imghistory' => 'تاريخ الصورة',
+'internalerror' => 'خطأ داخلي',
+'intl' => 'وصلات بين لغات الموسوعة',
+'invert' => 'عكس الإختيار',
+'ipblocklist' => 'قائمة أسماء الأعضاء و عناوين ال IP الممنوعة',
+'ipboptions' => '2 hours,1 day,3 days,1 week,2 weeks,1 month,3 months,6 months,1 year,infinite',
+'ipbreason' => 'السبب',
+'isredirect' => 'صفحة تحويل',
+'italic_sample' => 'نص مائل',
+'italic_tip' => 'نص مائل',
+'last' => 'السابق',
+'lastmodified' => 'أخر تعديل لهذه الصفحة كان في $1.',
+'lineno' => 'سطر $1:',
+'link_sample' => 'عنوان وصلة',
+'linkshere' => 'الصفحات التالية تحتوي على وصلة إلى هنا:',
+'linkstoimage' => 'الصفحات التالية تحتوي على وصلة لهذه الصورة:',
+'listform' => 'قائمة',
+'listusers' => 'قائمة الأعضاء',
+'loadhist' => 'تحميل تاريخ الصفحة',
+'localtime' => 'عرض الوقت المحلي',
+'log' => 'تحميل و حذف',
+'login' => 'دخول',
+'loginerror' => 'خطأ في الدخول',
+'loginpagetitle' => 'تسجيل الدخول للمستخدم',
+'loginproblem' => '<b>حدثت مشكلة أثناء الدخول.</b><br />يرجى المحاولة مرى أخرى!',
+'loginprompt' => 'يجب أن يدعم متصفحك الكوكيز Cookies لتتمكن من الدخول.',
+'loginsuccess' => 'لقد قمت بتسجيل الدخول لويكيبيديا بإسم "$1".',
+'loginsuccesstitle' => 'تم الدخول بشكل صحيح',
+'logout' => 'خروج',
+'logouttext' => 'أنت الآن غير مسجل الدخول للنظام.
+تستطيع المتابعة بإستعمال ويكيبيديا كمجهول، أو الدخول مرة أخرى بنفس الإسم أو بإسم آخر. من الممكن أن ترى بعض الصفحات في الموسوعة كما وأنك مسجل في النظام.، وذلك بسبب إستعمال الصفحات المخبأة Cache في المنتصفح لديك.',
+'logouttitle' => 'تسجيل الخروج للمستخدم',
+'lonelypages' => 'صفحات يتيمة',
+'longpages' => 'صفحات طويلة',
+'mailmypassword' => 'أرسل لي كلمة السر عبر البريد الإلكتروني.',
+'mailnologin' => 'لا يوجد عنوان للإرسال',
+'mailnologintext' => 'يجب أن تقوم <a href="/wiki/Special:Userlogin">بتسجيل الدخول</a>
+وتوفير بريد إلكتروني صالح في صفحة  <a href="/wiki/Special:Preferences">التفضيلات</a>
+لتتمكن من إرسال الرسائل لمستخدمين آخرين.',
+'maintenance' => 'صفحة الصيانة',
+'maintenancebacklink' => 'العودة لصفحة الصيانة',
+'minoredit' => 'هذا تعديل طفيف',
+'minoreditletter' => 'ط',
+'mispeelings' => 'صفحات بأخطاء إملائية',
+'mispeelingspage' => 'قائمة بالأخطاء الإملائية الشائعة',
+'missinglanguagelinks' => 'وصلات مفقودة للغات',
+'missinglanguagelinksbutton' => 'إبحث عن وصلة لغة مفقودة ل',
+'moredotdotdot' => 'المزيد...',
+'move' => 'نقل',
+'movearticle' => 'نقل صفحة',
+'movedto' => 'تم نقلها إلى',
+'movelogpage' => 'سجل النقل',
+'movenologin' => 'غير مسجل',
+'movepage' => 'نقل صفحة',
+'movepagebtn' => 'أنقل الصفحة',
+'movepagetalktext' => 'صفحة النقاش المرفقة بالمقالة سيتم نقلها كذلك، إذا وجدت. ولكن لا يتم نقل صفحة النقاش في الحالات التالية:
+* نقل الصفحة عبر نطاقات namespaces مختلفة.
+* يوجد صفحة نقاش غير فارغة تحت العنوان الجديد للمقالة.
+* قمت بإزالة إختيار نقل صفحة النقاش في الأسفل.
+
+وفي الحالات أعلاه، يجب عليك نقل أو دمج محتويات صفحة النقاش يدويا، إذا رغب في ذلك.',
+'movepagetext' => 'بإستعمال النموذج أدنه، تستطيع تغيير أسم الصفحة،
+ونقل تاريخ الصفحة للإسم الجديد.
+سيتم أنشاء تحويل من العنوان القديم، للصفحة بالعنوان الجديد.
+لكن، لن يتم تغيير الوصلات في الصفحات التي تتصل بهذه الصفحة، لذا عليك
+[[Special:Maintenance|التأكد]] من عدم وجود وصلات مقطوعة، أو وصلات متتالية،
+للتأكد من أن المقالات تتصل مع بعضها بشكل مناسب.
+
+يرجى الملاحظة انه \'\'\'لن يتم\'\'\' نقل الصفحة إذا وجدت صفحة بالإسم الجديد،
+إلا إذا كانت صفحة فارغة، أو صفحة تحويل، ولا تاريخ لها. وهذا يعني أنك لا تستطيع
+وضع صفحة مكان صفحة، كما أنه من الممكن إرجاع الصفحة لمكانها في حال تم النقل بشكل خاطئ.
+
+<b>تحذير!</b>
+قد يكون لنقل الصفحة آثار كبيرة، وتغييرا غير متوقع بالنسبة للصفحات المشهورة.
+يرجى فهم وإدارك عواقب نقل الصفحات قبل القيام به.',
+'movereason' => 'السبب',
+'movetalk' => 'أنقل صفحة \'\'\'النقاش\'\'\' أن أمكن.',
+'movethispage' => 'أنقل هذه الصفحة',
+'mycontris' => 'مساهماتي',
+'mypage' => 'صفحتي',
+'namespace' => 'النطاق:',
+'namespacesall' => 'الكل',
+'navigation' => 'تصفح',
+'nbytes' => '$1 بايت',
+'nchanges' => '$1 تغييرات',
+'newarticle' => '(جديد)',
+'newarticletext' => 'لقد تبعت وصلة لصفحة لم يتم إنشائها بعد.
+لإنشاء هذه الصفحة إبدأ بالكتابة في الصندوق بالأسفل.
+(أنظر في [[ويكيبيديا:مساعدة|صفحة المساعدة]] للمزيد من المعلومات)
+إذا كانت زيارتك لهذه الصفحة بالخطأ، إضغم على زر \'\'رجوع\'\' في متصفح الإنترنت لديك.',
+'newimages' => 'معرض الصور الجديدة',
+'newmessages' => 'لديك $1.',
+'newmessageslink' => 'رسائل جديدة',
+'newpage' => 'صفحة جديدة',
+'newpageletter' => 'ج',
+'newpages' => 'صفحات جديدة',
+'newpassword' => 'كلمة السر الجديدة',
+'newtitle' => 'إلى العنوان الجديد',
+'newusersonly' => ' (للمستخدمين الجدد فقط)',
+'newwindow' => '(يفتح في شباك جديد)',
+'next' => 'التالي',
+'nextn' => '$1 التالية',
+'nlinks' => '$1 وصلة',
+'noarticletext' => '(لا يوجد حاليا أي نص في هذه الصفحة)',
+'noemail' => 'لا يوجد أي عنوان بريدي مسجل للمستخدم "$1".',
+'noemailtext' => 'لم يحدد هذا المستخدم عنوان بريد إلكتروني صحيح،
+أو طلب عدم إستلام الرسائل من المستخدمين الآخرين.',
+'noemailtitle' => 'لا يوجد عنوان بريد إلكتروني',
+'nogomatch' => 'لا يوجد صفحة بنفس العنوان، حاول البحث بشكل مفصل أكثر من خلال إستعمال صندوق البحث أدناه. بإمكانك أيضاً إنشاء <a href="$1" class="new">صفحة جديدة</a> بالعنوان الذي طلبته.',
+'nohistory' => 'لا يوجد تاريخ للتغييرات لهذه الصفحة.',
+'nolinkshere' => 'لا يوجد صفحات تصل لهذه الصفحة.',
+'nolinkstoimage' => 'لا يوجد صفحات تصل لهذه الصورة.',
+'noname' => 'لم تحدد إسم مستخدم صحيح.',
+'nospecialpagetext' => 'لقد طلبت صفحة خاصة لا يمكن التعرف عليها من قبل نظام الويكي.',
+'nosuchspecialpage' => 'لا يوجد صفحة خاصة بهذا الإسم',
+'nosuchuser' => 'لا يوجد مستخدم بالإسم "$1".
+تأكد من إملاء الإسم، أو إستعمل النموذج الموجود في الأسفل لإنشاء مستخدم جديد.',
+'note' => '<strong>ملاحظة:</strong>',
+'notextmatches' => 'لم يتم إيجاد أي نص مطابق',
+'notitlematches' => 'لم يتم إيجاد أي عنوان مطابق',
+'notloggedin' => 'غير مسجل',
+'nowatchlist' => 'لا يوجد شيء في قائمة مراقبتك.',
+'nowiki_tip' => 'أهمل تهيئة الويكي',
+'nstab-category' => 'تصنيف',
+'nstab-help' => 'مساعدة',
+'nstab-image' => 'صورة',
+'nstab-main' => 'مقالة',
+'nstab-mediawiki' => 'رسالة',
+'nstab-special' => 'خاص',
+'nstab-template' => 'قالب',
+'nstab-user' => 'صفحة مستخدم',
+'nstab-wp' => 'حول',
+'ok' => 'موافق',
+'oldpassword' => 'كلمة السر القديمة',
+'orig' => 'الأصلي',
+'orphans' => 'الصفحات اليتيمة',
+'otherlanguages' => ' لغات أخرى',
+'pagemovedsub' => 'تم النقل بنجاح',
+'pagemovedtext' => 'تم نقل الصفحة "[[$1]]" إلى "[[$2]]".',
+'passwordremindertitle' => 'تذكير بكلمة السر من ويكيبيديا',
+'passwordsent' => 'تم إرسال كلمة سر جديدة إلى العنوان البريدي المسجل للمستخدم "$1".
+يرجى محاولة تسجيل الدخول مرة أخرى عند إستلامها.',
+'popularpages' => 'الصفحات المشهورة',
+'portal' => 'بوابة المجتمع',
+'portal-url' => 'ويكيبيديا:بوابة المجتمع',
+'postcomment' => 'أرسل تعليق',
+'powersearch' => 'بحث',
+'preferences' => 'تفضيلات',
+'prefsnologin' => 'غير مسجل',
+'preview' => 'عرض مسبق',
+'previewnote' => 'تذكر، هذا فقط عرض مسبق للصفحة، ولم يتم حفظه بعد!',
+'prevn' => '$1 السابقة',
+'printableversion' => 'نسخة للطباعة',
+'printsubtitle' => '(من http://ar.wikipedia.org)',
+'protectcomment' => 'سبب الحماية',
+'protectedarticle' => 'حماية [[$1]]',
+'protectedpage' => 'صفحة محمية',
+'protectlogpage' => 'سجل_الحماية',
+'protectpage' => 'صفحة محمية',
+'protectthispage' => 'حماية هذه الصفحة',
+'qbbrowse' => 'تصفح',
+'qbedit' => 'تحرير',
+'qbfind' => 'بحث',
+'qbmyoptions' => 'صفحاتي',
+'qbpageinfo' => 'سياق النص',
+'qbpageoptions' => 'هذه الصفحة',
+'qbsettings' => 'خيارات لوحة الوصلات',
+'qbspecialpages' => 'الصفحات الخاصّة',
+'randompage' => 'صفحة عشوائية',
+'rclinks' => 'أظهر آخر $1 تعديل في آخر $2 يوم، $3',
+'rclistfrom' => 'أظهر التغييرات بدأ من $1',
+'rcliu' => '; $1 تعديل من مستخدم مسجل',
+'rcloaderr' => 'تحميل التغييرات الأخيرة',
+'rclsub' => '(لصفحات تصل بها الصفحة "$1")',
+'rcnote' => 'في الأسفل ستجد آخر <strong>$1</strong> تعديل في آخر <strong>$2</strong> أيام.',
+'rcnotefrom' => 'في الأسفل التغييرات منذ <b>$2</b> (ولغاية <b>$1</b>).',
+'readonly' => 'قاعدة البيانات مغلقة',
+'readonlytext' => 'قاعدة البيانات مغلقة حاليا أمام الإضافات والتعديلات، السبب غالبا ما يكون الصيانة، وستعود قاعدة البيانات للوضع الطبيعي قريبا.
+عندما تم أغلاق قاعدة البيانات أمام التعديلات والإضافات تم أعطاء السبب التالي:
+<p>$1',
+'recentchanges' => 'أحدث التغييرات',
+'recentchangescount' => 'عدد العناوين في صفحة أحدث التغييرات',
+'recentchangeslinked' => 'تغييرات ذات علاقة',
+'recentchangestext' => 'تابع آخر التغييرات في الموسوعة من هذه الصفحة.',
+'redirectedfrom' => '(تم التحويل من $1)',
+'remembermypassword' => 'تذكر كلمة السر عبر الجلسات.',
+'removechecked' => 'حذف المواد المختارة من قائمة المراقبة.',
+'removedwatch' => 'تم الحذف من قائمة المراقبة',
+'removedwatchtext' => 'تم حذف الصفحة "$1" من قائمة مراقبتك.',
+'removingchecked' => 'حذف الصفحات المطلوبة من قائمة المراقبة...',
+'returnto' => 'أرجع إلى $1.',
+'retypenew' => 'أعد كتابة كلمة السر الجديدة',
+'revertpage' => 'إسترجاع المقال حتى أخر تعديل من قبل $1',
+'revhistory' => 'تاريخ التغييرات',
+'revnotfound' => 'النسخة غير موجودة',
+'rows' => 'أسطر',
+'savearticle' => 'حفظ الصفحة',
+'savedprefs' => 'تم حفظ تفضيلاتك.',
+'savefile' => 'حفظ الملف',
+'saveprefs' => 'حفظ التفضيلات',
+'scarytranscludefailed' => '[Template fetch failed; sorry]',
+'search' => 'بحث',
+'searchdisabled' => '<p>عذرا! لقد تم إيقاف ميزة البحث في النصوص بشكل مؤقت، لأسباب تتعلق بتأثيرها على الأداء العام. في الوقت الحالي من الممكن أن تستعمل محرك البحث جووجل Google بدل من خاصية البحث في النصوص. من الممكن أن لا يكون البحث في جووجل يشمل آخر التعديلات والصفحات.
+</p>',
+'searchquery' => 'لصيغة البحث "$1"',
+'searchresults' => 'نتائج البحث',
+'searchresultshead' => 'خيارات نتائج البحث',
+'searchresulttext' => 'للمزيد من المعلومات حول البحث في ويكيبيديا، راجع [[ويكيبيديا:تصفح]].',
+'selflinks' => 'صفحات بوصلات ذاتية',
+'servertime' => 'الوقت في الأجهزة الخادمة الآن هو',
+'shortpages' => 'صفحات قصيرة',
+'show' => 'عرض',
+'showdiff' => 'أظهر الفرق',
+'showhideminor' => '$1 التعديلات الطفيفة',
+'showpreview' => 'عرض التعديلات',
+'showtoc' => 'إظهار',
+'sidebar' => '
+* navigation
+** mainpage|mainpage
+** portal-url|portal
+** currentevents-url|currentevents
+** recentchanges-url|recentchanges
+** randompage-url|randompage
+** helppage|help
+** sitesupport-url|sitesupport',
+'sitestats' => 'إحصاءات الموقع',
+'sitestatstext' => 'يوجد <b>$1</b> صفحة في قاعدة بيانات الموسوعة العربية، وهذا يشمل صفحات النقاش، والصفحات الخاصة بنظام ويكيبيديا، والمقالات الصغيرة التي تحتاج تطوير، والتحويلات، وغيرها مما لا يرقى لأن يكون مقالا. إذا تم أهمال تلك الصفحات، فإن عدد الصفحات التي قد تحتوي على مقالات يكون <b>$2</b>.<p>
+تم عرض الصفحات <b>$3</b> مرة، وعدد التعديلات على الصفحات<b>$4</b> تعديل، منذ إنشاء الموسوعة العربية في يوليو/تموز 2003.
+وهذا يعني أن معدل التعديل لكل صفحة <b>$5</b> تعديل، ومعدل عرض كل صفحة <b>$6</b> عرض.
+
+<div dir="ltr">
+There are <b>$1</b> total pages in the database.
+This includes "talk" pages, pages about Wikipedia, minimal "stub"
+pages, redirects, and others that probably don\'t qualify as articles.
+Excluding those, there are <b>$2</b> pages that are probably legitimate
+articles.<p>
+There have been a total of <b>$3</b> page views, and <b>$4</b> page edits
+since the Arabic wikipedia creation in July 2003.
+That comes to <b>$5</b> average edits per page, and <b>$6</b> views per edit.
+
+</div>',
+'sitesubtitle' => ' الموسوعة الحرة',
+'sitesupport' => 'التبرعات',
+'sitetitle' => 'ويكيبيديا',
+'specialpage' => 'صفحة خاصة',
+'specialpages' => 'الصفحات الخاصّة',
+'spheading' => 'الصفحات الخاصة لكل المستخدمين',
+'statistics' => 'إحصاءات',
+'storedversion' => 'النسخة المخزنة',
+'subcategories' => 'التصنيفات الفرعية',
+'subcategorycount' => 'يوجد $1 تصنيف فرعي في هذا التصنيف.',
+'subcategorycount1' => 'هناك تصنيف فرعي واحد في هذا التصنيف.',
+'subject' => 'موضوع',
+'subjectpage' => 'عرض العنوان',
+'successfulupload' => 'تحميل الملف بنجاح',
+'summary' => 'ملخص',
+'sysoptitle' => 'يتطلب صلاحيات مشغل نظام Sysop',
+'talkexists' => 'تم نقل الصفحة بنجاح، لكن لم
+يتم نقل صفحة النقاش المرافقة، بسبب وجود صفحة نقاش
+مسبقا تحت العوان الجديد.
+يرجى نقل محتويات صفحة النقاش يدويا، ودمجها مع المحتويات السابقة.',
+'talkpage' => 'ناقش هذه الصفحة',
+'talkpagemoved' => 'تم نقل صفحة النقاش أيضا.',
+'talkpagenotmoved' => '<strong>لم</strong> يتم نقل صفحة النقاش.',
+'templatesused' => 'القوالب المستخدمة في هذه الصفحة:',
+'textboxsize' => 'أبعاد صندوق النصوص',
+'thumbnail-more' => 'تكبير',
+'thumbsize' => 'Thumbnail size :',
+'toc' => 'فهرست',
+'tog-underline' => 'Underline links',
+'toolbox' => 'أدوات',
+'uclinks' => 'عرض آخر $1 تعديل;  عرض أخر $2 يوم.',
+'ucnote' => 'في الأسفل ستجد آخر <b>$1</b> تعديل لهذا المستخدم في <b>$2</b> أيام.',
+'uctop' => ' (أعلى)',
+'unblocklink' => 'رفع المنع عن مستخدم',
+'uncategorizedcategories' => 'تصنيفات غير مصنفة',
+'uncategorizedpages' => 'صفحات غير مصنفة',
+'undelete' => 'إرجاع صفحات محذوفة',
+'unprotect' => 'أزل الحماية',
+'unprotectcomment' => 'سبب إزالة الحماية',
+'unprotectedarticle' => 'ازالة حماية [[$1]]',
+'unprotectthispage' => 'أزل الحماية عن الصفحة',
+'unusedimages' => 'صور غير مستعملة',
+'upload' => 'تحميل ملف',
+'uploadbtn' => 'تحميل الملف',
+'uploaddisabled' => 'عذرا، تم إيقاف خاصية تحميل الملفات.',
+'uploadedfiles' => 'الملفات المحملة',
+'uploadedimage' => 'تم تحميل "$1"',
+'uploaderror' => 'خطأ في التحميل',
+'uploadlink' => 'تحميل الصور',
+'uploadlogpagetext' => 'في الأسفل قائمة بأخر الملفات التي تم تحميلها.
+كل الأوقات المعروضة هي حسب توقيت الأجهزةالخادمة (UTC).
+<ul>
+</ul>',
+'uploadnologin' => 'لم تقم بتسجيل الدخول',
+'uploadnologintext' => 'يجب أن تكون <a href="/wiki/Special:Userlogin">مسجلا الدخول</a>
+لتتمكن من تحميل الملفات.',
+'uploadtext' => '<strong>توقف!</strong>
+قبل تحميل أي ملف تأكد من قرائتك وثيقة <a href="/wiki/Wikipedia:Image_use_policy">سياسة إستعمال الصور</a>.
+إذا وجد ملف بنفس الإسم في ويكيبيديا سيتم إستبدال الملف بدون أي تحذير أو إشعار مسبق.
+فإذا لم يكن الملف تحديثا لملف مسبق، تأكد من أن إسم الملف غير موجود من قبل.
+لعرض أو البحث في الملفات التي تم تحميلها من قبل إذهب إلى <a href="/wiki/Special:Imagelist">قائمة الملفات المحملة</a>.
+يتم تسجيل كل حالات التحميل والحذث للملفات في <a href="/wiki/Wikipedia:Upload_log">سجل التحميل</a>.
+<p>إستعمل النموذج الموجود الموجود في الأسفل لتحميل الصور التي تساعد على توضيح مقالاتك.
+في أغلب متصفحات الإنترنت سترى زر "إستعراض..." الذي سيفتح لك شاشة إختيار الملفات. إختيار الملف سيملأ الخانة المجاورة للزر بإسم الملف وموقعه.
+يجب عليك كذلك التأكيد على أنك لم تخالف أي حقوق نسخ من خلال تحميلك للملف.
+إضغط على زر "تحميل الملف" لإنهاء عملية التحميل.
+قد تأخذ هذه العملية بعض الوقت، بناء على سرعة الإتصال للإنترنت لديك.
+<p>أنواع الملفات المفضلة هنا هي: JPEG للصور الفوتوغرافية، PNG للرسومات وصور الصغيرة، و OGG لملفات الصوتية.
+يرجى تسمية الملفات بشكل يوضح المحتوي، وذلك لمنع أي إلتباس.
+لوضع الصورة في مقالتك، إستعمل وصلة على النحو التالي:<b><nowiki>[[صورة:file.jpg]]</nowiki></b> أو <b><nowiki>[[صورة:file.jpg|نص بديل]]</nowiki></b> أو <b><nowiki>[[media:file.ogg]]</nowiki></b> للملفات الصوتية.
+<p>تذكر أنه بما أن هذا نظام [[ويكي]]، فقد يقوم آخرون بتغيير أو بحذف الملفات التي تم تحميلها إذا كانوا يعتقدون أن هذا في مصلحة الموسوعة. وقد يتم منعك من تحميل الملفات إذا تبين أنك تستعمل النظام بشكل مسيئ.',
+'uploadwarning' => 'تحذير تحميل الملفات',
+'userexists' => 'إسم المستخدم الذي إخترته مستخدم من قبل، يرجى إختيار إسم مستخدم آخر.',
+'userlogin' => 'دخول',
+'userlogout' => 'خروج',
+'userpage' => 'عرض صفحة المستخدم',
+'userstats' => 'إحصاءات المستخدم',
+'userstatstext' => 'يوجد <b>$1</b> عضو مسجل. ومنهم <b>$2</b> إداريين. (أنظر $3)
+<div dir="ltr">
+There are <b>$1</b> registered users.
+<b>$2</b> of these are administrators (see $3).
+</div>',
+'version' => 'رقم النسخة',
+'viewcount' => 'تم عرض محتويات هذه الصفحة $1 مرة.',
+'viewsource' => 'عرض المصدر للمقالة',
+'viewtalkpage' => 'عرض النقاش',
+'wantedpages' => 'صفحات مطلوبة',
+'watchdetails' => '($1  صفحة يتم مراقبتها، بدون عد صفحات النقاش;
+$2 تحرير تم على الصفحات منذ بدأ المراقبة;
+$3...
+<a href=\'$4\'>عرض وتحرير القائمة الكاملة</a>.)',
+'watcheditlist' => 'فيما يلي قائمة مرتبة أبجديا للصفحات الموجودة في قائمة المراقبة لديك.
+أختر الصفحات التري تريد إزالتها من خلال الإشارة عليها من الصندوق بجانبها.
+وإضغط على زر \'حذف المختارات\' في آخر الصفحة.',
+'watchlist' => 'قائمة مراقبتي',
+'watchlistcontains' => 'تحتوي قائمة المراقبة لديك على $1 صفحة.',
+'watchlistsub' => '(للمستخدم "$1")',
+'watchmethod-list' => 'إظهار التحريرات في الصفحات المراقبة',
+'watchmethod-recent' => 'تفحص التغييرات الأخيرة في قائمة المراقة لديك',
+'watchnochange' => 'لم يتم تعديل أي صفحة في قائمة المراقبة لديك خلال الفترة المحددة.',
+'watchnologin' => 'غير مسجل',
+'watchnologintext' => 'يجب أن تقوم  <a href="/wiki/Special:Userlogin">بتسجيل الدخول</a>
+لتتمكن من تعديل قائمة المراقبة لديك.',
+'watchthis' => 'راقب هذه الصفحة',
+'welcomecreation' => '<h2>أهلا بك يا , $1!</h2><p> تم إنشاء حسابك.
+لا تنسى أن تقوم بتغيير وتحديد تفضيلاتك في ويكيبيديا.',
+'whatlinkshere' => 'ماذا يرتبط هنا؟',
+'whitelistacctitle' => 'لا يسمح لك بإنشاء إشتراك',
+'whitelistedittext' => 'يجب عليك  [[Special:Userlogin|تسجيل الدخول]] لتتمكن من تعديل الصفحات.',
+'whitelistedittitle' => 'الدخول ضروري للقيام بالتعديل',
+'whitelistreadtext' => 'يجب عليك [[Special:Userlogin|تسجيل الدخول]] لتتمكن من قراءة المقالات.',
+'whitelistreadtitle' => 'تسجيل الدخول ضروري للقراءة',
+'wikipediapage' => 'عرض الصفحة العامة',
+'wlnote' => 'في الأسفل آخر $1 تعديل في آخر <b>$2</b> ساعة.',
+'wlsaved' => 'هذه نسخة مخزنة من قائمة المراقبة لديك.',
+'wlshowlast' => 'عرض أخر $1 ساعات $2 أيام $3',
+'wrongpassword' => 'كلمة السر التي أدخلتها غير صحيحة، يرجى إعادة المحاولة.',
+'yourdiff' => 'الفروقات',
+'youremail' => 'بريدك الإلكتروني*',
+'yourname' => 'اسمك',
+'yournick' => 'اللقب الخاص بك (للتواقيع)',
+'yourpassword' => 'كلمة السر خاصتك',
+'yourpasswordagain' => 'أعد كتابة كلمة السر',
+'yourrealname' => 'اسمك الحقيقي*',
+'yourtext' => 'النص الذي كتبته',
+);
+
+class LanguageAr extends LanguageUtf8 {
+       var $digitTransTable = array(
+               '0' => '٠',
+               '1' => '١',
+               '2' => '٢',
+               '3' => '٣',
+               '4' => '٤',
+               '5' => '٥',
+               '6' => '٦',
+               '7' => '٧',
+               '8' => '٨',
+               '9' => '٩',
+               '%' => '٪',
+               '.' => '٫',
+               ',' => '٬'
+       );
+
+       function getNamespaces() {
+               global $wgNamespaceNamesAr;
+               return $wgNamespaceNamesAr;
+       }
+
+       function getMonthAbbreviation( $key ) {
+               /* No abbreviations in Arabic */
+               return $this->getMonthName( $key );
+       }
+
+       function isRTL() {
+               return true;
+       }
+
+       function linkPrefixExtension() {
+               return true;
+       }
+
+       function getDefaultUserOptions() {
+               $opt = parent::getDefaultUserOptions();
+
+               # Swap sidebar to right side by default
+               $opt['quickbar'] = 2;
+
+               # Underlines seriously harm legibility. Force off:
+               $opt['underline'] = 0;
+               return $opt ;
+       }
+
+       function fallback8bitEncoding() {
+               return 'windows-1256';
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesAr;
+               if( isset( $wgAllMessagesAr[$key] ) ) {
+                       return $wgAllMessagesAr[$key];
+               } else {
+                       return parent::getMessage( $key );
+               }
+       }
+
+       function formatNum( $number ) {
+               global $wgTranslateNumerals;
+               if( $wgTranslateNumerals ) {
+                       return strtr( $number, $this->digitTransTable );
+               } else {
+                       return $number;
+               }
+       }
+}
+
+?>
diff --git a/languages/LanguageArc.php b/languages/LanguageArc.php
new file mode 100644 (file)
index 0000000..3b61cee
--- /dev/null
@@ -0,0 +1,18 @@
+<?php
+/** Aramaic language file ( ܕܥܒܪܸܝܛ )
+  *
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+require_once( 'LanguageUtf8.php' );
+
+class LanguageArc extends LanguageUtf8 {
+       #FIXME: inherit almost everything for now
+
+       function isRTL() {
+               return true;
+       }
+}
+
+?>
diff --git a/languages/LanguageAs.php b/languages/LanguageAs.php
new file mode 100644 (file)
index 0000000..411a2a1
--- /dev/null
@@ -0,0 +1,34 @@
+<?php
+/** Assamese (অসমীয়া)
+  *
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+require_once( 'LanguageUtf8.php' );
+
+class LanguageAs extends LanguageUtf8 {
+       var $digitTransTable = array(
+               '0' => '০',
+               '1' => '১',
+               '2' => '২',
+               '3' => '৩',
+               '4' => '৪',
+               '5' => '৫',
+               '6' => '৬',
+               '7' => '৭',
+               '8' => '৮',
+               '9' => '৯'
+       );
+
+       function formatNum( $number ) {
+               global $wgTranslateNumerals;
+               if( $wgTranslateNumerals ) {
+                       return strtr( $number, $this->digitTransTable );
+               } else {
+                       return $number;
+               }
+       }
+}
+
+?>
diff --git a/languages/LanguageAst.php b/languages/LanguageAst.php
new file mode 100644 (file)
index 0000000..d2176ff
--- /dev/null
@@ -0,0 +1,49 @@
+<?php
+/** Asturian
+  *
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+/** */
+require_once( 'LanguageUtf8.php' );
+
+# See Language.php for notes.
+
+if($wgMetaNamespace === FALSE)
+       $wgMetaNamespace = str_replace( ' ', '_', $wgSitename );
+
+/* $wgMetaNamespace == 'Uiquipedia' */
+/* private */ $wgNamespaceNamesAst = array(
+       NS_MEDIA            => 'Media',
+       NS_SPECIAL          => 'Especial',
+       NS_MAIN             => '',
+       NS_TALK             => 'Discusión',
+       NS_USER             => 'Usuariu',
+       NS_USER_TALK        => 'Usuariu_discusión',
+       NS_PROJECT          => $wgMetaNamespace,
+       NS_PROJECT_TALK     => $wgMetaNamespace . '_discusión',
+       NS_IMAGE            => 'Imaxen',
+       NS_IMAGE_TALK       => 'Imaxen_discusión',
+       NS_MEDIAWIKI        => 'MediaWiki',
+       NS_MEDIAWIKI_TALK   => 'MediaWiki_discusión',
+       NS_TEMPLATE         => 'Plantilla',
+       NS_TEMPLATE_TALK    => 'Plantilla_discusión',
+       NS_HELP             => 'Ayuda',
+       NS_HELP_TALK        => 'Ayuda_discusión',
+       NS_CATEGORY         => 'Categoría',
+       NS_CATEGORY_TALK    => 'Categoría_discusión',
+) + $wgNamespaceNamesEn;
+
+
+/** @package MediaWiki */
+class LanguageAst extends LanguageUtf8 {
+
+       function getNamespaces() {
+               global $wgNamespaceNamesAst;
+               return $wgNamespaceNamesAst;
+       }
+
+}
+
+?>
diff --git a/languages/LanguageBe.php b/languages/LanguageBe.php
new file mode 100644 (file)
index 0000000..a18d22e
--- /dev/null
@@ -0,0 +1,590 @@
+<?php
+/** Belarusian (Беларуская мова)
+  *
+  * @package MediaWiki
+  * @subpackage Language
+  *
+  * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
+  * @bug 1638, 2135
+  * @link http://be.wikipedia.org/wiki/Talk:LanguageBe.php
+  * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
+  * @license http://www.gnu.org/copyleft/fdl.html GNU Free Documentation License
+  */
+
+require_once('LanguageUtf8.php');
+
+/* private */ $wgNamespaceNamesBe = array(
+       NS_MEDIA                => 'Мэдыя',
+       NS_SPECIAL              => 'Спэцыяльныя',
+       NS_MAIN                 => '',
+       NS_TALK                 => 'Абмеркаваньне',
+       NS_USER                 => 'Удзельнік',
+       NS_USER_TALK            => 'Гутаркі_ўдзельніка',
+       NS_PROJECT              => $wgMetaNamespace,
+       NS_PROJECT_TALK         => 'Абмеркаваньне_' . $wgMetaNamespace,
+       NS_IMAGE                => 'Выява',
+       NS_IMAGE_TALK           => 'Абмеркаваньне_выявы',
+       NS_MEDIAWIKI            => 'MediaWiki',
+       NS_MEDIAWIKI_TALK       => 'Абмеркаваньне_MediaWiki',
+       NS_TEMPLATE             => 'Шаблён',
+       NS_TEMPLATE_TALK        => 'Абмеркаваньне_шаблёну',
+       NS_HELP                 => 'Дапамога',
+       NS_HELP_TALK            => 'Абмеркаваньне_дапамогі',
+       NS_CATEGORY             => 'Катэгорыя',
+       NS_CATEGORY_TALK        => 'Абмеркаваньне_катэгорыі'
+);
+
+/* private */ $wgQuickbarSettingsBe = array(
+       'Не паказваць', 'Замацаваная зьлева', 'Замацаваная справа', 'Рухомая зьлева'
+);
+
+/* private */ $wgSkinNamesBe = array(
+       'standard' => 'Клясычны',
+       'nostalgia' => 'Настальгія',
+       'cologneblue' => 'Кёльнскі смутак',
+       'davinci' => 'Да Вінчы',
+       'mono' => 'Мона',
+       'monobook' => 'Монакніга',
+       'myskin' => 'MySkin',
+       'chick' => 'Цыпа'
+) + $wgSkinNamesEn;
+
+/* private */ $wgMagicWordsBe = array(
+       MAG_REDIRECT            => array( 0,    '#redirect', '#перанакіраваньне' ),
+       MAG_NOTOC               => array( 0,    '__NOTOC__', '__БЯЗЬ_ЗЬМЕСТУ__' ),
+       MAG_FORCETOC            => array( 0,    '__FORCETOC__', '__ЗЬМЕСТ_ПРЫМУСАМ__' ),
+       MAG_TOC                 => array( 0,    '__TOC__', '__ЗЬМЕСТ__'  ),
+       MAG_NOEDITSECTION       => array( 0,    '__NOEDITSECTION__', '__БЕЗ_РЭДАГАВАНЬНЯ_СЭКЦЫІ__' ),
+       MAG_START               => array( 0,    '__START__', '__ПАЧАТАК__'),
+       MAG_CURRENTMONTH        => array( 1,    'CURRENTMONTH', 'БЯГУЧЫ_МЕСЯЦ'),
+       MAG_CURRENTMONTHNAME    => array( 1,    'CURRENTMONTHNAME', 'НАЗВА_БЯГУЧАГА_МЕСЯЦА'),
+       MAG_CURRENTDAY          => array( 1,    'CURRENTDAY', 'БЯГУЧЫ_ДЗЕНЬ'),
+       MAG_CURRENTDAYNAME      => array( 1,    'CURRENTDAYNAME', 'НАЗВА_БЯГУЧАГА_ДНЯ'),
+       MAG_CURRENTYEAR         => array( 1,    'CURRENTYEAR', 'БЯГУЧЫ_ГОД'),
+       MAG_CURRENTTIME         => array( 1,    'CURRENTTIME', 'БЯГУЧЫ_ЧАС'),
+       MAG_NUMBEROFARTICLES    => array( 1,    'NUMBEROFARTICLES', 'КОЛЬКАСЬЦЬ_АРТЫКУЛАЎ'),
+       MAG_CURRENTMONTHNAMEGEN => array( 1,    'CURRENTMONTHNAMEGEN', 'НАЗВА_БЯГУЧАГА_МЕСЯЦА_Ў_РОДНЫМ_СКЛОНЕ' ),
+       MAG_PAGENAME            => array( 1,    'PAGENAME', 'НАЗВА_СТАРОНКІ' ),
+       MAG_PAGENAMEE           => array( 1,    'PAGENAMEE', 'НАЗВА_СТАРОНКІ_2' ),
+       MAG_NAMESPACE           => array( 1,    'NAMESPACE', 'ПРАСТОРА_НАЗВАЎ'),
+       MAG_SUBST               => array( 0,    'SUBST:', 'ПАДСТАНОЎКА:'),
+       MAG_MSGNW               => array( 0,    'MSGNW:', 'ПАВЕДАМЛЕНЬНЕ_БЯЗЬ_ВІКІ:' ),
+       MAG_END                 => array( 0,    '__END__', '__КАНЕЦ__'   ),
+       MAG_IMG_THUMBNAIL       => array( 1,    'thumbnail', 'thumb', 'значак', 'міні'),
+       MAG_IMG_RIGHT           => array( 1,    'right', 'справа' ),
+       MAG_IMG_LEFT            => array( 1,    'left', 'зьлева'   ),
+       MAG_IMG_NONE            => array( 1,    'none', 'няма'         ),
+       MAG_IMG_WIDTH           => array( 1,    '$1px', '$1пкс'                 ),
+       MAG_IMG_CENTER          => array( 1,    'center', 'centre', 'цэнтар' ),
+       MAG_IMG_FRAMED          => array( 1,    'framed', 'enframed', 'frame', 'рамка' ),
+       MAG_INT                 => array( 0,    'INT:'             ),
+       MAG_SITENAME            => array( 1,    'SITENAME', 'НАЗВА_САЙТУ'),
+       MAG_NS                  => array( 0,    'NS:', 'ПН:' ),
+       MAG_LOCALURL            => array( 0,    'LOCALURL:', 'ЛЯКАЛЬНЫ_АДРАС:' ),
+       MAG_LOCALURLE           => array( 0,    'LOCALURLE:', 'ЛЯКАЛЬНЫ_АДРАС_2' ),
+       MAG_SERVER              => array( 0,    'SERVER', 'СЭРВЭР' ),
+       MAG_GRAMMAR             => array( 0,    'GRAMMAR:', 'ГРАМАТЫКА:'       ),
+       MAG_NOTITLECONVERT      => array( 0,    '__NOTITLECONVERT__', '__NOTC__', '__БЕЗ_КАНВЭРТАЦЫІ_НАЗВЫ__'),
+       MAG_NOCONTENTCONVERT    => array( 0,    '__NOCONTENTCONVERT__', '__NOCC__', '__БЕЗ_КАНВЭРТАЦЫІ_ТЭКСТУ__'),
+       MAG_CURRENTWEEK         => array( 1,    'CURRENTWEEK', 'БЯГУЧЫ_ТЫДЗЕНЬ'),
+       MAG_CURRENTDOW          => array( 1,    'CURRENTDOW', 'БЯГУЧЫ_ДЗЕНЬ_ТЫДНЯ'),
+);
+
+/* private */ $wgAllMessagesBe = array(
+# Belarusian Cyrillic alphabet:
+# Аа Бб Вв Гг Дд (ДЖдж ДЗдз) Ее Ёё Жж Зз Іі Йй Кк Лл Мм Нн Оо Пп Рр Сс Тт Уу Ўў Фф Хх Цц Чч Шш Ыы Ьь Ээ Юю Яя
+# Short ([^a-z]): абвгд (ДЖдж ДЗдз) еёжзійклмнопрстуўфхцчшыьэюя
+#
+# Belarusian Latin alphabet:
+# Aa Bb Cc Ćć Čč Dd (DŽdž DZdz) Ee Ff Gg Hh Ii Jj Kk Ll Łł Mm Be Ńń Oo Pp Rr Ss Śś Šš Tt Uu Ŭŭ Vv Yy Zz Źź Žž
+# Short ([^a-z]): ćč (DŽdž)  łńśšŭźž
+
+# Note: use /u (unicode) and /i to turn of case-sensativity.
+'linktrail' => '/^([абвгґджзеёжзійклмнопрстуўфхцчшыьэюяćčłńśšŭźža-z]+)(.*)$/sDu',
+
+'1movedto2' => '$1 перанесеная ў $2',
+'1movedto2_redir' => '$1 перанесеная ў $2, выдаліўшы перанакіраваньне',
+'about' => 'Пра',
+'aboutpage' => 'Project:Пра {{SITENAME}}',
+'aboutsite' => 'Пра {{SITENAME}}',
+'accmailtext' => 'Пароль для \'$1\' быў адасланы па адрасу $2.',
+'accmailtitle' => 'Пароль адасланы.',
+'addedwatch' => 'Даданая ў сьпіс назіраньня',
+'addgroup' => 'Дадаць групу',
+'administrators' => 'Project:Адміністрацыя',
+'allarticles' => 'Усе артыкулы',
+'allmessages' => 'Усе сыстэмныя паведамленьні',
+'allmessagescurrent' => 'Бягучы тэкст',
+'allmessagesname' => 'Назва',
+'allmessagestext' => 'Сьпіс усіх сыстэмных паведамленьняў, якія існуюць у прасторы назваў \'\'\'MediaWiki:\'\'\'.',
+'allpages' => 'Усе старонкі',
+'allpagesnext' => 'Наступныя',
+'allpagesprev' => 'Папярэднія',
+'allpagessubmit' => 'Паказаць',
+'alphaindexline' => 'ад $1 да $2',
+'ancientpages' => 'Найстарэйшыя старонкі',
+'and' => 'і',
+'anonymous' => 'Ананімныя ўдзельнікі і ўдзельніцы {{SITENAME}}',
+'apr' => '04',
+'april' => 'красавіка',
+'article' => 'Артыкул',
+'articlepage' => 'Паказаць артыкул',
+'aug' => '08',
+'august' => 'жніўня',
+'badfilename' => 'Назва выявы была зьмененая на «$1».',
+'badfiletype' => '«.$1» не зьяўляецца рэкамэндаваным фарматам для файлаў выяваў.',
+'badipaddress' => 'Некарэктны IP адрас',
+'badtitle' => 'Некарэктная назва',
+'blanknamespace' => 'Артыкул',
+'bydate' => 'па даце',
+'byname' => 'па назьве',
+'bysize' => 'па памеры',
+'cancel' => 'Адмяніць',
+'cannotdelete' => 'Немагчыма выдаліць указаную старонку альбо выяву. (Магчыма, яна ўжо выдаленая кімсьці іншым.)',
+'categories' => 'Катэгорыі',
+'categoriespagetext' => 'У вікі існуюць наступныя катэгорыі:',
+'category' => 'катэгорыя',
+'category_header' => 'Артыкулы ў катэгорыі \'$1\'',
+'categoryarticlecount' => 'У катэгорыі ёсьць $1 артыкул(а,аў).',
+'categoryarticlecount1' => 'У катэгорыі ёсьць $1 артыкул.',
+'changepassword' => 'Зьмяніць пароль',
+'compareselectedversions' => 'Параўнаць выбраныя вэрсіі',
+'confirmprotecttext' => 'Вы сапраўды жадаеце абараніць гэтую старонку?',
+'contribslink' => 'унёсак',
+'contributions' => 'Унёсак удзельніка/удзельніцы',
+'copyright' => 'Зьмест старонкі падпадае пад ліцэнзію $1.',
+'copyrightpage' => 'Project:Аўтарскія правы',
+'copyrightpagename' => 'Аўтарскія правы {{SITENAME}}',
+'copyrightwarning' => '<strong>НІ Ў ЯКІМ РАЗЕ НЕ СТАЎЦЕ БЕЗ ДАЗВОЛУ ТЭКСТЫ, ЯКІЯ АБАРОНЕНЫЯ АЎТАРСКІМ ПРАВАМ</strong><br />
+Please note that all contributions to {{SITENAME}} are
+considered to be released under the $2
+ (see $1 for details).
+If you don\'t want your writing to be edited mercilessly and redistributed
+at will, then don\'t submit it here.<br />
+You are also promising us that you wrote this yourself, or copied it from a
+public domain or similar free resource.<br />
+<strong>DO NOT SUBMIT COPYRIGHTED WORK WITHOUT PERMISSION!</strong>',
+'couldntremove' => 'Немагчыма выдаліць «$1»...',
+'createaccount' => 'Стварыць новы рахунак',
+'createaccountmail' => 'па электроннай пошце',
+'creditspage' => 'Падзякі',
+'cur' => 'бяг',
+'currentevents' => 'Бягучыя падзеі',
+'currentevents-url' => 'Бягучыя падзеі',
+'currentrev' => 'Бягучая вэрсія',
+'currentrevisionlink' => 'паказаць бягучую вэрсію',
+'data' => 'Дадзеныя',
+'databaseerror' => 'Памылка базы дадзеных',
+'dateformat' => 'Фармат даты',
+'deadendpages' => 'Тупіковыя старонкі',
+'dec' => '12',
+'december' => 'сьнежня',
+'delete' => 'Выдаліць',
+'deletecomment' => 'Прычына выдаленьня',
+'deletedarticle' => 'выдалены «$1»',
+'deletedrevision' => 'Выдаленая старая вэрсія $1.',
+'deleteimg' => 'выдаліць',
+'deleteimgcompletely' => 'Выдаліць усе вэрсіі',
+'deletepage' => 'Выдаліць старонку',
+'deletesub' => '(Выдаленьне «$1»)',
+'deletethispage' => 'Выдаліць гэтую старонку',
+'dellogpagetext' => 'Сьпіс апошніх выдаленьняў.',
+'diff' => 'розьн',
+'difference' => '(Адрозьненьні паміж вэрсіямі)',
+'disambiguationstext' => 'The following pages link to a <i>disambiguation page</i>. They should link to the appropriate topic instead.<br />A page is treated as dismbiguation if it is linked from $1.<br />Links from other namespaces are <i>not</i> listed here.',
+'disclaimerpage' => 'Project:Адмова ад адказнасьці',
+'disclaimers' => 'Адмова ад адказнасьці',
+'doubleredirects' => 'Двайныя перанакіраваньні',
+'edit' => 'Рэдагаваць',
+'editconflict' => 'Канфлікт рэдагаваньня: $1',
+'editcurrent' => 'Рэдагаваць бягучую вэрсію гэтага артыкула',
+'editgroup' => 'Рэдагаваць групу',
+'edithelp' => 'Дапамога ў рэдагаваньні',
+'edithelppage' => 'Дапамога:Рэдагаваньне',
+'editing' => 'Рэдагаваньне: $1',
+'editingcomment' => 'Рэдагаваньне: $1 (камэнтар)',
+'editingsection' => 'Рэдагаваньне: $1 (сэкцыя)',
+'editsection' => 'рэдагаваць',
+'editthispage' => 'Рэдагаваць гэтую старонку',
+'editusergroup' => 'Рэдагаваць групы ўдзельнікаў і ўдзельніц',
+'emailflag' => 'Не прымаць электронную пошту ад іншых удзельнікаў і ўдзельніц',
+'emailfrom' => 'Ад',
+'emailmessage' => 'Паведамленьне',
+'emailpage' => 'Даслаць ліст ўдзельніку ці ўдзельніцы па электроннай пошце',
+'emailsend' => 'Даслаць',
+'emailsubject' => 'Тэма',
+'emailto' => 'Каму',
+'emailuser' => 'Даслаць ліст па электроннай пошце гэтаму ўдзельніку/гэтай удзельніцы',
+'error' => 'Памылка',
+'errorpagetitle' => 'Памылка',
+'exblank' => 'старонка была пустая',
+'export' => 'Экспартаваць старонкі',
+'exportcuronly' => 'Экспартаваць толькі бягучую вэрсію, бяз поўнай гісторыі',
+'extlink_tip' => 'Зьнешняя спасылка (не забывайцеся пачынаць з http:// )',
+'feb' => '02',
+'february' => 'лютага',
+'filecopyerror' => 'Немагчыма cкапіяваць файл «$1» у «$2».',
+'filedeleteerror' => 'Немагчыма выдаліць файл «$1».',
+'filedesc' => 'Апісаньне',
+'filename' => 'Назва файла',
+'filenotfound' => 'Немагчыма знайсьці файл «$1».',
+'filerenameerror' => 'Немагчыма перайменаваць файл «$1» у «$2».',
+'filesource' => 'Крыніца',
+'friday' => 'пятніца',
+'geo' => 'Геаграфічныя каардынаты',
+'getimagelist' => 'атрыманьне сьпісу выяваў',
+'go' => 'Старонка',
+'help' => 'Дапамога',
+'helppage' => 'Дапамога:Зьмест',
+'hide' => 'схаваць',
+'hidetoc' => 'схаваць',
+'hist' => 'гіст',
+'history' => 'Гісторыя старонкі',
+'history_short' => 'Гісторыя',
+'historywarning' => 'Папярэджаньне: у старонкі, якую Вы зьбіраецеся выдаліць, ёсьць гісторыя:',
+'hr_tip' => 'Гарызантальная лінія (не выкарыстоўвайце часта)',
+'ignorewarning' => 'Праігнараваць папярэджаньне і захаваць файл.',
+'illegalfilename' => 'Назва файла «$1» зьмяшчае сымбалі, якія нельга выкарыстоўваць у назвах старонак. Калі ласка, зьмяніце назву файла і паспрабуйце загрузіць яго зноў.',
+'ilsubmit' => 'Шукаць',
+'image_sample' => 'Прыклад.jpg',
+'imagelist' => 'Сьпіс выяваў',
+'imagelisttext' => 'Сьпіс $1 выяваў, адсартаваных $2.',
+'imagepage' => 'Паказаць старонку выявы',
+'imgdelete' => 'выдаліць',
+'imgdesc' => 'апісаньне',
+'imghistory' => 'Гісторыя выявы',
+'import' => 'Імпартаваць старонкі',
+'importfailed' => 'Немагчыма імпартаваць: $1',
+'info_short' => 'Інфармацыя',
+'infosubtitle' => 'Інфармацыя пра старонку',
+'internalerror' => 'Унутраная памылка',
+'ip_range_invalid' => 'Некарэктны дыяпазон IP адрасоў.',
+'ipaddress' => 'IP адрас/Імя ўдзельніка/ўдзельніцы',
+'ipbreason' => 'Прычына',
+'isredirect' => 'старонка-перанакіраваньне',
+'jan' => '01',
+'january' => 'студзеня',
+'jul' => '07',
+'july' => 'ліпеня',
+'jun' => '06',
+'june' => 'чэрвеня',
+'lastmodified' => 'Гэтая старонка апошні раз рэдагавалася $1.',
+'lastmodifiedby' => 'Гэтую старонку апошні раз рэдагаваў $2 $1.',
+'link_tip' => 'Унутраная спасылка',
+'linklistsub' => '(Сьпіс спасылак)',
+'linkshere' => 'Наступныя старонкі спасылаюцца на гэтую:',
+'linkstoimage' => 'Наступныя старонкі спасылаюцца на гэтую выяву:',
+'listform' => 'сьпіс',
+'listusers' => 'Сьпіс удзельнікаў і ўдзельніц',
+'loadhist' => 'Загрузка гісторыі старонкі',
+'loadingrev' => 'Загрузка вэрсіі для параўнаньня',
+'localtime' => 'Мясцовы час',
+'logout' => 'Выйсьці',
+'lonelypages' => 'Старонкі-сіраціны',
+'longpages' => 'Доўгія старонкі',
+'mailmypassword' => 'Даслаць мне новы пароль',
+'mainpage' => 'Галоўная старонка',
+'maintenance' => 'Старонка падтрымкі',
+'makesysopname' => 'Імя ўдзельніка/ўдзельніцы:',
+'mar' => '03',
+'march' => 'сакавіка',
+'math_sample' => 'Зьмясьціце тут формулу',
+'math_syntax_error' => 'сынтаксычная памылка',
+'math_tip' => 'Матэматычная формула (LaTeX)',
+'math_unknown_error' => 'невядомая памылка',
+'math_unknown_function' => 'невядомая функцыя',
+'may' => '05',
+'may_long' => 'траўня',
+'media_sample' => 'Прыклад.ogg',
+'media_tip' => 'Спасылка на мэдыя-файл',
+'minlength' => 'Назва выявы павінна быць не карацейшай за тры сымбалі.',
+'minoredit' => 'Гэта дробная праўка',
+'minoreditletter' => 'Д',
+'monday' => 'панядзелак',
+'move' => 'Перанесьці',
+'movearticle' => 'Перанесьці старонку',
+'movedto' => 'перанесеная ў',
+'movepage' => 'Перанесьці старонку',
+'movepagebtn' => 'Перанесьці старонку',
+'movetalk' => 'Перанесьці таксама старонку «абмеркаваньня», калі гэта магчыма.',
+'movethispage' => 'Перанесьці гэтую старонку',
+'mw_math_html' => 'HTML калі магчыма, інакш PNG',
+'mw_math_mathml' => 'MathML калі магчыма (экспэрымэнтальна)',
+'mw_math_simple' => 'HTML у простых выпадках, інакш PNG',
+'mycontris' => 'Мой унёсак',
+'mypage' => 'Мая старонка',
+'mytalk' => 'Мае размовы',
+'navigation' => 'Навігацыя',
+'newarticle' => '(Новы)',
+'newbies' => 'Пачынаючыя ўдзельнікі і ўдзельніцы',
+'newimages' => 'Галерэя новых выяваў',
+'newmessages' => 'Вы атрымалі $1.',
+'newmessageslink' => 'новыя паведамленьні',
+'newpage' => 'Новая старонка',
+'newpageletter' => 'Н',
+'newpages' => 'Новыя старонкі',
+'newpassword' => 'Новы пароль',
+'newtitle' => 'Новая назва',
+'newusersonly' => ' (толькі для новых удзельнікаў і ўдзельніц)',
+'newwindow' => '(адчыняецца ў новым акне)',
+'nextdiff' => 'Перайсьці да наступнай зьмены →',
+'nextn' => 'наступныя $1',
+'nextpage' => 'Наступная старонка ($1)',
+'noarticletext' => '(Зараз тэкст на гэтай старонцы адсутнічае)',
+'nodb' => 'Немагчыма выбраць базу дадзеных $1',
+'noemailtitle' => 'Адрас электроннай пошты адсутнічае',
+'nogomatch' => 'Старонкі з гэткай назвай не існуе.',
+'nohistory' => 'Гісторыя зьменаў для гэтай старонкі адсутнічае.',
+'noimages' => 'Выявы адсутнічаюць.',
+'nolinkshere' => 'Ніводная старонка сюды не спасылаецца.',
+'nolinkstoimage' => 'Ніводная старонка не спасылаецца на гэтую выяву.',
+'nosuchaction' => 'Няма такога дзеяньня',
+'nosuchspecialpage' => 'Такой спэцыяльнай старонкі не існуе',
+'nosuchuser' => 'Не існуе ўдзельніка ці ўдзельніцы «$1».
+Праверце напісаньне, альбо выкарыстайце форму ніжэй, каб стварыць новы рахунак ўдзельніка ці ўдзельніцы.',
+'nosuchusershort' => 'Не існуе ўдзельніка ці ўдзельніцы «$1». Праверце напісаньне.',
+'notanarticle' => 'Не артыкул',
+'note' => '<strong>Заўвага: </strong>',
+'nov' => '11',
+'november' => 'лістапада',
+'nowatchlist' => 'Ваш сьпіс назіраньня — пусты.',
+'nowiki_sample' => 'Пішыце сюды нефарматаваны тэкст',
+'nowiki_tip' => 'Ігнараваць вікі-фарматаваньне',
+'nstab-category' => 'Катэгорыя',
+'nstab-help' => 'Дапамога',
+'nstab-image' => 'Выява',
+'nstab-main' => 'Артыкул',
+'nstab-media' => 'Мэдыя',
+'nstab-mediawiki' => 'Паведамленьне',
+'nstab-special' => 'Спэцыяльная',
+'nstab-template' => 'Шаблён',
+'nstab-user' => 'Старонка ўдзельніка/ўдзельніцы',
+'nstab-wp' => 'Пра',
+'numauthors' => 'Колькасьць розных аўтараў і аўтарак (артыкула): $1',
+'numedits' => 'Колькасьць зьменаў (артыкула): $1',
+'numtalkauthors' => 'Колькасьць розных аўтараў і аўтарак (старонкі абмеркаваньня): $1',
+'numtalkedits' => 'Колькасьць зьменаў (старонкі абмеркаваньня): $1',
+'numwatchers' => 'Колькасьць назіральнікаў і назіральніц: $1',
+'nviews' => '$1 прагляд(у,аў)',
+'oct' => '10',
+'october' => 'кастрычніка',
+'ok' => 'Добра',
+'oldpassword' => 'Стары пароль',
+'orig' => 'арыг',
+'orphans' => 'Старонкі-сіраціны',
+'otherlanguages' => 'На іншых мовах',
+'others' => 'іншыя',
+'pagemovedtext' => 'Старонка «[[$1]]» перанесеная ў «[[$2]]».',
+'pagetitle' => '$1 - {{SITENAME}}',
+'popularpages' => 'Папулярныя старонкі',
+'portal' => 'Суполка',
+'portal-url' => 'Project:Суполка',
+'postcomment' => 'Пракамэнтаваць',
+'preferences' => 'Устаноўкі',
+'preview' => 'Прагляд',
+'previousdiff' => '← Перайсьці да папярэдняй зьмены',
+'prevn' => 'папярэднія $1',
+'printableversion' => 'Вэрсія для друку',
+'protect' => 'Абараніць',
+'protectcomment' => 'Прычына для абароны',
+'protectedarticle' => 'абаронены $1',
+'protectedpage' => 'Абароненая старонка',
+'protectsub' => '(Абарона «$1»)',
+'protectthispage' => 'Абараніць гэтую старонку',
+'qbbrowse' => 'Праглядзець',
+'qbedit' => 'Рэдагаваць',
+'qbfind' => 'Знайсьці',
+'qbpageoptions' => 'Гэтая старонка',
+'qbspecialpages' => 'Спэцыяльныя старонкі',
+'randompage' => 'Выпадковая старонка',
+'rclistfrom' => 'Паказаць зьмены з $1',
+'rclsub' => '(да старонак, спасылкі на якія ёсьць на «$1»)',
+'recentchanges' => 'Апошнія зьмены',
+'recentchangeslinked' => 'Зьвязаныя праўкі',
+'redirectedfrom' => '(Перанакіраваная з $1)',
+'removechecked' => 'Выдаліць выбраныя старонкі са сьпісу назіраньня',
+'removedwatch' => 'Выдаленая са сьпісу назіраньня',
+'removedwatchtext' => 'Старонка «$1» была выдаленая з Вашага сьпісу назіраньня.',
+'removingchecked' => 'Выдаленьне выбраных старонак са сьпісу назіраньня...',
+'resultsperpage' => 'Колькасьць вынікаў на старонцы',
+'retrievedfrom' => 'Атрымана з «$1»',
+'returnto' => 'Вярнуцца да $1.',
+'reupload' => 'Загрузіць зноў',
+'reuploaddesc' => 'Вярнуцца да формы загрузкі.',
+'revertimg' => 'вярнуць',
+'revhistory' => 'Гісторыя зьменаў',
+'revisionasof' => 'Вэрсія ад $1',
+'revisionasofwithlink' => 'Вэрсія ад $1; $2<br />$3 | $4',
+'revnotfound' => 'Вэрсія ня знойдзеная',
+'rollback' => 'Адмяніць рэдагаваньні',
+'saturday' => 'субота',
+'savearticle' => 'Захаваць старонку',
+'savefile' => 'Захаваць файл',
+'savegroup' => 'Захаваць групу',
+'saveprefs' => 'Захаваць перавагі',
+'saveusergroups' => 'Захаваць групы ўдзельнікаў і ўдзельніц',
+'search' => 'Пошук',
+'searchresults' => 'Вынікі пошуку',
+'searchresulttext' => 'Для атрыманьня больш падрабязнай інфармацыі аб пошуку, глядзіце [[Project:Пошук|Пошук]].',
+'selflinks' => 'Старонкі, якія спасылаюцца на сябе',
+'selflinkstext' => 'Наступныя старонкі ўтрымліваюць спасылкі на саміх сябе, чаго не павінна быць.',
+'sep' => '09',
+'september' => 'верасьня',
+'servertime' => 'Бягучы час на сэрвэры',
+'sharedupload' => 'Гэты файл знаходзіцца ў [[Commons:Галоўная старонка|ВікіСховішчы]]. Калі ласка, глядзіце \'\'\'[[Commons:Image:{{НАЗВА_СТАРОНКІ}}|яго апісаньне ]]\'\'\' там.',
+'shortpages' => 'Кароткія старонкі',
+'show' => 'паказаць',
+'showbigimage' => 'Паказаць варыянт большага памеру ($1 × $2, $3 Кб)',
+'showlast' => 'Паказаць $1 апошніх выяваў адсартаваных $2.',
+'showpreview' => 'Праглядзець',
+'showtoc' => 'паказаць',
+'sig_tip' => 'Ваш подпіс і момант часу',
+'sitesubtitle' => 'Вольная энцыкляпэдыя',
+'sitesupport' => 'Ахвяраваньні',
+'sitetitle' => '{{SITENAME}}',
+'siteuser' => 'Удзельнік/удзельніца $1',
+'specialloguserlabel' => 'Удзельнік/удзельніца:',
+'specialpage' => 'Спэцыяльная старонка',
+'specialpages' => 'Спэцыяльныя старонкі',
+'spheading' => 'Спэцыяльныя старонкі для ўсіх удзельнікаў і ўдзельніц',
+'statistics' => 'Статыстыка',
+'storedversion' => 'Захаваная вэрсія',
+'subcategories' => 'Падкатэгорыі',
+'subcategorycount' => 'У гэтай катэгорыі — $1 падкатэгоры(я,і,й).',
+'subcategorycount1' => 'У гэтай катэгорыі — $1 падкатэгорыя.',
+'subject' => 'Тэма/назва',
+'subjectpage' => 'Паказаць тэму',
+'summary' => 'Кароткае апісаньне зьменаў',
+'sunday' => 'нядзеля',
+'tableform' => 'табліца',
+'tagline' => 'Зьвесткі з сайту {{SITENAME}}.',
+'talk' => 'Гутаркі',
+'talkpage' => 'Абмеркаваць гэтую старонку',
+'talkpagemoved' => 'Адпаведная старонка абмеркаваньня таксама перанесеная.',
+'talkpagenotmoved' => 'Адпаведная старонка абмеркаваньня <strong>не</strong> перанесеная.',
+'templatesused' => 'На гэтай старонцы выкарыстаныя наступныя шаблёны:',
+'textboxsize' => 'Рэдагаваньне',
+'thumbnail-more' => 'Павялічыць',
+'thursday' => 'чацьвер',
+'timezonelegend' => 'Часавы пояс',
+'toc' => 'Зьмест',
+'tog-editsection' => 'Дазволіць рэдагаваньне асобных сэкцыяў па спасылках [рэдагаваць]',
+'tog-editwidth' => 'Поле рэдагаваньня ў поўную шырыню',
+'tog-hideminor' => 'Хаваць дробныя зьмены ў сьпісе апошніх зьменаў',
+'tog-showtoc' => 'Паказваць зьмест<br />(для старонак з колькасьцю сэкцый болей за 3)',
+'tog-showtoolbar' => 'Паказваць панэль інструмэнтаў рэдагаваньня',
+'tog-underline' => 'Падкрэсьліваць спасылкі',
+'toolbox' => 'Інструмэнты',
+'tooltip-minoredit' => 'Пазначыць гэтую зьмену як дробную [alt-i]',
+'tooltip-save' => 'Захаваць Вашы зьмены [alt-s]',
+'tooltip-watch' => 'Дадаць гэтую старонку ў Ваш сьпіс назіраньня [alt-w]',
+'tuesday' => 'аўторак',
+'unusedimages' => 'Выявы, якія не выкарыстоўваюцца',
+'unwatch' => 'Не назіраць',
+'unwatchthispage' => 'Перастаць назіраць',
+'upload' => 'Загрузіць файл',
+'uploadbtn' => 'Загрузіць файл',
+'uploadedfiles' => 'Загружаныя файлы',
+'uploadedimage' => 'загружаная «$1»',
+'uploadlink' => 'Загрузіць выявы',
+'uploadlogpagetext' => 'Сьпіс апошніх загружаных файлаў.',
+'uploadtext' => '\'\'\'Перад тым, як загрузіць файл:\'\'\'
+
+* Азнаёмцеся з \'\'\'[[Project:Правілы выкарыстаньня выяваў|правіламі выкарыстаньня выяваў]]\'\'\'.
+* Праверце з дапамогай \'\'\'[[Special:Imagelist|сьпісу выяваў]]\'\'\', ці не загружаны гэты файл з іншай назвай.
+* Выкарыстоўвайце наступныя \'\'\'фарматы\'\'\': [[JPG]] — для фотаздымкаў; [[GIF]] — для анімацыі; [[PNG]] — для іншых выяваў; [[OGG]] — для аўдыёфайлаў.
+* Давайце файлам \'\'\'зразумелыя назвы\'\'\', якія адлюстроўваюць іх зьмест. Напрыклад: \'\'Janka Kupala, 1910.jpg\'\' замест \'\'JK1.jpg\'\'. Назву файла \'\'\' немагчыма \'\'\' зьмяніць пасьля загрузкі.
+* Пытайцеся \'\'\'дазволу\'\'\' на публікацыю фотаздымка ва ўсіх людзей, якія там прысутнічаюць.
+
+\'\'\'Пасьля таго, як выява загружаная:\'\'\'
+
+* \'\'\'Абавязкова\'\'\' дадайце:
+** \'\'\'дэталёвае апісаньне зьместу\'\'\';
+** \'\'\'крыніцу\'\'\': файл створаны Вамі; адсканаваны з кнігі \'\'X\'\'; узяты з Інтэрнэт па адрасу \'\'Y\'\';
+** для файлаў, якія зроблены \'\'\'ня\'\'\' Вамі, укажыце, ці атрымалі Вы \'\'\'дазвол\'\'\' на выкарыстаньне гэтага файла ў {{SITENAME}};
+** \'\'\'ліцэнзіі\'\'\', згодна ўмоваў якіх магчыма распаўсюджваць файл.
+* \'\'\'Выкарыстоўвайце файл\'\'\' у артыкуле(ах). Напрыклад: <code><nowiki>[[Image:file.jpg]]</nowiki></code> ці <code><nowiki>[[Image:file.jpg|thumb|200px|Апісаньне]]</nowiki></code> — для выяваў; <code><nowiki>[[Media:file.ogg]]</nowiki></code> — для аўдыёфайлаў.',
+'userexists' => 'Выбранае Вамі імя ўдзельніка/ўдзельніцы ўжо выкарыстоўваецца кімсьці іншым. Калі ласка, выберыце іншае імя.',
+'userlogout' => 'Выйсьці',
+'val_table_header' => '<tr><th>Кляса</th>$1<th colspan=4>Меркаваньне</th>$1<th>Камэнтар</th></tr>',
+'val_version' => 'Вэрсія',
+'val_version_of' => 'Вэрсія $1',
+'val_view_version' => 'Паказаць гэтую вэрсію',
+'version' => 'Вэрсія',
+'viewprevnext' => 'Паказаць ($1) ($2) ($3).',
+'viewsource' => 'Паказаць крыніцу',
+'viewtalkpage' => 'Паказаць абмеркаваньне',
+'watch' => 'Назіраць',
+'watchlist' => 'Мой сьпіс назіраньня',
+'watchthis' => 'Назіраць за гэтай старонкай',
+'watchthispage' => 'Назіраць за гэтай старонкай',
+'wednesday' => 'серада',
+'whatlinkshere' => 'Адкуль спасылаюцца на старонку',
+'whitelistacctitle' => 'Вам не дазволена ствараць рахунак',
+'youremail' => 'Ваш адрас электроннай пошты (*)',
+'yourname' => 'Ваша імя ўдзельніка/ўдзельніцы',
+'yournick' => 'Ваша мянушка (для подпісаў)',
+'yourpassword' => 'Ваш пароль',
+'yourrealname' => 'Вашае сапраўднае імя*',
+'yourtext' => 'Ваш тэкст',
+);
+
+class LanguageBe extends LanguageUtf8 {
+
+       // Namespaces
+       function getNamespaces() {
+               global $wgNamespaceNamesBe;
+               return $wgNamespaceNamesBe;
+       }
+
+       // Quickbar
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsBe;
+               return $wgQuickbarSettingsBe;
+       }
+
+       // Skins
+       function getSkinNames() {
+               global $wgSkinNamesBe;
+               return $wgSkinNamesBe;
+       }
+
+       // Magic words
+       function getMagicWords() {
+               global $wgMagicWordsBe;
+               return $wgMagicWordsBe;
+       }
+
+       // The date and time format
+       function date( $ts, $adj = false ) {
+               if ( $adj ) { $ts = $this->userAdjust( $ts ); } # Adjust based on the timezone setting.
+               // 20050310001506 => 10.03.2005
+               $date = (substr( $ts, 6, 2 )) . '.' . substr( $ts, 4, 2 ) . '.' . substr( $ts, 0, 4 );
+               return $date;
+       }
+
+       function time( $ts, $adj = false ) {
+               if ( $adj ) { $ts = $this->userAdjust( $ts ); }
+               // 20050310001506 => 00:15
+               $time = substr( $ts, 8, 2 ) . ':' . substr( $ts, 10, 2 );
+               return $time;
+       }
+
+       function timeanddate( $ts, $adj = false ) {
+               return $this->time( $ts, $adj ) . ', ' .$this->date( $ts, $adj );
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesBe;
+               if( isset( $wgAllMessagesBe[$key] ) ) {
+                       return $wgAllMessagesBe[$key];
+               } else {
+                       return parent::getMessage( $key );
+               }
+       }
+
+       function formatNum( $number ) {
+               return strtr($number, '.,', ',.' );
+       }
+}
+?>
diff --git a/languages/LanguageBg.php b/languages/LanguageBg.php
new file mode 100644 (file)
index 0000000..20ba51f
--- /dev/null
@@ -0,0 +1,1247 @@
+<?php
+/** Bulgarian (Български)
+  *
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+#--------------------------------------------------------------------------
+# Language-specific text
+#--------------------------------------------------------------------------
+
+# The names of the namespaces can be set here, but the numbers
+# are magical, so don't change or move them!  The Namespace class
+# encapsulates some of the magic-ness.
+#
+
+/* private */ $wgNamespaceNamesBg = array(
+       NS_MEDIA            => 'Медия',
+       NS_SPECIAL          => 'Специални',
+       NS_MAIN             => '',
+       NS_TALK             => 'Беседа',
+       NS_USER             => 'Потребител',
+       NS_USER_TALK        => 'Потребител_беседа',
+       NS_PROJECT          => $wgMetaNamespace,
+       NS_PROJECT_TALK     => $wgMetaNamespace . '_беседа',
+       NS_IMAGE            => 'Картинка',
+       NS_IMAGE_TALK       => 'Картинка_беседа',
+       NS_MEDIAWIKI        => 'МедияУики',
+       NS_MEDIAWIKI_TALK   => 'МедияУики_беседа',
+       NS_TEMPLATE         => 'Шаблон',
+       NS_TEMPLATE_TALK    => 'Шаблон_беседа',
+       NS_HELP             => 'Помощ',
+       NS_HELP_TALK        => 'Помощ_беседа',
+       NS_CATEGORY         => 'Категория',
+       NS_CATEGORY_TALK    => 'Категория_беседа'
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgQuickbarSettingsBg = array(
+       'Без меню', 'Неподвижно вляво', 'Неподвижно вдясно', 'Плаващо вляво'
+);
+
+/* private */ $wgSkinNamesBg = array(
+       'standard' => 'Основен',
+       'nostalgia' => 'Носталгия',
+       'cologneblue' => 'Кьолнско синьо',
+       'smarty' => 'Падингтън',
+       'montparnasse' => 'Монпарнас',
+       'davinci' => 'ДаВинчи',
+) + $wgSkinNamesEn;
+
+
+/* private */ $wgDateFormatsBg = array();
+
+/* private */ $wgBookstoreListBg = array(
+       'books.bg'       => "http://www.books.bg/ISBN/$1",
+) + $wgBookstoreListEn;
+
+
+/* private */ $wgMagicWordsBg = array(
+#   ID                                 CASE  SYNONYMS
+       MAG_REDIRECT             => array( 0, '#redirect', '#пренасочване', '#виж' ),
+       MAG_NOTOC                => array( 0, '__NOTOC__', '__БЕЗСЪДЪРЖАНИЕ__' ),
+       MAG_FORCETOC             => array( 0, '__FORCETOC__', '__СЪДЪРЖАНИЕ__' ),
+       MAG_NOEDITSECTION        => array( 0, '__NOEDITSECTION__', '__БЕЗ_РЕДАКТИРАНЕ_НА_РАЗДЕЛИ__' ),
+       MAG_START                => array( 0, '__START__', '__НАЧАЛО__'         ),
+       MAG_CURRENTMONTH         => array( 1, 'CURRENTMONTH', 'ТЕКУЩМЕСЕЦ'      ),
+       MAG_CURRENTMONTHNAME     => array( 1, 'CURRENTMONTHNAME', 'ТЕКУЩМЕСЕЦИМЕ' ),
+       MAG_CURRENTDAY           => array( 1, 'CURRENTDAY', 'ТЕКУЩДЕН'            ),
+       MAG_CURRENTDAYNAME       => array( 1, 'CURRENTDAYNAME', 'ТЕКУЩДЕНИМЕ'     ),
+       MAG_CURRENTYEAR          => array( 1, 'CURRENTYEAR', 'ТЕКУЩАГОДИНА'       ),
+       MAG_CURRENTTIME          => array( 1, 'CURRENTTIME', 'ТЕКУЩОВРЕМЕ'        ),
+       MAG_NUMBEROFARTICLES     => array( 1, 'NUMBEROFARTICLES', 'БРОЙСТАТИИ'    ),
+       MAG_CURRENTMONTHNAMEGEN  => array( 1, 'CURRENTMONTHNAMEGEN' ),
+       MAG_PAGENAME             => array( 1, 'PAGENAME', 'СТРАНИЦА'               ),
+       MAG_NAMESPACE            => array( 1, 'NAMESPACE', 'ИМЕНПРОСТРАНСТВО'              ),
+       MAG_SUBST                => array( 0, 'SUBST:', 'ЗАМЕСТ:'              ),
+       MAG_MSGNW                => array( 0, 'MSGNW:', 'СЪОБЩNW:'             ),
+       MAG_END                  => array( 0, '__END__', '__КРАЙ__'            ),
+       MAG_IMG_THUMBNAIL        => array( 1, 'thumbnail', 'thumb', 'мини'     ),
+       MAG_IMG_RIGHT            => array( 1, 'right', 'вляво'                 ),
+       MAG_IMG_LEFT             => array( 1, 'left', 'вдясно'                 ),
+       MAG_IMG_NONE             => array( 1, 'none'                   ),
+       MAG_IMG_WIDTH            => array( 1, "$1px", "$1пкс"          ),
+       MAG_IMG_CENTER           => array( 1, 'center', 'centre', 'център' ),
+       MAG_IMG_FRAMED           => array( 1, 'framed', 'enframed', 'frame', 'рамка', 'врамка' ),
+       MAG_INT                  => array( 0, 'INT:'                   ),
+       MAG_SITENAME             => array( 1, 'SITENAME', 'САЙТ'       ),
+       MAG_NS                   => array( 0, 'NS:'                    ),
+       MAG_LOCALURL             => array( 0, 'LOCALURL:'              ),
+       MAG_LOCALURLE            => array( 0, 'LOCALURLE:'             ),
+       MAG_SERVER               => array( 0, 'SERVER', 'СЪРВЪР'       )
+);
+
+#-------------------------------------------------------------------
+# Default messages
+#-------------------------------------------------------------------
+# БЕЛЕЖКА: За да изключите "Текущите събития" в страничното меню,
+# въведете 'currentevents' => '-'
+
+# БЕЛЕЖКА: За да изключите "Условията за ползване" в заглавните препратки,
+# въведете 'disclaimers' => ''
+
+# БЕЛЕЖКА: За да изключите "Портала" за общността в заглавните препратки,
+# въведете 'portal' => ''
+
+/* private */ $wgAllMessagesBg = array(
+# User toggles
+'tog-underline'      => 'Подчертаване на препратките',
+'tog-highlightbroken' => 'Показване на невалидните препратки <a href="" class="new">така</a> (алтернативно: така<a href="" class="internal">?</a>)',
+'tog-justify'        => 'Двустранно подравняване на абзаците',
+'tog-hideminor'      => 'Скриване на малки редакции в последните промени',
+'tog-usenewrc'       => 'Подобряване на последните промени (не за всички браузъри)',
+'tog-numberheadings' => 'Номериране на заглавията',
+'tog-showtoolbar'    => 'Показване на лента за редактиране',
+'tog-editondblclick' => 'Редактиране при двойно щракване (Javascript)',
+'tog-editsection'    =>'Възможност за редактиране на раздел чрез препратка [редактиране]',
+'tog-editsectiononrightclick' => 'Възможност за редактиране на раздел при щракване с десния бутон върху заглавие на раздел (Javascript)',
+'tog-showtoc'        =>'Показване на съдържание (за статии с повече от три раздела)',
+'tog-rememberpassword' => 'Запомняне на паролата между сесиите',
+'tog-editwidth'      => 'Максимална ширина на кутията за редактиране',
+'tog-watchdefault'   => 'Добавяне на редактираните страници към списъка за наблюдение',
+'tog-minordefault'   => 'Отбелязване на всички промени като малки по подразбиране',
+'tog-previewontop'   => 'Показване на предварителния преглед преди текстовата кутия, а не след нея',
+'tog-nocache'        => 'Без складиране на страниците',
+# Dates
+'sunday' => 'неделя',
+'monday' => 'понеделник',
+'tuesday' => 'вторник',
+'wednesday' => 'сряда',
+'thursday' => 'четвъртък',
+'friday' => 'петък',
+'saturday' => 'събота',
+'january' => 'януари',
+'february' => 'февруари',
+'march' => 'март',
+'april' => 'април',
+'may_long' => 'май',
+'june' => 'юни',
+'july' => 'юли',
+'august' => 'август',
+'september' => 'септември',
+'october' => 'октомври',
+'november' => 'ноември',
+'december' => 'декември',
+'jan' => 'яну',
+'feb' => 'фев',
+'mar' => 'мар',
+'apr' => 'апр',
+'may' => 'май',
+'jun' => 'юни',
+'jul' => 'юли',
+'aug' => 'авг',
+'sep' => 'сеп',
+'oct' => 'окт',
+'nov' => 'ное',
+'dec' => 'дек',
+
+# Bits of text used by many pages:
+#
+'categories' => 'Категории',
+'category' => 'категория',
+'category_header' => "Статии в категория \"$1\"",
+'subcategories' => 'Подкатегории',
+'linktrail'    => "/^((?:[a-z]|а|б|в|г|д|е|ж|з|и|й|к|л|м|н|о|п|р|с|т|у|ф|х|ц|ч|ш|щ|ъ|ы|ь|э|ю|я)+)(.*)\$/sD",
+'mainpage'    => 'Начална страница',
+'mainpagetext'  => 'Системата на Уики бе успешно инсталирана.',
+'mainpagedocfooter' => "Моля, разгледайте [http://meta.wikipedia.org/wiki/MediaWiki_i18n документацията]
+     и [http://meta.wikipedia.org/wiki/MediaWiki_User%27s_Guide ръководството] за подробна информация относно МедияУики.",
+'portal'     => 'Портал за общността',
+'portal-url' => '{{ns:4}}:Портал',
+'about'      => "За {{SITENAME}}",
+'aboutsite'      => "За {{SITENAME}}",
+'aboutpage'    => "{{ns:4}}:За {{SITENAME}}",
+'article'   => 'Статия',
+'help'      => 'Помощ',
+'helppage'    => "{{ns:12}}:Помощ",
+'bugreports'  => 'Съобщения за грешки',
+'bugreportspage' => "{{ns:4}}:Съобщения_за_грешки",
+"sitesupport"   => "Дарения", # Set a URL in $wgSiteSupportPage in LocalSettings.php
+'faq'      => 'ЧЗВ',
+'faqpage'    => "{{ns:4}}:ЧЗВ",
+'edithelp'    => 'Помощ при редактиране',
+'edithelppage'  => "{{ns:12}}:Как_се_редактират_страници",
+'cancel'    => 'Отказ',
+'qbfind'    => 'Търсене',
+'qbbrowse'    => 'Избор',
+'qbedit'    => 'Редактиране',
+'qbpageoptions' => 'Настройки за страницата',
+'qbpageinfo'  => 'Информация за страницата',
+'qbmyoptions'  => 'Моите настройки',
+'qbspecialpages' => 'Специални страници',
+'moredotdotdot' => 'Повече...',
+'mypage'    => 'Моята страница',
+'mytalk'    => 'Моята беседа',
+'anontalk'  => 'Беседа за адреса',
+'navigation' => 'Навигация',
+'currentevents' => 'Текущи събития',
+'disclaimers' => 'Условия за ползване',
+'disclaimerpage' => "{{ns:4}}:Условия_за_ползване",
+'errorpagetitle' => 'Грешка',
+'returnto'    => "Обратно към $1.",
+'tagline'        => "от {{SITENAME}}, свободната енциклопедия",
+'whatlinkshere'  => 'Какво сочи насам',
+'help'      => 'Помощ',
+'search'    => 'Търсене',
+'go'    => 'Отваряне',
+'history'    => 'История',
+'history_short' => 'История',
+'printableversion' => 'Версия за печат',
+'edit' => 'Редактиране',
+'editthispage'  => 'Редактиране',
+'delete' => 'Изтриване',
+'deletethispage' => 'Изтриване',
+'undelete_short' => 'Възстановяване',
+'undelete_short1' => 'Възстановяване',
+'protect' => 'Защита',
+'protectthispage' => 'Защита',
+'unprotect' => 'Сваляне на защитата',
+'unprotectthispage' => 'Сваляне на защитата',
+'newpage' => 'Нова страница',
+'talkpage'    => 'Дискусионна страница',
+'specialpage' => 'Специална страница',
+'personaltools' => 'Лични инструменти',
+'postcomment'   => 'Оставяне на съобщение',
+'addsection'   => '+',
+'articlepage'  => 'Преглед на статия',
+'subjectpage'  => 'Преглед на тема', # For compatibility
+'talk' => 'Беседа',
+'toolbox' => 'Кутия с инструменти',
+'userpage' => 'Потребителска страница',
+'wikipediapage' => 'Основна страница',
+'imagepage' =>   'Преглед на картинка',
+'viewtalkpage' => 'Преглед на беседа',
+'otherlanguages' => 'Други езици',
+'redirectedfrom' => "(пренасочване от $1)",
+'lastmodified'  => "Последна промяна на страницата: $1.",
+'viewcount'    => "Страницата е била преглеждана $1 пъти.",
+'copyright'     => "Съдържанието е достъпно при условията на $1.",
+'poweredby'     => "{{SITENAME}} се задвижва от [http://www.mediawiki.org/ МедияУики], софтуер за уики с отворен код.",
+'printsubtitle' => '(от {{SERVER}})',
+'protectedpage' => 'Защитена страница',
+'administrators' => "{{ns:4}}:Администратори",
+'sysoptitle'  => 'Изискване на администраторски права',
+'sysoptext'    => "Желаното действие може да се изпълни само от администратори.
+Вижте $1.",
+'developertitle' => 'Изискват се права на разработчик',
+'developertext'  => "Желаното действие може да се изпълни само от разработчици.
+Вижте $1.",
+"nbytes"    => "$1 байта",
+'go'      => 'Отваряне',
+'ok'      => 'Добре',
+'sitetitle'    => "{{SITENAME}}",
+'pagetitle'    => "$1 - {{SITENAME}}",
+'sitesubtitle' => 'Свободната енциклопедия',
+'retrievedfrom' => "Взето от \"$1\".",
+'newmessages' => "Имате $1.",
+'newmessageslink' => 'нови съобщения',
+'editsection' => 'редактиране',
+'toc' => 'Съдържание',
+'showtoc' => 'показване',
+'hidetoc' => 'скриване',
+'thisisdeleted' => "Преглед или възстановяване на $1?",
+'restorelink' => "$1 изтрити редакции",
+'feedlinks' => 'Feed:',
+
+# Short words for each namespace, by default used in the 'article' tab in monobook
+'nstab-main' => 'Статия',
+'nstab-user' => 'Потребителска страница',
+'nstab-media' => 'Медия',
+'nstab-special' => 'Специална страница',
+'nstab-wp' => "За {{SITENAME}}",
+'nstab-image' => 'Картинка',
+'nstab-mediawiki' => 'Съобщение',
+'nstab-template' => 'Шаблон',
+'nstab-help' => 'Помощ',
+'nstab-category' => 'Категория',
+
+# Main script and global functions
+#
+'nosuchaction'  => 'Няма такова действие',
+'nosuchactiontext' => 'Действието, указано от мрежовия адрес, не се разпознава от системата.',
+'nosuchspecialpage' => 'Няма такава специална страница',
+'nospecialpagetext' => 'Отправихте заявка за специална страница, която не се разпознава от системата.',
+
+# General errors
+#
+'error'      => 'Грешка',
+'databaseerror' => 'Грешка при работа с базата данни',
+'dberrortext'  => "Възникна синтактична грешка при заявка към базата данни.
+Последната заявка към базата данни бе:
+<blockquote><tt>$1</tt></blockquote>
+при функцията \"<tt>$2</tt>\".
+MySQL дава грешка \"<tt>$3: $4</tt>\".",
+'dberrortextcl' => "Възникна синтактична грешка при заявка към базата данни.
+Последната заявка към базата данни бе:
+\"$1\"
+при функцията \"$2\".
+MySQL дава грешка \"$3: $4\".\n",
+'noconnect'    => "В момента има технически трудности и не може да се осъществи връзка с базата данни.",
+'nodb'      => "Неуспех при избиране на база данни $1",
+'cachederror'  => 'Показано е складирано копие на желаната страница, което евентуално може да е остаряло.',
+'readonly'    => 'Базата данни е затворена за промени',
+'enterlockreason' => 'Посочете причина за затварянето, като дадете и
+приблизителна оценка кога базата данни ще бъде отново отворена',
+'readonlytext'  => "Базата данни е временно затворена за промени - вероятно за рутинна поддръжка,
+след която ще бъде отново на разположение.
+Администраторът, който я е затворил, дава следното обяснение:
+<p>$1",
+'missingarticle' => "Текстът на страницата \"$1\" не бе намерен в базата данни.
+
+<p>Това обикновено е причинено от последване на остаряла разлика или
+препратка от историята към изтрита страница.
+
+<p>Ако не това е причината, е възможно да сте открили грешка в системата.
+Моля, съобщете за това на администратор, като включите и името на статията.",
+'internalerror' => 'Вътрешна грешка',
+'filecopyerror' => "Файлът \"$1\" не можа да бъде копиран като \"$2\".",
+'filerenameerror' => "Файлът \"$1\" не можа да бъде преименуван на \"$2\".",
+'filedeleteerror' => "Файлът \"$1\" не можа да бъде изтрит.",
+'filenotfound'  => "Файлът \"$1\" не бе намерен.",
+'unexpected'  => "Неочаквана стойност: \"$1\"=\"$2\".",
+'formerror'    => 'Възникна грешка при изпращане на формуляра',
+'badarticleerror' => 'Действието не може да се изпълни върху страницата.',
+'cannotdelete'  => 'Указаната страница или картинка не можа да бъде изтрита. Възможно е вече да е изтрита от някой друг.',
+'badtitle'    => 'Невалидно заглавие',
+'badtitletext'  => 'Желаното заглавие на статия е невалидно, празно или
+неправилна препратка към Уикипедия на друг език.',
+'perfdisabled' => 'Съжаляваме! Това свойство е временно изключено,
+защото забавя базата данни дотам, че никой не може да използва уикито.',
+'perfdisabledsub' => "Съхранен екземпляр от $1:",
+'perfcached' => 'Следните данни са извлечени от склада и затова може да не отговарят на текущото състояние:',
+'wrong_wfQuery_params' => "Невалидни аргументи за wfQuery()<br />
+Функция: $1<br />
+Заявка: $2
+",
+'viewsource' => 'Защитена страница',
+'protectedtext' => "Страницата е затворена за промени. Съществуват няколко
+причини това да е така, моля, вижте
+[[{{ns:4}}:Защитена_страница]].
+
+Може да прегледате и копирате изходния код на страницата:",
+
+# Login and logout pages
+#
+"logouttitle"  => "Излизане на потребител",
+"logouttext"  => "Излязохте от системата.
+Може да продължите да използвате {{SITENAME}} анонимно или да влезете отново
+като друг потребител. Обърнете внимание, че някои страници все още
+ще се показват така, сякаш сте влезли, докато не изтриете кеш-паметта на браузъра.\n",
+
+"welcomecreation" => "<h2>Добре дошли, $1!</h2><p>Вашата сметка бе успешно открита.
+Сега може да промените настройките по Ваш вкус.",
+
+"loginpagetitle" => "Влизане в системата",
+"yourname"    => "Вашето потребителско име",
+"yourpassword"  => "Вашата парола",
+"yourpasswordagain" => "Въведете повторно парола",
+"newusersonly"  => " (само за нови потребители)",
+"remembermypassword" => "Запомняне на паролата между сесиите.",
+"loginproblem"  => "<b>Имаше проблем с Вашето влизане.</b><br />Опитайте отново!",
+"alreadyloggedin" => "<strong>$1, вече сте влезли в системата!</strong><br />\n",
+
+'login'      => 'Влизане',
+'loginprompt'  => "Бисквитките трябва да са разрешени, за да може да влезете в {{SITENAME}}.",
+'userlogin'    => 'Влизане',
+'logout'    => 'Излизане',
+'userlogout'  => 'Излизане',
+'notloggedin'  => 'Не сте влезли',
+'createaccount'  => 'Създаване на сметка',
+'createaccountmail'     => 'с писмо по електронната поща',
+'badretype'    => 'Въведените пароли не съвпадат.',
+'userexists'  => 'Въведеното потребителско име вече се използва. Моля, изберете друго име.',
+'youremail'    => 'Вашата е-поща*',
+'yourrealname' => 'Вашето истинско име*',
+'yournick'    => 'Вашият псевдоним (за подписи)',
+'emailforlost'  => '* Полетата, отбелязани със звезда (*), са незадължителни. Посочването на електронна поща позволява на хората да се свържат с Вас, без да се налага да им съобщавате адреса си, а също може да се използва, за да Ви се изпрати нова парола, ако случайно забравите сегашната си.<br /><br /> Ако посочите истинското си име, на него ще бъдат приписани Вашите приноси.',
+'prefs-help-realname' => '* <strong>Истинско име</strong> (незадължително): ако го посочите, на него ще бъдат приписани Вашите приноси.<br />',
+'prefs-help-email' => '* <strong>Електронна поща</strong> (незадължително): позволява на хората да се свържат с Вас, без да се налага да им съобщавате адреса си, а също може да се използва, за да Ви се изпрати нова парола, ако случайно забравите сегашната си.',
+'loginerror'  => 'Грешка при влизане',
+'nocookiesnew'  => "Потребителската сметка бе създадена, но все още не сте влезли. {{SITENAME}} използва бисквитки при влизане на потребителите. Моля, разрешете бисквитките във Вашия браузър, тъй като те са забранени, и след това влезте с потребителското си име и парола.",
+'nocookieslogin'        => "{{SITENAME}} използва бисквитки за запис на влизанията. Моля, разрешете бисквитките във Вашия браузър, тъй като те са забранени, и опитайте отново.",
+'noname'    => 'Не указахте валидно потребителско име.',
+'loginsuccesstitle' => 'Успешно влизане',
+'loginsuccess'  => "Влязохте в {{SITENAME}} като \"$1\".",
+'nosuchuser'  => "Няма потребител с името \"$1\".
+Проверете изписването или се регистрирайте, използвайки долния формуляр.",
+'wrongpassword'  => 'Въведената парола е невалидна. Моля, опитайте отново.',
+'mailmypassword' => 'Изпращане на нова парола',
+'passwordremindertitle' => "Напомняне за парола от {{SITENAME}}",
+'passwordremindertext' => "Някой (най-вероятно Вие, от IP-адрес $1)
+помоли да Ви изпратим новата парола за влизане в {{SITENAME}}.
+Паролата за потребителя \"$2\" е \"$3\".
+Сега би трябвало да влезете в системата и да смените паролата си.",
+'noemail'    => "Няма записана електронна поща за потребителя \"$1\".",
+'passwordsent'  => "Нова парола беше изпратена на електронната поща на \"$1\".
+Моля, влезте отново, след като я получите.",
+'loginend'   => "За да се регистрирате, просто въведете потребителско име и парола (два пъти) и щракнете върху бутона '<b>Създаване на сметка</b>'.<br /><br />
+
+Следващия път е достатъчно да попълните само първите две полета и да щракнете върху '<b>Влизане</b>'.<br /><br />",
+'mailerror' => "Грешка при изпращане на писмо: $1",
+
+# Edit page toolbar
+'bold_sample'      => 'Получер текст',
+'bold_tip'         => 'Получер (удебелен) текст',
+'italic_sample'    => 'Курсивен текст',
+'italic_tip'       => 'Курсивен (наклонен) текст',
+'link_sample'      => 'Име на препратка',
+'link_tip'         => 'Вътрешна препратка',
+'extlink_sample'   => 'http://www.primer.com Име на препратката',
+'extlink_tip'      => 'Външна препратка (не забравяйте http:// отпред)',
+'headline_sample'  => 'Заглавен текст',
+'headline_tip'     => 'Заглавие',
+'math_sample'      => 'Тук въведете формулата',
+'math_tip'         => 'Математическа формула (LaTeX)',
+'nowiki_sample'    => 'Тук въведете текст',
+'nowiki_tip'       => 'Пренебрегване на форматиращите команди',
+'image_sample'     => 'Пример.jpg',
+'image_tip'        => 'Вмъкване на картинка',
+'media_sample'     => 'Пример.mp3',
+'media_tip'        => 'Препратка към файл',
+'sig_tip'          => 'Вашият подпис заедно с времева отметка',
+'hr_tip'           => 'Хоризонтална линия (използвайте пестеливо)',
+'infobox'          => 'Щракнете върху бутон за демонстрация',
+# alert box shown in browsers where text selection does not work, test e.g. with mozilla or konqueror
+'infobox_alert' => "Моля, въведете текста, който искате да форматирате.\\n Той ще се покаже в информационното поле, откъдето ще може да го изберете.\\nПример:\\n$1\\nще се превърне в:\\n$2",
+
+# Edit pages
+#
+'summary'       => '<a href="http://bg.wikipedia.org/wiki/{{ns:4}}:Резюме" title="Моля, дайте кратко описание на направените промени">Резюме</a>',
+'subject'       => 'Тема/заглавие',
+'minoredit'     => 'Това е малка промяна',
+'watchthis'     => 'Наблюдение на статията',
+'savearticle'   => 'Съхранение',
+'preview'       => 'Предварителен преглед',
+'showpreview'   => 'Предварителен преглед',
+'blockedtitle'  => 'Потребителят е блокиран',
+'blockedtext'   => "Вашето потребителско име (или IP-адрес) е блокирано от $1.
+Причината за това е:<br />''$2''<p>Може да се свържете с $1 или с някой от останалите
+[[{{ns:4}}:Администратори|администратори]], за да обсъдите това.
+
+Може да използвате услугата \"'''Пращане писмо на потребителя'''\" единствено, ако сте посочили валидна електронна поща в [[{{ns:-1}}:Preferences|настройки]] си.
+
+Вашият IP-адрес е $3. Моля, вмъквайте този адрес във всяко питане, което правите.",
+'whitelistedittitle' => 'Необходимо е да влезете, за да може да редактирате',
+'whitelistedittext' => 'Необходимо е да [[{{ns:-1}}:Userlogin|влезете]], за да може да редактирате статии.',
+'whitelistreadtitle' => 'Необходимо е да влезете, за да може да четете',
+'whitelistreadtext' => 'Необходимо е да [[{{ns:-1}}:Userlogin|влезете]], за да може да четете статии.',
+'whitelistacctitle' => 'Не ви е позволено да създавате сметка',
+'whitelistacctext' => 'За да Ви бъде позволено създаването на сметки, трябва да [[{{ns:-1}}:Userlogin|влезете]] и да имате подходящото разрешение.',
+'loginreqtitle' => 'Изисква се влизане',
+'loginreqtext'  => 'Необходимо е да [[{{ns:-1}}:Userlogin|влезете]], за да може да разглеждате други страници.',
+'accmailtitle' => 'Паролата бе изпратена.',
+'accmailtext' => "Паролата за '$1' бе изпратена на $2.",
+'newarticle'  => '(нова)',
+'newarticletext' => "<div style=\"font-size:small;color:#033;border-width:1px;border-style:solid;border-color:#aaa;padding:3px\">Последвали сте препратка към страница, която все още не съществува.
+За да я създадете, започнете да пишете в долната текстова кутия
+(вижте '''[[{{ns:4}}:Помощ|помощната страница]]''' за повече информация).
+Ако сте дошли тук по грешка, просто натиснете '''бутона за връщане''' на Вашия браузър.
+
+'''Въведете съдържателен текст, който би обогатил енциклопедията.''' Вашата добавка към Уикипедия ще бъде видима '''веднага''' след съхранението, затова ако просто искате да изпробвате как работят нещата, използвайте нашия '''[[{{ns:4}}:Пясъчник|пясъчник]]'''.</div>",
+'talkpagetext' => '<!-- МедияУики:talkpagetext -->',
+'anontalkpagetext' => "----
+''Това е дискусионната страница на анонимен потребител, който  все още няма сметка или не я използва. Затова се налага да използваме цифров мрежов адрес (IP address), за да го/я идентифицираме. Такъв адрес може да се споделя от няколко потребителя.
+
+Ако сте анонимен потребител и мислите, че тези неуместни коментари са отправени към Вас, моля [[{{ns:-1}}:Userlogin|регистрирайте се или влезте в системата]], за да избегнете евентуално бъдещо объркване с други анонимни потребители.''",
+'noarticletext' => "(Тази страница все още не съществува. Може да я създадете, като щракнете на '''Редактиране'''.)",
+'usercssjsyoucanpreview' => "<strong>Съвет:</strong> Използвайте бутона 'Предварителен преглед', за да изпробвате новия код на css/js преди съхранението.",
+'usercsspreview' => "'''Не забравяйте, че това е само предварителен преглед на кода на CSS, страницата все още не е съхранена!'''",
+'userjspreview' => "'''Не забравяйте, че това е само изпробване/предварителен преглед на кода на Javascript, страницата все още не е съхранена!'''",
+'updated'    => '(актуализирана)',
+'note'      => '<strong>Забележка:</strong> ',
+'previewnote'  => 'Не забравяйте, че това е само предварителен преглед и страницата все още не е съхранена!',
+'previewconflict' => 'Този предварителен преглед отразява текста в горната текстова кутия така, както би се показал, ако съхраните.',
+'editing'    => "Редактиране на $1",
+'editingsection'    => "Редактиране на $1 (раздел)",
+'editingcomment'    => "Редактиране на $1 (коментар)",
+'editconflict'  => "Различна редакция: $1",
+'explainconflict' => "Някой друг вече е променил тази страница, откакто започнахте да я редактирате.
+Горната текстова кутия съдържа текущия текст на страницата без Вашите промени, които са показани в долната кутия. За да бъдат и те съхранени, е необходимо ръчно да ги преместите в горното поле, тъй като <b>единствено</b> текстът в него ще бъде съхранен при натискането на бутона \"Съхранение\".<br />",
+"yourtext"    => "Вашият текст",
+"storedversion" => "Съхранена версия",
+"editingold"  => "<strong>ВНИМАНИЕ: Редактирате остаряла
+версия на страницата.
+Ако съхраните, всякакви промени, направени след тази версия, ще бъдат изгубени.</strong>",
+"yourdiff"    => "Разлики",
+"copyrightwarning" => "<div style=\"border:1px solid #333; padding:0.5em\">
+Моля, обърнете внимание на това, че
+всички приноси към {{SITENAME}} се публикуват при условията на
+лиценза за свободна документация на ГНУ
+(за подробности вижте $1).
+Ако не сте съгласни Вашето произведение да бъде променяно и
+преразпределяно от останалите, не го публикувайте.
+<br />
+Също потвърждавате, че Вие сте написали материала
+или сте използвали <b>свободни ресурси</b> -
+<i>обществено достояние</i> или друг свободен източник.
+Ако сте ползвали чужди материали, за които имате разрешение, непременно посочете източника.
+<strong>НЕ ПУБЛИКУВАЙТЕ ПРОИЗВЕДЕНИЯ С АВТОРСКИ ПРАВА БЕЗ РАЗРЕШЕНИЕ!</strong>
+</div>",
+"longpagewarning" => "<strong>ВНИМАНИЕ: Страницата има размер $1 килобайта; някои
+браузъри могат да имат проблеми при редактиране на страници
+по-големи от 32Кб.
+Моля, обмислете дали страницата не може да се раздели на няколко по-малки части.</strong>",
+"readonlywarning" => "<strong>ВНИМАНИЕ: Базата данни бе затворена за поддръжка,
+затова в момента Вашите промени не мога да бъдат съхранени.
+Ако желаете, може да съхраните страницата като текстов файл и да се
+опитате да я публикувате по-късно.</strong>",
+"protectedpagewarning" => "<strong>ВНИМАНИЕ: Страницата е затворена за промени, само
+администратори могат да я редактират.
+Моля, следвайте [[Project:Защитена_страница|указанията за защитена страница]].</strong>",
+
+# History pages
+#
+'revhistory'      => 'История на версиите',
+'nohistory'       => 'Няма редакционна история за тази страница.',
+'revnotfound'     => 'Версията не е открита',
+'revnotfoundtext' => "Желаната стара версия на страницата не бе открита.
+Моля, проверете адреса, който използвахте за достъп към страницата.\n",
+'loadhist'        => 'Зареждане история на страницата',
+'currentrev'      => 'Текуща версия',
+'revisionasof'    => "Версия от $1",
+'cur'             => 'тек',
+'next'            => 'след',
+'last'            => 'посл',
+'orig'            => 'ориг',
+'histlegend'      => 'Разлики: направете отметки в кутийките срещу версиите, които желаете да сравните, и натиснете "Enter" или бутона отдолу.<br />
+Легенда: (<b>тек</b>) = разлика с текущата версия,
+(<b>посл</b>) = разлика с предишната версия, <b>М</b>&nbsp;=&nbsp;малка промяна',
+
+# Diffs
+#
+'difference'   => '(Разлики между версиите)',
+'loadingrev'   => 'зареждане на версии за функцията <em>разл</em>',
+'lineno'       => "Ред $1:",
+'editcurrent'  => 'Редактиране на текущата версия на страницата',
+'selectnewerversionfordiff' => 'Избиране на нова версия за сравнение',
+'selectolderversionfordiff' => 'Избиране на стара версия за сравнение',
+'compareselectedversions' => 'Сравнение на избраните версии',
+
+# Search results
+#
+'searchresults' => 'Резултати от търсенето',
+'searchresulttext' => "За повече информация относно {{SITENAME}}, вижте [[Project:Търсене|Търсене в {{SITENAME}}]].",
+'searchquery'  => "За заявка \"$1\"",
+'badquery'    => 'Лошо формулирана заявка за търсене',
+'badquerytext'  => 'Вашата заявка не можа да бъде обработена.
+Вероятно сте се опитали да търсите дума с по-малко от три букви, което все
+още не се поддържа.
+Възможно е и да сте сгрешили в изписването на израза, например: "риба и и везни".
+Моля, опитайте с нова заявка.',
+'matchtotals'  => "Заявката \"$1\" отговаря на $2 заглавия на статии
+и на текста на $3 статии.",
+'nogomatch' => 'Не съществуват страници с точно това заглавие, опит за пълнотекстово търсене.',
+'titlematches'  => 'Съответствия в заглавията на статии',
+'notitlematches' => 'Няма съответствия в заглавията на статии',
+'textmatches'  => 'Съответствия в текста на статии',
+'notextmatches'  => 'Няма съответствия в текста на статии',
+'prevn'      => "предишни $1",
+'nextn'      => "следващи $1",
+'viewprevnext'  => "Преглед ($1) ($2) ($3).",
+'showingresults' => "Показване на <b>$1</b> резултата, започвайки от #<b>$2</b>.",
+'showingresultsnum' => "Показване на <b>$3</b> резултата, започвайки от #<b>$2</b>.",
+'nonefound'    => "<strong>Забележка</strong>: безрезултатните търсения често са причинени
+от това, че се търсят основни думи като \"има\" или \"от\", които не се индексират,
+или от това, че се търсят повече от една думи (показват се само страници, съдържащи всички
+зададени понятия).",
+'powersearch' => 'Търсене',
+'powersearchtext' => "
+Търсене в именни пространства:<br />
+$1<br />
+$2 Показване на пренасочвания &nbsp; Търсене на $3 $9",
+'searchdisabled' => "<p>Пълнотекстовото търсене бе временно изключено поради
+голямото натоварване на сървъра.
+Междувременно може да търсите чрез Google:</p>",
+'googlesearch' => "
+<!-- претърсване на сайта чрез Google -->
+<form method='GET' action='http://www.google.com/search'>
+<table bgcolor='#FFFFFF'><tr><td>
+<a href='http://www.google.com/'>
+<img src='http://www.google.com/logos/Logo_40wht.gif'
+border='0' alt='Google'/></a>
+</td>
+<td>
+<input type='text' name='q' size='31' maxlength='255' value='$1'/>
+<input type='submit' name='btnG' value='Google Search'/>
+<small>
+<input type='hidden' name='domains' value='{{SERVER}}'/><br />
+<input type='radio' name='sitesearch' value=''/> WWW
+<input type='radio' name='sitesearch' value='{{SERVER}}' checked='checked'/> {{SERVER}} <br />
+<input type='hidden' name='ie' value='$2'/>
+<input type='hidden' name='oe' value='$2'/>
+</small>
+</td></tr></table>
+</form>
+<!-- претърсване на сайта чрез  Google -->
+
+Може да използвате следната препратка, за да създадете или редактирате страницата: <a href='{{localurl:$1|action=edit}}'>$1</a>",
+'blanknamespace' => '(Основно)',
+
+# Preferences page
+#
+'preferences'  => 'Настройки',
+'prefsnologin' => 'Не сте влезли',
+'prefsnologintext'  => "Необходимо е да [[Special:Userlogin|влезете]],
+за да може да променяте потребителските си настройки.",
+"prefslogintext" => "Влязохте като \"$1\".
+Вашият вътрешен номер e $2.
+
+Вижте [[{{ns:4}}:Настройки|помощта за потребителските настройки]], за да се ориентирате при избора.",
+'prefsreset'  => 'Стандартните настройки бяха възстановени.',
+'qbsettings'  => 'Настройки на лентата за бърз избор',
+'changepassword' => 'Смяна на парола',
+'skin'      => 'Облик',
+'math'      => 'Показване на математически формули',
+'dateformat'  => 'Формат на датата',
+'math_failure'    => 'Неуспех при разбора',
+'math_unknown_error'  => 'непозната грешка',
+'math_unknown_function'  => 'непозната функция',
+'math_lexing_error'  => 'лексикална грешка',
+'math_syntax_error'  => 'синтактична грешка',
+'math_image_error' => 'Превръщането към PNG не сполучи. Проверете дали latex, dvips и gs са правилно инсталирани.',
+'math_bad_tmpdir' => 'Невъзможно е писането или създаването на временна папка за математическите операции',
+'math_bad_output' => 'Невъзможно е писането или създаването на изходяща папка за математическите операции',
+'math_notexvc'  => 'Липсва изпълнимият файл на texvc. Моля, прегледайте math/README за информация относно конфигурирането.',
+'prefs-personal' => 'Потребителски данни',
+'prefs-rc' => 'Последни промени и мъничета',
+'prefs-misc' => 'Други настройки',
+'saveprefs'    => 'Съхранение на настройките',
+'resetprefs'  => 'Стандартни настройки',
+'oldpassword'  => 'Стара парола',
+'newpassword'  => 'Нова парола',
+'retypenew'    => 'Нова парола повторно',
+'textboxsize'  => 'Размери на текстовата кутия',
+'rows'      => 'Редове',
+'columns'    => 'Колони',
+'searchresultshead' => 'Настройки за резултати от търсене',
+'resultsperpage' => 'Резултати на страница',
+'contextlines'  => 'Редове за резултат',
+'contextchars'  => 'Знаци от контекста на ред',
+'stubthreshold' => 'Определяне като къси статии до',
+'recentchangescount' => 'Брой заглавия в последни промени',
+'savedprefs'  => 'Вашите настройки бяха съхранени.',
+'timezonetext'  => 'Въведете броя часове, с които Вашето местно време се
+различава от това на сървъра ([[UTC]]).',
+'localtime'  => 'Местно време',
+'timezoneoffset' => 'Отместване',
+'servertime'  => 'Време на сървъра',
+'guesstimezone' => 'Попълване чрез браузъра',
+'emailflag'    => 'Забраняване на писма от други потребители',
+'defaultns'    => 'Търсене в тези именни пространства по подразбиране:',
+
+# Recent changes
+#
+'changes' => 'промени',
+'recentchanges' => 'Последни промени',
+'recentchangestext' => "Проследяване на последните промени в {{SITENAME}}.
+
+Легенда: <b>тек</b> = разлика на текущата версия,
+<b>ист</b> = история на версиите, <b>М</b>&nbsp;=&nbsp;малка промяна, <b>Н</b>&nbsp;=&nbsp;начало",
+'rcloaderr'    => 'Зареждане последни промени',
+'rcnote'    => "Показани са последните <strong>$1</strong> промени през последните <strong>$2</strong> дни.",
+'rcnotefrom'  => "Дадени са промените от <b>$2</b> (до <b>$1</b> показани).",
+'rclistfrom'  => "Показване на промени, започвайки от $1.",
+# 'rclinks'    => "Показване на последните $1 промени през последните $2 часа / последните $3 дни",
+# 'rclinks'    => "Показване на последните $1 промени през последните $2 дни.",
+'rclinks'    => "Показване на последните $1 промени през последните $2 дни<br />$3",
+'showhideminor' => "$1 на малки промени | $2 на ботове | $3 на влезли потребители | $4 patrolled edits",
+'rchide'    => "$4; $1 малки промени; $2 вторични именни пространства; $3 многократни редакции.",
+'rcliu'      => "; $1 редакции от влезли потребители",
+'diff'      => 'разл',
+'hist'      => 'ист',
+'hide'      => 'скриване',
+'show'      => 'показване',
+'tableform'    => 'таблица',
+'listform'    => 'списък',
+'nchanges'    => "$1 промени",
+'minoreditletter' => 'М',
+'newpageletter' => 'Н',
+
+# Upload
+#
+'upload'    => 'Качване',
+'uploadbtn'    => 'Качване',
+'uploadlink'  => 'Качване на картинки',
+'reupload'    => 'Повторно качване',
+'reuploaddesc'  => 'Връщане към формуляра за качване.',
+'uploadnologin' => 'Не сте влезли',
+'uploadnologintext'  => "Необходимо е да [[Special:Userlogin|влезете]], за да качвате файлове.",
+'uploaderror'  => 'Грешка при качване',
+# TODO $wgMetaNamespace - Project or NS_PROJECT
+'uploadtext'  => "'''ВНИМАНИЕ!''' Преди да качите нещо,
+прочетете и се придържайте към [[Project:Политика_за_използване_на_картинки|политиката за използване на картинки]].
+
+Ако файл с указаното име вече съществува в {{SITENAME}}, то той ще бъде
+заменен без предупреждение. Затова, ако не правите актуализация, първо се убедете,
+че такъв файл не съществува.</p>
+
+За да прегледате съществуващите в базата данни картинки,
+разгледайте [[Special:Imagelist|списъка с качените картинки]].
+Качванията и изтриванията се записват в [[Project:Дневник_на_качванията|дневника на качванията]].
+
+Използвайте долния формуляр, за да качвате нови картинки,
+които да използвате в статиите си.
+В повечето браузъри ще видите бутон \"Browse...\"
+(ако използвате преведен интерфейс, може да видите \"Избор на файл...\",
+\"Избор...\" и др.), който ще отвори основния за вашата операционна система
+диалогов прозорец за избиране на файл.
+След като изберете файл, името му ще се появи в текстовото поле до бутона.
+Трябва също да отметнете и кутийката, с която потвърждавате, че не
+нарушавате никакви авторски права посредством качването на файла.
+Натиснете бутона \"Качване\", за да завършите качването.
+Това може да отнеме известно време, ако връзката Ви към Интернет е бавна.</p>
+<p>Предпочитаните формати са JPEG за фотографии, PNG за рисунки и иконки и OGG за музикални файлове, като самото име на файла може да съдържа и кирилски букви, например ''Васил_Левски.jpg''. Хубаво е да дадете описателно име на файловете, за да се избегне евентуално объркване.
+
+За да включите картинка в статия, използвайте една от следните препратки: '''<nowiki>[[{{ns:6}}:картинка.jpg]]</nowiki>''' или '''<nowiki>[[{{ns:6}}:картинка.png|алтернативен текст]]</nowiki>''' или '''<nowiki>[[{{ns:-2}}:звук.ogg]]</nowiki>''' за музикални файлове.
+
+Моля, обърнете внимание на това, че както при страниците, останалите потребители могат да редактират или изтрият Вашите качени неща, ако сметнат, че това помага на енциклопедията, а на Вас може да Ви бъде забранено да качвате файлове, ако злоупотребявате със системата.",
+'uploadlog'    => 'дневник на качванията',
+'uploadlogpage' => 'Дневник_на_качванията',
+'uploadlogpagetext' => 'Списък с последните качвания.
+Показаните времена са според часовата зона на сървъра ([[UTC]]).',
+'filename'    => 'Име на файл',
+'filedesc'    => 'Описание',
+'filestatus' => 'Авторско право',
+'filesource' => 'Изходен код',
+'copyrightpage' => "{{ns:4}}:Авторски права",
+'copyrightpagename' => "авторските права в {{SITENAME}}",
+'uploadedfiles'  => 'Качени файлове',
+'ignorewarning'  => 'Съхраняване на файла въпреки предупрежденията.',
+'minlength'    => 'Имената на картинките трябва да съдържат поне три знака.',
+'badfilename'  => "Картинката бе преименувана на \"$1\".",
+'badfiletype'  => "Файловият формат \".$1\" не се препоръчва за картинки.",
+'largefile'    => 'Препоръчва се картинките да не надвишават 100 килобайта.',
+'successfulupload' => 'Качването бе успешно',
+'fileuploaded'  => "Файлът \"$1\" бе успешно качен.
+Моля, последвайте препратката: ($2) към страницата за описание и
+въведете малко информация за файла - кога и от кого е създаден
+и всякаква друга информация, която имате за него.",
+'uploadwarning' => 'Предупреждение при качване',
+'savefile'    => 'Съхраняване на файл',
+'uploadedimage' => "качена \"[[$1]]\"",
+'uploaddisabled' => 'Съжаляваме, качванията бяха спрени.',
+
+# Image list
+#
+'imagelist'    => 'Списък на картинките',
+'imagelisttext'  => "Списък от $1 картинки, сортирани $2.",
+'getimagelist'  => 'донасяне на списъка с картинки',
+'ilsubmit'    => 'Търсене',
+'showlast'    => "Показване на последните $1 картинки, сортирани $2.",
+'byname'    => 'по име',
+'bydate'    => 'по дата',
+'bysize'    => 'по размер',
+'imgdelete'    => 'изтр',
+'imgdesc'    => 'опис',
+'imglegend'    => 'Легенда: (опис) = показване/редактиране описание на картинка.',
+'imghistory'  => 'История на картинката',
+'revertimg'    => 'връщ',
+'deleteimg'    => 'изтр',
+'imghistlegend' => 'Легенда: (тек) = текущата картинка, (изтр) = изтриване
+на съответната версия, (връщ) = възвръщане към съответната версия.
+<br /><i>Щракнете върху датата, за да видите картинката, качена на тази дата</i>.',
+'imagelinks'  => 'Препратки към картинката',
+'linkstoimage'  => 'Следните страници сочат към картинката:',
+'nolinkstoimage' => 'Няма страници, сочещи към картинката.',
+
+# Statistics
+#
+'statistics'  => 'Статистика',
+'sitestats'    => 'Статистика',
+'userstats'    => 'Потребителска статистика',
+'sitestatstext' => "Има '''$1''' страници в базата данни.
+Това включва дискусионни страници, страници за {{SITENAME}}, изключително къси
+страници, пренасочващи страници и други, които вероятно не са статии.
+Изключвайки тези, има '''$2''' страници, които може би са действителни статии.<p>
+Имало е '''$4''' редакции на страници откакто уикито бе пуснато.
+Това прави средно по '''$5''' редакции на страница.
+
+За по-подробна статистическа информация вижте:
+<ul>
+<li><a href='http://bg.wikipedia.org/stats'>Потребителска статистика</a>,</li>
+<li><a href='http://www.wikipedia.org/wikistats/EN/Sitemap.htm'>Уики-статистика</a>,</li>
+<li><a href='http://www.wikipedia.org/wiki/Wikipedia:Statistics'>Прираст</a>.</li>
+</ul>",
+'userstatstext' => "Има '''$1''' регистрирани потребителя. '''$2''' от тях са администратори (вижте $3).",
+
+# Maintenance Page
+#
+'maintenance'    => 'Страница за поддръжка',
+'maintnancepagetext'  => 'Тази страница съдържа няколко удобни инструмента за всекидневна поддръжка. Някои от тези функции доста натоварват базата данни, затова, моля, не обновявайте страницата след всяка Ваша операция, ;-)',
+'maintenancebacklink'  => 'Обратно към страницата за поддръжка',
+'disambiguations'  => 'Пояснителни страници',
+'disambiguationspage'  => "{{ns:4}}:Препратки_към_пояснителни_страници",
+'disambiguationstext'  => "Следните статии сочат към <i>пояснителна страница</i>. Вместо това те би трябвало да сочат към съответната статия.<br /> Страница се определя като <i>\"пояснителна\"</i>, ако към нея се сочи от $1.<br />Тук <i>не</i> са посочени препратки от други именни пространства.",
+'doubleredirects'  => 'Двойни пренасочвания',
+'doubleredirectstext' => '<b>Внимание:</b> Този списък може да съдържа лъжливи записи. Това означава, че една пренасочваща страница съдържа допълнителен текст с препратки след заповедта #REDIRECT.<br />\nВсеки ред съдържа препратки към първото и второто пренасочване, както и първия ред на текста на второто пренасочване, който обикновено посочва <i>"истинката"</i> целева статия, към която първото пренасочване би трябвало да сочи.',
+'brokenredirects'  => 'Невалидни пренасочвания',
+'brokenredirectstext'  => 'Следните пренасочващи страници сочат към несъществуващи статии.',
+'selflinks'    => 'Страници с препратки към себе си',
+'selflinkstext'    => 'Следните страници правят препратки към себе се, което не би трябвало да е така.',
+'mispeelings'           => 'Страници с правописни грешки',
+'mispeelingstext'  => "Следните страници съдържат основни правописни грешки, които са
+изброени в $1. Правилните форми може да се посочат в скоби: (ето така).",
+'mispeelingspage'       => 'Списък на основните правописни грешки',
+'missinglanguagelinks'  => 'Липсващи езикови препратки',
+'missinglanguagelinksbutton'    => 'Търсене на липсващи езикови препратки за',
+'missinglanguagelinkstext'      => "Тези статии <i>не</i> сочат към техните копия в $1. Пренасочванията и подстраниците <i>не са</i> показани.",
+
+
+# Miscellaneous special pages
+#
+'orphans'    => 'Страници-сираци',
+'lonelypages'  => 'Страници-сираци',
+'unusedimages'  => 'Неизползвани картинки',
+'popularpages'  => 'Известни страници',
+'nviews'    => "$1 прегледа",
+'wantedpages'  => 'Желани страници',
+'nlinks'    => "$1 препратки",
+'allpages'    => 'Всички страници',
+'randompage'  => 'Случайна страница',
+'shortpages'  => 'Кратки страници',
+'longpages'    => 'Дълги страници',
+'deadendpages'  => 'Задънени страници',
+'listusers'    => 'Списък на потребителите',
+'specialpages'  => 'Специални страници',
+'spheading'    => 'За всички потребители',
+'protectpage'  => 'Защитена страница',
+'recentchangeslinked' => 'Сродни промени',
+'rclsub'    => "(на страници, сочени от \"$1\")",
+'debug'      => 'Отстраняване на грешки',
+'newpages'    => 'Нови страници',
+'ancientpages'    => 'Стари статии',
+'intl'          => 'Междуезикови препратки',
+'move' => 'Преместване',
+'movethispage'  => 'Преместване на страницата',
+'unusedimagestext' => '<p>Моля, обърнете внимание на това, че други сайтове могат да сочат към картинката чрез пряк адрес и въпреки това тя може да се намира в списъка.',
+'booksources'  => 'Източници на книги',
+'booksourcetext' => 'Показани са препратки към други сайтове, които продават нови и
+използвани книги и могат да имат допълнителна информация за книгите, които търсите.
+{{SITENAME}} не е свързана с никоя от тези фирми и този списък не трябва да
+се разглежда като подкрепа към тях.',
+'isbn'  => 'ISBN',
+'rfcurl' =>  "http://www.faqs.org/rfcs/rfc$1.html",
+'alphaindexline' => "от $1 до $2",
+'version'       => 'Версия',
+
+# Email this user
+#
+'mailnologin'  => 'Няма електронна поща',
+'mailnologintext' => "Необходмимо е да [[Special:Userlogin|влезете]] и да посочите валидна електронна поща в [[{{ns:-1}}:Preferences|настройките]] си, за да може да пращате писма на други потребители.",
+'emailuser'    => 'Пращане писмо на потребителя',
+'emailpage'    => 'Пращане писмо на потребител',
+'emailpagetext'  => 'Ако потребителят е посочил валидна електронна поща в
+настройките си, чрез долния формуляр може да му се изпрати съобщение.
+Адресът, записан в настройките Ви, ще се появи в полето "От" на
+изпратеното писмо, така че получателят ще е в състояние да Ви отговори.',
+'usermailererror'  => 'Пощенският обект даде грешка: ', # Mail object returned error:
+'defemailsubject'  => "Писмо от {{SITENAME}}",
+'noemailtitle'  => 'Няма електронна поща',
+'noemailtext'  => 'Потребителят не посочил валидна електронна поща или е избрал да не получава
+писма от други потребители.',
+'emailfrom'    => 'От',
+'emailto'    => 'До',
+'emailsubject'  => 'Относно',
+'emailmessage'  => 'Съобщение',
+'emailsend'    => 'Изпращане',
+'emailsent'    => 'Писмото е изпратено',
+'emailsenttext' => 'Писмото Ви бе изпратено.',
+
+# Watchlist
+#
+'watchlist'    => 'Моят списък за наблюдение',
+'watchlistsub'  => "(за потребител \"$1\")",
+'nowatchlist'  => 'Списъкът Ви за наблюдение е празен.',
+'watchnologin'  => 'Не сте влезли',
+'watchnologintext'  => "Необходимо е да [[Special:Userlogin|влезете]], за да може да променяте списъка си за наблюдение.",
+'addedwatch'  => 'Добавено в списъка за наблюдение',
+'addedwatchtext' => "Страницата \"$1\" бе добавена към [[{{ns:-1}}:Watchlist|списъка Ви за наблюдение]].
+Нейните бъдещи промени, както и на съответната й дискусионна страница, ще се описват там, а тя ще се появява с '''удебелен шрифт''' в
+[[{{ns:-1}}:Recentchanges|списъка с последните промени]],
+което ще направи по-лесно избирането й.
+
+<p>Ако по-късно искате да премахнете страницата от списъка си за наблюдение,
+щракнете на \"Спиране на наблюдение\" в страничната лента.",
+'removedwatch'  => 'Премахнато от списъка за наблюдение',
+'removedwatchtext' => "Страницата \"$1\" бе премахната от списъка Ви за наблюдение.",
+'watch' => 'Наблюдаване',
+'watchthispage'  => 'Наблюдаване на страницата',
+'unwatch' => 'Спиране на наблюдение',
+'unwatchthispage' => 'Спиране на наблюдение',
+'notanarticle'  => 'Не е статия',
+'watchnochange' => 'Никоя от наблюдаваните страници не е била редактирана в показаното време.',
+'watchdetails' => "($1 наблюдавани страници (без дискусионни);
+$2 редактирани страници в избраното време;
+$3...
+[$4 показване и редактиране на пълния списък].)",
+'watchmethod-recent' => 'проверка на последните промени за наблюдавани страници',
+'watchmethod-list' => 'проверка на наблюдаваните страници за скорошни редакции',
+'removechecked' => 'Премахване на избраните от списъка за наблюдение',
+'watchlistcontains' => "Вашият списък за наблюдение съдържа $1 страници.",
+'watcheditlist' => 'Показани са наблюдаваните страници в
+азбучен ред. Отметнете кутийките на страниците, които искате да премахнете
+от списъка Ви за наблюдение и натиснете бутона "Премахване на избраните".',
+'removingchecked' => 'Премахване на избраните от списъка за наблюдение...',
+'couldntremove' => "Неуспех при премахването на '$1'...",
+'iteminvalidname' => "Проблем с '$1', грешно име...",
+'wlnote' => "Показани са последните $1 промени през последните <b>$2</b> часа.",
+'wlshowlast' => "Показване на последните $1 часа $2 дни $3",
+'wlsaved' => 'Това е съхранена версия на вашия списък за наблюдение.',
+
+# Delete/protect/revert
+#
+'deletepage'  => 'Изтриване на страница',
+'confirm'    => 'Потвърждение',
+'excontent' => "съдържанието бе: '$1'",
+'exbeforeblank' => "съдържанието преди изпразването бе: '$1'",
+'exblank' => 'страницата бе празна',
+'confirmdelete' => 'Потвърждение за изтриване',
+'deletesub'    => "(Изтриване на \"$1\")",
+'historywarning' => 'Внимание: Страницата, която ще изтриете, има история: ',
+'confirmdeletetext' => "На път сте безвъзвратно да изтриете страница или картинка заедно с
+цялата й история от базата данни.
+Моля, потвърдете, че искате това, разбирате последствията и правите това
+в съответствие с нашата [[{{ns:4}}:Линия на поведение|линия на поведение]].",
+'actioncomplete' => 'Действието бе изпълнено',
+'deletedtext'  => "Страницата \"$1\" беше изтрита.
+Вижте $2 за запис на последните изтривания.",
+"deletedarticle" => "изтрита \"$1\"",
+"dellogpage"  => "Дневник_на_изтриванията",
+"dellogpagetext" => 'Списък на най-скорошните изтривания.
+Показаните времена са според часовата зона на сървъра ([[UTC]]).',
+'deletionlog'  => 'дневника на изтриванията',
+'reverted'    => 'Възвръщане към предишна версия',
+'deletecomment'  => 'Причина за изтриването',
+'imagereverted' => 'Възвръщането към предишна версия бе успешно.',
+'rollback'    => 'Връщане назад на промените', #Roll back edits
+'rollback_short' => 'Връщане',
+'rollbacklink'  => 'връщане', #rollback
+'rollbackfailed' => 'Връщането не сполучи', #Rollback failed
+'cantrollback'  => 'Промяната не може да се извърши; последният автор е единственият собственик на статията.',
+'alreadyrolled'  => "Последната редакция на [[$1]], направена от [[Потребител:$2|$2]] ([[Потребител беседа:$2|Беседа]]) не може да се върне назад; някой друг вече е редактирал статията или е върнал назад промените.
+
+Последната редакция е на [[Потребител:$3|$3]] ([[Потребител беседа:$3|Беседа]]). ",
+#   only shown if there is an edit comment
+'editcomment' => "Коментарът на редакцията е бил: \"<i>$1</i>\".",
+'revertpage'  => "Възвръщане към последната редакция на $1",
+'protectlogpage' => 'Дневник_на_защитата',
+'protectlogtext' => "Списък на защитите и техните сваляния за страницата.
+За повече информация вижте [[{{ns:4}}:Защитена страница]].",
+'protectedarticle' => "защитена [[$1]]",
+'unprotectedarticle' => "незащитена [[$1]]",
+'protectsub' => "(Защитаване на \"$1\")",
+'confirmprotecttext' => 'Наистина ли искате да защитите страницата?',
+'confirmprotect' => 'Потвърдете защитата',
+'protectcomment' => 'Причина за защитата',
+'unprotectsub' => "(Сваляне на защита на \"$1\")",
+'confirmunprotecttext' => 'Наистина ли искате да свалите защитата на страницата?',
+'confirmunprotect' => 'Потвърдете свалянето на защитата',
+'unprotectcomment' => 'Причина за сваляне на защитата',
+
+# Undelete
+'undelete' => 'Възстановяване на изтрита страница',
+'undeletepage' => 'Преглед и възстановяване на изтрити страници',
+'undeletepagetext' => 'Следните страници бяха изтрити, но се намират все още
+в архива и могат да бъдат възстановени. Архивът може да се почиства от време на време.',
+'undeletearticle' => 'Възстановяване на изтрита статия',
+'undeleterevisions' => "$1 версии архивирани",
+'undeletehistory' => 'Ако възстановите страницата, всички версии ще бъдат
+върнати в историята.
+Ако след изтриването е създадена страница със същото име, възстановените
+версии ще се появят като по-ранна история, а текущата версия на страницата
+няма да бъде автоматично заменена.',
+'undeleterevision' => "Изтрита версия на $1",
+'undeletebtn' => 'Възстановяване!',
+'undeletedarticle' => "възстановена \"$1\"",
+'undeletedtext'   => "Статията [[$1]] бе успешно възстановена.
+Вижте [[{{ns:4}}:Дневник_на_изтриванията|дневника на изтриванията]] за запис на последните изтривания и възстановявания.",
+
+# Contributions
+#
+'contributions'  => 'Приноси',
+'mycontris' => 'Моите приноси',
+'contribsub'  => "За $1",
+'nocontribs'  => 'Не са намерени промени, отговарящи на критерия.',
+'ucnote'    => "Показани са последните <b>$1</b> промени, извършени от този потребител през последните <b>$2</b> дни.",
+'uclinks'    => "Показване на последните $1 промени; показване на последните $2 дни.",
+'uctop'    => ' (последна)' ,
+
+# What links here
+#
+'whatlinkshere'  => 'Какво сочи насам',
+'notargettitle' => 'Няма цел',
+'notargettext'  => 'Не указахте целева страница или потребител,
+върху която/който да се изпълни действието.',
+'linklistsub'  => '(Списък с препратки)',
+'linkshere'    => 'Следните страници сочат насам:',
+'nolinkshere'  => 'Няма страници, сочещи насам.',
+'isredirect'  => 'пренасочваща страница',
+
+# Block/unblock IP
+#
+'blockip'    => 'Блокиране на потребител',
+'blockiptext'  => "Използвайте долния формуляр, за да забраните правото на писане
+на определен IP-адрес или потребител.
+Това трябва да се направи само, за да се предотвратят прояви на вандализъм,
+и в съответствие с [[{{ns:4}}:Линия_на_поведение|линията на поведение]] на {{SITENAME}}.
+Посочете също и причина за блокирането (например, заглавия на страници,
+станали обект на вандализъм).
+
+Времето за изтичане на блокирането се въвежда според установения ГНУ-формат, описан в [http://www.gnu.org/software/tar/manual/html_chapter/tar_7.html ръководството], например: '1 hour', '2 days', 'next Wednesday', '1 January 2017'. Неограничено блокиране може да се зададе чрез 'indefinite' или 'infinite'.",
+'ipaddress'    => 'IP-адрес/потребител',
+'ipbexpiry'    => 'Изтичане на срока',
+'ipbreason'    => 'Причина',
+'ipbsubmit'    => 'Блокиране на потребителя',
+'badipaddress'  => 'Невалиден IP-адрес или грешно име на потребител',
+'blockipsuccesssub' => 'Блокирането бе успешно',
+'blockipsuccesstext' => "\"$1\" беше блокиран.
+<br />Вижте [[{{ns:-1}}:Ipblocklist|списъка на блокираните IP-адреси]], за да прегледате блокираните.",
+'unblockip'    => 'Отблокиране на потребител',
+'unblockiptext'  => 'Използвайте долния формуляр, за да възстановите
+правото на писане на по-рано блокиран IP-адрес или потребител.',
+'ipusubmit'    => 'Отблокиране на адреса',
+'ipusuccess'  => "\"$1\" бе отблокиран",
+'ipblocklist'  => 'Списък на блокирани IP-адреси и потребители',
+'blocklistline'  => "$1, $2 е блокирал $3 ($4)",
+'infiniteblock' => 'изтича на infinite', //fixme
+'expiringblock' => 'изтича на $1',
+'blocklink'    => 'блокиране',
+'unblocklink'  => 'отблокиране',
+'contribslink'  => 'приноси',
+'autoblocker'  => "Автоматично блокиране поради взаимно ползване на IP-адрес с \"$1\". Причина \"$2\".",
+'blocklogpage'  => 'Дневник_на_блокиранията',
+'blocklogentry' => 'блокиране на "$1" със срок на изтичане $2',
+'blocklogtext'  => "Това е дневник на блокиранията и отблокиранията, извършени от този потребител. Автоматично блокираните IP-адреси не са показани. Вижте  [[{{ns:-1}}:Ipblocklist|списъка на блокираните IP-адреси]] за текущото състояние
+на блокиранията.",
+'unblocklogentry'       => 'отблокиране на "$1"',
+'range_block_disabled'  => 'Възможността на администраторите да задават интервали (<i>range blocks</i>) е изключена.',
+'ipb_expiry_invalid'    => 'Невалиден срок на изтичане.',
+'ip_range_invalid'      => "Невалидни граници за IP-адреси.\n",
+'proxyblocker'  => 'Блокировач на проксита',
+'proxyblockreason'      => 'Вашият IP-адрес беше блокиран, тъй като е отворено прокси. Моля, свържете се с Вашия интернет-доставчик и го информирайте за този сериозен проблем в сигурността.',
+'proxyblocksuccess'     => "Готово.\n",
+
+# Developer tools
+#
+'lockdb'    => 'Заключване на базата данни',
+'unlockdb'    => 'Отключване на базата данни',
+'lockdbtext'  => 'Заключването на базата данни ще попречи на всички
+потребители да редактират страници, да сменят своите настройки, да редактират
+своите списъци за наблюдение и на всички други техни действия, изискващи
+промени в базата данни.
+Моля, потвърдете, че искате точно това и ще отключите базата данни,
+когато привършите с работата по подръжката.',
+'unlockdbtext'  => 'Отключването на базата данни ще възстанови способността на
+потребителите да редактират страници, да сменят своите настройки, да редактират
+своите списъци за наблюдение и изпълнението на всички други действия, изискващи
+промени в базата данни.
+Моля, потвърдете, че искате точно това.',
+'lockconfirm'  => 'Да, наистина искам да заключа базата данни.',
+'unlockconfirm'  => 'Да, наистина искам да отключа базата данни.',
+'lockbtn'    => 'Заключване на базата данни',
+'unlockbtn'    => 'Отключване на базата данни',
+'locknoconfirm' => 'Не сте отметнали кутийката за потвърждение.',
+'lockdbsuccesssub' => 'Заключване на базата данни успешно',
+'unlockdbsuccesssub' => 'Отключване на базата данни успешно',
+'lockdbsuccesstext' => "Базата данни на {{SITENAME}} бе заключена.
+<br />Не забравяйте да отключите базата данни, когато привършите с работата по поддръжката.",
+'unlockdbsuccesstext' => "Базата данни на {{SITENAME}} бе отключена.",
+
+# Make sysop
+'makesysoptitle'        => 'Превръщане на потребител в администратор',
+'makesysoptext'         => 'Този формуляр се използва от бюрократи за превръщане на обикновени потребители в администратори.
+
+Въведете името на потребителя в полето и натиснете бутона, за да направите съответния потребител администратор',
+'makesysopname'         => 'Име на потребителя:',
+'makesysopsubmit'       => 'Превръщане на потребителя в администратор',
+'makesysopok'           => "<b>Потребителят '$1' бе направен администратор</b>.",
+'makesysopfail'         => "<b>Потребителят '$1' не бе направен администратор. (Правилно ли въведохте името?)</b>",
+'setbureaucratflag' => 'Вдигане на флага "бюрократ"',
+'bureaucratlog'         => 'Дневник_на_бюрократите',
+'bureaucratlogentry'    => "Права за потребителя \"$1\": \"$2\"",
+'rights'                => 'Права:',
+'set_user_rights'       => 'Даване на потребителски права',
+'user_rights_set'       => "<b>Потребителските права за \"$1\" са променени</b>",
+'set_rights_fail'       => "<b>Потребителските права за \"$1\" не бяха променени. (Правилно ли въведохте името?)</b>",
+'makesysop'             => 'Превръщане на потребител в администратор',
+# Move page
+#
+'movepage'    => 'Преместване на страница',
+'movepagetext'  => "Посредством долния формуляр може да преименувате
+страница, премествайки цялата й история на новото име.
+Старото заглавие ще се превърне в пренасочваща страница.
+Препратките към старата страница няма да бъдат променени; затова
+проверете за двойни или невалидни пренасочвания.
+Вие сами би трябвало да се убедите в това, дали препратките продължават да сочат там,
+където се предполага.
+
+Страницата '''няма''' да бъде преместена, ако вече съществува страница с
+новото име, освен ако е празна или пренасочване и няма редакционна история.
+
+<b>ВНИМАНИЕ!</b>
+Това може да е голяма и неочаквана промяна за известна страница;
+моля, уверете се, че разбирате последствията, преди да продължите.",
+"movepagetalktext" => "Съответната дискусионна страница, ако съществува,
+ще бъде автоматично преместена заедно с нея, '''освен ако:'''
+*не местите страницата от едно именно пространство в друго,
+*вече съществува непразна дискусионна страница с това име или
+*не сте отметнали долната кутийка.
+
+В тези случаи, ако желаете, ще е необходимо да преместите страницата ръчно.",
+'movearticle'  => 'Преместване на страница',
+'movenologin'  => 'Не сте влезли',
+'movenologintext' => "Необходимо е да [[Special:Userlogin|влезете]], за да може да премествате страници.",
+'newtitle'    => 'Към ново заглавие',
+'movepagebtn'  => 'Преместване',
+'pagemovedsub'  => 'Преместването бе успешно',
+'pagemovedtext' => "Страницата \"[[$1]]\" бе преместена под името \"[[$2]]\".",
+'articleexists' => "Вече съществува страница с това име или името, което сте избрали,
+е невалидно. Моля, изберете друго име.",
+'talkexists'  => 'Страницата бе успешно преместена, но без
+съответната дискусионна страница, защото под новото име
+има една съществуваща. Моля, обединете ги ръчно.',
+'movedto'    => 'преместена като',
+'movetalk'    => 'Преместване и на дискусионната страница, ако е приложимо.',
+'talkpagemoved' => 'Съответната дискусионна страница също бе преместена.',
+'talkpagenotmoved' => 'Съответната дискусионна страница <strong>не</strong> бе преместена.',
+'1movedto2' => "$1 преместена като $2",
+
+# Export
+'export'     => 'Изнасяне на страници',
+'exporttext'    => 'Тук може да изнесете като XML текста и историята на една или повече страници. Получените данни може да:
+<ul>
+<li>вмъкнете в друг сайт, използващ софтуера на МедияУики, </li>
+<li>обработвате или </li>
+<li>просто запазите за лично ползване.</li>
+</ul>
+
+Въвеждайте всяко ново заглавие на статия на <b>нов ред</b>.',
+'exportcuronly' => 'Включване само на текущата версия, а не на цялата история',
+
+# Namespace 8 related
+
+'allmessages'   => 'Всички системни съобщения',
+'allmessagestext' => 'Това е списък на всички системни съобщения, намиращи се в именното пространство МедияУики',
+
+# Thumbnails
+
+'thumbnail-more' => 'Увеличаване',
+'missingimage'   => "<b>Липсваща картинка</b><br /><i>$1</i>\n",
+
+# Special:Import
+'import'        => 'Внасяне на страници',
+'importtext'    => 'Моля, изнесете файла от изходното уики, използвайки инструмента {{ns:-1}}:Export, съхранете го на Вашия диск и го качете тук.',
+'importfailed'  => "Внасянето пропадна: $1",
+'importnotext'  => 'Празно',
+'importsuccess' => 'Внасянето бе успешно!',
+'importhistoryconflict' => 'Съществува версия от историята, която си противоречи с тази (възможно е страницата да е била вече внесена)',
+
+# Keyboard access keys for power users
+'accesskey-search' => 's',
+'accesskey-minoredit' => 'i',
+'accesskey-save' => 's',
+'accesskey-preview' => 'p',
+'accesskey-contributions' => '',
+'accesskey-emailuser' => '',
+'accesskey-compareselectedversions' => 'v',
+
+# tooltip help for the main actions
+'tooltip-watch' => 'Добавяне на страницата към списъка Ви за наблюдение [alt-w]',
+'tooltip-search' => 'Търсене в Уикито',
+'tooltip-minoredit' => 'Отбелязване на промяната като малка [alt-i]',
+'tooltip-save' => 'Съхраняване на промените [alt-s]',
+'tooltip-preview' => 'Предварителен преглед, моля, използвайте го преди да съхраните! [alt-p]',
+'tooltip-compareselectedversions' => 'Показване на разликите между двете избрани версии на страницата [alt-v]',
+
+# Metadata
+'nodublincore' => 'Dublin Core RDF metadata disabled for this server.',
+'nocreativecommons' => 'Creative Commons RDF metadata disabled for this server.',
+'notacceptable' => 'Сървърът не може да предостави данни във формат, който да се разпознава от клиента Ви.',
+
+# Attribution
+
+'anonymous' => "Анонимен потребител(и) на {{SITENAME}}",
+'siteuser'  => "потребителя на {{SITENAME}} $1",
+"lastmodifiedby" => "Последна промяна на $1 от $2.",
+'and' => 'и',
+"othercontribs" => "Основано върху работа на $1.",
+"siteusers" => "потребителите на {{SITENAME}} $1",
+
+# Math
+  'mw_math_png'    => 'Използване винаги на PNG',
+  'mw_math_simple' => 'HTML при опростен TeX, иначе PNG',
+  'mw_math_html'   => 'HTML по възможност, иначе PNG',
+  'mw_math_source' => 'Оставяне като TeX (за текстови браузъри)',
+  'mw_math_modern' => 'Препоръчително за нови браузъри',
+  'mw_math_mathml' => 'MathML по възможност (експериментално)'
+);
+
+/** This is an UTF-8 language */
+require_once( 'LanguageUtf8.php' );
+
+/**
+ * @package MediaWiki
+ * @subpackage Language
+ */
+class LanguageBg extends LanguageUtf8 {
+
+       function getBookstoreList () {
+               global $wgBookstoreListBg ;
+               return $wgBookstoreListBg ;
+       }
+
+       function getNamespaces() {
+               global $wgNamespaceNamesBg;
+               return $wgNamespaceNamesBg;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsBg;
+               return $wgQuickbarSettingsBg;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesBg;
+               return $wgSkinNamesBg;
+       }
+
+       function getDateFormats() {
+               global $wgDateFormatsBg;
+               return $wgDateFormatsBg;
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesBg;
+               if( isset( $wgAllMessagesBg[$key] ) ) {
+                       return $wgAllMessagesBg[$key];
+               } else {
+                       return parent::getMessage( $key );
+               }
+       }
+
+       function getMagicWords()  {
+               global $wgMagicWordsBg;
+               return $wgMagicWordsBg;
+       }
+}
+?>
diff --git a/languages/LanguageBm.php b/languages/LanguageBm.php
new file mode 100644 (file)
index 0000000..958bf32
--- /dev/null
@@ -0,0 +1,16 @@
+<?php
+/** Bambara (Bamanankan)
+  *
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+# Stub for Bambara; import French (official language of Mali)
+
+require_once( 'LanguageFr.php' );
+
+class LanguageBm extends LanguageFr {
+       // Inherit all for now
+}
+
+?>
diff --git a/languages/LanguageBn.php b/languages/LanguageBn.php
new file mode 100644 (file)
index 0000000..ab354ef
--- /dev/null
@@ -0,0 +1,174 @@
+<?php
+/** Bengali (বাংলা)
+  *
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+/** This is an UTF8 language */
+require_once( 'LanguageUtf8.php' );
+
+/* private */ $wgNamespaceNamesBn = array(
+       NS_SPECIAL  => 'বিশেষ',
+       NS_MAIN => '',
+       NS_TALK => 'আলাপ',
+       NS_USER => 'ব্যবহারকারী',
+       NS_USER_TALK => 'ব্যবহারকারী_আলাপ',
+       NS_PROJECT => 'উইকিপেডিয়া',
+       NS_PROJECT_TALK => 'উইকিপেডিয়া_আলাপ',
+       NS_IMAGE => 'চিত্র',
+       NS_IMAGE_TALK => 'চিত্র_আলাপ',
+       NS_MEDIAWIKI_TALK => 'MediaWik i_আলাপ',
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgDateFormatsBn = array();
+
+/* private */ $wgAllMessagesBn = array(
+# Dates
+
+'sunday' => 'রবিবার',
+'monday' => 'সোমবার',
+'tuesday' => 'মঙ্গলবার',
+'wednesday' => 'বুধবার',
+'thursday' => 'বৃহস্পতিবার',
+'friday' => 'শুক্রবার',
+'saturday' => 'শনিবার',
+'january' => 'জানুয়ারী',
+'february' => 'ফেব্রুয়ারী',
+'march' => 'মার্চ',
+'april' => 'এপ্রিল',
+'may_long' => 'মে',
+'june' => 'জুন',
+'july' => 'জুলাই',
+'august' => 'আগস্ট',
+'september' => 'সেপ্টেম্বর',
+'october' => 'অক্টোবর',
+'november' => 'নভেম্বর',
+'december' => 'ডিসেম্বর',
+'jan' => 'জানু',
+'feb' => 'ফেব্রু',
+'mar' => 'মার্চ',
+'apr' => 'এপ্রিল',
+'may' => 'মে',
+'jun' => 'জুন',
+'jul' => 'জুলাই',
+'aug' => 'আগস্ট',
+'sep' => 'সেপ্টে',
+'oct' => 'অক্টো',
+'nov' => 'নভে',
+'dec' => 'ডিসে',
+
+# Bits of text used by many pages:
+#
+
+'mainpage'    => 'প্রধান পাতা',
+'about'     => 'বৃত্তান্ত',
+'aboutsite'      => 'উইকিপেডিয়ার বৃত্তান্ত',
+'aboutpage'   => 'উইকিপেডিয়া:বৃত্তান্ত',
+'help'      => 'সহায়িকা',
+'helppage'    => 'উইকিপেডিয়া:সহায়িকা',
+'bugreports'  => 'ত্রুটি বিবরণী',
+'bugreportspage' => 'উইকিপেডিয়া:ত্রুটি_বিবরণী',
+'faq'     => 'প্রশ্নোত্তর',
+'faqpage'   => 'উইকিপেডিয়া:প্রশ্নোত্তর',
+'edithelp'    => 'সম্পাদনা সহায়িকা',
+'edithelppage'  => 'উইকিপেডিয়া:কিভাবে_একটি_পৃষ্ঠা_সম্পাদনা_করবেন',
+'cancel'    => 'বাতিল কর',
+'qbfind'    => 'খঁুজে দেখ',
+'qbbrowse'    => 'ঘুরে দেখ',
+'qbedit'    => 'সম্পাদনা কর',
+'qbpageoptions' => 'এ পৃষ্ঠার বিকল্পসমূহ',
+'qbpageinfo'  => 'পৃষ্ঠা-সংক্রান্ত তথ্য',
+'qbmyoptions' => 'আমার পছন্দ',
+'mypage'    => 'আমার পাতা',
+'mytalk'    => 'আমার কথাবার্তা',
+'currentevents' => 'সমসাময়িক ঘটনা',
+'errorpagetitle' => 'ভুল',
+'returnto'    => 'ফিরে যাও $1.',
+'tagline'       => 'উইকিপেডিয়া, মুক্ত বিশ্বকোষ থেকে',
+'whatlinkshere' => 'যেসব পাতা থেকে এখানে সংযোগ আছে',
+'help'      => 'সহায়িকা',
+'search'    => 'খঁুজে দেখ',
+'go'    => 'চল',
+'history'   => 'এ পৃষ্ঠার ইতিহাস',
+'printableversion' => 'ছাপার যোগ্য সংস্করণ',
+'editthispage'  => 'এই পৃষ্ঠাটি সম্পাদনা করুন',
+'deletethispage' => 'এই পৃষ্ঠাটি মুছে ফেলুন',
+'protectthispage' => 'এই পৃষ্ঠাটি সংরক্ষণ করুন',
+'unprotectthispage' => 'এই পৃষ্ঠার সংরক্ষণ ছেড়ে দিন',
+'newpage' => 'নতুন পাতা',
+'talkpage'    => 'এই পৃষ্ঠা নিয়ে আলোচনা করুন',
+'articlepage' => 'নিবন্ধ দেখুন',
+'subjectpage' => 'বিষয় দেখুন', # For compatibility
+'userpage' => 'ব্যাবহারকারীর পাতা দেখুন',
+'wikipediapage' => 'মেটা-পাতা দেখুন',
+'imagepage' =>  'ছবির পাতা দেখুন',
+'viewtalkpage' => 'আলোচনা দেখুন',
+'otherlanguages' => 'অন্যান্য ভাষা',
+'redirectedfrom' => '($1 থেকে ঘুরে এসেছে)',
+'lastmodified'  => 'এ পৃষ্ঠায় শেষ পরিবর্তন হয়েছিল $1.',
+'viewcount'   => 'এ পৃষ্ঠা দেখা হয়েছে $1 বার।',
+'administrators' => 'উইকিপেডিয়া:প্রশাসকবৃন্দ',
+'sysoptitle'  => 'Sysop এর  ক্ষমতা প্রয়োজন',
+'sysoptext'   => 'এ কাজটি কেবল \'sysop\' ক্ষমতাসম্পন্ন ব্যক্তিই করতে পারেন। $1 দেখুন।',
+'developertitle' => 'developer এর ক্ষমতা প্রয়োজন',
+'developertext' => 'এ কাজটি কেবল \'developer\' ক্ষমতাসম্পন্ন ব্যক্তিই করতে পারেন। $1 দেখুন।',
+'nbytes'    => '$1 বাইট',
+'go'      => 'চল',
+'ok'      => 'ঠিক আছে',
+'sitetitle'   => 'উইকিপেডিয়া',
+'sitesubtitle'  => 'মুক্ত বিশ্বকোষ ',
+'retrievedfrom' => '\'$1\' থেকে আনীত',
+'newmessages' => 'আপনার $1 এসেছে।',
+'newmessageslink' => 'নতুন বার্তা',
+'editsection'=>'সম্পাদনা করুন',
+'toc' => 'সূচীপত্র',
+'showtoc' => 'দেখাও',
+'hidetoc' => 'সরিয়ে রাখ',
+
+);
+
+class LanguageBn extends LanguageUtf8 {
+       function getNamespaces() {
+               global $wgNamespaceNamesBn;
+               return $wgNamespaceNamesBn;
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesBn;
+               if(array_key_exists($key, $wgAllMessagesBn)) {
+                       return $wgAllMessagesBn[$key];
+               } else {
+                       return parent::getMessage( $key );
+               }
+       }
+
+       function getDateFormats() {
+               global $wgDateFormatsBn;
+               return $wgDateFormatsBn;
+       }
+
+       var $digitTransTable = array(
+               '0' => '০',
+               '1' => '১',
+               '2' => '২',
+               '3' => '৩',
+               '4' => '৪',
+               '5' => '৫',
+               '6' => '৬',
+               '7' => '৭',
+               '8' => '৮',
+               '9' => '৯'
+       );
+
+       function formatNum( $number ) {
+               global $wgTranslateNumerals;
+               if( $wgTranslateNumerals ) {
+                        return strtr( $number, $this->digitTransTable );
+               } else {
+                       return $number;
+               }
+       }
+}
+
+?>
diff --git a/languages/LanguageBo.php b/languages/LanguageBo.php
new file mode 100644 (file)
index 0000000..999c2a6
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+/** Tibetan (བོད་ཡིག)
+  *
+  * @package MediaWiki
+  * @subpackage Language
+  *
+  * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
+  */
+
+require_once( 'LanguageUtf8.php' );
+
+class LanguageBo extends LanguageUtf8 {
+       var $digitTransTable = array(
+               '0' => '༠',
+               '1' => '༡',
+               '2' => '༢',
+               '3' => '༣',
+               '4' => '༤',
+               '5' => '༥',
+               '6' => '༦',
+               '7' => '༧',
+               '8' => '༨',
+               '9' => '༩'
+       );
+
+       function formatNum( $number ) {
+               global $wgTranslateNumerals;
+               if( $wgTranslateNumerals ) {
+                       return strtr( $number, $this->digitTransTable );
+               } else {
+                       return $number;
+               }
+       }
+}
+
+?>
diff --git a/languages/LanguageCa.php b/languages/LanguageCa.php
new file mode 100644 (file)
index 0000000..c02628e
--- /dev/null
@@ -0,0 +1,867 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+# The names of the namespaces can be set here, but the numbers
+# are magical, so don't change or move them!  The Namespace class
+# encapsulates some of the magic-ness.
+#
+/* private */ $wgNamespaceNamesCa = array(
+       NS_MEDIA                        => 'Media',
+       NS_SPECIAL                      => 'Especial',
+       NS_MAIN                         => '',
+       NS_TALK                         => 'Discussió',
+       NS_USER                         => 'Usuari',
+       NS_USER_TALK            => 'Usuari_Discussió',
+       NS_PROJECT                      => $wgMetaNamespace,
+       NS_PROJECT_TALK         => $wgMetaNamespace.'_Discussió',
+       NS_IMAGE                        => 'Imatge',
+       NS_IMAGE_TALK           => 'Imatge_Discussió',
+       NS_MEDIAWIKI            => 'MediaWiki',
+       NS_MEDIAWIKI_TALK       => 'MediaWiki_Discussió',
+       NS_TEMPLATE                     => 'Template',
+       NS_TEMPLATE_TALK        => 'Template_Discussió',
+       NS_HELP                         => 'Ajuda',
+       NS_HELP_TALK            => 'Ajuda_Discussió',
+       NS_CATEGORY                     => 'Categoria',
+       NS_CATEGORY_TALK        => 'Categoria_Discussió'
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgQuickbarSettingsCa = array(
+       "Cap", "Fixa a la dreta", "Fixa a l'esquerra", "Surant a l'esquerra"
+);
+
+/* private */ $wgSkinNamesCa = array(
+       'standard' => "Estàndard",
+       'nostalgia' => "Nostàlgia",
+       'cologneblue' => "Colònia blava",
+) + $wgSkinNamesEn;
+
+/* private */ $wgDateFormatsCa = array(
+#      "No preference",
+);
+
+/* private */ $wgAllMessagesCa = array(
+# User Toggles
+
+"tog-underline" => "Subratlla enllaços",
+"tog-highlightbroken" => "Destaca enllaços a temes buits",
+"tog-justify"  => "Ajusta paràgrafs",
+"tog-hideminor" => "Amaga edicions menors en canvis recents",
+"tog-usenewrc" => "Canvis recents remarcats (no per tots els navegadors)",
+"tog-numberheadings" => "Autoenumera encapçalaments",
+"tog-showtoolbar" => "Show edit toolbar",
+"tog-rememberpassword" => "Recorda la contrasenya entre sessions",
+"tog-editwidth" => "La caixa d'edició té l'ample màxim",
+"tog-editondblclick" => "Edita pàgines amb un doble clic (JavaScript)",
+"tog-editsection"=>"Enable section editing via [edit] links",
+"tog-editsectiononrightclick"=>"Enable section editing by right clicking<br /> on section titles (JavaScript)",
+"tog-showtoc"=>"Show table of contents<br />(for articles with more than 3 headings)",
+"tog-watchdefault" => "Vigila articles nous i modificats",
+"tog-minordefault" => "Marca totes les edicions com menors per defecte",
+"tog-previewontop" => "Show preview before edit box and not after it",
+"tog-nocache" => "Disable page caching",
+#Dates
+
+'sunday' => 'Diumenge',
+'monday' => 'Dilluns',
+'tuesday' => 'Dimarts',
+'wednesday' => 'Dimecres',
+'thursday' => 'Dijous',
+'friday' => 'Divendres',
+'saturday' => 'Dissabte',
+'january' => 'gener',
+'february' => 'febrer',
+'march' => 'març',
+'april' => 'abril',
+'may_long' => 'maig',
+'june' => 'juny',
+'july' => 'juliol',
+'august' => 'agost',
+'september' => 'setembre',
+'october' => 'octubre',
+'november' => 'novembre',
+'december' => 'desembre',
+'jan' => 'gen',
+'feb' => 'feb',
+'mar' => 'mar',
+'apr' => 'abr',
+'may' => 'mai',
+'jun' => 'jun',
+'jul' => 'jul',
+'aug' => 'ago',
+'sep' => 'set',
+'oct' => 'oct',
+'nov' => 'nov',
+'dec' => 'des',
+
+
+# Bits of text used by many pages:
+#
+"linktrail"     => "/^((?:[a-z]|à|è|é|í|ò|ó|ú|ç|·|ï|ü|')+)(.*)\$/sD",
+"mainpage"             => "Portada",
+"about"                        => "Quant a...",
+"aboutsite"      => "Quant a la {{SITENAME}}",
+"aboutpage"            => "{{ns:4}}: Quant a",
+"help"                 => "Ajuda",
+"helppage"             => "{{ns:4}}:Ajuda",
+"bugreports"   => "Informes d'error del programari",
+"bugreportspage" => "{{ns:4}}:Informes_d'error",
+"faq"                  => "PMF",
+"faqpage"              => "{{NS:4}}:PMF",
+"edithelp"             => "Ajuda d'edició",
+"edithelppage" => "{{NS:4}}:Com_s'edita_una_pàgina",
+"cancel"               => "Anul·la",
+"qbfind"               => "Troba",
+"qbbrowse"             => "Fulleja",
+"qbedit"               => "Edita",
+"qbpageoptions" => "Opcions de pàgina",
+"qbpageinfo"   => "Informació de pàgina",
+"qbmyoptions"  => "Les meves opcions",
+"mypage"               => "La meva pàgina",
+"mytalk"        => "La meva discussió",
+"currentevents" => "Actualitat",
+"errorpagetitle" => "Error",
+"returnto"             => "Torna a $1.",
+"tagline"              => "De {{SITENAME}}",
+"whatlinkshere"        => "Pàgines que enllacen ací",
+"help"                 => "Ajuda",
+"search"               => "Cerca",
+"history"              => "Història",
+"printableversion" => "Versió per imprimir",
+"editthispage" => "Edita aquesta pàgina",
+"deletethispage" => "Esborra aquesta pàgina",
+"protectthispage" => "Protegeix aquesta pàgina",
+"unprotectthispage" => "Desprotegeix aquesta pàgina",
+"talkpage"             => "Discuteix aquesta pàgina",
+"articlepage"   => "Mostra article",
+"subjectpage"  => "Article",
+"userpage" => "Mostra pàgina d'usuari",
+"wikipediapage" => "Mostra meta pàgina",
+"imagepage" =>         "Mostra pàgina d'imatge",
+"otherlanguages" => "Altres idiomes",
+"redirectedfrom" => "(Redirigit des de $1)",
+"lastmodified" => "Aquesta pàgina ha estat modificada per última vegada el $1.",
+"viewcount"            => "Aquesta pàgina ha estat visitada $1 vegades.",
+"printsubtitle" => "(De {{SERVER}})",
+"protectedpage" => "Pàgina protegida",
+"administrators" => "{{ns:4}}:Administradors",
+"sysoptitle"   => "Accés requerit de Sysop",
+"sysoptext"            => "L'acció que heu requerit només pot ser duta a terme per usuaris amb estatus de \"sysop\".
+Ver $1.",
+"developertitle" => "Accés de desenvolupador requerit",
+"developertext"        => "L'acció que heu requerit només pot ser duta a terme per usuaris amb l'estatus de \"desenvolpador\".
+Vegeu $1.",
+"nbytes"               => "$1 octets",
+"go"                   => "Vés-hi",
+"ok"                   => "D'acord",
+"sitetitle"            => "{{SITENAME}}",
+"sitesubtitle" => "L'Enciclopèdia Lliure",
+"retrievedfrom" => "Obtingut de \"$1\"",
+
+# Main script and global functions
+#
+"nosuchaction" => "Aquesta acció no existeix",
+"nosuchactiontext" => "L'acció especificada per l'URL no és reconeguda pel programari de la {{SITENAME}}",
+"nosuchspecialpage" => "No existeix aquesta pàgina especial",
+"nospecialpagetext" => "Heu requerit una pàgina especial que no és reconeguda pel programari de la {{SITENAME}}.",
+
+# General errors
+#
+"error"                        => "Error",
+"databaseerror" => "Error de la base de dades",
+"dberrortext"  => "Ha ocorregut un error de sintaxi en una consulta a la base de dades.
+L'última consulta que s'ha intentat ha estat:
+<blockquote><tt>$1</tt></blockquote>L'error de retorn de MySQL ha estat\"<tt>$3: $4</tt>\".",
+"noconnect"            => "No s'ha pogut connectar a la base de dades a $1",
+"nodb"                 => "No s'ha pogut seleccionar la base de dades$1",
+"readonly"             => "Base de dades bloquejada",
+"enterlockreason" => "Entreu una raó per bloquejar-la, incloent una estimació de quan s'efecturarà el bloqueig",
+"readonlytext" => "La base de dades de la {{SITENAME}} està temporalment bloquejada per noves entrades o altres modificacions,
+
+probablement per manteniment de rutina, després del qual tornarà a la normalitat. L'administrador la bloquejada ha ofert aquesta explicació:
+<p>$1",
+"missingarticle" => "La base de dades no ha trobat el text d'una
+pàgina que hauria d'haver trobat, anomenada \"$1\".
+Això no és un error de la base de dades, sinó més probablement
+un error en el programari. Informeu-ne si us plau a un administrador,
+fent-ne arribar l'URL.",
+"internalerror" => "Error intern",
+"filecopyerror" => "No s'ha pogut copiar l'arxiu \"$1\" a \"$2\".",
+"filerenameerror" => "No s'ha pogut reanomenar l'arxiu \"$1\" a \"$2\".",
+"filedeleteerror" => "No s'ha pogut esborrar l'arxiu \"$1\".",
+"filenotfound" => "No s'ha pogut trobar l'arxiu \"$1\".",
+"unexpected"   => "Valor no esperat: \"$1\"=\"$2\".",
+"formerror"            => "Error: no s'ha pogut trametre la forma",
+"badarticleerror" => "Aquesta acció no es pot dur a terme en aquesta pagina.",
+"cannotdelete" => "No s`'ha pogut esborrar la pàgina o imatge especificada.(Pot haver estat esborrada per algú abans)",
+"badtitle"             => "Títol incorrecte",
+"badtitletext" => "El títol de la pàgina requerida era invàlid, buit, o un enllaç interidioma o interwiki incorrecte.",
+
+"perfdisabled" => "Aquesta funció està temporalment desactivada",
+
+# Login and logout pagesítulo
+"logouttitle"  => "Fin de sessió",
+"logouttext"   => "Heu acabat la vostra sessió.
+Podeu continuar emprant la {{SITENAME}} de forma anònima, o podeu
+iniciar sessió un altre cop amb el mateix o un altre nom d'usuari.\n",
+
+"welcomecreation" => "<h2>Benvingut, $1!</h2><p>El vostre compte ha estat creat.
+Recordeu personalitzar les vostres preferències del {{SITENAME}}.",
+
+"loginpagetitle" => "Registre/Entrada",
+"yourname"             => "Nom d'usuari",
+"yourpassword" => "Contrasenya",
+"yourpasswordagain" => "Repetiu la contrasenya",
+"newusersonly" => " (només usuaris nous)",
+"remembermypassword" => "Vull que recordis la meva contrasenya entre sessions.",
+"loginproblem" => "<b>Hi ha hagut un problema amb l'entrada.</b><br />Proveu-ho de nou!",
+"alreadyloggedin" => "<strong>Benvingut, usuari $1!</strong><br />\n",
+
+"login"                        => "Registre/Entrada",
+"userlogin"            => "Registre/Entrada",
+"logout"               => "Sortida",
+"userlogout"   => "Sortida",
+"createaccount"        => "Crea un nou compte",
+"badretype"            => "Les contrasenyes que heu ingressat no concorden.",
+"userexists"   => "El nom que heu entrat ja és en ús. Escolliu un nombre diferent.",
+"youremail"            => "Direcció electrònica",
+"yournick"             => "Malnom (nom que es mostrarà)",
+"emailforlost" => "Si perdeu o oblideu la vostra contrasenya, podeu demanar que se us enviï una nova a la vostra direcció electrònica.",
+"loginerror"   => "Error d'inici de sessió",
+"noname"               => "No heu especificat un nom vàlid d'usuari.",
+"loginsuccesstitle" => "S'ha iniciat la sessió amb èxit",
+"loginsuccess" => "Heu iniciat la sessió a {{SITENAME}} com a \"$1\".",
+"nosuchuser"   => "No hi ha cap usuari amb el nom \"$1\".
+Reviseu-ne l'ortografia, o empreu el formulari d'avall per crear un nou compte d'usuari.",
+"wrongpassword"        => "La contrasenya que heu ingressat és incorrecta. Torneu-ho a provar.",
+"mailmypassword" => "Envia'm una nova contrasenya per correu electrònic",
+"passwordremindertitle" => "Recordatori de contrasenya de la {{SITENAME}}",
+"passwordremindertext" => "Algú (amb l'IP $1)
+ha sol·licitat que li enviéssim una nova contrasenya per iniciar la sessió a la {{SITENAME}}.
+La contrasenya per l'usuari \"$2\" és ara \"$3\".
+Ara hauríeu d'iniciar la sessió i canviar la vostra contrasenya.",
+"noemail"              => "No hi ha cap direcció electrònica registrada per l'usuari \"$1\".",
+"passwordsent" => "S'ha enviat una nova contrasenya a la direcció electrònica registrada per \"$1\".
+Entreu-hi de nou després de rebre-la.cibas.",
+
+# Edit pages
+#
+"summary"              => "Resum",
+"minoredit"            => "Aquesta és una edició menor.",
+"watchthis"            => "Vigila aquest article.",
+"savearticle"  => "Desa la pàgina",
+"preview"              => "Previsualitza",
+"showpreview"  => "Mostra previsualizació",
+"blockedtitle" => "L'usuari està bloquejat",
+"blockedtext"  => "El vostre nombre d'usuari o direcció IP ha estat bloquejada per $1.
+La raó és la que segueix:<br />$2<p>Podeu contactar amb l'administrador per discutir el bloqueig.",
+"newarticle"   => "(Nou)",
+"newarticletext" => "Poseu el text per la pàgina nova ací.",
+"noarticletext" => "(En aquest moment, a aquesta pàgina, no hi ha text)",
+"updated"              => "(Actualitzat)",
+"note"                 => "<strong>Nota:</strong> ",
+"previewnote"  => "Recordeu que això només és una previsualització, i encara no s'ha gravat!",
+"previewconflict" => "Aquesta previsualització reflexa el text a l'ària
+d'edició superior tal i com apareixerà si escolliu gravar.",
+"editing"              => "S'està editant $1",
+"editconflict" => "Conflicte d'edició: $1",
+"explainconflict" => "Algú més ha canviat aquesta pàgina des que l'heu editada.
+L'ària de text superior conté el text de la pàgina com existeix actualment. Els vostres canvis es mostren a l'ària de text inferior.
+Haureu d'incorporar els vostres canvis en el text existent.
+<b>Sólo</b> el text a l'ària de text superior serà gravat quan premeu
+ \"Desa pàgina\".<br />",
+"yourtext"             => "El vostre text",
+"storedversion" => "Versió emmagatzemada",
+"editingold"   => "<strong>ATENCIÓ:Esteu editant una versió antiga d'aquesta pàgina.
+Si la graveu, els canvis fets des d'eixa revisió es perdran.</strong>",
+"yourdiff"             => "Diferències",
+"copyrightwarning" => "Noteu que totes les contribucions a la {{SITENAME}}
+es consideren fetes públiques sota la llicència de documentació lliure GNU
+(mostra detalls a $1).
+ Si no desitgeu que la gent corregeixi els vostres escrits sense pietat
+i els distribueixi lliurement, llavors no els poseu ací. <br />
+També ens heu d'assegurar que tot plegat és obra vostra i que sou l'amo dels drets d'autor, o els heu copiat des del domini públic
+o una altra font lliura.
+ <strong>NO EMPREU ESCRITS AMB COPYRIGHT SENSE PERMÍS!</strong>",
+
+# History pages
+#
+"revhistory"   => "Història de revisions",
+"nohistory"            => "No hi ha una història de revisions per a aquesta pàgina.",
+"revnotfound"  => "Revisió no trobada",
+"revnotfoundtext" => "No s'ha pogut trobar la revisió antiga de la pàgina.
+Revidseu l'URL que heu emprat per accedir-hi.\n",
+"loadhist"             => "Recuperant la història de la pàgina",
+"currentrev"   => "Revisió actual",
+"revisionasof" => "Revisió de $1",
+"cur"                  => "act",
+"next"                 => "seg",
+"last"                 => "prev",
+"orig"                 => "orig",
+"histlegend"   => "Simbologia: (act) = diferència amb la versió actual,
+(prev) = diferència amb la versió prèvia, M = edició menor",
+
+# Diffs
+#
+"difference"   => "(Diferència entre revisions)",
+"loadingrev"   => "recuperant revisió per a diff",
+"lineno"               => "Línia $1:",
+"editcurrent"  => "Edita la versió actual d'aquesta pàgina",
+
+# Search results
+#
+"searchresults" => "Resultats de la recerca",
+"searchresulttext" => "Per a més informació sobre les recerques de la {{SITENAME}}, aneu a [[Project:Recerca|S'està cercant a la {{SITENAME}}]].",
+"searchquery"  => "Per consulta \"$1\"",
+"badquery"             => "Consulta de recerca formulada de manera incorrecta",
+"badquerytext" => "No s'ha pogut processar la recerca.
+El motiu és probablement per què heu intentat cercar una paraula de menys de tres lletres, la qual cosa encara no és possible.
+També pot ser que hàgiu comès un error en lletrejar el terme.
+Torneu-ho a provar amb una altra recerca.",
+"matchtotals"  => "La consulta \"$1\" ha coincidit amb $2  títols d'articles
+i el text de $3 articles.",
+"titlematches" => "Coincidències de títol d'article",
+"notitlematches" => "No hi ha coincidències de títol d'article",
+"textmatches"  => "Coincidències de text d'article",
+"notextmatches"        => "No hi ha coincidències de text d'article",
+"prevn"                        => "$1 anteriors",
+"nextn"                        => "$1 següents",
+"viewprevnext" => "Vés a ($1) ($2) ($3).",
+"showingresults" => "S'està mostrant a sota <b>$1</b> resultats començant per #<b>$2</b>.",
+"nonefound"            => "<strong>Nota</strong>: les recerques sense èxit són causades tot sovint
+per recerques de paraules comunes com \"la\" o \"de\",
+que no es troben a l'índex, o per especificar més d'una paraula a cercar( només pàgines
+que contenen tots els termes d'una recerca apareixeran en el resultat).",
+"powersearch" => "Recerca",
+"powersearchtext" => "
+Cerca en espais de nom :<br />
+$1<br />
+$2 Llista redireccions   Cerca $3 $9",
+
+# Preferences page
+#
+"preferences"  => "Preferències",
+"prefsnologin" => "No heu entrat",
+"prefsnologintext"     => "Has haver [[Especial:Userlogin|entrat]]
+per seleccionar preferències d'usuari.",
+"prefslogintext" => "Heu entrat amb el nom \"$1\".
+El vostre número d'identificació intern és $2.",
+"prefsreset"   => "Les preferències han estat respostes des d'emmagatzematge.",
+"qbsettings"   => "Preferències de \"Quickbar\"",
+"changepassword" => "Canvia contrasenya",
+"skin"                 => "Aparença",
+"math"                 => "Com es mostren les fòrmules",
+"math_failure"         => "No s'ha pogut entendre",
+"math_unknown_error"   => "error desconegut",
+"math_unknown_function"        => "funció desconeguda",
+"math_lexing_error"    => "error de lèxic",
+"math_syntax_error"    => "error de sintaxi",
+"saveprefs"            => "Desa preferències",
+"resetprefs"   => "Torna a preferències per defecte",
+"oldpassword"  => "Contrasenya antiga",
+"newpassword"  => "Contrasenya nova",
+"retypenew"            => "Reescriviu la nova contrasenya",
+"textboxsize"  => "Dimensions de la caixa de text",
+"rows"                 => "Files",
+"columns"              => "Columnes",
+"searchresultshead" => "Preferències de resultat de recerca",
+"resultsperpage" => "Resultats a mostrar per pàgina",
+"contextlines" => "Línies a mostrar per resultat",
+"contextchars" => "Caràcters de context per línia",
+"stubthreshold" => "Llindar d'article mínim" ,
+"recentchangescount" => "Nombre de títols en canvis recents",
+"savedprefs"   => "Les vostres preferències han estat desades.",
+"timezonetext" => "Entreu el número d'hores de diferència entre la vostra hora local
+i l'hora del servidor (UTC).",
+"localtime"    => "Hora local",
+"timezoneoffset" => "Diferència",
+"emailflag"     => "No voleu rebre correu electrònic d'altres usuaris",
+
+# Recent changes
+#
+"recentchanges" => "Canvis recents",
+"recentchangestext" => "Seguiu els canvis més recentes de la {{SITENAME}} en aquesta pàgina.
+[[{{ns:4}}:Benvingut]]!
+Mireu aquestes pàgines, si us plau: [[{{ns:4}}:PMF|PMF de la {{SITENAME}}]],
+[[{{ns:4}}:Polítiques i guies|polítiques de la {{SITENAME}}]]
+(especialment [[{{ns:4}}:Convencions de noms|les convencions per anomenar articles]]i
+[[{{ns:4}}:Punt de vista neutral|punt de vista neutral]]).
+
+Si voleu que la {{SITENAME}} tingui èxit, és molt important que no hi afegiu
+material restringit per [[{{ns:4}}:Copyrights|drets d'autor]].
+La responsabilitat legal podria realment malmetre un projecte com aquest, així que si us plau, no ho feu.",
+"rcloaderr"            => "s'està carregant els canvis recents",
+"rcnote"               => "A sota hi ha els últims <b>$1</b> canvis en els últims <b>$2</b> dies.",
+"rclistfrom"   => "Mostra els canvis nous des de $1",
+"rcnotefrom"   => "A sota hi ha els canvis des de <b>$2</b> (es mostren fins <b>$1</b>).",
+"rclinks"              => "Mostra els últims $1 canvis en els últims $2 dies.",
+"rchide"               => "en forma $4 ; $1 edicions menors; $2 espais de nom secundaris; $3 ediciones múltiples.",
+"diff"                 => "diferències",
+"hist"                 => "història",
+"hide"                 => "amaga",
+"show"                 => "mostra",
+"tableform"     => "taula",
+"listform"             => "llistat",
+"nchanges"             => "$1 canvis",
+"minoreditletter" => "M",
+"newpageletter" => "N",
+
+# Upload
+#
+"upload"               => "Carrega",
+"uploadbtn"            => "Carrega un arxiu",
+
+"uploadlink"   => "Carrega imatges",
+"reupload"             => "Carrega de nou",
+"reuploaddesc" => "Torna al formulari per pujar.",
+"uploadnologin" => "No heu iniciat una sessió",
+"uploadnologintext"    => "Deveu haver [[Especial:Userlogin|entrat]]
+per carregar arxius.",
+"uploaderror"  => "S'ha produït un error en l'intent de carregar",
+"uploadtext"   => "Per veure o cercar imatges que s'hagin carregat
+previament, aneu al [[Especial:Imagelist|llistat d'imatges carregades]].
+Le càrregues i els esborrats són registrats en el
+[[Project:Registre de càrregues|registre de càrregues]].
+Aneu també a [[Project:Política d'ús d'imatges|política d'ús d'imatges]].
+
+Empreu la forma de sota per carregar nous arxius d'imatges per il·lustrar els articles.
+Amb la majoria dels navegadors, veureu un botó \"Browse...\", que
+farà aparèixer la selecció d'arxius estàndard en el vostre sistema operatiu.
+Quan escolliu un arxiu el nom d'aqueix arxiu apareixerà en el camp de text
+al costat del botó.
+També heu de marcar la caixa afirmant que no esteu
+violant cap copyright en carregar l'arxiu.
+Pitgeu el botó \"Carrega\" per completar la càrrega.
+això pot prendre algun temps si teniu una connexió lenta a internet.
+
+Els formats preferits són el JPEG per imatges fotogràfiques, el PNG
+per dibuixos i altres imatges icòniques, i OGG per sons.
+Seria convenient que donéssiu noms descriptius als arxius per evitar confusions.
+Per incloure la imatge en un article, empreu un enllaç de la forma
+'''<nowiki>[[imatge:arxiu.jpg]]</nowiki> o
+'''<nowiki>[[imatge:arxiu.png|alt text]]</nowiki> o
+'''<nowiki>[[media:arxiu.ogg]]</nowiki>''' per sons.
+
+Noteu que de la mateixa manera com passa amb les pàgines de la {{SITENAME}}, altri pot
+editar o esborrar els arxius que heu carregat si pensen que és bo per a
+l'enciclopèdia, i se us pot bloquejar, impedint-vos carregar arxius si abuseu del sistema.",
+"uploadlog"            => "registre de càrregues",
+"uploadlogpage" => "Registre_de_càrregues",
+"uploadlogpagetext" => "A sota hi ha un llistat dels arxius que s'han
+carregat més recentement. Totes les hores són les del servidor (UTC).
+<ul>
+</ul>
+",
+"filename"             => "Nom de l'arxiu",
+"filedesc"             => "Sumari",
+"copyrightpage" => "{{ns:4}}:Copyrights",
+"copyrightpagename" => "{{ns:4}} copyright",
+"uploadedfiles"        => "Arxius carregats",
+"ignorewarning"        => "Ignora l'advertència i desa l'arxiu de totes maneres.",
+"minlength"            => "Els noms de les imatges han de tenir un mínim de tres lletres.",
+"badfilename"  => "El nom de la imatge s'ha canviat a \"$1\".",
+"badfiletype"  => "\".$1\" no és un format recomanat d'imatge.",
+"largefile"            => "Es recomana que les imatges no superin la mida de 100k.",
+"successfulupload" => "L'arxiu s'ha carregat amb èxit",
+"fileuploaded" => "L'arxiu \"$1\" s'ha carregat amb èxit.
+Seguiu aquest enllaç si us plau: ($2) a la pàgina de descripció i empleneu
+la informació necesàir sobre l'arxiu, tal com la procedència, la data de creació
+i l'autor, i qualsevol altra cosa que pugueu saber al respecte.",
+"uploadwarning" => "Advertència de càrrega d'arxiu",
+"savefile"             => "Desa arxiu",
+"uploadedimage" => "\"[[$1]]\" carregat.",
+
+# Image list
+#
+"imagelist"            => "Llistat d'imatges",
+"imagelisttext"        => "A sota hi ha un llistat de $1 imatges ordenades $2.",
+"getimagelist" => " obtenint el llistat d'imatges",
+"ilsubmit"             => "Recerca",
+"showlast"             => "Mostra les últimes $1 imatges ordenades  $2.",
+"byname"               => "per nom",
+"bydate"               => "per data",
+"bysize"               => "per mida",
+"imgdelete"            => "edi",
+"imgdesc"              => "desc",
+"imglegend"            => "Simbologia: (edi) = mostra/edita la descripció de la imatge.",
+"imghistory"   => "Història de la imatge",
+"revertimg"            => "rev",
+"deleteimg"            => "borr",
+"deleteimgcompletely"          => "borr",
+"imghistlegend" => "Simbologia: (act) = aquesta és la imatge actual, (esb) = esborra
+aquesta versió antiga, (rev) = reverteix a aquesta versió antiga.
+<br /><i>Cliqueu a la data per veure la imatge carregada en aquesta data</i>.",
+"imagelinks"   => "Enllaços a la imatge",
+"linkstoimage" => "Les següents pàgines enllacen a aquesta imatge:",
+"nolinkstoimage" => "No hi ha pàgines que enllacen aquesta imatge.",
+
+# Statistics
+#
+"statistics"   => "Estadístiques",
+"sitestats"            => "Estadístiques del lloc",
+"userstats"            => "Estadístiques d'usuari",
+"sitestatstext" => "Hi ha un total de <b>$1</b> pàgines en la base de dades.
+Això inclou pàgines de discussió, pàgines sobre la {{SITENAME}}, pàgines mínimes,
+redireccions, i altres que probablement no es poden classificar com a articles.
+Excloent-les, hi ha <b>$2</b> pàgines que probablement són articles legítims.<p>
+Hi ha hagut un total de <b>$3</b> visites a pàgines, i <b>$4</b> edicions de pàgina
+des que el programari ha estat actualitzat (Febrer 2003).
+Això resulta en un promig de <b>$5</b> edicions per pàgina,
+i <b>$6</b> visites per edició.",
+"userstatstext" => "Hi ha <b>$1</b> usuaris registrats.
+dels quals <b>$2</b> són administradors (vegeu $3).",
+
+# Maintenance Page
+#
+"maintenance"          => "Pàgina de manteniment",
+"maintnancepagetext"   => "Aquesta pàgina inclou diverses eines útils per al manteniment diari. Algunes d'aquestes funcions tendeixen a
+
+sobrecarregar la base de dades, així que si us plau, no torneu a carregar la pàgina després de cada element que arregleu ;-)",
+"maintenancebacklink"  => "Torna a la pàgina de manteniment",
+"disambiguations"      => "Pàgines de desambiguació",
+"disambiguationspage"  => "{{ns:4}}:Enllaços a pàgines de desambiguació",
+"disambiguationstext"  => "Els següents articles enllacen a una<i>pàgina de desambiguació</i>. Haurien d'enllaçar al tema apropiat.
+
+<br />Una pàgina és considerada una pàgina de desambiguació si és enllaçada des de $1.<br />Enllaços des d'altres espais de nom (Com Viquipè
+
+dia: o usuari:) <i>no</i> són  llistats ací.",
+"doubleredirects"      => "Redireccions Dobles",
+"doubleredirectstext"  => "<b>Atenció:</b> aquest llistat pot contenir falsos positius. Això normalment significa que hi ha text
+
+addicional amb enllaços sota el primer #REDIRECT.<br />\nCada fila conté enllaços al segon i tercer redireccionament, així com la primera línia del
+
+segon redireccionament, la qual cosa dóna normalment l'article \"real\", al que el primer redireccionamet hauria d'apuntar.",
+"selflinks"            => "Pàgines amb autoenllaços",
+"selflinkstext"                => "Les següents pàgines contenen un enllaç a si mateixes, la qual cosa no és recomanable.",
+"mispeelings"       => "Pàgines amb faltes d'ortografia",
+"mispeelingstext"               => "Les següents pàgines contenen una falta d'ortografia comuna, les quals s'han llistat a $1. L'escriptura correcta
+
+pot ser donada (com això).",
+"mispeelingspage"       => "Llistat de faltes d'ortografia comunes",
+"missinglanguagelinks"  => "Enllaços Interidioma Faltants",
+"missinglanguagelinksbutton"    => "Troba els enllaços interidioma que falten per",
+"missinglanguagelinkstext"      => "Aquests articles <i>no</i> enllacen a les seves contraparts a $1. <i>No</i> es mostren redireccions i
+
+subpàgines.",
+
+
+# Miscellaneous special pages
+#
+"orphans"              => "Pàgines orfes",
+"lonelypages"  => "Pàgines orfes",
+"unusedimages" => "Imatges sens ús",
+"popularpages" => "Pàgines populars",
+"nviews"               => "$1 visites",
+"wantedpages"  => "Pàgines requerides",
+"nlinks"               => "$1 enllaços",
+"allpages"             => "Totes les pàgines",
+"randompage"   => "Pàgina aleatòria",
+"shortpages"   => "Pàgines curtes",
+"longpages"            => "Pàgines llargues",
+"listusers"            => "Llistat d'usuaris",
+"specialpages" => "Pàgines especials",
+"spheading"            => "Pàgines especials",
+"protectpage"  => "Pàgines protegides",
+"recentchangeslinked" => "Seguiment d'enllaços",
+"rclsub"               => "(a pàgines enllaçades des de \"$1\")",
+"debug"                        => "Debug",
+"newpages"             => "Pàgines noves",
+"movethispage" => "Trasllada aquesta pàgina",
+"unusedimagestext" => "<p>Noteu que altres llocs web
+com ara altres Viquipèdies poden enllaçar a una imatge
+amb un URL directe, i d'aquixa manera estar encara llistada ací
+tot i estar en ús actiu.",
+"booksources"   => "Fonts de llibres",
+"booksourcetext" => "A continuació hi ha un llistat d'enllaços a altres llocs que venen llibres nous i de segona mà, i també poden contenir
+
+informació addicional sobre els llibres que esteu cercant.
+La {{SITENAME}} no està afiliada amb cap d'aquests negocis, i aquest llistat no ha de ser considerat com propaganda.",
+
+# Email this user
+#
+"mailnologin"  => "No enviïs la direcció",
+"mailnologintext" => "Heu d'haver [[Especial:Userlogin|entrat]]
+i tenir una direcció electrònica vàlida en les vostres [[Especial:Preferences|preferències]]
+per enviar un correu electrònic a altres usuaris.",
+"emailuser"            => "Envia correu electrònic a aquest usuari",
+"emailpage"            => "Correu electrònic a usuari",
+"emailpagetext"        => "Si aquest usuari ha entrat una direcció electrònica vàlida en les vostres preferències d'usuari, el següent formulari
+
+serveix per enviar-li un missatge.
+La direcció electrònica que heu entrat en les vostres preferències d'usuari apareixerà en el remitent, de manera que el destinatari pugui
+
+respondre.",
+"noemailtitle" => "No hi ha cap direcció electrònica",
+"noemailtext"  => "Aquest usuari no ha especificat una direcció electrònica vàlida, o ha escollit no rebre correu electrònic d'altres usuaris
+
+.",
+"emailfrom"            => "De",
+"emailto"              => "Per",
+"emailsubject" => "Assumpte",
+"emailmessage" => "Missatge",
+"emailsend"            => "Envia",
+"emailsent"            => "Correu electrònic enviat",
+"emailsenttext" => "El vostre correu electrònic ha estat enviat.",
+
+# Watchlist
+#
+"watchlist"            => "Llistat de seguiment",
+"watchlistsub" => "(per a l'usuari \"$1\")",
+"nowatchlist"  => "No teniu cap element en el vostre llistat de seguiment.",
+"watchnologin" => "No heu iniciat sessió",
+"watchnologintext"     => "Heu d'[[Especial:Userlogin|entrar]]
+per modificar el vostre llistat de seguiment.",
+"addedwatch"   => "Afegit al llistat de seguiment",
+"addedwatchtext" => "La pàgina \"$1\" ha estat afegida al vostre  <a href=\"" .
+  "{{localurle:Especial:Watchlist}}\">llistat de seguiment</a>.
+Canvis futurs a aquesta pàgina i a la vostra pàgina de discussió associada hi serà llistat, i la pàgina apareixerà <b>en negreta</b> al <a href=
+
+\"" .
+  "{{localurle:Especial:Recentchanges}}\">llistat de canvis recents</a> per fer-la notar més fàcilment.</p>
+
+<p>Quan volgueu extreure la pàgina del vostre llistat de seguiment, pitgeu \"Deixa de vigilar\" a la barra del costat.",
+"removedwatch" => "S'ha extret del llistat de seguiment",
+"removedwatchtext" => "La pàgina \"$1\" ha estat extreta del vostre llistat de seguiment.",
+"watchthispage"        => "Vigila aquesta pàgina",
+"unwatchthispage" => "Deixa de vigilar",
+"notanarticle" => "No és un article",
+
+# Delete/protect/revert
+#
+"deletepage"   => "Esborra aquesta pàgina",
+"confirm"              => "Confirma",
+"confirmdelete" => "Confirma l'esborrat",
+"deletesub"            => "(Esborrant \"$1\")",
+"confirmdeletetext" => "Esteu a punt d'esborrar una pàgina o imatge
+de forma permanent, així com tota la seva història de la base de dades.
+Confirmeu que realment ho voleu fer, que enteneu les
+conseqüències, i que el esteu fent està d'acord amb [[{{ns:4}}:Polítiques]].",
+"actioncomplete" => "Acció completa",
+"deletedtext"  => "\"$1\" ha estat esborrat.
+Mostra $2 per a un registre dels esborrats més recents.",
+"deletedarticle" => "esborrat \"$1\"",
+"dellogpage"   => "Registre_d'esborrats",
+"dellogpagetext" => "A sota hi ha un llistat dels esborrats més recents.
+Tots els temps es mostren en l'hora del servidor (UTC).
+<ul>
+</ul>
+",
+"deletionlog"  => "Registre d'esborrats",
+"reverted"             => "Invertit amb una revisió anterior",
+"deletecomment"        => "Raó per ser esborrat",
+"imagereverted" => "S'ha revertit amb èxit a una versió anterior.",
+"rollback"             => "Reverteix edicions",
+"rollbacklink" => "Reverteix",
+"cantrollback" => "No s'ha pogut revertir les edicions; l'últim col·laborador és l'únic autor d'aquest article.",
+"revertpage"   => "Revertida a l'última edició por $1",
+
+# Undelete
+"undelete" => "Restaura una pàgina esborrada",
+"undeletepage" => "Mostra i restaura pàgines esborrades",
+"undeletepagetext" => "Les següents pàgines han estat esborrades però encara són a l'arxiu i poden ser restaurades. L'arxiu pot ser netejat
+
+periòdicament.",
+"undeletearticle" => "Restaura l'article esborrat",
+"undeleterevisions" => "$1 revisions arxivades",
+"undeletehistory" => "Si restaureu una pàgina, totes les revisions seran restaurades a la història.
+Si una nova pàgina amb el mateix nom ha estat creada des de l'esborrat, les versions restaurades apareixeran com a història anterior, i la
+
+revisió actual del la pàgina \"viva\" no serà substituïda automàticament.",
+"undeleterevision" => "Revisió esborrada al $1",
+"undeletebtn" => "Restaura!",
+"undeletedarticle" => "restaurat \"$1\"",
+"undeletedtext"   => "L'article [[$1]] ha estat restaurat amb èxit.
+Vegeu [[{{ns:4}}:Registre_d'esborrats]] per un llistat d'esborrats i restauracions recents.",
+
+# Contributions
+#
+"contributions"        => "Contribucions de l'usuari",
+"contribsub"   => "Per $1",
+"nocontribs"   => "No s'ha trobat canvis que encaixessin amb aquests criteris.",
+"ucnote"               => "A sota hi ha els últims <b>$1</b> canvis d'aquest usuari en els últims <b>$2</b> dies.",
+"uclinks"              => "Mostra els últims $1 canvis; mostra els últims $2 dies.",
+"uctop"                => " (amunt)" ,
+
+# What links here
+#
+"whatlinkshere"        => "El que enllaça ací",
+"notargettitle" => "No hi ha pàgina en blanc",
+"notargettext" => "No heu especificat a quina pàgina dur a terme aquesta funció.",
+"linklistsub"  => "(Llistat d'enllaços)",
+"linkshere"            => "Les següents pàgines enllacen ací:",
+"nolinkshere"  => "Ací no enllaça cap pàgina.",
+"isredirect"   => "pàgina redirigida",
+
+# Block/unblock IP
+#
+"blockip"              => "Bloqueig de direccions IP",
+"blockiptext"  => "Empreu el següent formulari per bloquejar l'accés
+d'escriptura des d'una direcció IP específica.
+això hauria de fer-se només per prevenir el vandalisme, i
+d'acord a la [[{{ns:4}}:Política| política de la {{SITENAME}}]].
+Empleneu el diàleg d'avall amb una raó específica (per exemple, citant
+quines pàgines en concret estan sent vandalitzades).",
+"ipaddress"            => "Direcció IP",
+"ipbreason"            => "Raó",
+"ipbsubmit"            => "Bloqueja aquesta direcció",
+"badipaddress" => "La direcció IP no té el format correcte.",
+"blockipsuccesssub" => "S'ha bloquejat amb èxit",
+"blockipsuccesstext" => "La direcció IP  \"$1\" ha estat bloquejada.
+<br />Vegeu [[Especial:llistat d'IP bloquejades|llistat d'IPs bloquejades]] per revisar bloquejos.",
+"unblockip"            => "Desbloqueja direcció IP",
+"unblockiptext"        => "Empreu el següent formulari per restaurar
+l'accés a l'escriptura a una direcció IP prèviament bloquejada.",
+"ipusubmit"            => "Desbloqueja aquesta direcció",
+"ipusuccess"   => "Direcció IP \"$1\" desbloquejada",
+"ipblocklist"  => "Llistat de direccions IP bloquejades",
+"blocklistline"        => "$1, $2 bloqueja $3 ($4)",
+"blocklink"            => "bloqueja",
+"unblocklink"  => "desbloqueja",
+"contribslink" => "contribucions",
+
+# Developer tools
+#
+"lockdb"               => "Bloqueja la base de dades",
+"unlockdb"             => "Desbloqueja la base de dades",
+"lockdbtext"   => "Bloquejant la base de dades s'anul·larà la capacitat de tots els
+usuaris d'editar pàgines, canviar les preferències, editar els llistats de seguiments, i
+altres canvis que requereixen canvis en la base de dades.
+Confirmeu que això és el que intenteu fer, i sobretot no us oblideu
+de desbloquejar la base de dades quan acabeu el manteniment.",
+"unlockdbtext" => "Desbloquejant la base de dades es restaurarà l'habilitat de tots
+els usuaris d'editar pàgines, canviar les preferències, editar els llistats de seguiment, i
+altres accions que requereixen canvis en la base de dades.
+Confirmeu que això és el que voleu fer.",
+"lockconfirm"  => "Sí, realment vull bloquejar la base de dades.",
+"unlockconfirm"        => "Sí, realment vull desbloquejar la base dades.",
+"lockbtn"              => "Bloqueja la base de dades",
+"unlockbtn"            => "Desbloqueja la base de dades",
+"locknoconfirm" => "No heu respost al diàleg de confirmació.",
+"lockdbsuccesssub" => "S'ha assolit el bloqueig de la base de dades",
+"unlockdbsuccesssub" => "S'ha extret el bloqueig de la base de dades",
+"lockdbsuccesstext" => "S'ha bloquejat la base de dades de la {{SITENAME}}.
+<br />Recordeu-vos-en d'extreure el bloqueig havent acabant el manteniment.",
+"unlockdbsuccesstext" => "La base de dades de la {{SITENAME}} ha estat desbloquejada.",
+
+# Move page
+#
+"movepage"             => "Reanomena pàgina",
+"movepagetext" => "Emprant el següent formulari reanomenareu una pàgina,
+movent tota la seva història al nou nom.
+El títol anterior es convertirà en un redireccionament al nou títol.
+Els enllaços a l'antic títol de la pàgina no es canviaran. Assegureu-vos-en de verificar que no deixeu redireccions
+
+dobles o trencades.
+Sou el responsable de fer que els enllaços segueixin apuntant on se suposa que ho facin.
+
+Noteu que la pàgina '''no''' serà traslladada si ja existeix una pàgina amb el títol nou, a no ser que sigui una pàgina buida o un
+
+''redireccionament'' sense història.
+Això significa que podeu reanomenar de nou una pàgina al seu títol original si cometeu un error, i que no podeu sobreescriure una pàgina
+
+existent.
+
+<b>ADVERTÈNCIA!</b>
+Això pot ser un canvi dràstic i inesperat per una pàgina popular;
+assegureu-vos-en d'entendre les conseqüències que comporta
+abans de seguir endavant.",
+"movepagetalktext" => "La pàgina de discussió associada, si existeix, serà traslladada automàticament '''a menys que:'''
+*Esteu movent la pàgina entre espais de nom diferents,
+*Una pàgina de discussió no buida ja existeix amb el nom nou, o
+*Heu deseleccionat la caixa de sota.
+
+En aquests casos, haureu de traslladar o barrejar la pàgina manualment si ho desitgeu.",
+"movearticle"  => "Reanomena pàgina",
+"movenologin"  => "No sou a dins d'una sessió",
+"movenologintext" => "Heu de ser un usuari registrat i estar[[Especial:Userlogin|dintre d'una sessió]]
+per reanomenar una pàgina.",
+"newtitle"             => "A títol nou",
+"movepagebtn"  => "Reanomena pàgina",
+"pagemovedsub" => "Reanomenament amb èxit",
+"pagemovedtext" => "Pàgina \"[[$1]]\" reanomenada a \"[[$2]]\".",
+"articleexists" => "Ja existeix una pàgina amb aquest nom, o el nom que heu
+escollit no és vàlid.
+Escolliu un altre nom, si us plau.",
+"talkexists"   => "S'ha reanomenat la pàgina amb èxit, però la pàgina de discussió no s'ha pogut moure car ja no existeix en el títol nou.
+
+Incorporeu-les manualment, si us plau.",
+"movedto"              => "reanomenat a",
+"movetalk"     => "Reanomena també la pàgina de discussió si és aplicable.",
+"talkpagemoved" =>  "També ha estat reanomenada la pàgina de discussió corresponent.",
+"talkpagenotmoved" => "La pàgina de discussió corresponent <strong>no</strong> ha estat reanomenada.",
+#Math
+'mw_math_png' => "Produeix sempre PNG",
+'mw_math_simple' =>"HTML si és molt simple, si no PNG",
+'mw_math_html' => "HTML si és possible, si no PNG",
+'mw_math_source' => "Deixa com a TeX (per a navegadors de text)",
+
+);
+
+/** This is an UTF8 language */
+require_once( 'LanguageUtf8.php' );
+
+/** @package MediaWiki */
+class LanguageCa extends LanguageUtf8 {
+
+       function getNamespaces() {
+               global $wgNamespaceNamesCa;
+               return $wgNamespaceNamesCa;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsCa;
+               return $wgQuickbarSettingsCa;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesCa;
+               return $wgSkinNamesCa;
+       }
+
+
+       function shortdate( $ts, $adj = false ) {
+               if ( $adj ) { $ts = $this->userAdjust( $ts ); }
+
+               $d = (0 + substr( $ts, 6, 2 )) . " " .$this->getMonthAbbreviation( substr( $ts, 4, 2 ) ) . ", " .
+                 substr( $ts, 0, 4 );
+               return $d;
+       }
+
+       function date( $ts, $adj = false ) {
+               if ( $adj ) { $ts = $this->userAdjust( $ts ); }
+
+               $d = (0 + substr( $ts, 6, 2 )) . " de " .$this->getMonthName( substr( $ts, 4, 2 ) ) . ", " .
+                 substr( $ts, 0, 4 );
+               return $d;
+       }
+
+       function time( $ts, $adj = false ) {
+               if ( $adj ) { $ts = $this->userAdjust( $ts ); }
+
+               $t = substr( $ts, 8, 2 ) . ":" . substr( $ts, 10, 2 );
+               return $t;
+       }
+
+       function timeanddate( $ts, $adj = false ) {
+               return $this->time( $ts, $adj ) . " " . $this->shortdate( $ts, $adj );
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesCa;
+               if( isset( $wgAllMessagesCa[$key] ) ) {
+                       return $wgAllMessagesCa[$key];
+               } else {
+                       return parent::getMessage( $key );
+               }
+       }
+
+       function formatNum( $number, $year = false ) {
+               return $year ? $number : strtr($this->commafy($number), '.,', ',.' );
+       }
+
+}
+
+?>
diff --git a/languages/LanguageConverter.php b/languages/LanguageConverter.php
new file mode 100644 (file)
index 0000000..270b009
--- /dev/null
@@ -0,0 +1,641 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  *
+  * @author Zhengzhu Feng <zhengzhu@gmail.com>
+  * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
+  */
+
+class LanguageConverter {
+       var $mPreferredVariant='';
+       var $mMainLanguageCode;
+       var $mVariants, $mVariantFallbacks;
+       var $mTablesLoaded = false;
+       var $mTables;
+       var $mTitleDisplay='';
+       var $mDoTitleConvert=true, $mDoContentConvert=true;
+       var $mCacheKey;
+       var $mLangObj;
+       var $mMarkup;
+       var $mFlags;
+       var $mUcfirst = false;
+       /**
+     * Constructor
+        *
+     * @param string $maincode the main language code of this language
+     * @param array $variants the supported variants of this language
+     * @param array $variantfallback the fallback language of each variant
+     * @param array $markup array defining the markup used for manual conversion
+        * @param array $flags array defining the custom strings that maps to the flags
+     * @access public
+     */
+       function LanguageConverter($langobj, $maincode,
+                                                               $variants=array(),
+                                                               $variantfallbacks=array(),
+                                                               $markup=array(),
+                                                               $flags = array()) {
+               global $wgDBname;
+               $this->mLangObj = $langobj;
+               $this->mMainLanguageCode = $maincode;
+               $this->mVariants = $variants;
+               $this->mVariantFallbacks = $variantfallbacks;
+               $this->mCacheKey = $wgDBname . ":conversiontables";
+               $m = array('begin'=>'-{', 'flagsep'=>'|', 'codesep'=>':',
+                                  'varsep'=>';', 'end'=>'}-');
+               $this->mMarkup = array_merge($m, $markup);
+               $f = array('A'=>'A', 'T'=>'T');
+               $this->mFlags = array_merge($f, $flags);
+       }
+
+       /**
+     * @access public
+     */
+       function getVariants() {
+               return $this->mVariants;
+       }
+
+       /**
+        * in case some variant is not defined in the markup, we need
+        * to have some fallback. for example, in zh, normally people
+        * will define zh-cn and zh-tw, but less so for zh-sg or zh-hk.
+        * when zh-sg is preferred but not defined, we will pick zh-cn
+        * in this case. right now this is only used by zh.
+        *
+        * @param string $v the language code of the variant
+        * @return string the code of the fallback language or false if there is no fallback
+     * @access private
+       */
+       function getVariantFallback($v) {
+               return $this->mVariantFallbacks[$v];
+       }
+
+
+       /**
+     * get preferred language variants.
+     * @return string the preferred language code
+     * @access public
+       */
+       function getPreferredVariant() {
+               global $wgUser, $wgRequest;
+
+               if($this->mPreferredVariant)
+                       return $this->mPreferredVariant;
+
+               // see if the preference is set in the request
+               $req = $wgRequest->getText( 'variant' );
+               if( in_array( $req, $this->mVariants ) ) {
+                       $this->mPreferredVariant = $req;
+                       return $req;
+               }
+
+               // get language variant preference from logged in users
+               if(is_object($wgUser) && $wgUser->isLoggedIn() )  {
+                       $this->mPreferredVariant = $wgUser->getOption('variant');
+                       return $this->mPreferredVariant;
+               }
+
+               # FIXME rewrite code for parsing http header. The current code
+               # is written specific for detecting zh- variants
+               if( !$this->mPreferredVariant ) {
+                       // see if some supported language variant is set in the
+                       // http header, but we don't set the mPreferredVariant
+                       // variable in case this is called before the user's
+                       // preference is loaded
+                       $pv=$this->mMainLanguageCode;
+                       if(array_key_exists('HTTP_ACCEPT_LANGUAGE', $_SERVER)) {
+                               $header = str_replace( '_', '-', strtolower($_SERVER["HTTP_ACCEPT_LANGUAGE"]));
+                               $zh = strstr($header, 'zh-');
+                               if($zh) {
+                                       $pv = substr($zh,0,5);
+                               }
+                       }
+                       return $pv;
+               }
+       }
+
+       /**
+     * dictionary-based conversion
+     *
+     * @param string $text the text to be converted
+     * @param string $toVariant the target language code
+     * @return string the converted text
+     * @access private
+     */
+       function autoConvert($text, $toVariant=false) {
+               $fname="LanguageConverter::autoConvert";
+
+               wfProfileIn( $fname );
+
+               if(!$this->mTablesLoaded)
+                       $this->loadTables();
+
+               if(!$toVariant)
+                       $toVariant = $this->getPreferredVariant();
+               if(!in_array($toVariant, $this->mVariants))
+                       return $text;
+
+               /* we convert everything except:
+                  1. html markups (anything between < and >)
+                  2. html entities
+                  3. place holders created by the parser
+               */
+               global $wgParser;
+               if (isset($wgParser))
+                       $marker = '|' . $wgParser->UniqPrefix() . '[\-a-zA-Z0-9]+';
+               else
+                       $marker = "";
+               $reg = '/<[^>]+>|&[a-z#][a-z0-9]+;' . $marker . '/';
+               $matches = preg_split($reg, $text, -1, PREG_SPLIT_OFFSET_CAPTURE);
+
+
+               $m = array_shift($matches);
+               $ret = strtr($m[0], $this->mTables[$toVariant]);
+               $mstart = $m[1]+strlen($m[0]);
+               foreach($matches as $m) {
+                       $ret .= substr($text, $mstart, $m[1]-$mstart);
+                       $ret .= strtr($m[0], $this->mTables[$toVariant]);
+                       $mstart = $m[1] + strlen($m[0]);
+               }
+               wfProfileOut( $fname );
+               return $ret;
+       }
+
+       /**
+     * convert text to all supported variants
+     *
+     * @param string $text the text to be converted
+     * @return array of string
+     * @access private
+     */
+       function autoConvertToAllVariants($text) {
+               $fname="LanguageConverter::autoConvertToAllVariants";
+               wfProfileIn( $fname );
+               if( !$this->mTablesLoaded )
+                       $this->loadTables();
+
+               $ret = array();
+               foreach($this->mVariants as $variant) {
+                       $ret[$variant] = strtr($text, $this->mTables[$variant]);
+               }
+               wfProfileOut( $fname );
+               return $ret;
+       }
+
+       /**
+        * convert text to different variants of a language. the automatic
+        * conversion is done in autoConvert(). here we parse the text
+        * marked with -{}-, which specifies special conversions of the
+        * text that can not be accomplished in autoConvert()
+        *
+        * syntax of the markup:
+        * -{code1:text1;code2:text2;...}-  or
+        * -{text}- in which case no conversion should take place for text
+     *
+     * @param string $text text to be converted
+     * @param bool $isTitle whether this conversion is for the article title
+     * @return string converted text
+     * @access public
+     */
+       function convert( $text , $isTitle=false) {
+               global $wgDisableLangConversion;
+               global $wgTitle;
+
+               /* don't do anything if this is the conversion table */
+               if($wgTitle->getNamespace() == NS_MEDIAWIKI &&
+                  strpos($wgTitle->getText(), "Conversiontable")!==false)
+                       return $text;
+
+               if($wgDisableLangConversion)
+                       return $text;
+
+               $mw =& MagicWord::get( MAG_NOTITLECONVERT );
+               if( $mw->matchAndRemove( $text ) )
+                       $this->mDoTitleConvert = false;
+
+               $mw =& MagicWord::get( MAG_NOCONTENTCONVERT );
+               if( $mw->matchAndRemove( $text ) ) {
+                       $this->mDoContentConvert = false;
+               }
+
+               // no conversion if redirecting
+               $mw =& MagicWord::get( MAG_REDIRECT );
+               if( $mw->matchStart( $text ))
+                       return $text;
+
+               if( $isTitle ) {
+                       if( !$this->mDoTitleConvert ) {
+                               $this->mTitleDisplay = $text;
+                               return $text;
+                       }
+                       if( !empty($this->mTitleDisplay))
+                               return $this->mTitleDisplay;
+
+                       global $wgRequest;
+                       $isredir = $wgRequest->getText( 'redirect', 'yes' );
+                       $action = $wgRequest->getText( 'action' );
+                       if ( $isredir == 'no' || $action == 'edit' ) {
+                               return $text;
+                       }
+                       else {
+                               $this->mTitleDisplay = $this->autoConvert($text);
+                               return $this->mTitleDisplay;
+                       }
+               }
+
+               if( !$this->mDoContentConvert )
+                       return $text;
+
+               $plang = $this->getPreferredVariant();
+               $fallback = $this->mVariantFallbacks[$plang];
+
+               $tarray = explode($this->mMarkup['begin'], $text);
+               $tfirst = array_shift($tarray);
+               $text = $this->autoConvert($tfirst);
+               foreach($tarray as $txt) {
+                       $marked = explode($this->mMarkup['end'], $txt);
+                       $flags = array();
+                       $tt = explode($this->mMarkup['flagsep'], $marked[0], 2);
+
+                       if(sizeof($tt) == 2) {
+                               $f = explode($this->mMarkup['varsep'], $tt[0]);
+                               foreach($f as $ff) {
+                                       $ff = trim($ff);
+                                       if(array_key_exists($ff, $this->mFlags) &&
+                                               !array_key_exists($this->mFlags[$ff], $flags))
+                                               $flags[] = $this->mFlags[$ff];
+                               }
+                               $rules = $tt[1];
+                       }
+                       else
+                               $rules = $marked[0];
+
+#FIXME: may cause trouble here...
+                       //strip &nbsp; since it interferes with the parsing, plus,
+                       //all spaces should be stripped in this tag anyway.
+                       $rules = str_replace('&nbsp;', '', $rules);
+
+                       $carray = $this->parseManualRule($rules, $flags);
+                       $disp = '';
+                       if(array_key_exists($plang, $carray))
+                               $disp = $carray[$plang];
+                       else if(array_key_exists($fallback, $carray))
+                               $disp = $carray[$fallback];
+                       if($disp) {
+                               if(in_array('T',  $flags))
+                                       $this->mTitleDisplay = $disp;
+                               else
+                                       $text .= $disp;
+
+                               if(in_array('A', $flags)) {
+                                       /* modify the conversion table for this session*/
+
+                                       /* fill in the missing variants, if any,
+                                           with fallbacks */
+                                       foreach($this->mVariants as $v) {
+                                               if(!array_key_exists($v, $carray)) {
+                                                       $vf = $this->getVariantFallback($v);
+                                                       if(array_key_exists($vf, $carray))
+                                                               $carray[$v] = $carray[$vf];
+                                               }
+                                       }
+
+                                       foreach($this->mVariants as $vfrom) {
+                                               if(!array_key_exists($vfrom, $carray))
+                                                       continue;
+                                               foreach($this->mVariants as $vto) {
+                                                       if($vfrom == $vto)
+                                                               continue;
+                                                       if(!array_key_exists($vto, $carray))
+                                                               continue;
+                                                       $this->mTables[$vto][$carray[$vfrom]] = $carray[$vto];
+
+                                               }
+                                       }
+                               }
+                       }
+                       else {
+                               $text .= $marked[0];
+                       }
+                       if(array_key_exists(1, $marked))
+                               $text .= $this->autoConvert($marked[1]);
+               }
+
+               return $text;
+       }
+
+       /**
+        * parse the manually marked conversion rule
+        * @param string $rule the text of the rule
+        * @return array of the translation in each variant
+        * @access private
+        */
+       function parseManualRule($rules, $flags=array()) {
+
+               $choice = explode($this->mMarkup['varsep'], $rules);
+               $carray = array();
+               if(sizeof($choice) == 1) {
+                       /* a single choice */
+                       foreach($this->mVariants as $v)
+                               $carray[$v] = $choice[0];
+               }
+               else {
+                       foreach($choice as $c) {
+                               $v = explode($this->mMarkup['codesep'], $c);
+                               if(sizeof($v) != 2) // syntax error, skip
+                                       continue;
+                               $carray[trim($v[0])] = trim($v[1]);
+                       }
+               }
+               return $carray;
+       }
+
+       /**
+        * if a language supports multiple variants, it is
+        * possible that non-existing link in one variant
+        * actually exists in another variant. this function
+        * tries to find it. See e.g. LanguageZh.php
+        *
+        * @param string $link the name of the link
+        * @param mixed $nt the title object of the link
+        * @return null the input parameters may be modified upon return
+     * @access public
+        */
+       function findVariantLink( &$link, &$nt ) {
+               static $count=0; //used to limit this operation
+               static $cache=array();
+               global $wgDisableLangConversion;
+               $pref = $this->getPreferredVariant();
+               $ns=0;
+               if(is_object($nt))
+                       $ns = $nt->getNamespace();
+               if( $count > 50 && $ns != NS_CATEGORY )
+                       return;
+               $count++;
+               $variants = $this->autoConvertToAllVariants($link);
+               if($variants == false) //give up
+                       return;
+               foreach( $variants as $v ) {
+                       if(isset($cache[$v]))
+                               continue;
+                       $cache[$v] = 1;
+                       $varnt = Title::newFromText( $v );
+                       if( $varnt && $varnt->getArticleID() > 0 ) {
+                               $nt = $varnt;
+                               if( !$wgDisableLangConversion )
+                                       $link = $v;
+                               break;
+                       }
+               }
+       }
+
+    /**
+     * returns language specific hash options
+     *
+     * @access public
+     */
+       function getExtraHashOptions() {
+               $variant = $this->getPreferredVariant();
+               return '!' . $variant ;
+       }
+
+    /**
+     * get title text as defined in the body of the article text
+     *
+     * @access public
+     */
+       function getParsedTitle() {
+               return $this->mTitleDisplay;
+       }
+
+       /**
+     * a write lock to the cache
+     *
+     * @access private
+     */
+       function lockCache() {
+               global $wgMemc;
+               $success = false;
+               for($i=0; $i<30; $i++) {
+                       if($success = $wgMemc->add($this->mCacheKey . "lock", 1, 10))
+                               break;
+                       sleep(1);
+               }
+               return $success;
+       }
+
+       /**
+     * unlock cache
+     *
+     * @access private
+     */
+       function unlockCache() {
+               global $wgMemc;
+               $wgMemc->delete($this->mCacheKey . "lock");
+       }
+
+
+       /**
+     * Load default conversion tables
+     * This method must be implemented in derived class
+     *
+     * @access private
+     */
+       function loadDefaultTables() {
+               $name = get_class($this);
+               die("Must implement loadDefaultTables() method in class $name");
+       }
+
+       /**
+     * load conversion tables either from the cache or the disk
+     * @access private
+     */
+       function loadTables($fromcache=true) {
+               global $wgMemc;
+               if( $this->mTablesLoaded )
+                       return;
+               $this->mTablesLoaded = true;
+               if($fromcache) {
+                       $this->mTables = $wgMemc->get( $this->mCacheKey );
+                       if( !empty( $this->mTables ) ) //all done
+                               return;
+               }
+               // not in cache, or we need a fresh reload.
+               // we will first load the default tables
+               // then update them using things in MediaWiki:Zhconversiontable/*
+               global $wgMessageCache;
+               $this->loadDefaultTables();
+               foreach($this->mVariants as $var) {
+                       $cached = $this->parseCachedTable($var);
+                       $this->mTables[$var] = array_merge($this->mTables[$var], $cached);
+               }
+
+               $this->postLoadTables();
+
+               if($this->lockCache()) {
+                       $wgMemc->set($this->mCacheKey, $this->mTables, 43200);
+                       $this->unlockCache();
+               }
+       }
+
+    /**
+     * Hook for post processig after conversion tables are loaded
+     *
+     */
+       function postLoadTables() {}
+
+    /**
+     * Reload the conversion tables
+     *
+     * @access private
+     */
+       function reloadTables() {
+               if($this->mTables)
+                       unset($this->mTables);
+               $this->mTablesLoaded = false;
+               $this->loadTables(false);
+       }
+
+
+       /**
+     * parse the conversion table stored in the cache
+     *
+     * the tables should be in blocks of the following form:
+
+     *         -{
+     *                 word => word ;
+     *                 word => word ;
+     *                 ...
+     *         }-
+     *
+     * to make the tables more manageable, subpages are allowed
+     * and will be parsed recursively if $recursive=true
+     *
+     * @access private
+        */
+       function parseCachedTable($code, $subpage='', $recursive=true) {
+               global $wgMessageCache;
+               static $parsed = array();
+
+               if(!is_object($wgMessageCache))
+                       return array();
+
+               $key = 'Conversiontable/'.$code;
+               if($subpage)
+                       $key .= '/' . $subpage;
+
+               if(array_key_exists($key, $parsed))
+                       return array();
+
+
+               $txt = $wgMessageCache->get( $key, true, true, true );
+
+               // get all subpage links of the form
+               // [[MediaWiki:conversiontable/zh-xx/...|...]]
+               $linkhead = $this->mLangObj->getNsText(NS_MEDIAWIKI) . ':Conversiontable';
+               $subs = explode('[[', $txt);
+               $sublinks = array();
+               foreach( $subs as $sub ) {
+                       $link = explode(']]', $sub, 2);
+                       if(count($link) != 2)
+                               continue;
+                       $b = explode('|', $link[0]);
+                       $b = explode('/', trim($b[0]), 3);
+                       if(count($b)==3)
+                               $sublink = $b[2];
+                       else
+                               $sublink = '';
+
+                       if($b[0] == $linkhead && $b[1] == $code) {
+                               $sublinks[] = $sublink;
+                       }
+               }
+
+
+               // parse the mappings in this page
+               $blocks = explode($this->mMarkup['begin'], $txt);
+               array_shift($blocks);
+               $ret = array();
+               foreach($blocks as $block) {
+                       $mappings = explode($this->mMarkup['end'], $block, 2);
+                       $stripped = str_replace(array("'", '"', '*','#'), '', $mappings[0]);
+                       $table = explode( ';', $stripped );
+                       foreach( $table as $t ) {
+                               $m = explode( '=>', $t );
+                               if( count( $m ) != 2)
+                                       continue;
+                               // trim any trailling comments starting with '//'
+                               $tt = explode('//', $m[1], 2);
+                               $ret[trim($m[0])] = trim($tt[0]);
+                       }
+               }
+               $parsed[$key] = true;
+
+
+               // recursively parse the subpages
+               if($recursive) {
+                       foreach($sublinks as $link) {
+                               $s = $this->parseCachedTable($code, $link, $recursive);
+                               $ret = array_merge($ret, $s);
+                       }
+               }
+
+               if ($this->mUcfirst) {
+                       foreach ($ret as $k => $v) {
+                               $ret[LanguageUtf8::ucfirst($k)] = LanguageUtf8::ucfirst($v);
+                       }
+               }
+               return $ret;
+       }
+
+       /**
+        * Enclose a string with the "no conversion" tag. This is used by
+        * various functions in the Parser
+        *
+        * @param string $text text to be tagged for no conversion
+        * @return string the tagged text
+       */
+       function markNoConversion($text) {
+               # don't mark if already marked
+               if(strpos($text, $this->mMarkup['begin']) ||
+                  strpos($text, $this->mMarkup['end']))
+                       return $text;
+
+               $ret = $this->mMarkup['begin'] . $text . $this->mMarkup['end'];
+               return $ret;
+       }
+
+       /**
+        * convert the sorting key for category links. this should make different
+        * keys that are variants of each other map to the same key
+       */
+       function convertCategoryKey( $key ) {
+               return $key;
+       }
+       /**
+     * hook to refresh the cache of conversion tables when
+     * MediaWiki:conversiontable* is updated
+     * @access private
+       */
+       function OnArticleSaveComplete($article, $user, $text, $summary, $isminor, $iswatch, $section) {
+               $titleobj = $article->getTitle();
+               if($titleobj->getNamespace() == NS_MEDIAWIKI) {
+            /*
+                       global $wgContLang; // should be an LanguageZh.
+                       if(get_class($wgContLang) != 'languagezh')
+                               return true;
+            */
+                       $title = $titleobj->getDBkey();
+                       $t = explode('/', $title, 3);
+                       $c = count($t);
+                       if( $c > 1 && $t[0] == 'Conversiontable' ) {
+                               if(in_array($t[1], $this->mVariants)) {
+                                       $this->reloadTables();
+                               }
+                       }
+               }
+               return true;
+       }
+}
+
+?>
diff --git a/languages/LanguageCs.php b/languages/LanguageCs.php
new file mode 100644 (file)
index 0000000..99a740f
--- /dev/null
@@ -0,0 +1,1932 @@
+<?php
+/** Czech (česky)
+ *
+ * @package MediaWiki
+ * @subpackage Language
+ */
+
+/** */
+require_once( 'LanguageUtf8.php' );
+
+# See Language.php for notes.
+
+if($wgMetaNamespace === FALSE)
+       $wgMetaNamespace = str_replace( ' ', '_', $wgSitename );
+
+# Yucky hardcoding hack
+switch( $wgMetaNamespace ) {
+case 'Wikipedie':
+       $wgUserNamespace = 'Wikipedista'; break;
+case 'Wikcionář':
+       $wgUserNamespace = 'Wikcionarista'; break;
+default:
+       $wgUserNamespace = 'Uživatel';
+}
+
+/* private */ $wgNamespaceNamesCs = array(
+       NS_MEDIA              => 'Média',
+       NS_SPECIAL            => 'Speciální',
+       NS_MAIN               => '',
+       NS_TALK               => 'Diskuse',
+       NS_USER               => $wgUserNamespace,
+       NS_USER_TALK          => $wgUserNamespace . '_diskuse',
+       NS_PROJECT            => $wgMetaNamespace,
+       NS_PROJECT_TALK       => $wgMetaNamespace . '_diskuse',
+       NS_IMAGE              => 'Soubor',
+       NS_IMAGE_TALK         => 'Soubor_diskuse',
+       NS_MEDIAWIKI          => 'MediaWiki',
+       NS_MEDIAWIKI_TALK     => 'MediaWiki_diskuse',
+       NS_TEMPLATE           => 'Šablona',
+       NS_TEMPLATE_TALK      => 'Šablona_diskuse',
+       NS_HELP               => 'Nápověda',
+       NS_HELP_TALK          => 'Nápověda_diskuse',
+       NS_CATEGORY           => 'Kategorie',
+       NS_CATEGORY_TALK      => 'Kategorie_diskuse',
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgQuickbarSettingsCs = array(
+       'Žádný', 'Leží vlevo', 'Leží vpravo', 'Visí vlevo'
+);
+
+/* private */ $wgSkinNamesCs = array(
+       'standard'            => 'Standard',
+       'nostalgia'           => 'Nostalgie',
+       'cologneblue'         => 'Kolínská modř',
+       'chick'               => 'Kuře'
+) + $wgSkinNamesEn;
+
+# Hledání knihy podle ISBN
+# $wgBookstoreListCs = ..
+/* private */ $wgBookstoreListCs = array(
+    'Národní knihovna'                       => 'http://sigma.nkp.cz/F/?func=find-a&find_code=ISN&request=$1',
+    'Státní technická knihovna' => 'http://www.stk.cz/cgi-bin/dflex/CZE/STK/BROWSE?A=01&V=$1'
+) + $wgBookstoreListEn;
+
+
+# Note to translators:
+#   Please include the English words as synonyms.  This allows people
+#   from other wikis to contribute more easily.
+#
+# Nepoužívá se, pro používání je třeba povolit getMagicWords dole v LanguageCs.
+#/* private */ $wgMagicWordsCs = array(
+##   ID                                 CASE  SYNONYMS
+#    MAG_REDIRECT             => array( 0,    '#redirect',        '#přesměruj'     ),
+#    MAG_NOTOC                => array( 0,    '__NOTOC__',        '__BEZOBSAHU__'  ),
+#    MAG_FORCETOC             => array( 0,    '__FORCETOC__',     '__VŽDYOBSAH__'  ),
+#    MAG_TOC                  => array( 0,    '__TOC__',          '__OBSAH__'      ),
+#    MAG_NOEDITSECTION        => array( 0,    '__NOEDITSECTION__', '__BEZEDITOVATČÁST__' ),
+#    MAG_START                => array( 0,    '__START__',        '__ZAČÁTEK__'        ),
+#    MAG_CURRENTMONTH         => array( 1,    'CURRENTMONTH',     'AKTUÁLNÍMĚSÍC'      ),
+#    MAG_CURRENTMONTHNAME     => array( 1,    'CURRENTMONTHNAME', 'AKTUÁLNÍMĚSÍCJMÉNO' ),
+#      MAG_CURRENTMONTHNAMEGEN  => array( 1,    'CURRENTMONTHNAMEGEN', 'AKTUÁLNÍMĚSÍCGEN' ),
+##     MAG_CURRENTMONTHABBREV   => array( 1,    'CURRENTMONTHABBREV' 'AKTUÁLNÍMĚSÍCZKR'  ),
+#      MAG_CURRENTDAY           => array( 1,    'CURRENTDAY',       'AKTUÁLNÍDEN' ),
+#    MAG_CURRENTDAYNAME       => array( 1,    'CURRENTDAYNAME',   'AKTUÁLNÍDENJMÉNO'   ),
+#    MAG_CURRENTYEAR          => array( 1,    'CURRENTYEAR',      'AKTUÁLNÍROK'        ),
+#    MAG_CURRENTTIME          => array( 1,    'CURRENTTIME',      'AKTUÁLNÍČAS'        ),
+#    MAG_NUMBEROFARTICLES     => array( 1,    'NUMBEROFARTICLES', 'POČETČLÁNKŮ'        ),
+#    MAG_PAGENAME             => array( 1,    'PAGENAME',         'NÁZEVSTRANY'        ),
+#      MAG_PAGENAMEE                    => array( 1,    'PAGENAMEE',        'NÁZEVSTRANYE'       ),
+#      MAG_NAMESPACE            => array( 1,    'NAMESPACE',        'JMENNÝPROSTOR'      ),
+#      MAG_MSG                  => array( 0,    'MSG:'                   ),
+#      MAG_SUBST                => array( 0,    'SUBST:',           'VLOŽIT:'            ),
+#    MAG_MSGNW                => array( 0,    'MSGNW:',           'VLOŽITNW:'          ),
+#      MAG_END                  => array( 0,    '__END__',          '__KONEC__'          ),
+#    MAG_IMG_THUMBNAIL        => array( 1,    'thumbnail', 'thumb', 'náhled'           ),
+#    MAG_IMG_RIGHT            => array( 1,    'right',            'vpravo'             ),
+#    MAG_IMG_LEFT             => array( 1,    'left',             'vlevo'              ),
+#    MAG_IMG_NONE             => array( 1,    'none',             'žádné'              ),
+#    MAG_IMG_WIDTH            => array( 1,    '$1px'                   ),
+#    MAG_IMG_CENTER           => array( 1,    'center', 'centre', 'střed'              ),
+#    MAG_IMG_FRAMED             => array( 1,    'framed', 'enframed', 'frame', 'rám'     ),
+#    MAG_INT                  => array( 0,    'INT:'                   ),
+#    MAG_SITENAME             => array( 1,    'SITENAME',         'NÁZEVSERVERU'       ),
+#    MAG_NS                   => array( 0,    'NS:'                    ),
+#      MAG_LOCALURL             => array( 0,    'LOCALURL:',        'MÍSTNÍURL:'         ),
+#      MAG_LOCALURLE            => array( 0,    'LOCALURLE:',       'MÍSTNÍURLE:'        ),
+#      MAG_SERVER               => array( 0,    'SERVER'                 ),
+##     MAG_REVISIONID           => array( 1,    'REVISIONID',       'IDREVIZE'           )
+#);
+
+/* private */ $wgAllMessagesCs = array(
+
+# Části textu používané různými stránkami:
+'categories' => 'Kategorie',
+'category' => 'kategorie',
+'category_header' => 'Články v kategorii „$1“',
+'subcategories' => 'Podkategorie',
+
+# Dates
+'sunday' => 'neděle',
+'monday' => 'pondělí',
+'tuesday' => 'úterý',
+'wednesday' => 'středa',
+'thursday' => 'čtvrtek',
+'friday' => 'pátek',
+'saturday' => 'sobota',
+'january' => 'leden',
+'february' => 'únor',
+'march' => 'březen',
+'april' => 'duben',
+'may_long' => 'květen',
+'june' => 'červen',
+'july' => 'červenec',
+'august' => 'srpen',
+'september' => 'září',
+'october' => 'říjen',
+'november' => 'listopad',
+'december' => 'prosinec',
+'jan' => '1.',
+'feb' => '2.',
+'mar' => '3.',
+'apr' => '4.',
+'may' => '5.',
+'jun' => '6.',
+'jul' => '7.',
+'aug' => '8.',
+'sep' => '9.',
+'oct' => '10.',
+'nov' => '11.',
+'dec' => '12.',
+
+# Písmena, která se mají objevit jako část odkazu ve formě '[[jazyk]]y' atd:
+'linktrail'     => '/^((?:[a-z]|á|č|ď|é|ě|í|ň|ó|ř|š|ť|ú|ů|ý|ž)+)(.*)$/sD',
+'mainpage'              => 'Hlavní strana',
+'mainpagetext'  => 'Wiki software úspěšně nainstalován.',
+'mainpagedocfooter' => 'Podívejte se prosím do [http://meta.wikipedia.org/wiki/MediaWiki_i18n dokumentace k nastavení rozhraní] a [http://meta.wikipedia.org/wiki/MediaWiki_User%27s_Guide uživatelské příručky] pro nápovědu k použití a nastavení.',
+'portal'                => 'Portál {{grammar:2sg|{{SITENAME}}}}',
+'portal-url'            => '{{ns:4}}:Portál {{grammar:2sg|{{SITENAME}}}}',
+'about'                 => 'Úvod',
+'aboutsite' => 'O&nbsp;{{grammar:6sg|{{SITENAME}}}}',
+'aboutpage'             => '{{SITENAME}}',
+'article' => 'Obsahová stránka',
+'help'                  => 'Nápověda',
+'helppage'              => '{{ns:12}}:Obsah',
+'bugreports'    => 'Hlášení chyb',
+'bugreportspage' => '{{ns:4}}:Chyby',
+'sitesupport'   => 'Sponzorství',
+'sitesupport-url' => 'Project:Sponzorství',
+'faq'                   => 'Často kladené otázky',
+'faqpage'               => '{{ns:12}}:Často kladené otázky',
+'edithelp'              => 'Pomoc při editování',
+'newwindow'             => '(otevře se v novém okně)',
+'edithelppage'  => '{{ns:12}}:Jak_editovat_stránku',
+'cancel'                => 'Storno',
+'qbfind'                => 'Hledání',
+'qbbrowse'              => 'Listování',
+'qbedit'                => 'Editování',
+'qbpageoptions' => 'Tato stránka',
+'qbpageinfo'    => 'Kontext',
+'qbmyoptions'   => 'Moje volby',
+'qbspecialpages'        => 'Speciální stránky',
+'moredotdotdot'        => 'Další…',
+'mypage'                => 'Moje stránka',
+'mytalk'        => 'Moje diskuse',
+'anontalk'              => 'Diskuse k této IP adrese',
+
+# Metadata in edit box
+'metadata' => '<b>Metadata</b> (vysvětlení najdete <a href="$1">zde</a>)',
+'metadata_page' => '{{ns:4}}:Metadata',
+
+'navigation' => 'Navigace',
+
+'currentevents' => 'Aktuality',
+'currentevents-url' => 'Aktuality',
+
+'disclaimers' => 'Vyloučení odpovědnosti',
+'disclaimerpage' => '{{ns:4}}:Vyloučení_odpovědnosti',
+'errorpagetitle' => 'Chyba',
+'returnto'             => 'Návrat na stránku „$1“.',
+'tagline' => '<small>Z {{grammar:2sg|{{SITENAME}}}}</small>',
+'whatlinkshere' => 'Odkazuje sem',
+'help'                  => 'Nápověda',
+'search'                => 'Hledat',
+'go'            => 'Jít na', #FIXME
+'history'               => 'Historie',
+'history_short' => 'Historie',
+'info_short'    => 'Informace',
+'printableversion' => 'Verze k tisku',
+'edit' => 'Editovat',
+'editthispage'  => 'Editovat stránku',
+'delete' => 'Smazat',
+'deletethispage' => 'Smazat stránku',
+'undelete_short' => 'Obnovit $1 verzí',
+'undelete_short1' => 'Obnovit $1 verzi',
+'protect' => 'Zamknout',
+'protectthispage' => 'Zamknout stránku',
+'unprotect' => 'Odemknout',
+'unprotectthispage' => 'Odemknout stránku',
+'newpage' => 'Nová stránka',
+'talkpage'              => 'Diskusní stránka',
+'specialpage' => 'Speciální stránka',
+'personaltools' => 'Osobní nástroje',
+'postcomment'   => 'Přidat komentář',
+'addsection'   => '+',
+'articlepage'   => 'Prohlédnout si článek',
+'subjectpage'   => 'Stránka námětu', #FIXME: ? (zřejmě se vůbec nepoužívá)
+'talk' => 'Diskuse',
+'views' => 'Zobrazení',
+'toolbox' => 'Nástroje',
+'userpage' => 'Prohlédnout si uživatelovu stránku',
+'wikipediapage' => 'Prohlédnout si stránku o projektu',
+'imagepage' =>       'Prohlédnout si stránku o obrázku',
+'viewtalkpage' => 'Ukázat diskusi',
+'otherlanguages' => 'V jiných jazycích',
+'redirectedfrom' => '(Přesměrováno z $1)',
+'lastmodified'  => ' Stránka byla naposledy editována v $1.',
+'viewcount'             => 'Stránka byla zobrazena $1-krát.',
+'copyright'     => 'Obsah je dostupný pod $1.',
+'poweredby'     => '{{SITENAME}} funguje pomocí [http://www.mediawiki.org/ MediaWiki open source wiki engine].',
+'printsubtitle' => '(Z {{SERVER}})',
+'protectedpage' => 'Zamčená stránka',
+'administrators' => '{{ns:4}}:Správci',
+'sysoptitle'    => 'Pouze pro správce',
+'sysoptext'      => 'Žádaný úkon může provést jen správce. Podívejte se prosím na $1.',
+'developertitle' => 'Jen pro vývojáře',
+'developertext'  => 'Žádaný úkon může provést jen vývojář. Podívejte se prosím na $1.',
+'nbytes'          => '$1 B',
+'ok'              => 'OK',
+'sitetitle'       => '{{SITENAME}}',
+'pagetitle'       => '$1 – {{SITENAME}}',
+'sitesubtitle'  => '{{SITENAME}}: Otevřená Encyklopedie',
+'retrievedfrom' => 'Citováno z „$1“', #FIXME: Ukazuje se po tisku strany
+'newmessages' => 'Máte $1.',
+'newmessageslink' => 'nové zprávy',
+'editsection'=>'editovat',
+'toc' => 'Obsah',
+'showtoc' => 'zobrazit',
+'hidetoc' => 'skrýt',
+'thisisdeleted' => '$1 – prohlédnout nebo obnovit?',
+'restorelink' => 'Počet smazaných editací: $1',             #TODO: plural
+'feedlinks' => 'Kanály:',
+'sitenotice'    => '-', # the equivalent to wgSiteNotice
+
+# Short words for each namespace, by default used in the 'article' tab in monobook
+'nstab-main' => 'Článek',
+'nstab-user' => 'Uživatelova stránka',
+'nstab-media' => 'Soubor',
+'nstab-special' => 'Speciální',
+'nstab-wp' => '{{SITENAME}}',
+'nstab-image' => 'Soubor',
+'nstab-mediawiki' => 'Hlášení',
+'nstab-template' => 'Šablona',
+'nstab-help' => 'Nápověda',
+'nstab-category' => 'Kategorie',
+
+# Main script and global functions
+#
+'nosuchaction'  => 'Neznámý úkon',
+'nosuchactiontext' => 'Tato wiki nezná činnost (action) uvedenou v URL.',
+'nosuchspecialpage' => 'Neexistující speciální stránka',
+'nospecialpagetext' => 'Žádaná speciální stránka na této wiki neexistuje.',
+
+# General errors
+#
+'error'         => 'Chyba',
+'databaseerror' => 'Databázová chyba',
+'dberrortext'   => 'Při dotazu do databáze došlo k syntaktické chybě.
+Příčinou může být chyba v programu.
+Poslední dotaz byl:
+<blockquote><tt>$1</tt></blockquote>
+z funkce \'<tt>$2</tt>\'.
+MySQL vrátil chybu \'<tt>$3: $4</tt>\'.',
+'dberrortextcl' => 'Při dotazu do databáze došlo k syntaktické chybě.
+Poslední dotaz byl:
+<blockquote><tt>$1</tt></blockquote>
+z funkce \'<tt>$2</tt>\'.
+MySQL vrátil chybu \'<tt>$3: $4</tt>\'.',
+'noconnect'             => 'Promiňte! Tato wiki má nějaké technické potíže a nepodařilo se připojit k databázovém serveru.<br />
+$1',
+'nodb'                  => 'Nebylo možné vybrat databázi $1',
+'cachederror'           => 'Následuje kopie požadované stránky z cache, která nemusí být aktuální.',
+'laggedslavemode'       => 'Upozornění: Stránka nemusí být zcela aktuální.',
+'readonly'              => 'Databáze je uzamčena',
+'enterlockreason' => 'Udejte důvod zamčení, včetně odhadu, za jak dlouho dojde k odemčení.',
+'readonlytext'  => 'Databáze je nyní uzamčena, takže nelze ukládat nové doplňky a změny.
+Důvodem je pravděpodobně pravidelná údržba, po které se vše vrátí do normálního stavu.
+Správce, který databázi zamkl, zanechal následující zprávu:
+<p>$1',
+'missingarticle' => 'Databáze nenašla text článku, který měla najít, nazvaného „$1“.
+<p>Důvodem je obvykle zastaralý odkaz do historie smazané stránky.
+<p>V jiném případě jste možná narazil(a) na chybu v programu. Oznamte to prosím správci systému (zapamatujte si použité URL).',
+'readonly_lag' => 'Databáze byla automaticky dočasně uzamčena kvůli zpoždění ostatních databázových servery proti hlavnímu',
+'internalerror' => 'Vnitřní chyba',
+'filecopyerror' => 'Nebylo možné zkopírovat soubor  „$1“ na „$2“.',
+'filerenameerror' => 'Nebylo možné přejmenovat soubor „$1“ na „$2“.',
+'filedeleteerror' => 'Nebylo možné smazat soubor „$1“.',
+'filenotfound'  => 'Nebylo možné najít soubor „$1“.',
+'unexpected'    => 'Neočekávaná hodnota: "$1"="$2".',
+'formerror'             => 'Chyba: nebylo možné odeslat formulář',
+'badarticleerror' => 'Tento úkon nelze použít na tento článek.',
+'cannotdelete'  => 'Nebylo možné smazat zvolenou stránku ani soubor. (Možná už byla smazána někým jiným.)',
+'badtitle'              => 'Neplatný název',
+'badtitletext'  => 'Požadovaný název stránky byl neplatný, prázdný nebo nesprávně adresovaný na jinojazyčný název nebo jiný článek {{grammar:2sg|{{SITENAME}}}}.',
+'perfdisabled' => 'Omlouváme se. Tato služba byla dočasně znepřístupněna, protože zpomalovala databázi natolik, že nikdo nemohl používat wiki.',
+'perfdisabledsub' => 'Tady je uložená kopie z $1:', # obsolete?
+'perfcached' => ' Následující data jsou z cache a nemusí být plně aktuální:',
+'wrong_wfQuery_params' => 'Nesprávné parametry do wfQuery()<br />
+Funkce: $1<br />
+Dotaz: $2',
+'viewsource' => ' Ukázat zdroj',
+'protectedtext' => 'Tato stránka byla zamčena, takže ji nelze editovat; je mnoho důvodů, proč se tak mohlo stát. Vizte prosím [[{{ns:4}}:Stránka je zamčena]]. Můžete si prohlédnout a okopírovat zdrojový text této stránky:',
+'sqlhidden' => '(SQL dotaz skryt)',
+
+# Login and logout pages
+#
+'logouttitle'   => 'Nashledanou!',
+'logouttext'    => 'Nyní jste odhlášeni.<br />
+Tento počítač může být používán k prohlížení a editaci {{grammar:2sg|{{SITENAME}}}} bez uživatelského jména, nebo pro přihlášení jiného uživatele. Upozorňujeme, že některé stránky se mohou i nadále zobrazovat, jako byste byli dosud přihlášeni. Tento jev potrvá do smazání cache vašeho prohlížeče.',
+
+'welcomecreation' => '<h2>Vítejte, $1!</h2> Váš účet je vytvořen.
+<strong>Nezapomeňte si upravit své nastavení!</strong>',
+
+'loginpagetitle' => 'Přihlaste se', #FIXME
+'yourname'              => 'Název vašeho účtu', #FIXME buď heslo nebo jméno uživatele nebo název účtu atd.?
+'yourpassword'  => 'Vaše heslo',
+'yourpasswordagain' => 'Napište heslo znovu',
+'newusersonly'  => ' (pouze noví uživatelé)',
+'yourdomainname'       => 'Vaše doména',
+'externaldberror'      => 'Buď nastalo chyba v databázi pro externí autentikaci, nebo nemáte dovoleno měnit svůj externí účet.',
+'remembermypassword' => 'Pamatovat si heslo mezi jednotlivými přihlášeními.',
+'loginproblem'  => '<b>Nastal problém při vašem přihlášení.</b><br />Zkuste to znovu!',
+'alreadyloggedin' => "<strong>Uživateli $1, již jste přihlášen!</strong><br />\n",
+
+'login'                 => 'Přihlašte se', #FIXME, what exactly do the following go to?
+'loginprompt'   => 'K přihlášení do {{grammar:2sg|{{SITENAME}}}} musíte mít povoleny cookies.',
+'userlogin'             => 'Přihlašte se',
+'logout'                => 'Odhlásit se',
+'userlogout'    => 'Na shledanou',
+'notloggedin'   => 'Nejste přihlášen(a)',
+'createaccount' => 'Vytvořit nový účet',
+'createaccountmail'     => 'pomocí e-mailu',
+'badretype'             => 'Vámi napsaná hesla nesouhlasí.',
+'userexists'    => 'Uživatel se stejným jménem je už registrován. Zvolte jiné jméno.',
+'youremail'             => 'Vaše e-mailová adresa *)',
+'yourrealname'          => 'Vaše skutečné jméno **)',
+'yourlanguage' => 'Jazyk rozhraní',
+'yourvariant'  => 'Jazyková varianta',
+'yournick'              => 'Alternativní podpis',
+'email'                        => 'E-mail',
+'emailforlost'  => 'Pole označená hvězdičkami (*, **) nejsou povinná. Pokud zadáte e-mailovou adresu, budou vás moci ostatní uživatelé kontaktovat, aniž by tato adresa byla zobrazena; také vám na tuto adresu může být zasláno nové heslo v případě, že své heslo zapomenete.<br /><br />Vaše skutečné jméno, pokud ho zadáte, bude použito pro označení autorství vaší práce.',
+'prefs-help-email-enotif' => 'Na tuto adresu vám budou zasílány informace o změně stránek, pokud o ně požádáte.',
+'prefs-help-realname'  => '**) Skutečné jméno (volitelné): pokud ho zadáte, bude použito pro označení autorství vaší práce.<br />',
+'prefs-help-email'      => '*) E-mail (volitelný): Umožní ostatním uživatelům vás kontaktovat, aniž by tato adresa byla zobrazena; také vám na tuto adresu může být zasláno nové heslo v případě, že své heslo zapomenete.',
+'loginerror'    => 'Chyba při přihlašování',
+'nocookiesnew'  => 'Uživatelský účet byl vytvřen, ale nejste přihlášeni. {{SITENAME}} používá cookies k přihlášení uživatelů. Vy máte cookies vypnuty. Prosím zapněte je a přihlaste se znovu s vaším novým uživatelským jménem a heslem.',
+'nocookieslogin'      => '{{SITENAME}} používá cookies k přihlášení uživatelů. Vy máte cookies vypnuty. Prosím zapněte je a zkuste znovu.',
+'noname'                => 'Musíte uvést jméno svého účtu.',
+'loginsuccesstitle' => 'Přihlášení uspělo',
+'loginsuccess' => 'Nyní jste přihlášen na {{grammar:6sg|{{SITENAME}}}} jako uživatel „$1“.',
+'nosuchuser'   => 'Neexistuje uživatel se jménem „$1“. Zkontrolujte zápis, nebo vytvořte účet pomocí níže uvedeného formuláře.',
+'nosuchusershort'      => 'Neexistuje uživatel se jménem „$1“. Zkontrolujte zápis.',
+'wrongpassword' => 'Vámi uvedené heslo nesouhlasí. Zkuste to znovu.',
+'mailmypassword' => 'Poslat e-mailem dočasné heslo',
+'mailmypasswordauthent'        => 'Poslat e-mailem dočasné heslo',
+'noemail'              => 'Uživatel „$1“ nemá zaregistrovanou e-mailovou adresu.',
+'passwordsent' => 'Dočasné heslo bylo zasláno na e-mailovou adresu registrovanou pro „$1“. Přihlašte se, prosím, znovu, jakmile ho obdržíte.',
+'eauthentsent'             =>  'Potvrzovací e-mail byl zaslán na zadanou adresu.
+Před tím, než vám na tuto adresu budou moci být zasílány další zprávy, následujte instrukce
+v e-mailu, abyste potvrdili, že tato adresa skutečně patří vám.',
+
+'loginend'             => 'Pro registraci si zvolte [[Project:Uživatelské jméno|uživatelské jméno]] a heslo a klikněte na „Vytvořit nový účet“. Nevybírejte si uživatelské jméno, které je jménem politika, vojenského velitele, náboženského činitele nebo události. Nepoužívejte uživatelské jméno, které je urážlivé, pobuřující nebo matoucí. Zvolte si prosím čitelné jméno, ne pouhé číslo.
+
+Pokud potřebujete více informací o přihlašování, podívejte se na článek [[Nápověda:Jak se přihlásit]].
+
+Uživatelé, kteří se vracejí, musejí jen vyplnit své uživatelské jméno a heslo.
+
+K přihlášení do {{grammar:2sg|{{SITENAME}}}} musíte mít zapnuty [[w:cs:HTTP cookie|cookies]].
+
+*Vložení e-mailové adresy je nepovinné a žádné potvrzení e-mailem není vyžadováno. Umožňuje však lidem, aby vás kontaktovali prostřednictvím webu, aniž byste museli svou e-mailovou adresu zveřejnit. Také je pro vás užitečné v případě, že zapomenete heslo.',
+'mailerror' => 'Chyba při zasílání e-mailu: $1',
+'acct_creation_throttle_hit' => 'Omlouváme se, ale už jste vyrobil(a) $1 účtů. Žádný další už nemůžete vytvořit.',
+'emailauthenticated'   => 'Vaše e-mailová adresa byla ověřena na $1.',
+'emailnotauthenticated'        => 'Vaše e-mailová adresa <strong>dosud nebyla ověřena</strong> a pokročilé e-mailové funkce do té doby nejsou dostupné.<br />
+Pro ověření se přihlašte dočasným heslem, které vám bylo posláno e-mailem, nebo požádejte o nové heslo na přihlašovací stránce.',
+'invalidemailaddress'  => 'Zadaná e-mailová adresa nemůže být přijata, neboť nemá správný formát. Zadejte laskavě platnou e-mailovou adresu, nebo obsah tohoto pole vymažte.',
+'disableduntilauthent' => '<strong>(neověřeno)</strong>',
+'emailconfirmlink' => 'Podvrďte svou e-mailovou adresu',
+'noemailprefs'              => '<strong>Nebyla zadána e-mailová adresa</strong>, následující možnosti jsou nefunkční.',
+
+# Edit page toolbar
+'bold_sample'=>'Tučný text',
+'bold_tip'=>' Tučný text',
+'italic_sample'=>'Kurzíva',
+'italic_tip'=>'Kurzíva',
+'link_sample'=>'Název odkazu',
+'link_tip'=>'Vnitřní odkaz',
+'extlink_sample'=>'http://www.example.com Titulek odkazu',
+'extlink_tip'=>'Externí odkaz (nezapomeňte na předponu http://)',
+'headline_sample'=>'Text nadpisu',
+'headline_tip'=>'Nadpis druhé úrovně',
+'math_sample'=>'Vložit sem vzorec',
+'math_tip'=>'Matematický vzorec (LaTeX)',
+'nowiki_sample'=>' Vložit sem neformátovaný text',
+'nowiki_tip'=>'Ignorovat formátování wiki',
+'image_sample'=>'Příklad.jpg',
+'image_tip'=>'Vložený obrázek',
+'media_sample'=>'Příklad.mp3',
+'media_tip'=>'Odkaz na mediální soubor',
+'sig_tip'=>'Váš podpis s časovým údajem',
+'hr_tip'=>'Vodorovná čára (používejte střídmě)',
+'infobox'=>'Stiskněte tlačítko pro zobrazení příkladu',
+# alert box shown in browsers where text selection does not work, test e.g. with mozilla or konqueror
+'infobox_alert'=>'Prosím vložte text, který chcete naformátovat.\nUkáže se v informačním rámečku, aby ho šlo zkopírovat.\nPříklad:\n$1\nse stane:\n$2',
+
+# Edit pages
+#
+'summary'               => '<a href="{{LOCALURLE:Project:Shrnutí_editace}}" class="internal" title="Stručně popište změny, které jste zde učinili">Shrnutí editace</a>',
+'subject'               => 'Předmět/nadpis',
+'minoredit'            => 'Tato změna je malá editace.&nbsp;',
+'watchthis'             => 'Sledovat tento článek',
+'savearticle'   => 'Uložit změny',
+'preview'               => 'Náhled',
+'showpreview'   => 'Ukázat náhled',
+'showdiff'             => 'Ukázat změny',
+'blockedtitle'  => 'Uživatel zablokován',
+'blockedtext'   => "Pokoušíte se editovat stránku, ať už kliknutím na tlačítko ''Editovat stránku'', nebo na červený odkaz.
+
+Vaše uživatelské jméno nebo IP adresa však byla [[{{ns:4}}:Blokování|zablokována]]
+správcem s uživatelským jménem „$1“. Byl uveden následující důvod:&nbsp;'''$2'''.
+
+Můžete [[Special:Emailuser/$4|poslat e-mail uživateli $4]] nebo jinému
+[[Special:Listadmins|správci]] k prodiskutování zablokování. Uvědomte si, že nemůžete použít
+nabídku „Poslat e-mail“, jestliže nemáte na {{grammar:6sg|{{SITENAME}}}} účet a uvedenu platnou e-mailovou adresu
+ve svém [[Special:Preferences|nastavení]].
+
+Vaše IP adresa je '''$3'''. Prosím vložte tuto adresu do všech žádostí, které pošlete.
+
+Pokud chcete vědět, kdy zablokování vyprší, podívejte se prosím na [[Special:Ipblocklist|seznam blokovaných adres IP]].
+
+Pokud se potřebujete podívat na wiki text článku, můžete použít nabídku [[Special:Export|exportovat stránky]].
+
+== Bez viny? ==
+Někdy jsou zablokovány celé skupiny IP adres nebo adresy veřejných [[w:cs:proxy server|proxy serverů]].
+To znamená, že mnoho nevinných lidí nemůže editovat. Pokud nastal tento případ, měl
+by být vysvětlen v důvodech zablokování.
+
+Někdy jsou také zablokovány dynamické IP adresy, obvykle na 24 hodin. Výjimečně
+se pak může stát, že jsou zablokováni uživatelé se stejnou dynamickou IP adresou
+díky tomu, že jejich nynější IP adresa byla používána zablokovaným uživatelem.
+
+Omlouváme se za nepohodlí s tím spojené. Pokud se tento problém objeví opakovaně
+a chcete nám pomoci ho vyřešit, kontaktujte [[Project:Správci|správce wiki]]
+a vašeho [[w:cs:Poskytovatel Internetu|poskytovatele Internetu]] (ISP). Správce by měl
+být schopen zjistit čas, datum a IP adresu používanou pro nevhodné dotyčné jednání.
+Tuto informaci potom můžete předložit ISP a vysvětlit, že nemůžete editovat {{grammar:4sg|{{SITENAME}}}}
+kvůli nevhodnému chování jiného uživatele tohoto ISP a požádat o vyřešení problému.
+
+== Jen číst? ==
+Blokování nebrání čtení stránek, jen jejich editaci. Pokud jste si chtěli jen
+přečíst stránku a vidíte tuto zprávu, pravděpodobně jste klikli na červený odkaz.
+To je odkaz na stránku, která zatím neexistuje, takže se uživateli otevře editační
+okénko. Tento problém mít nebudete, pokud budete klikat jen na modré odkazy.",
+'whitelistedittitle' => 'Pro editaci je vyžadováno přihlášení',
+'whitelistedittext' => 'Pro editaci se musíte [[Special:Userlogin|přihlásit]].',
+'whitelistreadtitle' => 'Vyžadováno přihlášení',
+'whitelistreadtext' => 'Pro čtení článků se musíte [[Special:Userlogin|přihlásit]].',
+'whitelistacctitle' => 'Není vám dovoleno vytvářet uživatelské účty',
+'whitelistacctext' => 'Abyste na této wiki mohl(a) vytvářet uživatelské účty, musíte se [[Special:Userlogin|přihlásit]] a mít příslušná oprávnění.',
+'loginreqtitle' => 'Vyžadováno přihlášení',
+'loginreqtext'  => ' K prohlížení jiných stránek se musíte [[Special:Userlogin|přihlásit]].',
+'accmailtitle' => 'Heslo odesláno.',
+'accmailtext' => 'Heslo pro „$1“ bylo odesláno na $2.',
+'newarticle'    => '(Nový)',
+'newarticletext' => "<div style=\"border: 1px solid #cccccc; padding: 7px;\">'''Na {{grammar:6sg|{{SITENAME}}}} dosud neexistuje stránka se jménem {{PAGENAME}}.'''
+* Pokud chcete takový článek vytvořit, napište jeho text do rámečku níže a stiskněte tlačítko ''Uložit změny''. Váš text bude okamžitě zveřejněn.
+* Nevytvářejte prosím reklamní články.
+* Pokud jste na {{grammar:6sg|{{SITENAME}}}} nováčkem, přečtěte si prosím napřed [[Nápověda:Obsah|nápovědu]]. Pro experimenty prosím používejte k tomu určené [[Project:Pískoviště|pískoviště]].</div>",
+'talkpagetext' => '<!-- MediaWiki:talkpagetext -->',
+'anontalkpagetext' => "---- ''Toto je diskusní stránka anonymního uživatele, který si dosud nevytvořil účet nebo ho nepoužívá. Musíme proto použít číselnou [[w:cs:IP adresa|IP adresu]] k jeho identifikaci. Taková IP adresa může být sdílena několika uživateli. Pokud jste anonymní uživatel a cítíte, že jsou Vám adresovány irrelevantní komentáře, prosím [[Special:Userlogin|vytvořte si účet nebo se přihlaste]] a tím se vyhnete budoucí záměně s jinými anonymními uživateli.''",
+'noarticletext' => '(Článek zatím neobsahuje text)',
+'clearyourcache' => "'''Poznámka:''' Po uložení musíte smazat cache vašeho prohlížeče, jinak změny neuvidíte: '''Mozilla / Firefox:''' ''Ctrl-Shift-R'', '''IE:''' ''Ctrl-F5'', '''Safari:''' ''Cmd-Shift-R'', '''Konqueror''': ''F5''.",
+'usercssjsyoucanpreview' => '<strong>Tip:</strong> Použijte tlačítko „Ukázat náhled“ k testování vašeho nového css/js před uložením.',
+'usercsspreview' => "'''Pamatujte, že si prohlížíte jen náhled vašeho uživatelského css, neboť ještě nebylo uloženo!'''",
+'userjspreview' => "'''Pamatujte, že testujete a prohlížíte pouze náhled vašeho uživatelského javascriptu, dosud nebyl uložen!'''",
+'updated'               => '(Změna uložena)', #FIXME: ?
+'note'                 => '<strong>Poznámka:</strong>&nbsp;', #FIXME: Where does this come from?
+'previewnote'   => 'Pamatujte, že toto je pouze náhled, ne uložení!',
+'previewconflict' => 'Tento náhled ukazuje text tak, jak bude vypadat po uložení stránky.', #FIXME
+'editing'               => 'Editace stránky $1',
+'editingsection'               => 'Editace stránky $1 (část)',
+'editingcomment'               => 'Editace stránky $1 (komentář)',
+'editconflict'  => 'Editační konflikt: $1',
+'explainconflict' => 'Někdo změnil stránku po započetí vaší editace. Výše vidíte aktuální text článku. Vaše změny jsou uvedeny dole. Musíte sloučit své změny se stávajícím článkem. <b>Pouze</b> výše uvedený text zůstane uchován po kliknutí na „Uložit“. <br />',
+'yourtext'              => 'Váš text',
+'storedversion' => ' Uložená verze',
+'nonunicodebrowser' => '<strong>UPOZORNĚNÍ: Váš prohlížeč není schopen pracovat se znaky [[w:cs:Unicode|Unicode]], pro editaci stránek prosím použijte nějaký jiný.</strong>',
+'editingold'    => '<strong>VAROVÁNÍ: Nyní editujete zastaralou verzi této stránky. Když ji uložíte, všechny změny provedené mezitím se ztratí.</strong>',
+'yourdiff'              => 'Rozdíly',
+'copyrightwarning' => '<strong>Vaše změny budou okamžitě zveřejněny.</strong> Pokud si chcete pouze editaci vyzkoušet, použijte prosím [[Project:Pískoviště|pískoviště]].<br />
+Všechny příspěvky do {{grammar:2sg|{{SITENAME}}}} jsou zveřejňovány podle volné licence GNU pro dokumenty (podívejte se na $1 na detaily). <strong>Pokud si nepřejete, aby váš text byl nemilosrdně upravován a volně šířen, pak ho do {{grammar:2sg|{{SITENAME}}}} neukládejte.</strong> Uložením příspěvku se zavazujete, že je vaším dílem nebo je zkopírován ze zdrojů, které [[w:cs:volné dílo|nejsou chráněny]] autorským právem (tzv. <em>public domain</em>) – to se <strong>netýká</strong> většiny webových stránek. <strong>Nepoužívejte díla chráněná autorským právem bez dovolení!</strong>',
+'copyrightwarning2' => '<strong>Vaše změny budou okamžitě zveřejněny.</strong> Pokud si chcete pouze editaci vyzkoušet, použijte prosím [[Project:Pískoviště|pískoviště]].<br />
+<strong>Pokud si nepřejete, aby váš text byl nemilosrdně upravován a volně šířen, pak ho do {{grammar:2sg|{{SITENAME}}}} neukládejte.</strong> Uložením příspěvku se zavazujete, že je vaším dílem nebo je zkopírován ze zdrojů, které [[w:cs:volné dílo|nejsou chráněny]] autorským právem (tzv. <em>public domain</em>) – to se <strong>netýká</strong> většiny webových stránek. <strong>Nepoužívejte díla chráněná autorským právem bez dovolení!</strong>',
+'longpagewarning' => 'VAROVÁNÍ: Tato stránka je $1 KB dlouhá; některé prohlížeče mohou mít problémy s editováním stran, které se blíží nebo jsou delší než 32 KB. Prosím zvažte rozdělení stránky na více částí.',
+'readonlywarning' => 'VAROVÁNÍ: Databáze byla uzamčena kvůli údržbě, takže nebudete moci uložit své změny. Můžete si okopírovat text do souboru a uložit ho na později.',
+'protectedpagewarning' => '<strong>Varování:</strong> Tato stránka byla zamčena, takže ji mohou editovat pouze správci. Ujistěte se, že dodržujete <a href="{{LOCALURLE:Project:Pravidla pro zamčené stránky}}">pravidla pro zamčené stránky</a>.',
+'templatesused'        => 'Šablony používané na této stránce:',
+
+# History pages
+#
+'revhistory'    => 'Historie editací',
+'nohistory'             => 'O této stránce neexistuje historie editací.',
+'revnotfound'   => 'Verze nenalezena',
+'revnotfoundtext' => 'Nelze najít starou verzi, kterou žádáte. Zkuste prosím zkontrolovat URL hledané stránky.\b',
+'loadhist'              => 'Načítá se stránka historie editací', #FIXME Apparently not used
+'currentrev'    => 'Aktuální verze',
+'revisionasof'          => 'Verze z $1',
+'revisionasofwithlink'  => 'Verze z $1; $2<br />$3 | $4',
+'previousrevision' => '← Starší verze',
+'nextrevision'         => 'Novější verze →',
+'currentrevisionlink'   => 'zobrazit aktuální verzi',
+'cur'                   => 'teď',
+'next'                  => 'násl',
+'last'                  => 'předchozí',
+'orig'                  => 'původní',
+'histlegend'    => '(teď) = rozdíly oproti nynější verzi, (předchozí) = rozdíly oproti předchozí verzi, <b>m</b> = malá editace',
+'history_copyright'    => '-',
+'deletedrev'                   => '[smazáno]',
+
+# Diffs
+#
+'difference'    => '(Rozdíly mezi verzemi)',
+'loadingrev'    => 'načítají se verze pro zjištění rozdílů', #FIXME Apparently not used
+'lineno'                => 'Řádka $1:',
+'editcurrent'   => ' Editovat nynější verzi této stránky',
+'selectnewerversionfordiff' => 'Vyberte novější verzi pro porovnání',
+'selectolderversionfordiff' => 'Vyberte starší verzi pro porovnání',
+'compareselectedversions' => 'Porovnat vybrané verze',
+
+# Search results
+#
+'searchresults' => 'Výsledky hledání',
+'searchresulttext' => 'Pro více informací o tom, jak hledat na {{grammar:6sg|{{SITENAME}}}}, se podívejte na [[Nápověda:Hledání]].',
+'searchquery'  => 'Hledáno „$1“',
+'badquery'              => 'Špatně vytvořený vyhledávací dotaz',
+'badquerytext'  => 'Nemůžeme zpracovat vaše zadání. Je to pravděpodobně tím, že hledáte slovo kratší než tři písmena, což zatím není podporováno. Může to být také tím, že zadání bylo napsáno nesprávně. Prosím zkuste jiné zadání.',
+'matchtotals'  => 'Zadanému „$1“ odpovídá $2 názvů stran a text $3 stran.',
+'nogomatch' => '      Neexistuje žádná stránka, která by měla přesně tento název, zkouším plnotextové vyhledávání.',
+'titlematches'  => 'Stránky s odpovídajícím názvem',
+'notitlematches' => 'Žádné stránky názvem neodpovídají.',
+'textmatches'   => 'Stránky s odpovídajícím textem',
+'notextmatches' => 'Žádné stránky textem neodpovídají.',
+'prevn'                 => '$1 předchozích',
+'nextn'                 => '$1 následujících',
+'viewprevnext'  => 'Ukázat ($1) ($2) ($3).',
+'showingresults' => 'Zobrazuji <strong>$1</strong> výsledků počínaje od <strong>$2</strong>.',
+'showingresultsnum' => 'Zobrazuji <strong>$3</strong> výsledků počínaje od <strong>$2</strong>.',
+'nonefound'             => '<strong>Poznámka</strong>: neúspěšná hledání jsou často důsledkem zadání slov, která nejsou indexována, nebo uvedením mnoha slov najednou (ve výsledku se objeví jen ty stránky, které obsahují všechna zadaná slova).',
+'powersearch' => 'Hledání',
+'powersearchtext' => 'Hledat',
+'powersearchtext' => '
+Hledat ve jmenných prostorech:<br />
+$1<br />
+$2 Vypsat přesměrování &nbsp; Hledat $3 $9',
+'searchdisabled' => '<p>Omlouváme se. Plnotextové vyhledávání je dočasně nedostupné, aby se zvýšila rychlost načítání běžných článků. Zatím můžete zkusit vyhledávání Googlem; je ale možné, že jeho výsledky nemusí být aktuální.</p>',
+'googlesearch' => '
+<div style="margin-left: 2em">
+
+<!-- Google search -->
+<div style="width:130px;float:left;text-align:center;position:relative;top:-8px"><a href="http://www.google.com/" style="padding:0;background-image:none"><img src="http://www.google.com/logos/Logo_40wht.gif" alt="Google" style="border:none" /></a></div>
+
+<form method="get" action="http://www.google.com/search" style="margin-left:135px">
+  <div>
+    <input type="hidden" name="domains" value="{{SERVER}}" />
+    <input type="hidden" name="num" value="50" />
+    <input type="hidden" name="ie" value="$2" />
+    <input type="hidden" name="oe" value="$2" />
+    
+    <input type="text" name="q" size="31" maxlength="255" value="$1" />
+    <input type="submit" name="btnG" value="Vyhledat Googlem" />
+  </div>
+  <div style="font-size:90%">
+    <input type="radio" name="sitesearch" id="gwiki" value="{{SERVER}}" checked="checked" /><label for="gwiki">{{SITENAME}}</label>
+    <input type="radio" name="sitesearch" id="gWWW" value="" /><label for="gWWW">WWW</label>
+  </div>
+</form>
+
+</div>',
+'blanknamespace' => ' (Hlavní)',
+
+# Preferences page
+#
+'preferences'   => 'Nastavení',
+'prefsnologin' => 'Nejste přihlášen(a)!',
+'prefsnologintext'      => 'Pro nastavení se musíte [[Special:Userlogin|přihlásit]].',
+'prefslogintext' => 'Jste přihlášen jako „$1“. Vaše interní identifikační číslo je $2.
+
+Podívejte se na [[{{ns:12}}:Uživatelské nastavení]] pro popis možností.',
+'prefsreset'    => 'Nastavení vráceno.', #FIXME: Hmm...
+'qbsettings'    => 'Nastavení lišty nástrojů',
+'changepassword' => 'Změna hesla',
+'skin'                  => 'Styl',
+
+'math'                  => 'Matematika',
+'dateformat'    => 'Formát data',
+'math_failure'          => 'Nelze pochopit',
+'math_unknown_error'    => 'neznámá chyba',
+'math_unknown_function' => 'neznámá funkce ',
+'math_lexing_error'     => 'chyba při lexingu',   #FIXME
+'math_syntax_error'     => 'syntaktická chyba',
+'math_image_error'      => 'Selhala konverze do PNG; zkontrolujte správnou instalaci latexu, dvips, gs a convertu',
+'math_bad_tmpdir'       => 'Nelze zapsat nebo vytvořit dočasný adresář pro matematiku',
+'math_bad_output'       => 'Nelze zapsat nebo vytvořit adresář pro výstup matematiky',
+'math_notexvc'  => 'Chybí spustitelný texvc; podívejte se prosím do math/README na konfiguraci.',
+'prefs-personal' => 'Údaje o uživateli',
+'prefs-rc' => ' Poslední změny a pahýly',
+'prefs-misc' => ' Různé',
+'saveprefs'             => 'Uložit nastavení',
+'resetprefs'    => 'Vrátit původní nastavení',
+'oldpassword'   => 'Staré heslo',
+'newpassword'   => 'Nové heslo',
+'retypenew'             => 'Napište znovu nové heslo',
+'textboxsize'   => 'Velikost editačního okna',
+'rows'                  => 'Řádky',
+'columns'               => 'Sloupce',
+'searchresultshead' => 'Vyhledávání',
+'resultsperpage' => 'Počet nalezených článků na jednu stránku výsledků',
+'contextlines'  => ' Počet řádek zobrazených z každé nalezené stránky',
+'contextchars'  => ' Počet znaků kontextu na každé řádce',
+'stubthreshold' => 'Hranice pro zobrazení pahýlu',
+'recentchangescount' => 'Počet zobrazených záznamů v posledních změnách',
+'savedprefs'    => 'Vaše nastavení bylo uloženo.',
+'timezonelegend' => 'Časové pásmo',
+'timezonetext' => 'Označte, o kolik se vaše časové pásmo liší od serveru (UTC). Například pro středoevropské časové pásmo (SEČ) vyplňte „01:00“ v zimě, „02:00“ v období platnosti letního času.',
+'localtime'     => 'Místní časové pásmo',
+'timezoneoffset' => 'Posun',
+'servertime'   => 'Aktuální čas na serveru',
+'guesstimezone' => 'Načíst z prohlížeče',
+'emailflag'     => 'Zakázat e-maily od jiných uživatelů',
+'defaultns'     => 'Implicitně hledat v těchto jmenných prostorech:',
+'default'              => 'implicitní',
+'files'                        => 'Soubory',
+
+# User levels special page
+#
+
+# switching pan
+'groups-lookup-group' => 'Spravovat práva skupin',
+'groups-group-edit' => 'Existující skupiny: ',
+'editgroup' => 'Upravit skupinu',
+'addgroup' => 'Přidat skupinu',
+
+'userrights-lookup-user' => 'Spravovat uživatelské skupiny',
+'userrights-user-editname' => 'Zadejte uživatelské jméno: ',
+'editusergroup' => 'Upravit uživatelskou skupinu',
+
+# group editing
+'groups-editgroup' => 'Upravit skupinu',
+'groups-addgroup' => 'Přidat skupinu',
+'groups-editgroup-preamble' => 'Pokud název či popis začínají dvojtečkou, bude
+zbytek chápán jako označení zprávy, takže bude text lokalizován pomocí
+jmenného prostoru MediaWiki.',
+'groups-editgroup-name' => 'Název skupiny: ',
+'groups-editgroup-description' => 'Popis skupiny (max. 255 znaků):<br />',
+'savegroup' => 'Uložit skupinu',
+'groups-tableheader'        => 'ID || Název || Popis || Práva',
+'groups-existing'           => 'Existující skupiny',
+'groups-noname'             => 'Zadejte prosím platný název skupiny',
+'groups-already-exists'     => 'Skupina s takovým názvem již existuje',
+'addgrouplogentry'          => 'Přidána skupina $2',
+'changegrouplogentry'       => 'Upravena skupina $2',
+'renamegrouplogentry'       => 'Skupina $2 přejmenována na $3',
+
+# user groups editing
+'userrights-editusergroup' => 'Upravit uživatelské skupiny',
+'saveusergroups' => 'Uložit uživatelské skupiny',
+'userrights-groupsmember' => 'Člen skupin:',
+'userrights-groupsavailable' => 'Dostupné skupiny:',
+'userrights-groupshelp' => 'Zvolte skupiny, do/ze kterých chcete uživatele přidat/odebrat.
+Nezvolené skupiny nebudou změněny. Skupinu můžete vyřadit z vybraných pomocí CTRL + Levé tlačítko myši',
+'userrights-logcomment' => 'Změněno členství ve skupinách z $1 na $2',
+
+# Default group names and descriptions
+#
+'group-anon-name'       => 'Anonym',
+'group-anon-desc'       => 'Anonymní uživatelé',
+'group-loggedin-name'   => 'Uživatel',
+'group-loggedin-desc'   => 'Běžný přihlášený uživatel',
+'group-admin-name'      => 'Správce',
+'group-admin-desc'      => 'Důvěryhodní uživatelé, kteří smí blokovat uživatele a mazat články',
+'group-bureaucrat-name' => 'Byrokrat',
+'group-bureaucrat-desc' => 'Skupina byrokratů může jmenovat správce',
+'group-steward-name'    => 'Stevard',
+'group-steward-desc'    => 'Úplný přístup',
+
+# Recent changes
+#
+'changes' => 'změny',
+'recentchanges' => 'Poslední změny',
+'recentchanges-url' => 'Speciální:Recentchanges',
+'recentchangestext' => 'Sledujte poslední změny na {{grammar:6sg|{{SITENAME}}}} na této stránce.',
+'rcloaderr'             => 'Načítám seznam posledních změn',
+'rcnote'                => 'Níže je posledních <strong>$1</strong> změn za posledních <strong>$2</strong> dnů.',
+'rcnotefrom'    => 'Níže je nejvýše <b>$1</b> změn od <b>$2</b>.',
+'rclistfrom'    => 'Ukázat nové změny, počínaje od $1',
+'showhideminor' => '$1 menší editace | $2 roboty | $3 přihlášené uživatele',
+'rclinks'               => 'Ukázat $1 posledních změn během posledních $2 dnů; $3.',
+'rchide'                => 'jako $4; $1 menších editací; $2 vedlejších jmenných prostorů; $3 násobných editací.',
+'rcliu'                 => '; $1 editací od přihlášených uživatelů',
+'diff'                  => 'rozdíl',
+'hist'                  => 'historie',
+'hide'                  => 'skrýt',
+'show'                  => 'ukázat',
+'tableform'             => 'tabulka',
+'listform'              => 'seznam',
+'nchanges'              => '$1 změn',
+'minoreditletter' => 'm',
+'newpageletter' => 'N',
+'sectionlink' => '→',
+'number_of_watching_users_RCview'      => '[$1]',
+'number_of_watching_users_pageview'    => '[Sledujících uživatelů: $1]',   #TODO: plural
+
+# Upload
+#
+'upload'                => 'Načíst soubor',
+'uploadbtn'             => 'Načíst soubor',
+'uploadlink'    => 'Načíst obrázek',
+'reupload'              => 'Načíst znovu',
+'reuploaddesc'  => 'Vrátit se k načtení.',
+'uploadnologin' => 'Nejste přihlášen(a)',
+'uploadnologintext'     => 'Pro načtení souboru se musíte [[Special:Userlogin|přihlásit]].',
+'upload_directory_read_only' => 'Do adresáře pro načítané soubory ($1) nemá webserver právo zápisu.',
+'uploaderror'   => 'Při načítání došlo k chybě',
+'uploadtext'   => "
+'''POZOR!''' Před nahráváním souborů si zcela určitě přečtěte
+[[Project:Pravidla použití obrázků|pravidla použití obrázků]]
+a dodržujte je.
+
+Pro prohlížení a hledání již dříve nahraných souborů se podívejte
+na [[Special:Imagelist|seznam načtených souborů]], popř.
+[[Special:Newimages|galerii nových obrázků]]. Všechny načtení
+a smazání jsou zaznamenány v [[Special:Log|protokolovacích záznamech]].
+
+Pomocí níže uvedeného formuláře můžete na wiki nahrát obrázky a jiné
+soubory, které poté budete moci použít v článcích. Ve většině prohlížečů
+je zobrazeno tlačítko „Procházet…“, pomocí kterého budete moci
+vybrat soubor k načtení, jehož jméno se poté objeví v políčku
+vedle tlačítka. Také musíte potvrdit, že nahráním souboru neporušujete
+ničí autorská práva. Poté stiskněte tlačítko „Načíst soubor“ k
+dokončení načtení. Buďte trpěliví, nahrávání může chvíli trvat.
+
+Preferované formáty jsou JPEG pro fotografie, PNG pro schémata
+a OGG pro zvuky. Používejte laskavě smysluplná jména souborů,
+soubor po načtení nelze přejmenovat.
+
+Pro vložení obrázku do stránky použijte syntaxi
+<code><nowiki>[[{{ns:6}}:soubor.jpg]]</nowiki></code> nebo
+<code><nowiki>[[{{ns:6}}:soubor.png|popisek]]</nowiki></code>, popř.
+<code><nowiki>[[{{ns:-2}}:soubor.ogg]]</nowiki></code> pro zvuky.
+
+Uvědomte si laskavě, že stejně jako u ostatních wikistránek mohou
+ostatní uživatelé vámi nahraný soubor smazat či upravit, pokud to
+uznají za vhodné; pokud budete tuto funkci zneužívat, může být
+váš uživatelský účet zablokován.",
+'uploadlog'            => 'kniha nahrávek',
+'uploadlogpage' => 'Kniha_nahrávek',
+'uploadlogpagetext' => 'Níže najdete seznam nejnovějších souborů.',
+'filename'              => 'Soubor',
+'filedesc'              => 'Popis',
+'filestatus' => 'Autorská práva',
+'filesource' => 'Zdroj',
+'copyrightpage' => '{{ns:4}}:Autorské právo',
+'copyrightpagename' => 'podmínek {{grammar:2sg|{{SITENAME}}}}',
+'uploadedfiles' => 'Načtené soubory',
+'ignorewarning' => 'Ignorovat varování a uložit soubor.',
+'minlength'             => 'Jméno souboru se musí skládat nejméně ze tří písmen.',
+'illegalfilename'       => 'Název souboru "$1" obsahuje znaky, které nejsou povoleny v názvech stránek. Prosím přejmenujte soubor a zkuste jej nahrát znovu.',
+'badfilename'  => 'Jméno souboru bylo změněno na „$1“.',
+'badfiletype'  => '„.$1“ není jeden z doporučených typů souborů.',
+'largefile'             => 'Doporučuje se, aby délka souboru nepřesahovala $1&nbsp;B, tento soubor má $2&nbsp;B.',
+'emptyfile'             => 'Soubor, který jste vložili, se zdá být prázdný. Mohl to způsobit překlep v názvu souboru. Prosím zkontrolujte, zda jste opravdu chtěli vložit tento soubor.',
+'fileexists'    => ' Soubor s tímto jménem již existuje, prosím podívejte se na $1, pokud nevíte jistě, zda chcete tento soubor nahradit.',
+'successfulupload' => 'Načtení úspěšně provedeno!',
+'fileuploaded' => 'Soubor „$1“ byl úspěšně načten. Prosím klikněte na tento odkaz: ($2), který vede na stránku popisu a napište tam informace o souboru: odkud pochází, kdy byl vytvořen a kým; a cokoliv dalšího, co o něm můžete vědět. Pokud je to obrázek, můžete ho do stránek vložit takto: <tt><nowiki>[[</nowiki>{{ns:6}}:$1|thumb|Nadpis]]</tt>',
+'uploadwarning' => 'Varování',
+'savefile'              => 'Uložit soubor',
+'uploadedimage' => 'načítá „[[$1]]“',
+'uploadscripted' => 'Tento soubor obsahuje HTML nebo kód skriptu, který by mohl být prohlížečem chybně interpretován.',
+'uploaddisabled' => 'Promiňte, ale načítání souborů je vypnuto.',
+'uploadcorrupt' => 'Soubor je poškozen nebo nemá správnou příponu. Zkontrolujte prosím soubor a zkuste ho načíst znovu.',
+'uploadvirus' => 'Tento soubor obsahuje virus! Podrobnosti: $1',
+'sourcefilename' => 'Jméno zdrojového souboru',
+'destfilename' => 'Cílové jméno',
+
+# Image list
+#
+'imagelist'             => 'Seznam načtených obrázků',
+'imagelisttext' => 'Níže je seznam $1 obrázků, setříděných $2.',
+'getimagelist'  => 'načítám seznam obrázků',
+'ilsubmit'              => 'Hledat',
+'showlast'              => 'Ukázat posledních $1 obrázků tříděných $2.',
+'byname'                => 'podle jména',
+'bydate'                => 'podle data',
+'bysize'                => 'podle velikosti',
+'imgdelete'             => 'smazat',
+'imgdesc'               => 'popis',
+'imglegend'             => '(popis) = ukázat / editovat popis souboru.',
+'imghistory'    => 'Historie načtených souborů',
+'revertimg'             => 'vrátit',
+'deleteimg'             => 'smazat',
+'deleteimgcompletely'           => 'smazat úplně',
+'imghistlegend' => '(teď) = toto je současná verze souboru, (smazat úplně) = smazat všechny verze tohoto souboru, (smazat) = smazat jen tuto verzi, (vrátit) = obnovit starou verzi. <br /> <i>Klikněte na datum pro zobrazení obrázku, který byl uložen v ten den.</i>',
+'imagelinks'    => 'Odkazy k souboru',
+'linkstoimage'  => 'Na soubor odkazují tyto stránky:',
+'nolinkstoimage' => 'Na tento soubor neodkazuje žádná stránka.',
+'sharedupload' => 'Tento soubor je sdílený a může být používán ostatními projekty.',
+'shareduploadwiki' => 'Více informací najdete na [$1 stránce s popisem].',
+'noimage'       => 'Soubor s tímto jménem neexistuje, můžete ho [$1 načíst]',
+'uploadnewversion' => '[$1 Načíst novou verzi tohoto souboru]',
+
+# User list
+'userlist'             => 'Seznam uživatelů',
+'userlisttext' => 'Níže je seznam $1 uživatelů, setříděných $2.',
+'ulshowmatch'  => 'Ukázat uživatele, jejichž jména vyhovují',
+'ulsubmit'             => 'Hledat',
+'ulshowlast'   => 'Ukázat posledních $1 uživatelů tříděných $2.',
+'byrights'             => 'podle oprávnění',
+
+# Statistics
+#
+'statistics'    => 'Statistika',
+'sitestats'             => 'O serveru',
+'userstats'             => 'O uživatelích',
+'sitestatstext' => 'V databázi je celkem <strong>$1</strong> stránek. Toto číslo zahrnuje diskusní stránky, stránky o {{grammar:6sg|{{SITENAME}}}}, pahýly, přesměrování a další, které nejsou články v pravém slova smyslu. Kromě nich zbývá <strong>$2</strong> pravděpodobně skutečných článků.<p>Od založení wiki bylo navštíveno celkem <strong>$3</strong> stránek a editováno <strong>$4</strong>-krát. To činí v průměru <strong>$5</strong> editací na stránku a <strong>$6</strong> návštěv na editaci.',
+'userstatstext' => 'Je zde <strong>$1</strong> registrovaných uživatelů. <strong>$2</strong> z nich jsou správci (podívejte se na $3).',
+
+# Maintenance Page
+#
+'maintenance'           => 'Nástroje pro opravy a údržbu',
+'maintnancepagetext'    => 'Zde jsou různé nástroje pro opravy a všeobecnou údržbu dat. Některé funkce mohou zatěžovat databázi, nenačítejte proto po každé drobné opravě!',
+'maintenancebacklink'   => 'Zpět na stránku nástrojů',
+'disambiguations'       => ' Stránky s rozcestníky',
+'disambiguationspage'   => '{{ns:12}}:Rozcestníky',
+'disambiguationstext'   => 'Následující stránky odkazují na <i>stránku s rozcestníky</i>. Místo toho by měly by odkazovat na náležitou stránku.<br />Se stránkou je zacházeno jako s rozcestníkem, pokud se na ni odkazuje z $1.<br />Odkazy z jiných jmenných prostorů zde <i>nejsou</i> vypsány.',
+'doubleredirects'       => 'Dvojitá přesměrování',
+'doubleredirectstext'  => '<b>Pozor:</b> Může se stát, že tento seznam bude obsahovat falešné pozitivy. Obvykle to znamená, že existuje další text s odkazy po #REDIRECT.<br />Každý řádek obsahuje odkaz na první a druhé přesměrování, plus první řádek textu druhého přesměrování, který obvykle ukazuje jméno „skutečného“ hlavního článku, na který by mělo první přesměrování odkazovat.',
+'brokenredirects'       => 'Přerušená přesměrování',
+'brokenredirectstext'   => ' Tato přesměrování vedou na neexistující články.',
+'selflinks'             => 'Samoodkazující stránky',
+'selflinkstext'         => 'Tyto stránky obsahují neužitečný odkaz samy na sebe.',
+'mispeelings'           => 'Stránky s překlepy',
+'mispeelingstext'       => ' Tyto stránky obsahují jeden z běžných překlepů, jejichž seznam je v $1. Měly by být opraveny na náležitý pravopis (uveden takto).',
+'mispeelingspage'       => 'Seznam častých překlepů',
+'missinglanguagelinks'  => 'Chybějící mezijazykové odkazy',
+'missinglanguagelinksbutton'    => 'Nalézt chybějící mezijazykové odkazy pro',
+'missinglanguagelinkstext'      => 'Těmto článkům chybí odkaz na ekvivalent v jazyce $1. Přesměrování a podstránky zde <i>nejsou</i> zobrazeny.',
+
+# Miscellaneous special pages
+#
+'orphans'               => 'Sirotci',
+'geo'                  => 'Zeměpisné souřadnice',
+'validate'             => 'Hodnocení stránek',
+'lonelypages'   => 'Sirotčí články',
+'uncategorizedpages'   => 'Nekategorizované stránky',
+'unusedimages'  => 'Nepoužívané obrázky a soubory',
+'popularpages'  => 'Nejnavštěvovanější stránky',
+'uncategorizedcategories' => 'Nekategorizované kategorie',
+'nviews'                => '$1 zobrazení',
+'wantedpages'   => 'Žádoucí články',
+'nlinks'                => '$1 odkazů',                                       #TODO: plural
+'allpages'              => 'Všechny stránky',
+'nextpage'             => 'Následující stránka ($1)',
+'randompage'    => 'Náhodná stránka',
+'randompage-url' => 'Speciální:Randompage',
+'shortpages'    => 'Nejkratší články',
+'longpages'             => 'Nejdelší články',
+'deadendpages'  => 'Slepé články',
+'listusers'             => 'Uživatelé',
+'specialpages'  => 'Speciální stránky',
+'spheading'             => 'Speciální stránky pro všechny uživatele',
+'restrictedpheading'   => 'Speciální stránky s omezeným přístupem',
+'protectpage'   => 'Zamčení stránky',
+'recentchangeslinked' => 'Související změny',
+'rclsub'                => '(stránek odkazovaných z „$1“)',
+'debug'                 => 'Odlaďování',
+'newpages'              => 'Nejnovější články',
+'ancientpages'         => 'Nejdéle needitované stránky',
+'intl'         => 'Mezijazykové odkazy',
+'move' => 'Přesunout',
+'movethispage'  => 'Přesunout stránku',
+'unusedimagestext' => '<p>Jiné WWW stránky mohou odkazovat přímo pomocí URL, na takové odkazy se v tomto seznamu nebere zřetel.',
+'categoriespagetext' => 'Ve wiki existují následující kategorie:',
+'booksources'   => 'Zdroje knih',
+'booksourcetext' => 'Následují odkazy na jiné WWW stránky, na kterých se prodávají knihy, nebo které mohou obsahovat další informace o knize, kterou hledáte. {{SITENAME}} nemá s těmito prodejnami žádný vztah, tyto odkazy nelze chápat jako doporučení.',
+'userrights' => 'Správa uživatelských skupin',
+'groups' => 'Uživatelské skupiny',
+'data' => 'Data',
+'isbn'  => 'ISBN',
+'rfcurl' =>  'http://www.faqs.org/rfcs/rfc$1.html',
+'pubmedurl' =>  'http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?cmd=Retrieve&db=pubmed&dopt=Abstract&list_uids=$1',
+'alphaindexline' => 'od $1 do $2',
+'version'               => 'Verze',
+'log'          => 'Protokolovací záznamy',
+'alllogstext'  => 'Společné zobrazení knihy nahrávek, smazání, zamčení, zablokování a uživatelských práv.
+Zobrazení můžete zůžit výběrem typu záznamu, uživatelského jména nebo dotčené stránky.',
+# labels for User: and Title: on Special:Log pages
+'specialloguserlabel' => 'Uživatel: ',
+'speciallogtitlelabel' => 'Název: ',
+
+# Special:Allpages
+'nextpage'          => 'Další stránka ($1)',
+'allpagesfrom'         => 'Všechny stránky počínaje od:',
+'allarticles'          => 'Všechny články',
+'allnonarticles'       => 'Všechny nečlánky',
+'allinnamespace'       => 'Všechny stránky (jmenný prostor $1)',
+'allnotinnamespace'    => 'Všechny stránky (mimo jmenný prostor $1)',
+'allpagesprev'         => 'Předchozí',
+'allpagesnext'         => 'Nálsedující',
+'allpagessubmit'       => 'Přejít',
+
+# Email this user
+#
+'mailnologin'   => 'Bez odesílací adresy',
+'mailnologintext' => 'Pokud chcete posílat e-maily jiným uživatelům, musíte se [[Special:Userlogin|přihlásit]] a mít platnou e-mailovou adresu ve svém [[Special:Preferences|nastavení]].',
+'emailuser'             => 'Poslat e-mail',
+'emailpage'             => 'Poslat e-mail',
+'emailpagetext' => 'Pokud tento uživatel uvedl platnou e-mailovou adresu ve svém nastavení, tímto formulářem mu lze poslat zprávu. E-mailová adresa, kterou máte uvedenu v nastavení, se objeví jako adresa odesílatele pošty, aby adresát mohl odpovědět.',
+'usermailererror' => 'Chyba poštovního programu: ',
+'defemailsubject'  => 'E-mail z {{grammar:2sg|{{SITENAME}}}}',
+'noemailtitle'  => 'Bez e-mailové adresy',
+'noemailtext'   => 'Tento uživatel buď nezadal platnou adresu nebo zakázal přijímat zprávy od jiných uživatelů.',
+'emailfrom'             => 'Od',
+'emailto'               => 'Komu',
+'emailsubject'  => 'Předmět',
+'emailmessage'  => 'Zpráva',
+'emailsend'             => 'Odeslat',
+'emailsent'             => 'Zpráva odeslána',
+'emailsenttext' => 'Váš e-mail byl odeslán.',
+
+# Watchlist
+#
+'watchlist'             => 'Sledované stránky',
+'watchlistsub' => '(uživatele „$1“)',
+'nowatchlist'   => 'Na svém seznamu sledovaných stránek nemáte žádné položky.',
+'watchnologin'  => 'Nejste přihlášen(a)',
+'watchnologintext'      => 'Pro sledování oblíbených stránek se musíte [[Special:Userlogin|přihlásit]].',
+'addedwatch'    => 'Přidáno k oblíbeným',
+'addedwatchtext' => 'Stránka „[[$1]]“ byla přidána mezi stránky, které [[Special:Watchlist|sledujete]]. Budoucí změny této stránky se objeví <b>tučně</b> v [[Special:Recentchanges|seznamu posledních změn]], aby bylo snadnější si jí povšimnout. Pokud budete později chtít stránku ze seznamu sledovaných smazat, klikněte na „Nesledovat tuto stránku“ v liště nástrojů.',
+'removedwatch'  => 'Vyřazeno ze seznamu sledovaných stránek',
+'removedwatchtext' => 'Stránka „$1“ byla vyřazena z vašeho seznamu sledovaných stránek.',
+'watch' => 'Sledovat',
+'watchthispage' => 'Sledovat tuto stránku',
+'unwatch' => 'Nesledovat',
+'unwatchthispage' => 'Nesledovat tuto stránku',
+'notanarticle'  => 'Toto není článek',
+'watchnochange'         => 'Žádná ze sledovaných položek nebyla editována v době, která je zobrazena.',
+'watchdetails'          => 'Počet sledovaných stránek nepočítaje diskusní: $1; můžete si nechat [$4 ukázat a editovat kompletní seznam]. V období vybraném níže bylo provedeno $2 editací. $3…',
+'wlheader-enotif'              => '* Upozorňování e-mailem je zapnuto.',
+'wlheader-showupdated'   => "* Stránky, které se změnily od vaší poslední návštěvy, jsou zobrazeny '''tučně'''",
+'watchmethod-recent'=> 'hledají se sledované stránky mezi posledními změnami',
+'watchmethod-list'      => 'hledají se nejnovější editace sledovaných stránek',
+'removechecked'         => 'Vyřadit označené položky ze seznamu sledovaných',
+'watchlistcontains' => 'Počet stránek ve vašem seznamu sledovaných stránek: $1',
+'watcheditlist'                => 'Tady je abecední seznam vašich sledovaných stránek. Zaškrtněte stránky, které chcete smazat z vašeho seznamu a klikněte na tlačítko „vyřadit označené“ na konci obrazovky. S každou stránkou je vždy sledována i její diskusní stránka a naopak.',
+'removingchecked'      => 'Požadované položky se odstraňují ze seznamu sledovaných…',
+'couldntremove'        => 'Nepodařilo se odstranit položku „$1“…',
+'iteminvalidname'      => 'Problém s položkou „$1“, neplatný název…',
+'wlnote'                        => 'Níže je posledních $1 změn v posledních <b>$2</b> hodinách.',
+'wlshowlast'            => 'Ukázat posledních $1 hodin $2 dnů $3',
+'wlsaved'                       => 'Toto je uložená verze vašeho seznamu sledovaných stránek.',
+'wlhideshowown'        => '$1 moje editace.',
+'wlshow'               => 'Zobrazit',
+'wlhide'               => 'Skrýt',
+
+'enotif_mailer'                => 'Zasílač hlášení {{grammar:2sg|{{SITENAME}}}}',
+'enotif_reset'                 => 'Vynulovat všechny příznaky (nastavit stav na „navštíveno“)',
+'enotif_newpagetext'=> 'Toto je nová stránka.',
+'changed'      => 'změněno',
+'created'      => 'vytvořeno',
+'enotif_subject'       => '$PAGEEDITOR upravil stránku $PAGETITLE na {{grammar:6sg|{{SITENAME}}}}.',
+'enotif_lastvisited' => 'Vizte $1 pro seznam všech změn od minulé návštěvy.',
+'enotif_body' => 'Vážený uživateli $WATCHINGUSERNAME,
+
+$PAGEEDITDATE upravil $PAGEEDITOR stránku $PAGETITLE, vizte $PAGETITLE_URL pro aktuální verzi.
+
+$NEWPAGE
+
+Shrnutí editace: $PAGESUMMARY $PAGEMINOREDIT
+Uživatele, který změnu provedl, můžete kontaktovat:
+e-mailem: $PAGEEDITOR_EMAIL
+na wiki: $PAGEEDITOR_WIKI
+
+Dokud stránku nenavštívíte, nebudou vám zasílána další oznámení o změnách této stránky, případně do doby, než vynulujete příznaky ve svém seznamu sledovaných stránek.
+
+       S pozdravem váš zasílač hlášení {{grammar:2sg|{{SITENAME}}}}
+
+--
+Pro změnu nastavení navštivte
+{{SERVER}}{{localurl:Special:Watchlist/edit}}
+
+Rady a kontakt:
+{{SERVER}}{{localurl:Project:Potřebuji pomoc}}',
+
+# Delete/protect/revert
+#
+'deletepage'    => 'Smazat stránku',
+'confirm'               => 'Potvrdit',
+'excontent' => 'obsah byl:',
+'excontentauthor' => "obsah byl: '$1' (a jediným přispěvatelem byl '$2')",
+'exbeforeblank' => 'obsah před vyprázdněním byl:',
+'exblank' => 'stránka byla prázdná',
+'confirmdelete' => 'Potvrdit smazání',
+'deletesub'            => '(Maže se „$1“)',
+'historywarning' => ' Varování: Stránka, kterou chcete smazat, má historii:&nbsp;',
+'confirmdeletetext' => 'Chystáte se trvale smazat z databáze stránku nebo obrázek s celou jeho historií. Prosím potvrďte, že to opravdu chcete učinit, že si uvědomujete důsledky a že je to v souladu s [[Project:Pravidla|pravidly]].',
+'actioncomplete' => 'Provedeno',
+'deletedtext'  => ' Stránka nebo soubor „$1“ byla smazána; $2 zaznamenává poslední smazání.',
+'deletedarticle' => 'maže „$1“',
+'dellogpage'    => 'Kniha_smazaných_stránek',
+'dellogpagetext' => 'Zde je seznam posledních smazaných z databáze. Všechny časové údaje uvedeny podle časového pásma serveru (UTC).
+<ul>
+</ul>
+',
+'deletionlog'   => 'kniha smazaných stránek',
+'reverted'              => 'Obnovení předchozí verze',
+'deletecomment' => 'Důvod smazání',
+'imagereverted' => 'Obnovení předchozí verze úspěšně provedeno.',
+'rollback'              => 'Vrátit zpět editace',
+'rollback_short' => 'Vrátit zpět',
+'rollbacklink'  => 'vrácení zpět',
+'rollbackfailed' => 'Nešlo vrátit zpět',
+'cantrollback'  => 'Nelze vrátit zpět poslední editaci, neboť poslední přispěvatel je jediným autorem tohoto článku.',
+'alreadyrolled' => 'Nelze vrátit zpět poslední editaci [[$1]] od [[User:$2|$2]] ([[User talk:$2|Diskuse]]), protože někdo jiný již článek editoval nebo vrátil tuto změnu zpět. Poslední editace byla od [[User:$3|$3]] ([[User talk:$3|Diskuse]]).',
+#   only shown if there is an edit comment
+'editcomment' => 'Shrnutí editace bylo: „<i>$1</i>“.',
+'revertpage'   => 'Editace uživatele „$2“ vrácena do předchozího stavu, jehož autorem je „$1“.',
+'sessionfailure' => 'Zřejmě je nějaký problém s vaším přihlášením;
+vámi požadovaná činnost byla stornována jako prevence před neoprávněným přístupem.
+Stiskněte tlačítko „zpět“, obnovte stránku, ze které jste přišli a zkuste činnost znovu.',
+'protectlogpage' => 'Kniha_zamčení',
+'protectlogtext' => 'Zde je seznam zamčení/odemčení stránek. Viz [[{{ns:4}}:Zamčená stránka]] pro další informace.',
+'protectedarticle' => 'zamyká „[[$1]]“',
+'unprotectedarticle' => 'odemyká „[[$1]]“',
+'protectsub' =>'(Zamyká se „$1“)',
+'confirmprotecttext' => 'Opravdu chcete zamknout tuto stránku?',
+'confirmprotect' => 'Potvrdit zamčení',
+'protectmoveonly' => 'Bránit pouze proti přesunutí',
+'protectcomment' => 'Důvod zamčení',
+'unprotectsub' => '(Odemyká se „$1“)',
+'confirmunprotecttext' => 'Opravdu chcete odemknout tuto stránku?',
+'confirmunprotect' => 'Potvrdit odemčení',
+'unprotectcomment' => 'Důvod odemčení',
+
+# Undelete
+'undelete' => 'Obnovit smazanou stránku',
+'undeletepage' => 'Prohlédnout si a obnovit smazanou stránku',
+'undeletepagetext' => 'Tyto stránky jsou smazány, avšak dosud archivovány, a proto je možno je obnovit. Archiv může být pravidelně vyprazdňován.',
+'undeletearticle' => 'Obnovit smazaný článek',
+'undeleterevisions' => '$1 verzí je archivováno',
+'undeletehistory' => 'Pokud stránku obnovíte, všechny revise budou v historii obnoveny. Pokud byla vytvořena nová stránka se stejným jménem jako smazaná, obnovené revise se zapíší na starší místo v historii a nová stránka nebude nahrazena.',
+'undeleterevision' => 'Smazaná verze z $1',
+'undeletebtn' => 'Obnovit',
+'undeletedarticle' => 'obnovuje „$1“',
+'undeletedrevisions' => 'Obnoveno $1 verzí',
+'undeletedtext'   => 'Stránka [[$1]] byla úspěšně obnovena. Vizte [[Special:Log/delete|knihu smazaných stránek]] na záznam posledních smazání a obnovení.',
+
+# Namespace form on various pages
+'namespace' => 'Jmenný prostor:',
+'invert' => 'Obrátit výběr',
+
+# Contributions
+#
+'contributions' => 'Příspěvky uživatele',
+'mycontris'             => 'Mé příspěvky',
+'contribsub'    => '$1',
+'nocontribs'    => 'Nenalezeny žádné změny podle těchto kritérií.',
+'ucnote'                => 'Níže jsou uživatelovy poslední <strong>$1</strong> změny během posledních <strong>$2</strong> dnů.',
+'uclinks'               => 'Ukaž posledních $1 změn; ukaž posledních $2 dnů.',
+'uctop'                 => ' (aktuální)',
+'newbies'       => 'nováčci',
+
+# What links here
+#
+'whatlinkshere' => 'Odkazuje sem',
+'notargettitle' => 'Bez cílové stránky',
+'notargettext'  => 'Této funkci musíte určit cílovou stránku nebo uživatele.',
+'linklistsub'   => '(Seznam odkazů)',
+'linkshere'             => 'Odkazují sem tyto stránky:',
+'nolinkshere'   => 'Žádná stránka sem neodkazuje.',
+'isredirect'    => 'přesměrování',
+
+# Block/unblock IP
+#
+'blockip'               => 'Zablokovat uživatele',
+'blockiptext'   => 'Tento formulář slouží k zablokování editací z konkrétní IP adresy nebo uživatelského jména. Toto by mělo být používáno jen v souladu s [[{{ns:4}}:blokování|pravidly blokování]]. Udejte přesný důvod níže (například ocitujte, které stránky byly poškozeny). Čas pro vypršení se udává ve standardním formátu GNU, který je popsán na [http://www.gnu.org/software/tar/manual/html_chapter/tar_7.html tar manual], např. „1 hour“, „2 days“, „next Wednesday“, „1 January 2017“. Alternativně můžete použít „indefinite“ (na dobu neurčitou) nebo „infinite“ (navždy). Pro informaci, jak zablokovat rozsah adres, se podívejte na [[meta:Range blocks]]. Pro odblokování se podívejte na [[Special:Ipblocklist|seznam blokovaných IP adres]].',
+'ipaddress'                      => 'IP adresa',
+'ipadressorusername' => 'IP adresa nebo uživatelské jméno',         #TODO: remove
+#'ipaddressorusername' => 'IP adresa nebo uživatelské jméno',
+'ipbexpiry'             => 'Vyprší',
+'ipbreason'             => 'Důvod',
+'ipbsubmit'             => 'Zablokovat',
+'badipaddress'  => 'Neplatná IP adresa',
+'blockipsuccesssub' => 'Zablokování uspělo',
+'blockipsuccesstext' => 'Uživatel „$1“ je zablokován. <br />Podívejte se na [[Special:Ipblocklist|seznam zablokovaných]], [[Project:Kniha zablokování]] zaznamenává všechny podobné úkony.',
+'unblockip'             => 'Odblokovat IP adresu',
+'unblockiptext' => 'Tímto formulářem je možno obnovit právo blokované IP adresy či uživatele opět přispívat do {{grammar:2sg|{{SITENAME}}}}.',
+'ipusubmit'             => 'Odblokovat',
+'ipusuccess'   => 'IP adresa „[[$1]]“ byla úspěšně odblokována',
+'ipblocklist'   => 'Seznam blokovaných IP adres',
+'blocklistline' => '$1 $2 zablokoval $3 ($4)',
+'infiniteblock' => 'čas vypršení: infinite', //fixme
+'expiringblock' => 'čas vypršení: $1',
+'blocklink'             => 'zablokovat',
+'unblocklink'   => 'uvolnit',
+'contribslink'  => 'příspěvky',
+'autoblocker'  => 'Automaticky zablokováno, protože sdílíte IP adresu s „$1“. Důvod: „$2“.',
+'blocklogpage' => 'Kniha_zablokování',
+'blocklogentry'        => 'zablokovává „[[$1]]“ s časem vypršení $2',
+'blocklogtext' => 'Toto je kniha úkonů blokování a odblokování uživatelů. Automaticky blokované IP adresy nejsou vypsány. Podívejte se na [[Special:Ipblocklist|seznam blokování IP]] s výčtem aktuálních zákazů a blokování.',
+'unblocklogentry'      => 'odblokovává „$1“',
+'range_block_disabled'  => 'Blokování rozsahů IP adres je zakázáno.',
+'ipb_expiry_invalid'    => 'Neplatný čas vypršení.',
+'ip_range_invalid'      => 'Neplatný IP rozsah.',
+'proxyblocker'  => 'Blokování proxy serverů',
+'proxyblockreason'      => 'Vaše IP adresa byla zablokována, protože funguje jako otevřený proxy server. Kontaktujte prosím vašeho poskytovatele Internetového připojení nebo technickou podporu a informujte je o tomto vážném bezpečnostním problému.',
+'proxyblocksuccess'     => 'Hotovo.',
+'sorbs'         => 'SORBS DNSBL',
+'sorbsreason'   => 'Vaše IP adresa je uvedena na seznamu [http://www.sorbs.net SORBS] DNSBL jako [[w:cs:otevřená proxy|otevřená proxy]].',
+
+# Developer tools
+#
+'lockdb'                => 'Zamknout databázi',
+'unlockdb'              => 'Odemknout databázi',
+'lockdbtext'    => 'Pokud zamknete databázi, znemožníte ostatním editovat, upravovat nastavení, sledované stránky apod. Potvrďte, že to opravdu chcete udělat a že odemknete databázi hned po opravách.',
+'unlockdbtext'  => ' Pokud odemknete databázi, umožníte ostatním editovat, upravovat nastavení, sledované stránky apod. Potvrďte, že to opravdu chcete udělat.',
+'lockconfirm'   => 'Ano, opravdu chci zamknout databázi.',
+'unlockconfirm' => 'Ano, opravdu chci odemknout databázi.',
+'lockbtn'               => 'Zamknout databázi',
+'unlockbtn'             => 'Odemknout databázi',
+'locknoconfirm' => 'Nebylo zaškrtnuto políčko potvrzení.',
+'lockdbsuccesssub' => 'Databáze uzamčena',
+'unlockdbsuccesssub' => 'Databáze odemčena',
+'lockdbsuccesstext' => 'Databáze {{grammar:2sg|{{SITENAME}}}} byla úspěšně uzamčena.
+<br />Nezapomeňte ji po opravách odemknout.',
+'unlockdbsuccesstext' => 'Databáze {{grammar:2sg|{{SITENAME}}}} je odemčena.',
+
+# Make sysop
+'makesysoptitle'        => 'Učinit uživatele správcem',
+'makesysoptext'         => 'Tento formulář je používán byrokraty pro změnu obyčejného uživatele na správce. Vepište jméno uživatele do políčka a stiskněte tlačítko.',
+'makesysopname'         => 'Jméno uživatele:',
+'makesysopsubmit'       => 'Učinit tohoto uživatele správcem',
+'makesysopok'          => '<b>Uživatel „$1“ nyní patří mezi správce</b>',
+'makesysopfail'                => '<b>Uživatel „$1“ nemůže být učiněn správcem. (Vložili jste jeho jméno správně?)</b>',
+'setbureaucratflag' => 'Nastavit příznak byrokrata',
+'setstewardflag'    => 'Nastavit příznak stevarda',
+'bureaucratlog'                => 'Kniha_byrokratů',
+'rightslogtext'                => 'Toto je záznam změn uživatelských oprávnění.',
+'bureaucratlogentry'   => 'Oprávnění pro uživatele „$1“ nastavena na „$2“.',
+'rights'                       => 'Oprávnění:',
+'set_user_rights'      => 'Nastavit uživatelova oprávnění',
+'user_rights_set'      => '<b>Uživatelova práva k „$1“ aktualizována</b>',
+'set_rights_fail'      => '<b>Uživatelova práva k „$1“ nemohla být nastavena. (Vložili jste jeho jméno správně?)</b>',
+'makesysop'         => 'Učinit uživatele správcem',
+'already_sysop'     => 'Tento uživatel už je správce.',
+'already_bureaucrat' => 'Tento uživatel už je byrokrat.',
+'already_steward'   => 'Tento uživatel už je stevard.',
+
+# Validation
+'val_yes' => 'Ano',
+'val_no' => 'Ne',
+'val_of' => '$1 z $2',
+'val_revision' => 'Verze',
+'val_time' => 'Čas',
+'val_user_stats_title' => 'Přehled hodnocení od uživatele $1',
+'val_my_stats_title' => 'Přehled mého hodnocení',
+'val_list_header' => '<th>#</th><th>Téma</th><th>Rozsah</th><th>Činnost</th>',
+'val_add' => 'Přidat',
+'val_del' => 'Smazat',
+'val_show_my_ratings' => 'Zobrazit moje hodnocení',
+'val_revision_number' => 'Revize #$1',
+'val_warning' => '<b><i>Absolutně</i> nikdy tady nic neměňte bez <i>výslovné</i> shody v komunitě!</b>',
+'val_rev_for' => 'Verze ',
+'val_details_th_user' => 'Uživatel $1',
+'val_validation_of' => 'Hodnocení stránky „$1“',
+'val_revision_of' => 'Verze $1',
+'val_revision_changes_ok' => 'Vaše hodnocení bylo uloženo!',
+'val_revision_stats_link' => '(<a href="$1">podrobnosti</a>)',
+'val_iamsure' => 'Jste si opravdu jisti?',
+'val_clear_old' => 'Smazat moje starší hodnocení',
+'val_merge_old' => 'Použít moje předchozí hodnocení tam, kde jsem zvolil „Bez názoru“',
+'val_form_note' => '<b>Rada:</b> Sloučení údajů znamená, že zvolené verze článku,
+které jsou označeny jako <i>bez názoru</i>, budou nastaveny na hodnotu a komentář
+nejnovější verze, pro kterou jste názor vyjádřil(a). Pokud například chcete
+změnit v nové verzi jedinou hodnotu, ale ostatní chcete ponechat, vyberte
+pouze tu hodnotu, kterou chcete <i>změnit</i>. Sloučením se vyplní ostatní
+hodnoty jejich předešlým nastavením.',
+'val_noop' => 'Bez názoru',
+'val_percent' => '<b>$1%</b><br />($2 / $3 bodů<br />$4 uživatelů)',                        #TODO: plural
+'val_percent_single' => '<b>$1%</b><br />($2 / $3 bodů<br />jeden uživatel)',        #TODO: plural
+'val_total' => 'Celkem',
+'val_version' => 'Verze',
+'val_tab' => 'Hodnocení',
+'val_this_is_current_version' => 'toto je nejnovější verze',
+'val_version_of' => 'Verze z $1',
+'val_table_header' => "<tr><th>Třída</th>$1<th colspan=4>Názor</th>$1<th>Komentář</th></tr>\n",
+'val_stat_link_text' => 'Statistiky hodnocení tohoto článku',
+'val_view_version' => 'Prohlédnout tuto verzi',
+'val_validate_version' => 'Hodnotit tuto verzi',
+'val_user_validations' => 'Tento uživatel zhodnotil $1 stran.',                                       #TODO: plural
+'val_no_anon_validation' => 'Pro hodnocení článků musíte být přihlášen(a).',
+'val_validate_article_namespace_only' => 'Hodnotit lze pouze články. Tato stránka <i>není</i> ve jmenném prostoru článků.',
+'val_validated' => 'Hodnocení uloženo.',
+'val_article_lists' => 'Seznam zhodnocených článků',
+'val_page_validation_statistics' => 'Statistiky hodnocení pro $1',
+
+# Move page
+#
+'movepage'              => 'Přesunout stránku',
+'movepagetext'  => 'Pomocí tohoto formuláře změníte název stránky a přesunete i celou její historii pod nový název. Původní název se stane přesměrováním na nový název. Odkazy na předchozí název <i>nebudou</i> změněny. <b>VAROVÁNÍ!</b> Toto může drastická a nečekaná změna pro oblíbené stránky. Ujistěte se, prosím, že chápete důsledky vašeho kroku před tím, než změnu provedete.',
+'movepagetalktext' => "Přidružená diskusní stránka, pokud existuje, bude automaticky přesunuta společně se stránkou, '''pokud:'''
+* Nepřesouváte stránku napříč jmennými prostory,
+* Již neexistuje neprázdná diskusní stránka pod novým jménem, nebo
+* Nezrušíte křížek ve formuláři.
+
+V těchto případech musíte přesunout nebo sloučit stránky manuálně, jestliže si to přejete.",
+'movearticle'   => 'Přesunout stránku',
+'movenologin' => 'Nejste přihlášen(a)!',
+'movenologintext'       => 'Pro přesouvání stránek se musíte [[Special:Userlogin|přihlásit]].',
+'newtitle'              => 'Na nový název',
+'movepagebtn'   => 'Přesunout stránku',
+'pagemovedsub'  => 'Úspěšně přesunuto',
+'pagemovedtext' => "Stránka „[[$1]]“ přesunuta na „[[$2]]“.
+
+'''Nyní''' následujte odkaz [[Speciální:Whatlinkshere/$1]]: pokud se v seznamu vyskytnou nějaké přesměrovače, je třeba je upravit tak, aby ukazovaly na nový název ($2), jinak nebudou fungovat.",
+'articleexists' => 'Takto nazvaná stránka již existuje, nebo Vámi zvolený název je neplatný. Zvolte jiný název.',
+'talkexists'   => 'Stránka byla přesunuta úspěšně, ale diskusní stránka přesunuta být nemohla, neboť pod novým názvem již nějaká stránka existuje. Proveďte prosím ruční sloučení.',
+'movedto'               => 'přesunuto na',
+'movetalk'              => 'Přesunout také diskusní stránku, existuje-li.',
+'talkpagemoved' => 'Diskusní stránka byla také přesunuta.',
+'talkpagenotmoved' => 'Diskusní stránka <strong>nebyla</strong> přesunuta.',
+'1movedto2'             => 'Stránka [[$1]] přemístěna na stránku [[$2]]',
+'1movedto2_redir' => 'Stránka [[$1]] přemístěna na stránku [[$2]] s výměnou přesměrování',
+'movelogpage' => 'Kniha přesunů',
+'movelogpagetext' => 'Toto je záznam všech přesunů stránek.',
+'movereason'   => 'Důvod',
+'revertmove'   => 'vrátit',
+'delete_and_move' => 'Smazat a přesunout',
+'delete_and_move_text' =>
+'==Je potřeba smazání==
+
+Cílová stránka „[[$1]]“ již existuje. Přejete si ji smazat pro uvolnění místa pro přesun?',
+'delete_and_move_reason' => 'Smazáno pro umožnění přesunu',
+'selfmove' => 'Původní a nový název jsou stejné; nelze stránku přesunout na sebe samu.',
+'immobile_namespace' => 'Nový název je speciálního druhu; do tohoto jmenného prostoru nelze stránky přesouvat.',
+
+# Export
+
+'export'                => 'Exportovat stránky',
+'exporttext'    => 'Můžete exportovat text a historii editací některé stránky nebo sady stránek zabalené v XML; to může být importováno do jiné wiki, která běží na software MediaWiki, tranformováno nebo jen uschováno pro vaši soukromou potřebu.',
+'exportcuronly' => 'Zahrnout jen současnou verzi, ne plnou historii',
+
+# Namespace 8 related
+
+'allmessages'   => 'Všechna systémová hlášení',
+'allmessagesname' => 'Označení hlášení',
+'allmessagesdefault' => 'Původní text',
+'allmessagescurrent' => 'Aktuální text',
+'allmessagestext'       => 'Toto je seznam všech hlášení dostupných ve jmenném prostoru MediaWiki.',
+'allmessagesnotsupportedUI' => 'Váš aktuální jazyk rozhraní <b>$1</b> není na tomto serveru pro {{ns:-1}}:AllMessages podporován.',
+'allmessagesnotsupportedDB' => '{{ns:-1}}:AllMessages není podporováno, neboť wgUseDatabaseMessages je vypnuto.',
+
+# Thumbnails
+
+'thumbnail-more'        => 'Zvětšit',
+'missingimage'          => "<b>Chybějící obrázek</b><br /><i>$1</i>\n",
+'filemissing'          => 'Chybějící soubor',
+
+# Special:Import
+'import'        => 'Importovat stránky',
+'importtext'    => 'Prosím exportujte soubor ze zdrojové wiki pomocí nástroje {{ns:-1}}:Export, uložte ji na svůj disk a nahrajte ji sem.',
+'importfailed'  => 'Import selhal: $1',
+'importnotext'  => 'Prázdný nebo žádný text',
+'importsuccess' => 'Import byl úspěšný!',
+'importhistoryconflict' => 'Existuje konflikt mezi historiemi verzí. Možná, že tato stránka byla již importována dříve.',
+
+# Keyboard access keys for power users
+'accesskey-search' => 'f',
+'accesskey-minoredit' => 'i',
+'accesskey-save' => 's',
+'accesskey-preview' => 'p',
+'accesskey-diff' => 'd',
+'accesskey-compareselectedversions' => 'v',
+
+# tooltip help for some actions, most are in Monobook.js
+'tooltip-search' => 'Hledat na této wiki [alt-f]',
+'tooltip-minoredit' => 'Označit jako malou editaci [alt-i]',
+'tooltip-save' => 'Uložit vaše úpravy [alt-s]',
+'tooltip-preview' => 'Prohlédnout vaše úpravy, prosíme použijte tuto funkci před uložením! [alt-p]',
+'tooltip-diff' => 'Zobrazit, jaké změny jste v textu provedli. [alt-d]',
+'tooltip-compareselectedversions' => 'Porovnat rozdíly mezi zvolenými verzemi této stránky. [alt-v]',
+'tooltip-watch' => 'Přidat stránku do seznamu sledovaných [alt-w]',
+
+# stylesheets
+
+'Monobook.css' => '/* editací tohoto souboru upravíte styl "monobook" pro celou {{grammar:4sg|{{SITENAME}}}} */',
+
+# Metadata
+'nodublincore' => 'Na tomto serveru je vypnuto generování metadat Dublin Core RDF.',
+'nocreativecommons' => 'Na tomto server je vypnuto generování metadat Creative Commons RDF.',
+'notacceptable' => 'Tento wiki server není schopen poskytnout data ve formátu, který by váš klient byl schopen přečíst.',
+
+# Attribution
+
+'anonymous' => "Anonymní uživatel(é) {{SITENAME}}",
+'siteuser' => "Uživatel {{SITENAME}} $1",
+'lastmodifiedby' => 'Tuto stránku naposledy měnil $2 v $1.',
+'and' => 'a',
+'othercontribs' => 'Založeno na textu od uživatele $1.',
+'others' => 'další',
+'siteusers' => "Uživatel(é) {{SITENAME}} $1",
+'creditspage' => 'Zásluhy za stránku',
+'nocredits' => 'K této stránce neexistuje informace o zásluhách.',
+
+# Spam protection
+
+'spamprotectiontitle' => 'Spam protection filter',
+'spamprotectiontext' => 'Stránka, kterou jste se pokusil(a) uložit, byla zablokována protispamovým filtrem. Pravděpodobnou příčinou je odkaz na externí stránky. Může vás zajímat následující regulární výraz, který označuje v současné době blokované stránky:',
+'spamprotectionmatch' => 'Následující text spustil náš filtr proti spamu: $1',
+
+# Categories
+
+'subcategorycount' => 'Počet podkategorií v této kategorii: $1',
+'subcategorycount1' => 'V této kategorii je $1 podkategorie.',
+'categoryarticlecount' => 'Počet článků v této kategorii: $1',
+'categoryarticlecount1' => 'V této kategorii je $1 článek.',
+'usenewcategorypage' => "1\n\nK vypnutí nového vzhledu stránek kategorií nastavte první znak na '0'.",
+'listingcontinuesabbrev' => 'pokrač.',
+
+# Info page
+'infosubtitle' => 'Informace o stránce',
+'numedits' => 'Počet editací (článek): ',
+'numtalkedits' => 'Počet editací (diskusní stránka): ',
+'numwatchers' => 'Počet sledujících uživatelů: ',
+'numauthors' => 'Počet různých autorů (článek): ',
+'numtalkauthors' => 'Počet rozdílných autorů (diskusní stránka): ',
+
+# Math options
+'mw_math_png' => 'Vždy jako PNG',
+'mw_math_simple' => 'Jednoduché jako HTML, jinak PNG',
+'mw_math_html' => 'HTML pokud je to možné, jinak PNG',
+'mw_math_source' => 'Ponechat jako TeX (pro textové prohlížeče)',
+'mw_math_modern' => 'Doporučené nastavení pro moderní prohlížeče',
+'mw_math_mathml' => 'MathML pokud je podporováno (experimentální)',
+
+# Patrolling
+'markaspatrolleddiff'   => 'Označit jako prověřené',
+'markaspatrolledlink'   => '<div class="patrollink">[$1]</div>',
+'markaspatrolledtext'   => 'Označit tento článek jako prověřený',
+'markedaspatrolled'     => 'Označeno jako prověřené',
+'markedaspatrolledtext' => 'Vybraná verze byla označena jako prověřená.',
+'rcpatroldisabled'      => 'Hlídka posledních změn vypnuta',
+'rcpatroldisabledtext'  => 'Hlídka posledních změn je momentálně vypnuta.',
+
+# Monobook.js: tooltips and access keys for monobook
+'Monobook.js' => "/* tooltips and access keys */
+ta = new Object();
+ta['pt-userpage'] = new Array('.','Moje uživatelská stránka');
+ta['pt-anonuserpage'] = new Array('.','Uživatelská stránka pro IP adresu, ze které editujete');
+ta['pt-mytalk'] = new Array('n','Moje diskusní stránka');
+ta['pt-anontalk'] = new Array('n','Diskuse o editacích provedených z této IP adresy');
+ta['pt-preferences'] = new Array('','Moje preference');
+ta['pt-watchlist'] = new Array('l','Seznam stránek, jejichž změny sleduji');
+ta['pt-mycontris'] = new Array('y','Seznam mých příspěvků');
+ta['pt-login'] = new Array('o','Doporučujeme vám přihlásit se, ovšem není to povinné.');
+ta['pt-anonlogin'] = new Array('o','Doporučujeme vám přihlásit se, ovšem není to povinné.');
+ta['pt-logout'] = new Array('o','Odhlásit se');
+ta['ca-talk'] = new Array('t','Diskuse ke stránce');
+ta['ca-edit'] = new Array('e','Tuto stránku můžete editovat. Prosíme použijte tlačítko Ukázat náhled před uložením.');
+ta['ca-addsection'] = new Array('+','Přidat k této diskusi svůj komentář.');
+ta['ca-viewsource'] = new Array('e','Tato stránka je zamčena. Můžete si prohlédnout její zdrojový kód.');
+ta['ca-history'] = new Array('h','Starší verze této stránky.');
+ta['ca-protect'] = new Array('=','Zamknout tuto stránku.');
+ta['ca-delete'] = new Array('d','Smazat tuto stránku.');
+ta['ca-undelete'] = new Array('d','Obnovit editace této stránky provedené před jejím smazáním.');
+ta['ca-move'] = new Array('m','Přesunout tuto stránku');
+ta['ca-watch'] = new Array('w','Přidat tuto stránku mezi sledované');
+ta['ca-unwatch'] = new Array('w','Vyjmout tuto stránku ze sledovaných');
+ta['search'] = new Array('f','Hledat na této wiki');
+ta['p-logo'] = new Array('','Hlavní strana');
+ta['n-mainpage'] = new Array('z','Navštívit Hlavní stranu');
+ta['n-portal'] = new Array('','O projektu, jak můžete pomoci, kde hledat');
+ta['n-currentevents'] = new Array('','Informace o aktuálních událostech');
+ta['n-recentchanges'] = new Array('r','Seznam posledních změn na této wiki');
+ta['n-randompage'] = new Array('x','Přejít na náhodně vybranou stránku');
+ta['n-help'] = new Array('','Místo, kde najdete pomoc');
+ta['n-sitesupport'] = new Array('','Podpořte nás');
+ta['t-whatlinkshere'] = new Array('j','Seznam všech wikistránek, které sem odkazují');
+ta['t-recentchangeslinked'] = new Array('k','Nedávné změny stránek, které sem odkazují');
+ta['feed-rss'] = new Array('','RSS kanál pro tuto stránku');
+ta['feed-atom'] = new Array('','Atom kanál pro tuto stránku');
+ta['t-contributions'] = new Array('','Prohlédnout si seznam příspěvků tohoto uživatele');
+ta['t-emailuser'] = new Array('','Poslat e-mail tomuto uživateli');
+ta['t-upload'] = new Array('u','Nahrát obrázky či jiná multimédia');
+ta['t-specialpages'] = new Array('q','Seznam všech speciálních stránek');
+ta['ca-nstab-main'] = new Array('c','Zobrazit článek');
+ta['ca-nstab-user'] = new Array('c','Zobrazit uživatelovu stránku');
+ta['ca-nstab-media'] = new Array('c','Zobrazit stránku souboru');
+ta['ca-nstab-special'] = new Array('','Toto je speciální stránka, kterou nelze editovat.');
+ta['ca-nstab-wp'] = new Array('a','Zobrazit stránku o wiki.');
+ta['ca-nstab-image'] = new Array('c','Zobrazit stránku obrázku.');
+ta['ca-nstab-mediawiki'] = new Array('c','Zobrazit systémovou zprávu.');
+ta['ca-nstab-template'] = new Array('c','Zobrazit šablonu.');
+ta['ca-nstab-help'] = new Array('c','Zobrazit stránku nápovědy.');
+ta['ca-nstab-category'] = new Array('c','Zobrazit kategorii.');",
+
+# preferences
+'tog-underline'                 => 'Podtrhnout odkazy',
+'tog-highlightbroken'           => 'Formátovat odkazy na neexistující články <a href="#" class="new">takto</a> (alternativa: takto<a href="#" class="broken">?</a>).',
+'tog-justify'                   => 'Zarovnat odstavce do bloku',
+'tog-hideminor'                 => 'Skrýt malé editace v posledních změnách',
+'tog-usenewrc'                  => 'Zdokonalené poslední změny (JavaScript)',
+'tog-numberheadings'            => 'Automaticky číslovat nadpisy',
+'tog-showtoolbar'               => 'Ukázat lištu s nástroji při editaci',
+'tog-editondblclick'            => 'Editovat dvojklikem (JavaScript)',
+'tog-editsection'               => 'Zapnout možnost editace části článku pomocí odkazu [editovat]',
+'tog-editsectiononrightclick'   => 'Zapnout možnost editace části článku pomocí kliknutí pravým tlačítkem na nadpisy v článku (JavaScript)',
+'tog-showtoc'                   => 'Ukázat obsah článku (pokud má článek více než tři nadpisy)',
+'tog-rememberpassword'          => 'Pamatovat si mé heslo mezi návštěvami',
+'tog-editwidth'                 => 'Roztáhnout editační okno na celou šířku',
+'tog-watchdefault'              => 'Přidat editace ke sledovaným článkům',
+'tog-minordefault'              => 'Označit editaci implicitně jako malá editace',
+'tog-previewontop'              => 'Zobrazovat náhled před editačním oknem (ne za ním)',
+'tog-previewonfirst'                   => 'Zobrazit při první editaci náhled',
+'tog-nocache'                   => 'Nepoužívat cache',
+'tog-fancysig'                 => 'Neupravovat podpis (nevkládat automaticky odkaz)',
+'tog-enotifwatchlistpages'             => 'Poslat e-mail při změnách stránky (poznámka: existující příznaky musí být v seznamu sledovaných odstraněny ručně)',
+'tog-enotifusertalkpages'              => 'Poslat e-mail při změnách mé diskusní stránky (poznámka: existující příznaky musí být v seznamu sledovaných odstraněny ručně)',
+'tog-enotifminoredits'                         => 'Poslat e-mail i pro menší editace (které jinak nezpůsobují odeslání e-mailu)',
+'tog-enotifrevealaddr'                         => 'Prozradit mou e-mailovou adresu v upozorňujících e-mailech (při mých změnách to umožňuje sledujícím uživatelům rychle mi odpovědět)',
+'tog-shownumberswatching'              => 'Zobrazovat počet sledujících uživatelů (v posledních změnách, sledovaných stránkách a patičkách stránek',
+'tog-externaleditor'                   => 'Implicitně používat externí editor',
+'tog-externaldiff'                             => 'Implicitně používat externí porovnávací program',
+
+# image deletion
+'deletedrevision' => 'Smazána stará verze $1.',
+
+# browsing diffs
+'previousdiff' => '← Předchozí porovnání',
+'nextdiff' => 'Následující porovnání →',
+
+'imagemaxsize' => 'Omezit obrázky na stránkách s popiskem na: ',
+'thumbsize'    => 'Velikost náhledu: ',
+'showbigimage' => 'Stáhnout verzi s vysokým rozlišením ($1&times;$2, $3 KB)',
+
+'newimages' => 'Galerie nových obrázků',
+'noimages'  => 'Není co zobrazit.',
+
+'passwordtooshort' => 'Vaše heslo je příliš krátké. Musí obsahovat nejméně $1 znaků.', #TODO: plural
+
+# Media Warning
+'mediawarning' => '\'\'\'Upozornění\'\'\': Tento soubor může obsahovat škodlivý kód, spuštěním můžete ohrozit svůj počítač.<hr>',
+
+'fileinfo' => '$1 KB, MIME typ: <code>$2</code>',
+
+# Metadata
+'metadata' => 'Metadata',
+
+# Exif tags
+# TODO: zkontrolovat překlad, profesionální fotograf/grafik by bodnul
+'exif-imagewidth' =>'Šířka',
+'exif-imagelength' =>'Výška',
+'exif-bitspersample' =>'Bitů na složku',
+'exif-compression' =>'Druh komprese',
+'exif-photometricinterpretation' =>'Barevný prostor',
+'exif-orientation' =>'Orientace',
+'exif-samplesperpixel' =>'Počet složek',
+'exif-planarconfiguration' =>'Uspořádání dat',
+'exif-ycbcrsubsampling' =>'Poměr podvzorkování Y ku C',
+'exif-ycbcrpositioning' =>'Umístění Y a C',
+'exif-xresolution' =>'Rozlišení obrázku na šířku',
+'exif-yresolution' =>'Rozlišení obrázku na výšku',
+'exif-resolutionunit' =>'Jednotky rozlišení',
+'exif-stripoffsets' =>'Umístění dat obrázku',
+'exif-rowsperstrip' =>'Počet řádků na pás',
+'exif-stripbytecounts' =>'Počet bajtů na komprimovaný pás',
+'exif-jpeginterchangeformat' =>'Ofset k JPEG SOI',
+'exif-jpeginterchangeformatlength' =>'Počet bajtů JPEG dat',
+'exif-transferfunction' =>'Přenosová funkce',
+'exif-whitepoint' =>'Chroma bílého bodu',
+'exif-primarychromaticities' =>'Chroma primárních barev',
+'exif-ycbcrcoefficients' =>'Koeficienty matice pro transformaci barevných prostorů',
+'exif-referenceblackwhite' =>'Světlost referenčního černého a bílého bodu',
+'exif-datetime' =>'Datum a čas vytvoření obrázku',
+'exif-imagedescription' =>'Název obrázku',
+'exif-make' =>'Značka fotoaparátu',
+'exif-model' =>'Model fotoaparátu',
+'exif-software' =>'Použitý software',
+'exif-artist' =>'Autor',
+'exif-copyright' =>'Držitel autorských práv',
+'exif-exifversion' =>'Verze Exif',
+'exif-flashpixversion' =>'Podporovaná verze Flashpix',
+'exif-colorspace' =>'Barevný prostor',
+'exif-componentsconfiguration' =>'Význam jednotlivých složek',
+'exif-compressedbitsperpixel' =>'Komprimační režim',
+'exif-pixelydimension' =>'Platná šířka obrazu',
+'exif-pixelxdimension' =>'Platná výška obrazu',
+'exif-makernote' =>'Poznámky výrobce',
+'exif-usercomment' =>'Uživatelské poznámky',
+'exif-relatedsoundfile' =>'Související zvukový soubor',
+'exif-datetimeoriginal' =>'Datum a čas pořízení obrázku',
+'exif-datetimedigitized' =>'Datum a čas digitalizace',
+'exif-subsectime' =>'zlomky sekundy pro DateTime',
+'exif-subsectimeoriginal' =>'zlomky sekundy pro DateTimeOriginal',
+'exif-subsectimedigitized' =>'zlomky sekundy pro DateTimeDigitized',
+'exif-exposuretime' =>'Expozice',
+'exif-fnumber' =>'Clona',
+'exif-exposureprogram' =>'Expoziční program',
+'exif-spectralsensitivity' =>'Spektrální citlivost',
+'exif-isospeedratings' =>'Nastavení ISO citlivosti',
+'exif-oecf' =>'Optoelectronická převodní funkce (OECF)',
+'exif-shutterspeedvalue' =>'Rychlost závěrky',
+'exif-aperturevalue' =>'Clona',
+'exif-brightnessvalue' =>'Světlost',
+'exif-exposurebiasvalue' =>'Změna expozice',
+'exif-maxaperturevalue' =>'Nejmenší clona',
+'exif-subjectdistance' =>'Vzdálenost k předmětu',
+'exif-meteringmode' =>'Způsob měření',
+'exif-lightsource' =>'Světelný zdroj',
+'exif-flash' =>'Blesk',
+'exif-focallength' =>'Ohnisková vzdálenost',
+'exif-subjectarea' =>'Umístění předmětu',
+'exif-flashenergy' =>'Výkon blesku',
+'exif-spatialfrequencyresponse' =>'Odezva prostorové frekvence',
+'exif-focalplanexresolution' =>'X rozlišení ohniskové roviny',
+'exif-focalplaneyresolution' =>'Y rozlišení ohniskové roviny',
+'exif-focalplaneresolutionunit' =>'Jednotka rozlišení ohniskové roviny',
+'exif-subjectlocation' =>'Umístění předmětu',
+'exif-exposureindex' =>'Expoziční index',
+'exif-sensingmethod' =>'Senzor',
+'exif-filesource' =>'Zdroj souboru',
+'exif-scenetype' =>'Druh scény',
+'exif-cfapattern' =>'Geometrické uspořádání senzoru',
+'exif-customrendered' =>'Uživatelské zpracování',
+'exif-exposuremode' =>'Expoziční režim',
+'exif-whitebalance' =>'Vyvážení bílé',
+'exif-digitalzoomratio' =>'Digitální zoom',
+'exif-focallengthin35mmfilm' =>'Ekvivalent ohniskové délky pro 35mm film',
+'exif-scenecapturetype' =>'Druh scény',
+'exif-gaincontrol' =>'Úprava světlosti',
+'exif-contrast' =>'Kontrast',
+'exif-saturation' =>'Sytost',
+'exif-sharpness' =>'Ostrost',
+'exif-devicesettingdescription' =>'Popis nastavení zařízení',
+'exif-subjectdistancerange' =>'Vzdálenost k předmětu',
+'exif-imageuniqueid' =>'Unikátní ID obrázku',
+'exif-gpsversionid' =>'Verze GPS tagu',
+'exif-gpslatituderef' =>'Severní/jižní zeměpisná šířka',
+'exif-gpslatitude' =>'Zeměpisná šířka',
+'exif-gpslongituderef' =>'Východní/západní zeměpisná délka',
+'exif-gpslongitude' =>'Zeměpisná délka',
+'exif-gpsaltituderef' =>'Nad/podmořská výška/hloubka',
+'exif-gpsaltitude' =>'Nadmořská výška',
+'exif-gpstimestamp' =>'GPS čas (podle atomových hodin)',
+'exif-gpssatellites' =>'Satelity použité pro měření',
+'exif-gpsstatus' =>'Stav přijímače',
+'exif-gpsmeasuremode' =>'Režim měření',
+'exif-gpsdop' =>'Přesnost měření',
+'exif-gpsspeedref' =>'Jednotka rychlosti',
+'exif-gpsspeed' =>'Rychlost GPS přijímače',
+'exif-gpstrackref' =>'Reference pro směr pohybu',
+'exif-gpstrack' =>'Směr pohybu',
+'exif-gpsimgdirectionref' =>'Reference pro orientaci obrázku',
+'exif-gpsimgdirection' =>'Orientace obrázku',
+'exif-gpsmapdatum' =>'Použitý geodetický systém',
+'exif-gpsdestlatituderef' =>'Severní/jižní zeměpisná šířka předmětu',
+'exif-gpsdestlatitude' =>'Zeměpisná šířka předmětu',
+'exif-gpsdestlongituderef' =>'Východní/západní zeměpisná délka předmětu',
+'exif-gpsdestlongitude' =>'Zeměpisná délka předmětu',
+'exif-gpsdestbearingref' =>'Reference pro směr k předmětu',
+'exif-gpsdestbearing' =>'Směr k předmětu',
+'exif-gpsdestdistanceref' =>'Jednotka vzdálenosti k předmětu',
+'exif-gpsdestdistance' =>'Vzdálenost k předmětu',
+'exif-gpsprocessingmethod' =>'Označení metody zpracování GPS dat',
+'exif-gpsareainformation' =>'Označení GPS oblasti',
+'exif-gpsdatestamp' =>'Datum podle GPS',
+'exif-gpsdifferential' =>'Diferenciální korekce GPS',
+
+# Make & model, can be wikified in order to link to the camera and model name
+
+'exif-make-value' => '$1',
+'exif-model-value' =>'$1',
+'exif-software-value' => '$1',
+
+# Exif attributes
+
+'exif-compression-1' => 'Nekomprimovaný',
+'exif-compression-6' => 'JPEG',
+
+'exif-photometricinterpretation-1' => 'RGB',
+'exif-photometricinterpretation-6' => 'YCbCr',
+
+'exif-orientation-1' => 'Normální', // 0th row: top; 0th column: left
+'exif-orientation-2' => 'Vodorovně převráceno', // 0th row: top; 0th column: right
+'exif-orientation-3' => 'Otočeno o 180°', // 0th row: bottom; 0th column: right
+'exif-orientation-4' => 'Svisle převráceno', // 0th row: bottom; 0th column: left
+'exif-orientation-5' => 'Otočeno o 90° proti směru hodinových ručiček a svisle převráceno', // 0th row: left; 0th column: top
+'exif-orientation-6' => 'Otočeno o 90° ve směru hodinových ručiček', // 0th row: right; 0th column: top
+'exif-orientation-7' => 'Otočeno o 90° ve směru hodinových ručiček a svisle převráceno', // 0th row: right; 0th column: bottom
+'exif-orientation-8' => 'Otočeno o 90° proti směru hodinových ručiček', // 0th row: left; 0th column: bottom
+
+'exif-planarconfiguration-1' => 'chunky',
+'exif-planarconfiguration-2' => 'planar',
+
+'exif-colorspace-1' => 'sRGB',
+'exif-colorspace-ffff.h' => 'FFFF.H',
+
+'exif-componentsconfiguration-0' => 'neexistuje',
+'exif-componentsconfiguration-1' => 'Y',
+'exif-componentsconfiguration-2' => 'Cb',
+'exif-componentsconfiguration-3' => 'Cr',
+'exif-componentsconfiguration-4' => 'R',
+'exif-componentsconfiguration-5' => 'G',
+'exif-componentsconfiguration-6' => 'B',
+
+'exif-exposureprogram-0' => 'Neuvedeno',
+'exif-exposureprogram-1' => 'Ruční',
+'exif-exposureprogram-2' => 'Normální',
+'exif-exposureprogram-3' => 'Priorita clony',
+'exif-exposureprogram-4' => 'Priorita závěrky',
+'exif-exposureprogram-5' => 'Kreativní (lepší hloubka ostrosti)',
+'exif-exposureprogram-6' => 'Akce (rychlejší závěrka)',
+'exif-exposureprogram-7' => 'Portrét (detailní fotografie s neostrým pozadím)',
+'exif-exposureprogram-8' => 'Krajina (fotografie krajiny s ostrým pozadím)',
+
+'exif-meteringmode-0' => 'Není známo',
+'exif-meteringmode-1' => 'Průměrové',
+'exif-meteringmode-2' => 'Vážený průměr',
+'exif-meteringmode-3' => 'Bodové',
+'exif-meteringmode-4' => 'Zónové',
+'exif-meteringmode-5' => 'Vzorové',
+'exif-meteringmode-6' => 'Částečné',
+'exif-meteringmode-255' => 'Jiné',
+
+'exif-lightsource-0' => 'Není známo',
+'exif-lightsource-1' => 'Denní světlo',
+'exif-lightsource-2' => 'Fluorescentní',
+'exif-lightsource-3' => 'Žárovka',
+'exif-lightsource-4' => 'Blesk',
+'exif-lightsource-9' => 'Jasno',
+'exif-lightsource-10' => 'Zamračeno',
+'exif-lightsource-11' => 'Stín',
+'exif-lightsource-12' => 'Zářivka denní světlo (D 5700 – 7100K)',
+'exif-lightsource-13' => 'Zářivka bílé denní světlo (N 4600 – 5400K)',
+'exif-lightsource-14' => 'Zářivka studená bílá (W 3900 – 4500K)',
+'exif-lightsource-15' => 'Bílá zářivka (WW 3200 – 3700K)',
+'exif-lightsource-17' => 'Standardní osvětlení A',
+'exif-lightsource-18' => 'Standardní osvětlení B',
+'exif-lightsource-19' => 'Standardní osvětlení C',
+'exif-lightsource-20' => 'D55',
+'exif-lightsource-21' => 'D65',
+'exif-lightsource-22' => 'D75',
+'exif-lightsource-23' => 'D50',
+'exif-lightsource-24' => 'ISO studiová žárovka',
+'exif-lightsource-255' => 'Jiný světelný zdroj',
+
+'exif-sensingmethod-1' => 'Není známo',
+'exif-sensingmethod-2' => 'Jednočipový plošný senzor',
+'exif-sensingmethod-3' => 'Dvoučipový plošný senzor',
+'exif-sensingmethod-4' => 'Tříčipový plošný senzor',
+'exif-sensingmethod-5' => 'Sekvenční plošný senzor',
+'exif-sensingmethod-7' => 'Trilineární senzor',
+'exif-sensingmethod-8' => 'Sekvenční lineární senzor',
+
+'exif-filesource-3' => 'Digitální fotoaparát',
+
+'exif-scenetype-1' => 'Přímo fotografováno',
+
+'exif-customrendered-0' => 'Běžné zpracování',
+'exif-customrendered-1' => 'Uživatelské zpracování',
+
+'exif-exposuremode-0' => 'Automatická expozice',
+'exif-exposuremode-1' => 'Ruční expozice',
+'exif-exposuremode-2' => 'Bracketing',
+
+'exif-whitebalance-0' => 'Automatické vyvážení bílé',
+'exif-whitebalance-1' => 'Ruční vyvážení bílé',
+
+'exif-scenecapturetype-0' => 'Standardní',
+'exif-scenecapturetype-1' => 'Na šířku',            # TODO: ?? portrét/krajina, nebo na šířku/na výšku -- co ta noční scéna?
+'exif-scenecapturetype-2' => 'Na výšku',
+'exif-scenecapturetype-3' => 'Noční scéna',
+
+'exif-gaincontrol-0' => 'Žádná',
+'exif-gaincontrol-1' => 'Mírné zvýšení jasu',
+'exif-gaincontrol-2' => 'Výrazné zvýšení jasu',
+'exif-gaincontrol-3' => 'Mírné snížení jasu',
+'exif-gaincontrol-4' => 'Výrazné snížení jasu',
+
+'exif-contrast-0' => 'Normální',
+'exif-contrast-1' => 'Měkký',
+'exif-contrast-2' => 'Tvrdý',
+
+'exif-saturation-0' => 'Normální',
+'exif-saturation-1' => 'Nízká sytost',
+'exif-saturation-2' => 'Vysoká sytost',
+
+'exif-sharpness-0' => 'Normální',
+'exif-sharpness-1' => 'Měkká',
+'exif-sharpness-2' => 'Tvrdá',
+
+'exif-subjectdistancerange-0' => 'Není známo',
+'exif-subjectdistancerange-1' => 'Makro',
+'exif-subjectdistancerange-2' => 'Detail',
+'exif-subjectdistancerange-3' => 'Pohled zdálky',
+
+// Pseudotags used for GPSLatitudeRef and GPSDestLatitudeRef
+'exif-gpslatitude-n' => 'Severní šířka',
+'exif-gpslatitude-s' => 'Jižní šířka',
+
+// Pseudotags used for GPSLongitudeRef and GPSDestLongitudeRef
+'exif-gpslongitude-e' => 'Východní délka',
+'exif-gpslongitude-w' => 'Západní délka',
+
+'exif-gpsstatus-a' => 'Probíhá měření',
+'exif-gpsstatus-v' => 'Měření mimo provoz',
+
+'exif-gpsmeasuremode-2' => 'Dvourozměrné měření',
+'exif-gpsmeasuremode-3' => 'Trojrozměrné měření',
+
+// Pseudotags used for GPSSpeedRef and GPSDestDistanceRef
+'exif-gpsspeed-k' => 'km/h',
+'exif-gpsspeed-m' => 'mph',
+'exif-gpsspeed-n' => 'kt',
+
+// Pseudotags used for GPSTrackRef, GPSImgDirectionRef and GPSDestBearingRef
+'exif-gpsdirection-t' => 'Pravý kurs',
+'exif-gpsdirection-m' => 'Magnetický kurs',
+
+# external editor support
+'edit-externally' => 'Editovat tento soubor v externím programu',
+'edit-externally-help' => 'Více informací najdete v [http://meta.wikimedia.org/wiki/Help:External_editors nápovědě pro nastavení].',
+
+# 'all' in various places, this might be different for inflicted languages
+'recentchangesall' => 'všechny',
+'imagelistall' => 'všechny',
+'watchlistall1' => 'všechny',
+'watchlistall2' => 'všechny',
+'namespacesall' => 'všechny',
+
+# E-mail address confirmation
+'confirmemail' => 'Potvrzení e-mailové adresy',
+'confirmemail_text' => 'Tato wiki vyžaduje, abyste potvrdili svou e-mailovou adresu
+před využíváním některých funkcí. Kliknutím na níže umístěné tlačítko dojde k odeslání
+potvrzovacího e-mailu na vámi uvedeno adresu. Tento mail obsahuje odkaz a potvrzovací kód;
+přejděte na odkazovanou stránku svým internatovým prohlížečem, tím potvrdíte, že
+zadaná adresa je platná.',
+'confirmemail_send' => 'Odeslat potvrzovací kód',
+'confirmemail_sent' => 'Potvrzovací e-mail byl odeslán',
+'confirmemail_sendfailed' => 'Nepodařilo se odeslat potvrzovací e-mail. Zkontrolujte, zda adresa neobsahuje chybné znaky.',
+'confirmemail_invalid' => 'Neplatný potvrzovací kód. Možná již vypršela platnost kódu.',
+'confirmemail_success' => 'Vaše e-mailová adresa byla potvrzena. Nyní se můžete přihlásit a používat wiki.',
+'confirmemail_loggedin' => 'Vaše e-mailová adresa byla potvrzena.',
+'confirmemail_error' => 'Nepodařilo se uložit vaše potvrzení.',
+
+'confirmemail_subject'  => 'Potvrzení e-mailové adresy pro {{grammar:4sg|{{SITENAME}}}}',
+'confirmemail_body' => 'Někdo (patrně vy, z IP adresy $1) si registroval účet se jménem "$2" a touto e-mailovou adresou na {{grammar:6sg|{{SITENAME}}}}.
+
+Pokud si přejete aktivovat e-mailové funkce na {{grammar:6sg|{{SITENAME}}}}, tak pro potvrzení,
+že tato adresa opravdu patří vám, přejděte svým internetovým prohlížečem na následující adresu:
+
+$3
+
+Pokud jste o toto potvrzení *nežádali*, neklikejte na předchozí odkaz. Platnost tohoto potvrzovacího
+kódu vyprší $4.',
+);
+
+#--------------------------------------------------------------------------
+# Internationalisation code
+#--------------------------------------------------------------------------
+
+class LanguageCs extends LanguageUtf8 {
+
+       function getBookstoreList () {
+               global $wgBookstoreListCs ;
+               return $wgBookstoreListCs ;
+       }
+
+       function getNamespaces() {
+               global $wgNamespaceNamesCs;
+               return $wgNamespaceNamesCs;
+       }
+
+       function getNsIndex( $text ) {
+               global $wgNamespaceNamesCs;
+
+               foreach ( $wgNamespaceNamesCs as $i => $n ) {
+                       if ( 0 == strcasecmp( $n, $text ) ) { return $i; }
+               }
+               return false;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsCs;
+               return $wgQuickbarSettingsCs;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesCs;
+               return $wgSkinNamesCs;
+       }
+
+       # Datové a časové funkce možno upřesnit podle jazyka
+       # TODO: Umožnit nastavování formátu data a času.
+       function date( $ts, $adj = false ) {
+               if ( $adj ) { $ts = $this->userAdjust( $ts ); }
+
+               $d = (0 + substr( $ts, 6, 2 )) . '. ' .
+               $this->getMonthAbbreviation( substr( $ts, 4, 2 ) ) .
+                 ' ' .
+                 substr( $ts, 0, 4 );
+               return $d;
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesCs;
+               if(array_key_exists($key, $wgAllMessagesCs))
+                       return $wgAllMessagesCs[$key];
+               else
+                       return parent::getMessage($key);
+       }
+
+       function getAllMessages() {
+               global $wgAllMessagesCs;
+               return $wgAllMessagesCs;
+       }
+
+       function checkTitleEncoding( $s ) {
+               global $wgInputEncoding;
+
+               # Check for non-UTF-8 URLs; assume they are WinLatin2
+               $ishigh = preg_match( '/[\x80-\xff]/', $s);
+               $isutf = ($ishigh ? preg_match( '/^([\x00-\x7f]|[\xc0-\xdf][\x80-\xbf]|' .
+               '[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xf7][\x80-\xbf]{3})+$/', $s ) : true );
+
+               if( $ishigh and !$isutf ) {
+                       return iconv( 'cp1250', 'utf-8', $s );
+       }
+
+               return $s;
+       }
+
+       var $digitTransTable = array(
+                       ',' => "\xc2\xa0", // @bug 2749
+                       '.' => ','
+       );
+
+       function formatNum( $number ) {
+               return strtr($number, $this->digitTransTable);
+       }
+
+               # Grammatical transformations, needed for inflected languages
+               # Invoked by putting {{grammar:case|word}} in a message
+               function convertGrammar( $word, $case ) {
+                       # allowed values for $case:
+                       #       1sg, 2sg, ..., 7sg -- nominative, genitive, ... (in singular)
+                       switch ( $word ) {
+                               case 'Wikipedia':
+                               case 'Wikipedie':
+                                       switch ( $case ) {
+                                               case '3sg':
+                                               case '4sg':
+                                               case '6sg':
+                                                       return 'Wikipedii';
+                                               case '7sg':
+                                                       return 'Wikipedií';
+                                               default:
+                                                       return 'Wikipedie';
+                                       }
+
+                               case 'Wiktionary':
+                               case 'Wikcionář':
+                                       switch ( $case ) {
+                                               case '2sg':
+                                                       return 'Wikcionáře';
+                                               case '3sg':
+                                               case '5sg';
+                                               case '6sg';
+                                                       return 'Wikcionáři';
+                                               case '7sg':
+                                                       return 'Wikcionářem';
+                                               default:
+                                                       return 'Wikcionář';
+                                       }
+
+                               case 'Wikiquote':
+                               case 'Wikicitáty':
+                                       switch ( $case ) {
+                                               case '2sg':
+                                                       return 'Wikicitátů';
+                                               case '3sg':
+                                                       return 'Wikicitátům';
+                                               case '6sg';
+                                                       return 'Wikicitátech';
+                                               default:
+                                                       return 'Wikicitáty';
+                                       }
+                       }
+                       # unknown
+                       return $word;
+               }
+}
+
+?>
diff --git a/languages/LanguageCsb.php b/languages/LanguageCsb.php
new file mode 100644 (file)
index 0000000..b245211
--- /dev/null
@@ -0,0 +1,351 @@
+<?php
+/**
+ * @package MediaWiki
+ * @subpackage Language
+ */
+
+$wgNamespaceNamesCsb = array(
+       NS_MEDIA            => 'Media',
+       NS_SPECIAL          => 'Specjalnô',
+       NS_MAIN             => '',
+       NS_TALK             => 'Diskùsëjô',
+       NS_USER             => 'Brëkòwnik',
+       NS_USER_TALK        => 'Diskùsëjô_brëkòwnika',
+       NS_PROJECT          => 'Wiki',
+       NS_PROJECT_TALK     => 'Diskùsëjô_Wiki',
+       NS_IMAGE            => 'Òbrôzk',
+       NS_IMAGE_TALK       => 'Diskùsëjô_òbrôzków',
+       NS_MEDIAWIKI        => 'MediaWiki',
+       NS_MEDIAWIKI_TALK   => 'Diskùsëjô_MediaWiki',
+       NS_TEMPLATE         => 'Szablóna',
+       NS_TEMPLATE_TALK    => 'Diskùsëjô_Szablónë',
+       NS_HELP             => 'Pòmòc',
+       NS_HELP_TALK        => 'Diskùsëjô_Pòmòcë',
+       NS_CATEGORY         => 'Kategòrëjô',
+       NS_CATEGORY_TALK    => 'Diskùsëjô_Kategòrëji'
+);
+
+
+/* private */ $wgAllMessagesCsb = array(
+'1movedto2' => '$1 przeniesłé do $2',
+'aboutpage' => '{{ns:4}}:Ò_Wiki',
+'aboutsite' => 'Ò {{SITENAME}}',
+'actioncomplete' => 'Òperacëjô wëkònónô',
+'addedwatch' => 'Dodónô do lëstë ùzérónëch',
+'administrators' => '{{ns:4}}:Administratorzë',
+'allmessages' => 'Wszëtczé systemòwé ògłosë',
+'ancientpages' => 'Nôstarszé starnë',
+'and' => 'ë',
+'anontalk' => 'Diskùsëjô dlô ti IP-adresë',
+'anonymous' => 'Anonimòwi brëkòwnik/-cë  Wiki',
+'april-gen' => 'Łżëkwiôta',
+'april' => 'Łżëkwiôt',
+'august-gen' => 'Zélnika',
+'august' => 'Zélnik',
+'badfilename' => 'Miono òbrôzka zmienioné na "$1".',
+'badfiletype' => '".$1" nie je nôlepszim fòrmatã lopka.',
+'badipaddress' => 'IP-adresa nie je richtich pòdónô.',
+'blockedtext' => 'Twòje kònto abò/ ë IP-adresa òstałë zascëgòwóné przez $1.\nPòdónô przëczëna to:<br />$2.<p>Bë wëjasnic sprawã zablokòwaniégò mòżesz skòntaktowac sã z $1 abò jińszim [[{{ns:4}}:Administratorzë|administratorã]].',
+'blockip' => 'Zascëgôj IP-adresã',
+'booksources' => 'Ksążczi',
+'brokenredirects' => 'Zerwóné przeczerowania',
+'bydate' => 'wedle datumù',
+'byname' => 'wedle miona',
+'bysize' => 'wedle wiôlgòscë',
+'categories' => 'Kategòrëje',
+'categoryarticlecount' => 'W ny kategòrëje je $1 artiklów.',
+'category_header' => 'Artikle w kategòrëji "$1"',
+'category' => 'Kategòrëjô',
+'changepassword' => 'Zmiana parolë',
+'compareselectedversions' => 'Przërównôj wëbróné wersëje',
+'confirmdelete' => 'Pòcwierdzë rëmónié',
+'confirm' => 'Pòcwierdzë',
+'confirmprotect' => 'Pòcwierdzë zazychrowanié',
+'confirmprotecttext' => 'Jes Të gwës, że chcesz zazychrowac ną starnã?',
+'confirmunprotect' => 'Pòcwierdzë òdzychrowónié',
+'confirmunprotecttext' => 'Jes Të gwës, że chcesz òdzychrowac ną starnã?',
+'contribslink' => 'wkłôd',
+'contribsub' => 'Dlô brëkòwnika $1',
+'contributions' => 'Wkłôd brëkòwników',
+'copyrightwarning' => 'Prosymë wdôrzëc, że przëjimô sã, ëż wszelejaczi\nwkłôd do Wiki je ùżëczóny wedle reglów <i>GNU Free Documentation License</i>\n(szczegóły w $1).  <br />Jeżle nie chcesz, bë Twój tekst bëł dowòlno zmieniwóny przez kòżdégò ë rozpòmiónowóny bez ògrańczeniów, tej nie dôwôj do niegò  doprzińdzeniô w Wiki. Równoczasno òswiôdczôsz, że nen tekst je Twòjim dokazã, abò pòchôdô z materiałów ôrtu <i>public domain</i> abò\n<i>GNU Free Documentation License</i>, abò téż kòmpatibilnégò ôrtu.\n<br /><strong>PROSYMË NIE ÙŻIWAC BEZ ZEZWÒLENIÉGÒ MATERIAŁÓW ÒBJIMNIÃTËCH AUTORSCZIM PRAWÃ!</strong>',
+'copyright' => 'Zamkłosc hewòtny starnë je ùżëczónô wedle reglów $1.',
+'couldntremove' => 'Ni móg rëmac pòzycëje "$1"...',
+'createaccount' => 'Założë nowé kònto',
+'cur' => 'aktualnô',
+'currentevents' => '-',
+'databaseerror' => 'Fela w pòdôwkòwi baze',
+'dateformat' => 'Fòrmat datumù',
+'debug' => 'Òdplëskwianié "(debug-òwónié)"',
+'december-gen' => 'Gòdnika',
+'december' => 'Gòdnik',
+'defaultns' => 'Domëslno przeszëkùjë nôslédné rëmnotë mionów:',
+'defemailsubject' => 'E-mail òd Wiki',
+'deletecomment' => 'Przëczëna rëmaniô',
+'deleteimg' => 'rëmôj nen òbrôzk',
+'deletepage' => 'Rëmôj starnã',
+'delete' => 'Rëmôj',
+'deletionlog' => 'register rëmaniów',
+'dellogpage' => 'Rëmóné',
+'developertext' => 'Ną òperacëjã mòże wëkònac blós brëkòwnik z prawama\n"Programista".\nZdrzë $1.',
+'difference' => '(różnice midzë wersëjama)',
+'disambiguationspage' => '{{ns:4}}:Starnë_ùjednoznacznieniô',
+'disclaimerpage' => '{{ns:4}}:General_disclaimer',
+'disclaimers' => 'Prawné zastrzedżi',
+'doubleredirects' => 'Dëbeltné przeczérowania',
+'editcurrent' => 'Editëjë aktualną wersëjã ny starnë',
+'edit' => 'Edicëjô',
+'editthispage' => 'Editëjë ną starnã',
+'emailfrom' => 'Òd',
+'emailmessage' => 'Wiadło',
+'emailpage' => 'Sélajë e-mail do brëkòwnika',
+'emailsend' => 'Wëslë',
+'emailsubject' => 'Téma',
+'emailto' => 'Do',
+'emailuser' => 'Wëslë e-maila do negò brëkòwnika',
+'errorpagetitle' => 'Brida',
+'excontent' => 'Zamkłosc starnë',
+'explainconflict' => 'Chtos sfórtowôł wprowadzëc swòją wersëjã artikla òbczôs Twòji edicëji. Górné pòle edicëji zamëkô w se tekst starnë aktualno zapisóny w pòdôwkòwi baze. Twòje zmianë są w dólnym pòlu edicëji. Bë wprowadzëc swòje zmianë mùszisz zmòdifikòwac tekst z górnégò pòla. <b>Blós</b> tekst z górnégò pòla mdze zapisóny w baze czej wcësniesz "Zapiszë".\n<p>',
+'export' => 'Ekspòrt starnów',
+'faqpage' => '{{ns:4}}:FAQ',
+'february-gen' => 'Gromicznika',
+'february' => 'Gromicznik',
+'filecopyerror' => 'Ni mòże skòpérowac lopka "$1" do "$2".',
+'filedeleteerror' => 'Ni mòże rëmac lopka "$1".',
+'filedesc' => 'Òpisënk',
+'filename' => 'Miono lopka',
+'filenotfound' => 'Ni mòże nalezc lopka "$1".',
+'filerenameerror' => 'Ni mòże zmienic miona lopka "$1" na "$2".',
+'filesource' => 'Zdrój',
+'fileuploaded' => 'Lopk"$1" òstôł wladowóny.\nBiôj, prosymë, do starnë òpisënkù lopka ($2) ë pòdôj tikającé gò infòrmacëje\ntaczé jak: pòchòdzenié lopka, czedë ë przez kògò òstôł ùtworzony, ôs dëcht co le ò nim wiész, a wëdôwô Cë sã wôżné.',
+'formerror' => 'Fela: ni mòże wëslac fòrmùlara',
+'getimagelist' => 'zladënk lëstë lopków',
+'go' => 'Biôj!',
+'guesstimezone' => 'Wezmi z przezérnika',
+'help' => 'Pòmòc',
+'hidetoc' => 'zatacë',
+'hide' => 'zatacë',
+'histlegend' => 'Legenda: (aktualnô) = różnice w przërównanim do aktualny wersëje,\n(wczasniészô) = różnice w przërównanim do wczasniészi wersëje, D = drobné edicëje',
+'history' => 'Historëjô starnë',
+'history_short' => 'Historëjô',
+'hr_tip' => 'Wòdorównô (horizontalnô) linijô (brëkùjë szpôrowno)',
+'ignorewarning' => 'Ignorëjë òstrzegã ë wëslë lopk.',
+'ilsubmit' => 'Szëkôj',
+'imagelinks' => 'Lënczi do lopka',
+'imagelist' => 'Lësta òbrôzków',
+'imagepage' => 'Starna òbrôzka',
+'imagereverted' => 'Przëwôrcenié wczasniészi wersëje darzëło sã.',
+'imgdelete' => 'rëmôj',
+'imgdesc' => 'òpisënk',
+'imghistlegend' => 'Legenda: (aktualny) = to je aktualny lopk, (rëmôj) = rëmôj\nną starszą wersëjã, (przëwôrcë) = przëwôrcë ną starszą wersëjã.\n<br /><i>Klëkni na datum bë òbôczëc jaczé lopczi bëlë wladowóné òb nen dzéń</i>.',
+'imghistory' => 'Historëjô lopka',
+'import' => 'Impòrtëjë starnë',
+'internalerror' => 'Bënowô fela',
+'ipbreason' => 'Przëczëna',
+'isredirect' => 'starna przeczerowaniô',
+'january-gen' => 'stëcznika',
+'january' => 'stëcznik',
+'july-gen' => 'Lëpinca',
+'july' => 'Lëpinc',
+'june' => 'Czerwińc',
+'june-gen' => 'Czerwińca',
+'largefile' => 'Nôlepi bë lopk ni miôł wicy jak 100 kilobajtów.',
+'lastmodifiedby' => 'Na starna bëła slédno editowónô $1 przez $2.',
+'lastmodified' => 'Na starna bëła slédno editowónô ò $1;',
+'last' => 'pòslédnô',
+'lineno' => 'Lëniô $1:',
+'linkshere' => 'Do ny starnë òdwòłëją sã hewòtné starnë:',
+'linkstoimage' => 'Hewò są starnë, jaczé òdwòłëją sã do negò lopka:',
+'listusers' => 'Lësta brëkòwników',
+'loadhist' => 'Zladënk historëji ny starnë',
+'localtime' => 'Twòja czasowô cona',
+'lockbtn' => 'Zascëgôj bazã pòdôwków',
+'loginerror' => 'Fela logòwaniô',
+'loginpagetitle' => 'Logòwanié brëkòwnika',
+'loginprompt' => 'Brëkùjesz miec \'\'cookies\'\' (kùszczi) włączoné bë sã wlogòwac do Wiki.',
+'loginsuccess' => 'Të jes wlogòwóny do Wiki jakno "$1".',
+'loginsuccesstitle' => 'ùdałé logòwanié',
+'login' => 'Wlogùjë mie',
+'logouttext' => 'Të jes ju wëlogòwóny.\nMòżesz prôcowac z Wiki jakno anonimòwi brëkòwnik\nabò wlogòwac sã jakno zaregistrowóny brëkòwnik.',
+'logouttitle' => 'Wëlogòwanié brëkòwnika',
+'logout' => 'Wëlogùjë mie',
+'lonelypages' => 'Niechóné starnë',
+'longpages' => 'Nôdłëgszé starnë',
+'mainpage' => 'Przédnô starna',
+'march-gen' => 'strumiannika',
+'march' => 'strumiannik',
+'math_failure' => 'Parser nie rozmiôł rozpòznac',
+'may-gen' => 'Môja',
+'may_long' => 'Môj',
+'minlength' => 'Miono òbrôzka brëkùje miec przënomni trzë lëterë.',
+'minoredit' => 'Drobnô edicëjô.',
+'minoreditletter' => 'D',
+'mispeelingspage' => 'Lësta nôczãstszëch pisënkòwich felów',
+'mispeelings' => 'Starnë z felama pisënkù',
+'missingarticle' => 'Programa ni mô nalôzłé tekstu starnë,\nchtërnô bë mùsza bëc w baze, to je starnë "$1".\n<p>Colemało mô to plac, czej òstónie wëbróné sparłãczenié\ndo rëmóny starnë, np. stôrszi wersëji jińszi starnë.\n<p>Jińszé leżnosce mògą znaczëc, że w soft-wôrze je fela.\nW taczim przëtrôfkù prosymë zameldowac nen fakt administratorowi\npòdającë hewòtną adresã.',
+'missingimage' => '<b>Felëjący òbrôzk</b><br /><i>$1</i>',
+'moredotdotdot' => 'Wicy...',
+'movearticle' => 'Przeniesë artikel',
+'movedto' => 'przeniesłô do',
+'movenologin' => 'Felënk logòwaniô',
+'movepagebtn' => 'Przeniesë starnã',
+'movepage' => 'Przeniesë starnã',
+'move' => 'Przeniesë',
+'movetalk' => 'Przeniesë téż starnã <i>Diskùsëje</i>, jeżle je to mòżlëwé.',
+'movethispage' => 'Przeniesë',
+'mycontris' => 'Mòje edicëje',
+'navigation' => 'Nawigacëjô',
+'newpages' => 'Nowé starnë',
+'newpassword' => 'Nowô parola',
+'newwindow' => '(òtmëkô sã w nowim òczenkù)',
+'nlinks' => '$1 lënków',
+'noemailtitle' => 'Felënk email-adresë',
+'noemail' => 'W baze ni ma email-adresë dlô brëkòwnika "$1".',
+'nogomatch' => 'Nie da starnë z dokładno taczim titlã. Spróbùjë fùl szëkbë.',
+'nolinkstoimage' => 'Niżódnô starna nie òdwòłëje sã do negò lopka.',
+'nosuchactiontext' => 'Programa Wiki nie rozpòznôwô taczi òperacëji jakô je w URL',
+'nosuchspecialpage' => 'Nie da taczi specjalny starnë',
+'nosuchuser' => 'Nie da taczégò brëkòwnika "$1". Sprôwdzë pisënk abò wëfùlujë fòrmular bë założëc nowé kònto.',
+'notanarticle' => 'To nie je artikel',
+'notargettitle' => 'Nie da taczi starnë',
+'notloggedin' => 'Felëje logòwóniô',
+'november-gen' => 'Lëstopadnika',
+'november' => 'Lëstopadnik',
+'nowiki_sample' => 'Wstôw tuwò niesfòrmatowóny tekst',
+'nowiki_tip' => 'Ignorëjë wiki-fòrmatowanié',
+'nstab-category' => 'Kategòrëjô',
+'nstab-help' => 'Pòmòc',
+'nstab-image' => 'Òbrôzk',
+'nstab-main' => 'Artikel',
+'nstab-mediawiki' => 'ògłosënk',
+'nstab-special' => 'Specjalnô',
+'nstab-template' => 'Szablóna',
+'nstab-user' => 'Starna brëkòwnika',
+'nstab-wp' => 'meta-starna',
+'october-gen' => 'Rujana',
+'october' => 'Rujan',
+'ok' => 'Jo!',
+'orphans' => 'Niechóné starnë',
+'othercontribs' => 'Òpiarté na prôcë $1.',
+'pagemovedsub' => 'Przeniesenié darzëło sã',
+'pagemovedtext' => 'Starna "[[$1]]" òsta przeniesłô do "[[$2]]".',
+'pagetitle' => '$1 - Wiki',
+'passwordremindertext' => 'Chtos (prôwdëjuwerno Të, z adresë $1) pòprosëł ò wësłanié nowi parolë dopùscënkù do Wiki. Aktualnô parola dlô brëkòwnika "$2" je "$3". Nôlepi mdze czej wlogùjesz sã terô ë zarô zmienisz parolã.',
+'personaltools' => 'Priwatné przërëchtënczi',
+'popularpages' => 'Nôwidzalszé starnë',
+'portal' => 'Pòrtal wëcmaniznë',
+'portal-url' => '{{ns:4}}:Pòrtal wëcmaniznë',
+'postcomment' => 'Dôj dopòwiesc',
+'powersearch' => 'Szëkba',
+'preferences' => 'Preferencëje',
+'prefsnologin' => 'Felënk logòwóniô',
+'prefs-personal' => 'Pòdôwczi brëkòwnika',
+'previewnote' => 'To je blós pòdzérk - artikel jesz nie je zapisóny!',
+'preview' => 'Pòdzérk',
+'protectcomment' => 'Przëczëna zazychrowóniô',
+'protectedarticle' => 'zazychrowónô [[$1]]',
+'protectedpage' => 'Starna je zazychrowónô',
+'protectpage' => 'Zazychrëjë starnã',
+'protect' => 'Zazychrëjë',
+'proxyblocksuccess' => 'Fertich.',
+'qbfind' => 'Nalézë',
+'qbmyoptions' => 'Mòje òptacëje',
+'qbspecialpages' => 'Specjalné starnë',
+'randompage' => 'Kawlowô starna',
+'rcloaderr' => 'Ladëjë slédné edicëje',
+'readonly' => 'Baza pòdôwków je zablokòwónô',
+'readonlywarning' => 'BÔCZËNK: Pòdôwkòwô baza òsta sztërkòwô zablokòwónô dlô administracëjnëch célów. Nie mòże tej timczasã zapisac nowi wersëje artikla. Bédëjemë przeniesc ji tekst do priwatnégò lopka\n(wëtnij/wstôw) ë zachòwac na pózni.',
+'recentchangescount' => 'Wielëna pòzycëji na lësce slédnëch edicëji',
+'recentchangeslinked' => 'Zmianë w dolënkòwónëch',
+'recentchanges' => 'Slédné edicëje',
+'recentchangestext' => 'Na starna prezentérëje historëjã slédnëch edicëjów w Wiki.\n\nWitôj! Jeżle Të jes tuwò dopiérze pierszi rôz, przeczëtôj né starnë: [[{{ns:4}}:FAQ|FAQ]], [[{{ns:4}}:Nazëwizna|konwencëje nazëwaniégò starnów]].',
+'redirectedfrom' => '(Przeczerowóné z $1)',
+'removedwatch' => 'Rëmóné z lëstë ùzérónëch',
+'returnto' => 'Wôrcë sã do starnë: $1.',
+'reupload' => 'Wëslë jesz rôz',
+'revertimg' => 'przëwôrcë',
+'rights' => 'Prawa:',
+'rollback' => 'Copnij edicëjã',
+'rollbackfailed' => 'Nie szło copnąc zmianë',
+'rollbacklink' => 'copnij',
+'savearticle' => 'Zapiszë artikel',
+'savefile' => 'Zapiszë lôpk',
+'search' => 'Szëkba',
+'september-gen' => 'Séwnika',
+'september' => 'Séwnik',
+'servertime' => 'Aktualny czas serwera',
+'shortpages' => 'Nôkrótszé starnë',
+'show' => 'pokôż',
+'showpreview' => 'Pòdzérk',
+'showtoc' => 'pokôż',
+'sitestats' => 'Statistika artiklów',
+'sitestatstext' => 'W pòdôwkòwi baze je w sëmie <b>$1</b> starn. Na wielëna zamëkô w se starnë <i>Diskùsëji</i>, starnë ò Wiki, starnë ôrtë <i>stub</i> (ùzémk), starnë przeczerowóniô, ë jińszé, chtërné grãdo je klasyfikòwac jakno artikle. Bez nëch to prôwdëjuwerno da <b>$2</b> starn artiklów.<p>\nBëło w sëmie <b>$3</b> òdwiôdënów ë <b>$4</b> edicëji òd sztótu, czej miôł plac\nupgrade soft-wôrë.\nDôwó to strzédno <b>$5</b> edicëji na jedną starnã ë <b>$6</b> òdwiôdënów na jedną edicëjã.',
+'sitesubtitle' => 'Wiki',
+'siteuser' => 'Brëkòwnik Wiki $1',
+'skin' => 'Wëzdrzatk',
+'spamprotectiontitle' => 'Anti-spamòwi filter',
+'specialpage' => 'Specjalnô starna',
+'specialpages' => 'Specjalné starnë',
+'spheading' => 'Specjalné nôpisma',
+'successfulupload' => 'Wladënk darzëł sã',
+'talk' => 'Diskùsëjô',
+'timezonelegend' => 'Czasowô cona',
+'toc' => 'Spisënk zamkłoscë',
+'toolbox' => 'Przërëchtënczi',
+'tooltip-watch' => 'Dodôj ną starnã do lëstë ùzérónëch [alt-w]',
+'ucnote' => 'Hewò je lësta slédnëch <b>$1</b> edicëjów dokònónëch przez\nbrëkòwnika òbczôs òstatnëch <b>$2</b> dni.',
+'unprotectcomment' => 'Przëczëna òdzychrowaniô',
+'unprotectedarticle' => 'òdzychrowóny [[$1]]',
+'unprotect' => 'Òdzychrëjë',
+'unusedimages' => 'Nie wëzwëskóné òbrôzczi',
+'unwatch' => 'Òprzestôj ùzerac',
+'unwatchthispage' => 'Òprzestôj ùzerac ną starnã',
+'uploaddisabled' => 'Przeprôszómë! Mòżlëwòta wladënkù lopków na nen serwer òsta wëłączonô.',
+'uploadedfiles' => 'Wladowóné lopczi',
+'uploadedimage' => 'wladënk: "$1"',
+'uploadlink' => 'Wladëjë lënk',
+'uploadlog' => 'Lësta wladënków',
+'uploadlogpage' => 'Dołączoné',
+'uploadlogpagetext' => 'Hewò je lësta slédno wladowónëch lopków.\nWszëtczé gòdzënë tikają conë ùniwersalnégò czasë (UTC).\n<ul>\n</ul>',
+'uploadnologin' => 'Felënk logòwaniô',
+'uploadtext' => '<strong>STOP!</strong> Nigle wladëjesz jaczi lopk,\nprzeczëtôj [[{{ns:4}}:Regle_wladowaniô_lopków|regle wladowaniô lopków]] ë ùgwësnij sã, że wladëwającë gò òstóniesz z\nnima w zgòdze.\n<p>Jeżle chcesz przezdrzec abò przeszëkac do terô wladowóné lopczi,\nprzeńdzë do [[Specjalnô:Imagelist|lëstë wladowónëch lopków]].\nWszëtczé wladënczi ë rëmania są òdnotérowóné w\nspecjalnëch zestôwkach: [[{{ns:4}}:wladënczi|wladënczi]] ë [[{{ns:4}}:Rëmóné|rëmóné]].\n<p>Bë wëslac nowi lopk do zòbrazowaniô Twòjégò artikla wëzwëskùj \nhewòtny fòrmùlar.\nW wikszoscë przezérników ùzdrzesz knąpã <i>Browse...</i>\nabò <i>Przezérôj...</i>, chtëren ùmożlëwi Cë òtemkniãcé sztandardowégò\nòkna wëbiérkù lopka. Wëbranié lopka sprawi wstôwienié jegò miona\nw tekstowim pòlu kòl knąpë.\nZaznaczającë pasowné pòle, mùszisz téż pòcwierdzëc, ëż sélającë\nlopk nie gwôłcësz nikògò autorsczich praw.\nWladënk zacznie sã pò wcësniãcym <i>Wladëjë lopk</i>.\nTo mòże sztërk zdérowac, òsoblëwò jeżle ni môsz chùtczégò dopùscënkù do internetu.\n<p>Preferowónyma fòrmatama są: JPEG dlô òdjimków, PNG dlô céchùnków\në òbrôzków ze znankama ikònów, ôs OGG dlô zwãków. Bë nie dac przińc do lëchòrozmieniów nadôwôj lopkom miona sparłãczóné z jich zamkłoscą.\nBë wstôwic òbrôzk do artikla, wpiszë lënk:\n<b>[[òbrôzk:miono.jpg]]</b> abò <b>[[òbrôzk:miono.png|òpcjonalny tekst]]</b>.\nDlô zwãkòwëch lopków lënk mdze wëzdrzôł tak: <b>[[media:file.ogg]]</b>.\n<p>Prosymë wdarzëc, ëż tak samò jak w przëtrôfkù zwëczajnëch starnów Wiki,\njińszi brëkòwnicë mògą editowac abò rëmac wladowóné przez Ce lopczi,\njeżle mdą dbë, że to mdze lepi służëc całi ùdbie Wiki.\nTwòje prawò do sélaniégò lopków mòże bëc Cë òdebróné, eżle nadùżëjesz systemë.',
+'uploadwarning' => 'Òstrzega ò wladënkù',
+'upload' => 'Wladënk lopka',
+'userlogin' => 'Logòwanié',
+'userlogout' => 'Wëlogòwanié',
+'userstats' => 'Statistika brëkòwników',
+'version' => 'Wersëjô',
+'wantedpages' => 'Nônótniészé starnë',
+'watchlistcontains' => 'Wielëna artiklów na Twòji lësce ùzérónëch: $1.',
+'watchlist' => 'Lësta ùzérónëch artiklów',
+'watchlistsub' => '(dlô brëkòwnika "$1")',
+'watchmethod-list' => 'szëkba ùzérónëch artiklów westrzód pòslédnëch edicëjów',
+'watchnologin' => 'Felënk logòwóniô',
+'watchthispage' => 'Ùzérôj ną starnã',
+'watchthis' => 'Ùzérôj',
+'watch' => 'Ùzérôj',
+'whatlinkshere' => 'Lënkùjącé',
+'whitelistedittitle' => 'Bë editowac je nót sã wlogòwac',
+'whitelistreadtitle' => 'Bë czëtac je nót sã wlogòwac',
+'yourlanguage' => 'Kaszëbsczi',
+'yourpasswordagain' => 'Pòwtórzë parolã',
+'yourpassword' => 'Twòja parola',
+'yourrealname' => 'Twòje jistné miono*',
+);
+
+require_once( 'LanguageUtf8.php' );
+class LanguageCsb extends LanguageUtf8 {
+       function getNamespaces() {
+               global $wgNamespaceNamesCsb;
+               return $wgNamespaceNamesCsb;
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesCsb, $wgAllMessagesEn;
+               if( isset( $wgAllMessagesCsb[$key] ) ) {
+                       return $wgAllMessagesCsb[$key];
+               } else {
+                       return parent::getMessage( $key );
+               }
+       }
+}
+?>
diff --git a/languages/LanguageCy.php b/languages/LanguageCy.php
new file mode 100644 (file)
index 0000000..b402133
--- /dev/null
@@ -0,0 +1,936 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+/* Cymraeg - Welsh */
+
+/* private */ $wgNamespaceNamesCy = array(
+       NS_MEDIA          => "Media",
+       NS_SPECIAL        => "Arbennig",
+       NS_MAIN           => "",
+       NS_TALK           => "Sgwrs",
+       NS_USER           => "Defnyddiwr",
+       NS_USER_TALK      => "Sgwrs_Defnyddiwr",
+       NS_PROJECT        => $wgMetaNamespace,
+       NS_PROJECT_TALK   => "Sgwrs_".$wgMetaNamespace,
+       NS_IMAGE          => "Delwedd",
+       NS_IMAGE_TALK     => "Sgwrs_Delwedd",
+       NS_MEDIAWIKI      => "MediaWiki",
+       NS_MEDIAWIKI_TALK => "Sgwrs_MediaWiki",
+       NS_TEMPLATE       => "Nodyn",
+       NS_TEMPLATE_TALK  => "Sgwrs_Nodyn"
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgQuickbarSettingsCy = array(
+       "Dim", "Sefydlog chwith", "Sefydlog de", "Arnawf de"
+);
+
+/* private */ $wgSkinNamesCy = array(
+       'standard' => "Safonol",
+       'nostalgia' => "Hiraeth",
+       'cologneblue' => "Glas Cwlen",
+) + $wgSkinNamesEn;
+
+/* private */ $wgDateFormatsCy = array(
+#      "Dim dewis",
+);
+
+/* private */ $wgBookstoreListCy = array(
+       "AddALL" => "http://www.addall.com/New/Partner.cgi?query=$1&type=ISBN",
+       "PriceSCAN" => "http://www.pricescan.com/books/bookDetail.asp?isbn=$1",
+       "Barnes & Noble" => "http://search.barnesandnoble.com/bookSearch/isbnInquiry.asp?isbn=$1",
+       "Amazon.com" => "http://www.amazon.com/exec/obidos/ISBN=$1",
+       "Amazon.co.uk" => "http://www.amazon.co.uk/exec/obidos/ISBN=$1"
+);
+
+
+/* private */ $wgMagicWordsCy = array(
+#   ID                                 CASE  SYNONYMS
+       MAG_REDIRECT             => array( 0,    "#redirect", "#ail-cyfeirio"                 ),
+       MAG_NOTOC                => array( 0,    "__NOTOC__", "__DIMTAFLENCYNNWYS__"          ),
+       MAG_NOEDITSECTION        => array( 0,    "__NOEDITSECTION__", "__DIMADRANGOLYGU__"    ),
+       MAG_START                => array( 0,    "__START__", "__DECHRAU__"                   ),
+       MAG_CURRENTMONTH         => array( 1, "CURRENTMONTH", "MISCYFOES"                ),
+       MAG_CURRENTMONTHNAME     => array( 1,    "CURRENTMONTHNAME", "ENWMISCYFOES"           ),
+       MAG_CURRENTDAY           => array( 1,    "CURRENTDAY", "DYDDIADCYFOES"                ),
+       MAG_CURRENTDAYNAME       => array( 1,    "CURRENTDAYNAME", "ENWDYDDCYFOES"            ),
+       MAG_CURRENTYEAR          => array( 1,    "CURRENTYEAR", "FLWYDDYNCYFOES"              ),
+       MAG_CURRENTTIME          => array( 1,    "CURRENTTIME", "AMSERCYFOES"                 ),
+       MAG_NUMBEROFARTICLES     => array( 1, "NUMBEROFARTICLES","NIFEROERTHYGLAU"       ),
+       MAG_CURRENTMONTHNAMEGEN  => array( 1,    "CURRENTMONTHNAMEGEN", "GENENWMISCYFOES"     ),
+       MAG_SUBST                => array( 1,    "SUBST:"                                     ),
+       MAG_MSGNW                => array( 0,    "MSGNW:"                                     ),
+       MAG_END                  => array( 0, "__DIWEDD__"                                   ),
+       MAG_IMG_THUMBNAIL        => array( 1, "ewin bawd", "bawd", "thumb", "thumbnail"  ),
+       MAG_IMG_RIGHT            => array( 1,    "de", "right"                                ),
+       MAG_IMG_LEFT             => array( 1,    "chwith", "left"                             ),
+       MAG_IMG_NONE             => array( 1,    "dim", "none"                                ),
+       MAG_IMG_WIDTH            => array( 1,    "$1px"                                       ),
+       MAG_IMG_CENTER           => array( 1, "canol", "centre", "center"                ),
+       MAG_INT                  => array( 0,    "INT:"                                       )
+
+);
+
+
+/* private */ $wgAllMessagesCy = array(
+# User Toggles
+
+"tog-underline" => "Tanllinellu cysylltiadau",
+"tog-highlightbroken" => "Fformatio cysylltiadau wedi'i dorri <a href=\"\" class=\"new\">fel hyn</a> (dewis arall: fel hyn<a href=\"\" class=\"internal\">?</a>).",
+"tog-justify" => "Unioni paragraffau",
+"tog-hideminor" => "Cuddiwch golygiadau bach mewn newidiadau diweddar",
+"tog-usenewrc" => "Newidiadau diweddar mwyhad (nid am pob porwr)",
+"tog-numberheadings" => "Rhifwch teiltau yn awtomatig",
+"tog-showtoolbar"=> "Dangos bar erfynbocs golygu",
+"tog-editondblclick" => "Golygu tudalennau gyda clic dwbwl (JavaScript)",
+"tog-editwidth" => "Mae gan bocs golygu lled llon",
+"tog-editsection"  => "Galluogwch golygu adrannau trwy cysylltiadau [golygu]",
+"tog-editsectiononrightclick" => "Galluogwch golygu adrannau trwy dde-clicio ar teitlau adran (JavaScript)",
+"tog-showtoc" => "Dangoswch Taflen Cynnwys (am erthyglau gyda mwy na 3 pennawdau",
+"tog-rememberpassword" => "Cofiwch allweddair dros sesiwnau",
+"tog-watchdefault" => "Gwiliwch erthyglau newydd ac wedi adnewid",
+"tog-minordefault" => "Marciwch pob golygiad fel un bach",
+"tog-previewontop" => "Dangos blaenwelediad cyn y bocs golygu, nid ar ol e",
+"tog-nocache" => "Anablwch casio tudanlen",
+
+# Dates
+'sunday' => 'Dydd Sul',
+'monday' => 'Dydd Llun',
+'tuesday' => 'Dydd Mawrth',
+'wednesday' => 'Dydd Mercher',
+'thursday' => 'Dydd Iau',
+'friday' => 'Dydd Gwener',
+'saturday' => 'Dydd Sadwrn',
+'january' => 'Ionawr',
+'february' => 'Chwefror',
+'march' => 'Mawrth',
+'april' => 'Ebrill',
+'may_long' => 'Mai',
+'june' => 'Mehefin',
+'july' => 'Gorffennaf',
+'august' => 'Awst',
+'september' => 'Medi',
+'october' => 'Hydref',
+'november' => 'Tachwedd',
+'december' => 'Rhagfyr',
+'jan' => 'Ion',
+'feb' => 'Chwe',
+'mar' => 'Maw',
+'apr' => 'Ebr',
+'may' => 'Mai',
+'jun' => 'Meh',
+'jul' => 'Gor',
+'aug' => 'Aws',
+'sep' => 'Med',
+'oct' => 'Hyd',
+'nov' => 'Tach',
+'dec' => 'Rhag',
+
+
+# Bits of text used by many pages:
+#
+"categories" => "Categorïau tudalen",
+"category" => "categori",
+"category_header" => "Erthyglau mewn categori \"$1\"",
+"subcategories" => "Is-categorïau",
+"linktrail" => "/^((?:à|á|â|è|é|ê|ì|í|î|ï|ò|ó|ô|û|ŵ|ŷ|[a-z])+)(.*)\$/sD",
+"mainpage" => "Prif tudalen",
+"mainpagetext" => "Meddalwedd Wicipedia wedi sefydlu'n llwyddiannus",
+"about"        => "Amdano",
+"aboutsite"      => "Amdano Wicipedia",
+"aboutpage" => "{{ns:project}}:Amdano",
+"help" => "Help",
+"helppage" => "{{ns:project}}:Help",
+"bugreports" => "Adroddiadau diffygion",
+"bugreportspage" => "{{ns:project}}:Adroddiadau_diffygion",
+"sitesupport" => "Rhoddion",
+"faq" => "COF",
+"faqpage" => "{{ns:project}}:COF",
+"edithelp" => "Help gyda golygu",
+"edithelppage" => "{{ns:project}}:Sut_ydy_chi'n_golygu_tudalen",
+"cancel" => "Dirymu",
+"qbfind" => "Cael",
+"qbbrowse" => "Pori",
+"qbedit" => "Golygu",
+"qbpageoptions" => "Dewysiadau tudalen",
+"qbpageinfo" => "Gwybodaeth tudalen",
+"qbmyoptions" => "Fy dewysiadau",
+"qbspecialpages" => "Tudalennau arbennig",
+"moredotdotdot"        => "Mwy...",
+"mypage" => "Fy nhudalen",
+"mytalk" => "Sgwrs fi",
+"disclaimers" => "Gwadiadau",
+"disclaimerpage" => "{{ns:project}}:Gwadiad_cyffredin",
+"currentevents" => "Digwyddiadau presennol",
+"errorpagetitle" => "Gwall",
+"returnto" => "Ewch yn ôl i $1.",
+"tagline"              => "Oddiwrth Wicipedia, y gwyddoniadur rhad.",
+"whatlinkshere"        => "Tudalennau sydd yn cysyllti fan hyn",
+"help" => "Help",
+"search" => "Chwilio",
+"go" => "Mynd",
+"history" => "Hanes y tudalen",
+"printableversion" => "Fersiwn argraffiol",
+"editthispage" => "Golygwch y tudalen hon",
+"deletethispage" => "Dileuwch y tudalen hon",
+"protectthispage" => "Amddiffynwch y tudalen hon",
+"unprotectthispage" => "Di-amddiffynwch y tudalen hon",
+"newpage" => "Tudalen newydd",
+"talkpage" => "Sgwrsio amdano'r tudalen hon",
+"postcomment" => "Postiwch esboniad",
+"articlepage" => "Gwyliwch erthygl",
+"subjectpage" => "Gwyliwch pwnc", # For compatibility
+"userpage" => "Gwyliwch tudalen defnyddiwr",
+"wikipediapage" => "Gwyliwch tudalen meta",
+"imagepage" => "Gwyliwch tudalen llun",
+"viewtalkpage" => "Gwyliwch sgwrs",
+"otherlanguages" => "Ieithoed eraill",
+"redirectedfrom" => "(Ail-cyfeiriad oddiwrth $1)",
+"lastmodified" => "Pryd cafodd ei newid diwethaf $1.",
+"viewcount" => "Mae'r tudalen hyn wedi cael ei gweld $1 o weithiau.",
+"printsubtitle" => "(Oddiwrth {{SERVER}})",
+"protectedpage" => "Tudalen amddiffyniol",
+"administrators" => "{{ns:project}}:Gweinyddwyr",
+"sysoptitle" => "Mynediad Sysop yn unig",
+"sysoptext" => "Mae'r peth rydych wedi gofyn amdano dim ond yn bosibl i ddefnyddwyr gyda statws \"sysop\".
+Gwelwch $1.",
+"developertitle" => "Mynediad Datblygwr yn unig",
+"developertext"        => "Mae'r peth rydych wedi gofyn amdano dim ond yn bosibl i ddefnyddwyr gyda statws \"datblygwr\".
+Gwelwch $1.",
+"nbytes" => "$1 bytes",
+"go" => "Mynd",
+"ok" => "OK",
+"sitetitle" => "Wicipedia",
+"sitesubtitle" => "Y Gwyddoniadur Rhydd",
+"retrievedfrom" => "Wedi dod o \"$1\"",
+"newmessages" => "Mae gen ti $1.",
+"newmessageslink" => "Neges(eueon) newydd",
+"editsection" => "golygu",
+"toc" => "Taflen Cynnwys",
+"showtoc" => "dangos",
+"hidetoc" => "cuddio",
+"thisisdeleted" => "Edrychwch at, neu atgyweirio $1?",
+"restorelink" => "$1 golygiadau wedi eu dileuo",
+
+# Main script and global functions
+#
+"nosuchaction" => "Does dim gweithred",
+"nosuchactiontext" => "Dydy'r meddalwedd Wicipedia ddim yn deallt y gweithrediad mae'r URL yn gofyn iddo fe gwneud",
+"nosuchspecialpage" => "Does dim tudalen arbennig",
+"nospecialpagetext" => "Yr ydych wedi gofyn am tudalen arbennig dydy'r meddalwedd Wicipedia ddim yn adnabod.",
+
+# General errors
+#
+"error"        => "Gwall",
+"databaseerror" => "Databas ar gam",
+"dberrortext" => "Mae gwall cystrawen wedi digwydd ar y databas.
+Y gofyniad olaf triodd y databas oedd:
+<blockquote><tt>$1</tt></blockquote>
+oddiwrth ffwythiant \"<tt>$2</tt>\".
+Dwedodd MySQL mae 'ne côd gwall \"<tt>$3: $4</tt>\".",
+"dberrortextcl"              => "Mae gwall cystrawen wedi digwydd ar y databas.
+Y gofyniad olaf triodd y databas oedd:
+\"$1\"
+oddiwrth ffwythiant \"$2\".
+Dwedodd MySQL mae 'ne côd gwall \"$3: $4\".\n",
+"noconnect" => "Ddim yn gallu cysylltu i'r databas ar $1",
+"nodb" => "Ddim yn gallu dewis databas $1",
+"cachederror" => "Dyma copi o'r stôr o'r tudalen rydych wedi gofyn, ac efallai dydi hi ddim yn cyfoes.",
+"readonly" => "Databas ar gloi",
+"enterlockreason" => "Rhowch reswm am paham mae'r databas yn cael eu gloi, yn cynnwys amcangyfrif pryd fydd y databas yn cael eu di-gloi",
+"readonlytext" => "Mae'r databas Wicipedia wedi eu cloi yn erbyn erthyglau newydd ac adnewidiadau eraill, yn tebygol am gofalaeth trefn y databas -- fydd y databas yn ôl cyn bo hir.
+Mae'r gweinyddwr wedi dweud yr achos cloi'r databas oedd:
+<p>$1",
+"missingarticle" => "Dydi'r databas ddim wedi dod o hyd i testun tudalen ddyler hi ffindio, sef \"$1\".
+Dydi hwn ddim yn gwall y databas, ond debyg byg yn y meddalwedd.
+Adroddwch hwn i gweinyddwr os gwelwch yn dda, a cofiwch sylwi'r URL.",
+"internalerror" => "Gwall mewnol",
+"filecopyerror" => "Ddim yn gallu copïo ffeil \"$1\" i \"$2\".",
+"filerenameerror" => "Ddim yn gallu ail-enw ffeil \"$1\" i \"$2\".",
+"filedeleteerror" => "Ddim yn gallu dileu ffeil \"$1\".",
+"filenotfound" => "Ddim yn gallu ffeindio ffeil \"$1\".",
+"unexpected" => "Gwerth annisgwyl: \"$1\"=\"$2\".",
+"formerror" => "Gwall: ddim yn medru ymostwng y ffurflen",
+"badarticleerror" => "Mae'n amhosib perfformio'r gweithred hwn ar tudalen hon.",
+"cannotdelete" => "Mae'n amhosib dileu y tudalen neu llun hwn. (Wyrach mae rhywun arall eisoes wedi eu dileu.)",
+"badtitle" => "Teitl drwg",
+"badtitletext" => "Mae'r teitl rydych wedi gofyn yn anilys, gwag, neu cysylltu'n anghywir rhwng ieithoedd neu wicïau.",
+"perfdisabled" => "Sori! Mae'r nodwedd hon wedi cael eu anablo am achosion perfformiadau yn yr amserau brysyrach; dewch yn ôl rhwng 02:00 a 14:00 GMT a triwch eto.",
+"perfdisabledsub" => "Dyma copi rydym wedi cadw ers $1:",
+"wrong_wfQuery_params" => "Incorrect parameters to wfQuery()<br />
+Function: $1<br />
+Query: $2
+",
+"viewsource" => "Gwyliwch y ffynhonnell",
+"protectedtext" => "Mae tudalen hon wedi cael eu gloi i gwahardd golygu'r tudalen. Mae nifer o rheswmau paham mae hwn wedi digwydd, gwelwch y tudalen
+[[{{ns:project}}:Protected page]].
+
+Ellwch gweld a copïo'r ffynhonnell y tudalen hon:",
+
+# Login and logout pages
+#
+"logouttitle" => "Allgofnodi'r defnyddwr",
+"logouttext" => "Yr ydych wedi allgofnodi.
+Gallwch chi defnyddio'r Wicipedia yn anhysbys, neu gallwch chi mewngofnodi eto fel yr un defnyddwr neu un arall.\n",
+
+"welcomecreation" => "<h2>Croeso, $1!</h2><p>Mae eich accownt wedi gael eu creu. Peidiwch ac anghofio i personaleiddio eich ffafraethau defnyddwr Wicipedia.",
+"loginpagetitle" => "Mewngofnodi'r defnyddwr",
+"yourname" => "Eich enw defnyddwr",
+"yourpassword" => "Eich allweddair",
+"yourpasswordagain" => "Ail-teipiwch allweddair",
+"newusersonly" => " (defnyddwyr newydd yn unig)",
+"remembermypassword" => "Cofiwch fy allweddair dros mwy nag un sesiwn.",
+"loginproblem" => "<b>Mae problem efo'ch mewngofnodi.</b><br />Triwch eto!",
+"alreadyloggedin" => "<strong>Defnyddwr $1, yr ydych eisioes wedi mewngofnodi!</strong><br />\n",
+
+"login"        => "Mewngofnodi",
+"loginprompt" => "Rhaid i chi galluogi cwcis i mewngofnodi i {{SITENAME}}.",
+"userlogin" => "Mewngofnodi",
+"logout" => "Allgofnodi",
+"userlogout" => "Allgofnodi",
+"notloggedin" => "Nid wedi mewngofnodi",
+"createaccount"        => "Creuwch accownt newydd",
+"createaccountmail" => "gan e-post",
+"badretype" => "Dydy'r allweddgeiriau ddim yn cymharu.",
+"userexists" => "Mae rhywun arall wedi dewis yr enw defnyddwr. Dewiswch un arall os gwelwch yn dda.",
+"youremail" => "Eich cyfeiriad e-bost",
+"yournick" => "Eich llysenw (am llofnod)",
+"emailforlost" => "Os anghofiwch eich allweddair, cewch cael un newydd postwyd i'ch cyfeiriad e-bost.",
+"loginerror" => "Problem mewngofnodi",
+"nocookiesnew" => "Mae'r accownt defnyddiwr wedi gael eu creu, ond dydwch chi ddim wedi mewngofnodi. Mae {{SITENAME}} yn defnyddio cwcis i mewngofnodi defnyddwyr. Rydych chi wedi anablo cwcis. Galluogwch nhw os welwch yn dda, felly mewngofnodwch gyda'ch enw defnyddiwr a cyfrinair newydd.",
+"nocookieslogin" => "Mae {{SITENAME}} yn defnyddio cwcis i mewngofnodi defnyddwyr. Rydych chi wedi anablo cwcis. Galluogwch nhw os welwch yn dda, a triwch eto.",
+"noname" => "Dydi chi ddim wedi enwi enw defnyddwr dilys.",
+"loginsuccesstitle" => "Mewngofnod llwyddiannus",
+"loginsuccess" => "Yr ydych wedi mewngofnodi i Wicipedia fel \"$1\".",
+"nosuchuser" => "Does dim defnyddwr gyda'r enw \"$1\".
+Sicrhau rydych chi wedi sillafu'n iawn, neu creuwch accownt newydd gyda'r ffurflen isod.",
+"wrongpassword"        => "Mae'r allweddair rydych wedi teipio ddim yn cywir. Triwch eto, os gwelwch yn dda.",
+"mailmypassword" => "E-postiwch allweddair newydd i fi",
+"passwordremindertitle" => "Nodyn atgoffa allweddair oddiwrth Wicipedia",
+"passwordremindertext" => "Mae rhywun (chi, yn tebygol, oddiwrth cyfeiriad IP $1) wedi gofyn iddi ni danfon allweddair mewngofnodi newydd Wicipedia.
+Allweddair defnyddwr \"$2\" rwan yw \"$3\". Ddylwch chi mewngofnodi rwan a newid yr allweddair.",
+"noemail" => "Does dim cyfeiriad e-bost wedi cofrestru dros defnyddwr \"$1\".",
+"passwordsent" => "Mae allweddair newydd wedi gael eu ddanfon at y cyfeiriad e-bost cofrestredig am \"$1\". Mewngofnodwch eto, os gwelwch yn dda, ar ol i chi dderbyn yr allweddair.",
+"loginend" => "",
+
+# Edit page toolbar
+"bold_sample" => "Testun cryf",
+"bold_tip" => "Testun cryf",
+"italic_sample" => "Testun italig",
+"italic_tip" => "Testun italig",
+"link_sample" => "Teitl cyswllt",
+"link_tip" => "Cyswllt mewnol",
+"extlink_sample" => "http://www.example.com cyswllt teitl",
+"extlink_tip" => "Cyswllt allanol (cofiwch y rhagddodiad http:// )",
+"headline_sample" => "Testun pennawd",
+"headline_tip" => "Pennawd safon 2",
+"math_sample" => "Mewnosodwch fformwla yma",
+"math_tip" => "Fformwla mathemategol (LaTeX)",
+"nowiki_sample" => "Mewnosodwch testun di-fformatedig yma",
+"nowiki_tip" => "Anwybyddwch fformatiaeth wiki",
+"image_sample" => "Example.jpg",
+"image_tip" => "Delwedd mewnosod",
+"media_sample" => "Example.mp3",
+"media_tip" => "Cyswllt ffeil media",
+"sig_tip" => "Eich llofnod gyda stamp amser",
+"hr_tip" => "Llinell llorweddol (defnyddiwch yn cynnil)",
+"infobox" => "Cliciwch botwm i cael testun enghraifft",
+
+# Edit pages
+#
+"summary" => "Crynodeb",
+"subject" => "Testun/pennawd",
+"minoredit" => "Mae hwn yn golygiad bach",
+"watchthis" => "Gwyliwch erthygl hon",
+"savearticle" => "Cadw tudalen",
+"preview" => "Blaenwelediad",
+"showpreview" => "Gweler blaenwelediad",
+"blockedtitle" => "Mae'r defnyddwr wedi gael eu blocio",
+"blockedtext" => "Mae eich enw defnyddwr neu cyfeiriad IP wedi gael eu blocio gan $1. Y rheswm yw:<br />''$2''<p>Ellwch cysylltu $1 neu un o'r
+[[Wicipedia:administrators|swyddogion]] eraill i trafodi'r bloc.",
+"whitelistedittitle" => "Rhaid mewngofnodi i golygu",
+"whitelistedittext" => "Rhaid i chi [[Special:Userlogin|mewngofnodi]] i olygu erthyglau.",
+"whitelistreadtitle" => "Rhaid mewngofnodi i ddarllen",
+"whitelistreadtext" => "Rhaid i chi [[Special:Userlogin|mewngofnodi]] i ddarllen erthyglau.",
+"whitelistacctitle" => "Ni chaniateir creu accownt",
+"whitelistacctext" => "I gael caniatâd i creu accownt yn y wiki hon, rhaid i chi [[Special:Userlogin|mewngofnodi]] a chael y caniatâd priodol.",
+"accmailtitle" => "Wedi danfon cyfrinair.",
+"accmailtext" => "Mae'r cyfrinair am '$1' wedi danfon i $2.",
+"newarticle" => "(Newydd)",
+"newarticletext" =>
+"Yr ydych wedi dilyn cysylltiad i tudalen sydd ddim wedi gael eu creu eto.
+I creuo'r tudalen, dechreuwch teipio yn y bocs isaf
+(gwelwch y [[Wicipedia:Help|tudalen help]] am mwy o hysbys).
+Os ydych yma trwy camgymeriad, cliciwch eich botwm '''nol'''.",
+"anontalkpagetext" => "---- ''Dyma tudalen sgwrsio am defnyddwr sydd ddim eto wedi creu accownt, neu ddim yn eu defnyddio. Rhaid i ni defnyddio'r [[cyfeiriad IP]] rhifiadol i adnabod fe neu hi. Mae'n posib i llawer o bobl siario'r un cyfeiriad IP. Os ydych chi'n defnyddwr anhysbys ac yn teimlo mae esboniadau amherthynol wedi cael eu gwneud arnach chi, creuwch accownt neu mewngofnodwch i osgoi anhrefn gyda defnyddwyr anhysbys yn y dyfodol.'' ",
+"noarticletext" => "(Does dim testun yn y tudalen hon eto)",
+"updated" => "(Diweddariad)",
+"note" => "<strong>Sylwch:</strong> ",
+"previewnote" => "Cofiwch blaenwelediad ydi hwn, a dydi e ddim wedi cael eu chadw!",
+"previewconflict" => "Mae blaenwelediad hwn yn dangos y testun yn yr ardal golygu uchaf, fel y fydd hi'n edrych os dewyswch chi arbed.",
+"editing" => "Yn golygu $1",
+"editingsection" => "Yn golygu $1 (rhan)",
+"editingcomment" => "Yn golygu $1 (esboniad)",
+"editconflict" => "Croestynnu golygyddol: $1",
+"explainconflict" => "Mae rhywun arall wedi newid y tudalen hon ers i chi dechrau golygu hi. Mae'r ardal testun uchaf yn cynnwys testun y tudalen fel y mae hi rwan. Mae eich newidiadau yn ddangos yn yr ardal testun isaf.
+Fydd rhaid i chi ymsoddi eich newidiadau i mewn i'r testun sydd mewn bod.
+<b>Dim ond</b> y testun yn yr ardal testun uchaf fydd yn cael eu cadw pan rydwch yn gwasgu \"Cadw tudalen\".<br />",
+"yourtext" => "Eich testun",
+"storedversion" => "Fersiwn wedi cadw",
+"editingold" => "<strong>RHYBUDD: Rydych yn golygu hen fersiwn y tudalen hon. Os cadwch hi, fydd unrhyw newidiadau hwyrach yn gael eu colli!.</strong>",
+"yourdiff" => "Gwahaniaethau",
+"copyrightwarning" => "Sylwch mae pob cyfraniad i Wicipedia yn gael eu rhyddhau o dan termau'r Trwydded Dogfen Rhydd GNU (gwelwch $1 am manylion).
+Os nid ydych chi'n fodlon cael eich ysgrifeniad eu golygu heb trugaredd, a creu copïau dros y wê, peidiwch cyfranu'r ysgrifeniad yma.<br />
+Hefyd, rydych chi'n addo chi yw'r awdur y cyfraniad, neu rydych chi wedi copïo fe oddiwrth y parth cyhoeddus neu rhyw modd rhydd tebyg.
+<strong>PEIDIWCH CYFRANNU GWAITH O DAN HAWLFRAINT HEB CANIATÂD!</strong>",
+"longpagewarning" => "<strong>RHYBUDD: Mae hyd y tudalen hon yn $1 kilobyte; mae rhai porwyr yn cael problemau yn golygu tudalennau hirach na 32kb.<br />
+Ystyriwch torri'r tudalen i mewn i ddarnau llai, os gwelwch yn dda.</strong>",
+"readonlywarning" => "<strong>RHYBUDD: Mae'r databas wedi cloi i gael eu trwsio,
+felly fyddwch chi ddim yn medru cadw eich olygiadau rwan. Efalle fyddwch chi'n eisio tori-a-pastio'r
+testun i mewn i ffeil testun, a cadw hi tan hwyrach.</strong>",
+"protectedpagewarning" => "<strong>RHYBUDD:  Mae tudalen hon wedi eu gloi -- dim ond defnyddwyr
+gyda braintiau 'sysop' sy'n medru eu olygu. Byddwch yn siwr rydych yn dilyn y
+[[Project:Protected_page_guidelines|gwifrau tywys tudalen amddiffyn]].</strong>",
+
+# History pages
+#
+"revhistory" => "Hanes cywiriadau",
+"nohistory" => "Does dim hanes cywiriadau am tudalen hon.",
+"revnotfound" => "Cywiriad nid wedi darganfod",
+"revnotfoundtext" => "Ni ellir darganfod yr hen cywiriad y tudalen rydych wedi gofyn amdano. Gwiriwch yr URL rydych wedi defnyddio i darganfod y tudalen hon.\n",
+"loadhist" => "Yn llwytho hanes y tudalen",
+"currentrev" => "Diwygiad cyfoes",
+"revisionasof" => "Diwygiad $1",
+"cur" => "cyf",
+"next" => "nesaf",
+"last" => "olaf",
+"orig" => "gwreidd",
+"histlegend" => "Eglurhad: (cyf) = gwahaniaeth gyda fersiwn cyfoes,
+(olaf) = gwahaniaeth gyda fersiwn gynt, M = golygiad mân",
+
+# Diffs
+#
+"difference" => "(Gwahaniaethau rhwng fersiwnau)",
+"loadingrev" => "yn llwytho diwygiad am wahaniaeth",
+"lineno" => "Llinell $1:",
+"editcurrent" => "Golygwch fersiwn cyfoes tudalen hon",
+
+# Search results
+#
+"searchresults" => "Canlyniadau chwiliad",
+"searchresulttext" => "Am mwy o hysbys amdano chwilio Wicipedia, gwelwch [[Wicipedia: Yn chwilio|Yn chwilio Wicipedia]].",
+"searchquery" => "Am gofyniad \"$1\"",
+"badquery" => "Gofyniad chwilio drwg",
+"badquerytext" => "Roedd yn amhosibl i prosesu'ch gofyniad.
+Mae'n tebygol roedd hyn am achos yr ydych wedi trio chwilio a gair gyda llai na tri llythyrau. Hefyd, wyrach rydych wedi cam-teipio'r gofyniad. Triwch gofyniad arall.",
+"matchtotals" => "Mae'r gofyniad \"$1\" wedi cyfatebu $2 teitlau erthyglau, a'r testun oddiwrth $3 erthyglau.",
+"nogomatch" => "Does dim erthygl gyda'r union teitl hon, yn trio chwiliad testun cyfan. ",
+"titlematches" => "Teitlau erthygl yn cyfateb",
+"notitlematches" => "Does dim teitlau erthygl yn cyfateb",
+"textmatches" => "Testun erthygl yn cyfateb",
+"notextmatches"        => "Does dim testun erthyglau yn cyfateb",
+"prevn"        => "$1 gynt",
+"nextn"        => "$1 nesaf",
+"viewprevnext" => "Gweler ($1) ($2) ($3).",
+"showingresults" => "Yn dangos isod y <b>$1</b> canlyniadau yn dechrau gyda #<b>$2</b>.",
+"nonefound" => "<strong>Sylwch</strong>: mae chwiliadau yn aml yn anlwyddiannus am achos mae'r chwiliad yn edrych a geiriau cyffredin fel \"y\" ac \"ac\",
+sydd ddim yn cael eu mynegai.",
+"powersearch" => "Chwilio",
+"powersearchtext" => "
+Edrychwch mewn lle-enw:<br />
+$1<br />
+$2 Rhestrwch ail-cyfeiriadau &nbsp; Chwiliwch am $3 $9",
+"searchdisabled" => "<p>Mae'r peiriant chwilio'r holl databas wedi cael eu troi i ffwrdd i gwneud pethau'n hawddach ar y gwasanaethwr. Gobeithiwn fydd yn bosibl i troi'r peiriant ymlaen cyn bo hir, ond yn y cyfamser mae'n posibl gofyn Google:</p>",
+"blanknamespace" => "(Prif)",
+
+
+# Preferences page
+#
+"preferences" => "ffafraethau",
+"prefsnologin" => "Nid wedi mewngofnodi",
+"prefsnologintext" => "Rhaid i chi [[Special:Userlogin|mewngofnodi]]
+i setio ffafraethau defnyddwr.",
+"prefslogintext"  => "Yr ydych wedi mewngofnodi fel \"$1\".
+$2 yw eich rhif hunaniaith mewnol.",
+"prefsreset" => "Mae ffafraethau wedi gael eu ail-setio oddiwrth y storfa.",
+"qbsettings" => "Gosodiadau bar-gyflym",
+"changepassword" => "Newydwch allweddair",
+"skin" => "Croen",
+"math" => "Rendro mathemateg",
+"math_failure" => "wedi methu dosbarthu",
+"math_unknown_error" => "gwall anhysbys",
+"math_unknown_function"        => "ffwythiant anhysbys ",
+"math_lexing_error" => "gwall lecsio",
+"math_syntax_error" => "gwall cystrawen",
+"saveprefs" => "Cadw ffafraethau",
+"resetprefs" => "Ail-setio ffafraethau",
+"oldpassword" => "Hen allweddair",
+"newpassword" => "Allweddair newydd",
+"retypenew" => "Ail-teipiwch yr allweddair newydd",
+"textboxsize" => "Maint y bocs testun",
+"rows" => "Rhesi",
+"columns" => "Colofnau",
+"searchresultshead" => "Sefydliadau canlyniadau chwilio",
+"resultsperpage" => "Hitiau i ddangos ar pob tudalen",
+"contextlines" => "Llinellau i ddangos ar pob hit",
+"contextchars" => "Characters of context per line",
+"stubthreshold" => "Threshold for stub display",
+"recentchangescount" => "Nifer o teitlau yn newidiadau diweddar",
+"savedprefs" => "Mae eich ffafraethau wedi cael eu chadw.",
+"timezonetext" => "Teipiwch y nifer o oriau mae eich amsel lleol yn wahân o'r amser y gwasanaethwr (UTC/GMT).",
+"localtime" => "Amser lleol",
+"timezoneoffset" => "Atred",
+"servertime" => "Amser y gwasanaethwr yw",
+"guesstimezone" => "Llenwch oddiwrth y porwr",
+"emailflag" => "Anablo e-bost oddiwrth defnyddwyr eraill",
+"defaultns" => "Gwyliwch yn llefydd-enw rhain:",
+
+# Recent changes
+#
+"changes" => "newidiadau",
+"recentchanges" => "Newidiadau diweddar",
+"recentchangestext" => "Traciwch y newidiadau mor diweddar i'r Wicipedia ac i'r tudalen hon.",
+"rcloaderr" => "Yn llwytho newidiadau diweddar",
+"rcnote" => "Isod yw'r newidiadau <strong>$1</strong> olaf yn y <strong>$2</strong> dyddiau olaf.",
+"rcnotefrom" => "Isod yw'r newidiadau ers <b>$2</b> (dangosir i fynu i <b>$1</b>).",
+"rclistfrom" => "Dangos newidiadau newydd yn dechrau oddiwrth $1",
+# "rclinks" => "Dangos y $1 newidiadau olaf yn y $2 oriau olaf / $3 dyddiau olaf",
+"showhideminor" => "$1 golygiadau bach | $2 botiau | $3 defnyddwyr wedi mewngofnodi | $4 patrolled edits",
+"rclinks" => "Dangos y $1 newidiadau olaf yn y $2 dyddiau olaf.",
+"rchide" => "yn ffurf $4; $1 golygiadon bach; $2 llefydd enw eilaidd; $3 golygiadon lluosrif.",
+"rcliu"        => "; $1 golygiadau gan defnyddwyr wedi mewngofnodi",
+"diff" => "gwahan",
+"hist" => "hanes",
+"hide" => "cuddio",
+"show" => "dangos",
+"tableform" => "taflen",
+"listform" => "rhestr",
+"nchanges" => "$1 newidiadau",
+"minoreditletter" => "B",
+"newpageletter" => "N",
+
+# Upload
+#
+"upload" => "Llwytho ffeil i fynu",
+"uploadbtn" => "Llwytho ffeil i fynu",
+"uploadlink" => "Llwytho lluniau i fynu",
+"reupload" => "Ail-llwytho i fynu",
+"reuploaddesc" => "Return to the upload form.",
+"uploadnologin" => "Nid wedi mewngofnodi",
+"uploadnologintext" => "Rhaid i chi bod wedi [[Special:Userlogin|mewngofnodi]]
+i lwytho ffeiliau i fynu.",
+"uploaderror" => "Gwall yn llwytho ffeil i fynu",
+"uploadtext" => "'''STOPIWCH!''' Cyn iddich chi llwytho lluniau yma, darllenwch a dilynwch [[Project:Polisi_defnyddio_lluniau|polisi defnyddio lluniau]] Wicipedia os gwelwch yn dda.
+
+I gweld neu chwilio hen lluniau ewch i'r
+[[Arbennig:Imagelist|rhestr lluniau wedi llwytho]].
+Mae pob llwyth a dileuo ffeil yn cael eu recordio ar y
+[[Project:Upload_log||log llwytho]].
+
+Defnyddwch y ffurflen isod i llwytho ffeil llun newydd i darluno eich erthyglau.
+Ar y mwyafrif o porwyr, fyddwch yn gweld botwm \"Pori/Browse...\" i agor y dialog agor ffeil arferol.
+Fydd dewis ffeil y llenwi enw'r ffeil yn y cae testun nesaf i'r botwm.
+Mae rhaid i chi hefyd ticio'r blaidd i addo rydych chi ddim yn torri hawlfraintiau rhywun arall trwy llwytho'r ffeil.
+Gwasgwch y botwm \"Llwytho/Upload\" i gorffen y llwyth.
+Ellith hwn cymyd dipyn o amser os mae gennych chi cysylltiad rhyngrwyd araf.
+
+Y fformatiau gwell gennym ni yw JPEG am lluniau ffotograffiaeth, PNG
+am lluniadau a delweddau iconydd eraill, ag OGG am seiniau.
+Enwch eich ffeil yn disgrifiadol i osgoi anhrefn os gwelwch yn dda.
+I cynnwys y llun mewn erthygl, defnyddwch cysylltiad yn y ffurf
+'''<nowiki>[[llun:ffeil.jpg]]</nowiki>''' neu
+'''<nowiki>[[llun:ffeil.png|testun arall]]</nowiki>''' neu
+'''<nowiki>[[media:ffeil.ogg]]</nowiki>''' am sain.
+
+Sylwch -- fel efo tudalennau Wicipedia, ellith pobl eraill golygu neu dileu eich ffeil os ydyn nhw'n meddwl fyddynt yn helpu'r gwyddoniadur, ac ellwch chi cael eich gwaharddio os ydych chi'n sarhau'r system.",
+"uploadlog" => "log llwytho i fynu",
+"uploadlogpage" => "log_llwytho_i_fynu",
+"uploadlogpagetext" => "Isod mae rhestr o'r llwythu ffeil diweddarach.
+Pob amser sy'n dangos yw amser y gwasanaethwr (UTC).
+<ul>
+</ul>
+",
+"filename" => "Enw ffeil",
+"filedesc" => "Crynodeb",
+"filestatus" => "Statws hawlfraint",
+"filesource" => "Ffynhonnell",
+"copyrightpage" => "{{ns:project}}:Hawlfraint",
+"copyrightpagename" => "Hawlfraint {{SITENAME}}",
+"uploadedfiles"        => "Ffeiliau wedi llwytho i fynu",
+"ignorewarning"        => "Anwybyddwch y rhybudd, a chadwch y tudalen beth bynnag.",
+"minlength" => "Rhaid enwau lluniau bod o leia tri llythrennau.",
+"badfilename" => "Mae enw'r llun wedi newid i \"$1\".",
+"badfiletype" => "Nid yw \".$1\" yn fformat ffeil lluniau cymeradwy.",
+"largefile" => "Mae'n cymeradwy dydy lluniau nid mwy na 100k o faint.",
+"successfulupload" => "Llwyth i fynu yn llwyddiannus",
+"fileuploaded" => "Mae ffeil \"$1\" wedi llwytho'n llwyddiannnus.
+Dilynwch y cyswllt hon: ($2) i'r tudalen disgrifiad a llenwch gwybodaeth amdano'r ffeil (ble mae'n dod o, pwy a creu o, beth bynnag arall rydych chi'n gwybod amdano'r ffeil.",
+"uploadwarning" => "Rhybudd llwytho i fynu",
+"savefile" => "Cadw ffeil",
+"uploadedimage" => "\"[[$1]]\" wedi llwytho",
+"uploaddisabled" => "Mae ddrwg gennym ni, mae uwchllwytho wedi anablo.",
+
+# Image list
+#
+"imagelist" => "Rhestr delweddau",
+"imagelisttext"        => "Isod mae rhestr o $1 delweddau wedi trefnu $2.",
+"getimagelist" => "yn nôl rhestr delweddau",
+"ilsubmit" => "Chwilio",
+"showlast" => "Dangos y $1 delweddau olaf wedi trefnu $2.",
+"byname" => "gan enw",
+"bydate" => "gan dyddiad",
+"bysize" => "gan maint",
+"imgdelete" => "difl",
+"imgdesc" => "disg",
+"imglegend" => "Eglurhad: (disg) = dangos/golygu disgrifiad y delwedd.",
+"imghistory" => "Hanes y delwedd",
+"revertimg" => "dych",
+"deleteimg" => "dil",
+"deleteimgcompletely" => "dil",
+"imghistlegend" => "Eglurhad: (cyf) = hon yw'r delwedd cyfoes, (dil) = dilewch yr hen fersiwn hon, (dych) = dychwelio i hen fersiwn hon.
+<br /><i>Cliciwch ar dyddiad i weld y delwedd ag oedd llwythiad ar y dyddiad hon</i>.",
+"imagelinks" => "Cysylltiadau delwedd",
+"linkstoimage" => "Mae'r tudalennau isod yn cysylltu i'r delwedd hon: ",
+"nolinkstoimage" => "Does dim tudalen yn cysylltu i'r  delwedd hon. ",
+
+# Statistics
+#
+"statistics" => "Ystadegau",
+"sitestats" => "Ystadegau'r seit",
+"userstats" => "Ystadegau defnyddwyr",
+"sitestatstext" => "Mae <b>$1</b> tudalennau ar y databas.
+Mae hyn yn cynnwys tudalennau \"sgwrs\", tudalennau amdano Wicipedia, tudalennau \"stwbyn\" bach, ail-cyfeirnodau, ac eraill sydd dim yn cymwysoli fel erthyglau. Ag eithrio y rheini, mae <b>$2</b> tudalennau yn tebyg yn erthyglau iawn.<p>
+Mae 'ne wedi bod <b>$3</b> golygon o tudalennau, a <b>$4</b> tudalennau wedi golygu ers i'r meddalwedd gael eu sefydliad (12 Gorffennaf 2003).
+Sef <b>$5</b> golygiadau pob tudalen, ar gyfartaledd, a <b>$6</b> golygon o bob golygiad.",
+"userstatstext" => "Mae 'ne <b>$1</b> defnyddwyr wedi cofrestru.
+(Mae <b>$2</b> yn gweinyddwyr (gwelwch $3)).",
+
+# Miscellaneous special pages
+#
+"orphans" => "Erthyglau heb cysylltiadau",
+"lonelypages" => "Erthyglau heb cysylltiadau",
+"unusedimages" => "Lluniau di-defnyddio",
+"popularpages" => "Erthyglau poblogol",
+"nviews" => "$1 golwgfeydd",
+"wantedpages" => "Erthyglau mewn eisiau",
+"nlinks" => "$1 cysylltiadau",
+"allpages" => "Pob tudalennau",
+"randompage" => "Erthygl hapgyrch",
+"shortpages" => "Erthyglau byr",
+"longpages" => "Erthyglau hir",
+"deadendpages" => "Tudalennau heb cysylltiadau",
+"listusers" => "Rhestr defnyddwyr",
+"specialpages" => "Erthyglau arbennig",
+"spheading" => "Erthyglau arbennig",
+"protectpage" => "Sicrhau erthygl",
+"recentchangeslinked" => "Newidiadau perthnasol",
+"rclsub" => "(i erthyglau cysyllt oddiwrth \"$1\")",
+"debug"        => "Debug",
+"newpages" => "Erthyglau newydd",
+"ancientpages" => "Erthyglau hynach",
+"intl" => "Cysylltiadau rhwng ieithau",
+"movethispage" => "Symydwch tudalen hon",
+"unusedimagestext" => "<p>Sylwch mae gwefannau eraill, e.e. y Wicipediau Rhwngwladol, yn medru cysylltu at llun gyda URL uniongychol, felly mae'n bosibl dangos enw ffeil yma er gwaethaf mae hi'n dal mewn iws.",
+"booksources" => "Ffynonellau llyfrau",
+"booksourcetext" => "Isod mae rhestr cysylltiadau i gwefannau eraill sydd yn gwerthu llyfrau newydd ac ail-law, ac wyrach mae ganddynt gwybodaeth am y llyfrau rydych yn chwilio amdano.
+Does gan Wicipedia dim cysylltiad gyda unrhyw o'r masnachau, a dydy rhestr hon ddim yn cymeradwyaeth o honnynt.",
+"alphaindexline" => "$1 i $2",
+"version" => "Fersiwn",
+
+# Email this user
+#
+"mailnologin" => "Dim cyfeiriad i anfon",
+"mailnologintext" => "Rhaid i chi wedi [[Arbennig:Mewngofnodidefnyddwr|mewngofnodi]]
+a rhoi cyfeiriad e-bost dilyn yn eich [[Arbennig:Ffafraethau|ffafraethau]]
+i anfon e-bost i ddefnyddwyr eraill.",
+"emailuser" => "Anfon e-bost i defnyddwr hwn",
+"emailpage" => "Anfon e-bost i defnyddwr",
+"emailpagetext"         => "Os yw defnyddwr hwn wedi rhoi cyfeiriad e-bost yn eu ffafraethau, fydd y ffurf isod yn anfon un neges iddo ef. Fydd y cyfeiriad e-bost rydych chi wedi rhoi yn eich ffafraethau yn dangos yn yr \"Oddiwrth\" cyfeiriad yr e-bost, felly fydd y defnyddwr arall yn gallu ateb.",
+"defemailsubject" => "e-post {{SITENAME}}",
+"noemailtitle" => "Dim cyfeiriad e-bost",
+"noemailtext" => "Dydy defnyddwr hwn ddim wedi rhoi cyfeiriad e-bost dilys, neu mae e wedi dewis nid i dderbyn e-bost oddiwrth defnyddwyr eraill.",
+"emailfrom" => "Oddiwrth",
+"emailto" => "I",
+"emailsubject" => "Pwnc",
+"emailmessage" => "Neges",
+"emailsend" => "Anfon",
+"emailsent" => "Neges e-bost wedi danfon",
+"emailsenttext" => "Mae eich neges e-bost wedi gael ei anfon.",
+
+# Watchlist
+#
+"watchlist" => "Fy rhestr gwylio",
+"watchlistsub" => "(am defnyddwr \"$1\")",
+"nowatchlist"  => "Does ganddoch chi ddim eitem ar eich rhestr gwylio.",
+"watchnologin" => "Dydych chi ddim wedi mewngofnodi",
+"watchnologintext" => "Rhaid i chi bod wedi [[Special:Userlogin|mewngofnodi]]
+i adnewid eich rhestr gwylio.",
+"addedwatch" => "Wedi adio i'ch rhestr gwylio",
+"addedwatchtext" => "Mae tudalen \"$1\" wedi gael eu ychwanegu i eich <a href=\"" .
+  "{{localurle:Arbennig:Rhestr_gwylio}}\">rhestr gwylio</a>.
+Pan fydd y tudalen hon, a'i tudalen Sgwrs, yn newid, fyddynt yn dangos  <b>yn cryf</b> yn y <a href=\"" .
+  "{{localurle:Arbennig:Newidiadau_diweddar}}\">rhestr newidiadau diweddar</a>, i bod yn hawsach i gweld.</p>
+
+<p>Os ydych chi'n eisiau cael gwared ar y tudalen yn hwyrach, cliciwch ar \"Stopiwch gwylio\" yn y bar ar y chwith.",
+"removedwatch" => "Wedi diswyddo oddiwrth y rhestr gwylio",
+"removedwatchtext" => "Mae tudalen \"$1\" wedi cael ei diswyddo oddiwrth eich rhestr gwylio.",
+"watchthispage"        => "Gwyliwch y tudalen hon",
+"unwatchthispage" => "Stopiwch gwylio",
+"notanarticle" => "Nid erthygl",
+"watchnochange" => "Does dim o'r erthyglau rydych chi'n gwylio wedi golygu yn yr amser sy'n dangos.",
+"watchdetails" => "(Yn gwylio $1 tudalennau, nid yn cyfri tudalennau sgwrs;
+wedi olygu $2 tudalennau ers y toriad;
+$3...
+[$4 dangos ac olygu y rhestr cyfan].)",
+"watchmethod-recent"=> "gwiriwch golygiadau diweddar am tudalennau gwyliad",
+"watchmethod-list" => "yn gwirio tudalennau gwyliad am olygiadau diweddar",
+"removechecked" => "Dileuwch eitemau sydd gyda tic o'ch rhestr gwylio",
+"watchlistcontains" => "Mae eich rhestr gwylio yn cynnwys $1 tudalennau.",
+"watcheditlist"        => "Dyma rhestr wyddorol o'r tudalennau rydych yn wylio.
+Ticiwch blwchau y tudalennau rydych eisiau symud o'ch rhestr gwylio, a cliciwch
+y botwm 'dileu' ar gwaelod y sgrîn.",
+"removingchecked" => "Yn dileu'r eitemau rydych wedi gofyn o'ch rhestr gwylio...",
+"couldntremove" => "Wedi methu dileu eitem '$1'...",
+"iteminvalidname" => "Problem gyda eitem '$1', enw annilys...",
+"wlnote" => "Isod yw'r $1 newidiadau olaf yn y <b>$2</b> oriau diwethaf.",
+"wlshowlast" => "Dangos y $1 oriau $2 dyddiau $3 diwethaf",
+"wlsaved" => "Dyma copi o'ch rhestr gwylio rydym ni wedi cadw.",
+
+# Delete/protect/revert
+#
+"deletepage" => "Dileuwch y tudalen",
+"confirm" => "Cadarnhau",
+"excontent" => "y cynnwys oedd: '$1'",
+"exbeforeblank" => "y cynnwys cyn blancio oedd: '$1'",
+"exblank" => "y tudalen oedd yn wâg",
+"confirmdelete" => "Cadarnhaewch y dileuad",
+"deletesub" => "(Yn dileuo \"$1\")",
+"historywarning" => "Rhubydd: Mae hanes gan y tudalen yr ydych yn mynd i dileuo: ",
+"confirmdeletetext" => "Rydych chi'n mynd i dileu erthygl neu llun yn parhaol, hefyd gyda'u hanes, oddiwrth y databas.
+Cadarnhaewch yr ydych yn bwriadu gwneud hwn, ac yr ydych yn ddeallt y canlyniad, ac yr ydych yn gwneud hwn yn ôl [[Wicipedia:Polisi]].",
+"actioncomplete" => "Gweithred llwyr",
+"deletedtext" => "Mae \"$1\" wedi eu dileu.
+Gwelwch $2 am cofnod o dileuon diweddar.",
+"deletedarticle" => "wedi dileu \"$1\"",
+"dellogpage" => "Log_dileuo",
+"dellogpagetext" => "Isod mae rhestr o'r dileuon diweddarach.
+<ul>
+</ul>
+",
+"deletionlog" => "Log dileuon",
+"reverted" => "Wedi mynd nôl i fersiwn gynt",
+"deletecomment"        => "Achos dileuad",
+"imagereverted" => "Gwrthdroad i fersiwn gynt yn llwyddiannus.",
+"rollback" => "Roliwch golygon yn ôl",
+"rollbacklink" => "rolio nôl",
+"cantrollback" => "Ddim yn gallu gwrthdroi golygiad; y cyfrannwr olaf oedd yr unrhyw awdur yr erthygl hon.",
+"alreadyrolled"        => "Amhosib rolio nôl golygiad olaf [[$1]]
+gan [[Defnyddwr:$2|$2]] ([[Sgwrs defnyddwr:$2|Sgwrs]]); mae rhywun arall yn barod wedi olygu neu rolio nôl yr erthygl.
+
+[[Defnyddwr:$3|$3]] ([[Sgwrs defnyddwr:$3|Sgwrs]] gwneuthoedd yr olygiad olaf). ",
+#   only shown if there is an edit comment
+"editcomment" => "Crynodeb y golygiad oedd: \"<i>$1</i>\".",
+"revertpage" => "Wedi gwrthdroi i golygiad olaf gan $1",
+"protectlogpage" => "Log_amdiffyno",
+"protectlogtext" => "Isod mae rhestr o cloion/datgloion tudalennau.
+Gwelwch [[{{ns:project}}:Tudalen amddiffynol]] am mwy o wybodaeth.",
+"protectedarticle" => "wedi amddiffyno [[$1]]",
+"unprotectedarticle" => "wedi di-amddiffyno [[$1]]",
+
+# Undelete
+"undelete" => "Gwrthdroi tudalen wedi dileuo",
+"undeletepage" => "Gwyliwch ac adferiwch tudalennau wedi dileuo",
+"undeletepagetext" => "Mae'r tudalennau isod wedi cael eu dileuo ond mae nhw'n dal yn yr archif ac maen bosibl adferio nhw. Mae'r archif yn cael eu glanhau o dro i dro.",
+"undeletearticle" => "Adferiwch erthygl wedi dileu",
+"undeleterevisions" => "$1 fersiwnau yn yr archif",
+"undeletehistory" => "Os adferiwch y tudalen, fydd holl y fersiwnau yn gael eu adferio yn yr hanes. Os mae tudalen newydd wedi gael eu creu ers i'r tudalen bod yn dileu, fydd y fersiwnau adferol yn dangos yn yr hanes gynt ond ni fydd y fersiwn cyfoes yn gael eu allosodi.",
+"undeleterevision" => "wedi dileu fersiwn $1",
+"undeletebtn" => "Adferiwch!",
+"undeletedarticle" => "wedi adferio \"$1\"",
+
+"undeletedtext" => "Mae'r erthygl [[$1]] wedi cael eu adferio'n llwyddiannus.
+Gwyliwch [[Wicipedia:Log_dileuon]] am record dileuon ac adferion diweddar.",
+
+# Contributions
+#
+"contributions"        => "Cyfraniadau defnyddwr",
+"mycontris" => "Fy nghyfraniadau",
+"contribsub" => "Dros $1",
+"nocontribs" => "Dim wedi dod o hyd i newidiadau gyda criterion hyn.",
+"ucnote" => "Isod mae y <b>$1</b> newidiadau yn y <b>$2</b> dyddiau olaf am defnyddwr hwn.",
+"uclinks" => "Gwelwch y $1 newidiadau olaf; gwelwch y $2 dyddiau olaf.",
+"uctop"        => " (top)" ,
+
+# What links here
+#
+"whatlinkshere"        => "Beth sy'n cysylltu yma",
+"notargettitle" => "Dim targed",
+"notargettext" => "Dydych chi ddim wedi dewis tudalen targed neu defnyddwr.",
+"linklistsub"  => "(Rhestr cysylltiadau)",
+"linkshere" => "Mae'r tudalennau isod yn cysylltu yma:",
+"nolinkshere" => "Does dim tudalennau yn cysylltu yma.",
+"isredirect" => "tudalen ail-cyfeirnod",
+
+# Block/unblock IP
+#
+"blockip" => "Blociwch cyfeiriad IP",
+"blockiptext" => "Defnyddwch y ffurflen isod i blocio mynedfa ysgrifenol oddiwrth cyfeiriad IP cymharol.
+Ddylwch dim ond gwneud hwn i stopio fandaliaeth, yn dilyn a  [[Wicipedia:Polisi|polisi Wicipedia]].
+Llenwch rheswm am y bloc, isod (e.e. enwch y tudalennau a oedd wedi fandalo).",
+"ipaddress" => "Cyfeiriad IP",
+"ipbexpiry" => "Diwedd",
+"ipbreason" => "Achos",
+"ipbsubmit" => "Blociwch y cyfeiriad hwn",
+"badipaddress" => "Dydy'r cyfeiriad IP ddim yn ddilys.",
+"blockipsuccesssub" => "Bloc yn llwyddiannus",
+"blockipsuccesstext" => "Mae cyfeiriad IP \"$1\" wedi cael eu blocio.
+<br />Gwelwch [[Arbennig:Ipblocklist|rhestr bloc IP]] i arolygu blociau.",
+"unblockip" => "Di-blociwch cyfeiriad IP",
+"unblockiptext"        => "Defnyddwch y ffurflen isod i di-blocio mynedfa ysgrifenol i cyfeiriad IP sydd wedi cael eu blocio'n gynt.",
+"ipusubmit" => "Di-blociwch y cyfeiriad hwn",
+"ipusuccess" => "Cyfeiriad IP \"$1\" wedi di-blocio",
+"ipblocklist" => "Rhestr cyfeiriadau IP wedi blocio",
+"blocklistline"        => "$1, $2 wedi blocio $3 ($4)",
+"blocklink" => "bloc",
+"unblocklink" => "di-bloc",
+"contribslink" => "cyfraniadau",
+"autoblocker" => "Wedi cloi'n awtomatig am achos rydych chi'n rhannu cyfeiriad IP gyda \"$1\". Rheswm \"$2\".",
+"blocklogpage" => "Log_blociau",
+"blocklogentry"        => 'wedi blocio "$1" efo amser diwedd o $2',
+"blocklogtext" => "Dyma log o pryd mae cyfeiriadau wedi cael eu blocio a datblocio. Dydy cyfeiriad
+a sydd wedi blocio'n awtomatig ddim yn cael eu ddangos yma. Gwelwch [[Special:Ipblocklist|rhestr block IP]] am
+y rhestr o blociau a gwaharddiadau sydd yn effeithiol rwan.",
+"unblocklogentry" => 'wedi datblocio "$1"',
+"range_block_disabled" => "Mae gallu sysop i creu dewis o blociau wedi anablo.",
+"ipb_expiry_invalid" => "Amser diwedd ddim yn dilys.",
+"ip_range_invalid" => "Dewis IP annilys.\n",
+
+
+# Make sysop
+"makesysoptitle" => "Gwnewch sysop allan o defnyddiwr",
+"makesysoptext"        => "Defnyddiwch y ffurflen hon i troi defnyddiwr cyffredin i gweinyddwr.
+Teipiwch enw'r defnyddiwr yn y blwch a cliciwch y botwm i troi'r defnyddiwr i gweinyddwr",
+"makesysopname"        => "Enw'r defnyddiwr:",
+"makesysopsubmit" => "Gwnewch y defnyddiwr hwn yn gweinyddwr",
+"makesysopok" => "<b>Mae defnyddwr '$1' rwan yn gweinyddwr</b>",
+"makesysopfail"        => "<b>Wedi methu troi defnyddwr '$1' i gweinyddwr. (Ydych chi wedi sillafu'r enw'n iawn?)</b>",
+"setbureaucratflag" => "Gosod y fflag biwrocrat",
+"bureaucratlog"        => "Log_biwrocrat",
+"bureaucratlogentry" => " gosod $1: $2",
+
+# Move page
+#
+"movepage" => "Symud tudalen",
+"movepagetext" => "Fydd defnyddio'r ffurflen isod yn ail-enwi tudalen, symud eu hanes gyfan i'r enw newydd.
+Fydd yr hen teitl yn dod tudalen ail-cyfeiriad i'r teitl newydd.
+Ni fydd cysylltiadau i'r hen teitl yn newid; mae rhaid i chi gwirio mae cysylltau'n dal yn mynd i'r lle mae angen iddyn nhw mynd!
+
+Sylwch fydd y tudalen '''ddim''' yn symud os mae 'ne tudalen efo'r enw newydd yn barod ar y databas (sef os mae hi'n gwâg neu yn ail-cyfeiriad heb unrhyw hanes golygu). Mae'n posibl i chi ail-enwi tudalen yn ôl i lle oedd hi os ydych chi wedi gwneud camgymeriad, ac mae'n amhosibl i ysgrifennu dros tudalen sydd barod yn bodoli.
+
+<b>RHYBUDD!</b>
+Ellith hwn bod newid sydyn a llym i tudalen poblogol; byddwch yn siwr rydych chi'n deallt y canlyniadau cyn iddich chi mynd ymlaen gyda hwn.",
+"movepagetalktext" => "Fydd y tudalen sgwrs , os oes ne un, yn symud gyda tudalen hon '''ac eithrio:'''
+*rydych yn symud y tudalen wrth llefydd-enw,
+*mae tudalen sgwrs di-wâg yn barod efo'r enw newydd, neu
+*rydych chi'n di-ticio'r blwch isod.",
+"movearticle" => "Symud tudalen",
+"movenologin" => "Nid wedi mewngofnodi",
+"movenologintext" => "Rhaid i chi bod defnyddwr cofrestredig ac wedi [[Arbennig:Userlogin|mewngofnodi]]
+to move a page.",
+"newtitle" => "i teitl newydd",
+"movepagebtn" => "Symud tudalen",
+"pagemovedsub" => "Symud yn llwyddiannus",
+"pagemovedtext" => "Mae tudalen \"[[$1]]\" wedi symud i \"[[$2]]\".",
+"articleexists" => "Mae tudalen gyda'r enw newydd yn bodoli'n barod, neu mae eich enw newydd ddim yn dilys.
+Dewiswch enw newydd os gwelwch yn dda.",
+"talkexists" => "Mae'r tudalen wedi symud yn llwyddiannus, ond roedd hi'n amhosibl symud y tudalen sgwrs am achos roedd ne un efo'r teitl newydd yn bodoli'n barod. Cysylltwch nhw eich hun, os gwelwch yn dda.",
+"movedto" => "symud i",
+"movetalk" => "Symud tudalen \"sgwrs\" hefyd, os oes un.",
+"talkpagemoved" => "Mae'r tudalen sgwrs hefyd wedi symud.",
+"talkpagenotmoved" => "Dydy'r tudalen sgwrs <strong>ddim</strong> wedi symud.",
+"1movedto2" => "$1 wedi symud i $2",
+
+# Export
+
+"export" => "Export pages",
+"exporttext" => "You can export the text and editing history of a particular
+page or set of pages wrapped in some XML; this can then be imported into another
+wiki running MediaWiki software, transformed, or just kept for your private
+amusement.",
+"exportcuronly"        => "Include only the current revision, not the full history",
+
+# Namespace 8 related
+
+"allmessages" => "Holl_negeseuon",
+"allmessagestext" => "Dyma rhestr holl y negeseuon ar gael yn y lle-enw MediaWiki: ",
+
+# Thumbnails
+
+"thumbnail-more" => "Helaethwch",
+
+#Math
+'mw_math_png' => "Rendrwch PNG o hyd",
+'mw_math_simple' => "HTML os yn syml iawn, PNG fel arall",
+'mw_math_html' => "HTML os bosibl, PNG fel arall",
+'mw_math_source' => "Gadewch fel TeX (am porwyr testun)",
+'mw_math_modern' => "Cymeradwedig am porwyr modern",
+'mw_math_mathml' => 'MathML',
+
+);
+
+
+/** */
+require_once( 'LanguageUtf8.php' );
+
+/** @package MediaWiki */
+class LanguageCy extends LanguageUtf8 {
+
+       function getBookstoreList () {
+               global $wgBookstoreListCy;
+               return $wgBookstoreListCy;
+       }
+
+       function getNamespaces() {
+               global $wgNamespaceNamesCy;
+               return $wgNamespaceNamesCy;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsCy;
+               return $wgQuickbarSettingsCy;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesCy;
+               return $wgSkinNamesCy;
+       }
+
+       function getDateFormats() {
+               global $wgDateFormatsCy;
+               return $wgDateFormatsCy;
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesCy;
+               if( isset( $wgAllMessagesCy[$key] ) ) {
+                       return $wgAllMessagesCy[$key];
+               } else {
+                       return parent::getMessage( $key );
+               }
+       }
+
+       function getAllMessages() {
+               global $wgAllMessagesCy;
+               return $wgAllMessagesCy;
+       }
+
+       function getMagicWords() {
+               global $wgMagicWordsCy, $wgMagicWordsEn;
+               return $wgMagicWordsCy + $wgMagicWordsEn;
+       }
+
+}
+
+?>
diff --git a/languages/LanguageDa.php b/languages/LanguageDa.php
new file mode 100644 (file)
index 0000000..7f6c017
--- /dev/null
@@ -0,0 +1,1599 @@
+<?php
+/** Danish (Dansk)
+  *
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+/** */
+require_once( "LanguageUtf8.php" );
+
+#--------------------------------------------------------------------------
+# Language-specific text
+#--------------------------------------------------------------------------
+
+# The names of the namespaces can be set here, but the numbers
+# are magical, so don't change or move them!  The Namespace class
+# encapsulates some of the magic-ness.
+#
+/* private */ $wgNamespaceNamesDa = array(
+       NS_MEDIA                        => 'Media',
+       NS_SPECIAL                      => 'Speciel',
+       NS_MAIN                         => '',
+       NS_TALK                         => 'Diskussion',
+       NS_USER                         => 'Bruger',
+       NS_USER_TALK            => 'Bruger_diskussion',
+       NS_PROJECT                      => $wgMetaNamespace,
+       NS_PROJECT_TALK         => $wgMetaNamespace.'_diskussion',
+       NS_IMAGE                        => 'Billede',
+       NS_IMAGE_TALK           => 'Billede_diskussion',
+       NS_MEDIAWIKI            => 'MediaWiki',
+       NS_MEDIAWIKI_TALK       => 'MediaWiki_diskussion',
+       NS_TEMPLATE             => 'Skabelon',
+       NS_TEMPLATE_TALK        => 'Skabelon_diskussion',
+       NS_HELP                         => 'Hjælp',
+       NS_HELP_TALK            => 'Hjælp_diskussion',
+       NS_CATEGORY                     => 'Kategori',
+       NS_CATEGORY_TALK        => 'Kategori_diskussion'
+
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgQuickbarSettingsDa = array(
+       'Ingen', 'Fast venstre', 'Fast højre', 'Flydende venstre'
+);
+
+/* private */ $wgSkinNamesDa = array(
+       'standard' => 'Klassisk',
+       'nostalgia' => 'Nostalgi',
+       'cologneblue' => 'Cologne-blå',
+) + $wgSkinNamesEn;
+
+/* private */ $wgDateFormatsDa = array();
+
+
+/* private */ $wgBookstoreListDa = array(
+       "Bibliotek.dk" => "http://bibliotek.dk/vis.php?base=dfa&origin=kommando&field1=ccl&term1=is=$1&element=L&start=1&step=10",
+       "Bogguide.dk" => "http://www.bogguide.dk/find_boeger_bog.asp?ISBN=$1",
+) + $wgBookstoreListEn;
+
+
+#-------------------------------------------------------------------
+# Default messages
+#-------------------------------------------------------------------
+
+/* private */ $wgAllMessagesDa = array(
+# User preference toggles
+"tog-underline" => "Understreg henvisninger",
+"tog-highlightbroken" => "Brug røde henvisninger til tomme sider",
+"tog-justify"  => "Justér afsnit",
+"tog-hideminor" => "Skjul mindre ændringer i seneste ændringer listen",
+"tog-usenewrc" => "Udvidet seneste ændringer liste<br />(ikke for alle browsere)",
+"tog-numberheadings" => "Automatisk nummerering af overskrifter",
+"tog-showtoolbar" => "Vis værktøjslinje til redigering",
+"tog-editondblclick" => "Redigér sider med dobbeltklik (JavaScript)",
+"tog-editsection"=>"Redigér afsnit ved hjælp af [redigér]-henvisning",
+"tog-editsectiononrightclick"=>"Redigér afsnit ved at højreklikke<br /> på afsnittets titel (JavaScript)",
+"tog-showtoc"=>"Vis indholdsfortegnelse<br />(for artikler med mere end tre afsnit)",
+"tog-rememberpassword" => "Husk adgangskode til næste besøg",
+"tog-editwidth" => "Redigeringsboksen har fuld bredde",
+"tog-watchdefault" => "Overvåg nye og ændrede artikler",
+"tog-minordefault" => "Markér som standard alle ændringer som mindre",
+"tog-previewontop" => "Vis forhåndsvisning før redigeringsboksen",
+'tog-previewonfirst' => 'Vis forhåndsvisning når du starter med at redigere',
+"tog-nocache" => "Husk ikke siderne til næste besøg",
+'tog-enotifwatchlistpages'     => 'Send mig en e-mail med sideændringer (bemærk: eksisterende beskedmarkeringer skal fjernes manuelt i overvågningslisten)',
+'tog-enotifusertalkpages'      => 'Send mig en e-mail når min brugerdiskussionsside ændres (bemærk: eksisterende beskedmarkeringer skal fjernes manuelt i overvågningslisten)',
+'tog-enotifminoredits'                 => 'Send mig også en e-mail for mindre ændringer af sider (der normalt ikke udløser mails med besked om ændringer)',
+'tog-enotifrevealaddr'                 => 'Offentliggør min e-mail-adresse i mails med besked om ændringer (når jeg ændrer en side kan brugere, der overvåger siden, hurtigt komme i kontakt med mig)',
+'tog-shownumberswatching'      => 'Vis antal brugere, der overvåger (i seneste ændringer-visning, overvågningslisten og i bunden af artikelsider)',
+'tog-fancysig' => 'Signaturer uden automatisk link',
+'tog-externaleditor' => 'Brug ekstern editor automatisk',
+'tog-externaldiff' => 'Brug ekstern forskelsvisning automatisk',
+
+# dates
+'sunday' => 'søndag',
+'monday' => 'mandag',
+'tuesday' => 'tirsdag',
+'wednesday' => 'onsdag',
+'thursday' => 'torsdag',
+'friday' => 'fredag',
+'saturday' => 'lørdag',
+'january' => 'januar',
+'february' => 'februar',
+'march' => 'marts',
+'april' => 'april',
+'may_long' => 'maj',
+'june' => 'juni',
+'july' => 'juli',
+'august' => 'august',
+'september' => 'september',
+'october' => 'oktober',
+'november' => 'november',
+'december' => 'december',
+'jan' => 'jan',
+'feb' => 'feb',
+'mar' => 'mar',
+'apr' => 'apr',
+'may' => 'maj',
+'jun' => 'jun',
+'jul' => 'jul',
+'aug' => 'aug',
+'sep' => 'sep',
+'oct' => 'okt',
+'nov' => 'nov',
+'dec' => 'dec',
+
+# Bits of text used by many pages:
+#
+"categories" => "Kategorier ",
+"category" => "kategori",
+"category_header" => 'Artikler i kategorien "$1"',
+"subcategories" => "Underkategorier",
+
+"linktrail"            => '/^([a-zæøå]+)(.*)$/sDu',
+"mainpage"             => "Forside",
+"mainpagetext" => "MediaWiki er nu installeret.",
+"mainpagedocfooter" => "Se vores engelsksprogede [http://meta.wikipedia.org/wiki/MediaWiki_i18n dokumentation om tilpasning af brugergrænsefladen]
+og [http://meta.wikipedia.org/wiki/MediaWiki_User%27s_Guide brugervejledningen] for oplysninger om opsætning og anvendelse.",
+
+# NOTE: To turn off "Community portal" in the title links,
+# set "portal" => "-"
+
+'portal'               => 'Forside for skribenter',
+'portal-url'           => '{{ns:4}}:Forside',
+"about"                        => "Om",
+"aboutsite"      => "Om {{SITENAME}}",
+"aboutpage"            => "{{ns:4}}:Om",
+'article' => 'Artikel',
+"help"                 => "Hjælp",
+"helppage"             => "{{ns:4}}:Hjælp",
+"bugreports"   => "Fejlrapporter",
+"bugreportspage" => "{{ns:4}}:Fejlrapporter",
+"sitesupport"   => "Donation",
+'sitesupport-url' => '{{ns:4}}:Donation', # If not set, won't appear. Can be wiki page or URL
+"faq"                  => "OSS",
+"faqpage"              => "{{ns:4}}:OSS",
+"edithelp"             => "Hjælp til redigering",
+"newwindow"            => "(åbner i et nyt vindue)",
+"edithelppage" => "{{ns:4}}:Hvordan redigerer jeg en side",
+"cancel"               => "Afbryd",
+"qbfind"               => "Find",
+"qbbrowse"             => "Gennemse",
+"qbedit"               => "Redigér",
+"qbpageoptions" => "Indstillinger for side",
+"qbpageinfo"   => "Information om side",
+"qbmyoptions"  => "Mine indstillinger",
+'qbspecialpages'       => 'Specielle sider',
+'moredotdotdot'        => 'Mere...',
+"mypage"               => "Min side",
+"mytalk"               => "Min diskussion",
+'anontalk'             => 'Diskussionsside for denne IP-adresse',
+'navigation' => 'Navigation',
+
+# Metadata in edit box
+'metadata' => '<b>Metadata</b> (for en foklaring se <a href="$1">her</a>)',
+'metadata_page' => '{{ns:4}}:Metadata',
+
+# NOTE: To turn off "Current Events" in the sidebar,
+# set "currentevents" => "-"
+
+"currentevents" => "Aktuelle begivenheder",
+'currentevents-url' => 'Aktuelle begivenheder',
+
+# NOTE: To turn off "Disclaimers" in the title links,
+# set "disclaimers" => "-"
+
+'disclaimers' => 'Forbehold',
+"disclaimerpage" => "{{ns:4}}:Generelle forbehold",
+"errorpagetitle" => "Fejl",
+"returnto"             => "Tilbage til $1.",
+"tagline"              => "Fra {{SITENAME}}, den frie encyklopædi",
+"whatlinkshere"        => "Hvad henviser hertil",
+"help"                 => "Hjælp",
+"search"               => "Søg",
+"go"           => "Gå til",
+"history"              => "Historik",
+'history_short' => 'Historik',
+'info_short'   => 'Information',
+"printableversion" => "Udskriftsvenlig udgave",
+'edit' => 'Redigér',
+"editthispage" => "Redigér side",
+'delete' => 'Slet',
+"deletethispage" => "Slet side",
+'undelete_short1' => 'Fortryd sletning af en version',
+"undelete_short" => "Fortryd sletning af $1 versioner",
+'protect' => 'Beskyt',
+"protectthispage" => "Beskyt side",
+'unprotect' => 'Fjern beskyttelse',
+"unprotectthispage" => "Fjern beskyttelse af side",
+"newpage" => "Ny side",
+"talkpage"             => "Diskussionssiden",
+'specialpage' => 'Speciel side',
+'personaltools' => 'Personlige værktøjer',
+"postcomment"   => "Tilføj en kommentar",
+'addsection'   => '+',
+"articlepage"  => "Se artiklen",
+"subjectpage"  => "Se emnesiden",
+'talk' => 'Diskussion',
+'toolbox' => 'Værktøjer ',
+"userpage" => "Se brugersiden",
+"wikipediapage" => "Se metasiden",
+"imagepage" =>         "Se billedsiden",
+"viewtalkpage" => "Se diskussion",
+"otherlanguages" => "Andre sprog",
+"redirectedfrom" => "(Omdirigeret fra $1)",
+"lastmodified" => "Denne side blev senest ændret den $1.",
+"viewcount"            => "Siden er vist i alt $1 gange.",
+'copyright'    => 'Indholdet&nbsp;er&nbsp;udgivet&nbsp;under&nbsp;$1.',
+'poweredby'    => "{{SITENAME}} kører på [http://www.mediawiki.org/ MediaWiki], en open source wiki engine.",
+"printsubtitle" => "(Fra {{SERVER}})",
+"protectedpage" => "Beskyttet side",
+"administrators" => "{{ns:4}}:Administratorer",
+"sysoptitle"   => "Sysop-adgang påkrævet",
+"sysoptext"            => "Den funktion du har bedt om kan kun
+udføres af brugere med \"sysop\"-status. Se $1.",
+"developertitle" => "Developer-adgang påkrævet",
+"developertext"        => "Den funktion du har bedt om, kan kun
+udføres af brugere med \"developer\"-status. Se $1.",
+'badaccess'     => 'Permission error',
+'badaccesstext' => 'The action you have requested is limited
+to users with the "$2" permission assigned.
+See $1.',
+
+'nbytes'               => '$1 bytes',
+"go"                   => "Gå til",
+"ok"                   => "OK",
+"sitetitle"            => "{{SITENAME}}",
+'pagetitle'            => "$1 - {{SITENAME}}",
+"sitesubtitle" => "Den frie encyklopædi",
+"retrievedfrom" => "Hentet fra \"$1\"",
+"newmessages" => "Du har $1.",
+"newmessageslink" => "nye beskeder",
+"editsection"=>"redigér",
+"toc" => "Indholdsfortegnelse",
+"showtoc" => "vis",
+"hidetoc" => "skjul",
+"thisisdeleted" => "Se eller gendan $1?",
+"restorelink" => "$1 slettede ændringer",
+'feedlinks' => 'Feed:',
+'sitenotice'   => '-', # the equivalent to wgSiteNotice
+
+# Short words for each namespace, by default used in the 'article' tab in monobook
+'nstab-main' => 'Artikel',
+'nstab-user' => 'Brugerside',
+'nstab-media' => 'Medie',
+'nstab-special' => 'Speciel',
+'nstab-wp' => 'Om',
+'nstab-image' => 'Billede',
+'nstab-mediawiki' => 'Besked',
+'nstab-template' => 'Skabelon',
+'nstab-help' => 'Hjælp',
+'nstab-category' => 'Kategori',
+
+# Main script and global functions
+#
+"nosuchaction" => "Funktionen findes ikke",
+"nosuchactiontext" => "Funktion angivet i URL'en kan ikke
+genkendes af MediaWiki-softwaren",
+"nosuchspecialpage" => "En sådan specialside findes ikke",
+"nospecialpagetext" => "Du har bedt om en specialside, der ikke kan
+genkendes af MediaWiki-softwaren.",
+
+# General errors
+#
+"error"                        => "Fejl",
+"databaseerror" => "Databasefejl",
+"dberrortext"  => "Der er opstået en syntaksfejl i en databaseforespørgsel.
+Dette kan være på grund af en ugyldig forespørgsel (se $5),
+eller det kan betyde en fejl i softwaren.
+Den seneste forsøgte databaseforespørgsel var:
+<blockquote><tt>$1</tt></blockquote>
+fra funktionen \"<tt>$2</tt>\".
+MySQL returnerede fejlen \"<tt>$3: $4</tt>\".",
+"dberrortextcl" => "Der er opstået en syntaksfejl i en databaseforespørgsel.
+Den seneste forsøgte databaseforespørgsel var:
+\"$1\"
+fra funktionen \"$2\".
+MySQL returnerede fejlen \"$3: $4\".\n",
+'noconnect'            => 'Der er problemer med {{SITENAME}}s database, vi kan desværre ikke komme i kontakt med den for øjeblikket. Prøv igen senere. <br />
+$1',
+"nodb"                 => "Kunne ikke vælge databasen $1",
+"cachederror"  => "Det følgende er en gemt kopi af den ønskede side, og er måske ikke helt opdateret.",
+"readonly"             => "Databasen er skrivebeskyttet",
+"enterlockreason" => "Skriv en begrundelse for skrivebeskyttelsen, også indeholdende et estimat
+på hvornår skrivebeskyttelsen vil blive ophævet igen",
+"readonlytext" => "{{SITENAME}}databasen er for øjeblikket skrivebeskyttet,
+hvilket forhindrer oprettelse af nye sider og andre ændringer,
+sandsynligvis på grund af rutinemæssig databasevedligeholdelse,
+hvorefter den vil returnere til normaldrift. Administratoren der
+skrivebeskyttede databasen har denne forklaring:
+<p>$1",
+"missingarticle" => "Databasen fandt ikke teksten på en side,
+som den skulle have fundet, med navnet \"$1\".
+
+<p>Dette er ikke en databasefejl, men sandsynligvis en fejl i softwaren.
+
+<p>Send venligst en rapport om dette til en administrator,
+hvor du også nævner URL'en.",
+'readonly_lag' => "Databasen er automatisk blevet låst mens slave database serverne synkronisere med master databasen",
+"internalerror" => "Intern fejl",
+"filecopyerror" => "Kunne ikke kopiere filen \"$1\" til \"$2\".",
+"filerenameerror" => "Kunne ikke omdøbe filen \"$1\" til \"$2\".",
+"filedeleteerror" => "Kunne ikke slette filen \"$1\".",
+"filenotfound" => "Kunne ikke finde filen \"$1\".",
+"unexpected"   => "Uventet værdi: \"$1\"=\"$2\".",
+"formerror"            => "Fejl: Kunne ikke afsende formular",
+"badarticleerror" => "Denne funktion kan ikke udføres på denne side.",
+"cannotdelete" => "Kunne ikke slette siden eller filen der blev angivet.",
+"badtitle"             => "Forkert titel",
+"badtitletext" => "Den ønskede sides titel var ikke tilladt, tom eller siden
+er forkert henvist fra en {{SITENAME}} på et andet sprog.",
+"perfdisabled" => "Denne funktion er desværre midlertidigt afbrudt,
+fordi den belaster databasen meget hårdt og i en sådan grad,
+at siden bliver meget langsom. Funktionen bliver forhåbentlig
+omskrevet i den nærmeste fremtid (måske af dig, det er jo open source!).",
+"perfdisabledsub" => "Her er en gemt kopi fra $1:",
+'perfcached' => 'Følgende data er gemt i cachen, det er muligvis ikke helt opdateret:',
+'wrong_wfQuery_params' => "Ugyldig parameter til wfQuery()<br />
+Funktion: $1<br />
+Forespørgsel: $2
+",
+'viewsource' => 'Vis kilden',
+'protectedtext' => "Denne side er skrivebeskyttet for at forhindre ændringer;
+der kan være flere årsager til at det er sket,
+se [[{{ns:4}}:Liste over beskyttede sider|listen over beskyttede sider]].
+
+Du kan sé og kopiere sidens indhold:",
+'sqlhidden' => '(SQL forespørgsel gemt)',
+
+# Login and logout pages
+#
+"logouttitle"  => "Bruger-log-af",
+"logouttext"   => "Du er nu logget af.
+Du kan fortsætte med at bruge {{SITENAME}} anonymt, eller du kan logge på
+igen som den samme eller en anden bruger.\n",
+
+"welcomecreation" => "== Velkommen, $1! ==
+
+Din konto er blevet oprettet. Glem ikke at personliggøre dine {{SITENAME}}-indstillinger.",
+
+"loginpagetitle" => "Bruger log på",
+"yourname"             => "Dit brugernavn",
+"yourpassword" => "Din adgangskode",
+"yourpasswordagain" => "Gentag adgangskode",
+"newusersonly" => " (kun nye brugere)",
+"remembermypassword" => "Husk min adgangskode til næste gang.",
+'yourdomainname'       => 'Your domain',
+'externaldberror'      => 'There was either an external authentication database error or you are not allowed to update your external account.',
+"loginproblem" => "<b>Der har været et problem med at få dig logget på.</b><br />Prøv igen!",
+"alreadyloggedin" => "<strong>Bruger $1, du er allerede logget på!</strong><br />\n",
+
+"login"                        => "Log på",
+'loginprompt'   => "Du skal have cookies slået til for at kunne logge på {{SITENAME}}.",
+"userlogin"            => "Opret en konto eller log på",
+"logout"               => "Log af",
+"userlogout"   => "Log af",
+"notloggedin"  => "Ikke logget på",
+"createaccount"        => "Opret en ny konto",
+'createaccountmail'    => 'via e-mail',
+"badretype"            => "De indtastede adgangskoder er ikke ens.",
+"userexists"   => "Det brugernavn du har valgt er allerede i brug. Vælg
+venligst et andet brugernavn.",
+"youremail"            => "Din e-mail-adresse *",
+'yourrealname'         => 'Dit rigtige navn*',
+'yourlanguage' => 'Grænsefladesprog',
+'yourvariant'  => 'Sprogvariant',
+"yournick"             => "Dit kaldenavn (til signaturer)",
+"emailforlost" => "&nbsp;",
+'prefs-help-email'     => '** <strong>E-mail-adresse</strong> (valgfrit): Giver andre mulighed for at kontakte dig, uden du behøver at afsløre din e-mail-adresse. Det kan også bruges til at fremsende en ny adgangskode til dig, hvis du glemmer den du har.',
+'prefs-help-email-enotif' => 'Denne e-mail-adresse bruges også til at sende beskeder til dig via e-mail, hvis du har aktiveret funktionerne.',
+'prefs-help-realname'  => '* <strong>Dit rigtige navn</strong> (valgfrit): Hvis du vælger at oplyse dit navn vil dette blive brugt til at tilskrive dig dit arbejde.',
+"loginerror"   => "Fejl med at logge på",
+'nocookiesnew' => "Din brugerkonto er nu oprettet, men du er ikke logget på. {{SITENAME}} bruger cookies til at logge brugere på. Du har slået cookies fra. Vær venlig at slå cookies til, og derefter kan du logge på med dit nye brugernavn og kodeord.",
+"nocookieslogin"       => "{{SITENAME}} bruger cookies til at logge brugere på. Du har slået cookies fra. Slå dem venligst til og prøv igen.",
+"noname"               => "Du har ikke angivet et gyldigt brugernavn.",
+"loginsuccesstitle" => "Logget på med succes",
+"loginsuccess" => "Du er nu logget på {{SITENAME}} som \"$1\".",
+"nosuchuser"   => "Der er ingen bruger med navnet \"$1\".
+Kontrollér stavemåden igen, eller brug formularen herunder til at oprette en ny brugerkonto.",
+'nosuchusershort'      => "Der er ingen bruger ved navn \"$1\". Tjek din stavning.",
+"wrongpassword"        => "Den indtastede adgangskode var forkert. Prøv igen.",
+"mailmypassword" => "Send en ny adgangskode til min e-mail-adresse",
+"passwordremindertitle" => "Ny adgangskode fra {{SITENAME}}",
+"passwordremindertext" => "Nogen (sandsynligvis dig, fra IP-adressen $1)
+har bedt om at vi sender dig en ny adgangskode til at logge på {{SITENAME}}.
+Den nye adgangskode for bruger \"$2\" er nu \"$3\".
+Du bør logge på nu og ændre din adgangskode.",
+"noemail"              => "Der er ikke oplyst en e-mail-adresse for bruger \"$1\".",
+"passwordsent" => "En ny adgangskode er sendt til e-mail-adressen,
+som er registreret for \"$1\".
+Du bør logge på og ændre din adgangskode straks efter du har modtaget e-mail'en.",
+'loginend'             => "'''For at oprette en konto skal du vælge et brugernavn og en adgangskode og trykke på \"Opret en ny konto\"'''
+
+* Brugernavnet skal starte med stort bogstav og det må gerne indeholde mellemrum.
+
+'''Hvis du allerede har en konto, skal du kun udfylde brugernavn og adgangskode og trykke \"Log på\"'''
+
+* Du skal have cookies slået til for at kunne logge på.
+
+<nowiki>*</nowiki> Det er valgfrit om du vil oplyse din e-mail-adresse. Men det gør andre brugere i stand til at sende dig en e-mail, uden at du behøver at offentliggøre din e-mail-adresse. Samtidig giver det mulighed for at få sendt en ny adgangskode til din e-mail-adresse. '''Vi videregiver aldrig din e-mail-adresse til nogen som helst.'''
+",
+'mailerror' => "Fejl ved afsendelse af e-mail: $1",
+'acct_creation_throttle_hit' => 'Du har allerede oprettet $1 kontoer. Du kan ikke oprette flere.',
+'emailauthenticated'   => 'Din e-mail-adresse blev bekræftet på $1.',
+'emailnotauthenticated'        => 'Din e-mail-adresse er <strong>endnu ikke bekræftet</strong> og de avancerede e-mail-funktioner er slået fra indtil bekræftelse har fundet sted <strong>(d.u.a.)</strong>.<br />
+Log ind med den midlertidige adgangskode, der er blevet sendt til dig, for at bekræfte, eller bestil et nyt på loginsiden.',
+'invalidemailaddress'  => 'E-mail-adressen kan ikke accepteres da den tilsyneladende har et ugyldigt format. Skriv venligst en e-mail-adresse med et korrekt format eller tøm feltet.',
+
+# Edit page toolbar
+'bold_sample'=>'Fed tekst',
+'bold_tip'=>'Fed tekst',
+'italic_sample'=>'Kursiv tekst',
+'italic_tip'=>'Kursiv tekst',
+'link_sample'=>'Henvisning',
+'link_tip'=>'Intern henvisning',
+'extlink_sample'=>'http://www.eksempel.dk Titel på henvisning',
+'extlink_tip'=>'Ekstern henvisning (husk http:// præfiks)',
+'headline_sample'=>'Tekst til overskrift',
+'headline_tip'=>'Type 2 overskrift',
+'math_sample'=>'Indsæt formel her (LaTeX)',
+'math_tip'=>'Matematisk formel (LaTeX)',
+'nowiki_sample'=>'Indsæt tekst her som ikke skal wikiformateres',
+'nowiki_tip'=>'Ignorer wikiformatering',
+'image_sample'=>'Eksempel.jpg',
+'image_tip'=>'Indlejret billede',
+'media_sample'=>'Eksempel.mp3',
+'media_tip'=>'Henvisning til multimediefil',
+'sig_tip'=>'Din signatur med tidsstempel',
+'hr_tip'=>'Horisontal linje (brug den sparsomt)',
+'infobox'=>'Tryk på en knap for at få et teksteksempel',
+# alert box shown in browsers where text selection does not work, test e.g. with mozilla or konqueror
+'infobox_alert'=>"Indtast teksten du ønsker formatteret.\\n Den vil blive vist i infoboksen så den kan klippe-klistres.\\nEksempel:\\n$1\\nbliver:\\n$2",
+
+# Edit pages
+#
+"summary"              => '<a href="{{SERVER}}/wiki/{{ns:4}}:Beskrivelse" title="Giv venligst en kort beskrivelse af din ændring">Beskrivelse</a>',
+"subject"              => "Emne/overskrift",
+"minoredit"            => "Dette er en mindre ændring.",
+"watchthis"            => "Overvåg denne artikel",
+"savearticle"  => "Gem side",
+"preview"              => "Forhåndsvisning",
+"showpreview"  => "Forhåndsvisning",
+'showdiff'     => 'Vis ændringer',
+"blockedtitle" => "Brugeren er blokeret",
+"blockedtext"  => "Dit brugernavn eller din IP-adresse er blevet blokeret af
+$1. Begrundelsen er denne:<br />$2<p>Du kan kontakte $1
+eller en af de andre [[{{ns:project}}:Administratorer|administratorer]] for at diskutere blokeringen.
+
+Din IP-adresse er $3.
+Sørg venligst for at medtage denne IP-adresse i alle henvendelser til en administrator.
+",
+'whitelistedittitle' => 'Log på for at redigere',
+'whitelistedittext' => 'Du skal [[Special:Userlogin|logge på]] for at kunne rette artikler.',
+'whitelistreadtitle' => 'Log på for at læse',
+'whitelistreadtext' => 'Du skal [[Special:Userlogin|logge på]] for at læse artikler.',
+'whitelistacctitle' => 'Du har ikke lov til at oprette en konto',
+'whitelistacctext' => 'For at få lov til at lave en konto på denne wiki skal du [[Speciel:Userlogin|logge på]] og have passende rettigheder.',
+'loginreqtitle'        => 'Log på nødvendigt',
+'loginreqtext' => 'Du skal [[speciel:Userlogin|logge på]] for at se andre sider.',
+'accmailtitle' => 'Adgangskode sendt.',
+'accmailtext' => "Adgangskoden for '$1' er sendt til $2.",
+"newarticle"   => "(Ny)",
+"newarticletext" => "<div style=\"font-size:small;color:\#003333;border-width:1px;border-style:solid;border-color:\#aaaaaa;padding:3px\">'''{{SITENAME}} har endnu ikke nogen {{NAMESPACE}}-side ved navn {{PAGENAME}}.'''<br /> Du kan begynde en side ved at skrive i boksen herunder. (se [[{{ns:4}}:Hjælp|hjælpen]] for yderligere oplysninger).<br /> Eller du kan [[{{ns:-1}}:Search/{{PAGENAME}}|søge efter {{PAGENAME}} i {{SITENAME}}]].<br /> Hvis det ikke var din mening, så tryk på '''Tilbage'''- eller '''Back'''-knappen. '''Dit bidrag til {{SITENAME}} vil fremkomme omgående''', så hvis du bare vil teste tingene, så brug venligst [[{{ns:4}}:Sandkassen|sandkassen]]!</div>",
+'talkpagetext' => '<!-- MediaWiki:talkpagetext -->',
+"anontalkpagetext" => "---- ''Dette er en diskussionsside for en anonym bruger, der ikke har oprettet en konto endnu eller ikke bruger den. Vi er derfor nødt til at bruge den nummeriske [[IP-adresse]] til at identificere ham eller hende. En IP-adresse kan være delt mellem flere brugere. Hvis du er en anonym bruger og synes, at du har fået irrelevante kommentarer på sådan en side, så vær venlig at oprette en brugerkonto og [[Speciel:Userlogin|logge på]], så vi undgår fremtidige forvekslinger med andre anonyme brugere.'' ",
+"noarticletext" => "<div style=\"border: 1px solid \#ccc; padding: 7px; background-color: \#fff; color: \#000\">'''{{SITENAME}} har ikke nogen side med præcis dette navn.''' * Du kan se om {{PAGENAME}} findes i [[Wiktionary:{{NAMESPACE}}:{{PAGENAME}}|wikiordbogen]] eller på '''[[:no:{{PAGENAME}}|norsk]]''', '''[[:nn:{{PAGENAME}}|nynorsk]]''', eller '''[[:sv:{{PAGENAME}}|svensk]]'''. * Du kan '''[{{SERVER}}{{localurl:{{NAMESPACE}}:{{PAGENAME}}|action=edit}} starte siden {{PAGENAME}}]''' * Eller [[{{ns:special}}:Search/{{PAGENAME}}|søge efter {{PAGENAME}}]] i andre artikler ---- * Hvis du har oprettet denne artikel indenfor de sidste få minutter, så kan de skyldes at der er lidt forsinkelse i opdateringen af {{SITENAME}}s cache. Vent venligst og tjek igen senere om artiklen dukker op, inden du forsøger at oprette artiklen igen. </div>",
+'clearyourcache' => "'''Bemærk''', efter at have gemt, er du nødt til at tømme din browsers cache for at kunne se ændringerne. '''Mozilla / Firefox / Safari''': hold ''shifttasten'' nede og klik på ''reload'' eller tryk på ''control-shift-r'' (Mac: ''cmd-shift-r''); '''Internet Explorer''': hold ''controltasten'' nede og klik på ''refresh'' eller tryk på ''control-F5''; '''Konqueror''': klik på ''reload'' eller tryk på ''F5''",
+'usercssjsyoucanpreview' => "<strong>Tip:</strong> Brug knappen 'forhåndsvisning' til at teste dit nye css/js før du gemmer.",
+'usercsspreview' => "'''Husk at du kun tester/forhåndsviser dit eget css, den er ikke gemt endnu!'''",
+'userjspreview' => "'''Husk at du kun tester/forhåndsviser dit eget javascript, det er ikke gemt endnu!'''",
+"updated"              => "(Opdateret)",
+'note'                 => '<strong>Bemærk:</strong> ',
+"previewnote"  => "Husk at dette er kun en forhåndsvisning, siden er ikke
+gemt endnu!",
+"previewconflict" => "Denne forhåndsvisning er resultatet af den
+redigérbare tekst ovenfor,
+sådan vil det komme til at se ud hvis du vælger at gemme teksten.",
+"editing"              => "Redigerer $1",
+"editingsection"       => "Redigerer $1 (afsnit)",
+"editingcomment"       => "Redigerer $1 (kommentar)",
+"editconflict" => "Redigeringskonflikt: $1",
+"explainconflict" => "Nogen har ændret denne side, efter du
+startede på at redigere den.
+Den øverste tekstboks indeholder den nuværende tekst.
+Dine ændringer er vist i den nederste tekstboks.
+Du er nødt til at sammenflette dine ændringer med den eksisterende tekst.
+<b>Kun</b> teksten i den øverste tekstboks vil blive gemt når du
+trykker \"Gem side\".<br />",
+"yourtext"             => "Din tekst",
+"storedversion" => "Den gemte version",
+'nonunicodebrowser' => "<strong>Advarsel: Din browser er ikke unicode-kompatibel, skift eller opdater din browser før du redigerer en artikel.</strong>",
+"editingold"   => "<strong>ADVARSEL: Du redigerer en gammel version
+af denne side.
+Hvis du gemmer den, vil alle ændringer foretaget siden denne revision blive
+overskrevet.</strong>",
+"yourdiff"             => "Forskelle",
+"copyrightwarning" => "<div id=\"editpage-specialchars\" class=\"plainlinks\" style=\"margin-top:15px;border-width:1px;border-style:solid;border-color:\#aaaaaa;padding:2px;\"> <small> Indsæt: <charinsert> Á á É é Í í Ó ó Ú ú </charinsert> &nbsp; <charinsert> À à È è Ì ì Ò ò Ù ù </charinsert> &nbsp; <charinsert> Â â Ê ê Î î Ô ô Û û </charinsert> &nbsp; <charinsert> Ä ä Ë ë Ï ï Ö ö Ü ü </charinsert> &nbsp; <charinsert> ß </charinsert> &nbsp; <charinsert> Ã ã Ñ ñ Õ õ </charinsert> &nbsp; <charinsert> Ç ç &\#290; &\#291; &\#310; &\#311; &\#315; &\#316; &\#325; &\#326; &\#342; &\#343; &\#350; &\#351; &\#354; &\#355; </charinsert> &nbsp; <charinsert> &\#262; &\#263; &\#313; &\#314; &\#323; &\#324; &\#340; &\#341; &\#346; &\#347; Ý ý &\#377; &\#378; </charinsert> &nbsp; <charinsert> Ð ð Þ þ </charinsert> &nbsp; <charinsert> Œ œ </charinsert> &nbsp; <charinsert> Æ æ Ø ø Å å </charinsert> &nbsp; <charinsert> &ndash; &mdash; &hellip; </charinsert> &nbsp; <charinsert> [+] [[+]] {{+}} </charinsert> &nbsp; <charinsert> ~ | ° </charinsert> &nbsp; <charinsert> ± &minus; × ² ³ </charinsert> &nbsp; <charinsert> &euro; </charinsert> &nbsp; </small> </div> *Bemærk at alle bidrag til {{SITENAME}} er at betragte som udgivet under GNU Free Documentation License (se $1 for flere oplysninger). *Hvis du ikke ønsker at din tekst skal udsættes for nådesløse redigeringer og at den kan blive kopieret efter forgodtbefindende, så skal du ikke placere den her. *Du lover os også, at du selv har forfattet teksten, kopieret den fra en public domain-kilde eller tilsvarende fri kilde. <div style=\"font-weight: bold; font-size: 120%;\">LÆG ALDRIG MATERIALE HER SOM ER BESKYTTET AF ANDRES OPHAVSRET UDEN DERES TILLADELSE!</div>",
+"longpagewarning" => "<strong>ADVARSEL: Denne side er $1 kilobyte stor; nogle browsere kan have problemer med at redigere sider der nærmer sig eller er større end 32 Kb. Overvej om siden kan opdeles i mindre dele.</strong>",
+"readonlywarning" => "<strong>ADVARSEL: Databasen er låst på grund af vedligeholdelse,
+så du kan ikke gemme dine ændringer lige nu. Det kan godt være en god ide at
+kopiere din tekst til en tekstfil, så du kan gemme den til senere.</strong>",
+"protectedpagewarning" => "<strong>ADVARSEL: Denne side er låst, så kun administratorer
+kan redigere den. Sørg for at du følger
+[[Project:Politik_for_beskyttede_sider|politiken for beskyttede sider]].</strong>",
+'templatesused'        => 'Skabeloner der er brugt på denne side:',
+
+# History pages
+#
+"revhistory"   => "Versionshistorik",
+"nohistory"            => "Der er ingen versionshistorik for denne side.",
+"revnotfound"  => "Versionen er ikke fundet",
+"revnotfoundtext" => "Den gamle version af den side du spurgte efter kan
+ikke findes. Kontrollér den URL du brugte til at få adgang til denne side.\n",
+"loadhist"             => "Indlæser sidens historik",
+"currentrev"   => "Nuværende version",
+"revisionasof" => "Versionen fra $1",
+'revisionasofwithlink'  => 'Revision pr. $1; $2<br />$3 | $4',
+'previousrevision'     => '←Ældre version',
+'nextrevision'         => 'Nyere version→',
+'currentrevisionlink'   => 'se nuværende version',
+"cur"                  => "nuværende",
+"next"                 => "næste",
+"last"                 => "forrige",
+"orig"                 => "originale",
+"histlegend"   => "Forklaring: (nuværende) = forskel til den nuværende
+version, (forrige) = forskel til den forrige version, M = mindre ændring",
+'history_copyright'    => '-',
+'deletedrev' => '[slettet]',
+
+# Diffs
+#
+"difference"   => "(Forskelle mellem versioner)",
+"loadingrev"   => "indlæser version for at se forskelle",
+"lineno"               => "Linje $1:",
+"editcurrent"  => "Redigér den nuværende version af denne side",
+'selectnewerversionfordiff' => 'Vælg en nyere version til sammenligning',
+'selectolderversionfordiff' => 'Vælg en ældre version til sammenligning',
+'compareselectedversions' => 'Sammenlign valgte versioner',
+
+# Search results
+#
+"searchresults" => "Søgeresultater",
+"searchresulttext" => "For mere information om søgning på {{SITENAME}}, se [[Project:Søgning|Søgning på {{SITENAME}}]].",
+"searchquery"  => "<big><div class=\"plainlinks\">Du søgte efter \"$1\": <a href=\"/wiki/$1\">Gå til</a> | <b><a href=\"/w/wiki.phtml?title=$1&action=edit\">Redigér</a></b> | <a href=\"/w/wiki.phtml?title=$1&action=history\">Historik</a> | <a href=\"/w/wiki.phtml?title=Speciel:Whatlinkshere&target=$1\">Hvad henviser hertil</a> | <a href=\"http://da.wiktionary.org/wiki/Special:Search?search=$1&go=G%E5+til\">Søg Wiktionary</a></div></big>",
+"badquery"             => "Forkert udformet forespørgsel",
+"badquerytext" => "Vi kunne ikke udføre din forespørgsel.
+Det er sandsynligvis fordi du har forsøgt at søge efter et ord med
+færre end tre bogstaver, hvilket ikke understøttes endnu.
+Det kan også være du har skrevet forkert, for
+eksempel \"fisk og og skaldyr\".
+Prøv en anden forespørgsel.",
+"matchtotals"  => "Forespørgslen \"$1\" opfyldte $2 artikeltitler
+og teksten i $3 artikler.",
+"nogomatch" => "{{SITENAME}} har ingen artikel med dette navn. Du kan [[$1|oprette en artikel med dette navn]] eller [[{{ns:4}}:Efterspurgte_artikler|efterspørge den]]. For at undgå flere artikler om samme emne, bedes du inden oprettelsen søge efter artiklen under alternative navne og stavemåder.",
+"titlematches" => "Artikeltitler der opfyldte forespørgslen",
+"notitlematches" => "Ingen artikeltitler opfyldte forespørgslen",
+"textmatches"  => "Artikeltekster der opfyldte forespørgslen",
+"notextmatches"        => "Ingen artikeltekster opfyldte forespørgslen",
+"prevn"                        => "forrige $1",
+"nextn"                        => "næste $1",
+"viewprevnext" => "Vis ($1) ($2) ($3).",
+"showingresults" => "Nedenfor vises <b>$1</b> resultater startende med
+nummer <b>$2</b>.",
+"showingresultsnum" => "Herunder vises <b>$3</b> resultater startende med nummer <b>$2</b>.",
+"nonefound"            => "<strong>Bemærk</strong>: Søgning uden resultat skyldes at man søger efter almindelige ord som \"har\" og \"fra\", der ikke er indekseret, eller at man har angivet mere end ét søgeord (da kun sider indeholdende alle søgeordene vil blive fundet).",
+"powersearch" => "Søg",
+"powersearchtext" => "
+Søg i navnerum:<br />
+$1<br />
+$2 List omdirigeringer &nbsp; Søg efter $3 $9",
+"searchdisabled" => "<p>Beklager! Fuldtekstsøgningen er midlertidigt afbrudt på grund af for stor belastning på serverne. I mellemtidem kan du anvende Google- eller Yahoo!-søgefelterne herunder. Bemærk at deres kopier af {{SITENAME}}s indhold kan være forældet.</p>",
+"blanknamespace" => "(Artikler)",
+
+# Preferences page
+#
+"preferences"  => "Indstillinger",
+"prefsnologin" => "Ikke logget på",
+"prefsnologintext"     => "Du skal være [[Speciel:Userlogin|logget på]]
+for at ændre brugerindstillinger.",
+"prefslogintext" => "Du logget på som \"[[Bruger:$1|$1]]\" ([[Bruger_diskussion:$1|Diskussion]], [[Speciel:Contributions/$1|bidrag]]).
+Dit interne ID-nummer er $2.
+
+Se [[Project:Hvordan sætter jeg mine indstillinger]] for en forklaring på de forskellige indstillinger.",
+"prefsreset"   => "Indstillingerne er blevet gendannet fra lageret.",
+"qbsettings"   => "Hurtigmenu",
+"changepassword" => "Skift adgangskode",
+"skin"                 => "Udseende",
+"math"                 => "Matematiske formler",
+"dateformat"   => "Datoformat",
+"math_failure"         => "Fejl i matematikken",
+"math_unknown_error"   => "ukendt fejl",
+"math_unknown_function"        => "ukendt funktion ",
+"math_lexing_error"    => "lexerfejl",
+"math_syntax_error"    => "syntaksfejl",
+'math_image_error'     => 'PNG-konvertering mislykkedes; undersøg om latex, dvips, gs og convert er installeret korrekt',
+'math_bad_tmpdir'      => 'Kan ikke skrive til eller oprette temp-mappe til math',
+'math_bad_output'      => 'Kan ikke skrive til eller oprette uddata-mappe til math',
+'math_notexvc' => 'Manglende eksekvérbar texvc; se math/README for opsætningsoplysninger.',
+'prefs-personal' => 'Brugerdata',
+'prefs-rc' => 'Seneste ændringer og artikelstumper',
+'prefs-misc' => 'Forskelligt',
+"saveprefs"            => "Gem indstillinger",
+"resetprefs"   => "Gendan indstillinger",
+"oldpassword"  => "Gammel adgangskode",
+"newpassword"  => "Ny adgangskode",
+"retypenew"            => "Gentag ny adgangskode",
+"textboxsize"  => "Redigering",
+"rows"                 => "Rækker",
+"columns"              => "Kolonner",
+"searchresultshead" => "Søgeresultater",
+"resultsperpage" => "Resultater pr. side",
+"contextlines" => "Linjer pr. resultat",
+"contextchars" => "Tegn pr. linje i resultatet",
+"stubthreshold" => "Grænse for visning af artikelstumper",
+"recentchangescount" => "Antallet af titler på siden \"seneste ændringer\"",
+"savedprefs"   => "Dine indstillinger er blevet gemt.",
+'timezonelegend' => 'Tidszone',
+"timezonetext" => "Indtast antal timer din lokale tid er forskellig
+fra serverens tid (UTC). Der bliver automatisk tilpasset til dansk tid,
+ellers skulle man for eksempel for dansk vintertid, indtaste \"1\"
+(og \"2\" når vi er på sommertid).",
+"localtime"    => "Lokaltid",
+"timezoneoffset" => "Forskel",
+"servertime"   => "Serverens tid er nu",
+"guesstimezone" => "Hent tidszone fra browseren",
+"emailflag"    => "Fravælg muligheden for at få e-mail fra andre brugere",
+"defaultns"            => "Søg som standard i disse navnerum:",
+'default'              => 'standard',
+'files'                        => 'Filer',
+
+# User levels special page
+#
+
+# switching pan
+'groups-lookup-group' => 'Administrér grupperettigheder',
+'groups-group-edit' => 'Eksisterende grupper: ',
+'editgroup' => 'Redigér gruppe',
+'addgroup' => 'Tilføj gruppe',
+
+'userrights-lookup-user' => 'Administrér brugergrupper',
+'userrights-user-editname' => 'Skriv et brugernavn: ',
+'editusergroup' => 'Redigér brugergrupper',
+
+# group editing
+'groups-editgroup' => 'Redigér gruppe',
+'groups-addgroup' => 'Tilføj gruppe',
+'groups-editgroup-preamble' => 'Hvis navn eller beskrivelse starter med et kolon, så vil
+resten blive behandlet som et navn på en besked, og derfor vil teksten blive behandlet som
+en besked i MediaWiki navnerummet',
+'groups-editgroup-name' => 'Gruppenavn: ',
+'groups-editgroup-description' => 'Gruppebeskrivelse (max 255 tegn):<br />',
+'savegroup' => 'Gem gruppe',
+'groups-tableheader'        => 'ID || Navn || Beskrivelse || Rettigheder',
+'groups-existing'           => 'Eksisterende grupper',
+'groups-noname'             => 'Angiv venligst et lovligt gruppenavn',
+'groups-already-exists'     => 'En gruppe ved et navn eksisterer allerede',
+'addgrouplogentry'          => 'Tilføjet gruppe $2',
+'changegrouplogentry'       => 'Ændret gruppe $2',
+'renamegrouplogentry'       => 'Omdøbt gruppe $2 to $3',
+
+# user groups editing
+#
+'userrights-editusergroup' => 'Redigér brugergrupper',
+'saveusergroups' => 'Gem brugergrupper',
+'userrights-groupsmember' => 'Medlem af:',
+'userrights-groupsavailable' => 'Tilgængelige grupper:',
+'userrights-groupshelp' => 'Vælg grupper som du ønsker brugeren skal fjernes fra eller føjes til.
+Grupper som ikke er valgt, vil ikke blive ændret. Du kan ophæve valget af en gruppe ved hjælp af CTRL-tasten og et venstreklik.',
+'userrights-logcomment' => 'Ændret gruppemedlemskab fra $1 til $2',
+
+# Default group names and descriptions
+#
+'group-anon-name'       => 'Anonym',
+'group-anon-desc'       => 'Anonyme brugere',
+'group-loggedin-name'   => 'Bruger',
+'group-loggedin-desc'   => 'Generel bruger der er logget på',
+'group-admin-name'      => 'Administrator',
+'group-admin-desc'      => 'En bruger der kan blokere andre brugere og slette sider',
+'group-bureaucrat-name' => 'Bureaukrat',
+'group-bureaucrat-desc' => 'Bureaukrater kan udnævne administratorer',
+'group-steward-name'    => 'Steward',
+'group-steward-desc'    => 'Fuld adgang',
+
+
+# Recent changes
+#
+"changes" => "ændringer",
+"recentchanges" => "Seneste ændringer",
+'recentchanges-url' => 'Speciel:Recentchanges',
+"rcloaderr"            => "Indlæser seneste ændrede sider",
+"rcnote"               => "Nedenfor er de seneste <strong>$1</strong> ændringer i de
+sidste <strong>$2</strong> dage.",
+"rcnotefrom"   => "Nedenfor er ændringerne fra <b>$2</b> indtil <b>$1</b> vist.",
+"rclistfrom"   => "Vis nye ændringer startende fra $1",
+'showhideminor' => "$1 mindre ændringer | $2 robotter | $3 brugere der er logget på | $4 patruljerede ændringer ",
+"rclinks"              => "Vis seneste $1 ændringer i de sidste $2 dage<br />$3",
+"rchide"               => "i $4 form; $1 mindre ændringer; $2 andre navnerum; $3 mere end en redigering.",
+"rcliu"                        => "; $1 redigeringer fra brugere der er logget på",
+"diff"                 => "forskel",
+"hist"                 => "historik",
+"hide"                 => "skjul",
+"show"                 => "vis",
+"tableform"            => "tabel",
+"listform"             => "liste",
+"nchanges"             => "$1 ændringer",
+"minoreditletter" => "m",
+"newpageletter" => "N",
+'sectionlink' => '→',
+'number_of_watching_users_RCview'      => '[$1]',
+'number_of_watching_users_pageview'    => '[$1 overvågende bruger/e]',
+
+# Upload
+#
+"upload"               => "Læg en fil op",
+"uploadbtn"            => "Læg en fil op",
+"uploadlink"   => "Læg en fil op",
+"reupload"             => "Læg en fil op igen",
+"reuploaddesc" => "Tilbage til formularen til at lægge filer op.",
+"uploadnologin" => "Ikke logget på",
+"uploadnologintext"    => "Du skal være [[Speciel:Userlogin|logget på]] for at kunne lægge filer op.",
+"uploaderror"  => "Fejl under oplægning af fil",
+"uploadtext"   => "[[Billede:Commons_without_text-35px.png|thumb|right|35px|Wiki-C]] Hvis du har billeder som kan være til nytte både her og på andre Wiki'er,
+anbefales det at lægge det op på '''[[Commons:Forside|Wikimedia Commons]]''' der er en fælles base for frie billeder og andre filer til alle Wikimedia-projekterne.
+For at lægge en fil op på Commons skal man oprette en brugerkonto der, på samme måde som på den danske {{SITENAME}}.
+Der er en oversat [[Commons:Commons:Første skridt|vejledning]], og en dansksproget [[Commons:Forside|forside]].
+Når du skal bruge et billede fra Commons skal du bare udskifte ''image:fexxx.jpg'' med ''billede:fexxx.jpg'' i koden.
+Logoet ovenfor til højre er hentet fra Commons, og sat ind her med denne kode: :<nowiki>[[Billede:Commons_without_text-35px.png|thumb|right|35px|Wiki-C]]</nowiki>
+
+<div style=\"border: 1px solid grey; background: \#ddf; padding: 7px; margin: 0 auto;\">
+<strong>STOP!</strong> Før du lægger filer op her,
+så vær sikker på du har læst og følger {{SITENAME}}s
+[[{{NS:4}}:Politik om brug af billeder|politik om brug af billeder]].
+
+Følg venligst disse retningslinjer:
+<ul>
+<li>Angiv tydeligt hvor filen stammer fra</li>
+<li>Angiv tydeligt hvilken licens filen er omfattet af, ved at tilføje en af skabelonerne <tt>&#123;{GFDL}}</tt> eller <tt>&#123;{PD}}</tt> eller en af de andre du kan finde på [[{{NS:4}}:Skabeloner#Ophavsret|skabelonsiden]].</li>
+<li>Brug et beskrivende filnavn, så det er til at se hvad filen indeholder</li>
+<li>Tjek i [[Speciel:Imagelist|listen over filer]] om filen allerede er lagt op</li>
+</ul>
+</div>
+<p>Brug formularen herunder til at lægge nye filer op, som kan bruges i dine artikler.
+På de fleste browsere vil du se en \"Browse...\" knap eller en
+\"Gennemse...\" knap, som vil
+bringe dig til dit styresystems standard-dialog til åbning af filer.
+Når du vælger en fil, vil navnet på filen dukke op i tekstfeltet
+ved siden af knappen.
+Du skal også bekræfte, at du ikke er ved at bryde nogens ophavsret.
+Det gør du ved at sætte et mærke i tjekboksen.
+Vælg \"Læg en fil op\"-knappen for at lægge filen op.
+Dette kan godt tage lidt tid hvis du har en langsom internetforbindelse.
+
+<p>De foretrukne formater er JPEG til fotografiske billeder, PNG
+til tegninger og andre små billeder, og OGG til lyd.
+For at bruge et billede i en artikel, så brug et link af denne type
+'''<nowiki>[[billede:fil.jpg]]</nowiki>''' eller
+'''<nowiki>[[billede:fil.png|alternativ tekst]]</nowiki>''' eller
+'''<nowiki>[[media:fil.ogg]]</nowiki>''' for lyd.
+
+<p>Læg mærke til at præcis som med alle andre sider, så kan og må andre gerne
+redigere eller
+slette de filer, du har lagt op, hvis de mener det hjælper {{SITENAME}}, og
+du kan blive blokeret fra at lægge op hvis du misbruger systemet.",
+"uploadlog"            => "oplægningslog",
+"uploadlogpage" => "Oplægningslog",
+"uploadlogpagetext" => "Herunder en liste over de senest oplagte filer. Alle de viste tider er serverens tid (UTC).
+",
+"filename"             => "Filnavn",
+"filedesc"             => "Beskrivelse",
+'filestatus' => 'Status på ophavsret',
+'filesource' => 'Kilde',
+"copyrightpage" => "{{ns:project}}:Ophavsret",
+"copyrightpagename" => "{{SITENAME}} ophavsret",
+"uploadedfiles"        => "Filer som er lagt op",
+"ignorewarning"        => "Ignorér advarslen og gem filen alligevel.",
+"minlength"            => "Navnet på filen skal være på mindst tre bogstaver.",
+'illegalfilename'      => 'Filnavnet "$1" indeholder tegn, der ikke er tilladte i sidetitler. Omdøb filen og prøv at lægge den op igen.',
+"badfilename"  => "Navnet på filen er blevet ændret til \"$1\".",
+"badfiletype"  => "\".$1\" er ikke et af de anbefalede filformater.",
+"largefile"            => "Det anbefales, at filer ikke fylder mere end 100kb.",
+'emptyfile'            => 'Filen du lagde op lader til at være tom. Det kan skyldes en slåfejl i filnavnet. Kontroller om du virkelig ønsker at lægge denne fil op.',
+'fileexists'           => 'En fil med det navn findes allerede, tjek venligst $1 om du er sikker på du vil ændre den.',
+"successfulupload" => "Oplægning er gennemført med succes",
+"fileuploaded" => "Filen \"$1\" er lagt op med succes.
+Følg dette link: ($2) til siden med beskrivelse, og udfyld
+information omkring filen, såsom hvor den kom fra, hvornår den er lavet
+og af hvem, og andre ting du ved om filen.",
+"uploadwarning" => "Oplægningsadvarsel",
+"savefile"             => "Gem fil",
+"uploadedimage" => "Lagde \"[[$1]]\" op",
+"uploaddisabled" => "Desværre er funktionen til at lægge billeder op afbrudt på denne server.",
+'uploadscripted' => 'Denne fil indeholder HTML eller script-kode, der i visse tilfælde can fejlfortolkes af en browser.',
+'uploadcorrupt' => 'Denne fil er beskadiget eller forsynet med en forkert endelse. Kontroller venligst filen og prøv at lægge den op igen.',
+'uploadvirus' => 'Denne fil indeholder en virus! Virusnavn: $1',
+
+# Image list
+#
+"imagelist"            => "Liste over billeder",
+"imagelisttext"        => "Herunder er en liste med $1 billeder sorteret $2.",
+"getimagelist" => "henter billedliste",
+"ilsubmit"             => "Søg",
+"showlast"             => "Vis de sidste $1 billeder sorteret $2.",
+"byname"               => "efter navn",
+"bydate"               => "efter dato",
+"bysize"               => "efter størrelse",
+"imgdelete"            => "slet",
+"imgdesc"              => "beskrivelse",
+"imglegend"            => "Forklaring: (beskrivelse) = vis/redigér billedebeskrivelse.",
+"imghistory"   => "Billedhistorik",
+"revertimg"            => "gendan",
+"deleteimg"            => "slet",
+"deleteimgcompletely"          => "Slet alle revisioner af dette billede",
+"imghistlegend" => "Forklaring: (nuværende) = dette er det nuværende billede,
+(slet) = slet denne gamle version, (gendan) = gendan en gammel version.
+<br /><i>Klik på en dato for at se billedet, som er lagt op den dag</i>.",
+"imagelinks"   => "Billedehenvisninger",
+"linkstoimage" => "De følgende sider henviser til dette billede:",
+"nolinkstoimage" => "Der er ingen sider der henviser til dette billede.",
+'sharedupload' => '<br clear=all> {| border="0" cellpadding="5" style="font-weight:normal; float:center; border:solid #008 1px;margin-left:5px;margin-bottom:5px" |- |[[Billede:CommonsLogo.png|50px|none|Commons|<nowiki></nowiki>]] |Denne fil er fra [[Commons:Forside|Wikimedia Commons]], en samling af [[åbent indhold]] som [[Wikimedia Foundation]] er vært for.<br />Se venligst siden med [[Commons:Image:{{PAGENAME}}|beskrivelse af billedet]] for information om ophavsret. |} <br clear=all>.',
+'shareduploadwiki' => 'Se venligst [$1 siden med billedbeskrivelsen] for yderligere information.',
+'noimage'       => 'Der eksisterer ingen fil med dette navn, du kan [$1 lægge den op]',
+'uploadnewversion' => '[$1 Læg en ny version af denne fil op]',
+
+# Statistics
+#
+"statistics"   => "Statistik",
+"sitestats"            => "Statistiske oplysninger om {{SITENAME}}",
+"userstats"            => "Statistik om brugere på {{SITENAME}}",
+"sitestatstext" => "Der er i alt '''$1''' sider i databasen.
+Dette tal indeholder \"diskussion\"-sider, sider om {{SITENAME}}, omdirigeringssider og andre sider der sikkert ikke kan kaldes artikler.
+Hvis man udelader disse, så er der '''$2''' sider som sandsynligvis er rigtige artikler.
+Der har i alt været '''$4''' sideredigeringer siden programmellet blev opdateret den 25. september 2002.
+Det vil sige, at der har været '''$5''' gennemsnitlige redigeringer pr. side.
+For mere udførlige statistikker se:
+*[http://www.wikipedia.org/wikistats/DA/Sitemap.htm Omfattende Wikipedia-statistik]
+*[http://wikimedia.org/stats/da.wikipedia.org Antal besøgende på Wikipedia]
+*[http://wikimedia.org/stats/live Aktuelle grafer over servertrafikken]
+*[[{{ns:4}}:Statistik|Statistik over væksten]] .",
+"userstatstext" => "Der er '''$1''' registrerede brugere.
+'''$2''' (eller '''$4%''') af disse er administratorer (se $3).
+* [http://www.wikipedia.org/wikistats/DA/TablesWikipediaDA.htm#wikipedians Aktive brugere].",
+
+# Maintenance Page
+#
+"maintenance"          => "Vedligeholdelsesside",
+"maintnancepagetext"   => "På denne side er der forskellige smarte
+værktøjer til at vedligeholde {{SITENAME}}. Nogle af disse funktioner er ret
+hårde for databasen (de tager lang tid), så lad være med at opdatere siden
+hver gang du har rettet en enkelt ting ;-)",
+"maintenancebacklink"  => "Tilbage til vedligeholdelsessiden",
+"disambiguations"      => "Artikler med flertydige titler",
+"disambiguationspage"  => "Project:Henvisninger til artikler med flertydige titler",
+"disambiguationstext"  => "De følgende artikler henviser til
+<i>artikler med flertydige titler</i>. De skulle henvise til en ikke-flertydig
+titel i stedet for.<br />En artikel bliver behandlet som flertydig, hvis den er
+henvist fra $1.<br />Henvisninger fra andre navnerum er <i>ikke</i> listet her.",
+"doubleredirects"      => "Dobbelte omdirigeringer",
+"doubleredirectstext"  => "<b>Bemærk:</b> Denne liste kan indeholde forkerte
+resultater. Det er som regel, fordi siden indeholder ekstra tekst under den
+første #REDIRECT.<br />\nHver linje indeholder henvisninger til den første og den
+anden omdirigering, og den første linje fra den anden omdirigeringstekst,
+det giver som regel den \"rigtige\" målartikel, som den første omdirigering
+skulle have peget på.",
+"brokenredirects"      => "Dårlige omdirigeringer",
+"brokenredirectstext"  => "De følgende omdirigeringer peger på en side der
+ikke eksisterer.",
+"selflinks"            => "Sider der henviser til sig selv",
+"selflinkstext"                => "De følgende sider indeholder henvisninger til sig selv,
+men det burde de ikke.",
+"mispeelings"           => "Sider med stavefejl",
+"mispeelingstext"               => "De følgende sider indeholder en af de
+almindelig stavefejl, som er listet på $1. Den korrekte stavemåde kan
+angives i paranteser efter den fejlagtige stavemåde (sådan her).",
+"mispeelingspage"       => "Liste over almindelige stavefejl",
+"missinglanguagelinks"  => "Manglende sproghenvisninger",
+"missinglanguagelinksbutton"    => "Find manglende sproghenvisninger for",
+"missinglanguagelinkstext"      => "Disse artikler har <i>ikke</i> nogen
+henvisning til den samme artikel i $1. Omdirigeringer og underartikler er
+<i>ikke</i> vist.",
+
+
+# Miscellaneous special pages
+#
+"orphans"              => "Forældreløse artikler",
+'geo'          => 'GEO-koordinater',
+'validate'             => 'Validér side',
+"lonelypages"  => "Forældreløse artikler",
+'uncategorizedpages'   => 'Ukategoriserede sider',
+'uncategorizedcategories'      => 'Ukategoriserede kategorier',
+"unusedimages" => "Ubrugte billeder",
+"popularpages" => "Populære artikler",
+"nviews"               => "$1 visninger",
+"wantedpages"  => "Ønskede artikler",
+"nlinks"               => "$1 henvisninger",
+"allpages"             => "Alle artikler",
+"randompage"   => "Tilfældig artikel",
+'randompage-url'=> 'Speciel:Randompage',
+"shortpages"   => "Korte artikler",
+"longpages"            => "Lange artikler",
+'deadendpages'  => 'Blindgydesider',
+"listusers"            => "Liste over brugere",
+"specialpages" => "Specielle sider",
+"spheading"            => "Specielle sider for alle brugere",
+'restrictedpheading'   => 'Specielle sider med begrænset adgang',
+"protectpage"  => "Beskyt side",
+"recentchangeslinked" => "Relaterede ændringer",
+"rclsub"               => "(til sider henvist fra \"$1\")",
+"debug"                        => "Aflus",
+"newpages"             => "Nyeste artikler",
+"ancientpages"         => "Ældste artikler",
+"intl"         => "Sproghenvisninger",
+"movethispage" => "Flyt side",
+"unusedimagestext" => "<p>Læg mærke til, at andre websider
+såsom de andre internationale {{SITENAME}}er måske henviser til et billede med
+en direkte URL, så det kan stadig være listet her, selvom det er
+i aktivt brug.",
+"booksources"  => "Bogkilder",
+'categoriespagetext' => 'De følgende kategorier eksisterer på {{SITENAME}}.',
+'data' => 'Data',
+
+# FIXME: Other sites, of course, may have affiliate relations with the booksellers list
+"booksourcetext" => "Herunder er en liste af henvisninger til steder der
+udlåner og/eller sælger nye og brugte bøger, og som måske også har
+yderligere oplysninger om bøger du leder efter.
+{{SITENAME}} er ikke associeret med nogen af disse steder,
+og denne liste skal ikke ses som en anbefaling af disse.",
+'isbn' => 'ISBN',
+'rfcurl' =>  'http://www.faqs.org/rfcs/rfc$1.html',
+'pubmedurl' =>  'http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?cmd=Retrieve&db=pubmed&dopt=Abstract&list_uids=$1',
+"alphaindexline" => "$1 til $2",
+'version'              => 'Information om MediaWiki',
+'log'          => 'Logs',
+'alllogstext'  => 'Samlet visning af oplægningslog, sletningslog, blokeringslog, bureaukratlog og listen over beskyttede sider.
+Du kan sortere i visningen ved at vælge type, brugernavn og/eller en udvalgt side.',
+
+# Special:Allpages
+'nextpage'          => 'Næste side ($1)',
+'allpagesfrom'         => 'Vis sider startende fra: $1',
+'allarticles'       => 'Alle artikler',
+'allnonarticles'       => 'Alle ikke-artikler',
+'allinnamespace'       => 'Alle sider (i $1 navnerummet)',
+'allnotinnamespace'    => 'Alle sider (ikke i $1 navnerummet)',
+'allpagesprev'      => 'Forrige',
+'allpagesnext'      => 'Næste',
+'allpagessubmit'    => 'Vis',
+
+# Email this user
+#
+"mailnologin"  => "Ingen afsenderadresse",
+"mailnologintext" => "Du skal være [[Speciel:Userlogin|logget på]] og have en gyldig e-mailadresse sat i dine [[Speciel:Preferences|indstillinger]] for at sende e-mail til andre brugere.",
+"emailuser"            => "E-mail til denne bruger",
+"emailpage"            => "E-mail bruger",
+"emailpagetext"        => "Hvis denne bruger har sat en gyldig e-mail-adresse i
+sine brugerindstillinger, så vil formularen herunder sende en enkelt
+besked.
+Den e-mailadresse, du har sat i dine brugerindstillinger, vil dukke op
+i \"Fra\" feltet på denne mail, så modtageren er i stand til at svare.",
+'usermailererror' => 'E-mail-modulet returnerede en fejl: ',
+'defemailsubject'  => "{{SITENAME}} e-mail",
+"noemailtitle" => "Ingen e-mail-adresse",
+"noemailtext"  => "Denne bruger har ikke angivet en gyldig e-mail-adresse,
+eller har valgt ikke at modtage e-mail fra andre brugere.",
+"emailfrom"            => "Fra",
+"emailto"              => "Til",
+"emailsubject" => "Emne",
+"emailmessage" => "Besked",
+"emailsend"            => "Send",
+"emailsent"            => "E-mail sendt",
+"emailsenttext" => "Din e-mail er blevet sendt.",
+
+# Watchlist
+#
+"watchlist"            => "Overvågningsliste",
+"watchlistsub" => "(for bruger \"$1\")",
+"nowatchlist"  => "Du har ingenting i din overvågningsliste.",
+"watchnologin" => "Ikke logget på",
+"watchnologintext"     => "Du skal være [[Speciel:Userlogin|logget på]] for at kunne ændre din overvågningsliste.",
+"addedwatch"   => "Tilføjet til din overvågningsliste",
+"addedwatchtext" => "Siden \"$1\" er blevet tilføjet til din [[Speciel:Watchlist|overvågningsliste]]. Fremtidige ændringer til denne side og den tilhørende diskussionsside vil blive listet der, og siden vil fremstå '''fremhævet''' i [[Speciel:Recentchanges|listen med de seneste ændringer]] for at gøre det lettere at finde den. Hvis du senere vil fjerne siden fra din overvågningsliste, så klik \"Fjern overvågning\".",
+"removedwatch" => "Fjernet fra overvågningsliste",
+"removedwatchtext" => "Siden \"$1\" er blevet fjernet fra din
+overvågningsliste.",
+'watch' => 'Overvåg',
+"watchthispage"        => "Overvåg side",
+'unwatch' => 'Fjern overvågning',
+"unwatchthispage" => "Fjern overvågning",
+"notanarticle" => "Ikke en artikel",
+"watchnochange" => "Ingen af siderne i din overvågningsliste er ændret i den valgte periode.",
+"watchdetails" => "* Du har $1 sider på din overvågningsliste (fratrukket alle diskussionssider).
+* I tidsintervallet valgt herunder, har brugerne foretaget $2 redigeringer i {{SITENAME}}.
+* $3
+* Du kan [[Special:Watchlist/edit|vise og redigere den komplette liste]].",
+'wlheader-enotif'              => "* E-mail underretning er slået til.",
+'wlheader-showupdated'   => "* Sider der er ændret siden dit sidste besøg er '''fremhævet'''",
+"watchmethod-recent" => "Tjekker seneste ændringer for sider i din overvågningsliste",
+"watchmethod-list" => "Tjekker seneste ændringer for sider i din overvågningsliste",
+"removechecked" => "Fjern valgte sider fra min overvågningsliste",
+"watchlistcontains" => "Din overvågningsliste indeholder $1 sider.",
+"watcheditlist" => "Her er en alfabetisk liste over siderne i din overvågningsliste.
+Vælg de sider du vil fjerne fra din overvågningsliste
+og klik på 'fjern valgte sider fra min overvågningsliste' knappen
+i bunden af skærmen.",
+"removingchecked" => "Fjerner de valgte sider fra din overvågningsliste...",
+"couldntremove" => "Kunne ikke fjerne '$1'...",
+"iteminvalidname" => "Problem med '$1', ugyldigt navn...",
+"wlnote" => "Nedenfor er de seneste $1 ændringer i de sidste <b>$2</b> timer.",
+'wlshowlast'           => "Vis de seneste $1 timer $2 dage $3",
+'wlsaved'                      => 'Dette er en gemt version af din overvågningsliste.',
+'wlshow'               => 'Vis',
+'wlhide'               => 'Skjul',
+'wlhideshowown'                => '$1 mine redigeringer.',
+'enotif_mailer'                => '{{SITENAME}} informationsmail',
+'enotif_reset'                 => 'Marker alle sider som besøgt',
+'enotif_newpagetext'=> 'Dette er en ny side.',
+'changed'                      => 'ændret',
+'created'                      => 'oprettet',
+'enotif_subject'       => '{{SITENAME}}-siden $PAGETITLE_QP er blevet ændret af $PAGEEDITOR_QP',
+'enotif_lastvisited' => 'Se $1 for alle ændringer siden dit sidste besøg.',
+'enotif_body' => 'Kære $WATCHINGUSERNAME,
+
+{{SITENAME}}-siden $PAGETITLE er blevet ændret den $PAGEEDITDATE af $PAGEEDITOR, se $PAGETITLE_URL for den nyeste version.
+
+$NEWPAGE
+
+Bidragyderens beskrivelse: $PAGESUMMARY $PAGEMINOREDIT
+Kontakt bidragyderen:
+mail $PAGEEDITOR_EMAIL
+wiki $PAGEEDITOR_WIKI
+
+Du vil ikke modtage flere beskeder om yderligere ændringer af denne side med mindre du besøger den. På din overvågningsliste kan du også nulstille alle markeringer på de sider, du overvåger.
+
+             Med venlig hilsen {{SITENAME}}s informationssystem
+
+--
+Besøg {{SERVER}}{{localurl:Special:Watchlist/edit}} for at ændre indstillingerne for din overvågningsliste
+
+Tilbagemelding og yderligere hjælp:
+{{SERVER}}{{localurl:Landsbybrønden}}',
+
+# Delete/protect/revert
+#
+"deletepage"   => "Slet side",
+"confirm"              => "Bekræft",
+"excontent" => "indholdet var: '$1'",
+"excontentauthor" => "indholdet var: '$1' (og den eneste forfatter var '$2')",
+"exbeforeblank" => "indholdet før siden blev tømt var: '$1'",
+"exblank" => "siden var tom",
+"confirmdelete" => "Bekræft sletning",
+"deletesub"            => "(Sletter \"$1\")",
+"historywarning" => "Advarsel: Siden du er ved at slette har en historie: ",
+"confirmdeletetext" => "Du er ved permanent at slette en side
+eller et billede sammen med hele den tilhørende historie fra databasen.
+Bekræft venligst at du virkelig vil gøre dette, at du forstår
+konsekvenserne, og at du gør dette i overensstemmelse med
+[[Project:Politik]].",
+"actioncomplete" => "Gennemført",
+"deletedtext"  => "\"$1\" er slettet.
+Se $2 for en fortegnelse over de nyeste sletninger.",
+"deletedarticle" => "slettede \"$1\"",
+"dellogpage"   => "Sletningslog",
+"dellogpagetext" => "Herunder er en liste over de nyeste sletninger.
+Alle tider er serverens tid (UTC).
+",
+"deletionlog"  => "sletningslog",
+"reverted"             => "Gendannet en tidligere version",
+"deletecomment"        => "Begrundelse for sletning",
+"imagereverted" => "Gendannelse af en tidligere version gennemført med
+succes.",
+"rollback"             => "Fjern redigeringer",
+'rollback_short' => 'Fjern redigering',
+"rollbacklink" => "fjern redigering",
+"rollbackfailed" => "Kunne ikke fjerne redigeringen",
+"cantrollback" => "Kan ikke fjerne redigering;
+den sidste bruger er den eneste forfatter.",
+"alreadyrolled"        => "Kan ikke fjerne den seneste redigering af [[$1]] foretaget af [[Bruger:$2|$2]] ([[Bruger diskussion:$2|diskussion]]); en anden har allerede redigeret siden eller fjernet redigeringen. Den seneste redigering er foretaget af [[Bruger:$3|$3]] ([[Bruger diskussion:$3|diskussion]]). ",
+#   only shown if there is an edit comment
+"editcomment" => "Kommentaren til redigeringen var: \"<i>$1</i>\".",
+"revertpage"   => "Gendannelse til seneste version ved $1, fjerner ændringer fra $2",
+'sessionfailure' => 'There seems to be a problem with your login session;
+this action has been canceled as a precaution against session hijacking.
+Please hit "back" and reload the page you came from, then try again.',
+"protectlogpage" => "Liste_over_beskyttede_sider",
+"protectlogtext" => "Herunder er en liste over sider der er blevet beskyttet/har fået fjernet beskyttelsen.
+Se [[Project:Beskyttet side]] for mere information.",
+"protectedarticle" => "[[$1]] beskyttet",
+"unprotectedarticle" => "fjernet beskyttelse af [[$1]]",
+'protectsub' =>"(Beskytter \"$1\")",
+'confirmprotecttext' => 'Vil du virkelig beskytte denne side?',
+'confirmprotect' => 'Bekræft beskyttelse',
+'protectmoveonly' => 'Beskyt kun fra at blive flyttet',
+'protectcomment' => 'Begrundelse for beskyttelse',
+'unprotectsub' =>"(Fjern beskyttelse af \"$1\")",
+'confirmunprotecttext' => 'Vil du virkelig fjerne beskyttelsen fra denne side?',
+'confirmunprotect' => 'Bekræft fjernelse af beskyttelse',
+'unprotectcomment' => 'Begrundelse for fjernet beskyttelse',
+
+# Undelete
+"undelete" => "Gendan en slettet side",
+"undeletepage" => "Se og gendan slettede sider",
+"undeletepagetext" => "De følgende sider er slettede, men de findes
+stadig i arkivet og kan gendannes. Arkivet blivet periodevis slettet.",
+"undeletearticle" => "Gendan slettet artikel",
+"undeleterevisions" => "$1 revisioner arkiveret",
+"undeletehistory" => "Hvis du gendanner siden, vil alle de historiske
+revisioner også blive gendannet. Hvis en ny side med det samme navn
+er oprettet siden denne blev slettet, så vil de gendannede revisioner
+dukke op i den tidligere historie, og den nyeste revision vil forblive
+på siden.",
+"undeleterevision" => "Slettet version fra $1",
+"undeletebtn" => "Gendan!",
+"undeletedarticle" => "gendannede \"$1\"",
+'undeletedrevisions' => "$1 versioner gendannet",
+"undeletedtext"   => "Artiklen [[$1]] er blevet gendannet med succes.
+Se [[{{ns:project}}:Sletningslog]] for en fortegnelse over nylige
+sletninger og gendannelser.",
+
+# Namespace form on various pages
+'namespace' => 'Namvnerum:',
+'invert' => 'Invert selection',
+
+# Contributions
+#
+"contributions"        => "Brugerbidrag",
+"mycontris" => "Mine bidrag",
+"contribsub"   => "For $1",
+"nocontribs"   => "Ingen ændringer er fundet som opfylder disse kriterier.",
+"ucnote"       => "Herunder er denne brugers sidste <b>$1</b> ændringer i de
+sidste <b>$2</b> dage.",
+"uclinks"      => "Vis de sidste $1 ændringer; vis de sidste $2 dage.",
+"uctop"                => " (top)" ,
+'newbies'       => 'nybegyndere',
+
+# What links here
+#
+"whatlinkshere"        => "Hvad henviser hertil",
+"notargettitle" => "Intet mål",
+"notargettext" => "Du har ikke angivet en målside eller bruger at udføre denne funktion på.",
+"linklistsub"  => "(Liste over henvisninger)",
+"linkshere"    => "De følgende sider henviser her til:",
+"nolinkshere"  => "Ingen sider henviser her til.",
+"isredirect"   => "omdirigeringsside",
+
+# Block/unblock IP
+#
+"blockip"              => "Bloker bruger",
+"blockiptext"  => "Brug formularen herunder til at blokere for skriveadgangen fra en specifik IP-adresse eller et brugernavn. Dette må kun gøres for at forhindre vandalisme og skal være i overensstemmelse med [[{{ns:4}}:Politik|{{SITENAME}}s politik]]. Angiv en specifik begrundelse herunder (for eksempel med angivelse af sider der har været udsat for vandalisme). Udløbet (expiry) angives i GNUs standardformat, som er beskrevet i [http://www.gnu.org/software/tar/manual/html_chapter/tar_7.html vejledningen til tar] (på engelsk), fx \"1 hour\", \"2 days\", \"next Wednesday\", \"1 January 2017\". Alternativt kan en blokering gøres uendelig (skriv \"indefinite\" eller \"infinite\"). For oplysninger om blokering af IP-adresseblokke, se [[meta:Range blocks|IP-adresseblokke]] (på engelsk). For at ophæve en blokering, se [[Speciel:Ipblocklist|listen over blokerede IP-adresser og brugernavne]].",
+"ipaddress"            => "IP-adresse/brugernavn",
+'ipbexpiry'            => 'Udløb',
+"ipbreason"            => "Begrundelse",
+"ipbsubmit"            => "Bloker denne bruger",
+"badipaddress" => "IP-adressen/brugernavnet er udformet forkert eller eksistere ikke.",
+"blockipsuccesssub" => "Blokering udført med succes",
+"blockipsuccesstext" => "\"$1\" er blevet blokeret.
+<br />Se [[Speciel:Ipblocklist|IP blokeringslisten]] for alle blokeringer.",
+"unblockip"            => "Ophæv blokering af bruger",
+"unblockiptext"        => "Brug formularen herunder for at gendanne skriveadgangen
+for en tidligere blokeret IP-adresse eller bruger.",
+"ipusubmit"            => "Ophæv blokeringen af denne adresse",
+"ipusuccess"   => "\"$1\" har fået ophævet blokeringen",
+"ipblocklist"  => "Liste over blokerede IP-adresser og brugernavne",
+'blocklistline'        => '$1, $2 blokerede $3 ($4)',
+'infiniteblock' => 'udløber infinite', //fixme
+'expiringblock' => 'udløber $1',
+"blocklink"            => "bloker",
+"unblocklink"  => "ophæv blokering",
+"contribslink" => "bidrag",
+"autoblocker"  => "Automatisk blokeret fordi du deler IP-adresse med \"$1\". Begrundelse \"$2\".",
+'blocklogpage' => 'Blokeringslog',
+'blocklogentry'        => 'blokerede "$1" med $2 som udløbstid',
+'blocklogtext' => 'Dette er en liste over blokerede brugere og ophævede blokeringer af brugere. Automatisk blokerede IP-adresser er ikke anført her. Se [[Speciel:Ipblocklist|blokeringslisten]] for den nuværende liste over blokerede brugere.',
+'unblocklogentry'      => 'ophævede blokering af "$1"',
+'range_block_disabled' => 'Sysop-muligheden for at oprette blokeringsklasser er slået fra.',
+'ipb_expiry_invalid'   => 'Udløbstiden er ugyldig.',
+'ip_range_invalid'     => "Ugyldigt IP-interval.\n",
+'proxyblocker' => 'Proxy-blokering',
+'proxyblockreason'     => 'Din IP-adresse er blevet blokeret fordi den er en såkaldt \'\'åben proxy\'\'. Kontakt din Internet-udbyder eller tekniske hotline og oplyse dem om dette alvorlige sikkerhedsproblem.',
+'proxyblocksuccess'    => "Færdig.\n",
+
+# Developer tools
+#
+"lockdb"               => "Lås database",
+"unlockdb"             => "Lås database op",
+"lockdbtext"   => "At låse databasen vil forhindre alle brugere i at kunne redigere sider, ændre indstillinger, redigere overvågningslister og andre ting der kræver ændringer i databasen. Bekræft venligst at du har til hensigt at gøre dette, og at du vil låse databasen op, når din vedligeholdelse er overstået.",
+"unlockdbtext" => "At låse databasen op vil gøre, at alle brugere igen
+kan redigere sider, ændre deres indstillinger, redigere deres
+overvågningsliste, og andre ting der kræver ændringer i databasen.
+Bekræft venligst at du har til hensigt at gøre dette.",
+"lockconfirm"  => "Ja, jeg vil virkelig låse databasen.",
+"unlockconfirm"        => "Ja, jeg vil virkelig låse databasen op.",
+"lockbtn"              => "Lås databasen",
+"unlockbtn"            => "Lås databasen op",
+"locknoconfirm" => "Du har ikke bekræftet handlingen.",
+"lockdbsuccesssub" => "Databasen er nu låst",
+"unlockdbsuccesssub" => "Databasen er nu låst op",
+"lockdbsuccesstext" => "MediaWikidatabasen er låst. <br />Husk at fjerne låsen når du er færdig med din vedligeholdelse.",
+"unlockdbsuccesstext" => "MediaWikidatabasen er låst op.",
+
+# Make sysop
+'makesysoptitle'       => 'Gør en bruger til administrator - sysop ',
+'makesysoptext'                => 'Denne formular bruges af bureaukrater til at gøre almindelige brugere til administratorer og/eller tildele andre rettigheder til en bruger.
+Indsæt navnet på brugeren i tekstboksen og tryk på knappen for at ændre rettighederne (i.e. gøre brugeren til administrator',
+'makesysopname'                => 'Brugerens navn:',
+'makesysopsubmit'      => 'Gør denne bruger til administrator',
+'makesysopok'          => "<b>Bruger \"$1\" er nu administrator</b>",
+'makesysopfail'                => "<b>Bruger \"$1\" kunne ikke gøres til administrator. (Har du stavet navnet rigtigt?)</b>",
+'setbureaucratflag' => 'Sæt bureaukratflag',
+'setstewardflag'    => 'Sæt steward flag',
+'bureaucratlog'                => 'Bureaukratlog',
+'rightslogtext'                => 'Dette er en log over ændringer i brugeres rettigheder.',
+'bureaucratlogentry'   => "Rettigheder for bruger \"$1\" sat til \"$2\"",
+'rights'                       => 'Rettigheder:',
+'set_user_rights'      => 'Tildel brugerrettigheder',
+'user_rights_set'      => "<b>Rettigheder for bruger \"$1\" er opdateret</b>",
+'set_rights_fail'      => "<b>Der kunne ikke tildeles brugerrettigheder til \"$1\". (Er navnet korrekt?)</b>",
+'makesysop'         => 'Tildel brugerrettigheder',
+'already_sysop'     => 'Denne bruger er allerede administrator',
+'already_bureaucrat' => 'Denne bruger er allerede bureaucrat',
+'already_steward'   => 'Denne bruger er allerede steward',
+
+# Validation
+'val_yes' => 'Ja',
+'val_no' => 'Nej',
+'val_of' => '$1 af $2',
+'val_revision' => 'Version',
+'val_time' => 'Tidspunkt',
+'val_user_stats_title' => 'Oversigt over valideringer for bruger $1',
+'val_my_stats_title' => 'Oversigt over mine valideringer',
+'val_list_header' => '<th>#</th><th>Topic</th><th>Range</th><th>Action</th>',
+'val_add' => 'Tilføj',
+'val_del' => 'Slet',
+'val_show_my_ratings' => 'Show my validations',
+'val_revision_number' => 'Version #$1',
+'val_warning' => '<b>Never, <i>ever</i>, change something here without <i>explicit</i> community consensus!</b>',
+'val_rev_for' => 'Revisions for $1',
+'val_details_th_user' => 'Bruger $1',
+'val_validation_of' => 'Validation of "$1"',
+'val_revision_of' => 'Version af $1',
+'val_revision_changes_ok' => 'Your ratings have been stored!',
+'val_rev_stats_link' => 'See the validation statistics for "$1" <a href="$2">here</a>',
+'val_revision_stats_link' => 'detaljer',
+'val_iamsure' => 'Check this box if you really mean it!',
+'val_details_th' => '<sub>Bruger</sub> \\ <sup>Emne</sup>',
+'val_clear_old' => 'Tøm mine andre valideringsdata for $1',
+'val_merge_old' => 'Anvend min tidligere vurdering hvor \'Ingen stillingtagen\' er valgt',
+'val_form_note' => '<b>Tip:</b> Kombinering af dine data betyder, at for den artikelrevision du vælger, vil alle valg hvor du har angivet <i>ingen stillingtagen</i> bliv sat til værdien og kommentaren fra den seneste revision du vurderede. Ønsker du for eksempel at ændre et enkelt valg for en nyere revision, men også at bevare dine øvrige valg for den pågældende artikel i denne revision, så angiv blot hvilket valg du ønsker at <i>ændre</i>, hvorefter kombineringen automatisk vil anvende dine tidligere valg ved de resterede valgmuligheder.',
+'val_noop' => 'Ingen stillingtagen',
+'val_topic_desc_page' => 'Project:Validation topics',
+'val_votepage_intro' => 'Change this text <a href="{{SERVER}}{{localurl:MediaWiki:Val_votepage_intro}}">here</a>!',
+'val_percent' => '<b>$1%</b><br />($2 af $3 point<br />pr. $4 brugere)',
+'val_percent_single' => '<b>$1%</b><br />($2 af $3 point<br />for én bruger)',
+'val_total' => 'Total',
+'val_version' => 'Version',
+'val_tab' => 'Validér',
+'val_this_is_current_version' => 'dette er den seneste version',
+'val_version_of' => "Version af $1" ,
+'val_table_header' => "<tr><th>Klasse</th>$1<th colspan=4>Vurdering</th>$1<th>Kommentar</th></tr>\n",
+'val_stat_link_text' => 'Valideringsstatistik for denne artikel',
+'val_view_version' => 'Se denne version',
+'val_validate_version' => 'Validér denne version',
+'val_user_validations' => 'Denne bruger har valideret $1 sider.',
+'val_no_anon_validation' => 'Du skal være logget på for at kunne validere artikler.',
+'val_validate_article_namespace_only' => 'Kun artikler kan valideres. Denne side er <i>ikke</i> i artikel-navnerummet.',
+'val_validated' => 'Validering afsluttet.',
+'val_article_lists' => 'Liste over validerede artikler',
+'val_page_validation_statistics' => 'Sidevalideringsstatistik for $1',
+
+# Move page
+#
+"movepage"             => "Flyt side",
+"movepagetext" => "Når du bruger formularen herunder vil du få omdøbt en
+side og flyttet hele sidens historie til det nye navn.
+Den gamle titel vil blive en omdirigeringsside til den nye titel.
+Henvisninger til den gamle titel vil ikke blive ændret. Sørg for at
+tjekke for dobbelte eller dårlige omdirigeringer.
+Du er ansvarlig for, at alle henvisninger stadig peger derhen, hvor det er
+meningen de skal pege.
+
+Bemærk at siden '''ikke''' kan flyttes hvis der allerede er en side
+med den nye titel, medmindre den side er tom eller er en omdirigering
+uden nogen historie. Det betyder at du kan flytte en side tilbage hvor
+den kom fra, hvis du kommer til at lave en fejl.
+
+<b>ADVARSEL!</b>
+Dette kan være en drastisk og uventet ændring for en populær side;
+vær sikker på, at du forstår konsekvenserne af dette før du
+fortsætter.",
+"movepagetalktext" => "Den tilhørende diskussionsside, hvis der er en,
+vil automatisk blive flyttet med siden '''medmindre:'''
+*Du flytter siden til et andet navnerum,
+*En ikke-tom diskussionsside allerede eksisterer under det nye navn, eller
+*Du fjerner markeringen i boksen nedenunder.
+
+I disse tilfælde er du nødt til at flytte eller sammenflette siden manuelt.",
+"movearticle"  => "Flyt side",
+"movenologin"  => "Ikke logget på",
+"movenologintext" => "Du skal være registreret bruger og være [[Speciel:Userlogin|logget på]]
+for at flytte en side.",
+"newtitle"             => "Til ny titel",
+"movepagebtn"  => "Flyt side",
+"pagemovedsub" => "Flytning gennemført",
+"pagemovedtext" => "Siden \"[[$1]]\" er flyttet til \"[[$2]]\".",
+"articleexists" => "En side med det navn eksisterer allerede, eller det
+navn du har valgt er ikke gyldigt. Vælg et andet navn.",
+"talkexists"   => "Siden blev flyttet korrekt, men den tilhørende
+diskussionsside kunne ikke flyttes, fordi der allerede eksisterer en
+med den nye titel. Du er nødt til at flette dem sammen manuelt.",
+"movedto"              => "flyttet til",
+"movetalk"             => "Flyt også \"diskussionssiden\", hvis den eksisterer.",
+"talkpagemoved" => "Den tilhørende diskussionsside blev også flyttet.",
+"talkpagenotmoved" => "Den tilhørende diskussionsside blev
+<strong>ikke</strong> flyttet.",
+'1movedto2'            => "$1 flyttet til $2",
+'1movedto2_redir' => '$1 flyttet til $2 over en omdirigering',
+'movelogpage' => 'Flyttelog',
+'movelogpagetext' => 'Nedenfor er en liste over flyttede sider.',
+'movereason'   => 'Begrundelse',
+'revertmove'   => 'gendan',
+'delete_and_move' => 'Slet og flyt',
+'delete_and_move_text' =>
+'==Sletning nødvendig==
+
+Målartiklen "[[$1]]" eksisterer allerede. Vil du slette den for at lave plads til flytningen?',
+'delete_and_move_reason' => 'Slet for at lave plads til flyningen',
+'selfmove' => "Begge sider har samme navn. Man kan ikke flytte en side oven i sig selv.",
+'immobile_namespace' => "Måltitlen er en speciel type; man kan ikke flytte sider ind i det navnerum.",
+
+# Export
+
+'export'               => 'Eksportér sider',
+'exporttext'   => 'Du kan eksportere teksten og historikken fra en eller flere sider i et simpelt XML format. Dette kan bruges til at indsætte siderne i en anden wiki der bruger MediaWiki softwaren, eller du kan beholde den for din egen fornøjelses skyld',
+'exportcuronly'        => 'Eksportér kun den nuværende version, ikke hele historikken',
+
+# Namespace 8 related
+
+'allmessages'  => 'Alle beskeder',
+'allmessagesname' => 'Navn',
+'allmessagesdefault' => 'Standard tekst',
+'allmessagescurrent' => 'Nuværende tekst',
+'allmessagestext'      => 'Dette er en liste over alle beskeder i MediaWiki: navnerummet.',
+'allmessagesnotsupportedUI' => 'Dit aktuelle grænsefladesprog <b>$1</b> er ikke understøttet af Special:AllMessages på dette websted. ',
+'allmessagesnotsupportedDB' => 'Special:AllMessages ikke understøttet fordi wgUseDatabaseMessages er slået fra.',
+
+# Thumbnails
+
+'thumbnail-more'       => 'Forstør ',
+'missingimage'         => "<b>Mangler billede</b><br /><i>$1</i>\n",
+'filemissing'          => 'Filen mangler',
+
+# Special:Import
+'import'       => 'Importere sider',
+'importinterwiki' => 'Transwiki import',
+'importtext'   => 'Eksportér filen fra kilde-wiki\'en ved hjælp af værktøjet Special:Export, gem den på din harddisk og læg den op her.',
+'importfailed' => "Importering fejlede: $1",
+'importnotext' => 'Tom eller ingen tekst',
+'importsuccess'        => 'Importen lykkedes!',
+'importhistoryconflict' => 'Der er en konflikt i versionhistorikken (siden kan have været importeret før)',
+'importnosources' => 'No transwiki import sources have been defined and direct history uploads are disabled.',
+
+# Keyboard access keys for power users
+'accesskey-search' => 'f',
+'accesskey-minoredit' => 'i',
+'accesskey-save' => 's',
+'accesskey-preview' => 'p',
+'accesskey-diff' => 'd',
+'accesskey-compareselectedversions' => 'v',
+
+# tooltip help for some actions, most are in Monobook.js
+'tooltip-search' => 'Søg i {{SITENAME}} [alt-f]',
+'tooltip-minoredit' => 'Marker dette som en mindre ændring [alt-i]',
+'tooltip-save' => 'Gem dine ændringer [alt-s]',
+'tooltip-preview' => 'Forhåndsvis dine ændringer, brug venligst denne funktion inden du gemmer! [alt-p]',
+'tooltip-diff' => 'Vis hvilke ændringer du har lavet i teksten. [alt-d]',
+'tooltip-compareselectedversions' => 'Se forskellene imellem de to valgte versioner af denne side. [alt-v]',
+'tooltip-watch' => 'Tilføj denne side til din overvågningsliste [alt-w]',
+
+# stylesheets
+#'Monobook.css' => '/* edit this file to customize the monobook skin for the entire site */',
+#'Monobook.js' => '/* redigér denne fil for at ændre js-indstillinger i monobook-udseendet */',
+
+# Metadata
+'nodublincore' => 'Dublin Core RDF-metadata er slået fra på denne server.',
+'nocreativecommons' => 'Creative Commons RDF-metadata er slået fra på denne server.',
+'notacceptable' => 'Wiki-serveren kan ikke levere data i et format, som din klient understøtter.',
+
+# Attribution
+
+'anonymous' => "Anonym(e) bruger(e) af {{SITENAME}}",
+'siteuser' => "{{SITENAME}} bruger $1",
+'lastmodifiedby' => "Denne side blev senest ændret $1 af $2.",
+'and' => 'og',
+'othercontribs' => "Baseret på arbejde af $1.",
+'others' => 'andre',
+'siteusers' => "{{SITENAME}} bruger(e) $1",
+'creditspage' => 'Sidens forfattere',
+'nocredits' => 'Der er ingen forfatteroplysninger om denne side.',
+
+# Spam protection
+
+'spamprotectiontitle' => 'Spambeskyttelsesfilter',
+'spamprotectiontext' => 'Siden du prøver at få adgang til er blokeret af spamfilteret. Dette skyldes sandsynligvis et link til et eksternt websted. Se [[m:spam blacklist]] for en komplet liste af blokerede websteder. Hvis du mener at spamfilteret blokerede redigeringen ved en fejl, så kontakt en [[m:Special:Listadmins|m:administrator]]. Det følgende er et udtræk af siden der bevirkede blokeringen:',
+'spamprotectionmatch' => 'Følgende tekst udløste vores spamfilter: $1',
+'subcategorycount' => "Der er $1 underkategorier i denne kategori.",
+'subcategorycount1' => "Der er $1 underkategori i denne kategori.",
+'categoryarticlecount' => "Der er $1 artikler i denne kategori.",
+'categoryarticlecount1' => "Der er $1 artikel i denne kategori.",
+'usenewcategorypage' => "1\n\nSet first character to \"0\" to disable the new category page layout.",
+'listingcontinuesabbrev' => " forts.",
+
+# Info page
+"infosubtitle" => "Information om siden",
+"numedits" => "Antal redigeringer (artikel): $1",
+"numtalkedits" => "Antal redigeringer (diskussionsside): $1",
+"numwatchers" => "Antal overvågere: $1",
+"numauthors" => "Antal forskellige forfattere (artikel): $1",
+"numtalkauthors" => "Antal forskellige forfattere (diskussionsside): $1",
+
+# Math options
+'mw_math_png' => "Vis altid som PNG",
+'mw_math_simple' => "HTML hvis meget simpel ellers PNG",
+'mw_math_html' => "HTML hvis muligt ellers PNG",
+'mw_math_source' => "Lad være som TeX (for tekstbrowsere)",
+'mw_math_modern' => "Anbefalet til moderne browsere",
+'mw_math_mathml' => "MathML hvis muligt",
+
+# Patrolling
+'markaspatrolleddiff'   => "Markér som patruljeret",
+'markaspatrolledlink'   => "<div class='patrollink'>[$1]</div>",
+'markaspatrolledtext'   => "Markér denne artikel som patruljeret",
+'markedaspatrolled'     => "Markeret som patruljeret",
+'markedaspatrolledtext' => "Den valgte revision er nu markeret som patruljeret.",
+'rcpatroldisabled'      => "Seneste ændringer-patruljeringen er slået fra",
+'rcpatroldisabledtext'  => "Funktionen til seneste ændringer-patruljeringen er pt. slået fra.",
+
+# Monobook.js: tooltips and access keys for monobook
+'Monobook.js' => '/* tooltips and access keys */
+ta = new Object();
+ta[\'pt-userpage\'] = new Array(\'.\',\'Min brugerside\');
+ta[\'pt-anonuserpage\'] = new Array(\'.\',\'Brugersiden for den ip-adresse du redigerer som\');
+ta[\'pt-mytalk\'] = new Array(\'n\',\'Min diskussionsside\');
+ta[\'pt-anontalk\'] = new Array(\'n\',\'Diskussion om redigeringer fra denne ip-adresse\');
+ta[\'pt-preferences\'] = new Array(\'\',\'Mine indstillinger\');
+ta[\'pt-watchlist\'] = new Array(\'l\',\'Listen over sider du overvåger for ændringer.\');
+ta[\'pt-mycontris\'] = new Array(\'y\',\'Listen over dine bidrag\');
+ta[\'pt-login\'] = new Array(\'o\',\'Du opfordres til at logge på, men det er ikke obligatorisk.\');
+ta[\'pt-anonlogin\'] = new Array(\'o\',\'Du opfordres til at logge på, men det er ikke obligatorisk\');
+ta[\'pt-logout\'] = new Array(\'o\',\'Log af\');
+ta[\'ca-talk\'] = new Array(\'t\',\'Diskussion om indholdet på siden\');
+ta[\'ca-edit\'] = new Array(\'e\',\'Du kan redigere denne side. Brug venligst forhåndsvisning før du gemmer.\');
+ta[\'ca-addsection\'] = new Array(\'+\',\'Tilføj en kommentar til denne diskussion.\');
+ta[\'ca-viewsource\'] = new Array(\'e\',\'Denne side er beskyttet. Du kan kigge på kildekoden.\');
+ta[\'ca-history\'] = new Array(\'h\',\'Tidligere versioner af denne side.\');
+ta[\'ca-protect\'] = new Array(\'=\',\'Beskyt denne side\');
+ta[\'ca-delete\'] = new Array(\'d\',\'Slet denne side\');
+ta[\'ca-undelete\'] = new Array(\'d\',\'Gendan de redigeringer der blev lavet på denne side før den blev slettet\');
+ta[\'ca-move\'] = new Array(\'m\',\'Flyt denne side\');
+ta[\'ca-watch\'] = new Array(\'w\',\'Sæt denne side på din overvågningsliste\');
+ta[\'ca-unwatch\'] = new Array(\'w\',\'Fjern denne side fra din overvågningsliste\');
+ta[\'search\'] = new Array(\'f\',\'Søg på denne wiki\');
+ta[\'p-logo\'] = new Array(\'\',\'Forsiden\');
+ta[\'n-mainpage\'] = new Array(\'z\',\'Besøg forsiden\');
+ta[\'n-portal\'] = new Array(\'\',\'Om projektet, hvad du kan gøre, hvor tingene findes\');
+ta[\'n-currentevents\'] = new Array(\'\',\'Find baggrundsinformation om aktuelle begivenheder\');
+ta[\'n-recentchanges\'] = new Array(\'r\',\'Listen over de seneste ændringer i wikien.\');
+ta[\'n-randompage\'] = new Array(\'x\',\'Gå til en tilfældig artikel\');
+ta[\'n-help\'] = new Array(\'\',\'Hvordan gør jeg ...\');
+ta[\'n-sitesupport\'] = new Array(\'\',\'Støt os\');
+ta[\'t-whatlinkshere\'] = new Array(\'j\',\'Liste med alle sider som henviser hertil\');
+ta[\'t-recentchangeslinked\'] = new Array(\'k\',\'Seneste ændringer i sider som denne side henviser til\');
+ta[\'feed-rss\'] = new Array(\'\',\'RSS-feed for denne side\');
+ta[\'feed-atom\'] = new Array(\'\',\'Atom-feed for denne side\');
+ta[\'t-contributions\'] = new Array(\'\',\'Se denne brugers bidrag\');
+ta[\'t-emailuser\'] = new Array(\'\',\'Send en e-mail til denne bruger\');
+ta[\'t-upload\'] = new Array(\'u\',\'Upload et billede eller anden mediafil\');
+ta[\'t-specialpages\'] = new Array(\'q\',\'Liste med alle specielle sider\');
+ta[\'ca-nstab-main\'] = new Array(\'c\',\'Se indholdet\');
+ta[\'ca-nstab-user\'] = new Array(\'c\',\'Se brugersiden\');
+ta[\'ca-nstab-media\'] = new Array(\'c\',\'Se mediasiden\');
+ta[\'ca-nstab-special\'] = new Array(\'\',\'Dette er en speciel side; man kan ikke redigere sådanne sider.\');
+ta[\'ca-nstab-wp\'] = new Array(\'a\',\'Se Wikipediasiden\');
+ta[\'ca-nstab-image\'] = new Array(\'c\',\'Se billedsiden\');
+ta[\'ca-nstab-mediawiki\'] = new Array(\'c\',\'Se systembeskeden\');
+ta[\'ca-nstab-template\'] = new Array(\'c\',\'Se skabelonen\');
+ta[\'ca-nstab-help\'] = new Array(\'c\',\'Se hjælpesiden\');
+ta[\'ca-nstab-category\'] = new Array(\'c\',\'Se kategorisiden\');
+',
+
+# image deletion
+'deletedrevision' => 'Slettede gammel version $1.',
+
+# browsing diffs
+'previousdiff' => '← Gå til forrige forskel',
+'nextdiff' => 'Gå til næste forskel →',
+
+'imagemaxsize' => 'Begræns størrelsen af billeder på billedsiderne til: ',
+'thumbsize'    => 'Thumbnail størrelse : ',
+'showbigimage' => 'Download en version i høj opløsning ($1x$2, $3 KB)',
+
+'newimages' => 'Galleri med de nyeste billeder',
+'noimages'  => 'Ingenting at se.',
+
+
+# labels for User: and Title: on Special:Log pages
+'specialloguserlabel' => 'Bruger: ',
+'speciallogtitlelabel' => 'Titel: ',
+
+'passwordtooshort' => 'Dit kodeord er for kort. Det skal være mindst $1 tegn langt.',
+
+# Media Warning
+'mediawarning' => "'''Advarsel''', denne filtype kan muligvis indeholde skadelig kode, du kan beskadige dit system hvis du udfører den.
+<hr>",
+# external editor support
+'edit-externally' => 'Rediger denne fil med en ekstern editor',
+'edit-externally-help' => 'Se [http://meta.wikimedia.org/wiki/Help:External_editors setup instruktionerne] for mere information.',
+
+# 'all' in various places, this might be different for inflicted languages
+'recentchangesall' => 'alle',
+'imagelistall' => 'alle',
+'watchlistall1' => 'alle',
+'watchlistall2' => 'alle',
+'namespacesall' => 'alle',
+
+);
+
+/** @package MediaWiki */
+class LanguageDa extends LanguageUtf8 {
+
+       function getBookstoreList () {
+               global $wgBookstoreListDa ;
+               return $wgBookstoreListDa ;
+       }
+
+       function getNamespaces() {
+               global $wgNamespaceNamesDa;
+               return $wgNamespaceNamesDa;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsDa;
+               return $wgQuickbarSettingsDa;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesDa;
+               return $wgSkinNamesDa;
+       }
+
+       function getDateFormats() {
+               global $wgDateFormatsDa;
+               return $wgDateFormatsDa;
+       }
+
+       function date( $ts, $adj = false ) {
+               if ( $adj ) { $ts = $this->userAdjust( $ts ); }
+
+               $d = (0 + substr( $ts, 6, 2 )) . ". " .
+                 $this->getMonthAbbreviation( substr( $ts, 4, 2 ) ) . " " .
+                 substr( $ts, 0, 4 );
+               return $d;
+       }
+
+       function timeanddate( $ts, $adj = false ) {
+               return $this->date( $ts, $adj ) . " kl. " . $this->time( $ts, $adj );
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesDa;
+               if( isset( $wgAllMessagesDa[$key] ) ) {
+                       return $wgAllMessagesDa[$key];
+               } else {
+                       return parent::getMessage( $key );
+               }
+       }
+
+       function formatNum( $number ) {
+               return strtr($number, '.,', ',.' );
+       }
+
+}
+
+?>
diff --git a/languages/LanguageDe.php b/languages/LanguageDe.php
new file mode 100644 (file)
index 0000000..8331e62
--- /dev/null
@@ -0,0 +1,1310 @@
+<?php
+/** German (Deutsch)
+  *
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+/** */
+require_once( 'LanguageUtf8.php' );
+
+# See Language.php for notes.
+
+if($wgMetaNamespace === FALSE)
+       $wgMetaNamespace = str_replace( ' ', '_', $wgSitename );
+
+/* private */ $wgNamespaceNamesDe = array(
+       NS_MEDIA            => 'Media',
+       NS_SPECIAL          => 'Spezial',
+       NS_MAIN             => '',
+       NS_TALK             => 'Diskussion',
+       NS_USER             => 'Benutzer',
+       NS_USER_TALK        => 'Benutzer_Diskussion',
+       NS_PROJECT          => $wgMetaNamespace,
+       NS_PROJECT_TALK     => $wgMetaNamespace . '_Diskussion',
+       NS_IMAGE            => 'Bild',
+       NS_IMAGE_TALK       => 'Bild_Diskussion',
+       NS_MEDIAWIKI        => 'MediaWiki',
+       NS_MEDIAWIKI_TALK   => 'MediaWiki_Diskussion',
+       NS_TEMPLATE         => 'Vorlage',
+       NS_TEMPLATE_TALK    => 'Vorlage_Diskussion',
+       NS_HELP             => 'Hilfe',
+       NS_HELP_TALK        => 'Hilfe_Diskussion',
+       NS_CATEGORY         => 'Kategorie',
+       NS_CATEGORY_TALK    => 'Kategorie_Diskussion'
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgQuickbarSettingsDe = array(
+       'Keine', 'Links, fest', 'Rechts, fest', 'Links, schwebend'
+);
+
+/* private */ $wgSkinNamesDe = array(
+       'standard'      => 'Klassik',
+       'nostalgia'     => 'Nostalgie',
+       'cologneblue'   => 'Kölnisch Blau',
+       'smarty'        => 'Paddington',
+       'montparnasse'  => 'Montparnasse',
+       'davinci'       => 'DaVinci',
+       'mono'          => 'Mono',
+       'monobook'      => 'MonoBook',
+       'myskin'        => 'MySkin',
+       'chick'         => 'Küken'
+);
+
+
+/* private */ $wgBookstoreListDe = array(
+       'Verzeichnis lieferbarer B&uuml;cher' => 'http://www.buchhandel.de/sixcms/list.php?page=buchhandel_profisuche_frameset&suchfeld=isbn&suchwert=$1&x=0&y=0',
+       'abebooks.de' => 'http://www.abebooks.de/servlet/BookSearchPL?ph=2&isbn=$1',
+       'Amazon.de' => 'http://www.amazon.de/exec/obidos/ISBN=$1',
+       'Lehmanns Fachbuchhandlung' => 'http://www.lob.de/cgi-bin/work/suche?flag=new&stich1=$1',
+);
+
+/* private */ $wgAllMessagesDe = array(
+'Monobook.css' =>
+'/** Do not force \'lowercase\' */
+.portlet h5,
+.portlet h6,
+#p-personal ul,
+#p-cactions li a {
+       text-transform: none;
+}',
+# User toggles
+"tog-underline"               => "Verweise unterstreichen",
+"tog-highlightbroken"         => "Verweise auf leere Themen hervorheben",
+"tog-justify"                 => "Text als Blocksatz",
+"tog-hideminor"               => "Keine kleinen Änderungen in Letzte Änderungen anzeigen",
+"tog-usenewrc"                => "Erweiterte letzte Änderungen (nicht für alle Browser geeignet)",
+"tog-numberheadings"          => "Überschriften automatisch nummerieren",
+"tog-showtoolbar"          => "Editier-Werkzeugleiste anzeigen",
+"tog-editondblclick"          => "Seiten mit Doppelklick bearbeiten (JavaScript)",
+"tog-editsection"             => "Links zum Bearbeiten einzelner Absätze anzeigen",
+"tog-editsectiononrightclick" => "Einzelne Absätze per Rechtsklick bearbeiten (Javascript)",
+"tog-showtoc"                 => "Anzeigen eines Inhaltsverzeichnisses bei Artikeln mit mehr als 3 Überschriften",
+"tog-rememberpassword"        => "Dauerhaftes Einloggen",
+"tog-editwidth"               => "Text-Eingabefeld mit voller Breite",
+"tog-watchdefault"            => "Neue und geänderte Seiten beobachten",
+"tog-minordefault"            => "Alle Änderungen als geringfügig markieren",
+"tog-previewontop"            => "Vorschau vor dem Editierfenster anzeigen",
+'tog-previewonfirst'           => 'Vorschau beim ersten Editieren anzeigen',
+"tog-nocache"                 => "Seitencache deaktivieren",
+'tog-enotifwatchlistpages'     => 'Benachrichtigungsmails für Änderungen an Wiki-Seiten',
+'tog-enotifusertalkpages'      => 'Benachrichtigungsmails für Änderungen an Ihren Benutzerseiten',
+'tog-enotifminoredits'                 => 'Benachrichtigungsmails auch für kleine Seitenänderungen',
+'tog-enotifrevealaddr'                 => 'Ihre E-Mail-Adresse wird in Benachrichtigungsmails gezeigt',
+'tog-shownumberswatching'      => 'Zeige die Anzahl seitenbeobachtender Benutzer (in Letzte Änderungen, Beobachtungsliste und Artikelseiten)',
+'tog-fancysig'                 => 'Einfache Unterschrift (Spitzname ohne Link)',
+'tog-externaleditor' => 'Benutze standardmäßig externen Editor',
+'tog-externaldiff' => 'Benutze standardmäßig externen Diff',
+
+# Dates
+'sunday' => "Sonntag",
+'monday' => "Montag",
+'tuesday' => "Dienstag",
+'wednesday' => "Mittwoch",
+'thursday' => "Donnerstag",
+'friday' => "Freitag",
+'saturday' => "Samstag",
+'january' => "Januar",
+'february' => "Februar",
+'march' => "März",
+'april' => "April",
+'may_long' => "Mai",
+'june' => "Juni",
+'july' => "Juli",
+'august' => "August",
+'september' => "September",
+'october' => "Oktober",
+'november' => "November",
+'december' => "Dezember",
+'jan' => "Jan",
+'feb' => "Feb",
+'mar' => "Mär",
+'apr' => "Apr",
+'may' => "Mai",
+'jun' => "Jun",
+'jul' => "Jul",
+'aug' => "Aug",
+'sep' => "Sep",
+'oct' => "Okt",
+'nov' => "Nov",
+'dec' => "Dez",
+
+
+# Bits of text used by many pages:
+#
+"categories" => "Seitenkategorien",
+"category" => "Kategorie",
+'category_header' => 'Artikel in der Kategorie "$1"',
+"subcategories" => "Unterkategorien",
+"linktrail"            => "/^([ä|ö|ü|ß|a-z]+)(.*)\$/sD",
+"mainpage"             => "Hauptseite",
+"mainpagetext"          => "Die Wiki Software wurde erfolgreich installiert.",
+"mainpagedocfooter" => "Siehe die [http://meta.wikipedia.org/wiki/MediaWiki_i18n Dokumentation zur Anpassung der Benutzeroberfläche]
+und das [http://meta.wikipedia.org/wiki/MediaWiki_User%27s_Guide Benutzerhandbuch] für Hilfe zur Benutzung und Konfiguration.",
+'portal'               => "{{SITENAME}}-Portal",
+"portal-url"           => "{{ns:4}}:Portal",
+"about"                        => "Über",
+"aboutsite"      => "Über {{SITENAME}}",
+"aboutpage"            => "{{ns:project}}:Über_{{SITENAME}}",
+"article" => "Artikel",
+"help"                 => "Hilfe",
+"helppage"             => "Project:Hilfe",
+"bugreports"   => "Kontakt",
+"bugreportspage" => "Project:Kontakt",
+"sitesupport"   => "Spenden",
+"faq"                  => "FAQ",
+"faqpage"              => "{{ns:project}}:Häufig_gestellte_Fragen",
+"edithelp"             => "Bearbeitungshilfe",
+"edithelppage" => "{{ns:project}}:Editierhilfe",
+"cancel"               => "Abbruch",
+"qbfind"               => "Finden",
+"qbbrowse"             => "Blättern",
+"qbedit"               => "Ändern",
+"qbpageoptions" => "Seitenoptionen",
+"qbpageinfo"   => "Seitendaten",
+"qbmyoptions"  => "Einstellungen",
+"qbspecialpages"       => "Spezialseiten",
+"moredotdotdot"        => "Mehr...",
+"mypage"               => "Meine Seite",
+"mytalk"               => "Meine Diskussion",
+"anontalk"             => "Diskussionsseite dieser IP",
+"navigation" => "Navigation",
+"currentevents" => "Aktuelle Ereignisse",
+"disclaimers" => "Lizenzbestimmungen",
+"disclaimerpage"               => "{{ns:4}}:Lizenzbestimmungen",
+"errorpagetitle" => "Fehler",
+"returnto"             => "Zurück zu $1.",
+"tagline"              => "aus {{SITENAME}}, der freien Wissensdatenbank",
+"whatlinkshere"        => "Was zeigt hierhin",
+"help"                 => "Hilfe",
+"search"               => "Suche",
+"history"              => "Versionen",
+"history_short" => "Versionen",
+"printableversion" => "Druckversion",
+"editthispage" => "Seite bearbeiten",
+"delete" => "löschen",
+"deletethispage" => "Diese Seite löschen",
+"undelete_short" => "Wiederherstellen",
+"undelete_short1" => "Wiederherstellen",
+"protect" => "Schützen",
+"protectthispage" => "Artikel schützen",
+"unprotect" => "Freigeben",
+"unprotectthispage" => "Schutz aufheben",
+"newpage" => "Neue Seite",
+"talkpage"             => "Diskussion",
+"specialpage" => "Spezialseite",
+"personaltools" => "'Persönliche Werkzeuge",
+"postcomment" => "Kommentar hinzufügen",
+"addsection"   => "+",
+"articlepage"  => "Artikel",
+"toolbox" => "Werkzeuge",
+"wikipediapage" => "Meta-Text",
+"userpage" => "Benutzerseite",
+"imagepage" => "Bildseite",
+"viewtalkpage" => "Diskussion",
+"otherlanguages" => "Andere Sprachen",
+"redirectedfrom" => "(Weitergeleitet von $1)",
+"lastmodified" => "Diese Seite wurde zuletzt geändert um $1.",
+"viewcount"            => "Diese Seite wurde bisher $1 mal abgerufen.",
+"copyright"    => "Inhalt ist verfügbar unter der $1.",
+"poweredby"    => "{{SITENAME}} benutzt [http://www.mediawiki.org/ MediaWiki], eine Open Source Wiki-Engine.",
+"printsubtitle" => "(Von {{SERVER}})",
+"protectedpage" => "Geschützte Seite",
+"administrators" => "Project:Administratoren",
+"sysoptitle"   => "Sysop-Zugang notwendig",
+'sysoptext'            => 'Dieser Vorgang kann aus Sicherheitsgründen nur von Benutzern mit"Sysop"-Status durchgeführt werden. Siehe auch $1.',
+"developertitle" => "Entwickler-Zugang notwendig",
+'developertext'        => 'Dieser Vorgang kann aus Sicherheitsgründen nur von Benutzern mit"Entwickler"-Status durchgeführt werden. Siehe auch $1.',
+"nbytes"               => "$1 Byte",
+"go"                   => "Los",
+"ok"                   => "OK",
+"sitetitle"            => "{{SITENAME}}",
+"sitesubtitle" => "Die freie Enzyklopädie",
+"pagetitle"            => "$1 - {{SITENAME}}",
+"sitesubtitle" => "Die freie Wissensdatenbank",
+'retrievedfrom' => 'Von "$1"',
+"newmessages" => "Sie haben $1.",
+"newmessageslink" => "neue Nachrichten",
+"editsection" => "bearbeiten",
+"toc" => "Inhaltsverzeichnis",
+"showtoc" => "Anzeigen",
+"hidetoc" => "Verbergen",
+"thisisdeleted" => "Ansehen oder wiederherstellen von $1?",
+"restorelink" => "$1 gelöschte Bearbeitungsvorgänge",
+"feedlinks" => "Feed:",
+
+# Namespace form on various pages
+'namespace' => 'Namensraum:',
+'invert' => 'Kehre Selektion um',
+
+# 'all' in various places, this might be different for inflected languages
+'watchlistall2' => 'Alles',
+'namespacesall' => 'Alle',
+
+# Kurzworte für jeden Namespace, u.a. von MonoBook verwendet
+'nstab-main' => 'Artikel',
+'nstab-user' => 'Benutzerseite',
+'nstab-media' => 'Media',
+'nstab-special' => 'Spezial',
+'nstab-image' => 'Bild',
+'nstab-help' => 'Hilfe',
+'nstab-category' => 'Kategorie',
+'nstab-wp' => 'Projektseite',
+
+# Editier-Werkzeugleiste
+"bold_sample"=>"Fetter Text",
+"bold_tip"=>"Fetter Text",
+"italic_sample"=>"Kursiver Text",
+"italic_tip"=>"Kursiver Text",
+"link_sample"=>"Link-Text",
+"link_tip"=>"Interner Link",
+"extlink_sample"=>"http://www.beispiel.de Link-Text",
+"extlink_tip"=>"Externer Link (http:// beachten)",
+"headline_sample"=>"Ebene 2 Überschrift",
+"headline_tip"=>"Ebene 2 Überschrift",
+"math_sample"=>"Formel hier einfügen",
+"math_tip"=>"Mathematische Formel (LaTeX)",
+"nowiki_sample"=>"Unformatierten Text hier einfügen",
+"nowiki_tip"=>"Unformatierter Text",
+"image_sample"=>"Beispiel.jpg",
+"image_tip"=>"Bild-Verweis",
+"media_sample"=>"Beispiel.mp3",
+"media_tip"=>"Mediendatei-Verweis",
+"sig_tip"=>"Ihre Signatur mit Zeitstempel",
+"hr_tip"=>"Horizontale Linie (sparsam verwenden)",
+
+# Main script and global functions
+#
+"nosuchaction" => "Diese Aktion gibt es nicht",
+"nosuchactiontext" => "Diese Aktion wird von der MediaWiki-Software nicht unterstützt",
+"nosuchspecialpage" => "Diese Spezialseite gibt es nicht",
+"nospecialpagetext" => "Diese Spezialseite wird von der MediaWiki-Software nicht unterstützt",
+
+# General errors
+#
+"error" => "Fehler",
+"databaseerror" => "Fehler in der Datenbank",
+"dberrortext"  => "Es gab einen Syntaxfehler in der Datenbankabfrage.
+Die letzte Datenbankabfrage lautete:
+<blockquote><tt>$1</tt></blockquote>
+aus der Funktion \"<tt>$2</tt>\".
+MySQL meldete den Fehler \"<tt>$3: $4</tt>\".",
+"dberrortextcl" => "Es gab einen Syntaxfehler in der Datenbankabfrage.
+Die letzte Datenbankabfrage lautete: \"$1\" aus der Funktion \"<tt>$2</tt>\".
+MySQL meldete den Fehler: \"<tt>$3: $4</tt>\".\n",
+"noconnect"            => "Konnte keine Verbindung zur Datenbank auf $1 herstellen",
+"nodb"                 => "Konnte Datenbank $1 nicht auswählen",
+"cachederror" => "Das folgende ist eine Kopie aus dem Cache und möglicherweise nicht aktuell.",
+"readonly"             => "Datenbank ist gesperrt",
+"enterlockreason" => "Bitte geben Sie einen Grund ein, warum die Datenbank
+gesperrt werden soll und eine Abschätzung über die Dauer der Sperrung",
+"readonlytext" => "Die {{SITENAME}}-Datenbank ist vorübergehend gesperrt, z.B. für Wartungsarbeiten. Bitte versuchen Sie es später noch einmal.\n",
+"missingarticle" => "Der Text für den Artikel \"$1\" wurde nicht in der Datenbank gefunden. Das ist wahrscheinlich ein Fehler in der Software. Bitte melden Sie dies einem Administrator, und geben sie den Artikelnamen an.",
+"internalerror" => "Interner Fehler",
+"filecopyerror" => "Konnte Datei \"$1\" nicht nach \"$2\" kopieren.",
+"filerenameerror" => "Konnte Datei \"$1\" nicht nach \"$2\" umbenennen.",
+"filedeleteerror" => "Konnte Datei \"$1\" nicht löschen.",
+"filenotfound" => "Konnte Datei \"$1\" nicht finden.",
+"unexpected"   => "Unerwarteter Wert: \"$1\"=\"$2\".",
+"formerror"            => "Fehler: Konnte Formular nicht verarbeiten",
+"badarticleerror" => "Diese Aktion kann auf diesen Artikel nicht angewendet werden.",
+"cannotdelete" => "Kann spezifizierte Seite oder Artikel nicht löschen. (Wurde möglicherweise schon von jemand anderem gelöscht.)",
+"badtitle"             => "Ungültiger Titel",
+"badtitletext" => "Der Titel der angeforderten Seite war ungültig, leer, oder ein ungültiger Sprachlink von einem anderen Wiki.",
+"perfdisabled" => "Diese Funktion wurde wegen Überlastung des Servers vorübergehend deaktiviert. Versuchen Sie es bitte zwischen 02:00 und 14:00 UTC noch einmal<br />(Aktuelle Serverzeit : ".date("H:i:s")." UTC).",
+"perfdisabledsub" => "Hier ist eine gespeicherte Kopie von $1:",
+"perfcached" => "Die folgenden Daten stammen aus dem Cache und sind möglicherweise nicht aktuell:",
+"wrong_wfQuery_params" => "Falsche Parameter für wfQuery()<br />
+Funktion: $1<br />
+Query: $2
+",
+"viewsource" => "Quelltext betrachten",
+"protectedtext" => "Diese Seite ist für das Bearbeiten gesperrt. Dafür kann es diverse Gründe geben; siehe [[{{ns:4}}:Geschützte Seiten]].
+
+Sie können den Quelltext dieser Seite betrachten und kopieren:",
+
+
+# Login and logout pages
+#
+"logouttitle"  => "Benutzer-Abmeldung",
+"logouttext"   => "Sie sind nun abgemeldet.
+Sie können {{SITENAME}} jetzt anonym weiterbenutzen, oder sich unter dem selben oder einem anderen Benutzernamen wieder anmelden.\n",
+
+"welcomecreation" => "<h2>Willkommen, $1!</h2><p>Ihr Benutzerkonto wurde eingerichtet.
+Vergessen Sie nicht, Ihre Einstellungen anzupassen.",
+
+"loginpagetitle" => "Benutzer-Anmeldung",
+"yourname"             => "Ihr Benutzername",
+"yourpassword" => "Ihr Passwort",
+"yourpasswordagain" => "Passwort wiederholen",
+"newusersonly" => " (nur für neue Mitglieder)",
+"remembermypassword" => "Dauerhaftes Einloggen",
+"loginproblem" => "<b>Es gab ein Problem mit Ihrer Anmeldung.</b><br />Bitte versuchen Sie es nochmal!",
+"alreadyloggedin" => "<strong>Benutzer $1, Sie sind bereits angemeldet!</strong><br />\n",
+
+"login"                        => "Anmelden",
+"loginprompt"           => "Um sich bei {{SITENAME}} anmelden zu können, müssen Cookies aktiviert sein.",
+"userlogin"            => "Anmelden",
+'disabled_on_this_wiki'        => '<div class="error"><b>Diese Funktion ist bei diesem Wiki dauerhaft abeschaltet.
+Durch die automatische Anmeldung beim Benutzerkonto sind eigene Benutzer-Anmeldung oder -Abmeldung nicht erforderlich.</b></div>',
+"logout"               => "Abmelden",
+"userlogout"   => "Abmelden",
+"notloggedin" => "Nicht angemeldet",
+"createaccount"        => "Neues Benutzerkonto anlegen",
+"createaccountmail" => "über eMail",
+"badretype"            => "Die beiden Passwörter stimmen nicht überein.",
+"userexists"   => "Dieser Benutzername ist schon vergeben. Bitte wählen Sie einen anderen.",
+"youremail"            => "Ihre E-Mail-Adresse**",
+"yournick"             => "Ihr \"Spitzname\" (zum \"Unterschreiben\")",
+"yourrealname"         => "Ihr echter Name (keine Pflichtangabe)*",
+"emailforlost" => "Falls Sie Ihr Passwort vergessen haben, kann Ihnen ein neues an Ihre E-Mail-Adresse gesendet werden.",
+'prefs-help-email'     => '** <strong>E-Mail-Adresse</strong> (optional): Erlaubt andern, Sie über Ihre Benutzerseiten zu kontaktieren, ohne dass Sie Ihre E-Mail-Adresse offenbaren müssen.
+Für den Fall, dass Sie Ihr Passwort vergessen haben, kann Ihnen so ein temporäres Einmal-Passwort gesendet werden.',
+'prefs-help-email-enotif' => 'An diese Adresse werden auch die Benachrichtigungsmails geschickt, sofern Sie das eingeschaltet haben.',
+'prefs-help-realname'  => '* <strong>Echter Name</strong> (optional): für anerkennende Nennungen Ihres Namens im Zusammenhang mit Ihren Beiträgen.',
+"loginerror"   => "Fehler bei der Anmeldung",
+"noname"               => "Sie müssen einen Benutzernamen angeben.",
+"loginsuccesstitle" => "Anmeldung erfolgreich",
+"loginsuccess" => "Sie sind jetzt als \"$1\" bei {{SITENAME}} angemeldet.",
+"nosuchuser"   => "Der Benutzername \"$1\" existiert nicht.
+Überprüfen Sie die Schreibweise, oder melden Sie sich als neuer Benutzer an.",
+"wrongpassword"        => "Das Passwort ist falsch (oder fehlt). Bitte versuchen Sie es erneut.",
+"mailmypassword" => "Ein neues (temporäres) Passwort schicken",
+'mailmypasswordauthent'        => 'Ein neues (temporäres) Passwort schicken, auch für Authentifizierung der E-Mailadresse',
+'passwordremindermailsubject' => "E-Mail-Adressenauthentifizierung und temporäres Passwort für {{SITENAME}}",
+'passwordremindermailbody'     => "Jemand, vielleicht Sie, hat von IP-Adresse $1
+um ein temporäres Einmal-Passwort für die Anmeldung bei {{SITENAME}} gebeten.
+
+Das Passwort für Benutzer \"$2\" lautet nun \"$3\".
+
+Bitte melden Sie sich nun mit diesem temporären Passwort an, das gleichzeitig der Authentifizierung
+Ihrer E-Mail-Adresse dient. Für weitere Anmeldungen verwenden Sie bitte wieder Ihr altes Passwort.
+Alternativ können Sie auch ein neues eintragen, zum Beispiel, wenn Sie das alte vergessen haben.,
+
+{{SERVER}}{{localurl:Special:Userlogin|wpName=$2&wpPassword=$3&returnto=Special:Preferences}}",
+"noemail"              => "Benutzer \"$1\" hat keine E-Mail-Adresse angegeben.",
+"passwordsent" => "Ein temporäres Passwort wurde an die E-Mail-Adresse von Benutzer \"$1\" gesendet.
+Bitte melden Sie sich damit an, sobald Sie es erhalten.",
+'passwordsentforemailauthentication'
+       => "Ein temporäres Passwort wurde an die gerade neu eingetragene E-Mail-Adresse des Benutzers \"$1\" gesendet.
+Bitte melden Sie sich damit an, um die Adressauthentifizierung durchzuführen.",
+"loginend"             => "&nbsp;",
+"mailerror" => "Fehler beim Senden von Mail: $1",
+'acct_creation_throttle_hit' => 'Sie haben schon $1 Benutzerkonten und können jetzt keine weiteren mehr anlegen.',
+'emailconfirmlink'     => 'E-Mail-Adresse bestätigen (authentifizieren).',
+'emailauthenticated'   => 'Ihre E-Mail-Adresse wurde am $1 authentifiziert.',
+'emailnotauthenticated'        => 'Ihre E-Mail-Adresse ist <strong>noch nicht authentifiziert</strong> und die erweiterten E-Mailfunktionen sind bis zur Authentifizierung ohne Funktion <strong>(aus)</strong>.<br />
+Für die Authentifizierung melden Sie sich bitte mit dem per E-Mail geschickten temporären Passwort an, oder fordern Sie auf der Anmeldeseite ein neues an.',
+'invalidemailaddress'  => 'Die E-Mail-Adresse wurde nicht akzeptiert, da sie ein ungültiges Format aufzuweisen scheint. Bitte geben Sie eine Adresse in einem gültigen Format ein, oder leeren Sie das Feld.',
+'disableduntilconfirmation'    => '<strong>(aus)</strong>',
+'noemailprefs' => '<strong>Sie haben keine E-Mail-Adresse angegeben</strong>, die folgenden
+Funktionen sind zur Zeit deshalb nicht möglich.',
+
+# Edit pages
+#
+"summary"      => "Zusammenfassung",
+#"subject"       => "Betreff/Schlagzeile",
+"subject"       => "Betreff",
+"minoredit"    => "Nur Kleinigkeiten wurden verändert.",
+"watchthis"     => "Diesen Artikel beobachten",
+"savearticle"  => "Artikel speichern",
+"preview"      => "Vorschau",
+"showpreview"  => "Vorschau zeigen",
+"showdiff"     => "&Auml;nderungen zeigen",
+"blockedtitle" => "Benutzer ist blockiert",
+"blockedtext"  => "Ihr Benutzername oder Ihre IP-Adresse wurde von $1 blockiert.
+Als Grund wurde angegeben:<br />$2<p>Bitte kontaktieren Sie den Administrator, um über die Blockierung zu sprechen.",
+"whitelistedittitle" => "Zum Bearbeiten ist es erforderlich angemeldet zu sein",
+"whitelistedittext" => "Sie müssen sich [[Spezial:Userlogin|hier anmelden]] um Artikel bearbeiten zu können.",
+"whitelistreadtitle" => "Zum Lesen ist es erforderlich angemeldet zu sein",
+"whitelistreadtext" => "Sie müssen sich [[Spezial:Userlogin|hier anmelden]] um Artikel lesen zu können.",
+"whitelistacctitle" => "Sie sind nicht berechtigt einen Account zu erzeugen",
+"whitelistacctext" => "Um in diesem Wiki Accounts anlegen zu dürfen müssen Sie sich [[Spezial:Userlogin|hier anmelden]] und die nötigen Berechtigungen haben.",
+"loginreqtitle"        => "Anmeldung erforderlich",
+"loginreqtext" => "Sie müssen sich [[Spezial:Userlogin|anmelden]], um andere Seiten betrachten zu können.",
+"accmailtitle" => "Passwort wurde verschickt.",
+"accmailtext" => "Das Passwort von $1 wurde an $2 geschickt.",
+"newarticle"   => "(Neu)",
+"newarticletext" => "Hier den Text des neuen Artikels eintragen.\nBitte nur in ganzen Sätzen schreiben und keine urheberrechtsgeschützten Texte anderer kopieren.",
+"anontalkpagetext" => "---- ''Dies ist die Diskussions-Seite eines nicht angemeldeten Benutzers. Wir müssen hier die numerische [[IP-Adresse]] zur Identifizierung verwenden. Eine solche Adresse kann nacheinander von mehreren Benutzern verwendet werden. Wenn Sie ein anonymer Benutzer sind und denken, dass irrelevante Kommentare an Sie gerichtet wurden, [[Spezial:Userlogin|melden Sie sich bitte
+ an]], um zukünftige Verwirrung zu vermeiden. ''",
+"noarticletext" => "(Dieser Artikel enthält momentan keinen Text)",
+'usercsspreview' => "== Vorschau ihres Benutzer-CSS. ==
+'''Beachten Sie:''' Nach dem Speichern müssen Sie ihrem Browser sagen, die neue Version zu laden: '''Mozilla:''' ''Strg-Shift-R'', '''IE:''' ''Strg-F5'', '''Safari:''' ''Cmd-Shift-R'', '''Konqueror:''' ''F5''.",
+'userjspreview' => "== Vorschau Ihres Benutzer-Javascript. ==
+'''Beachten Sie:''' Nach dem Speichern müssen Sie ihrem Browser sagen, die neue Version zu laden: '''Mozilla:''' ''Strg-Shift-R'', '''IE:''' ''Strg-F5'', '''Safari:''' ''Cmd-Shift-R'', '''Konqueror:''' ''F5''.",
+'clearyourcache' => "'''Beachten Sie:''' Nach dem Speichern müssen Sie ihrem Browser sagen, die neue Version zu laden: '''Mozilla/Firefox:''' ''Strg-Shift-R'', '''IE:''' ''Strg-F5'', '''Safari:''' ''Cmd-Shift-R'', '''Konqueror:''' ''F5''.",
+'usercssjsyoucanpreview' => "<strong>Tipp:</strong> Benutzen Sie den Vorschau-Button, um Ihr neues css/js vor dem Speichern zu testen.",
+"updated"              => "(Geändert)",
+"note"                 => "<strong>Hinweis:</strong> ",
+"previewnote"  => "Dies ist nur eine Vorschau, der Artikel wurde noch nicht gespeichert!",
+"previewconflict" => "Diese Vorschau gibt den Inhalt des oberen Textfeldes wieder; so wird der Artikel aussehen, wenn Sie jetzt speichern.",
+"editing"              => "Bearbeiten von $1",
+"editingsection"       => "Bearbeiten von $1 (Absatz)",
+"editingcomment"       => "Bearbeiten von $1 (Kommentar)",
+"editconflict" => "Bearbeitungs-Konflikt: $1",
+"explainconflict" => "Jemand anders hat diesen Artikel geändert, nachdem Sie angefangen haben, ihn zu bearbeiten.
+Das obere Textfeld enthält den aktuellen Artikel.
+Das untere Textfeld enthält Ihre Änderungen.
+Bitte fügen Sie Ihre Änderungen in das obere Textfeld ein.
+<b>Nur</b> der Inhalt des oberen Textfeldes wird gespeichert, wenn Sie auf \"Speichern\" klicken!<br />",
+"yourtext"             => "Ihr Text",
+"storedversion" => "Gespeicherte Version",
+"editingold"   => "<strong>ACHTUNG: Sie bearbeiten eine alte Version dieses Artikels.
+Wenn Sie speichern, werden alle neueren Versionen überschrieben.</strong>",
+"yourdiff"             => "Unterschiede",
+"copyrightwarning" => "
+<b>Bitte <big>kopieren Sie keine Webseiten</big>, die nicht Ihre eigenen sind, benutzen Sie <big>keine urheberrechtlich geschützten Werke</big> ohne Erlaubnis des Copyright-Inhabers!</b>
+<p>Sie geben uns hiermit ihre Zusage, dass Sie den Text <strong>selbst verfasst</strong> haben, dass der Text Allgemeingut (<strong>public domain</strong>) ist, oder dass der <strong>Copyright-Inhaber</strong> seine <strong>Zustimmung</strong> gegeben hat. Falls dieser Text bereits woanders veröffentlicht wurde, weisen Sie bitte auf der 'Diskussion:'-Seite darauf hin.
+<p><i>Bitte beachten Sie, dass alle {{SITENAME}}-Beiträge automatisch unter der \"GNU Freie Dokumentationslizenz\" stehen. Falls Sie nicht möchten, dass Ihre Arbeit hier von anderen verändert und verbreitet wird, dann drücken Sie nicht auf \"Speichern\".</i>",
+"longpagewarning" => "<strong>WARNUNG: Diese Seite ist $1KB groß; einige Browser könnten Probleme haben, Seiten zu bearbeiten, die größer als 32KB sind.
+Überlegen Sie bitte, ob eine Aufteilung der Seite in kleinere Abschnitte möglich ist.</strong>",
+"readonlywarning" => "<strong>WARNUNG: Die Datenbank wurde während dem Ändern der
+Seite für Wartungsarbeiten gesperrt, so dass Sie die Seite im Moment nicht
+speichern können. Sichern Sie sich den Text und versuchen Sie die Änderungen
+später einzuspielen.</strong>",
+"protectedpagewarning" => "<strong>WARNUNG: Diese Seite wurde gesperrt, so dass sie nur
+Benutzer mit Sysop-Rechten bearbeitet werden kann. Beachten Sie bitte die
+[[Project:Geschützte Seiten|Regeln für geschützte Seiten]].</strong>",
+
+# History pages
+#
+"revhistory"   => "Frühere Versionen",
+"nohistory"            => "Es gibt keine früheren Versionen von diesem Artikel.",
+"revnotfound"  => "Keine früheren Versionen gefunden",
+"revnotfoundtext" => "Die Version dieses Artikels, nach der Sie suchen, konnte nicht gefunden werden. Bitte überprüfen Sie die URL dieser Seite.\n",
+"loadhist"             => "Lade Liste mit früheren Versionen",
+"currentrev"   => "Aktuelle Version",
+"revisionasof" => "Version vom $1",
+'revisionasofwithlink' => 'Version vom $1; $2<br />$3 | $4',
+'nextrevision'         => '←Nächstjüngere Version',
+'previousrevision'     => 'Nächstältere Version→',
+"cur"                  => "Aktuell",
+"next"                 => "Nächste",
+"last"                 => "Vorherige",
+"orig"                 => "Original",
+"histlegend"   => "Diff Auswahl: Die Boxen der gewünschten
+Versionen markieren und 'Enter' drücken oder den Button unten klicken/alt-v.<br />
+Legende:
+(Aktuell) = Unterschied zur aktuellen Version,
+(Letzte) = Unterschied zur vorherigen Version,
+M = Kleine Änderung",
+
+# Diffs
+#
+"difference"   => "(Unterschied zwischen Versionen)",
+"loadingrev"   => "lage Versionen zur Unterscheidung",
+"lineno"               => "Zeile $1:",
+"editcurrent"  => "Die aktuelle Version dieses Artikels bearbeiten",
+'selectnewerversionfordiff' => 'Eine neuere Version zum Vergleich auswählen',
+'selectolderversionfordiff' => 'Eine ältere Version zum Vergleich auswählen',
+'compareselectedversions' => 'Gewählte Versionen vergleichen',
+
+# Search results
+#
+"searchresults" => "Suchergebnisse",
+"searchresulttext" => "Für mehr Information über {{SITENAME}}, siehe [[Project:Suche|{{SITENAME}} durchsuchen]].",
+"searchquery"  => "Für die Suchanfrage \"$1\"",
+"badquery"             => "Falsche Suchanfrage",
+"badquerytext" => "Wir konnten Ihre Suchanfrage nicht verarbeiten.
+Vermutlich haben Sie versucht, ein Wort zu suchen, das kürzer als zwei Buchstaben ist.
+Dies funktioniert im Moment noch nicht.
+Möglicherweise haben Sie auch die Anfrage falsch formuliert, z.B.
+\"Lohn und und Steuern\".
+Bitte versuchen Sie eine anders formulierte Anfrage.",
+"matchtotals"  => "Die Anfrage \"$1\" stimmt mit $2 Artikelüberschriften
+und dem Text von $3 Artikeln überein.",
+"nogomatch" => "Es existiert kein Artikel [[$1|$1]]. Bitte versuchen
+Sie die Volltextsuche oder [[$1|legen Sie den Artikel neu an]]. ",
+"titlematches" => "Übereinstimmungen mit Überschriften",
+"notitlematches" => "Keine Übereinstimmungen",
+"textmatches"  => "Übereinstimmungen mit Texten",
+"notextmatches"        => "Keine Übereinstimmungen",
+"prevn"                        => "vorherige $1",
+"nextn"                        => "nächste $1",
+"viewprevnext" => "Zeige ($1) ($2) ($3).",
+"showingresults" => "Hier sind <b>$1</b> Ergebnisse, beginnend mit #<b>$2</b>.",
+"showingresultsnum" => "Hier sind <b>$3</b> Ergebnisse, beginnend mit #<b>$2</b>.",
+"nonefound"            => "<strong>Hinweis</strong>:
+Erfolglose Suchanfragen werden häufig verursacht durch den Versuch, nach 'gewöhnlichen' Worten zu suchen; diese sind nicht indiziert.",
+"powersearch" => "Suche",
+"powersearchtext" => "
+Suche in Namensräumen :<br />
+$1<br />
+$2 Zeige auch REDIRECTs &nbsp; Suche nach $3 $9",
+"searchdisabled" => "<p>Entschuldigung! Die Volltextsuche wurde wegen Überlastung temporär deaktiviert. Derweil können Sie die folgende Google Suche verwenden, die allerdings nicht den aktuellen Stand wiederspiegelt.<p>",
+"blanknamespace" => "(Haupt-)",
+
+# Preferences page
+#
+"preferences"  => "Einstellungen",
+"prefsnologin" => "Nicht angemeldet",
+"prefsnologintext"     => "Sie müssen [[Special:Userlogin|angemeldet]] sein, um Ihre Einstellungen zu ändern.",
+"prefslogintext" => "Sie sind angemeldet als \"$1\".
+Ihre interne ID-Nummer ist $2.",
+"prefsreset"   => "Einstellungen wurden auf Standard zurückgesetzt.",
+"qbsettings"   => "Seitenleiste",
+"changepassword" => "Passwort ändern",
+"skin"                 => "Skin",
+"math"                 => "TeX",
+"dateformat" => "Datumsformat",
+"math_failure"         => "Parser-Fehler",
+"math_unknown_error"   => "Unbekannter Fehler",
+"math_unknown_function"        => "Unbekannte Funktion ",
+"math_lexing_error"    => "'Lexing'-Fehler",
+"math_syntax_error"    => "Syntaxfehler",
+"saveprefs"            => "Einstellungen speichern",
+"resetprefs"   => "Einstellungen zurücksetzen",
+"oldpassword"  => "Altes Passwort",
+"newpassword"  => "Neues Passwort",
+"retypenew"            => "Neues Passwort (nochmal)",
+"textboxsize"  => "Textfeld-Größe",
+"rows"                 => "Zeilen",
+"columns"              => "Spalten",
+"searchresultshead" => "Suchergebnisse",
+"resultsperpage" => "Treffer pro Seite",
+"contextlines" => "Zeilen pro Treffer",
+"contextchars" => "Zeichen pro Zeile",
+"stubthreshold" => "Kurze Artikel markieren bis",
+"recentchangescount" => "Anzahl \"Letzte Änderungen\"",
+"savedprefs"   => "Ihre Einstellungen wurden gespeichert.",
+"timezonelegend" => "Zeitzone",
+"timezonetext" => "Geben Sie die Anzahl der Stunden ein, die zwischen Ihrer Zeitzone und UTC liegen.",
+"localtime"    => "Ortszeit",
+"timezoneoffset" => "Unterschied",
+"servertime" => "Aktuelle Zeit auf dem Server",
+"guesstimezone" => "Einfügen aus dem Browser",
+"emailflag"            => "Keine E-Mail von anderen Benutzern erhalten",
+'enotifnewpages'       => 'Sende mir eine Benachrichtigungsmail, wenn jemand eine neue Seite anlegt.',
+"defaultns"            => "In diesen Namensräumen soll standardmäßig gesucht werden:",
+'skinpreview' => '(Vorschau)',
+'yourlanguage' => 'Sprache',
+'imagemaxsize' => 'Verkleinere Bilder auf Bildbeschreibungsseiten auf: ',
+'thumbsize'    => 'Thumbnail-  Größe: ',
+'files'                        => 'Bilder',
+
+# Recent changes
+#
+"changes" => "Änderungen",
+"recentchanges" => "Letzte Änderungen",
+"recentchangestext" => "
+Diese Seite wird beim Laden automatisch aktualisiert. Angezeigt werden Seiten, die zuletzt bearbeitet wurden, sowie die Zeit und der Name des Autors.<br />
+Falls Sie neu bei {{SITENAME}} sind, lesen Sie bitte die [[Project:Willkommen|Willkommensseite]] und [[Project:Erste Schritte|Erste Schritte]].<br />
+Wenn Sie möchten, dass {{SITENAME}} zu einem Erfolg wird, dann fügen Sie bitte keine Texte hinzu, die dem [[Project:Urheberrechte beachten|Urheberrecht]] anderer unterliegen. Dies könnte dem Projekt sonst schweren Schaden zufügen.",
+"rcloaderr"            => "Lade Letzte Änderungen",
+"rcnote"               => "Hier sind die letzten <b>$1</b> Änderungen der letzten <b>$2</b> Tage. (<b>N</b> - Neuer Artikel; <b>M</b> - kleine Änderung)",
+"rcnotefrom"   => "Dies sind die Änderungen seit <b>$2</b> (bis zu <b>$1</b> gezeigt).",
+"rclistfrom"   => "Zeige neue Änderungen seit $1",
+"rclinks"              => "Zeige die letzten $1 Änderungen; zeige die letzten $2 Tage.",
+"diff"                 => "Unterschied",
+"hist"                 => "Versionen",
+"hide"                 => "Ausblenden",
+"show"                 => "Einblenden",
+"tableform"            => "Tabelle",
+"listform"             => "Liste",
+"nchanges"             => "$1 Änderungen",
+"minoreditletter" => "M",
+"newpageletter" => "N",
+'number_of_watching_users_pageview'    => '[$1 Benutzer beobachten diese Seite]',
+
+
+# Upload
+#
+"upload"               => "Hochladen",
+"uploadbtn"            => "Dateien hochladen",
+"uploadlink"           => "Bilder hochladen",
+"reupload"             => "Erneut hochladen",
+"reuploaddesc" => "Zurück zur Hochladen-Seite.",
+"uploadnologin" => "Nicht angemeldet",
+"uploadnologintext"    => "Sie müssen [[Spezial:Userlogin|angemeldet sein]],
+ um Dateien hochladen zu können.",
+"uploaderror"  => "Fehler beim Hochladen",
+"uploadtext"   => "
+Um hochgeladene Bilder zu suchen und anzusehen,
+gehen Sie zu der [[Spezial:Imagelist|Liste hochgeladener Bilder]].
+
+Benutzen Sie das Formular, um neue Bilder hochzuladen und
+sie in Artikeln zu verwenden.
+In den meisten Browsern werden Sie ein \"Durchsuchen\"-Feld sehen,
+das einen Standard-Dateidialog öffnet.
+Suchen Sie sich eine Datei aus. Die Datei wird dann im Textfeld angezeigt.
+Bestätigen Sie dann die Copyright-Vereinbarung.
+Schließlich drücken Sie den \"Hochladen\"-Knopf.
+Dies kann eine Weile dauern, besonders bei einer langsamen Internet-Verbindung.
+
+Für Photos wird das JPEG-Format, für Zeichnungen und Symbole das PNG-Format bevorzugt.
+Um ein Bild in einem Artikel zu verwenden, schreiben Sie an Stelle des Bildes
+'''<nowiki>[[bild:datei.jpg]]</nowiki>''' oder
+'''<nowiki>[[bild:datei.jpg|Beschreibung]]</nowiki>'''.
+
+Bitte beachten Sie, dass, genau wie bei den Artikeln, andere Benutzer Ihre Dateien löschen oder verändern können.",
+"uploadlog"            => "Datei-Logbuch",
+"uploadlogpage" => "Datei-Logbuch",
+"uploadlogpagetext" => "Hier ist die Liste der letzten hochgeladenen Dateien.
+Alle Zeiten sind UTC.
+<ul>
+</ul>
+",
+"filename"             => "Dateiname",
+"filedesc"             => "Beschreibung",
+"filestatus" => "Copyright-Status",
+"filesource" => "Quelle",
+'sourcefilename' => 'Quelldatei',
+'destfilename' => 'Dateiname ändern',
+"copyrightpage" => "Project:Copyright",
+"copyrightpagename" => "{{SITENAME}} copyright",
+"uploadedfiles"        => "Hochgeladene Dateien",
+"ignorewarning"        => "Warnung ignorieren und Datei trotzdem speichern.",
+"minlength"            => "Bilddateien müssen mindestens drei Buchstaben haben.",
+"badfilename"  => "Der Bildname wurde in \"$1\" geändert.",
+"badfiletype"  => "\".$1\" ist kein empfohlenes Dateiformat.",
+"largefile"            => "Bitte keine Bilder über 100 KByte hochladen.",
+'emptyfile'            => "Die hochgeladene Datei ist leer. Der Grund kann ein Tippfehler im Dateinamen sein. Bitte kontrollieren Sie, ob Sie die Datei wirklich hochladen wollen.",
+'fileexists'           => 'Eine Datei mit diesem Namen existiert schon. Bitte überprüfen Sie $1, falls Sie sich nicht sicher sind, ob Sie diese Datei überschreiben wollen.',
+"uploadedimage" => "\"[[$1]]\" hochgeladen",
+'uploadscripted' => 'Diese Datei enthält HTML- oder Scriptcode der irrtümlich von einem Webbrowser ausgeführt werden könnte.',
+'uploadvirus' => 'Diese Datei enthält einen Virus! Details: $1',
+'uploadcorrupt' => 'Die Datei ist beschädigt oder hat einen falschen Namen. Bitte überprüfen Sie die Datei und laden Sie sie erneut hoch.',
+"successfulupload" => "Erfolgreich hochgeladen",
+"fileuploaded" => "Die Datei \"$1\" wurde erfolgreich hochgeladen.
+Bitte verwenden Sie diesen ($2) Link zur Beschreibungsseite und füllen Sie die Informationen über die Datei
+ aus, insbesondere seine Herkunft, von wem und wann es
+ gemacht wurde und besondere Angaben zum Copyright, falls notwendig.
+ Falls es sich um ein Bild handelte, so können Sie mit
+ <tt><nowiki>[[Bild:$1|thumb|Beschreibung]]</nowiki></tt> ein Vorschaubild
+ auf der Seite erzeugen lassen.",
+"uploadwarning" => "Warnung",
+"savefile"             => "Datei speichern",
+"uploadedimage" => "\"[[$1]]\" hochgeladen",
+
+# Image list
+#
+"imagelist"            => "Bilderliste",
+"imagelisttext"        => "Hier ist eine Liste von $1 Bildern, sortiert $2.",
+"getimagelist" => "Lade Bilderliste",
+"ilsubmit"             => "Suche",
+"showlast"             => "Zeige die letzten $1 Bilder, sortiert nach $2.",
+"byname"               => "nach Name",
+"bydate"               => "nach Datum",
+"bysize"               => "nach Grösse",
+"imgdelete"            => "Löschen",
+"imgdesc"              => "Beschreibung",
+"imglegend"            => "Legende: (Beschreibung) = Zeige/Bearbeite Bildbeschreibung.",
+"imghistory"   => "Bild-Versionen",
+"revertimg"            => "Zurücksetzen",
+"deleteimg"            => "Löschen",
+"deleteimgcompletely"          => "Löschen",
+"imghistlegend" => "Legende: (cur) = Dies ist das aktuelle Bild, (Löschen) = lösche
+diese alte Version, (Zurücksetzen) = verwende wieder diese alte Version.",
+"imagelinks"   => "Bildverweise",
+"linkstoimage" => "Die folgenden Artikel benutzen dieses Bild:",
+"nolinkstoimage" => "Kein Artikel benutzt dieses Bild.",
+
+# Statistics
+#
+"statistics"   => "Statistik",
+"sitestats"            => "Seitenstatistik",
+"userstats"            => "Benutzerstatistik",
+"sitestatstext" => "Es gibt insgesamt <b>$1</b> Seiten in der Datenbank.
+Das schliesst \"Diskussion\"-Seiten, Seiten über {{SITENAME}}, extrem kurze Artikel, Weiterleitungen und andere Seiten ein, die nicht als Artikel gelten können.
+Diese ausgenommen, gibt es <b>$2</b> Seiten, die als Artikel gelten können.<p>
+Es wurden insgesamt <b>$3</b>&times; Seiten aufgerufen, und <b>$4</b>&times; Seiten bearbeitet.
+Daraus ergeben sich <b>$5</b> Bearbeitungen pro Seite, und <b>$6</b> Betrachtungen pro Bearbeitung.",
+"userstatstext" => "Es gibt <b>$1</b> registrierte Benutzer.
+Davon haben <b>$2</b> Administrator-Rechte (siehe $3).",
+
+# Maintenance Page
+#
+"maintenance"          => "Wartungsseite",
+"maintnancepagetext"   => "Diese Seite enthält mehrere praktische Funktionen zur täglichen Wartung von {{SITENAME}}. Einige dieser Funktionen können die Datenbank stark beanspruchen, also bitte nicht nach jeder Änderung neu laden ;-)",
+"maintenancebacklink"  => "Zurück zur Wartungsseite",
+"disambiguations"      => "Begriffsklärungsseiten",
+"disambiguationspage"  => "Project:Begriffsklärung",
+"disambiguationstext"  => "Die folgenden Artikel verweisen auf eine <i>Seite zur Begriffsklärung</i>. Sie sollten statt dessen auf die eigentlich gemeinte Seite verweisen.<br />Eine Seite wird als Begriffsklärungsseite behandelt, wenn $1 auf sie verweist.<br />Verweise aus Namensräumen werden hier <i>nicht</i> aufgelistet.",
+"doubleredirects"      => "Doppelte Redirects",
+"doubleredirectstext"  => "<b>Achtung:</b> Diese Liste kann \"falsche Positive\" enthalten. Das ist dann der Fall, wenn ein Redirect außer dem Redirect-Verweis noch weiteren Text mit anderen Verweisen enthält. Letztere sollten dann entfernt werden.",
+"brokenredirects"      => "Kaputte Redirects",
+"brokenredirectstext"  => "Die folgenden Redirects leiten zu einem nicht existierenden Artikel weiter",
+"selflinks"            => "Seiten, die auf sich selbst verweisen",
+"selflinkstext"                => "Die folgenden Artikel verweisen auf sich selbst, was sie nicht sollten.",
+"mispeelings"           => "Seiten mit falsch geschriebenen Worten",
+"mispeelingstext"       => "Die folgenden Seiten enthalten falsch geschriebene Worte, wie sie auf $1 definiert sind. In Klammern angegebene Worte geben die korrekte Schreibweise wieder.<p><strong>Zitate, Buchtitel u.ä. bitte im Originalzustand belassen, also ggf. in alter Rechtschreibung und mit Rechtschreibfehlern!</strong>",
+"mispeelingspage"       => "Liste von Tippfehlern",
+"missinglanguagelinks"  => "Fehlende Sprachverweise",
+"missinglanguagelinksbutton"    => "Zeige fehlende Sprachverweise nach",
+"missinglanguagelinkstext"      => "Diese Artikel haben <i>keinen</i> Verweis zu ihrem Gegenstück in $1. Redirects und Unterseiten werden <i>nicht</i> angezeigt.",
+
+
+# Miscellaneous special pages
+#
+"orphans"              => "Verwaiste Seiten",
+"lonelypages"  => "Verwaiste Seiten",
+"unusedimages" => "Verwaiste Bilder",
+"popularpages" => "Beliebte Seiten",
+"nviews"               => "$1 Abfragen",
+"wantedpages"  => "Gewünschte Seiten",
+"nlinks"               => "$1 Verweise",
+"randompage"   => "Zufälliger Artikel",
+"shortpages"   => "Kurze Artikel",
+"longpages"            => "Lange Artikel",
+"listusers"            => "Benutzerverzeichnis",
+"specialpages" => "Spezialseiten",
+"spheading"            => "Spezialseiten",
+'restrictedpheading'   => 'Spezialseiten für Administratoren',
+"protectpage"  => "Artikel schützen",
+"recentchangeslinked" => "Verlinkte Seiten",
+"rclsub"               => "(auf Artikel von \"$1\")",
+"debug"                        => "Debug",
+"newpages"             => "Neue Artikel",
+'newimages'    => 'Neue Dateien',
+"ancientpages" => "Älteste Artikel",
+"movethispage" => "Artikel verschieben",
+"unusedimagestext" => "<p>Bitte beachten Sie, dass andere Wikis möglicherweise einige dieser Bilder benutzen.",
+"booksources"  => "Buchhandlungen",
+"booksourcetext" => "Dies ist eine Liste mit Links zu Internetseiten, die neue und gebrauchte Bücher verkaufen. Dort kann es auch weitere Informationen über die Bücher geben, die Sie interessieren. {{SITENAME}} ist mit keinem dieser Anbieter geschäftlich verbunden.",
+"alphaindexline" => "$1 bis $2",
+'mostlinked'   => 'Meistverlinke Seiten',
+'uncategorizedpages'   => 'Nicht kategorisierte Artikel',
+'uncategorizedcategories'      => 'Nicht kategorisierte Kategorien',
+'unusedcategories' => 'Verwaiste Kategorien',
+
+# Special:Allpages
+'allpages'     => 'Alle Artikel',
+'nextpage'     => "Nächste Seite ($1)",
+'allpagesfrom' => 'Seiten anzeigen ab:',
+'allarticles'  => 'Alle Artikel',
+'allnonarticles'       => 'Alle Nicht-Artikel',
+'allinnamespace'       => "Alle Seiten im Namensraum: $1",
+'allnotinnamespace'    => "Alle Seiten (ohne Namensraum: $1)",
+'allpagesprev' => 'Vorherige',
+'allpagesnext' => 'Nächste',
+'allpagessubmit'       => 'Zeige',
+
+#Special:Logs
+'log'          => 'Logbücher',
+'alllogstext'  => 'Kombinierte Anzeige der Datei-, Lösch-, Seitenschutz-, Verschiebungs-, Benutzerblockaden- und Bürokraten-Logbücher.
+Sie können die Anzeige einschränken, indem Sie ein Logbuch auswählen und/oder einen Benutzernamen, bzw. eine Seite angeben..',
+'specialloguserlabel' => 'Benutzer: ',
+'speciallogtitlelabel' => 'Titel: ',
+"1movedto2"            => "$1 wurde nach $2 verschoben",
+"1movedto2_redir" => "$1 wurde nach $2 verschoben und überschrieb einen Redirect",
+'movelogpage' => 'Verschiebungslogbuch',
+'movelogpagetext' => 'Liste verschobener Seiten',
+'rightslogtext'                => 'Dies ist ein Logbuch für Änderungen an Benutzerrechten.',
+
+# Email this user
+#
+"mailnologin"  => "Sie sind nicht angemeldet.",
+"mailnologintext" => "Sie müssen [[Spezial:Userlogin|angemeldet sein]]
+und eine gültige E-Mail-Adresse haben, um anderen Benutzern E-Mail zu schicken.",
+"emailuser"            => "E-Mail an diesen Benutzer",
+"emailpage"            => "E-Mail an Benutzer",
+"emailpagetext"        => "Wenn dieser Benutzer eine gültige E-Mail-Adresse angegeben hat, können Sie ihm mit dem untenstehenden Formular eine E-Mail senden. Als Absender wird die E-Mail-Adresse aus Ihren Einstellungen eingetragen, damit der Benutzer Ihnen antworten kann.",
+"usermailererror" => "Das Mail-Objekt gab einen Fehler zurück: ",
+"defemailsubject"  => "{{SITENAME}} e-mail",
+"noemailtitle" => "Keine E-Mail-Adresse",
+"noemailtext"  => "Dieser Benutzer hat keine gültige E-Mail-Adresse angegeben, oder möchte keine E-Mail von anderen Benutzern empfangen.",
+"emailfrom"            => "Von",
+"emailto"              => "An",
+"emailsubject" => "Betreff",
+"emailmessage" => "Nachricht",
+"emailsend"            => "Senden",
+"emailsent"            => "E-Mail verschickt",
+"emailsenttext" => "Ihre E-Mail wurde verschickt.",
+
+
+# Beobachtungsliste
+#
+"watchlist"            => "Beobachtungsliste",
+"watchlistsub" => "(für Benutzer \"$1\")",
+"nowatchlist"  => "Sie haben keine Einträge auf Ihrer Beobachtungsliste.",
+"watchnologin" => "Sie sind nicht angemeldet",
+"watchnologintext"     => "Sie müssen [[Special:Userlogin|angemeldet]]
+sein, um Ihre Beobachtungsliste zu bearbeiten.",
+"addedwatch"   => "Zur Beobachtungsliste hinzugefügt",
+"addedwatchtext" => "Der Artikel \"$1\" wurde zu Ihrer [[Special:Watchlist|Beobachtungsliste]] hinzugefügt.
+Spätere Änderungen an diesem Artikel und der zugehörigen Diskussions-Seite
+werden dort gelistet und der Artikel wird in der [[Special:Recentchanges|Liste der letzten Änderungen]] <b>fett</b> angezeigt. <p>Wenn Sie den Artikel wieder von ihrer
+Beobachtungsliste entfernen wollen, klicken Sie auf \"Nicht mehr beobachten\"
+am Ende des Artikels.",
+"removedwatch" => "Von der Beobachtungsliste entfernt",
+"removedwatchtext" => "Der Artikel \"$1\" wurde von Ihrer Beobachtungsliste entfernt.",
+"watchthispage"        => "Seite beobachten",
+"unwatchthispage" => "Nicht mehr beobachten",
+"notanarticle" => "Kein Artikel",
+"watchnochange" => "Keine Ihrer beobachteten Artikel wurde während des angezeigten Zeitraums bearbeitet.",
+"watchdetails" => "* Sie beobachten zur Zeit insgesamt $1 Artikel (Diskussionsseiten wurden hier nicht mitgezählt).
+* [[Special:Watchlist/edit|Gesamte Beobachtungsliste]] anzeigen und bearbeiten.
+",
+'wlheader-enotif'              => "* E-Mail-Benachrichtigungsdienst ist eingeschaltet.",
+'wlheader-showupdated'   => "* Seiten mit noch nicht gesehenen Änderungen werden '''fett''' dargestellt.",
+"watchmethod-recent" => "Überprüfen der letzten Bearbeitungen für die Beobachtungsliste",
+"watchmethod-list" => "Überprüfen der Beobachtungsliste nach letzten Bearbeitungen",
+"removechecked" => "Markierte Einträge löschen",
+"watchlistcontains" => "Ihre Beobachtungsliste enthält $1 Seiten.",
+"watcheditlist" => "Alphabetische Liste der von Ihnen beobachteten Seiten.<br />
+Hier können Sie Seiten markieren, um Sie dann von der Beobachtungsliste zu löschen.",
+"removingchecked" => "Wunschgemäß werden die Einträge aus der Beobachtungsliste entfernt...",
+"couldntremove" => "Der Eintrag '$1' kann nicht gelöscht werden...",
+"iteminvalidname" => "Problem mit dem Eintrag '$1', ungültiger Name...",
+'wlnote' => 'Es folgen die letzten $1 Änderungen der letzten <b>$2</b> Stunden.',
+'wlshowlast' => 'Zeige die letzen $1 Stunden $2 Tage $3',
+'wlsaved'       => 'Dies ist eine gespeicherte Version Ihrer Beobachtungsliste.',
+'wlhideshowown'  => '$1 von mir bearbeitete Artikel.',
+'wlshow'         => 'Zeige ',
+'wlhide'         => 'Verstecke ',
+
+'updatedmarker'                        => '<span class=\'updatedmarker\'>&nbsp;(geändert)&nbsp;</span>',
+'enotif_mailer'                => '{{SITENAME}} E-Mail-Benachrichtigungsdienst',
+'enotif_reset'                 => 'Alle Benachrichtigungsmarker zurücksetzen (alle Seiten als "gesehen" markieren)',
+'enotif_newpagetext'           => 'Dies ist eine neue Seite.',
+'changed'                      => 'geändert',
+'created'                      => 'neu angelegt',
+'enotif_subject'               => 'Die {{SITENAME}} Seite $PAGETITLE wurde von $PAGEEDITOR $CHANGEDORCREATED',
+'enotif_lastvisited' => '$1 zeigt alle Änderungen auf einen Blick.',
+'enotif_to'    => '$WATCHINGUSERNAME_QP <$WATCHINGUSEREMAILADDR>',
+'enotif_body' => 'Liebe/r $WATCHINGUSERNAME,
+
+die {{SITENAME}} Seite $PAGETITLE wurde von $PAGEEDITOR am $PAGEEDITDATE $CHANGEDORCREATED,
+die aktuelle Version ist: $PAGETITLE_URL
+
+$NEWPAGE
+
+Zusammenfassung des Editors: $PAGESUMMARY $PAGEMINOREDIT
+Kontakt zum Editor:
+Mail $PAGEEDITOR_EMAIL
+Wiki $PAGEEDITOR_WIKI
+
+Es werden solange keine weiteren Benachrichtigungsmails gesendet, bis Sie die Seite wieder besuchen. Auf Ihrer Beobachtungsseite können Sie alle Benachrichtigungsmarker zusammen zurücksetzen.
+
+             Ihr freundliches {{SITENAME}} Benachrichtigungssystem
+
+---
+Ihre Beobachtungsliste {{SERVER}}{{localurl:Special:Watchlist/edit}}
+Hilfe zur Benutzung gibt {{SERVER}}{{localurl:WikiHelpdesk}}',
+
+# Delete/protect/revert
+#
+"deletepage"   => "Seite löschen",
+"confirm"              => "Bestätigen",
+"excontent" => "Alter Inhalt: '$1'",
+"excontentauthor" => "Alter Inhalt: '$1' (einziger Autor war '$2')",
+"exbeforeblank" => "Inhalt vor dem Leeren der Seite: '$1'",
+"exblank" => "Seite war leer",
+"confirmdelete" => "Löschung bestätigen",
+"deletesub"            => "(Lösche \"$1\")",
+"historywarning" => "WARNUNG: Die Seite die Sie zu löschen gedenken hat
+eine Versionsgeschichte: ",
+"confirmdeletetext" => "Sie sind dabei, einen Artikel oder ein Bild und alle älteren Versionen permanent aus der Datenbank zu löschen.
+Bitte bestätigen Sie Ihre Absicht, dies zu tun, dass Sie sich der Konsequenzen bewusst sind, und dass Sie in Übereinstimmung mit unseren [[Project:Leitlinien|Leitlinien]] handeln.",
+"actioncomplete" => "Aktion beendet",
+"deletedtext"  => "\"$1\" wurde gelöscht.
+Im $2 finden Sie eine Liste der letzten Löschungen.",
+"deletedarticle" => "\"$1\" gelöscht",
+"dellogpage"   => "Lösch-Logbuch",
+"dellogpagetext" => "Hier ist eine Liste der letzten Löschungen (UTC).
+<ul>
+</ul>
+",
+"deletionlog"  => "Lösch-Logbuch",
+"reverted"             => "Auf eine alte Version zurückgesetzt",
+"deletecomment"        => "Grund der Löschung",
+"imagereverted" => "Auf eine alte Version zurückgesetzt.",
+"rollback" => "Zurücknahme der Änderungen",
+'rollback_short' => 'Rollback',
+"rollbacklink" => "Rollback",
+"rollbackfailed" => "Zurücknahme gescheitert",
+"cantrollback" => "Die Änderung kann nicht zurückgenommen werden; der
+letzte Autor ist der einzige.",
+"alreadyrolled" => "Die Zurücknahme des Artikels [[$1]] von [[Benutzer:$2|$2]]
+([[Benutzer Diskussion:$2|Diskussion]]) ist nicht möglich, da eine andere
+Änderung oder Rücknahme erfolgt ist.
+
+Die letzte Änderung ist von [[Benutzer:$3|$3]]
+([[Benutzer Diskussion:$3|Diskussion]])",
+#   only shown if there is an edit comment
+"editcomment" => "Der Änderungskommentar war: \"<i>$1</i>\".",
+"revertpage" => "Wiederhergestellt zur letzten Änderung von $1",
+
+# Undelete
+"undelete" => "Gelöschte Seite wiederherstellen",
+"undeletepage" => "Gelöschte Seiten wiederherstellen",
+"undeletepagetext" => "Die folgenden Seiten wurden gelöscht, sind aber immer noch
+gespeichert und können wiederhergestellt werden.",
+"undeletearticle" => "Gelöschten Artikel wiederherstellen",
+"undeleterevisions" => "$1 Versionen archiviert",
+"undeletehistory" => "Wenn Sie diese Seite wiederherstellen, werden auch alle alten
+Versionen wiederhergestellt. Wenn seit der Löschung ein neuer Artikel gleichen
+Namens erstellt wurde, werden die wiederhergestellten Versionen als alte Versionen
+dieses Artikels erscheinen.",
+"undeleterevision" => "Gelöschte Version vom $1",
+"undeletebtn" => "Wiederherstellen!",
+"undeletedarticle" => "\"$1\" wiederhergestellt",
+"undeletedtext"   => "Der Artikel [[$1]] wurde erfolgreich wiederhergestellt.",
+
+# Contributions
+#
+"contributions"        => "Benutzerbeiträge",
+"mycontris" => "Meine Beiträge",
+"contribsub"   => "Für $1",
+"nocontribs"   => "Es wurden keine Änderungen für diese Kriterien gefunden.",
+"ucnote"               => "Dies sind die letzten <b>$1</b> Beiträge des Benutzers in den letzten <b>$2</b> Tagen.",
+"uclinks"              => "Zeige die letzten $1 Beiträge; zeige die letzten $2 Tage.",
+"uctop"                => " (aktuell)" ,
+
+# What links here
+#
+"whatlinkshere"        => "Was zeigt hierhin",
+"notargettitle" => "Kein Artikel angegeben",
+"notargettext" => "Sie haben nicht angegeben, auf welche Seite Sie diese Funktion anwenden wollen.",
+"linklistsub"  => "(Liste der Verweise)",
+"linkshere"            => "Die folgenden Artikel verweisen hierhin:",
+"nolinkshere"  => "Kein Artikel verweist hierhin.",
+"isredirect"   => "Weiterleitungs-Seite",
+
+# Block/unblock IP
+#
+"blockip"              => "IP-Adresse blockieren",
+"blockiptext"  => "Benutzen Sie das Formular, um eine IP-Adresse zu blockieren.
+Dies sollte nur erfolgen, um Vandalismus zu verhindern, in Übereinstimmung mit unseren [[Project:Leitlinien|Leitlinien]].
+Bitte tragen Sie den Grund für die Blockade ein.",
+"ipaddress"            => "IP-Adresse",
+'ipadressorusername' => 'IP-Adresse oder Benutzername',
+"ipbreason"            => "Grund",
+"ipbsubmit"            => "Adresse blockieren",
+'ipbother'             => 'Andere Zeit',
+'ipboptions'           => '2 Stunden:2 hours,1 Tag:1 day,3 Tage:3 days,1 Woche:1 week,2 Wochen:2 weeks,1 Monat:1 month,3 Monate:3 months,6 Monate:6 months,1 Jahr:1 year,Unendlich:infinite',
+'ipbotheroption'       => 'Andere',
+"badipaddress" => "Die IP-Adresse hat ein falsches Format.",
+"blockipsuccesssub" => "Blockade erfolgreich",
+"blockipsuccesstext" => "Die IP-Adresse \"$1\" wurde blockiert.
+<br />Auf [[Spezial:Ipblocklist|IP block list]] ist eine Liste der Blockaden.",
+"unblockip"            => "IP-Adresse freigeben",
+"unblockiptext"        => "Benutzen Sie das Formular, um eine blockierte IP-Adresse freizugeben.",
+"ipusubmit"            => "Diese Adresse freigeben",
+"ipusuccess"   => "IP-Adresse \"$1\" wurde freigegeben",
+"ipblocklist"  => "Liste blockierter IP-Adressen",
+"blocklistline"        => "$1, $2 blockierte $3 ($4)",
+"blocklink"            => "blockieren",
+"unblocklink"  => "freigeben",
+"contribslink" => "Beiträge",
+"autoblocker" => "Automatische Blockierung, da Sie eine IP-Adresse benutzen mit \"$1\". Grund: \"$2\".",
+
+# Developer tools
+#
+"lockdb"               => "Datenbank sperren",
+"unlockdb"             => "Datenbank freigeben",
+"lockdbtext"   => "Mit dem Sperren der Datenbank werden alle Änderungen an Benutzereinstellungen, watchlisten, Artikeln usw. verhindert. Bitte bestätigen Sie Ihre Absicht, die Datenbank zu sperren.",
+"unlockdbtext" => "Das Aufheben der Datenbank-Sperre wird alle Änderungen wieder zulassen. Bitte bestätigen Sie Ihre Absicht, die Sperrung aufzuheben.",
+"lockconfirm"  => "Ja, ich möchte die Datenbank sperren.",
+"unlockconfirm"        => "Ja, ich möchte die Datenbank freigeben.",
+"lockbtn"              => "Datenbank sperren",
+"unlockbtn"            => "Datenbank freigeben",
+"locknoconfirm" => "Sie haben das Bestätigungsfeld nicht markiert.",
+"lockdbsuccesssub" => "Datenbank wurde erfolgreich gesperrt",
+"unlockdbsuccesssub" => "Datenbank wurde erfolgreich freigegeben",
+"lockdbsuccesstext" => "Die {{SITENAME}}-Datenbank wurde gesperrt.
+<br />Bitte geben Sie die Datenbank wieder frei, sobald die Wartung abgeschlossen ist.",
+"unlockdbsuccesstext" => "Die {{SITENAME}}-Datenbank wurde freigegeben.",
+
+
+# User levels special page
+#
+'userrights' => 'Benutzerrechtsverwaltung',
+
+'userrights-lookup-user' => 'Verwalte Gruppenzugehörigkeit',
+'userrights-user-editname' => 'Benutzername: ',
+'editusergroup' => 'Bearbeite Benutzerrechte',
+
+# user groups editing
+#
+'userrights-editusergroup' => 'Bearbeite Gruppenzugehörigkeit des Benutzers',
+'saveusergroups' => 'Speichere Gruppenzugehörigkeit',
+'userrights-groupsmember' => 'Mitglied von: ',
+'userrights-groupsavailable' => 'Verfügbare Gruppen: ',
+'userrights-groupshelp' => 'Wähle die Gruppen, aus denen der Benutzer entfernt oder zu denen er hinzugefügt werden soll.
+Nicht selektierte Gruppen werden nicht geändert. Eine Selektion kann mit Strg + Linksklick (bzw. Ctrl + Linksklick) entfernt werden.',
+
+# Move page
+#
+"movepage"             => "Artikel verschieben",
+"movepagetext" => "Mit diesem Formular können Sie einen Artikel umbenennen, mitsamt allen Versionen. Der alte Titel wird zum neuen weiterleiten. Verweise auf den alten Titel werden nicht geändert, und die Diskussionsseite wird auch nicht mitverschoben.",
+"movepagetalktext" => "Die dazugehörige Diskussionsseite wird, sofern vorhanden, mitverschoben, '''es sei denn:'''
+*Sie verschieben die Seite in einen anderen Namensraum, oder
+*Es existiert bereits eine Diskussionsseite mit diesem Namen, oder
+*Sie wählen die untenstehende Option ab
+
+In diesen Fällen müssen Sie die Seite, falls gewünscht, von Hand verschieben.",
+"movearticle"  => "Artikel verschieben",
+"movenologin"   => "Sie sind nicht angemeldet",
+"movenologintext" => "Sie müssen ein registrierter Benutzer und
+[[Special:Userlogin|angemeldet]] sein,
+um eine Seite zu verschieben.",
+"newtitle"             => "Zu neuem Titel",
+"movepagebtn"  => "Artikel verschieben",
+"pagemovedsub" => "Verschiebung erfolgreich",
+"pagemovedtext" => "Artikel \"[[$1]]\" wurde nach \"[[$2]]\" verschoben.",
+"articleexists" => "Unter diesem Namen existiert bereits ein Artikel.
+Bitte wählen Sie einen anderen Namen.",
+"talkexists"    => "Die Seite selbst wurde erfolgreich verschoben, aber die
+Diskussions-Seite nicht, da schon eine mit dem neuen Titel existiert. Bitte gleichen Sie die Inhalte von Hand ab.",
+"movedto"              => "verschoben nach",
+"movetalk"             => "Die \"Diskussions\"-Seite mitverschieben, wenn möglich.",
+"talkpagemoved" => "Die \"Diskussions\"-Seite wurde ebenfalls verschoben.",
+"talkpagenotmoved" => "Die \"Diskussions\"-Seite wurde <strong>nicht</strong> verschoben.",
+
+"export"        => "Seiten exportieren",
+"exporttext"    => "Sie können den Text und die Bearbeitungshistorie einer bestimmten oder einer Auswahl von Seiten nach XML exportieren. Das Ergebnis kann in ein anderes Wiki mit WikiMedia Software eingespielt werden, bearbeitet oder archiviert werden.",
+"exportcuronly" => "Nur die aktuelle Version der Seite exportieren",
+"missingimage"          => "<b>Fehlendes Bild</b><br /><i>$1</i>\n",
+
+#Tooltips:
+'tooltip-watch' => 'Diese Seite beobachten. [alt-w]',
+'tooltip-search' => 'Suchen [alt-f]',
+'tooltip-minoredit' => 'Diese Änderung als klein markieren. [alt-i]',
+'tooltip-save' => 'Änderungen speichern [alt-s]',
+'tooltip-preview' => 'Vorschau der Änderungen an dieser Seite. Benutzen Sie dies vor dem Speichern! [alt-p]',
+'tooltip-diff' => 'Zeigt Ihre Änderungen am Text tabellarisch an [alt-d]',
+'tooltip-compareselectedversions' => 'Unterschiede zwischen zwei ausgewählten Versionen dieser Seite vergleichen. [alt-v]',
+
+#Tastatur-Shortcuts
+'accesskey-search' => 'f',
+'accesskey-minoredit' => 'i',
+'accesskey-save' => 's',
+'accesskey-preview' => 'p',
+'accesskey-diff' => 'd',
+'accesskey-compareselectedversions' => 'v',
+
+"makesysoptitle"        => "Mache einen Benutzer zum Administrator",
+"makesysoptext"         => "Diese Maske wird von Bürokraten benutzt, um normale Benutzer zu Administratoren zu machen.",
+"makesysopname"         => "Name des Benutzers:",
+"makesysopsubmit"       => "Mache diesen Benutzer zu einem Administrator",
+"makesysopok"           => "<b>Benutzer \"$1\" ist nun ein Administrator.</b>",
+"makesysopfail"         => "<b>Benutzer \"$1\" konnte nicht zu einem Administrator gemacht werden. (Haben Sie den Namen richtig geschrieben?)</b>",
+"makesysop"         => "Mache einen Benutzer zum Administrator",
+"bureaucratlogentry"   => "Rechte für Benutzer \"$1\" auf \"$2\" gesetzt",
+"rights"               => "Rechte:",
+"set_user_rights"      => "Benutzerrechte setzen",
+"user_rights_set"      => "<b>Benutzerrechte für \"$1\" aktualisiert</b>",
+"set_rights_fail"      => "<b>Benutzerrechte für \"$1\" konnten nicht gesetzt werden. (Haben Sie den Namen korrekt eingegeben?)</b>",
+"allmessages"          => "Alle MediaWiki-Meldungen",
+"allmessagestext"      => "Dies ist eine Liste aller möglichen Meldungen im MediaWiki-Namensraum.",
+"thumbnail-more"       => "vergrößern",
+"and"                  => "und",
+"rchide"               => "in $4 form; $1 kleine Änderungen; $2 sekundäre Namensräume; $3 mehrfache Änderungen.",
+"showhideminor"                => "kleine Änderungen $1 | $2 bots | $3 logged in users | $4 patrolled edits ",
+"rcliu"                        => "$1 Änderungen durch eingeloggte Benutzer",
+"uploaddisabled"       => "Entschuldigung, das Hochladen ist deaktiviert.",
+"deadendpages"         => "Sackgassenartikel",
+"intl"                 => "InterWikiLinks",
+"version"              => "Version",
+"protectlogpage"       => "Seitenschutz-Logbuch",
+"protectlogtext"       => "Dies ist eine Liste der blockierten Seiten. Siehe [[{{SITENAME}}:Geschützte Seiten]] für mehr Informationen.",
+"protectedarticle" => "Artikel [[$1]] geschützt",
+"unprotectedarticle" => "Artikel [[$1]] freigegeben",
+"protectsub" =>"(Sperren von \"$1\")",
+"confirmprotecttext" => "Soll diese Seite wirklich geschützt werden?",
+"ipbexpiry"            => "Ablaufzeit",
+"blocklogpage"         => "Benutzerblockaden-Logbuch",
+"blocklogentry"                => "blockiert [[Benutzer:$1]] - ([[Spezial:Contributions/$1|Beiträge]]) für einen Zeitraum von: $2",
+"blocklogtext"         => "Dies ist ein Log über Sperrungen und Entsperrungen von Benutzern. Automatisch geblockte IP-Adressen werden nicht erfasst. Siehe [[Special:Ipblocklist|IP block list]] für eine Liste der gesperrten Benutzern.",
+"unblocklogentry"      => "Blockade von [[Benutzer:$1]] aufgehoben",
+"range_block_disabled" => "Die Möglichkeit, ganze Adressräume zu sperren, ist nicht aktiviert.",
+"ipb_expiry_invalid"   => "Die angegebeben Ablaufzeit ist ungültig.",
+"ip_range_invalid"     => "Ungültiger IP-Addressbereich.",
+"confirmprotect"       => "Sperrung bestätigen",
+"protectcomment"       => "Grund der Sperrung",
+"unprotectsub"         => "(Aufhebung der Sperrung von \"$1\")",
+"confirmunprotecttext" => "Wollen Sie wirklich die Sperrung dieser Seite aufheben?",
+"confirmunprotect"     => "Aufhebung der Sperrung bestätigen",
+"unprotectcomment"     => "Grund für das Aufheben der Sperrung",
+"proxyblocker"         => "Proxyblocker",
+"proxyblockreason"      => "Ihre IP-Adresse wurde gesperrt, da sie ein offener Proxy ist. Bitte kontaktieren Sie Ihren Provider oder Ihre Systemtechnik und informieren Sie sie über dieses mögliche Sicherheitsproblem.",
+"proxyblocksuccess"     => "Fertig.\n",
+"math_image_error"     => "die PNG-Konvertierung schlug fehl.",
+"math_bad_tmpdir"      => "Kann das Temporärverzeichnis für mathematische Formeln nicht anlegen oder beschreiben.",
+"math_bad_output"      => "Kann das Zielverzeichnis für mathematische Formeln nicht anlegen oder beschreiben.",
+"math_notexvc"         => "Das texvc-Programm kann nicht gefunden werden. Bitte beachten Sie math/README.",
+'prefs-personal' => 'Benutzerdaten',
+'prefs-rc' => 'Letzte Änderungen und Anzeige kurzer Artikel',
+'prefs-misc' => 'Verschiedene Einstellungen',
+"import"               => "Seiten importieren",
+"importtext"           => "Bitte exportieren Sie die Seite vom Quellwiki mittels Spezial:Export und laden Sie die Datei dann über diese Seite wieder hoch.",
+"importfailed"         => "Import fehlgeschlagen: $1",
+"importnotext"         => "Leer oder kein Text",
+"importsuccess"        => "Import erfolgreich!",
+"importhistoryconflict" => "Es existieren bereits ältere Versionen, die mit diesen kollidieren. (Möglicherweise wurde die Seite bereits vorher importiert)",
+"isbn"                 => "ISBN",
+"rfcurl"               => "http://www.faqs.org/rfcs/rfc$1.html",
+"siteuser" => "{{SITENAME}}-Benutzer $1",
+"siteusers" => "{{SITENAME}}-Benutzer $1",
+'watch' => 'Beobachten',
+'unwatch' => 'nicht mehr beobachten',
+'move' => "verschieben",
+'edit' => 'bearbeiten',
+'talk' => 'Diskussion',
+"infobox" => "Klicken Sie einen Button, um einen Beispieltext zu erhalten.",
+"infobox_alert" => "Bitte geben Sie den Text ein, den Sie formatiert haben möchten.\\nEr wird dann zum Kopieren in der Infobox angezeigt.\\nBeispiel:\\n$1\\nwird zu\\n$2",
+"nocookiesnew" => "Der Benutzerzugang wurde erstellt, aber Sie sind nicht eingeloggt. {{SITENAME}} benötigt für diese Funktion Cookies, bitte aktivieren Sie diese und loggen sich dann mit Ihrem neuen Benutzernamen und dem Passwort ein.",
+"nocookieslogin" => "{{SITENAME}} benutzt Cookies zum Einloggen der Benutzer. Sie haben Cookies deaktiviert, bitte aktivieren Sie diese und versuchen es erneut.",
+"subcategorycount" => "Diese Kategorie hat $1 Unterkategorien.",
+"categoryarticlecount" => "Dieser Kategorie gehören $1 Artikel an.",
+'categoryarticlecount1' => "Dieser Kategorie gehört $1 Artikel an.",
+'categoriespagetext' => 'In diesem Wiki gibt es die folgenden Kategorien:',
+'unusedcategoriestext' => 'Die folgenden Kategorieseiten existieren, obwohl sie nicht verwendet werden.',
+'groups-editgroup-name'     => 'Gruppenname: ',
+# math
+       'mw_math_png' => "Immer als PNG darstellen",
+       'mw_math_simple' => "Einfaches TeX als HTML darstellen, sonst PNG",
+       'mw_math_html' => "Wenn möglich als HTML darstellen, sonst PNG",
+       'mw_math_source' =>"Als TeX belassen (für Textbrowser)",
+       'mw_math_modern' => "Empfehlenswert für moderne Browser",
+       'mw_math_mathml' => 'MathML (experimentell)',
+       
+'passwordtooshort' => 'Ihr Passwort ist zu kurz. Es muss mindestens $1 Zeichen lang sein.',
+
+# Media Warning
+'mediawarning' => '
+===Warnung!===
+Diese Art von Datei kann böswilligen Programmcode enthalten.
+Durch das Herunterladen oder Öffnen der Datei kann der Computer beschädigt werden.
+Bereits das Anklicken des Links kann dazu führen dass der Browser die Datei öffnet
+und unbekannter Programmcode zur Ausführung kommt.
+
+Die Betreiber dieses Wikis können keine Verantwortung für den Inhalte
+dieser Datei übernehmen. Sollte diese Datei tatsächlich böswilligen Programmcode enthalten,
+sollte umgehend ein Administrator informiert werden!
+
+',
+
+'fileinfo' => '$1KB, [http://de.wikipedia.org/wiki/Multipurpose_Internet_Mail_Extensions $2]',
+
+# external editor support
+'edit-externally' => 'Diese Datei mit einem externen Programm bearbeiten',
+'edit-externally-help' => 'Siehe [http://meta.wikimedia.org/wiki/Hilfe:Externe_Editoren Installations-Anweisungen] für weitere Informationen',
+
+# Metadata
+'exif-make'    => 'Hersteller',     # Image input equipment manufacturer
+'exif-model'   => 'Modell',         # Image input equipment model
+'exif-software' => 'Software',       # Software used
+'exif-artist'   => 'Fotograf',       # Person who created the image
+'exif-copyright'=> 'Copyright',      # Copyright holder
+
+# Tags relating to image structure
+'exif-imagewidth'  => 'Breite',      # Image width
+'exif-imagelength' => 'Länge',      # Image height
+'exif-orientation' => 'Orientierung',# Orientation of image
+'exif-xresolution' => 'Horizontale Auflösung',            # Image resolution in width direction
+'exif-yresolution' => 'Vertikale Auflösung',              # Image resolution in height direction
+'exif-resolutionunit' => 'Masseinheit der Auflösung',     # Unit of X and Y resolution
+
+# Tags relating to image data characteristics
+'exif-ycbcrcoefficients' => 'YCbCr-Koeffizienten',              # Color space transformation matrix coefficients
+'exif-referenceblackwhite' => 'Schwarz/Weiß-Referenzpunkte',  # Pair of black and white reference values
+
+# Tags relating to Image Data Characteristics
+'exif-colorspace' => 'Farbraum',                                # Color space information
+
+# Tags relating to picture-taking conditions
+'exif-exposuretime' => 'Belichtungsdauer',                 # Exposure time
+'exif-fnumber' => 'F-Wert',                      # F Number
+'exif-exposureprogram' => 'Belichtungsprogramm',              # Exposure Program
+'exif-spectralsensitivity' => 'Spectral Sensitivity',          # Spectral sensitivity
+'exif-isospeedratings' => 'Filmempfindlichkeit (ISO)',              # ISO speed rating
+'exif-shutterspeedvalue' => 'Shutter Speed Value',            # Shutter speed
+'exif-aperturevalue' => 'Blendenwert',                # Aperture
+'exif-brightnessvalue' => 'Brightness Value',              # Brightness
+'exif-exposurebiasvalue' => 'Belichtungsvorgabe',            # Exposure bias
+'exif-maxaperturevalue' => 'Größte Blende',             # Maximum land aperture
+'exif-subjectdistance' => 'Entfernung',              # Subject distance
+'exif-meteringmode' => 'Messverfahren',                 # Metering mode
+'exif-lightsource' => 'Lichtquelle',                  # Light source
+'exif-flash' => 'Blitz',                        # Flash
+'exif-focallength' => 'Brennweite',                  # Lens focal length
+'exif-flashenergy' => 'Blitzstärke',                  # Flash energy
+'exif-exposuremode' => 'Belichtungsmodus',                 # Exposure mode
+'exif-whitebalance' => 'Weißabgleich',                 # White Balance
+'exif-focallengthin35mmfilm' => 'Brennweite (Kleinbildäquivalent)',        # Focal length in 35 mm film
+'exif-contrast' => 'Kontrast',                     # Contrast
+'exif-saturation'=> 'Sättigung',                   # Saturation
+'exif-sharpness' => 'Schärfe',                    # Sharpness
+
+# E-mail address confirmation
+'confirmemail' => 'E-Mail-Adressenbestätigung (Authentifizierung)',
+'confirmemail_text' => "Diese Wiki erfordert, dass Sie Ihre E-Mailadresse bestätigen (authentifizieren),
+bevor Sie die erweiterten Mailfunktionen benutzen können. Ein Klick auf die Schaltfläche unten sendet eine E-Mail zu Ihnen.
+Diese Mail enthält einen Link mit einem Kode; durch Klicken auf diesen Link bestätigen Sie, dass Ihre Adresse gültig ist.",
+'confirmemail_send' => 'Anforderung einer E-Mail zur Adressenbestätigung',
+'confirmemail_sent' => 'Es wurde Ihnen eine Mail zur Adressenbestätigung gesendet.',
+'confirmemail_sendfailed' => 'Could not send confirmation mail due to misconfigured server or invalid characters in e-mail address.',
+'confirmemail_invalid' => 'Ungültiger Bestätigungskode. Die Gültigkeitsdauer des Kodes ist eventuell abgelaufen.',
+'confirmemail_success' => 'Ihre E-Mailadresse wurde bestätigt. Sie können sich jetzt einloggen.',
+'confirmemail_loggedin' => 'Ihre E-Mailadresse ist nun bestätigt.',
+'confirmemail_error' => 'Es gab einen Fehler bei der Bestätigung Ihrer E-Mailadresse.',
+
+'confirmemail_subject' => '{{SITENAME}} E-Mail-Adressenbestätigung (Authentifizierung)',
+'confirmemail_body'    => "Jemand, vielleicht Sie, hat von IP-Adresse $1
+ein Benutzerkonto \"$2\" mit dieser E-Mailadresse bei {{SITENAME}} angemeldet.
+
+Zur Bestätigung, dass dieses Konto wirklich Ihnen gehört, und um die erweiterten
+E-Mailfunktionen für Sie bei {{SITENAME}} einzuschalten, öffnen Sie bitte den folgenden Link
+in Ihrem Browser:
+
+$3
+
+Wenn Sie *nicht* $2 sind, folgen Sie dem Link bitte nicht.
+
+Der Bestätigungskode läuft am $4 ab.
+"
+
+);
+
+/** @package MediaWiki */
+class LanguageDe extends LanguageUtf8 {
+
+       function getBookstoreList() {
+               global $wgBookstoreListDe ;
+               return $wgBookstoreListDe ;
+       }
+
+       function getNamespaces() {
+               global $wgNamespaceNamesDe;
+               return $wgNamespaceNamesDe;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsDe;
+               return $wgQuickbarSettingsDe;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesDe;
+               return $wgSkinNamesDe;
+       }
+
+       function date( $ts, $adj = false ) {
+               if ( $adj ) { $ts = $this->userAdjust( $ts ); }
+
+               $d = (0 + substr( $ts, 6, 2 )) . ". " .
+               $this->getMonthAbbreviation( substr( $ts, 4, 2 ) ) .
+                 " " .
+                 substr( $ts, 0, 4 );
+               return $d;
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesDe;
+               if( isset( $wgAllMessagesDe[$key] ) ) {
+                       return $wgAllMessagesDe[$key];
+               } else {
+                       return parent::getMessage( $key );
+               }
+       }
+
+       function formatNum( $number ) {
+               return strtr($number, '.,', ',.' );
+       }
+
+}
+
+?>
diff --git a/languages/LanguageDv.php b/languages/LanguageDv.php
new file mode 100644 (file)
index 0000000..cb4de84
--- /dev/null
@@ -0,0 +1,18 @@
+<?php
+/** Dhivehi language file ( ދިވެހިބަސް',      )
+  *
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+require_once( 'LanguageUtf8.php' );
+
+class LanguageDv extends LanguageUtf8 {
+       #FIXME: inherit almost everything for now
+
+       function isRTL() {
+               return true;
+       }
+}
+
+?>
diff --git a/languages/LanguageDz.php b/languages/LanguageDz.php
new file mode 100644 (file)
index 0000000..581faf3
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+/** Dzongkha (རྫོང་ཁ)
+  *
+  * @package MediaWiki
+  * @subpackage Language
+  *
+  * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
+  */
+
+require_once( 'LanguageUtf8.php' );
+
+class LanguageDz extends LanguageUtf8 {
+       var $digitTransTable = array(
+               '0' => '༠',
+               '1' => '༡',
+               '2' => '༢',
+               '3' => '༣',
+               '4' => '༤',
+               '5' => '༥',
+               '6' => '༦',
+               '7' => '༧',
+               '8' => '༨',
+               '9' => '༩'
+       );
+
+       function formatNum( $number ) {
+               global $wgTranslateNumerals;
+               if( $wgTranslateNumerals ) {
+                       return strtr( $number, $this->digitTransTable );
+               } else {
+                       return $number;
+               }
+       }
+}
+
+?>
diff --git a/languages/LanguageEl.php b/languages/LanguageEl.php
new file mode 100644 (file)
index 0000000..d322b40
--- /dev/null
@@ -0,0 +1,2023 @@
+<?php
+/** Greek (Ελληνικά)
+  *
+  * Translation by Pasok Internet Volunteers
+  * http://forum.pasok.gr
+  * version 1.0 (initial release)
+  *
+  *The project for the translation of MediaWiki into Greek 
+  *was undertaken by a group of ICT volunteers working under 
+  *the auspices of the Greek political party PASOK.
+  *
+  *The idea behind this effort was  to provide an extensible,
+  *easy-to-use and non-intimidating tool for content development
+  *and project management, to be used throughout the administrative 
+  *and political structure of PASOK by staff, volunteers, party members 
+  *and elected officials (all of whom possess varying degrees of ICT skills).
+  *
+  *The PASOK ICT team and the volunteers who worked on this project are 
+  *now returning the translated interface to the Open-Source Community 
+  *with over 98% of the messages translated into user-friendly Greek.
+  *
+  *We hope that it will be used as a tool by other civil society organizations
+  *in Greece, and that it will enhance the collective creation and the dissemination 
+  *of knowledge - an essential component of the democratic process.
+  *
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+/** */
+require_once( 'LanguageUtf8.php' );
+
+$wgNamespaceNamesEl = array(
+       NS_MEDIA            => 'Μέσον',
+       NS_SPECIAL          => 'Special',
+       NS_MAIN             => '',
+       NS_TALK             => 'Συζήτηση',
+       NS_USER             => 'Χρήστης',
+       NS_USER_TALK        => 'Συζήτηση_χρηστών',
+       NS_PROJECT          => $wgMetaNamespace,
+       NS_PROJECT_TALK     => $wgMetaNamespace . '_συζήτηση',
+       NS_IMAGE            => 'Εικόνες',
+       NS_IMAGE_TALK       => 'Συζήτηση_εικόνων',
+       NS_MEDIAWIKI        => 'MediaWiki',
+       NS_MEDIAWIKI_TALK   => 'MediaWiki_talk',
+       NS_TEMPLATE         => 'Πρότυπο',
+       NS_TEMPLATE_TALK    => 'Συζήτηση_προτύπων',
+       NS_HELP             => 'Βοήθεια',
+       NS_HELP_TALK        => 'Συζήτηση_βοήθειας',
+       NS_CATEGORY         => 'Κατηγορία',
+       NS_CATEGORY_TALK    => 'Συζήτηση_κατηγοριών',
+) + $wgNamespaceNamesEn;
+
+$wgAllMessagesEl = array(
+
+# User preference toggles
+#----------------------------------------#
+'tog-underline' => 'Υπογράμμιση συνδέσμων',
+'tog-highlightbroken' => 'Κατεστραμένοι σύνδεσμοι μορφοποίησης <a href="" class="new">όπως αυτός</a> (εναλλακτικά: όπως αυτός<a href="" class="internal">?</a>).',
+'tog-justify' => 'Στοίχιση παραγράφων',
+'tog-hideminor' => 'Απόκρυψη αλλαγών μικρής κλίμακας',
+'tog-usenewrc' => 'Ανάδειξη πρόσφατων αλλαγών (δεν λειτουργεί σε όλους τους browser)',
+'tog-numberheadings' => 'Αυτόματη αρίθμιση τίτλων',
+'tog-showtoolbar' => 'Εμφάνιση μπάρας εργαλείων επεξεργασίας',
+'tog-editondblclick' => 'Επεξεργασία σελίδων με διπλό κλικ (JavaScript)',
+'tog-editsection' => 'Ενεργοποίηση επεξεργασίας τμημάτων μέσω των συνδέσμων [επεξεργασία]',
+'tog-editsectiononrightclick' => 'Ενεργοποίηση επεξεργασίας τμήματος με δεξύ κλικ<br /> στους τίτλους των τμημάτων (JavaScript)',
+'tog-showtoc' => 'Εμφάνιση πίνακα περιεχομένων <br />(για σελίδες με περισσότερες από τρεις κεφαλίδες)',
+'tog-rememberpassword' => 'Διατήρηση του κωδικού πρόσβασης σε αυτό τον υπολογιστή',
+'tog-editwidth' => 'Πλαίσιο επεξεργασίας στο μέγιστο πλάτος',
+'tog-watchdefault' => 'Προσθήκη των σελίδων που επεξεργάζεστε στη λίστα παρακολούθησης.',
+'tog-minordefault' => 'Προκαθορίστε να χαρακτηρίζονται όλες οι αλλαγές "μικρής κλίμακας".',
+'tog-previewontop' => 'Εμφάνιση προεπισκόπησης πριν από το πλαίσο επεξεργασίας και όχι μετά',
+'tog-previewonfirst' => 'Εμφάνιση προεπισκόπησης κατά την πρώτη επεξεργασία',
+'tog-nocache' => 'Απενεργοποίηση της δυνατότητας δημιουργίας cache των σελίδων',
+'tog-enotifwatchlistpages' => 'Ειδοποίηση με e-mail σχετικά με αλλαγές στις σελίδες που παρακολουθώ.',
+'tog-enotifusertalkpages' => 'Ειδοποίηση με e-mail σχετικά με αλλαγές στη συζήτηση της δικής μου σελίδας χρήστη',
+'tog-enotifminoredits' => 'Ειδοποίηση με e-mail και για τις αλλαγές μικρής κλίμακας σε αυτή τη σελίδα',
+'tog-enotifrevealaddr' => 'Εμφάνιση της ηλεκτρονικής μου διεύθυνσης στις ειδοποιήσεις που μου αποστέλλονται.',
+'tog-shownumberswatching' => 'Εμφάνιση του αριθμού των συνδεδεμένων χρηστών',
+'tog-fancysig' => 'Απλή υπογραφή (χωρίς τη χρήση αυτόματου συνδέσμου)',
+'tog-externaleditor' => 'Εξ αρχής χρήση εξωτερικού επεξεργαστή κειμένου',
+'tog-externaldiff' => 'Εξ αρχής χρήση εξωτερικού λογισμικού αντιπαραβολής (diffing)',
+
+'underline-always' => 'Πάντα',
+'underline-never' => 'Ποτέ',
+'underline-default' => 'Όπως ορίζεται από το browser σας.',
+
+'skinpreview' => '(προεπισκόπηση)',
+
+#Months
+#-----------#
+'jan' => 'Ιαν',
+'january' => 'Ιανουαρίου',
+'feb' => 'Φεβρ',
+'february' => 'Φεβρουαρίου',
+'mar' => 'Μαρτ',
+'march' => 'Μαρτίου',
+'apr' => 'Απρ',
+'april' => 'Απριλίου',
+'may' => 'Μαΐου',
+'may_long' => 'Μαΐου',
+'jun' => 'Ιουν',
+'june' => 'Ιουνίου',
+'jul' => 'Ιουλ',
+'july' => 'Ιουλίου',
+'aug' => 'Αυγ',
+'august' => 'Αυγούστου',
+'sep' => 'Σεπτ',
+'september' => 'Σεπτεμβρίου',
+'oct' => 'Οκτ',
+'october' => 'Οκτωβρίου',
+'nov' => 'Νοε',
+'november' => 'Νοεμβρίου',
+'dec' => 'Δεκ',
+'december' => 'Δεκεμβρίου',
+
+#Days
+#-------#
+'sunday' => 'Κυριακή',
+'monday' => 'Δευτέρα',
+'tuesday' => 'Τρίτη',
+'wednesday' => 'Τετάρτη',
+'thursday' => 'Πέμπτη',
+'friday' => 'Παρασκευή',
+'saturday' => 'Σαββάτο',
+
+
+# Bits of text used by many pages:
+#----------------------------------------------------#
+'categories' => 'Κατηγορίες',
+'category' => 'κατηγορία',
+'category_header' => 'Άρθρα στην κατηγορία "$1"',
+'subcategories' => 'Υποκατηγορίες',
+
+'linktrail' => '/^([a-z]+)(.*)$/sD',
+'linkprefix' => '/^(.*?)([a-zA-Z\x80-\xff]+)$/sD',
+'mainpage' => 'Αρχική σελίδα',
+'mainpagetext' => 'To λογισμικό Wiki εγκαταστάθηκε επιτυχώς.',
+
+'mainpagedocfooter' => 'Περισσότερες πληροφορίες σχετικά με τη χρήση και με τη ρύθμιση παραμέτρων θα βρείτε στους συνδέσμους: [http://meta.wikipedia.org/wiki/MediaWiki_i18n Οδηγίες για τροποποίηση του περιβάλλοντος εργασίας] και [http://meta.wikipedia.org/wiki/MediaWiki_User%27s_Guide Εγχειρίδιο χρήστη].',
+
+'portal' => 'Ο ιστοχώρος της κοινότητας',
+'portal-url' => '{{ns:4}}:Ο_ιστοχώρος_της_κοινότητας',
+'about' => 'Σχετικά με',
+'aboutsite' => 'Σχετικά με το {{SITENAME}}',
+'aboutpage' => '{{ns:4}}:Σχετικά με',
+'article' => 'Σελίδα κειμένου (ή άλλου περιεχομένου)',
+'help' => 'Βοήθεια',
+'helppage' => '{{ns:12}}:Περιεχόμενα',
+#'wikititlesuffix' => '{{SITENAME}}',
+'bugreports' => 'Αναφορές σφαλμάτων',
+'bugreportspage' => '{{ns:4}}:Αναφορά_σφάλματος',
+'sitesupport' => 'Υποστήριξη ιστοχώρου',
+'sitesupport-url' => '{{ns:4}}:Υποστήριξη_ιστοχώρου',
+'faq' => 'Συνήθεις ερωτήσεις (FAQ)',
+'faqpage' => '{{ns:12}}:Συνήθεις ερωτήσεις (FAQ)',
+'edithelp' => 'Βοήθεια σχετικά με την επεξεργασία',
+'newwindow' => '(ανοίγει σε ξεχωριστό παράθυρο)',
+'edithelppage' => '{{ns:12}}:Επεξεργασία',
+'cancel' => 'Ακύρωση',
+'qbfind' => 'Εύρεση',
+'qbbrowse' => 'Περιήγηση',
+'qbedit' => 'Επεξεργασία',
+'qbpageoptions' => 'Αυτή η σελίδα',
+'qbpageinfo' => 'Συμφραζόμενα',
+'qbmyoptions' => 'Οι σελίδες μου',
+'qbspecialpages' => 'Σελίδες λειτουργιών',
+'moredotdotdot' => 'Περισσότερα...',
+'mypage' => 'Η σελίδα μου',
+'mytalk' => 'Οι συζητήσεις μου',
+'anontalk' => 'Οι συζητήσεις αυτής της διεύθυνσης IP',
+'navigation' => 'Πλοήγηση',
+
+
+# Metadata in edit box
+#---------------------------------#
+'metadata' => '<b>Μεταδεδομένα</b> (επεξήγηση στο σύνδεσμο <a href="$1">here</a>)',
+'metadata_page' => '{{ns:project}}:Μεταδεδομένα',
+
+'currentevents' => 'Τρέχοντα γεγονότα',
+'currentevents-url' => 'Τρέχοντα γεγονότα',
+
+'disclaimers' => 'Αποποίηση ευθυνών',
+'disclaimerpage' => '{{ns:4}}:Αποποίηση_ευθύνης',
+
+'errorpagetitle' => 'Σφάλμα',
+'returnto' => 'Επιστροφή στη σελίδα $1.',
+'tagline' => 'Από {{SITENAME}}',
+'whatlinkshere' => 'Αναφορές στη σελίδα',
+'help' => 'Βοήθεια',
+'search' => 'Αναζήτηση',
+'go' => 'Μετάβαση',
+'history_short' => 'Ιστορικό',
+'info_short' => 'Πληροφορίες',
+'printableversion' => 'Εκτυπώσιμη έκδοση',
+'print' => 'Εκτύπωση',
+'edit' => 'Επεξεργασία',
+'editthispage' => 'Επεξεργασία αυτής της σελίδας',
+'delete' => 'Διαγραφή',
+'deletethispage' => 'Διαγραφή αυτής της σελίδας',
+'undelete_short1' => 'Να αναστραφεί η διαγραφή μίας επεξεργασίας.',
+'undelete_short' => 'Να αναστραφεί η διαγραφή $1 επεξεργασιών.',
+'protect' => 'Προστασία',
+'protectthispage' => 'Κλείδωμα της σελίδας',
+'unprotect' => 'Άρση προστασίας',
+'unprotectthispage' => 'Άρση προστασίας αυτής της σελίδας',
+'newpage' => 'Νέα σελίδα',
+'talkpage' => 'Συζήτηση για αυτή τη σελίδα',
+'specialpage' => 'Σελίδα λειτουργιών',
+'personaltools' => 'Προσωπικά εργαλεία',
+'postcomment' => 'Καταχωρίστε ένα σχόλιο.',
+'addsection' => '+',
+'articlepage' => 'Εμφάνιση σελίδας κειμένου',
+'subjectpage' => 'Εμφάνιση θέματος',
+'talk' => 'Συζήτηση',
+'views' => 'Εμφανίσεις',
+'toolbox' => 'Εργαλεία',
+'userpage' => 'Εμφάνιση σελίδας χρήστη',
+'wikipediapage' => 'Εμφάνιση σελίδας βοήθειας',
+'imagepage' => 'Εμφάνιση σελίδας εικόνων',
+'viewtalkpage' => 'Εμφάνιση συζήτησης',
+'otherlanguages' => 'Άλλες γλώσσες',
+'redirectedfrom' => '(Ανακατεύθυνση από $1)',
+'lastmodified' => 'Η σελίδα αυτή τροποποιήθηκε τελευταία φορά στις $1.',
+'viewcount' => 'Αυτή η σελίδα έχει προσπελαστεί $1 φορές.',
+'copyright' => 'Το περιεχόμενο είναι διαθέσιμο σύμφωνα με την $1.',
+'poweredby' => 'Το {{SITENAME}} χρησιμοποιεί [http://www.mediawiki.org/|MediaWiki] -μια μηχανή Wiki ανοιχτού λογισμικού.',
+'printsubtitle' => '(Προέλευση {{SERVER}})',
+'protectedpage' => 'Κλειδωμένη σελίδα',
+'administrators' => '{{ns:4}}:Διαχειριστές',
+
+'sysoptitle' => 'Απαιτείται η πρόσβαση διαχειριστή.',
+'sysoptext' => 'Το αίτημά σας αφορά σε ενέργεια 
+
+που εκτελείται μόνον από διαχειριστές
+(βλ.$1).',
+'developertitle' => 'Απαιτείται η πρόσβαση των προγραμματιστών.',
+'developertext' => 'Η ενέργεια αυτή μπορεί να εκτελείται μόνον από τους προγραμματιστές (βλ. $1).',
+'badaccess' => 'Ακατάλληλη άδεια',
+
+'badaccesstext' => 'Η ενέργεια που ζητήσατε μπορεί να εκτελεσθεί μόνον από χρήστες στους οποίους έχει δοθεί άδεια "$2".
+Βλ. $1.',
+
+'versionrequired' => 'Απαιτείται η έκδοση $1 του MediaWiki.',
+'versionrequiredtext' => 'Για να χρησιμοποιήσετε αυτή τη σελίδα απαιτείται η έκδοση $1 του MediaWiki . Βλ. [[Special:Έκδοση]]',
+'nbytes' => '$1 bytes',
+#'ok' => 'OK',
+'sitetitle' => '{{SITENAME}}',
+'pagetitle' => "$1 - {{SITENAME}}",
+#'sitesubtitle'        => 'The Free Encyclopedia', # FIXME
+'retrievedfrom' => 'Ανακτήθηκε από το "$1".',
+'newmessages' => 'Έχετε $1.',
+'newmessageslink' => 'νέο μήνυμα',
+'editsection' => 'επεξεργασία',
+'toc' => 'Πίνακας περιεχομένων',
+'showtoc' => 'εμφάνιση',
+'hidetoc' => 'απόκρυψη',
+'thisisdeleted' => 'Εμφάνιση ή αποκατάσταση της $1;',
+'restorelink' => '$1 επεξεργασίες έχουν διαγραφεί.',
+'feedlinks' => 'Ροή δεδομένων:',
+#'sitenotice' => '-', # the equivalent to wgSiteNotice
+
+
+# Short words for each namespace, by default used in the 'article' tab in monobook
+#---------------------------------------------------------------------------------------------------------------------------------#
+'nstab-main' => 'Άρθρο',
+'nstab-user' => 'Σελίδα χρήστη',
+'nstab-media' => 'Ηλεκτρονικά μέσα',
+'nstab-special' => 'Σελίδα λειτουργιών',
+'nstab-wp' => 'Σχετικά με',
+'nstab-image' => 'Εικόνα',
+'nstab-mediawiki' => 'Μήνυμα',
+'nstab-template' => 'Πρότυπο',
+'nstab-help' => 'Βοήθεια',
+'nstab-category' => 'Κατηγορία',
+
+# Main script and global functions
+#--------------------------------------------------#
+'nosuchaction' => 'Δεν υπάρχει τέτοια ενέργεια.',
+'nosuchactiontext' => 'Η ενέργεια που καθορίστηκε από την διεύθυνση URL δεν αναγνωρίζεται από το Wiki.',
+'nosuchspecialpage' => 'Δεν υπάρχει τέτοια σελίδα λειτουργιών.',
+'nospecialpagetext' => 'Έχετε ζητήσει μια ειδική σελίδα που δεν αναγνωρίζεται από το Wiki.',
+
+# General errors
+#------------------------#
+'error' => 'Σφάλμα',
+'databaseerror' => 'Σφάλμα στη βάση δεδομένων',
+
+'dberrortext' => 'Σημειώθηκε συντακτικό σφάλμα σε αίτημα προς τη βάση δεδομένων. Πιθανόν να πρόκειται για ένδειξη σφάλματος στο λογισμικό. Το τελευταίο αίτημα προς τη βάση δεδομένων που επιχειρήθηκε ήταν: <blockquote><tt>$1</tt></blockquote> μέσα από τη λειτουργία "<tt>$2</tt>".  Το MySQL επέστρεψε σφάλμα "<tt>$3: $4</tt>".',
+
+'dberrortextcl' => 'Σημειώθηκε συντακτικό σφάλμα σε αίτημα προς τη βάση δεδομένων. Το τελευταίο αίτημα που επιχειρήθηκε ήταν: "$1" μέσα από τη λειτουργία "$2". Το MySQL επέστρεψε σφάλμα "$3: $4".',
+'noconnect' => 'Λυπούμαστε! Λόγω τεχνικών δυσκολιών το Wiki δεν μπορεί να επικοινωνήσει με τον server της βάσης δεδομένων. <br />
+
+$1',
+
+'nodb' => 'Αδύνατη η επιλογή της βάσης δεδομένων $1',
+'cachederror' => 'Το ακόλουθο κείμενο προέρχεται από το προσωρινό αρχείο (cache) και πιθανόν να μην περιέχει τις πιο πρόσφατες αλλαγές.',
+'laggedslavemode' => 'Προειδοποίηση: Η σελίδα μπορεί να μην έχει ενημερωθεί με τις πρόσφατες αλλαγές.<br/>',
+'readonly' => 'Κλειδωμένη βάση δεδομένων',
+'enterlockreason' => 'Εξηγήστε τους λόγους για το κλείδωμα και το πότε, κατά την εκτίμησή σας, το κλείδωμα αυτό θα αναιρεθεί.',
+
+'readonlytext' => 'Η βάση δεδομένων είναι προσωρινά κλειδωμένη και δεν μπορεί να δεχθεί νέα λήμματα και άλλες τροποποιήσεις -πιθανότατα λόγω συντήρησης. Μετά τη συντήρηση θα επανέλθει σε κανονική λειτουργία.  Η αιτιολογία για το κλείδωμα της βάσης δεδομένων ήταν η εξής: <p>$1',
+
+'missingarticle' => 'Η βάση δεδομένων δεν βρήκε το αναμενόμενο περιεχόμενο σελίδας κάτω από το όνομα "$1".
+
+<p> Αυτό συμβαίνει όταν ακολουθούμε συνδέσμους μιας παλιάς \'αντιπαραβολής\' ή \'ίστορικού\' σε σελίδες που έχουν διαγραφεί. Αν δεν πρόκειται για τέτοια περίπτωση, είναι πιθανόν να υπάρχει σφάλμα στο λογισμικό. Σας παρακαλούμε να το αναφέρετε στους διαχειριστές, παραπέμποντας στο συγκεκριμένο URL.',
+
+'readonly_lag' => 'Η βάση δεδομένων έχει κλειδωθεί αυτόματα για να μπορέσουν οι επιμέρους servers των αντιγράφων της βάσης δεδομένων (slaves) να καλύψουν τη διαφορά με τον κεντρικό server του πρωτοτύπου της βάσης (master).',
+
+'internalerror' => 'Εσωτερικό σφάλμα',
+'filecopyerror' => 'Δεν ήταν δυνατή η αντιγραφή του αρχείου "$1" στο "$2".',
+'filerenameerror' => 'Δεν είναι δυνατή η μετονομασία του αρχείου "$1" σε "$2".',
+'filedeleteerror' => 'Δεν ήταν δυνατή η διαγραφή του αρχείου "$1".',
+'filenotfound' => 'Δεν είναι δυνατή η ανεύρεση του αρχείου "$1".',
+'unexpected' => 'Μη προσδοκώμενη τιμή: "$1"="$2"',
+'formerror' => 'Λάθος: Δεν ολοκληρώθηκε η υποβολή της φόρμας!',
+'badarticleerror' => 'Η ενέργεια αυτή δεν μπορεί να εκτελεσθεί στη συγκεκριμένη σελίδα.',
+'cannotdelete' => 'Αδύνατη η διαγραφή της συγκεκριμένης σελίδας ή εικόνας (Ενδεχομένως να έχει ήδη διαγραφεί από άλλο χρήστη.)',
+'badtitle' => 'Ακατάλληλος τίτλος',
+'badtitletext' => 'Ο τίτλος της σελίδας που ζητήσατε είναι άκυρος ή κενός ή πρόκειται για έναν εσφαλμένα συνδεδεμένο διαγλωσσικό τίτλο (ή εσφαλμένα συνδεδεμένο τίτλο ανάμεσα σε διαφορετικά Wiki).',
+'perfdisabled' => 'Λυπούμαστε! Αυτή η λειτουργία έχει προσωρινά απενεργοποιηθεί επειδή επιβραδύνει τη βάση δεδομένων σε βαθμό που κανένας χρήστης δεν μπορεί να χρησιμοποιήσει το Wiki.',
+'perfdisabledsub' => 'Αυτό είναι ένα αποθηκευμένο αντίγραφο της $1:',
+'perfcached' => 'Τα δεδομένα που ακολουθούν είναι cached και είνα πιθανόν να μην είναι πλήρως ενημερωμένα:',
+
+'wrong_wfQuery_params' => 'Λανθανσμένες παράμετροι στο wfQuery()<br />
+Λειτουργία: $1<br />
+Αίτημα: $2',
+
+'viewsource' => 'Εμφάνιση κώδικα',
+
+'protectedtext' => 'Η σελίδα αυτή είναι κλειδωμένη και δεν είναι δυνατή η επεξεργασία της. Για περισσότερες πληροφορίες σχετικά με τους λόγους για τους οποίους προστατεύεται η σελίδα, παρακαλούμε επισκεφθείτε το σύνδεσμο 
+[[{{ns:4}}:Κλειδωμένες_σελίδες]].
+
+Μπορείτε να δείτε και να αντιγράψετε τον πηγαίο κώδικα αυτής σελίδας:',
+
+'sqlhidden' => '(το αίτημα SQL δεν εμφανίζεται)',
+
+
+# Login and logout pages
+#-------------------------------------#
+'logouttitle' => 'Έξοδος χρήστη',
+'logouttext' => 'Έχετε αποσυνδεθεί.
+Μπορείτε να παραμείνετε στο {{SITENAME}} ανώνυμα, ή μπορείτε να συνδεθείτε ξανά με το ίδιο ή με διαφορετικό (εάν έχετε) όνομα χρήστη. Έχετε υπ\' όψη σας πως αρκετές σελίδες θα συνεχίσουν να εμφανίζονται κανονικά, σαν να μην έχετε αποσυνδεθεί, μέχρι να καθαρίσετε το cache του browser σας.',
+
+'welcomecreation' => '== Καλώς ήλθατε, $1! ==
+
+Ο λογαριασμός σας έχει δημιουργθεί. Μπορείτε να εξατομικεύσετε το {{SITENAME}} σύμφωνα με τις ανάγκες σας μέσα από το σύνδεσμο [[Special:Preferences|Προτιμήσεις]].',
+
+'loginpagetitle' => 'Είσοδος χρήστη',
+'yourname' => 'Όνομα χρήστη',
+'yourpassword' => 'Κωδικός',
+'yourpasswordagain' => 'Πληκτρολογήστε ξανά τον κωδικό',
+'newusersonly' => '(μόνον νέοι χρήστες)',
+'remembermypassword' => 'Διατήρηση του κωδικού πρόσβασης σε αυτόν τον υπολογιστή',
+#'yourdomainname' => 'Your domain',
+'externaldberror' => 'Συνέβη εξωτερικό σφάλμα πιστοποίησης στη βάση δεδομένων ή δεν σας έχει επιτραπεί να ενημερώσετε τον εξωτερικό σας λογαριασμό.',
+'loginproblem' => '<b>Εμφανίστηκε πρόβλημα κατά την είσοδό σας.</b><br />Παρακαλούμε δοκιμάστε ξανά!',
+'alreadyloggedin' => '<font color=red><b>Ο χρήστης $1, είναι ήδη συνδεδεμένος!</b></font><br />',
+'login' => 'Είσοδος',
+'loginprompt' => 'Πρέπει να έχετε ενεργοποιήσει τα cookies για να συνδεθείτε στο {{SITENAME}}.',
+'userlogin' => 'Δημιουργία Λογαριασμού/Είσοδος',
+'logout' => 'Έξοδος',
+'userlogout' => 'Έξοδος χρήστη',
+'notloggedin' => 'Δεν έχετε συνδεθεί.',
+'createaccount' => 'Δημιουργία νέου λογαριασμού',
+'createaccountmail' => 'Με ηλεκτρονικό ταχυδρομείο',
+'badretype' => 'Οι κωδικοί που έχετε δηλώσει δεν συμφωνούν μεταξύ τους.',
+'userexists' => 'Το όνομα χρήστη που συμπληρώσατε είναι ήδη σε χρήση. Παρακαλούμε διαλέξτε ένα άλλο όνομα.',
+'youremail' => 'Ηλεκτρονική διεύθυνση*',
+'yourrealname' => 'Όνομα και επώνυμο*',
+'yourlanguage' => 'Γλώσσα διασύνδεσης',
+'yourvariant' => 'Η γλώσσα που χρησιμοποιείτε',
+'yournick' => 'Το ψευδώνυμό σας (για την υπογραφή)',
+'email' => 'αλληλογραφία',
+
+'emailforlost' => 'Τα πεδία που σημειώνονται με αστερίσκο (*) είναι προαιρετικά. Αφήνοντας μια ηλεκτρονική διεύθυνση στο αρχείο δίνετε τη δυνατότητα σε άλλους χρήστες να επικοινωνήσουν μαζί σας μέσω αυτής της ιστοσελίδας, χωρίς η διεύθυνσή σας να εμφανίζεται δημόσια. Η ηλεκτρονική σας διεύθυνση μπορεί επίσης να χρησιμοποιηθεί για να σας σταλεί ένας νέος κωδικός πρόσβασης αν κάποτε τον χάσετε. Το πραγματικό σας όνομα, αν επιλέξετε να μας το δώσετε, θα χρησιμοποιηθεί μόνον για την αναγνώριση της συνεισφοράς σας.',
+
+'prefs-help-email-enotif' => 'Αυτή η διεύθυνση χρησιμοποιείται για να σας αποστέλλονται ειδοποιήσεις εφόσον έχετε ενεργοποιήσει τις σχετικές επιλογές.',
+'prefs-help-realname' => '* Πραγματικό όνομα (προαιρετικό): εφόσον εισάγετε το όνομά σας, αυτό θα μπορεί να χρησιμοποιηθεί για να αναγνωριστεί ευρύτερα η δουλειά σας.',
+'loginerror' => 'Λάθος σύνδεσης',
+
+'prefs-help-email' => '* Email (προαιρετικό): Δίνει τη δυνατότητα σε άλλους χρήστες να επικοινωνήσουν μαζί σας μέσω της σελίδας χρήστη (ή της συζήτησης για την σελίδα χρήστη) χωρίς να εμφανίζεται η ταυτότητά σας.',
+
+'nocookiesnew' => 'Ο λογαριασμός χρήστη έχει δημιουργηθεί, αλλά δεν έχετε ακόμα συνδεθεί. Το {{SITENAME}} χρησιμοποιεί cookies κατά τη σύνδεση των χρηστών. Τα cookies είναι απενεργοποιημένα στον υπολογιστή σας. Παρακαλούμε ενεργοποιήστε τα και στη συνέχεια συνδεθείτε χρησιμοποιώντας το νέο όνομα χρήστη σας και τον κωδικό σας.',
+
+'nocookieslogin' => 'Το {{SITENAME}} χρησιμοποιεί cookies κατά τη σύνδεση των χρηστών. Τα cookies είναι απενεργοποιημένα στον υπολογιστή σας. Παρακαλούμε ενεργοποιήστε τα και ξαναδοκιμάστε!',
+'noname' => 'Το όνομα χρήστη που έχετε καθορίσει δεν είναι έγκυρο.',
+'loginsuccesstitle' => 'Επιτυχής σύνδεση',
+'loginsuccess' => 'Είστε συνδεδεμένος(-η) στο {{SITENAME}} ως "$1".',
+
+'nosuchuser' => 'Δεν υπάρχει χρήστης με το όνομα "$1".
+Ελέγξτε την ορθογραφία ή χρησιμοποιείστε την παρακάτω φόρμα για να δημιουργήσετε ένα νέο λογαριασμό.',
+
+'nosuchusershort' => 'Δεν υπάρχει χρήστης με το όνομα "$1". Παρακαλούμε ελέγξτε την ορθογραφία.',
+'wrongpassword' => 'Ο κωδικός που πληκτρολογήσατε είναι λανθασμένος. Παρακαλούμε προσπαθήστε ξανά.',
+'mailmypassword' => 'Στείλτε μου ένα νέο κωδικό.',
+'passwordremindertitle' => 'Υπενθύμιση κωδικού από το {{SITENAME}}',
+
+'passwordremindertext' => 'Κάποιος (πιθανώς εσείς) με διεύθυνση IP $1, ζήτησε να σας στείλουμε ένα νέο κωδικό πρόσβασης στο {{SITENAME}}. Ο κωδικός πρόσβασης για το χρήστη "$2" είναι αυτή τη στιγμή "$3". Συνιστούμε να συνδεθείτε και να αλλάξετε αυτόν τον κωδικό το συντομότερο δυνατόν.',
+
+'noemail' => 'Δεν υπάρχει ηλεκτρονική διεύθυνση για το χρήστη "$1".',
+
+'passwordsent' => 'Σας έχει σταλεί ένας νέος κωδικός στην ηλεκτρονική διέθυνση που δηλώσατε για "$1".
+Σας παρακαλούμε να ξανασυνδεθείτε μόλις τον λάβετε.',
+
+'eauthentsent' => 'Ένα μήνυμα επαλήθευσης έχει σταλεί στην ηλεκτρονική διεύθυνση που έχετε δηλώσει στο σύστημα. Πριν αρχίσει η αποστολή μηνυμάτων στη συγκεκριμένη διεύθυνση, πρέπει να ακολουθήσετε τις οδηγίες που βρίσκονται στο μήνυμα που σας έχει σταλεί για να επαληθεύσετε ότι η συγκεκριμένη ηλεκτρονική διεύθυνση ανήκει πραγματικά σε εσάς. ',
+
+'loginend' => '&nbsp;',
+'mailerror' => 'Λάθος στην αποστολή του μηνύματος: $1',
+'acct_creation_throttle_hit' => 'Λυπούμαστε, έχετε ήδη δημιουργήσει $1 λογαριασμούς και δεν μπορείτε να δημιουργήσετε άλλους.',
+'emailauthenticated' => 'Η ηλεκτρονική σας διεύθυνση επιβεβαιώθηκε στις $1.',
+
+'emailnotauthenticated' => 'Η ηλεκτρονική σας διεύθυνση δεν έχει επαληθευθεί ακόμα. Μέχρι να ολοκληρώσετε την επαλήθευση της διεύθυνσής σας, δεν είναι δυνατόν το σύστημα να σας αποστείλει αλληλογραφία για καμμία από τις ακόλουθες λειτορυγίες.',
+
+'noemailprefs' => '<strong>Δεν έχει ορισθεί ηλεκτρονική διέυθυνση</strong>, οι λειτουργίες που ακολουθούν δεν θα είναι δυνατόν να ολοκληρωθούν.',
+'emailconfirmlink' => 'Επαληθεύστε την ηλεκτρονική σας διεύθυνση',
+'invalidemailaddress' => 'Η ηλεκτρονική διεύθυνση δεν έγινε δεκτή γιατί ενδεχομένως δεν είχε έγκυρη μορφή. Παρακαλούμε συμπληρώστε μια σωστά διαμορφωμένη διεύθυνση ή αφήστε το πεδίο κενό.',
+
+
+# Edit page toolbar
+#----------------------------#
+'bold_sample' => 'Έντονο κείμενο',
+'bold_tip' => 'Έντονο κείμενο',
+
+'italic_sample' => 'Κείμενο με πλάγιους χαρακτήρες',
+'italic_tip' => 'Κείμενο με πλάγιους χαρακτήρες',
+
+'link_sample' => 'Τίτλος συνδέσμου',
+'link_tip' => 'Εσωτερικός σύνδεσμος',
+
+'extlink_sample' => 'http://www.paradeigma.com τίτλος συνδέσμου',
+'extlink_tip' => 'Εξωτερικός σύνδεσμος (μην ξεχάστε το πρόθεμα http:// )',
+
+'headline_sample' => 'Κείμενο τίτλου',
+'headline_tip' => 'Δεύτερος τίτλος (επίπεδο 2)',
+
+'math_sample' => 'Εισαγωγή τύπου εδώ',
+'math_tip' => 'Μαθηματικός τύπος (LaTeX)',
+
+'nowiki_sample' => 'Εισάγετε εδώ το μη μορφοποιημένο κείμενο.',
+'nowiki_tip' => 'Να αγνοηθεί η μορφοποίηση Wiki.',
+
+'image_sample' => 'paradeigma.jpg',
+'image_tip' => 'Ενσωματωμένη εικόνα',
+
+'media_sample' => 'paradeigma.mp3',
+'media_tip' => 'Σύνδεσμος αρχείου πολυμέσων',
+
+'sig_tip' => 'Υπογραφή με ημερομηνία',
+'hr_tip' => 'Οριζόντια γραμμή (να χρησιμοποιείται με μέτρο!)',
+
+'infobox' => 'Πατήσετε κάποιο κουμπί για να δείτε ένα παράδειγμα κειμένου',
+# alert box shown in browsers where text selection does not work, test e.g. with mozilla or konqueror
+'infobox_alert' => 'Παρακαλούμε εισάγετε το κείμενο που θέλετε να μορφοποιήσετε.
+ Θα εμφανιστεί στο πλαίσιο για αντιγραφή και επικόλληση.
+Παράδειγμα:
+Το $1
+θα γίνει:
+$2',
+
+
+# Edit pages
+#-----------------#
+'summary' => 'Σύνοψη',
+'subject' => 'Θέμα/επικεφαλίδα',
+'minoredit' => 'Αλλαγή μικρής κλίμακας',
+'watchthis' => 'Παρακολούθηση αυτής της σελίδας',
+'savearticle' => 'Αποθήκευση σελίδας',
+'preview' => 'Προεπισκόπηση',
+'showpreview' => 'Προεπισκόπηση',
+'showdiff' => 'Δείτε τις αλλαγές',
+'blockedtitle' => 'Ο χρήστης έχει υποστεί φραγή.',
+
+'blockedtext' => 'Το όνομα χρήστη ή η διεύθυνση IP σας έχει υποστεί φραγή από τον/την $1 με την αιτιολογία :<br />\'\'$2\'\'<p> Μπορείτε να απευθυνθείτε στον/στην $1 ή σε κάποιον άλλον από τους [[{{ns:4}}:Διαχειριστές |διαχειριστές]] για να συζητήσετε το πρόβλημα.
+
+Έχετε υπ\' όψη σας ότι δεν μπορείτε να χρησιμοποιήσετε τη δυνατότητα "αποστολή e-mail σε χρήστη" εκτός αν έχετε μια έγκυρη διεύθυνση e-mail δηλωμένη στις [[Special:Preferences|Προτιμήσεις χρήστη]].
+
+<br>
+<br>Η διεύθυνση IP σας είναι: $3. Παρακαλούμε να την αναφέρετε σε κάθε σας αίτημα.',
+
+'whitelistedittitle' => 'Για να επεξεργαστείτε μια σελίδα πρέπει πρώτα να συνδεθείτε.',
+'whitelistedittext' => 'Πρέπει να [[Special:Userlogin|συνδεθείτε]] για να επεξεργαστείτε μια σελίδα.',
+'whitelistreadtitle' => 'Για να διαβάσετε πρέπει πρώτα να συνδεθείτε.',
+'whitelistreadtext' => 'Πρέπει να [[Special:Userlogin|συνδεθείτε]] για να διαβάσετε σελίδες.',
+'whitelistacctitle' => 'Δεν έχετε το δικαίωμα να δημιουργήσετε λογαριασμό.',
+'whitelistacctext' => 'Για να σας επιτραπεί η δημιουργία λογαριασμού σε αυτό το Wiki πρέπει να [[Special:Userlogin|συνδεθείτε]] και να κατέχετε την κατάλληλη άδεια.',
+'loginreqtitle' => 'Απαιτείται η σύνδεση του χρήστη.',
+'loginreqtext' => 'Πρέπει να [[Special:Userlogin|συνδεθείτε]] για να δείτε άλλες σελίδες.',
+'accmailtitle' => 'Ο κωδικός έχει σταλεί.',
+'accmailtext' => 'Ο κωδικός για τον/την \'$1\' έχει σταλεί στο $2.',
+'newarticle' => '(Νέο)',
+
+'newarticletext' => 'Έχετε ακολουθήσει ένα σύνδεσμο που δεν υπάρχει ακόμα. Για να δημιουργήσετε μια νέα σελίδα εδώ, αρχίστε να γράφετε το κείμενό σας στο πλαίσιο.(Βλ. [[{{ns:12}}:Περιεχόμενα|Σελίδα βοήθειας]] για περισσότερες πληροφορίες).
+Αν έχετε βρεθεί εδώ κατά λάθος, απλώς πατήστε \'\'\'επιστροφή (back)\'\'\' στον browser του υπολογιστή σας.',
+
+#'talkpagetext' => '<!-- MediaWiki:talkpagetext -->',
+
+'anontalkpagetext' => '----\'\'Αυτή η σελίδα συζήτησης προορίζεται για ανώνυμους χρήστες που δεν έχουν δημιουργήσει ακόμα λογαριασμό (ή που δεν τον χρησιμοποιούν). Έτσι για την ταυτοποίηση ενός ανώνυμου χρήστη χρησιμοποιείται η [[{{ns:12}}:διεύθυνση IP  |διεύθυνση IP ]] του. Είναι όμως πιθανόν η διεύθυνση αυτή να είναι κοινή για πολλούς διαφορετικούς χρήστες (όπως π.χ. για τους χρήστες ενός Internet Cafe ή ενός [[{{ns:12}}:proxy server|proxy server]]). Αν είστε ανώνυμος χρήστης και έχετε δεχθεί σχόλια άσχετα με τα θέματά σας (κάτι που μπορεί να συμβεί αν χρησιμοποιείτε την ίδια [[{{ns:12}}:διεύθυνση IP|διεύθυνση IP]] με κάποιον άλλο ανώνυμο χρήστη) θα ήταν καλό να [[Special:Userlogin|δημιουργήσετε ένα λογαριασμό χρήστη ή να συνδεθείτε]] για να αποφεύγεται η σύγχυση\'\'.',
+
+'noarticletext' => '(Δεν υπάρχει κείμενο στη σελίδα)',
+
+'clearyourcache' => '\'\'\'Σημείωση:\'\'\' Μετά την αποθήκευση, θα χρειαστεί να καθαρίσετε  το cache στον browser για να μπορέσετε να δείτε τις αλλαγές: \'\'\'Mozilla:\'\'\' click \'\'Reload\'\' (or \'\'Ctrl-R\'\'), \'\'\'IE / Opera:\'\'\' \'\'Ctrl-F5\'\', \'\'\'Safari:\'\'\' \'\'Cmd-R\'\', \'\'\'Konqueror\'\'\' \'\'Ctrl-R\'\'.<br/>',
+
+'usercssjsyoucanpreview' => '<strong>Χρήσιμη συμβουλή:</strong> Χρησιμοποιήστε το κουμπί "Προεπισκόπηση" για να ελέγξτε τα νέα σας CSS/JS πριν τα αποθηκεύσετε.',
+'usercsspreview' => '\'\'\'Σας υπενθυμίζουμε ότι κάνετε απλώς έλεγχο/προεπισκόπηση του CSS του χρήστη -δεν το έχετε ακόμα αποθηκεύσει! \'\'\'',
+'userjspreview' => '\'\'\'Σας υπενθυμίζουμε ότι κάνετε απλώς έλεγχο/προεπισκόπηση του JavaScript του χρήστη -δεν το έχετε ακόμα αποθηκεύσει!\'\'\'',
+'updated' => '(Ενημερώθηκε.)',
+'note' => '<strong>Προσοχή: </strong>',
+'previewnote' => 'Σας υπενθυμίζουμε ότι βλέπετε μόνον την προεπισκόπηση -δεν έχετε ακόμα αποθηκεύσει τις αλλαγές σας!',
+'previewconflict' => 'Αυτή η προεπισκόπηση απεικονίζει το κείμενο στην επάνω περιοχή επεξεργασίας κειμένου, όπως θα εμφανιστεί εάν επιλέξετε να το αποθηκεύσετε.',
+'editing' => 'Επεξεργασία $1',
+'editingsection' => 'Επεξεργασία $1 (τμήμα)',
+'editingcomment' => 'Επεξεργασία $1 (σχόλια)',
+'editconflict' => 'Ανταγωνιστικές επεξεργασίες: $1',
+
+'explainconflict' => 'Κάποιος άλλος χρήστης έχει αλλάξει αυτή τη σελίδα από τότε που αρχίσατε να την επεξεργάζεστε. Στο επάνω τμήμα βρίσκεται το τρέχον κείμενο της σελίδας. Οι δικές σας αλλαγές εμφανίζονται στο κάτω τμήμα. Θα πρέπει να ενσωματώσετε εσείς τις αλλαγές σας στο τρέχον κείμενο. <b>Μόνον</b> το επάνω τμήμα θα αποθηκευθεί όταν πατήσετε "Αποθήκευση σελίδας".<p>',
+
+'yourtext' => 'Το κείμενό σας',
+'storedversion' => 'Αποθηκευμένη έκδοση',
+
+'nonunicodebrowser' => '<strong>ΠΡΟΣΟΧΗ! Ο browser σας δεν είναι συμβατός με unicode. Παρακαλούμε χρησιμοποιήστε έναν άλλο browser για επεξεργαστείστε αυτό το άρθρο έτσι ώστε να αποδοθούν σωστά όλοι οι ελληνικοί χαρακτήρες. </strong><br/>',
+
+'editingold' => '<strong>ΠΡΟΕΙΔΟΠΟΙΗΣΗ: Επεξεργάζεστε μια παλιότερη αναθεώρηση αυτής της σελίδας. Αν προσπαθείστε να την αποθηκεύσετε, όσες αλλαγές έχουν γίνει πριν από αυτή την αναθεώρηση θα χαθούν.</strong><br/>',
+
+'yourdiff' => 'Διαφορές',
+
+'copyrightwarning' => 'Ολες οι προσθήκες/ αλλαγές στο {{SITENAME}} θα πρέπει να συμφωνούν με την $2 (Βλ. $1 για λεπτομέρειες).
+Αν δεν επιθυμείτε τα κείμενά σας να τα επεξεργαστούν κατά την κρίση τους άλλοι χρήστες και να τα διαδώσουν κατά βούληση παρακαλούμε να μην τα αναρτήσετε σε αυτό το χώρο. Ότι συνεισφέρετε στο χώρο αυτό σε κείμενα, διαγράμματα, στοιχεία ή εικόνες πρέπει να είναι δικά σας έργα ή να ανήκουν στο δημόσιο τομέα (public domain) ή να προέρχονται από ελεύθερες ή ανοιχτές πηγές με ρητή άδεια αναδημοσίευσης. <br />
+
+Τέλος μας υπόσχεστε και δηλώνετε πως ότι γράφετε σε αυτό τον χώρο είναι πρωτότυπο δικό σας έργο και, άσχετα με την έκτασή του, δεν έχει εκχωρηθεί σε τρίτους η δημοσίευση και η εκμετάλλευσή του. 
+<strong>ΠΑΡΑΚΑΛΟΥΜΕ ΝΑ ΜΗΝ ΑΝΑΡΤΗΣΕΤΕ ΚΕΙΜΕΝΑ ΤΡΙΤΩΝ ΕΑΝ ΔΕΝ ΕΧΕΤΕ ΤΗΝ ΑΔΕΙΑ ΤΟΥ ΙΔΙΟΚΤΗΤΗ ΤΟΥ COPYRIGHT!</strong>',
+
+'copyrightwarning2' => 'Έχετε υπ\' όψη σας ότι όλες οι προσθήκες/αλλαγές που κάνετε στο {{SITENAME}} μπορούν να υποστούν επεξεργασία και αλλαγές ή ακόμα και να διαγραφούν από άλλους χρήστες.
+Αν δεν επιθυμείτε τα κείμενά σας να τα επεξεργαστούν κατά την κρίση τους άλλοι χρήστες και να τα διαδώσουν κατά βούληση παρακαλούμε να μην τα αναρτήσετε σε αυτό το χώρο. Ότι συνεισφέρετε στο χώρο αυτό σε κείμενα, διαγράμματα, στοιχεία ή εικόνες πρέπει να είναι δικά σας έργα ή να ανήκουν στο δημόσιο τομέα (public domain) ή να προέρχονται από ελεύθερες ή ανοιχτές πηγές με ρητή άδεια αναδημοσίευσης. <br />
+Τέλος μας υπόσχεστε και δηλώνετε πως ότι γράφετε σε αυτό τον χώρο είναι πρωτότυπο δικό σας έργο και, άσχετα με την έκτασή του, δεν έχει εκχωρηθεί σε τρίτους η δημοσίευση και η εκμετάλλευσή του. 
+<strong>ΠΑΡΑΚΑΛΟΥΜΕ ΝΑ ΜΗΝ ΑΝΑΡΤΗΣΕΤΕ ΚΕΙΜΕΝΑ ΤΡΙΤΩΝ ΕΑΝ ΔΕΝ ΕΧΕΤΕ ΤΗΝ ΑΔΕΙΑ ΤΟΥ ΙΔΙΟΚΤΗΤΗ ΤΟΥ COPYRIGHT!</strong>',
+
+'longpagewarning' => 'ΠΡΟΕΙΔΟΠΟΙΗΣΗ: Η σελίδα έχει μέγεθος $1kb. Είναι πιθανόν μερικοί browser να παρουσιάσουν προβλήματα στην επεξεργασία σελίδων της τάξης των 32kb και άνω. Μπορείτε να αποφύγετε το πρόβλημα κόβωντας τη σελίδα σε μικρότερα τμήματα.<br/>',
+
+'readonlywarning' => 'ΠΡΟΕΙΔΟΠΟΙΗΣΗ: Η βάση δεδομένων έχει κλειδωθεί προσωρινά για συντήρηση και δεν θα μπορέσετε να αποθηκεύσετε αυτά που έχετε επεξεργαστεί.  Μπορείτε αν θέλετε να αποθηκεύσετε το κείμενο στον υπολογιστή σας (με αποκοπή-και-επικόλληση) και να το ξαναχρησιμοποιήσετε αργότερα όταν η συντήρηση θα έχει ολοκληρωθεί.',
+
+'protectedpagewarning' => 'ΠΡΟΕΙΔΟΠΟΙΗΣΗ:  Η σελίδα αυτή έχει κλειδωθεί -η οποιαδήποτε επεξεργασία της μπορεί να γίνει μόνον από διαχειριστές. Βεβαιωθείτε πως ακολουθείτε [[{{ns:4}}:Σελίδες_υπό_προστασία|τους κανόνες για τις υπό προστασία σελίδες]].<br/>',
+
+'templatesused' => 'Πρότυπα που χρησιμοποιήθηκαν στη σελίδα αυτή:',
+
+
+# History pages
+#----------------------#
+'revhistory' => 'Ιστορικό αναθεωρήσεων',
+'nohistory' => 'Δεν υπάρχει ιστορικό επεξεργασίας για αυτή τη σελίδα.',
+'revnotfound' => 'Η αναθεώρηση δεν βρέθηκε.',
+'revnotfoundtext' => 'Η παλιά αναθεώρηση της σελίδας που ζητήσατε δεν ήταν δυνατόν να βρεθεί. Παρακαλούμε ελέγξτε τo URL που χρησιμοποιήσατε για να φτάσετε σε αυτήν τη σελίδα.',
+'loadhist' => 'Φόρτωση ιστορικού σελίδας',
+'currentrev' => 'Τρέχουσα αναθεώρηση',
+'revisionasof' => 'Αναθεώρηση της $1',
+'revisionasofwithlink' => 'Αναθεώρηση της $1; $2<br />$3 | $4',
+'previousrevision' => '&larr;Παλιότερη αναθεώρηση',
+'nextrevision' => 'Νεώτερη αναθεώρηση&rarr;',
+'currentrevisionlink' => 'εμφάνιση της τρέχουσας αναθεώρησης',
+'cur' => 'τρέχουσα',
+'next' => 'επόμενη',
+'last' => 'τελευταία',
+'orig' => '\'πρωτότυπη\'',
+
+'histlegend' => 'Σύγκριση διαφορών: Επιλέξτε τις εκδόσεις που θέλετε να συγκρίνετε και πατήστε enter ή κάντε κλικ στην μπάρα "Σύγκριση...". <br />
+Υπόμνημα: (τρέχον) = διαφορές με την τρέχουσα έκδοση,
+(τελευταίο) = διαφορές με την προηγούμενη έκδοση, μ = αλλαγές μικρής κλίμακας.',
+
+#'history_copyright' => '-',
+'deletedrev' => '[διαγράφτηκε]',
+'histfirst' => 'Η πιο παλιά',
+'histlast' => 'Η πιο πρόσφατη',
+
+
+# Diffs
+#--------#
+'difference' => '(Διαφορές μεταξύ αναθεωρήσεων)',
+'loadingrev' => 'φόρτωση αναθεώρησης για \'σύγκριση\'',
+'lineno' => 'Γραμμή $1:',
+'editcurrent' => 'Επεξεργασία της τρέχουσας έκδοσης της σελίδας',
+'selectnewerversionfordiff' => 'Επιλέξτε μια πιο πρόσφατη έκδοση για σύγκριση.',
+'selectolderversionfordiff' => 'Επιλέξτε μια παλιότερη έκδοση για σύγκριση.',
+'compareselectedversions' => 'Σύγκριση των εκδόσεων που έχουν επιλεγεί',
+
+
+# Search results
+#------------------------#
+'searchresults' => 'Αποτελέσματα αναζήτησης',
+'searchresulttext' => 'Για περισσότερες πληροφορίες σχετικά με την αναζήτηση στο {{SITENAME}}, βλ. [[{{ns:12}}:Αναζήτηση|Αναζήτηση στο {{SITENAME}}]].',
+'searchquery' => 'Κριτήρια αναζήτησης: "$1"',
+'badquery' => 'Λανθασμένη μορφή αιτήματος αναζήτησης',
+
+'badquerytext' => 'Το σύστημα δεν μπόρεσε να επεξεργαστεί το αίτημα σας. Αυτό πιθανόν οφείλεται στο ότι αναζητήσατε μια λέξη με λιγότερα από τρία γράμματα (κάτι που δεν υποστηρίζεται προς το παρόν). Μπορεί επίσης να οφείλεται σε λάθος πληκτρολόγησης π.χ. "Διάλογος και διαλούβευση". Παρακαλoύμε δοκιμάστε πάλι.',
+
+'matchtotals' => 'Το αίτημα "$1" βρήκε $2 παρόμοιους τίτλους σελίδων και παρόμοιο κείμενο σε $3 σελίδες',
+'nogomatch' => 'Δεν υπάρχει καμμία σελίδα με αυτόν ακριβώς τον τίτλο -έγινε αναζήτηση με το πλήρες κείμενο.',
+'titlematches' => 'Τίτλοι άρθρων που ανταποκρίνονται',
+'notitlematches' => 'Δεν υπάρχουν αντίστοιχοι τίτλοι σελίδων.',
+'textmatches' => 'Κείμενα σελίδων που ανταποκρίνονται:',
+'notextmatches' => 'Δεν υπάρχουν αντίστοιχα κείμενα σελίδων.',
+'prevn' => '$1 προηγουμένων',
+'nextn' => '$1 επομένων',
+'viewprevnext' => 'Εμφάνιση ($1) ($2) ($3).',
+'showingresults' => 'Εμφάνιση <b>$1</b> αποτελεσμάτων που αρχίζουν με #<b>$2</b>',
+'showingresultsnum' => 'Εμφάνιση <b>$3</b> αποτελεσμάτων που αρχίζουν με #<b>$2</b>',
+
+'nonefound' => '\'\'\'Σημείωση\'\'\': Οι ανεπιτυχείς αναζητήσεις οφείλονται συνήθως στο ότι έχουμε συμπεριλάβει στα κριτήρια πολύ συνηθισμένες λέξεις, όπως "έχει" ή "από" (που δεν υπάρχουν στο ευρετήριο) ή στο ότι προκαθορίσαμε πολλά κριτήρια αναζήτησης ταυτοχρόνως. (Στην τελευταία περίπτωση, μόνον οι σελίδες που περιέχουν \'\'όλα\'\' τα κριτήρια αναζήτησης θα εμφανιστούν στα αποτελέσματα).<br/>',
+
+'powersearch' => 'Αναζήτηση',
+
+'powersearchtext' => 'Αναζήτηση στις περιοχές :<br />
+
+$1<br />
+$2 Εμφάνιση ανακατευθύνσεων &nbsp; Κριτήρια αναζήτησης $3 $9',
+
+'googlesearch' => '
+<div style="margin-left: 2em">
+
+<!-- Google search -->
+<div style="width:130px;float:left;text-align:center;position:relative;top:-8px"><a href="http://www.google.com/" style="padding:0;background-image:none"><img src="http://www.google.com/logos/Logo_40wht.gif" alt="Google" style="border:none" /></a></div>
+
+<form method="get" action="http://www.google.com/search" style="margin-left:135px">
+  <div>
+    <input type="hidden" name="domains" value="{{SERVER}}" />
+    <input type="hidden" name="num" value="50" />
+
+    <input type="hidden" name="ie" value="$2" />
+    <input type="hidden" name="oe" value="$2" />
+    
+    <input type="text" name="q" size="31" maxlength="255" value="$1" />
+    <input type="submit" name="btnG" value="Google Search" />
+  </div>
+  <div style="font-size:90%">
+    <input type="radio" name="sitesearch" id="gwiki" value="{{SERVER}}" checked="checked" /><label for="gwiki">{{SITENAME}}</label>
+    <input type="radio" name="sitesearch" id="gWWW" value="" /><label for="gWWW">WWW</label>
+
+  </div>
+</form>
+
+</div>',
+'blanknamespace' => '(Αρχική περιοχή)',
+
+
+# Preferences page
+#-----------------------------#
+'preferences' => 'Προτιμήσεις',
+'prefsnologin' => 'Δεν έχετε συνδεθεί.',
+
+'prefsnologintext' => 'Πρέπει να έχετε [[Special:Userlogin|συνδεθεί]]
+για να καθορίσετε τις προτιμήσεις χρήστη.',
+
+'prefslogintext' => 'Έχετε συνδεθεί ως "$1".
+Ο εσωτερικός σας αριθμός ταυτοποίησης (ID) είναι $2.
+
+Στον παρακάτω σύνδεσμο θα βρείτε πληροφορίες για το πώς θα "αποκρυπτογραφήσετε" τις διάφορες επιλογές: 
+[[{{ns:12}}:Προτιμήσεις_Χρηστών]]',
+
+'prefsreset' => 'Οι προτιμήσεις σας έχουν αποκατασταθεί σύμφωνα με την αποθηκευμένη έκδοσή τους.',
+#'qbsettings' => 'Quickbar',
+'changepassword' => 'Αλλαγή κωδικού',
+'skin' => 'Οπτική οργάνωση (skin)',
+'math' => 'Απόδοση μαθηματικών',
+'dateformat' => 'Μορφή ημερομηνίας',
+'math_failure' => 'Δεν μπόρεσε να γίνει ανάλυση του όρου.',
+'math_unknown_error' => 'Άγνωστο λάθος',
+'math_unknown_function' => 'άγνωστη συνάρτηση',
+'math_lexing_error' => 'Σφάλμα στην λεξική ανάλυση',
+'math_syntax_error' => 'Λάθος σύνταξης',
+'math_image_error' => 'Η μετατροπή σε PNG απέτυχε. Παρακαλούμε ελέγξτε ότι έχουν εγκατασταθεί σωστά τα latex, dvips, gs, και ξαναπροσπαθήστε!',
+'math_bad_tmpdir' => 'Δεν είναι δυνατή η δημιουργία μαθηματικών δεδομένων (ή η εγγραφή σε προσωρινό κατάλογο) ',
+'math_bad_output' => 'Δεν είναι δυνατή η δημιουργία  μαθηματικών δεδομένων (ή η εγγραφή σε κατάλογο εξόδου)',
+'math_notexvc' => 'Αγνοείται το εκτελέσιμο texvc -παρακαλούμε συμβουλευτείτε το math/README για να ρυθμίσετε τις παραμέτρους.',
+'prefs-personal' => 'Στοιχεία χρήστη',
+'prefs-rc' => 'Πρόσφατες αλλαγές και εμφάνιση πολύ σύντομων άρθρων',
+'prefs-misc' => 'Διάφορες ρυθμίσεις',
+'saveprefs' => 'Αποθήκευση προτιμήσεων',
+'resetprefs' => 'Επαναφορά προτιμήσεων',
+'oldpassword' => 'Παλιός κωδικός',
+'newpassword' => 'Νέος κωδικός πρόσβασης',
+'retypenew' => 'Πληκτρολογήστε ξανά το νέο κωδικό.',
+'textboxsize' => 'Επεξεργασία',
+'rows' => 'Σειρές',
+'columns' => 'Στήλες',
+'searchresultshead' => 'Αποτελέσματα αναζήτησης/Ρυθμίσεις',
+'resultsperpage' => 'Αποτελέσματα ανά σελίδα',
+'contextlines' => 'Σειρές που θα εμφανίζονται ανά αποτέλεσμα',
+'contextchars' => 'Αριθμός χαρακτήρων στο εμφανιζόμενο κείμενο',
+'stubthreshold' => 'Ελάχιστο μέγεθος πολύ σύντομων σελίδων (stub)',
+'recentchangescount' => 'Αριθμός τίτλων στις πρόσφατες αλλαγές',
+'savedprefs' => 'Οι προτιμήσεις σας έχουν αποθηκευθεί.',
+'timezonelegend' => 'Ζώνη ώρας (Time zone)',
+'timezonetext' => 'Συμπληρώστε τον αριθμό των ωρών κατά τις οποίες η τοπική σας ώρα διαφέρει από την ώρα του server (UTC).',
+'localtime' => 'Εμφάνιση τοπικής ώρας',
+'timezoneoffset' => 'Διαφορά ωρών',
+'servertime' => 'Η ώρα του server είναι:',
+'guesstimezone' => 'Συμπλήρωση μέσω του browser',
+'emailflag' => 'Απενεργοποίηση ηλεκτρονικού ταχυδρομείου από άλλους χρήστες',
+'defaultns' => 'Προκαθορισμένη αναζήτηση στις περιοχές:',
+'default' => 'Προκαθορισμένο',
+'files' => 'Αρχεία',
+
+
+# User levels special page
+#--------------------------------------#
+
+# switching pan
+'groups-lookup-group' => 'Διαχείριση των δικαιωμάτων της ομάδας',
+'groups-group-edit' => 'Υπάρχουσες ομάδες:',
+'editgroup' => 'Ομάδα επεξεργασίας',
+'addgroup' => 'Προσθήκη ομάδας',
+
+'userrights-lookup-user' => 'Διαχείριση ομάδων χρηστών',
+'userrights-user-editname' => 'Δηλώστε όνομα χρήστη:',
+'editusergroup' => 'Επεξεργασία \'Ομάδα Χρηστών\'',
+
+# group editing
+'groups-editgroup' => 'Επεξεργασία ομάδας',
+'groups-addgroup' => 'Προσθήκη ομάδας',
+
+'groups-editgroup-preamble' => 'Εαν το όνομα της περιγραφής αρχίζει με άνω-κάτω τελεία, το υπόλοιπο του ονόματος θα εκληφθεί ως τίτλος μηνύματος και, για το λόγο αυτό, το κείμενο θα χωροθετηθεί με βάση το όνομα της περιοχής MediaWiki',
+
+'groups-editgroup-name' => 'Επωνυμία ομάδας:',
+'groups-editgroup-description' => 'Περιγραφή ομάδας (max 255 χαρακτήρες):<br />',
+'savegroup' => 'Αποθήκευση ομάδας',
+'groups-tableheader' => 'ID || Επωνυμία|| Περιγραφή || Δικαιώματα',
+'groups-existing' => 'Υπάρχουσες ομάδες',
+'groups-noname' => 'Παρακαλούμε δηλώστε μία έγκυρη επωνυμία ομάδας',
+'groups-already-exists' => 'Υπάρχει ήδη ομάδα με αυτό το όνομα',
+'addgrouplogentry' => 'H ομάδα $2 έχει προστεθεί.',
+'changegrouplogentry' => 'Η ομάδα $2 έχει υποστεί αλλαγή.',
+'renamegrouplogentry' => 'Μετονομασία της ομάδας $2 σε $3',
+
+# user groups editing
+#
+'userrights-editusergroup' => 'Επεξεργασία ομάδων χρηστών',
+'saveusergroups' => 'Αποθήκευση ομάδων χρηστών',
+'userrights-groupsmember' => 'Μελος της ομάδας:',
+'userrights-groupsavailable' => 'Υπάρχουσες ομάδες:',
+
+'userrights-groupshelp' => 'Επιλέξτε όμάδες στις οποίες επιθυμείτε να προστεθεί ο χρήστης ή ομάδες από τις οποίες επιθυμείτε να αφαιρεθεί ο χρήστης. Μπορείτε να αναιρέσετε την επιλογή μιας ομάδας με το πλήκτο CTRL + αριστερό κλικ',
+
+'userrights-logcomment' => 'Τα μέλη της ομάδας έχουν αλλάξει $1 σε $2',
+
+
+# Default group names and descriptions
+#-------------------------------------------------------------#
+'group-anon-name' => 'Ανώνυμος',
+'group-anon-desc' => 'Ανώνυμοι χρήστες',
+'group-loggedin-name' => 'Χρήστης',
+'group-loggedin-desc' => 'Γενικοί συνδεδεμένοι χρήστες',
+'group-admin-name' => 'Διαχειριστής',
+'group-admin-desc' => 'Έμπειροι χρήστες έχουν τη δυνατότητα να επιβάλλουν φραγή ή να διαγράφουν άρθρα.',
+'group-bureaucrat-name' => 'Διαχειριστής',
+'group-bureaucrat-desc' => 'Οι διαχειριστές μπορούν να ορίζουν επιπλέον διαχειριστές',
+'group-steward-name' => 'Διαχειριστής',
+'group-steward-desc' => 'Πλήρης πρόσβαση',
+
+
+# Recent changes
+#--------------------------#
+'changes' => 'αλλαγές',
+'recentchanges' => 'Πρόσφατες αλλαγές',
+'recentchanges-url' => 'Special:Recentchanges',
+'recentchangestext' => 'Παρακολουθείστε σε αυτή τη σελίδα τις πιο πρόσφατες αλλαγές στο Wiki.',
+'rcloaderr' => 'Φόρτωση πρόσφατων αλλαγών',
+'rcnote' => 'Ακολουθούν οι <strong>$1</strong> πιο πρόσφατες αλλαγές στο διάστημα των τελευταίων <strong>$2</strong> ημερών.',
+'rcnotefrom' => 'Ακολουθούν οι αλλαγές από <b>$2</b> (εμφάνιση <b>$1</b> αλλαγών max).',
+'rclistfrom' => 'Εμφάνιση νέων αλλαγών αρχίζοντας από $1',
+'showhideminor' => '$1 αλλαγές μικρής κλίμακας | $2 διαχειριστές | $3 συνδεδεμένοι χρήστες | $4 επεξεργασίες υπό παρακολούθηση',
+'rclinks' => 'Εμφάνιση των τελευταίων $1 αλλαγών στο διάστημα των τελευταίων $2 ημερών <br />$3',
+'rchide' => 'σε μορφή $4 : $1 επεξεργασίες μικρής κλίμακας, $2 δευτερεύουσες περιοχές, $3 πολλαπλές επεξεργασίες',
+'rcliu' => '; $1 επεξεργασίες από συνδεδεμένους χρήστες',
+'diff' => '\'διαφορά\'',
+'hist' => '\'ιστορικό\'',
+'hide' => 'απόκρυψη',
+'show' => 'εμφάνιση',
+'tableform' => 'πίνακας',
+'listform' => 'κατάλογος',
+'nchanges' => '$1 αλλαγές',
+'minoreditletter' => 'μ',
+'newpageletter' => 'N',
+#'sectionlink' => '&rarr;',
+'number_of_watching_users_RCview' => '[$1]',
+'number_of_watching_users_pageview' => '[$1 χρήστης (-ες) που παρακολουθούν]',
+
+
+# Upload
+#------------#
+'upload' => 'Φόρτωση αρχείου',
+'uploadbtn' => 'Φόρτωση αρχείου',
+'uploadlink' => 'Φόρτωση εικόνων',
+'reupload' => 'Επανάληψη φόρτωσης',
+'reuploaddesc' => 'Επιστροφή στη φόρμα φόρτωσης',
+'uploadnologin' => 'Δεν έχετε συνδεθεί!',
+'uploadnologintext' => 'Για να φορτώσετε αρχεία πρέπει πρώτα να [[Special:Userlogin|συνδεθείτε]].',
+'upload_directory_read_only' => 'Δεν είναι δυνατή η εγγραφή στον κατάλογο ($1) από τον server.',
+'uploaderror' => 'Σφάλμα στη φόρτωση αρχείου',
+
+'uploadtext' => '\'\'\'ΠΕΡΙΜΕΝΕΤΕ!\'\'\' Πριν προχωρήσετε στη φόρτωση αρχείων σε αυτό το χώρο βεβαιωθείτε πως διαβάσατε και πως ακολουθείτε τους [[{{ns:4}}:Κανόνες_χρήσης_εικόνων|Κανόνες χρήσης εικόνων]].
+
+Μπορείτε να δείτε ή να αναζητήσετε εικόνες που έχουν φορτωθεί κατά το παρελθόν κάτω από το σύνδεσμο [[Special:Imagelist|Κατάλογος εικόνων που έχουν φορτωθεί]].
+Οι φορτώσεις και οι διαγραφές έχουν καταγραφεί στη σελίδα
+[[{{ns:4}}:Καταγραφές_φόρτωσης|Καταγραφές φόρτωσης]].
+
+Χρησιμοποιήστε την παρακάτω φόρμα για να φορτώσετε νέα αρχεία εικόνας που θα χρησιμοποιηθούν στον οπτικό εμπλουτισμό των σελίδων. Στους περισσότερους browsers υπάρχει ένα κουμπί "Browse..." το οποίο εμφανίζει το πεδίο διαλόγου του συστήματός σας για το άνοιγμα αρχείων. Αν επιλέξετε ένα αρχείο, το όνομά τoυ θα συμπληρωθέι αυτόματα στο πεδίο κειμένου που βρίσκεται δίπλα στο κουμπί. Μην ξεχάστε να επιβεβαιώσετε (σημειώνοντας το ανάλογο κουτάκι) πως με τη φόρτωση του συγκεκριμένου αρχείου δεν παραβιάζετε πνευματικά δικαιώματα.
+
+Πατήστε το κουμπί "Upload" για να ολοκληρωθέι η φόρτωση.
+Η διαδικασία μπορεί να διαρκέσει λίγο περισσότερο αν διαθέτετε αργή σύνδεση με το internet.
+
+Οι προτιμώμενες μορφές αρχείου είναι: JPEG για φωτογραφίες, PNG για σχήματα και άλλες εικόνες και OGG για αρχεία ήχου. Δώστε περιγραφικά ονόματα στα αρχεία σας για να αποφευχθεί τυχόν σύγχυση.
+
+Για να συμπεριληφθεί μια εικόνα σε μια σελίδα, χρησιμοποιήστε συνδέσμους της μορφής
+\'\'\'<nowiki>[[{{ns:6}}:file.jpg]]</nowiki>\'\'\' ή
+\'\'\'<nowiki>[[{{ns:6}}:file.png|alt text]]</nowiki>\'\'\' ή
+\'\'\'<nowiki>[[{{ns:-2}}:file.ogg]]</nowiki>\'\'\' για αρχεία ήχου.
+
+Σας παρακαλούμε να λάβετε υπ΄όψη σας ότι, ακριβώς όπως συμβαίνει με τις σελίδες Wiki, είναι δυνατόν άλλοι χρήστες να επεξεργαστούν ή να διαγράψουν κατά την κρίση τους αρχεία που έχετε φορτώσει. Έχετε επίσης υπ΄όψη σας πως είναι δυνατόν να υποστείτε φραγή σαν χρήστης αν διαπιστωθεί πως έχετε κάνει κατάχρηση του συστήματος.<br/>',
+
+'uploadlog' => 'Φόρτωση αρχείου γεγονότων',
+'uploadlogpage' => 'Καταγραφές φόρτωσης',
+'uploadlogpagetext' => 'Ακολουθεί κατάλογος των αρχείων που έχουν φορτωθεί πρόσφατα.',
+'filename' => 'Όνομα αρχείου',
+'filedesc' => 'Σύνοψη',
+'filestatus' => 'Κατάσταση του copyright',
+'filesource' => 'Πηγή',
+'copyrightpage' => '{{ns:12}}:Copyrights',
+'copyrightpagename' => '{{SITENAME}} copyright',
+'uploadedfiles' => 'Αρχεία που έχουν φορτωθεί',
+'ignorewarning' => 'Αγνόηση της προειδοποίησης. Αποθήκευση αρχείου.',
+'minlength' => 'Τα ονόματα εικόνων δεν πρέπει να περιέχουν λιγότερους από τρεις χαρακτήρες.',
+'illegalfilename' => 'Το όνομα του αρχείου "$1" περιέχει χαρακτήρες που δεν επιτρέπονται στους τίτλους των σελίδων. Παρακαλούμε δώστε άλλο όνομα στο αρχείο και προσπαθήστε ξανά να το ανεβάσετε.',
+'badfilename' => 'Το όνομα της εικόνας άλλαξε σε "$1".',
+'badfiletype' => 'Το ".$1" δεν είναι προτεινόμενος τύπος εικόνας.',
+'largefile' => 'Συνιστούμε οι εικόνες να μην υπερβαίνουν σε μέγεθος τα 100k .',
+
+'emptyfile' => 'Το αρχείο που φορτώσατε φαίνεται να είναι κενό. Αυτό μπορεί να οφείλεται σε λάθος πληκτρολόγησης του ονόματος του αρχείου. Παρακαλούμε ελέγξτε εαν αυτό είναι πραγματικά το αρχείο που θέλετε να φορτώσετε.',
+
+'fileexists' => 'Υπάρχει ήδη αρχείο με αυτό το όνομα -παρακαλούμε ελέγξτε στο $1. Είστε βέβαιος (-η) πως θέλετε να αλλάξετε το όνομα του αρχείου;',
+'successfulupload' => 'Επιτυχής φόρτωση',
+
+'fileuploaded' => 'Το αρχείο $1 φορτώθηκε επιτυχώς!
+Παρακαλούμε ακολουθήστε το σύνδεσμο: $2 προς τη σελίδα της περιγραφής και συμπληρώστε πληροφορίες σχετικές με το αρχείο, όπως το από πού προήλθε, πότε δημιουργήθηκε και από ποιόν, και οτιδήποτε άλλο γνωρίζετε σχετικά με αυτό. Αν πρόκειται για εικόνα μπορείτε να την ενθέσετε με τον εξής τρόπο: <tt><nowiki>[[{{ns:6}}:$1|thumb|Description]]</nowiki></tt>',
+
+'uploadwarning' => 'Προειδοιποίηση φόρτωσης',
+'savefile' => 'Αποθήκευση αρχείου',
+'uploadedimage' => 'Η φόρτωση του "$1" ολοκληρώθηκε.',
+'uploaddisabled' => 'Λυπούμαστε, η φόρτωση έχει απενεργοποιηθεί.',
+'uploadscripted' => 'Αυτό το αρχείο περιέχει κώδικα HTML ή script που μπορεί να παρερμηνευθεί από μερικούς browser.',
+'uploadcorrupt' => 'Το αρχείο είναι κατεστραμένο ή έχει κάποια λανθασμένη επέκταση. Παρακαλούμε ελέγξτε το και ξαναδοκιμάστε να το ανεβάσετε.',
+'uploadvirus' => 'Το αρχείο περιέχει ιό! Λεπτομέρειες: $1',
+'sourcefilename' => 'Όνομα πηγαίου αρχείου',
+'destfilename' => 'Όνομα αρχείου προορισμού',
+
+
+# Image list
+#----------------#
+'imagelist' => 'Κατάλογος εικόνων',
+'imagelisttext' => 'Ακολουθεί κατάλογος $1 εικόνων ταξινομημένων κατά σειρά $2.',
+'getimagelist' => 'Προσκόμιση καταλόγου εικόνων',
+'ilsubmit' => 'Αναζήτηση',
+'showlast' => 'Εμφάνιση των $1 πιο πρόσφατων εικόνων κατά σειρά $2.',
+'byname' => 'ονόματος',
+'bydate' => 'ημερομηνίας',
+'bysize' => 'μεγέθους',
+'imgdelete' => '\'διαγραφή\'',
+'imgdesc' => '\'περιγραφή\'',
+'imglegend' => 'Υπόμνημα: (\'περιγραφή\') = εμφάνιση/επεξεργασία της περιγραφής εικόνας',
+'imghistory' => 'Ιστορικό εικόνας',
+'revertimg' => '\'επαναφορά\'',
+'deleteimg' => '\'διαγραφή\'',
+'deleteimgcompletely' => 'Διαγραφή όλων των αναθεωρήσεων',
+
+'imghistlegend' => 'Υπόμνημα: (\'τρέχον\') = αυτή είναι η τρέχουσα εικόνα, (\'διαγραφή\') = διαγραφή αυτής της παλιότερης έκδοσης, (\'επαναφορά\') = επαναφορά σε αυτή την παλιότερη έκδοση
+
+<br /><i>Κάνοντας κλικ στην ημερομηνία θα δείτε την εικόνα που φορτώθηκε εκείνη την ημέρα</i>.',
+
+'imagelinks' => 'Σύνδεσμοι εικόνων',
+'linkstoimage' => 'Οι ακόλουθες σελίδες συνδέονται με αυτή την εικόνα:',
+'nolinkstoimage' => 'Δεν υπάρχουν σελίδες που συνδέονται με αυτήν την εικόνα.',
+'sharedupload' => 'Το αρχείο αυτό φορτώθηκε για κοινή χρήση και είναι δυνατόν να χρησιμοποιείται ταυτοχρόνως σε περισσότερα από ένα έργα.',
+'shareduploadwiki' => 'Παρακαλούμε συμβουλευθείτε την [$1 σελίδα περιγραφής αρχείου] για περισσότερες πληροφορίες.',
+#'shareddescriptionfollows' => '-',
+'noimage' => 'Δεν υπάρχει αρχείο με αυτό το όνομα, μπορείτε να [$1 το φορτώσετε].',
+'uploadnewversion' => '[$1 Φορτώστε μια νέα έκδοση αυτού του αρχείου]',
+
+
+# Statistics
+#---------------#
+'statistics' => 'Στατιστικές',
+'sitestats' => 'Στατιστικές ιστοχώρου',
+'userstats' => 'Στατιστικές χρηστών',
+
+'sitestatstext' => 'Υπάρχουν συνολικά \'\'\'$1\'\'\' σελίδες στη βάση δεδομένων. Σε αυτές συμπεριλαμβάνονται και οι σελίδες "συζήτησης", σελίδες σχετικά με το {{SITENAME}}, σελίδες με πολύ σύντομο κείμενο (stub), ανακατευθύνσεις, και άλλες που πιθανόν να μην χαρακτηρίζονται σελίδες-με- κείμενο (ή περιεχόμενο).
+Επιπλέον υπάρχουν και \'\'\'$2\'\'\' άλλες σελίδες που πληρούν τα κριτήρια και χαρακτηρίζονται, επίσης, σελίδες περιεχομένου.
+
+Από τη στιγμή που δημιουργήθηκε αυτό το Wiki έχουν καταγραφεί \'\'\'$3\'\'\' επισκέψεις σε σελίδες και \'\'\'$4\'\'\' επεξεργασίες σε σελίδες.
+Ο μέσος όρος κατά την τελευταία ενημέρωση ήταν \'\'\'$5\'\'\' επεξεργασίες ανά σελίδα και \'\'\'$6\'\'\' επισκέψεις ανά επεξεργασία.',
+
+'userstatstext' => 'Υπάρχουν \'\'\'$1\'\'\' εγγεγραμένοι χρήστες.
+\'\'\'$2\'\'\' από αυτούς είναι διαχειριστές (βλ. $3 | διαχειριστές).',
+
+
+# Maintenance Page
+#-----------------------------#
+'maintenance' => 'Σελίδα συντήρησης',
+
+'maintnancepagetext' => 'Η σελίδα αυτή περιέχει διάφορα εύχρηστα εργαλεία για την καθημερινή συντήρηση. 
+
+Μερικές από τις λειτουργίες αυτές είναι δυνατόν να καταπονήσουν τη βάση δεδομένων, για το λόγο αυτό σας παρακαλούμε να κάνετε \'επαναφόρτωση\' μετά από κάθε στοιχείο που έχετε επιδιορθώσει;-)',
+
+'maintenancebacklink' => 'Επιστροφή στη σελίδα συντήρησης',
+'disambiguations' => 'Σελίδες αποσαφήνισης',
+'disambiguationspage' => '{{ns:4}}:Σύνδεσμοι_προς_τις_σελίδες_αποσαφήνισης',
+
+'disambiguationstext' => 'Οι σελίδες που ακολουθούν συνδέονται με μια <i>σελίδα αποσαφήνισης</i> ενώ θα έπρεπε κανονικά να συνδέονται με το αντίστοιχο θέμα.<br />Μια σελίδα θεωρείται σελίδα αποσαφήνισης όταν συνδέεται μέσω της $1.<br />Σύνδεσμοι μέσα από άλλες περιοχές <i>δεν</i> περιλαμβάνονται σε αυτό τον κατάλογο.',
+
+'doubleredirects' => 'Διπλές ανακατευθύνσεις',
+
+'doubleredirectstext' => 'Κάθε σειρά περιέχει συνδέσμους προς την πρώτη και τη δεύτερη σελίδα ανακατεύθυνσης, όπως επίσης και την πρώτη αράδα του κειμένου στη δεύτερη σελίδα ανακατεύθυνσης η οποία και είναι, κανονικά, ο πραγματικός προορισμός της ανακατεύθυνσης -εκεί δηλαδή όπου θα έπρεπε να είχατε οδηγηθεί από την αρχή.',
+
+'brokenredirects' => 'Κατεστραμένες ανακατευθύνσεις',
+'brokenredirectstext' => 'Οι παρακάτω ανακατευθύνσεις οδηγούν σε σελίδες που δεν υπάρχουν.',
+'selflinks' => 'Σελίδες με αυτο-συνδέσμους',
+'selflinkstext' => 'Οι εξής σελίδες έχουν σύνδεσμο προς τον εαυτό τους -αυτό δεν θα έπρεπε να συμβαίνει.',
+'mispeelings' => 'Σελίδες με ορθογραφικά λάθη',
+'mispeelingstext' => 'Οι παρακάτω σελίδες περιέχουν συνηθισμένα ορθογραφικά λάθη, τα οποία βρίσκονται συγκεντρωμένα στο $1. Η σωστή ορθογραφία πρέπει να τοποθετείται (εντός παρενθέσεων).',
+'mispeelingspage' => 'Κατάλογος συνηθισμένων ορθογραφικών λαθών',
+'missinglanguagelinks' => 'Αγνοούμενοι σύνδεσμοι γλώσσας',
+'missinglanguagelinksbutton' => 'Εύρεση αγνοουμένων συνδέσμων γλώσσας για',
+'missinglanguagelinkstext' => 'Αυτές οι σελίδες <i>δεν</i> συνδέονται με τις ομόλογές τους στο $1. Οι ανακατευθύνσεις και οι υποσελίδες <i>δεν</i> εμφανίζονται.',
+
+# Miscellaneous special pages
+#
+'orphans' => 'Ορφανές σελίδες',
+'geo' => 'Γεωγραφικές συντεταγμένες',
+'validate' => 'Επικύρωση σελίδας',
+'lonelypages' => 'Ορφανές σελίδες',
+'uncategorizedpages' => 'Αταξινόμητες σελίδες',
+'uncategorizedcategories' => 'Αταξινόμητες κατηγορίες',
+'unusedcategories' => 'Κενές κατηγορίες',
+'unusedimages' => 'Αχρησιμοποίητες εικόνες',
+'popularpages' => 'Δημοφιλείς σελίδες',
+'nviews' => '$1 επισκέψεις',
+'wantedpages' => 'Σελίδες σε ζήτηση',
+'mostlinked'   => 'Οι σελίδες με τις περισσότερες αναφορές',
+'nlinks' => '$1 σύνδεσμοι',
+'allpages' => 'Όλες οι σελίδες',
+'randompage' => 'Σελίδα στην τύχη',
+'randompage-url' => 'Special:Randompage',
+'shortpages' => 'Σύντομες σελίδες',
+'longpages' => 'Εκτενείς σελίδες',
+'deadendpages' => 'Αδιέξοδες σελίδες',
+'listusers' => 'Κατάλογος χρηστών',
+'specialpages' => 'Σελίδες λειτουργιών',
+'spheading' => 'Σελίδες λειτουργιών για όλους τους χρήστες',
+'restrictedpheading' => 'Ειδικές σελίδες με περιορισμούς πρόσβασης',
+'blockpheading' => 'Διαβαθμίσεις φραγής',
+'createaccountpheading' => 'διαβάθμιση \'δημιουργίας λογαριασμού\'',
+'deletepheading' => 'Διαβαθμίσεις διαγραφής',
+'userrightspheading' => 'Διαβαθμίσεις δικαιωμάτων χρηστών',
+'grouprightspheading' => 'Διαβάθμιση δικαιωμάτων ομάδας',
+'siteadminpheading' => 'Διαβαθμίσεις διαχείρισης ιστοχώρου',
+/** obsoletes
+'sysopspheading' => 'Μόνον για χρήση των διαχειριστών',
+'developerspheading' => 'Μόνον για χρήση των προγραμματιστών',
+*/
+'protectpage' => 'Προστασία σελίδας',
+'recentchangeslinked' => 'Σχετικές αλλαγές',
+'rclsub' => '(σε σελίδες που συνδέονται από το "$1")',
+'debug' => 'Διόρθωση σφαλμάτων',
+'newpages' => 'Νέες σελίδες',
+'ancientpages' => 'Οι παλιότερες σελίδες',
+'intl' => 'Διαγλωσσικοί σύνδεσμοι',
+'move' => 'Μετακίνηση',
+'movethispage' => 'Μετακίνηση αυτής της σελίδας',
+
+'unusedimagestext' => '<p>Παρακαλούμε να λάβετε υπ` όψη σας πως άλλες ιστοσελίδες είναι δυνατόν να  συνδέονται με μια εικόνα με απευθείας URL - για το λόγο αυτό μπορεί μερικές εικόνες να εμφανίζονται ακόμα εδώ παρόλο που στην πραγματικότητα είναι σε χρήση.</p>',
+
+'unusedcategoriestext' => 'Οι ακόλουθες κατηγοριοποιημένες σελίδες δεν συνδέονται με άλλο άρθρο ή κατηγορία.',
+'booksources' => 'Πηγές βιβλίων',
+'categoriespagetext' => 'Υπάρχουν οι ακόλουθες κατηγορίες στο Wiκi.',
+'data' => 'Δεδομένα',
+'userrights' => 'Διαχείριση δικαιωμάτων χρηστών',
+'groups' => 'Ομάδες χρηστών',
+
+'booksourcetext' => 'Ακολουθούν σύνδεσμοι για διαδικτυακούς τόπους που εμπορεύονται καινούργια ή μεταχειρισμένα βιβλία και όπου μπορείτε να αναζητήσετε τα βιβλία που σας ενδιαφέρουν. Το {{SITENAME}} δεν έχει σχέση με αυτές τις επιχειρήσεις και ο κατάλογος αυτός δεν αποτελεί κατά κανένα τρόπο προώθηση ή διαφήμισή τους.',
+
+'isbn' => 'ISBN',
+'rfcurl' => 'http://www.faqs.org/rfcs/rfc$1.html',
+#'pubmedurl' => 'http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?cmd=Retrieve&db=pubmed&dopt=Abstract&list_uids=$1',
+'alphaindexline' => '$1 έως $2',
+'version' => 'Έκδοση',
+'log' => 'Καταγραφές γεγονότων',
+
+'alllogstext' => 'Εποπτική εμφάνιση όλων των ενεργειών φόρτωσης αρχείων, διαγραφής, προστασίας, φραγής και όλων των καταγραφών των διαχειριστών στο αρχείο γεγονότων. Μπορείτε να περιορίσετε τα αποτελέσματα που εμφανίζονται επιλέγοντας συγκεκριμένο είδος γεγονότων, όνομα χρήστη ή τη σελίδα που επηρεάστηκε.',
+
+
+# Special:Allpages
+#--------------------------#
+'nextpage' => 'Επόμενη σελίδα ($1)',
+'allpagesfrom' => 'Εμφάνιση όλων των σελίδων που αρχίζουν στο:',
+'allarticles' => 'Όλα τα άρθρα',
+'allnonarticles' => 'Όλα τα μη-άρθρα',
+'allinnamespace' => 'Όλες οι σελίδες (στην περιοχή $1)',
+'allnotinnamespace' => 'Όλες οι σελίδες (που δεν βρίσκονται στην περιοχή $1)',
+'allpagesprev' => 'Προηγούμενες',
+'allpagesnext' => 'Επόμενες',
+'allpagessubmit' => 'Μετάβαση',
+
+
+# E this user
+#-----------------#
+'mailnologin' => 'Δεν υπάρχει διεύθυνση παραλήπτη.',
+
+'mailnologintext' => 'Πρέπει να έχετε [[Special:Userlogin|συνδεθεί]] και να έχετε δηλώσει
+μια έγκυρη ηλεκτρονική διεύθυνση στις [[Special:Preferences|Προτιμήσεις]]
+για να στείλετε e-mail σε άλλους χρήστες.',
+
+'emailuser' => 'Στείλτε e-mail σε αυτόν το χρήστη',
+'emailpage' => 'Αποστολή e-mail σε χρήστη',
+
+'emailpagetext' => 'Συπληρώνοντας την παρακάτω φόρμα θα στείλετε ένα μήνυμα εφόσον ο παραλήπτης έχει δηλώσει μια έγκυρη διεύθυνση ηλεκτρονικού ταχυδρομείου στις \'προτιμήσεις χρήστη\'. Η διεύθυνση ηλεκτρονικού ταχυδρομείου που έχετε δηλώσει στις δικές σας \'προτιμήσεις χρήστη\' θα εμφανιστεί ως διεύθυνση αποστολέα του μηνύματος, ούτως ώστε ο παραλήπτης να μπορέσει να σας απαντήσει.',
+
+'usermailererror' => 'Σφάλμα ηλεκτρονικού ταχυδρομείου:',
+'defemailsubject' => 'Ηλεκτρονικό ταχυδρομείο {{SITENAME}}',
+'noemailtitle' => 'Δεν υπάρχει ηλεκτρονική διεύθυνση.',
+'noemailtext' => 'Ο χρήστης αυτός δεν έχει δηλώσει την ηλεκτρονική του διέθυνση ή έχει επιλέξει να μην δέχεται μηνύματα από άλλους χρήστες.',
+'emailfrom' => 'Αποστολέας',
+'emailto' => 'Προς',
+'emailsubject' => 'Θέμα',
+'emailmessage' => 'Μήνυμα',
+'emailsend' => 'Αποστολή',
+'emailsent' => 'Το μήνυμα έχει σταλεί',
+'emailsenttext' => 'Το μήνυμά σας έχει σταλεί.',
+
+
+# Watchlist
+#---------------#
+'watchlist' => 'Λίστα παρακολούθησης',
+'watchlistsub' => '(για το χρήστη "$1")',
+'nowatchlist' => 'Δεν υπάρχουν εγγραφές στη λίστα παρακολούθησης.',
+'watchnologin' => 'Δεν έχετε συνδεθεί.',
+'watchnologintext' => 'Για να κάνετε αλλαγές στη λίστα παρακολούθησης πρέπει να <a href="{{localurl:Special:Userlogin}}"> συνδεθείτε </a>.',
+'addedwatch' => 'Η σελίδα έχει προστεθεί στη λίστα παρακολούθησης.',
+
+'addedwatchtext' => 'Η σελίδα "$1" έχει προστεθεί στη [[Special:Watchlist|λίστα παρακολούθησης]].
+Μελλοντικές αλλαγές στη σελίδα καθώς και στη σχετική με τη σελίδα συζήτηση θα φαίνονται \'\'\'με έντονα γράμματα\'\'\' στη [[Special:Recentchanges|λίστα πρόσφατων αλλαγών]] έτσι ώστε να διευκολύνεται η παρακολούθηση.
+
+
+<p>Αν θελήσετε να αφαιρέσετε τη σελίδα αυτή από τη λίστα παρακολούθησης, κάνετε κλικ στην επιλογή "παύση παρακολούθησης" στην μπάρα ενεργειών.',
+
+'removedwatch' => 'Αφαιρέθηκε απο τη λίστα παρακολούθησης.',
+'removedwatchtext' => 'Η σελίδα "$1" έχει αφαιρεθεί από τη λίστα παρακολούθησής σας.',
+'watch' => 'Παρακολούθηση',
+'watchthispage' => 'Παρακολούθηση αυτής της σελίδας',
+'unwatch' => 'Παύση παρακολούθησης',
+'unwatchthispage' => 'Παύση παρακολούθησης αυτής της σελίδας',
+'notanarticle' => 'Η σελίδα αυτή δεν είναι σελίδα περιεχομένου.',
+'watchnochange' => 'Δεν υπήρξε δραστηριότητα επεξεργασίας στις σελίδες που παρακολουθείτε κατά την εμφανιζόμενη χρονική περίοδο.',
+'watchdetails' => '(Υπό παρακολούθηση: $1 σελίδες, χωρίς τις σελίδες συζήτησης. $2 συνολικά σελίδες έχουν υποστεί επεξεργασία. $3... <a href="$4">Προβολή και επεξεργασία ολόκληρης της λίστας </a>)',
+'wlheader-enotif' => '* Η ειδοποίηση με ηλεκτρονικό ταχυδρομείο έχει ενεργοποιηθεί.',
+'wlheader-showupdated' => '* Σελίδες που έχουν υποστεί αλλαγές από την τελευταία φορά που τις επισκεφθήκατε εμφανίζονται με \'\'\'έντονους χαρακτήρες\'\'\'.',
+'watchmethod-recent' => 'Έλεγχος πρόσφατων αλλαγών σε σελίδες υπό παρακολούθηση',
+'watchmethod-list' => 'Έλεγχος σελίδων υπό παρακολούθηση για πρόσφατες αλλαγές',
+'removechecked' => 'Αφαίρεση επιλεγμένων σελίδων από τη λίστα παρακολούθησης',
+'watchlistcontains' => 'Η λίστα παρακολούθησής σας περιέχει $1 σελίδες.',
+
+'watcheditlist' => 'Ακολουθεί μια λίστα των σελίδων που παρακολουθείτε (κατά αλφαβητική σειρά). Σημειώστε τις σελίδες που επιθυμείτε να αφαιρέσετε από τη λίστα σας και επικυρώστε με ένα κλικ στο κουμπί \'αφαίρεση σελίδων\' στο κάτω μέρος της οθόνης.',
+
+'removingchecked' => 'Εξάλειψη των αντικειμένων που ζητήσατε να αφαιρεθούν από τη λίστα παρακολούθησης...',
+'couldntremove' => 'Δεν ήταν δυνατόν να εξαλειφθεί το στοιχείο $1...',
+'iteminvalidname' => 'Πρόβλημα με το στοιχείο "$1", άκυρο όνομα...',
+'wlnote' => 'Ακολουθούν οι $1 πιο πρόσφατες αλλαγές κατά τη διάρκεια των τελευταίων <b>$2</b> ωρών.',
+'wlshowlast' => 'Εμφάνιση των τελευταίων $1 ωρών $2 ημερών $3',
+'wlsaved' => 'Αποθηκευμένη έκδοση της λίστας παρακολούθησης',
+'wlhideshowown' => '$1 από τις επεξεργασίες μου',
+'wlshow' => 'Εμφάνιση',
+'wlhide' => 'Απόκρυψη',
+'enotif_mailer' => 'Σύστημα ειδοποίησης μέσω αλληλογραφίας του {{SITENAME}}',
+'enotif_reset' => 'Σημειώστε όλες τις σελίδες ως αναγνωσμένες.',
+'enotif_newpagetext' => 'Αυτή είναι μια νέα σελίδα.',
+'changed' => 'έχει αλλάξει',
+'created' => 'δημιουργήθηκε',
+'enotif_subject' => 'Η σελίδα $PAGETITLE του {{SITENAME}}έχει $CHANGEDORCREATED από το χρήστη $PAGEEDITOR',
+'enotif_lastvisited' => 'Δείτε το $1 για όλες τις αλλαγές που έγιναν από την τελευταία σας επίσκεψη.',
+'enotif_body' => 'Αγαπητέ $WATCHINGUSERNAME...
+
+Η σελίδα $PAGETITLE του {{SITENAME}}έχει $CHANGEDORCREATED στις $PAGEEDITDATE από το χρήστη $PAGEEDITOR -ακολουθήστε το σύνδεσμο $PAGETITLE_URL για να δείτε την τρέχουσα αναθεώρηση.
+
+$NEWPAGE
+
+Περιγραφή: $PAGESUMMARY $PAGEMINOREDIT
+
+Επικοινωνήστε με το συγκεκριμένο χρήστη:
+mail: $PAGEEDITOR_EMAIL
+wiki: $PAGEEDITOR_WIKI
+
+Δεν θα υπάρξει άλλη ειδοποίηση για περαιτέρω αλλαγές αν δεν επισκεφθείτε τη σελίδα. Μπορείτε επίσης να επαναφέρετε την επιλογή ειδοποίησης για όλες τις σελίδες στη λίστα παρακολούθησής σας.
+
+Φιλικά,<<br/>
+Tο σύστημα ειδοποίησης του {{SITENAME}}
+
+--
+Για να αλλάξετε τις προτιμήσεις της λίστας παρακολούθησής σας, ακολουθήστε το σύνδεσμο:
+{{SERVER}}{{localurl:Special:Watchlist/edit}}
+
+Ερωτήσεις και περισσότερες πληροφορίες: 
+{{SERVER}}{{localurl:{{ns:12}}:Περιεχόμενα}}',
+
+
+# Delete/protect/revert
+#----------------------------------#
+'deletepage' => 'Διαγραφή σελίδας',
+'confirm' => 'Επιβεβαίωση',
+'excontent' => 'το περιεχόμενο ήταν:',
+'excontentauthor' => 'το περιεχόμενο ήταν: \'$1\' (και οι μοναδικές συνεισφορές ήταν του \'$2\')',
+'exbeforeblank' => 'το περιεχόμενο πριν απο την εκκαθάριση ήταν:',
+'exblank' => 'η σελίδα ήταν κενή',
+'confirmdelete' => 'Επιβεβαίωση διαγραφής',
+'deletesub' => '(Διαγραφή της "$1")',
+'historywarning' => 'ΠΡΟΕΙΔΟΠΟΙΗΣΗ! Η σελίδα που πρόκειται να διαγράψετε έχει ιστορικό.<br/>',
+'confirmdeletetext' => 'Πρόκειται να διαγράψετε οριστικά από τη βάση δεδομένων μια σελίδα (ή μια εικόνα) μαζί με το ιστορικό της. Παρακαλούμε επιβεβαιώστε ότι θέλετε πραγματικά να το κάνετε, ότι αντιλαμβάνεσθε τις συνέπειες και ότι το κάνετε σύμφωνα με τους [[{{ns:4}}:Κανόνες|Κανόνες]].',
+'actioncomplete' => 'Η ενέργεια ολοκληρώθηκε.',
+'deletedtext' => 'Η "$1" έχει διαγραφεί.
+Για το ιστορικό των πρόσφατων διαγραφών ανατρέξτε στο σύνδεσμο $2',
+'deletedarticle' => 'Η $1 διαγράφτηκε.',
+'dellogpage' => 'Καταγραφές διαγραφών',
+'dellogpagetext' => 'Λίστα των πιο πρόσφατων διαγραφών',
+'deletionlog' => 'Καταγραφές διαγραφών',
+'reverted' => 'Επαναφορά σε προηγούμενη αναθεώρηση',
+'deletecomment' => 'Αιτιολογία διαγραφής',
+'imagereverted' => 'Η επαναφορά σε παλιότερη έκδοση ήταν επιτυχής.',
+'rollback' => 'Επαναφορά επεξεργασιών',
+'rollback_short' => 'Επαναφορά',
+'rollbacklink' => 'Επαναφορά στην προηγούμενη',
+'rollbackfailed' => 'Η επαναφορά απέτυχε.',
+'cantrollback' => 'Δεν είναι δυνατή η αναίρεση αυτής της αλλαγής, πρόκειται για την αρχική ενέργεια δημιουργίας της σελίδας.',
+
+'alreadyrolled' => 'Αδύνατον να αναιρεθεί η τελευταία αλλαγή της σελίδας [[$1]]
+από το χρήστη [[User:$2|$2]] ([[User talk:$2|Συζήτηση]]), κάποιος έχει ήδη αναιρέσει την αλλαγή ή έχει αλλάξει εκ νέου τη σελίδα.
+
+Τελευταία αλλαγή από το χρήστη [[User:$3|$3]] ([[User talk:$3|Συζήτηση]]).',
+#   only shown if there is an edit comment
+'editcomment' => 'Το σχόλιο της επεξεργασίας ήταν: "<i>$1</i>".',
+'revertpage' => 'Ανάκληση των αλλαγών $2 (επιστροφή στην προηγούμενη αναθεώρηση $1)',
+
+'sessionfailure' => 'Υπάρχει πρόβλημα με τη σύνδεσή σας -η ενέργεια αυτή ακυρώθηκε προληπτικά για την αντιμετώπιση τυχόν πειρατείας συνόδου (session hijacking). Παρακαλoύμε πατήστε "Επιστροφή", ξαναφορτώστε τη σελίδα από την οποία φθάσατε εδώ και προσπαθήστε ξανά.',
+
+'protectlogpage' => 'Καταγραφές προστασίας (κλειδώματος)',
+
+'protectlogtext' => 'Ακολουθεί κατάλογος ενεργειών κλειδώματος και ξεκλειδώματος σελίδων.
+(Βλ. [[{{ns:4}}:Σελίδες_υπό_προστασία]] για περισσότερες πληροφορίες).',
+
+'protectedarticle' => 'Κλειδωμένο $1',
+'unprotectedarticle' => 'έχει αρθεί η προστασία του $1',
+'protectsub' => '(Κλειδώνεται η "$1")',
+'confirmprotecttext' => 'Θέλετε πραγματικά να κλειδώσετε αυτή τη σελίδα;',
+'confirmprotect' => 'Επιβεβαίωση κλειδώματος',
+'protectmoveonly' => 'Προστασία μόνον από μετακινήσεις',
+'protectcomment' => 'Αιτιολογία προστασίας',
+'unprotectsub' => '(Άρση προστασίας για το "$1")',
+'confirmunprotecttext' => 'Θέλετε πραγματικά να ξεκλειδώσετε αυτή τη σελίδα;',
+'confirmunprotect' => 'Επιβεβαίωση ξεκλειδώματος',
+'unprotectcomment' => 'Αιτιολογία για την άρση προστασίας',
+
+
+# Undelete
+#---------------#
+'undelete' => 'Αποκατάσταση σελίδων που έχουν διαγραφεί',
+'undeletepage' => 'Εμφάνιση και αποκατάσταση σελίδων που έχουν διαγραφεί',
+'undeletepagetext' => 'Οι σελίδες που ακολουθούν έχουν διαγραφεί αλλά βρίσκονται ακόμα αποθηκευμένες στο αρχείο και μπορούν να αποκατασταθούν. (Κατά καιρούς γίνεται εκκαθάριση του αρχείου.)',
+'undeletearticle' => 'Αποκατάσταση σελίδας που έχει διαγραφεί',
+'undeleterevisions' => '$1 αναθεωρήσεις έχουν αρχειοθετηθεί.',
+
+'undeletehistory' => 'Αν αποκαταστήσετε αυτή τη σελίδα, όλες οι αναθεωρήσεις θα αποκατασταθούν στο ιστορικό. Αν μετά τη διαγραφή αυτής της σελίδας έχει δημιουργηθεί μια νέα σελίδα με το ίδιο όνομα, οι αναθεωρήσεις που αποκαταστάθηκαν θα εμφανιστούν στο πρότερο ιστορικό και η τρέχουσα αναθεώρηση της σελίδας δεν θα αντικαταστθεί αυτομάτως.',
+
+'undeleterevision' => 'Αναθεώρηση που έχει διαγραφεί στις $1',
+'undeletebtn' => 'Αποκατάσταση!',
+'undeletedarticle' => 'αποκατάσταση "$1"',
+'undeletedrevisions' => 'Αποκατάσταση $1 αναθεωρήσεων',
+
+'undeletedtext' => 'Η [[$1]] έχει αποκατασταθεί επιτυχώς.
+(Βλ. [[Special:Log|Σελίδες που έχουν διαγραφεί]] για λεπτομερή στοιχεία σχετικά με τις πρόσφατες διαγραφές και αποκαταστάσεις).',
+
+
+# Namespace form on various pages
+#-------------------------------------------------------#
+'namespace' => 'Περιοχή:',
+'invert' => 'Αντιστροφή της επιλογής',
+
+
+# Contributions
+#---------------------#
+'contributions' => 'Συνεισφορές χρήστη',
+'mycontris' => 'Οι προσθήκες μου',
+'contribsub' => 'Για τον/την $1',
+'nocontribs' => 'Δεν βρέθηκαν αλλαγές με αυτά τα κριτήρια.',
+'ucnote' => 'Ακολουθούν οι τελευταίες <b>$1</b> αλλαγές του χρήστη κατά τη διάρκεια των τελευταίων <b>$2</b> ημερών.',
+'uclinks' => 'Εμφάνιση των τελευταίων $1 αλλαγών - Εμφάνιση των τελευταίων $2 ημερών',
+'uctop' => ' (τελευταία)',
+'newbies' => 'νέοι χρήστες',
+'contribs-showhideminor' => '$1 αλλαγές μικρής κλίμακας',
+
+
+# What links here
+#-------------------------#
+'whatlinkshere' => 'Αναφορές στη σελίδα',
+'notargettitle' => 'Δεν έχει καθοριστεί προορισμός.',
+'notargettext' => 'Δεν έχετε καθορίσει ένα χρήστη ή μια σελίδα προορισμού για να εκτελεσθεί αυτή η λειτουργία.',
+'linklistsub' => '(Κατάλογος συνδέσμων)',
+'linkshere' => 'Εδώ παραπέμπουν οι ακόλουθες σελίδες:',
+'nolinkshere' => 'Δεν υπάρχουν σελίδες με συνδέσεις προς τα εδώ.',
+'isredirect' => 'ανακατεύθυνση σελίδας',
+
+
+# Block/unblock IP
+#--------------------------#
+'blockip' => 'Φραγή χρήστη ή διεύθυνσης IP',
+
+'blockiptext' => 'Χρησιμοποιήστε την παρακάτω φόρμα για να εμποδίσετε παρεμβάσεις στο κείμενο από μια συγκεκριμένη διεύθυνση IP ή όνομα χρήστη.
+Το μέτρο αυτό πρέπει να λαμβάνεται μόνο σε περιπτώσεις βανδαλισμού σελίδων και πάντα σύμφωνα με τους [[{{ns:4}}:Κανόνες|Κανόνες]].
+Παρακαλούμε να αιτιολογήσετε την ενέργειά σας (παραπέμποντας π.χ. σε συγκεκριμένες σελίδες που υπέστησαν βανδαλισμό).',
+
+'ipaddress' => 'Διεύθυνση IP/όνομα χρήστη',
+'ipadressorusername' => 'Διεύθυνση IP ή όνομα χρήστη',
+'ipbexpiry' => 'Λήξη',
+'ipbreason' => 'Αιτιολογία',
+'ipbsubmit' => 'Φραγή σε αυτό το χρήστη',
+'ipbother' => 'Άλλη ώρα',
+'ipboptions' => '2 hours:2 ώρες,1 day:1 ημέρα,3 days:3 ημέρες,1 week:1 εβδομάδα,2 weeks:2 εβδομάδες,1month:1 μήνα,3 months:3 μήνες,6 months:6 μήνες,1 year:1 χρόνο,infinite:επ΄αόριστον',
+'ipbotheroption' => 'άλλη',
+'badipaddress' => 'Άκυρη διεύθυνση IP.',
+'blockipsuccesssub' => 'Η φραγή ολοκληρώθηκε επιτυχώς.',
+'blockipsuccesstext' => 'Η διεύθυνση "$1" έχει υποστεί φραγή. <br />Δείτε τη [[Special:Ipblocklist|λίστα διευθύνσεων IP που έχουν υποστεί φραγή]] για να το επιβεβαιώσετε.',
+'unblockip' => 'Άρση φραγής χρήστη',
+'unblockiptext' => 'Χρησιμοποιήστε την παρακάτω φόρμα για να αποκαταστήσετε την πρόσβαση σε επεξεργασία, σε μια διεύθυνση IP ή σε ένα χρήστη που είχε αποκλειστεί με φραγή.',
+'ipusubmit' => 'Άρση φραγής αυτής της διεύθυνσης',
+'ipusuccess' => 'Η άρση της φραγής του/της "$1" ολοκληρώθηκε επιτυχώς.',
+'ipblocklist' => 'Λίστα διευθύνσεων IP και ονομάτων χρηστών που έχουν υποστεί φραγή.',
+'blocklistline' => 'Φραγή του/της $3 από τους $1, $2 (λήγει $4)',
+'blocklink' => 'φραγή',
+'unblocklink' => 'Άρση φραγής',
+'contribslink' => 'Συνεισφορές/Προσθήκες',
+'autoblocker' => 'Έχετε υποστεί αυτόματα φραγή από το σύστημα επειδή χρησιμοποιείτε την ίδια διεύθυνση IP με το χρήστη "$1". Αιτιολογία "$2".',
+'blocklogpage' => 'Καταγραφές φραγής',
+'blocklogentry' => 'Φραγή του/της "$1" με χρόνο λήξης $2',
+
+'blocklogtext' => 'Σε αυτή τη σελίδα υπάρχουν οι καταγραφές φραγής και κατάργησης φραγής των χρηστών (αρχείο γεγονότων).
+
+<br />Δεν συμπεριλαμβάνονται οι διευθύνσεις IP που υπέστησαν αυτόματα φραγή. <br />Στο σύνδεσμο [[Special:Ipblocklist|διευθύνεις IP που έχουν υποστεί φραγή]] θα βρείτε τον πλήρη κατάλογο με τις τρέχουσες φραγές.',
+
+'unblocklogentry' => 'Άρση φραγής του "$1"',
+'range_block_disabled' => 'Η δυνατότητα του διαχειριστή να δημιουργεί περιοχές φραγής είναι απενεργοποιημένη.',
+'ipb_expiry_invalid' => 'Άκυρος χρόνος λήξης',
+'ip_range_invalid' => 'Το εύρος των διευθύνσεων IP δεν είναι έγκυρο.',
+'proxyblocker' => 'Εργαλείο φραγής διακομιστών (proxy blocker)',
+
+'proxyblockreason' => 'Η διεύθυνσήη IP σας έχει υποστεί φραγή γιατί είναι open proxy. Παρακαλούμε επικοινωνείστε με την υπηρεσία παροχής Internet που χρησιμοποιείτε ή με την τεχνική υποστήριξη, για να θέσετε υπ΄ όψη τους αυτό το σοβαρό θέμα ασφάλειας.',
+
+'proxyblocksuccess' => 'Ολοκληρώθηκε!',
+#'sorbs' => 'SORBS DNSBL',
+'sorbsreason' => 'Η διεύθνυση IP σας έχει χαρακτηρισθεί ως open proxy στο [http://www.sorbs.net SORBS] DNSBL.',
+'sorbs_create_account_reason' => 'Η διεύθυνση IP σας έχει χαρακτηρισθεί open proxy στο [http://www.sorbs.net SORBS] DNSBL. Δεν μπορείτε να δημιουργήσετε λογαριασμό χρήστη.',
+
+
+# Developer tools
+#-------------------------#
+'lockdb' => 'Κλείδωμα βάσης δεδομένων',
+'unlockdb' => 'Ξεκλείδωμα βάσης δεδομένων',
+
+'lockdbtext' => 'Το κλείδωμα της βάσης δεδομένων αναιρεί τη δυνατότητα όλων των χρηστών να επεξεργαστούν σελίδες, να αλλάξουν τις προτιμήσεις τους, να επεξεργαστούν τις λίστες παρακολούθησης και να εκτελέσουν οποιαδήποτε ενέργεια επηρεάζει τη βάση δεδομένων. Παρακαλούμε να επιβεβαιώσετε ότι γνωρίζετε τις επιπτώσεις της ενέργειάς σας και ότι θα ξεκλειδώσετε τη βάση δεδομένων μόλις ολοκληρωθεί η συντήρηση.',
+
+'unlockdbtext' => 'Το ξεκλείδωμα της βάσης δεδομένων θα αποκαταστήσει τη δυνατότητα των χρηστών να επεξεργάζονται σελίδες, να αλλάζουν τις προτιμήσεις τους, να τροποποιούν τις λίστες παρακολούθησης και να προβαίνουν γενικότερα σε ενέργειες που επιφέρουν αλλαγές στη βάση δεδομένων. Παρακαλούμε επιβεβαιώστε πως θέλετε να προχωρήσετε.',
+
+'lockconfirm' => 'Ναι, επιθυμώ να κλειδώσω τη βάση δεδομένων.',
+'unlockconfirm' => 'Ναι, επιθυμώ να ξεκλειδώσω τη βάση δεδομένων.',
+'lockbtn' => 'Κλείδωμα βάσης δεδομένων',
+'unlockbtn' => 'Ξεκλείδωμα βάσης δεδομένων',
+'locknoconfirm' => 'Δεν έχετε σημειώσει το κουτάκι της επιβεβαίωσης.',
+'lockdbsuccesssub' => 'Η βάση δεδομένων κλειδώθηκε επιτυχώς.',
+'unlockdbsuccesssub' => 'Άρση κλειδώματος τη βάσης δεδομένων',
+
+
+# Make sysop
+#-------------------#
+'lockdbsuccesstext' => 'Η βάση δεδομένων έχει κλειδωθεί.
+<br />Μην ξεχάσετε να την ξεκλειδώσετε όταν τελειώσετε τη συντήρηση.',
+
+'makesysoptitle' => 'Κάντε ένα χρήστη διαχειριστή',
+
+'makesysoptext' => 'Η φόρμα αυτή απευθύνεται στους διαχειριστές και χρησιμεύει στο να χαρακτηρισθεί ένας χρήστης \'διαχειριστής\'. Πληκτρολογήστε το όνομα του χρήστη στο πεδίο κειμένου και επικυρώστε πατώντας το αντίστοιχο κουμπί.',
+
+'makesysopname' => 'Όνομα χρήστη:',
+'makesysopsubmit' => 'Κάνετε αυτό το χρήστη διαχειριστή',
+'makesysopok' => '<b>Ο χρήστης "$1" είναι εφεξής διαχειριστής</b>',
+'makesysopfail' => '<b>Ο χαρακτηρισμός του χρήστη "$1" σε διαχειριστή δεν ολοκληρώθηκε. (Βεβαιωθείτε πως δεν υπήρχαν λάθη στην πληκτρολόγηση του ονόματός του.)</b>',
+'setbureaucratflag' => 'Σηματοδότηση διαχειριστή (flag)',
+#'setstewardflag' => 'Set steward flag',
+'bureaucratlog' => 'Καταγραφές διαχειριστών',
+'rightslogtext' => 'Καταγραφές των αλλαγών στα δικαιώματα χρηστών.',
+'bureaucratlogentry' => 'Τα δικαιώματα του χρήστη "$1" είναι "$2"',
+'rights' => 'Δικαιώματα:',
+'set_user_rights' => 'Καθορισμός δικαιωμάτων χρήστη',
+'user_rights_set' => '<b>Τα δικαιώματα χρήστη για τον/την "$1" έχουν ενημερωθεί.</b>',
+'set_rights_fail' => '<b>Δεν ήταν δυνατή η ρύθμιση των δικαιωμάτων για το χρήστη "$1". Βεβαιωθείτε πως έχετε πληκτρολογήσει σωστά το όνομα.</b>',
+'makesysop' => 'Χαρακτηρισμός χρήστη ως διαχειριστή',
+'already_sysop' => 'Ο χρήστης αυτός είναι ήδη διαχειριστής.',
+'already_bureaucrat' => 'Ο χρήστης αυτός είναι ήδη διαχειριστής.',
+'already_steward' => 'Ο χρήστης αυτός είναι ήδη διαχειριστής.',
+
+
+# Validation
+#----------------#
+'val_yes' => 'Ναι',
+'val_no' => 'Όχι',
+'val_of' => '$1 από $2',
+'val_revision' => 'Αναθεώρηση',
+'val_time' => 'Χρόνος',
+'val_user_stats_title' => 'Επισκόπηση επικυρώσεων του χρήστη $1',
+'val_my_stats_title' => 'Επισκόπηση των επικυρώσεών μου',
+#'val_list_header' => '<th>#</th><th>Topic</th><th>Range</th><th>Action</th>',
+'val_add' => 'Προσθήκη',
+'val_del' => 'Διαγραφή',
+'val_show_my_ratings' => 'Εμφάνιση των επικυρώσεών μου',
+'val_revision_number' => 'Αναθεώρηση #$1',
+'val_warning' => '<b>Ποτέ, <i>ποτέ</i>, μην αλλάξετε κάτι εδώ χωρίς τη <i>ρητή</i> συναίνεση της κοινότητας!</b>',
+'val_rev_for' => 'Αναθεωρήσεις για την $1',
+'val_details_th_user' => 'Χρήστης $1',
+'val_validation_of' => 'Επικύρωση της "$1"',
+'val_revision_of' => 'Αναθεώρηση της $1',
+'val_revision_changes_ok' => 'Η βαθμολόγησή σας έχει αποθηκευθεί.!',
+'val_rev_stats' => 'Εμφάνιση των στατιστικών επικύρωσης για την "$1" <a href="$2">here</a>',
+'val_revision_stats_link' => 'λεπτομέρειες',
+'val_iamsure' => 'Σημειώστε σε αυτό το κουτάκι ότι πραγματικά το εννοείτε!',
+#'val_details_th' => '<sub>User</sub> \ <sup>Topic</sup>',
+'val_clear_old' => 'Εκκαθάριση των υπολοίπων δεδομένων επικύρωσης για $1',
+'val_merge_old' => 'Να χρησιμοποιηθεί η προηγούμενη αξιολόγησή μου όπου έχω δηλώσει \'χωρίς άποψη\'.',
+
+'val_form_note' => '<b>ΧΡΗΣΙΜΗ ΣΥΜΒΟΥΛΗ:</b> Ενσωμάτωση δεδομένων σημαίνει πως, για την αναθεώρηση του άρθρου που επιλέγετε, όλες οι επιλογές όπου έχετε δηλώσει \'χωρίς άποψη\' θα προσαρμοστούν στις αντίστοιχες επιλογές της τελευταίας έκδοσης για την οποία \'\'έχετε\'\' εκφράσει άποψη.  Αν για παράδειγμα θέλετε να αλλάξετε μια επιλογή μόνον σε μία αναθεώρηση αλλά θέλετε να διατηρήσετε τις άλλες ρυθμίσεις για αυτό το άρθρο σε αυτήν την αναθεώρηση, επιλέξτε απλώς ποια επιλογή προτίθεστε να \'\'αλλάξετε\'\'. Με την "ενσωμάτωση" θα συμπληρωθούν αυτόματα οι άλλες επιλογές από τις προηγούμενες ρυθμίσεις.',
+
+'val_noop' => 'Χωρίς άποψη',
+'val_topic_desc_page' => '{{ns:4}}:Θέματα_Επικύρωσης',
+'val_votepage_intro' => 'Αλλάξτε αυτό το κείμενο <a href="{{SERVER}}{{localurl:MediaWiki:Val_votepage_intro}}">εδώ</a>!',
+'val_percent' => '<b>$1%</b><br />($2 από $3 μονάδες<br />από $4 χρήστες)',
+'val_percent_single' => '<b>$1%</b><br />($2 από $3 μονάδες<br />από ένα χρήστη)',
+'val_total' => 'Σύνολο',
+'val_version' => 'Έκδοση',
+'val_tab' => 'Επικύρωση',
+'val_this_is_current_version' => 'αυτή είναι η τρέχουσα έκδοση',
+'val_version_of' => 'Έκδοση της $1',
+'val_table_header' => '<tr><th>Κλάση</th>$1<th colspan=4>Πρόταση</th>$1<th>Σχόλιο</th></tr>',
+'val_stat_link_text' => 'Στατιστικές επικύρωσης αυτού του άρθρου',
+'val_view_version' => 'Εμφάνιση αυτής της έκδοσης',
+'val_validate_version' => 'Επικύρωση αυτής της έκδοση',
+'val_user_validations' => 'Ο χρήστης έχει επικυρώσει $1 σελίδα(-ες)',
+'val_no_anon_validation' => 'Πρέπει να συνδεθείτε ως χρήστης για να επικυρώσετε ένα άρθρο.',
+'val_validate_article_namespace_only' => 'Μόνο άρθρα μπορούν να επικυρωθούν.  Αυτή η σελίδα <i>δεν<i> ανήκει στην περιοχή των άρθρων.',
+'val_validated' => 'Επικυρώθηκε.',
+'val_article_lists' => 'Λίστα επικυρωμένων άρθρων',
+'val_page_validation_statistics' => 'Στατιστικές επικύρωσης σελίδας για την $1',
+
+
+
+# Move page
+#-----------------#
+'movepage' => 'Μετακίνηση σελίδας',
+
+'movepagetext' => 'Χρησιμοποιήστε τη φόρμα που ακολουθεί για να μετονομάσετε σελίδες και για να μεταφέρετε όλο το ιστορικό τους κάτω από το νέο όνομα. Κάτω από τον παλιό τίτλο της σελίδας θα παραμείνει μια σελίδα ανακατεύθυνσης στο νέο τίτλο. Οι τυχόν σύνδεσμοι που οδηγούσαν στην παλιά σελίδα δεν θα επηρεαστούν. Βεβαιωθείτε πως [[Special:Maintenance|ελέγξατε]] τα διπλά διαστήματα και τους κατεστραμένους συνδέσμους. Αναλαμβάνετε την ευθύνη να επιβεβαιώσετε ότι οι συνδεσμοι εξακολουθούν να οδηγούν προς τις κατευθύνσεις που πρέπει.
+
+Λάβετε υπ` όψη σας ότι η σελίδα \'\'\'δεν\'\'\' θα μετακινηθεί αν υπάρχει ήδη μια άλλη σελίδα κάτω από το νέο τίτλο, εκτός αν η σελίδα αυτή είναι κενή \'\'\'και\'\'\' χωρίς ιστορικό επεξεργασίας. Αυτό σημαίνει ότι, στην περίπτωση που έχετε κάνει λάθος, μπορείτε να μετονομάσετε μια σελίδα ξαναδίνοντας της την αρχική της ονομασία αλλά δεν μπορείτε να αντικαταστήσετε μια υπάρχουσα σελίδα. 
+
+
+<b>ΠΡΟΣΟΧΗ!</b>
+Η μετονομασία σελίδας είναι μια αιφνίδια και δραστική αλλαγή όταν πρόκειται για δημοφιλείς σελίδες. Παρακαλούμε, πριν το αποφασίσετε, να εξετάσετε προσεκτικά τις πιθανές επιπτώσεις αυτής της ενέργειας .',
+
+'movepagetalktext' => 'Η σελίδα συζήτησης που αντιστοιχεί, εάν υπάρχει, θα μετακινηθεί αυτόματα μαζί με αυτήν \'\'\'έκτός αν:\'\'\'
+*Μετακινείτε τη σελίδα σε διαφορετική περιοχή (namespace),
+*Υπάρχει κάτω από το νέο όνομα μια σελίδα συζήτησης που δεν είναι κενή, ή 
+*Έχετε αφαιρέσει τη σημείωση (check) από το κουτάκι που υπάρχει παρακάτω.
+
+Σε αυτές τις περιπτώσεις, θα πρέπει να μετακινήσετε (ή να ενσωματώσετε αν το θέλετε) τη σελίδα με αντιγραφή-και-επικόλληση.',
+
+'movearticle' => 'Μετακίνηση σελίδας',
+'movenologin' => 'Δεν έχετε συνδεθεί.',
+'movenologintext' => 'Για να μετακινήσετε μια σελίδα πρέπει να είστε εγγεγραμένος χρήστης και [[Special:Userlogin|να έχετε συνδεθεί]] στο Wiκi.',
+'newtitle' => 'νέος τίτλος',
+'movepagebtn' => 'Μετακίνηση σελίδας',
+'pagemovedsub' => 'Η μετακίνηση ήταν επιτυχής',
+'pagemovedtext' => 'Η σελίδα "[[$1]]" μετακινήθηκε στη "[[$2]]".',
+'articleexists' => 'Υπάρχει ήδη σελίδα με αυτό το όνομα. Παρακαλούμε δώστε άλλο όνομα στη σελίδα.',
+'talkexists' => 'Η ίδια η σελίδα μετακινήθηκε επιτυχώς αλλά όχι και η σελίδα συζήτησης, λόγω του ότι υπάρχει ήδη άλλη σελίδα συζήτησης κάτω από το νέο τίτλο. Παρακαλούμε ενοποιήστε τις δύο σελίδες με \'αντιγραφή-και-επικόλληση\'.',
+'movedto' => 'Μεκακινήθηκε στο',
+'movetalk' => 'Μετακίνηση της σελίδας "συζήτηση" (εάν υπάρχει)',
+'talkpagemoved' => 'Η αντίστοιχη σελίδα συζήτησης έχει επίσης μεταφερθεί.',
+'talkpagenotmoved' => 'Η σελίδα συζήτησης που αντιστοιχεί <strong>δεν</strong> έχει μεταφερθεί.',
+'1movedto2' => 'Η $1 μετονομάστηκε σε $2',
+'1movedto2_redir' => 'Η $1 μετακινήθηκε στη θέση $2 (με ανακατεύθυνση)',
+'movelogpage' => '΄Μετακίνηση αρχείου καταγραφών',
+'movelogpagetext' => 'Ακολουθεί η λίστα με τις σελίδες που έχουν μετακινηθεί.',
+'movereason' => 'Αιτιολογία',
+'revertmove' => 'έπαναφορά',
+'delete_and_move' => 'Διαγραφή και μετακίνηση',
+
+'delete_and_move_text' => '==Χρειάζεται διαγραφή.==
+
+Το άρθρο [[$1]] υπάρχει ήδη. Θέλετε να το διαγράψετε για να εκτελεσθεί η μετακίνηση;',
+
+'delete_and_move_reason' => 'Διαγράφτηκε για να εκτελεθεί η μετακίνηση.',
+'selfmove' => 'Ο τίτλος προέλευσης είναι ο ίδιος με τον τίτλο προορισμού -δεν είναι δυνατόν να μετακινηθεί μια σελίδα προς τον εαυτό της.',
+
+'immobile_namespace' => 'Ο τίτλος του προορισμού είναι ειδικού τύπου -δεν είναι δυνατή η μετακίνηση σελίδων σε εκείνη την περιοχή.',
+
+
+# Export
+#----------#
+'export' => 'Εξαγωγή σελίδων',
+
+'exporttext' => 'Μπορείτε να κάνετε εξαγωγή του κειμένου και του ιστορικού επεξεργασίας μιας συγκεκριμένης σελίδας (ή περισσοτέρων σελίδων που έχουν ομαδοποιηθεί με χρήση XML).  
+
+Για την εξαγωγή ολόκληρων άρθρων, συμπληρώστε τους τίτλους στο παρακάτω πλαίσιο (ένα τίτλο σε κάθε σειρά) και επιλέξτε ανάμεσα από το να εξαγάγετε μόνο την τρέχουσα έκδοση (με τις πληροφορίες της πιο πρόσφατης επεξεργασίας) ή εναλλακτικά και τις παλιότερες εκδόσεις (με τις αντίστοιχες καταγραφές στη σελιδα του ιστορικού).
+
+Στην τελευταία περίπτωση μπορείτε να κάνετε και χρήση συνδέσμου, π.χ. [[{{ns:Special}}:Export/Train]] για το άρθρο [[Train]].',
+
+'exportcuronly' => 'Να συμπεριληφθεί μόνον η τρέχουσα αναθεώρηση, όχι το πλήρες ιστορικό.',
+
+
+# Namespace 8 related
+#----------------------------------#
+'allmessages' => 'Όλα τα μηνύματα του συστήματος',
+'allmessagesname' => 'Όνομα',
+'allmessagesdefault' => 'Προκαθορισμένο κείμενο',
+'allmessagescurrent' => 'Παρόν κείμενο',
+'allmessagestext' => 'Η λίστα με όλα τα μηνύματα συστήματος που βρίσκονται στην περιοχή MediaWiki:',
+'allmessagesnotsupportedUI' => 'Η τρέχουσα γλώσσα διασύνδεσής σας <b>$1</b> δεν υποστηρίζεται από το Special:AllMessages σε αυτό τον ιστοχώρο.',
+'allmessagesnotsupportedDB' => 'Special:Το AllMessages δεν υποστηρίζεται επειδή το wgUseDatabaseMessages είναι απενεργοποιημένο.',
+
+
+# Thumbnails
+#------------------#
+'thumbnail-more' => 'Μεγέθυνση',
+'missingimage' => '<b>Αγνοούμενη εικόνα</b><br /><i>$1</i>',
+'filemissing' => 'Αγνοούμενο αρχείο',
+
+
+# Special:Import
+#----------------------#
+'import' => 'Εισαγωγή σελίδων',
+'importinterwiki' => 'Εισαγωγή από άλλο Wiki',
+'importtext' => 'Παρακαλούμε εξάγετε το αρχείο από το πηγαίο Wiki (χρησιμοποιώντας Special:Export), αποθηκεύστε το στο δίσκο του υπολογιστή σας και φορτώστε το από εκεί.',
+'importfailed' => 'Η εισαγωγή απέτυχε: $1',
+'importnotext' => 'Κενό (-ή) ή χωρίς κείμενο',
+'importsuccess' => 'Η εισαγωγή επέτυχε!',
+'importhistoryconflict' => 'Υπάρχει αντιφατικό ιστορικό αναθεωρήσεων (μπορεί να έχετε κάνει παλιότερα  εισαγωγή αυτής της σελίδας).',
+'importnosources' => 'Δεν έχουν καθοριστεί πηγές για την εισαγωγή από άλλο Wiki και η απευθείας φόρτωση στο ιστορικό έχει απενεργοποιηθεί.',
+
+
+# Keyboard access keys for power users
+#------------------------------------------------------------#
+'accesskey-search' => 'f',
+'accesskey-minoredit' => 'i',
+'accesskey-save' => 's',
+'accesskey-preview' => 'p',
+'accesskey-diff' => 'd',
+'accesskey-compareselectedversions' => 'v',
+
+
+# Tooltip help for some actions, most are in Monobook.js
+#--------------------------------------------------------------------------------------#
+'tooltip-search' => 'Αναζήτηση στο Wiki [alt-f]',
+'tooltip-minoredit' => 'Χαρακτηρήστε τις αλλαγές "μικρής κλίμακας" [alt-i]',
+'tooltip-save' => 'Αποθήκευση αλλαγών [alt-s]',
+'tooltip-preview' => 'Προεπισκόπηση - Παρακαλούμε να χρησιμοποιήτε αυτή την επιλογή πριν αποθηκεύσετε τις αλλαγές σας! [alt-p]',
+'tooltip-diff' => 'Προβολή των αλλαγών που κάνατε στο κείμενο. [alt-d]',
+'tooltip-compareselectedversions' => 'Εμφάνιση των διαφορών ανάμεσα στις δύο αναθεωρήσεις της σελίδας που έχετε επιλέξει. [alt-v]',
+'tooltip-watch' => 'Προσθήκη της σελίδας στη λίστα παρακολούθησης [alt-w]',
+
+
+# stylesheets
+#-------------------#
+'Monobook.css' => '/* edit this file to customize the monobook skin for the entire site */',
+#'Monobook.js' => '/* edit this file to change js things in the monobook skin */',
+
+
+# Metadata
+#---------------#
+'nodublincore' => 'Τα μεταδεδομένα RDF που αφορούν στο Dublin Core έχουν απενεργοποιηθεί σε αυτό τον server.',
+'nocreativecommons' => 'Τα μεταδεδομένα RDF που αφορούν στο Creative Commons έχουν απενεργοποιηθεί σε αυτό τον server.',
+'notacceptable' => 'Ο server του Wiki δεν μπορεί να αποδόσει δεδομένα σε μορφή που τα διαβάζει ο client',
+
+
+# Attribution
+#-----------------#
+'anonymous' => 'Ανώνυμος(-οι) χρήστης(-ες) του {{SITENAME}}',
+'siteuser' => '{{SITENAME}} χρήστης $1',
+'lastmodifiedby' => 'Η σελίδα αυτή τροποποιήθηκε τελευταία φορά στις  $1 από το χρήστη $2.',
+'and' => 'και',
+'othercontribs' => 'Βασισμένο στη δουλειά του/της $1',
+'others' => 'άλλοι',
+'siteusers' => '{{SITENAME}} χρήστης (-ες) $1',
+'creditspage' => 'Αναγνώριση συνεισφοράς στη σελίδα',
+'nocredits' => 'Δεν υπάρχουν πληροφορίες σχετικά με την αναγνώριση συνεισφοράς σε αυτή τη σελίδα.',
+
+
+# Spam protection
+#--------------------------#
+'spamprotectiontitle' => 'Φίλτρο προστασίας από spam',
+'spamprotectiontext' => 'Η σελίδα που επιχειρήσατε να αποθηκεύσετε απομονώθηκε από το φίλτρο spam. Αυτό οφείλεται, πιθανότατα, στην ύπαρξη ενός (ή περισσότερων) συνδέσμων προς εξωτερικές σελίδες.',
+'spamprotectionmatch' => 'Το φίλτρο spam έχει τεθεί σε ενέργεια εξ αιτίας του εξής κειμένου: $1',
+'subcategorycount' => 'Υπάρχουν $1 υποκατηγορίες σε αυτή την κατηγορία.',
+'subcategorycount1' => 'Υπάρχει $1 υποκατηγορία σε αυτή την κατηγορία.',
+'categoryarticlecount' => 'Υπάρχουν $1 άρθρα σε αυτή την κατηγορία.',
+'categoryarticlecount1' => 'Υπάρχει $1 άρθρο σε αυτή την κατηγορία.',
+
+'usenewcategorypage' => '1
+
+Τοποθετείστε ένα "0" στη θέση του πρώτου χαρακτήρα για να μην αλλάξει η διάταξη στη σελίδα κατηγοριών.',
+
+'listingcontinuesabbrev' => 'συνεχίζεται...',
+
+
+# Info page
+#---------------#
+'infosubtitle' => 'Πληροφορίες για τη σελίδα',
+'numedits' => 'Αριθμός επεξεργασιών (στο άρθρο): $1',
+'numtalkedits' => 'Αριθμός επεξεργασιών (στη σελίδα συζήτησης): $1',
+'numwatchers' => 'Αριθμός παρακολουθήσεων: $1',
+'numauthors' => 'Αριθμός διακριτών συγγραφέων (στο άρθρο): $1',
+'numtalkauthors' => 'Αριθμός διακριτών συγγραφέων (στη σελίδα συζήτησης): $1',
+
+
+# Math options
+#---------------------#
+'mw_math_png' => 'Απόδοση πάντα σε PNG',
+'mw_math_simple' => 'HTML αν είναι αρκετά απλό, διαφορετικά PNG',
+'mw_math_html' => 'HTML αν είναι δυνατόν, διαφορετικά PNG',
+'mw_math_source' => 'Να παραμείνει ως TeX (για text browsers)',
+'mw_math_modern' => 'Προτεινόμενο για σύγχρονους browser',
+'mw_math_mathml' => 'MathML όποτε είναι δυνατόν (πειραματικό)',
+
+
+# Patrolling
+#--------------#
+'markaspatrolleddiff' => 'Να σημειωθεί \'υπό παρακολούθηση\'',
+'markaspatrolledlink' => '<div class=\'patrollink\'>[$1]</div>',
+'markaspatrolledtext' => 'Να σημειωθεί αυτό το άρθρο ως \'υπό παρακολούθηση\'.',
+'markedaspatrolled' => 'Σημειωμένο ως \'υπό παρακολούθηση\'',
+'markedaspatrolledtext' => 'Η αναθεώρηση που έχει επιλεγεί έχει σημειωθεί ως \'υπό παρακολούθηση\'.',
+'rcpatroldisabled' => 'Η λειτουργία \'Παρακολούθηση Πρόσφατων Αλλαγών\' έχει απενεργοποιηθεί.',
+'rcpatroldisabledtext' => 'Η λειτουργία \'Παρακολούθηση Πρόσφατων Αλλαγών\' είναι αυτή τη στιγμή απενεργοποιημένη.',
+
+
+# Monobook.js: tooltips and access keys for monobook
+#------------------------------------------------------------------------------------#
+'Monobook.js' => '/* tooltips and access keys */
+ta = new Object();
+ta[\'pt-userpage\'] = new Array(\'.\',\'Η προσωπική μου σελίδα στο Wiκi\');
+ta[\'pt-anonuserpage\'] = new Array(\'.\',\'Η σελίδα χρήστη στον οποίο αντιστοιχεί η διεύθυνση IP που έχετε\');
+ta[\'pt-mytalk\'] = new Array(\'n\',\'Η σελίδα συζητήσεών μου\');
+ta[\'pt-anontalk\'] = new Array(\'n\',\'Συζήτηση σχετικά με τις αλλαγές που έγιναν από αυτή τη διεύθυνση IP\');
+ta[\'pt-preferences\'] = new Array(\'\',\'Οι προτιμήσεις μου\');
+ta[\'pt-watchlist\'] = new Array(\'l\',\'Η λίστα με τις σελίδες που παρακολουθείτε για αλλαγές\');
+ta[\'pt-mycontris\'] = new Array(\'y\',\'Κατάλογος των συνεισφορών μου\');
+ta[\'pt-login\'] = new Array(\'o\',\'Σας προτείνουμε να συνδεθείτε παρόλο που δεν είναι αναγκαίο.\');
+ta[\'pt-anonlogin\'] = new Array(\'o\',\'Σας προτείνουμε να συνδεθείτε παρόλο που δεν είναι αναγκαίο.\');
+ta[\'pt-logout\'] = new Array(\'o\',\'Αποσύνδεση\');
+ta[\'ca-talk\'] = new Array(\'t\',\'Συζήτηση για το παρόν άρθρο\');
+ta[\'ca-edit\'] = new Array(\'e\',\'Μπορείτε να επεξεργαστείτε αυτό το άρθρο. Χρησιμοποιείστε την "Προεπισκόπηση" πριν αποθηκεύσετε.\');
+ta[\'ca-addsection\'] = new Array(\'+\',\'Προσθέστε σχόλιο στη συζήτηση.\');
+ta[\'ca-viewsource\'] = new Array(\'e\',\'Αυτό το άρθρο είναι κλειδωμένο. Μπορείτε να δείτε τον πηγαίο κώδικά του.\');
+ta[\'ca-history\'] = new Array(\'h\',\'Παλιές αναθεωρήσεις του άρθρου.\');
+ta[\'ca-protect\'] = new Array(\'=\',\'Κλείδωμα αυτού του άρθρου\');
+ta[\'ca-delete\'] = new Array(\'d\',\'Διαγραφή αυτής της σελίδας\');
+ta[\'ca-undelete\'] = new Array(\'d\',\'Αποκαταστήστε τις αλλαγές που έγιναν σε αυτή τη σελίδα πριν διαγραφεί.\');
+ta[\'ca-move\'] = new Array(\'m\',\'Μετακινήστε αυτή τη σελίδα\');
+ta[\'ca-nomove\'] = new Array(\'\',\'Δεν έχετε εξουσιοδότηση να μετακινήσετε αυτή τη σελίδα.\');
+ta[\'ca-watch\'] = new Array(\'w\',\'Προσθήκη της σελίδας στη λίστα παρακολούθησης\');
+ta[\'ca-unwatch\'] = new Array(\'w\',\'Αφαίρεση της σελίδας από τη λίστα παρακολούθησης\');
+ta[\'search\'] = new Array(\'f\',\'Αναζήτηση στο WiKi\');
+ta[\'p-logo\'] = new Array(\'\',\'Αρχική σελίδα\');
+ta[\'n-mainpage\'] = new Array(\'z\',\'Δείτε την Αρχική σελίδα\');
+ta[\'n-portal\'] = new Array(\'\',\'Σχετικά με το Wiκi - πώς μπορείτε να βοηθήσετε, πού μπορείτε να απευθυνθείτε\');
+ta[\'n-currentevents\'] = new Array(\'\',\'Πληροφορίες για πρόσφατα γεγονότα\');
+ta[\'n-recentchanges\'] = new Array(\'r\',\'Η λίστα με τις πρόσφατες αλλαγές στο WiKi\');
+ta[\'n-randompage\'] = new Array(\'x\',\'Επισκεφθείτε μια τυχαία σελίδα του Wiκi\');
+ta[\'n-help\'] = new Array(\'\',\'Το μέρος για να βρείτε τις απαντήσεις που ψάχνετε.\');
+ta[\'n-sitesupport\'] = new Array(\'\',\'Βοηθήστε το έργο.\');
+ta[\'t-whatlinkshere\'] = new Array(\'j\',\'Λίστα από άρθρα που αναφέρουν το παρόν άρθρο\');
+ta[\'t-recentchangeslinked\'] = new Array(\'k\',\'Πρόσφατες αλλαγές σε άρθρα που συνδέονται με το παρόν\');
+ta[\'feed-rss\'] = new Array(\'\',\'RSS feed για\' αυτή την σελίδα\');
+ta[\'feed-atom\'] = new Array(\'\',\'Atom feed για\' αυτή την σελίδα\');
+ta[\'t-contributions\'] = new Array(\'\',\'Δείτε τη λίστα με τις συνεισφορές αυτού του χρήστη στο Wiκi\');
+ta[\'t-emailuser\'] = new Array(\'\',\'Αποστολή μηνύματος σε αυτό το χρήστη\');
+ta[\'t-upload\'] = new Array(\'u\',\'Φόρτωση εικόνας ή αρχείου πολυμέσων\');
+ta[\'t-specialpages\'] = new Array(\'q\',\'Η λίστα με όλες τις σελίδες λειτουργιών\');
+ta[\'ca-nstab-main\'] = new Array(\'c\',\'Άρθρο\');
+ta[\'ca-nstab-user\'] = new Array(\'c\',\'Δείτε τη σελίδα του χρήστη\');
+ta[\'ca-nstab-media\'] = new Array(\'c\',\'Δείτε τη σελίδα πολυμέσων\');
+ta[\'ca-nstab-special\'] = new Array(\'\',\'Αυτή είναι ειδική σελίδα και δεν μπορείτε να την επεξεργαστείτε.\');
+ta[\'ca-nstab-wp\'] = new Array(\'a\',\'Δείτε τη σελίδα του συστήματος\');
+ta[\'ca-nstab-image\'] = new Array(\'c\',\'Δείτε την εικόνα\');
+ta[\'ca-nstab-mediawiki\'] = new Array(\'c\',\'Δείτε το μήνυμα του συστήματος\');
+ta[\'ca-nstab-template\'] = new Array(\'c\',\'Δείτε το πρότυπο\');
+ta[\'ca-nstab-help\'] = new Array(\'c\',\'Δείτε τη σελίδα βοήθειας\');
+ta[\'ca-nstab-category\'] = new Array(\'c\',\'Δείτε τη σελίδα κατηγοριών\');',
+
+
+# image deletion
+#------------------------#
+'deletedrevision' => 'Η παλιά έκδοση της $1 διαγράφτηκε.',
+
+
+# browsing diffs
+#----------------------#
+'previousdiff' => '&larr; Δείτε την προηγούμενη \'διαφορά\'',
+'nextdiff' => 'Μετάβαση στην επόμενη \'διαφορά\' &rarr;',
+
+'imagemaxsize' => 'Περιορισμός του μεγέθους των εικόνων (στις σελίδες περιγραφής εικόνων) σε:',
+'thumbsize'    => 'Μεγεθος μινιατούρας:',
+'showbigimage' => 'Κατέβασμα του αρχείου υψηλής ανάλυσης ($1x$2, $3 KB)',
+
+'newimages' => 'Πινακοθήκη νέων εικόνων',
+'noimages' => 'Δεν υπάρχουν εικόνες.',
+
+
+# short names for language variants used for language conversion links.
+# to disable showing a particular link, set it to 'disable', e.g.
+# 'variantname-zh-sg' => 'disable',
+'variantname-zh-cn' => 'cn',
+'variantname-zh-tw' => 'tw',
+'variantname-zh-hk' => 'hk',
+'variantname-zh-sg' => 'sg',
+'variantname-zh' => 'zh',
+
+
+# labels for User: and Title: on Special:Log pages
+#--------------------------------------------------------------------------#
+'specialloguserlabel' => 'Χρήστης:',
+'speciallogtitlelabel' => 'Τίτλος:',
+'passwordtooshort' => 'Ο κωδικός σας είναι πολύ σύντομος. Πρέπει να περιέχει τουλάχιστον $1 χαρακτήρες.',
+
+# Media Warning
+#-----------------------#
+'mediawarning' => '\'\'\'Προειδοποίηση\'\'\': Το αρχείο αυτό μπορεί να περιέχει κακοπροαίρετο κώδικα που μπορεί να βλάψει το σύστημα του υπολογιστή σας.
+
+<hr>',
+
+'fileinfo' => '$1KB, MIME type: <code>$2</code>',
+
+# Metadata
+#---------------#
+'metadata' => 'Μεταδεδομένα',
+
+
+# Exif tags
+#-------------#
+'exif-imagewidth' => 'Πλάτος',
+'exif-imagelength' => 'Υψος',
+'exif-bitspersample' => 'Bits ανά στοιχείο',
+'exif-compression' => 'Σχήμα συμπίεσης',
+'exif-photometricinterpretation' => 'Σύνθεση των pixel ',
+'exif-orientation' => 'Προσαντολισμός',
+'exif-samplesperpixel' => 'Αριθμός στοιχείων',
+'exif-planarconfiguration' => 'Διάταξη δεδομένων',
+'exif-ycbcrsubsampling' =>'Αναλογικό δείγμα σε φωτεινότητα και χρώμα',
+'exif-ycbcrpositioning' =>'Ρύθμιση φωτεινότητας και χρώματος',
+'exif-xresolution' => 'Οριζόντια ανάλυση',
+'exif-yresolution' => 'Κατακόρυφη ανάλυση',
+'exif-resolutionunit' => 'Μονάδα μέτρησης ανάλυσης X και Y',
+'exif-stripoffsets' => 'Τοποθέτηση δεδομένων εικόνας',
+'exif-rowsperstrip' =>'Αριθμός σειρών ανά λωρίδα',
+'exif-stripbytecounts' =>'Bytes ανά συμπιεσμένη λωρίδα',
+'exif-jpeginterchangeformat' => 'Μετάθεση σε JPEG SOI',
+'exif-jpeginterchangeformatlength' => 'Bytes δεδομένων JPEG',
+'exif-transferfunction' => 'Λειτουργία μεταφοράς',
+'exif-whitepoint' =>'Χρωματικός προσδιορισμός λευκού',
+'exif-primarychromaticities' =>'Πρωτεύοντες χρωματισμοί',
+'exif-ycbcrcoefficients' =>'Συντελεστές μητρών μετασχηματισμού χρώματος',
+'exif-referenceblackwhite' => 'Ζεύγος μαύρων και άσπρων αξιών αναφοράς',
+'exif-datetime' => 'Δηλώστε την ημερομηνία και την ώρα της επεξεργασίας.',
+'exif-imagedescription' => 'Τίτλος εικόνας',
+'exif-make' => 'Κατασκευαστής φωτογραφικής μηχανής',
+'exif-model' => 'Μοντέλο φωτογραφικής μηχανής',
+'exif-software' => 'Λογισμικό που χρησιμοποιήθηκε',
+'exif-artist' => 'Δημιουργός',
+'exif-copyright' => 'Ιδιοκτήτης του copyright',
+'exif-exifversion' => 'Έκδοση exif',
+'exif-flashpixversion' => 'Υποστηριζόμενη έκδοση Flashpix',
+'exif-colorspace' => 'Χρωματική περιοχή',
+'exif-componentsconfiguration' => 'Νόημα του κάθε στοιχείου',
+'exif-compressedbitsperpixel' => 'Κατάσταση συμπίεσης εικόνας',
+'exif-pixelydimension' => 'Έγκυρο πλάτος εικόνας',
+'exif-pixelxdimension' => 'Έγκυρο ύψος εικόνας',
+'exif-makernote' => 'Σημειώσεις του κατασκευαστή',
+'exif-usercomment' => 'Σχόλια χρήστη',
+'exif-relatedsoundfile' => 'Σχετικό αρχείο ήχου',
+'exif-datetimeoriginal' => 'Ημερομηνία και ώρα της παραγωγής ψηφιακών δεδομένων',
+'exif-datetimedigitized' => 'Ημερομηνία και ώρα της μετατροπής σε ψηφιακή μορφή',
+#'exif-subsectime' =>'DateTime subseconds',
+#'exif-subsectimeoriginal' =>'DateTimeOriginal subseconds',
+#'exif-subsectimedigitized' =>'DateTimeDigitized subseconds',
+'exif-exposuretime' => 'Χρόνος έκθεσης',
+'exif-fnumber' => 'Αριθμός F',
+'exif-exposureprogram' => 'Πρόγραμμα έκθεσης',
+'exif-spectralsensitivity' => 'Ευαισθησία φάσματος',
+'exif-isospeedratings' => 'Βαθμολόγηση ταχύτητας ISO',
+'exif-oecf' => 'Οπτικοηλεκτρονικός συντελεστής μετατροπής',
+'exif-shutterspeedvalue' => 'Ταχύτητα κλείστρου',
+'exif-aperturevalue' => 'Διάφραγμα',
+'exif-brightnessvalue' => 'Φωτεινότητα',
+'exif-exposurebiasvalue' => 'Προτεραιότητα έκθεσης',
+'exif-maxaperturevalue' => 'Μέγιστο διάφραγμα ξηράς',
+'exif-subjectdistance' => 'Απόσταση αντικειμένου',
+'exif-meteringmode' => 'Κατάσταση λειτουργίας φωτόμετρου',
+'exif-lightsource' => 'Πηγή φωτός',
+'exif-flash' => 'Φλας',
+'exif-focallength' => 'Εστιακή απόσταση του φακού',
+'exif-subjectarea' => 'Θεματική περιοχή',
+'exif-flashenergy' => 'Ενέργεια του φλας',
+'exif-spatialfrequencyresponse' =>'Χωρική απόκριση συχνότητας',
+'exif-focalplanexresolution' => 'Ανάλυση εστιακού επιπέδου Χ',
+'exif-focalplaneyresolution' => 'Ανάλυση εστιακού πειπέδου Υ',
+'exif-focalplaneresolutionunit' => 'Μονάδα μέτρησης ανάλυσης εστιακού επιπέδου',
+'exif-subjectlocation' => 'Τοποθέτηση του αντικειμένου',
+'exif-exposureindex' => 'Δείκτης έκθεσης',
+'exif-sensingmethod' => 'Μέθοδος αισθητήρα',
+'exif-filesource' => 'Πηγή αρχείου',
+'exif-scenetype' => 'Τύπος σκηνής',
+'exif-cfapattern' => 'CFA pattern',
+'exif-customrendered' => 'Ειδική επεξεργασία εικόνας',
+'exif-exposuremode' => 'Κατάσταση λειτουργίας έκθεσης',
+'exif-whitebalance' => 'Ισορροπία των λευκών',
+'exif-digitalzoomratio' => 'Αναλογία ψηφιακού zoom',
+'exif-focallengthin35mmfilm' => 'Εστιακή απόσταση σε φιλμ 35 mm',
+'exif-scenecapturetype' => 'Τύπος σύλληψης της σκηνής',
+'exif-gaincontrol' => 'Έλεγχος πεδίου',
+'exif-contrast' => 'Αντίθεση',
+'exif-saturation' => 'Κορεσμός',
+'exif-sharpness' => 'Όξυνση',
+'exif-devicesettingdescription' => 'Περιγραφή των ρυθμίσεων του μηχανήματος',
+'exif-subjectdistancerange' => 'Περιοχή διακύμανσης της απόστασης του αντικειμένου',
+'exif-imageuniqueid' => 'Μονοσήμαντη ταυτοποίηση εικόνας',
+'exif-gpsversionid' => 'Έκδοση με GPS tag',
+'exif-gpslatituderef' => 'Βόρειο ή Νότιο γεωγραφικό πλάτος',
+'exif-gpslatitude' => 'Γεωγραφικό πλάτος',
+'exif-gpslongituderef' => 'Ανατολικό ή Δυτικό γεωγραφικό μήκος',
+'exif-gpslongitude' => 'Γεωγραφικό μήκος',
+'exif-gpsaltituderef' => 'Αναφορές υψομέτρου',
+'exif-gpsaltitude' => 'Υψόμετρο',
+'exif-gpstimestamp' => 'Ώρα GPS (ατομικό ρολόι)',
+'exif-gpssatellites' => 'Δορυφόροι που χρησιμοποιήθηκαν για τις μετρήσεις',
+'exif-gpsstatus' => 'Κατάσταση δέκτη',
+'exif-gpsmeasuremode' => 'Τρόπος λειτουργίας μετρήσεων',
+'exif-gpsdop' => 'Ακρίβεια μέτρησης',
+'exif-gpsspeedref' => 'Μονάδα μέτρησης ταχύτητας',
+'exif-gpsspeed' => 'Ταχύτητα δέκτη GPS',
+'exif-gpstrackref' => 'Αναφορές για την κατεύθυνση της κίνησης',
+'exif-gpstrack' => 'Κατεύθυνση κίνησης',
+'exif-gpsimgdirectionref' => 'Αναφορές για την κατεύθυνση της εικόνας',
+'exif-gpsimgdirection' => 'Κατεύθυνση της εικόνας',
+'exif-gpsmapdatum' => 'Στοιχεία γεωδετικών μετρήσεων ΄που έχουν χρησιμοποιηθεί',
+'exif-gpsdestlatituderef' => 'Αναφορές για το γεωγραφικό πλάτος του προορισμού',
+'exif-gpsdestlatitude' => 'Αναφορές γεωγραφικού πλάτους',
+'exif-gpsdestlongituderef' => 'Αναφορές για το γεωγραφικό μήκος του προορισμού',
+'exif-gpsdestlongitude' => 'Γεωγραφικό πλάτος προορισμού',
+'exif-gpsdestbearingref' => 'Αναφορές για τις συντεταγμένες προορισμού',
+'exif-gpsdestbearing' => 'Συντεταγμένες προορισμού',
+'exif-gpsdestdistanceref' => 'Αναφορές για την απόσταση μέχρι τον προορισμό',
+'exif-gpsdestdistance' => 'Απόσταση μέχρι τον προορισμό',
+'exif-gpsprocessingmethod' => 'Όνομα μεθόδου επεξεργασίας GPS',
+'exif-gpsareainformation' => 'Όνομα περιοχής GPS',
+'exif-gpsdatestamp' => 'Ημερομηνία GPS',
+'exif-gpsdifferential' => 'Διαφορική διόρθωση GPS',
+
+
+# Make & model, can be wikified in order to link to the camera and model name
+
+'exif-make-value' => '$1',
+'exif-model-value' => '$1',
+'exif-software-value' => '$1',
+
+'exif-compression-1' => 'Έχει αποσυμπιεστεί.',
+'exif-compression-6' => 'JPEG',
+
+'exif-photometricinterpretation-1' => 'RGB',
+'exif-photometricinterpretation-6' => 'YCbCr',
+
+'exif-orientation-1' => 'Φυσικός', // 0th row: top; 0th column: left
+'exif-orientation-2' => 'Έχει αντιστραφεί οριζόντια.', // 0th row: top; 0th column: right
+'exif-orientation-3' => 'Έχει περιστραφεί κατά 180° μοίρες.', // 0th row: bottom; 0th column: right
+'exif-orientation-4' => 'Έχει αντιστραφεί κατακόρυφα.', // 0th row: bottom; 0th column: left
+'exif-orientation-5' => 'Έχει περιστραφεί κατά 90° μοίρες με φορά αντίθετα προς τη φορά των δεικτών του ρολογιού και έχει αντιστραφεί κατακόρυφα.', // 0th row: left; 0th column: top
+'exif-orientation-6' => 'Έχει περιστραφεί κατά 90° μοίρες κατά τη φορά των δεικτών του ρολογιού.', // 0th row: right; 0th column: top
+'exif-orientation-7' => 'Έχει περιστραφεί κατά 90° μοίρες κατά τη φορά των δεικτών του ρολογιού και έχει αντιστραφεί κατακόρυφα.',  // 0th row: right; 0th column: bottom
+'exif-orientation-8' => 'Έχει περιστραφή κατά 90° μοίρες αντίθετα προς τη φορά των δεικτών του ρολογιού.', // 0th row: left; 0th column: bottom
+
+'exif-planarconfiguration-1' => 'πεπλατυσμένος σχηματισμός',
+'exif-planarconfiguration-2' => 'επίπεδος σχηματισμός',
+
+'exif-xyresolution-i' => '$1 dpi',
+'exif-xyresolution-c' => '$1 dpc',
+
+'exif-colorspace-1' => 'sRGB',
+'exif-colorspace-ffff.h' => 'FFFF.H',
+'exif-componentsconfiguration-0' => 'δεν υπάρχει',
+'exif-componentsconfiguration-1' => 'Y',
+'exif-componentsconfiguration-2' => 'Cb',
+'exif-componentsconfiguration-3' => 'Cr',
+'exif-componentsconfiguration-4' => 'R',
+'exif-componentsconfiguration-5' => 'G',
+'exif-componentsconfiguration-6' => 'B',
+
+'exif-exposureprogram-0' => 'Δεν έχει προκαθοριστεί',
+'exif-exposureprogram-1' => 'Χειροκίνητο',
+'exif-exposureprogram-2' => 'Κανονικό πρόγραμμα',
+'exif-exposureprogram-3' => 'Προτεραιότητα διαφράγματος',
+'exif-exposureprogram-4' => 'Προτεραιότητα κλείστρου',
+'exif-exposureprogram-5' => 'Δημιουργικό πρόγραμμα (με προτεραιότητα το βάθος πεδίου)',
+'exif-exposureprogram-6' => 'Δημιουργικό πρόγραμμα (με προτεραιόττηα την ταχύτητα του κλείστρου)',
+'exif-exposureprogram-7' => 'Επιλογή λειτουργίας "πορτραίτου" (για φωτογραφίες closeup με το φόντο εκτός εστίασης)',
+'exif-exposureprogram-8' => 'Επιλογή λειτουργίας "τοπίου" (για φωτογραφίες τοπίου με εστιασμένο φόντο)',
+
+'exif-subjectdistance-value' => '$1 μέτρα',
+'exif-meteringmode-0' => 'Άγνωστη',
+'exif-meteringmode-1' => 'Μέση τιμή',
+'exif-meteringmode-2' => 'Μέση τιμή με έμφαση στο κέντρο',
+'exif-meteringmode-3' => 'Ένα σημείο',
+'exif-meteringmode-4' => 'Πολλά σημεία',
+'exif-meteringmode-5' => 'Μοτίβο',
+'exif-meteringmode-6' => 'Μερική',
+'exif-meteringmode-255' => 'Άλλο',
+'exif-lightsource-0' => 'Άγνωστη',
+'exif-lightsource-1' => 'Φως ημέρας',
+'exif-lightsource-2' => 'Φωσφορίζον',
+'exif-lightsource-3' => 'Tungsten (φωτισμός από λυχνίες πυράκτωσης)',
+'exif-lightsource-4' => 'Φλας',
+'exif-lightsource-9' => 'Αίθριος καιρός',
+'exif-lightsource-10' => 'Συννεφιά',
+'exif-lightsource-11' => 'Σκιά',
+'exif-lightsource-12' => 'Φως ημέρας φωσφορίζον (D 5700 – 7100K)',
+'exif-lightsource-13' => 'Λευκό φως ημέρας  (N 4600 – 5400K)',
+'exif-lightsource-14' => 'Κρύο λευκό φως fluorescent (W 3900 – 4500K)',
+'exif-lightsource-15' => 'Λευκό φως φωσφορίζον (WW 3200 – 3700K)',
+'exif-lightsource-17' => 'Τυποποιημένος φωτισμός A',
+'exif-lightsource-18' => 'Τυποποιημένος φωτισμός B',
+'exif-lightsource-19' => 'Τυποποιημένος φωτισμός C',
+'exif-lightsource-20' => 'D55',
+'exif-lightsource-21' => 'D65',
+'exif-lightsource-22' => 'D75',
+'exif-lightsource-23' => 'D50',
+#'exif-lightsource-24' => 'ISO studio tungsten',
+'exif-lightsource-255' => 'Άλλη πηγή φωτός',
+
+'exif-focalplaneresolutionunit-2' => 'ίντσες',
+
+'exif-sensingmethod-1' => 'Δεν έχει καθοριστεί',
+'exif-sensingmethod-2' => 'One-chip color area sensor',
+'exif-sensingmethod-3' => 'Two-chip color area sensor',
+'exif-sensingmethod-4' => 'Three-chip color area sensor',
+'exif-sensingmethod-5' => 'Color sequential area sensor',
+'exif-sensingmethod-7' => 'Trilinear sensor',
+'exif-sensingmethod-8' => 'Color sequential linear sensor',
+
+'exif-filesource-3' => 'DSC',
+'exif-scenetype-1' => 'Εικόνα που φωτογραφήθηκε απ` ευθείας',
+
+'exif-customrendered-0' => 'Κανονική επεξεργασία',
+'exif-customrendered-1' => 'Ειδική επεξεργασία',
+
+'exif-exposuremode-0' => 'Αυτόματη έκθεση',
+'exif-exposuremode-1' => 'Χειροκίνητη έκθεση',
+'exif-exposuremode-2' => 'Αυτόματο bracket',
+
+'exif-whitebalance-0' => 'Αυτόματη ισορροπία των λευκών',
+'exif-whitebalance-1' => 'Χειροκίνητη ισορροπία των λευκών',
+
+'exif-scenecapturetype-0' => 'Συνήθης',
+'exif-scenecapturetype-1' => 'Τοπίο',
+'exif-scenecapturetype-2' => 'Πορτραίτο',
+'exif-scenecapturetype-3' => 'Νυκτερινή σκηνή',
+
+'exif-gaincontrol-0' => 'Κανένα',
+'exif-gaincontrol-1' => 'Χαμηλό κέρδος επάνω',
+'exif-gaincontrol-2' => 'Υψηλό κέρδος επάνω',
+'exif-gaincontrol-3' => 'Χαμηλό κέρδος κάτω',
+'exif-gaincontrol-4' => 'Υψηλό κέρδος κατω',
+
+'exif-contrast-0' => 'Φυσικό',
+'exif-contrast-1' => 'Απαλό',
+'exif-contrast-2' => 'Ισχυρό',
+
+'exif-saturation-0' => 'Φυσικός',
+'exif-saturation-1' => 'Χαμηλός κορεσμός',
+'exif-saturation-2' => 'Υψηλός κορεσμός',
+
+'exif-sharpness-0' => 'Φυσική',
+'exif-sharpness-1' => 'Απαλή',
+'exif-sharpness-2' => 'Σκληρή',
+
+'exif-subjectdistancerange-0' => 'Άγνωστη',
+'exif-subjectdistancerange-1' => 'Macro',
+'exif-subjectdistancerange-2' => 'Κοντινή λήψη',
+'exif-subjectdistancerange-3' => 'Μακρίνή λήψη',
+
+// Pseudotags used for GPSLatitudeRef and GPSDestLatitudeRef
+'exif-gpslatitude-n' => 'Βόρειο γεωγραφικό πλάτος',
+'exif-gpslatitude-s' => 'Νότιο γεωγραφικό πλάτος',
+
+// Pseudotags used for GPSLongitudeRef and GPSDestLongitudeRef
+'exif-gpslongitude-e' => 'Ανατολικό γεωγραφικό μήκος',
+'exif-gpslongitude-w' => 'Δυτικό γεωγραφικό μήκος',
+
+'exif-gpsstatus-a' => 'Μέτρηση εν εξελίξει',
+'exif-gpsstatus-v' => 'Διαλειτουργικότητα μετρήσεων',
+
+'exif-gpsmeasuremode-2' => 'μέτρηση δύο διαστάσεων',
+'exif-gpsmeasuremode-3' => 'μέτρηση τριών διαστάσεων',
+
+// Pseudotags used for GPSSpeedRef and GPSDestDistanceRef
+'exif-gpsspeed-k' => 'Χιλιόμετρα/ώρα',
+'exif-gpsspeed-m' => 'Μίλια/ώρα',
+'exif-gpsspeed-n' => 'Κόμβοι',
+
+// Pseudotags used for GPSTrackRef, GPSImgDirectionRef and GPSDestBearingRef
+'exif-gpsdirection-t' => 'Πραγματική κατεύθυνση',
+'exif-gpsdirection-m' => 'Μαγνητική κατεύθυνση',
+
+
+# external editor support
+#-------------------------------------#
+'edit-externally' => 'Επεξεργαστείτε το συγκεκριμένο αρχείο χρησιμοποιώντας μια από τις εξωτερικές εφαρμογές.',
+'edit-externally-help' => 'Για περισσότερες πληροφορίες ακολουθήστε το σύνδεσμο: [http://meta.wikimedia.org/wiki/Help:External_editors setup instructions].',
+
+
+# 'all' in various places, this might be different for inflicted languages
+#---------------------------------------------------------------------------------------------------------#
+'recentchangesall' => 'όλες',
+'imagelistall' => 'όλες',
+'watchlistall1' => 'όλες',
+'watchlistall2' => 'όλες',
+'contributionsall' => 'όλες',
+
+
+# E-mail address confirmation
+#--------------------------------------------#
+'confirmemail' => 'Επαλήθευση διεύθυνσης e-mail',
+
+'confirmemail_text' => 'Το σύστημα χρειάζεται να επαληθεύσει τη διεύθυνση e-mail που δώσατε για να χρησιμοποιήσετε τις δυνατότητες αλληλογραφίας. Κάνετε κλικ στο παρακάτω κουμπί και θα σας αποσταλεί μήνυμα επαλήθευσης στη διεύθυνσή σας. Στο μήνυμα αυτό θα εμφανίζεται ένας σύνδεσμος που Θα περιέχει τον κωδικό επαλήθευσης -ακολουθήστε το σύνδεσμο αυτό για να μπορέσει το σύστημα να επαληθεύσει τη διεύθυνση αλληλογραφίας σας.',
+
+'confirmemail_send' => 'Αποστολή κωδικού επαλήθευσης με e-mail .',
+'confirmemail_sent' => 'Το μήνυμα επαλήθευσης έχει σταλεί, ελέγξτε την αλληλογραφία σας.',
+'confirmemail_sendfailed' => 'Δεν ήταν δυνατή η αποστολή του μηνύματος επαλήθευσης. Ελέγξτε την ηλεκτρονική διεύθυνση που συμπληρώσατε για πιθανά λάθη πληκτρολόγησης.',
+'confirmemail_invalid' => 'Λάθος κωδικός επαλήθευσης. Είναι πιθανόν ο κωδικός σας να έχει λήξει.',
+'confirmemail_success' => 'Η ηλεκτρονική σας διεύθυνση σας επαληθεύτηκε. Μπορείτε πλέον να συνδεθείτε και να απολαύσετε τις δυνατότητες του Wiκi.',
+'confirmemail_loggedin' => 'Η ηλεκτρονική σας διεύθυνση επαληθεύτηκε.',
+'confirmemail_error' => 'Παρουσιάστηκε λάθος κατά την αποθήκευση των ρυθμίσεών σας.',
+'confirmemail_subject' => 'Επαλήθευση ηλεκτρονικής διεύθυνσης του {{SITENAME}}',
+
+'confirmemail_body' =>  'Κάποιος, πιθανόν εσείς από τη διεύθυνση IP $1, δημιούργησε στο {{SITENAME}} ένα λογαριασμό χρήστη "$2" με τη συγκεκριμένη ηλεκτρονική διεύθυνση. 
+
+Για να επιβεβαιώσετε ότι αυτός ο λογαριασμός χρήστη ανήκει πραγματικά σε εσάς και για να ενεργοποιηθούν οι δυνατότητες e-mail του {{SITENAME}}, ακολουθήστε αυτό το σύνδεσμο:
+
+$3
+
+Αν ο χρήστης που δημιούργησε το συγκεκριμένο λογαριασμό δεν είστε εσείς, μην ακολουθήστε το σύνδεσμο. Ο κωδικός επιβεβαίωσης θα λήξει στις $4',
+
+
+
+# Inputbox extension, may be useful in other contexts as well
+#----------------------------------------------------------------------------------------------#
+'tryexact' => 'Δοκιμάστε την επακριβή αντιστοιχία.',
+'searchfulltext' => 'Αναζήτηση με το πλήρες κείμενο',
+'createarticle' => 'Δημιουργία άρθρου',
+
+
+# Scary transclusion
+#------------------------------#
+'scarytranscludedisabled' => '[Η ενσωμάτωση εξωτερικών ιστοσελίδων σε αυτό το Wiki είναι απενεργοποιημένη.]',
+'scarytranscludefailed' => '[Λυπούμαστε, η προσκόμιση προτύπου για το $1 απέτυχε.]',
+'scarytranscludetoolong' => '[Λυπούμαστε η διεύθυνση URL είναι πολύ μεγάλη.]',
+
+
+# Trackbacks
+#------------------#
+/*'trackbackbox' => '<div id=\'mw_trackbacks\'>
+Trackbacks for this article:<br/>
+$1
+</div>',
+*/
+'trackback' => '; $4$5 : [$2 $1]',
+'trackbackexcerpt' => '; $4$5 : [$2 $1]: <nowiki>$3</nowiki>',
+'trackbackremove' => ' ([$1΄- Διαγραφή])',
+'trackbacklink' => 'Επιστροφή για αναζήτηση',
+'trackbackdeleteok' => 'Η επιστροφή για αναζήτηση έχει διαγραφεί επιτυχώς.',
+
+
+);
+
+/** @package MediaWiki */
+class LanguageEl extends LanguageUtf8 {
+
+       function getNamespaces() {
+               global $wgNamespaceNamesEl;
+               return $wgNamespaceNamesEl;
+       }
+       
+       function getMessage( $key ) {
+               global $wgAllMessagesEl;
+
+               return isset( $wgAllMessagesEl[$key] ) ? $wgAllMessagesEl[$key] : parent::getMessage( $key );
+       }
+       
+       function fallback8bitEncoding() {
+               return 'iso-8859-7';
+       }
+       
+       function formatNum( $number, $year = false ) {
+               return $year ? $number : strtr($this->commafy( $number ), '.,', ',.' );
+       }
+}
+
+?>
diff --git a/languages/LanguageEn.php b/languages/LanguageEn.php
new file mode 100644 (file)
index 0000000..3feba17
--- /dev/null
@@ -0,0 +1,16 @@
+<?php
+/** English (English)
+  *
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+/** */
+require_once( 'LanguageUtf8.php' );
+
+/** @package MediaWiki */
+class LanguageEn extends LanguageUtf8 {
+       # Inherit everything
+}
+
+?>
diff --git a/languages/LanguageEo.php b/languages/LanguageEo.php
new file mode 100644 (file)
index 0000000..4297f7b
--- /dev/null
@@ -0,0 +1,1024 @@
+<?php
+/** Esperanto (Esperanto)
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+/** */
+require_once('LanguageUtf8.php');
+
+/* private */ $wgNamespaceNamesEo = array(
+       NS_MEDIA          => 'Media',
+       NS_SPECIAL        => 'Speciala',
+       NS_MAIN           => '',
+       NS_TALK           => 'Diskuto',
+       NS_USER           => 'Vikipediisto',
+       NS_USER_TALK      => 'Vikipediista_diskuto',
+       NS_PROJECT            => $wgMetaNamespace, # FIXME: Generalize v-isto kaj v-io
+       NS_PROJECT_TALK   => $wgMetaNamespace.'_diskuto', # FIXME
+       NS_IMAGE          => 'Dosiero', #FIXME: Check the magic for Image: and Media:
+       NS_IMAGE_TALK     => 'Dosiera_diskuto',
+       NS_MEDIAWIKI      => 'MediaWiki',
+       NS_MEDIAWIKI_TALK => 'MediaWiki_diskuto',
+       NS_TEMPLATE       => 'Ŝablono',
+       NS_TEMPLATE_TALK  => 'Ŝablona_diskuto',
+       NS_HELP           => 'Helpo',
+       NS_HELP_TALK      => 'Helpa_diskuto',
+       NS_CATEGORY       => 'Kategorio',
+       NS_CATEGORY_TALK  => 'Kategoria_diskuto',
+
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgQuickbarSettingsEo = array(
+       'Nenia', 'Fiksiĝas maldekstre', 'Fiksiĝas dekstre', 'Ŝvebas maldekstre'
+);
+
+/* private */ $wgSkinNamesEo = array(
+       'standard' => 'Klasika',
+       'nostalgia' => 'Nostalgio',
+       'cologneblue' => 'Kolonja Bluo',
+       'mono' => 'Senkolora',
+       'monobook' => 'Librejo',
+       'chick' => 'Kokido',
+) + $wgSkinNamesEn;
+
+
+
+# Se eble, trovu Esperantajn libroservoj traserĉeblaj laŭ ISBN
+# $wgBookstoreListEo = ..
+
+
+/* private */ $wgAllMessagesEo = array(
+# User toggles
+'tog-underline' => 'Substreku ligilojn',
+'tog-highlightbroken' => 'Ruĝigu ligilojn al neekzistantaj paĝoj',
+'tog-justify'  => 'Alkadrigu liniojn',
+'tog-hideminor' => 'Kaŝu malgrandajn redaktetojn ĉe <i>Lastaj ŝanĝoj</i>',
+'tog-usenewrc'  => 'Novstila Lastaj Ŝanĝoj (bezonas JavaSkripton)',
+'tog-numberheadings' => 'Aŭtomate numeru sekciojn',
+'tog-showtoolbar' => 'Show edit toolbar',
+'tog-editondblclick' => 'Redaktu per duobla alklako (JavaScript)',
+'tog-editsection' => 'Montru [redaktu]-ligiloj por sekcioj',
+'tog-editsectiononrightclick' => 'Redaktu sekciojn per dekstra musklako',
+'tog-showtoc' => 'Montru liston de enhavoj',
+'tog-rememberpassword' => 'Memoru mian pasvorton',
+'tog-editwidth' => 'Redaktilo estu plenlarĝa',
+'tog-watchdefault' => 'Priatentu paĝojn de vi redaktintajn',
+'tog-minordefault' => 'Marku ĉiujn redaktojn malgrandaj',
+'tog-previewontop' => 'Montru antaŭrigardon antaŭ redaktilo',
+'tog-altencoding' => 'Montru supersignojn X-sisteme', # FIXME: forpreni cxi tiun; estas cimoplena
+# Dates
+
+'sunday' => 'dimanĉo',
+'monday' => 'lundo',
+'tuesday' => 'mardo',
+'wednesday' => 'merkredo',
+'thursday' => 'ĵaŭdo',
+'friday' => 'vendredo',
+'saturday' => 'sabato',
+'january' => 'januaro',
+'february' => 'februaro',
+'march' => 'marto',
+'april' => 'aprilo',
+'may_long' => 'majo',
+'june' => 'junio',
+'july' => 'julio',
+'august' => 'aŭgusto',
+'september' => 'septembro',
+'october' => 'oktobro',
+'november' => 'novembro',
+'december' => 'decembro',
+'jan' => 'Jan',
+'feb' => 'Feb',
+'mar' => 'Mar',
+'apr' => 'Apr',
+'may' => 'Maj',
+'jun' => 'Jun',
+'jul' => 'Jul',
+'aug' => 'Aŭg',
+'sep' => 'Sep',
+'oct' => 'Okt',
+'nov' => 'Nov',
+'dec' => 'Dec',
+
+# Teksteroj uzataj fare de diversaj paĝoj:
+#
+'categories' => 'Kategorioj',
+'category' => 'kategorio',
+'category_header' => 'Artikoloj en kategorio "$1"',
+'subcategories' => 'Subkategorioj',
+
+# Tiuj literoj, kiuj aperu kiel parto de la ligilo en formo "[[lingvo]]jn" ktp:
+'linktrail'     => '/^([a-z]+)(.*)\$/sD',
+'mainpage'             => 'Ĉefpaĝo',
+'about'                        => 'Enkonduko',
+'aboutsite'      => 'Pri {{SITENAME}}', #FIXME
+'aboutpage'            => '{{ns:4}}:Enkonduko',
+'article'              => 'Artikolo',
+'help'                 => 'Helpo',
+'helppage'             => '{{ns:4}}:Helpo',
+'bugreports'   => 'Raportu cimojn',
+'bugreportspage' => '{{ns:4}}:Raportu_cimojn',
+'sitesupport'   => 'Subteno',
+'faq'                  => 'Oftaj demandoj',
+'faqpage'              => '{{ns:4}}:Oftaj demandoj',
+'edithelp'             => 'Helpo pri redaktado',
+'newwindow'            => '(en nova fenestro)',
+'edithelppage' => '{{ns:4}}:Kiel_redakti_paĝon', #FIXME: Kontrolu
+'cancel'               => 'Nuligu',
+'qbfind'               => 'Trovu',
+'qbbrowse'             => 'Foliumado', # FIXME
+'qbedit'               => 'Redaktado', #FIXME
+'qbpageoptions' => 'Paĝagado', #FIXME
+'qbpageinfo'   => 'Paĝinformoj', #FIXME
+'qbmyoptions'  => 'Personaĵoj', #FIXME
+'qbspecialpages'       => 'Specialaj paĝoj',
+'moredotdotdot'        => 'Pli...',
+'mypage'               => 'Mia paĝo', #FIXME
+'mytalk'        => 'Mia diskuto',
+'currentevents' => 'Aktualaĵoj', #FIXME - Novaĵoj? Aktualaj novaĵoj? Aktualaj eventoj?
+'errorpagetitle' => 'Eraro', #FIXME - Arero? ;)
+'returnto'             => 'Revenu al $1.',
+'tagline'              => 'El {{SITENAME}}, la libera enciklopedio.',
+'whatlinkshere'        => 'Paĝoj kiuj ligas ĉi tien',
+'help'                 => 'Helpo',
+'search'               => 'Serĉu',
+'go'                   => 'Ek',
+'history'              => 'Malnovaj versioj',
+'history_short'        => 'Historio',
+'printableversion' => 'Presebla versio',
+'editthispage' => 'Redaktu la paĝon',
+'deletethispage' => 'Forigu la paĝon',
+'protectthispage' => 'Protektu la paĝon', #FIXME: Ĉu 'gardu' / 'protekti' bonas /Bertilo
+'unprotectthispage' => 'Malprotektu la paĝon', #FIXME: ĉu 'malgardu', 'ne plu', ktp? / '(mal)gardi' ne estas bona /Bertilo
+'newpage'              => 'Nova paĝo',
+'talkpage'             => 'Diskutu la paĝon',
+'postcomment'   => 'Afiŝu komenton',
+'articlepage'  => 'Vidu la artikolon',
+'subjectpage'  => 'Vidu la artikolon', #FIXME: ?
+'talk'                 => 'Diskuto',
+'toolbox'              => 'Iloj',
+'userpage'             => 'Vidu personan paĝon',
+'wikipediapage'        => 'Vidu meta-paĝon',
+'imagepage'            => 'Vidu dosieropaĝon',
+'viewtalkpage' => 'Vidu diskutopaĝon',
+'otherlanguages' => 'Aliaj lingvoj',
+'redirectedfrom' => '(Alidirektita el $1)',
+'lastmodified' => 'Laste redaktita je $1.',
+'viewcount'            => 'Montrita $1-foje.',
+'printsubtitle' => '(El {{SERVER}})',
+'protectedpage' => 'Protektita paĝo', #FIXME: ĉu 'gardita' ktp?
+'administrators' => '{{ns:4}}:Administrantoj', # FIXME?
+'sysoptitle'   => 'Konto de administranto bezonatas',
+'sysoptext'            => 'La ago kiun vi petis fari estas
+farebla nur de uzuloj agnoskitaj kiel "sistemestroj".
+Bonvolu legi $1.', #FIXME
+'developertitle' => 'Sistemestra konto nepras',
+'developertext'        => 'Nur tiuj kiuj havas la staton, "programisto", povas fari tiun agon.
+Vidu $1.',
+'nbytes'               => '$1 bitokoj',
+'go'                   => 'Ek!', #FIXME
+'ok'                   => 'Ek!', #FIXME
+'sitetitle'            => '{{SITENAME}}',
+'pagetitle'            => '$1 - {{SITENAME}}',
+'sitesubtitle' => 'La Libera Enciklopedio', # FIXME
+'retrievedfrom' => 'Citita el "$1"', #FIXME: Aperas post presita paĝo
+'newmessages'  => 'Jen $1 por vi.',
+'newmessageslink' => 'nova mesaĝo',
+'editsection'   => 'redaktu',
+'toc'           => 'Enhavo',
+'showtoc'       => 'montru',
+'hidetoc'       => 'kaŝu',
+'thisisdeleted' => 'Vidu aŭ restarigu $1?',
+'restorelink' => '$1 forigita(j)n versio(j)n',
+
+# Main script and global functions
+#
+'nosuchaction' => 'Ne ekzistas tia ago',
+'nosuchactiontext' => "La agon ('action') nomitan de la URL
+ne agnoskas la programaro de {{SITENAME}}",
+'nosuchspecialpage' => 'Ne ekzistas tia speciala paĝo',
+'nospecialpagetext' => 'Vi petis specialan paĝon kiun
+ne agnoskas la programaro de {{SITENAME}}',
+
+# General errors
+#
+'error'         => 'Eraro', #FIXME: Fuŝo
+'databaseerror' => 'Datumbaza eraro',
+"dberrortext"  => "Sintakseraro okazis en informpeto al la datumaro.
+Jen la plej laste provita informmendo:
+<blockquote><tt><nowiki>$1</nowiki></tt></blockquote>
+el la funkcio \"<tt>$2</tt>\".
+MySQL redonis eraron  \"<tt>$3: $4</tt>\".",
+'noconnect'            => 'Neeblis konekti al la datumbazo; estas ia erarao aŭ oni riparadas la servilon.',
+'nodb'                 => 'Neeblis elekti datumaron $1',
+'cachederror'   => 'Intertempe, jen konservita kopio de la petita paĝo (ĝi eble ne estas ĝisdata).',
+'readonly'             => 'Datumaro ŝlosita, nurlega',
+'enterlockreason' => 'Bonvolu klarigi, kial oni ŝlosas la datumaron, kaj
+la estimatan tempon de malŝlosado.',
+"readonlytext" => "La datumaro de {{SITENAME}} estas nun ŝlosita kontraŭ
+novaj aldonaj kaj aliaj ŝanĝoj, probable pro laŭkutima flegado de la datumaro.
+Bonvolu reprovu post iom da tempo.
+
+La ŝlosinto lasis la jenan mesaĝon:
+<p>$1</p>\n",
+'missingarticle' => 'La datumbazo ne trovis la tekston de
+artikolo, kiun ĝi devus trovi, nomita "$1".
+Ĉi tio ne estas eraro de la datumbazo, sed probable cimo en la programo.
+Bonvolu raporti ĉi tion al iu sistemestro, kaj rimarkigi la retadreson (URL).',
+'internalerror' => 'Interna eraro',
+'filecopyerror' => 'Neeblis kopii dosieron  "$1" al "$2".',
+'filerenameerror' => 'Neeblis alinomi dosieron "$1" al "$2".',
+'filedeleteerror' => 'Neeblis forigi dosieron "$1".',
+'filenotfound' => 'Neeblis trovi dosieron "$1".',
+'unexpected'   => 'Neatendita valuto: "$1"="$2".',
+'formerror'            => 'Eraro: neeblis liveri formulon',
+'badarticleerror' => 'Tiu ago ne povas esti aplikata al tiu artikolo.',
+'cannotdelete'  => 'Neeblis forigi la elektitan paĝon aŭ dosieron.',
+'badtitle'             => 'Nevalida titolo',
+'badtitletext' => 'La petita paĝotitolo estas nevalida, malplena, aŭ
+malĝuste ligita interlingva aŭ intervikia titolo.',
+'perfdisabled' => 'Ni petas pardonon! La petita funkcio estas malebligita
+provizore por konservi la rapidecon de la servilo.',
+'perfdisabledsub' => 'Jen konservita kopio laŭ $1:',
+'viewsource' => 'Vidu vikitekston',
+'protectedtext' => 'Tiu ĉi paĝon estas ŝlosita kontraŭ redaktado;
+estas diversaj eblaj kialoj por tio.
+Bv legi [[{{ns:4}}:Ŝlositaj paĝoj]].
+
+Vi ja rajtas vidi kaj kopii la fontotekston de la vikipaĝo:',
+
+# Login and logout pages
+#
+'logouttitle'  => 'Elsalutu!',
+'logouttext'   => "Vi elsalutis kaj finis vian seancon.
+Vi rajtas daŭre Vikipediumi sennome, aŭ vi povas reensaluti
+kiel la sama aŭ kiel alia uzulo.\n", #FIXME
+
+'welcomecreation' => "<h2>Bonvenon, $1!</h2> Via konto estas kreita.
+<strong>Ne forgesu fari viajn {{SITENAME}}-preferojn!</strong>",
+
+'loginpagetitle' => 'Ensalutu / enskribu', #FIXME
+'yourname'             => 'Via salutnomo', #FIXME ĉu kaŝnomo ĉu uzantonomo ĉu kontonomo ktp?
+'yourpassword' => 'Via pasvorto',
+'yourpasswordagain' => 'Retajpu pasvorton',
+'newusersonly' => ' (nur novaj uzuloj)',
+'remembermypassword' => 'Rememoru mian pasvorton.',
+"loginproblem" => "<b>Okazis problemo pri via ensalutado.</b><br />Bonvolu reprovi!",
+"alreadyloggedin" => "<strong>Uzulo $1, vi jam estas ensalutinta!</strong><br />\n",
+
+'login'                        => 'Ensalutu', #FIXME, what exactly do the following go to?
+'userlogin'            => 'Ensalutu',
+'logout'               => 'Elsalutu',
+'userlogout'   => 'Elsalutu',
+'notloggedin'  => 'Ne ensalutinta',
+'createaccount'        => 'Kreu novan konton',
+'badretype'            => 'La pasvortoj kiujn vi tajpis ne egalas.',
+'userexists'   => 'Jam estas uzulo kun la nomo kiun vi elektis. Bonvolu elekti alian nomon.',
+'youremail'            => 'Via retpoŝtadreso',
+'yournick'             => 'Via kaŝnomo (por subskriboj)', #FIXME - ĉu kaŝnomo, plumnomo? / 'Kaŝnomo' ŝajnas bona /Bertilo
+'emailforlost' => 'Se vi forgesos vian pasvorton, vi povas peti ke ni sendu novan al via retpoŝtadreso.',
+'loginerror'   => 'Ensaluta eraro', #FIXME
+'noname'               => 'Vi ne enmetis validan salutnomon.',
+'loginsuccesstitle' => 'Ensalutado sukcesis',
+'loginsuccess' => 'Vi nun estas en la {{SITENAME}} kiel uzulo "$1".',
+'nosuchuser'   => 'Neniu uzulo nomiĝas "$1".
+Bonvolu kontroli vian literumadon, aŭ uzu la malsupran formularon por krei novan konton.',
+'wrongpassword'        => 'Vi tajpis malĝustan pasvorton. Bonvolu provi denove.',
+'mailmypassword' => 'Retpoŝtu al mi novan pasvorton',
+'passwordremindertitle' => 'Rememorigo el {{SITENAME}} pri perdita pasvorto', #FIXME
+'passwordremindertext' => 'Iu (probable vi, el IP-adreso $1)
+petis, ke ni sendu al vi novan pasvorton por ensaluti {{SITENAME}}n.
+La pasvorto por uzulo "$2" nun estas "$3".
+Ni rekomendas, ke vi nun ensalutu kaj ŝanĝu vian pasvorton.', #FIXME
+'noemail'              => 'Retpoŝtadreso ne estas registrita por uzulo "$1".',
+'passwordsent' => 'Oni sendis novan pasvorton al la retpoŝtadreso
+registrita por "$1".
+Bonvolu saluti denove ricevinte ĝin.',
+
+# Edit pages
+#
+'summary'              => 'Resumo',
+'minoredit'            => 'Ĉi tiu ŝanĝo estas redakteto',
+'watchthis'            => 'Atentadu la artikolon',
+'savearticle'  => 'Konservu ŝanĝojn',
+'preview'              => 'Antaŭrigardo',
+'showpreview'  => 'Antaŭrigardu', #FIXME eh?
+'blockedtitle' => 'Uzulo forbarita', #FIXME ĉu 'Konto forbarita'?
+'blockedtext'  => "Via konto aŭ IP-adreso estis forbarita fare de $1,
+kiu priskribis la kialon jene:<br />$2
+<p>Vi rajtas kontakti tiun administranton por pridiskuti la forbaradon.", #FIXME - sistemestro?
+'newarticle'   => '(Nova)',
+'newarticletext' => 'Vi sekvis ligilon al paĝo jam ne ekzistanta.
+Se vi volas krei ĝin, ektajpu sube (vidu la [[{{ns:4}}:Helpo|helpopaĝo]] por klarigoj.)
+Se vi malintence alvenis ĉi tien, simple alklaku la "reen" butonon de via retumilo.',
+'anontalkpagetext' => '---- \'\'Jen diskutopaĝo por iu anonima kontribuanto kiu ne jam kreis
+konton aŭ ne uzas ĝin. Ni tial devas uzi la cifran [[IP-adreso]] por tiun identigi.
+Tia IA-adreso povas kundividiĝi de pluraj uzuloj. Se vi estas anonimulo kaj preferus
+eviti tiajn maltrafajn komentojn kaj konfuziĝon kun aliaj anonimuloj ĉe via retero,
+bonvolu [[Special:Userlogin|kreu konton aŭ ensalutu]].',
+'noarticletext' => '(La paĝo nun estas malplena)', #FIXME
+'updated'              => '(Ŝanĝo registrita)', #FIXME: ?
+'note'                 => '<strong>Noto:</strong> ', #FIXME: Where does this come from?
+'previewnote'  => 'Memoru, ke ĉi tio estas nur antaŭrigardo kaj ne jam konservita!',
+'previewconflict' => 'La jena antaŭrigardo montras la tekston el la supra tekstujo,
+kiel ĝi aperos se vi elektos konservi la paĝon.', #FIXME
+'editing'              => 'Redaktante $1',
+'editingsection'       => 'Redaktante $1 (sekcion)',
+'editingcomment'       => 'Redaktante $1 (komenton)',
+'editconflict' => 'Redakta konflikto: $1',
+'explainconflict' => 'Iu alia ŝanĝis la paĝon post kiam vi ekredaktis.
+La supra tekstujo enhavas la aktualan tekston de la artikolo.
+Viaj ŝanĝoj estas en la malsupra tekstujo.
+Vi devas mem kunfandi viajn ŝanĝojn kaj la jaman tekston.
+<b>Nur</b> la teksto en la supra tekstujo estos konservita kiam
+vi alklakos "Konservu".<br />' , #FIXME - double-check that this makes sense
+'yourtext'             => 'Via teksto',
+'storedversion' => 'Registrita versio',
+"editingold"   => "<strong>AVERTO: Vi nun redaktas malnovan version de tiu ĉi artikolo.
+Se vi konservos vian redakton, ĉiuj ŝanĝoj faritaj post tiu versio perdiĝos.</strong>",
+'yourdiff'             => 'Malsamoj',
+'copyrightwarning' => 'Bonvolu noti, ke ĉiu kontribuaĵo al la {{SITENAME}}
+estu rigardata kiel eldonita laŭ la <i>GNU Free Documentation License</i> (vidu je $1).
+Se vi volas, ke via verkaĵo ne estu redaktota senkompate kaj disvastigota
+laŭvole, ne alklaku "Konservu".
+Vi ankaŭ ĵuras, ke vi mem verkis la tekston, aŭ ke vi kopiis ĝin el
+fonto senkopirajta. <strong>NE UZU KOPIRAJTAJN VERKOJN SENPERMESE!</strong>',
+'longpagewarning' => '<strong>AVERTO: Tiu ĉi paĝo longas $1 kilobitokojn; kelkaj retumiloj
+povas fuŝi redaktante paĝojn je longo proksime aŭ preter 32kb.
+Se eble, bonvolu disigi la paĝon al malpli grandajn paĝerojn.</strong>',
+'readonlywarning' => '<strong>AVERTO: La datumbazo estas ŝlosita por teknika laboro;
+pro tio neeblas nun konservi vian redaktadon. Vi povas elkopii kaj englui
+la tekston al tekstdosiero por poste reenmeti ĝin al la vikio.</strong>',
+'protectedpagewarning' => '<strong>AVERTO: Tiu ĉi paĝo estas ŝlosita kontraŭ redaktado
+krom per administrantoj (t.e., vi). Bv certiĝi, ke vi sekvas la normojn de
+la komunumo per via redaktado. Vidu [[Project:Ŝlositaj paĝoj]].</strong>',
+
+# History pages
+#
+'revhistory'   => 'Historio de redaktoj',
+
+'nohistory'            => 'Ne ekzistas historio de redaktoj por ĉi tiu paĝo.', #FIXME
+'revnotfound'  => 'Ne ekzistas malnova versio de la artikolo', #fixme
+'revnotfoundtext' => "Ne eblis trovi malnovan version de la artikolo kiun vi petis.
+Bonvolu kontroli la retadreson (URL) kiun vi uzis por atingi la paĝon.\b",
+'loadhist'             => 'Ŝarĝas redaktohistorion', #FIXME Apparently not used
+
+'currentrev'   => 'Aktuala versio', #FIXME ĉu 'plej lasta'?
+'revisionasof' => 'Kiel registrite je $1',
+'cur'                  => 'nun',
+
+'next'                 => 'sekv',
+'last'                 => 'ant',
+'orig'                 => 'orig',
+'histlegend'   => 'Klarigo: (nun) = vidu malsamojn kompare kun la nuna versio,
+(ant) = malsamojn kompare kun la antaŭa versio, M = malgranda redakteto',
+
+# Diffs
+#
+'difference'   => '(Malsamoj inter versioj)',
+'loadingrev'   => 'ŝarĝas version por malsamoj', #FIXME Apparently not used
+'lineno'               => 'Linio $1:',
+'editcurrent'  => 'Redaktu la nunan version de la paĝo',
+
+# Search results
+#
+'searchresults' => 'Serĉrezultoj',
+'searchresulttext' => 'Por pliaj informoj kiel priserĉi la {{SITENAME}}n, vidu [[Project:Serĉado|Priserĉante la {{SITENAME}}n]].',
+'searchquery'  => 'Serĉmendo "$1"',
+'badquery'             => 'Misformita serĉmendo',
+'badquerytext' => 'Via serĉmendo ne estis plenumebla.
+Eble vi provis serĉi vorton malpli longan ol tri literoj.
+Tion la programo ne jam povas fari. Ankaŭ eblas, ke vi mistajpis la
+esprimon'.
+#", ekzemple \"fiŝoj kaj kaj skaloj\"".   # FIXME ? eblas
+'. Bonvolu reserĉi per alia mendo.',
+'matchtotals'  => 'La serĉmendo "$1" liveris $2 artikolojn laŭ titolo
+kaj $3 artikolojn laŭ enhavo.',
+'nogomatch'    => 'Neniu paĝo havas precize la titolon; provas tekstoserĉon... ',
+'titlematches' => 'Trovitaj laŭ titolo',
+'notitlematches' => 'Neniu trovita laŭ titolo',
+'textmatches'  => 'Trovitaj laŭ enhavo',
+'notextmatches'        => 'Neniu trovita laŭ enhavo',
+'prevn'                        => '$1 antaŭajn',
+'nextn'                        => '$1 sekvajn',
+'viewprevnext' => 'Montru ($1) ($2) ($3).',
+'showingresults' => 'Montras <b>$1</b> trovitajn ekde la <b>$2</b>-a.',
+'showingresultsnum' => 'Montras <b>$3</b> trovitajn ekde la <b>$2</b>-a.',
+'nonefound'            => '<strong>Noto</strong>: malsukcesaj serĉoj ofte
+okazas ĉar oni serĉas tro da ofte uzataj vortoj, kiujn ne enhavas la indekso,
+aŭ ĉar oni petas tro da serĉvortoj (nur paĝoj kiuj enhavas ĉiun serĉvorton
+montriĝos en la rezulto).',
+'powersearch' => 'Trovu',
+
+'powersearchtext' => '
+Serĉu en sekcioj: :<br />
+$1<br />
+$2 Kun alidirektiloj   Serĉu $3 $9',
+'searchdisabled' => '<p>Oni provizore malŝaltis serĉadon per la plenteksta
+indekso pro troŝarĝita servilo. Intertempe, vi povas serĉi per google:</p>',
+'blanknamespace' => '(Artikoloj)',
+
+# Preferences page
+#
+'preferences'  => 'Preferoj',
+'prefsnologin' => 'Ne jam salutis!',
+'prefsnologintext'     => '[[Special:Userlogin|Ensalutu]]
+kaj vi povos ŝanĝi viajn preferojn.',
+'prefslogintext' => 'Vi ensalutis kiel "$1".
+Via interna identeconumero estas $2.',
+'prefsreset'   => 'Preferoj reprenitaj el la registro.', #FIXME: Hmm...
+'qbsettings'   => 'Preferoj pri ilaro',
+'changepassword' => 'Ŝanĝu pasvorton',
+'skin'                 => 'Aspekto',
+'math'                 => 'Tradukas matematikaĵon',
+'math_failure' => 'Malsukcesis analizi formulon',
+'math_unknown_error'   => 'Nekonata eraro',
+'math_unknown_function'        => 'Nekonata funkcio',
+'math_lexing_error'    => 'Leksika analizo malsukcesis',
+'math_syntax_error' => 'Eraro de sintakso',
+'prefs-personal'       => 'Idento',
+'prefs-rc'             => 'Lastaj Ŝanĝoj kaj elmontro de stumpoj',
+'prefs-misc'   => 'Miksitaĵoj',
+'saveprefs'            => 'Konservu preferojn',
+'resetprefs'   => 'Restarigi antaŭajn preferojn',
+'oldpassword'  => 'Malnova pasvorto',
+'newpassword'  => 'Nova pasvorto',
+'retypenew'            => 'Retajpu novan pasvorton',
+'textboxsize'  => 'Grandeco de redakta tekstujo',
+'rows'                 => 'Linioj',
+'columns'              => 'Kolumnoj',
+'searchresultshead' => 'Agordaĵoj pri serĉorezulto',
+'resultsperpage' => 'Montru trovitajn po',
+'contextlines' => 'Montru liniojn el paĝoj po',
+'contextchars' => 'Montru literojn el linioj ĝis po',
+'stubthreshold' => 'Indiku paĝojn malpli grandajn ol',
+'recentchangescount' => 'Montru kiom da titoloj en \'Lastaj ŝanĝoj\'',
+'savedprefs'   => 'Viaj preferoj estas konservitaj.',
+'timezonelegend'       => 'Horzono',
+'timezonetext' => 'Indiku je kiom da horoj via
+loka horzono malsamas disde tiu de la servilo (UTC).
+Ekzemple, por la Centra Eŭropa Horzono, indiku "1" vintre aŭ "2" dum somertempo.',
+'localtime'    => 'Loka horzono',
+'timezoneoffset' => 'Malsamo', #FIXME (?)
+'servertime'   => 'Norma tempo aktuale',
+'guesstimezone'        => 'Petu al foliumilo',
+'emailflag'     => 'Malakceptu retmesaĝojn de aliaj vikipediistoj',
+'defaultns'            => 'Serĉu la jenajn sekciojn:',
+
+# Recent changes
+#
+'changes'      => 'ŝanĝoj', # RIPARUMIN n?
+'recentchanges' => 'Lastaj ŝanĝoj',
+'recentchangestext' => 'Sekvu la plej lastajn ŝanĝojn al la vikio per ĉi tiu paĝo.',
+'rcloaderr'            => 'Ŝarĝas lastajn ŝanĝojn',
+'rcnote'               => 'Jen la plej lastaj <b>$1</b> ŝanĝoj en la lastaj <b>$2</b> tagoj.',
+'rcnotefrom'   => 'Jen la ŝanĝoj ekde <b>$2</b> (lastaj ĝis <b>$1</b>).',
+'rclistfrom'   => 'Montru novajn ŝanĝojn ekde $1',
+'rclinks'              => 'Montru $1 lastajn ŝanĝojn; montru la ŝanĝojn dum la $2 lastaj tagoj.',
+'diff'                 => 'malsamoj',
+'hist'                 => 'historio',
+'hide'                 => 'kaŝu',
+'show'                 => 'montru',
+'tableform'            => 'tabelo',
+'listform'             => 'listo',
+'nchanges'             => '$1 ŝanĝoj',
+'minoreditletter' => 'M',
+'newpageletter' => 'N',
+
+# Upload
+#
+'upload'               => 'Alŝutu dosieron',
+'uploadbtn'            => 'Alŝutu dosieron',
+'uploadlink'   => 'Alŝutu bildon', # Ĉu neuzata?
+'reupload'             => 'Realŝutu',
+'reuploaddesc' => 'Revenu al la alŝuta formularo.',
+'uploadnologin' => 'Ne ensalutinta',
+'uploadnologintext'    => 'Se vi volas alŝuti dosierojn, vi devas [[Special:Userlogin|ensaluti]].',
+'uploaderror'  => 'Eraro okazis dum alŝuto',
+'uploadtext'   => "Por okulumi aŭ serĉi jam alŝutitajn dosierojn,
+aliru la [[Special:Imagelist|liston de alŝutaĵoj]].
+Ĉiuj alŝutoj kaj forigoj estas registrataj en la
+[[Project:Loglibro de alŝutaĵoj|alŝuta loglibro]].
+
+Uzu ĉi tiun formularon por alŝuti novajn bildojn kaj aliajn dosierojn
+por ilustrado de viaj artikoloj.
+Ĉe kutimaj retumiloj, vi vidos ĉi-sube butonon \"Foliumi...\" aŭ simile;
+tiu malfermas la dosierelektilon de via operaciumo.
+Kiam vi elektos dosieron, ĝia nomo plenigos la tekstujon apud la butono.
+Vi ankaŭ nepre devas klakjesi la skatolon por aserti, ke vi ne
+malobeas la leĝan kopirajton de aliuloj per alŝuto de la dosiero.
+Por plenumi la alŝutadon, alklaku la butono \"Alŝutu\".
+Tio ĉi eble iomete longe daŭros, se estas granda dosiero kaj se via interreta konekto malrapidas.
+
+La dosiertipoj preferataj ĉe {{SITENAME}} estas JPEG por fotografaĵoj,
+PNG por grafikaĵoj, diagramoj, ktp; kaj OGG por sonregistraĵoj.
+Bonvolu doni al via dosiero nomon informan, por eviti konfuzon.
+Por enmeti la dosieron en artikolon, skribu ligilon laŭ la formo
+'''<nowiki>[[dosiero:dosiero.jpg]]</nowiki>''' aŭ
+'''<nowiki>[[dosiero:bildo.png|teksto por retumiloj negrafikaj]]</nowiki>''', aŭ
+'''<nowiki>[[dosiero:dosiero.ogg]]</nowiki>''' por sono.
+
+Bonvolu rimarki, ke same kiel artikoloj en la {{SITENAME}}, aliaj Vikipediistoj
+rajtas redakti, anstataŭigi, aŭ forigi viajn alŝutaĵojn se ili pensas, ke
+tio servus la enciklopedion. Se vi aĉe misuzas la sistemon, eblas ke vi estos
+forbarita.",
+'uploadlog'            => 'loglibro de alŝutaĵoj',
+'uploadlogpage' => 'Loglibro_de_alŝutaĵoj',
+"uploadlogpagetext" => "Jen la plej laste alŝutitaj dosieroj.
+Ĉiuj tempoj montriĝas laŭ la horzono UTC.
+<ul>
+</ul>
+",
+'filename'             => 'Dosiernomo',
+'filedesc'             => 'Priskribo',
+'copyrightpage' => '{{ns:4}}:Kopirajto',
+'copyrightpagename' => 'permesilo GFDL uzata por la {{SITENAME}}',
+'uploadedfiles'        => 'Alŝutitaj dosieroj',
+'ignorewarning'        => 'Malatentu averton kaj tamen konservu la dosieron.',
+'minlength'            => 'Dosiernomo devas havi pli ol du literojn.',
+'badfilename'  => 'Dosiernomo estis ŝanĝita al "$1".',
+'badfiletype'  => '".$1" estas dosiertipo malrekomendata.',
+'largefile'            => 'Oni rekomendas, ke dosieroj ne superu grandon de 100 kilobitoj.',
+'successfulupload' => 'Alŝuto sukcesis!',
+'fileuploaded' => 'Vi sukcese alŝutis dosieron "$1".
+Bonvolu sekvi la jenan ligilo: ($2) al la priskrib-paĝo kaj
+verki iom da informo pri la dosiero. Ekzemple, de kie ĝi devenas;
+kiam ĝi estis kreita, kaj kiu kreis ĝin; kaj ion ajn, kion vi scias pri ĝi.',
+'uploadwarning' => 'Averto',
+'savefile'             => 'Konservu dosieron',
+'uploadedimage' => 'alŝutis "[[$1]]"',
+'uploaddisabled' => 'Ni petas pardonon, sed oni malebligis alŝutadon.',
+
+# Image list
+#
+'imagelist'            => 'Listo de alŝutitaj dosieroj',
+'imagelisttext'        => 'Jen listo de $1 alŝutaĵoj, ordigitaj laŭ $2.',
+'getimagelist' => 'akiras dosierliston',
+'ilsubmit'             => 'Trovu!',
+'showlast'             => 'Montru la $1 lastajn bildojn laŭ $2.',
+'byname'               => 'nomo',
+'bydate'               => 'dato',
+'bysize'               => 'grandeco',
+'imgdelete'            => 'forigu',
+'imgdesc'              => 'pri',
+'imglegend'            => '(pri) = montru/redaktu priskribon de dosiero.',
+'imghistory'   => 'Historio de alŝutoj',
+'revertimg'            => 'res',
+'deleteimg'            => 'for',
+'deleteimgcompletely'          => 'for',
+'imghistlegend' => '(nun) = ĉi tiu estas la nuna versio de la dosiero, (for) = forigu
+ĉi tiun malnovan version, (res) = restarigu ĉi tiun malnovan version.
+<br /><i>Por vidi la dosieron laŭdate, alklaku la daton</i>.',
+'imagelinks'   => 'Ligiloj al la dosiero',
+'linkstoimage' => 'La jenaj paĝoj ligas al ĉi tiu dosiero:',
+'nolinkstoimage' => 'Neniu paĝo ligas al ĉi tiu dosiero.',
+
+# Statistics
+#
+'statistics'   => 'Statistiko',
+'sitestats'            => 'Pri la retejo',
+'userstats'            => 'Pri la uzularo',
+'sitestatstext' => "Troviĝas en nia datumaro sume '''$1''' paĝoj.
+Tiu nombro enhavas \"diskutpaĝojn\", paĝojn pri {{SITENAME}}, \"artikoletetojn\", alidirektilojn, kaj aliajn, kiuj eble ne vere estas artikoloj. Malatentante ilin, oni povas nombri '''$2''' probablajn ĝustajn
+artikolojn.
+
+Oni vidis sume '''$3''' paĝojn, kaj redaktis sume '''$4''' paĝojn
+ekde la starigo de la nuna vikiprogramo (novembro 2002).
+Tio estas meznombre po unu paĝo por '''$5''' paĝoj viditaj, kaj por '''$6''' redaktoj.",
+'userstatstext' => "Enskribiĝis '''$1''' uzuloj. El tiuj, '''$2''' estas administrantoj (vidu $3).",
+
+# Maintenance Page
+#
+'maintenance'          => 'Ripariloj kaj zorgiloj',
+"maintnancepagetext"   => "Jen diversaj iloj por riparado kaj ĝenerala zorgado de la datumaro.
+Kelkaj funkcioj povas streĉi la datumbazon, do bonvolu ne reŝuti post ĉiu riparita ero!",
+'maintenancebacklink'  => 'Revenu al la ilaro',
+'disambiguations'      => 'Misligitaj apartigiloj',
+'disambiguationspage'  => '{{ns:4}}:Apartigiloj',
+"disambiguationstext"  => "La jenaj paĝoj alligas <i>paĝon-apartigilon</i>. Ili devus anstataŭe alligi la ĝustan temon.<br />Oni konsideras tiujn paĝojn, kiujn alligas $1 apartigiloj.<br />Ligado el ne-artikolaj sekcioj <i>ne</i> listiĝas ĉi tie.",
+"doubleredirects"      => "Duoblaj alidirektadoj",
+"doubleredirectstext"  => "<b>Atentu:</b> Eblas, ke la jena listo enhavas falsajn rezultojn. Ĝenerale, tio signifas, ke estas plua teksto kun ligiloj post la #REDIRECT.<br />
+Ĉiu linio montras ligilojn ĉe la unua kaj dua alidirektadoj, kaj la unua linio de la teksto de la dua alidirektado, kiu ĝenerale montras la \"veran\" artikolon, kiu devus celi la unuan alidirektadon.",
+'brokenredirects'      => 'Rompitaj alidirektadoj',
+'brokenredirectstext'  => 'La jenaj alidirektadoj ligas al neekzistantaj artikoloj.',
+'selflinks'            => 'Paĝoj memligantaj',
+'selflinkstext'                => 'La jenaj paĝoj enhavas ligilon al si mem, kiuj neutilas.',
+'mispeelings'           => 'Paĝoj kun misliterumoj',
+"mispeelingstext"               => "La jenaj paĝoj enhavas unu el la oftaj misliterumadoj listitaj en $1. La ĝusta literumo montriĝos (ĉi tiel).",
+'mispeelingspage'       => 'Listo de oftaj misliterumoj',
+'missinglanguagelinks'  => 'Mankantaj interlingvaj ligiloj',
+"missinglanguagelinksbutton"    => "Montru mankajn interlingvajn ligilojn por",
+"missinglanguagelinkstext"      => "La jenaj artikoloj <i>ne</i> ligas al sia versio en la lingvo $1. Alidirektadoj kaj subpaĝoj <i>ne</i> montriĝas.",
+
+
+# Miscellaneous special pages
+#
+'orphans'              => 'Neligitaj paĝoj',
+'lonelypages'  => 'Neligitaj paĝoj',
+'unusedimages' => 'Neuzataj bildoj',
+'popularpages' => 'Plej vizitataj paĝoj',
+'nviews'               => '$1-foje',
+'wantedpages'  => 'Dezirataj paĝoj',
+'nlinks'               => '$1 ligiloj',
+'allpages'             => 'Ĉiuj paĝoj',
+'randompage'   => 'Hazarda paĝo',
+'shortpages'   => 'Paĝetoj',
+'longpages'            => 'Paĝegoj',
+'listusers'            => 'Uzularo',
+'specialpages' => 'Specialaj paĝoj',
+'spheading'            => 'Specialaj paĝoj',
+'protectpage'  => 'Protektu paĝon',
+'recentchangeslinked' => 'Rilataj paĝoj',
+'rclsub'               => '(al paĝoj ligitaj de "$1")',
+'debug'                        => 'Kontraŭcima', #CHUCK ĉu 'malcimigu'? | Pli bone 'sencimigi' /Bertilo
+'newpages'             => 'Novaj paĝoj',
+'movethispage' => 'Movu la paĝon',
+"unusedimagestext" => "Notu, ke aliaj TTT-ejoj, ekzemple
+la alilingvaj {{SITENAME}}j, povas rekte ligi al dosiero per URL.
+Tio ne estus enkalkutita en la jena listo.",
+"booksources"  => "Libroservoj",
+"booksourcetext" => "Jen ligilaro al aliaj TTT-ejoj, kiuj vendas librojn,
+kaj/aŭ informumos pri la libro ligita.
+La {{SITENAME}} ne estas komerce ligita al tiuj vendejoj, kaj la listo ne estu
+komprenata kiel rekomendo aŭ reklamo.",
+'alphaindexline' => '$1 ĝis $2',
+
+# Email this user
+#
+'mailnologin'  => 'Neniu alsendota adreso',
+'mailnologintext' => 'Vi nepre estu [[Special:Userlogin|salutanta]]
+kaj havanta validan retpoŝtadreson en viaj [[Special:Preferences|preferoj]]
+por retpoŝti al aliaj Vikipediistoj.',
+'emailuser'            => 'Retpoŝtu',
+'emailpage'            => 'Retpoŝtu',
+'emailpagetext'        => 'Se la alsendota vikipediisto donis validan retpoŝtadreson
+en la preferoj, vi povas sendi unu mesaĝon per la jena formulo.
+La retpoŝtadreso, kiun vi metis en la preferoj, aperos kiel "El"-adreso
+de la poŝto, por ke la alsendonto povos respondi.',
+'noemailtitle' => 'Neniu retpoŝtadreso',
+'noemailtext'  => 'Ĉi tiuj vikipediistoj aŭ ne donis validan retpoŝtadreson
+aŭ elektis ne ricevi retpoŝton de aliaj vikipediistoj.',
+'emailfrom'            => 'El',
+'emailto'              => 'Al',
+'emailsubject' => 'Subjekto',
+'emailmessage' => 'Mesaĝo',
+'emailsend'            => 'Sendu',
+'emailsent'            => 'Retmesaĝo sendita',
+'emailsenttext' => 'Via retmesaĝo estas sendita.',
+
+
+
+# Watchlist
+#
+'watchlist'            => 'Atentaro',
+'watchlistsub' => '(de uzulo "$1")',
+'nowatchlist'  => 'Vi ne jam elektis priatenti iun ajn paĝon.',
+'watchnologin' => 'Ne salutinta',
+'watchnologintext'     => 'Nepras [[Special:Userlogin|saluti]]
+por ŝanĝi vian atentaron.',
+'addedwatch'   => 'Aldonis al atentaro',
+"addedwatchtext" => "La paĝo \"[[$1]]\" estis aldonita al via [[Special:Watchlist|atentaro]].
+Estontaj ŝanĝoj al tiu paĝo aperos en '''grasa tiparo''' en la
+[[Special:Recentchanges|listo de Lastaj Ŝanĝoj]],
+kaj estos kalkulitaj en la listo de via atentaro.
+
+Se vi poste volos eksigi la paĝon el via atentaro, alklaku \"Malatentu paĝon\" en la ilobreto.",
+'removedwatch' => 'Forigis el atentaro',
+'removedwatchtext' => 'La paĝo "[[$1]]" estas forigita el via atentaro.',
+'watchthispage'        => 'Priatentu paĝon',
+'unwatchthispage' => 'Malatentu paĝon',
+'notanarticle' => 'Ne estas artikolo',
+'watchnochange' => 'Neniu artikolo en via atentaro redaktiĝis dum la prispektita tempoperiodo.',
+"watchdetails" => "(Vi priatentas $1 paĝojn [krom diskutopaĝoj];
+laste $2 paĝoj entute redaktiĝis en la vikio; $3...
+[$4 redaktu vian atentaron].)",
+'watchmethod-recent' => 'traserĉas lastajn redaktojn',
+'watchmethod-list' => 'traserĉas priatentitajn',
+'removechecked' => 'Forprenu elektitajn el la listo',
+'watchlistcontains' => 'Via atentaro enhavas $1 paĝojn.',
+'watcheditlist' => 'Jen listo de ĉiu paĝtitolo en via atentaro.
+Elektu forigotajn paĝojn kaj alklaku "forprenu elektitajn" sube.',
+'removingchecked' => 'Forprenas elektitajn...',
+'couldntremove' => 'Neeblas forigi titolon "$1"...',
+'iteminvalidname' => 'Ia eraro pri "$1", nevalida titolo...',
+'wlnote' => 'Jen la lastaj $1 redaktoj de la lastaj <b>$2</b> horoj.',
+'wlshowlast' => 'Montru el lastaj $1 horoj $2 tagoj $3',
+
+
+# Delete/protect/revert
+#
+'deletepage'   => 'Forigu paĝon',
+'confirm'              => 'Konfirmu',
+'excontent'            => 'enhavis: \'$1\'',
+'exbeforeblank' => 'antaŭ malplenigo enhavis: \'$1\'',
+'exblank'       => 'estis malplena',
+'confirmdelete' => 'Konfirmu forigadon',
+'deletesub'            => '(Forigas "$1")',
+'historywarning' => 'Averto: la forigota paĝo havas historion: ',
+"confirmdeletetext" => "Vi forigos la artikolon aŭ dosieron kaj
+forviŝos ĝian tutan historion el la datumaro.<br />
+Bonvolu konfirmi, ke vi vere intencas tion, kaj ke vi komprenas
+la sekvojn, kaj ke vi ja sekvas la [[{{ns:4}}:Reguloj pri forigado|regulojn pri forigado]].",
+'actioncomplete' => 'Ago farita',
+'deletedtext'  => '"$1" estas forigita.
+Vidu la paĝon $2 por registro de lastatempaj forigoj.',
+'deletedarticle' => 'forigis "$1"',
+'dellogpage'   => 'Loglibro_de_forigoj', # NEPRE NE FORIGU LA '_'-SIGNOJN!
+'dellogpagetext' => 'Jen listo de la plej lastaj forigoj el la datumaro.
+Ĉiuj tempoj sekvas la horzonon UTC.
+<ul>
+</ul>
+',
+'deletionlog'  => 'listo de forigoj',
+'reverted'             => 'Restarigis antaŭan version',
+'deletecomment'        => 'Kialo por forigo',
+'imagereverted' => 'Restarigo de antaŭa versio sukcesis.',
+'rollback'     => 'Restarigu antaŭan redakton',
+'rollbacklink' => 'restarigu antaŭan',
+'rollbackfailed' => 'Restarigo malsukcesis',
+'cantrollback' => 'Neeblas restarigi antaŭan redakton; la redaktinto lasta estas la sola de la paĝo.',
+"alreadyrolled" => "Neeblas restarigi lastan redakton al [[$1]]
+de [[Vikipediisto:$2|$2]] ([[Vikipediista diskuto:$2|diskuto]]) pro tio,
+ke oni intertempe redaktis la paĝon.
+
+Lasta redaktinto estas [[Vikipediisto:$3|$3]] ([[Vikipediista diskuto:$3|diskuto]]). ",
+'editcomment' => 'La komento estis: \'<i>$1</i>\'.',
+'revertpage'   => 'Restarigis lastan redakton de $1',
+
+# Undelete
+'undelete' => 'Restarigu forigitan paĝon',
+'undeletepage' => 'Montru kaj restarigu forigitajn paĝojn',
+'undeletepagetext' => 'La jenaj paĝoj estis forigitaj, sed ankoraŭ restas arkivitaj,
+kaj oni povas restarigi ilin. La arkivo povas esti malplenigita periode.',
+'undeletearticle' => 'Restarigu forigitan artikolon',
+'undeleterevisions' => '$1 versioj arkivitaj',
+'undeletehistory' => 'Se vi restarigos la paĝon, ĉiuj versioj estos restarigitaj
+en la historio. Se nova paĝo kun la sama nomo estis kreita post la forigo, la restarigitaj
+versioj aperos antaŭe en la historio, kaj la aktuala versio ne estos anstataŭigita.',
+'undeleterevision' => 'Forigita versio de $1', # ( estas tempo)
+'undeletebtn' => 'Restarigu!',
+'undeletedarticle' => 'restarigis "$1"',
+'undeletedtext'   => 'La artikolo [[$1]] estas sukcese restarigita.
+Vidu [[{{ns:4}}:Loglibro de forigoj]] por registro de lastatempaj forigoj kaj restarigoj.',
+
+# Contributions
+#
+'contributions'        => 'Kontribuoj de Vikipediisto',
+'mycontris'    => 'Miaj kontribuoj',
+'contribsub'   => 'De $1',
+'nocontribs'   => 'Trovis neniajn redaktojn laŭ tiu kriterio.',
+'ucnote'               => 'Jen la <b>$1</b> lastaj redaktoj de tiu Vikipediisto dum la <b>$2</b> lastaj tagoj.',
+'uclinks'              => 'Montru la $1 lastajn redaktojn; montru la $2 lastajn tagojn.',
+'uctop'                        => ' (lasta)',
+
+# What links here
+#
+'whatlinkshere'        => 'Ligiloj ĉi tien',
+'notargettitle' => 'Sen celpaĝo',
+'notargettext' => 'Vi ne precizigis, kiun paĝon aŭ uzulon priumi.',
+'linklistsub'  => '(Listo de ligiloj)',
+'linkshere'            => 'La jenaj paĝoj ligas ĉi tien:',
+'nolinkshere'  => 'Neniu paĝo ligas ĉi tien.',
+'isredirect'   => 'alidirekto',
+
+# Block/unblock IP
+#
+'blockip'              => 'Forbaru IP-adreson/nomon',
+"blockiptext"  => "Per la jena formularo vi povas forbari iun nomon aŭ
+IP-adreson de la rajto enskribiĝi en la vikion.
+Oni tion faru ''nur'' por eviti vandalismon, kaj sekvante la
+[[{{ns:4}}:Reguloj pri forbarado|regulojn pri forbarado]].
+Klarigu la precizan kialon malsupre (ekzemple, citu paĝojn, kiuj estis
+vandalumitaj).",
+'ipaddress'            => 'IP-adreso/nomo',
+'ipbreason'            => 'Kialo',
+'ipbsubmit'            => 'Forbaru la adreson',
+'badipaddress' => 'Neniu uzanto, aŭ la IP-adreso estas misformita.',
+'noblockreason' => 'Vi nepre klarigu kialon pri la forbaro.',
+'blockipsuccesssub' => 'Sukcesis forbari',
+'blockipsuccesstext' => '"$1" estas forbarita.
+<br />Vidu la [[Special:Ipblocklist|liston de IP-forbaroj]].',
+'unblockip'            => 'Malforbaru IP-adreson/nomon',
+'unblockiptext'        => 'Per la jena formulo vi povas repovigi al iu
+forbarita IP-adreso/nomo la povon enskribi en la vikio.',
+'ipusubmit'            => 'Malforbaru la adreson',
+'ipusuccess'   => '"$1" estas malforbarita',
+'ipblocklist'  => 'Listo de forbaritaj IP-adresoj/nomoj',
+'blocklistline'        => 'Je $1, $2 forbaris $3 ($4)',
+'blocklink'            => 'forbaru',
+'unblocklink'  => 'malforbaru',
+'contribslink' => 'kontribuoj',
+'autoblocker'  => 'Provizore forbarita aŭtomate pro tio, ke vi uzas saman IP-adreson kiel "$1", kiu estis blokita pro tio: "$2".',
+
+# Developer tools
+#
+'lockdb'               => 'Ŝlosi datumaron',
+'unlockdb'             => 'Malŝlosi datumaron',
+'lockdbtext'   => 'Se vi ŝlosos la datumaron, tio malebligos al ĉiuj uzuloj
+redakti paĝojn, ŝanĝi preferojn, priumi atentarojn, kaj fari diversajn aliajn
+aferojn, por kiuj nepras ŝanĝi la datumaron.
+Bonvolu certigu, ke vi efektive intencas tion fari, kaj ke vi ja malŝlosos
+la datumaron post ol vi finos vian riparadon.',
+'unlockdbtext' => 'Se vi malŝlosos la datumaron, tio reebligos al ĉiuj uzuloj
+redakti paĝojn, ŝanĝi preferojn, priumi la atentaron, kaj fari aliajn aferojn,
+por kiuj nepras ŝanĝi al la datumaro.
+Bonvolu certigu, ke vi efektive intencas tion fari.',
+'lockconfirm'  => 'Jes, mi vere volas ŝlosi la datumaron.',
+'unlockconfirm'        => 'Jes, mi vere volas malŝlosi la datumaron.',
+'lockbtn'              => 'Ŝlosi datumaron',
+'unlockbtn'            => 'Malŝlosi datumaron',
+'locknoconfirm' => 'Vi ne konfirmis.',
+'lockdbsuccesssub' => 'Datumaro ŝlosita',
+'unlockdbsuccesssub' => 'Datumaro malŝlosita',
+'lockdbsuccesstext' => 'La datumaro de {{SITENAME}} estas ŝlosita.
+<br />Ne forgesu malŝlosi ĝin post kiam vi finos la riparadon.',
+'unlockdbsuccesstext' => 'La datumaro de {{SITENAME}} estas malŝlosita.',
+
+# Move page
+#
+'movepage'             => 'Movu paĝon',
+'movepagetext' => 'Per la jena formulo vi povas ŝanĝi la nomon de iu paĝo, kunportante
+ĝian historion de redaktoj je la nova nomo.
+La antaŭa titolo fariĝos alidirektilo al la nova titolo.
+Ligiloj al la antaŭa titolo <i>ne</i> estos ŝanĝitaj; uzu
+la riparilojn kaj zorgilojn por certigi,
+ke ne restos duoblaj aŭ fuŝitaj alidirektiloj.
+Kiel movanto, vi respondecas pri ĝustigado de fuŝitaj ligiloj.
+
+Notu, ke la paĝo \'\'\'ne\'\'\' estos movita se jam ekzistas paĝo
+ĉe la nova titolo, krom se ĝi estas malplena aŭ alidirektilo
+al ĉi tiu paĝo, kaj sen antaŭa redaktohistorio. Pro tio, vi ja
+povos removi la paĝon je la antaŭa titolo se vi mistajpus, kaj
+neeblas ke vi neintence forviŝus ekzistantan paĝon per movo.
+
+<b>AVERTO!</b>
+Tio povas esti drasta kaj neatendita ŝanĝo por populara paĝo;
+bonvolu certigi vin, ke vi komprenas ties konsekvencojn antaŭ
+ol vi antaŭeniru.',
+
+'movepagetalktext' => 'La movo aŭtomate kunportos la diskuto-paĝon, se tia ekzistas, \'\'\'krom se:\'\'\'
+*Vi movas la paĝon tra sekcioj (ekz de \'\'Nomo\'\' je \'\'Vikipediisto:Nomo\'\'),
+*Ne malplena diskuto-paĝo jam ekzistas je la nova nomo, aŭ
+*Vi malelektas la suban ŝaltilon.
+
+Tiujokaze, vi nepre permane kunigu la diskuto-paĝojn se vi tion deziras.',
+'movearticle'  => 'Movu paĝon',
+'movenologin'  => 'Ne ensalutinta',
+'movenologintext' => 'Vi nepre estu registrita uzulo kaj [[Special:Userlogin|ensalutu]]
+por rajti movi paĝojn.',
+'newtitle'             => 'Al nova titolo',
+'movepagebtn'  => 'Movu paĝon',
+'pagemovedsub' => 'Sukcesis movi',
+'pagemovedtext' => 'Paĝo "[[$1]]" estas movita al "[[$2]]".',
+'articleexists' => 'Paĝo kun tiu nomo jam ekzistas, aŭ la nomo kiun vi elektis ne validas.
+Bonvolu elekti alian nomon.',
+'talkexists'   => 'Oni ja sukcesis movi la paĝon mem, sed
+ne movis la diskuto-paĝon ĉar jam ekzistas tia ĉe la nova titolo.
+Bonvolu permane kunigi ilin.',
+'movedto'              => 'movis al',
+'movetalk'             => 'Movu ankaŭ la "diskuto"-paĝon, se ĝi ekzistas.',
+'talkpagemoved' => 'Ankaŭ la diskutpaĝo estas movita.',
+'talkpagenotmoved' => 'La diskutpaĝo <strong>ne</strong> estas movita.',
+# Math
+'mw_math_png' => 'Ĉiam krei PNG-bildon',
+'mw_math_simple' => 'HTMLigu se simple, aŭ PNG',
+'mw_math_html' => 'HTMLigu se eble, aŭ PNG',
+'mw_math_source' => 'Lasu TeX-fonton (por tekstfoliumiloj)',
+'mw_math_modern' => 'Rekomendita por modernaj foliumiloj',
+'mw_math_mathml' => 'MathML seeble (provizora)',
+
+);
+
+/** @package MediaWiki */
+class LanguageEo extends LanguageUtf8 {
+
+       function getDefaultUserOptions () {
+               $opt = parent::getDefaultUserOptions();
+               $opt['altencoding'] = 0;
+               return $opt;
+       }
+
+       function getNamespaces() {
+               global $wgNamespaceNamesEo;
+               return $wgNamespaceNamesEo;
+       }
+
+
+       function getNsIndex( $text ) {
+               global $wgNamespaceNamesEo;
+
+               foreach ( $wgNamespaceNamesEo as $i => $n ) {
+                       if ( 0 == strcasecmp( $n, $text ) ) { return $i; }
+               }
+               return false;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsEo;
+               return $wgQuickbarSettingsEo;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesEo;
+               return $wgSkinNamesEo;
+       }
+
+       # La dato- kaj tempo-funkciojn oni povas precizigi laŭ lingvo
+       function date( $ts, $adj = false ) {
+               if ( $adj ) { $ts = $this->userAdjust( $ts ); }
+
+               $d = (0 + substr( $ts, 6, 2 )) . '. ' .
+               $this->getMonthAbbreviation( substr( $ts, 4, 2 ) ) .
+                 ' ' .
+                 substr( $ts, 0, 4 );
+               return $d;
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesEo;
+               if(array_key_exists($key, $wgAllMessagesEo))
+                       return $wgAllMessagesEo[$key];
+               else
+                       return parent::getMessage($key);
+       }
+
+       function iconv( $in, $out, $string ) {
+               # For most languages, this is a wrapper for iconv
+               # Por multaj lingvoj, ĉi tiu nur voku la sisteman funkcion iconv()
+               # Ni ankaŭ konvertu X-sistemajn surogotajn
+               if( strcasecmp( $in, 'x' ) == 0 and strcasecmp( $out, 'utf-8' ) == 0) {
+                       $xu = array (
+                               'xx' => 'x' , 'xX' => 'x' ,
+                               'Xx' => 'X' , 'XX' => 'X' ,
+                               "Cx" => "\xc4\x88" , "CX" => "\xc4\x88" ,
+                               "cx" => "\xc4\x89" , "cX" => "\xc4\x89" ,
+                               "Gx" => "\xc4\x9c" , "GX" => "\xc4\x9c" ,
+                               "gx" => "\xc4\x9d" , "gX" => "\xc4\x9d" ,
+                               "Hx" => "\xc4\xa4" , "HX" => "\xc4\xa4" ,
+                               "hx" => "\xc4\xa5" , "hX" => "\xc4\xa5" ,
+                               "Jx" => "\xc4\xb4" , "JX" => "\xc4\xb4" ,
+                               "jx" => "\xc4\xb5" , "jX" => "\xc4\xb5" ,
+                               "Sx" => "\xc5\x9c" , "SX" => "\xc5\x9c" ,
+                               "sx" => "\xc5\x9d" , "sX" => "\xc5\x9d" ,
+                               "Ux" => "\xc5\xac" , "UX" => "\xc5\xac" ,
+                               "ux" => "\xc5\xad" , "uX" => "\xc5\xad"
+                               ) ;
+                       return preg_replace ( '/([cghjsu]x?)((?:xx)*)(?!x)/ei',
+                         'strtr( "$1", $xu ) . strtr( "$2", $xu )', $string );
+               } else if( strcasecmp( $in, 'UTF-8' ) == 0 and strcasecmp( $out, 'x' ) == 0 ) {
+                       $ux = array (
+                               'x' => 'xx' , 'X' => 'Xx' ,
+                               "\xc4\x88" => "Cx" , "\xc4\x89" => "cx" ,
+                               "\xc4\x9c" => "Gx" , "\xc4\x9d" => "gx" ,
+                               "\xc4\xa4" => "Hx" , "\xc4\xa5" => "hx" ,
+                               "\xc4\xb4" => "Jx" , "\xc4\xb5" => "jx" ,
+                               "\xc5\x9c" => "Sx" , "\xc5\x9d" => "sx" ,
+                               "\xc5\xac" => "Ux" , "\xc5\xad" => "ux"
+                       ) ;
+                       # Double Xs only if they follow cxapelutaj literoj.
+                       return preg_replace( '/((?:[cghjsu]|\xc4[\x88\x89\x9c\x9d\xa4\xa5\xb4\xb5]'.
+                         '|\xc5[\x9c\x9d\xac\xad])x*)/ei', 'strtr( "$1", $ux )', $string );
+               }
+               return iconv( $in, $out, $string );
+       }
+
+       function checkTitleEncoding( $s ) {
+               global $wgInputEncoding;
+
+               # Check for X-system backwards-compatibility URLs
+               $ishigh = preg_match( '/[\x80-\xff]/', $s);
+               $isutf = preg_match( '/^([\x00-\x7f]|[\xc0-\xdf][\x80-\xbf]|' .
+                       '[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xf7][\x80-\xbf]{3})+$/', $s );
+
+               if($ishigh and !$isutf) {
+                       # Assume Latin1
+                       $s = utf8_encode( $s );
+               } else {
+                       if( preg_match( '/(\xc4[\x88\x89\x9c\x9d\xa4\xa5\xb4\xb5]'.
+                               '|\xc5[\x9c\x9d\xac\xad])/', $s ) )
+                       return $s;
+               }
+
+               if( preg_match( '/[cghjsu]x/i', $s ) )
+                       return $this->iconv( 'x', 'utf-8', $s );
+               return $s;
+       }
+
+       function initEncoding() {
+               global $wgEditEncoding, $wgInputEncoding, $wgOutputEncoding;
+               $wgInputEncoding = 'utf-8';
+               $wgOutputEncoding = 'utf-8';
+               $wgEditEncoding = 'x';
+       }
+
+       function setAltEncoding() {
+               global $wgEditEncoding, $wgInputEncoding, $wgOutputEncoding;
+               $wgInputEncoding = 'utf-8';
+               $wgOutputEncoding = 'x';
+               $wgEditEncoding = '';
+       }
+
+}
+
+?>
diff --git a/languages/LanguageEs.php b/languages/LanguageEs.php
new file mode 100644 (file)
index 0000000..86d9492
--- /dev/null
@@ -0,0 +1,1090 @@
+<?php
+/** Spanish (Español)
+  *
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+require_once( "LanguageUtf8.php" );
+
+/* private */ $wgNamespaceNamesEs = array(
+       NS_MEDIA          => "Media",
+       NS_SPECIAL        => "Especial",
+       NS_MAIN           => "",
+       NS_TALK           => "Discusión",
+       NS_USER           => "Usuario",
+       NS_USER_TALK      => "Usuario_Discusión",
+       NS_PROJECT            => $wgMetaNamespace,
+       NS_PROJECT_TALK   => "{$wgMetaNamespace}_Discusión",
+       NS_IMAGE          => "Imagen",
+       NS_IMAGE_TALK     => "Imagen_Discusión",
+       NS_MEDIAWIKI      => "MediaWiki",
+       NS_MEDIAWIKI_TALK => "MediaWiki_Discusión",
+       NS_TEMPLATE       => "Plantilla",
+       NS_TEMPLATE_TALK  => "Plantilla_Discusión",
+       NS_HELP           => "Ayuda",
+       NS_HELP_TALK      => "Ayuda_Discusión",
+       NS_CATEGORY       => "Categoría",
+       NS_CATEGORY_TALK  => "Categoría_Discusión",
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgQuickbarSettingsEs = array(
+       "Ninguna", "Fija a la izquierda", "Fija a la derecha", "Flotante a la izquierda"
+);
+
+/* private */ $wgSkinNamesEs = array(
+       'standard' => "Estándar",
+) +  $wgSkinNamesEn;
+
+/* private */ $wgDateFormatsEs = array();
+
+/* private */ $wgAllMessagesEs = array(
+# User Toggles
+
+"tog-underline" => "Subrayar enlaces",
+"tog-highlightbroken" => "Destacar enlaces a artículos vacíos <a href=\"\" class=\"new\">como este</a> (alternativa: como éste<a href=\"\" class=\"internal\">?</a>).",
+"tog-justify"  => "Ajustar párrafos",
+"tog-hideminor" => "Esconder ediciones menores en Cambios Recientes",
+"tog-usenewrc" => "Cambios recientes realzados (no para todos los navegadores)",
+"tog-numberheadings" => "Auto-numerar encabezados",
+"tog-showtoolbar" => "Mostrar barra de edición",
+"tog-rememberpassword" => "Recordar la contraseña entre sesiones",
+"tog-editwidth" => "La caja de edición tiene el ancho máximo",
+"tog-editondblclick" => "Editar páginas con doble clic (JavaScript)",
+"tog-editsection"=>"Habilitar la edición de secciones usando el enlace [editar]",
+"tog-editsectiononrightclick"=>"Habilitar la edición de secciones presionando el botón de la derecha<br /> en los títulos de secciones (JavaScript)",
+"tog-showtoc"=>"Mostrar la tabla de contenidos<br />(para paginas con más de 3 encabezados)",
+"tog-watchdefault" => "Vigilar artículos nuevos y modificados",
+"tog-minordefault" => "Marcar todas las ediciones como menores por defecto",
+"tog-previewontop" => "Mostrar la previsualización antes de la caja de edición en lugar de después",
+"tog-nocache"=> "Inhabilitar el ''cache'' de páginas",
+
+# Dates
+'sunday' => 'Domingo',
+'monday' => 'Lunes',
+'tuesday' => 'Martes',
+'wednesday' => 'Miércoles',
+'thursday' => 'Jueves',
+'friday' => 'Viernes',
+'saturday' => 'Sábado',
+'january' => 'enero',
+'february' => 'febrero',
+'march' => 'marzo',
+'april' => 'abril',
+'may_long' => 'mayo',
+'june' => 'junio',
+'july' => 'julio',
+'august' => 'agosto',
+'september' => 'septiembre',
+'october' => 'octubre',
+'november' => 'noviembre',
+'december' => 'diciembre',
+'jan' => 'ene',
+'feb' => 'feb',
+'mar' => 'mar',
+'apr' => 'abr',
+'may' => 'may',
+'jun' => 'jun',
+'jul' => 'jul',
+'aug' => 'ago',
+'sep' => 'sep',
+'oct' => 'oct',
+'nov' => 'nov',
+'dec' => 'dic',
+# Bits of text used by many pages:
+#
+"linktrail"     => "/^((?:[a-z]|á|é|í|ó|ú|ñ)+)(.*)\$/sD",
+"mainpage"             => "Portada",
+"mainpagetext" => "Software wiki instalado con éxito.",
+"about"                        => "Acerca de",
+"aboutsite"      => "Acerca de {{SITENAME}}",
+"aboutpage"            => "{{ns:project}}:Acerca de",
+"help"                 => "Ayuda",
+"helppage"             => "{{ns:project}}:Ayuda",
+"bugreports"   => "Informes de error de software",
+"bugreportspage" => "{{ns:project}}:Informes_de_error",
+
+"faq"                  => "FAQ",
+"faqpage"              => "{{ns:project}}:FAQ",
+"edithelp"             => "Ayuda de edición",
+"edithelppage" => "{{ns:project}}:Cómo_se_edita_una_página",
+"cancel"               => "Cancelar",
+"qbfind"               => "Encontrar",
+"qbbrowse"             => "Hojear",
+"qbedit"               => "Editar",
+"qbpageoptions" => "Opciones de página",
+"qbpageinfo"   => "Información de página",
+"qbmyoptions"  => "Mis opciones",
+"mypage"               => "Mi página",
+"mytalk"        => "Mi discusión",
+"currentevents" => "Actualidad",
+"errorpagetitle" => "Error",
+"returnto"             => "Regresa a $1.",
+"tagline"              => "De {{SITENAME}}, la enciclopedia libre.",
+"whatlinkshere"        => "Páginas que enlazan aquí",
+"help"                 => "Ayuda",
+"search"               => "Buscar",
+"go"           => "Ir",
+"history"              => "Historial",
+"printableversion" => "Versión para imprimir",
+"editthispage" => "Editar esta página",
+"deletethispage" => "Borrar esta página",
+"protectthispage" => "Proteger esta página",
+"unprotectthispage" => "Desproteger esta página",
+
+"newpage" => "Página nueva",
+"talkpage"             => "Discutir esta página",
+"postcomment" => "Poner un comentario",
+"articlepage"   => "Ver artículo",
+"subjectpage"  => "Artículo",
+"userpage" => "Ver página de usuario",
+"wikipediapage" => "Ver página meta",
+"imagepage" =>         "Ver página de imagen",
+"viewtalkpage" => "Ver discusión",
+"otherlanguages" => "Otros idiomas",
+"redirectedfrom" => "(Redirigido desde $1)",
+"lastmodified" => "Esta página fue modificada por última vez el $1.",
+"viewcount"            => "Esta página ha sido visitada $1 veces.",
+"printsubtitle" => "(De {{SERVER}})",
+"protectedpage" => "Página protegida",
+"administrators" => "{{ns:project}}:Administradores",
+"sysoptitle"   => "Acceso de Administrador requerido",
+"sysoptext"            => "La acción que has requerido sólo puede ser llevada a cabo
+ por usuarios con status de administrador.
+Ver $1.",
+"developertitle" => "Acceso de developer requerido",
+"developertext"        => "La acción que has requerido sólo puede ser llevada a cabo
+por usuarios con status de \"developer\".
+Ver $1.",
+"nbytes"               => "$1 bytes",
+"go"                   => "Ir",
+"ok"                   => "OK",
+"sitetitle"            => "{{SITENAME}}",
+"sitesubtitle" => "La Enciclopedia Libre",
+"retrievedfrom" => "Obtenido de \"$1\"",
+"newmessages" => "Tienes $1.",
+"newmessageslink" => "mensajes nuevos",
+"editsection" =>"editar",
+"toc" => "Tabla de contenidos",
+"showtoc" => "mostrar",
+"hidetoc" => "esconder",
+"thisisdeleted" => "¿Ver o restaurar $1?",
+"restorelink" => "$1 ediciones borradas",
+
+
+# Main script and global functions
+#
+"nosuchaction" => "No existe tal acción",
+"nosuchactiontext" => "La acción especificada por el URL no es
+ reconocida por el software de {{SITENAME}}",
+"nosuchspecialpage" => "No existe esa página especial",
+"nospecialpagetext" => "Has requerido una página especial que no es
+ reconocida por el software de {{SITENAME}}.",
+
+# General errors
+#
+"error"                        => "Error",
+"databaseerror" => "Error de la base de datos",
+"dberrortext"  => "Ha ocurrido un error de sintaxis en una consulta
+a la base de datos.
+La última consulta que se intentó fue:
+<blockquote><tt>$1</tt></blockquote>El error de retorno de
+MySQL fue\"<tt>$3: $4</tt>\".",
+"dberrortextcl" => "Ha ocurrido un error de sintaxis en una consulta
+a la base de datos.
+La última consulta que se intentó fue:
+\"$1\"
+desde la función \"$2\".
+MySQL retornó el error \"$3: $4\".\n",
+"noconnect"            => "No se pudo conectar a la base de datos en $1",
+"nodb"                 => "No se pudo seleccionar la base de datos $1",
+"readonly"             => "Base de datos bloqueada",
+"cachederror"  => "Esta es una copia guardada en el cache de la página requerida, y puede no estar actualizada.",
+"enterlockreason" => "Explica el motivo del bloqueo, incluyendo una estimación de cuándo se producirá el desbloqueo",
+"readonlytext" => "La base de datos de {{SITENAME}} está temporalmente
+bloqueada para nuevas entradas u otras modificaciones, probablemente
+para mantenimiento de rutina, después de lo cual volverá a la normalidad.
+El administrador que la bloqueó ofreció esta explicación:
+<p>$1",
+"missingarticle" => "La base de datos no encontró el texto de una
+página que debería haber encontrado, llamada \"$1\".
+
+<p>Esto es causado usualmente por seguir un enlace a una diferencia de páginas o historial obsoleto a una página que ha sido borrada.
+
+<p>Si esta no es la causa, puedes haber encontrado un error en el software. Por favor, informa de esto a un administrador,
+incluyendo el URL.",
+"internalerror" => "Error interno",
+"filecopyerror" => "No se pudo copiar el archivo \"$1\" a \"$2\".",
+"filerenameerror" => "No se pudo renombrar el archivo \"$1\" a \"$2\".",
+
+"filedeleteerror" => "No se pudo borrar el archivo \"$1\".",
+"filenotfound" => "No se pudo encontrar el archivo \"$1\".",
+"unexpected"   => "Valor no esperado: \"$1\"=\"$2\".",
+"formerror"            => "Error: no se pudo enviar el formulario",
+"badarticleerror" => "Esta acción no se puede llevar a cabo en esta página.",
+"cannotdelete" => "No se pudo borrar la página o imagen especificada. (Puede haber sido borrada por alguien antes)",
+"badtitle"             => "Título incorrecto",
+"badtitletext" => "El título de la página requerida era incorrecto, vacío, o un enlace interleguaje o interwiki incorrecto.",
+
+"perfdisabled" => "Lo siento, esta función está temporalmente desactivada porque enlentece la base de datos a tal punto que nadie puede usar el wiki. Será reescrita para mayor eficiencia en el futuro) probablemente por ti!",
+"perfdisabledsub" => "Aquí hay una copia grabada de $1:",
+
+# Login and logout pagesítulo
+"logouttitle"  => "Fin de sesión",
+"logouttext"   => "Has terminado tu sesión.
+Puedes continuar usando {{SITENAME}} en forma anónima, o puedes
+iniciar sesión otra vez como el mismo u otro usuario.\n",
+
+"welcomecreation" => "<h2>Bienvenido(a), $1!</h2><p>Tu cuenta ha sido creada.
+No olvides personalizar tus preferencia de {{SITENAME}}.",
+
+"loginpagetitle" => "Registrarse/Entrar",
+"yourname"             => "Tu nombre de usuario",
+"yourpassword" => "Tu contraseña",
+"yourpasswordagain" => "Repite tu contraseña",
+"newusersonly" => " (sólo usuarios nuevos)",
+"remembermypassword" => "Quiero que recuerden mi contraseña entre sesiones.",
+"loginproblem" => "<b>Hubo un problema con tu entrada.</b><br />¡Inténtalo otra vez!",
+"alreadyloggedin" => "<strong>Usuario $1, ya entraste!</strong><br />\n",
+
+"login"                        => "Registrarse/Entrar",
+"userlogin"            => "Registrarse/Entrar",
+"logout"               => "Salir",
+"userlogout"   => "Salir",
+"notloggedin"  => "No has entrado",
+"createaccount"        => "Crea una nueva cuenta",
+"badretype"            => "Las contraseñas que ingresaste no concuerdan.",
+"userexists"   => "El nombre que entraste ya está en uso. Por favor, elije un nombre diferente.",
+"youremail"            => "Tu dirección electrónica (e-mail)",
+"yournick"             => "Tu apodo (para firmas)",
+"emailforlost" => "Ingresar una dirección electrónica es opcional, pero permite a los demás usuarios contactarse contigo a través del sitio web sin tener que revelarles tu dirección electrónica. Además, si pierdes u olvidas tu contraseña, puedes pedir que se te envíe una nueva.",
+"loginerror"   => "Error de inicio de sesión",
+"noname"               => "No has especificado un nombre de usuario válido.",
+"loginsuccesstitle" => "Inicio de sesión exitoso",
+"loginsuccess" => "Has iniciado tu sesión en {{SITENAME}} como \"$1\".",
+"nosuchuser"   => "No existe usuario alguno llamado \"$1\".
+Revisa tu escritura, o usa el formulario de abajo para crear una nueva cuenta de usuario.",
+"wrongpassword"        => "La contraseña que ingresaste es incorrecta. Por favor inténtalo de nuevo.",
+"mailmypassword" => "Envíame una nueva contraseña por correo electrónico",
+"passwordremindertitle" => "Recordatorio de contraseña de {{SITENAME}}",
+"passwordremindertext" => "Alguien (probablemente tú, desde la dirección IP $1)
+solicitó que te enviáramos una nueva contraseña para iniciar sesión en {{SITENAME}}.
+La contraseña para el usuario \"$2\" es ahora \"$3\".
+Ahora deberías iniciar sesión y cambiar tu contraseña.",
+"noemail"              => "No hay dirección electrónica (e-mail) registrada para el(la) usuario(a) \"$1\".",
+"passwordsent" => "Una nueva contraseña ha sido enviada a la dirección electrónica registrada para \"$1\".
+Por favor entra otra vez después de que la recibas.",
+
+# Edit pages
+#
+"summary"              => "Resumen",
+"subject" => "Tema/título",
+"minoredit"            => "Esta es una edición menor",
+"watchthis"            => "Vigilar este artículo",
+"savearticle"  => "Grabar la página",
+"preview"              => "Previsualizar",
+"showpreview"  => "Mostrar previsualización",
+"blockedtitle" => "El usuario está bloqueado",
+"blockedtext"  => "Tu nombre de usuario o dirección IP ha sido bloqueada por $1.
+La razón dada es la que sigue:<br />$2<p> Puedes contactar a $1 o a otro de los [[{{ns:project}}:Administradores|administradores]] para
+discutir el bloqueo.",
+"newarticle"   => "(Nuevo)",
+"newarticletext" => "{{SITENAME}} es una enciclopedia en desarrollo, y esta página aún no existe. Puedes pedir información en [[{{ns:project}}:Consultas]], pero no esperes una respuesta pronta. Si lo que quieres es crear esta página, empieza a escribir en la caja que sigue. Si llegaste aquí por error, presiona la tecla para volver a la página anterior de tu navegador.",
+"anontalkpagetext" => "---- ''Esta es la página de discusión para un usuario anónimo que aún no ha creado una cuenta, o no la usa. Por lo tanto, tenemos que usar su [[dirección IP]] numérica para identificarlo. Una dirección IP puede ser compartida por varios usuarios. Si eres un usuario anónimo y sientes que comentarios irrelevantes han sido dirigidos a ti, por favor [[Especial:Userlogin|crea una cuenta o entra]] para evitar confusiones futuras con otros usuarios anónimos.'' ",
+"noarticletext" => "(En este momento no hay texto en esta página)",
+
+"updated"              => "(Actualizado)",
+"note"                 => "<strong>Nota:</strong> ",
+"previewnote"  => "Recuerda que esto es sólo una previsualización, y no ha sido grabada todavía!",
+"previewconflict" => "Esta previsualización refleja el texto en el área
+de edición superior como aparecerá si eliges grabar.",
+"editing"              => "Editando $1",
+"editingsection"       => "Editando $1 (sección)",
+"editingcomment"       => "Editando $1 (comentario)",
+"editconflict" => "Conflicto de edición: $1",
+"explainconflict" => "Alguien más ha cambiado esta página desde que empezaste
+a editarla.
+El área de texto superior contiene el texto de la página como existe
+actualmente. Tus cambios se muestran en el área de texto inferior.
+Vas a tener que incorporar tus cambios en el texto existente.
+<b>Sólo</b> el texto en el área de texto superior será grabado cuando presiones
+ \"Grabar página\".<br />",
+"yourtext"             => "Tu texto",
+"storedversion" => "Versión almacenada",
+"editingold"   => "<strong>ADVERTENCIA: Estás editando una versión antigua
+ de esta página.
+Si la grabas, los cambios hechos desde esa revisión se perderán.</strong>",
+"yourdiff"             => "Diferencias",
+"copyrightwarning" => "Ayuda de edición, caracteres especiales: á é í ó ú Á É Í Ó Ú ü Ü ñ Ñ ¡ ¿ <br /><br />Nota por favor que todas las contribuciones a {{SITENAME}}
+se consideran hechas públicas bajo la Licencia de Documentación Libre GNU
+(ver detalles en $1).
+ Si no deseas que la gente corrija tus escritos sin piedad
+y los distribuya libremente, entonces no los pongas aquí. <br />
+También tú nos aseguras que escribiste esto tú mismo y
+eres dueño de los derechos de autor, o lo copiaste desde el dominio público
+u otra fuente libre.
+ <strong>¡NO USES ESCRITOS CON COPYRIGHT SIN PERMISO!</strong><br />",
+"longpagewarning" => "<strong>ADVERTENCIA: Esta página tiene un tamaño de $1 kilobytes; algunos navegadores pueden tener problemas editando páginas de 32kb o más.
+Por favor considera la posibilidad de descomponer esta página en secciones más pequeñas.</strong>",
+"readonlywarning" => "<strong>ADVERTENCIA: La base de datos ha sido bloqueada para mantenimiento, así que no podrás grabar tus modificaciones en este momento.
+Puedes \"cortar y pegar\" a un archivo de texto en tu computador, y grabarlo para
+intentarlo después.</strong>",
+"protectedpagewarning" => "<strong>ADVERTENCIA: Esta página ha sido bloqueada de manera que s&ocute;lo usuarios con privilegios de administrador pueden editarla. Asegúrate de que estás siguiendo las
+[[Project:Guías_para_páginas_protegidas|guías para páginas protegidas]].</strong>",
+
+# History pages
+#
+"revhistory"   => "Historial de revisiones",
+"nohistory"            => "No hay un historial de ediciones para esta página.",
+"revnotfound"  => "Revisión no encontrada",
+"revnotfoundtext" => "La revisión antigua de la página por la que preguntaste no se pudo encontrar.
+Por favor revisa el URL que usaste para acceder a esta página.\n",
+"loadhist"             => "Recuperando el historial de la página",
+"currentrev"   => "Revisión actual",
+"revisionasof" => "Revisión de $1",
+"cur"                  => "act",
+"next"                 => "sig",
+"last"                 => "prev",
+"orig"                 => "orig",
+"histlegend"   => "Simbología: (act) = diferencia con la versión actual,
+(prev) = diferencia con la versión previa, M = edición menor",
+
+# Diffs
+#
+"difference"   => "(Diferencia entre revisiones)",
+"loadingrev"   => "recuperando revisión para diff",
+"lineno"               => "Línea $1:",
+"editcurrent"  => "Edita la versión actual de esta página",
+
+# Search results
+#
+"searchresults" => "Resultados de búsqueda",
+"searchresulttext" => "Para más información acerca de búsquedas en {{SITENAME}}, ve a [[Project:Búsqueda|Buscando en {{SITENAME}}]].",
+"searchquery"  => "Para consulta \"$1\"",
+
+"badquery"             => "Consulta de búsqueda formateada en forma incorrecta",
+"badquerytext" => "No pudimos procesar tu búsqueda.
+Esto es probablemente porque intentaste buscar una palabra de menos de tres letras, lo que todavía no es posible.
+También puede ser que hayas cometido un error de escritura en la expresión.
+Por favor, intenta una búsqueda diferente.",
+"matchtotals"  => "La consulta \"$1\" coincidió con $2 títulos de artículos
+y el texto de $3 artículos.",
+"nogomatch" => "No existe ninguna página con exactamente este título, estamos intentando una búsqueda en todo el texto.",
+"titlematches" => "Coincidencias de título de artículo",
+"notitlematches" => "No hay coincidencias de título de artículo",
+"textmatches"  => "Coincidencias de texto de artículo",
+"notextmatches"        => "No hay coincidencias de texto de artículo",
+"prevn"                        => "$1 previos",
+"nextn"                        => "$1 siguientes",
+"viewprevnext" => "Ver ($1) ($2) ($3).",
+"showingresults" => "Mostrando abajo <b>$1</b> resultados empezando con #<b>$2</b>.",
+"showingresultsnum" => "Mostrando abajo  <b>$3</b> resultados comenzando con #<b>$2</b>.",
+"nonefound"            => "<strong>Nota</strong>: búsquedas no exitosas son causadas a menudo
+por búsquedas de palabras comunes como \"la\" o \"de\",
+que no están en el índice, o por especificar más de una palabra para buscar (sólo las páginas
+que contengan todos los términos de una búsqueda aparecerán en el resultado).",
+"powersearch" => "Búsqueda",
+"powersearchtext" => "
+Buscar en espacios de nombre :<br />
+$1<br />
+$2 Listar redirecciones   Buscar $3 $9",
+"searchdisabled" => "<p>Búsqueda en todo el texto ha sido desactivada temporalmente
+debido a carga alta del servidor; esperamos tenerla otra vez en linea después de algunas actualizaciones de
+soporte físico próximas.",
+"blanknamespace" => "(Principal)",
+# Preferences page
+#
+"preferences"  => "Preferencias",
+"prefsnologin" => "No has entrado",
+"prefsnologintext"     => "Debes [[Especial:Userlogin|entrar]]
+para seleccionar preferencias de usuario.",
+"prefslogintext" => "Has entrado con el nombre \"$1\".
+Tu número de identificación interno es $2.",
+"prefsreset"   => "Las preferencias han sido repuestas a sus valores almacenados.",
+"qbsettings"   => "Preferencias de \"Quickbar\"",
+"changepassword" => "Cambiar contraseña",
+"skin"                 => "Piel",
+"math"                 => "Cómo se muestran las fórmulas",
+"dateformat"   => "Formato de fecha",
+"math_failure"         => "No se pudo entender",
+"math_unknown_error"   => "error desconocido",
+"math_unknown_function"        => "función desconocida",
+"math_lexing_error"    => "error de léxico",
+"math_syntax_error"    => "error de sintaxis",
+"saveprefs"            => "Grabar preferencias",
+"resetprefs"   => "Volver a preferencias por defecto",
+"oldpassword"  => "Contraseña antigua",
+"newpassword"  => "Contraseña nueva",
+"retypenew"            => "Reescriba la nueva contraseña",
+"textboxsize"  => "Dimensiones del área de texto",
+"rows"                 => "Filas",
+"columns"              => "Columnas",
+"searchresultshead" => "Preferencias de resultado de búsqueda",
+"resultsperpage" => "Resultados para mostrar por página",
+"contextlines" => "Líneas para mostrar por resultado",
+"contextchars" => "Caracteres de contexto por línea",
+"stubthreshold" => "Umbral de artículo mínimo" ,
+"recentchangescount" => "Número de títulos en cambios recientes",
+"savedprefs"   => "Tus preferencias han sido grabadas.",
+'timezonelegend' => "Huso horario",
+"timezonetext" => "Entra el número de horas de diferencia entre tu hora local
+y la hora del servidor (UTC).",
+"localtime"    => "Hora local",
+"timezoneoffset" => "Diferencia",
+"servertime"   => "La hora en el servidor es",
+"guesstimezone" => "Obtener la hora del navegador",
+"emailflag"     => "No quiero recibir correo electrónico de otros usuarios",
+"defaultns"            => "Buscar en estos espacios de nombres por defecto:",
+
+# Recent changes
+#
+"changes" => "cambios",
+"recentchanges" => "Cambios recientes",
+"recentchangestext" => "Sigue los cambios más recientes a {{SITENAME}} en esta página.
+¡[[{{ns:project}}:Bienvenidos|Bienvenidos]]!
+Por favor, lee estas páginas: [[{{ns:project}}:FAQ|{{SITENAME}} FAQ]],
+[[{{ns:project}}:Políticas y guías|políticas de {{SITENAME}}]]
+(especialmente [[{{ns:project}}:Convenciones de nombres|las convenciones para nombrar artículos]] y
+[[{{ns:project}}:Punto de vista neutral|punto de vista neutral]]).
+
+Si quieres que {{SITENAME}} tenga éxito, es muy importante que no agregues
+material restringido por [[{{ns:project}}:Copyrights|derechos de autor]]. La responsabilidad legal realmente podría dañar el proyecto, así que por favor no lo hagas.",
+"rcloaderr"            => "cargando cambios recientes",
+"rcnote"               => "Abajo están los últimos <b>$1</b> cambios en los últimos <b>$2</b> días.",
+"rclistfrom"   => "Mostrar cambios nuevos desde $1",
+"rcnotefrom"   => "Abajo están los cambios desde <b>$2</b> (se muestran hasta <b>$1</b>).",
+"rclinks"              => "Ver los últimos $1 cambios en los últimos $2 días.",
+"rchide"               => "en forma $4 ; $1 ediciones menores; $2 espacios de nombre secundarios; $3 ediciones múltiples.",
+"rcliu"                        => "; $1 ediciones de usuarios en sesión",
+"diff"                 => "dif",
+"hist"                 => "hist",
+"hide"                 => "esconder",
+"show"                 => "mostrar",
+"tableform"             => "tabla",
+"listform"             => "lista",
+"nchanges"             => "$1 cambios",
+"minoreditletter" => "M",
+"newpageletter" => "N",
+
+# Upload
+#
+"upload"               => "Subir",
+"uploadbtn"            => "Subir un archivo",
+"uploadlink"   => "Subir imágenes",
+"reupload"             => "Subir otra vez",
+"reuploaddesc" => "Regresar al formulario para subir.",
+"uploadnologin" => "No has iniciado sesión",
+"uploadnologintext"    => "Tú debes [[Especial:Userlogin|iniciar sesión]]
+para subir archivos.",
+"uploaderror"  => "Error tratando de subir",
+"uploadtext"   => "Para ver o buscar imágenes que se hayan subido
+previamente, ve a la [[Especial:Imagelist|lista de imágenes subidas]].
+Los archivos subidos y borrados son registrados en el
+[[Project:Registro de subidas|registro de subidas]].
+Consulta también la [[Project:Política de uso de imágenes|política de uso de imágenes]].
+
+Usa el formulario siguiente para subir nuevos archivos de imágenes que
+vas a usar para ilustrar tus artículos.
+En la mayoría de los navegadores, verás un botón \"Browse...\", que
+abrirá el diálogo de selección de archivos estándar de tu sistema operativo.
+Cuando hayas elegido un archivo, su nombre aparecerá en el campo de texto
+al lado del botón \"Examinar...\".
+También debes marcar la caja afirmando que no estás
+violando ningún copyright al subir el archivo.
+Presiona el botón \"Subir\" para completar la subida.
+Esto puede tomar algún tiempo si tienes una conexión a Internet lenta.
+
+Los formatos preferidos son JPEG para imágenes fotográficas, PNG
+para dibujos y diagramas, y OGG para sonidos.
+Por favor, dale a tus archivos nombres descriptivos para evitar confusiones.
+Para incluir la imagen en un artículo, usa un enlace de la forma
+'''<nowiki>[[imagen:archivo.jpg]]</nowiki>''' o
+'''<nowiki>[[imagen:archivo.png|alt text]]</nowiki>''' o
+'''<nowiki>[[media:archivo.ogg]]</nowiki>''' para sonidos.
+
+Por favor recuerda que, al igual que con las páginas {{SITENAME}}, otros pueden
+editar o borrar los archivos que has subido si piensan que es bueno para
+la enciclopedia, y se te puede bloquear, impidiéndote subir más archivos si abusas del sistema.",
+"uploadlog"            => "registro de subidas",
+"uploadlogpage" => "Registro_de_subidas",
+"uploadlogpagetext" => "Abajo hay una lista de los archivos que se han
+subido más recientemente. Todas las horas son del servidor (UTC).
+<ul>
+</ul>
+",
+"filename"             => "Nombre del archivo",
+"filedesc"             => "Sumario",
+"copyrightpage" => "{{ns:projec}}:Copyrights",
+"copyrightpagename" => "{{SITENAME}} copyright",
+"uploadedfiles"        => "Archivos subidos",
+"ignorewarning"        => "Ignora la advertencia y graba el archivo de todos modos.",
+"minlength"            => "Los nombres de imágenes deben ser al menos de tres letras.",
+"badfilename"  => "El nombre de la imagen se ha cambiado a \"$1\".",
+"badfiletype"  => "\".$1\" no es un formato de imagen recomendado.",
+#"largefile"           => "Se recomienda que las imágenes no excedan 100k de tamaño.",
+"successfulupload" => "Subida exitosa",
+"fileuploaded" => "El archivo \"$1\" se subió en forma exitosa.
+Por favor sigue este enlace: ($2) a la página de descripción y escribe
+la información acerca del archivo, tal como de dónde viene, cuándo fue
+creado y por quién, y cualquier otra cosa que puedas saber al respecto.",
+"uploadwarning" => "Advertencia de subida de archivo",
+"savefile"             => "Grabar archivo",
+"uploadedimage" => "\"[[$1]]\" subido.",
+"uploaddisabled" => "Lo sentimos, subir archivos ha sido desactivado en este servidor.",
+# Image list
+#
+"imagelist"            => "Lista de imágenes",
+"imagelisttext"        => "Abajo hay una lista de $1 imágenes ordenadas $2.",
+"getimagelist" => " obteniendo la lista de imágenes",
+
+"ilsubmit"             => "Búsqueda",
+"showlast"             => "Mostrar las últimas $1 imágenes ordenadas  $2.",
+"byname"               => "por nombre",
+"bydate"               => "por fecha",
+"bysize"               => "por tamaño",
+"imgdelete"            => "borr",
+"imgdesc"              => "desc",
+"imglegend"            => "Simbología: (desc) = mostrar/editar la descripción de la imagen.",
+"imghistory"   => "Historial de la imagen",
+"revertimg"            => "rev",
+"deleteimg"            => "borr",
+"deleteimgcompletely"          => "borr",
+"imghistlegend" => "Simbología: (act) = esta es la imagen actual, (borr) = borrar
+esta versión antigua, (rev) = revertir a esta versión antigua.
+<br /><i>Clic en la fecha para ver imagen subida en esa fecha</i>.",
+"imagelinks"   => "Enlaces a la imagen",
+"linkstoimage" => "Las siguientes páginas enlazan a esta imagen:",
+"nolinkstoimage" => "No hay páginas que enlacen a esta imagen.",
+
+# Statistics
+#
+"statistics"   => "Estadísticas",
+"sitestats"            => "Estadísticas del sitio",
+"userstats"            => "Estadísticas de usuario",
+"sitestatstext" => "Hay un total de <b>$1</b> páginas en la base de datos.
+Esto incluye páginas de discusión, páginas acerca de {{SITENAME}}, páginas mínimas,
+redirecciones, y otras que probablemente no puedan calificarse como artículos.
+Excluyéndolas, hay <b>$2</b> páginas que probablemente son artículos legítimos.<p>
+Ha habido un total de <b>$3</b> visitas a páginas, y <b>$4</b> ediciones de página
+desde que el software fue actualizado (Octubre 2002).
+Esto resulta en un promedio de <b>$5</b> ediciones por página,
+y <b>$6</b> visitas por edición.",
+"userstatstext" => "Hay <b>$1</b> usuarios registrados.
+de los cuales <b>$2</b> son administradores (ver $3).",
+
+# Maintenance Page
+#
+"maintenance"          => "Página de mantenimiento",
+"maintnancepagetext"   => "Esta página incluye varias herramientas útiles para el mantenimiento diario de la enciclopedia. Algunas de estas funciones tienden a sobrecargar la base de datos, así que, por favor, no vuelvas a cargar la página después de cada ítem que arregles ;-)",
+"maintenancebacklink"  => "Volver a la Página de Mantenimiento",
+"disambiguations"      => "Páginas de desambiguación",
+"disambiguationspage"  => "{{ns:project}}:Enlaces a páginas de desambiguación",
+"disambiguationstext"  => "Los siguientes artículos enlazan a una <i>página de desambiguación</i>. Deberían enlazar al artículo apropiado.<br />Una página es considerada de desambiguación si está enlazada desde $1.<br />Enlaces desde otros espacios de nombre (Como {{ns:project}}: o usuario:) <b>no</b> son listados aquí.",
+"doubleredirects"      => "Redirecciones dobles",
+"doubleredirectstext"  => "<b>Atención:</b> Esta lista puede contener falsos positivos. Eso significa usualmente que hay texto adicional con enlaces bajo el primer #REDIRECT.<br />\nCada fila contiene enlaces al segundo y tercer redirect, así como la primera línea del segundo redirect, en la que usualmente se encontrará el artículo \"real\" al que el primer redirect debería apuntar.",
+"brokenredirects"      => "Redirecciones incorrectas",
+"brokenredirectstext"  => "Las redirecciones siguientes enlazan a un artículo que no existe.",
+"selflinks"            => "Páginas con enlaces a sí mismas",
+"selflinkstext"                => "Las siguientes páginas contienen un enlace a sí mismas, lo que no se recomienda.",
+"mispeelings"       => "Páginas con faltas de ortografía",
+"mispeelingstext"               => "Las siguientes páginas contienen una falta de ortografía común de las listadas en $1. La escritura correcta se indica entre paréntesis.",
+"mispeelingspage"       => "Lista de faltas de ortografía comunes",
+"missinglanguagelinks"  => "Enlaces Interleguaje Faltantes",
+"missinglanguagelinksbutton"    => "Encontrar los enlaces interlenguaje que faltan para",
+"missinglanguagelinkstext"      => "Estos artículos <b>no</b> enlazan a sus correspondientes en $1. <b>No</b> se muestran redirecciones ni subpáginas.",
+
+
+# Miscellaneous special pages
+#
+"orphans"              => "Páginas huérfanas",
+"lonelypages"  => "Páginas huérfanas",
+"unusedimages" => "Imágenes sin uso",
+"popularpages" => "Páginas populares",
+"nviews"               => "$1 visitas",
+"wantedpages"  => "Páginas requeridas",
+"nlinks"               => "$1 enlaces",
+"allpages"             => "Todas las páginas",
+
+"randompage"   => "Página aleatoria",
+"shortpages"   => "Páginas cortas",
+"longpages"            => "Páginas largas",
+"listusers"            => "Lista de usuarios",
+"specialpages" => "Páginas especiales",
+"spheading"            => "Páginas especiales",
+"protectpage"  => "Páginas protegidas",
+"recentchangeslinked" => "Seguimiento de enlaces",
+"rclsub"               => "(a páginas enlazadas desde \"$1\")",
+"debug"                        => "Debug",
+"newpages"             => "Páginas nuevas",
+"ancientpages"         => "Artículos más antiguos",
+"intl"                  => "Enlaces interlenguaje",
+"movethispage" => "Trasladar esta página",
+"unusedimagestext" => "<p>Por favor note que otros sitios web
+tales como otras wikipedias pueden enlazar a una imagen
+con un URL directo, y de esa manera todavía estar listada aquí
+a pesar de estar en uso activo.",
+"booksources"   => "Fuentes de libros",
+"booksourcetext" => "A continuación hay una lista de enlaces a otros sitios que venden libros nuevos y usados, y también pueden contener información adicional acerca de los libros que estás buscando.
+{{SITENAME}} no está relacionada con ninguno de estos negocios, y esta lista no debe ser considerada un patrocinio de los mismos.",
+"alphaindexline" => "$1 a $2",
+
+# Email this user
+#
+"mailnologin"  => "No enviar dirección",
+"mailnologintext" => "Debes [[Especial:Userlogin|iniciar sesión]]
+y tener una dirección electrónica válida en tus [[Especial:Preferences|preferencias]]
+para enviar un correo electrónico a otros usuarios.",
+"emailuser"            => "Enviar correo electrónico a este usuario",
+"emailpage"            => "Correo electrónico a usuario",
+"emailpagetext"        => "Si este usuario ha registrado una dirección electrónica válida en sus preferencias de usuario, el siguiente formulario sirve para enviarle un mensaje.
+La dirección electrónica que indicaste en tus preferencias de usuario aparecerá en el remitente para que el destinatario te pueda responder.",
+"noemailtitle" => "No hay dirección electrónica",
+"noemailtext"  => "Este usuario no ha especificado una dirección electrónica válida, o ha elegido no recibir correo electrónico de otros usuarios.",
+"emailfrom"            => "De",
+"emailto"              => "Para",
+"emailsubject" => "Tema",
+"emailmessage" => "Mensaje",
+"emailsend"            => "Enviar",
+"emailsent"            => "Correo electrónico enviado",
+"emailsenttext" => "Tu correo electrónico ha sido enviado.",
+
+# Watchlist
+#
+"watchlist"            => "Lista de seguimiento",
+"watchlistsub" => "(para el usuario \"$1\")",
+"nowatchlist"  => "No tienes ninguna página en tu lista de seguimiento.",
+"watchnologin" => "No has iniciado sesión",
+"watchnologintext"     => "Debes [[Especial:Userlogin|iniciar sesión]]
+para modificar tu lista de seguimiento.",
+"addedwatch"   => "Añadido a la lista de seguimiento",
+"addedwatchtext" => "La página \"$1\" ha sido añadida a tu  <a href=\"" .
+  "{{localurle:Especial:Watchlist}}\">lista se seguimiento</a>.
+Cambios futuros en esta página y su página de discusión asociada se indicarán ahí, y la página aparecerá <b>en negritas</b> en la <a href=\"" .
+  "{{localurle:Especial:Recentchanges}}\">lista de cambios recientes</a> para hacerla más fácil de detectar.</p>
+
+<p>Cuando quieras eliminar la página de tu lista de seguimiento, presiona \"Dejar de vigilar\" en el menú.",
+"removedwatch" => "Eliminada de la lista de seguimiento",
+"removedwatchtext" => "La página \"$1\" ha sido eliminada de tu lista de seguimiento.",
+"watchthispage"        => "Vigilar esta página",
+"unwatchthispage" => "Dejar de vigilar",
+"notanarticle" => "No es un artículo",
+"watchnochange" => "Ninguno de los artículos en tu lista de seguimiento fue editado en el periodo de tiempo mostrado.",
+"watchdetails" => "($1 páginas en tu lista de seguimiento, sin contar las de discusión;
+$2 páginas editadas en total desde el cutoff;
+$3...
+[$4 mostrar y editar la lista completa].)",
+"watchmethod-recent" => "chequeando ediciones recientes en la lista de seguimiento",
+
+"watchmethod-list" => "buscando ediciones recientes en la lista de seguimiento",
+"removechecked" => "Borrar artículos seleccionados de la lista de seguimiento",
+"watchlistcontains" => "Tu lista de seguimiento posee $1 páginas.",
+"watcheditlist" => "Aquí está un listado alfabético de tu lista de seguimiento.
+Selecciona los artículos que deseas remover de tu lista de seguimiento y
+click el botón 'remover seleccionados' en el fin de la pantalla.",
+"removingchecked" => "Removiendo los artículos solicitados de la lista de seguimiento...",
+"couldntremove" => "No se pudo remover el artículo '$1'...",
+"iteminvalidname" => "Problema con el artículo '$1', nombre inválido...",
+"wlnote" => "Abajo están los últimos $1 cambios en las últimas <b>$2</b> horas.",
+# Delete/protect/revert
+#
+"deletepage"   => "Borrar esta página",
+"confirm"              => "Confirma",
+"excontent" => "contenido era: '$1'",
+"exbeforeblank" => "contenido antes de borrar era: '$1'",
+"exblank" => "página estaba vacía",
+"confirmdelete" => "Confirma el borrado",
+"deletesub"            => "(Borrando \"$1\")",
+"historywarning" => "Atención: La página que estás por borrar tiene un historial: ",
+"confirmdeletetext" => "Estás a punto de borrar una página o imagen
+en forma permanente,
+así como todo su historial, de la base de datos.
+Por favor, confirma que realmente quieres hacer eso, que entiendes las
+consecuencias, y que lo estás haciendo de acuerdo con [[{{ns:project}}:Políticas]].",
+"actioncomplete" => "Acción completa",
+"deletedtext"  => "\"$1\" ha sido borrado.
+Ve $2 para un registro de los borrados más recientes.",
+"deletedarticle" => "borrado \"$1\"",
+"dellogpage"   => "Registro_de_borrados",
+"dellogpagetext" => "Abajo hay una lista de los borrados más recientes.
+Todos los tiempos se muestran en hora del servidor (UTC).
+<ul>
+</ul>
+",
+"deletionlog"  => "registro de borrados",
+"reverted"             => "Recuperar una revisión anterior",
+"deletecomment"        => "Razón para el borrado",
+"imagereverted" => "Revertido a una versión anterior tuvo éxito.",
+"rollback"             => "Revertir ediciones",
+"rollbacklink" => "Revertir",
+"rollbackfailed" => "Reversión fallida",
+"cantrollback" => "No se pueden revertir las ediciones; el último colaborador es el único autor de este artículo.",
+"alreadyrolled"        => "No se puede revertir la última edición de [[$1]]
+por [[Colaborador:$2|$2]] ([[Colaborador Discusión:$2|Discusión]]); alguien más ya ha editado o revertido esa página.
+
+La última edición fue hecha por [[Colaborador:$3|$3]] ([[Colaborador Discusión:$3|Discusión]]). ",
+#   only shown if there is an edit comment
+"editcomment" => "El resumen de la edición fue: \"<i>$1</i>\".",
+"revertpage"   => "Revertida a la última edición por $1",
+
+# Undelete
+"undelete" => "Restaurar una página borrada",
+"undeletepage" => "Ver y restaurar páginas borradas",
+"undeletepagetext" => "Las siguientes páginas han sido borradas pero aún están en el archivo y pueden ser restauradas. El archivo puede ser limpiado periódicamente.",
+"undeletearticle" => "Restaurar artículo borrado",
+"undeleterevisions" => "$1 revisiones archivadas",
+"undeletehistory" => "Si tú restauras una página, todas las revisiones serán restauradas al historial.
+Si una nueva página con el mismo nombre ha sido creada desde el borrado, las versiones restauradas aparecerán como historial anterior, y la revisión actual de la página \"viva\" no será automáticamente reemplazada.",
+"undeleterevision" => "Revisión borrada al $1",
+"undeletebtn" => "Restaurar!",
+"undeletedarticle" => "restaurado \"$1\"",
+"undeletedtext"   => "El artículo [[$1]] ha sido restaurado con éxito.
+Véase [[{{ns:project}}:Registro_de_borrados]] para una lista de borrados y restauraciones recientes.",
+
+# Contributions
+#
+"contributions"        => "Contribuciones del usuario",
+"mycontris"=>"Mis contribuciones",
+"contribsub"   => "$1",
+"nocontribs"   => "No se encontraron cambios que cumplieran estos criterios.",
+"ucnote"               => "Abajo están los últimos <b>$1</b> cambios de este usuario en los últimos <b>$2</b> días.",
+"uclinks"              => "Ver los últimos $1 cambios; ver los últimos $2 días.",
+"uctop"                => " (última modificación)" ,
+
+# What links here
+#
+"whatlinkshere"        => "Lo que enlaza aquí",
+"notargettitle" => "No hay página objetivo",
+"notargettext" => "No has especificado en qué página
+llevar a cabo esta función.",
+"linklistsub"  => "(Lista de enlaces)",
+"linkshere"            => "Las siguientes páginas enlazan aquí:",
+"nolinkshere"  => "Ninguna página enlaza aquí.",
+"isredirect"   => "pagina redirigida",
+
+# Block/unblock IP
+#
+"blockip"              => "Bloqueo de direcciones IP",
+"blockiptext"  => "Usa el formulario siguiente para bloquear el
+acceso de escritura desde una dirección IP específica.
+Esto debería hacerse sólo para prevenir vandalismo, y de
+acuerdo a las [[{{ns:project}}:Políticas|políticas de {{SITENAME}}]].
+Explica la razón específica del bloqueo (por ejemplo, citando
+ls páginas en particular que han sido objeto de vandalismo desde la dirección IP a bloquear).",
+"ipaddress"            => "Dirección IP",
+"ipbreason"            => "Razón",
+"ipbsubmit"            => "Bloquear esta dirección",
+"badipaddress" => "La dirección IP no tiene el formato correcto.",
+
+"blockipsuccesssub" => "Bloqueo exitoso",
+"blockipsuccesstext" => "La dirección IP  \"$1\" ha sido bloqueada.
+<br />Ver [[Especial:Ipblocklist|lista de IP bloqueadas]] para revisar bloqueos.",
+"unblockip"            => "Desbloquear dirección IP",
+"unblockiptext"        => "Usa el formulario que sigue para restaurar el
+acceso de escritura a una dirección IP previamente bloqueada.",
+"ipusubmit"            => "Desbloquea esta dirección",
+"ipusuccess"   => "Dirección IP \"$1\" desbloqueada",
+"ipblocklist"  => "Lista de direcciones IP bloqueadas",
+"blocklistline"        => "$1, $2 bloquea $3 ($4)",
+"blocklink"            => "bloquear",
+"unblocklink"  => "desbloquear",
+"contribslink" => "contribuciones",
+"autoblocker"  => "Bloqueado automáticamente porque compartes una dirección IP con \"$1\". Motivo \"$2\".",
+
+# Developer tools
+#
+
+"lockdb"               => "Bloquear la base de datos",
+"unlockdb"             => "Desbloquear la base de datos",
+"lockdbtext"   => "El bloqueo de la base de datos impedirá a todos los usuarios editar páginas, cambiar sus preferencias, modificar sus listas de seguimiento y cualquier otra función que requiera realizar cambios en la base de datos. Por favor, confirma que ésto es precisamente lo que quieres hacer y que desbloquearás la base de datos tan pronto hayas finalizado las operaciones de mantenimiento.",
+"unlockdbtext" => "El desbloqueo de la base de datos permitirá a todos los usuarios editar páginas, cambiar sus preferencias, modificar sus listas de seguimiento y cualesquiera otras funciones que impliquen modificar la base de datos. Por favor, confirma que ésto es precisamente lo que quieres hacer.",
+"lockconfirm"  => "Sí, realmente quiero bloquear la base de datos.",
+"unlockconfirm"        => "Sí, realmente quiero desbloquear la base de datos.",
+"lockbtn"              => "Bloquear la base de datos",
+"unlockbtn"            => "Desbloquear la base de datos",
+"locknoconfirm" => "No has confirmado lo que deseas hacer.",
+"lockdbsuccesssub" => "El bloqueo se ha realizado con éxito",
+"unlockdbsuccesssub" => "El desbloqueo se ha realizado con éxito",
+"lockdbsuccesstext" => "La base de datos de {{SITENAME}} ha sido bloqueada.
+<br />Recuerda retirar el bloqueo después de completar las tareas de mantenimiento.",
+"unlockdbsuccesstext" => "La base de datos de {{SITENAME}} ha sido desbloqueada.",
+
+# Move page
+#
+"movepage"             => "Renombrar página",
+"movepagetext" => "Usando el formulario que sigue renombrará una página,
+moviendo todo su historial al nombre nuevo.
+El título anterior se convertirá en un redireccionamiento al nuevo título.
+Enlaces al antiguo título de la página no se cambiarán. Asegúrate de verificar no dejar redirecciones dobles o rotas.
+Tú eres responsable de hacer que los enlaces sigan apuntando adonde se supone que lo deberían hacer.
+
+Recuerda que la página '''no''' será renombrada si ya existe una página con el nuevo título, a no ser que sea una página vacía o un ''redirect'' sin historial.
+Esto significa que podrás renombrar una página a su título original si cometes un error de escritura en el nuevo título, pero que no podrás sobreescribir una página existente.
+
+<b>ADVERTENCIA!</b>
+Este puede ser un cambio drástico e inesperado para una página popular;
+por favor, asegúrate de entender las consecuencias que acarreará
+antes de seguir adelante.",
+"movepagetalktext" => "La página de discusión asociada, si existe, será renombrada automáticamente '''a menos que:'''
+*Estés moviendo la página entre espacios de nombre diferentes,
+*Una página de discusión no vacía ya existe con el nombre nuevo, o
+*Desactivaste la opción \"Renombrar la página de discusión también\".
+
+En estos casos, deberás trasladar manualmente el contenido de la página de discusión.",
+"movearticle"  => "Renombrar página",
+"movenologin"  => "No has iniciado sesión",
+"movenologintext" => "Es necesario ser usuario registrado y [[Especial:Userlogin|haber iniciado sesión]]
+para renombrar una página.",
+"newtitle"             => "A título nuevo",
+"movepagebtn"  => "Renombrar página",
+"pagemovedsub" => "Renombrado realizado",
+"pagemovedtext" => "Página \"[[$1]]\" renombrada a \"[[$2]]\".",
+"articleexists" => "Ya existe una página con ese nombre, o el nombre que has
+escogido no es válido.
+Por favor, elige otro nombre.",
+"talkexists"   => "La página fue renombrada con éxito, pero la página de discusión no se pudo mover porque ya existe una en el título nuevo. Por favor incorpora su contenido manualmente.",
+"movedto"              => "renombrado a",
+"movetalk"     => "Renombrar la página de discusión también, si es aplicable.",
+"talkpagemoved" =>  "La página de discusión correspondiente también fue renombrada.",
+"talkpagenotmoved" => "La página de discusión correspondiente <strong>no</strong> fue renombrada.",
+# Math
+'mw_math_png' => "Producir siempre PNG",
+'mw_math_simple' => "HTML si es muy simple, si no PNG",
+'mw_math_html' => "HTML si es posible, si no PNG",
+'mw_math_source' => "Dejar como TeX (para navegadores de texto)",
+'mw_math_modern' => "Recomendado para navegadores modernos",
+'mw_math_mathml' => 'MathML',
+
+# Bits of text used by many pages:
+#
+'categories' => 'Categorías',
+'category' => 'categoría',
+'category_header' => 'Artículos en la categoría "$1"',
+'subcategories' => 'Subcategorías',
+
+# Short words for each namespace, by default used in the 'article' tab in monobook
+'nstab-main' => 'Artículo',
+'nstab-user' => 'Usuario',
+'nstab-media' => 'Media',
+'nstab-special' => 'Especial',
+'nstab-wp' => 'Acerca de',
+'nstab-image' => 'Imagen',
+'nstab-mediawiki' => 'Mensaje',
+'nstab-template' => 'Plantilla',
+'nstab-help' => 'Ayuda',
+'nstab-category' => 'Categoría',
+
+
+# Edit page toolbar
+'bold_sample' => "Texto en negrita",
+'bold_tip' => "Texto en negrita",
+'italic_sample' => "Texto en cursiva",
+'italic_tip' => "Texto en cursiva",
+'link_sample' => "Título del enlace",
+'link_tip' => "Enlace interno",
+'extlink_sample' => "http://www.ejemplo.com Título del enlace",
+'extlink_tip' => "Enlace externo (recuerda añadir el prefijo http://)",
+'headline_sample' => "Texto de titular",
+'headline_tip' => "Titular de nivel 2",
+'math_sample' => "Escribe aquí una fórmula",
+'math_tip' => "Fórmula matemática (LaTeX)",
+'nowiki_sample' => "Aquí inserta texto sin formato",
+'nowiki_tip' => "Pasar por alto el formato wiki",
+'image_sample' => "Ejemplo.jpg",
+'image_tip' => "Imagen incorporada",
+'media_sample' => "Ejemplo.mp3",
+'media_tip'=> 'Enlace a archivo multimedia',
+'sig_tip' => "Firma, fecha y hora",
+'hr_tip' => "Línea horizontal (utilízala con moderación)",
+'infobox' => "Pulsa un botón para ver un texto de ejemplo",
+# alert box shown in browsers where text selection does not work, test e.g. with mozilla or konqueror
+'infobox_alert' => "Escribe el texto al que quieres dar formato.\n Se mostrará en la caja de información para poder copiar y pegar.\nEjemplo:\n$1\nse convertirá en:\n$2",
+
+# Special:Allpages
+'nextpage'          => 'Next page ($1)',
+'allarticles'       => 'Todos los artículos',
+'allpagesprev'      => 'Anterior',
+'allpagesnext'      => 'Siguiente',
+'allinnamespace' => 'Todas las páginas (espacio $1)',
+'allpagessubmit'    => 'Mostrar',
+
+# Patrolling
+'markaspatrolleddiff'   => "Marcar como revisado",
+'markaspatrolledlink'   => "[$1]",
+'markaspatrolledtext'   => "Marcar este artículo como revisado",
+'markedaspatrolled'     => "Marcar como revisado",
+'markedaspatrolledtext' => "La versión seleccionada ha sido marcada como revisada.",
+'rcpatroldisabled'      => "Revisión de los Cambios Recientes deshabilitada",
+'rcpatroldisabledtext'  => "La capacidad de revisar los Cambios Recientes está deshabilitada en este momento.",
+
+'showhideminor' => "$1 ediciones menores | $2 bots | $3 usuarios registrados | $4 ediciones revisadas ",
+
+# labels for User: and Title: on Special:Log pages
+'specialloguserlabel' => 'Usuario: ',
+'speciallogtitlelabel' => 'Título: ',
+
+'subcategorycount' => "Hay $1 subcategorías en esta categoría.",
+'subcategorycount1' => "Hay $1 subcategoría en esta categoría.",
+'categoryarticlecount' => "Hay $1 artículos en esta categoría.",
+'categoryarticlecount1' => "Hay $1 artículo en esta categoría.",
+'categoriespagetext' => "Existen las siguientes categorías en este wiki.",
+
+'toolbox' => "Herramientas",
+
+
+'tooltip-compareselectedversions' => "Ver las diferencias entre las dos versiones seleccionadas de esta página. [alt-v]",
+'tooltip-minoredit' => "Marcar este cambio como menor [alt-i]",
+'tooltip-preview' => "Previsualiza tus cambios, ¡por favor, usa esto antes de grabar! [alt-p]",
+'tooltip-save' => "Guardar tus cambios [alt-s]",
+'tooltip-search' => "Buscar en este wiki [alt-f]",
+
+'clearyourcache' => "'''Nota:''' Tras salvar el fichero, debes refrescar la caché de tu navegador para ver los cambios:
+*'''Mozilla:'''  ''ctrl-shift-r'',
+*'''Internet Explorer:''' ''ctrl-f5'',
+*'''Safari:''' ''cmd-shift-r'',
+*'''Konqueror''' ''f5''.",
+'compareselectedversions' => "Comparar versiones seleccionadas",
+
+'feedlinks' => "Sindicación:",
+
+'import' => "Importar páginas",
+'importfailed' => "La importación ha fallado: $1",
+'importhistoryconflict' => "Existe un historial de revisiones en conflicto (puede haberse importado esta página con anterioridad)",
+'importnotext' => "Vacío o sin texto",
+'importsuccess' => "¡La importación tuvo éxito!",
+'importtext' => "Por favor, exporta el archivo desde el wiki de origen usando la utilidad Special:Export, guardalo en tu disco y súbelo aquí.",
+
+'thumbnail-more' => "Aumentar",
+
+'imagemaxsize' => 'Limitar imágenes en las páginas descripción a: ',
+'showbigimage' => 'Descargar versión de alta resolución ($1x$2, $3 KB)',
+
+'newimages' => 'Galería de imágenes nuevas',
+'noimages'  => 'No hay nada que ver.',
+
+'previousdiff' => "← Ir a diferencia anterior",
+'nextdiff' => "Ir a siguiente diferencia →",
+
+'deletedrevision' => "Borrada revisión antigua $1.",
+
+'Monobook.js' => "/* tooltips and access keys */
+ta = new Object();
+ta['pt-userpage'] = new Array('.','Mi página de usuario');
+ta['pt-anonuserpage'] = new Array('.','La página de usuario de la IP desde la que editas');
+ta['pt-mytalk'] = new Array('n','Mi página de discusión');
+ta['pt-anontalk'] = new Array('n','Discusión sobre ediciones hechas desde esta dirección IP');
+ta['pt-preferences'] = new Array('','Mis preferencias');
+ta['pt-watchlist'] = new Array('l','La lista de páginas para las que estás vigilando los cambios');
+ta['pt-mycontris'] = new Array('y','Lista de mis contribuciones');
+ta['pt-login'] = new Array('o','Te animamos a registrarte, aunque no es obligatorio');
+ta['pt-anonlogin'] = new Array('o','Te animamos a registrarte, aunque no es obligatorio');
+ta['pt-logout'] = new Array('o','Salir de la sesión');
+ta['ca-talk'] = new Array('t','Discusión acerca del artículo');
+ta['ca-edit'] = new Array('e','Puedes editar esta página. Por favor, usa el botón de previsualización antes de grabar.');
+ta['ca-addsection'] = new Array('+','Añade un comentario a esta discusión');
+ta['ca-viewsource'] = new Array('e','Esta página está protegida, sólo puedes ver su código fuente');
+ta['ca-history'] = new Array('h','Versiones anteriores de esta página');
+ta['ca-protect'] = new Array('=','Proteger esta página');
+ta['ca-delete'] = new Array('d','Borrar esta página');
+ta['ca-undelete'] = new Array('d','Restaurar las ediciones hechas a esta página antes de que fuese borrada');
+ta['ca-move'] = new Array('m','Trasladar (renombrar) esta página');
+ta['ca-watch'] = new Array('w','Añadir esta página a tu lista de seguimiento');
+ta['ca-unwatch'] = new Array('w','Borrar esta página de tu lista de seguimiento');
+ta['search'] = new Array('f','Buscar en este wiki');
+ta['p-logo'] = new Array('','Portada');
+ta['n-mainpage'] = new Array('z','Visitar la Portada');
+ta['n-portal'] = new Array('','Acerca del proyecto, qué puedes hacer, dónde encontrar información');
+ta['n-currentevents'] = new Array('','Información de contexto sobre acontecimientos actuales');
+ta['n-recentchanges'] = new Array('r','La lista de cambios recientes en el wiki');
+ta['n-randompage'] = new Array('x','Cargar una página aleatoriamente');
+ta['n-help'] = new Array('','El lugar para aprender');
+ta['n-sitesupport'] = new Array('','Respáldanos');
+ta['t-whatlinkshere'] = new Array('j','Lista de todas las páginas del wiki que enlazan con ésta');
+ta['t-recentchangeslinked'] = new Array('k','Cambios recientes en las páginas que enlazan con esta otra');
+ta['feed-rss'] = new Array('','Sindicación RSS de esta página');
+ta['feed-atom'] = new Array('','Sindicación Atom de esta página');
+ta['t-contributions'] = new Array('','Ver la lista de contribuciones de este usuario');
+ta['t-emailuser'] = new Array('','Enviar un mensaje de correo a este usuario');
+ta['t-upload'] = new Array('u','Subir imágenes o archivos multimedia');
+ta['t-specialpages'] = new Array('q','Lista de todas las páginas especiales');
+ta['ca-nstab-main'] = new Array('c','Ver el artículo');
+ta['ca-nstab-user'] = new Array('c','Ver la página de usuario');
+ta['ca-nstab-media'] = new Array('c','Ver la página de multimedia');
+ta['ca-nstab-special'] = new Array('','Esta es una página especial, no se puede editar la página en sí');
+ta['ca-nstab-wp'] = new Array('a','Ver la página de proyecto');
+ta['ca-nstab-image'] = new Array('c','Ver la página de la imagen');
+ta['ca-nstab-mediawiki'] = new Array('c','Ver el mensaje de sistema');
+ta['ca-nstab-template'] = new Array('c','Ver la plantilla');
+ta['ca-nstab-help'] = new Array('c','Ver la página de ayuda');
+ta['ca-nstab-category'] = new Array('c','Ver la página de categoría');",
+'navigation' => "Navegación",
+
+'portal'               => 'Portal de la comunidad',
+'portal-url'           => 'Project:Portal de la comunidad',
+
+'validate'             => 'Validar página',
+'uncategorizedpages'   => 'Páginas sin categorizar',
+'uncategorizedcategories'      => 'Categorías sin categorizar',
+
+'movedto' => "renombrado a",
+'moredotdotdot' => "Más...",
+);
+
+class LanguageEs extends LanguageUtf8 {
+
+       function getNamespaces() {
+               global $wgNamespaceNamesEs;
+               return $wgNamespaceNamesEs;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsEs;
+               return $wgQuickbarSettingsEs;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesEs;
+               return $wgSkinNamesEs;
+       }
+
+       function shortdate( $ts, $adj = false ) {
+               if ( $adj ) { $ts = $this->userAdjust( $ts ); }
+
+               $d = (0 + substr( $ts, 6, 2 )) . " " .$this->getMonthAbbreviation( substr( $ts, 4, 2 ) ) . ", " .
+                 substr( $ts, 0, 4 );
+               return $d;
+       }
+
+       function date( $ts, $adj = false ) {
+               if ( $adj ) { $ts = $this->userAdjust( $ts ); }
+
+               $d = (0 + substr( $ts, 6, 2 )) . " de " .$this->getMonthName( substr( $ts, 4, 2 ) ) . ", " .
+                 substr( $ts, 0, 4 );
+               return $d;
+       }
+
+       function time( $ts, $adj = false ) {
+               if ( $adj ) { $ts = $this->userAdjust( $ts ); }
+
+               $t = substr( $ts, 8, 2 ) . ":" . substr( $ts, 10, 2 );
+               return $t;
+       }
+
+       function timeanddate( $ts, $adj = false ) {
+               return $this->time( $ts, $adj ) . " " . $this->shortdate( $ts, $adj );
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesEs;
+               if( isset( $wgAllMessagesEs[$key] ) ) {
+                       return $wgAllMessagesEs[$key];
+               } else {
+                       return parent::getMessage( $key );
+               }
+       }
+
+       function formatNum( $number, $year = false ) {
+               return $year ? $number : strtr($this->commafy($number), '.,', ',.' );
+       }
+}
+
+?>
diff --git a/languages/LanguageEt.php b/languages/LanguageEt.php
new file mode 100644 (file)
index 0000000..af24e77
--- /dev/null
@@ -0,0 +1,1166 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+$wgNamespaceNamesEt = array(
+       NS_MEDIA            => 'Meedia',
+       NS_SPECIAL          => 'Eri',
+       NS_MAIN             => '',
+       NS_TALK             => 'Arutelu',
+       NS_USER             => 'Kasutaja',
+       NS_USER_TALK        => 'Kasutaja_arutelu',
+       NS_PROJECT          => $wgMetaNamespace,
+       NS_PROJECT_TALK     => $wgMetaNamespace . '_arutelu',
+       NS_IMAGE            => 'Pilt',
+       NS_IMAGE_TALK       => 'Pildi_arutelu',
+       NS_MEDIAWIKI        => 'MediaWiki',
+       NS_MEDIAWIKI_TALK   => 'MediaWiki_arutelu',
+       NS_TEMPLATE         => 'Mall',
+       NS_TEMPLATE_TALK    => 'Malli_arutelu',
+       NS_HELP             => 'Juhend',
+       NS_HELP_TALK        => 'Juhendi_arutelu',
+       NS_CATEGORY         => 'Kategooria',
+       NS_CATEGORY_TALK    => 'Kategooria_arutelu'
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgSkinNamesEt = array(
+       'standard' => "Standard",
+       'nostalgia' => "Nostalgia",
+       'cologneblue' => "Kölni sinine",
+       'smarty' => "Paddington",
+       'montparnasse' => "Montparnasse",
+       'davinci' => "DaVinci",
+       'mono' => "Mono",
+       'monobook' => "MonoBook",
+        "myskin" => "Mu oma nahk"
+);
+
+
+/* private */ $wgDateFormatsEt = array(
+        'Eelistus puudub',
+        '15.01.2001, kell 16.12',
+        '15. jaanuar 2001, kell 16.12',
+        '15. I 2005, kell 16.12',
+        'ISO 8601' => '2001-01-15 16:12:34'
+);
+
+
+/* private */ $wgQuickbarSettingsEt = array(
+       "Ei_ole", "Püsivalt_vasakul", "Püsivalt paremal", "Ujuvalt vasakul"
+);
+
+#Lisasin eestimaised poed, aga võõramaiseid ei julenud kustutada.
+
+
+/* private */ $wgBookstoreListEt = array(
+       "Apollo" => "http://www.apollo.ee/search.php?keyword=$1&search=OTSI",
+       "minu Raamat" => "http://www.raamat.ee/advanced_search_result.php?keywords=$1",
+       "Raamatukoi" => "http://www.raamatukoi.ee/cgi-bin/index?valik=otsing&paring=$1",
+       "AddALL" => "http://www.addall.com/New/Partner.cgi?query=$1&type=ISBN",
+       "PriceSCAN" => "http://www.pricescan.com/books/bookDetail.asp?isbn=$1",
+       "Barnes & Noble" => "http://search.barnesandnoble.com/bookSearch/isbnInquiry.asp?isbn=$1",
+       "Amazon.com" => "http://www.amazon.com/exec/obidos/ISBN=$1"
+);
+
+
+/* private */ $wgMagicWordsEt = array(
+#   ID                                 CASE  SYNONYMS
+       MAG_REDIRECT             => array( 0,    '#redirect', "#suuna"    ),
+       MAG_NOTOC                => array( 0,    '__NOTOC__'              ),
+       MAG_FORCETOC             => array( 0,    '__FORCETOC__'           ),
+       MAG_TOC                  => array( 0,    '__TOC__'                ),
+       MAG_NOEDITSECTION        => array( 0,    '__NOEDITSECTION__'      ),
+       MAG_START                => array( 0,    '__START__'              ),
+       MAG_CURRENTMONTH         => array( 1,    'CURRENTMONTH'           ),
+       MAG_CURRENTMONTHNAME     => array( 1,    'CURRENTMONTHNAME'       ),
+       MAG_CURRENTDAY           => array( 1,    'CURRENTDAY'             ),
+       MAG_CURRENTDAYNAME       => array( 1,    'CURRENTDAYNAME'         ),
+       MAG_CURRENTYEAR          => array( 1,    'CURRENTYEAR'            ),
+       MAG_CURRENTTIME          => array( 1,    'CURRENTTIME'            ),
+       MAG_NUMBEROFARTICLES     => array( 1,    'NUMBEROFARTICLES'       ),
+       MAG_CURRENTMONTHNAMEGEN  => array( 1,    'CURRENTMONTHNAMEGEN'    ),
+       MAG_PAGENAME             => array( 1,    'PAGENAME'               ),
+       MAG_PAGENAMEE                    => array( 1,    'PAGENAMEE'              ),
+       MAG_NAMESPACE            => array( 1,    'NAMESPACE'              ),
+       MAG_SUBST                => array( 0,    'SUBST:'                 ),
+       MAG_MSGNW                => array( 0,    'MSGNW:'                 ),
+       MAG_END                  => array( 0,    '__END__'                ),
+       MAG_IMG_THUMBNAIL        => array( 1,    'thumbnail', 'thumb'     ),
+       MAG_IMG_RIGHT            => array( 1,    'right'                  ),
+       MAG_IMG_LEFT             => array( 1,    'left'                   ),
+       MAG_IMG_NONE             => array( 1,    'none'                   ),
+       MAG_IMG_WIDTH            => array( 1,    '$1px'                   ),
+       MAG_IMG_CENTER           => array( 1,    'center', 'centre'       ),
+       MAG_IMG_FRAMED           => array( 1,    'framed', 'enframed', 'frame' ),
+       MAG_INT                  => array( 0,    'INT:'                   ),
+       MAG_SITENAME             => array( 1,    'SITENAME'               ),
+       MAG_NS                   => array( 0,    'NS:'                    ),
+       MAG_LOCALURL             => array( 0,    'LOCALURL:'              ),
+       MAG_LOCALURLE            => array( 0,    'LOCALURLE:'             ),
+       MAG_SERVER               => array( 0,    'SERVER'                 ),
+       MAG_GRAMMAR              => array( 0,    'GRAMMAR:'               )
+);
+
+/* private */ $wgAllMessagesEt = array(
+"tog-underline" => "Lingid alla kriipsutada",
+"tog-highlightbroken" => "Vorminda lingirikked<a href=\"\" class=\"new\">nii</a> (alternatiiv: nii<a href=\"\" class=\"internal\">?</a>).",
+"tog-justify" => "Lõikude rööpjoondus",
+"tog-hideminor" => "Peida pisiparandused viimastes muudatustes",
+"tog-usenewrc" => "Laiendatud viimased muudatused (mitte kõikide brauserite puhul)",
+"tog-numberheadings" => "Pealkirjade automaatnummerdus",
+"tog-showtoolbar" => "Redigeerimise tööriistariba näitamine",
+"tog-rememberpassword" => "Parooli meeldejätmine tulevasteks seanssideks",
+"tog-editwidth" => "Redaktoriboksil on täislaius",
+"tog-editondblclick" => "Artiklite redigeerimine topeltklõpsu peale (JavaScript)",
+"tog-watchdefault" => "Jälgi uusi ja muudetud artikleid",
+"tog-minordefault" => "Märgi kõik parandused vaikimisi pisiparandusteks",
+"tog-previewontop" => "Näita eelvaadet redaktoriboksi ees, mitte järel",
+
+# Dates
+'sunday' => 'pühapäev',
+'monday' => 'esmaspäev',
+'tuesday' => 'teisipäev',
+'wednesday' => 'kolmapäev',
+'thursday' => 'neljapäev',
+'friday' => 'reede',
+'saturday' => 'laupäev',
+'january' => 'jaanuar',
+'february' => 'veebruar',
+'march' => 'märts',
+'april' => 'aprill',
+'may_long' => 'mai',
+'june' => 'juuni',
+'july' => 'juuli',
+'august' => 'august',
+'september' => 'september',
+'october' => 'oktoober',
+'november' => 'november',
+'december' => 'detsember',
+'jan' => 'jaan',
+'feb' => 'veebr',
+'mar' => 'märts',
+'apr' => 'apr',
+'may' => 'mai',
+'jun' => 'juuni',
+'jul' => 'juuli',
+'aug' => 'aug',
+'sep' => 'sept',
+'oct' => 'okt',
+'nov' => 'nov',
+'dec' => 'dets',
+
+# Bits of text used by many pages:
+#
+'categories' => 'Kategooriad',
+'category' => 'kategooria',
+'category_header' => 'Selles kategoorias on "$1" artiklit',
+'subcategories' => 'Alamkategooriad',
+
+
+"linktrail"            => "/^([a-z]+)(.*)\$/sD",
+"mainpage"             => "Esileht",
+"mainpagetext" => "Wiki tarkvara installeeritud.",
+"mainpagedocfooter" => "Juhiste saamiseks kasutamise ning konfigureerimise kohta vaata palun inglisekeelset [http://meta.wikipedia.org/wiki/MediaWiki_i18n dokumentatsiooni liidese kohaldamisest]
+ning [http://meta.wikipedia.org/wiki/MediaWiki_User%27s_Guide kasutusjuhendit].",
+'portal'                =>  'Kogukonnavärav', # Kirjutajate portaal?
+'portal-url'            => '{{ns:4}}:Kogukonnavärav',
+"about"                        => "Tiitelandmed",
+"aboutsite" => "{{SITENAME}} tiitelandmed",
+"aboutpage"            => "{{ns:4}}:Tiitelandmed",
+"article"              => "Sisu",  # või "Artikkel" nagu praegu Vikipeedias?
+"help"                 => "Juhend", # Vikipeedias "Spikker"
+"helppage"             => "{{ns:12}}:Juhend",
+"bugreports"   => "Teated programmivigadest",
+"bugreportspage" => "{{ns:4}}:Teated_programmivigadest",
+'sitesupport'   => 'Annetused', # Set a URL in $wgSiteSupportPage in LocalSettings.php
+"faq"                  => "KKK",
+"faqpage"              => "{{ns:4}}:KKK",
+"edithelp"             => "Redigeerimisjuhend",
+"newwindow"             => "(avaneb uues aknas)",
+"edithelppage" => "{{ns:12}}:Kuidas_artiklit_redigeerida",
+"cancel"               => "Tühista",
+"qbfind"               => "Otsi",
+"qbbrowse"             => "Sirvi",
+"qbedit"               => "Redigeeri",
+"qbpageoptions" => "Lehekülje suvandid",  // en: this page
+"qbpageinfo"   => "Lehekülje andmed",    // en: context
+"qbmyoptions"  => "Minu suvandid",       // en: my pages
+"qbspecialpages" => "Erileheküljed",
+'moredotdotdot' => 'Veel...',
+"mypage"               => "Minu lehekülg",
+"mytalk"               => "Minu arutelu",
+'anontalk'              => 'Arutelu selle IP jaoks',
+"currentevents" => "Jooksvad sündmused",
+"navigation"   => "Navigeerimine",
+"errorpagetitle" => "Viga",
+'disclaimers' => 'Hoiatused',
+"disclaimerpage"   => "{{ns:4}}:Üldised_hoiatused", # lihtsalt "Hoiatused"?
+"returnto"             => "Naase $1 juurde",
+"tagline"      => "Allikas: {{SITENAME}}",
+"whatlinkshere"        => "Siia viitavad artiklid",
+"help"                 => "Juhend",
+"search"               => "Otsi",
+"go"           => "Mine",
+"history"              => "Artikli ajalugu",
+'history_short' => 'Ajalugu',
+'info_short'    => 'Info',
+"printableversion" => "Prinditav versioon",
+"editthispage" => "Redigeeri seda artiklit",
+'edit' => 'Redigeeri',
+
+"delete" => "Kustuta",
+"deletethispage" => "Kustuta see artikkel",
+"undelete_short" => "Taasta $1 muudatust",
+"undelete_short1" => "Taasta 1 muudatust",
+"protect" => "Kaitse",
+"protectthispage" => "Kaitse seda artiklit",
+"unprotect" => "Ära kaitse",
+"unprotectthispage" => "Ära kaitse seda artiklit",
+"newpage" => "Uus artikkel",
+"talkpage"             => "Selle artikli arutelu",
+'specialpage' => 'Erilehekülg',
+'personaltools' => 'Personaalsed tööriistad',
+'postcomment'   => 'Lisa kommentaar',
+'addsection'   => '+',
+"articlepage"  => "Artiklilehekülg",
+"subjectpage"  => "Teema", # For compatibility
+'talk' => 'Arutelu',
+'toolbox' => 'Tööriistakast',
+"userpage" => "Kasutajalehekülg",
+"wikipediapage" => "Metalehekülg",
+"imagepage" =>         "Pildilehekülg",
+"viewtalkpage" => "Arutelulehekülg",
+"otherlanguages" => "Teised keeled",
+"redirectedfrom" => "(Ümber suunatud artiklist $1)",
+"lastmodified" => "Viimane muutmine: $1",
+"viewcount"            => "Seda lehekülge on külastatud $1 korda.",
+# aegunud, võib vist eemaldada, asendada järgmisega:
+"copyright" => "Kogu tekst on kasutatav litsentsi <a class=internal href='$wgScriptPath/GNU_FDL'>GNU Vaba Dokumentatsiooni Litsentsi</a> (GFDL) tingimustel.",
+'poweredby'     => "{{SITENAME}} kasutab avatud koodiga wiki mootorit [http://www.mediawiki.org/ MediaWiki].",
+"printsubtitle" => "(Allikas: {{SERVER}})",
+"protectedpage" => "Kaitstud artikkel",
+"administrators" => "{{ns:4}}:Administraatorid",
+"sysoptitle"   => "Nõutav süsteemi operaatori staatus",
+"sysoptext"    => "Seda toimingut saavad sooritada ainult süsteemi operaatori staatusega kasutajad. Vaata $1.",
+"developertitle" => "Nõutav süsteemiarendaja staatus",
+"developertext"        => "Seda toimingut saavad sooritada ainult süsteemiarendaja staatusega kasutajad.
+Vaata $1.",
+"nbytes"               => "$1 baiti",
+"go"                   => "Mine",
+"ok"                   => "OK",
+"sitetitle"            => "{{SITENAME}}",
+'pagetitle'             => "$1 - {{SITENAME}}",
+"sitesubtitle" => "Vaba entsüklopeedia", # sõltub saidist (FIXME)
+"retrievedfrom" => "Välja otsitud andmebaasist \"$1\"", # parandaks sõnastust?
+"newmessages" => "Teile on uusi sõnumeid ($1).",
+"newmessageslink" => "Vaata sõnumeid.",
+'editsection'=>'redigeeri',
+'toc' => 'Sisukord',
+'showtoc' => 'näita',
+'hidetoc' => 'peida',
+'thisisdeleted' => "Vaata või taasta $1?", # View or restore...
+'restorelink' => "Kustutatud muudatuste arv: $1",
+'feedlinks' => 'Sööde:', # See sõna ei meeldi, aga paremat ei tea.
+'sitenotice'    => '', # the equivalent to wgSiteNotice
+
+
+# Short words for each namespace, by default used in the 'article' tab in monobook
+'nstab-main' => 'Artikkel',
+'nstab-user' => 'Kasutaja',
+'nstab-media' => 'Meedia',
+'nstab-special' => 'Eri',
+'nstab-wp' => 'Tiitelandmed', # about
+'nstab-image' => 'Pilt',
+'nstab-mediawiki' => 'Sõnum', # Message
+'nstab-template' => 'Mall',
+'nstab-help' => 'Juhend',
+'nstab-category' => 'Kategooria',
+
+# Main script and global functions
+#
+"nosuchaction" => "Sellist toimingut pole.",
+"nosuchactiontext" => "Wiki ei tunne sellele aadressile vastavat toimingut.",
+"nosuchspecialpage" => "Sellist erilehekülge pole.",
+"nospecialpagetext" => "Wiki ei tunne sellist erilehekülge.",
+
+
+# General errors
+#
+"error"                        => "Viga",
+"databaseerror" => "Andmebaasi viga",
+"dberrortext"  => "Andmebaasipäringus oli süntaksiviga.
+Otsingupäring oli ebakorrektne (vaata $5) või on tarkvaras viga.
+Viimane andmebaasipäring oli:
+<blockquote><tt>$1</tt></blockquote>
+ja see kutsuti funktsioonist \"<tt>$2</tt>\".
+MySQL andis vea \"<tt>$3: $4</tt>\".",
+"dberrortextcl" => "Andmebaasipäringus oli süntaksiviga.
+Viimane andmebaasipäring oli:
+\"$1\"
+ja see kutsuti funktsioonist \"$2\".
+MySQL andis vea \"$3: $4\".\n",
+"noconnect"            => "Vabandame! Wikil on tehnilisi probleeme ning ta ei saa andmebaasiserveriga $1 ühendust",
+"nodb"                 => "Andmebaasi $1 ei õnnestunud kätte saada",
+'cachederror'           => 'Järgnev lehekülg on puhverdatud koopia soovitud leheküljest ja ei pruugi seega olla värskeim.',
+"readonly"             => "Andmebaas on hetkel kirjutuskaitse all", # 'Database locked', võimalik et siiski "Andmebaas kaitse alla"
+"enterlockreason" => "Sisesta lukustamise põhjus ning juurdepääsu taastamise ligikaudne aeg",
+"readonlytext" => "Andmebaas on praegu kirjutuskaitse all, tõenäoliselt andmebaasi rutiinseks hoolduseks, mille lõppedes normaalne olukord taastub.
+Administraator, kes selle kaitse alla võttis, andis järgmise selgituse:
+<p>$1",
+"missingarticle" => "Andmebaas ei leidnud lehekülje \"$1\" teksti, kuigi see oleks pidanud olema leitav.
+
+<p>Tavaliselt on selle põhjuseks vananenud sisuerinevuste- või ajaloolink leheküljele, mis on kustutatud.
+
+<p>Kui ei ole tegemist sellise juhtumiga, siis võib olla tegemist tarkvaraveaga. Palun teatage sellest administraatorile, märkides ära kasutatud aadressi.",
+"internalerror" => "Sisemine viga",
+"filecopyerror" => "Ei saanud faili \"$1\" failiks \"$2\" kopeerida.",
+"filerenameerror" => "Ei saanud faili \"$1\" failiks \"$2\" ümber nimetada.",
+"filedeleteerror" => "Faili nimega \"$1\" ei ole võimalik kustutada.",
+"filenotfound" => "Faili nimega \"$1\" ei leitud.",
+"unexpected"   => "Ootamatu väärtus: \"$1\"=\"$2\".",
+"formerror"            => "Viga: vormi ei saanud salvestada",
+"badarticleerror" => "Seda toimingut ei saa sellel leheküljel sooritada.",
+"cannotdelete" => "Seda lehekülge või pilti ei ole võimalik kustutada. (Võib-olla keegi teine juba kustutas selle.)",
+"badtitle"             => "Vigane pealkiri",
+"badtitletext" => "Küsitud artiklipealkiri oli kas vigane, tühi või siis
+valesti viidatud keelte- või wikidevaheline pealkiri.",
+"perfdisabled" => "Vabandage! See funktsioon ajutiselt ei tööta, sest ta aeglustab andmebaasi kasutamist võimatuseni. Sellepärast täiustatakse vastavat programmi lähitulevikus. Võib-olla teete seda Teie!",
+'perfdisabledsub' => "Siin on salvestatud koopia $1-st:", # obsolete?
+'perfcached' => 'Järgnevad andmed on puhverdatud ja ei pruugi olla kõige värskemad:',
+'wrong_wfQuery_params' => "Valed parameeterid funktsioonile wfQuery()<br />
+Funktsioon: $1<br />
+Päring: $2
+",
+'viewsource' => 'Vaata lähteteksti',
+'protectedtext' => "See lehekülg on lukustatud, et muudatusi vältida. Selleks võib olla
+mitmesuguseid põhjusi, vaata palun artiklit
+[[{{ns:4}}:Lukustatud lehekülg]].
+Sa saad aga vaadata ja kopeerida selle lehekülje lähteteksti -- ",
+
+
+
+
+# Login and logout pages
+#
+"logouttitle"  => "Väljalogimine",
+"logouttext"   => "Te olete välja loginud.
+Võite kasutada süsteemi anonüümselt, aga ka sama või mõne teise kasutajana uuesti sisse logida.\n",
+        # rookisin Vikipeedia välja, {{SITENAME}} oleks õige, aga vajab ümbersõnastamist.
+
+"welcomecreation" => "<h2>Tere tulemast, $1!</h2><p>Teie konto on loodud. Ärge unustage seada oma eelistusi.",
+
+"loginpagetitle" => "Sisselogimine",
+"yourname"             => "Teie kasutajanimi",
+"yourpassword" => "Teie parool",
+"yourpasswordagain" => "Sisestage parool uuesti",
+"newusersonly" => " (ainult uued kasutajad)",
+"remembermypassword" => "Parooli meeldejätmine tulevasteks seanssideks.",
+"loginproblem" => "<b>Sisselogimine ei õnnestunud.</b><br />Proovige uuesti!",
+"alreadyloggedin" => "<strong>Kasutaja $1, Te olete juba sisse loginud!</strong><br />\n",
+
+"login"                        => "Logi sisse",
+'loginprompt'           => "{{SITENAME}} võimaldab sisselogimist vaid siis kui küpsised on lubatud.",
+"userlogin"            => "Logi sisse",
+"logout"               => "Logi välja",
+"userlogout"   => "Logi välja",
+"createaccount"        => "Loo uus konto",
+'createaccountmail'     => 'meili teel',
+"badretype"            => "Sisestatud paroolid ei lange kokku.",
+"userexists"   => "Sisestatud kasutajanimi on juba kasutusel. Valige uus nimi.",
+"youremail"            => "Teie e-posti aadress*",
+"yournick"             => "Teie hüüdnimi (allakirjutamiseks)",
+"emailforlost" => "* Meiliaadressi sisestamine ei ole kohustuslik. Kuid see aitab inimestel Teiega veebisaidi kaudu ühendust võtta, ilma et Te peaksite neile oma meiliaadressi avaldama, ning samuti on sellest kasu, kui unustate parooli. <br /><br />Teie päris nime, kui otsustate selle avaldada, kasutatakse Teie tööpanuse seostamiseks Teiega.",
+'prefs-help-realname' => '* <strong>Tegelik nimi</strong> (pole kohustuslik): kui otsustate selle avaldada, kasutatakse seda Teie tööpanuse seostamiseks Teiega.<br />',
+'prefs-help-email' => '* <strong>E-post</strong> (pole kohustuslik): Võimaldab inimestel Teiega veebisaidi kaudu ühendust võtta, ilma et Te peaksite neile oma meiliaadressi avaldama, samuti on sellest kasu, kui unustate parooli.',
+
+"loginerror"   => "Viga sisselogimisel",
+'nocookiesnew'  => "Kasutajakonto loodi, aga sa ei ole sisse logitud, sest {{SITENAME}} kasutab kasutajate tuvastamisel küpsiseid. Sinu brauseris on küpsised keelatud. Palun sea küpsised lubatuks ja logi siis oma vastse kasutajanime ning parooliga sisse.",
+"nocookieslogin"      => "{{SITENAME}} kasutab kasutajate tuvastamisel küpsiseid. Sinu brauseris on küpsised keelatud. Palun sea küpsised lubatuks ja proovi siis uuesti.",
+"noname"               => "Sa ei sisestanud kasutajanime lubataval kujul.",
+"loginsuccesstitle" => "Sisselogimine õnnestus",
+"loginsuccess" => "Te olete sisse loginud. Teie kasutajanimi on \"$1\".",
+"nosuchuser"   => "Kasutajat nimega \"$1\" ei ole olemas. Kontrollige kirjapilti või kasutage alljärgnevat vormi uue kasutajakonto loomiseks.",
+"wrongpassword"        => "Vale parool. Proovige uuesti.",
+"mailmypassword" => "Saada mulle meili teel uus parool",
+"passwordremindertitle" => "{{SITENAME}} - unustatud salasõna",
+"passwordremindertext" => "Keegi (tõenäoliselt Teie, IP-aadressilt $1),
+palus, et me saadaksime Teile uue parooli süsteemi sisselogimiseks.
+Kasutaja \"$2\" parool on nüüd \"$3\".
+Võiksid sisse logida ja selle ajutise parooli ära muuta. <BR \>
+
+Sinu {{SITENAME}}.",
+"noemail"              => "Kasutaja \"$1\" meiliaadressi meil kahjuks pole.",
+"passwordsent" => "Uus parool on saadetud kasutaja \"$1\" registreeritud meiliaadressil.
+Pärast parooli saamist logige palun sisse.",
+'loginend'              => ' ',
+'mailerror' => "Viga kirja saatmisel: $1",
+'acct_creation_throttle_hit' => 'Vabandame, aga te olete loonud juba $1 kontot. Rohkem te ei saa.',
+
+
+# Edit page toolbar
+'bold_sample'=>'Rasvane kiri',
+'bold_tip'=>'Rasvane kiri',
+'italic_sample'=>'Kursiiv',
+'italic_tip'=>'Kursiiv',
+'link_sample'=>'Lingitav pealkiri',
+'link_tip'=>'Siselink',
+'extlink_sample'=>'http://www.välislink.com Lingi nimi',
+'extlink_tip'=>'Välislink (ära unusta prefiksit http://)',
+'headline_sample'=>'Pealkiri',
+'headline_tip'=>'Teise taseme pealkiri',
+'math_sample'=>'Sisesta valem siia',
+'math_tip'=>'Matemaatiline tekst (LaTeX)',
+'nowiki_sample'=>'Sisesta formaatimata tekst',
+'nowiki_tip'=>'Ignoreeri viki vormindust',
+'image_sample'=>'Näidis.jpg',
+'image_tip'=>'Pilt',
+'media_sample'=>'Näidis.mp3',
+'media_tip'=>'Meediafail',
+'sig_tip'=>'Sinu allkiri koos ajatempliga',
+'hr_tip'=>'Horisontaaljoon',
+'infobox'=>'Näidisteksti saamiseks vajuta nupule',
+# alert box shown in browsers where text selection does not work, test e.g. with konqueror
+'infobox_alert'=>"Sisesta palun tekst, mida tahad formaatida.\\n See ilmub kopeerimiseks ja kleepimiseks
+infokasti.\\nNäide:\\n$1\\nmuutub selliseks:\\n$2",
+
+
+# Edit pages
+#
+"summary"              => "Resümee",
+'subject'               => 'Pealkiri',
+"minoredit"            => "See on pisiparandus",
+"watchthis"            => "Jälgi seda artiklit",
+"savearticle"  => "Salvesta",
+"preview"              => "Vaata",
+"showpreview"  => "Näita eelvaadet",
+"blockedtitle" => "Kasutaja on blokeeritud",
+"blockedtext"  => "Teie kasutajanime või IP-aadressi blokeeris $1.
+Tema põhjendus on järgmine:<br />''$2''<p>Küsimuse arutamiseks võite pöörduda $1 või mõne teise
+[[{{ns:4}}:administraatorid|administraatori]] poole.
+
+Pange tähele, et Te ei saa sellele kasutajale teadet saata, kui Te pole registreerinud oma [[Eri:Eelistused|eelistuste lehel]] kehtivat e-posti aadressi.
+
+Teie IP on $3. Lisage see aadress kõigile järelpärimistele, mida kavatsete teha.",
+
+'whitelistedittitle' => 'Toimetamiseks on vaja sisse logida',
+'whitelistedittext' => 'Lehekülgede toimetamiseks peate [[Eri:Userlogin|sisse logima]].',
+'whitelistreadtitle' => 'Lugemiseks peate olema sisse logitud',
+'whitelistreadtext' => 'Lehekülgede lugemiseks peate [[Eri:Userlogin|sisse logima]].',
+'whitelistacctitle' => 'Teil pole õigust kasutajakontot luua',
+'whitelistacctext' => 'Et selles Vikis kontosid luua, peate olema [[Eri:Userlogin|sisse logitud]] ja omama vastavaid õigusi.',
+
+'loginreqtitle' => 'Vajalik on sisselogimine',
+'loginreqtext'  => 'Lehekülgede vaatamiseks peate [[Eri:Userlogin|sisse logima]].',
+'accmailtitle' => 'Saadeti parool.',
+'accmailtext' => "Kasutaja '$1' parool saadeti aadressile $2.",
+
+"newarticle"   => "(Uus)",
+"newarticletext" =>
+"Seda lehekülge veel ei ole.
+Lehekülje loomiseks hakake kirjutama all olevasse boksi
+(lisainfo saamiseks vaadake [[{{ns:4}}:Juhend|juhendit]]).
+Kui sattusite siia kogemata, klõpsake lihtsalt brauseri ''back''-nupule.",
+"anontalkpagetext" => "---- ''See on arutelulehekülg anonüümse kasutaja kohta, kes ei ole loonud kontot või ei kasuta seda. Sellepärast tuleb meil kasutaja identifitseerimiseks kasutada tema [[IP-aadress]]i. See IP-aadress võib olla mitmele kasutajale ühine. Kui olete anonüümne kasutaja ning leiate, et kommentaarid sellel leheküljel ei ole mõeldud Teile, siis palun [[{{ns:4}}:Kasutaja sisselogimine|looge konto või logige sisse]], et edaspidi arusaamatusi vältida.'' ",
+"noarticletext" => "(See lehekülg on praegu tühi)",
+'clearyourcache' => "'''Märkus:''' Pärast salvestamist pead sa muudatuste nägemiseks oma brauseri puhvri tühjendama: '''Mozilla:''' ''ctrl-shift-r'', '''IE:''' ''ctrl-f5'', '''Safari:''' ''cmd-shift-r'', '''Konqueror''' ''f5''.",
+'usercssjsyoucanpreview' => "<strong>Vihje:</strong> Kasuta nuppu 'Näita eelvaadet' oma uue css/js testimiseks enne salvestamist.",
+'usercsspreview' => "'''Ärge unustage, et seda versiooni teie isiklikust stiililehest pole veel salvestatud!'''",
+'userjspreview' => "'''Ärge unustage, et see versioon teie isiklikust javascriptist on alles salvestamata!'''",
+
+"updated"              => "(Värskendatud)",
+"note"                 => "<strong>Meeldetuletus:</strong> ",
+"previewnote"  => "Ärge unustage, et see versioon ei ole veel salvestatud!",
+"previewconflict" => "See eelvaade näitab, kuidas ülemises toimetuskastis olev tekst hakkab välja nägema, kui otsustate salvestada.", ## redaktoriboks?
+"editing"              => "Redigeerimisel on $1",
+"editconflict" => "Redigeerimiskonflikt: $1",
+"explainconflict" => "Keegi teine on muutnud seda lehekülge pärast seda, kui Teie seda redigeerima hakkasite.
+Ülemine toimetuskast sisaldab teksti viimast versiooni.
+Teie muudatused on alumises kastis.
+Teil tuleb need viimasesse versiooni üle viia.
+Kui Te klõpsate nupule
+ \"Salvesta\", siis salvestub <b>ainult</b> ülemises toimetuskastis olev tekst.<br />",
+"yourtext"             => "Teie tekst",
+"storedversion" => "Salvestatud redaktsioon",
+"editingold"   => "<strong>ETTEVAATUST! Te redigeerite praegu selle lehekülje vana redaktsiooni.
+Kui Te selle salvestate, siis lähevad kõik vahepealsed muudatused kaduma.</strong>",
+"yourdiff"             => "Erinevused",
+"copyrightwarning" => "Pidage silmas, et kõik kaastööd loetakse avaldatuks vastavalt GNU Vaba Dokumentatsiooni Litsentsile
+(Üksikasjad on leheküljel $1).
+Kui Te ei soovi, et Teie poolt kirjutatut halastamatult redigeeritakse ja omal äranägemisel kasutatakse, siis ärge seda siia salvestage.<br />
+Te kinnitate ka, et kirjutasite selle ise või võtsite selle kopeerimiskitsenduseta allikast.
+<strong>ÄRGE SAATKE AUTORIÕIGUSTEGA KAITSTUD MATERJALI ILMA LOATA!</strong>", # Vikipeedia võtsin välja, {{SITENAME}} paigutada kuidagi?
+"longpagewarning" => "<strong>HOIATUS: Selle lehekülje pikkus ületab $1 kilobaiti. Mõne brauseri puhul valmistab raskusi juba 32-le kilobaidile läheneva pikkusega lehekülgede redigeerimine. Palun kaaluge selle lehekülje sisu jaotamist lühemate lehekülgede vahel.</strong>",
+"readonlywarning" => "<strong>HOIATUS: Andmebaas on lukustatud hooldustöödeks, nii et praegu ei saa parandusi salvestada. Võite teksti alal hoida tekstifailina ning salvestada hiljem.</strong>",
+"protectedpagewarning" => "<strong>HOIATUS:  See lehekülg on lukustatud, nii et seda saavad redigeerida ainult süsteemi operaatori õigustega kasutajad. Järgige juhtnööre leheküljel
+[[Project:Juhtnöörid_kaitstud_lehekülje_kohta]]</strong>.",
+
+# History pages
+#
+"revhistory"   => "Redigeerimislugu",
+"nohistory"            => "Sellel leheküljel ei ole eelmisi redaktsioone.",
+"revnotfound"  => "Redaktsiooni ei leitud",
+"revnotfoundtext" => "Teie poolt päritud vana redaktsiooni ei leitud.
+Palun kontrollige aadressi, millel Te seda lehekülge leida püüdsite.\n",
+"loadhist"             => "Lehekülje ajaloo laadimine",
+"currentrev"   => "Viimane redaktsioon",
+"revisionasof" => "Redaktsioon: $1",
+"cur"                  => "viim",
+"next"                 => "järg",
+"last"                 => "eel",
+"orig"                 => "orig",
+"histlegend"   => "Märgi versioonid, mida tahad võrrelda ja vajuta võrdlemisnupule.
+Legend: (viim) = erinevused võrreldes viimase redaktsiooniga,
+(eel) = erinevused võrreldes eelmise redaktsiooniga, P = pisimuudatus",
+'history_copyright'    => '-',
+# Diffs
+#
+"difference"   => "(Erinevused redaktsioonide vahel)",
+"loadingrev"   => "Redaktsiooni laadimine erinevustelehekülje jaoks",
+"lineno"               => "Rida $1:",
+"editcurrent"  => "Redigeeri selle lehekülje viimast redaktsiooni",
+'selectnewerversionfordiff' => 'Vali võrdlemiseks uuem versioon',
+'selectolderversionfordiff' => 'Vali võrdlemiseks vanem versioon',
+'compareselectedversions' => 'Võrdle valitud versioone',
+# Search results
+#
+"searchresults" => "Otsingu tulemid",
+"searchresulttext" => "Lisainfot otsimise kohta vaata $1.",
+"searchquery"  => "Päring \"$1\"",
+"badquery"             => "Vigane päring",
+"badquerytext" => "Teie päringut ei saanud menetleda.
+Tõenäoliselt püüdsite otsida vähem kui kolme-tähelist sõna.
+Selline otsing ei ole praegu veel võimalik. Võib ka olla,
+et päring oli vigane, nt. \"koer and and kass\" ei ole lubatav.
+Palun proovige teistsugust päringut.",
+"matchtotals"  => "Otsitud sõna \"$1\" leidub $2 artikli pealkirjas
+ning $3 artikli tekstis.",
+"nogomatch" => "Täpselt sellise pealkirjaga lehekülge ei ole, proovime täistekstotsingut.",
+"titlematches" => "Tabamused artiklipealkirjades",
+"notitlematches" => "Artiklipealkirjades tabamusi ei ole",
+"textmatches"  => "Tabamused artiklitekstides",
+"notextmatches"        => "Artiklitekstides tabamusi ei ole",
+"prevn"                        => "eelmised $1",
+"nextn"                        => "järgmised $1",
+"viewprevnext" => "Näita ($1) ($2) ($3).",
+"showingresults" => "Allpool näitame <b>$1</b> tulemit alates tulemist #<b>$2</b>.",
+"nonefound"            => "<strong>Märkus</strong>: otsingute ebaõnnestumise sagedaseks põhjuseks on asjaolu,
+et väga sageli esinevaid sõnu ei võta süsteem otsimisel arvesse. Teine põhjus võib olla
+mitme otsingusõna kasutamine (tulemusena ilmuvad ainult leheküljed, mis sisaldavad kõiki otsingusõnu).",
+"powersearch" => "Otsi",
+"powersearchtext" => "
+Otsing nimeruumidest :<br />
+$1<br />
+$2 Loetle ümbersuunamisi &nbsp; Otsi $3 $9",
+
+
+# Preferences page
+#
+"preferences"  => "Teie eelistused",
+"prefsnologin" => "Te ei ole sisse loginud",
+"prefsnologintext"     => "Et oma eelistusi seada, [[Special:Userlogin|tuleb Teil]]
+sisse logida.",
+"prefslogintext" => "Te olete sisse loginud kasutajanimega \"$1\".
+Teie sisemine ID-number on $2.",
+"prefsreset"   => "Teie eelistused on arvutimälu järgi taastatud.",
+"qbsettings"   => "Kiirriba sätted",
+"changepassword" => "Muuda parool",
+"skin"                 => "Nahk",
+"math"                 => "Valemite näitamine",
+"dateformat"            => "Kuupäeva formaat",
+"math_failure"         => "Arusaamatu süntaks",
+"math_unknown_error"   => "Tundmatu viga",
+"math_unknown_function"        => "Tundmatu funktsioon ",
+"math_lexing_error"    => "Väljalugemisviga",
+"math_syntax_error"    => "Süntaksiviga",
+"saveprefs"            => "Salvesta eelistused",
+"resetprefs"   => "Lähtesta eelistused",
+"oldpassword"  => "Vana parool",
+"newpassword"  => "Uus parool",
+"retypenew"            => "Sisestage uus parool uuesti",
+"textboxsize"  => "Redaktoriboksi suurus",
+"rows"                 => "Ridade arv",
+"columns"              => "Veergude arv",
+"searchresultshead" => "Otsingutulemite sätted",
+"resultsperpage" => "Tulemeid leheküljel",
+"contextlines" => "Ridu tulemis",
+"contextchars" => "Konteksti pikkus real",
+"stubthreshold" => "Nupu näitamise lävi",
+"recentchangescount" => "Pealkirjade arv viimastes muudatustes",
+"savedprefs"   => "Teie eelistused on salvestatud.",
+"timezonetext" => "Kohaliku aja ja serveri aja (maailmaaja) vahe tundides.",
+"localtime"    => "Kohalik aeg",
+"timezoneoffset" => "Ajavahe",
+"emailflag"            => "Blokeeri e-kirjad teistelt kasutajatelt",
+
+
+# Recent changes
+#
+"changes" => "muudatused",
+"recentchanges" => "Viimased muudatused",
+"recentchangestext" => "Jälgige sellel leheküljel viimaseid muudatusi.",
+"rcloaderr"            => "Viimaste muudatuste laadimine",
+"rcnote"               => "Allpool on esitatud viimased <strong>$1</strong> muudatust viimase <strong>$2</strong> päeva jooksul.",
+"rcnotefrom"   => "Allpool on esitatud muudatused alates <b>$2</b> (näidatakse kuni <b>$1</b> muudatust).",
+"rclistfrom"   => "Näita muudatusi alates $1",
+# "rclinks"            => "Näita viimast $1 muudatust viimase $2 tunni / viimase $3 päeva jooksul",
+"rclinks"              => "Näita viimast $1 muudatust viimase $2 päeva jooksul.",
+"rchide"               => "in $4 form; $1 pisiparandust; $2 sekundaarset nimeruumi; $3 multiple edits.", ##MIS SEE ON?
+"diff"                 => "erin",
+"hist"                 => "ajal",
+"hide"                 => "peida",
+"show"                 => "näita",
+"tableform"            => "tabel",
+"listform"             => "list",
+"nchanges"             => "$1 muudatust",
+"minoreditletter" => "P",
+"newpageletter" => "U",
+
+# Upload
+#
+"upload"               => "Faili üleslaadimine",
+"uploadbtn"            => "Üleslaadimine",
+"uploadlink"   => "Piltide üleslaadimine",
+"reupload"             => "Uuesti üleslaadimine",
+"reuploaddesc" => "Tagasi üleslaadimise vormi juurde.",
+"uploadnologin" => "sisse logimata",
+"uploadnologintext"    => "Kui Te soovite faile üles laadida, peate [[Special:Userlogin|sisse logima]].",
+"uploaderror"  => "Viga üleslaadimisel",
+"uploadtext"   => "<strong>STOPP!</strong> Enne kui sooritad üleslaadimise,
+peaksid tagama, et see järgib siinset [[{{ns:4}}:Image_use_policy|piltide kasutamise korda]].
+
+Et näha või leida eelnevalt üleslaetud pilte,
+mine vaata [[Special:Imagelist|piltide nimekirja]].
+Üleslaadimised ning kustutamised logitakse [[Special:Log/upload|üleslaadimise logis]].
+
+Järgneva vormi abil saad laadida üles uusi pilte
+oma artiklite illustreerimiseks.
+Enamikul brauseritest, näed nuppu \"Browse...\", mis viib sind
+sinu operatsioonisüsteemi standardsesse failiavamisaknasse.
+Faili valimisel sisestatakse selle faili nimi tekstiväljale
+nupu kõrval.
+Samuti pead märgistama kastikese, kinnitades sellega,
+et sa ei riku seda faili üleslaadides kellegi autoriõigusi.
+Üleslaadimise lõpuleviimiseks vajuta nupule \"Üleslaadimine\".
+See võib võtta pisut aega, eriti kui teil on aeglane internetiühendus.
+
+Eelistatud formaatideks on fotode puhul JPEG , joonistuste
+ja ikoonilaadsete piltide puhul PNG, helide jaoks aga OGG.
+Nimeta oma failid palun nõnda, et nad kirjeldaksid arusaadaval moel faili sisu, see aitab segadusi vältida.
+Pildi lisamiseks artiklile, kasuta linki kujul:
+<b><nowiki>[[image:pilt.jpg]]</nowiki></b> või <b><nowiki>[[image:pilt.png|alt. tekst]]</nowiki></b>.
+Helifaili puhul: <b><nowiki>[[media:fail.ogg]]</nowiki></b>.
+
+Pane tähele, et nagu ka ülejäänud siinsete lehekülgede puhul,
+võivad teised sinu poolt laetud faile saidi huvides
+muuta või kustutada ning juhul kui sa süsteemi kuritarvitad
+võidakse sinu ligipääs sulgeda.",
+"uploadlog"            => "üleslaadimise logi",
+"uploadlogpage" => "Upload_log",
+"uploadlogpagetext" => "Järgnev on nimekiri viimastest üleslaadimistest.
+Kellaajad on märgitud serveri ajaarvamise järele (UTC).
+<ul>
+</ul>
+",
+"filename"             => "Faili nimi",
+"filedesc"             => "Lühikirjeldus",
+"copyrightpage" => "{{ns:4}}:Autoriõigused",
+"copyrightpagename" => "{{SITENAME}} ja autoriõigused",
+"uploadedfiles"        => "Üleslaetud failid",
+"ignorewarning"        => "Ignoreeri hoiatust ja salvesta sellest hoolimata.",
+"minlength"            => "Pildi nimi peab sisaldama vähemalt kolme tähte.",
+"badfilename"  => "Pildi nimi on muudetud. Uus nimi on \"$1\".",
+"badfiletype"  => "\".$1\" ei ole soovitatav formaat.",
+"largefile"            => "Soovitame mitte saata faile, mille suurus ületab 100 kilobaiti.",
+"successfulupload" => "Üleslaadimine õnnestus",
+"fileuploaded" => "Fail nimega \"$1\" õnnestus üles laadida.
+Palun järgi seda linki: ($2). See viib su kirjelduslehele, et saaksid esita
+asjassepuutuvad andmed faili kohta: kust on ta pärit, millal
+ja kelle poolt ta loodi, jne.",
+"uploadwarning" => "Hoiatus üleslaadimise asjus",
+"savefile"             => "Salvesta fail",
+"uploadedimage" => "laadisin üles \"[[$1]]\"",
+
+# Image list
+#
+"imagelist"            => "Piltide loend",
+"imagelisttext"        => "Piltide arv järgnevas loendis: $1. Sorteeritud $2.", # $2 -- nt. "kuupäeva järgi".
+"getimagelist" => "hangin piltide nimekirja",
+"ilsubmit"             => "Otsi",
+"showlast"             => "Näita viimast $1 pilti sorteerituna $2.", # $2 nt. "nime järgi"
+"byname"               => "nime järgi",
+"bydate"               => "kuupäeva järgi",
+"bysize"               => "suuruse järgi",
+"imgdelete"            => "del",
+"imgdesc"              => "kirj",
+"imglegend"            => "Legend: (kirj) = näita/redigeeri pildi kirjeldust.",
+"imghistory"   => "Pildi ajalugu",
+"revertimg"            => "taas",
+"deleteimg"            => "del",
+"deleteimgcompletely"          => "del",
+"imghistlegend" => "Legend: (viim) = see on pildi viimane versioon, (del) = kustuta
+see vana versioon, (taas) = taasta see vana versioon.
+<br /><i>Klõpsa kuupäevale, et näha tookord laetud pilti.</i>.",
+"imagelinks"   => "Pildilingid",
+"linkstoimage" => "Sellele pildile viitavad järgmised leheküljed:",
+"nolinkstoimage" => "Selle pildile ei viita ükski lehekülg.",
+
+# Statistics
+#
+"statistics"   => "Statistika",
+"sitestats"            => "Saidi statistika",
+"userstats"            => "Kasutaja statistika",
+"sitestatstext" => "Lehekülgede koguarv andmebaasis: <b>$1</b>.
+
+See arv hõlmab ka arutelulehekülgi, abiartikleid Vikipeedia kohta, väga lühikesi lehekülgi (nuppe), ümbersuunamislehekülgi ning muid lehekülgi, millel tõenäoliselt ei ole entsüklopeediaartikleid. Ilma neid arvestamata on Vikipeedias praegu <b>$2</b> lehekülge, mida võib pidada artikliteks.
+
+Alates uuele programmile üleminekust 18. detsembril 2003 on lehekülgi vaadatud kokku <b>$3</b> korda ja redigeeritud kokku <b>$4</b> korda. Seega on lehekülje kohta tehtud <b>$5</b> parandust ja iga paranduse kohta tuleb <b>$5</b> vaatamist.", # viimase lausepoole võiks kohalikes seadetes eemaldada,
+  # sest see kipub mingil põhjusel olema null, tõenäoliselt praegu külastusi lihtsalt kokku ei loeta.
+  # enamasti on arvud.
+  # Võiks veel ainsust silmas pidades ühtteist ümber sõnastada, aga see esineb tõesti üliharva.
+"userstatstext" => "Registreeritud kasutajate arv: <b>$1</b>.
+Administraatori staatuses kasutajaid: <b>$2</b> (vt $3).",
+# Maintenance Page
+#
+"maintenance"          => "Hoolduslehekülg",
+"maintnancepagetext"   => "This page includes several handy tools for everyday maintenance. Some of these functions tend to stress the database, so please do not hit reload after every item you fixed ;-)",
+"maintenancebacklink"  => "Tagasi hooldusleheküljele",
+"disambiguations"      => "Disambiguation pages",
+"disambiguationspage"  => "Wikipedia:Links_to_disambiguating_pages",
+"disambiguationstext"  => "The following articles link to a <i>disambiguation page</i>. They should link to the appropriate topic instead.<br />A page is treated as dismbiguation if it is linked from $1.<br />Links from other namespaces are <i>not</i> listed here.",
+"doubleredirects"      => "Double Redirects",
+"doubleredirectstext"  => "<b>Attention:</b> This list may contain false positives. That usually means there is additional text with links below the first #REDIRECT.<br />\nEach row contains links to the first and second redirect, as well as the first line of the second redirect text, usually giving the \"real\" taget article, which the first redirect should point to.",
+"brokenredirects"      => "Broken Redirects",
+"brokenredirectstext"  => "The following redirects link to a non-existing article.",
+"selflinks"            => "Iseendale viitavad leheküljed",
+"selflinkstext"                => "Järgmised leheküljed sisaldavad viita iseendale, mis ei ole soovitatav.",
+"mispeelings"           => "Pages with misspellings",
+"mispeelingstext"               => "The following pages contain a common misspelling, which are listed on $1. The correct spelling might be given (like this).",
+"mispeelingspage"       => "List of common misspellings",
+"missinglanguagelinks"  => "Missing Language Links",
+"missinglanguagelinksbutton"    => "Find missing language links for",
+"missinglanguagelinkstext"      => "These articles do <i>not</i> link to their counterpart in $1. Redirects and subpages are <i>not</i> shown.",
+
+# Miscellaneous special pages
+#
+"orphans"              => "Üksildased artiklid",
+"lonelypages"  => "Üksildased artiklid",
+"unusedimages" => "Kasutamata pildid",
+"popularpages" => "Populaarsed leheküljed",
+"nviews"               => "Külastuste arv: $1",
+"wantedpages"  => "Kõige oodatumad artiklid",
+"nlinks"               => "Linkide arv: $1",
+"allpages"             => "Kõik artiklid",
+"randompage"   => "Juhuslik artikkel",
+"shortpages"   => "Lühikesed artiklid",
+"longpages"            => "Pikad artiklid",
+"listusers"            => "Kasutajad",
+"specialpages" => "Erileheküljed",
+"spheading"            => "Erileheküljed",
+"protectpage"  => "Kaitse lehekülge",
+"recentchangeslinked" => "Seotud muudatused",
+"rclsub"               => "(lehekülgedel, millele \"$1\" viitab)", #
+"debug"                        => "Silu",
+"newpages"             => "Uued leheküljed",
+'ancientpages'          => 'Vanimad leheküljed',
+"intl"         => "Keeltevahelised lingid",
+'move' => 'Teisalda',
+"movethispage" => "Teisalda lehekülg",
+"unusedimagestext" => "<p>Pange palun tähele, et teised
+veebisaidid, nagu nt. rahvusvahelised Vikipeediad, võivad
+linkida lehekülgedele otselinginga ja seega võivad
+siin esitatud pildid olla ikkagi aktiivses kasutuses.",
+"booksources"  => "Raamatud",
+"booksourcetext" => "All on esitatud linkide loend teistesse
+saitidesse, mis müüvad uusi ja kasutatud raamatuid ning võivad
+omada lisainfot otsitavate raamatute kohta.
+{{ns:4}} ei ole nende ettevõtmistega seotud ja seda nimekirja
+ei tohiks konstrueerida reklaami tegemiseks.",
+"alphaindexline" => "$1 to $2",
+
+# Email this user
+#
+"mailnologin"  => "No send address",
+"mailnologintext" => "You must be [[Special:Userlogin|logged in]]
+and have a valid e-mail address in your [[Special:Preferences|preferences]]
+to send e-mail to other users.",
+"emailuser"            => "E-mail this user",
+"emailpage"            => "E-mail user",
+"emailpagetext"        => "If this user has entered a valid e-mail address in
+his or her user preferences, the form below will send a single message.
+The e-mail address you entered in your user preferences will appear
+as the \"From\" address of the mail, so the recipient will be able
+to reply.",
+"noemailtitle" => "No e-mail address",
+"noemailtext"  => "This user has not specified a valid e-mail address,
+or has chosen not to receive e-mail from other users.",
+"emailfrom"            => "From",
+"emailto"              => "To",
+"emailsubject" => "Subject",
+"emailmessage" => "Sõnum",
+"emailsend"            => "Saada",
+"emailsent"            => "E-post saadetud",
+"emailsenttext" => "Teie sõnum on saadetud.",
+
+# Watchlist
+#
+"watchlist"            => "Minu jälgimisloend",
+"watchlistsub" => "(kasutajale nimega \"$1\")",
+"nowatchlist"  => "Teie jälgimisloend on tühi.",
+"watchnologin" => "Ei ole sisse loginud",
+"watchnologintext"     => "Jälgimisloendi muutmiseks peate [[Special:Userlogin|sisse logima]].",
+"addedwatch"   => "Lisatud jälgimisloendile",
+"addedwatchtext" => "Lehekülg \"$1\" on lisatud Teie [[Special:Watchlist|jälgimisloendile]].
+Edasised muudatused sellel lehel ja sellega seotud aruteluküljel reastatakse siin
+ning [[Special:Recentchanges||viimaste muudatuste lehel]] tuuakse ta esile
+<b>rasvase</b> kirja abil.</p>
+<p>Kui tahad seda lehte hiljem jälgimisloendist eemaldada, klõpsa päisenupule \"Lõpeta jälgimine\".",
+"removedwatch" => "Jälgimisloendist eemaldatud",
+"removedwatchtext" => "Lehekülg pealkirjaga \"$1\" on Teie jälgimisloendist eemaldatud.",
+'watch' => 'Jälgi',
+"watchthispage"        => "Jälgi seda lehekülge",
+"unwatchthispage" => "Lõpeta jälgimine",
+"notanarticle" => "Pole artikkel",
+
+# Delete/protect/revert
+#
+"deletepage"   => "Kustuta lehekülg",
+"confirm"              => "Kinnita",
+"confirmdelete" => "Kinnita kustutamine",
+"deletesub"            => "(Kustutan lehekülje \"$1\")",
+"confirmdeletetext" => "Sa oled andmebaasist jäädavalt kustutamas lehte või pilti
+koos kogu tema ajalooga. Palud kinnita, et sa tahad seda tõepoolest teha, et
+sa mõistad tagajärgi ja et sinu tegevus on kooskõlas siinse
+[[{{ns:4}}:Policy|sisekorraga]].", # Wikipedia:Policy tuleks ka tõlkida
+"actioncomplete" => "Toiming sooritatud",
+"deletedtext"  => "\"$1\" on kustutatud.
+Viimaste kustutuste loendit näed siit: $2.",
+"deletedarticle" => "\"$1\" kustutatud",
+"dellogpage"   => "Kustutatud_leheküljed",
+"dellogpagetext" => "Allpool on esitatud nimekiri viimastest kustutamistest.
+Kõik toodud kellaajad järgivad serveriaega (UTC).
+<ul>
+</ul>
+",
+"deletionlog"  => "Kustutatud leheküljed",
+"reverted"             => "Pöörduti tagasi varasemale versioonile",
+"deletecomment"        => "Kustutamise põhjus",
+"imagereverted" => "Varasemale versioonile tagasipöördumine õnnestus.",
+"rollback"             => "Pöördu varasemale versioonile",
+"rollbacklink" => "taasta varasem versioon",
+"cantrollback" => "Ei saa muudatusi tagasi pöörata; viimane kaastööline on artikli ainus autor.",
+"revertpage"   => "Pöörduti tagasi viimasele muudatusele, mille tegi $1",
+
+# Undelete
+"undelete" => "Taasta kustutatud lehekülg",
+"undeletepage" => "Kustutatud lehekülgede vaatamine ja taastamine",
+"undeletepagetext" => "Järgnevad leheküljed on kustutatud, kuis arhiivis
+veel olemas, neid saab taastada. Arhiivi sisu vistatakse aegajalt üle parda.",
+"undeletearticle" => "Taasta kustutatud artikkel",
+"undeleterevisions" => "Arhiveeritud versioone on $1.",
+"undeletehistory" => "Kui taastate lehekülje, taastuvad kõik versioonid artikli
+ajaloona. Kui vahepeal on loodud uus samanimeline lehekülg, ilmuvad taastatud
+versioonid varasema ajaloona. Kehtivat versiooni automaatselt välja ei vahetata.",
+"undeleterevision" => "Kustutatud versioon seisuga $1",
+"undeletebtn" => "Taasta!",
+"undeletedarticle" => "\"$1\" taastatud",
+"undeletedtext"   => "Artikkel [[$1]] on taastatud.
+Viimaste kustutamiste ja taastamiste logi on esitatud lehel [[{{ns:4}}:Kustutatud_leheküljed]].",
+
+# Contributions
+#
+"contributions"        => "Kasutaja kaastööd",
+"mycontris" => "Minu kaastöö",
+"contribsub"   => "Kasutaja \"$1\" jaoks",
+"nocontribs"   => "Antud kriteeriumile vastavaid muudatusi ei leidnud.",
+"ucnote"               => "Esitatakse selle kasutaja tehtud viimased <b>$1</b> muudatust viimase <b>$2</b> päeva jooksul.",
+"uclinks"              => "Näita viimast $1 muudatust; viimase $2 päeva jooksul.",
+"uctop"                => " (üles)" ,
+
+# What links here
+#
+"whatlinkshere"        => "Viidad siia",
+"notargettitle" => "Puudub sihtlehekülg",
+"notargettext" => "Sa ei ole esitanud sihtlehekülge ega kasutajat, kelle kallal seda operatsiooni toime panna.",
+"linklistsub"  => "(Linkide loend)",
+"linkshere"            => "Siia viitavad järgmised leheküljed:",
+"nolinkshere"  => "Siia ei viita ükski lehekülg.",
+"isredirect"   => "ümbersuunamislehekülg",
+
+# Block/unblock IP
+#
+"blockip"              => "Blokeeri IP-aadress",
+"blockiptext"  => "Use the form below to block write access
+from a specific IP address.
+This should be done only only to prevent vandalism, and in
+accordance with [[Wikipedia:Policy|Wikipedia policy]].
+Fill in a specific reason below (for example, citing particular
+pages that were vandalized).",
+"ipaddress"            => "IP-aadress",
+"ipbreason"            => "Põhjus",
+"ipbsubmit"            => "Blokeeri see aadress",
+"badipaddress" => "The IP address is badly formed.",
+"blockipsuccesssub" => "Block succeeded",
+"blockipsuccesstext" => "IP-aadress \"$1\" on blokeeritud.
+<br />See [[Special:Ipblocklist|IP block list]] to review blocks.",
+"unblockip"            => "Unblock IP address",
+"unblockiptext"        => "Use the form below to restore write access
+to a previously blocked IP address.",
+"ipusubmit"            => "Unblock this address",
+"ipusuccess"   => "IP address \"$1\" unblocked",
+"ipblocklist"  => "Blokeeritud IP-aadresside loend",
+"blocklistline"        => "$1, $2 blocked $3 ($4)",
+"blocklink"            => "blokeeri",
+"unblocklink"  => "unblock",
+"contribslink" => "contribs",
+
+# Developer tools
+#
+"lockdb"               => "Lukusta andmebaas",
+"unlockdb"             => "Tee andmebaas lukust lahti",
+"lockdbtext"   => "Locking the database will suspend the ability of all
+users to edit pages, change their preferences, edit their watchlists, and
+other things requiring changes in the database.
+Please confirm that this is what you intend to do, and that you will
+unlock the database when your maintenance is done.",
+"unlockdbtext" => "Unlocking the database will restore the ability of all
+users to edit pages, change their preferences, edit their watchlists, and
+other things requiring changes in the database.
+Please confirm that this is what you intend to do.",
+"lockconfirm"  => "Yes, I really want to lock the database.",
+"unlockconfirm"        => "Yes, I really want to unlock the database.",
+"lockbtn"              => "Võta andmebaas kirjutuskaitse alla",
+"unlockbtn"            => "Taasta andmebaasi kirjutuspääs",
+"locknoconfirm" => "You did not check the confirmation box.",
+"lockdbsuccesssub" => "Andmebaas kirjutuskaitse all",
+"unlockdbsuccesssub" => "Kirjutuspääs taastatud",
+"lockdbsuccesstext" => "Andmebaas on nüüd kirjutuskaitse all.
+<br />Kui Teie hooldustöö on läbi, ärge unustage kirjutuspääsu taastada!",
+"unlockdbsuccesstext" => "Andmebaasi kirjutuspääs on taastatud.",
+
+# Move page
+#
+"movepage"             => "Teisalda artikkel",
+"movepagetext" => "Using the form below will rename a page, moving all
+of its history to the new name.
+The old title will become a redirect page to the new title.
+Links to the old page title will not be changed; be sure to
+check for double or broken redirects.
+You are responsible for making sure that links continue to
+point where they are supposed to go.
+
+Note that the page will '''not''' be moved if there is already
+a page at the new title, unless it is empty or a redirect and has no
+past edit history. This means that you can rename a page back to where
+it was just renamed from if you make a mistake, and you cannot overwrite
+an existing page.
+
+<b>ETTEVAATUST!</b>
+Võimalik, et olete tegemas ootamatut ning drastilist muudatust väga loetavasse artiklisse;
+enne muudatuse tegemist mõelge palun järele, milised võivad olla selle tagajärjed.",
+"movepagetalktext" => "Koos artiklileheküljega teisaldatakse automaatselt ka arutelulehekülg, '''välja arvatud juhtudel, kui:'''
+*liigutate lehekülge ühest nimeruumist teise,
+*uue nime all on juba olemas mittetühi arutelulehekülg või
+*jätate alumise kastikese märgistamata.
+
+Neil juhtudel teisaldage arutelulehekülg soovi korral eraldi või ühendage ta omal käel uue aruteluleheküljega.",
+"movearticle"  => "Teisalda artiklilehekülg",
+"movenologin"  => "Te ei ole sisse loginud",
+"movenologintext" => "Et lehekülge teisaldada, peate registreeruma
+kasutajaks ja [[Special:Userlogin|sisse logima]]",
+"newtitle"             => "Uue pealkirja alla",
+"movepagebtn"  => "Teisalda artikkel",
+"pagemovedsub" => "Artikkel on teisaldatud",
+"pagemovedtext" => "Artikkel \"[[$1]]\" on teisaldatud pealkirja \"[[$2]]\" alla.",
+"articleexists" => "Selle nimega artikkel on juba olemas või pole valitud nimi lubatav. Palun valige uus nimi.",
+"talkexists"   => "Artikkel on teisaldatud, kuid arutelulehekülge ei saanud teisaldada, sest uue nime all on arutelulehekülg juba olemas. Palun ühendage aruteluleheküljed ise.",
+"movedto"              => "Teisaldatud pealkirja alla:",
+"movetalk"             => "Teisalda ka \"arutelu\", kui saab.",
+"talkpagemoved" => "Ka vastav arutelulehekülg on teisaldatud.",
+"talkpagenotmoved" => "Vastav arutelulehekülg jäi teisaldamata.",
+ #Math
+ 'mw_math_png' => "Alati PNG",
+ 'mw_math_simple' => "Kui väga lihtne, siis HTML, muidu PNG",
+ 'mw_math_html' => "Võimaluse korral HTML, muidu PNG",
+ 'mw_math_source' => "Säilitada TeX (tekstibrauserite puhul)",
+ 'mw_math_modern' => "Soovitatav moodsate brauserite puhul",
+ 'mw_math_mathml' => 'MathML',
+
+);
+
+require_once( "LanguageUtf8.php" );
+
+class LanguageEt extends LanguageUtf8 {
+
+
+       function getBookstoreList () {
+               global $wgBookstoreListEt ;
+               return $wgBookstoreListEt ;
+       }
+
+       function getDateFormats() {
+               global $wgDateFormatsEt;
+               return $wgDateFormatsEt;
+       }
+
+       function getNamespaces() {
+               global $wgNamespaceNamesEt;
+               return $wgNamespaceNamesEt;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsEt;
+               return $wgQuickbarSettingsEt;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesEt;
+               return $wgSkinNamesEt;
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesEt;
+               if( isset( $wgAllMessagesEt[$key] ) ) {
+                       return $wgAllMessagesEt[$key];
+               } else {
+                       return parent::getMessage( $key );
+               }
+       }
+
+       /**
+        * Estonian numeric formatting is 123 456,78.
+        * Notice that the space is non-breaking.
+        */
+       function formatNum( $number, $year = false ) {
+               return $year ? $number : strtr($this->commafy($number), '.,', ", " );
+       }
+
+       /**
+        * Avoid grouping whole numbers between 0 to 9999
+        */
+       function commafy($_) {
+               if (!preg_match('/^\d{1,4}$/',$_)) {
+                       return strrev((string)preg_replace('/(\d{3})(?=\d)(?!\d*\.)/','$1,',strrev($_)));
+               } else {
+                       return $_;
+               }
+       }
+
+
+
+
+       /**
+        * @access public
+        * @param mixed  $ts the time format which needs to be turned into a
+        *               date('YmdHis') format with wfTimestamp(TS_MW,$ts)
+        * @param bool   $adj whether to adjust the time output according to the
+        *               user configured offset ($timecorrection)
+        * @param mixed  $format what format to return, if it's false output the
+        *               default one.
+        * @param string $timecorrection the time offset as returned by
+        *               validateTimeZone() in Special:Preferences
+        * @return string
+        */
+       function date( $ts, $adj = false, $format = true, $timecorrection = false ) {
+               global $wgAmericanDates, $wgUser;
+
+               if ( $adj ) { $ts = $this->userAdjust( $ts, $timecorrection ); }
+
+               $datePreference = $this->dateFormat($format);
+
+               if ($datePreference == '0'
+                   || $datePreference == '' ) {$datePreference = $wgAmericanDates ? '0' : '2';}
+
+               $month = $this->getMonthName( substr( $ts, 4, 2 ) );
+               $day = $this->formatNum( 0 + substr( $ts, 6, 2 ) );
+               $year = $this->formatNum( substr( $ts, 0, 4 ), true );
+               $lat_month = $this->monthByLatinNumber( substr ($ts, 4, 2));
+
+               switch( $datePreference ) {
+                       case '2': return "$day. $month $year";
+                       case '3': return "$day. $lat_month $year";
+                       case 'ISO 8601': return substr($ts, 0, 4). '-' . substr($ts, 4, 2). '-' .substr($ts, 6, 2);
+                       default: return substr($ts, 6, 2). '.' . substr($ts, 4, 2). '.' .substr($ts, 0, 4);
+               }
+       }
+
+
+
+       /**
+       * @access public
+       * @param mixed  $ts the time format which needs to be turned into a
+       *              date('YmdHis') format with wfTimestamp(TS_MW,$ts)
+       * @param bool   $adj whether to adjust the time output according to the
+       *              user configured offset ($timecorrection)
+       * @param mixed  $format what format to return, if it's false output the
+       *              default one (default true)
+       * @param string $timecorrection the time offset as returned by
+       *              validateTimeZone() in Special:Preferences
+       * @return string
+       */
+       function time( $ts, $adj = false, $format = true, $timecorrection = false ) {
+               global $wgUser, $wgAmericanDates;
+
+               if ( $adj ) { $ts = $this->userAdjust( $ts, $timecorrection ); }
+               $datePreference = $this->dateFormat($format);
+
+               if ($datePreference == '0') {$datePreference = $wgAmericanDates ? '0' : '2';}
+
+               if ( $datePreference === 'ISO 8601' ) {
+                       $t = substr( $ts, 8, 2 ) . ':' . substr( $ts, 10, 2 );
+                       $t .= ':' . substr( $ts, 12, 2 );
+               } else {
+                       $t = substr( $ts, 8, 2 ) . '&#46;' . substr( $ts, 10, 2 );
+               }
+               return $this->formatNum( $t );
+       }
+
+
+
+
+       /**
+       * @access public
+       * @param mixed  $ts the time format which needs to be turned into a
+       *              date('YmdHis') format with wfTimestamp(TS_MW,$ts)
+       * @param bool   $adj whether to adjust the time output according to the
+       *              user configured offset ($timecorrection)
+       * @param mixed  $format what format to return, if it's false output the
+       *              default one (default true)
+       * @param string $timecorrection the time offset as returned by
+       *              validateTimeZone() in Special:Preferences
+       * @return string
+       */
+       function timeanddate( $ts, $adj = false, $format = true, $timecorrection = false) {
+               global $wgUser, $wgAmericanDates;
+
+               $datePreference = $this->dateFormat($format);
+               switch ( $datePreference ) {
+                       case 'ISO 8601': return $this->date( $ts, $adj, $datePreference, $timecorrection ) . ' ' .
+                               $this->time( $ts, $adj, $datePreference, $timecorrection );
+                       default: return $this->date( $ts, $adj, $datePreference, $timecorrection ) . ', kell ' .
+                               $this->time( $ts, $adj, $datePreference, $timecorrection );
+
+               }
+
+       }
+
+
+       /**
+       * retuns latin number corresponding to given month number
+       * @access public
+       * @param number
+       * @return string
+       */
+       function monthByLatinNumber( $key ) {
+               $latinNumbers= array(
+                       'I', 'II', 'III', 'IV', 'V', 'VI',
+                       'VII','VIII','IX','X','XI','XII'
+               );
+
+               return $latinNumbers[$key-1];
+       }
+
+
+}
+?>
diff --git a/languages/LanguageFa.php b/languages/LanguageFa.php
new file mode 100644 (file)
index 0000000..1e2b04e
--- /dev/null
@@ -0,0 +1,1055 @@
+<?php
+/** Persian (فارسی)
+  *
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+# Wikipedia localization for Persian
+
+require_once("LanguageUtf8.php");
+
+#--------------------------------------------------------------------------
+# Language-specific text
+#--------------------------------------------------------------------------
+
+/** TODO: fix me! */
+/* private */ $wgNamespaceNamesFa = array(
+       NS_MEDIA                => "مدیا",
+       NS_SPECIAL        => "ویژه",
+       NS_MAIN           => '',
+       NS_TALK           => "بحث",
+       NS_USER           => "کاربر",
+       NS_USER_TALK      => "بحث_کاربر",
+       NS_PROJECT        => "ویکی‌پدیا",
+       NS_PROJECT_TALK   => "بحث_ویکی‌پدیا",
+       NS_IMAGE          => "تصویر",
+       NS_IMAGE_TALK     => "بحث_تصویر",
+       NS_MEDIAWIKI      => "مدیاویکی",
+       NS_MEDIAWIKI_TALK       => "بحث_مدیاویکی",
+       NS_TEMPLATE       => "Template",
+       NS_TEMPLATE_TALK  => "Template_talk"
+
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgQuickbarSettingsFa = array(
+       "نباشد", "ثابت چپ", "ثابت راست", "شناور چپ"
+);
+
+/* private */ $wgSkinNamesFa = array(
+       'standard' => "استاندارد",
+       'nostalgia' => "نوستالژی",
+       'cologneblue' => "آبی کلون",
+       'smarty' => "پدینگتون",
+       'montparnasse' => "مون‌پارناس",
+) + $wgSkinNamesEn;
+
+#-------------------------------------------------------------------
+# Default messages
+#-------------------------------------------------------------------
+
+/* private */ $wgAllMessagesFa = array(
+# User toggles
+
+"tog-underline" => "زیر پیوندها خط کشیده شود",
+"tog-highlightbroken" => "قالب‌بندی پیوندهای ناقص <a href=\"\" class=\"new\">به این شکل</a> (امکان دیگر: به این شکل<a href=\"\" class=\"internal\">؟</a>).",
+"tog-justify"  => "تنظیم بندها",
+"tog-hideminor" => "نشان ندادن تغییرات جزئی در فهرست تغییرات اخیر",
+"tog-usenewrc" => "تغییرات اخیر گسترش‌یافته (برای هر مرورگری نیست)",
+"tog-numberheadings" => "شماره‌گذاری خودکار عناوین",
+"tog-showtoolbar"=>"نمایش نوار ابزار جعبه‌ی ویرایش",
+"tog-editondblclick" => "ویرایش صفحه‌ها با دوکلیک (جاوااسکریپت)",
+"tog-editsection"=>"به کار انداختن ویرایش قسمت‌ها از طریق پیوندهای [ویرایش]",
+"tog-editsectiononrightclick"=>"به کار انداختن ویرایش قسمت‌ها با کلیک راست<br />روی عناوین قسمت‌ها (جاوااسکریپت)",
+"tog-showtoc"=>"نمایش فهرست مندرجات<br />(برای مقالات با بیش از ۳ سرفصل)",
+"tog-rememberpassword" => "کلمه‌ی عبور برای نشست‌های بعدی بماند",
+"tog-editwidth" => "عرض جعبه‌ی ویرایش کامل باشد",
+"tog-watchdefault" => "افزودن صفحاتی که ویرایش می‌کند به فهرست تعقیبات",
+"tog-minordefault" => "پیش‌فرض همه‌ی ویرایش‌ها «جزئی» باشد",
+"tog-previewontop" => "نمایش پیش‌نمایش قبل از جعبه‌ی ویرایش و نه قبل از آن",
+"tog-nocache" => "از کار انداختن حافظه‌ی نهانی صفحات",
+# Dates
+
+'sunday' => "یک‌شنبه",
+'monday' => "دوشنبه",
+'tuesday' => "سه‌شنبه",
+'wednesday' => "چهارشنبه",
+'thursday' => "پنجشنبه",
+'friday' => "جمعه",
+'saturday' => "شنبه",
+'january' => "ژانویه",
+'february' => "فوریه",
+'march' => "مارس",
+'april' => "آوریل",
+'may_long' => "مه",
+'june' => "ژوئن",
+'july' => "ژوئیه",
+'august' => "اوت",
+'september' => "سپتامبر",
+'october' => "اکتبر",
+'november' => "نوامبر",
+'december' => "دسامبر",
+'jan' => "ژانویه",
+'feb' => "فوریه",
+'mar' => "مارس",
+'apr' => "آوریل",
+'may' => "مه",
+'jun' => "ژوئن",
+'jul' => "ژوئیه",
+'aug' => "اوت",
+'sep' => "سپتامبر",
+'oct' => "اکتبر",
+'nov' => "نوامبر",
+'dec' => "دسامبر",
+
+# Bits of text used by many pages:
+#
+"categories" => "رده‌های صفحات",
+"category" => "رده",
+"category_header" => "مقاله‌های رده‌ی «$1»",
+"subcategories" => "زیررده‌ها",
+
+"linktrail"            => "/^([a-z]+)(.*)\$/sD", /* This may need to be changed --RP */
+"mainpage"             => "صفحه‌ی اصلی",
+"mainpagetext" => "نرم‌افزار ویکی با موفقیت نصب شد.",
+"about"                        => "درباره",
+"aboutsite"      => "درباره‌ی ویکی‌پدیا",
+"aboutpage"            => "ویکی‌پدیا:درباره",
+"help"                 => "راهنما",
+"helppage"             => "ویکی‌پدیا:راهنما",
+"bugreports"   => "گزارش اشکالات",
+"bugreportspage" => "ویکی‌پدیا:گزارش اشکالات",
+"sitesupport"   => "کمک مالی",
+"faq"                  => "سؤالات معمول",
+"faqpage"              => "ویکی‌پدیا:سؤالات معمول",
+"edithelp"             => "راهنمای ویرایش کردن",
+"edithelppage" => "ویکی‌پدیا:چگونه_صفحات_را_ویرایش_کنیم",
+"cancel"               => "لغو",
+"qbfind"               => "یافتن",
+"qbbrowse"             => "مرور",
+"qbedit"               => "ویرایش",
+"qbpageoptions" => "این صفحه",
+"qbpageinfo"   => "بافت",
+"qbmyoptions"  => "صفحات من",
+"qbspecialpages"       => "صفحات ویژه",
+"moredotdotdot"        => "بیشتر...",
+"mypage"               => "صفحه‌ی من",
+"mytalk"               => "بحث من",
+"currentevents" => "وقایع کنونی",
+"disclaimers" => "تکذیب‌نامه‌ها",
+"disclaimerpage"               => "ویکی‌پدیا:تکذیب‌نامه‌ی عمومی",
+"errorpagetitle" => "خطا",
+"returnto"             => "بازگشت به $1.",
+"tagline"              => "از ویکی‌پدیا، دایرةالمعارف آزاد.",
+"whatlinkshere"        => "صفحاتی که به اینجا پیوند دارند",
+"help"                 => "راهنما",
+"search"               => "جستجو شود",
+"go"           => "برود",
+"history"              => "تاریخچه‌ی صفحه",
+"printableversion" => "نسخه‌ی قابل چاپ",
+"editthispage" => "ویرایش این صفحه",
+"deletethispage" => "حذف این صفحه",
+"protectthispage" => "محافظت از این صفحه",
+"unprotectthispage" => "از محافظت در آوردن این صفحه",
+"newpage" => "صفحه‌ی جدید",
+"talkpage"             => "بحث درباره‌ی این صفحه",
+"postcomment"   => "نوشتن نظر",
+"articlepage"  => "نمایش مقاله",
+"subjectpage"  => "نمایش موضوع", # For compatibility
+"userpage" => "نمایش صفحه‌ی کاربر",
+"wikipediapage" => "نمایش فوق صفحه",
+"imagepage" =>         "نمایش صفحه‌ی تصویر",
+"viewtalkpage" => "نمایش مباحثات",
+"otherlanguages" => "زبان‌های دیگر",
+"redirectedfrom" => "(تغییر مسیر از $1)",
+"lastmodified" => "این صفحه آخرین بار در $1 تغییر کرده است.",
+"viewcount"            => "این صفحه $1 بار دیده شده است.",
+"printsubtitle" => "(از {{SERVER}})",
+"protectedpage" => "صفحه‌ی محافظت‌شده",
+"administrators" => "ویکی‌پدیا:مدیران",
+"sysoptitle"   => "دسترسی اپراتور سیستم لازم است",
+"sysoptext"            => "عملی را که شما درخواست کرده‌اید فقط کاربران با وضعیت «اپراتور سیستم» می‌توانند انجام دهند.
+به $1 مراجعه کنید.",
+"developertitle" => "دسترسی برنامه‌نویس لازم است",
+"developertext"        => "عملی را که شما درخواست کرده‌اید فقط می‌تواند توسط کاربران با وضعیت «برنامه‌نویس» انجام شود.
+به $1 مراجعه کنید.",
+"nbytes"               => "$1 بایت",
+"go"                   => "برو",
+"ok"                   => "باشد",
+"sitetitle"            => "ویکی‌پدیا",
+"sitesubtitle" => "دایرةالمعارف آزاد",
+"retrievedfrom" => "گرفته شده از «$1»",
+"newmessages" => "$1 دارید.",
+"newmessageslink" => "پیغام جدید",
+"editsection"=>"ویرایش",
+"toc" => "فهرست مندرجات",
+"showtoc" => "نمایش داده شود",
+"hidetoc" => "مخفی شود",
+"thisisdeleted" => "نمایش یا احیای $1؟",
+"restorelink" => "$1 ویرایش حذف‌شده",
+
+# Main script and global functions
+#
+"nosuchaction" => "چنین عملی وجود ندارد",
+"nosuchactiontext" => "ویکی عمل مشخص شده در URL را نمی‌شناسد",
+"nosuchspecialpage" => "چنین صفحه‌ی ویژه‌ای وجود ندارد",
+"nospecialpagetext" => "شما صفحه‌ی ویژه‌ای را درخواست کرده‌اید که ویکی نمی‌شناسد.",
+
+# General errors
+#
+"error"                        => "خطا",
+"databaseerror" => "خطای پایگاه داده",
+"dberrortextcl" => "A database query syntax error has occurred.
+The last attempted database query was:
+\"$1\"
+from within function \"$2\".
+MySQL returned error \"$3: $4\".\n",
+"noconnect"            => "شرمنده! ویکی مشکلات فنی دارد، و نمی‌تواند با خادم پایگاه داده تماس بگیرد.",
+"nodb"                 => "نمی‌توان پایگاه داده‌ی $1 را انتخاب کرد",
+"cachederror"          => "در زیر یک نسخه‌ی بایگانی‌شده‌ی صفحه‌ی درخواستی می‌آید، و ممکن است به‌روز نباشد.",
+"readonly"             => "پایگاه داده قفل شد",
+"enterlockreason" => "دلیلی برای قفل کردن ذکر کنید، شامل تقریبی برای زمانی که قفل برداشته خواهد شد",
+"readonlytext" => "The database is currently locked to new
+entries and other modifications, probably for routine database maintenance,
+after which it will be back to normal.
+The administrator who locked it offered this explanation:
+<p>$1",
+"missingarticle" => "پایگاه داده متن صفحه‌ای به نام «$1» را که باید می‌یافت، نیافت.
+
+<p>این مشکل معمولاٌ بر اثر ادامه دادن پیوندهای تاریخ‌گذشته‌ی تفاوت یا تاریخچه‌ی صفحاتی رخ می‌دهد که حذف شده‌اند.
+
+<p>اگر مورد شما این نیست، ممکن است اشکالی در نرم‌افزار پیدا کرده باشید.
+لطفاً این مسئله را، با ذکر URL، به یکی از مدیران گزارش کنید.",
+"internalerror" => "خطای داخلی",
+"filecopyerror" => "نتوانستم از پرونده‌ی «$1» روی «$2» نسخه‌برداری کنم.",
+"filerenameerror" => "نتوانستم پرونده‌ی «$1» را به «$2» تغییر نام دهم.",
+"filedeleteerror" => "نتوانستم پرونده‌ی «$1» را حذف کنم",
+"filenotfound" => "پرونده‌ی «$1» یافت نشد.",
+"unexpected"   => "مقدار غیرمنتظره: «$1»=«$2».",
+"formerror"            => "خطا: نمی‌توان فرم را فرستاد",
+"badarticleerror" => "نمی‌توان این عمل را بر این صفحه انجام داد.",
+"cannotdelete" => "نتوانستم صفحه را تصویر مشخص‌شده را حذف کنم. (ممکن است قبلاً کس دیگری آن را حذف کرده باشد.)",
+"badtitle"             => "عنوان بد",
+"badtitletext" => "عنوان درخواستی نامعتبر، خالی، یا عنوانی بین زبانی یا بین‌ویکی‌ای با پیوند نادرست بود.",
+"perfdisabled" => "شرمنده! این امکان موفقتاً برداشته شده چون پایگاه داده را چنان کند می‌کند
+که هیچ کس نمی‌تواند از ویکی استفاده کند.",
+"perfdisabledsub" => "این نسخه‌ی ذخیره‌شده‌ای از $1 است: ",
+"wrong_wfQuery_params" => "پارامترهای wfQuery() نادرست است<br />
+تابع: $1<br />
+پرس‌وجو: $2
+",
+"viewsource" => "نمایش مبدأ",
+"protectedtext" => "این صفحه برای جلوگیری از ویرایش قفل شده است؛ این کار ممکن است دلایل مختلفی داشته باشد. لطفاً به
+[[ویکی‌پدیا:صفحه‌ی محافظت‌شده]] مراجعه کنید.
+
+شما می‌توانید مبدأ این صفحه را مشاهده و تکثیر کنید:",
+
+# Login and logout pages
+#
+"logouttitle"  => "خروج کاربر از سیستم",
+"logouttext" => "اکنون از سیستم خارج شدید.
+شما می‌توانید به استفاده‌ی گمنام از ویکی‌پدیا ادامه دهید، یا می‌توانید با همین کاربر یا کاربر دیگری
+به سیستم وارد شوید. توجه کنید که تا زمانی که cache مرورگرتان را پاک کنید،
+بعضی صفحات ممکن است به شکلی نمایش یابند که انگار هنوز وارد سیستم هستید.\n",
+
+"welcomecreation" => "<h2>$1، خوش آمدید!</h2><p>حساب شما ایجاد شد.
+فراموش نکنید که ترجیحات ویکی‌پدیاتان را تنظیم کنید.",
+
+"loginpagetitle" => "ورود کاربر به سیستم",
+"yourname"             => "نام کاربری شما",
+"yourpassword" => "کلمه‌ی عبور شما",
+"yourpasswordagain" => "کلمه‌ی عبور را دوباره وارد کنید",
+"newusersonly" => " (فقط کاربران جدید)",
+"remembermypassword" => "کلمه‌ی عبور بین نشست‌ها به خاطر سپرده شود.",
+"loginproblem" => "<b>ورود شما به سیستم با مشکلی مواجه شد.</b><br />دوباره تلاش کنید!",
+"alreadyloggedin" => "<strong>کاربر $1, شما از قبل وارد سیستم شده‌اید!</strong><br />\n",
+
+"login"                        => "ورود به سیستم",
+"loginprompt"           => "برای ورود به ویکی‌پدیا باید cookieها را فعال کنید.",
+"userlogin"            => "ورود به سیستم",
+"logout"               => "خروج از سیستم",
+"userlogout"   => "خروج از سیستم",
+"notloggedin"  => "به سیستم وارد نشده‌اید",
+"createaccount"        => "ایجاد حساب جدید",
+"createaccountmail"    => "با پست الکترونیکی",
+"badretype"            => "کلمه‌های عبوری که وارد کردید یکسان نیستند.",
+"userexists"   => "نام کاربری‌ای که وارد کردید قبلاً استفاده شده است. لطفاً یک نام دیگر انتخاب کنید.",
+"youremail"            => "پست الکترونیکی شما*",
+"yournick"             => "لقب شما (برای امضاها)",
+"emailforlost" => "* وارد کردن نشانی پست الکترونیکی اختیاری است. اما اجازه می‌دهد دیگران،
+بدون نیاز به این که نشانی پست الکترونیک‌تان را افشا کنید، با شما از طریق وبگاه تماس بگیرند،
+و اگر کلمه‌ی عبورتان را فراموش کنید نیز کمکتان می‌کند.",
+"loginerror"   => "خطا در ورود به سیستم",
+"nocookiesnew" => "حساب کاربری ایجاد شد، اما شما وارد سیستم نشدید. ویکی‌پدیا برای ورود کاربران به سیستم از cookie استفاده می‌کند. شما
+cookieها را از کار انداخته‌اید. لطفاً cookieها را به کار بیندازید، و سپس با نام کاربری و کلمه‌ی عبور جدیدتان به سیستم وارد شوید.",
+"nocookieslogin"       => "ویکی‌پدیا برای ورود کاربران به سیستم از cookie استفاده می‌کند. شما cookieها را از کار
+انداخته‌اید. لطفاً cookieها را به کار بیندازید و دوباره تلاش کنید.",
+"noname"               => "شما نام کاربری معتبری مشخص نکرده‌اید.",
+"loginsuccesstitle" => "ورود موفقیت‌آمیز به سیستم",
+"loginsuccess" => "شما اکنون با نام «$1» به ویکی‌پدیا وارد شده‌اید.",
+"nosuchuser"   => "کاربری با نام «$1» وجود ندارد.
+املای نام را بررسی کنید، یا از فرم زیر برای ایجاد یک حساب کاربری جدید استفاده کنید.",
+"wrongpassword"        => "کلمه‌ی عبوری که وارد کردید نادرست است. لطفاٌ دوباره تلاش کنید.",
+"mailmypassword" => "یک کلمه‌ی عبور جدید به شما فرستاده شود",
+/* The following two messages should not be translated, in case
+   the user doesn't use email software able to read Persian. */
+"passwordremindertitle" => "Password reminder from Wikipedia",
+"passwordremindertext" => "Someone (probably you, from IP address $1)
+requested that we send you a new Wikipedia login password.
+The password for user \"$2\" is now \"$3\".
+You should log in and change your password now.",
+"noemail"              => "هیچ نشانی پست الکترونیکی‌ای برای کاربر «$1» ثبت نشده است.",
+"passwordsent" => "یک کلمه‌ی عبور جدید به نشانی الکترونیکی ثبت شده برای کاربر «$1» فرستاده شد.
+لطفاٌ پس از دریافت آن دوباره به سیستم وارد شوید.",
+"loginend"             => "",
+
+# Edit page toolbar
+"bold_sample"=>"متن سیاه",
+"bold_tip"=>"متن سیاه",
+"italic_sample"=>"متن ایتالیک",
+"italic_tip"=>"متن ایتالیک",
+"link_sample"=>"عنوان پیوند",
+"link_tip"=>"پیوند داخلی",
+"extlink_sample"=>"http://www.example.com عنوان پیوند",
+"extlink_tip"=>"پیوند خارجی (پیشوند http://‎ را فراموش نکنید)",
+"headline_sample"=>"متن عنوان",
+"headline_tip"=>"عنوان سطح ۲",
+"math_sample"=>"درج فرمول در اینجا",
+"math_tip"=>"فرمول ریاضی (LaTeX)",
+"nowiki_sample"=>"اینجا متن قالب‌بندی‌نشده وارد شود",
+"nowiki_tip"=>"نادیده گرفتن قالب‌بندی ویکی",
+"image_sample"=>"مثال.jpg",
+"image_tip"=>"تصویر داخل متن",
+"media_sample"=>"مثال.mp3",
+"media_tip"=>"پیوند پرونده‌ی رسانه",
+"sig_tip"=>"امضای شما و برچسب زمان",
+"hr_tip"=>"خط افقی (با صرفه‌جویی استفاده کنید)",
+"infobox"=>"برای درج متن نمونه روی یک دکمه کلیک کنید",
+
+# Edit pages
+#
+"summary"              => "خلاصه",
+"subject"              => "موضوع/عنوان",
+"minoredit"            => "این ویرایش جزئی است",
+"watchthis"            => "تعقیب این مقاله",
+"savearticle"  => "صفحه ذخیره شود",
+"preview"              => "پیش‌نمایش",
+"showpreview"  => "پیش‌نمایش نمایش یابد",
+"blockedtitle" => "کاربر بسته شده است",
+"blockedtext"  => "نام کاربری یا نشانی IP شما توسط $1 بسته شده است.
+دلیل داده‌شده این است:<br />''$2''<p>شما می‌توانید با $1 یا یکی از
+[[ویکی‌پدیا:مدیران|مدیران]] تماس بگیرید و در این باره صحبت کنید.
+
+توجه کنید که شما نمی‌توانید از امکان «فرستادن پست الکترونیکی به این کاربر» استفاده کنید مگر اینکه نشانی پست الکترونیکی
+معتبری در [[ویژه:ترجیحات|ترجیحات کاربری]]‌تان ثبت کرده باشید.
+
+نشانی IP شما $3 است. لطفاً این نشانی را در کلیه‌ی پرس‌وجوهایتان ذکر کنید.
+
+==نکته برای کاربران AOL==
+به خاطر اعمال تخریبی یک کاربر مشخص AOL، ویکی‌پدیا معمولاً proxyهای AOL را می‌بندد.
+متأسفانه ممکن است تعداد زیادی از کاربران AOL از یک خادم proxy واحد استفاده کنند، و در نتیجه کاربران بی‌تقصیر AOL معمولاً ندانسته بسته می‌شوند.
+از دردسر ایجاد شده عذر می‌خواهیم.
+
+اگر این اتفاق برای شما افتاد، لطفاً به یکی از مدیران از یک نشانی پست الکترونیک AOL پیغام بفرستید. حتماً نشانی IPی را در فوق داده شده
+ذکر کنید.
+",
+"whitelistedittitle" => "برای ویرایش باید به سیستم وارد شوید",
+"whitelistedittext" => "برای ویرایش مقاله‌ها باید به سیستم [[ویژه:Userlogin|وارد]] شوید.",
+"whitelistreadtitle" => "برای خواندن باید به سیستم وارد شوید",
+"whitelistreadtext" => "
+برای خواندن مقالات باید [[ویژه:Userlogin|به سیستم وارد شوید]].",
+"whitelistacctitle" => "شما مجاز نیستید حساب درست کنید.",
+"whitelistacctext" => "برای ایجاد حساب در این ویکی باید [[ویژه:Userlogin|به سیستم وارد شوید]] و اجازه
+‌های مربوط به این کار را داشته باشید.",
+"accmailtitle" => "کلمه‌ی عبور فرستاده شد.",
+"accmailtext" => "کلمه‌ی عبور «$1» به «$2» فرستاده شد.",
+"newarticle"   => "(جدید)",
+"newarticletext" =>
+"شما پیوندی را دنبال کرده‌اید و به صفحه‌ای رسیده‌اید که هنوز وجود ندارد.
+برای ایجاد صفحه، در مستطیل زیر شروع به تایپ کنید
+(برای اطلاعات بیشتر به [[ویکی‌پدیا:راهنما|صفحه‌ی راهنما]] مراجعه کنید).
+اگر اشتباهاً اینجا آمده‌اید، دکمه‌ی '''back''' مرورگرتان را بزنید.",
+"anontalkpagetext" => "---- ''این صفحه‌ی بحث برای کاربر گمنامی است که هنوز حسابی درست نکرده است یا از آن استفاده نمی‌کند.
+بنابراین برای شناسایی‌اش مجبوریم از [[نشانی IP]] عددی استفاده کنیم. چنین نشانی‌های IPای ممکن است توسط چندین کاربر به شکل
+مشترک استفاده شود.
+اگر شما کاربر گمنامی هستید و تصور می‌کنید اظهار نظرات نامربوط به شما صورت گرفته است،
+لطفاً برای پیشگیری از اشتباه گرفته شدن با کاربران گمنام دیگر در آیند [[ویژه:Userlogin|حسابی ایجاد کنید یا به سیستم وارد شوید]].'' ",
+"noarticletext" => "(این صفحه در حال حاضر متنی ندارد)",
+"updated"              => "(به‌روز شد)",
+"note"                 => "<strong>نکته:</strong> ",
+"previewnote"  => "توجه کنید که این فقط پیش‌نمایش است، و ذخیره نشده است!",
+"previewconflict" => "این پیش‌نمایش منعکس‌کننده‌ی متن ناحیه‌ی ویرایش متن بالایی است،
+به شکلی که اگر بخواهید متن را ذخیره کنید نشان داده خواهد شد.",
+"editing"              => "در حال ویرایش $1",
+"editingsection"       => "در حال ویرایش $1 (قسمت)",
+"editingcomment"       => "در حال ویرایش $1 (یادداشت)",
+"editconflict" => "تعارض ویرایشی: $1",
+"explainconflict" => "از وقتی شما ویرایش این صفحه را آغاز کرده‌اید شخص دیگری آن را تغییر داده است.
+ناحیه‌ی متنی بالایی شامل متن صفحه به شکل فعلی آن است.
+تغییرات شما در ناحیه‌ی متنی پایینی نشان داده شده است.
+شما باید تغییراتتان را با متن فعلی ترکیب کنید.
+وقتی «ذخیره‌ی صفحه» را فشار دهید، <b>فقط</b> متن ناحیه‌ی متنی بالایی ذخیره خواهد شد.<br />",
+"yourtext"             => "متن شما",
+"storedversion" => "نسخه‌ی ضبط‌شده",
+"editingold"   => "<strong>هشدار:
+شما دارید نسخه‌ی قدیمی‌ای از این صفحه را ویرایش می‌کنید.
+اگر ذخیره‌اش کنید، هر تغییری که پس از این نسخه انجام شده از بین خواهد رفت.</strong>",
+"yourdiff"             => "تفاوت‌ها",
+# FIXME: This is inappropriate for third-party use!
+"copyrightwarning" => "لطفاٌ توجه داشته باشید که فرض می‌شود کلیه‌ی مشارکت‌های شما با ویکی‌پدیا
+تحت اجازه‌نامه‌ی مستندات آزاد گنو منتشر می‌شوند
+(برای جزئیات بیشتر به $1 مراجعه کنید).
+اگر نمی‌خواهد نوشته‌هایتان بیرحمانه ویرایش شده و به دلخواه توزیع شود،
+اینجا نفرستیدشان.<br />
+همینطور شما دارید به ما قول می‌دهید که خودتان این را نوشته‌اید، یا آن را از یک منبع آزاد با
+مالکیت عمومی یا مشابه آن برداشته‌اید.
+<strong>کارهای دارای حق انحصاری تکثیر (کپی‌رایت) را بی اجازه نفرستید!</strong>",
+"longpagewarning" => "<strong>هشدار: این صفحه $1 کیلوبایت طول دارد؛
+بعضی مرورگرها ممکن با ویرایش صفحات نزدیک به ۳۲ کیلوبایت یا طولانیتر از آن مشکلاتی داشته باشند.
+لطفاً درباره‌ی شکستن این صفحه به قسمت‌های کوچکتر فکر کنید.</strong>",
+"readonlywarning" => "<strong>هشدار: پایگاه داده برای نگهداری قفل شده است،
+بنابراین نمی‌توانید ویرایش‌هایتان را همین الآن ذخیره کنید.
+اگر می‌خواهید متن را در یک پرونده‌ی متنی ببرید و بچسبانید و برای آینده ذخیره‌اش کنید.</strong>",
+"protectedpagewarning" => "<strong>هشدار: این صفحه قفل شده است تا فقط کاربران با امتیاز اپراتور سیستم بتوانند ویرایشش کنند.
+مطمئن شوید که از
+[[ویکی‌پدیا:توصیه‌های صفحات محافظت‌شده|توصیه‌های صفحات محافظت‌شده]] پیروی می‌کنید.<strong>",
+
+# History pages
+#
+"revhistory"   => "تاریخچه‌ی تغییرات",
+"nohistory"            => "این صفحه تاریخچه‌ی ویرایش ندارد.",
+"revnotfound"  => "نسخه یافت نشد",
+"revnotfoundtext" => "نسخه‌ی قدیمی‌از از صفحه که درخواست کرده بودید یافت نشد.
+لطفاً URLی را که برای دسترسی به این صفحه استفاده کرده‌اید بررسی کنید.\n",
+"loadhist"             => "در حال خواندن تاریخچه‌ی صفحه",
+"currentrev"   => "نسخه‌ی فعلی",
+"revisionasof" => "نسخه‌ی $1",
+"cur"                  => "فعلی",
+"next"                 => "بعدی",
+"last"                 => "آخرین",
+"orig"                 => "اصلی",
+"histlegend"   => "شرح: (فعلی) = تفاوت با نسخه‌ی فعلی،
+(آخرین) = تفاوت با نسخه‌ی قبلی، جز = ویرایش جزئی",
+
+# Diffs
+#
+"difference"   => "(تفاوت بین نسخه‌ها)",
+"loadingrev"   => "در حال خواندن نسخه برای تفاوت گرفتن",
+"lineno"               => "سطر $1:",
+"editcurrent"  => "ویرایش نسخه‌ی فعلی این صفحه",
+
+# Search results
+#
+"searchresults" => "نتایج جستجو",
+"searchresulttext" => "برای اطلاعات بیشتر درباره‌ی جستجوی ویکی‌پدیا، به [[ویکی‌پدیا:جستجو کردن|جستجوی ویکی‌پدیا]] مراجعه کنید.",
+"searchquery"  => "برای پرس‌وجوی «$1»",
+"badquery"             => "پرس‌وجوی جستجویی بدشکل",
+"badquerytext" => "نتوانستیم پرس‌وجوی شما را پردازش کنیم.
+این مشکل احتمالاً به این دلیل است که سعی کرده‌اید به دنبال کلمه‌ای کوتاهتر از سه حرف
+بگردید، که هنوز پشتیبانی نمی‌شود.
+همین‌طور ممکن است عبارت را اشتباه وارد کرده باشید، مثلاً «ماهی و و پولک».
+لطفاً یک پرس‌وجوی دیگر را امتحان کنید.",
+"matchtotals"  => "پرس‌وجوی «$1» متناظر $2 عنوان مقاله
+و $3 متن مقاله است.",
+"nogomatch" => "صفحه‌ی با دقیقاً این عنوان وجود ندارد، تلاش برای جستجوی کل متن.",
+"titlematches" => "Article title matches",
+"notitlematches" => "عنوان هیچ مقاله‌ای نمی‌خورد",
+"textmatches"  => "Article text matches",
+"notextmatches"        => "متن هیچ مقاله‌ای نمی‌خورد",
+"prevn"                        => "$1تای قبلی",
+"nextn"                        => "$1تای بعدی",
+"viewprevnext" => "نمایش ($1) ($2) ($3).",
+"showingresults" => "Showing below <b>$1</b> results starting with #<b>$2</b>.",
+"showingresultsnum" => "Showing below <b>$3</b> results starting with #<b>$2</b>.",
+"nonefound"            => "<strong>نکته</strong>: unsuccessful searches are
+often caused by searching for common words like \"have\" and \"from\",
+which are not indexed, or by specifying more than one search term (only pages
+containing all of the search terms will appear in the result).",
+"powersearch" => "جستجو",
+"powersearchtext" => "
+جستجو در فضاهای نام :<br />
+$1<br />
+$2 تغییرمسیرها فهرست شوند &nbsp; جستجو برای $3 $9",
+"searchdisabled" => "<p>شرمنده! جستجوی کل متن موقتاً از کار انداخته شده, for performance reasons. In the meantime, you can use the Google search below, which may be out of date.</p>",
+"blanknamespace" => "(اصلی)",
+
+# Preferences page
+#
+"preferences"  => "ترجیحات",
+"prefsnologin" => "به سیستم وارد نشده‌اید",
+"prefsnologintext"     => "برای تنظیم ترجیحات کاربر باید [[ویژه:Userlogin|به سیستم وارد شوید]].",
+"prefslogintext" => "شما با نام «$1» وارد سیستم شده‌اید.
+شماره‌ی شناسایی داخلی شما $2 است.
+
+برای راهنمایی در فهمیدن گزینه‌ها، به [[ویکی‌پدیا:راهنمای ترجیحات کاربر]] مراجعه کنید.",
+"prefsreset"   => "ترجیحات از حافظه میزان شد.",
+"qbsettings"   => "تنظیمات نوار سریع",
+"changepassword" => "تغییر کلمه‌ی عبور",
+"skin"                 => "پوسته",
+"math"                 => "نمایش ریاضیات",
+"dateformat"   => "قالب تاریخ",
+"math_failure"         => "شکست در تجزیه",
+"math_unknown_error"   => "خطای ناشناخته",
+"math_unknown_function"        => "تابع ناشناخته‌ی ",
+"math_lexing_error"    => "خطای lexing",
+"math_syntax_error"    => "خطای نحوی",
+"math_image_error"     => "تبدیل به PNG شکست خورد",
+"saveprefs"            => "ذخیره‌ی ترجیحات",
+"resetprefs"   => "صفر کردن ترجیحات",
+"oldpassword"  => "کلمه‌ی عبور قدیمی",
+"newpassword"  => "کلمه‌ی عبور جدید",
+"retypenew"            => "کلمه‌ی عبور جدید را دوباره وارد کنید",
+"textboxsize"  => "ابعاد جعبه‌ی متن",
+"rows"                 => "تعداد سطرها",
+"columns"              => "تعداد ستون‌ها",
+"searchresultshead" => "تنظیمات نتیجه‌ی جستجو",
+"resultsperpage" => "تعداد نتایج در هر صفحه",
+"contextlines" => "تعداد سطرها در هر نتیجه",
+"contextchars" => "تعداد نویسه‌های اطراف در سطر",
+"stubthreshold" => "آستانه‌ی نمایش ناقص‌ها",
+"recentchangescount" => "تعداد عناوین در تغییرات اخیر",
+"savedprefs"   => "ترجیحات شما ذخیره شد.",
+"timezonetext" => "تفاوت تعداد ساعت زمان محلی‌تان با زمان خادم (وقت گرینیچ) را وارد کنید.",
+"localtime"    => "نمایش زمان محلی",
+"timezoneoffset" => "تفاوت",
+"servertime"   => "زمان فعلی خادم",
+"guesstimezone" => "از مرورگر گرفته شود",
+"emailflag"            => "از کار انداختن پست الکترونیکی از کاربران دیگر",
+"defaultns"            => "به طور پیشفرض در این فضاهای نام جستجو شود:",
+
+# Recent changes
+#
+"changes" => "تغییرات",
+"recentchanges" => "تغییرات اخیر",
+"recentchangestext" => "آخرین تغییرات ویکی را در این صفحه تعقیب کنید.",
+"rcloaderr"            => "در حال خواندن تغییرات اخیر",
+"rcnote"               => "در زیر آخرین <strong>$1</strong> تغییر در <strong>$2</strong> روز اخیر آمده است.",
+"rcnotefrom"   => "در زیر تغییرات از تاریخ <b>$2</b> آمده‌اند (تا <b>$1</b> مورد نشان داده می‌شود).",
+"rclistfrom"   => "نمایش تغییرات جدید با شروع از $1",
+# "rclinks"            => "نمایش آخرین $1 تغییر در $2 ساعت اخیر / $3 روز اخیر",
+# "rclinks"            => "نمایش آخرین $1 تغییر در $2 روز اخیر.",
+"showhideminor"         => "ویرایش‌های جزئی $1 | $2 bots | $3 logged in users | $4 patrolled edits",
+"rclinks"              => "نمایش آخرین $1 تغییر در $2 روز اخیر؛ $3",
+"rchide"               => "به شکل $4؛ $1 ویرایش جزئی؛ $2 فضای نام ثانویه؛ $3 ویرایش چندگانه.",
+"rcliu"                        => "؛ $1 ویرایش از کاربران وارد شده به سیستم",
+"diff"                 => "تفاوت",
+"hist"                 => "تاریخچه",
+"hide"                 => "مخفی شود",
+"show"                 => "نمایش یابد",
+"tableform"            => "جدول",
+"listform"             => "فهرست",
+"nchanges"             => "$1 تغییر",
+"minoreditletter" => "جز",
+"newpageletter" => "جد",
+
+# Upload
+#
+"upload"               => "بار کردن پرونده",
+"uploadbtn"            => "پرونده بار شود",
+"uploadlink"   => "بار کردن تصاویر",
+"reupload"             => "بار کردن مجدد",
+"reuploaddesc" => "بازگشت به فرم بار کردن",
+"uploadnologin" => "به سیستم وارد نشده‌اید",
+"uploadnologintext"    => "برای بار کردن پرونده‌ها باید [[ویژه:Userlogin|وارد سیستم شوید]].",
+"uploaderror"  => "خطا در بار کردن",
+"uploadtext"   => "'''ایست!''' قبل از این که چیزی اینجا بار کنید،
+مطمئن شوید که
+[[Project:سیاست_استفاده_از_تصاویر|سیاست استفاده از تصاویر]]
+را خوانده‌اید و از آن پیروی می‌کنید.
+
+If a file with the name you are specifying already
+exists on the wiki, it'll be replaced without warning.
+So unless you mean to update a file, it's a good idea
+to first check if such a file exists.
+
+To view or search previously uploaded images,
+go to the [[Special:Imagelist|list of uploaded images]].
+Uploads and deletions are logged on the
+[[Project:Upload_log|upload log]].
+
+Use the form below to upload new image files for use in
+illustrating your articles.
+On most browsers, you will see a \"Browse...\" button, which will
+bring up your operating system's standard file open dialog.
+Choosing a file will fill the name of that file into the text
+field next to the button.
+You must also check the box affirming that you are not
+violating any copyrights by uploading the file.
+Press the \"Upload\" button to finish the upload.
+This may take some time if you have a slow internet connection.
+
+The preferred formats are JPEG for photographic images, PNG
+for drawings and other iconic images, and OGG for sounds.
+Please name your files descriptively to avoid confusion.
+To include the image in an article, use a link in the form
+'''<nowiki>[[image:file.jpg]]</nowiki>''' or
+'''<nowiki>[[image:file.png|alt text]]</nowiki>''' or
+'''<nowiki>[[media:file.ogg]]</nowiki>''' for sounds.
+
+Please note that as with wiki pages, others may edit or
+delete your uploads if they think it serves the encyclopedia, and
+you may be blocked from uploading if you abuse the system.",
+
+"uploadlog"            => "سیاهه‌ی بارکردن‌ها",
+"uploadlogpage" => "سیاهه‌ی_بارکردن‌ها",
+"uploadlogpagetext" => "فهرست زیر فهرستی از آخرین بارکردن‌های پرونده‌های است.
+همه‌ی زمان‌های نشان‌داده‌شده زمان خادم هستند (وقت گرینیچ).
+<ul>
+</ul>
+",
+"filename"             => "نام پرونده",
+"filedesc"             => "خلاصه",
+"filestatus" => "وضعیت حق تکثیر",
+"filesource" => "منبع",
+"copyrightpage" => "ویکی‌پدیا:حق_تکثیر",
+"copyrightpagename" => "حق تکثیر ویکی‌پدیا",
+"uploadedfiles"        => "پرونده‌های بارشده",
+"ignorewarning"        => "هشدار نادیده گرفته شود و پرونده به‌هرحال ذخیره شود.",
+"minlength"            => "نام پرونده باید حداقل سه‌حرفی باشد.",
+"badfilename"  => "نام پرونده به «$1» تغییر کرد.",
+"badfiletype"  => "قالب پرونده‌ای «‎.$1» برای پرونده‌های تصویری توصیه نمی‌شود.",
+"largefile"            => "توصیه می‌شود که اندازه‌ی تصاویر از ۱۰۰ کیلوبایت بیشتر نباشد.",
+"successfulupload" => "بار کردن با موفقیت انجام شد",
+"fileuploaded" => "پرونده‌ی «$1» با موفقیت بار شد.
+لطفاً این پیوند را تعقیب کنید: ($2) تا صفحه‌ی توصیف و اطلاعات در مورد
+پرونده را، از قبیل این که از کجا آمده است، چه کسی و در چه زمانی آن را ایجاد کرده است،
+و هر چیز دیگری که ممکن است در مورد آن بدانید، پر کنید.",
+"uploadwarning" => "هشدار بار کردن",
+"savefile"             => "ذخیره‌ی پرونده",
+"uploadedimage" => "«[[$1]]» بار شد",
+"uploaddisabled" => "شرمنده، بار کردن از کار افتاده است.",
+
+# Image list
+#
+"imagelist"            => "فهرست تصاویر",
+"imagelisttext"        => "در زیر فهرست $1 تصویری که $2 مرتب شده است آمده است.",
+"getimagelist" => "در حال اخذ فهرست تصاویر",
+"ilsubmit"             => "جستجو",
+"showlast"             => "نمایش آخرین $1 تصویر مرتب‌شده $2.",
+"byname"               => "از روی نام",
+"bydate"               => "از روی تاریخ",
+"bysize"               => "از روی اندازه",
+"imgdelete"            => "حذف",
+"imgdesc"              => "توصیف",
+"imglegend"            => "شرح: (توصیف) = نمایش/ویرایش توصیف تصویر.",
+"imghistory"   => "تاریخچه‌ی تصویر",
+"revertimg"            => "برگرد",
+"deleteimg"            => "حذف",
+"deleteimgcompletely"          => "حذف",
+"imghistlegend" => "شرح: (فعلی) = این تصویر فعلی است، (حذف) = این
+نسخه‌ی قدیمی حذف شود، (برگرد) = برگرداندن به این نسخه‌ی قدیمی.
+<br /><i>برای دیدن تصویر بار شده در تاریخ مشخص، روی تاریخ کلیک کنید</i>.",
+"imagelinks"   => "پیوند‌های تصاویر",
+"linkstoimage" => "این صفحات به این تصویر پیوند دارند:",
+"nolinkstoimage" => "هیچ صفحه‌ای به این تصویر پیوند ندارد.",
+
+# Statistics
+#
+"statistics"   => "آمار",
+"sitestats"            => "آمار وبگاه",
+"userstats"            => "آمار کاربران",
+"sitestatstext" => "کلاً <b>$1</b> صفحه در پایگاه داده هست.
+این شامل صفحات «بحث»، صفحات درباره‌ی ویکی‌پدیا، صفحات «ناقص» کوچک،
+تغییرمسیرها، و صفحات دیگری می‌شود که احتمالاً مقاله به حساب نمی‌آیند.
+فارق از این‌ها، <b>$2</b> صفحه هست که احتمالاً مقاله‌ی معقول هستند.<p>
+از زمانی که نرم‌افزار ارتقا یافته (۲۰ ژوئیه‌ی ۲۰۰۲)، کلاً <b>$3</b> بازدید از صفحات،
+و <b>$4</b> ویرایش صفحات صورت گرفته است.
+این می‌شود به طور متوسط <b>$5</b> ویرایش برای هر صفحه، و <b>$6</b> بازدید به‌ازای هر ویرایش.",
+"userstatstext" => "تعداد <b>$1</b> کاربر ثبت‌شده وجود دارد.
+تعداد <b>$2</b> از این کاربران مدیرند (به $3 مراجعه شود).",
+
+# Maintenance Page
+#
+"maintenance"          => "صفحه‌ی نگهداری",
+"maintnancepagetext"   => "This page includes several handy tools for everyday maintenance. Some of these functions tend to stress the database, so please do not hit reload after every item you fixed ;-)",
+"maintenancebacklink"  => "بازگشت به صفحه‌ی نگهداری",
+"disambiguations"      => "صفحات رفع ابهام",
+"disambiguationspage"  => "ویکی‌پدیا:پیوند به صفحات رفع ابهام",
+"disambiguationstext"  => "مقاله‌های زیر به یک <i>صفحه‌ی رفع ابهام</i> پیوند دارند. به جای این، این صفحات باید به
+They should link to the appropriate topic instead.<br />A page is treated as dismbiguation if it is linked from $1.<br />Links from other namespaces are <i>not</i> listed here.",
+"doubleredirects"      => "تغییرمسیرهای دوتایی",
+"doubleredirectstext"  => "<b>توجه:</b> This list may contain false positives. That usually means there is additional text with links below the first #REDIRECT.<br />\nEach row contains links to the first and second redirect, as well as the first line of the second redirect text, usually giving the \"real\" taget article, which the first redirect should point to.",
+"brokenredirects"      => "تغییرمسیرهای خراب",
+"brokenredirectstext"  => "تغییرمسیرهای زیر به یک صفحه‌ی ناموجود پیوند دارند.",
+"selflinks"            => "صفحات با پیوند به خود",
+"selflinkstext"                => "این صفحات به خودشان پیوند دارند، که نباید داشته باشند.",
+"mispeelings"           => "صفحات با غلط املایی",
+"mispeelingstext"               => "صفحات زیر یک غلط املایی معمول دارند، که در $1 آمده است. ممکن است املای درست (به این شکل) آمده باشد.",
+"mispeelingspage"       => "فهرست غلط‌های املایی معمول",
+"missinglanguagelinks"  => "پیوندهای زبانی گم‌شده",
+"missinglanguagelinksbutton"    => "یافتن پیوندهای زبانی گم‌شده برای",
+"missinglanguagelinkstext"      => "این مقاله‌ها به همتایشان در $1 پیوند <i>ندارند</i>. Redirects و زیرصفحه‌ها نشان داده <i>نشده‌اند</i>.",
+
+
+# Miscellaneous special pages
+#
+"orphans"              => "صفحات یتیم",
+"lonelypages"  => "صفحات یتیم",
+"unusedimages" => "تصاویر بلااستفاده",
+"popularpages" => "صفحات محبوب",
+"nviews"               => "$1 نمایش",
+"wantedpages"  => "صفحات مورد نیاز",
+"nlinks"               => "$1 پیوند",
+"allpages"             => "همه‌ی صفحات",
+"randompage"   => "صفحه‌ی تصادفی",
+"shortpages"   => "صفحات کوتاه",
+"longpages"            => "صفحات بلند",
+"deadendpages"  => "صفحات بن‌بست",
+"listusers"            => "فهرست کاربران",
+"specialpages" => "صفحات ویژه",
+"spheading"            => "صفحات ویژه‌ی همه‌ی کاربران",
+"protectpage"  => "محافظت از صفحه",
+"recentchangeslinked" => "تغییرات مرتبط",
+"rclsub"               => "(به صفحات پیونددار از «$1»)",
+"debug"                        => "اشکال‌زدایی",
+"newpages"             => "صفحات جدید",
+"ancientpages"         => "قدیمی‌ترین مقاله‌ها",
+"intl"         => "پیوندهای بین زبانی",
+"movethispage" => "انتقال این صفحه",
+"unusedimagestext" => "<p>لطفاٌ توجه کنید که وبگاه‌های دیگر از جمله ویکی‌پدیاهای بین‌المللی
+ممکن است با URL مستقیم به تصاویر پیوند داشته باشند، و نتیجتاً با وجود استفاده‌ی فعال
+اینجا فهرست شده باشند.",
+"booksources"  => "منابع کتاب",
+# FIXME: Other sites, of course, may have affiliate relations with the booksellers list
+"booksourcetext" => "در زیر فهرستی از پیوندها به وبگاه‌های دیگری که کتاب‌های نو و دست دوم می‌فروشند آمده است،
+و ممکن است اطلاعات بیشتری نیز درباره‌ی کتاب‌هایی که دنبالشان می‌گردید داشته باشند.
+ویکی‌پدیا وابستگی یا ارتباطی با هیچ یک از این کسب‌وکارها ندارد، و این فهرست
+نباید به معنی تأیید یا حمایت تعبیر شود.",
+"alphaindexline" => "$1 تا $2",
+
+# Email this user
+#
+"mailnologin"  => "نشانی فرستنده‌ای نیست",
+"mailnologintext" => "برای فرستادن پست الکترونیکی به کاربران دیگر باید [[ویژه:Userlogin|به سیستم وارد شوید]]
+و نشانی پست الکترونیکی معتبری در [[ویژه:ترجیحات|ترجیحات]]
+خود داشته باشید.",
+"emailuser"            => "پست الکترونیکی به این کاربر",
+"emailpage"            => "پست الکترونیکی به کاربر",
+"emailpagetext"        => "اگر این کاربر نشانی پست الکترونیکی معتبری در ترجیحات کاربریش وارد کرده
+باشد، فرم زیر یک پیغام می‌فرستد.
+نشانی پست الکترونیکی‌ای که در ترجیحات کاربریتان وارد کرده‌اید در نشانی فرستنده (From) نامه
+خواهد آمد، تا گیرنده بتواند پاسخ دهد.",
+"noemailtitle" => "نشانی پست‌الکترونیک موجود نیست",
+"noemailtext"  => "این کاربر نشانی پست الکترونیکی معتبری مشخص نکرده است،
+یا تصمیم گرفته از کاربران دیگر پست الکترونیکی دریافت نکند.",
+"emailfrom"            => "از",
+"emailto"              => "به",
+"emailsubject" => "عنوان",
+"emailmessage" => "پیغام",
+"emailsend"            => "فرستاده شود",
+"emailsent"            => "پست الکترونیکی فرستاده شد",
+"emailsenttext" => "پیغام پست الکترونیکی شما فرستاده شد.",
+
+# Watchlist
+#
+"watchlist"                    => "فهرست تعقیبات من",
+"watchlistsub"         => "(برای کاربر «$1»)",
+"nowatchlist"          => "در فهرست تعقیبات شما هیچ موردی نیست.",
+"watchnologin"         => "به سیستم وارد نشده‌اید",
+"watchnologintext"     => "برای تغییر فهرست تعقیباتتان باید [[ویژه:Userlogin|به سیستم وارد شوید]].",
+"addedwatch"           => "به فهرست تعقیبات اضافه شود",
+"addedwatchtext"       => "صفحه‌ی «$1» به <a href=\"" .
+  "{{localurle:ویژه:Watchlist}}\">فهرست تعقیبات</a> شما اضافه شد.
+تغییرات این صفحه و صفحه‌ی بحث متناظرش در آینده در اینجا فهرست خواهد شد. به‌علاوه، این صفحه، برای واضحتر دیده شدن در
+<a href=\"" .
+  "{{localurle:ویژه:Recentchanges}}\">فهرست تغییرات اخیر</a> to
+به شکل<b>سیاه</b> خواهد آمد.</p>
+
+<p>اگر بعداً می‌خواستید این صفحه از فهرست تعقیباتتان برداشته شود، روی «تعقیب متوقف شود» در نوار حاشیه کلیک کنید.",
+"removedwatch"         => "از فهرست تعقیبات برداشته شد",
+"removedwatchtext"     => "صفحه‌ی «$1» از فهرست تعقیبات شما برداشته شد",
+"watchthispage"                => "تعقیب این صفحه",
+"unwatchthispage"      => "توقف تعقیب",
+"notanarticle"         => "مقاله نیست",
+"watchnochange"        => "هیچ یک از موارد در حال تعقیب شما در دوره‌ی زمانی نمایش‌یافته ویرایش نشده است.",
+"watchdetails"         => "($1 pages watched not counting talk pages;
+$2 total pages edited since cutoff;
+$3...
+[$4 نمایش و ویرایش فهرست کامل].)",
+"watchmethod-recent"=> "بررسی ویرایش‌های اخیر برای صفحات در حال تعقیب",
+"watchmethod-list"     => "بررسی صفحات در حال تعقیب برای ویرایش‌های اخیر",
+"removechecked"        => "برداشتن موارد تیک‌خورده از فهرست تعقیبات",
+"watchlistcontains" => "فهرست تعقیبات شما حاوی $1 صفحه است.",
+"watcheditlist"                => "در اینجا فهرست الفبایی‌ای از صفحات در تعقیب شما می‌آید.
+در جعبه‌ی صفحاتی که می‌خواهید از فهرست تعقیباتتان حذف شود تیک بزنید و روی دکمه‌ی «برداشتن موارد» در پایین
+صفحه کلیک کنید.",
+"removingchecked"      => "در حال برداشتن موارد درخواستی از فهرست تعقیبات...",
+"couldntremove"        => "نمی‌توان مورد «$1» را حذف کرد...",
+"iteminvalidname"      => "مشکل با مورد «$1»، نام نامعتبر است...",
+"wlnote"                       => "در زیر آخرین $1 تغییر در $2 ساعت آخر آمده است.",
+"wlshowlast"           => "نمایش آخرین $1 ساعت $2 روز $3",
+"wlsaved"                      => "این نسخه‌ی ذخیره‌شده‌ای از فهرست تعقیبات شما است.",
+
+
+# Delete/protect/revert
+#
+"deletepage"   => "حذف صفحه",
+"confirm"              => "تأیید",
+"excontent" => "content was: '$1'",
+"exbeforeblank" => "content before blanking was: '$1'",
+"exblank" => "صفحه خالی بود",
+"confirmdelete" => "تأیید حذف",
+"deletesub"            => "(در حال حذف «$1»)",
+"historywarning" => "هشدار: صفحه‌ای که دارید حذف می‌کند تاریخچه‌ای دارد: ",
+"confirmdeletetext" => "You are about to permanently delete a page
+or image along with all of its history from the database.
+Please confirm that you intend to do this, that you understand the
+consequences, and that you are doing this in accordance with
+[[$wgMetaNamespace:Policy]].",
+"actioncomplete" => "عمل انجام شد",
+"deletedtext"  => "«$1» حذف شده است.
+برای سابقه‌ی حذف‌های اخیر به $2 مراجعه کنید.",
+"deletedarticle" => "«$1» حذف شد",
+"dellogpage"   => "سیاهه‌ی_حذف",
+"dellogpagetext" => "فهرست زیر فهرستی از اخیرترین حذف‌ها است.
+همه‌ی زمان‌های نشان‌داده‌شده زمان خادم (وقت گرینیچ) است.
+<ul>
+</ul>
+",
+"deletionlog"  => "سیاهه‌ی حذف",
+"reverted"             => "به نسخه‌ی قدیمی‌تر برگردانده شد",
+"deletecomment"        => "دلیل حذف",
+"imagereverted" => "برگرداندن به نسخه‌ی قدیمی‌تر با موفقیت انجام شد.",
+"rollback"             => "Roll back edits",
+"rollbacklink" => "rollback",
+"rollbackfailed" => "Rollback failed",
+"cantrollback" => "نمی‌توان ویرایش را برگرداند؛ آخرین مشارکت‌کننده تنها مؤلف این مقاله است.",
+"alreadyrolled"        => "Cannot rollback last edit of [[$1]]
+by [[User:$2|$2]] ([[User talk:$2|Talk]]); someone else has edited or rolled back the article already.
+
+آخرین ویرایش توسط [[کاربر:$3|$3]] ([[بحث کاربر:$3|بحث]]). ",
+#   only shown if there is an edit comment
+"editcomment" => "توضیح ویرایش این بود: \"<i>$1</i>\".",
+"revertpage"   => "ویرایش $2 برگردانده شد، به آخرین تغییری که  $1 انجام داده است",
+"protectlogpage" => "سیاهه‌ی_محافظت",
+"protectlogtext" => "در زیر فهرست قفل کردن‌ها/ازقفل‌درآوردن‌های صفحات آمده است.
+برای اطلاعات بیشتر به [[ویکی‌پدیا:صفحه‌ی محافظت‌شده]] مراجعه کنید.",
+"protectedarticle" => "[[$1]] محافظت شد",
+"unprotectedarticle" => "[[$1]] از محافظت در آمد",
+
+# Undelete
+"undelete" => "احیای صفحه‌ی حذف شده",
+"undeletepage" => "نمایش و احیای صفحات حذف شده",
+"undeletepagetext" => "صفحات زیر حذف شده‌اند ولی هنوز در بایگانی هستند و می‌توانند احیا شوند.
+این آرشیو ممکن است هر چند وقت تمیز شود.",
+"undeletearticle" => "احیای مقاله‌ی حذف‌شده",
+"undeleterevisions" => "$1 نسخه بایگانی شده است",
+"undeletehistory" => "اگر این صفحه را احیا کنید، همه‌ی نسخه‌های آن در تاریخچه احیا خواهند شد.
+اگر صفحه‌ی جدیدی با نام یکسان از زمان حذف ایجاد شده باشد، نسخه‌های احیاشده در تاریخچه‌ی قبلی خواهند آمد،
+و نسخه‌ی فعلی صفحه‌ی زنده به طور خودکار جایگزین نخواهد شد.",
+"undeleterevision" => "حذف نسخه‌ی به تاریخ $1",
+"undeletebtn" => "احیا شود!",
+"undeletedarticle" => "«$1» احیا شد",
+"undeletedtext"   => "مقاله‌ی [[$1]] با موفقیت احیا شد.
+برای سوابق حذف‌ها و احیاهای اخیر به [[ویکی‌پدیا:سیاهه‌ی_حذف]] مراجعه کنید.",
+
+# Contributions
+#
+"contributions"        => "مشارکت‌های کاربر",
+"mycontris" => "مشارکت‌های من",
+"contribsub"   => "برای $1",
+"nocontribs"   => "هیچ تغییری نظیر این مشخصات یافت نشد.",
+"ucnote"               => "در زیر آخرین <b>$1</b> تغییر این کاربر در <b>$2</b> روز اخیر می‌آید.",
+"uclinks"              => "نمایش آخرین $1 تغییر؛ نمایش $2 روز اخیر.",
+"uctop"                => " (بالا)" ,
+
+# What links here
+#
+"whatlinkshere"        => "آنچه به اینجا پیوند دارد",
+"notargettitle" => "مقصدی نیست",
+"notargettext" => "شما صفحه‌ی یا کاربر مقصدی برای انجام این عمل روی آن مشخص نکرده‌اید.",
+"linklistsub"  => "(فهرست پیوندها)",
+"linkshere"            => "صفحات زیر به اینجا پیوند دارند:",
+"nolinkshere"  => "هیچ صفحه‌ای به اینجا پیوند ندارد.",
+"isredirect"   => "صفحه‌ی تغییر مسیر",
+
+# Block/unblock IP
+#
+"blockip"              => "بستن کاربر",
+"blockiptext"  => "از فرم زیر برای بستن دسترسی نوشتن از یک نشانی IP یا
+نام کاربری مشخص استفاده کنید.
+این کار فقط فقط باید برای جلوگیری از خرابکاری انجام شود، و بر اساس
+[[ویکی‌پدیا:خط مشی|خط مشی].
+دلیل مشخص این کار را در زیر ذکر کنید (مثلاً با ذکر صفحات به‌خصوصی که تخریب شده‌اند).",
+"ipaddress"            => "نشانی IP/نام کاربر",
+"ipbreason"            => "دلیل",
+"ipbsubmit"            => "این کاربر بسته شود",
+"badipaddress" => "کاربری با این نام وجود ندارد.",
+"blockipsuccesssub" => "بستن با موفقیت انجام شد",
+"blockipsuccesstext" => "«$1» بسته شده است.
+<br />برای بررسی بسته‌شدن‌ها، به [[ویژه:فهرستIPهای‌بسته|فهرست IPهای بسته]] مراجعه کنید.",
+"unblockip"            => "باز کردن کاربر",
+"unblockiptext"        => "برای باز گرداندن دسترسی نوشتن به یک نشانی IP یا نام کاربری بسته‌شده
+از فرم زیر استفاده کنید.",
+"ipusubmit"            => "باز کردن این نشانی",
+"ipusuccess"   => "«$1» باز شد",
+"ipblocklist"  => "فهرست نشانی‌های IP و نام‌های کاربری بسته‌شده",
+"blocklistline"        => "$1، $2 بست $3 را ($4)",
+"blocklink"            => "بسته شود",
+"unblocklink"  => "باز شود",
+"contribslink" => "مشارکت‌ها",
+"autoblocker"  => "به طور خودکار بسته شد چون IP شما و «$1» یکی است. دلیل «$2».",
+"blocklogpage" => "سیاهه‌ی_بسته‌شدن‌ها",
+"blocklogentry"        => '«$1» بسته شد',
+"blocklogtext" => "این سیاهه‌ای از اعمال بستن و باز کردن کاربرها است. نشانی‌های IPی که به طور
+خودکار بسته شده‌اند فهرست نشده‌اند. برای فهرست محرومیت‌ها و بسته‌شدن‌های عملیاتی در لحظه‌ی حاضر،
+به [[Special:Ipblocklist|فهرست IPهای بسته]] مراجعه کنید.",
+"unblocklogentry"      => '«$1» باز شد',
+
+# Developer tools
+#
+"lockdb"               => "قفل کردن پایگاه داده",
+"unlockdb"             => "از قفل در آوردن پایگاه داده",
+"lockdbtext"   => "Locking the database will suspend the ability of all
+users to edit pages, change their preferences, edit their watchlists, and
+other things requiring changes in the database.
+Please confirm that this is what you intend to do, and that you will
+unlock the database when your maintenance is done.",
+"unlockdbtext" => "Unlocking the database will restore the ability of all
+users to edit pages, change their preferences, edit their watchlists, and
+other things requiring changes in the database.
+Please confirm that this is what you intend to do.",
+"lockconfirm"  => "بله، من جداً می‌خواهم پایگاه داده را قفل کنم.",
+"unlockconfirm"        => "بله، من جداً می‌خواهم پایگاه داده را از قفل در آورم.",
+"lockbtn"              => "قفل کردن پایگاه داده",
+"unlockbtn"            => "از قفل درآوردن پایگاه داده",
+"locknoconfirm" => "شما در جعبه‌ی تأیید تیک نزدید",
+"lockdbsuccesssub" => "قفل کردن پایگاه داده با موفقیت انجام شد",
+"unlockdbsuccesssub" => "قفل پایگاه داده برداشته شد",
+"lockdbsuccesstext" => "پایگاه داده قفل شد.
+<br />فراموش نکنید که پس از اتمام نگهداری قفل را بردارید.",
+"unlockdbsuccesstext" => "پایگاه داده از قفل در آمد.",
+
+# Move page
+#
+"movepage"             => "انتقال صفحه",
+"movepagetext" => "با استفاده از فرم زیر نام صفحه تغییر خواهد کرد، و تمام تاریخچه‌اش به
+نام جدید منتقل خواهد شد.
+عنوان قدیمی تبدیل به یک صفحه‌ی تغییر مسیر به عنوان جدید خواهد شد.
+پیوندهای به عنوان صفحه‌ی قدیمی تغییر نخواهند کرد؛ حتماً تغییرمسیرهای دوتایی یا خراب را
+[[ویژه:نگهداری|بررسی کنید]].
+شما مسئول اطمینان از این هستید که پیوندها هنوز به همان‌جایی که قرار است بروند.
+
+توجه کنید که اگر از قبل صفحه‌ای در عنوان جدید وجود داشته باشد صفحه منتقل '''نخواهد شد'''، مگر
+این که صفحه خالی یا تغییر مسیر باشد و تاریخچه‌ی ویرایشی نداشته باشد.
+این یعنی اگر اشتباه کردید صفحه را به همان جایی که از آن منتقل شده بود برگردانید،
+و این که نمی‌توانید روی صفحات موجود بنویسید.
+
+<b>هشدار!</b>
+این کار ممکن است تغییر اساسی و غیرمنتظره‌ای برای صفحات محبوب باشد؛
+لطفاً مطمئن شوید که قبل از ادامه دادن عواقب این کار را درک می‌کنید.",
+"movepagetalktext" => "The associated talk page, if any, will be automatically moved along with it '''unless:'''
+*You are moving the page across namespaces,
+*A non-empty talk page already exists under the new name, or
+*You uncheck the box below.
+
+In those cases, you will have to move or merge the page manually if desired.",
+"movearticle"  => "انتقال صفحه",
+"movenologin"  => "به سیستم وارد نشده‌اید",
+"movenologintext" => "برای انتقال صفحات باید کاربر ثبت‌شده بوده و
+[[ویژه:Userlogin|به سیستم وارد شوید]].",
+"newtitle"             => "به عنوان جدید",
+"movepagebtn"  => "صفحه منتقل شود",
+"pagemovedsub" => "انتقال با موفقیت انجام شد",
+"pagemovedtext" => "صفحه‌ی «[[$1]]» به «[[$2]]» منتقل شد.",
+"articleexists" => "صفحه‌ای با این نام از قبل وجود دارد، یا نامی که انتخاب کرده‌اید معتبر نیست.
+لطفاً نام دیگری انتخاب کنید.",
+"talkexists"   => "صفحه با موفقیت منتقل شد، ولی صفحه‌ی بحث را، به این دلیل که صفحه‌ی بحثی در عنوان جدید
+وجود دارد، نمی‌توان منتقل کرد. لطفاً آنها را دستی ترکیب کنید.",
+"movedto"              => "منتقل شد به",
+"movetalk"             => "صفحه‌ی «بحث» هم، در صورت لزوم، منتقل شود.",
+"talkpagemoved" => "صفحه‌ی بحث متناظر نیز منتقل شد.",
+"talkpagenotmoved" => "صفحه‌ی بحث متناظر منتقل <strong>نشد</strong>.",
+"1movedto2"            => "$1 به $2 منتقل شد",
+
+# Export
+
+"export"               => "صدور صفحات",
+"exporttext"   => "شما می‌توانید متن و تاریخچه‌ی ویرایش یک صفحه‌ی مشخص یا مجموعه‌ای از صفحات را به شکل پوشیده در XML صادر کنید؛
+این اطلاعات را می‌توان وارد ویکی دیگری که نرم‌افزار مدیاویکی اجرا می‌کند کرد، تبدیل کرد، یا برای سرگرمی شخصی نگه داشت.",
+"exportcuronly"        => "فقط نسخه‌ی فعلی بیاید، نه کل تاریخچه",
+
+# Namespace 8 related
+
+"allmessages"  => "همه‌ی پیغام‌ها",
+"allmessagestext"      => "این فهرستی از همه‌ی پیغام‌های موجود در فضای نام مدیاویکی: است",
+
+# Thumbnails
+
+"thumbnail-more"      => "بزرگ شود",
+
+# Math
+
+'mw_math_png' => "همیشه PNG کشیده شود",
+'mw_math_simple' => "اگر خیلی ساده بودHTML وگرنه PNG",
+'mw_math_html' => "اگر ممکن بود HTML وگرنه PNG",
+'mw_math_source' => "در قالب TeX باقی بماند (برای مرورگرهای متنی)",
+'mw_math_modern' => "توصیه برای مرورگرهای امروزی",
+
+);
+
+#--------------------------------------------------------------------------
+# Internationalisation code
+#--------------------------------------------------------------------------
+
+class LanguageFa extends LanguageUtf8 {
+       var $digitTransTable = array(
+               "0" => "۰",
+               "1" => "۱",
+               "2" => "۲",
+               "3" => "۳",
+               "4" => "۴",
+               "5" => "۵",
+               "6" => "۶",
+               "7" => "۷",
+               "8" => "۸",
+               "9" => "۹",
+               "%" => "٪",
+               "." => "٫",
+               "," => "٬"
+       );
+
+       function getDefaultUserOptions() {
+               $opt = Language::getDefaultUserOptions();
+               $opt["quickbar"] = 2;
+               $opt["underline"] = 0;
+               return $opt;
+       }
+
+       function getNamespaces() {
+               global $wgNamespaceNamesFa;
+               return $wgNamespaceNamesFa;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsFa;
+               return $wgQuickbarSettingsFa;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesFa;
+               return $wgSkinNamesFa;
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesFa;
+               if(array_key_exists($key, $wgAllMessagesFa))
+                       return $wgAllMessagesFa[$key];
+               else
+                       return parent::getMessage($key);
+       }
+
+       # For right-to-left language support
+       function isRTL() { return true; }
+
+       function formatNum( $number ) {
+               global $wgTranslateNumerals;
+               if( $wgTranslateNumerals ) {
+                       return strtr( $number, $this->digitTransTable );
+               } else {
+                       return $number;
+               }
+       }
+
+}
+?>
diff --git a/languages/LanguageFi.php b/languages/LanguageFi.php
new file mode 100644 (file)
index 0000000..09a1a51
--- /dev/null
@@ -0,0 +1,1527 @@
+<?php
+/** Finnish (Suomi)
+ *
+ * @package MediaWiki
+ * @subpackage Language
+ */
+
+require_once( 'LanguageUtf8.php' );
+
+# Revised 2005-09-12 for MediaWiki 1.5rc4 -- Nikerabbit
+
+/* private */ $wgNamespaceNamesFi = array(
+       NS_MEDIA            => 'Media',
+       NS_SPECIAL          => 'Toiminnot',
+       NS_MAIN             => '',
+       NS_TALK             => 'Keskustelu',
+       NS_USER             => 'Käyttäjä',
+       NS_USER_TALK        => 'Keskustelu_käyttäjästä',
+       NS_PROJECT          => $wgMetaNamespace,
+       NS_PROJECT_TALK     => FALSE,  # Set in constructor
+       NS_IMAGE            => 'Kuva',
+       NS_IMAGE_TALK       => 'Keskustelu_kuvasta',
+       NS_MEDIAWIKI        => 'MediaWiki',
+       NS_MEDIAWIKI_TALK   => 'MediaWiki_talk',
+       NS_TEMPLATE         => 'Malline',
+       NS_TEMPLATE_TALK    => 'Keskustelu_mallineesta',
+       NS_HELP             => 'Ohje',
+       NS_HELP_TALK        => 'Keskustelu_ohjeesta',
+       NS_CATEGORY         => 'Luokka',
+       NS_CATEGORY_TALK    => 'Keskustelu_luokasta'
+
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgQuickbarSettingsFi = array(
+       'Ei mitään', 'Tekstin mukana, vasen', 'Tekstin mukana, oikea', 'Pysyen vasemmalla'
+);
+
+/* private */ $wgSkinNamesFi = array(
+       'standard'          => 'Perus',
+       'cologneblue'       => 'Kölnin sininen',
+       'myskin'            => 'Oma tyylisivu'
+) + $wgSkinNamesEn;
+
+/* private */ $wgDateFormatsFi = array(
+       'Ei valintaa',
+       '15. tammikuuta 2001 kello 16.12',
+       '15. tammikuuta 2001 kello 16:12:34',
+       '15.1.2001 16.12',
+       'ISO 8601' => '2001-01-15 16:12:34'
+);
+
+/* private */ $wgBookstoreListFi = array(
+       'Akateeminen kirjakauppa'       => 'http://www.akateeminen.com/search/tuotetieto.asp?tuotenro=$1',
+       'Bookplus'                      => 'http://www.bookplus.fi/product.php?isbn=$1',
+       'Helsingin yliopiston kirjasto' => 'http://pandora.lib.hel.fi/cgi-bin/mhask/monihask.py?volname=&author=&keyword=&ident=$1&submit=Hae&engine_helka=ON',
+       'Pääkaupunkiseudun kirjastot'   => 'http://www.helmet.fi/search*fin/i?SEARCH=$1',
+       'Tampereen seudun kirjastot'    => 'http://pandora.lib.hel.fi/cgi-bin/mhask/monihask.py?volname=&author=&keyword=&ident=$1-1&lang=kaikki&mat_type=kaikki&submit=Hae&engine_tampere=ON'
+) + $wgBookstoreListEn;
+
+# Current practices (may be changed if not good ones)
+# Refer namespaces with the English name or 'Project' in case of project namespace
+# Avoid any hard coded references to any particular subject which may not apply everywhere, e.g. artikkeli, wikipedia
+# Don't use participial phrases (lauseenkastikkeita) incorrectly
+# Avoid unnecessary parenthesis, quotes and html code
+#
+
+#-------------------------------------------------------------------
+# Translated messages
+#-------------------------------------------------------------------
+
+/* private */ $wgAllMessagesFi = array(
+
+# User preference toggles
+'tog-underline'       => 'Alleviivaa linkit',
+'tog-highlightbroken' => 'Näytä linkit puuttuville sivuille <a href="" class="new">näin</a> (vaihtoehtoisesti näin: <a href="" class="internal">?</a>).',
+'tog-justify'         => 'Tasaa kappaleet',
+'tog-hideminor'       => 'Piilota pienet muutokset tuoreet muutokset -listasta',
+'tog-usenewrc'        => 'Kehittynyt tuoreet muutokset -listaus (JavaScript)',
+'tog-numberheadings'  => 'Numeroi otsikot',
+'tog-showtoolbar'     => 'Näytä työkalupalkki',
+'tog-editondblclick'  => 'Muokkaa sivuja kaksoisnapsautuksella (JavaScript)',
+'tog-editsection'     => 'Näytä muokkauslinkit jokaisen osion yläpuolella',
+'tog-editsectiononrightclick' => 'Muokkaa osioita napsauttamalla otsikkoa hiiren oikealla painikkeella (JavaScript)',
+'tog-showtoc'         =>'Näytä sisällysluettelo sivuille, joilla yli 3 otsikkoa',
+'tog-rememberpassword'=> 'Älä kysy salasanaa saman yhteyden eri istuntojen välillä',
+'tog-editwidth'       => 'Muokkauskenttä on sivun levyinen',
+'tog-watchdefault'    => 'Lisää oletuksena uudet ja muokatut sivut tarkkailulistalle',
+'tog-minordefault'    => 'Muutokset ovat oletuksena pieniä',
+'tog-previewontop'    => 'Näytä esikatselu muokkauskentän yläpuolella',
+'tog-previewonfirst'  => 'Näytä esikatselu heti, kun muokkaus aloitetaan',
+'tog-nocache'         => 'Älä tallenna sivuja välimuistiin',
+'tog-enotifwatchlistpages' => 'Lähetä sähköpostiviesti tarkkailtujen sivujen muutoksista',
+'tog-enotifusertalkpages'  => 'Lähetä sähköpostiviesti, kun käyttäjäsivun keskustelusivu muuttuu',
+'tog-enotifminoredits'     => 'Lähetä sähköpostiviesti myös pienistä muokkauksista',
+'tog-enotifrevealaddr'     => 'Näytä sähköpostiosoitteeni muille lähetetyissä ilmoituksissa',
+'tog-shownumberswatching'  => 'Näytä sivua tarkkailevien käyttäjien määrä',
+'tog-fancysig'        => 'Muotoilematon allekirjoitus ilman automaattista linkkiä',
+'tog-externaleditor'  => 'Käytä ulkoista tekstieditoria oletuksena',
+'tog-externaldiff'    => 'Käytä ulkoista diff-ohjelmaa oletuksena',
+
+'underline-always'    => 'Aina',
+'underline-never'     => 'Ei koskaan',
+'underline-default'   => 'Selaimen oletustapa',
+
+'skinpreview'         => '(Esikatsele...)',
+
+# dates
+'sunday'      => 'sunnuntai',
+'monday'      => 'maanantai',
+'tuesday'     => 'tiistai',
+'wednesday'   => 'keskiviikko',
+'thursday'    => 'torstai',
+'friday'      => 'perjantai',
+'saturday'    => 'lauantai',
+'january'     => 'tammikuu',
+'february'    => 'helmikuu',
+'march'       => 'maaliskuu',
+'april'       => 'huhtikuu',
+'may_long'    => 'toukokuu',
+'june'        => 'kesäkuu',
+'july'        => 'heinäkuu',
+'august'      => 'elokuu',
+'september'   => 'syyskuu',
+'october'     => 'lokakuu',
+'november'    => 'marraskuu',
+'december'    => 'joulukuu',
+'jan'         => 'tammikuu',
+'feb'         => 'helmikuu',
+'mar'         => 'maaliskuu',
+'apr'         => 'huhtikuu',
+'may'         => 'toukokuu',
+'jun'         => 'kesäkuu',
+'jul'         => 'heinäkuu',
+'aug'         => 'elokuu',
+'sep'         => 'syyskuu',
+'oct'         => 'lokakuu',
+'nov'         => 'marraskuu',
+'dec'         => 'joulukuu',
+
+# Bits of text used by many pages:
+#
+'categories'          => 'Luokat',
+'category'            => 'Luokka',
+'category_header'     => 'Sivut, jotka ovat luokassa $1',
+'subcategories'       => 'Alaluokat',
+'linktrail'           => '/^((?:[a-z]|ä|ö|å)+)(.*)$/sD',
+'mainpage'            => 'Etusivu',
+'mainpagetext'        => 'Mediawiki on onnistuneesti asennettu.',
+'mainpagedocfooter'   => 'Lisätietoja käytöstä ja asetusten tekoa varten on sivuilla [http://meta.wikipedia.org/wiki/MediaWiki_i18n documentation on customizing the interface] ja [http://meta.wikipedia.org/wiki/MediaWiki_User%27s_Guide User\'s Guide].<br />Tarkista, että alla olevat taivutusmuodot ovat oikein. Jos eivät, tee tarvittavat muutokset LanguageFi.php:n <tt>convertGrammar</tt>-funktioon.<br />{{GRAMMAR:genitive|{{SITENAME}}}} (yön) — {{GRAMMAR:partitive|{{SITENAME}}}} (yötä) — {{GRAMMAR:elative|{{SITENAME}}}} (yöstä) — {{GRAMMAR:inessive|{{SITENAME}}}} (yössä) — {{GRAMMAR:illative|{{SITENAME}}}} (yöhön).',
+'portal'              => 'Kahvihuone',
+'portal-url'          => 'Project:Kahvihuone',
+'about'               => 'Tietoja',
+'aboutsite'           => 'Tietoja {{GRAMMAR:elative|{{SITENAME}}}}',
+'aboutpage'           => 'Project:Tietoja',
+'article'             => 'Sivu',
+'help'                => 'Ohje',
+'helppage'            => 'Help:Ohje',
+'bugreports'          => 'Ongelmat ja parannusehdotukset',
+'bugreportspage'      => 'Project:Ongelmat ja parannusehdotukset',
+'sitesupport'         => 'Lahjoitukset', # Set a URL in $wgSiteSupportPage in LocalSettings.php
+'sitesupport-url'     => 'Project:Lahjoitukset',
+
+'faq'                 => 'VUKK',
+'faqpage'             => 'Project:VUKK',
+'edithelp'            => 'Muokkausohjeet',
+'newwindow'           => '(avautuu uuteen ikkunaan)',
+'edithelppage'        => 'Help:Kuinka_sivuja_muokataan', // TODO: no docs
+'cancel'              => 'Keskeytä',
+'qbfind'              => 'Etsi',
+'qbbrowse'            => 'Selaa',
+'qbedit'              => 'Muokkaa',
+'qbpageoptions'       => 'Sivuasetukset',
+'qbpageinfo'          => 'Sivun tiedot',
+'qbmyoptions'         => 'Asetukset',
+'qbspecialpages'      => 'Toimintosivut',
+'moredotdotdot'       => 'Lisää...',
+'mypage'              => 'Oma käyttäjäsivu',
+'mytalk'              => 'Oma keskustelusivu',
+'anontalk'            => 'Keskustele tämän IP:n kanssa',
+'navigation'          => 'Valikko',
+'currentevents'       => 'Ajankohtaista',
+'currentevents-url'   => 'Project:Ajankohtaista',
+
+'disclaimers'         => 'Vastuuvapaus',
+'disclaimerpage'      => 'Project:Vastuuvapaus',
+'errorpagetitle'      => 'Virhe',
+'returnto'            => 'Palaa sivulle $1.',
+'tagline'             => '{{SITENAME}}',
+'whatlinkshere'       => 'Tänne viittaavat sivut',
+'help'                => 'Ohje',
+'search'              => 'Etsi',
+'go'                  => 'Siirry',
+'history'             => 'Historia',
+'history_short'       => 'Historia',
+'info_short'          => 'Tiedostus',
+'printableversion'    => 'Tulostettava versio',
+'edit'                => 'Muokkaa',
+'editthispage'        => 'Muokkaa tätä sivua',
+'delete'              => 'Poista',
+'deletethispage'      => 'Poista tämä sivu',
+'undelete_short'      => 'Palauta $1 muokkausta',
+'undelete_short1'     => 'Palauta 1 muokkaus',
+'protect'             => 'Suojaa',
+'protectthispage'     => 'Suojaa tämä sivu',
+'unprotect'           => 'Poista suojaus',
+'unprotectthispage'   => 'Poista tämän sivun suojaus',
+'newpage'             => 'Uusi sivu',
+'talkpage'            => 'Keskustele tästä sivusta',
+'specialpage'         => 'Toimintosivu',
+'personaltools'       => 'Henkilökohtaiset työkalut',
+'postcomment'         => 'Kommentti sivun loppuun',
+'addsection'          => '+',
+'articlepage'         => 'Näytä varsinainen sivu',
+'subjectpage'         => 'Näytä aihe', # For compatibility
+'talk'                => 'Keskustelu',
+'toolbox'             => 'Työkalut',
+'userpage'            => 'Näytä käyttäjän sivu',
+'wikipediapage'       => 'Näytä erikoissivu',
+'imagepage'           => 'Näytä kuvasivu',
+'viewtalkpage'        => 'Näytä keskustelusivu',
+'otherlanguages'      => 'Muut kielet',
+'redirectedfrom'      => 'Uudelleenohjattu sivulta $1',
+'lastmodified'        => 'Sivua on viimeksi muutettu  $1.',
+'viewcount'           => 'Tämä sivu on näytetty $1 kertaa.',
+'copyright'           => 'Sisältö on käytettävissä lisenssillä $1.',
+'poweredby'           => '{{GRAMMAR:genitive|{{SITENAME}}}} tarjoaa [http://www.mediawiki.org/ MediaWiki], avoimen lähdekoodin ohjelmisto.',
+'printsubtitle'       => '(Lähde: {{SERVER}})',
+'protectedpage'       => 'Suojattu sivu',
+'administrators'      => 'Project:Ylläpitäjät',
+'sysoptitle'          => 'Vaatii ylläpitäjäoikeudet',
+'sysoptext'           => 'Tämän toiminnon voi suorittaa vain käyttäjä, jolla on ylläpitäjäoikeudet. Katso $1.',
+'developertitle'      => 'Ohjelmiston kehittäjän oikeuksia vaaditaan',
+'developertext'       => 'Yrittämäsi toiminnon voi suorittaa vain henkilö, jolla on ohjelmistokehittäjänoikeudet. Katso $1.',
+
+'badaccess'           => 'Lupa evätty',
+'badaccesstext'       => 'Toiminto, jonka halusit suorittaa on rajoitettu käyttäjille, joilla on oikeus "$2". Katso $1.',
+
+'versionrequired'     => 'Mediawikistä tarvitaan vähintään versio $1',
+'versionrequiredtext' => 'Mediawikistä tarvitaan vähintään versio $1 tämän sivun käyttämiseen. Katso [[Special:Version|versio]]',
+
+'nbytes'              => '$1 tavua',
+'go'                  => 'Siirry',
+'ok'                  => 'OK',
+'sitetitle'           => '{{SITENAME}}',
+'pagetitle'           => '$1 — {{SITENAME}}',
+'sitesubtitle'        => '',
+'retrievedfrom'       => 'Haettu osoitteesta $1',
+'newmessages'         => 'Sinulle on $1',
+'newmessageslink'     => 'uusia viestejä.',
+'editsection'         => 'muokkaa',
+'toc'                 => 'Sisällysluettelo',
+'showtoc'             => 'näytä',
+'hidetoc'             => 'piilota',
+'thisisdeleted'       => 'Näytä tai palauta $1.',
+'viewdeleted'         => 'Näytä $1?',
+'restorelink1'        => 'yksi poistettu muokkaus.',
+'restorelink'         => '$1 poistettua muokkausta',
+'feedlinks'           => 'Uutissyötteet:',
+'sitenotice'          => '', # the equivalent to wgSiteNotice
+
+# Short words for each namespace, by default used in the 'article' tab in monobook
+'nstab-main'          => 'Sivu',
+'nstab-user'          => 'Käyttäjäsivu',
+'nstab-media'         => 'Media',
+'nstab-special'       => 'Toiminto',
+'nstab-wp'            => 'Projektisivu',
+'nstab-image'         => 'Tiedosto',
+'nstab-mediawiki'     => 'Järjestelmäviesti',
+'nstab-template'      => 'Malline',
+'nstab-help'          => 'Ohje',
+'nstab-category'      => 'Luokka',
+
+# Main script and global functions
+#
+'nosuchaction'        => 'Määrittelemätön pyyntö',
+'nosuchactiontext'    => 'Wikiohjelmisto ei tunnista URL:ssä määriteltyä pyyntöä',
+'nosuchspecialpage'   => 'Kyseistä toimintosivua ei ole',
+'nospecialpagetext'   => 'Wikiohjelmisto ei tunnista pyytämääsi toimintosivua.',
+
+# General errors
+#
+'error'               => 'Virhe',
+'databaseerror'       => 'Tietokantavirhe',
+'dberrortext'         => 'Tietokantakyselyssä oli syntaksivirhe. Syynä saattaa olla virheellinen kysely, tai se saattaa johtua ohjelmointivirheestä. Viimeinen tietokantakysely, jota yritettiin, oli: <blockquote><tt>$1</tt></blockquote>. Se tehtiin funktiosta "<tt>$2</tt>". MySQL palautti virheen "<tt>$3: $4</tt>".',
+'dberrortextcl'       => 'Tietokantakyselyssä oli syntaksivirhe. Viimeinen tietokantakysely, jota yritettiin, oli: "$1". Se tehtiin funktiosta "$2". MySQL palautti virheen "$3: $4".\n',
+'noconnect'           => 'Tietokantaan ei saatu yhteyttä, ole hyvä ja yritä uudestaan.',
+'nodb'                => 'Tietokantaa $1 ei voitu valita',
+'cachederror'         => 'Pyydetystä sivusta näytettiin välimuistissa oleva kopio, ja se saattaa olla vanhentunut.',
+'laggedslavemode'     => 'Varoitus: Sivu ei välttämättä sisällä viimeisimpiä muutoksia.',
+'readonly'            => 'Tietokanta on lukittu',
+'enterlockreason'     => 'Anna lukituksen syy sekä sen arvioitu poistamisaika',
+'readonlytext'        => '{{GRAMMAR:genitive|{{SITENAME}}}} tietokanta on tällä hetkellä lukittu. Uusia sivuja ei voi luoda eikä muitakaan muutoksia tehdä. Syynä ovat todennäköisimmin rutiininomaiset tietokannan ylläpitotoimet. Tietokannan lukinneen ylläpitäjän selitys: <p>$1',
+'missingarticle'      => 'Tietokannasta ei löytynyt sivua <b>$1</b>. Koita hetken päästä uudelleen. Jos ongelma ei katoa, ota yhteyttä ylläpitäjään ja anna mukaan tämän sivun URL-osoite.',
+'readonly_lag'        => 'Tietokanta on automaattisesti lukittu, jotta kaikki tietokantapalvelimet saisivat kaikki tuoreet muutokset',
+'internalerror'       => 'Sisäinen virhe',
+'filecopyerror'       => 'Tiedostoa <b>$1</b> ei voitu kopioida tiedostoksi <b>$2</b>.',
+'filerenameerror'     => 'Tiedostoa <b>$1</b> ei voitu nimetä uudelleen nimellä <b>$2</b>.',
+'filedeleteerror'     => 'Tiedostoa <b>$1</b> ei voitu poistaa.',
+'filenotfound'        => 'Tiedostoa <b>$1</b> ei löytynyt.',
+'unexpected'          => 'Odottamaton arvo: "$1"="$2".',
+'formerror'           => 'Lomakkeen tiedot eivät kelpaa',
+'badarticleerror'     => 'Toimintoa ei voi suorittaa tälle sivulle.',
+'cannotdelete'        => 'Sivun tai tiedoston poisto epäonnistui. Joku muu on saattanut poistaa sen.',
+'badtitle'            => 'Virheellinen otsikko',
+'badtitletext'        => 'Pyytämäsi sivuotsikko oli virheellinen, tyhjä tai väärin linkitetty kieltenvälinen tai wikienvälinen otsikko.',
+'perfdisabled'        => 'Pahoittelut! Tämä ominaisuus ei toistaiseksi ole käytetössä, sillä se hidastaa tietokantaa niin paljon, että kukaan ei voi käyttää wikiä. Toiminto ohjelmoidaan tehokkaammaksi lähiaikoina. (Sinäkin voit tehdä sen! Tämä on vapaa ohjelmisto.)',
+'perfdisabledsub'     => 'Tässä on tallennettu kopio $1', # obsolete? ei ole
+'perfcached'          => 'Seuraava data on tuotu välimuistista, eikä se ole välttämättä ajan tasalla.',
+'wrong_wfQuery_params'=> 'Virheelliset parametrit wfQuery()<br />Funktio: $1<br />Tiedustelu: $2',
+'viewsource'          => 'Lähdekoodi',
+'protectedtext'       => '<big>\'\'\'Tämä sivu on suojattu muutoksilta\'\'\'</big>
+* [[Talk:{{PAGENAME}}|Keskustele tästä sivusta]] muiden kanssa
+----
+Sivun lähdekoodi:',
+'sqlhidden'           => '(SQL-kysely piilotettu)',
+
+# Login and logout pages
+#
+'logouttitle'         => 'Uloskirjautuminen',
+'logouttext'          => 'Olet nyt kirjautunut ulos {{GRAMMAR:elative|{{SITENAME}}}}. Voit jatkaa {{GRAMMAR:genitive|{{SITENAME}}}} käyttöä nimettömänä, tai kirjautua uudelleen sisään.',
+'welcomecreation'     => '== Tervetuloa, $1! == <p>Käyttäjätunnuksesi on luotu. Älä unohda virittää [[Special:Preferences|{{GRAMMAR:genitive|{{SITENAME}}]] asetuksiasi]].</p>',
+'loginpagetitle'      => 'Sisäänkirjautuminen',
+'yourname'            => 'Käyttäjätunnus',
+'yourpassword'        => 'Salasana',
+'yourpasswordagain'   => 'Salasana uudelleen',
+'newusersonly'        => 'vain uudet käyttäjät',
+'remembermypassword'  => 'Muista minut',
+'yourdomainname'      => 'Verkkonimi',
+'externaldberror'     => 'Tapahtui virhe ulkoisen autentikointitietokannan käytössä tai sinulla ei ole lupaa päivittää tunnustasi.',
+'loginproblem'        => '<b>Sisäänkirjautuminen ei onnistunut.</b><br />Yritä uudelleen!',
+'alreadyloggedin'     => '<strong>Käyttäjä $1, olet jo kirjautunut sisään!</strong><br />\n',
+'login'               => 'Kirjaudu sisään',
+'loginprompt'         => '<!-- -->',
+'userlogin'           => 'Kirjaudu sisään tai luo tunnus',
+'logout'              => 'Kirjaudu ulos',
+'userlogout'          => 'Kirjaudu ulos',
+'notloggedin'         => 'Et ole kirjautunut',
+'createaccount'       => 'Luo uusi käyttäjätunnus',
+'createaccountmail'   => 'sähköpostitse',
+'badretype'           => 'Syöttämäsi salasanat ovat erilaiset.',
+'userexists'          => 'Pyytämäsi käyttäjänimi on jo käytössä. Ole hyvä ja valitse toinen käyttäjänimi.',
+'youremail'           => 'Sähköpostiosoite',
+'yourrealname'        => 'Nimi',
+'yourlanguage'        => 'Käyttöliittymän kieli',
+'yourvariant'         => 'Kielivariantti', // TODO: CHECK ME (language varian)
+'yournick'            => 'Nimimerkki allekirjoituksia varten',
+'email'               => 'Sähköpostitoiminnot',
+'emailforlost'        => '&nbsp;',
+'prefs-help-email-enotif' => 'Tätä osoitetta käytetään myös artikkelien muuttumisilmoituksiin, jos ominaisuus on käytössä.',
+'prefs-help-realname' => 'Nimi (vapaaehtoinen): Nimeäsi käytetään antaamaan kunnia työllesi.',
+'loginerror'          => 'Sisäänkirjautumisvirhe',
+'prefs-help-email'    => 'Sähköpostiosoite (vapaaehtoinen): Muut käyttäjät voivat ottaa sinuun yhteyttä sähköpostilla ilman, että osoitteesi paljastuu.',
+
+'nocookiesnew'        => 'Käyttäjä luotiin, mutta et ole kirjautunut sisään. {{SITENAME}} käyttää evästeitä sisäänkirjautumisen yhteydessä. Selaimesi ei salli evästeistä. Kytke ne päälle, ja sitten kirjaudu sisään juuri luomallasi käyttäjänimellä ja salasanalla.',
+'nocookieslogin'      => '{{SITENAME}} käyttää evästeitä sisäänkirjautumisen yhteydessä. Selaimesi ei salli evästeitä. Ota ne käyttöön, ja yritä uudelleen.',
+'noname'              => 'Et ole määritellyt kelvollista käyttäjänimeä.',
+'loginsuccesstitle'   => 'Sisäänkirjautuminen onnistui',
+'loginsuccess'        => 'Olet kirjautunut käyttäjänä $1.',
+'nosuchuser'          => 'Käyttäjää <strong>$1</strong> ei ole olemassa. Tarkista kirjoititko nimen oikein, tai käytä alla olevaa lomaketta uuden käyttäjätunnuksen luomiseksi.', // TODO NOWIKIMARKUP
+'nosuchusershort'     => 'Käyttäjää nimellä <b>$1</b> ei ole. Kirjoititko nimen oikein?', // TODO NO WIKIMARKUP
+'wrongpassword'       => 'Syöttämäsi salasana ei ole oikein. Ole hyvä ja yritä uudelleen.',
+'mailmypassword'      => 'Lähetä minulle uusi salasana sähköpostilla',
+'passwordremindertitle' => 'Salasanamuistutus {{GRAMMAR:elative|{{SITENAME}}}}',
+
+'passwordremindertext'=> 'Joku IP-osoitteesta $1 pyysi {{GRAMMAR:partitive|{{SITENAME}}}} lähettämään uuden salasanan. Salasana käyttäjälle $2 on nyt $3. Kirjaudu sisään ja vaihda salasana.',
+'noemail'             => 'Käyttäjälle \'\'\'$1\'\'\' ei ole määritelty sähköpostiosoitetta.',
+'passwordsent'        => 'Uusi salasana on lähetetty käyttäjän <b>$1</b> sähköpostiosoitteeseen.', // TODO NOWIKIMARKUP
+'eauthentsent'        => 'Varmennussähköposti on lähetetty annettuun sähköpostiosoitteeseen. Muita viestejä ei lähetetä, ennen kuin olet toiminut viestin ohjeiden mukaan ja varmistanut, että sähköpostiosoite kuuluu sinulle.',
+'loginend'            => '\'\'\'Rekisteröidäksesi käyttäjätunnuksen:\'\'\'
+#<small>Valitse itsellesi käyttäjätunnus ja kirjoita se \'\'käyttäjätunnus\'\'-kenttään.</small>
+#<small>Valitse salasana ja kirjoita se sekä \'\'salasana\'\'- että \'\'salasana uudelleen\'\' -kenttiin.</small>
+#<small>Halutessasi voit kirjoittaa sähköpostiosoitteesi \'\'sähköpostiosoite\'\'-kenttään. Jos annat sähköpostiosoitteesi, muut käyttäjät voivat lähettää sinulle sähköpostia saamatta osoitettasi tietoonsa, ja voit pyytää uuden salasanan, mikäli satut unohtamaan salasanasi.</small>
+
+\'\'\'Kirjautuaksesi sisään:\'\'\'
+*<small>Syötä käyttäjätunnuksesi ja salasanasi.</small>
+
+<small>Huomaa, että {{GRAMMAR:illative|{{SITENAME}}}} kirjautuminen edellyttää evästeiden käyttöä.</small>',
+'mailerror'           => 'Virhe lähetettäessä sähköpostia: $1',
+'acct_creation_throttle_hit' => 'Olet jo luonut $1 tunnusta. Et voi luoda uutta.',
+'emailauthenticated'         => 'Sähköpostiosoitteesi varmennettiin $1.',
+'emailnotauthenticated'      => 'Sähköpostiosoitteesi ei ole vielä varmennettu. Sähköpostia ei lähetetä liittyen alla oleviin toimintoihin.',
+'noemailprefs'        => 'Sähköpostiosoitetta ei ole määritelty. <!-- Seuraavat ominaisuudet eivät ole käytössä. -->', // MAYCHANGE
+'emailconfirmlink'    => 'Varmenna sähköpostiosoite',
+'invalidemailaddress' => 'Sähköpostiosoitetta ei voida hyväksyä, koska se ei ole oikeassa muodossa. Ole hyvä ja anna oikea sähköpostiosoite tai jätä kenttä tyhjäksi.',
+
+
+
+# Edit page toolbar
+'bold_sample'         => 'Lihavoitu teksti',
+'bold_tip'            => 'Lihavointi',
+'italic_sample'       => 'Kursivoitu teksti',
+'italic_tip'          => 'Kursivointi',
+'link_sample'         => 'linkki',
+'link_tip'            => 'Sisäinen linkki',
+'extlink_sample'      => 'http://www.example.com linkin otsikko',
+'extlink_tip'         => 'Ulkoinen linkki (muista http:// edessä)',
+'headline_sample'     => 'Otsikkoteksti',
+'headline_tip'        => 'Otsikko',
+'math_sample'         => 'Lisää kaava tähän',
+'math_tip'            => 'Matemaattinen kaava (LaTeX)',
+'nowiki_sample'       => 'Lisää muotoilematon teksti tähän',
+'nowiki_tip'          => 'Tekstiä, jota wiki ei muotoile',
+'image_sample'        => 'Esimerkki.jpg',
+'image_tip'           => 'Tallennettu kuva',
+'media_sample'        => 'Esimerkki.ogg',
+'media_tip'           => 'Mediatiedostolinkki',
+'sig_tip'             => 'Allekirjoitus aikamerkinnällä',
+'hr_tip'              => 'Vaakasuora viiva (käytä rajoitetusti)',
+'infobox'             => 'Napsauta painiketta saadaksesi esimerkkitekstin',
+
+# alert box shown in browsers where text selection does not work, test e.g. with mozilla or konqueror
+'infobox_alert'       => "Syötä teksti, jonka haluat muotoilluksi.\\n Se näytetään toisessa laatikossa leikkaa-liimaamista varten.\\nEsimerkki:\\n$1\\n muuttuu seuraavaksi:\\n$2",
+
+# Edit pages
+#
+'summary'             => 'Yhteenveto',
+'subject'             => 'Aihe',
+'minoredit'           => 'Tämä on pieni muutos',
+'watchthis'           => 'Tarkkaile tätä sivua',
+'savearticle'         => 'Tallenna sivu',
+'preview'             => 'Esikatselu',
+'showpreview'         => 'Esikatsele',
+'showdiff'            => 'Näytä muutokset',
+'blockedtitle'        => 'Pääsy estetty',
+'blockedtext'         => 'Yritit muokata sivua tai luoda uuden sivun. $1 on estänyt pääsysi {{GRAMMAR:illative|{{SITENAME}}}} joko käyttäjänimesi tai IP-osoitteesi perusteella. Annettu syy estolle on: <br />\'\'$2\'\'<p>Jos olet sitä mieltä, että sinut on estetty syyttä, voit keskustella asiasta [[Project:Ylläpitäjät|ylläpitäjän]] kanssa. Huomaa, ettet voi lähettää sähköpostia {{GRAMMAR:genitive|{{SITENAME}}}} kautta, ellet ole asettanut olemassaolevaa sähköpostiosoitetta [[Special:Preferences|asetuksissa]] ==Syytön?== Ajoittain kokonaisia IP-alueita tai yhteiskäytössä olevia osoitteita estetään. Se tarkoittaa, että myös viattomat käyttäjät voivat joutua estetyksi. Jos IP-osoitteesi on dynaaminen, eli se voi toisinaan vaihtua, olet saattanut saada estetyn osoitteen käyttöösi, ja esto vaikuttaa nyt sinuun. Jos tämä ongelma toistuu jatkuvasti, ota yhteyttä Internet-palveluntarjoajaasi tai {{GRAMMAR:genitive|{{SITENAME}}}} ylläpitäjään. Ilmoita IP-osoitteesi, joka on $3.',
+
+'whitelistedittitle'  => 'Sisäänkirjautuminen vaaditaan muokkaamiseen',
+'whitelistedittext'   => 'Sinun täytyy kirjautua [[Special:Userlogin|sisään]] muokataksesi sivuja.',
+'whitelistreadtitle'  => 'Sisäänkirjautuminen vaaditaan lukemiseen',
+'whitelistreadtext'   => 'Sinun täytyy kirjautua [[Special:Userlogin|sisään]] lukeaksesi sivuja.',
+'whitelistacctitle'   => 'Sinun ei ole sallittu luoda tunnusta',
+'whitelistacctext'    => 'Saadaksesi oikeudet luoda tunnus sinun täytyy kirjautua [[Special:Userlogin|sisään]] ja sinulla tulee olla asiaankuuluvat oikeudet.',
+'loginreqtitle'       => 'Sisäänkirjautuminen vaaditaan',
+'loginreqtext'        => 'Sinun täytyy [[Special:Userlogin|kirjautua sisään]], jotta voisit nähdä muut sivut.',
+
+'accmailtitle'        => 'Salasana lähetetty.',
+'accmailtext'         => 'käyttäjän \'\'\'$1\'\'\' salasana on lähetetty osoitteeseen \'\'\'$2\'\'\'.',
+'newarticle'          => '(uusi)',
+'newarticletext'      => 'Linkki toi sivulle, jota ei vielä ole. Voit luoda sivun kirjoittamalla alla olevaan tilaan. Jos et halua luoda sivua, käytä selaimen paluutoimintoa.',
+'talkpagetext'        => '<!-- MediaWiki:talkpagetext -->',
+'anontalkpagetext'    => '----\'\'Tämä on nimettömän käyttäjän keskustelusivu. Hän ei ole joko luonut itselleen käyttäjätunnusta tai ei käytä sitä. Siksi hänet tunnistetaan nyt numeerisella IP-osoitteella. Kyseinen IP-osoite voi olla useamman henkilön käytössä. Jos olet nimetön käyttäjä, ja sinusta tuntuu, että aiheettomia kommentteja on ohjattu sinulle, [[Special:Userlogin|luo itsellesi käyttäjätunnus tai kirjaudu sisään]] välttääksesi jatkossa sekaannukset muiden nimettömien käyttäjien kanssa.\'\'',
+'noarticletext'       => '<big>\'\'\'{{GRAMMAR:inessive|{{SITENAME}}}} ei ole tämän nimistä sivua.\'\'\'</big>
+* Voit kirjoittaa uuden sivun \'\'\'<span class="plainlinks">[{{SERVER}}{{localurl:{{NAMESPACE}}:{{PAGENAME}}|action=edit}} {{PAGENAME}}]</span>.\'\'\'
+* Jos olet luonut sivun tällä nimellä, se on saatettu poistaa — katso [[Special:Log/delete|poistoloki]].',
+'clearyourcache'      => '\'\'\'Huomautus:\'\'\' Selaimen välimuisti pitää ehkä tyhjentää asetusten tallentamisen jälkeen, jotta muutokset tulisivat voimaan: \'\'\'Mozilla, Firefox ja Safari:\'\'\' napsauta shift-näppäin pohjassa päivitä tai  paina \'\'shift-ctrl-r\'\' / \'\'shift-cmd-r\'\', \'\'\'IE:\'\'\' \'\'ctrl-f5\'\' tai \'\'\'Konqueror:\'\'\' \'\'F5\'\'.',
+'usercssjsyoucanpreview' => '\'\'\'Vinkki:\'\'\' Käytä esikatselupainiketta testataksesi uutta CSS:ää tai JavaScriptiä ennen tallennusta.',
+'usercsspreview'      => '\'\'\'Tämä on vasta CSS:n testaus ja esikatselu.\'\'\'',
+'userjspreview'       => '\'\'\'Tämä on vasta JavaScriptin testaus ja esikatselu.\'\'\'',
+'updated'             => '(Päivitetty)',
+'note'                => 'Huomautus: ', // TODO: NO WIKI MARKUP
+'previewnote'         => 'Tämä on vasta sivun esikatselu. Sivua ei ole vielä tallennettu!',
+'previewconflict'     => 'Tämä esikatselu näyttää miltä muokkausalueella oleva teksti näyttää tallennettuna.',
+'editing'             => 'Muokataan sivua $1',
+'editingsection'      => 'Muokataan osiota sivusta $1',
+'editingcomment'      => 'Muokataan kommenttia sivulla $1',
+'editconflict'        => 'Päällekkäinen muokkaus: $1',
+'explainconflict'     => 'Joku muu on muuttanut tätä sivua sen jälkeen, kun aloit muokata sitä. Ylempi tekstialue sisältää tämänhetkisen tekstin. Tekemäsi muutokset näkyvät alemmassa ikkunassa. Sinun täytyy yhdistää muutoksesi olemassa olevaan tekstiin. \'\'\'Vain\'\'\' ylemmässä alueessa oleva teksti tallentuu, kun tallennat sivun.',
+'yourtext'            => 'Oma tekstisi',
+'storedversion'       => 'Tallennettu versio',
+'nonunicodebrowser'   => '\'\'\'Varoitus: Selaimesi ei ole Unicode-yhteensopiva. Ole hyvä ja vaihda selainta, ennen kuin muokkaat sivua.\'\'\'',
+'editingold'          => '<center><strong>Varoitus</strong>: Olet muokkaamassa vanhaa versiota tämän sivun tekstistä. Jos tallennat sen, kaikki tämän version jälkeen tehdyt muutokset katoavat.</center>',
+'yourdiff'            => 'Eroavaisuudet',
+'copyrightwarning'    => '<strong>Muutoksesi astuvat voimaan välittömästi.</strong> Jos haluat harjoitella muokkaamista, ole hyvä ja käytä [[Project:Hiekkalaatikko|hiekkalaatikkoa]].<br /><br />Kaikki {{GRAMMAR:illative|{{SITENAME}}}} tehtävät tuotokset katsotaan julkaistuksi GNU Free Documentation -lisenssin mukaisesti ([[Project:{{SITENAME}} ja tekijänoikeudet|lisätietoja]]). Jos et halua, että kirjoitustasi muokataan armottomasti ja uudelleenkäytetään vapaasti, älä tallenna kirjoitustasi. Tallentamalla muutoksesi lupaat, että kirjoitit tekstisi itse, tai kopioit sen jostain vapaasta lähteestä. <strong>ÄLÄ KÄYTÄ TEKIJÄNOIKEUDEN ALAISTA MATERIAALIA ILMAN LUPAA!</strong>',
+'copyrightwarning2'   => '<br />Huomaa, että kuka tahansa voi muokata, muuttaa ja poistaa kaikkia sivustolle tekemiäsi lisäyksiä ja muutoksia. Muokkaamalla sivustoa luovutat sivuston käyttäjille tämän oikeuden ja takaat, että lisäämäsi aineisto on joko itse kirjoittamaasi tai peräisin jostain vapaasta lähteestä. <strong>TEKIJÄNOIKEUDEN ALAISEN MATERIAALIN KÄYTTÄMINEN ILMAN LUPAA ON EHDOTTOMASTI KIELLETTYÄ!</strong>',
+'longpagewarning'     => '<center>Tämän sivun tekstiosuus on $1 binäärikilotavua pitkä. Harkitse, voisiko sivun jakaa pienempiin osiin.</center>',
+'readonlywarning'     => '<strong>Varoitus</strong>: Tietokanta on lukittu huoltoa varten, joten voi olla ettet pysty tallentamaan muokkauksiasi juuri nyt. Saattaa olla paras leikata ja liimata tekstisi omaan tekstitiedostoosi ja tallentaa se tänne myöhemmin.',
+'protectedpagewarning'=> '<center><small>Tämä sivu on lukittu. Vain ylläpitäjät voivat muokata sitä.</small></center>',
+'templatesused'       => 'Tällä sivulla käytetyt mallineet:',
+
+# History pages
+#
+'revhistory'          => 'Muutoshistoria',
+'nohistory'           => 'Tällä sivulla ei ole muutoshistoriaa.',
+'revnotfound'         => 'Versiota ei löydy',
+'revnotfoundtext'     => 'Pyytämääsi versiota ei löydy. Tarkista URL-osoite, jolla hait tätä sivua.',
+'loadhist'            => 'Ladataan sivuhistoriaa',
+'currentrev'          => 'Nykyinen versio',
+'revisionasof'        => 'Versio $1',
+'revisionasofwithlink'=> 'Versio, joka luotiin $1.<br />$3 | $2 | $4',
+'previousrevision'    => '← Vanhempi versio',
+'nextrevision'        => 'Uudempi versio →',
+'currentrevisionlink' => 'Näytä nykyinen versio',
+'cur'                 => 'nyk.',
+'next'                => 'seur.',
+'last'                => 'edell.',
+'orig'                => 'alkup.',
+'histlegend'          => 'Merkinnät: (nyk.) = eroavaisuudet nykyiseen versioon, (edell.) = eroavaisuudet edelliseen versioon, <span class="minor">p</span> = pieni muutos', // TODO NO WIKIMARKUP
+'history_copyright'   => '-',
+'histfirst'           => 'Ensimmäiset',
+'histlast'            => 'Viimeisimmät',
+
+# Diffs
+#
+'difference'           => 'Versioiden väliset erot',
+'loadingrev'           => 'Ladataan versiota vertailua varten',
+'lineno'               => 'Rivi $1:',
+'editcurrent'          => 'Muokkaa tämän sivun uusinta versiota',
+'selectnewerversionfordiff' => 'Valitse uudempi versio vertailuun',
+'selectolderversionfordiff' => 'Valitse vanhempi versio vertailuun',
+'compareselectedversions'   => 'Vertaile valittuja versioita',
+
+# Search results
+#
+'searchresults'       => 'Hakutulokset',
+'searchresulttext'    => '<!-- -->',
+'searchquery'         => 'Haku termeillä $1',
+'badquery'            => 'Kelvoton hakumerkkijono',
+'badquerytext'        => 'Tekemäsi kysely ei ole kelvollinen. Tämä johtuu todennäköisesti siitä, että et ole määritellyt hakumerkkijonoa.',
+'matchtotals'         => 'Haulla \'\'\'$1\'\'\' löytyi $2 osumaa sivujen otsikoista ja $3 osumaa sivujen sisällöistä.',
+'nogomatch'           => '<big>Täsmälleen tällä otsikolla ei ole sivua.</big>
+
+:Voit [[$1|luoda aiheesta uuden sivun]].
+:<small>Etsi ensin vastaavaa sivua, joka voi olla kirjoitusasultaan hieman erilainen</small>
+',
+'titlematches'        => 'Osumat sivujen otsikoissa',
+'notitlematches'      => 'Hakusanaa ei löytynyt minkään sivun otsikosta',
+'textmatches'         => 'Osumat sivujen teksteissä',
+'notextmatches'       => 'Hakusanaa ei löytynyt sivujen teksteistä',
+'prevn'               => '← $1 edellistä',
+'nextn'               => '$1 seuraavaa →',
+'viewprevnext'        => "Näytä [$3] kerralla.\n\n$1 | $2",
+'showingresults'      => '<b>$1</b> tulosta tuloksesta <b>$2</b> alkaen.',
+'showingresultsnum'   => 'Alla on <b>$3</b> hakutulosta alkaen <b>$2.</b> tuloksesta.',
+'nonefound'           => '\'\'\'Huomautus\'\'\': Epäonnistuneet haut johtuvat usein hyvin yleisten sanojen, kuten \'\'on\'\' ja \'\'ei\'\', etsimisestä tai useamman kuin yhden hakutermin määrittelemisestä. Vain sivut, joilla on kaikki hakutermin sanat, näkyvät tuloksissa.',
+'powersearch'         => 'Etsi',
+'powersearchtext'     => 'Haku nimiavaruuksista:<br />$1<br /><b>Etsi</b> $3 $9 $2 Luettele uudelleenohjaukset', # TODO NOWIKIMARKUP
+'searchdisabled'      => '<p style="margin: 1.5em 2em 1em">Tekstihaku on poistettu toistaiseksi käytöstä suuren kuorman vuoksi. Voit käyttää alla olevaa Googlen hakukenttää sivujen etsimiseen, kunnes haku tulee taas käyttöön.<small>Huomaa, että ulkopuoliset kopiot {{GRAMMAR:genitive|{{SITENAME}}}} sisällöstä eivät välttämättä ole ajan tasalla.</small></p>', # TODO NOWIKIMARKUP
+'blanknamespace'      => '(sivut)',
+
+# Preferences page
+#
+'preferences'         => 'Asetukset',
+'prefsnologin'        => 'Et ole kirjautunut sisään',
+'prefsnologintext'    => 'Sinun täytyy [[Special:Userlogin|kirjautua sisään]], jotta voisit muuttaa asetuksia.',
+'prefslogintext'      => 'Olet kirjautunut sisään käyttäjänä \'\'\'$1\'\'\'. Sisäinen tunnistenumerosi on \'\'\'$2\'\'\'.',
+'prefsreset'          => 'Asetukset on palautettu tallennetuista asetuksistasi.',
+'qbsettings'          => 'Pikavalikko',
+'changepassword'      => 'Vaihda salasanaa',
+'skin'                => 'Ulkonäkö',
+'math'                => 'Matematiikka',
+'dateformat'          => 'Päiväyksen muoto',
+'math_failure'        => 'Jäsentäminen epäonnistui',
+'math_unknown_error'  => 'Tuntematon virhe',
+'math_unknown_function' => 'Tuntematon funktio',
+'math_lexing_error'   => 'Tulkintavirhe',
+'math_syntax_error'   => 'Jäsennysvirhe',
+'math_image_error'    => 'PNG-muunnos epäonnistui; tarkista, että latex, dvips, gs ja convert on asennettu oikein.',
+'math_bad_tmpdir'     => 'Matematiikan kirjoittaminen väliaikaishakemistoon tai tiedostonluonti ei onnistu',
+'math_bad_output'     => 'Matematiikan tulostehakemistoon kirjoittaminen tai tuedostonluonti ei onnistu',
+'math_notexvc'        => 'Texvc-sovellus puuttuu, lue math/READMEstä asennustietoja',
+'prefs-personal'      => 'Käyttäjätiedot',
+'prefs-rc'            => 'Tuoreet muutokset ja tyngät',
+'prefs-misc'          => 'Muut asetukset',
+'saveprefs'           => 'Tallenna asetukset',
+'resetprefs'          => 'Palauta tallennetut asetukset',
+'oldpassword'         => 'Vanha salasana',
+'newpassword'         => 'Uusi salasana',
+'retypenew'           => 'Uusi salasana uudelleen',
+'textboxsize'         => 'Muokkaaminen',
+'rows'                => 'Rivit',
+'columns'             => 'Sarakkeet',
+'searchresultshead'   => 'Haku',
+'resultsperpage'      => 'Tuloksia sivua kohti',
+'contextlines'        => 'Rivien määrä tulosta kohti',
+'contextchars'        => 'Sisällön merkkien määrä riviä kohden',
+'stubthreshold'       => 'Tynkäsivun osoituskynnys',
+'recentchangescount'  => 'Sivujen määrä tuoreissa muutoksissa',
+'savedprefs'          => 'Asetuksesi tallennettiin onnistuneesti.',
+'timezonelegend'      => 'Aikavyöhyke',
+'timezonetext'        => 'Paikallisen ajan ja palvelimen ajan (UTC) välinen aikaero tunteina.',
+'localtime'           => 'Paikallinen aika',
+'timezoneoffset'      => 'Aikaero',
+'servertime'          => 'Palvelimen aika',
+'guesstimezone'       => 'Utele selaimelta',
+'emailflag'           => 'Estä sähköpostin lähetys osoitteeseen',
+'defaultns'           => 'Etsi oletusarvoisesti näistä nimiavaruuksista:',
+'default'             => 'oletus',
+'files'               => 'Tiedostot',
+
+# User levels special page
+#
+
+# switching pan
+/*'groups-lookup-group' => 'Manage group rights',
+'groups-group-edit' => 'Existing groups: ',
+'editgroup' => 'Edit Group',
+'addgroup' => 'Add Group',*/
+
+'userrights-lookup-user'   => 'Käyttöoikeuksien hallinta',
+'userrights-user-editname' => 'Käyttäjätunnus: ',
+'editusergroup'            => 'Muokkaa käyttäjän ryhmiä',
+
+# user groups editing
+#
+'userrights-editusergroup' => 'Käyttäjän ryhmät',
+'saveusergroups' => 'Tallenna',
+'userrights-groupsmember' => 'Jäsenenä ryhmissä:',
+'userrights-groupsavailable' => 'Saatavilla olevat ryhmät:',
+'userrights-groupshelp' => 'Valitse ryhmät, jotka haluat poistaa tai lisätä. Valitsemattomia ryhmiä ei muuteta. Voit poistaa valinnan pitämällä Ctrl-näppäintä pohjassa napsautuksen aikana.',
+
+# Default group names and descriptions
+#
+'group-sysop-name'      => 'Ylläpitäjät',
+'group-sysop-desc'      => 'Luotetut käyttäjät voivat estää käyttäjiä ja poistaa ja suojata artikkeleita',
+'group-bureaucrat-name' => 'Byrokraatit',
+'group-bureaucrat-desc' => 'Byrokraatit voivat tehdä ylläpitäjiä',
+'group-bot-name'        => 'Botit',
+'group-bot-desc'        => '',
+
+# Recent changes
+#
+'changes'             => 'muutosta',
+'recentchanges'       => 'Tuoreet muutokset',
+'recentchangestext'   => 'Tällä sivulla voi seurata tuoreita {{GRAMMAR:illative|{{SITENAME}}}} tehtyjä muutoksia.',
+'rcloaderr'           => 'Ladataan tuoreita muutoksia',
+'rcnote'              => 'Alla on <b>$1</b> tuoreinta muutosta viimeisten <b>$2</b> päivän ajalta.',
+'rcnotefrom'          => 'Alla on muutokset <b>$2</b> lähtien. Enintään <b>$1</b> merkintää näytetään.',
+'rclistfrom'          => 'Näytä uudet muutokset $1 alkaen',
+'showhideminor'       => '$1 pienet muutokset | $2 botit | $3 kirjautuneet | $4 tarkastetut',
+'rclinks'             => 'Näytä $1 tuoretta muutosta viimeisten $2 päivän ajalta.<br />$3',
+'rchide'              => 'muodossa $4 ; $1 pientä muutosta; $2 toissijaista nimiavaruutta; $3 moninkertaista muutosta.',
+'rcliu'               => ' ; $1 muokkausta sisäänkirjautuneilta ',
+'diff'                => 'ero',
+'hist'                => 'historia',
+'hide'                => 'piilota',
+'show'                => 'näytä',
+'tableform'           => 'taulukko',
+'listform'            => 'luettelo',
+'nchanges'            => '$1 muutosta',
+'minoreditletter'     => 'p',
+'newpageletter'       => 'U',
+'sectionlink'         => '→',
+'number_of_watching_users_RCview'   => '[$1]',
+'number_of_watching_users_pageview' => '[$1 tarkkailevaa käyttäjää]', // TODO sigplu
+
+# Upload
+#
+'upload'              => 'Tallenna tiedosto',
+'uploadbtn'           => 'Tallenna tiedosto',
+'uploadlink'          => 'Tallenna kuvia',
+'reupload'            => 'Uusi tallennus',
+'reuploaddesc'        => 'Paluu tallennuslomakkeelle.',
+'uploadnologin'       => 'Et ole kirjautunut sisään',
+'uploadnologintext'   => 'Sinun pitää olla [[Special:Userlogin|kirjautuneena sisään]], jotta voisit tallentaa tiedostoja.',
+'upload_directory_read_only' => 'Palvelimella ei ole kirjoitusoikeuksia tallennushakemistoon "$1".',
+'uploaderror'         => 'Tallennusvirhe',
+'uploadtext'          => '\'\'\'SEIS!\'\'\' Ennen kuin tallennat tiedostoja {{GRAMMAR:illative|{{SITENAME}}}}, tutustu [[Project:Tiedostojen tallennus|sääntöihin]] ja noudata niitä.
+*\'\'Kirjoita tiedoston tietoihin tarkka tieto tiedoston lähteestä.\'\' Jos teit tiedoston itse, sano se. Jos löysit tiedoston Internetistä, varmista, että sitä saa käyttää {{GRAMMAR:inessive|{{SITENAME}}}} laita mukaan linkki kyseiselle sivulle.
+*\'\'Kerro tiedoston tekijänoikeuksien tila.\'\'
+*\'\'Käytä järkevää tiedostonimeä.\'\' Nimeä tiedostosi mieluummin tyyliin ”Eiffel-torni Pariisissa, yökuva.jpg” kuin ”etpan1024c.jpg”. Näin vältät mahdollisesti jo olemassa olevan tiedoston korvaamisen omallasi. Voit etsiä aikaisemmin tallennettuja tiedostoja [[Special:Imagelist|tiedostoluettelosta]].
+*Laita johonkin aiheeseen liittyvään sivuun linkki kyseiseen tiedostoon, tai kirjoita kuvaussivulle kuvaus tiedoston sisällöstä.
+*Jos haluat nähdä tai etsiä aiemmin tallennettuja tiedostoja, katso [[Special:Imagelist|tiedostoluettelo]]. Tallennukset ja poistot kirjataan [[Special:Log/upload|tallennuslokiin]].
+
+Suositellut kuvaformaatit ovat JPEG valokuville, PNG piirroksille ja kuvakkeille ja Ogg Vorbis äänille. Voit liittää kuvan sivulle käyttämällä seuraavan muotoista merkintää \'\'\'<nowiki>[[Kuva:tiedosto.jpg]]</nowiki>\'\'\' tai \'\'\'<nowiki>[[Kuva:tiedosto.png|kuvausteksti]]</nowiki>\'\'\' tai \'\'\'<nowiki>[[media:tiedosto.ogg]]</nowiki>\'\'\' äänille.
+
+Huomaa, että {{GRAMMAR:inessive|{{SITENAME}}}} muut voivat muokata tai poistaa tallentamasi tiedoston, jos he katsovat, että se ei palvele projektin tarpeita. Tallentamismahdollisuutesi voidaan estää, jos käytät järjestelmää väärin.',
+'uploadlog'           => 'Tallennusloki',
+'uploadlogpage'       => 'Tallennusloki',
+'uploadlogpagetext'   => 'Alla on luettelo uusimmista tallennuksista. Kaikki ajat näytetään palvelimen aikavyöhykkeessä (UTC).',
+'filename'            => 'Tiedoston nimi',
+'filedesc'            => 'Yhteenveto',
+'filestatus'          => 'Tiedoston tekijänoikeudet',
+'filesource'          => 'Lähde',
+'copyrightpage'       => 'Project:Tekijänoikeudet',
+'copyrightpagename'   => '{{SITENAME}} ja tekijänoikeudet',
+'uploadedfiles'       => 'Tallennetut tiedostot',
+'ignorewarning'       => 'Jätä tämä varoitus huomiotta, ja tallenna tiedosto.',
+'minlength'           => 'Tiedoston nimessä pitää olla vähintään kolme merkkiä.',
+'illegalfilename'     => 'Tiedoston nimessä \'\'\'$1\'\'\' on merkkejä, joita ei sallita sivujen nimissä. Vaihda tiedoston nimeä, ja yritä tallentamista uudelleen.',
+'badfilename'         => 'Tiedoston nimi vaihdettiin: $1.',
+'badfiletype'         => '".$1" ei ole suositeltava tiedostomuoto.',
+'largefile'           => 'Tiedostojen ei tulisi olla yli $1 kilotavun kokoisia. Tiedoston, jonka yritit tallentaa, koko on $2.',
+'emptyfile'           => 'Tiedosto, jonka yritit tallentaa näyttää olevan tyhjä. Tarkista, että kirjoitit polun ja nimen oikein ja että se ei ole liian suuri kohdepalvelimelle.',
+'fileexists'          => 'Samanniminen tiedosto on jo olemassa. Katso tiedoston sivu $1, jos et ole varma, haluatko muuttaa sitä.',
+'successfulupload'    => 'Tallennus onnistui',
+'fileuploaded'        => 'Tiedosto \'\'\'$1\'\'\' on tallennettu onnistuneesti. Seuraa linkkiä ($2) kuvaussivulle, ja täytä tiedostoon liityvät tiedot, kuten mistä se on peräisin, milloin se on luotu, kuka sen loi ja mahdollisesti muita tietämiäsi tietoja. Jos tiedosto on kuva, voit lisätä sen sivulle näin: \'\'\'<nowiki>[[Kuva:$1|thumb|Kuvaus]]</nowiki>\'\'\'',
+'uploadwarning'       => 'Tallennusvaroitus',
+'savefile'            => 'Tallenna',
+'uploadedimage'       => 'tallensi tiedoston [[$1]]',
+'uploaddisabled'      => 'Tiedostojen tallentaminen ei ole käytöstä.',
+'uploadscripted'      => 'Tämä tiedosto sisältää HTML-koodia tai skriptejä, jotka selain saattaa virheellisesti suorittaa.',
+'uploadcorrupt'       => 'Tiedosto on vioittunut tai sillä on väärä tiedostopääte. Tarkista tiedosto ja lähetä se uudelleen.',
+'uploadvirus'         => 'Tiedosto sisältää viruksen. Tarkemmat tiedot: $1',
+'sourcefilename'      => 'Lähdenimi',
+'destfilename'        => 'Kohdenimi',
+
+# Image list
+#
+'imagelist'           => 'Tiedostoluettelo',
+'imagelisttext'       => 'Alla on $1 tiedostoa lajiteltuna $2.',
+'getimagelist'        => 'noudetaan tiedostoluetteloa',
+'ilsubmit'            => 'Hae',
+'showlast'            => 'Näytä viimeiset $1 tiedostoa lajiteltuna $2.',
+'byname'              => 'nimen mukaan',
+'bydate'              => 'päiväyksen mukaan',
+'bysize'              => 'koon mukaan',
+'imgdelete'           => 'poista',
+'imgdesc'             => 'kuvaus',
+'imglegend'           => 'Merkinnät: (kuvaus) = näytä tai muokkaa tiedoston kuvausta.',
+'imghistory'          => 'Historia',
+'revertimg'           => 'palauta',
+'deleteimg'           => 'poista',
+'deleteimgcompletely' => 'poista',
+'imghistlegend'       => 'Merkinnät: (nyk.) = nykyinen versio, (poista) = poista tämä vanha versio, (palauta) = palauta tiedosto tähän vanhaan versioon.<br />Napsauta päiväystä nähdäksesi silloin tallennettu tiedosto.',
+'imagelinks'          => 'Viittaukset sivuilta',
+'linkstoimage'        => 'Seuraavilta sivuilta on linkki tähän tiedostoon:',
+'nolinkstoimage'      => 'Tähän tiedostoon ei ole linkkejä miltään sivulta.',
+'sharedupload'        => 'Tämä tiedosto on jaettu ja muut projektit saattavat käyttää sitä.',
+'shareduploadwiki'    => 'Katso [$1 kuvaussivulta] lisätietoja.',
+'noimage'             => 'Tämän nimistä tiedostoa ei ole olemassa. Voit [$1 tallentaa tiedoston] {{GRAMMAR:genitive|{{SITENAME}}}}',
+'uploadnewversion'    => '[$1 Tallenna] uusi versio tästä tiedostosta',
+
+# Statistics
+#
+'statistics'          => 'Tilastoja',
+'sitestats'           => 'Sivuston tilastoja',
+'userstats'           => 'Käyttäjätilastoja',
+'sitestatstext'       => 'Tietokannassa on yhteensä \'\'\'$1\'\'\' sivua. Tähän on laskettu mukaan keskustelusivut, {{GRAMMAR:genitive|{{SITENAME}}}} erikoissivut, hyvin lyhyet sivut, uudelleenohjaukset sekä muita sivuja, joita ei voi pitää kunnollisina sivuina. Nämä poislukien tietokannassa on \'\'\'$2\'\'\' sivua.<br />Sivuja on katsottu yhteensä \'\'\'$3\'\'\' kertaa ja muokattu \'\'\'$4\'\'\' kertaa. Keskimäärin yhtä sivua on muokattu \'\'\'$5\'\'\' kertaa, ja muokkausta kohden sivua on katsottu keskimäärin \'\'\'$6\'\'\' kertaa.',
+'userstatstext'       => 'Rekisteröityneitä käyttäjiä on \'\'\'$1\'\'\'. Näistä \'\'\'$2\'\'\' on ylläpitäjiä.<!-- $3 -->',
+
+# Maintenance Page
+#
+# NOTICE: Currently not used
+'maintenance'         => 'Ylläpitosivu',
+'maintnancepagetext'  => 'Tämä sivu sisältää useita käteviä työkaluja jokapäiväistä ylläpitoa varten. Jotkut näistä toiminnoista kuormittavat tietokantaa, joten ole hyvä äläkä paina päivitysnappia jokaisessa kohdassa ;-)',
+'maintenancebacklink' => 'Takaisin ylläpitosivulle',
+'disambiguations'     => 'Linkit tarkennusivuihin',
+'disambiguationspage' => 'Project:Linkkejä_tarkennussivuihin',
+'disambiguationstext' => 'Seuraavat artikkelit linkittävät <i>tarkennussivuun</i>. Sen sijasta niiden pitäisi linkittää asianomaiseen aiheeseen.<br />Sivua kohdellaan tarkennussivuna jos siihen on linkki sivulta $1.<br />Linkkejä muihin nimiavaruuksiin <i>ei</i> ole listattu tässä.',
+'doubleredirects'     => 'Kaksinkertaiset uudelleenohjaukset',
+'doubleredirectstext' => '<b>Huomio:</b> Tässä listassa saattaa olla virheitä. Yleensä kyseessä on sivu, jossa ensimmäisen #REDIRECTin jälkeen on tekstiä.<br />\nJokaisella rivillä on linkit ensimmäiseen ja toiseen uudelleenohjaukseen sekä toisen uudelleenohjauksen kohteen ensimmäiseen riviin, eli yleensä \'oikeaan\' kohteeseen, johon ensimmäisen uudelleenohjauksen pitäisi osoittaa.',
+'brokenredirects'     => 'Virheelliset uudelleenohjaukset',
+'brokenredirectstext' => 'Seuraavat uudelleenohjaukset on linkitetty artikkeleihin, joita ei ole olemassa.',
+'selflinks'           => 'Sivut, jotka linkittävät itseensä',
+'selflinkstext'       => 'Seuraavat sivut sisältävät linkkejä itseensä.',
+'mispeelings'         => 'Kirjoitusvirheitä sisältävät sivut',
+'mispeelingstext'     => 'Seuraavat sivut sisältävät yleisen kirjoitusvirheen, joka on lueteltu sivulla $1. Oikea kirjoitustapa on ehkä annettu (tähän tapaan).',
+'mispeelingspage'     => 'Lista tavallisimmista kirjoitusvirheistä',
+'missinglanguagelinks'=> 'Puuttuvat kielilinkit',
+'missinglanguagelinksbutton'  => 'Etsi puuttuvat kielilinkit',
+'missinglanguagelinkstext'    => 'Näitä artikkeleita <i>ei</i> ole linkitetty vastineeseensa $1:ssä. Uudelleenohjauksia ja alasivuja <i>ei</i> ole näytetty.', // suks
+
+# Miscellaneous special pages
+#
+'orphans'             => 'Orposivut',
+'geo'                 => 'GEO-koordinaatit',
+'validate'            => 'Kelpuuta sivu',
+'lonelypages'         => 'Yksinäiset sivut',
+'uncategorizedpages'  => 'Luokittelemattomat sivut',
+'uncategorizedcategories' => 'Luokittelemattomat luokat',
+'unusedcategories'    => 'Käyttämättömät luokat',
+'unusedimages'        => 'Käyttämättömät tiedostot',
+'popularpages'        => 'Suositut sivut',
+'nviews'              => '$1 latausta',
+'wantedpages'         => 'Halutut sivut',
+'nlinks'              => '$1 linkkiä',
+'allpages'            => 'Kaikki sivut',
+'randompage'          => 'Satunnainen sivu',
+'shortpages'          => 'Lyhyet sivut',
+'longpages'           => 'Pitkät sivut',
+'deadendpages'        => 'Sivut, joilla ei ole linkkejä',
+'listusers'           => 'Käyttäjälista',
+'specialpages'        => 'Toimintosivut',
+'spheading'           => 'Toimintosivut',
+'restrictedpheading'  => 'Rajoitetut toimintosivut',
+'protectpage'         => 'Suojaa sivu',
+'recentchangeslinked' => 'Linkitettyjen sivujen muutokset',
+'rclsub'              => 'Sivut, joihin linkki sivulta $1',
+'debug'               => 'Virheenetsintä',
+'newpages'            => 'Uudet sivut',
+'ancientpages'        => 'Kauan muokkaamattomat sivut',
+'intl'                => 'Kieltenväliset linkit',
+'move'                => 'Siirrä',
+'movethispage'        => 'Siirrä tämä sivu',
+'unusedimagestext'    => 'Huomaa, että muut verkkosivut saattavat viitata tiedostoon suoran URL:n avulla, jolloin tiedosto saattaa olla tässä listassa, vaikka sitä käytetäänkin.',
+'unusedcategoriestext'=> 'Nämä luokat ovat olemassa, mutta niitä ei käytetä.',
+'booksources'         => 'Kirjalähteet',
+'categoriespagetext'  => '{{GRAMMAR:inessive|{{SITENAME}}}} on seuraavat luokat:',
+'data'                => 'Data', // TODO: CHECK ME
+'userrights'          => 'Käyttöoikeuksien hallinta',
+'groups'              => 'Ryhmät',
+'booksourcetext'      => 'Alla on lista linkeistä ulkopuolisiin sivustoihin, joilla myydään uusia ja käytettyjä kirjoja. Niillä voi myös olla lisätietoa kirjoista, joita etsit. {{SITENAME}} ei liity mitenkään näihin sivustoihin, eikä tätä listaa tule pitää suosituksena tai hyväksyntänä.',
+'isbn'                => 'ISBN',
+
+# No reason to overwrite
+//  'rfcurl'              => 'http://www.faqs.org/rfcs/rfc$1.html',
+'alphaindexline'      => 'Alkaen sivusta $1 päättyen sivuun $2',
+'version'             => 'Versio',
+'log'                 => 'Lokit',
+'alllogstext'         => 'Yhdistetty tallennus-, poisto-, suojaus-, esto- ja ylläpitolokien näyttö. Voit rajoittaa listaa valitsemalla lokityypin, käyttäjän tai sivun johon muutos on kohdistunut.',
+
+# Special:Allpages
+'nextpage'            => 'Seuraava sivu ($1)',
+'allpagesfrom'        => 'Näytä sivuja lähtien sivusta:',
+'allarticles'         => 'Kaikki sivut',
+'allnonarticles'      => 'Kaikki sivut, jotka eivät ole oletusnimiavaruudessa',
+'allinnamespace'      => 'Kaikki sivut nimiavaruudessa $1',
+'allnotinnamespace'   => 'Kaikki sivut, jotka eivät ole nimiavaruudessa $1',
+'allpagesprev'        => 'Edellinen',
+'allpagesnext'        => 'Seuraava',
+'allpagessubmit'      => 'Vaihda',
+
+# Email this user
+#
+'mailnologin'         => 'Lähettäjän osoite puuttuu',
+'mailnologintext'     => 'Sinun pitää olla [[Special:Userlogin|kirjautuneena sisään]] ja [[Special:Preferences|asetuksissasi]] pitää olla toimiva sähköpostiosoite jotta voit lähettää sähköpostia muille käyttäjille.',
+'emailuser'           => 'Lähetä sähköpostia tälle käyttäjälle',
+'emailpage'           => 'Lähetä sähköpostia käyttäjälle',
+'emailpagetext'       => 'Jos tämä käyttäjä on antanut asetuksissaan kelvollisen sähköpostiosoitteen, alla olevalla lomakeella voi lähettää yhden viestin hänelle. Omissa asetuksissasi annettu sähköpostiosoite näkyy sähköpostin lähettäjän osoitteena, jotta vastaanottaja voi vastata viestiin.',
+'usermailererror'     => 'Postitus palautti virheen: ',
+'defemailsubject'     => '{{SITENAME}}-sähköposti',
+'noemailtitle'        => 'Ei sähköpostiosoitetta',
+'noemailtext'         => 'Tämä käyttäjä ei ole määritellyt kelpoa sähköpostiosoitetta tai ei halua postia muilta käyttäjiltä.',
+'emailfrom'           => 'Lähettäjä',
+'emailto'             => 'Vastaanottaja',
+'emailsubject'        => 'Aihe',
+'emailmessage'        => 'Viesti',
+'emailsend'           => 'Lähetä',
+'emailsent'           => 'Sähköposti lähetetty',
+'emailsenttext'       => 'Sähköpostiviestisi on lähetetty.',
+
+# Watchlist
+#
+'watchlist'           => 'Tarkkailulista',
+'watchlistsub'        => 'Käyttäjälle $1',
+'nowatchlist'         => 'Tarkkailulistallasi ei ole sivuja.',
+'watchnologin'        => 'Et ole kirjautunut sisään',
+'watchnologintext'    => 'Sinun pitää kirjautua sisään, jotta voisit käyttää tarkkailulistaa.',
+'addedwatch'          => 'Lisätty tarkkailulistalle',
+'addedwatchtext'      => 'Sivu \'\'\'$1\'\'\' on lisätty [[Special:Watchlist|tarkkailulistallesi]]. Tulevaisuudessa sivuun ja sen keskustelusivuun tehtävät muutokset listataan täällä. Sivu on \'\'\'lihavoitu\'\'\' [[Special:Recentchanges|tuoreiden muutosten listassa]], jotta huomaisit sen helpommin. Jos haluat myöhemmin poistaa sivun tarkkailulistaltasi, napsauta linkkiä \'\'lopeta tarkkailu\'\' sivun reunassa.',
+'removedwatch'        => 'Poistettu tarkkailulistalta',
+'removedwatchtext'    => 'Sivu \'\'\'$1\'\'\' on poistettu tarkkailulistaltasi.',
+'watch'               => 'Tarkkaile',
+'watchthispage'       => 'Tarkkaile tätä sivua',
+'unwatch'             => 'Lopeta tarkkailu',
+'unwatchthispage'     => 'Lopeta tarkkailu',
+'notanarticle'        => 'Ei ole sivu',
+'watchnochange'       => 'Valittuna ajanjaksona yhtäkään tarkkailemistasi sivuista ei muokattu.',
+'watchdetails'        => 'Keskustelusivuja mukaan laskematta tarkkailun alla on $1 sivua, joista $2 on muokattu määritellyllä aikavälillä. <span class="plainlinks"> [$4 Muokkaa listaa]</span>.',
+'wlheader-enotif'     => '* Sähköposti-ilmoitukset ovat käytössä.',
+'wlheader-showupdated'=> '* Sivut, joita on muokattu viimeisen käyntisi jälkeen on merkitty \'\'\'paksummalla\'\'\'',
+'watchmethod-recent'  => 'tarkistetaan tuoreimpia muutoksia tarkkailluille sivuille',
+'watchmethod-list'    => 'tarkistetaan tarkkailtujen sivujen tuoreimmat muutokset',
+'removechecked'       => 'Poista valitut sivut tarkkailulistalta',
+'watchlistcontains'   => 'Tarkkailulistallasi on $1 sivua.',
+'watcheditlist'       => 'Tässä on aakkostettu lista tarkkailemistasi sivuista. Merkitse niiden sivujen ruudut, jotka haluat poistaa tarkkailulistaltasi.',
+'removingchecked'     => 'Merkityt sivut poistettiin tarkkailulistalta.',
+'couldntremove'       => 'Sivua $1 ei voitu poistaa tarkkailulistalta',
+'iteminvalidname'     => 'Sivun $1 kanssa oli ongelmia! Sivun nimessä on vikaa.',
+'wlnote'              => 'Alla on <b>$1</b> muutosta viimeisen <b>$2</b> tunnin ajalta.', // TODO NOWIKIMARKUP
+'wlshowlast'          => 'Näytä viimeiset $1 tuntia tai $2 päivää$3',
+'wlsaved'             => 'Tämä on tallennettu versio tarkkailulistastasi.',
+'wlhideshowown'       => '$1 omat muokkaukset.',
+'wlshow'              => 'Näytä',
+'wlhide'              => 'Piilota',
+
+'enotif_mailer'       => '{{GRAMMAR:genitive|{{SITENAME}}}} sivu on muuttunut -ilmoitus',
+'enotif_reset'        => 'Merkitse kaikki sivut katsotuiksi',
+'enotif_newpagetext'  => 'Tämä on uusi sivu.',
+'changed'             => 'muuttanut sivua',
+'created'             => 'luonut sivun',
+'enotif_subject'      => '$PAGEEDITOR on $CHANGEDORCREATED $PAGETITLE',
+'enotif_lastvisited'  => 'Osoitteessa $1 on kaikki muutokset viimeisen käyntisi jälkeen.',
+'enotif_body'         => 'Käyttäjä $WATCHINGUSERNAME,
+
+{{GRAMMAR:genitive|{{SITENAME}}}} käyttäjä $PAGEEDITOR on $CHANGEDORCREATED $PAGETITLE $PAGEEDITDATE. Nykyinen versio on osoitteessa $PAGETITLE_URL .
+
+$NEWPAGE
+
+Muokkaajan yhteenveto: $PAGESUMMARY $PAGEMINOREDIT
+
+Ota yhteyttä muokkaajaan:
+sähköposti: $PAGEEDITOR_EMAIL
+wiki: $PAGEEDITOR_WIKI
+
+Uusia ilmoituksia tästä sivusta ei tule kunnes vierailet sivulla. Voit myös nollata ilmoitukset kaikille tarkkailemillesi sivuille tarkkailulistallasi.
+
+             {{GRAMMAR:genitive|{{SITENAME}}}} ilmoitusjärjestelmä
+
+--
+Tarkkailulistan asetuksia voit muuttaa osoitteessa:
+{{SERVER}}{{localurl:Special:Watchlist/edit}}
+
+Palaute ja lisäapu osoitteessa:
+{{SERVER}}{{localurl:Help:Sähköposti-ilmoitus}}',
+
+
+# Delete/protect/revert
+#
+'deletepage'          => 'Poista sivu',
+'confirm'             => 'Toteuta',
+'excontent'           => 'sisälsi: \'$1 \'',
+'excontentauthor'     => 'sisälsi: \'$1\' (ainoa muokkaaja oli $2)',
+'exbeforeblank'       => 'ennen tyhjentämistä sisälsi: \'$1\'',
+'exblank'             => 'oli tyhjä',
+'confirmdelete'       => 'Vahvista poisto',
+'deletesub'           => 'Sivun $1 poisto',
+'historywarning'      => 'Varoitus: Sivulla, jonka aiot poistaa on muokkaushistoria: ',
+'confirmdeletetext'   => 'Olet tuhomassa sivun tai tiedoston ja kaiken sen historian tietokannasta. Ymmärrä teon seuraukset ja tee poisto {{GRAMMAR:genitive|{{SITENAME}}}} käytännön mukaisesti.',
+'actioncomplete'      => 'Toiminto suoritettu',
+'deletedtext'         => '\'\'\'$1\'\'\' on poistettu. Katso $2 nähdäksesi tallenteen viimeaikaisista poistoista.',
+'deletedarticle'      => 'poisti sivun $1',
+'dellogpage'          => 'Poistoloki',
+'dellogpagetext'      => 'Alla on loki viimeisimmistä poistoista.',
+'deletionlog'         => 'poistoloki',
+'reverted'            => 'Palautettu aikaisempaan versioon',
+'deletecomment'       => 'Poistamisen syy',
+'imagereverted'       => 'Aikaisempaan versioon palauttaminen onnistui.',
+'rollback'            => 'palauta aiempaan versioon',
+'rollback_short'      => 'Palautus',
+'rollbacklink'        => 'palauta',
+'rollbackfailed'      => 'Palautus epäonnistui',
+'cantrollback'        => 'Aiempaan versioon ei voi palauttaa; viimeisin kirjoittaja on sivun ainoa tekijä.',
+'alreadyrolled'       => 'Käyttäjän [[User:$2|$2]] ([[User_talk:$2|keskustelu]]) tekemiä muutoksia sivuun $1 ei voi palauttaa. Käyttäjä [[User:$3|$3]] ([[User_talk:$3|keskustelu]]) on tehnyt uudempia muutoksia.',
+'editcomment'         => 'Muokkauksen yhteenveto oli: <i>$1</i>.', // TODO NOWIKIMARKUP
+'revertpage'          => 'Käyttäjän [[Special:Contributions/$2|$2]] ([[User_talk:$2|keskustelu]]) muokkaukset palautettiin viimeisimpään käyttäjän $1 tekemään muutokseen.',
+
+'sessionfailure'      => 'Istuntosi kanssa on ongelma. Muutosta ei toteutettu varotoimena sessionkaappauksien takia. Käytä selaimen paluutoimintoa ja päivitä sivu, jolta tulit, ja koita uudelleen.',
+'protectlogpage'      => 'Suojausloki',
+'protectlogtext'      => 'Alla loki sivujen suojauksista ja suojauksien poistoista.',
+'protectedarticle'    => 'suojasi sivun $1',
+'unprotectedarticle'  => 'poisti suojauksen sivulta $1',
+'protectsub'          => 'Sivun $1 suojaus',
+'confirmprotecttext'  => 'Haluatko varmasti suojata tämän sivun?',
+'confirmprotect'      => 'Vahvista suojaus',
+'protectmoveonly'     => 'Suojaa vain siirroilta',
+'protectcomment'      => 'Suojauksen syy',
+'unprotectsub'        => 'Suojauksen poisto sivulta $1',
+'confirmunprotecttext'=> 'Haluatko varmasti poistaa tämän sivun suojauksen?',
+'confirmunprotect'    => 'Vahvista suojauksen poisto',
+'unprotectcomment'    => 'Syy suojauksen poistoon',
+
+# Undelete
+'undelete'            => 'Palauta poistettu sivu',
+'undelete_short'      => 'Palauta $1 muokkausta',
+'undeletepage'        => 'Selaa ja palauta poistettuja sivuja',
+'undeletepagetext'    => 'Seuraavat sivut on poistettu, mutta ne löytyvät vielä arkistosta, joten ne ovat palautettavissa. Arkisto saatetaan tyhjentää aika ajoin.',
+'undeletearticle'     => 'Palauta poistettu sivu',
+'undeleterevisions'   => '$1 versiota arkistoitu.',
+'undeletehistory'     => 'Jos palautat sivun, kaikki versiot lisätään sivun historiaan. Jos uusi sivu samalla nimellä on luotu poistamisen jälkeen, palautetut versiot lisätään sen historiaan, ja olemassa olevaa versiota ei korvata automaattisesti.',
+'undeleterevision'    => 'Poistettu versio hetkellä $1',
+'undeletebtn'         => 'Palauta!',
+'undeletedarticle'    => 'palautti sivun $1',
+'undeletedrevisions'  => '$1 versiota palautettiin',
+'undeletedtext'       => 'Sivu [[$1]] on palautettu onnistuneesti. Lista viimeisimmistä poistoista ja palautuksista on [[Special:Log/delete|poistolokissa]].',
+
+'namespace'           => 'Nimiavaruus',
+'invert'              => 'Käännä nimiavaruusvalinta päinvastaiseksi',
+
+# Contributions
+#
+'contributions'       => 'Käyttäjän muokkaukset',
+'mycontris'           => 'Omat muokkaukset',
+'contribsub'          => 'Käyttäjän $1 muokkaukset',
+'nocontribs'          => 'Näihin ehtoihin sopivia muokkauksia ei löytynyt.',
+'ucnote'              => 'Alla on \'\'\'$1\'\'\' viimeisintä tämän käyttäjän tekemää muokkausta viimeisten \'\'\'$2\'\'\' päivän aikana.',
+'uclinks'             => 'Katso $1 viimeisintä muokkausta; katso $2 viimeisintä päivää.',
+'uctop'               => ' (uusin)' ,
+'newbies'             => 'tulokkaat',
+
+# What links here
+#
+'whatlinkshere'       => 'Tänne viittaavat sivut',
+'notargettitle'       => 'Ei kohdetta',
+'notargettext'        => 'Et ole määritellyt kohdesivua tai -käyttäjää johon toiminto kohdistuu.',
+'linklistsub'         => 'Lista linkeistä',
+'linkshere'           => 'Seuraavilta sivuilta on linkki tälle sivulle:',
+'nolinkshere'         => 'Tänne ei ole linkkejä.',
+'isredirect'          => 'uudelleenohjaussivu',
+
+# Block/unblock IP
+#
+'blockip'             => 'Aseta muokkausesto',
+'blockiptext'         => 'Tällä lomakkeella voit estää käyttäjän tai IP-osoitteen muokkausoikeudet. Muokkausoikeuksien poistamiseen pitää olla syy, esimerkiksi sivujen vandalisointi. Kirjoita syy siihen varattuun kenttään.<br />Vanhenemisajat noudattavat GNUn standardimuotoa, joka on kuvattu tar-manuaalissa ([http://www.gnu.org/software/tar/manual/html_chapter/tar_7.html] [EN]), esimerkiksi ”1 hour”, ”2 days”, ”next Wednesday”, 2005-08-29”. Esto voi olla myös ”indefinite” tai ”infinite”, joka kestää kunnes se poistetaan.',
+'ipaddress'           => 'IP-osoite', // TODO bug
+'ipadressorusername'  => 'IP-osoite tai käyttäjätunnus',
+'ipbexpiry'           => 'Umpeutuu',
+'ipbreason'           => 'Syy',
+'ipbsubmit'           => 'Estä',
+'ipbother'            => 'Vapaamuotoinen kesto',
+'ipboptions'          => '2 tuntia:2 hours,1 päivä:1 day,3 päivää:3 days,1 viikko:1 week,2 viikkoa:2 weeks,1 kuukausi:1 month,3 kuukautta:3 months,6 kuukautta:6 months,1 vuosi:1 year,ikuisesti:infinite',
+'ipbotheroption'      => 'Muu kesto',
+'badipaddress'        => 'IP-osoite on väärin muotoiltu.',
+'blockipsuccesssub'   => 'Esto onnistui',
+'blockipsuccesstext'  => 'Käyttäjä tai IP-osoite \'\'\'$1\'\'\' on estetty.<br />Nykyiset estot löytyvät [[Special:Ipblocklist|estolistalta]].',
+'unblockip'           => 'Muokkauseston poisto',
+'unblockiptext'       => 'Tällä lomakkeella voit poistaa käyttäjän tai IP-osoitteen muokkauseston.',
+'ipusubmit'           => 'Poista esto',
+'ipusuccess'          => 'IP-osoitteen tai käyttäjän <b>$1</b> esto poistettu', // TODO NOWIKIMARKUP
+'ipblocklist'         => 'Lista estetyistä IP-osoitteista',
+'ipblocklistempty'    => 'Estolista on tyhjä.',
+'blocklistline'       => '$1 — $2 on estänyt käyttäjän $3 ($4)',
+'infiniteblock'       => 'ikuisesti',
+'expiringblock'       => 'vanhenee $1',
+'blocklink'           => 'esto',
+'unblocklink'         => 'poista esto',
+'contribslink'        => 'muokkaukset',
+'autoblocker'         => 'Olet automaattisesti estetty, koska jaat IP-osoitteen käyttäjän $1 kanssa. Eston syy: $2.', // TODO: IS WIKIMARKUP?
+'blocklogpage'        => 'Estoloki',
+'blocklogentry'       => 'esti käyttäjän tai IP-osoitteen $1. Eston kesto: $2',
+'blocklogtext'        => 'Tässä on loki muokkausestoista ja niiden purkamisista. Automaattisesti estettyjä IP-osoitteita ei kirjata. Tutustu [[Special:Ipblocklist|estolistaan]] nähdäksesi listan tällä hetkellä voimassa olevista estoista.',
+'unblocklogentry'     => 'poisti käyttäjältä $1 muokkauseston',
+'range_block_disabled'=> 'Ylläpitäjän oikeis luoda alue-estoja ei ole käytöstä.',
+'ipb_expiry_invalid'  => 'Virheellinen umpeutumisaika.',
+'ip_range_invalid'    => 'Virheellinen IP-alue.',
+'proxyblocker'        => 'Välityspalvelinesto',
+'proxyblockreason'    => 'IP-osoitteestasi on estetty muokkaukset, koska se on avoin välityspalvelin. Ota yhteyttä Internet-palveluntarjoajaasi tai tekniseen tukeen ja kerro heillä tästä tietoturvaongelmasta.',
+'proxyblocksuccess'   => 'Valmis.',
+'sorbs'               => 'SORBS DNSBL',
+'sorbsreason'         => 'IP-osoitteesti on listattu avoimena välityspalvelimena [http://www.sorbs.net SORBSin] mustalla listalla.',
+
+# Developer tools
+#
+'lockdb'              => 'Lukitse tietokanta',
+'unlockdb'            => 'Vapauta tietokanta',
+'lockdbtext'          => 'Tietokannan lukitseminen estää käyttäjiä muokkaamasta sivuja, vaihtamasta asetuksia, muokkaamasta tarkkailulistoja ja tekemästä muita tietokannan muuttamista vaativia toimia. Ole hyvä ja vahvista, että tämä on tarkoituksesi, ja että vapautat tietokannan kun olet suorittanut ylläpitotehtävät.',
+'unlockdbtext'        => 'Tietokannan vapauttaminen antaa käyttäjille mahdollisuuden muokkata sivuja, vaihtamaa asetuksia, muokkata tarkkailulistoja ja tehdä muita tietokannan muuttamista vaativia toimia. Ole hyvä ja vahvista, että tämä on tarkoituksesi.',
+'lockconfirm'         => 'Kyllä, haluan varmasti lukita tietokannan.',
+'unlockconfirm'       => 'Kyllä, haluan varmasti vapauttaa tietokannan.',
+'lockbtn'             => 'Lukitse tietokanta',
+'unlockbtn'           => 'Vapauta tietokanta',
+'locknoconfirm'       => 'Et merkinnyt vahvistuslaatikkoa.',
+'lockdbsuccesssub'    => 'Tietokannan lukitseminen onnistui',
+'unlockdbsuccesssub'  => 'Tietokannan vapauttaminen onnistui',
+'lockdbsuccesstext'   => 'Tietokanta on lukittu.<br />Muista vapauttaa tietokanta ylläpitotoimenpiteiden jälkeen.',
+'unlockdbsuccesstext' => 'Tietokanta on vapautettu.',
+
+# Make sysop
+'makesysoptitle'      => 'Tee käyttäjästä ylläpitäjä',
+'makesysoptext'       => 'Byrokraatit voivat tällä lomakkeella tehdä käyttäjistä ylläpitäjiä ja byrokraatteja. Kirjoita laatikkoon sen käyttäjän nimi, jolle haluat antaa oikeuksia.',
+'makesysopname'       => 'Käyttäjän nimi:',
+'makesysopsubmit'     => 'Tee käyttäjästä ylläpitäjä',
+'makesysopok'         => 'Käyttäjä <b>$1</b> on nyt ylläpitäjä.',
+'makesysopfail'       => 'Käyttäjästä <b>$1</b> ei voitu tehdä ylläpitäjää. Kirjoititko nimen oikein?', // TODO: NOWIKIMARKUP
+'setbureaucratflag'   => 'Tee käyttäjästä myös byrokraatti',
+'bureaucratlog'       => 'Byrokraattiloki',
+'rightslogtext'       => 'Alla on loki on käyttäjien käyttöoikeuksien muutoksista.',
+'bureaucratlogentry'  => 'Käyttäjän [[$1|]] sai oikeudet$3', // TODO: Inflect me
+'rights'              => 'Oikeudet:',
+'set_user_rights'     => 'Aseta käyttäjän oikeudet',
+'user_rights_set'     => 'Käyttäjän <b>$1</b> oikeudet päivitetty.',
+'set_rights_fail'     => 'Käyttäjän <b>$1</b> oikeuksia ei voita asettaa. Kirjoititko nimen oikein?',
+'makesysop'           => 'Tee käyttäjästä ylläpitäjä',
+'already_sysop'       => 'Käyttäjä on jo ylläpitäjä',
+'already_bureaucrat'  => 'Käyttäjä on jo byrokraatti',
+'already_steward'     => 'Käyttäjä on jo ylivalvoja',
+
+
+# Validation
+# Let this mature a bit
+
+# Move page
+#
+'movepage'            => 'Siirrä sivu',
+'movepagetext'        => 'Alla olevalla lomakkeella voit nimetä uudelleen sivuja, jolloin niiden koko historia siirtyy uuden nimen alle. Vanhasta sivusta tulee uudelleenohjaussivu, joka osoittaa uuteen sivuun. Vanhaan sivuun suunnattuja linkkejä ei muuteta, muista tehdä tarkistukset kaksinkertaisten tai rikkinäisten uudellenohjausten varalta. Olet vastuussa siitä, että linkit osoittavat sinne, mihin niiden on tarkoituskin osoittaa.
+
+Huomaa, että sivua \'\'\'ei\'\'\' siirretä mikäli uusi otsikko on olemassaolevan sivun käytössä, paitsi milloin kyseessä on tyhjä sivu tai uudelleenohjaus, jolla ei ole muokkaushistoriaa. Tämä tarkoittaa sitä, että voit siirtää sivun takaisin vanhalle nimelleen mikäli teit virheen, mutta et voi kirjoittaa olemassa olevan sivun päälle. Jos sivu tarvitsee siirtää olemassa olevan sivun päälle, ota yhteyttä [[Special:Listusers|ylläpitäjään]].
+
+\'\'\'HUOMIO!\'\'\'
+Saatat olla tekemässä huomattavaa ja odottamatonta muutosta suositulle sivulle. Ole varma, että ymmärrät seuraukset ennen kuin jatkat.',
+'movepagetalktext'    => 'Sivuun mahdollisesti kytketty keskustelusivu siirretään automaattisesti, \'\'\'paitsi jos\'\'\':
+*Siirrät sivua nimiavaruudesta toiseen
+*Kohdesivulla on olemassa keskustelusivu, joka ei ole tyhjä, tai
+*Kumoat allaolevan ruudun asetuksen.
+
+Näissä tapauksissa sivut täytyy siirtää tai yhdistää käsin.',
+'movearticle'         => 'Siirrä sivu',
+'movenologin'         => 'Et ole kirjautunut sisään',
+'movenologintext'     => 'Sinun pitää olla rekisteröitynyt käyttäjä ja kirjautua sisään, jotta voisit siirtää sivun.',
+'newtitle'            => 'Uusi nimi sivulle',
+'movepagebtn'         => 'Siirrä sivu',
+'pagemovedsub'        => 'Siirto onnistui',
+'pagemovedtext'       => 'Sivu \'\'\'[[$1]]\'\'\' siirrettiin nimelle \'\'\'[[$2]]\'\'\'.',
+'articleexists'       => 'Kohdesivu on jo olemassa, tai valittu nimi ei ole sopiva. Ole hyvä ja valitse uusi nimi.',
+'talkexists'          => 'Sivun siirto onnistui, mutta keskustelusivua ei voitu siirtää, koska uuden otsikon alla on jo keskustelusivu. Ole hyvä ja yhdistä keskustelusivujen sisältö käsin.',
+'movedto'             => 'Siirretty uudelle otsikolle',
+'movetalk'            => 'Siirrä myös keskustelusivu, jos mahdollista.',
+'talkpagemoved'       => 'Myös sivun keskustelusivu siirrettiin.',
+'talkpagenotmoved'    => 'Sivun keskustelusivua \'\'\'ei\'\'\' siirretty.',
+'1movedto2'           => 'siirsi sivun $1 uudelle nimelle $2',
+'1movedto2_redir'     => 'siirsi sivun $1 uudelleenohjauksen $2 päälle',
+'movelogpage'         => 'Siirtoloki',
+'movelogpagetext'     => 'Anna on loki siirretyistä sivuista.',
+'movereason'          => 'Syy',
+'revertmove'          => 'kumoa',
+'delete_and_move'     => 'Poista kohdesivu ja siirrä',
+'delete_and_move_text'   => 'Kohdesivu [[$1]] on jo olemassa. Haluatko poistaa sen, jotta nykyinen sivu voitaisiin siirtää?',
+'delete_and_move_reason' => 'Sivu on siirron tiellä.',
+'selfmove'            => 'Lähde- ja kohdenimi ovat samat.',
+'immobile_namespace'  => 'Sivuja ei voi siirtää tähän nimiavaruuteen.',
+
+# Export
+
+'export'              => 'Sivujen vienti',
+'exporttext'          => 'Voit viedä sivun tai sivujen tekstiä ja muokkaushistoriaa XML-muodossa. Tulevaisuudessa tämä tieto voidaan tuoda johonkin toiseen wikiin, jossa käytetään MediaWiki-ohjelmistoa. Nykyisessä MediaWikin versiossa tätä ei tosin vielä tueta.
+
+Syötä sivujen otsikoita riveittäin alla olevaan laatikkoon. Valitse myös, haluatko kaikki versiot sivuista, vai ainoastaan nykyisen version.
+
+Jälkimmäisessä tapauksessa voit myös käyttää linkkiä. Esimerkiksi [[Juna]]sivun saa vietyä linkistä [[Special:Export/Juna]].',
+'exportcuronly'       => 'Liitä mukaan ainoastaan uusin versio, ei koko historiaa.',
+
+# Namespace 8 related
+
+'allmessages'         => 'Kaikki järjestelmäviestit',
+'allmessagesname'     => 'Nimi',
+'allmessagesdefault'  => 'Oletusarvo',
+'allmessagescurrent'  => 'Nykyinen arvo',
+'allmessagestext'     => 'Tämä on luettelo kaikista MediaWiki-nimiavaruudessa olevista viesteistä.',
+'allmessagesnotsupportedUI' => 'Special:Allmessages-sivu ei tue täällä käyttöliittymäkieltäsi <b>$1</b>.',
+'allmessagesnotsupportedDB' => 'Special:AllMessages-sivu ei ole käytössä, koska wgUseDatabaseMessages-asetus on pois päältä.',
+
+# Thumbnails
+
+'thumbnail-more'      => 'Suurenna',
+'missingimage'        => '<b>Puuttuva kuva</b><br /><i>$1</i>',
+'filemissing'         => 'Tiedosto puuttuu',
+
+# Special:Import
+'import'            => 'Tuo sivuja',
+'importinterwiki'   => 'Tuo sivuja lähiwikeistä',
+'importtext'        => 'Vie sivuja lähdewikistä käyttäen Special:Export-työkalua. Tallenna tiedot koneellesi ja tallenna ne täällä.',
+'importfailed'      => 'Tuonti epäonnistui: $1',
+'importnotext'      => 'Tyhjä tai ei tekstiä',
+'importsuccess'     => 'Tuonti onnistui!',
+'importhistoryconflict' => 'Sivusta on olemassa tuonnin kanssa ristiriitainen muokkausversio. Tämä sivu on saatettu tuoda jo aikaisemmin.',
+'importnosources'   => 'Wikienvälisiä tuontilähteitä ei ole määritelty ja suorat historiatallennukset on poistettu käytöstä.',
+
+# Keyboard access keys for power users
+'accesskey-search'    => 'f',
+'accesskey-minoredit' => 'i',
+'accesskey-save'      => 's',
+'accesskey-preview'   => 'p',
+'accesskey-diff'      => 'd',
+'accesskey-compareselectedversions' => 'v',
+
+# tooltip help for some actions, most are in Monobook.js
+'tooltip-search'      => 'Etsi {{GRAMMAR:elative|{{SITENAME}}}} [alt-f]',
+'tooltip-minoredit'   => 'Merkitse tämä pieneksi muutokseksi [alt-i]',
+'tooltip-save'        => 'Tallenna muokkaukset [alt-s]',
+'tooltip-preview'     => 'Esikatsele muokkausta ennen tallennusta [alt-p]',
+'tooltip-diff'        => 'Näytä tehdyt muutokset [alt-d]',
+'tooltip-compareselectedversions' => 'Vertaile valittuja versioita [alt-v]',
+'tooltip-watch'       => 'Lisää tämä sivu tarkkailulistaan [alt-w]',
+
+# Metadata
+'nodublincore'        => 'Dublin Core RDF-metatieto on poissa käytöstä tällä palvelimella.',
+'nocreativecommons'   => 'Creative Commonsin RDF-metatieto on poissa käytöstä tällä palvelimella.',
+'notacceptable'       => 'Wikipalvelin ei voi näyttää tietoja muodossa, jota ohjelmasi voisi lukea.',
+
+# Attribution
+
+'anonymous'           => '{{GRAMMAR:genitive|{{SITENAME}}}} anonyymit käyttäjät',
+'siteuser'            => '{{GRAMMAR:genitive|{{SITENAME}}}} käyttäjä $1',
+'lastmodifiedby'      => 'Tätä sivua muokkasi viimeksi $2, $1.',
+'and'                 => 'ja',
+'othercontribs'       => 'Perustuu työlle, jonka teki $1.',
+'others'              => 'muut',
+'siteusers'           => '{{GRAMMAR:genitive|{{SITENAME}}}} käyttäjä(t) $1',
+'creditspage'         => 'Sivun tekijäluettelo',
+'nocredits'           => 'Tämän sivun tekijäluettelotietoja ei löydy.',
+
+# Spam protection
+#
+'spamprotectiontitle' => 'Roskapostisuodatin',
+'spamprotectiontext'  => 'Roskapostisuodatin on estänyt sivun tallentamisen. Syynä on todennäköisimmin {{GRAMMAR:genitive|{{SITENAME}}}} ulkopuolelle osoittava linkki.',
+'spamprotectionmatch' => 'Teksti, joka ei läpäissyt roskapostisuodatinta: $1',
+'subcategorycount'    => 'Tällä luokalla on $1 alaluokkaa.',
+'subcategorycount1'   => 'Tällä luokalla on $1 alaluokka.',
+'categoryarticlecount'=> 'Tässä luokassa on $1 sivua.',
+'categoryarticlecount1' => 'Tässä luokassa on yksi sivu.',
+'usenewcategorypage'  => '1\n\nLaita ensimmäiseksi merkiksi nolla, kun et halua käyttää uutta luokittelutyyliä.',
+'listingcontinuesabbrev' => ' jatkuu',
+
+# Info page
+'infosubtitle'        => 'Tietoja sivusta',
+'numedits'            => 'Sivun muokkausten määrä: $1',
+'numtalkedits'        => 'Keskustelusivun muokkausten määrä: $1',
+'numwatchers'         => 'Tarkkailijoiden määrä: $1',
+'numauthors'          => 'Sivun erillisten kirjoittajien määrä: $1',
+'numtalkauthors'      => 'Keskustelusivun erillisten kirjoittajien määrä: $1',
+
+# Math options
+'mw_math_png'         => 'Näytä aina PNG:nä',
+'mw_math_simple'      => 'Näytä HTML:nä, jos yksinkertainen, muuten PNG:nä',
+'mw_math_html'        => 'Näytä HTML:nä, jos mahdollista, muuten PNG:nä',
+'mw_math_source'      => 'Näytä TeX-muodossa (tekstiselaimille)',
+'mw_math_modern'      => 'Suositus nykyselaimille',
+'mw_math_mathml'      => 'Näytä MathML:nä jos mahdollista (kokeellinen)',
+
+// HOX
+# Patrolling
+'markaspatrolleddiff'   => 'Merkitse tarkastetuksi',
+'markaspatrolledlink'   => '[$1]',
+'markaspatrolledtext'   => 'Merkitse muokkaus tarkastetuksi',
+'markedaspatrolled'     => 'Tarkastettu',
+'markedaspatrolledtext' => 'Valittu versio on tarkastettu.',
+'rcpatroldisabled'      => 'Tuoreiden muutosten tarkastustoiminto ei ole käytössä',
+'rcpatroldisabledtext'  => 'Tuoreiden muutosten tarkastustoiminto ei ole käytössä.',
+
+'Monobook.css' => "/* Tätä sivua muokkaamalla voi muokata koko sivuston Monobook-tyyliä */",
+
+# Monobook.js: tooltips and access keys for monobook
+'Monobook.js' => "/* <pre> */
+ta = new Object();
+ta['pt-userpage'] = new Array('.','Oma käyttäjäsivu');
+ta['pt-anonuserpage'] = new Array('.','IP-osoitteesi käyttäjäsivu');
+ta['pt-mytalk'] = new Array('n','Oma keskustelusivu');
+ta['pt-anontalk'] = new Array('n','Keskustelu tämän IP-osoitteen muokkauksista');
+ta['pt-preferences'] = new Array('','Omat asetukset');
+ta['pt-watchlist'] = new Array('l','Lista sivuista, joiden muokkauksia tarkkailet');
+ta['pt-mycontris'] = new Array('y','Lista omista muokkauksista');
+ta['pt-login'] = new Array('o','Kirjaudu sisään tai luo tunnus');
+ta['pt-anonlogin'] = new Array('o','Kirjaudu sisään tai luo tunnus');
+ta['pt-logout'] = new Array('o','Kirjaudu ulos');
+ta['ca-talk'] = new Array('t','Keskustele sisällöstä');
+ta['ca-edit'] = new Array('e','Muokkaa tätä sivua');
+ta['ca-addsection'] = new Array('+','Lisää kommentti tälle sivulle');
+ta['ca-viewsource'] = new Array('e','Näytä sivun lähdekoodi');
+ta['ca-history'] = new Array('h','Sivun aikaisemmat versiot');
+ta['ca-protect'] = new Array('=','Suojaa tämä sivu');
+ta['ca-delete'] = new Array('d','Poista tämä sivu');
+ta['ca-undelete'] = new Array('d','Palauta tämä sivu');
+ta['ca-move'] = new Array('m','Siirrä tämä sivu');
+ta['ca-watch'] = new Array('w','Lisää tämä sivu tarkkailulistallesi');
+ta['ca-unwatch'] = new Array('w','Poista tämä sivu tarkkailulistaltasi');
+ta['search'] = new Array('f','Etsi sivu');
+ta['p-logo'] = new Array('','Etusivu');
+ta['n-mainpage'] = new Array('z','Mene etusivulle');
+ta['n-portal'] = new Array('','Keskustelua projektista');
+ta['n-currentevents'] = new Array('','Taustatietoa tämänhetkisistä tapahtumista');
+ta['n-recentchanges'] = new Array('r','Lista tuoreista muutoksista');
+ta['n-randompage'] = new Array('x','Avaa satunnainen sivu');
+ta['n-help'] = new Array('','Ohjeita');
+ta['n-sitesupport'] = new Array('','Tue sivuston toimintaa');
+ta['t-whatlinkshere'] = new Array('j','Lista sivuista, jotka viittavat tänne');
+ta['t-recentchangeslinked'] = new Array('k','Viimeisimmät muokkaukset sivuissa, joille viitataan tältä sivulta');
+ta['feed-rss'] = new Array('','RSS-syöte tälle sivulle');
+ta['feed-atom'] = new Array('','Atom-syöte tälle sivulle');
+ta['t-contributions'] = new Array('','Näytä lista tämän käyttäjän muokkauksista');
+ta['t-emailuser'] = new Array('','Lähetä sähköpostia tälle käyttäjälle');
+ta['t-upload'] = new Array('u','Tallenna kuvia tai muita mediatiedostoja');
+ta['t-specialpages'] = new Array('q','Näytä toimintosivut');
+ta['ca-nstab-main'] = new Array('c','Näytä sisältösivu');
+ta['ca-nstab-user'] = new Array('c','Näytä käyttäjäsivu');
+ta['ca-nstab-media'] = new Array('c','Näytä mediasivu');
+ta['ca-nstab-special'] = new Array('','Tämä on toimintosivu');
+ta['ca-nstab-wp'] = new Array('c','Näytä projektisivu');
+ta['ca-nstab-image'] = new Array('c','Näytä tiedostosivu');
+ta['ca-nstab-mediawiki'] = new Array('c','Näytä järjestelmäviesti');
+ta['ca-nstab-template'] = new Array('c','Näytä malline');
+ta['ca-nstab-help'] = new Array('c','Näytä ohjesivu');
+ta['ca-nstab-category'] = new Array('c','Näytä luokkasivu');
+/* </pre> */",
+
+# image deletion
+'deletedrevision'     => 'Poistettiin vanha versio $1.',
+
+# browsing diffs
+'previousdiff'        => '← Edellinen muutos',
+'nextdiff'            => 'Seuraava muutos →',
+
+'imagemaxsize'        => 'Rajoita kuvien koko kuvien kuvaussivuilla arvoon ',
+'thumbsize'           => 'Pikkukuvien koko: ',
+'showbigimage'        => 'Lataa korkeatarkkuuksinen versio ($1×$2, $3 KiB)',
+
+'newimages'           => 'Uudet kuvat',
+'noimages'            => 'Ei uusia kuvia.',
+
+# labels for User: and Title: on Special:Log pages
+'specialloguserlabel' => 'Käyttäjä: ',
+'speciallogtitlelabel'=> 'Kohde: ',
+
+'passwordtooshort'    => 'Salasanasi on liian lyhyt. Salasanan pitää olla vähintään $1 merkkiä pitkä.',
+
+# Media Warning
+'mediawarning' => '\'\'\'Varoitus\'\'\': Tämä tiedosto saattaa sisältää vahingollista koodia, ja suorittamalla sen järjestelmäsi voi muuttua epäluotettavaksi.
+<hr>',
+
+'fileinfo' => '$1 KiB, MIME-tyyppi: <code>$2</code>',
+
+# external editor support
+'edit-externally'     => 'Muokkaa tätä tiedostoa ulkoisessa sovelluksessa',
+'edit-externally-help'=> 'Katso [http://meta.wikimedia.org/wiki/Help:External_editors ohjeet], jos haluat lisätietoja.',
+
+'watchlistall1'       => 'kaikkia',
+'watchlistall2'       => ', koko historia',
+'namespacesall'       => 'kaikki',
+
+# E-mail address confirmation
+'confirmemail'        => 'Varmenna sähköpostiosoite',
+'confirmemail_text'   => 'Tämä wiki vaatii sähköpostiosoitteen varmentamisen, ennen kuin voit käyttää sähköpostitoimintoja. Lähetä alla olevasta painikkeesta varmennusviesti osoitteeseesi. Viesti sisältää linkin, jonka avaamalla varmennat sähköpostiosoitteesi.',
+'confirmemail_send'   => 'Lähetä varmennusviesti',
+'confirmemail_sent'   => 'Varmennusviesi lähetetty.',
+'confirmemail_sendfailed' => 'Varmennusviestin lähettäminen epäonnistui. Tarkista, onko osoitteessa kiellettyjä merkkejä.',
+'confirmemail_invalid'    => 'Varmennuskoodi ei kelpaa. Koodi on voinut vanhentua.',
+'confirmemail_success'    => 'Sähköpostiosoitteesi on nyt varmennettu. Voit kirjautua sisään.',
+'confirmemail_loggedin'   => 'Sähköpostiosoitteesti on nyt varmennettu.',
+'confirmemail_error'  => 'Jokin epäonnistui varmennnuksen tallentamisessa.',
+'confirmemail_subject'=> '{{GRAMMAR:genitive|{{SITENAME}}}} sähköpostiosoitteen varmennus',
+'confirmemail_body'   => 'Joku IP-osoitteesta $1 on rekisteröinyt {{GRAMMAR:inessive|{{SITENAME}}}} tunnuksen $2 tällä sähköpostiosoitteella.
+
+Varmenna, että tämä tunnus kuuluu sinulle avamaalla seuraava linkki selaimellasi:
+
+$3
+
+Jos tämä tunnus ei ole sinun, ÄLÄ seuraa linkkiä. Varmennuskoodi vanhenee $4.
+',
+
+
+# Inputbox extension, may be useful in other contexts as well
+'tryexact'            => 'Koita tarkkaa osumaa',
+'searchfulltext'      => 'Etsi koko tekstiä',
+'createarticle'       => 'Luo sivu',
+
+'unit-pixel' => ' px',
+
+);
+
+
+       #--------------------------------------------------------------------------
+       # Internationalisation code
+       #--------------------------------------------------------------------------
+
+class LanguageFi extends LanguageUtf8 {
+       function LanguageFi() {
+               global $wgNamespaceNamesFi, $wgMetaNamespace;
+               LanguageUtf8::LanguageUtf8();
+               $wgNamespaceNamesFi[NS_PROJECT_TALK] = 'Keskustelu_' . $this->convertGrammar( $wgMetaNamespace, 'elative' );
+       }
+
+       function getBookstoreList () {
+               global $wgBookstoreListFi ;
+               return $wgBookstoreListFi ;
+       }
+
+       function getNamespaces() {
+               global $wgNamespaceNamesFi;
+               return $wgNamespaceNamesFi;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsFi;
+               return $wgQuickbarSettingsFi;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesFi;
+               return $wgSkinNamesFi;
+       }
+
+       function getDateFormats() {
+               global $wgDateFormatsFi;
+               return $wgDateFormatsFi;
+       }
+
+       /**
+        * @access public
+        * @param mixed  $ts the time format which needs to be turned into a
+        *               date('YmdHis') format with wfTimestamp(TS_MW,$ts)
+        * @param bool   $adj whether to adjust the time output according to the
+        *               user configured offset ($timecorrection)
+        * @param mixed  $format what format to return, if it's false output the
+        *               default one.
+        * @param string $timecorrection the time offset as returned by
+        *               validateTimeZone() in Special:Preferences
+        * @return string
+        */
+       function date( $ts, $adj = false, $format = true, $timecorrection = false ) {
+               if ( $adj ) { $ts = $this->userAdjust( $ts, $timecorrection ); }
+
+               $yyyy = substr( $ts, 0, 4 );
+               $mm = substr( $ts, 4, 2 );
+               $m = 0 + $mm;
+               $mmmm = $this->getMonthName( $mm ) . 'ta';
+               $dd = substr( $ts, 6, 2 );
+               $d = 0 + $dd;
+
+               $datePreference = $this->dateFormat($format);
+               switch( $datePreference ) {
+                       case '3': return "$d.$m.$yyyy";
+                       case 'ISO 8601': return "$yyyy-$mm-$dd";
+                       default: return "$d. $mmmm $yyyy";
+               }
+       }
+
+       /**
+       * @access public
+       * @param mixed  $ts the time format which needs to be turned into a
+       *               date('YmdHis') format with wfTimestamp(TS_MW,$ts)
+       * @param bool   $adj whether to adjust the time output according to the
+       *               user configured offset ($timecorrection)
+       * @param mixed  $format what format to return, if it's false output the
+       *               default one (default true)
+       * @param string $timecorrection the time offset as returned by
+       *               validateTimeZone() in Special:Preferences
+       * @return string
+       */
+       function time( $ts, $adj = false, $format = true, $timecorrection = false ) {
+               if ( $adj ) { $ts = $this->userAdjust( $ts, $timecorrection ); }
+
+               $hh = substr( $ts, 8, 2 );
+               $mm =  substr( $ts, 10, 2 );
+               $ss = substr( $ts, 12, 2 );
+
+               $datePreference = $this->dateFormat($format);
+               switch( $datePreference ) {
+                       case '2':
+                       case 'ISO 8601': return "$hh:$mm:$ss";
+                       default: return "$hh.$mm";
+               }
+       }
+
+       /**
+       * @access public
+       * @param mixed  $ts the time format which needs to be turned into a
+       *               date('YmdHis') format with wfTimestamp(TS_MW,$ts)
+       * @param bool   $adj whether to adjust the time output according to the
+       *               user configured offset ($timecorrection)
+       * @param mixed  $format what format to return, if it's false output the
+       *               default one (default true)
+       * @param string $timecorrection the time offset as returned by
+       *               validateTimeZone() in Special:Preferences
+       * @return string
+       */
+       function timeanddate( $ts, $adj = false, $format = true, $timecorrection = false) {
+               $date = $this->date( $ts, $adj, $format, $timecorrection );
+               $time = $this->time( $ts, $adj, $format, $timecorrection );
+
+               $datePreference = $this->dateFormat($format);
+               switch( $datePreference ) {
+                       case '3':
+                       case 'ISO 8601': return "$date $time";
+                       default: return "$date kello $time";
+               }
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesFi;
+               if( isset( $wgAllMessagesFi[$key] ) ) {
+                       return $wgAllMessagesFi[$key];
+               } else {
+                       return parent::getMessage( $key );
+               }
+       }
+
+       /**
+        * Finnish numeric formatting is 123 456,78.
+        * Notice that the space is non-breaking.
+        */
+       function formatNum( $number, $year = false ) {
+               return $year ? $number : strtr($this->commafy($number), '.,', ", " );
+       }
+
+       /**
+        * Avoid grouping whole numbers between 0 to 9999
+        */
+       function commafy($_) {
+               if (!preg_match('/^\d{1,4}$/',$_)) {
+                       return strrev((string)preg_replace('/(\d{3})(?=\d)(?!\d*\.)/','$1,',strrev($_)));
+               } else {
+                       return $_;
+               }
+       }
+
+       # Convert from the nominative form of a noun to some other case
+       # Invoked with {{GRAMMAR:case|word}}
+       function convertGrammar( $word, $case ) {
+               # These rules are not perfect, but they are currently only used for site names so it doesn't
+               # matter if they are wrong sometimes. Just add a special case for your site name if necessary.
+               switch ( $case ) {
+                       case 'genitive':
+                               if ( $word == 'Wikisitaatit' ) {
+                                       $word = 'Wikisitaattien';
+                               } else {
+                                       $word .= 'n';
+                               }
+                       break;
+                       case 'elative':
+                               if ( $word == 'Wikisitaatit' ) {
+                                       $word = 'Wikisitaateista';
+                               } else {
+                                       if ( mb_substr($word, -1) == 'y' ) {
+                                               $word .= 'stä';
+                                       } else {
+                                               $word .= 'sta';
+                                       }
+                               }
+                               break;
+                       case 'partitive':
+                               if ( $word == 'Wikisitaatit' ) {
+                                       $word = 'Wikisitaatteja';
+                               } else {
+                                       if ( mb_substr($word, -1) == 'y' ) {
+                                               $word .= 'ä';
+                                       } else {
+                                               $word .= 'a';
+                                       }
+                               }
+                               break;
+                       case 'illative':
+                               # Double the last letter and add 'n'
+                               # mb_substr has a compatibility function in GlobalFunctions.php
+                               if ( $word == 'Wikisitaatit' ) {
+                                       $word = 'Wikisitaatteihin';
+                               } else {
+                                       $word = $word . mb_substr($word,-1) . 'n';
+                               }
+                               break;
+                       case 'inessive':
+                               if ( $word == 'Wikisitaatit' ) {
+                                       $word = 'Wikisitaateissa';
+                               } else {
+                                       if ( mb_substr($word, -1) == 'y' ) {
+                                               $word .= 'ssä';
+                                       } else {
+                                               $word .= 'ssa';
+                                       }
+                               }
+                               break;
+
+               }
+               return $word;
+       }
+
+}
+
+?>
diff --git a/languages/LanguageFo.php b/languages/LanguageFo.php
new file mode 100644 (file)
index 0000000..b04820e
--- /dev/null
@@ -0,0 +1,162 @@
+<?php
+/** Faroese (Føroyskt)
+  *
+  * @package MediaWiki
+  * @subpackage Language
+  */
+require_once( 'LanguageUtf8.php');
+
+/* private */ $wgNamespaceNamesFo = array(
+       NS_MEDIA            => "Miðil",
+       NS_SPECIAL          => "Serstakur",
+       NS_MAIN             => "",
+       NS_TALK             => "Kjak",
+       NS_USER             => "Brúkari",
+       NS_USER_TALK        => "Brúkari_kjak",
+       NS_PROJECT          => "Wikipedia",
+       NS_PROJECT_TALK     => "Wikipedia_kjak",
+       NS_IMAGE            => "Mynd",
+       NS_IMAGE_TALK       => "Mynd_kjak",
+       NS_MEDIAWIKI        => "MidiaWiki",
+       NS_MEDIAWIKI_TALK   => "MidiaWiki_kjak",
+       NS_TEMPLATE         => "Fyrimynd",
+       NS_TEMPLATE_TALK    => "Fyrimynd_kjak",
+       NS_HELP             => "Hjálp",
+       NS_HELP_TALK        => "Hjálp_kjak",
+       NS_CATEGORY         => "Bólkur",
+       NS_CATEGORY_TALK    => "Bólkur_kjak"
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgQuickbarSettingsFo = array(
+       "Eingin", "Fast vinstru", "Fast høgru", "Flótandi vinstru"
+);
+
+/* private */ $wgSkinNamesFo = array(
+       "Standardur", "Nostalgiskur", "Cologne-bláur", "Paddington", "Montparnasse"
+);
+
+/* private */ $wgDateFormatsFo = array(
+#      "Ongi forrættindi",
+);
+
+/* private */ $wgBookstoreListFo = array(
+       "Bokasolan.fo" => "http://www.bokasolan.fo/vleitari.asp?haattur=bok.alfa&Heiti=&Hovindur=&Forlag=&innbinding=Oell&bolkur=Allir&prisur=Allir&Aarstal=Oell&mal=Oell&status=Oell&ISBN=$1",
+) + $wgBookstoreListEn;
+
+
+/* private */ $wgAllMessagesFo = array(
+
+# User toggles
+"tog-underline"           => "Undurstrika ávísingar",
+"tog-highlightbroken" => "Brúka reyða ávísing til tómar síður",
+"tog-justify"     => "Stilla greinpart",
+"tog-hideminor"           => "Goym minni broytingar í seinast broytt listanum",                 # Skjul mindre ændringer i seneste ændringer listen
+"tog-usenewrc"    => "víðka seinastu broytingar lista<br />(ikki til alla kagarar)",
+"tog-numberheadings"   => "Sjálvtalmerking av yvirskrift",
+"tog-showtoolbar"         => "Vís amboðslinju í rætting",
+"tog-editondblclick"   => "Rætta síðu við at tvíklikkja (JavaScript)",
+"tog-editsection"         =>"Rætta greinpart við hjálp av [rætta]-ávísing",
+"tog-editsectiononrightclick"=>"Rætta greinpart við at høgraklikkja<br /> á yvirskrift av greinparti (JavaScript)",
+"tog-showtoc"=>"Vís innihaldsyvurlit<br />(Til greinir við meira enn trimun greinpartum)",
+"tog-rememberpassword" => "Minst til loyniorð næstu ferð",
+"tog-editwidth" => "Rættingarkassin hevur fulla breid",
+"tog-watchdefault" => "Vaka yvur nýggjum og broyttum greinum",
+"tog-minordefault" => "Merk sum standard allar broytingar sum smærri",
+"tog-previewontop" => "Vís forhondsvísning áðren rættingarkassan",
+"tog-nocache" => "Minst ikki til síðurnar til næstu ferð",
+
+# Dates
+'sunday' => 'sunnudagur',
+'monday' => 'mánadagur',
+'tuesday' => 'týsdagur',
+'wednesday' => 'mikudagur',
+'thursday' => 'hósdagur',
+'friday' => 'fríggjadagur',
+'saturday' => 'leygardagur',
+'january' => 'januar',
+'february' => 'februar',
+'march' => 'mars',
+'april' => 'apríl',
+'may_long' => 'mai',
+'june' => 'juni',
+'july' => 'juli',
+'august' => 'august',
+'september' => 'september',
+'october' => 'oktober',
+'november' => 'november',
+'december' => 'desember',
+'jan' => 'jan',
+'feb' => 'feb',
+'mar' => 'mar',
+'apr' => 'apr',
+'may' => 'mai',
+'jun' => 'jun',
+'jul' => 'jul',
+'aug' => 'aug',
+'sep' => 'sep',
+'oct' => 'okt',
+'nov' => 'nov',
+'dec' => 'des',
+
+# Math options
+'mw_math_png' => "Vís altíð sum PNG",
+'mw_math_simple' => "HTML um sera einfalt annars PNG",
+'mw_math_html' => "HTML um møguligt annars PNG",
+'mw_math_source' => "Lat verða sum TeX (til tekstkagara)",
+'mw_math_modern' => "Tilmælt nýtíðarkagara",
+'mw_math_mathml' => 'MathML if possible (experimental)',
+
+'linktrail' => '/^([áðíóúýæøa-z]+)(.*)$/sDu',
+);
+class LanguageFo extends LanguageUtf8 {
+
+       function getBookstoreList () {
+               global $wgBookstoreListFo ;
+               return $wgBookstoreListFo ;
+       }
+
+       function getNamespaces() {
+               global $wgNamespaceNamesFo;
+               return $wgNamespaceNamesFo;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsFo;
+               return $wgQuickbarSettingsFo;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesFo;
+               return $wgSkinNamesFo;
+       }
+
+       function getDateFormats() {
+               global $wgDateFormatsFo;
+               return $wgDateFormatsFo;
+       }
+
+
+       function date( $ts, $adj = false ) {
+               if ( $adj ) { $ts = $this->userAdjust( $ts ); }
+
+               $d = (0 + substr( $ts, 6, 2 )) . ". " .
+                 $this->getMonthAbbreviation( substr( $ts, 4, 2 ) ) . " " .
+                 substr( $ts, 0, 4 );
+               return $d;
+       }
+
+       function timeanddate( $ts, $adj = false ) {
+               return $this->date( $ts, $adj ) . " kl. " . $this->time( $ts, $adj );
+       }
+
+       function getMessage( $key ) {
+           global $wgAllMessagesFo, $wgAllMessagesEn;
+           $m = $wgAllMessagesFo[$key];
+
+           if ( "" == $m ) { return $wgAllMessagesEn[$key]; }
+           else return $m;
+       }
+
+}
+
+?>
diff --git a/languages/LanguageFr.php b/languages/LanguageFr.php
new file mode 100644 (file)
index 0000000..99cdf11
--- /dev/null
@@ -0,0 +1,1248 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+require_once( 'LanguageUtf8.php' );
+
+/* private */ $wgNamespaceNamesFr = array(
+       NS_MEDIA                        => 'Media',
+       NS_SPECIAL                      => 'Special',
+       NS_MAIN                         => '',
+       NS_TALK                         => 'Discuter',
+       NS_USER                         => 'Utilisateur',
+       NS_USER_TALK            => 'Discussion_Utilisateur',
+       NS_PROJECT                      => $wgMetaNamespace,
+       NS_PROJECT_TALK         => 'Discussion_'.$wgMetaNamespace,
+       NS_IMAGE                        => 'Image',
+       NS_IMAGE_TALK           => 'Discussion_Image',
+       NS_MEDIAWIKI            => 'MediaWiki',
+       NS_MEDIAWIKI_TALK       => 'Discussion_MediaWiki',
+       NS_TEMPLATE                     => 'Modèle',
+       NS_TEMPLATE_TALK        => 'Discussion_Modèle',
+       NS_HELP                         => 'Aide',
+       NS_HELP_TALK            => 'Discussion_Aide',
+       NS_CATEGORY                     => 'Catégorie',
+       NS_CATEGORY_TALK        => 'Discussion_Catégorie'
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgQuickbarSettingsFr = array(
+       'Aucune', 'Gauche', 'Droite', 'Flottante à gauche'
+);
+
+/* private */ $wgSkinNamesFr = array(
+       'standard'              => 'Standard',
+       'nostalgia'             => 'Nostalgie',
+) + $wgSkinNamesEn;
+
+
+
+/* private */ $wgBookstoreListFr = array(
+       'Amazon.fr'             => 'http://www.amazon.fr/exec/obidos/ISBN=$1',
+       'alapage.fr'    => 'http://www.alapage.com/mx/?tp=F&type=101&l_isbn=$1&donnee_appel=ALASQ&devise=&',
+       'fnac.com'              => 'http://www3.fnac.com/advanced/book.do?isbn=$1',
+       'chapitre.com'  => 'http://www.chapitre.com/frame_rec.asp?isbn=$1',
+);
+
+
+/* private */ $wgAllMessagesFr = array(
+
+# User Toggles
+
+'tog-editwidth' => 'La fenêtre d\'édition s\'affiche en pleine largeur',
+'tog-editondblclick' => 'Double cliquer pour éditer une page (JavaScript)',
+'tog-editsection'      => 'Éditer une section via les liens [éditer]',
+'tog-editsectiononrightclick'  => 'Éditer une section en cliquant à droite<br /> sur le titre de la section',
+'tog-fancysig' => 'Signatures brutes (sans lien automatique)',
+'tog-hideminor' => 'Cacher les <i>Modifications récentes</i> mineures',
+'tog-highlightbroken' => 'Liens vers les sujets non existants en rouge',
+'tog-justify' => 'Paragraphes justifiés',
+'tog-minordefault' => 'Mes modifications sont considérées<br /> comme mineures par défaut',
+'tog-nocache' => 'Désactiver le cache des pages',
+'tog-numberheadings' => 'Numérotation automatique des titres',
+'tog-previewonfirst' => 'Montrer la prévisualisation lors de la première édition',
+'tog-previewontop' => 'La prévisualisation s\'affiche au<br /> dessus de la boite de rédaction',
+'tog-rememberpassword' => 'Se souvenir de mon mot de passe (cookie)',
+'tog-showtoc'  => 'Afficher la table des matières<br /> (pour les articles ayant plus de 3 sections)',
+'tog-showtoolbar' => 'Montrer la barre de menu d\'édition',
+'tog-usenewrc' => 'Modifications récentes améliorées<br /> (certains navigateurs seulement)',
+'tog-underline' => 'Liens soulignés',
+'tog-watchdefault' => 'Suivre les articles que je crée ou modifie',
+
+
+# Dates
+
+'sunday' => 'dimanche',
+'monday' => 'lundi',
+'tuesday' => 'mardi',
+'wednesday' => 'mercredi',
+'thursday' => 'jeudi',
+'friday' => 'vendredi',
+'saturday' => 'samedi',
+'january' => 'janvier',
+'february' => 'février',
+'march' => 'mars',
+'april' => 'avril',
+'may_long' => 'mai',
+'june' => 'juin',
+'july' => 'juillet',
+'august' => 'août',
+'september' => 'septembre',
+'october' => 'octobre',
+'november' => 'novembre',
+'december' => 'décembre',
+'jan' => 'jan',
+'feb' => 'fév',
+'mar' => 'mar',
+'apr' => 'avr',
+'may' => 'mai',
+'jun' => 'jun',
+'jul' => 'jul',
+'aug' => 'aoû',
+'sep' => 'sep',
+'oct' => 'oct',
+'nov' => 'nov',
+'dec' => 'déc',
+
+
+# Bits of text used by many pages:
+#
+'categories'   => 'Catégories de la page',
+'category'     => 'catégorie',
+'category_header' => 'Articles dans la catégorie « $1 ».',
+'subcategories'        => 'Sous-catégories',
+'uncategorizedcategories' => 'Catégories sans catégories',
+'uncategorizedpages' => 'Pages sans catégories',
+'subcategorycount' => 'Cette catégorie possède $1 sous-catégories.',
+'subcategorycount1' => 'Cette catégorie possède $1 sous-catégorie.',
+
+'allarticles'   => 'Tous les articles',
+'linktrail'     => '/^([a-zàâçéèêîôûäëïöüùÇÉÂÊÎÔÛÄËÏÖÜÀÈÙ]+)(.*)$/sD',
+'mainpage'      => 'Accueil',
+'mainpagetext' => 'Logiciel {{SITENAME}} installé.',
+'portal'        => 'Communauté',
+'portal-url'   => '{{ns:4}}:Accueil',
+'about'         => 'À propos',
+'aboutsite'     => 'À propos de {{SITENAME}}',
+'aboutpage'     => '{{ns:4}}:À propos',
+'article'       => 'Article',
+'help'          => 'Aide',
+'helppage'      => '{{ns:help}}:Aide',
+'bugreports'    => 'Rapport d\'erreurs',
+'bugreportspage' => '{{ns:4}}:Rapport d\'erreurs',
+'sitesupport'  => 'Participer en faisant un don',
+'sitesupport'  => 'Faire un don',
+'sitesupportpage'      => '{{ns:4}}:Dons',
+'faq'           => 'FAQ',
+'faqpage'       => '{{ns:4}}:FAQ',
+'edithelp'      => 'Aide',
+'edithelppage'  => '{{ns:help}}:Comment éditer une page',
+'cancel'        => 'Annuler',
+'qbfind'        => 'Rechercher',
+'qbbrowse'      => 'Défiler',
+'qbedit'        => 'Modifier',
+'qbpageoptions' => 'Page d\'option',
+'qbpageinfo'    => 'Page d\'information',
+'qbmyoptions'   => 'Mes options',
+'qbspecialpages'       => 'Pages spéciales',
+'moredotdotdot'        => 'Et plus...',
+'mypage'        => 'Ma page',
+'mytalk'        => 'Ma page de discussion',
+'anontalk'     => 'Discussion avec cette adresse ip',
+'navigation'   => 'Navigation',
+'currentevents' => 'Actualités',
+'disclaimers'  => 'Avertissements',
+'disclaimerpage' => '{{ns:4}}:Avertissements généraux',
+'errorpagetitle' => 'Erreur',
+'returnto'      => 'Revenir à la page $1.',
+'tagline'       => 'Un article de {{SITENAME}}.',
+'whatlinkshere' => 'Références à cette page',
+'help'          => 'Aide',
+'search'        => 'Rechercher',
+'history'       => 'Historique',
+'printableversion' => 'Version imprimable',
+'edit'         => 'Modifier',
+'editthispage'  => 'Modifier cette page',
+'delete'       => 'Supprimer',
+'deletethispage' => 'Supprimer cette page',
+'undelete_short' => 'Restaurer',
+'undelete_short1' => 'Restaurer',
+'protect' => 'Protéger',
+'protectthispage' => 'Protéger cette page',
+'unprotect' => 'Déprotéger',
+'unprotectthispage' => 'Déprotéger cette page',
+'newpage'       => 'Nouvelle page',
+'talkpage'      => 'Page de discussion',
+'specialpage'  => 'Page Spéciale',
+'personaltools'        => 'Outils personels',
+'postcomment'  => 'Ajouter un commentaire',
+'addsection'   => '+',
+'articlepage'  => 'Voir l\'article',
+'subjectpage'   => 'Page sujet',
+'talk'         => 'Discussion',
+'toolbox'      => 'Boîte à outils',
+'userpage'      => 'Page utilisateur',
+'wikipediapage' => 'Page méta',
+'imagepage'     => 'Page image',
+'viewtalkpage'  => 'Page de discussion',
+'otherlanguages' => 'Autres langues',
+'redirectedfrom' => '(Redirigé depuis $1)',
+'lastmodified'  => 'Dernière modification de cette page le $1.',
+'viewcount'     => 'Cette page a été consultée $1 fois.',
+'copyright'    => 'Contenu disponible sous $1.',
+'printsubtitle' => '(de {{SERVER}})',
+'protectedpage' => 'Page protégée',
+'administrators' => '{{ns:4}}:Administrateurs',
+'sysoptitle'    => 'Accès administrateur requis',
+'sysoptext'     => 'L\'action que vous avez tentée ne peut être effectuée que par un utilisateur ayant le statut d\'« administrateur ».
+Voir $1.',
+'developertitle' => 'Accès développeur requis',
+'developertext' => 'L\'action que vous avez tentée ne peut être effectuée que par un utilisateur ayant le statut de « développeur ».
+Voir $1.',
+'nbytes'        => '$1 octets',
+'go'            => 'Consulter',
+'ok'            => 'OK',
+'pagetitle'    => '$1 - {{SITENAME}}',
+'history'      => 'Historique de la page',
+'history_short' => 'Historique',
+'sitetitle'     => '{{SITENAME}}',
+'sitesubtitle'  => '',
+'retrievedfrom' => 'Récupérée de « $1 »',
+'newmessages'   => 'Vous avez des $1.',
+'newmessageslink' => 'nouveaux messages',
+'editsection'  => 'modifier',
+'toc'          => 'Sommaire',
+'showtoc'      => 'afficher',
+'hidetoc'      => 'masquer',
+'thisisdeleted' => 'Afficher ou restaurer $1 ?',
+'restorelink'  => '1 modifications effacées',
+'feedlinks'    => 'Flux:',
+'sitenotice'   => '-', # the equivalent to wgSiteNotice
+
+# Short words for each namespace, by default used in the 'article' tab in monobook
+'nstab-main' => 'Article',
+'nstab-user' => 'Page utilisateur',
+'nstab-media' => 'Média',
+'nstab-special' => 'Spécial',
+'nstab-wp' => 'À propos',
+'nstab-image' => 'Image',
+'nstab-mediawiki' => 'Message',
+'nstab-template' => 'Modèle',
+'nstab-help' => 'Aide',
+'nstab-category' => 'Catégorie',
+
+# Main script and global functions
+#
+'nosuchaction' => 'Action inconnue',
+'nosuchactiontext' => 'L\'action spécifiée dans l\'Url n\'est pas reconnue par le wiki.',
+'nosuchspecialpage' => 'Page spéciale inexistante',
+'nospecialpagetext' => 'Vous avez demandé une page spéciale qui n\'est pas reconnue par le wiki.',
+
+# General errors
+#
+'error'                => 'Erreur',
+'badaccess' => 'Erreur de permission',
+'badaccesstext' => 'L\'action entreprise est limitée aux utilisateurs possédant le droit « $2 ».
+Voir $1',
+'databaseerror' => 'Erreur base de données',
+'dberrortext'  => 'Erreur de syntaxe dans la base de données. La dernière requête traitée par la base de données était :
+<blockquote><tt>$1</tt></blockquote>
+depuis la fonction « <tt>$2</tt> ».
+MySQL a renvoyé l\'erreur « <tt>$3: $4</tt> ».',
+'dberrortextcl' => 'Une requête à la base de donnée comporte une erreur de syntaxe. La dernière requête envoyée était:
+« $1 »
+effectuée par la fonction « $2 »
+MySQL a retourné l\'erreur « $3 : $4 ».',
+'noconnect'    => 'Désolé! Suite à des problèmes techniques, il est impossible de se connecter à la base de données pour le moment.',
+'nodb'         => 'Sélection impossible de la base de données $1',
+'cachederror'  => 'Ceci est une copie de la page demandée et peut ne pas être à jour',
+'readonly'     => 'Mises à jour bloquées sur la base de données',
+'enterlockreason' => 'Indiquez la raison du blocage, ainsi qu\'une estimation de la durée de blocage ',
+'readonlytext' => 'Les ajouts et mises à jour sur la base de donnée {{SITENAME}} sont actuellement bloqués, probablement pour permettre la maintenance de la base, après quoi, tout rentrera dans l\'ordre. Voici la raison pour laquelle l\'administrateur a bloqué la base :
+<p>$1',
+'missingarticle' => 'La base de données n\'a pas pu trouver le texte d\'une page existante, dont le titre est « $1 ».
+Ce n\'est pas une erreur de la base de données, mais plus probablement un bogue du wiki.
+Veuillez rapporter cette erreur à un administrateur, en lui indiquant l\'adresse de la page fautive.',
+'internalerror' => 'Erreur interne',
+'filecopyerror' => 'Impossible de copier « $1 » vers « $2 ».',
+'fileinfo' => '$1Ko, type MIME: <tt>$2</tt>',
+'filerenameerror' => 'Impossible de renommer « $1 » en « $2 ».',
+'filedeleteerror' => 'Impossible de supprimer « $1 ».',
+'filenotfound' => 'Le fichier « $1 » introuvable.',
+'unexpected' => 'Valeur inattendue : « $1 » = « $2 ».',
+'formerror'    => 'Erreur: Impossible de soumettre le formulaire',
+'badarticleerror' => 'Cette action ne peut pas être effectuée sur cette page.',
+'cannotdelete' => 'Impossible de supprimer la page ou l\'image indiquée.',
+'badtitle'     => 'Mauvais titre',
+'badtitletext' => 'Le titre de la page demandée est invalide, vide ou le lien interlangue est invalide',
+'laggedslavemode' => 'Attention : la page n\'intègre peut être pas les dernières éditions',
+'readonly_lag' => 'La base de donnée a été automatiquement bloquée pendant que les serveurs secondaires rattrapent leur retard avec le serveur principal',
+'perfdisabled' => 'Désolé! Cette fonctionnalité est temporairement désactivée
+car elle ralentit la base de données à un point tel que plus personne
+ne peut utiliser le wiki.',
+'perfdisabledsub' => 'Ceci est une copie de sauvegarde de $1:',
+'viewsource'   => 'Voir le texte source',
+'protectedtext'        => 'Cette page a été bloquée pour empêcher sa modification. Consulter [[{{ns:4}}:Page protégée]] pour voir les différentes raisons possibles.',
+'allmessagesnotsupportedDB' => 'Special:AllMessages n\'est pas disponible parce que wgUseDatabaseMessages est désactivé.',
+'allmessagesnotsupportedUI' => 'Special:AllMessages n\'accepte pas la langue de votre interface (<b>$1</b>) sur ce site.',
+'wrong_wfQuery_params' => 'Paramètres incorrects sur la commande wfQuery()<br />
+Fonction : $1<br />
+Requête : $2',
+'versionrequired' => 'Version $1 de MediaWiki nécessaire',
+'versionrequiredtext' => 'La version $1 de MediaWiki est nécessaire pour utiliser cette page. Voyez [[Special:Version]]',
+
+
+# Login and logout pages
+#
+'logouttitle'  => 'Déconnexion',
+'logouttext'   => 'Vous êtes à présent déconnecté(e).
+Vous pouvez continuer à utiliser {{SITENAME}} de façon anonyme, ou vous reconnecter, éventuellement sous un autre nom.',
+
+'welcomecreation' => '<h2>Bienvenue, $1!</h2><p>Votre compte d\'utilisateur a été créé.
+N\'oubliez pas de personnaliser votre {{SITENAME}} en consultant la page Préférences.',
+'loginpagetitle'     => 'Votre identifiant',
+'yourname'           => 'Votre nom d\'utilisateur',
+'yourpassword'       => 'Votre mot de passe',
+'yourpasswordagain'  => 'Entrez à nouveau votre mot de passe',
+'newusersonly'       => ' (nouveaux utilisateurs uniquement)',
+'remembermypassword' => 'Se souvenir de mon mot de passe (cookie)',
+'loginproblem'       => '<b>Problème d\'identification.</b><br />Essayez à nouveau !',
+'alreadyloggedin'    => '<strong>\'\'\'Utilisateur $1, vous êtes déjà identifié!\'\'\'</strong><br />',
+
+'login'         => 'Identification',
+'loginprompt'  => 'Vous devez activer les cookies pour vous connecter à {{SITENAME}}.',
+'userlogin'     => 'Créer un compte ou se connecter',
+'logout'        => 'Déconnexion',
+'userlogout'    => 'Déconnexion',
+'notloggedin'  => 'Non connecté',
+'createaccount' => 'Créer un nouveau compte',
+'createaccountmail'    => 'par courriel',
+'badretype'     => 'Les deux mots de passe que vous avez saisis ne sont pas identiques.',
+'userexists'    => 'Le nom d\'utilisateur que vous avez saisi est déjà utilisé. Veuillez en choisir un autre.',
+'youremail'     => 'Mon adresse électronique',
+'yournick'      => 'Signature pour les discussions (avec <tt><nowiki>~~~</nowiki></tt>)&nbsp;',
+'yourrealname' => 'Votre nom réel*',
+'emailforlost'  => 'Si vous égarez votre mot de passe, vous pouvez demander à ce qu\'un nouveau vous soit envoyé à votre adresse électronique.',
+'prefs-help-realname' => '* <strong>Votre nom</strong> (facultatif): si vous le spécifiez, il sera utilisé pour l\'attribution de vos contributions.',
+'prefs-help-email' => '* <strong>Adresse électronique</strong> (facultatif): permet de vous contacter depuis le site sans dévoiler votre adresse, et utilisée pour vous envoyer un nouveau mot de passe si vous l\'oubliez.',
+'loginerror'    => 'Problème d\'identification',
+'nocookiesnew' => 'Le compte utilisateur a été créé, mais vous n\'êtes pas connecté. {{SITENAME}} utilise des cookies pour la connexion mais vous avez les cookies désactives. Merci de les activer et de vous reconnecter.',
+'nocookieslogin' => '{{SITENAME}} utilise des cookies pour la connexion mais vous avez les cookies désactives. Merci de les activer et de vous reconnecter.',
+'noname'        => 'Vous n\'avez pas saisi de nom d\'utilisateur.',
+'loginsuccesstitle' => 'Identification réussie.',
+'loginsuccess'  => 'Vous êtes actuellement connecté sur {{SITENAME}} en tant que « $1 ».',
+'nosuchuser'    => 'L\'utilisateur « $1 » n\'existe pas.
+Vérifiez que vous avez bien orthographié le nom, ou utilisez le formulaire ci-dessous pour créer un nouveau compte utilisateur.',
+'nosuchusershort' => 'Il n\'y a pas de contributeur avec le nom « $1 ». Vérifiez l\'orthographe.',
+'wrongpassword' => 'Le mot de passe est incorrect. Essayez à nouveau.',
+'mailmypassword' => 'Envoyez-moi un nouveau mot de passe',
+'passwordremindertitle' => 'Votre nouveau mot de passe sur {{SITENAME}}',
+'passwordremindertext' => 'Quelqu\'un (probablement vous) ayant l\'adresse IP $1 a demandé à ce qu\'un nouveau mot de passe vous soit envoyé pour votre accès au wiki.
+Le mot de passe de l\'utilisateur « $2 » est à présent « $3 ».
+Nous vous conseillons de vous connecter et de modifier ce mot de passe dès que possible.',
+'noemail'  => 'Aucune adresse électronique n\'a été enregistrée pour l\'utilisateur « $1 ».',
+'passwordsent' => 'Un nouveau mot de passe a été envoyé à l\'adresse électronique de l\'utilisateur « $1 ».
+Veuillez vous identifier dès que vous l\'aurez reçu.',
+'loginend'     => '&nbsp;',
+'mailerror'    => 'Erreur en envoyant le courriel : $1',
+'acct_creation_throttle_hit' => 'Désolé, vous avez déjà créé $1 comptes. Vous ne pouvez pas en créer de nouveaux.',
+
+# Edit page toolbar
+'bold_sample'   => 'Texte gras',
+'bold_tip'      => 'Texte gras',
+'italic_sample' => 'Texte italique',
+'italic_tip'    => 'Texte italique',
+'link_sample'   => 'Lien titre',
+'link_tip'      => 'Lien interne',
+'extlink_sample'  => 'http://www.example.com lien titre',
+'extlink_tip'     => 'Lien externe (n\'oubliez pas http://)',
+'headline_sample' => 'Texte de sous-titre',
+'headline_tip'  => 'Sous-titre niveau 2',
+'math_sample'   => 'Entrez votre formule ici',
+'math_tip'      => 'Formule mathématique (LaTeX)',
+'nowiki_sample' => 'Entrez le texte non formatté ici',
+'nowiki_tip'    => 'Ignorer la syntaxe wiki',
+'image_sample'  => 'Exemple.jpg',
+'image_tip'     => 'Image insérée',
+'media_sample'  => 'Exemple.ogg',
+'media_tip'     => 'Lien fichier média',
+'sig_tip'       => 'Votre signature avec la date',
+'hr_tip'        => 'Lien horizontal (ne pas en abuser)',
+'infobox'       => 'Cliquez ce bouton pour avoir un exemple de texte',
+'infobox_alert'        => "Veuillez entrer le texte que vous voulez formater.\\n Il sera affiché dans la boîte pour être copié et collé.\\nExemple\\n$1\\ndeviendra:\\n$2",
+
+# Edit pages
+#
+'summary'      => 'Résumé&nbsp;',
+'subject'         => 'Sujet/titre',
+'minoredit'    => 'Modification mineure.',
+'watchthis'    => 'Suivre cet article',
+'savearticle'  => 'Sauvegarder',
+'preview'      => 'Prévisualiser',
+'showpreview'  => 'Prévisualisation',
+'blockedtitle' => 'Utilisateur bloqué',
+'blockedtext'  => 'Votre compte utilisateur ou votre adresse IP ont été bloqués par $1 pour la raison suivante :<br />$2<p>Vous pouvez contacter $1 ou un des autres [[{{ns:4}}:Administrateurs|administrateurs]] pour en discuter.',
+'whitelistedittitle' => 'Login requis pour rédiger',
+'whitelistedittext' => 'Vous devez être [[Special:Userlogin|connecté]] pour pouvoir rédiger',
+'whitelistreadtitle' => 'Login requis pour lire',
+'whitelistreadtext' => 'Vous devez être [[Special:Userlogin|connecté]] pour pouvoir lire les articles',
+'whitelistacctitle' => 'Vous n\'êtes pas autorisé à créer un compte',
+'whitelistacctext' => 'Pour pouvoir créer un compte sur ce Wiki vous devez être [[Special:Userlogin|connecté]] et avoir les permissions appropriées', // Looxix
+'loginreqtitle'        => 'Nom d\'utilisateur nécessaire',
+'loginreqtext' => "Vous devez vous [[Special:Userlogin|connecter]] pour voir les autres pages.",
+'accmailtitle' => 'Mot de passe envoyé.',
+'accmailtext' => 'Le mot de passe de « $1 » a été envoyé à $2.',
+
+'newarticle'   => '(Nouveau)',
+'newarticletext' => 'Saisissez ici le texte de votre article.',
+'anontalkpagetext' => '---- \'\'Vous êtes sur la page de discussion d\'un utilisateur anonyme qui n\'a pas encore créé un compte ou qui ne l\'utilise pas. Pour cette raison, nous devons utiliser l\'[[adresse IP]] numérique pour l\'identifier. Une adresse de ce type peut être partagée entre plusieurs utilisateurs. Si vous êtes un utilisateur anonyme et si vous constatez que des commentaires qui ne vous concernent pas vous ont été adressés, vous pouvez [[Special:Userlogin|créer un compte ou vous connecter]] afin d\'éviter toute future confusion.\'\'',
+'noarticletext' => '(Il n\'y a pour l\'instant aucun texte sur cette page)',
+'clearyourcache'    => '\'\'\'Note :\'\'\' Après avoir sauvegardé, vous devez forcer le rechargement de la page pour voir les changements : \'\'\'Mozilla / Firefox\'\'\' : \'\'ctrl-shift-r\'\', \'\'\'IE\'\'\' : \'\'ctrl-f5\'\', \'\'\'Safari\'\'\' : \'\'cmd-shift-r\'\'; \'\'\'Konqueror\'\'\' : \'\'f5\'\'.',
+'updated'      => '(Mis à jour)',
+'note'         => '<strong>Note :</strong> ',
+'previewnote'  => 'Attention, ce texte n\'est qu\'une prévisualisation et n\'a pas encore été sauvegardé!',
+'previewconflict' => 'La prévisualisation montre le texte de cette page tel qu\'il apparaîtra une fois sauvegardé.',
+'editing'         => 'modification de $1',
+'editingsection'  => 'modification de $1 (section)',
+'editingcomment'  => 'modification de $1 (commentaire)',
+'editconflict' => 'Conflit de modification : $1',
+'explainconflict' => '<b>Cette page a été sauvegardée après que vous avez commencé à la modifier.
+La zone d\'édition supérieure contient le texte tel qu\'il est enregistré actuellement dans la base de données. Vos modifications apparaissent dans la zone d\'édition inférieure. Vous allez devoir apporter vos modifications au texte existant. Seul le texte de la zone supérieure sera sauvegardé.<br />',
+'yourtext'     => 'Votre texte',
+'storedversion' => 'Version enregistrée',
+'editingold'   => '<strong>Attention : vous êtes en train de modifier une version obsolète de cette page. Si vous sauvegardez, toutes les modifications effectuées depuis cette version seront perdues.</strong>',
+'yourdiff'  => 'Différences',
+'copyrightwarning' => 'Toutes les contributions à {{SITENAME}} sont considérées comme publiées sous les termes de la GNU Free Documentation Licence, une licence de documentation libre (Voir $1 pour plus de détails). Si vous ne désirez pas que vos écrits soient édités et distribués à volonté, ne les envoyez pas. De même, merci de ne contribuer qu\'en apportant vos propres écrits ou des écrits issus d\'une source libre de droits. <b>N\'UTILISEZ PAS DE TRAVAUX SOUS COPYRIGHT SANS AUTORISATION EXPRESSE!</b>',
+'longpagewarning' => '\'\'\'AVERTISSEMENT : cette page a une longueur de $1 ko;
+quelques navigateurs gèrent mal les pages approchant ou dépassant 32 ko lors de leur rédaction.
+Peut-être serait-il mieux que vous divisiez la page en sections plus petites.\'\'\'',
+'readonlywarning' => '\'\'\'AVERTISSEMENT : cette page a été bloquée pour maintenance,
+vous ne pourrez donc pas sauvegarder vos modifications maintenant. Vous pouvez copier le texte dans un fichier et le sauver pour plus tard.\'\'\'',
+'protectedpagewarning' => '\'\'\'AVERTISSEMENT : cette page a été bloquée.
+Seuls les utilisateurs ayant le statut d\'administrateur peuvent la modifier. Soyez certain que
+vous suivez les [[Project:Page_protégée|directives concernant les pages protégées]].\'\'\'',
+
+# History pages
+#
+'revhistory'   => 'Versions précédentes',
+'nohistory'    => 'Il n\'existe pas d\'historique pour cette page.',
+'revnotfound'  => 'Version introuvable',
+'revnotfoundtext' => 'La version précédente de cette page n\'a pas pu être retrouvée. Vérifiez l\'URL que vous avez utilisée pour accéder à cette page.',
+
+'loadhist'     => 'Chargement de l\'historique de la page',
+'currentrev'   => 'Version actuelle',
+'revisionasof' => 'Version du $1',
+'cur'    => 'actu',
+'next'   => 'suiv',
+'last'   => 'dern',
+'orig'   => 'orig',
+'histlegend' => 'Légende : (actu) = différence avec la version actuelle ,
+(dern) = différence avec la version précédente, <b>m</b> = modification mineure',
+'selectnewerversionfordiff' => 'Choisir une version plus récente',
+'selectolderversionfordiff' => 'Choisir une version plus ancienne',
+'previousdiff' => '← Différence précédente',
+'previousrevision' => '← Version précédente',
+'nextdiff' => 'Différence suivante →',
+'nextrevision' => 'Version suivante →',
+
+
+# Category pages
+#
+'categoriespagetext' => 'Les catégories suivantes existent sur le wiki :',
+'categoryarticlecount' => 'Il y a $1 articles dans cette catégorie.',
+'categoryarticlecount1' => 'Il y a $1 article dans cette catégorie.',
+
+
+#  Diffs
+#
+'difference' => '(Différences entre les versions)',
+'loadingrev' => 'chargement de l\'ancienne version pour comparaison',
+'lineno'  => 'Ligne $1:',
+'editcurrent' => 'Modifier la version actuelle de cette page',
+
+
+# Search results
+#
+'searchresults' => 'Résultat de la recherche',
+'searchresulttext' => 'Pour plus d\'informations sur la recherche dans {{SITENAME}}, voir [[Project:Recherche|Chercher dans {{SITENAME}}]].',
+'searchquery' => 'Pour la requête « $1 »',
+'badquery'  => 'Requête mal formulée',
+'badquerytext' => 'Nous n\'avons pas pu traiter votre requête.
+Vous avez probablement recherché un mot d\'une longueur inférieure à trois lettres, ce qui n\'est pas encore possible. Vous avez aussi pu faire une erreur de syntaxe, telle que « poisson et écailles ». 
+Veuillez essayer une autre requête.', // FIXME
+'matchtotals' => 'La requête « $1 » correspond à $2 titre(s) d\'article et au texte de $3 article(s).',
+'nogomatch' => 'Aucune page avec ce titre n\'existe, essai avec la recherche complète.',
+'titlematches' => 'Correspondances dans les titres',
+'notitlematches' => 'Aucun titre d\'article ne contient le(s) mot(s) demandé(s)',
+'textmatches' => 'Correspondances dans les textes',
+'notextmatches' => 'Aucun texte d\'article ne contient le(s) mot(s) demandé(s)',
+'prevn'   => '$1 précédents',
+'nextn'   => '$1 suivants',
+'viewprevnext' => 'Voir ($1) ($2) ($3).',
+'showingresults' => 'Affichage de <b>$1</b> résultats à partir du #<b>$2</b>.',
+'showingresultsnum' => 'Affichage de <b>$3</b> résultats à partir du #<b>$2</b>.',
+'nonefound'  => '<strong>Note</strong>: l\'absence de résultat est souvent due à l\'emploi de termes de recherche trop courants, comme « à » ou « de »,
+qui ne sont pas indexés, ou à l\'emploi de plusieurs termes de recherche (seules les pages
+contenant tous les termes apparaissent dans les résultats).',
+'powersearch' => 'Recherche',
+'powersearchtext' => 'Rechercher dans les espaces :<br />
+$1<br />
+$2 Inclure les page de redirections &nbsp; Rechercher $3 $9',
+'searchdisabled' => '<p>La fonction de recherche sur l\'intégralité du texte a été temporairement désactivée à cause de la grande charge que cela impose au serveur. Nous espérons la rétablir prochainement lorsque nous disposerons d\'un serveur plus puissant. En attendant, vous pouvez faire la recherche avec Google:</p>
+', // FIXME wikipedia specific
+'blanknamespace' => '(Principal)',     // FIXME FvdP: translation of "(Main)"
+
+# Preferences page
+#
+'preferences'       => 'Préférences',
+'prefsnologin'      => 'Non connecté',
+'prefsnologintext'  => 'Vous devez être [[Special:Userlogin|connecté]] pour modifier vos préférences d\'utilisateur.',
+'prefslogintext' => 'Je suis connecté(e) en tant que $1 avec le numéro d\'utilisateur $2.
+
+Voir [[{{ns:4}}:Aide pour les préférences]] pour les explications concernant les options.',
+'prefsreset'        => 'Les préférences ont été rétablies à partir de la version enregistrée.',
+'qbsettings'        => 'Personnalisation de la barre outils',
+'changepassword'    => 'Modification du mot de passe',
+'skin'              => 'Apparence',
+'math'                         => 'Rendu des maths',
+'dateformat'           => 'Format de date',
+'math_failure'         => 'Erreur math',
+'math_unknown_error'   => 'erreur indéterminée',
+'math_unknown_function'        => 'fonction inconnue',
+'math_lexing_error'    => 'erreur lexicale',
+'math_syntax_error'    => 'erreur de syntaxe',
+'math_image_error'     => 'La conversion en PNG a échouée, vérifiez l\'installation de Latex, dvips, gs et convert',
+'math_bad_tmpdir'      => 'Ne peux pas crééer ou écrire dans le répertoire temporaire',
+'math_bad_output'      => 'Ne peux pas crééer ou écrire dans le répertoire de sortie',
+'math_notexvc'         => 'L\'éxécutable « texvc » est introuvable. Lisez math/README pour le configurer.',
+'prefs-personal'    => 'Informations personnelles',
+'prefs-rc'          => 'Modifications récentes et affichage des ébauches',
+'prefs-misc'        => 'Préférences diverses',
+'saveprefs'         => 'Enregistrer les préférences',
+'resetprefs'        => 'Rétablir les préférences',
+'oldpassword'       => 'Ancien mot de passe',
+'newpassword'       => 'Nouveau mot de passe&nbsp;',
+'retypenew'         => 'Confirmer le nouveau mot de passe',
+'textboxsize'       => 'Taille de la fenêtre d\'édition',
+'rows'              => 'Rangées&nbsp;',
+'columns'           => 'Colonnes',
+'searchresultshead' => 'Affichage des résultats de recherche',
+'resultsperpage'    => 'Nombre de réponses par page&nbsp;',
+'contextlines'      => 'Nombre de lignes par réponse',
+'contextchars'      => 'Nombre de caractères de contexte par ligne',
+'stubthreshold'     => 'Taille minimale des articles courts',
+'recentchangescount' => 'Nombre de titres dans les modifications récentes',
+'savedprefs'        => 'Les préférences ont été sauvegardées.',
+'timezonelegend'    => 'Zone horaire',
+'timezonetext'      => 'Si vous ne précisez pas de décalage horaire, c\'est l\'heure de l\'Europe de l\'ouest qui sera utilisée.',
+'localtime'         => 'Heure locale',
+'timezoneoffset'    => 'Décalage horaire',
+'servertime'       => 'Heure du serveur',
+'guesstimezone'     => 'Utiliser la valeur du navigateur',
+'emailflag'         => 'Ne pas recevoir de courrier électronique<br /> des autres utilisateurs',
+'defaultns'         => 'Par défaut, rechercher dans ces espaces :',
+'yourlanguage' => 'Langue de l\'interface',
+
+# Recent changes
+#
+'changes'      => 'modifications',
+'recentchanges' => 'Modifications récentes',
+'recentchangestext' => "Suivez sur cette page les dernières modifications de {{SITENAME}}.
+[[{{ns:4}}:Bienvenue|Bienvenue]] aux nouveaux participants!
+Jetez un coup d'&oelig;il sur ces pages&nbsp;: [[{{ns:4}}:FAQ|foire aux questions]],
+[[{{ns:4}}:Recommandations et règles à suivre|recommandations et règles à suivre]]
+(notamment [[{{ns:4}}:Règles de nommage|conventions de nommage]],
+[[{{ns:4}}:La neutralité de point de vue|la neutralité de point de vue]]),
+et [[{{ns:4}}:Les faux-pas les plus courants|les faux-pas les plus courants]].
+
+Si vous voulez que {{SITENAME}} connaisse le succès, merci de ne pas y inclure pas de matériaux protégés par des [[{{ns:4}}:Copyright|copyrights]]. La responsabilité juridique pourrait en effet compromettre le projet. ",
+'rcloaderr'  => 'Chargement des dernières modifications',
+'rcnote'  => 'Voici les <strong>$1</strong> dernières modifications effectuées au cours des <strong>$2</strong> derniers jours.',
+'rcnotefrom'   => 'Voici les modifications effectuées depuis le <strong>$2</strong> (<b>$1</b> au maximum).',
+'rclistfrom'   => 'Afficher les nouvelles modifications depuis le $1.',
+# "rclinks"  => "Afficher les $1 dernières modifications effectuées au cours des $2 dernières heures / $3 derniers jours",
+# "rclinks"  => "Afficher les $1 dernières modifications effectuées au cours des $2 derniers jours.",
+'showhideminor' => '$1 modifications mineures | $2 robots | $3 utilisateurs enregistrés | $4 patrolled edits',
+'rclinks'      => 'Afficher les $1 dernières modifications effectuées au cours des $2 derniers jours; $3 modifications mineures.',
+'rchide'  => 'in $4 form; $1 modifications mineures; $2 espaces secondaires; $3 modifications multiples.', // FIXME
+'rcliu'        => '; $1 modifications par des contributeurs connectés',
+'diff'            => 'diff',
+'hist'            => 'hist',
+'hide'            => 'masquer',
+'show'            => 'montrer',
+'tableform'       => 'table',
+'listform'        => 'liste',
+'nchanges'        => '$1 modification(s)',
+'minoreditletter' => 'M',
+'newpageletter'   => 'N',
+
+# Upload
+#
+'upload'       => 'Copier sur le serveur',
+'uploadbtn'    => 'Copier un fichier',
+'uploadlink'   => 'Copier des images',
+'reupload'     => 'Copier à nouveau',
+'reuploaddesc' => 'Retour au formulaire.',
+
+'uploadnologin' => 'Non connecté(e)',
+'uploadnologintext' => 'Vous devez être [[Special:Userlogin|connecté]] pour copier des fichiers sur le serveur.',
+'uploaderror'  => 'Erreur',
+'uploadtext'   => "'''STOP !''' Avant de copier votre fichier sur le serveur,
+prenez connaissance des [[Project:règles d'utilisation des images|règles d'utilisation des images]] de {{SITENAME}} et assurez-vous que vous les respectez.<br />
+N'oubliez pas de remplir la [[Project:Page de description d'une image|page de description de l'image]] quand celle-ci sera sur le serveur.
+
+Pour voir les images déjà placées sur le serveur ou pour effectuer une recherche parmi celles-ci,
+allez à la [[Special:Imagelist|liste des images]].
+Les uploads et les suppressions sont listés dans le [[Project:Journal_des_uploads|journal des uploads]].
+
+Utilisez le formulaire ci-dessous pour copier sur le serveur de nouvelles images destinées à illustrer vos articles.
+Sur la plupart des navigateurs, vous verrez un bouton \"Browse...\" qui ouvre la fenêtre de dialogue standard de votre système d'exploitation pour l'ouverture des fichiers.
+Sélectionnez un fichier, son nom apparaîtra dans le champ situé à côté du bouton.
+Vous devez également confirmer, en cochant la case prévue à cet effet, que la copie de ce fichier ne viole aucun copyright.
+Cliquez sur le bouton \"Envoyer\" pour terminer.
+Si votre connexion est lente, l'opération peut prendre un certain temps.
+
+Les formats recommandés sont JPEG pour les photos, PNG
+pour les dessins et les autres images, et OGG pour les fichiers sonores.
+Donnez à vos fichiers des noms descriptifs clairs, afin d'éviter toute confusion.
+Pour incorporer l'image dans un article, placez dans celui-ci un lien rédigé comme suit:
+'''<nowiki>[[image:nom_du_fichier.jpg]]</nowiki>''' ou
+'''<nowiki>[[image:nom_du_fichier.png|autre texte]]</nowiki>''' ou
+'''<nowiki>[[media:nom_du_fichier.ogg]]</nowiki>''' pour les sons.
+
+N'oubliez pas que, comme toutes les pages de {{SITENAME}}, les fichiers que vous copiez peuvent être modifiés ou supprimés par les autres utilisateurs s'ils estiment que cela est dans l'intérêt du site. Sachez aussi que votre accès au serveur peut être bloqué si vous faites un mauvais usage du système.",
+'uploadlog'  => 'log d\'upload',
+'uploadlogpage' => 'Log_d\'upload',
+'uploadlogpagetext' => 'Voici la liste des derniers fichiers copiés sur le serveur.
+L\'heure indiquée est celle du serveur (UTC).
+<ul>
+</ul>
+',
+'filename'     => 'Nom',
+'filedesc'     => 'Description',
+'filestatus'   => 'Statut du copyright',
+'filesource'   => 'Source',
+'copyrightpage' => '{{ns:4}}:Copyright',
+'copyrightpagename' => 'licence {{SITENAME}}',
+'uploadedfiles' => 'Fichiers copiés',
+'ignorewarning' => 'Ignorer l\'avertissement et copier le fichier quand même.',
+'minlength'    => 'Les noms des images doivent comporter au moins trois lettres.',
+'illegalfilename'      => 'Le nom de fichier « $1 » contient des caractères interdits dans les titres de pages. Merci de le renommer et de le copier à nouveau.',
+'badfilename' => 'L\'image a été renommée « $1 ».',
+'badfiletype' => '« .$1 » n\'est pas un format recommandé pour les fichiers images.',
+'largefile'  => 'La taille maximale conseillée pour les images est de 100 ko.',
+'successfulupload' => 'Copie réussie',
+'fileuploaded' => 'Le fichier « $1 » a été copié sur le serveur.
+Suivez ce lien ($2) pour accéder à la page de description, et donner des informations sur le fichier, par exemple son origine, sa date de création, son auteur, ou tout autre renseignement en votre possession.',
+'uploadwarning' => 'Attention !',
+'savefile'  => 'Sauvegarder le fichier',
+'uploadedimage' => '« [[$1]] » copié sur le serveur',
+'uploaddisabled' => 'Désolé, l\'envoi de fichier est désactivé.',
+'uploadcorrupt' => 'Ce fichier est corrompu, a une taille nulle ou possède une extension invalide.
+Veuillez vérifer le fichier.',
+'fileexists' => 'Un fichier avec ce nom existe déjà. Merci de vérifier $1. Êtes-vous certain de vouloir modifier ce fichier ?',
+'filemissing' => 'Fichier non présent',
+
+
+# Image list
+#
+'imagelist'  => 'Liste des images',
+'imagelisttext' => 'Voici une liste de $1 images classées $2.',
+'getimagelist' => 'Récupération de la liste des images',
+'ilsubmit'  => 'Chercher',
+'showlast'  => 'Afficher les $1 dernières images classées $2.',
+'byname'  => 'par nom',
+'bydate'  => 'par date',
+'bysize'  => 'par taille',
+'imgdelete'  => 'suppr',
+'imgdesc'  => 'descr',
+'imglegend'  => 'Légende : (descr) = afficher/modifier la description de l\'image.',
+'imghistory' => 'Historique de l\'image',
+'revertimg'  => 'rétab',
+'deleteimg'  => 'suppr',
+'deleteimgcompletely'  => 'suppr',
+'imghistlegend' => 'Légende : (actu) = ceci est l\'image actuelle, (suppr) = supprimer
+cette ancienne version, (rétab) = rétablir cette ancienne version.
+<br /><i>Cliquez sur la date pour voir l\'image copiée à cette date</i>.',
+'imagelinks' => 'Liens vers l\'image',
+'linkstoimage' => 'Les pages ci-dessous comportent un lien vers cette image :',
+'nolinkstoimage' => 'Aucune page ne comporte de lien vers cette image.',
+'showbigimage' => 'Télécharger une version haute résolution ($1x$2, $3 Ko)',
+
+# Statistics
+
+'statistics' => 'Statistiques',
+'sitestats'  => 'Statistiques du site',
+'userstats'  => 'Statistiques utilisateur',
+'sitestatstext' => 'La base de données contient actuellement <b>$1</b> pages.
+
+Ce chiffre inclut les pages « discussion », les pages relatives à {{SITENAME}}, les pages minimales ("bouchons"),  les pages de redirection, ainsi que d\'autres pages qui ne peuvent sans doute pas être considérées comme des articles.
+Si l\'on exclut ces pages, il reste <b>$2</b> pages qui sont probablement de véritables articles.<p>
+<b>$3</b> pages ont été consultées et <b>$4</b> pages modifiées.
+
+Cela représente une moyenne de <b>$5</b> modifications par page et de <b>$6</b> consultations pour une modification.',
+'userstatstext' => 'Il y a <b>$1</b> utilisateurs enregistrés. Parmi ceux-ci, <b>$2</b> ont le statut d\'administrateur (voir $3).',
+
+
+# Maintenance Page
+#
+'maintenance'          => 'Page de maintenance',
+'maintnancepagetext'   => 'Cette page inclut plusieurs utilitaires pour la maintenance quotidienne. Certains de ces outils ont tendance à charger la base de données; ne rechargez pas la page a chaque modification.',
+'maintenancebacklink'  => 'Retour à la page de maintenance',
+'disambiguations'      => 'Pages d\'homonymie',
+'disambiguationspage'  => '{{ns:template}}:Homonymie',
+'disambiguationstext'  => 'Les articles suivants sont liés à une <i>page d\'homonymie</i>. Or, ils devraient être liés au sujet.<br />Une page est considérée comme page d\'homonymie si elle est liée à partir de $1.<br />Les liens à partir d\'autres <i>espaces</i> ne sont pas pris en compte.',
+'doubleredirects'      => 'Double redirection',
+'doubleredirectstext'  => '<b>Attention:</b> cette liste peut contenir des « faux positifs ». Dans ce cas, c\'est probablement la page du premier #REDIRECT contient aussi du texte.<br />Chaque ligne contient les liens à la 1re et 2e page de redirection, ainsi que la première ligne de cette dernière, qui donne normalement la « vraie » destination. Le premier #REDIRECT devrait lier vers cette destination.',
+'brokenredirects'      => 'Redirections cassées',
+'brokenredirectstext'  => 'Ces redirections mènent a une page qui n\'existe pas.',
+'selflinks'            => 'Page avec un lien circulaire',
+'selflinkstext'                => 'Les pages suivantes contiennent un lien vers elles-mêmes, ce qui n\'est pas permis.',
+'mispeelings'           => 'Pages avec fautes d\'orthographe',
+'mispeelingstext'               => 'Les pages suivantes contiennent une faute d\'orthographe courante (la liste de celles-ci est sur $1). L\'orthographe correcte est peut-être (ceci).',
+'mispeelingspage'       => 'Liste de fautes d\'orthographe courantes',
+
+# FIXME les 3 messages suivants ne sont plus utilisés (plus de page Special:Intl)
+'missinglanguagelinks'  => 'Liens inter-langues manquants',
+'missinglanguagelinksbutton'    => 'Je n\'ai pas trouvé de lien/langue pour cette page',
+'missinglanguagelinkstext'      => 'Ces articles ne lient pas à leur contrepartie sur $1. Les redirections et les liens ne sont pas affichés.',
+
+
+# Miscellaneous special pages
+#
+'orphans'       => 'Pages orphelines',
+'lonelypages'   => 'Pages orphelines',
+'unusedimages'  => 'Images orphelines',
+'popularpages'  => 'Pages les plus consultées',
+'nviews'        => '$1 consultations',
+'wantedpages'   => 'Pages les plus demandées',
+'nlinks'        => '$1 références',
+'allpages'      => 'Toutes les pages',
+'randompage'    => 'Une page au hasard',
+'shortpages'    => 'Articles courts',
+'longpages'     => 'Articles longs',
+'listusers'     => 'Liste des participants',
+'specialpages'  => 'Pages spéciales',
+'spheading'     => 'Pages spéciales',
+'protectpage'   => 'Protéger la page',
+'recentchangeslinked' => 'Suivi des liens',
+'rclsub'        => '(des pages liées à « $1 »)',
+'debug'         => 'Déboguer',
+'newpages'      => 'Nouvelles pages',
+'ancientpages' => 'Articles les plus anciens',
+'move'         => 'renommer',
+'movethispage'  => 'Renommer la page',
+'unusedimagestext' => '<p>N\'oubliez pas que d\'autres sites, comme certains Wikipédias non francophones, peuvent contenir un lien direct vers cette image, et que celle-ci peut être placée dans cette liste alors qu\'elle est en réalité utilisée.',
+'booksources'   => 'Ouvrages de référence',
+'booksourcetext' => 'Voici une liste de liens vers d\'autres sites qui vendent des livres neufs et d\'occasion et sur lesquels vous trouverez peut-être des informations sur les ouvrages que vous cherchez. {{SITENAME}} n\'étant liée à aucune de ces sociétés, elle n\'a aucunement l\'intention d\'en faire la promotion.',
+'alphaindexline' => '$1 à $2',
+'version' => 'Version',
+
+# All pages
+#
+'allinnamespace' => 'Toutes les pages (espace $1)',
+'allpagesnext' => 'Suivant',
+'allpagesprev' => 'Précédent',
+'allpagessubmit' => 'Valider',
+
+# Email this user
+#
+'mailnologin' => 'Pas d\'adresse',
+'mailnologintext' => 'Vous devez être [[Special:Userlogin|connecté]]
+et avoir indiqué une adresse électronique valide dans vos [[Special:Preferences|préférences]]
+pour pouvoir envoyer un message à un autre utilisateur.',
+'emailuser'  => 'Envoyer un message à cet utilisateur',
+'emailpage'  => 'Envoyer un email à l\'utilisateur',
+'emailpagetext' => 'Si cet utilisateur a indiqué une adresse électronique valide dans ses préférences, le formulaire ci-dessous lui enverra un message.
+L\'adresse électronique que vous avez indiquée dans vos préférences apparaîtra dans le champ « Expéditeur » de votre message afin que le destinataire puisse vous répondre.',
+'noemailtitle' => 'Pas d\'adresse électronique',
+'noemailtext' => 'Cet utilisateur n\'a pas spécifié d\'adresse électronique valide ou a choisi de ne pas recevoir de courrier électronique des autres utilisateurs.',
+
+'emailfrom'  => 'Expéditeur',
+'emailto'  => 'Destinataire',
+'emailsubject' => 'Objet',
+'emailmessage' => 'Message',
+'emailsend'  => 'Envoyer',
+'emailsent'  => 'Message envoyé',
+'emailsenttext' => 'Votre message a été envoyé.',
+'usermailererror' => 'Erreur de mail :',
+'defemailsubject' => 'courriel envoyé depuis {{SITENAME}}',
+
+# Watchlist
+#
+'watchlist'    => 'Liste de suivi',
+'watchlistsub' => '(pour l\'utilisateur « $1 »)',
+'nowatchlist'  => 'Votre liste de suivi ne contient aucun article.',
+'watchnologin' => 'Non connecté',
+'watchnologintext' => 'Vous devez être [[Special:Userlogin|connecté]] pour modifier votre liste.',
+'addedwatch'   => 'Ajouté à la liste',
+'addedwatchtext' => 'La page « $1 » a été ajoutée à votre [[Special:Watchlist|liste de suivi]].
+Les prochaines modifications de cette page et de la page discussion associée seront répertoriées ici, et la page apparaîtra \'\'\'en gras\'\'\' dans la [[Special:Recentchanges|liste des modifications récentes]] pour être repérée plus facilement.
+
+Pour supprimer cette page de votre liste de suivi, cliquez sur « Ne plus suivre » dans le cadre de navigation.',
+'removedwatch' => 'Supprimée de la liste de suivi',
+'removedwatchtext' => 'La page « $1 » a été supprimée de votre liste de suivi.',
+'watch'                => 'Suivre',
+'watchthispage'        => 'Suivre cette page',
+'unwatch'      => 'Ne plus suivre',
+'unwatchthispage' => 'Ne plus suivre',
+'notanarticle' => 'Aucun article',
+'watchnochange' => "Aucune des pages que vous suivez n'a été modifiée pendant la période affichée",
+'watchdetails' => 'Vous suivez $1 pages, sans compter les pages de discussion.  [$4 Afficher et modifier la liste complète].',
+'watchmethod-recent' => 'vérification des modifications récentes des pages suivies',
+'watchmethod-list' => 'vérification des pages suivies pour des modifications récentes',
+'removechecked' => 'Retirer de la liste de suivi les articles sélectionnés',
+'watchlistcontains' => 'Votre liste de suivi contient $1 pages',
+'watcheditlist' => 'Ceci est votre liste de suivi par ordre alphabétique. Sélectionnez les pages que vous souhaitez retirer de la liste et cliquez le bouton « retirer de la liste de suivi » en bas de l\'écran.',
+'removingchecked' => 'Les articles sélectionnés sont retirés de votre liste de suivi...',
+'couldntremove' => 'Impossible de retirer l\'article « $1 »...',
+'iteminvalidname' => 'Problème avec l\'article « $1 » : le nom est invalide...',
+'wlnote' => 'Ci-dessous se trouvent les $1 dernières modifications depuis les <b>$2</b> dernières heures.',
+'wlshowlast' => 'Montrer les dernières $1 heures $2 jours $3',
+'wlsaved' => 'La liste de suivi n\'est remise à jour qu\'une fois par heure pour alléger la charge sur le serveur.',
+
+# Delete/protect/revert
+#
+'deletepage'   => 'Supprimer une page',
+'confirm'      => 'Confirmer',
+'excontent'    => 'contenant « $1 »',
+'exbeforeblank' => 'Avant son blanchiment, cette page contenait : $1',
+'exblank'      => 'page vide',
+'confirmdelete' => 'Confirmer la suppression',
+'deletesub'    => '(Suppression de « $1 »)',
+'historywarning' => 'Attention : La page que vous êtes sur le point de supprimer a un historique : ',
+'confirmdeletetext' => 'Vous êtes sur le point de supprimer définitivement de la base de données une page ou une image, ainsi que toutes ses versions antérieures.
+
+Veuillez confirmer que c\'est bien là ce que vous voulez faire, que vous en comprenez les conséquences et que vous faites cela en accord avec les [[{{ns:4}}:Recommandations Et Règles à  Suivre|recommandations et règles à suivre]].',
+'actioncomplete' => 'Suppression effectuée',
+'deletedtext'  => '« $1 » a été supprimé.
+Voir $2 pour une liste des suppressions récentes.',
+'deletedarticle' => 'a effacé « $1 »',
+'dellogpage'   => 'Historique des effacements',
+'dellogpagetext' => 'Voici la liste des suppressions récentes.
+L\'heure indiquée est celle du serveur (UTC).',
+'deletionlog'  => 'historique des effacements',
+'reverted'     => 'Rétablissement de la version précédente',
+'deletecomment' => 'Motif de la suppression',
+'imagereverted' => 'La version précédente a été rétablie.',
+'rollback'     => 'révoquer modifications',
+'rollback_short' => 'Révoquer',
+'rollbacklink' => 'révoquer',
+'rollbackfailed' => 'La révocation a échoué',
+'cantrollback' => 'Impossible de révoquer : dernier auteur est le seul à avoir modifié cet article',
+'alreadyrolled'        => 'Impossible de révoquer la dernière modification de « $1 » effectuée par [[User:$2|$2]] ([[User talk:$2|Talk]]); quelqu\'un d\'autre à déjà modifer ou révoquer l\'article.
+
+La dernière modificaion a été effectuée par [[User:$3|$3]] ([[User talk:$3|Talk]]).', // FIXME: namespaces
+#   only shown if there is an edit comment
+'editcomment' => 'Le résumé de la modification était: <i>« $1 »</i>.',
+'revertpage'   => 'restitution de la dernière modification de $1',
+'protectlogpage' => 'Log_de_protection',
+'protectlogtext' => "Voir les [[{{ns:4}}:Page protégée|directives concernant les pages protégées]].",
+'protectedarticle' => 'a protégé [[$1]]',
+'unprotectedarticle' => 'a déprotégé [[$1]]',
+
+'protectsub' => '(Protéger « $1 »)',
+'confirmprotect' => 'Confirmer la protection',
+'confirmprotecttext' => 'Voulez-vous réellement protéger cette page ?',
+'protectcomment' => 'Raison du bloquage',
+
+'unprotectsub' => '(Débloque « $1 »)',
+'confirmunprotecttext' => 'Voulez-vous réellement déprotéger cette page ?',
+'confirmunprotect' => 'Raison de la déprotection',
+'unprotectcomment' => 'Raison du débloquage',
+'protectmoveonly' => 'Protéger uniquement les déplacements',
+
+
+# Groups
+#
+'addgroup' => 'Ajouter un groupe',
+'editgroup' => 'Modification du groupe',
+'editusergroup' => 'Modification des groupes utilisateurs',
+
+# Special:Undelete
+#
+'undelete'     => 'Restaurer la page effacée',
+'undeletepage' => 'Voir et restaurer la page effacée',
+'undeletepagetext' => 'Ces pages ont été effacées et se trouvent dans la corbeille, elles sont toujours dans la base de donnée et peuvent être restaurées.
+La corbeille peut être effacée périodiquement.',
+
+'undeletearticle' => 'Restaurer les articles effacés',
+'undeleterevisions' => '$1 révisions archivées',
+'undeletehistory' => 'Si vous restaurez la page, toutes les révisions seront restaurées dans l\'historique.
+
+Si une nouvelle page avec le même nom a été crée depuis la suppression, les révisions restaurées apparaîtront dans l\'historique antérieur et la version courante ne sera pas automatiquement remplacée.',
+'undeleterevision' => 'Version effacée ($1)',
+'undeletebtn'  => 'Restaurer!',
+'undeletedarticle' => 'restauré « $1 »',
+'undeletedtext'   => 'L\'article [[$1]] a été restauré avec succès.
+
+Voir [[{{ns:4}}:Trace des effacements]] pour la liste des suppressions et des restaurations récentes.',
+'undeletedrevisions' => '$1 versions ont été restaurées',
+
+# Contributions
+#
+'contributions'        => 'Contributions',
+'mycontris'    => 'Mes contributions',
+'contribsub'   => 'Pour $1',
+'nocontribs'   => 'Aucune modification correspondant à ces critères n\'a été trouvée.',
+'ucnote'       => 'Voici les <b>$1</b> dernières modifications effectuées par cet utilisateur au cours des <b>$2</b> derniers jours.',
+'uclinks'      => 'Afficher les $1 dernières modifications; afficher les $2 derniers jours.',
+'uctop'                => ' (dernière)',
+
+# What links here
+#
+'whatlinkshere' => 'Pages liées',
+'notargettitle' => 'Pas de cible',
+'notargettext' => 'Indiquez une page cible ou un utilisateur cible.',
+'linklistsub'  => '(Liste de liens)',
+'linkshere'    => 'Les pages ci-dessous contiennent un lien vers celle-ci :',
+'nolinkshere'  => 'Aucune page ne contient de lien vers celle-ci.',
+'isredirect'   => 'page de redirection',
+
+# Block/unblock IP
+#
+'blockip'      => 'Bloquer une adresse IP ou un utilisateur',
+'blockiptext'  => 'Utilisez le formulaire ci-dessous pour bloquer l\'accès en écriture à partir d\'une adresse IP donnée ou d\'un nom d\'utilisateur.
+
+Une telle mesure ne doit être prise que pour empêcher le vandalisme et en accord avec [[{{ns:4}}:Recommandations et règles à suivre|recommandations et règles à suivre]].
+Donnez ci-dessous une raison précise (par exemple en indiquant les pages qui ont été vandalisées).',
+'ipaddress'    => 'Adresse IP ou pseudonyme',
+'ipbreason'    => 'Motif du blocage',
+'ipbsubmit'    => 'Bloquer cette adresse',
+'badipaddress' => 'L\'adresse IP n\'est pas correcte.',
+'blockipsuccesssub' => 'Blocage réussi',
+'blockipsuccesstext' => 'L\'adresse IP « $1 » a été bloquée.<br />Vous pouvez consulter sur cette [[Special:Ipblocklist|page]] la liste des adresses IP bloquées.',
+'unblockip'    => "Débloquer une adresse IP",
+'unblockiptext' => 'Utilisez le formulaire ci-dessous pour rétablir l\'accès en écriture
+à partir d\'une adresse IP précédemment bloquée.',
+'ipusubmit'    => 'Débloquer cette adresse',
+'ipusuccess'   => 'L\'adresse IP « $1 » débloquée.',
+'ipblocklist'  => 'Liste des blocages',
+'blocklistline' => '$1 (expire le $4): $2 a bloqué $3',
+'blocklink'    => 'bloquer',
+'unblocklink'  => 'débloquer',
+'contribslink' => 'contribs',
+'autoblocker'  => 'Bloqué automatiquement parce que vous partagez une adresse IP avec « $1 ». Raison : « $2 ».',
+'blocklogpage' => 'Log de blocage',
+'blocklogentry'        => 'blocage de « $1 »',
+'blocklogtext' => 'Ceci est la trace des blocages et déblocages des utilisateurs. Les adresses IP automatiquement bloquées ne sont pas listées. Consultez la [[Special:Ipblocklist|liste des utilisateurs bloqués]] pour voir qui est actuellement effectivement bloqué.',
+'unblocklogentry'      => 'déblocage de « $1 »',
+'ipb_expiry_invalid' => 'temps d\'expiration invalide.',
+'ip_range_invalid' => 'Bloc IP incorrect.',
+'proxyblocker' => 'Bloqueur de proxy',
+'proxyblockreason' => 'Votre ip a été bloquée car c\'est un proxy ouvert. Merci de contacter votre fournisseur d\'accès internet ou votre support technique et de l\'informer de ce problème de sécurité.',
+'proxyblocksuccess' => 'Terminé.',
+'ipbexpiry' => 'Durée du blocage',
+
+# Developer tools
+#
+'lockdb'  => 'Verrouiller la base',
+'unlockdb'  => 'Déverrouiller la base',
+'lockdbtext' => 'Le verrouillage de la base de données empêchera tous les utilisateurs de modifier des pages, de sauvegarder leurs préférences, de modifier leur liste de suivi et d\'effectuer toutes les autres opérations nécessitant des modifications dans la base de données.
+Veuillez confirmer que c\'est bien là ce que vous voulez faire et que vous débloquerez la base dès que votre opération de maintenance sera terminée.',
+'unlockdbtext' => 'Le déverrouillage de la base de données permettra à nouveau à tous les utilisateurs de modifier des pages, de mettre à jour leurs préférences et leur liste de suivi, ainsi que d\'effectuer les autres opérations nécessitant des modifications dans la base de données.
+
+Veuillez confirmer que c\'est bien là ce que vous voulez faire.',
+'lockconfirm' => 'Oui, je confirme que je souhaite verrouiller la base de données.',
+'unlockconfirm' => 'Oui, je confirme que je souhaite déverrouiller la base de données.',
+
+'lockbtn'  => 'Verrouiller la base',
+'unlockbtn'  => 'Déverrouiller la base',
+'locknoconfirm' => 'Vous n\'avez pas coché la case de confirmation.',
+'lockdbsuccesssub' => 'Verrouillage de la base réussi.',
+'unlockdbsuccesssub' => 'Base déverrouillée.',
+'lockdbsuccesstext' => 'La base de données de {{SITENAME}} est verrouillée.
+
+N\'oubliez pas de la déverrouiller lorsque vous aurez terminé votre opération de maintenance.',
+'unlockdbsuccesstext' => 'La base de données de {{SITENAME}} est déverrouillée.',
+
+# Special:Makesysop
+'bureaucratlog'                => 'Log_bureaucrate',
+'bureaucratlogentry'   => 'Droits de l\'utilisateur « $1 » mis à « $2 »',
+'makesysoptitle'       => 'Donne les droits d\'adminitrateur.',
+'makesysoptext'                => 'Ce formulaire est utilisé par les bureaucrates pour donner les droits d\'administrateur.
+Tapez le nom de l\'utilisateur dans la boite et pressez le bouton pour lui donner les droits.',
+'makesysopname'                => 'Nom de l\'utilisateur:',
+'makesysopsubmit'      => 'Donner les droits d\'adminitrateur à cet utilisateur',
+'makesysopok'          => '<b>L\'utilisateur « $1 » est désormais administrateur.</b>',
+'makesysopfail'                => '<b>L\'utilisateur « $1 » n\'a pas pu recevoir les droits d\'adminitrateurs. (Avez vous entré le nom correctement?)</b>',
+'rights'                       => 'Droits:',
+'set_user_rights'      => 'Met les droits de l\'utilisateur',
+'user_rights_set'      => '<b>Les droits de l\'utilisateur « $1 » sont mis à jour</b>',
+'setbureaucratflag'    => 'Ajouter le statut de bureaucrate',
+'set_rights_fail'      => '<b>Les droits de l\'utilisateur « $1 » n\'ont pas pu être mis en place. (Avez vous entré le nom correctement?)</b>',
+'makesysop'         => 'Donner les droits d\'adminitrateur à un utilisateur',
+
+# Special:Validate
+'val_article_lists' => 'Liste d\'articles validés',
+'val_clear_old' => 'Supprimer mes données de validation pour $1',
+'val_details_th_user' => 'Utilisateur $1',
+'val_merge_old' => 'Utiliser mes précédents choix pour les choix marqués \'Sans opinion\'',
+'val_no_anon_validation' => 'Vous devez être identifié pour valider un article.',
+'val_no' => 'Non',
+'val_noop' => 'Sans opinion',
+'val_page_validation_statistics' => 'Statistiques de validation pour $1',
+'val_percent' => '<b>$1%</b><br />($2 sur $3 points<br />par $4 utilisateurs)',
+'val_percent_single' => '<b>$1%</b><br />($2 sur $3 points<br />par un utilisateur)',
+'val_rev_for' => 'Correction pour $1',
+'val_revision' => 'Révision',
+'val_show_my_ratings' => 'Voir mes validations',
+'val_stat_link_text' => 'Statistiques de validation pour cet article',
+'val_table_header' => "<tr><th>Class</th>$1<th colspan=4>Opinion</th>$1<th>Commentaire</th></tr>\n",
+'val_tab' => 'Valider',
+'val_this_is_current_version' => 'ceci est la dernière version',
+'val_total' => 'Total',
+'val_user_validations' => 'Cet utilisateur a validé $1 pages.',
+'val_validate_article_namespace_only' => 'Seul les articles peuvent être validés. Cette page n\'est <i>pas</i> un article.',
+'val_validated' => 'Validation effectuée.',
+'val_validate_version' => 'Valider cette version',
+'val_version_of' => 'Version de $1' ,
+'val_version' => 'Version',
+'val_view_version' => 'Voir cette version',
+'val_yes' => 'Oui',
+
+
+# Spam
+#
+'spamprotectionmatch' => 'Le texte suivant a déclenché le détecteur de spam: $1',
+'spamprotectiontext' => 'Page automatiquement protégée pour cause de spam',
+'spamprotectiontitle' => 'Page automatiquement protégée pour cause de spam',
+
+# Patrolling
+#
+'markaspatrolleddiff' => 'Marquer comme vérifiée',
+'markaspatrolledtext' => 'Marquer cet article comme vérifié',
+'markedaspatrolled' => 'Marqué comme vérifié',
+'markedaspatrolledtext' => 'La version sélectionnée a été marquée comme vérifiée.',
+'rcpatroldisabledtext' => 'La fonctionnalité de surveillance des modifications récentes n\'est pas activée.',
+
+# Move page
+#
+'movepage'  => 'Renommer un article',
+'movepagetext' => 'Utilisez le formulaire ci-dessous pour renommer un article, en déplaçant toutes ses versions antérieures vers le nouveau nom.
+
+Le titre précédent deviendra une page de redirection vers le nouveau titre. Les liens vers l\'ancien titre ne seront pas modifiés et la page discussion, si elle existe, ne sera pas déplacée.
+
+\'\'\'ATTENTION!\'\'\'
+Il peut s\'agir d\'un changement radical et inattendu pour un article souvent consulté; assurez-vous que vous en comprenez bien les conséquences avant de procéder.',
+'movepagetalktext' => 'La page de discussion associée, si présente, sera automatiquement renommée avec \'\'\'sauf si:\'\'\'
+*Vous renommez une page vers un autre espace,
+*Une page de discussion existe déjà avec le nouveau nom, ou
+*Vous avez désélectionné le bouton ci-dessous.
+
+Dans ce cas, vous devrez renommer ou fusionner la page manuellement si vous le désirez.',
+
+'movearticle'  => 'Déplacer l\'article',
+'movenologin'  => 'Non connecté',
+'movenologintext' => 'Pour pouvoir renommer un article, vous devez être [[Special:Userlogin|connecté]] en tant qu\'utilisateur enregistré.',
+'newtitle'     => 'Nouveau titre',
+'movepagebtn'  => 'Renommer l\'article',
+'pagemovedsub' => 'Déplacement réussi',
+'pagemovedtext' => 'L\'article « [[$1]] » a été déplacé vers « [[$2]] ».',
+'articleexists' => 'Il existe déjà un article portant ce titre, ou le titre que vous avez choisi n\'est pas valide. Veuillez en choisir un autre.',
+'talkexists'   => 'La page elle-même a été déplacée avec succès, mais la page de discussion n\'a pas pu être déplacée car il en existait déjà une sous le nouveau nom. S\'il vous plait, fusionnez les manuellement.',
+'1movedto2_redir' => '$1 déplacé vers $2 (redirect)',
+'movedto'  => 'renommé en',
+'movetalk'  => 'Renommer aussi la page « discussion », s\'il y a lieu.',
+'talkpagemoved' => 'La page discussion correspondante a également été déplacée.',
+'talkpagenotmoved' => 'La page discussion correspondante n\'a <strong>pas</strong> été déplacée.',
+'1movedto2' => '$1 déplacé vers $2',
+'movereason' => 'Raison du déplacement',
+
+
+# Export page
+'export'       => 'Exporter des pages',
+'exporttext'   => 'Vous pouvez exporter en XML le texte et l\'historique d\'une page ou d\'un ensemble de pages; le résultat peut alors être importé dans un autre wiki fonctionnant avec le logiciel MediaWiki, transformé ou sauvegardé pour votre usage personnel.',
+'exportcuronly'        => 'Exporter uniquement la version courante sans l\'historique',
+
+# Namespace 8 related
+
+'allmessages'  => 'Tous les messages',
+'allmessagestext'      => 'Ceci est la liste de tous les messages disponibles dans l\'espace MediaWiki',
+
+# Thumbnails
+
+'thumbnail-more'       => 'Agrandir',
+'missingimage'         => '<b>Image manquante</b><br /><i>$1</i>',
+
+# Special:Import
+'import'       => 'Importer des pages',
+'importfailed' => 'Échec de l\'import : $1',
+'importhistoryconflict' => 'Il y a un conflit dans l\'historique des versions (cette page à peut être déjà été importée avant)',
+'importnotext' => 'Vide ou sans texte',
+'importsuccess'        => 'L\'import a réussi !',
+'importtext'   => 'Exportez un fichier depuis le wiki source en utilisant la fonction Special:Export, sauvez la page sur votre disque puis envoyez là ici.',
+
+# Keyboard access keys for power users
+'accesskey-compareselectedversions' => 'v',
+'accesskey-minoredit'          => 'i',
+'accesskey-preferences'                => '',
+'accesskey-preview'                    => 'p',
+'accesskey-save'                       => 's',
+'accesskey-search'                     => 'f',
+
+# tooltip help for the main actions
+'tooltip-compareselectedversions' => 'Voir les différences entre les deux versions séléctionnées de cette page. [alt-v]',
+'tooltip-minoredit' => 'Marquer cette modification comme mineur [alt-i]',
+'tooltip-save' => 'Sauvegarder vos modifications [alt-s]',
+'tooltip-search' => 'Rechercher dans ce wiki',
+
+# Metadata
+'nocreativecommons' => 'Les données méta « Creative Commons RDF » sont désactivées sur ce serveur.',
+'nodublincore' => 'Les données méta « Dublin Core RDF » sont désactivées sur ce serveur.',
+'notacceptable' => 'Ce serveur wiki ne peut pas fournir les données dans un format que votre client est capable de lire.',
+
+# Attribution
+'anonymous'    => 'Utilisateur(s) anonyme(s) de {{SITENAME}}',
+'siteuser'     => 'Utilisateur $1 de {{SITENAME}}',
+'lastmodifiedby' => 'Cette page a été modifiée pour la dernière fois le $1 par $2',
+'and'  => 'et',
+'contributions' => 'Basé sur le travail de $1.',
+'siteusers'    => 'Utilisateur(s) $1 de {{SITENAME}}',
+'creditspage' => 'Page crédits',
+
+# confirmemail
+'confirmemail' => 'Confirmer email',
+'confirmemail_text' => 'Ce wiki nécessite la vérification de votre adresse email avant de pouvoir utiliser toute fonction de messagerie. Utilisez le bouton ci dessous pour envoyer un email de confirmation à votre adresse. L\'email contiendra un lien contenant un code, chargez ce lien dans votre navigateur pour valider votre adresse.',
+'confirmemail_send' => 'Envoyer un code de confirmation',
+'confirmemail_sent' => 'Email de confirmation envoyé',
+'confirmemail_sendfailed' => 'Impossible d\'envoyer l\'email de confirmation. Vérifiez votre adresse.',
+'confirmemail_invalid' => 'Code de confirmation incorrect. Le code a peut être expiré',
+'confirmemail_success' => 'Votre email est confirmée. Vous pouvez maintenant vous connecter et profiter du wiki.',
+'confirmemail_loggedin' => 'Votre adresse est maintenant confirmée',
+'confirmemail_error' => 'Un problème est survenu en voulant enregistrer votre confirmation',
+'confirmemail_subject' => '{{SITENAME}} email address confirmation',
+'confirmemail_body' => 'Quelqu\'un, probablement vous avec l\'adresse email $1, a enregistré un compte « $2 » avec cette email sur le site {{SITENAME}}.
+
+Pour confirmer que ce compte vous appartient vraiment et activer les fonctions de messagerie sur {{SITENAME}}, veuillez suivre le lien ci dessous dans votre navigateur :
+
+$3
+
+Si il ne s\'agit pas de vous, n\'ouvrez pas le lien. Ce code de confirmation expirera le $4.',
+
+
+# Math
+'mw_math_html' => 'HTML si possible, autrement PNG',
+'mw_math_mathml' => 'MathML',
+'mw_math_modern' => 'Pour les navigateurs modernes',
+'mw_math_png' => 'Toujours produire une image PNG',
+'mw_math_simple' => 'HTML si très simple, autrement PNG',
+'mw_math_source' => 'Laisser le code TeX original',
+
+
+'usercssjsyoucanpreview' => "'''Astuce :''' utilisez le bouton '''Prévisualisation''' pour tester votre nouvelle feuille css/js avant de l'enregistrer.",
+'usercsspreview' => "'''Rappelez-vous que vous êtes en train de prévisualiser votre propre feuille css et qu'elle n'a pas encore été enregistrée !'''",
+'userjspreview' => "'''Rappelez-vous que vous êtes en train de visualiser ou de tester votre code javascript et qu'il n'a pas encore été enregistré !'''",
+'validate' => 'Valider la page',
+
+# EXIF
+'exif-imagewidth' => 'Largeur',
+'exif-imagelength' => 'Hauteur',
+'exif-compression' => 'Type de compression',
+'exif-samplesperpixel' => 'Nombre d\'échantillons',
+'exif-xresolution' => 'Résolution de l\'image en largeur',
+'exif-yresolution' => 'Résolution de l\'image en hauteur',
+'exif-jpeginterchangeformat' => 'Position du SOI JPEG',
+'exif-jpeginterchangeformatlength' => 'Taille en octet des données JPEG',
+'exif-transferfunction' => 'Fonction de transfert',
+'exif-datetime' => 'Date et heure de changement du fichier',
+'exif-imagedescription' => 'Titre de l\'image',
+'exif-make' => 'Fabricant de l\'appareil',
+'exif-model' => 'Modèle de l\'appareil',
+'exif-software' => 'Logiciel utilisé',
+'exif-artist' => 'Auteur',
+'exif-copyright' => 'Détenteur du copyright',
+'exif-exifversion' => 'Version exif',
+'exif-makernote' => 'Notes du fabricant',
+'exif-relatedsoundfile' => 'Fichier audio lié',
+'exif-flash' => 'Flash',
+'exif-whitebalance' => 'Balance des blancs',
+'exif-contrast' => 'Contraste',
+'exif-saturation' => 'Saturation',
+'exif-compression-1' => 'Sans compression',
+'exif-orientation-1' => 'Normal',
+'exif-orientation-2' => 'Inversée horizontalement',
+'exif-orientation-3' => 'Tournée de 180°',
+'exif-orientation-4' => 'Inversée verticalement',
+'exif-orientation-5' => 'Tournée de 90° à gauche et inversée verticalement',
+'exif-orientation-6' => 'Tournée de 90° à droite',
+'exif-orientation-7' => 'Tournée de 90° à droite et inversée verticalement',
+'exif-orientation-8' => 'Tournée de 90° à gauche',
+'exif-componentsconfiguration-0' => 'n\'existe pas',
+
+
+// exifgps:
+
+);
+
+class LanguageFr extends LanguageUtf8 {
+
+       function getBookstoreList () {
+               global $wgBookstoreListFr ;
+               return $wgBookstoreListFr ;
+       }
+
+       function getNamespaces() {
+               global $wgNamespaceNamesFr;
+               return $wgNamespaceNamesFr;
+       }
+
+       function getNsIndex( $text ) {
+               global $wgNamespaceNamesFr, $wgSitename;
+
+               foreach ( $wgNamespaceNamesFr as $i => $n ) {
+                       if ( 0 == strcasecmp( $n, $text ) ) { return $i; }
+               }
+               if( $wgSitename == 'Wikipédia' ) {
+                       if( 0 == strcasecmp( 'Wikipedia', $text ) ) return 4;
+                       if( 0 == strcasecmp( 'Discussion_Wikipedia', $text ) ) return 5;
+               }
+               return false;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsFr;
+               return $wgQuickbarSettingsFr;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesFr;
+               return $wgSkinNamesFr;
+       }
+
+       function date( $ts, $adj = false ) {
+               if ( $adj ) { $ts = $this->userAdjust( $ts ); }
+
+               $d = (0 + substr( $ts, 6, 2 )) . ' ' .
+                 $this->getMonthAbbreviation( substr( $ts, 4, 2 ) ) .
+                 ' ' . substr( $ts, 0, 4 );
+               return $d;
+       }
+
+       function timeanddate( $ts, $adj = false ) {
+               return $this->date( $ts, $adj ) . ' à ' . $this->time( $ts, $adj );
+       }
+
+       var $digitTransTable = array(
+               ',' => "\xc2\xa0", // @bug 2749
+               '.' => ','
+       );
+
+       function formatNum( $number ) {
+               global $wgTranslateNumerals;
+               return $wgTranslateNumerals ? strtr($number, $this->digitTransTable ) : $number;
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesFr, $wgAllMessagesEn;
+               if( isset( $wgAllMessagesFr[$key] ) ) {
+                       return $wgAllMessagesFr[$key];
+               } else {
+                       return parent::getMessage( $key );
+               }
+       }
+
+}
+
+?>
diff --git a/languages/LanguageFur.php b/languages/LanguageFur.php
new file mode 100644 (file)
index 0000000..3351a85
--- /dev/null
@@ -0,0 +1,682 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+require_once( 'LanguageUtf8.php' );
+
+/* private */ $wgNamespaceNamesFur = array(
+       NS_MEDIA                        => 'Media',
+       NS_SPECIAL                      => 'Speciâl',
+       NS_MAIN                         => '',
+       NS_TALK                         => 'Discussion',
+       NS_USER                         => 'Utent',
+       NS_USER_TALK                    => 'Discussion_utent',
+       NS_PROJECT                      => $wgMetaNamespace,
+       NS_PROJECT_TALK                 => 'Discussion_'.$wgMetaNamespace,
+       NS_IMAGE                        => 'Figure',
+       NS_IMAGE_TALK                   => 'Discussion_figure',
+       NS_MEDIAWIKI                    => 'MediaWiki',
+       NS_MEDIAWIKI_TALK               => 'Discussion_MediaWiki',
+       NS_TEMPLATE                     => 'Model',
+       NS_TEMPLATE_TALK                => 'Discussion_model',
+       NS_HELP                         => 'Jutori',
+       NS_HELP_TALK                    => 'Discussion_jutori',
+       NS_CATEGORY                     => 'Categorie',
+       NS_CATEGORY_TALK                => 'Discussion_categorie'
+) + $wgNamespaceNamesEn;
+
+
+
+/* private */ $wgQuickbarSettingsFur = array(
+       'Nissune', 'Fis a Çampe', 'Fis a Drete', 'Flutuant a çampe'
+);
+
+/* private */ $wgSkinNamesFur = array(
+       'nostalgia'             => 'Nostalgie',
+) + $wgSkinNamesEn;
+
+$wgAllMessagesFur = array(
+'1movedto2'            => "$1 movût in $2",
+'about' => "Informazions",
+'aboutsite' => "Informazions su {{SITENAME}}",
+'addedwatch'           => "Zontât aes pagjinis tignudis di voli",
+'addedwatchtext'       => "La pagjine \"$1\" e je stade zontade ae [[Special:Watchlist|liste di chês tignudis di voli]].
+Tal futûr i cambiaments a cheste pagjine e ae pagjine di discussion relative a saran segnalâts ca,
+e la pagjine e sarà '''gruessute''' te [[Special:Recentchanges|liste dai ultins cambiaments]] cussì che tu puedis notâle daurman.
+
+<p>Se tu vuelis gjavâle de liste pi indevant, frache su \"No stâ tignî di voli\" te sbare in alt.",
+
+'administrators' => "Project:Aministradôrs",
+'allarticles' => "Ducj i articui",
+'allinnamespace'       => "Dutis lis pagjinis (non dal spazi $1)",
+'allmessages' => "Ducj i messaçs di sisteme",
+'allmessagescurrent' => "Test curint",
+'allmessagesdefault' => "Test predeterminât",
+'allmessagesname' => "Non",
+'allmessagestext'      => "Cheste e je une liste dai messaçs di sisteme disponibii tal non dal spazi MediaWiki:",
+'allnonarticles'       => "Ducj i no-articui",
+'allnotinnamespace'    => "Dutis lis pagjinis (no tal non dal spazi $1)",
+'allpages' => "Dutis lis pagjinis",
+'allpagesfrom'         => "Mostre pagjinis scomençant di:",
+'allpagesnext'         => "Prossim",
+'allpagesprev'         => "Precedent",
+'allpagessubmit' => "Va",
+'and' => 'e',
+'anontalk'             => 'Discussion par chest IP',
+'anonymous' => 'Utent(s) anonim(s) di {{SITENAME}}',
+'apr' => "Avr",
+'april' => "Avrîl",
+'articleexists' => 'Une pagjine cun chest non e esist za, o il non sielt nol è valit.
+Sielç par plasê un altri non.',
+'aug' => "Avo",
+'august' => "Avost",
+'badfilename'  => 'File non gambiât in "$1".',
+'badretype'            => "Lis peraulis clâfs inseridis no son compagnis.",
+'blockedtitle' => 'Utent blocât',
+'blocklink' => "bloche",
+'bold_sample'=>'Test in gruessut',
+'bold_tip'=>'Test in gruessut',
+'byname'               => 'par non',
+'bydate'               => 'par date',
+'bysize'               => 'par dimension',
+'cancel' => "Scancele",
+'categories' => "Categoriis",
+'categoriespagetext' => 'Te wiki a esistin lis categoriis ca sot.',
+'category' => "categorie",
+'category_header' => "Articui inte categorie \"$1\"",
+'categoryarticlecount' => "In cheste categorie tu puedis cjatâ $1 articui.",
+'categoryarticlecount1' => "In cheste categorie tu puedis cjatâ $1 articul.",
+'changepassword' => 'Gambie peraule clâf',
+'changes' => 'cambiaments',
+'compareselectedversions' => 'Confronte versions selezionadis',
+'confirm' => "Conferme",
+'confirmdelete' => "Conferme eliminazion",
+'confirmprotect' => "Conferme protezion",
+'confirmprotecttext' => "Vuelistu pardabon protezi cheste pagjine?",
+'confirmunprotect' => "Conferme par gjavâ la protezion",
+'confirmunprotecttext' => "Vuelistu pardabon gjavâ la protezion a cheste pagjine?",
+'contextlines' => 'Riis par risultât',
+'contributions' => "Contribûts dal utent",
+'contribsub'    => "Par $1",
+'contribs-showhideminor' => '$1 piçulis modifichis',
+'copyright' => "Il contignût al è disponibil sot de $1",
+'copyrightwarning' => "<!-- Perché i link non abbiano l'aspetto di link esterni: -->
+<div class=\"plainlinks\">
+
+<div style=\"margin-top:2em\">
+<div style=\"font-weight: bold; font-size: 120%;\">I cambiaments che tu âs fat a saran visibii daurman.</div>
+* Par plasê, dopre la [[Vichipedie:Sandbox|sandbox]] se tu vuelis fâ cualchi prove.
+----
+<p style=\"background: red; color: white; font-weight: bold; text-align: center; padding: 2px;\">'''NO ST DOPR MATERIÂL CUVIERT DAL DIRIT DI AUTÔR (COPYRIGHT - ©) SE NO TU ÂS UNE AUTORIZAZION ESPLICITE!!!'''</p></div>
+
+* Sta atent, par plasê, che ducj i contribûts ae Vichipedie a son considerâts come dâts fûr sot di une licence GNU Free Documentation License (cjale $1 par altris detais).
+* Se no tu vuelis che il to test al puedi jessi gambiât e tornât a jessi distribuît da cualsisei persone cence limits, no stâ mandâlu ae Vichipedie, al è miôr se tu ti fasis un to sît web personâl.
+* Inviant chest test, tu stâs garantint che chest al è stât scrit di te in origjin, o che al è stât copiât di une sorzint di public domini, o alc   di simil, opûr che tu âs vût une autorizazion esplicite pe publicazion e  tu puedis dimostrâ chest fat.
+</div>
+
+</div>",
+'createaccount' => "Cree une gnove identitât",
+'createarticle' => "Cree articul",
+'creditspage' => 'Pagjine dai ricognossiments',
+'cur' => "cor",
+'currentevents' => "Lis gnovis",
+'data' => 'Dâts',
+'dateformat'           => 'Formât de date',
+'deadendpages'  => 'Pagjinis cence usite',
+'dec' => "Dic",
+'december' => "Dicembar",
+'default' => "predeterminât",
+'delete' => "Elimine",
+'delete_and_move' => 'Elimine e môf',
+'deletecomment'        => 'Reson pe eliminazion',
+'deletedarticle' => "eliminât \"$1\"",
+'deletedtext'  => "\"$1\" al è stât eliminât.
+Cjale $2 par une liste des ultimis eliminazions.",
+'deleteimg' => "eli",
+'deletepage' => "Elimine pagjine",
+'deletesub' => "(Eliminant \"$1\")",
+'deletethispage' => "Elimine cheste pagjine",
+'deletionlog'  => 'regjistri eliminazions',
+'dellogpage'   => 'Regjistri des eliminazions',
+'destfilename' => 'Non dal file di destinazion',
+'diff' => "difarencis",
+'difference' => "(Difarence jenfri des revisions)",
+'disambiguations'      => 'Pagjinis di disambiguazion',
+'disambiguationspage'  => 'Template:disambig',
+'disclaimers' => "Avîs legâi",
+'doubleredirects'      => 'Reindirizaments doplis',
+'edit-externally' => 'Modifiche chest file cuntune aplicazion esterne',
+'edit-externally-help' => 'Cjale [http://meta.wikimedia.org/wiki/Help:External_editors setup instructions] par altris informazions.',
+'edit' => "Modifiche",
+'editcurrent'  => 'Modifiche la version corinte di cheste pagjine',
+'editing' => "Modificant $1",
+'edithelp'             => "Jutori pe modifiche",
+'edithelppage' => "Jutori:Modifiche",
+'editingsection' => "Modificant $1 (sezion)",
+'editsection' => "modifiche",
+'editthispage' => "Modifiche cheste pagjine",
+'emailflag'            => 'No vueli email da altris utents',
+'emailmessage' => "Messaç",
+'emailuser' => "Messaç di pueste a chest utent",
+'error' => "Erôr",
+'errorpagetitle' => "Erôr",
+'exbeforeblank' => "il contignût prime di disvuedâ al jere: '$1'",
+'exblank' => 'pagjine vueide',
+'excontent' => "il contignût al jere: '$1'",
+'excontentauthor' => "il contignût al jere: '$1' (e al veve contribuît dome '$2')",
+'export' => "Espuarte pagjinis",
+'exportcuronly'        => 'Inclût dome la revision corinte, no dut il storic',
+'feb' => "Fev",
+'february' => "Fevrâr",
+'filedesc' => "Descrizion",
+'fileinfo' => '$1KB, gjenar MIME: <code>$2</code>',
+'filemissing' => "File mancjant",
+'filename' => "Non dal file",
+'filenotfound' => "No si pues cjatâ il file \"$1\".",
+'filesource' => 'Surzint',
+'filestatus' => 'Stât dal copyright',
+'friday' => "Vinars",
+'go' => "Va",
+'googlesearch' => "
+<div style=\"margin-left: 2em\">
+
+<!-- Google search -->
+<div style=\"width:130px;float:left;text-align:center;position:relative;top:-8px\"><a href=\"http://www.google.com/\" style=\"padding:0;background-image:none\"><img src=\"http://www.google.com/logos/Logo_40wht.gif\" alt=\"Google\" style=\"border:none\" /></a></div>
+
+<form method=\"get\" action=\"http://www.google.com/search\" style=\"margin-left:135px\">
+  <div>
+    <input type=\"hidden\" name=\"domains\" value=\"{{SERVER}}\" />
+    <input type=\"hidden\" name=\"num\" value=\"50\" />
+    <input type=\"hidden\" name=\"ie\" value=\"$2\" />
+    <input type=\"hidden\" name=\"oe\" value=\"$2\" />
+
+    <input type=\"text\" name=\"q\" size=\"31\" maxlength=\"255\" value=\"$1\" />
+    <input type=\"submit\" name=\"btnG\" value=\"Cîr cun Google\" />
+  </div>
+  <div style=\"font-size:90%\">
+    <input type=\"radio\" name=\"sitesearch\" id=\"gwiki\" value=\"{{SERVER}}\" checked=\"checked\" /><label for=\"gwiki\">{{SITENAME}}</label>
+    <input type=\"radio\" name=\"sitesearch\" id=\"gWWW\" value=\"\" /><label for=\"gWWW\">WWW</label>
+  </div>
+</form>
+
+</div>",
+'guesstimezone' => "Cjape impostazions dal sgarfadôr",
+'help' => "Jutori",
+'helppage' => "Jutori:Contignûts",
+'hide' => "plate",
+'hidetoc' => "plate",
+'hist' => "storic",
+'history' => "Storic de pagjine",
+'history_copyright' => "-",
+'history_short' => "Storic",
+'historywarning' => 'Atenzion: la pagjine che tu stâs eliminant e à un storic.',
+'hr_tip' => "Rie orizontâl (no stâ doprâle masse spes)",
+'ilsubmit' => "Cîr",
+'image_sample' => "Esempli.jpg",
+'imagelinks' => "Leams de figure",
+'imagelist' => "Liste des figuris",
+'imagelistall' => 'ducj',
+'imagelisttext'        => "Ca sot e je une liste di $1 files ordenâts $2.",
+'imagepage' => "Cjale pagjine de figure",
+'imgdelete' => "eli",
+'imgdesc' => "desc",
+'imghistlegend' => "Legenda: (cor) = cheste e je la figure corinte, (eli) = elimine
+cheste vecje version, (rip) = torne a ripristinâ cheste vecje version.
+<br /><i>Frache su une date par viodi la figure cjamade su chê volte</i>.",
+'imghistory' => "Storic de figure",
+'imglegend' => "Legenda: (desc) = mostre/modifiche descrizion de figure.",
+'import'       => 'Impuarte pagjinis',
+'importfailed' => "Impuartazion falide: $1",
+'importnotext' => "Vueit o cence test",
+'importsuccess'        => 'Impuartât cun sucès!',
+'info_short' => "Informazions",
+'infosubtitle' => 'Informazions pe pagjine',
+'intl'         => 'Leams interlengâi',
+'invert' => "Invertìs selezion",
+'ipbsubmit' => "Bloche chest utent",
+'isbn' => "ISBN",
+'isredirect' => "pagjine di reindirizament",
+'italic_sample'=>'Test in corsîf',
+'italic_tip'=>'Test in corsîf',
+'jan' => "Zen",
+'january' => "Zenâr",
+'jul' => "Lui",
+'jun' => "Zug",
+'june' => "Zugn",
+'largefile' => "Si racomande che lis figuris no sedin pi grandis di 100KB.",
+'last' => "ultime",
+'lastmodified' => "Modificât par l'ultime volte il ai $1",
+'lastmodifiedby' => "Modificât par l'ultime volte ai $1 di",
+'lineno' => "Rie $1:",
+'link_sample' => "Titul dal leam",
+'link_tip' => "Leams internis",
+'linklistsub' => "(Liste di leams)",
+'linkshere' => "Lis pagjinis ca sot a son leadis a cheste:",
+'linkstoimage' => "Lis pagjinis ca sot a son leadis a cheste figure:",
+'linktrail' => "/^([a-z]+)(.*)$/sD",
+'listform' => "liste",
+'listingcontinuesabbrev' => " cont.",
+'listusers' => "Liste dai utents",
+'lockbtn' => "Bloche base di dâts",
+'lockdb' => "Bloche base di dâts",
+'log'          => 'Regjistris',
+'login' => "Jentre",
+'loginend' => "&nbsp;",
+'loginerror' => "Erôr te jentrade",
+'loginpagetitle' => "Jentrade dal utent",
+'loginreqtitle'        => 'Si scugne jentrâ',
+'loginreqpagetext'     => 'Tu scugnis [[{{ns:special}}:Userlogin|jentrâ\']] par viodi lis altris pagjinis.',
+'loginsuccess' => "Cumò tu sês jentrât te {{SITENAME}} sicu \"$1\".",
+'loginsuccesstitle' => "Jentrât cun sucès",
+'logout' => "Jes",
+'lonelypages'  => 'Pagjinis solitaris',
+'longpages'            => 'Pagjinis lungjis',
+'mailmypassword'       => "Mandimi une gnove peraule clâf",
+'mainpage' => "Pagjine principâl",
+'math'                 => 'Matematiche',
+'may' => "Mai",
+'may_long' => "Mai",
+'media_sample' => "Esempli.mp3",
+'media_tip' => "Leam a un file multimediâl",
+'minlength' => "Il non di une figure al à di jessi lunc al mancul trê letaris.",
+'minoredit' => "Cheste e je une piçule modifiche",
+'minoreditletter' => "p",
+'missingimage'         => "<b>Figure mancjante</b><br /><i>$1</i>\n",
+'monday' => "Lunis",
+'Monobook.css' => '/* modifiche chest file par personalizâ la mascare monobook par dut il sît */',
+'moredotdotdot'        => 'Plui...',
+'move' => "Môf",
+'movearticle' => "Môf l'articul",
+'movedto' => "Movude in",
+'movelogpage' => 'Regjistri des pagjinis movudis',
+'movelogpagetext' => 'Ca sot e je une liste des pagjinis movudis.',
+'movenologin' => "No tu sês jentrât",
+'movenologintext' => "Tu âs di jessi un utent regjistrât e <a href=\"{{localurl:Special:Userlogin}}\">jentrât</a> par movi une pagjine.",
+'movepage' => "Môf pagjine",
+'movepagetext' => 'Cun il formulari ca sot tu puedis gambiâ il non a une pagjine, movint dut il sô storic al gnûf non.
+Il vieri titul al deventarà une pagjine di reindirizament al gnûf titul. I leams ae vecje pagjine no saran gambiâts; verifiche
+par plasê che no sedin reindirizaments doplis o no funzionants.
+Tu sês responsabil che i leams a continui a mandâ tal puest just.
+
+Note che la pagjine \'\'\'no\'\'\' sarà movude se e je za une pagjine cul gnûf titul, a mancul che no sedi vueide o un reindirizament e
+cence un storic. Chest al vûl dî che tu puedis tornâ a movi la pagjine tal titul precedent, se
+tu \'nd âs sbaliât e che no tu puedis sorescrivi une pagjine esistìnte.
+
+<b>ATENZION!</b>
+Chest al pues jessi un cambiament drastic e surprendint par une pagjine popolâr;
+tu âs di cognossi lis conseguencis prime di lâ indevant.',
+'movepagebtn' => "Môf pagjine",
+'movereason'   => 'Reson',
+'movetalk'             => 'Môf ancje la pagjine di discussion, se pussibil.',
+'movethispage' => "Môf cheste pagjine",
+'mw_math_png' => 'Torne simpri PNG',
+'mw_math_simple' => 'HTML se une vore sempliç, se no PNG',
+'mw_math_html' => 'HTML se pussibil se no PNG',
+'mw_math_source' => 'Lassile come TeX (par sgarfadôrs testuâi)',
+'mw_math_modern' => 'Racomandât pai sgarfadôrs testuâi',
+'mw_math_mathml' => 'MathML se pussibil (sperimentâl)',
+'mycontris' => "Miei contribûts",
+'mypage' => "Mê pagjine",
+'mytalk' => "Mês discussions",
+'navigation' => "somari",
+'nbytes' => "$1 bytes",
+'namespace' => 'Non dal spazi:',
+'nchanges' => "$1 cambiaments",
+'newarticle' => "(Gnûf)",
+'newarticletext' => "Tu âs seguît un leam a une pagjine che no esist ancjemò. Par creâ une pagjine, scomence a scrivi tal spazi ca sot (cjale il [[Jutori:Contignûts|jutori]] par altris informazions). Se tu sês ca par erôr, frache semplicementri il boton '''Indaûr''' dal to sgarfadôr.",
+'newimages' => "Galarie dai gnûfs files",
+'newmessages' => "Tu âs $1.",
+'newmessageslink' => "gnûf(s) messaç(s)",
+'newpage' => "Gnove pagjine",
+'newpageletter' => "G",
+'newpages' => "Gnovis pagjinis",
+'newpassword'  => 'Gnove peraule clâf',
+'newtitle' => "Al gnûf titul",
+'newusersonly' => "(dome gnûfs utents)",
+'newwindow' => "(al vierç un gnûf barcon)",
+'nextdiff' => "Prossime difarence &rarr;",
+'nlinks' => "$1 leams",
+'noarticletext' => "(Par cumò nol è nuie in cheste pagjine)",
+'nocontribs'    => 'Nissun cambiament che al rispiete chescj criteris cjatât.',
+'nocredits' => 'Nissune informazion sui ricognossiments disponibil par cheste pagjine.',
+'nogomatch' => "No esist nissune pagjine cun chest titul esat, provant la ricercje in dut il test.",
+'nohistory' => "Nol è presint un storic des modifichis par cheste pagjine.",
+'noimages' => "Nuie di viodi.",
+'nolinkshere' => "Nissune pagjine e à leams a chest articul",
+'nolinkstoimage' => 'No son pagjinis leadis a chest file.',
+'nowatchlist'          => 'No tu stâs tignint di voli nissun element.',
+'nov' => "Nov",
+'november' => "Novembar",
+'nowatchlist' => "Nissun element al è tignût di voli.",
+'nstab-category' => "Categorie",
+'nstab-help' => "Jutori",
+'nstab-image' => "Figure",
+'nstab-main' => "Articul",
+'nstab-media' => "Media",
+'nstab-mediawiki' => "Messaç",
+'nstab-special' => "Speciâl",
+'nstab-template' => "Model",
+'nstab-user' => "Pagjine dal utent",
+'nstab-wp' => "Informazions",
+'numauthors' => 'Numar di autôrs diviers (articul): $1',
+'numedits' => 'Numar di modifichis (articul): $1',
+'numtalkauthors' => 'Numar di autôrs diviers (pagjine di discussion): $1',
+'numtalkedits' => 'Numar di modifichis (pagjine di discussion): $1',
+'numwatchers' => 'Numar di chei che e àn cjalât: $1',
+'oct' => "Otu",
+'october' => "Otubar",
+'ok' => "OK",
+'oldpassword'  => 'Vecje peraule clâf',
+'orig' => "orig",
+'orphans'              => 'Pagjinis solitaris',
+'othercontribs' => 'Basât sul lavôr di $1.',
+'otherlanguages' => "Altris lenghis",
+'others' => 'altris',
+'pagemovedsub' => 'Movude cun sucès',
+'pagemovedtext' => "Pagjine \"[[$1]]\" movude in \"[[$2]]\".",
+'passwordtooshort' => "La tô peraule clâf e je masse curte, e à di jessi lungje almancul $1 caratars.",
+'popularpages' => 'Pagjinis popolârs',
+'portal' => "Ostarie",
+'portal-url' => "Vichipedie:Ostarie",
+'poweredby' => "{{SITENAME}} e dopre [http://www.mediawiki.org/ MediaWiki], un motôr wiki a risultive vierte.",
+'powersearch' => "Cîr",
+'powersearchtext' => "
+Cîr tai nons dai spazis :<br />
+$1<br />
+$2 Liste redirezions &nbsp; Cîr $3 $9",
+'preferences' => "Preferencis",
+'prefs-personal' => 'Dâts utents',
+'prefs-rc' => 'Ultins cambiaments & stubs',
+'prefs-misc' => 'Variis',
+'prefs-help-realname'  => "* Non vêr (opzionâl): se tu sielzis di inserîlu al vignarà doprât par dâti un ricognossiment dal tô lavôr.",
+'prefs-help-email'      => "* Email (opzionâl): Permet ai altris di contatâti vie la to pagjine utent o di discussion cence scugnî mostrâ a ducj la tô identitât.",
+'prefslogintext' => "Tu sês jentrât come \"$1\".
+Il to numar identificatîf interni al è $2.
+
+Cjale [[Project:Preferencis utent]] par un aiût a lis diviersis opzions.",
+'preview' => "Anteprime",
+'previewnote' => "Visiti che cheste e je dome une anteprime, e no je stade ancjemò salvade!",
+'previousdiff' => "&larr; Difarence precedente",
+'printableversion' => "Version stampabil",
+'printsubtitle' => "(Articul dal sît {{SERVER}})",
+'protect' => "Protêç",
+'protectcomment' => "Reson pe protezion",
+'protectedarticle' => "$1 protezût",
+'protectedpage' => "Pagjine protezude",
+'protectedtext' => "Cheste pagjine e je stade blocade par prevignî la modifiche; a son
+diviersis resons par chest fat, cjale par plasê
+[[Project:Pagjinis protezudis]].
+
+Tu puedis instès viodi e copiâ la risultive di cheste pagjine:",
+'protectmoveonly' => "Protêç dome dai spostaments",
+'protectpage' => "Protêç pagjine",
+'protectsub' => "(Protezint \"$1\")",
+'protectthispage' => "Protêç cheste pagjine",
+'qbbrowse' => "Sgarfe",
+'qbedit' => "Modifiche",
+'qbfind' => "Cjate",
+'qbmyoptions'  => "Mês pagjinis",
+'qbpageinfo'   => "Contest",
+'qbpageoptions' => "Cheste pagjine",
+'qbsettings' => "Sbare svelte",
+'qbspecialpages' => "Pagjinis speciâls",
+'randompage' => "Une pagjine a câs",
+'rclinks' => "Mostre i ultins $1 cambiaments tes ultimis $2 zornadis<br />$3",
+'rclistfrom' => "Mostre i ultins cambiaments dal $1",
+'rcnote' => "Ca sot tu cjatis i ultins <strong>$1</strong> cambiaments tes ultimis <strong>$2</strong> zornadis.",
+'recentchanges' => "Ultins cambiaments",
+'recentchangesall' => 'ducj',
+'recentchangescount' => "Numar di titui tai ultins cambiaments",
+'recentchangeslinked' => "Cambiaments leâts",
+'recentchangestext' => "Cheste pagjine e mostre i plui recents cambiaments inte Vichipedie.",
+'rclsub'               => "(aes pagjinis leadis di \"$1\")",
+'redirectedfrom' => "(Inviât ca di $1)",
+'remembermypassword' => "Visiti di me",
+'removedwatch'         => 'Gjavade de liste',
+'removedwatchtext'     => "La pagjine \"$1\" e je stade gjavade de liste di chês tignudis di voli.",
+'resetprefs'   => 'Predeterminât',
+'restorelink' => "$1 modifichis eliminadis",
+'restrictedpheading'   => 'Pagjinis speciâls cun restrizions',
+'resultsperpage' => 'Risultâts par pagjine',
+'retrievedfrom' => "Cjapât fûr di $1",
+'returnto' => "Torne a $1.",
+'retypenew'            => 'Torne a scrivi chê gnove',
+'reupload' => "Torne a cjamâ sù",
+'revertimg' => "rip",
+'revertmove'   => 'ripristine',
+'revhistory' => "Storic des revisions",
+'rows' => "Riis",
+'saturday' => "Sabide",
+'savearticle' => "Salve la pagjine",
+'savedprefs' => "Lis preferencis a son stadis salvadis",
+'savefile' => "Salve file",
+'saveprefs' => "Salve lis preferencis",
+'scarytranscludedisabled' => '[Inclusion dai interwikis no ative]',
+'scarytranscludefailed' => '[Recupar dal model falît par $1; o si scusin]',
+'scarytranscludetoolong' => '[URL masse lungje; o si scusin]',
+'search' => "Cîr",
+'searchresults' => "Risultâts de ricercje",
+'searchresulttext' => "Par plui informazions su lis ricercjis in {{SITENAME}}, cjale [[Project:Ricercje|Ricercje in {{SITENAME}}]].",
+
+'sep' => "Set",
+'september' => "Setembar",
+'sharedupload' => 'Chest file al è condivîs e al pues jessi doprât di altris progjets.',
+'shareduploadwiki' => 'Cjale par plasê la [pagjine di descrizion dal file $1] par altris informazions.',
+'shareddescriptionfollows' => '-',
+'shortpages'   => 'Pagjinis curtis',
+'show' => "mostre",
+'showbigimage' => "Discjame version a alte risoluzion ($1x$2, $3 KB)",
+'showdiff'     => 'Mostre cambiaments',
+'showhideminor' => "$1 piçulis modifichis | $2 bots | $3 utents jentrâts | $4 modifichis verificadis",
+'showlast'             => "Mostre i ultins $1 files ordenâts $2.",
+'showpreview' => "Mostre anteprime",
+'showtoc' => "mostre",
+'sig_tip' => "La tô firme cun ore e date",
+'sitestats' => "Statistichis dal sît",
+'sitestatstext' => "Tu puedis cjatâ in dut '''$1''' pagjine inte base di dâts.
+Chest numar al inclût pagjinis \"discussion\", pagjinis su la {{SITENAME}}, pagjinis cun pocjis peraulis, reindirizaments, e altris che probabilmentri no si puedin considerâ pardabon come pagjinis di contignût.
+Gjavant chestis, o vin '''$2''' pagjinis che a son probabilmentri pagjinis di contignût legjitimis.
+
+O vin vût in dut '''$3''' viodudis de pagjinis e '''$4''' modifichis aes pagjinis di cuant che la wiki e je stade implantade.
+Chest al vûl dî une medie di '''$5''' modifichis par pagjine, e '''$6''' viodudis par modifiche.",
+'sitesubtitle' => "L'enciclopedie libare",
+'sitesupport' => 'Doninus',
+'sitesupport-url' => 'Project:Supuarte il sît',
+'siteuser' => 'Utent di {{SITENAME}} $1',
+'siteusers' => 'Utents di {{SITENAME}} $1',
+'skin'                 => 'Mascare',
+'sourcefilename' => 'Non dal file origjinâl',
+'specialloguserlabel' => "Utent:",
+'speciallogtitlelabel' => "Titul: ",
+'specialpage' => "Pagjine speciâl",
+'specialpages' => "Pagjinis speciâls",
+'spheading'            => 'Pagjinis speciâls par ducj i utents',
+'statistics' => "Statistichis",
+'subcategories' => "Sot categoriis",
+'successfulupload' => "Cjamât sù cun sucès",
+'summary' => "Somari",
+'sunday' => "Domenie",
+'tableform' => "tabele",
+'tagline' => "Di {{SITENAME}}",
+'talk' => "Discussion",
+'talkexists'   => "'''La pagjine e je stade movude cun sucès, ma no si à podût movi la pagjine di discussion parcè che e esist za tal gnûf titul. Trasferìs il contignût a man par plasê.'''",
+'talkpage' => "Fevelin di cheste pagjine",
+'talkpagemoved' => "Ancje la pagjine di discussion corispondente e je stade movude.",
+'talkpagenotmoved' => "La pagjine di discussion corispondente <strong>no</strong> je stade movude.",
+'templatesused' => "Modei doprâts par cheste pagjine:",
+'textboxsize' => "Modifiche",
+'thisisdeleted' => "Vuelistu cjalâ o ripristinâ $1?",
+'thumbnail-more' => "Slargje",
+'thursday' => "Joibe",
+'timezonelegend' => "Fûs orari",
+'toc' => "Indis",
+'tog-highlightbroken' => 'Mostre leams sbaliâts <a href="" class="new">cussì</a> (invezit di cussì<a href="" class="internal">?</a>).',
+'tog-justify'  => 'Justifiche paragraf',
+'tog-hideminor' => 'Plate modifichis piçulis tai ultins cambiaments',
+'tog-usenewrc' => 'Ultins cambiaments avanzâts (JavaScript)',
+'tog-numberheadings' => 'Numerazion automatiche dai titui',
+'tog-editondblclick' => 'Modifiche pagjinis fracant dôs voltis (JavaScript)',
+'tog-editsection'              => 'Inserìs un leam [modifiche] pe editazion veloç di une sezion',
+'tog-editsectiononrightclick'  => 'Modifiche une sezion fracant cul tast diestri<br /> sui titui des sezions (JavaScript)',
+'tog-showtoc'                  => 'Mostre indis (par pagjinis cun plui di 3 sezions)',
+'tog-editwidth' => 'Il spazi pe modifiche al è larc il plui pussibil',
+'tog-minordefault' => 'Imposte come opzion predeterminade dutis lis modifichis come piçulis',
+'tog-previewontop' => 'Mostre anteprime parsore dal spazi pe modifiche',
+'tog-previewonfirst' => 'Mostre anteprime te prime modifiche',
+'tog-nocache' => 'No stâ tignî in memorie (caching) lis pagjinis',
+'tog-enotifwatchlistpages'     => 'Mandimi une email se la pagjine e gambie',
+'tog-enotifusertalkpages'      => 'Mandimi une email cuant che la mê pagjine di discussion e gambie',
+'tog-enotifminoredits'                 => 'Mandimi une email ancje pes modifichis piçulis ae pagjine',
+'tog-enotifrevealaddr'                 => 'Distapone fûr il gno recapit email tai messaçs di notifiche',
+'tog-shownumberswatching'      => 'Mostre il numar di utents che a stan tignint di voli',
+'tog-fancysig' => 'Firmis crudis (cence leam automatic)',
+'tog-externaleditor' => 'Dopre editôr esterni come opzion predeterminade',
+'tog-externaldiff' => 'Dopre editôr difarencis esterni come opzion predeterminade',
+'tog-rememberpassword' => 'Visiti tes prossimis sessions',
+'tog-showtoolbar'              => 'Mostre sbare dai imprescj di modifiche (JavaScript)',
+'tog-underline' => 'Sotlinee leams',
+'tog-watchdefault' => 'Zonte pagjinis che o modifichi inte liste di chês tignudis di voli',
+'toolbox' => "imprescj",
+'tooltip-compareselectedversions' => 'Viôt lis difarencis framieç lis dôs versions di cheste pagjine selezionadis. [alt-v]',
+'tooltip-diff' => 'Mostre i cambiaments che tu âs fat al test. [alt-d]',
+'tooltip-minoredit' => "Segne cheste come une piçule modifiche [alt-i]",
+'tooltip-preview' => "Anteprime dai tiei cambiaments, doprile par plasê prime di salvâ! [alt-p]",
+'tooltip-save' => "Salve i tiei cambiaments [alt-s]",
+'tooltip-search' => "Cîr in cheste wiki [alt-f]",
+'tooltip-watch' => "Zonte cheste pagjine ae liste di chês tignudis di voli [alt-w]",
+'tuesday' => "Martars",
+'ucnote'        => "Ca sot a son i ultins <b>$1</b> cambiaments dal utent tes ultimis <b>$2</b> zornadis.",
+'uclinks'       => "Viôt i ultins $1 cambiaments; viôt lis ultimis $2 zornadis.",
+'uctop' => " (su)",
+'uncategorizedpages'   => 'Pagjinis cence categorie',
+'uncategorizedcategories'      => 'Categoriis cence categorie',
+'underline-always' => "Simpri",
+'underline-never' => "Mai",
+'underline-default' => "Predeterminât dal sgarfadôr",
+'unusedimages' => 'Files no doprâts',
+'unwatch' => 'No stâ tignî di voli',
+'unwatchthispage'      => 'No stâ tignî di voli plui',
+'updated' => "(Inzornât)",
+'upload' => "Cjame sù un file",
+'uploadbtn' => "Cjame sù un file",
+'uploaddisabled' => "Nus displâs, par cumò no si pues cjamâ sù robe.",
+'uploadedfiles' => "Files cjamâts sù",
+'uploadedimage' => "cjamât sù \"$1\"",
+'uploaderror' => "Erôr cjamant sù",
+'uploadlink' => "Cjame sù figuris",
+'uploadlog'            => 'regjistri cjamâts sù',
+'uploadlogpagetext' => 'Ca sot e je une liste dai file cjamâts su di recent.',
+'uploadnologin' => 'No jentrât',
+'userexists'   => "Il non utent inserît al è za doprât. Sielç par plasê un non diferent.",
+'userlogin' => "Regjistriti o jentre",
+'userlogout' => "Jes",
+'userpage' => "Cjale pagjine dal utent",
+'userstats' => "Statistichis dai utents",
+'userstatstext'  => "A son '''$1''' utents regjistrâts, di chescj '''$2''' (il '''$4%''') a son aministradôrs (cjale $3).",
+'val_tab' => "Convalide",
+'val_version' => "Version",
+'val_version_of' => "Version di $1",
+'val_view_version' => "Cjale cheste version",
+'validate' => "Convalide la pagjine",
+'version' => "Version",
+'viewcount' => "Cheste pagjine e je stade viodude $1 voltis.",
+'viewprevnext' => "Cjale ($1) ($2) ($3).",
+'viewsource' => "Cjale risultive",
+'wantedpages'  => 'Pagjinis desideradis',
+'watch' => "Ten di voli",
+'watchlist' => "Tignûts di voli",
+'watchlistall1' => "ducj",
+'watchlistall2' => "dutis",
+'watchlistcontains' => "Tu stâs tignint di voli $1 pagjinis.",
+'watchlistsub'         => "(par l'utent \"$1\")",
+'watchnochange'        => 'Nissun element di chei tignûts di voli al è stât modificât tal periodi mostrât.',
+'watchdetails'         => "* $1 pagjinis tignudis di voli cence contâ lis pagjinis di discussion
+* [[Special:Watchlist/edit|Mostre e modfiche la liste complete]]",
+'watchnologin'         => 'No tu sês jentrât',
+'watchnologintext'     => "Tu 'nd âs di [[Speciâl:Userlogin|jentrâ]] par modificâ la liste des pagjinis tignudis di voli.",
+'watchthis' => "Ten di voli cheste pagjine",
+'watchthispage' => "Ten di voli cheste pagjine",
+'wednesday' => "Miercus",
+'welcomecreation' => "== Mandi e benvignût $1! ==
+
+La tô identitât e je stade creade. No stâ dismenteâti di gambiâ lis preferencis de {{SITENAME}}.",
+'whatlinkshere' => "Leams a chest articul",
+'wikipediapage' => "Cjale pagjine dal progjet",
+'wlheader-enotif'              => "* Notifiche par email ativade.",
+'wlheader-showupdated'   => "* Lis pagjinis gambiadis de ultime volte che tu lis âs cjaladis a son mostradis in '''gruessut'''",
+'wlnote'               => 'Ca sot a son i ultins $1 cambiaments tes ultimis <b>$2</b> oris.',
+'wlshowlast'           => 'Mostre ultimis $1 oris $2 zornadis $3',
+'wlsaved'              => 'This is a saved version of your watchlist.',
+'wlhideshowown'        => '$1 lis mês modifichis.',
+'wlshow'               => 'Mostre',
+'wlhide'               => 'Plate',
+'wrongpassword' => "La peraule clâf zontade no je juste. Torne par plasê a provâ.",
+'yourdiff' => "Difarencis",
+'youremail'            => "Email *",
+'yourlanguage' => "Lenghe di mostrâ",
+'yourpassword' => "Peraule clâf",
+'yourpasswordagain' => "Torne a scrivile",
+'yourrealname'         => "Non vêr *",
+'yourvariant' => 'Varietât',
+);
+
+class LanguageFur extends LanguageUtf8 {
+
+       function getNamespaces() {
+               global $wgNamespaceNamesFur;
+               return $wgNamespaceNamesFur;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsFur;
+               return $wgQuickbarSettingsFur;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesFur;
+               return $wgSkinNamesFur;
+       }
+
+
+       function getDateFormats() {
+               return false;
+       }
+
+
+       function date( $ts, $adj = false ) {
+               if ( $adj ) { $ts = $this->userAdjust( $ts ); }
+
+               $d = (0 + substr( $ts, 6, 2 )) . " di " .
+                 $this->getMonthAbbreviation( substr( $ts, 4, 2 ) ) .
+                 " " . substr( $ts, 0, 4 );
+               return $d;
+       }
+
+       function timeanddate( $ts, $adj = false ) {
+               return $this->date( $ts, $adj ) . " a lis " . $this->time( $ts, $adj );
+       }
+
+       var $digitTransTable = array(
+               ',' => "\xc2\xa0", // @bug 2749
+               '.' => ','
+       );
+
+       function formatNum( $number ) {
+               return strtr($number, $this->digitTransTable);
+       }
+
+
+       function getMessage( $key ) {
+               global $wgAllMessagesFur;
+               if( isset( $wgAllMessagesFur[$key] ) ) {
+                       return $wgAllMessagesFur[$key];
+               } else {
+                       return parent::getMessage( $key );
+               }
+       }
+
+}
+
+?>
diff --git a/languages/LanguageFy.php b/languages/LanguageFy.php
new file mode 100644 (file)
index 0000000..f32586b
--- /dev/null
@@ -0,0 +1,1022 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+require_once( "LanguageUtf8.php" );
+
+if($wgMetaNamespace === FALSE)
+       $wgMetaNamespace = str_replace( " ", "_", $wgSitename );
+
+/* private */ $wgNamespaceNamesFy = array(
+       NS_MEDIA          => "Media",
+       NS_SPECIAL        => "Wiki",
+       NS_MAIN           => "",
+       NS_TALK           => "Oerlis",
+       NS_USER           => "Meidogger",
+       NS_USER_TALK      => "Meidogger_oerlis",
+       NS_PROJECT        => $wgMetaNamespace,
+       NS_PROJECT_TALK   => $wgMetaNamespace . "_oerlis",
+       NS_IMAGE          => "Ofbyld",
+       NS_IMAGE_TALK     => "Ofbyld_oerlis",
+       NS_MEDIAWIKI      => "MediaWiki",
+       NS_MEDIAWIKI_TALK => "MediaWiki_oerlis",
+       NS_TEMPLATE       => "Berjocht",
+       NS_TEMPLATE_TALK  => "Berjocht_oerlis",
+       NS_HELP           => "Hulp",
+       NS_HELP_TALK      => "Hulp_oerlis",
+       NS_CATEGORY       => "Kategory",
+       NS_CATEGORY_TALK  => "Kategory_oerlis"
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgQuickbarSettingsFy = array(
+       "Ut", "Lofts fêst", "Rjochts fêst", "Lofts sweevjend"
+);
+
+/* private */ $wgSkinNamesFy = array(
+       'standard' => "Standert",
+       'nostalgia' => "Nostalgy",
+) + $wgSkinNamesEn;
+
+
+/* private */ $wgDateFormatsFy = array(
+       'Gjin foarkar',
+       '16.12, jan 15, 2001',
+       '16.12, 15 jan 2001',
+       '16.12, 2001 jan 15',
+       'ISO 8601' => '2001-01-15 16:12:34'
+);
+
+/* private */ $wgBookstoreListFy = array(
+);
+
+/* private */ $wgAllMessagesFy = array(
+# User Toggles
+
+"tog-underline"                => "Keppelings ûnderstreekje",
+"tog-highlightbroken"  => "Keppelings nei lege siden ta <a href=\"\" class=\"new\">read</a> (oars mei in fraachteken<a href=\"\" class=\"internal\">?</a>).",
+"tog-justify"          => "Paragrafen útfolje",
+"tog-hideminor"                => "Tekstwizigings wei litte út 'Koarts feroare'",
+"tog-usenewrc"         => "Utwreide ferzje fan 'Koarts feroare' brûke (net mei alle blêdzjers mooglik)",
+"tog-numberheadings"   => "Koppen fansels nûmerje",
+"tog-showtoolbar" => "Show edit toolbar",
+"tog-editondblclick"   => "Dûbelklik jout bewurkingsside (freget JavaScript)",
+"tog-editsection"      => "Jou [bewurk]-keppelings foar seksjebewurking",
+"tog-editsectiononrightclick" => "Rjochtsklik op sekjsetitels jout seksjebewurking (freget JavaScript)",
+"tog-showtoc"          => "Ynhâldsopjefte, foar siden mei mear as twa koppen",
+"tog-rememberpassword" => "Oare kear fansels oanmelde",
+"tog-editwidth"                => "Bewurkingsfjild sa breed as de side",
+"tog-watchdefault"     => "Sides dy't jo feroare hawwe folgje",
+"tog-minordefault"     => "Feroarings yn it earst oanjaan as tekstwizigings.",
+"tog-previewontop"     => "By it neisjen, bewurkingsfjild ûnderoan sette",
+"tog-nocache"          => "Gjin oerslag brûke",
+# Dates
+'sunday' => 'snein',
+'monday' => 'moandei',
+'tuesday' => 'tiisdei',
+'wednesday' => 'woansdei',
+'thursday' => 'tongersdei',
+'friday' => 'freed',
+'saturday' => 'sneon',
+'january' => 'jannewaris',
+'february' => 'febrewaris',
+'march' => 'maart',
+'april' => 'april',
+'may_long' => 'maaie',
+'june' => 'juny',
+'july' => 'july',
+'august' => 'augustus',
+'september' => 'septimber',
+'october' => 'oktober',
+'november' => 'novimber',
+'december' => 'decimber',
+'jan' => 'jan',
+'feb' => 'feb',
+'mar' => 'mar',
+'apr' => 'apr',
+'may' => 'mai',
+'jun' => 'jun',
+'jul' => 'jul',
+'aug' => 'aug',
+'sep' => 'sep',
+'oct' => 'okt',
+'nov' => 'nov',
+'dec' => 'dec',
+
+
+# Bits of text used by many pages:
+#
+#"linktrail"           => "/^([àáèéìíòóùúâêîôûäëïöüa-z]+)(.*)\$/sD",
+"linktrail"            => "/^((?:[a-z]|à|á|è|é|ì|í|ò|ó|ù|ú|â|ê|î|ô|û|ä|ë|ï|ö|ü)+)(.*)\$/sD",
+"mainpage"             => "Haadside",
+"mainpagetext" => "Wiki-programma goed installearre.",
+"about"                => "Ynfo",
+"aboutsite"            => "Oer de {{SITENAME}}",
+"aboutpage"            => "{{ns:project}}:Ynfo",
+"help"         => "Help",
+"helppage"             => "{{ns:project}}:Help",
+"bugreports"   => "Brekmelding",
+"bugreportspage"       => "{{ns:project}}:Brekmelding",
+"faq"                  => "FAQ",
+"faqpage"              => "{{ns:project}}:FAQ",
+"edithelp"             => "Siden bewurkje",
+"edithelppage" => "{{ns:project}}:Bewurk-rie",
+"cancel"               => "Ferlitte",
+"qbfind"               => "Sykje",
+"qbbrowse"             => "Blêdzje",
+"qbedit"               => "Bewurkje",
+"qbpageoptions"        => "Side-opsjes",
+"qbpageinfo"   => "Side-ynfo",
+"qbmyoptions"  => "Myn Opsjes",
+"mypage"               => "Myn side",
+"mytalk"               => "Myn oerlis",
+"currentevents"        => "Hjoeddeis",
+"errorpagetitle"       => "Fout",
+"returnto"             => "Werom nei \"$1\".",
+"tagline"              => "Fan {{SITENAME}}, de frije ensyklopedy.", # FIXME
+"whatlinkshere"        => "Siden mei in keppeling hjirhinne",
+"help"         => "Help",
+"search"               => "Sykje",
+"go"                   => "Side",
+"history"              => "Sideskiednis",
+"printableversion" => "Ofdruk-ferzje",
+"editthispage" => "Side bewurkje",
+"deletethispage"       => "Side wiskje",
+"protectthispage" => "Side beskermje",
+"newpage"              => "Nije side",
+"talkpage"             => "Sideoerlis",
+"postcomment"          => "Skrieuw in opmerking",
+"articlepage"  => "Side lêze",
+"subjectpage"  => "Side lêze", # For compatibility
+"userpage"             => "Brûkerside",
+"wikipediapage"        => "Metaside",
+"imagepage"    => "Ofbyldside",
+"viewtalkpage"         => "Oerlisside",
+"otherlanguages"       => "Oare talen",
+"redirectedfrom"       => "(Trochwiisd fan \"$1\")",
+"lastmodified" => "Lêste kear bewurke op $1.",
+"viewcount"            => "Disse side is $1 kear iepenslein.",
+"printsubtitle"        => "(Fan {{SERVER}})",
+"protectedpage"        => "Beskerme side",
+"administrators"       => "{{ns:project}}:Behear",
+"sysoptitle"   => "Allinnich foar behearders",
+"sysoptext"            => "Om dit te dwaan moatte jo behearder wêze. Sjoch \"$1\".",
+"developertitle"  => "Allinich foar untwiklers",
+"developertext"        => "Om dit te dwaan moatte jo ûntwikler wêze. Sjoch \"$1\".",
+"nbytes"               => "$1 byte",
+"go"                   => "Side",
+"ok"                   => "Goed",
+"sitetitle"            => '{{SITENAME}}',
+"sitesubtitle" => "De frije ensyklopedy",
+"retrievedfrom"        => "Untfongen fan \"$1\"",
+"newmessages"  => "Jo hawwe $1.",
+"newmessageslink" => "nije berjochten",
+"editsection"  => "edit",
+"toc"          => "Ynhâld",
+"showtoc"              => "sjen litte",
+"hidetoc"              => "net sjen litte",
+"thisisdeleted"        => "\"$1\" lêze of werombringje?",
+"restorelink"  => "$1 wiske ferzjes",
+
+# Main script and global functions
+#
+"nosuchaction" => "Unbekende aksje.",
+"nosuchactiontext" => "De aksje dy't jo oanjoegen fia de URL is net bekind by it Wiki-programma",
+"nosuchspecialpage" => "Unbekende side",
+"nospecialpagetext" => "Jo hawwe in Wiki-side opfrege dy't net bekind is by it Wiki-programma.",
+
+
+# General errors
+#
+"error"                        => "Fout",
+"databaseerror"                => "Databankfout",
+"dberrortext"          => "Sinboufout in databankfraach.
+De lêst besochte databankfraach wie:
+<blockquote><tt>$1</tt></blockquote>
+fan funksje \"<tt>$2</tt>\" út.
+MySQL joech fout \"<tt>$3: $4</tt>\" werom.",
+
+"dberrortextcl"                => "Sinboufout in databankfraach.
+De lêst besochte databankfraach wie:
+\"$1\"
+fan funksje \"$2\" út.
+MySQL joech fout \"<tt>$3: $4</tt>\" werom.",
+
+"noconnect"                    => "Sorry! Troch in fout yn de technyk, kin de Wiki gjin ferbining meitsje mei de databanktsjinner.",
+"nodb"                 => "Kin databank \"$1\" net berikke.",
+"cachederror"          => "Dit is in ferzje út de oerslag, mar it kin wêze dat dy ferâldere is.",
+"readonly"                     => "Databank is Net-skriuwe",
+"enterlockreason"      => "Skriuw wêrom de databank net-skriuwe makke is,
+en sawat hoenear't de men wêr skriuwe kin",
+"readonlytext" => "De {{SITENAME}} databank is ôfsletten foar nije siden en oare wizigings,
+nei alle gedachten is it foar ûnderhâld, en kinne jo der letter gewoan wer brûk fan meitsje.
+De behearder hat dizze útlis joen:
+<p>$1</p>",
+
+"missingarticle"               => "De databank kin in side net fine, nammentlik: \"$1\".
+<p>Faak is dit om't in âlde ferskil-, of skiednisside opfreege wurdt fan in side dy't wiske is.
+<p>As dat it hjir net is, dan hawwe jo faaks in brek yn it programa fûn.
+Jou dat asjebleaft troch oan de [[{{ns:project}}:Brekmelding|behearder]], tegearre mei de URL.",
+
+"internalerror"                => "Ynwindige fout",
+"filecopyerror"                => "Koe bestân \"$1\" net kopiearje as \"$2\".",
+"filerenameerror"      => "Koe bestân \"$1\" net werneame as \"$2\".",
+"filedeleteerror"      => "Koe bestân \"$1\" net wiskje.",
+"filenotfound"         => "Koe bestân \"$1\" net fine.",
+"unexpected"           => "Hommelse wearde: \"$1\"=\"$2\".",
+"formerror"                    => "Fout: koe formulier net oerlizze",
+"badarticleerror"      => "Dit kin op dizze side net dien wurden.",
+"cannotdelete"         => "Koe de oantsjutte side of ôfbyld net wiskje. (Faaks hat in oar dat al dien.)",
+"badtitle"                     => "Misse titel",
+"badtitletext"         => "De opfreeche side titel wie ûnjildich, leech, of in
+miskeppele ynter-taal of ynter-wiki titel.",
+"perfdisabled"                 => "Sorry! Dit ûnderdiel is tydlik út set om't it de databank sa starich makket
+dat gjinien de wiki brûke kin.",
+"perfdisabledsub"      => "Dit is in opsleine ferzje fan \"$1\":",
+
+
+# Login and logout pages
+#
+"logouttitle"  => "Ofmelde",
+"logouttext"   => "Jo binne no ôfmeld.
+Jo kinne de {{SITENAME}} fierders anonym brûke,
+of jo op 'e nij [[Wiki:Userlogin|oanmelde]] ûnder in oare namme.\n",
+"welcomecreation" => "<h2>Wolkom, $1!</h2><p>Jo ynstellings bin oanmakke.
+Ferjit net se oan jo foarkar oan te passen.",
+
+"loginpagetitle"       => "Oanmelde",
+"yourname"     => "Jo brûkersnamme",
+"yourpassword" => "Jo wachtwurd",
+"yourpasswordagain" => "Jo wachtwurd (nochris)",
+"newusersonly"         => " (allinnich foar nije brûkers)",
+"remembermypassword" => "Oare kear fansels oanmelde.",
+"loginproblem"         => "<b>Der wie wat mis mei jo oanmelden.</b><br />Besykje it nochris, a.j.w.",
+"alreadyloggedin" => "<strong>Brûker $1, jo binne al oanmeld!</strong><br />\n",
+"login"                => "Oanmelde",
+"userlogin"            => "Oanmelde",
+"logout"               => "Ofmelde",
+"userlogout"   => "Ofmelde",
+"notloggedin"  => "Net oanmelde",
+"createaccount"        => "Nije ynstelingd oanmeitsje",
+"badretype"            => "De infierde wuchtwurden binne net lyk.",
+"userexists"   => "Dy brûkersname wurdt al brûkt. Besykje in oarenien.",
+"youremail"            => "Jo e-postadres (*).",
+"yournick"             => "Jo alias (foar sinjaturen)",
+"emailforlost" => "* In e-postadres hoecht net.<br />
+Mar it helpt, soenen jo jo wachtwurd ferjitte.
+En mei in e-postadres kinne oaren fan de web siden contact mei jo krije,
+sûnder dat se dat adres witte. (Dat leste kin ek wer útset by de instellings.)",
+
+"loginerror"   => "Oanmeldflater",
+"noname"               => "Jo moatte in brûkersnamme opjaan.",
+"loginsuccesstitle" => "Oanmelden slagge.",
+"loginsuccess" => "Jo binne no oanmelde op de {{SITENAME}} as: $1.",
+"nosuchuser"   => "Brûkersnamme en wachtwurd hearre net by elkoar.
+Besykje op 'e nij, of fier it wachtwurd twa kear yn en meitsje neie brûkersynstellings.",
+
+"wrongpassword"        => "Brûkersnamme en wachtwurd hearre net by elkoar.
+Besykje op 'e nij, of fier it wachtwurd twa kear yn en meitsje neie brûkersynstellings.",
+
+"mailmypassword"       => "Stjoer my in nij wachtwurd.",
+"passwordremindertitle" => "Nij wachtwurd foar de {{SITENAME}}",
+"passwordremindertext" => "Immen (nei alle gedachten jo, fan Ynternet-adres $1)
+hat frege en stjoer jo in nij {{SITENAME}} wachtwurd.
+I wachtwurd foar brûker \"$2\" is no \"$3\".
+Meld jo no oan, en feroarje jo wachtwurd.",
+"noemail"              => "Der is gjin e-postadres foar brûker \"$1\".",
+"passwordsent" => "In nij wachtwurd is tastjoert oan it e-postadres foar \"$1\".
+Please log in again after you receive it.",
+
+# Edit pages
+#
+"summary"              => "Gearfetting",
+"subject"              => "Mêd",
+"minoredit"            => "Dit is in tekstwiziging",
+"watchthis"            => "Folgje dizze side",
+"savearticle"  => "Fêstlizze",
+"preview"              => "Oerlêze",
+"showpreview"  => "Oerlêze foar de side fêstlein is",
+"blockedtitle" => "Brûker is útsletten troch",
+"blockedtext"  => "Jo brûkersname of Ynternet-adres is útsletten.
+As reden is opjûn:<br />''$2''<p>As jo wolle, kinne jo hjiroer kontakt op nimme meid de behearder.
+
+(Om't in Ynternet-adressen faak mar foar ien sessie tawiisd wurde, kin it wêze
+dat it eins gjit om in oar dy't deselde tagongferskaffer hat as jo hawwe. As it jo
+net betreft, besykje dan earst of it noch sa is as jo in skofke gjin
+Ynternet-ferbining hân hawwe. As it in probleem bliuwt, skriuw dan de behearder.
+Sorry, foar it ûngemak.)
+
+Jo Ynternet-adres is: $3. Nim dat op yn jo berjocht.
+
+Tink derom, dat \"skriuw nei dizze brûker\" allinich wol as jo in
+e-postadres opjûn hawwe in jo [[Wiki:Preferences|ynstellings]].",
+
+"newarticle"   => "(Nij)",
+"newarticletext" =>
+"Jo hawwe in keppeling folge nei in side dêr't noch gjin tekst op stiet.
+Om sels tekst te meistjsen kinne jo dy gewoan yntype in dit bewurkingsfjild
+([[{{ns:project}}:Bewurk-rie|Mear ynformaasje oer bewurkjen]].)
+Oars kinne jo tebek mei de tebek-knop fan jo blêdzjer.",
+
+"anontalkpagetext" => "---- ''Dit is de oerlisside fan in unbekinde brûker; in brûker
+dy't sich net oanmeld hat. Om't der gjin namme is wurd it Ynternet-adres brûkt om
+oan te jaan wa. Mar faak is it sa dat sa'n adres net altid troch deselde brûkt wurdt.
+As jo it idee hawwe dat jo as ûnbekinde brûker opmerkings foar in oar krije, dan kinne
+jo jo [[Wiki:Userlogin|oanmelde]], dat jo allinnich opmerkings foar josels krije.'' ",
+"noarticletext" => "(Der stjit noch gjin tekst op dizze side.)",
+"updated"              => "(Bewurke)",
+"note"         => "<strong>Opmerking:</strong> ",
+"previewnote"  => "Tink der om dat dizze side noch net fêstlein is!",
+"previewconflict" => "Dizze side belanget allinich it earste bewurkingsfjild oan.",
+"editing"              => "Bewurkje \"$1\"",
+"editing"              => "Bewurkje \"$1\" (seksje)",
+"editing"              => "Bewurkje \"$1\" (nije opmerking)",
+"editconflict" => "Tagelyk bewurke: \"$1\"",
+"explainconflict" => "In oar hat de side feroare sûnt jo begûn binne mei it bewurkjen.
+It earste bewurkingsfjild is hoe't de tekst wilens wurde is.
+Jo feroarings stean yn it twadde fjild.
+Dy wurde allinnich tapasse safier as jo se yn it earste fjild ynpasse.
+<b>Allinnich</b> de tekst út it earste fjild kin fêstlein wurde.<br />",
+"yourtext"             => "Jo tekst",
+"storedversion" => "Fêstleine ferzje",
+"editingold"   => "<strong>Waarskôging: Jo binne dwaande mei in âldere ferzje fan dizze side.
+Soenen jo dizze fêstlizze, dan is al wat sûnt dy tiid feroare is kwyt.</strong>",
+"yourdiff"             => "Feroarings",
+# REPLACE THE COPYRIGHT WARNING IF YOUR SITE ISN'T GFDL!
+"copyrightwarning" => "Alle bydragen ta de {{SITENAME}} wurde sjoen
+as fallend ûnder de GNU Iepen Dokumentaasje Lisinsje
+(sjoch fierders: \"$1\").
+As jo net wolle dat jo skriuwen ûnferbidlik oanpast en frij ferspraat wurdt,
+dan is it baas, en set it net op de {{SITENAME}}.<br />
+Jo ferklare ek dat jo dit sels skreaun hawwe, of it oernaam hawwe út in
+publyk eigendom of in oare iepen boarne.
+<strong><big>Foeg gjin wurk ûnder auteursrjocht ta sûnder tastimming!</big></strong>",
+"longpagewarning" => "<strong>Waarskôging: Dizze side is $1 kilobyte lang;
+der binne blêdzjers dy problemen hawwe mei siden fan tsjin de 32kb. of langer.
+Besykje de side yn lytsere stikken te brekken.</strong>",
+"readonlywarning" => "<strong>Waarskôging: De databank is ôfsletten foar
+ûnderhâld, dus jo kinne jo bewurkings no net fêstlizze.
+It wie baas en nim de tekst foar letter oer yn in tekstbestân.</strong>",
+"protectedpagewarning" => "<strong>Waarskôging: Dizze side is beskerme, dat
+gewoane brûkers dy net bewurkje kinne. Tink om de
+[[Project:Beskerm-rie|rie oer beskerme siden]].</strong>",
+
+# History pages
+#
+"revhistory"   => "Sideskiednis",
+"nohistory"            => "Dit is de earste ferzje fan de side.",
+"revnotfound"  => "Ferzje net fûn",
+"revnotfoundtext" => "De âlde ferzje fan dizze side dêr't jo om frege hawwe, is der net.
+Gean nei of de keppeling dy jo brûkt hawwe wol goed is.\n",
+"loadhist"             => "Sideskiednis ...",
+"currentrev"   => "Dizze ferzje",
+"revisionasof" => "Ferzje op $1",
+"cur"                  => "no",
+"next"         => "dan",
+"last"         => "doe",
+"orig"         => "ea",
+"histlegend"   => "Utlis: (no) = ferskil mei de side sa't dy no is,
+(doe) = ferskill mei de side sa't er doe wie, foar de feroaring, T = Tekstwiziging",
+
+
+# Diffs
+#
+"difference"   => "(Ferskil tusken ferzjes)",
+"loadingrev"   => "Ferskil tusken ferzjes ...",
+"lineno"               => "Rigel $1:",
+"editcurrent"  => "Bewurk de hjoeddeistiche ferzje fan dizze side",
+
+# Search results
+#
+"searchresults" => "Sykresultaat",
+"searchresulttext" => "\"[[Project:Syk-rie|Ynformaasje oer it sykjen|Sykje troch de {{SITENAME}}]]\" troch de {{SITENAME}}.",
+"searchquery"  => "Foar fraach \"$1\"",
+"badquery"             => "Misfoarme sykfraach",
+"badquerytext" => "Jo fraach koe net ferwurke wurde.
+Dit is faaks om't jo besyke hawwe en sykje in word fan ien of twa letters, wat it programma noch net kin.
+Of it soe kinne dat jo de fraach misskreaun hawwe, lykas \"frysk en en frei\". Besykje it nochris.",
+"matchtotals"  => "Foar \"$1\" binne $2 titles fûn en $3 siden.",
+"nogomatch" => "Der is gjin side mei krekt dizze titel. Faaks is it better en Sykje nei dizze tekst.",
+"titlematches" => "Titels",
+"notitlematches" => "Gjin titels",
+"textmatches"  => "Siden",
+"notextmatches"        => "Gjin siden",
+"prevn"                => "foarige $1",
+"nextn"                => "folgende $1",
+"viewprevnext" => "($1) ($2) ($3) besjen.",
+"showingresults"       => "<b>$1</b> resultaten fan <b>$2</b> ôf.",
+"showingresultsnum" => "<b>$3</b> resultaten fan <b>$2</b> ôf.",
+"nonefound"            => "As der gjin resultaten binne, tink der dan om dat der <b>net</b> socht
+wurde kin om wurden as \"it\" en \"in\", om't dy net byhâlden wurde, en dat as der mear
+wurden syke wurde, allinnich siden fûn wurde wêr't <b>alle</b> worden op fûn wurde.",
+
+"powersearch" => "Sykje",
+"powersearchtext" => "
+Sykje in nammeromten :<br />
+$1<br />
+$2 List trochferwizings &nbsp; Sykje nei \"$3\" \"$9\"",
+
+"searchdisabled" => "<p>Op it stuit stjit it trochsykjen fan tekst net oan, om't de
+tsjinner it net oankin. Mei't we nije apparatuer krije wurdt it nei alle gedanken wer
+mooglik. Foar now kinne jo sykje fia Google:</p>",
+
+
+
+# Preferences page
+#
+"preferences"          => "Ynstellings",
+"prefsnologin"                 => "Net oanmeld",
+"prefsnologintext"     => "Jo moatte [[Wiki:Userlogin|oanmeld]] wêze om jo ynstellings te feroarjen.",
+
+"prefslogintext"               => "Jo binne oanmeld, $1.
+Jo Wiki-nûmer is $2.
+
+([[{{ns:project}}:Ynstelling-rie|Help by de ynstellings]].",
+
+"prefsreset"           => "De ynstellings binne tebek set sa't se fêstlein wienen.",
+"qbsettings"           => "Menu",
+"changepassword"               => "Wachtword feroarje",
+"skin"                 => "Side-oansjen",
+"math"                 => "Formules",
+"dateformat"           => "Datum",
+"math_failure"         => "Untsjutbere formule",
+"math_unknown_error"   => "Unbekinde fout",
+"math_unknown_function"        => "Unbekinde funksje",
+"math_lexing_error"    => "Unbekind wurd",
+"math_syntax_error"    => "Sinboufout",
+"saveprefs"                    => "Ynstellings fêstlizze",
+"resetprefs"           => "Ynstellings tebek sette",
+"oldpassword"          => "Ald wachtwurd",
+"newpassword"          => "Nij wachtwurd",
+"retypenew"                    => "Nij wachtwurd (nochris)",
+"textboxsize"          => "Tekstfjid-omjittings",
+"rows"                 => "Rigen",
+"columns"                      => "Kolommen",
+"searchresultshead"    => "Sykje",
+"resultsperpage"               => "Treffers de side",
+"contextlines"         => "Rigels inhâld de treffer",
+"contextchars"         => "Tekens fan de inhâld de rigel",
+"stubthreshold"                => "Grins foar stobben",
+"recentchangescount"   => "Nûmer of titels op 'Koarts feroare'",
+"savedprefs"           => "Jo ynstellings binne fêstlein.",
+"timezonetext"         => "Jou it tal fan oeren dat jo tiidsône ferskilt fan UTC (Greenwich).",
+"localtime"                    => "Jo tiidsône",
+"timezoneoffset"               => "Ferskil",
+"servertime"           => "UTC",
+"guesstimezone"                => "Freegje de blêdzjer",
+"emailflag"                    => "Gjin post fan oare brûkers",
+"defaultns"                    => "Nammeromten dy't normaal trochsykje wurde:",
+
+# Recent changes
+#
+"changes"                      => "feroarings",
+"recentchanges"                => "Koarts feroare",
+# This is the default text, and can be overriden by editing [[{{ns:project}}::Recentchanges]]
+"recentchangestext"    => "De lêste feroarings fan de {{SITENAME}}.",
+"rcloaderr"                    => "Koarts feroare ...",
+"rcnote"                       => "Dit binne de lêste <strong>$1</strong> feroarings yn de lêste <strong>$2</strong> dagen.",
+"rcnotefrom"           => "Dit binne de feroarings sûnt <b>$2</b> (maksimaal <b>$1</b>).",
+"rclistfrom"           => "Jou nije feroarings, begjinnende mei $1",
+"rclinks"                      => "Jou $1 nije feroarings yn de lêste $2 dagen; $3 tekstwiziging",
+"rchide"                       => "in $4 form; $1 tekstwizigings; $2 oare nammeromten; $3 meartallige feroarings.",
+"rcliu"                        => "; $1 feroarings troch oanmelde brûkers",
+"diff"                 => "ferskil",
+"hist"                 => "skiednis",
+"hide"                 => "gjin",
+"show"                 => "al",
+"tableform"                    => "tabel",
+"listform"                     => "list",
+"nchanges"                     => "$1 feroarings",
+"minoreditletter"      => "T",
+"newpageletter"                => "N",
+
+# Upload
+#
+"upload"               => "Bied bestân oan",
+"uploadbtn"            => "Bied bestân oan",
+"uploadlink"   => "Bied ôfbylden oan",
+"reupload"             => "Op 'e nij oanbiede",
+"reuploaddesc" => "Werom nei oanbied-side.",
+"uploadnologin"        => "Net oanmelde",
+"uploadnologintext" => "Jo moatte [[Wiki:Userlogin|oanmeld]] wêze om in bestân oanbieden te kinnen.",
+
+"uploaderror"  => "Oanbied-fout",
+"uploadtext"   => "'''STOP!''' Lês ear't jo eat oanbiede
+de [[Project:Ofbyld-rie|regels foar ôfbyldbrûk]] foar de {{SITENAME}}.
+
+Earder oanbeane ôfbylden, kinne jo fine op de
+[[Project:Imagelist|list of oanbeane ôfbylden]].
+Wat oanbean en wat wiske wurdt, wurdt delskreaun yn it
+[[Project:Oanbied-loch|lochboek]].
+
+Om't nije ôfbylden oan te bieden, kieze jo in bestân út sa't dat
+normaal is foar jo blêdzjer en bestjoersysteem.
+Dan jouwe jo oan jo gjin auteursrjocht skeine troch it oanbieden.
+Mei \"Bied oan\" begjinne jo dan it oanbieden.
+Dit kin efkes duorje as jo Ynternet-ferbining net sa flug is.
+
+Foar de bestânsforam wurdt foto's JPEG oanret, foar tekenings ensfh. PNG, en foar
+lûden OGG. Brûk in dúdlike bestânsnamme, sa't in oar ek wit wat it is.
+
+Om it ôfbyld yn in side op te nimmen, meitsje jo dêr sa'n keppeling:<br />
+'''<nowiki>[[ôfbyld:jo_foto.jpg|omskriuwing]]</nowiki>''' of
+'''<nowiki>[[ôfbyld:jo_logo.png|omskriuwing]]</nowiki>''';
+en foar lûden '''<nowiki>[[media:jo_lûd.ogg]]</nowiki>'''.
+
+Tink derom dat oaren bewurkje kinne wat jo oanbiede, as dat better is foar de {{SITENAME}},
+krekt's sa't dat foar siden jildt, en dat jo útsletten wurde kinne as jo misbrûk
+meitsje fan it systeem..",
+
+"uploadlog"            => "oanbied log",
+"uploadlogpage"        => "Oanbied_log",
+"uploadlogpagetext" => "Liste fan de lêst oanbeane bestannen.
+(Tiid oanjûn as UTC).
+<ul>
+</ul>
+",
+
+"filename"             => "Bestânsnamme",
+"filedesc"             => "Omskriuwing",
+"copyrightpage"        => "{{ns:project}}:Auteursrjocht",
+"copyrightpagename" => "{{SITENAME}} auteursrjocht",
+"uploadedfiles"        => "Oanbeane bestannen",
+"ignorewarning"        => "Sjoch oer de warskôging hinne en lis bestân dochs fêst.",
+"minlength"            => "Ofbyldnammen moatte trije letters of mear wêze.",
+"badfilename"  => "De ôfbyldnamme is feroare nei \"$1\".",
+"badfiletype"  => "\".$1\" is net yn in oanrette bestânsfoarm.",
+"largefile"            => "It is baas as ôfbylden net grutter as 100k binne.",
+"successfulupload" => "Oanbieden slagge.",
+"fileuploaded" => "Bestân \"$1\" goed oanbean.
+Gean no fierder nei de beskriuwingsside: ($2). Dêr kinne jo oanjaan
+wêr't it bestân wei kaam, hoenear it oanmakke is en wa't it makke hat,
+en wat jo fierder mar oan ynformaasje hawwe.",
+
+"uploadwarning"        => "Oanbied waarskôging",
+"savefile"             => "Lis bestân fêst",
+"uploadedimage"        => " \"[[$1]]\" oanbean",
+"uploaddisabled" => "Sorry, op dizze tsjinner kin net oanbean wurde.",
+
+# Image list
+#
+"imagelist"            => "Ofbyld list",
+"imagelisttext"        => "Dit is in list fan $1 ôfbylden, op $2.",
+"getimagelist" => "Ofbyld list ...",
+"ilsubmit"             => "Sykje",
+"showlast"             => "Jou lêste $1 ôfbylden, op $2.",
+"byname"               => "namme",
+"bydate"               => "datum",
+"bysize"               => "grutte",
+"imgdelete"            => "wisk",
+"imgdesc"              => "tekst",
+"imglegend"            => "Utlis: (tekst) = Jou/bewurk ôfbyld-omskriuwing.",
+"imghistory"   => "Ofbyldskiednis",
+"revertimg"            => "tebek",
+"deleteimg"            => "wisk",
+"deleteimgcompletely"          => "wisk",
+"imghistlegend"        => "Utlis: (no) = dit is it hjoeddeiske ôfbyld,
+(wisk) = wiskje dizze âldere ferzje, (tebek) = set ôfbyld tebek nei dizze âldere ferzje.
+<br /><i>Fia de datum kinne jo it ôfbyld dat doe oanbean besjen</i>.",
+
+"imagelinks"   => "Ofbyldkeppelings",
+"linkstoimage" => "Dizze siden binne keppele oan it ôfbyld:",
+"nolinkstoimage" => "Der binne gjin siden oan dit ôfbyld keppelje.",
+
+# Statistics
+#
+"statistics"   => "Statistyk",
+"sitestats"            => "Side statistyk",
+"userstats"            => "Brûker statistyk",
+"sitestatstext" => "It tal fan siden in de {{SITENAME}} is: <b>$2</b>.<br />
+(Oerlissiden, siden oer de {{SITENAME}}, oare bysûndere siden,  stobben en
+trochferwizings yn de databank binne dêrby net meiteld.)<br />
+It tal fan siden in de databank is: <b>$1</b>.
+<p>
+Der is <b>$3</b> kear in side opfrege, en <b>$4</b> kear in side bewurke,
+sûnt it programma bywurke is (15 oktober 2002).
+Dat komt yn trochslach del op <b>$5</b> kear bewurke de side,
+en <b>$6</b> kear opfrege de bewurking.",
+
+"userstatstext" => "It tal fan registreare brûkers is <b>$1</b>.
+It tal fan behearders dêrfan is: <b>$2</b>.",
+
+# Maintenance Page
+#
+"maintenance"          => "Underhâld",
+"maintnancepagetext"   => "Op dizze side stiet ark foar it deistich ûnderhâld.
+In part fan de funksjes freegje in soad fan de databank, dus freegje net nei
+eltse oanpassing daalks in fernijde side op.",
+
+"maintenancebacklink"  => "Werom nei Underhâldside",
+"disambiguations"              => "Trochverwizings",
+"disambiguationspage"  => "{{ns:project}}:trochferwizing",
+"disambiguationstext"  => "Dizze siden binne keppele fia in
+[[{{ns:project}}:trochferwizing]].
+Se soenen mei de side sels keppele wurde moatte.<br />
+(Allinnich siden út deselde nammeromte binne oanjûn.)",
+
+"doubleredirects"      => "Dûbele trochverwizings",
+"doubleredirectstext"  => "<b>Let op!</b> Der kinne missen yn dizze list stean!
+Dat komt dan ornaris troch oare keppelings ûnder de \"#REDIRECT\".<br />
+Eltse rigel jout keppelings nei de earste en twadde trochverwizing, en dan de earste regel fan
+de twadde trochferwizing, wat it \"echte\" doel wêze moat.",
+
+"brokenredirects"              => "Misse trochferwizings",
+"brokenredirectstext"  => "Dizze trochferwizings ferwize nei siden dy't der net binne.",
+"selflinks"                    => "Siden mei sels-ferwizings",
+"selflinkstext"                => "Dizze siden hawwe in keppeling nei de side sels, wat net sa wêze moat.",
+"mispeelings"           => "Siden mei skriuwflaters",
+"mispeelingstext"              => "Op dizze siden stiet in skriuw- of typ-flater dy't in soad makke wurd, lykas oanjoen op \"$1\".
+Dêr soe ek stean moatte hoe't it (goed skreaun) wurdt.",
+"mispeelingspage"       => "List fan faak makke flaters",
+"missinglanguagelinks"  => "Untbrekkende taalkeppelings",
+"missinglanguagelinksbutton"    => "Fyn ûntbrekkende taalkeppelings foar",
+"missinglanguagelinkstext"      => "Dizze siden hawwe gjin taalkeppeling nei deselde side yn taal \"$1\".
+(Ferwizings en oanheake siden binne net <i>net</i> besocht.",
+
+
+# Miscellaneous special pages
+#
+"orphans"              => "Lossteande siden",
+"lonelypages"  => "Lossteande siden",
+"unusedimages" => "Lossteande ôbylden",
+"popularpages" => "Grage siden",
+"nviews"               => "$1 kear sjoen",
+"wantedpages"  => "Nedige siden",
+"nlinks"               => "$1 keer keppele",
+"allpages"             => "Alle titels",
+"randompage"   => "Samar in side",
+"shortpages"   => "Koarte siden",
+"longpages"            => "Lange siden",
+"listusers"            => "Brûkerlist",
+"specialpages" => "Bysûndere siden",
+"spheading"            => "Bysûndere siden foar all brûkers",
+"protectpage"  => "Beskerm side",
+"recentchangeslinked" => "Folgje keppelings",
+"rclsub"               => "(nei siden dêr't \"$1\" keppelings nei hat)",
+"debug"                => "Breksykje",
+"newpages"             => "Nije siden",
+"ancientpages" => "Alde siden",
+"movethispage" => "Move this side",
+"unusedimagestext" => "<p>Tink derom dat ore web sides lykas fan de oare
+parten fan it meartaliche projekt mei in keppeling nei in direkte URL nei
+an ôfbyld makke hawwe kinne. Dan wurde se noch brûke, mar stean al in dizze list.",
+
+"booksources"  => "",
+"booksourcetext"       => "",
+"alphaindexline"       => "$1 oan't $2",
+
+
+# Email this brûker
+#
+"mailnologin"  => "Gjin adres beskikber",
+"mailnologintext" => "Jo moatte [[Wiki:Userlogin|oanmeld]]
+wêze, en in jildich e-postadres [[Wiki:Preferences|ynsteld]]
+hawwe, om oan oare brûkers e-post stjoere te kinnen.",
+
+"emailuser"            => "Skriuw dizze brûker",
+"emailpage"            => "E-post nei brûker",
+"emailpagetext"        => "As dizze brûker in jildich e-postadres in ynsteld hat,
+dan kinne jo ien berjocht ferstjoere.
+It e-postadres dat jo ynsteld hawwe wurdt brûkt as de ôfstjoerder, sa't de ûntfanger
+antwurdzje kin.",
+"noemailtitle" => "Gjin e-postadres",
+"noemailtext"  => "Dizze brûker had gjin jildich e-postadres ynsteld,
+of hat oanjaan gjin post fan oare brûkers krije te wollen.",
+"emailfrom"            => "Fan",
+"emailto"              => "Oan",
+"emailsubject" => "Oer",
+"emailmessage" => "Tekst",
+"emailsend"            => "Stjoer",
+"emailsent"            => "Berjocht stjoerd",
+"emailsenttext" => "Jo berjocht is stjoerd.",
+
+# Watchlist
+#
+"watchlist"            => "Folchlist",
+"watchlistsub" => "(foar brûker \"$1\")",
+"nowatchlist"  => "Jo hawwe gjin siden op jo folchlist.",
+"watchnologin" => "Not oanmeld in",
+"watchnologintext"=> "Jo moatte [[Wiki:Userlogin|oanmeld]] wêze om jo folchlist te feroarjen.",
+
+"addedwatch"   => "Oan folchlist tafoege",
+"addedwatchtext"       => "De side \"$1\" is tafoege oan jo <a href=\""
+. "{{localurle:Wiki:Watchlist}}\">folchlist</a>.
+As dizze side sels, of de oerlisside, feroare wurd, dan komt dat dêr yn,
+en de side stiet dan ek <b>fet</b> yn de <a href=\"" .
+  "{{localurle:Wiki:Recentchanges}}\">Koarts feroare</a> list.
+
+<p>As jo letter in side net mear folgje wolle, dan brûke jo \"Ferjit dizze side\".",
+"removedwatch" => "Net mear folgje",
+"removedwatchtext" => "De side \"$1\" stiet net mear op jo folchlist.",
+"watchthispage"        => "Folgje dizze side",
+"unwatchthispage" => "Ferjit dizze side",
+"notanarticle" => "Dit kin net folge wurde.",
+"watchnochange"        => "Fan de siden dy't jo folgje is der yn dizze perioade net ien feroare.",
+"watchdetails" => "Jo folchlist hat $1 siden (oerlissiden net meiteld).
+In dizze perioade binne der $2 siden feroare.
+$3. ([$4 Gâns myn folchlist].)",
+
+"watchmethod-recent" => "Koarts feroare ...",
+"watchmethod-list" => "Folge ...",
+"removechecked"        => "Ferjit dizze siden",
+"watchlistcontains" => "Jo folgje op it stuit $1 siden.",
+"watcheditlist"        => "Dit binne de siden op jo folchlist, oardere op alfabet.
+Jou oan hokfoar siden jo net mear folgje wolle, en befêstigje dat ûnderoan de side.",
+
+"removingchecked" => "Wiskje siden fan jo folchlist ...",
+"couldntremove"        => "Koe \"$1\" net ferjitte ...",
+"iteminvalidname" => "Misse namme: \"$1\" ...",
+"wlnote"               => "Dit binne de lêste <strong>$1</strong> feroarings yn de lêste <strong>$2</strong> oeren.",
+
+
+# Delete/protect/revert
+#
+"deletepage"   => "Wisk side",
+"confirm"              => "Befêstigje",
+"excontent"            => "inhâld wie: '$1'",
+"exbeforeblank"        => "foar de tekst wiske wie, wie dat: '$1'",
+"exblank"              => "side wie leech",
+"confirmdelete"        => "Befestigje wiskjen",
+"deletesub"            => "(Wiskje \"$1\")",
+"historywarning"       => "Waarskôging: De side dy't jo wiskje wolle hat skiednis: ",
+"confirmdeletetext" => "Jo binne dwaande mei it foar altyd wiskjen fan in side
+of ôfbyld, tegearre mei alle skiednis, út de databank.
+Befêstigje dat jo dat wier dwaan wolle. Befêstigje dat dat is wat jo witte wat it gefolch
+is en dat jo dit dogge neffens de [[{{ns:project}}:wisk-rie]].",
+
+"actioncomplete"       => "Dien",
+"deletedtext"  => "\"$1\" is wiske.
+Sjoch \"$2\" foar in list fan wat resint wiske is.",
+"deletedarticle"       => "\"$1\" is wiske",
+"dellogpage"   => "Wisk_loch",
+"dellogpagetext" => "Dit is wat der resint wiske is.
+(Tiden oanjûn as UTC).
+<ul>
+</ul>
+",
+
+"deletionlog"  => "wisk loch",
+"reverted"             => "Tebekset nei eardere ferzje",
+"deletecomment"        => "Reden foar it wiskjen",
+"imagereverted"        => "Tebeksette nei eardere ferzje is slagge.",
+"rollback"             => "Feroarings tebeksette",
+"rollbacklink" => "feroaring tebeksette",
+"rollbackfailed"       => "Feroaring tebeksette net slagge",
+"cantrollback" => "Disse feroaringt kin net tebek set, om't der mar ien skriuwer is.",
+"alreadyrolled"        => "Kin de feroaring fan [[$1]]
+troch [[Brûker:$2|$2]] ([[Brûker oerlis:$2|Oerlis]]) net tebeksette;
+inoar hat de feroaring tebekset, of oars wat oan de side feroare.
+
+De lêste feroaring wie fan [[Brûker:$3|$3]] ([[Brûker oerlis:$3|Oerlis]]). ",
+#   only shown if there is an edit comment
+"editcomment"  => "De gearfetting wie: \"<i>$1</i>\".",
+"revertpage"   => "Tebek set ta de ferzje fan \"$1\"",
+
+# Undelete
+"undelete"             => "Side werom set",
+"undeletepage" => "Side besjen en werom sette",
+"undeletepagetext" => "Dizze siden binne wiske, mar sitte noch yn it argyf en kinne weromset wurde.
+(It argyf kin út en troch leechmeitsje wurde.)",
+"undeletearticle" => "Set side werom",
+"undeleterevisions" => "$1 ferzjes in it argyf",
+"undeletehistory" => "Soenen jo dizze side weromsette, dan wurde alle ferzjes weromset as part
+fan de skiednis. As der in nije side is mei dizze namme, dan wurd de hjoeddeise ferzje <b>net</b>
+troch de lêste ferzje út dy weromsette skiednis ferfangen.",
+"undeleterevision" => "Wiske side, sa't dy $1 wie.",
+"undeletebtn"  => "Weromset!",
+"undeletedarticle" => "\"$1\" weromset",
+"undeletedtext"   => "It weromsette fan side [[$1]] is slagge.
+(List fan resint [[{{ns:project}}:wisk-loch|wiske of weromsette siden]].",
+
+# Contributions
+#
+"contributions"        => "Brûker bydragen",
+"mycontris"            => "Myn bydragen",
+"contribsub"   => "Foar \"$1\"",
+"nocontribs"   => "Der binne gjin feroarings fûn dyt't hjirmei oerienkomme.",
+"ucnote"               => "Dit binne dizze brûker's leste <b>$1</b> feroarings yn de lêste <b>$2</b> dagen.",
+"uclinks"              => "Besjoch de lêste $1 feroarings; besjoch de lêste $2 dagen.",
+"uctop"                => " (boppen)",
+
+# What links here
+#
+"whatlinkshere"        => "Wat is hjirmei keppele",
+"notargettitle"        => "Gjin side",
+"notargettext" => "Jo hawwe net sein oer hokfoar side jo dit witte wolle.",
+"linklistsub"  => "(List fan keppelings)",
+"linkshere"            => "Dizze siden binne hjirmei keppele:",
+"nolinkshere"  => "Gjinien side is hjirmei keppele!",
+"isredirect"   => "trochverwizing",
+
+# Block/unblock IP
+#
+"blockip"              => "Slut brûker út",
+"blockiptext"  => "Brûk dizze fjilden om in brûker fan skriuwtagong út te sluten.
+Dit soe allinnich omwillens fan fandalisme dwaan wurde moatte, sa't de
+[[{{ns:project}}:Utslut-rie|útslut-rie]] it oanjout.
+Meld de krekte reden! Begelyk, neam de siden dy't oantaaste waarden.",
+"ipaddress"            => "Brûkernamme of Ynternet-adres",
+"ipbreason"            => "Reden",
+"ipbsubmit"            => "Slut dizze brûker út",
+"badipaddress" => "Dy brûker bestiet net",
+"blockipsuccesssub" => "Utsluting slagge",
+"blockipsuccesstext" => "Brûker \"$1\" is útsletten.<br />
+(List fan [[Wiki:Ipblocklist|útslette brûkers]].)",
+"unblockip"            => "Lit brûker der wer yn",
+"unblockiptext"        => "Brûk dizze fjilden om in brûker wer skriuwtagong te jaan.",
+"ipusubmit"            => "Lit dizze brûker der wer yn",
+"ipusuccess"   => "Brûker \"$1\" ynlitten",
+"ipblocklist"  => "List fan útsletten Ynternet-adressen en brûkersnammen",
+"blocklistline"        => '"$3", troch "$2" op $1 ($4)',
+"blocklink"            => "slut út",
+"unblocklink"  => "lit yn",
+"contribslink" => "bydragen",
+"autoblocker"  => "Jo wienen útsletten om't jo Ynternet-adres oerienkomt mei dat fan \"$1\".
+Foar it útslute fan dy brûker waard dizze reden joen: \"$2\".",
+
+# Developer tools
+#
+"lockdb"               => "Meitsje de database 'Net-skriuwe'",
+"unlockdb"     => "Meitsje de databank skriuwber",
+"lockdbtext"   => "Salang as de databank 'Net-skriuwe' is,
+is foar brûkers it feroarjen fan siden, ynstellings, folchlisten, ensfh. net mooglik.
+Befêstigje dat dit is wat jo wolle, en dat jo de databank wer skriuwber meitsje as
+jo ûnderhâld ree is.",
+"unlockdbtext" => "As de databank skriuwber makke wurdt,
+is foar brûkers it feroarjen fan siden, ynstelingen, folchlisten, ensfh, wer mooglik.
+Befêstigje dat dit is wat jo wolle.",
+"lockconfirm"  => "Ja, ik wol wier de databank 'Net--skriuwe' meitsje.",
+"unlockconfirm"        => "Ja, ik wol wier de databank skriuwber meitsje.",
+"lockbtn"              => "Meitsje de database 'Net-skriuwe'",
+"unlockbtn"            => "Meitsje de databank skriuwber",
+"locknoconfirm"        => "Jo hawwe jo hanneling net befêstige.",
+"lockdbsuccesssub" => "Databank is 'Net-skriuwe'",
+"unlockdbsuccesssub" => "Database is skriuwber",
+"lockdbsuccesstext" => "De {{SITENAME}} databank is 'Net-skriuwe' makke.
+<br />Tink derom en meitsje de databank skriuwber as jo ûnderhâld ree is.",
+"unlockdbsuccesstext" => "De {{SITENAME}} databank is skriuwber makke.",
+
+# Move page
+#
+"movepage"             => "Werneam side",
+"movepagetext" => "Dit werneamt in side, mei alle sideskiednis.
+De âlde titel wurdt in trochferwizing nei de nije.
+Keppelings mei de âlde side wurde net feroare;
+gean sels nei of't der dûbele of misse ferwizings binne.
+It hinget fan jo ôf of't de siden noch keppelen binne sa't it mient wie.
+
+De side wurdt '''net''' werneamt as der al in side mei dy namme is, útsein as it in side
+sûnder skiednis is en de side leech is of in trochferwizing is. Sa kinne jo in side
+daalks weromneame as jo in flater meitsje, mar jo kinne in oare side net oerskriuwe.",
+
+"movepagetalktext" => "As der in oerlisside by heart, dan bliuwt dy oan de side keppele, '''útsein''':
+*De nije sidenamme yn in oare nammeromte is,
+*Der keppele oan de nije namme al in net-lege oerlisside is, of
+*Jo dêr net foar kieze.
+
+In dizze gefallen is it oan jo hoe't jo de oerlisside werneame of ynfoegje wolle.",
+
+"movearticle"  => "Werneam side",
+"movenologin"  => "Net oameld",
+"movenologintext" => "Jo moatte [[Wiki:Userlogin|oanmeld]] wêze om in side wer te neamen.",
+
+"newtitle"             => "As nij titel",
+"movepagebtn"  => "Werneam side",
+"pagemovedsub" => "Werneamen slagge",
+"pagemovedtext"        => "Side \"[[$1]]\" werneamd as \"[[$2]]\".",
+"articleexists"        => "Der is al in side mei dy namme,
+of oars is de namme dy't jo oanjûn hawwe net tastean.
+Besykje it op 'e nij.",
+
+"talkexists"   => "It werneamen op sich is slagge, mar de eardere oerlisside is
+net mear keppele om't der foar de nije namme el al in oerlisside wie.
+Gearfoegje de oerlissiden hânmjittig.",
+
+"movedto"              => "werenamd as",
+"talkpagemoved"        => "De oerlisside is al noch keppele.",
+"talkpagenotmoved" => "De oerlisside is <strong>net</strong> mear keppele.",
+# Math
+'mw_math_png' => "Altiten as PNG ôfbyldzje",
+'mw_math_simple' => "HTML foar ienfâldiche formules, oars PNG",
+'mw_math_html' => "HTML as mooglik, oars PNG",
+'mw_math_source' => "Lit de TeX ferzje stean (foar tekstblêdzjers)",
+'mw_math_modern' => "Oanbefelle foar resinte blêdzjers",
+'mw_math_mathml' => 'MathML',
+
+);
+
+
+class LanguageFy extends LanguageUtf8 {
+
+       function getBookstoreList () {
+               global $wgBookstoreListFy ;
+               return $wgBookstoreListFy ;
+       }
+
+       function getNamespaces() {
+               global $wgNamespaceNamesFy;
+               return $wgNamespaceNamesFy;
+       }
+
+
+       function getNsIndex( $text ) {
+               global $wgNamespaceNamesFy;
+
+               foreach ( $wgNamespaceNamesFy as $i => $n ) {
+                       if ( 0 == strcasecmp( $n, $text ) ) { return $i; }
+               }
+               if ( 0 == strcasecmp( "Brûker", $text ) ) return 2;
+               if ( 0 == strcasecmp( "Brûker_oerlis", $text ) ) return 3;
+               if ( 0 == strcasecmp( "Special", $text ) ) return -1;
+               return false;
+       }
+
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsFy;
+               return $wgQuickbarSettingsFy;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesFy;
+               return $wgSkinNamesFy;
+       }
+
+       function getDateFormats() {
+               global $wgDateFormatsFy;
+               return $wgDateFormatsFy;
+       }
+
+       /**
+        * @access public
+        * @param mixed  $ts the time format which needs to be turned into a
+        *               date('YmdHis') format with wfTimestamp(TS_MW,$ts)
+        * @param bool   $adj whether to adjust the time output according to the
+        *               user configured offset ($timecorrection)
+        * @param bool   $format true to use user's date format preference
+        * @param string $timecorrection the time offset as returned by
+        *               validateTimeZone() in Special:Preferences
+        * @return string
+        */
+       function date( $ts, $adj = false, $format = true, $timecorrection = false ) {
+               global $wgUser;
+
+               if ( $adj ) { $ts = $this->userAdjust( $ts, $timecorrection ); }
+
+               $datePreference = $this->dateFormat( $format );
+
+               $month = $this->getMonthAbbreviation( substr( $ts, 4, 2 ) );
+               $day = $this->formatNum( 0 + substr( $ts, 6, 2 ) );
+               $year = $this->formatNum( substr( $ts, 0, 4 ), true );
+
+               switch( $datePreference ) {
+                       case MW_DATE_DMY: return "$day $month $year";
+                       case MW_DATE_YMD: return "$year $month $day";
+                       case MW_DATE_ISO: return substr($ts, 0, 4). '-' . substr($ts, 4, 2). '-' .substr($ts, 6, 2);
+                       default: return "$month $day, $year";
+               }
+       }
+
+       /**
+       * @access public
+       * @param mixed  $ts the time format which needs to be turned into a
+       *               date('YmdHis') format with wfTimestamp(TS_MW,$ts)
+       * @param bool   $adj whether to adjust the time output according to the
+       *               user configured offset ($timecorrection)
+       * @param bool   $format true to use user's date format preference
+       * @param string $timecorrection the time offset as returned by
+       *               validateTimeZone() in Special:Preferences
+       * @return string
+       */
+       function time( $ts, $adj = false, $format = true, $timecorrection = false ) {
+               global $wgUser;
+
+               if ( $adj ) { $ts = $this->userAdjust( $ts, $timecorrection ); }
+               $datePreference = $this->dateFormat( $format );
+
+               if ( $datePreference == MW_DATE_ISO ) {
+                       $sep = ':';
+               } else {
+                       $sep = '.';
+               }
+               
+               $t = substr( $ts, 8, 2 ) . $sep . substr( $ts, 10, 2 );
+
+               if ( $datePreference == MW_DATE_ISO ) {
+                       $t .= $sep . substr( $ts, 12, 2 );
+               }
+               return $this->formatNum( $t );
+       }
+       
+       function getMessage( $key ) {
+               global $wgAllMessagesFy;
+               if( isset( $wgAllMessagesFy[$key] ) ) {
+                       return $wgAllMessagesFy[$key];
+               } else {
+                       return parent::getMessage( $key );
+               }
+       }
+}
+
+?>
diff --git a/languages/LanguageGa.php b/languages/LanguageGa.php
new file mode 100644 (file)
index 0000000..cac3ca2
--- /dev/null
@@ -0,0 +1,2127 @@
+<?php
+
+/* Gaeilge - Irish */
+
+/*
+Seo é an dara leagan den comhad LanguageGa.php. Úsáidtear an iomaí foclóirí agus
+achmhainní idirlín - má tá aon contrárthacht, pléigh é ar an leathanch phlé ach
+NA HATHRAIGH É GO DÍREACH É, MÁS É DO THOIL É!
+
+
+
+This is the second version of the LanguageGa.php file. Multiple dictionaries and
+internet resources have been utilised - if there is any inconsistency or other
+error, discuss it on the talk page but PLEASE DO NOT CHANGE IT DIRECTLY WITHOUT
+DISCUSSION!
+
+*/
+
+# FIXME: Use $wgSitename, $wgMetaNamespace etc
+#  - that could be hard:
+#
+# NOTE TO DEVELOPERS - a genitive version of the sitename Vicipéid
+# is needed for "of" uses etc. The genitive varies for each sitename.
+# How can this be incorporated?
+
+/* private */ $wgNamespaceNamesGa = array(
+       NS_MEDIA            => 'Meán',
+       NS_SPECIAL          => 'Speisialta',
+       NS_MAIN             => '',
+       NS_TALK             => 'Plé',
+       NS_USER             => 'Úsáideoir',
+       NS_USER_TALK        => 'Plé_úsáideora',
+       NS_PROJECT          => 'Vicipéid',
+       NS_PROJECT_TALK     => 'Plé_Vicipéide',
+
+ # NOTE TO DEVELOPERS: A different genitive spelling is needed for
+ # each Wiki name, as can be seen. So the $wgMetaNamespace tag has not been used
+ # here for the moment in some cases, and in other places with a FIXME flag.
+ # Perhaps we'll just have to customise each project file.
+
+       NS_IMAGE            => 'Íomhá',
+       NS_IMAGE_TALK       => 'Plé_íomhá',
+       NS_MEDIAWIKI        => 'MediaWiki',
+       NS_MEDIAWIKI_TALK   => 'Plé_MediaWiki',
+       NS_TEMPLATE         => 'Teimpléad',
+       NS_TEMPLATE_TALK    => 'Plé_teimpléid',
+       NS_HELP             => 'Cabhair',
+       NS_HELP_TALK        => 'Plé_cabhrach',
+       NS_CATEGORY         => 'Catagóir',
+       NS_CATEGORY_TALK    => 'Plé_catagóire'
+) + $wgNamespaceNamesEn;
+
+
+/* private */ $wgQuickbarSettingsGa = array(
+       "Faic", "Greamaithe ar chlé", "Greamaithe ar dheis", "Ag faoileáil ar chlé", "Ag faoileáil ar dheis"
+);
+
+/* private */ $wgSkinNamesGa = array(
+       'standard' => "Gnáth",
+       'nostalgia' => "Sean-nós",
+       'cologneblue' => "Gorm na Colóna",
+       'smarty' => "Paddington",
+       'montparnasse' => "Montparnasse",
+       'davinci' => "DaVinci",
+       'mono' => "Mono",
+       'monobook' => "MonoBook",
+       "myskin" => "MySkin",
+       'chick' => 'Chick'
+) + $wgSkinNamesEn;
+
+/* private */ $wgDateFormatsGa = array(
+       'Is cuma liom',
+       '16:12, Eanáir 15, 2001',
+       '16:12, 15 Eanáir 2001',
+       '16:12, 2001 Eanáir 15',
+       'ISO 8601' => '2001-01-15 16:12:34'
+);
+
+/* private */ $wgMagicWordsGa = array(
+#   ID                          CASE  SYNONYMS
+       MAG_REDIRECT             => array( 0,    '#redirect', '#athsheoladh' ),
+       MAG_NOTOC                => array( 0,    '__NOTOC__', '__GANCÁ__'              ),
+       MAG_FORCETOC             => array( 0,    '__FORCETOC__',         '__CÁGACHUAIR__'  ),
+       MAG_TOC                  => array( 0,    '__TOC__', '__CÁ__'                ),
+       MAG_NOEDITSECTION        => array( 0,    '__NOEDITSECTION__',    '__GANMHÍRATHRÚ__'  ),
+       MAG_START                => array( 0,    '__START__', '__TÚS__'              ),
+       MAG_CURRENTMONTH         => array( 1,    'CURRENTMONTH',  'MÍLÁITHREACH'  ),
+       MAG_CURRENTMONTHNAME     => array( 1,    'CURRENTMONTHNAME',     'AINMNAMÍOSALÁITHREAÍ'  ),
+       MAG_CURRENTMONTHNAMEGEN  => array( 1,    'CURRENTMONTHNAMEGEN',  'GINAINMNAMÍOSALÁITHREAÍ'  ),
+       MAG_CURRENTMONTHABBREV   => array( 1,    'CURRENTMONTHABBREV',   'GIORRÚNAMÍOSALÁITHREAÍ'  ),
+       MAG_CURRENTDAY           => array( 1,    'CURRENTDAY',           'LÁLÁITHREACH'  ),
+       MAG_CURRENTDAYNAME       => array( 1,    'CURRENTDAYNAME',       'AINMANLAELÁITHRIGH'  ),
+       MAG_CURRENTYEAR          => array( 1,    'CURRENTYEAR',          'BLIAINLÁITHREACH'  ),
+       MAG_CURRENTTIME          => array( 1,    'CURRENTTIME',          'AMLÁITHREACH'  ),
+       MAG_NUMBEROFARTICLES     => array( 1,    'NUMBEROFARTICLES',     'LÍONNANALT'  ),
+       MAG_NUMBEROFFILES        => array( 1,    'NUMBEROFFILES',        'LÍONNAGCOMHAD'  ),
+       MAG_PAGENAME             => array( 1,    'PAGENAME',             'AINMANLGH'  ),
+       MAG_PAGENAMEE            => array( 1,    'PAGENAMEE',            'AINMANLGHB'  ),
+       MAG_NAMESPACE            => array( 1,    'NAMESPACE',            'AINMSPÁS'  ),
+       MAG_MSG                  => array( 0,    'MSG:',                 'TCHT:'  ),
+       MAG_SUBST                => array( 0,    'SUBST:',               'IONAD:'  ),
+       MAG_MSGNW                => array( 0,    'MSGNW:',               'TCHTFS:'  ),
+       MAG_END                  => array( 0,    '__END__',              '__DEIREADH__'  ),
+       MAG_IMG_THUMBNAIL        => array( 1,    'thumbnail', 'thumb',   'mionsamhail', 'mion'  ),
+       MAG_IMG_RIGHT            => array( 1,    'right',                'deas'  ),
+       MAG_IMG_LEFT             => array( 1,    'left',                 'clé'  ),
+       MAG_IMG_NONE             => array( 1,    'none',                 'faic'  ),
+       MAG_IMG_WIDTH            => array( 1,    '$1px'                   ),
+       MAG_IMG_CENTER           => array( 1,    'center', 'centre',     'lár'  ),
+       MAG_IMG_FRAMED           => array( 1,    'framed', 'enframed', 'frame', 'fráma', 'frámaithe' ),
+       MAG_INT                  => array( 0,    'INT:', 'INMH:'                   ),
+       MAG_SITENAME             => array( 1,    'SITENAME',             'AINMANTSUÍMH'  ),
+       MAG_NS                   => array( 0,    'NS:', 'AS:'                    ),
+       MAG_LOCALURL             => array( 0,    'LOCALURL:',            'URLÁITIÚIL'  ),
+       MAG_LOCALURLE            => array( 0,    'LOCALURLE:',           'URLÁITIÚILB'  ),
+       MAG_SERVER               => array( 0,    'SERVER',               'FREASTALAÍ'  ),
+       MAG_SERVERNAME           => array( 0,    'SERVERNAME',            'AINMANFHREASTALAÍ' ),
+       MAG_SCRIPTPATH           => array( 0,    'SCRIPTPATH',           'SCRIPTCHOSÁN'  ),
+       MAG_GRAMMAR              => array( 0,    'GRAMMAR:',             'GRAMADACH:'  ),
+       MAG_NOTITLECONVERT       => array( 0,    '__NOTITLECONVERT__', '__NOTC__', '__GANTIONTÚNADTEIDEAL__', '__GANTT__'),
+       MAG_NOCONTENTCONVERT     => array( 0,    '__NOCONTENTCONVERT__', '__NOCC__', '__GANTIONTÚNANÁBHAIR__', '__GANTA__' ),
+       MAG_CURRENTWEEK          => array( 1,    'CURRENTWEEK',          'SEACHTAINLÁITHREACH'  ),
+       MAG_CURRENTDOW           => array( 1,    'CURRENTDOW',           'LÁLÁITHREACHNAS'  ),
+       MAG_REVISIONID           => array( 1,    'REVISIONID',           'IDANLEASAITHE'  ),
+);
+
+#-------------------------------------------------------------------
+# Default messages
+#-------------------------------------------------------------------
+
+# required for copyrightwarning
+global $wgRightsText;
+
+/* private */ $wgAllMessagesGa = array(
+
+# User Toggles'tog-underline'           => "Cuir línte faoi na naisc",
+'tog-highlightbroken'     => "Cuir dath dearg ar naisc briste, <a href=\"\" class=\"new\">mar sin</a>
+(rogha eile: mar sin<a href=\"\" class=\"internal\">?</a>).",
+'tog-justify'             => "Comhfhadaigh na paragraif",
+'tog-hideminor'                 => "Ná taispeáin fo-athruithe i measc na n-athruithe is déanaí",
+'tog-usenewrc'           => "Stíl nua do na hathruithe is déanaí (le JavaScript)",
+'tog-numberheadings'       => "Uimhrigh ceannteidil go huathoibríoch",
+'tog-showtoolbar'              => 'Taispeáin an barra uirlisí eagair (JavaScript)',
+"tog-editondblclick"       => "Cuir leathanaigh in eagar le déchliceáil (JavaScript)",
+"tog-editsection"             =>"Cumasaigh mír-eagarthóireacht le naisc mar seo: [athrú]",
+"tog-editsectiononrightclick"   =>"Cumasaigh mír-eagarthóireacht le deaschliceáil<br> ar ceannteidil (JavaScript)",
+"tog-showtoc"             =>"Taispeáin an clár ábhair (d'ailt le níos mó ná 3 ceannteidil)",
+"tog-rememberpassword"   => "Cuimhnigh m'fhocal faire",
+"tog-editwidth"                 => "Cuir uasmhéid ar an mbosca eagair",
+"tog-watchdefault"           => "Déan faire ar leathanaigh a athraíonn tú",
+"tog-minordefault"           => "Déan mionathrú de gach aon athrú, mar réamhshocrú",
+"tog-previewontop"           => "Cuir an réamhamharc os cionn an bhosca eagair, <br>agus ná cuir é taobh thíos de",
+'tog-previewonfirst'       => 'Taispeáin réamhamharc don chéad athrú',
+"tog-nocache"             => "Ciorraigh taisce na leathanach",
+
+'tog-enotifwatchlistpages'      => 'Cuir ríomhphost chugam nuair a athraítear leathanaigh',
+'tog-enotifusertalkpages'       => 'Cuir ríomhphost chugam nuair a athraítear mo leathanach phlé úsáideora',
+'tog-enotifminoredits'   => 'Cuir ríomhphost chugam nuair a dhéantar mionathruithe chomh maith',
+'tog-enotifrevealaddr'   => 'Taispeáin mo sheoladh ríomhphoist i dteachtaireachtaí fógra',
+'tog-shownumberswatching'       => 'Taispeán an méid úsáideoirí atá ag faire',
+'tog-fancysig'           => 'Síniuithe bunúsacha (gan nasc uathoibríoch)',
+'tog-externaleditor'       => 'Bain úsáid as eagarthóir seachtrach, mar réamhshocrú',
+'tog-externaldiff'           => 'Bain úsáid as difríocht sheachtrach, mar réamhshocrú',
+
+'underline-always' => 'Déan é gach uair é',
+'underline-never' => 'Ná déan é riamh',
+'underline-default' => 'Reamhshocrú ón brabhsálaí',
+
+'sunday' => 'an Domhnach',
+'monday' => 'an Luan',
+'tuesday' => 'an Mháirt',
+'wednesday' => 'an Chéadaoin',
+'thursday' => 'an Déardaoin',
+'friday' => 'an Aoine',
+'saturday' => 'an Satharn',
+'january' => 'Eanáir',
+'february' => 'Feabhra',
+'march' => 'Márta',
+'april' => 'Aibreán',
+'may_long' => 'Bealtaine',
+'june' => 'Meitheamh',
+'july' => 'Iúil',
+'august' => 'Lúnasa',
+'september' => 'Meán Fómhair',
+'october' => 'Deireadh Fómhair',
+'november' => 'Mí na Samhna',
+'december' => 'Mí na Nollag',
+'jan' => 'Ean',
+'feb' => 'Feabh',
+'mar' => 'Márta',
+'apr' => 'Aib',
+'may' => 'Beal',
+'jun' => 'Meith',
+'jul' => 'Iúil',
+'aug' => 'Lún',
+'sep' => 'MFómh',
+'oct' => 'DFómh',
+'nov' => 'Samh',
+'dec' => 'Noll',
+
+
+# Bits of text used by many pages:
+#
+# FIXME
+#
+'categories' => 'Catagóirí',
+'category' => 'catagóir',
+'category_header' => 'Ailt sa chatagóir "$1"',
+"subcategories" => "Fo-chatagóirí",
+
+"linktrail"     => '/^([a-z]+)(.*)\$/sD',
+"mainpage"      => "Príomhleathanach",
+"mainpagetext"  => "Suiteáladh an ríomhchlár vicí go rathúil.",
+"mainpagedocfooter" => "Féach ar [http://meta.wikimedia.org/wiki/MediaWiki_i18n doiciméid um conas an chomhéadán a athrú]
+agus an [http://meta.wikimedia.org/wiki/MediaWiki_User%27s_Guide Lámhleabhar úsáideora] chun cabhair úsáide agus fíoraíochta a fháil.",
+
+# NOTE: To turn off "Community portal" in the title links,
+# set "portal" => "-"
+
+'portal'               => 'Ionad pobail',
+'portal-url'       => '{{ns:4}}:Ionad pobail',
+"about"     => "Maidir leis",
+"aboutsite"     => "Maidir le {{SITENAME}}",
+'article'       => "Leathanach ábhair",
+"aboutpage"     => "{{ns:4}}:Maidir leis",
+"help"      => "Cabhair",
+"helppage"      => "Cabhair:Clár_ábhair",
+"bugreports"    => "Fabht-thuairiscí",
+"bugreportspage"    => "{{ns:4}}:Fabht-thuairiscí",
+'sitesupport'   => 'Síntiúis',
+'sitesupport-url' => '{{ns:4}}:Tacaíocht an tsuímh',
+"faq"     => "Ceisteanna Coiteanta",
+"faqpage"       => "{{ns:4}}:Ceisteanna_Coiteanta",
+"edithelp"      => "Cabhair eagarthóireachta",
+"newwindow"     => "(osclaítear i bhfuinneog eile é)",
+"edithelppage"  => "Cabhair:Eagarthóireacht",
+"cancel"       => "Cealaigh",
+"qbfind"       => "Aimsigh",
+"qbbrowse"      => "Brabhsáil",
+"qbedit"       => "Cuir in eagar",
+"qbpageoptions" => "An leathanach seo",
+"qbpageinfo"    => "Comhthéacs",
+"qbmyoptions"   => "Mo chuid leathanaigh",
+"qbspecialpages" => "Leathanaigh speisialta",
+"moredotdotdot" => "Tuilleadh...",
+"mypage"       => "Mo leathanach",
+"mytalk"       => "Mo chuid phlé",
+"anontalk"      => "Plé don IP seo",
+"navigation"    => "Nascleanúint",
+
+# Metadata in edit box
+'metadata' => '<b>Meiteashonraí</b> (féach ar <a href="$1">here</a> le haghaidh a thuilleadh eolais)',
+'metadata_page' => '{{ns:4}}:Meiteashonraí',
+
+# NOTE: To turn off "Current Events" in the sidebar,
+# set "currentevents" => "-"
+
+"currentevents" => "Cursaí reatha",
+'currentevents-url' => 'Cursaí reatha',
+
+# NOTE: To turn off "Disclaimers" in the title links,
+# set "disclaimers" => "-"
+
+'disclaimers' => 'Séanadh',
+"disclaimerpage" => "{{ns:4}}:Séanadh_ginearálta",
+"errorpagetitle" => "Earráid",
+"returnto"      => "Dul ar ais go $1.",
+"tagline"       => "Ó {{SITENAME}}.",
+"whatlinkshere" => "Leathanaigh a nascaíonn chuig an leathanach seo",
+"help"      => "Cabhair",
+"search"       => "Cuardaigh",
+"go"       => "Téir",
+"history"       => "Stair an lgh seo",
+'history_short' => 'Stair',
+'info_short'    => 'Eolas',
+"printableversion" => "Eagrán inphriontáilte",
+"print"         => "Priontáil",
+"edit"   => "Athraigh an lch seo",
+"editthispage"  => "Athraigh an lch seo",
+"delete"       => "Scrios",
+"deletethispage"    => "Scrios an lch seo",
+'undelete_short1' => 'Díscrios athrú amháin',
+"undelete_short" => "Díscrios $1 athruithe",
+"protect"      => "Glasáil",
+"protectthispage" => "Glasáil an lch seo",
+"unprotect"     =>  "Díghlasáil",
+"unprotectthispage" => "Díghlasáil an lch seo",
+"newpage"       => "Leathanach nua",
+"talkpage"      => "Pléigh an lch seo",
+'specialpage' => 'Leathanach Speisialta',
+'personaltools' => 'Uirlisí phearsánta',
+"postcomment"   => "Caint ar an lch",
+'addsection'   => '+',
+"articlepage"   => "Féach ar an alt",
+"subjectpage"   => "Féach ar an t-ábhar", # For compatibility
+'talk' => 'Plé',
+'views' => 'Tuairimí',
+'toolbox' => 'Bosca uirlisí',
+"userpage"      => "Féach ar lch úsáideora",
+"wikipediapage" => "Féach ar lch thionscadail",
+"imagepage"     => "Féach ar lch íomhá",
+"viewtalkpage"  => "Féach ar phlé",
+"otherlanguages"    => "I dteangacha eile",
+"redirectedfrom"    => "(Athsheolta ó $1)",
+"lastmodified"  => "Athraíodh an leathanach seo ag $1.",
+"viewcount"     => "Rochtainíodh an leathanach seo $1 uair.",
+'copyright'     => "Tá an t-ábhar le fáil faoin $1.",
+'poweredby'     => "Cumhachtaítear {{SITENAME}} ag [http://www.mediawiki.org/ MediaWiki], vicí-inneall le foinse oscailte.",
+"printsubtitle" => "(Ó {{SERVER}})",
+"protectedpage" => "Leathanach glasáilte",
+"administrators"    => "{{ns:4}}:Riarthóirí",
+"sysoptitle"    => "Tá cuntas oibreora córais de dhíth",
+"sysoptext"     => "Ní mór duit bheith i do \"oibreoir córais\"
+chun an gníomh seo a dhéanamh.
+Féach ar $1.",
+"developertitle"    => "Tá cuntas ríomhchláraitheora de dhíth",
+"developertext" => "Ní mór duit bheith i do \"ríomhchláraitheoir\"
+chun an gníomh seo a dhéanamh.
+Féach ar $1.",
+
+'badaccess'     => 'Earráid ceada',
+'badaccesstext' => 'Ní féidir an gníomh seo a dhéanamh muna bhfuil
+an cead "$2" agat.
+See $1.',
+
+'versionrequired' => 'Tá leagan $1 de MediaWiki de dhíth',
+'versionrequiredtext' => 'Tá an leagan $1 de MediaWiki riachtanach chun an leathanach seo a úsáid. Féach ar [[Speisialta:Version]]',
+
+
+"nbytes"       => "$1 beart",
+"go"       => "Téir",
+"ok"       => "Déan",
+"sitetitle"     => "{{SITENAME}}",
+'pagetitle'         => "$1 - {{SITENAME}}",
+"sitesubtitle"  => "An Chiclipéid Shaor",
+"retrievedfrom" => "Fuarthas ar ais ó \"$1\"",
+"newmessages"   => "Tá $1 agat.",
+"newmessageslink" => "teachtaireachtaí nua",
+"editsection"   => "athraigh",
+"toc"     => "Clár ábhair",
+"showtoc"       => "taispeáin",
+"hidetoc"       => "folaigh",
+"thisisdeleted" => "Breathnaigh nó cuir ar ais $1?",
+"restorelink"   => "$1 athruithe scriosaithe",
+'feedlinks' => 'Fotha:',
+'sitenotice'    => '-', # the equivalent to wgSiteNotice
+
+# Short words for each namespace, by default used in the 'article' tab in monobook
+'nstab-main' => 'Alt',
+'nstab-user' => 'Lch úsáideora',
+'nstab-media' => 'Lch meáin',
+'nstab-special' => 'Speisialta',
+'nstab-wp' => 'Lch thionscadail',
+'nstab-image' => 'Comhad',
+'nstab-mediawiki' => 'Teachtaireacht',
+'nstab-template' => 'Teimpléad',
+'nstab-help' => 'Cabhair',
+'nstab-category' => 'Catagóir',
+
+# Main script and global functions
+#
+"nosuchaction"  => "Níl a leithéid de ghníomh ann",
+"nosuchactiontext" => "Níl aithníonn an vicí an gníomh atá ann sa líonsheoladh.",
+"nosuchspecialpage" => "Níl a leithéid de leathanach speisialta ann",
+"nospecialpagetext" => "Níl aithníonn an vicí an leathanach speisialta a d'iarr tú ar.",
+
+# General errors
+#
+"error"         => "Earráid",
+"databaseerror"     => "Earráid sa bunachar sonraí",
+"dberrortext"   => "Tharlaigh earráid chomhréire in iarratas chuig an bhunachar sonraí.
+<blockquote><tt>$1</tt></blockquote>, ón suim \"<tt>$2</tt>\",
+an iarratas deireanach chuig an bhunachar sonrai.
+Chuir MySQL an earráid seo ar ais: \"<tt>$3: $4</tt>\".",
+"dberrortextcl"     => "Tharlaigh earráid chomhréire in iarratas chuig an bhunachar
+
+sonraí.
+\"$1\", ón suim \"$2\",
+ab ea an iarratas fiosraithe deireanach chuig an bhunachar sonrai,
+Chuir MySQL an earráid seo ar ais: \"$3: $4\".\n",
+"noconnect"     => "Tá brón orainn! Tá roinnt deacrachtaí teicniúla ag an vicí faoi
+
+láthair,
+agus ní féidir leis teagmháil a dhéanamh leis an mbunachar sonraí.",
+"nodb"      => "Theip rogha an bhunachair sonraí $1",
+"cachederror"   => "Seo í cóip taisce den leathanach atá á lorg agat (is dócha nach bhfuil sí bord ar bhord leis an leagan
+
+láithreach).",
+'laggedslavemode'   => 'Fógra: B\'fhéidir nach bhfuil an leathanach suas chun dáta.',
+"readonly"      => "Bunachar sonraí glasáilte",
+"enterlockreason" => "Iontráil cúis don glasáil, agus meastachán
+den uair a díghlasálfar an bunachar sonraí.",
+"readonlytext"  => "Tá an bunachar sonraí Vicipéide glasáilte anois do iontráilí agus athruithe nua
+(is dócha go bhfuil sé do gnáthchothabháil).
+Tar éis seo, díghlasálfar an bunachar sonraí arís.
+Tugadh an míniú seo ag an riarthóir a ghlasáil é:
+$1",
+"missingarticle" => "Chuardaigh an bunachar sonraí ar leathanach a mba chóir bheith
+faighte darb teideal \"$1\" ach níor bhfuarthas an leathanach.
+
+Is dócha gur lean tu nasc chuig sean-dhifríocht nó nasc staire a bhaineann le
+leathanach atá scriosta cheana féin.
+
+Muna bhfuil seo an scéal, b'fhéidir go bhfuair tú amach fabht sna bogearraí MediaWiki.
+Déan nóta den URL le do thoil, agus cuir an ábhar in iúl do riarthóir.",
+'readonly_lag' => "Glasáladh an bunachar sonraí go huathoibríoch, mar tá freastalaithe
+sclábhánta an bhunachair sonraí ag teacht suas chun dáta leis an máistirfhreastalaí
+fós.",
+"internalerror" => "Earráid inmhéanach",
+"filecopyerror" => "Ní féidir an comhad \"$1\" a chóipeáil go \"$2\".",
+"filerenameerror" => "Ní féidir an comhad \"$1\" a athainmnigh mar \"$2\".",
+"filedeleteerror" => "Ní féidir an comhad \"$1\" a scriosaigh amach.",
+"filenotfound"  => "Ní bhfuarthas an comhad \"$1\".",
+"unexpected"    => "Luach gan súil leis: \"$1\"=\"$2\".",
+"formerror"     => "Earráid: ní féidir an foirm a tabhair isteach",
+"badarticleerror" => "Ní féidir an gníomh seo a dhéanamh ar an leathanach seo.",
+"cannotdelete"  => "Ní féidir an leathanach nó íomhá sonraithe a scriosaigh. (B'fhéidir gur scrios duine eile é cheana féin.)",
+"badtitle"      => "Teideal neamhbhailí",
+"badtitletext"  => "Bhí teideal an leathanaigh a d'iarr tú ar neamhbhailí, folamh, nó
+teideal idirtheangach nó idirvicí nasctha go mícheart.",
+"perfdisabled" => "Tá brón orainn! Díchumasaíodh an gné seo ar feadh tamaill chun luas an bhunachair sonraí a chosaint.",
+"perfdisabledsub" => "Is cóip i dtaisce é seo, ó $1:",
+"wrong_wfQuery_params" => "Paraiméadair míchearta don wfQuery()<br>
+Feidhm: $1<br>
+Iarratas: $2
+",
+'perfcached' => 'Fuarthas na sonraí seo as dtaisce, agus is dócha nach bhfuil siad suas chun dáta:',
+"viewsource" => "Féach ar fhoinse",
+"protectedtext" => "Glasáladh an leathanach seo chun é a chosaint i gcoinne athruithe. Tá go leor
+cúiseanna féideartha don scéal seo. Féach ar
+[[{{ns:project}}:Leathanach glasáilte]] más é do thoil é.
+
+Is féidir leat foinse an leathanaigh seo a féachaint agus a chóipeáil:",
+'sqlhidden' => '(Iarratas SQL folaithe)',
+
+# Login and logout pages
+#
+"logouttitle"   => "Logáil amach",
+"logouttext" => "Tá tú logáilte amach anois.
+Is féidir leat an {{SITENAME}} a úsáid fós gan ainm, nó is féidir leat logáil isteach
+arís mar an úsáideoir céanna, nó mar úsáideoir eile. Tabhair faoi deara go taispeáinfear roinnt
+leathanaigh mar atá tú logtha ann fós, go dtí go ghlanfá amach do thaisce brabhsálaí\n",
+
+"welcomecreation" => "== Tá fáilte romhat, $1! ==
+
+Cruthaíodh do chuntas. Ná déan dearmad ar do sainroghanna phearsanta Vicipéide a hathrú.",
+
+"loginpagetitle" => "Logáil isteach",
+"yourname"      => "D'ainm úsáideora",
+"yourpassword"  => "D'fhocal faire",
+"yourpasswordagain" => "Athiontráil d'fhocal faire",
+"newusersonly"  => " (D'úsáideoirí úrnua amháin)",
+"remembermypassword" => "Cuimhnigh orm",
+"yourdomainname"       => "D'fhearann",
+'externaldberror'      => 'Bhí earráid bhunachair sonraí ann maidir le fíordheimhniú seachtrach, nóThere was either an external authentication database error or you are not allowed to update your external account.',
+"loginproblem"  => "<b>Bhí fadhb ann maidir leis an logáil isteach.</b><br>Déan iarracht eile!",
+"alreadyloggedin" => "<font color=red><b>A húsáideoir $1, tá tú logáilte isteach cheana féin!</b></font><br>\n",
+
+"login"     => "Logáil isteach",
+'loginprompt'   => "Tá fianáin de dhíth chun logáil isteach a dhéanamh ag {{SITENAME}}.",
+"userlogin"     => "Logáil isteach",
+"logout"       => "Logáil amach",
+"userlogout"    => "Logáil amach",
+"notloggedin"   => "Níl tú logáilte isteach",
+"createaccount" => "Cruthaigh cuntas nua",
+"createaccountmail" => "le ríomhphost",
+"badretype"     => "D'iontráil tú dhá fhocal faire difriúla.",
+"userexists"    => "Tá an ainm úsáideora a d'iontráil tú á úsáid cheana féin. Déan rogha d'ainm eile, más é do thoil é.",
+"youremail"     => "Do ríomhphost *",
+'yourrealname'  => "D'fhíorainm **",
+'yourlanguage'  => 'Teanga',
+'yourvariant'  => 'Malairt',
+"yournick"      => "Do leasainm (i síniuithe)",
+"emailforlost"  => "* Níl na boscaí le réalt (*, **) ach roghnach.  Le seoladh ríomhphoist i dtaisce, ba féidir le
+daoine teagmhail a dhéanamh leat tríd an suíomh gan do sheoladh ríomhphoist a nochtaigh dóibh. Ina theannta sin,
+is cabhair é má dheanfá dearmad ar d'fhocal faire.<br /><br />Má toghaíonn tú d'ainm ceart a chur isteach,
+úsáidfear é chun do chuid dreachtaí a chur i leith tusa.",
+'prefs-help-email'      => '** <strong>Ríomhphost</strong> (roghnach): Leis an tréith seo is féidir teagmháil a dhéanamh leat tríd do leathanach úsáideora nó phlé_úsáideora gan do sheoladh ríomhphost a thaispeáint.',
+'prefs-help-email-enotif' => 'Úsáidtear an seoladh seo chun fógraíocht ríomhphoist a sheoladh dhuit, má chumasaigh tú an rogha sin.',
+'prefs-help-realname'   => '* <strong>Fíorainm</strong> (roghnach): má toghaíonn tú é sin a chur ar fáil, úsáidfear é chun
+do chuid dreachtaí a chur i leith tusa.',
+"loginerror"    => "Earráid leis an logáil isteach",
+'nocookiesnew'  => "Chruthaíodh an cuntas úsáideora, ach níl tú logáilte isteach.
+
+Úsáideann {{SITENAME}} fianáin chun úsáideoirí a logáil isteach. Tá fianáin díchumasaithe agat. Cumasaigh iad le do thoil, agus ansin logáil isteach le d'ainm úsáideora agus d'fhocal faire úrnua.",
+"nocookieslogin"      => "Úsáideann {{SITENAME}} fianáin chun úsáideoirí a logáil
+isteach. Tá fianáin díchumasaithe agat. Cumasaigh iad agus déan athiarracht, le do thoil.",
+"noname"       => "Níor shonraigh tú ainm úsáideora bailí.",
+"loginsuccesstitle" => "Logáil isteach rathúil",
+"loginsuccess"  => "Tá tú logáilte isteach anois sa Vicipéid mar \"$1\".",
+"nosuchuser"    => "Níl aon úsáideoir ann leis an ainm \"$1\".
+Cinntigh do litriú, nó bain úsáid as an foirm thíos chun cuntas úsáideora nua a chruthú.",
+'nosuchusershort'       => "Níl aon úsáideoir ann leis an ainm \"$1\". Cinntigh do litriú.",
+"wrongpassword" => "D'iontráil tú focal faire mícheart (nó ar iarraidh). Déan iarracht eile le do thoil.",
+"mailmypassword" => "Seol m'fhocal faire chugam.",
+'passwordremindertitle' => "Cuimneachán an fhocail faire ó {{SITENAME}}",
+'passwordremindertext' => "D'iarr duine éigin (tusa de réir cosúlachta, ón seoladh IP $1)
+go sheolfaimis focal faire Vicipéide nua.
+\"$3\" an focal faire don úsáideoir \"$2\" anois.
+Ba chóir duit lógail isteach anois agus d'fhocal faire a athrú.",
+
+"noemail"       => "Níl aon seoladh ríomhphoist i gcuntas don úsáideoir \"$1\".",
+"passwordsent"  => "Cuireadh focal faire nua chuig an seoladh ríomhphoist atá cláraithe do \"$1\".
+Nuair atá sé agat, logáil isteach arís le do thoil chun fíordheimhniu a dhéanamh.",
+'eauthentsent'      =>  "Cuireadh teachtaireacht ríomhphoist chuig an seoladh
+chun fíordheimhniú a dhéanamh. Chun fíordheimhniú a dhéanamh gur leatsa an cuntas, caithfidh tú glac leis an teachtaireacht sin nó ní sheolfar aon rud eile chuig do chuntas.",
+'loginend'           => ' ',
+'mailerror' => "Tharlaigh earráid leis an seoladh: $1",
+'acct_creation_throttle_hit' => 'Tá brón orainn, ach tá tú i ndiadh $1 cuntas á chruthú. Ní féidir leat níos mó a dhéanamh.',
+
+'emailauthenticated'    => 'D\'fhíordheimhníodh do sheoladh ríomhphoist ar $1.',
+'emailnotauthenticated' => '<strong>Ní dhearna fíordheimhniú</strong> ar do sheoladh ríomhphoist fós, agu díchumasaítear na hardtréithe ríomhphoist go dtí go fíordheimhneofaí é <strong>(d.c.f.)</strong>.<br>
+Chun fíordheimhniú a dhéanamh, logáil isteach leis an focal faire neamhbhuan atá seolta chugat, nó iarr ar ceann nua ar an leathanach logála istigh.',
+'invalidemailaddress'   => 'Ní féidir an seoladh ríomhphoist a ghlacadh leis mar is dócha go bhfuil formáid neamhbhailí aige.
+
+Iontráil seoladh dea-fhormáidte le do thoil, nó glan an réimse sin.',
+
+# Edit page toolbar
+'bold_sample'=>'Cló trom',
+'bold_tip'=>'Cló trom',
+'italic_sample'=>'Cló Iodáileach',
+'italic_tip'=>'Cló Iodáileach',
+'link_sample'=>'Ainm naisc',
+'link_tip'=>'Nasc inmhéanach',
+'extlink_sample'=>'http://www.sampla.com ainm naisc',
+'extlink_tip'=>'Nasc seachtrach (cuimhnigh an réimír http://)',
+'headline_sample'=>'Cló ceannlíne',
+'headline_tip'=>'Ceannlíne Leibhéil 2',
+'math_sample'=>'Cuir foirmle isteach anseo',
+'math_tip'=>'Foirmle matamataice (LaTeX)',
+'nowiki_sample'=>'Cuir téacs neamh-fhormáide anseo',
+'nowiki_tip'=>'Scaoil thar ar fhormáid mearshuímh',
+'image_sample'=>'Sámpla.jpg',
+'image_tip'=>'Íomhá leabaithe',
+'media_sample'=>'Sámpla.mp3',
+'media_tip'=>'Nasc chuig comhad meáin',
+'sig_tip'=>'Do shíniú le stampa ama',
+'hr_tip'=>'Líne cothrománach (inúsáidte go coigilteach)',
+'infobox'=>'Roghnaigh cnaipe chun téacs sámpla a fháil',
+# alert box shown in browsers where text selection does not work, test e.g. with mozilla or konqueror
+'infobox_alert'=>"Más mhaith leat téacs a fhormáidigh, cuir isteach anseo é.\\n
+
+Taispeánfar an
+téacs sa bhosca eolais le haghaidh gearr agus greamaithe.\\nSámpla:\\nTaispeánfar\\n$1
+
+\\nmar sin:\\n$2",
+
+# Edit pages
+#
+"summary"       => "Achoimriú",
+"subject"       => "Ábhar/ceannlíne",
+"minoredit"     => "Is mionathrú é seo",
+"watchthis"     => "Déan faire ar an lch seo",
+"savearticle"   => "Sábháil an lch",
+"preview"       => "Réamhamharc",
+"showpreview"   => "Taispeáin réamhamharc",
+"blockedtitle"  => "Tá an úsáideoir seo faoi chosc",
+"blockedtext"   => "Chuir $1 cosc ar d'ainm úsáideora nó ar do sheoladh IP.
+Seo é an cúis a thugadh:<br>''$2''<p>Is féidir leat teagmháil a dhéanamh le $1 nó le ceann eile de na
+[[{{ns:4}}:Riarthóirí|riarthóirí]] chun an cosc a phléigh.
+
+Tabhair faoi deara nach bhfuil cead agat an gné \"cuir ríomhphost chuig an úsáideoir seo\" a úsáid
+mura bhfuil seoladh ríomhphoist bailí cláraithe i do [[Speisialta:Preferences|shainroghanna úsáideora]].
+
+Is é $3 do sheoladh IP. Más é do thoil é, déan tagairt den seoladh seo le gach ceist a chuirfeá.
+",
+"whitelistedittitle" => "Logáil isteach chun athrú a dhéanamh",
+"whitelistedittext" => "Ní mór duit [[Speisialta:Userlogin|logáil isteach]] chun ailt a athrú.",
+"whitelistreadtitle" => "Logáil isteach chun ailt a léamh",
+"whitelistreadtext" => "Ní mór duit [[Speisialta:Userlogin|logáil isteach]] chun ailt a léamh.",
+"whitelistacctitle" => "Níl cead agat cuntas a chruthú",
+"whitelistacctext" => "Chun cuntais nua a chruthú sa vicí seo, caithfidh tú [[Speisialta:Userlogin|logáil
+isteach]] agus caithfidh go bhfuil an cead riachtanach agat.",
+'loginreqtitle' => 'Tá logáil isteach de dhíth ort',
+"accmailtitle" => "Seoladh an focal faire.",
+"accmailtext" => "Seoladh chuig $2 focal faire an úsáideora '$1'.",
+"newarticle"    => "(Nua)",
+"newarticletext" =>
+"Lean tú nasc chuig leathanach a nach bhfuil ann fós.
+Chun an leathanach a chruthú, tosaigh ag clóscríobh san bosca anseo thíos
+(féach ar an [[Vicipéid:Cabhair|leathanach cabhrach]] chun a thuilleadh eolais a fháil).
+Má tháinig tú anseo as dearmad, brúigh an cnaipe '''ar ais''' ar do líonléitheoir.",
+'talkpagetext' => '<!-- MediaWiki:teacsphlé -->',
+"anontalkpagetext" => "---- ''Is é seo an leathanach plé do úsáideoir gan ainm nach chruthaigh
+cuntas fós nó nach úsáideann a chuntas phéarsanta. Dá bhrí sin, caithfimid an [[seoladh IP]] uimhriúil a úsáid
+chun é/í a ionannaigh. Is féidir cuid mhaith úsáideoirí an seoladh IP céanna a úsáid. Má tá tú
+i do úsáideoir gan ainm agus má tá sé do thuairim go rinneadh léiriuithe neamhfheidhmeacha fút,
+[[Special:Userlogin|cruthaigh cuntas nó logáil isteach]] le do thoil chun mearbhall a héalú
+le húsáideoirí eile gan ainmneacha amach anseo.'' ",
+"noarticletext" => "(Níl aon téacs ar an leathanach seo faoi láthair)",
+'clearyourcache' => "'''Tabhair faoi deara:''' Tar éis duit ábhar a shábháil, ní mór duit
+taisce do líonléitheora chun na hathruithe a fheiceáil After saving, you have to clear your
+browser cache to see the changes: '''Mozilla / Netscape:''' roghnaigh ''Athlódáil''
+(nó ''Ctrl-R''), '''IE / Opera:''' ''Ctrl-F5'', '''Safari:''' ''Cmd-R'', '''Konqueror''' ''Ctrl-R''.",
+'usercssjsyoucanpreview' => "<strong>Leid:</strong> Sula sábhálaím tú, úsáid an cnaipe
+'Réamhamharc' chun do CSS/JS nua a tástáil.",
+'usercsspreview' => "'''Cuimhnigh nach bhfuil seo ach réamhamharc do CSS úsáideora -
+níor sábháladh é go fóill!'''",
+'userjspreview' => "'''Cuimhnigh nach bhfuil seo ach réamhamharc do JavaScript úsáideora
+- níor sábháladh é go fóill!'''",
+"updated"       => "(Leasaithe)",
+"note"   => "<strong>Tabhair faoi deara:</strong> ",
+"previewnote"   => "Cuimhnigh nach bhfuil seo ach réamhamharc, agus nach sábháladh é fós!",
+"previewconflict" => "San réamhamharc seo, feachann tú an téacs dé réir an eagarbhosca
+thuas mar a taispeáinfear é má sábháilfear é.",
+"editing"       => "Ag athrú $1",
+"editconflict"  => "Coimhlint athraithe: $1",
+"explainconflict" => "D'athraigh duine eile an leathanach seo ó shin a thosaigh tú ag athrú é.
+Sa bhosca seo thuas feiceann tú téacs an leathanaigh mar atá sé faoi láthair.
+Tá do chuid athruithe sa bhosca thíos.
+Caithfidh tú do chuid athruithe a chumasadh leis an leagan láithreach.
+Nuair a brúann tú ar an cnaipe \"Sábháil an leathanach\", ní shábhálfar aon rud <b>ach
+amháin</b> an téacs sa bhosca thuas.\n<p>",
+"yourtext"      => "Do chuid téacs",
+"storedversion" => "Eagrán sábháilte",
+"editingold"    => "<strong>AIRE: Tá tú ag athrú eagrán an leathanaigh atá as dáta.
+Dá shábhálfá é, caillfear aon athrú a rinneadh ó shin an eagrán seo.</strong>\n",
+"yourdiff"      => "Difríochtaí",
+"copyrightwarning" => "Tabhair faoi dearadh go scaoiltear gach ceart le Vicipéid de réir tearmaí an <i>GNU Free Documentation License</i> (féach ar $1 le haghaidh tuilleadh eolais).
+Munar mian leat go gcuirfí do chuid scríbhinn in eagar go héadrócaireach agus go n-athdálfaí gan teorainn iad, ná
+tabhair isteach anseo iad.<br>
+Ina theannta sin, geallann tú gur scríobh tú féin an dréacht seo, nó gur chóipeáil tú é ó fhoinse gan chóipcheart
+é. <strong>NÁ TABHAIR ISTEACH OBAIR LE CÓIPCHEART GAN CHEAD!</strong>",
+"copyrightwarning2" => "Tabhair faoi dearadh gur féidir le cuiditheoirí eile gach dréacht do {{SITENAME}} a chur in eagar, a athrú agus a scriosadh. Munar mian leat go gcuirfí do chuid scríbhinn in eagar go héadrócaireach agus go n-athdálfaí gan teorainn iad, ná tabhair isteach anseo iad.<br> Ina theannta sin, geallann tú gur scríobh tú féin an dréacht seo, nó gur chóipeáil tú é ó fhoinse gan chóipcheart é (féach ar $1 le haghaidh tuilleadh eolais). <strong>NÁ TABHAIR ISTEACH OBAIR LE CÓIPCHEART GAN CHEAD!</strong>",
+"longpagewarning" => "AIRE: Tá an leathanach seo $1 cilibheart i bhfad; ní féidir le roinnt brabhsálaithe
+leathanaigh a athrú má tá siad breis agus 32kb, nó níos fada ná sin.
+Más féidir, giotaigh an leathanach i gcodanna níos bige.",
+"readonlywarning" => "AIRE: Glasáladh an bunachar sonraí, agus mar sin
+ní féidir leat do chuid athruithe a shábháil díreach anois. B'fhéidir gur mhaith leat an téacs a ghearr is
+ghreamú i gcomhad téacs agus é a úsáid níos déanaí.",
+"protectedpagewarning" => "AIRE:  Glasáladh an leathanach seo, agus ní féidir le duine ar bith é a athrú
+ach amhaín na húsáideoirí le pribhléidí oibreora córais. Bí cinnte go leanann tú na
+<a href='$wgScriptPath/$wgMetaNamespace:Treoirlínte_do_leathanaigh_glasáilte'>treoirlínte do leathanaigh
+glasáilte</a>.",
+
+# History pages
+#
+"revhistory"    => "Stáir athraithe",
+"nohistory"     => "Níl aon stáir athraithe ag an leathanach seo.",
+"revnotfound"   => "Ní bhfuarthas an athrú",
+"revnotfoundtext" => "Ní bhfuarthas seaneagrán an leathanaigh a d'iarr tú ar.
+Cinntigh an URL a d'úsáid tú chun an leathanach seo a rochtain.\n",
+"loadhist"      => "Ag lódáil stáir an leathanaigh",
+"currentrev"    => "Leagan láithreach",
+"revisionasof"  => "Leagan ó $1",
+'revisionasofwithlink'  => 'Leagan ó $1; $2<br />$3 | $4',
+'previousrevision'      => '?Leagan níos sine',
+'nextrevision'   => 'Leagan níos nuaí?',
+'currentrevisionlink'   => 'féach ar an leagan laithreach',
+"cur"     => "rth",
+"next"   => "lns",
+"last"   => "rmh",
+"orig"   => "bun",
+'histlegend'    => "Difríochtaí a roghnú: marcáil na boscaí de na eagráin atá ag teastail uait á cuir i gcomparáid, agus brúigh Iontráil nó an cnaipe ag bun an leathanaigh.<br/>
+Eochair: (rth) = difríocht leis an leagan láithreach,
+(rmh) = difríocht leis an eagrán roimhe, M = mionathrú",
+'history_copyright'    => '-',
+'deletedrev' => '[scriosta]',
+'histfirst' => 'An ceann is luaithe',
+'histlast' => 'An ceann is déanaí',
+
+# Diffs
+#
+"difference"    => "(Difríochtaí idir leaganacha)",
+"loadingrev"    => "ag lódáil leagan don difríocht",
+"lineno"       => "Líne $1:",
+"editcurrent"   => "Athraigh leagan láithreach an leathanaigh seo",
+'selectnewerversionfordiff' => 'Roghnaigh leagan níos nuaí mar chomparáid',
+'selectolderversionfordiff' => 'Roghnaigh leagan níos sine mar chomparáid',
+'compareselectedversions' => 'Cuir na leagain roghnaithe i gcomparáid',
+
+# Search results
+#
+"searchresults" => "Torthaí an chuardaigh",
+"searchresulttext" => "Féach ar [[Vicipéid:Cuardach|Cuardach sa Vicipéid]] chun a thuilleadh eolais a fháil maidir le cuardaigh Vicipéide.",
+"searchquery"   => "Don iarratas \"$1\"",
+"badquery"      => "Iarratas fiosraithe neamhbhailí",
+"badquerytext"  => "Nior éirigh linn d'iarratas a phróiseáil.
+Is dócha go rinne tú cuardach ar focal le níos lú ná trí litir,
+gné a nach bhfuil le tacaíocht aige fós.
+B'fhéidir freisin go mhíchlóshcríobh tú an leagan, mar shampla
+\"éisc agus agus lanna\". Déan athiarracht.",
+"matchtotals"   => "Bhí an cheist \"$1\" ina mhacasamhail le $2 teidil alt
+agus leis an téacs i $3 ailt.",
+"nogomatch" => "Níl aon leathanach ann leis an teideal áirithe seo air. Tá cuardach á dhéanamh sa téacs iomlán...",
+"titlematches"  => "Tá macasamhla teidil alt ann",
+"notitlematches" => "Níl macasamhla teidil alt ann",
+"textmatches"   => "Tá macasamhla téacs alt ann",
+"notextmatches" => "Níl macasamhla téacs alt ann",
+"prevn"         => "na $1 roimhe",
+"nextn"         => "an chéad $1 eile",
+"viewprevnext"  => "Taispeáin ($1) ($2) ($3).",
+"showingresults" => "Ag taispeáint thíos <b>$1</b> toraidh, ag tosachh le #<b>$2</b>.",
+"showingresultsnum" => "Ag taispeáint thíos <b>$3</b> toraidh, ag tosach le #<b>$2</b>.",
+"nonefound"     => "<strong>Tabhair faoi deara</strong>: go minic, ní éiríonn cuardaigh nuair a cuardaítear focail an-coiteanta, m.sh., \"ag\" is \"an\",
+a nach bhfuil innéacsaítear, nó nuair a ceisteann tú níos mó ná téarma amháin (ní
+taispeáintear sna toraidh ach na leathanaigh ina bhfuil go leoir na téarmaí cuardaigh).",
+"powersearch" => "Cuardaigh",
+"powersearchtext" => "
+Cuardaigh sna hainmspásanna :<br>
+$1<br>
+$2 Cuir athsheolaidh in áireamh   Cuardaigh ar $3 $9",
+"searchdisabled" => "<p>Tá brón orainn! Mhíchumasaíodh an cuardach téacs iomlán go sealadach chun luas an tsuímh
+a chosaint. Idir an dá linn, is féidir leat an cuardach Google anseo thíos a úsáid - b'fhéidir go bhfuil sé as dáta.</p>",
+
+"blanknamespace" => "(Gnáth)",
+
+# Preferences page
+#
+"preferences"   => "Sainroghanna",
+"prefsnologin" => "Níl tú logáilte isteach",
+"prefsnologintext"  => "Ní mór duit [[Speisialta:Userlogin|logáil isteach]] chun do chuid sainroghanna phearsanta a shocrú.",
+"prefslogintext" => "Tá tú logáilte isteach mar \"$1\".
+Is é $2 d'uimhir aitheantais inmhéanach.
+
+Féach ar [[{{ns:4}}:Cabhair do sainroghanna úsáideora]] chun cabhair a fháil mar gheall ar na roghanna.",
+ "prefsreset"    => "D'athraíodh do chuid sainroghanna ar ais chuig an leagan bunúsach ón stóras.",
+"qbsettings"    => "Sainroghanna an bosca uirlisí",
+"changepassword" => "Athraigh d'fhocal faire",
+"skin"   => "Craiceann",
+"math"   => "Ag aistriú na matamaitice",
+"dateformat"    => "Formáid dáta",
+"math_failure"      => "Theip anailís an fhoirmle",
+"math_unknown_error"    => "earráid anaithnid",
+"math_unknown_function" => "foirmle anaithnid ",
+"math_lexing_error" => "Theipeadh anailís an fhoclóra",
+"math_syntax_error" => "earráid comhréire",
+'math_image_error'      => 'Theipeadh aistriú an PNG; tástáil má tá na ríomhchláir latex, dvips, gs, agus convert
+i suite go maith.',
+'math_bad_tmpdir'       => 'Ní féidir scríobh chuig an fillteán mata sealadach, nó é a chruthú',
+'math_bad_output'       => 'Ní féidir scríobh chuig an fillteán mata aschomhaid, nó é a chruthú',
+'math_notexvc'  => 'Níl an ríomhchlár texvc ann; féach ar mata/EOLAIS chun é a sainathrú.',
+'prefs-personal' => 'Sonraí úsáideora',
+'prefs-rc' => 'Athruithe le déanaí agus taispeántas stumpaí',
+'prefs-misc' => 'Sainroghanna éagsúla',
+"saveprefs"     => "Sábháil sainroghanna",
+"resetprefs"    => "Athshuigh sainroghanna",
+"oldpassword"   => "Seanfhocal faire",
+"newpassword"   => "Nuafhocal faire",
+"retypenew"     => "Athiontráil an nuafhocal faire",
+"textboxsize"   => "Eagarthóireacht",
+"rows"   => "Sraitheanna",
+"columns"       => "Colúin",
+"searchresultshead" => "Sainroghanna do toraidh cuardaigh",
+"resultsperpage" => "Cuairt le taispeáint ar gach leathanach",
+"contextlines"  => "Línte le taispeáint do gach cuairt",
+"contextchars"  => "Litreacha chomhthéacs ar gach líne",
+"stubthreshold" => "Tairseach do taispeántas stumpaí",
+"recentchangescount" => "Méid teideal sna hathruithe le déanaí",
+"savedprefs"    => "Sábháladh do chuid sainroghanna.",
+'timezonelegend' => 'Crios ama',
+"timezonetext"  => "Iontráil an méid uaireanta a difríonn do am áitiúil
+den am an freastalaí (UTC).",
+"localtime" => "An t-am áitiúil",
+"timezoneoffset" => "Difear",
+"servertime"    => "Am an freastalaí anois",
+"guesstimezone" => "Líon ón líonléitheoir",
+"emailflag"     => "Coisc ríomhphost a sheolann úsáideoirí eile",
+"defaultns"     => "Cuardaigh sna ranna seo a los éagmaise:",
+'default'             => 'réamhshocrú',
+'files'                        => 'Comhaid',
+
+# User levels special page
+#
+
+# switching pan
+'editgroup' => 'Cuir Grúpa In Eagar',
+'addgroup' => 'Cuir Grúpa Leis',
+'editusergroup' => 'Cuir Grúpái Úsáideoirí In Eagar',
+
+# group editing
+'savegroup' => 'Sábháil an Ghrúpa',
+
+# user groups editing
+'saveusergroups' => 'Sábháil Grúpaí Úsáideoirí',
+
+# group editing
+'groups-editgroup'       => 'Cuir grúpa in eagar',
+'groups-addgroup'         => 'Cuir grúpa leis',
+'groups-editgroup-preamble' => 'Má thosaíonn an ainm nó an cur síos le hidirstad,
+measfar go bhfuil ainm teachtaireacha ann sa chuid eile, agus mar sin
+beidh an téacs san ainmspás MediaWiki.',
+'groups-editgroup-name'     => 'Ainm an ghrúpa: ',
+'groups-editgroup-description' => 'Cur síos ar an ngrúpa (255 carachtar an uasmhéid):<br/>',
+'savegroup'             => 'Sábháil an Ghrúpa',
+'groups-tableheader'   => 'ID || Ainm || Cur Síos || Cearta',
+'groups-existing'         => 'Grúpaí atá ann cheana féin',
+'groups-noname'             => 'Cuir ainm bailí i leith don ghrúpa',
+'groups-already-exists'     => 'Tá grúpa ann leis an ainm sin cheana féin',
+'addgrouplogentry'       => 'Cuireadh an ghrúpa $2 leis',
+'changegrouplogentry'       => 'Athraíodh an ghrúpa $2',
+'renamegrouplogentry'       => 'Athainmníodh an ghrúpa $2 mar $3',
+
+# user groups editing
+#
+'userrights-editusergroup' => 'Cuir grúpaí na n-úsáideoirí in eagar',
+'saveusergroups' => 'Sábháil Grúpaí na n-Úsáideoirí',
+'userrights-groupsmember' => 'Ball de:',
+'userrights-groupsavailable' => 'Grúpaí atá le fáil:',
+'userrights-groupshelp' => 'Roghnaigh na grúpaí a bhfuil tú ag cur an úsáideoir leis nó ag baint an úsáideoir de.
+Ní bheidh aon athrú le grúpaí neamhroghnaithe. Is féidir leat grúpa a díroghnú le húsáid CTRL + cléchliceáil',
+'userrights-logcomment' => 'Athraíodh an ballraíocht grúpa ó $1 go $2',
+
+# Default group names and descriptions
+#
+'group-anon-name'       => 'Gan ainm',
+'group-anon-desc'       => 'úsáideoirí gan ainmneacha',
+'group-loggedin-name'   => 'Úsáideoir',
+'group-loggedin-desc'   => 'Gnáth-úsáideoirí atá logáilte isteach',
+'group-admin-name'      => 'Riarthóir',
+'group-admin-desc'      => 'Úsáideoirí iontaofa, atá ar a gcumas úsáideoirí a chosc agus ailt a scriosadh',
+'group-bureaucrat-name' => 'Maorlathach',
+'group-bureaucrat-desc' => 'Is féidir le grúpa na maorlathach oibreoirí córais a dhéanamh',
+'group-steward-name'    => 'Maor',
+'group-steward-desc'    => 'Rochtain iomlán',
+
+# Recent changes
+#
+"changes" => "athruithe",
+"recentchanges" => "Athruithe is déanaí",
+'recentchanges-url' => 'Speisialta:Recentchanges',
+"recentchangestext" => "Déan faire ar na hathruithe is déanaí sa vicí ar an leathanach seo.",
+"rcloaderr"     => "Ag lódáil na athruithe is déanaí",
+"rcnote"       => "Is iad seo a leanas na <strong>$1</strong> athruithe is déanaí sna <strong>$2</strong> lae seo caite.",
+"rcnotefrom"    => "Is iad seo a leanas na hathruithe ó <b>$2</b> (go dti <b>$1</b> taispeánaithe).",
+"rclistfrom"    => "Taispeáin nua-athruithe dom ó <b>$1</b> anuas)",
+'showhideminor' => "$1 mionathruithe | $2 robait | $3 úsáideoirí atá logáilte isteach | $4 athruithe faoi phatról",
+# "rclinks"     => "Taispeáin na $1 athruithe is déanaí sna $2 uaire seo caite / $3 laethanta seo caite.",
+# "rclinks"     => "Taispeáin na $1 athruithe is déanaí sna $2 laethanta seo caite.",
+"rclinks"       => "Taispeáin na $1 athruithe is déanaí sna $2 laethanta seo caite; $3 mionathruithe",
+"rchide"       => "san fhoirm $4; $1 mionathruithe; $2 fo-ainmspásanna; $3 athruithe ilchodacha.",
+"rcliu"         => "; $1 athruithe de úsáideoirí atá logáilte isteach",
+"diff"   => "difr",
+"hist"   => "stáir",
+"hide"   => "Folaigh",
+"show"   => "taispeán",
+"tableform"     => "tábla",
+"listform"      => "liosta",
+"nchanges"      => "$1 athruithe",
+"minoreditletter" => "m",
+"newpageletter" => "N",
+'sectionlink' => '?',
+'number_of_watching_users_RCview'       => '[$1]',
+'number_of_watching_users_pageview'     => '[$1 úsáideoirí ag breathnú]',
+
+# Upload
+#
+"upload"       => "Uaslódáil comhad",
+"uploadbtn"     => "Uaslódáil comhad",
+"uploadlink"    => "Uaslódáil íomhánna",
+"reupload"      => "Athuaslódáil",
+"reuploaddesc"  => "Dul ar ais chuig an fhoirm uaslódála.",
+"uploadnologin" => "Nil tú logáilte isteach",
+"uploadnologintext" => "Ní mór duit <a href=\"" .
+  "{{localurle:Speisialta:Userlogin}}\">logáil isteach</a>
+chun comhaid a huaslódáil.",
+"uploaderror"   => "Earráid uaslódála",
+"uploadtext"    => "'''STOP!''' Sul má dhéanann tú uaslódáil anseo,
+bí cinnte an [[Vicipéid:Polasaí_úsáide_íomhá|polasaí úsáide íomhá]] atá ag Vicipéid a léamh agus géilleadh dó.
+
+Má tá comhad ann cheana leis an ainm céanna atá tú ag tabhairt don chomhad nua, cuirfear an comhad nua
+in áit an sean-chomhaid gan fógra.
+Mar sin, muna roghnaíonn tú comhad, is fearr féachaint an bhfuil comhad leis an ainm chéanna ann cheana féin.
+
+Le breathnú nó cuardach a dhéanamh ar íomhánna a uaslódáladh cheana féin, téigh go dtí an
+[[Speisialta:Imagelist|liosta íomhánna]] uaslódáilte. Déantar liosta de uaslódála agus scriosaidh ar an [[Vicipéid:Liosta_uaslódála|liosta uaslódála]].
+
+Bain úsáid as an bhfoirm thíos chun íomhá-chomhaid nua a uaslódáil. Is féidir leat na h-íomhánna a úsáid i do chuid alt.
+Ar an gcuid is mó de na líonléitheoirí, feicfidh tú cnaipe \"Brabhsáil...\" nó rud éigin mar sin.
+Lé brú ar an gcnaipe seo, gheobhaigh tú an ghnáthbhosca dialóige comhad-oscailte dod'chóras oibriúcháin.
+Nuair a roghnaíonn tú comhad, líonfar ainm an chomhaid sa téacsbhosca in aice leis an gcnaipe.
+Caithfidh tú dearfú le brú sa bhosca beag nach bhfuil tú ag sárú aon chóipcheart leis an suaslódáil seo.
+Brúigh an cnaipe \"Uaslódáil\" chun an uaslódáil a chríochnú. Mura bhfuil nasc Idirlín tapaidh agat,
+beidh roinnt ama uait leis seo.
+
+Is iad na formáidí inmholta ná [[JPEG]] do íomhánna grianghrafa, [[PNG]] do pictiúir tarraingte agus léaráidí,
+agus [[OGG]] d'huaimeanna. Ainmnigh do chuid comhad i mbealach a mbeidh sé éasca ciall a bhaint astu, chun dul
+amú a sheachaint. Chun an íomhá a úsáid san alt, úsáid nasc mar seo:
+
+'''[[{{ns:6}}:comhad.jpg]]'''
+nó '''[[{{ns:6}}:íomhá.png|téacs eile]]''',
+nó '''[[{{ns:-2}}:comhad.ogg]]''' d'fhuaimeanna.
+
+Mar is fíor maidir le leathanaigh Vicipéide, is féidir le daoine eile do chuid comhad
+
+uaslódáilte a athrú nó a
+scriosadh, má shíltear go bhfuil sé i gcabhair don ciclipéid. Má bhaineann tú mí-úsáid as an gcóras tá seans
+go gcoscfar ón gcóras tú.",
+
+"uploadlog"     => "Stair uaslódála",
+"uploadlogpage" => "Stair_uaslódála",
+"uploadlogpagetext" => "Is liosta é seo a leanas de na uaslódáil comhad is deanaí.
+Is am an freastalaí (UTC) iad na hamanna atá anseo thíos.
+<ul>
+</ul>
+",
+"filename"      => "Comhadainm",
+"filedesc"      => "Achoimriú",
+"filestatus" => "Stádas cóipchirt",
+"filesource" => "Foinse",
+"copyrightpage" => "{{ns:4}}:Cóipchearta",
+"copyrightpagename" => "Cóipcheart Vicipéide",
+"uploadedfiles" => "Comhaid uaslódáilte",
+"ignorewarning" => "Scaoil tharat an rabhadh agus sábháil an comhad ar aon chaoi.",
+"minlength"     => "Caithfidh trí litreacha ar a laghad bheith ann sa comhadainm.",
+'illegalfilename'       => 'Tá litreacha san comhadainm  "$1" nach ceadaítear in ainm leathanaigh. Athainmnigh
+an comhad agus déan athiarracht, más é do thoil é.',
+"badfilename"   => "D'athraíodh an comhadainm bheith \"$1\".",
+"badfiletype"   => "Níl \".$1\" ina formáid comhaid íomhá inmholta.",
+"largefile"     => "Moltar nach uaslódálaítear comhaid íomhá thar 100kb i méid.",
+'emptyfile'         => "De réir a chuma, ní aon rud san chomhad a d'uaslódáil tú ach comhad folamh. Is dócha gur
+míchruinneas é seo san ainm chomhaid. Seiceáil más é an comhad seo atá le huaslódáil agat.",
+"successfulupload" => "Uaslódáil rathúil",
+"fileuploaded"  => "Uaslódáladh an comhad \"$1\" go rathúil.
+Lean an nasc seo: ($2) chuig an leathanach cuir sios agus líon isteach
+eolas faoin comhad, mar shampla cá bhfuarthas é, cathain a
+chruthaíodh é agus rud eile ar bith tá 'fhios agat faoi. Más íomhá an comhad seo,
+is féidir leat é a hionsú mar sin: <tt>[[Íomhá:$1|mion|Cur síos]]</tt>",
+"uploadwarning" => "Rabhadh suaslódála",
+"savefile"      => "Sábháil comhad",
+"uploadedimage" => "D'uaslódáladh \"$1\"",
+'uploaddisabled' => 'Tá brón orainn, díchumasaítear an córas uaslódála faoi láthair.',
+'uploadcorrupt' => 'Tá an comhad truaillithe nó tá iarmhír comhadainm neamhbhailí aige. Scrúdaigh an comhad agus
+uaslódáil é arís, le do thoil.',
+'uploadvirus' => 'Tá víreas ann sa comhad seo! Eolas: $1',
+'sourcefilename' => 'Comhadainm foinse',
+'destfilename' => 'Comhadainm sprice',
+
+# Image list
+#
+"imagelist"     => "Liosta íomhánna",
+"imagelisttext" => "Is liosta é seo a leanas de $1 íomhánna, curtha in eagar le $2.",
+"getimagelist"  => "ag fáil an liosta íomhánna",
+"ilsubmit"      => "Cuardaigh",
+"showlast"      => "Taispeáin na $1 íomhánna seo caite, curtha in eagar le $2.",
+"byname"       => "de réir hainm",
+"bydate"       => "de réir dáta",
+"bysize"       => "de réir méid",
+"imgdelete"     => "scrios",
+"imgdesc"       => "curs",
+"imglegend"     => "Eochair: (curs) = taispeáin/athraigh an cur síos comhaid.",
+"imghistory"    => "Stair an chomhaid",
+"revertimg"     => "ath",
+"deleteimg"     => "scr",
+"deleteimgcompletely"     => "Scrios gach leasú don comhad seo",
+"imghistlegend" => "Eochair: (rth) = an leagan láithreach is ea seo, (scr) = scrios an
+seanleagan seo, (ath) = athúsáid an seanleagan seo.
+<br><i>Bruigh an dáta chun feach ar an íomhá mar a suaslódálaíodh é ar an dáta sin</i>.",
+"imagelinks"    => "Naisc íomhá",
+"linkstoimage"  => "Is iad na leathanaigh seo a leanas a nascaíonn chuig an íomhá seo:",
+"nolinkstoimage" => "Níl aon leathanach ann a nascaíonn chuig an íomhá seo.",
+'sharedupload' => 'Is uaslodáil roinnte atá ann sa comhad seo, agus is féidir le tionscadail eile é a úsáid.',
+'shareduploadwiki' => 'Féach ar an [leathanach cur síos don comhad $1] le tuilleadh eolais.',
+'shareddescriptionfollows' => '-',
+'noimage'       => 'Níl aon chomhad ann leis an ainm seo, ba féidir leat [$1 é a uaslódáil]',
+'uploadnewversion' => '[$1 Uaslódáil leagan nua den comhad seo]',
+
+# Statistics
+#
+"statistics"    => "Staidreamh",
+"sitestats"     => "Staidreamh do {{SITENAME}}",
+"userstats"     => "Staidreamh úsáideora",
+"sitestatstext" => "Is é '''$1''' líon na leathanach sa bunachar sonraí.
+Cuirtear leathanaigh \"phlé\", leathanaigh a bhaineann le Vicipéid í fhéin, ailt \"stumpaí\"
+íosmhéadacha, athsheolaidh, agus leathanaigh eile nach cáileann mar ailt i ndáiríre, san áireamh.
+Ag fágáil na leathanaigh seo as, tá '''$2''' leathanaigh ann atá ina nailt dlisteanacha, is dócha.
+
+In iomlán tá '''$3''' radhairc leathanaigh, agus ''''$4''' athruithe leathanaigh sa Vicipéid
+ó thus athchóiriú an vicí (25 Eanáir, 2004).
+Is é sin '''$5''' athruithe ar meán do gach leathanach, agus '''$6''' radhairc do gach athrú.",
+"userstatstext" => "Tá '''$1''' úsáideoirí cláraithe anseo.
+Tá '''$2''' de na úsáideoirí seo ina riarthóirí (féach ar $3).",
+
+# Maintenance Page
+#
+"maintenance"       => "Leathanach cothabhála",
+"maintnancepagetext"    => "Sa leathanach seo faightear uirlisí éagsúla don gnáthcothabháil. Is féidir le roinnt
+de na feidhmeanna seo an bunachar sonraí a cuir strus ar, mar sin ná athbhruigh athlódáil tar éis gach mír a
+chríochnaíonn tú ;-)",
+"maintenancebacklink"   => "Ar ais go dtí an Leathanach Cothabhála",
+"disambiguations"   => "Leathanaigh idirdhealaithe",
+"disambiguationspage"   => "Vicipéid:Naisc_go_leathanaigh_idirdhealaithe",
+"disambiguationstext"   => "Nascaíonn na ailt seo a leanas go <i>leathanach
+idirdhealaithe</i>. Ba chóir dóibh nasc a dhéanamh dón ábhar áirithe atá i gceist.<br>Tugtar
+an teideal \"idirdhealán\" ar leathanach má tá nasc ar $1 dó.<br><i>Ní</i> cuirtear ar
+an liosta seo naisc as na hainmspásanna eile.",
+"doubleredirects"   => "Athsheolaidh dúbailte",
+"doubleredirectstext"   => "<b>Tabhair faoi deara:</b> B'fheidir go bhfuil toraidh bréagacha ar an liosta seo.
+De ghnáth cíallaíonn sé sin go bhfuil téacs breise le naisc thíos sa chéad #REDIRECT no #ATHSHEOLADH.<br>\n Sa
+gach sraith tá náisc chuig an chéad is an dara athsheoladh, chomh maith le chéad líne an dara téacs athsheolaidh. De
+ghnáth tugann sé sin an sprioc-alt \"fíor\".",
+"brokenredirects"   => "Athsheolaidh Briste",
+"brokenredirectstext"   => "Is iad na athsheolaidh seo a leanas a nascaíonn go ailt nach bhfuil ann fós.",
+"selflinks"     => "Leathanaigh le féin-naisc",
+"selflinkstext"     => "Sna leathanaigh seo a leanas tá naisc a nascaíonn chuig an leathanach céanna é fhéin. Tá an méid seo flúirseach.",
+"mispeelings"     => "Leathanaigh mílitrithe",
+"mispeelingstext"             => "Sna leathanaigh seo a leanas tá mílitriú coiteanta, atá san liosta ar $1. Is
+dócha go taispeántar an litriú ceart (mar sin).",
+"mispeelingspage"       => "Liosta mhílitriuithe coitianta",
+"missinglanguagelinks"  => "Naisc Teangacha Ar Iarraidh",
+"missinglanguagelinksbutton"    => "Cuardaigh ar naisc teangacha ar iarraidh do",
+"missinglanguagelinkstext"      => "<i>Ní</i> nascaíonn na hailt seo chuig a macasamhail sa $1. <i>Ní</i>
+taispeántar athsheolaidh nó fo-leathanaigh.",
+
+
+# Miscellaneous special pages
+#
+"orphans"       => "Leathanaigh dhílleachtacha",
+'geo'     => 'Comhardanáidí GEO',
+'validate'      => 'Cuir an leathanach i bhailí',
+"lonelypages"   => "Leathanaigh dhílleachtacha",
+'uncategorizedpages'    => 'Leathanaigh gan catagóir',
+'unusedcategories' => 'Catagóirí nach úsáidtear',
+"unusedimages"  => "Íomhánna nach úsáidtear",
+"popularpages"  => "Leathanaigh coitianta",
+"nviews"       => "$1 radhairc",
+"wantedpages"   => "Leathanaigh de dhíth",
+"nlinks"       => "$1 naisc",
+"allpages"      => "Na leathanaigh go léir",
+'nextpage'           => 'An lch a leanas ($1)',
+"randompage"    => "Leathanach fánach",
+'randompage-url'=> 'Speisialta:Random',
+"shortpages"    => "Leathanaigh gearra",
+"longpages"     => "Leathanaigh fada",
+'deadendpages'  => 'Leathanaigh caocha',
+"listusers"     => "Liosta úsáideoirí",
+"specialpages"  => "Leathanaigh speisialta",
+"spheading"     => "Leathanaigh speisialta do gach úsáideoir",
+
+"protectpage"   => "Glasáil leathanach",
+"recentchangeslinked" => "Athruithe gaolmhara",
+"rclsub"       => "(go leathanaigh nasctha ó \"$1\")",
+"debug"         => "Bain fabhtanna",
+"newpages"      => "Leathanaigh nua",
+"ancientpages"      => "Na leathanaigh is sine",
+"intl"      => "Naisc idirtheangacha",
+'move' => 'Athainmnigh',
+"movethispage"  => "Athainmnigh an leathanach seo",
+"unusedimagestext" => "<p>Tabhair faoi deara gur féidir le shuímh
+eile naisc a dhéanamh leis an íomha le URL díreach,
+agus mar sin bheadh siad ar an liosta seo fós cé go bhfuil siad
+in úsáid faoi láthair.",
+'unusedcategoriestext' => 'Tá na leathanaigh catagóire seo a leanas ann, cé nach úsáidtear
+iad in aon alt eile nó in aon chatagóir eile.',
+"booksources"   => "Leabharfhoinsí",
+'categoriespagetext' => 'Tá na catagóir seo a leanas ann sa vicí.',
+'data'  => 'Sonraí',
+"booksourcetext" => "Liosta is ea seo thíos de suímh eile a
+dhíolann leabhair nua agus athdhíolta, agus tá seans ann go bhfuil eolas
+breise acu maidir leis na leabhair a bhfuil tú ag iarradh ar.
+Níl aon baint ag {{SITENAME}} le gnó ar bith anseo, agus ní
+aontú leo é an liosta seo.",
+'isbn'  => 'ISBN',
+'rfcurl' =>  "http://www.ietf.org/rfc/rfc$1.txt",
+"alphaindexline" => "$1 go $2",
+'version'             => 'Leagan',
+'log'     => 'Logaí',
+'alllogstext'   => 'Taispeántas comhcheangaltha de logaí a bhaineann le huaslódáil, scriosadh, glasáil, coisc,
+agus oibreoirí córais. Is féidir leat an taispeántas a ghéarú - roghnaigh an saghas loga, an ainm úsáideora, nó an
+leathanach atá i gceist agat.',
+
+# Special:Allpages
+'nextpage'       => 'An leathanach a leanas ($1)',
+'allarticles'       => 'Gach alt',
+'allpagesprev'      => 'Roimhe',
+'allpagesnext'      => 'Ar aghaidh',
+'allpagessubmit'    => 'Dul',
+
+# Email this user
+#
+"mailnologin"   => "Níl aon seoladh maith ann",
+"mailnologintext" => "Ní mór duit bheith  <a href=\"{{localurl:Special:Userlogin\">logáilte isteach</a>
+agus bheith le seoladh ríomhphoist bhailí i do chuid <a href=\"{{localurl:Special:Preferences}}\">sainroghanna</a>
+más mian leat ríomhphost a sheoladh chuig úsáideoirí eile.",
+"emailuser"     => "Cuir ríomhphost chuig an úsáideoir seo",
+"emailpage"     => "Seol ríomhphost",
+"emailpagetext" => "Má d'iontráil an úsáideoir seo seoladh ríomhphoist bhailí
+ina chuid sainroghanna úsáideora, cuirfidh an foirm anseo thíos teachtaireacht amháin do.
+Beidh do seoladh ríomhphoist a d'iontráil tú i do chuid sainroghanna úsáideora
+sa bhosca \"Seoltóir\" an riomhphoist, agus mar sin ba féidir léis an faighteoir ríomhphost eile a chur leatsa.",
+'usermailererror' => 'Earráid leis an píosa ríomhphoist: ',
+'defemailsubject'  => "Ríomhphost Vicipéide",
+"noemailtitle"  => "Níl aon seoladh ríomhphoist ann",
+"noemailtext"   => "Níor thug an úsáideoir seo seoladh ríomhphoist bhailí, nó shocraigh sé nach
+mian leis ríomhphost a fháil ón úsáideoirí eile.",
+"emailfrom"     => "Seoltóir",
+"emailto"       => "Chuig",
+"emailsubject"  => "Ábhar",
+"emailmessage"  => "Teachtaireacht",
+"emailsend"     => "Seol",
+"emailsent"     => "Ríomhphost seolta",
+"emailsenttext" => "Seoladh do theachtaireacht ríomhphoist go ráthúil.",
+
+# Watchlist
+#
+"watchlist"     => "Mo liosta faire",
+"watchlistsub"  => "(don úsáideoir \"$1\")",
+"nowatchlist"   => "Níl aon rud i do liosta faire.",
+"watchnologin"  => "Níl tú logáilte isteach",
+"watchnologintext"  => "Ní mór duit <a href=\"" .
+  "{{localurle:Speisialta:Userlogin}}\">logáil isteach</a>
+chun do liosta faire a athrú.",
+"addedwatch"    => "Curtha san liosta faire",
+"addedwatchtext" => "Cuireadh an leathanach \"$1\" le do <a href=\"" .
+  "{{localurle:Speisialta:Watchlist}}\">liosta faire</a>.
+Cuirfear athruithe amach anseo, don leathanach sin agus don leathanach phlé, ar an liosta ann,
+agus beidh <b>cló trom</b> ar a theideal san <a href=\"" .
+  "{{localurle:Speisialta:Recentchanges}}\">liosta de na hathruithe is déanaí</a> sa chaoi go bhfeicfeá iad go héasca.</p>
+<p>Más mian leat an leathanach a bain amach do liosta faire níos déanaí, brúigh ar \"Stop ag faire\" ar an taobhbharra.",
+"removedwatch"  => "Bainthe amach ón liosta faire",
+"removedwatchtext" => "Baineadh an leathanach \"$1\" amach ó do liosta faire.",
+'watch' => 'Fair',
+"watchthispage" => "Fair ar an leathanach seo",
+'unwatch' => 'Stop ag faire',
+"unwatchthispage" => "Stop ag faire",
+"notanarticle"  => "Níl alt ann",
+"watchnochange" => "Níor athraíodh ceann ar bith de na leathanaigh atá ar do liosta faire,
+taobh istigh den tréimhse atá roghnaithe agat.",
+"watchdetails" => "Tá tú ag faire ar $1 leathanaigh, gan leathanaigh phlé a chur san áireamh.",
+"watchmethod-recent" => "ag seiceáil na athruithe deireanacha ar do chuid leathanaigh faire",
+"watchmethod-list" => "ag seiceáil na leathanaigh faire ar do chuid athruithe deireanacha",
+"removechecked" => "Bain míreanna marcálaithe as do liosta faire",
+"watchlistcontains" => "Tá $1 leathanaigh i do liosta faire.",
+"watcheditlist" => "Is é seo liosta de na leathanaigh i do liosta faire, in ord aibitre.
+Marcáil boscaí de na leathanaigh atá le baint amach an liosta faire, agus bruigh
+an cnaipe 'bain amach le marcanna' ag bun an leathanaigh.",
+"removingchecked" => "Ag baint amach na míreanna ón liosta faire, mar a iarraidh...",
+"couldntremove" => "Níor baineadh amach an mír '$1'...",
+"iteminvalidname" => "Fadhb leis an mír '$1', ainm neamhbhailí...",
+"wlnote" => "Is iad seo na $1 athruithe deireanacha sna <b>$2</b> uaire deireanacha.",
+"wlshowlast" => "Taispeáin an $1 uair $2 lá seo caite$3", #FIXME
+'wlsaved'       => 'Leagan sábháilte is ea seo de do liosta faire.',
+'wlhideshowown'   => '$1 mo chuid athruithe.',
+'wlshow'               => 'Taispeáin',
+'wlhide'               => 'Folaigh',
+
+'updatedmarker'         => '<span class=\'updatedmarker\'> leasaithe (ó shin mo chuairt dheireanach) </span>',
+
+'enotif_mailer'                => 'Fógrasheoltóir as {{SITENAME}}',
+'enotif_reset'                 => 'Marcáil gach leathanach bheith tadhlaithe',
+'enotif_newpagetext'=> 'Is leathanach nua é seo.',
+'changed'                      => 'D\'athraigh',
+'created'                      => 'Cruthaigh',
+'enotif_subject'       => '  $CHANGEDORCREATED $PAGEEDITOR an leathanach $PAGETITLE ag {{SITENAME}}.',
+'enotif_lastvisited' => 'Féach ar $1 le haghaidh gach athrú a rinneadh ó thús na cuairte seo caite a rinne tú.',
+'enotif_body' => 'A $WATCHINGUSERNAME, a chara,
+
+$CHANGEDORCREATED $PAGEEDITOR an leathanach $PAGETITLE  ag {{SITENAME}} ar $PAGEEDITDATE, féach ar $PAGETITLE_URL chun an leagan reatha a fháil.
+
+$NEWPAGE
+
+Athchoimriú an úsáideora a rinne é: $PAGESUMMARY $PAGEMINOREDIT
+
+Déan teagmháil leis an úsáideoir:
+r-phost: $PAGEEDITOR_EMAIL
+vicí: $PAGEEDITOR_WIKI
+
+I gcás athruithe eile, ní bheidh aon fhógra eile muna dtéann tú go dtí an leathanach seo. Ba féidir leat na bratacha fógraithe a athrú do gach leathanach ar do liosta faire.
+
+            Is mise le meas,
+            An fógrachóras uathoibríoch ag {{SITENAME}}
+
+--
+Chun do chuid socruithe a athrú maidir leis an liosta faire, teir go dtí
+{{SERVER}}{{localurl:Speisialta:Watchlist/edit}}
+
+Aiseolas agus a thuilleadh cabhrach:
+{{SERVER}}{{localurl:Help:Contents}}',
+
+# Delete/protect/revert
+#
+"deletepage"    => "Scrios an leathanach",
+"confirm"       => "Cinntigh",
+"excontent" => "is é seo a raibh an ábhar:",
+"exbeforeblank" => "is é seo a raibh an ábhar roimh an folmhadh:",
+"exblank" => "bhí an leathanach folamh",
+"confirmdelete" => "Cinntigh an scriosadh",
+"deletesub"     => "(Ag scriosadh \"$1\")",
+"historywarning" => "Aire: Ta stair ag an leathanach a bhfuil tú ar tí é a scriosadh: ",
+"confirmdeletetext" => "Tá tú ar tí leathanach nó íomhá a scrios,
+chomh maith leis a chuid stair, ón bunachar sonraí.
+Cinntigh go mian leis an méid seo a dhéanamh, go dtuigeann tú na
+iarmhairtaí, agus go ndéanann tú é dar le [[Vicipéid:Polasaí]].",
+"actioncomplete" => "Gníomh críochnaithe",
+"deletedtext"   => "scriosadh \"$1\".
+Féach ar $2 chun cuntas na scriosiadh deireanacha a fháil.",
+"deletedarticle" => "scriosadh \"$1\"",
+"dellogpage"    => "Cuntas_scriosaidh",
+"dellogpagetext" => "Seo é liosta de na scriosaidh is deireanacha.
+Is in am an freastalaí (UTC) iad na hamanna anseo thíos.
+<ul>
+</ul>
+",
+"deletionlog"   => "cuntas scriosaidh",
+"reverted"      => "Tá eagrán níos luaithe in úsáid anois",
+"deletecomment" => "Cúis don scriosadh",
+"imagereverted" => "D'éirigh le athúsáid eagráin níos luaithe.",
+"rollback"      => "Athúsáid seanathruithe",
+"rollbacklink"  => "athúsáid",
+"rollbackfailed" => "Theip an athúsáid",
+"cantrollback"  => "Ní féidir an athrú a athúsáid; ba é údar an ailt an t-aon duine a rinne athrú dó.",
+"alreadyrolled" => "Ní féidir eagrán níos luaí an leathanaigh [[$1]]
+le [[Úsáideoir:$2|$2]] ([[Plé úsáideora:$2|Plé]]) a athúsáid; d'athraigh duine eile é cheana fein, nó
+d'athúsáid duine eile eagrán níos luaí cheana féin.
+
+[[Úsáideoir:$3|$3]] ([[Plé úsáideora:$3|Plé]]) an té a rinne an athrú is déanaí. ",
+#   only shown if there is an edit comment
+"editcomment" => "Seo a raibh an mínithe athraithe: \"<i>$1</i>\".",
+"revertpage"    => "D'athúsáideadh an athrú seo caite le $1",
+"protectlogpage" => "Cuntas_cosanta",
+"protectlogtext" => "Seo é liosta de glais a cuireadh ar / baineadh de leathanaigh.
+Féach ar [[{{ns:4}}:Leathanach glasáilte]] chun a thuilleadh eolais a fháil.",
+'protectedarticle' => 'glasáladh "[[$1]]"',
+'unprotectedarticle' => 'díghlasáladh "[[$1]]"',
+'protectsub' =>'(Ag glasáil "$1")',
+'confirmprotecttext' => 'Ar mhaith leat go fírinneach an leathanach seo a ghlasáil?',
+'confirmprotect' => 'Cinntigh an glasáil',
+'protectcomment' => 'Cúis don glasáil',
+'unprotectsub' =>"(Ag díghlasáil \"$1\")",
+'confirmunprotecttext' => 'Ar mhaith leat go fírinneach an leathanach seo a díghlasáil?',
+'confirmunprotect' => 'Cinntigh baint an glais',
+'unprotectcomment' => 'Cúis do baint an glais',
+
+# Undelete
+"undelete" => "Díscrios leathanach scriosta",
+"undeletepage" => "Féach ar leathanaigh scriosta agus díscrios iad",
+"undeletepagetext" => "Scriosaíodh na leathanaigh seo a leanas cheana féin, ach
+tá síad sa cartlann fós agus is féidir iad a dhíscrios.
+Ó am go ham, is féidir an cartlann a fholmhú.",
+"undeletearticle" => "Díscrios alt scriosta",
+"undeleterevisions" => "Cuireadh $1 leagain sa chartlann",
+"undeletehistory" => "Dá díscriosfá an leathanach, díscriosfar gach leasú i stair an leathanaigh.
+Dá gcruthaíodh leathanach nua leis an teideal céanna ó shin an scriosadh, taispeáinfear
+na sean-athruithe san stair roimhe seo, agus ní athshuífear leagan láithreach an
+
+leathanaigh go huathoibríoch.",
+"undeleterevision" => "Leagan scriosta den dáta $1",
+"undeletebtn" => "Díscrios!",
+"undeletedarticle" => "Díscriosadh \"$1\" ar ais",
+"undeletedtext"   => "Díscriosadh an alt [[$1]] go rathúil.
+Féach ar [[{{ns:4}}:Cuntas_scriosaidh]] chun cuntas de scriosaidh agus athchóirithe deireanacha a fháil.",
+
+
+# Namespace form on various pages
+'namespace' => 'Ainmspás:',
+'invert' => 'Cuir an roghnú bun os cionn',
+
+# Contributions
+#
+"contributions" => "Dréachtaí úsáideora",
+"mycontris" => "Mo chuid dréachtaí",
+"contribsub"    => "Do $1",
+"nocontribs"    => "Níor bhfuarthas aon athrú a raibh cosúil le na crítéir seo.",
+"ucnote"       => "Is iad seo thíos na <b>$1</b> athruithe is déanaí a rinne an
+
+úsáideoir sna <b>$2</b> lae
+
+seo caite.",
+"uclinks"       => "Féach ar na $1 athruithe is déanaí; féach ar na $2 lae seo caite.",
+"uctop"     => " (barr)" ,
+'newbies'       => 'núíosaigh',
+'contribs-showhideminor' => '$1 mionathruithe',
+
+# What links here
+#
+"whatlinkshere" => "Naisc don leathanch seo",
+"notargettitle" => "Níl aon cuspóir ann",
+"notargettext"  => "Níor thug tú leathanach nó úsáideoir sprice
+chun an gníomh seo a dhéanamh ar.",
+"linklistsub"   => "(Liosta nasc)",
+"linkshere"     => "Nascaíonn na leathanaigh seo a leanas chuig an leathanach seo:",
+"nolinkshere"   => "Ní nascaíonn aon leathanach chuig an leathanach seo.",
+"isredirect"    => "Leathanach athsheolaidh",
+
+# Block/unblock IP
+#
+"blockip"       => "Coisc úsáideoir",
+"blockiptext"   => "Úsáid an foirm anseo thíos chun bealach scríofa a chosc ó
+seoladh IP nó ainm úsáideora áirithe.
+Is féidir leat an rud seo a dhéanamh amháin chun an chreachadóireacht a chosc, de réir
+mar a deirtear sa [[Vicipéid:Polasaí|polasaí Vicipéide]].
+Líonaigh cúis áirithe anseo thíos (mar shampla, is féidir leat a luaigh
+leathanaigh áirithe a rinne an duine damáiste ar).",
+"ipaddress"     => "Seoladh IP / ainm úsáideora",
+'ipbexpiry'         => 'Am éaga',
+"ipbreason"     => "Cúis",
+"ipbsubmit"     => "Coisc an úsáideoir seo",
+'ipbother'           => 'Méid eile ama',
+#'ipboptions'      => '2 uair:2 uair,1 lá amháin:1 lá amháin,3 lá:3 lá,1 sheachtain amháin:1 sheachtain amháin,2 sheachtain:2 sheachtain,1 mhí amháin:1 mhí amháin,3 mhí:3 mhí,6 mhí:6 mhí,1 bhliain amháin:1 bhliain amháin,gan teorainn:gan teorainn',
+'ipbotheroption'       => 'eile',
+"badipaddress"  => "Níl aon úsáideoir ann leis an ainm seo.",
+"blockipsuccesssub" => "D'éirigh leis an cosc",
+"blockipsuccesstext" => "Choisceadh [[{{ns:Special}}:Contributions/$1|$1]].
+<br/>Féach ar an g[[{{ns:Special}}:Ipblocklist|liosta coisc IP]] chun coisc a athbhreithniú.",
+"unblockip"     => "Díchoisc úsáideoir",
+"unblockiptext" => "Úsáid an foirm anseo thíos chun bealach scríofa a thabhairt ar ais do seoladh
+IP nó ainm úsáideora a raibh faoi chosc roimhe seo.",
+"ipusubmit"     => "Díchoisc an seoladh seo",
+"ipusuccess"    => "Díchoisceadh \"$1\"",
+"ipblocklist"   => "Liosta seoltaí IP agus ainmneacha úsáideoirí coiscthe",
+"blocklistline" => "$1, $2 a choisc $3 ($4)",
+'infiniteblock' => 'am éaga infinite', //fixme
+'expiringblock' => 'am éaga  $1',
+"blocklink"     => "Cosc",
+"unblocklink"   => "bain an cosc",
+"contribslink"  => "dréachtaí",
+"autoblocker"   => "Coisceadh go huathoibríoch thú dá bharr gur úsáideadh do sheoladh IP ag an úsáideoir \"[[Úsáideoir:$1|$1]]\". Is é seo an cúis don cosc ar $1: \"$2\".",
+"blocklogpage"  => "Cuntas_coisc",
+"blocklogentry" => 'coisceadh "$1"; is é $2 an am éaga',
+"blocklogtext"  => "Seo é cuntas de gníomhartha coisc úsáideoirí agus míchoisc úsáideoirí. Ní cuirtear
+seoltaí IP a raibh coiscthe go huathoibríoch ar an liosta seo. Féach ar an
+[[Speisialta:Ipblocklist|Liosta coisc IP]] chun
+liosta a fháil de coisc atá i bhfeidhm faoi láthair.",
+"unblocklogentry"   => 'díchoisceadh $1',
+'range_block_disabled'  => 'Faoi láthair, míchumasaítear an cumas riarthóra chun réimsechoisc a dhéanamh.',
+'ipb_expiry_invalid'    => 'Am éaga neamhbhailí.',
+'ip_range_invalid'      => "Réimse IP neamhbhailí.\n",
+'proxyblocker'  => 'Cosc ar seachfhreastalaithe',
+'proxyblockreason'      => "Coisceadh do sheoladh IP dá bharr gur seachfhreastalaí
+neamhshlándála is ea é. Déan teagmháil le do chomhlacht idirlín nó le do lucht cabhrach teicneolaíochta
+go mbeidh 'fhios acu faoin fadhb slándála tábhachtach seo.",
+'proxyblocksuccess'     => "Rinneadh.\n",
+'sorbs'         => 'DNSBL SORBS',
+'sorbsreason'   => 'Liostalaítear do sheoladh IP mar sheachfhreastalaí oscailte sa DNSBL [http://www.sorbs.net SORBS].',
+
+# Developer tools
+#
+"lockdb"       => "Glasáil an bunachar sonraí",
+"unlockdb"      => "Díghlasáil bunachar sonraí",
+"lockdbtext"    => "Dá nglasálfá an bunachar sonraí, ní beidh cead ar aon úsáideoir
+leathanaigh a chur in eagar, a socruithe a athrú, a liostaí faire a athrú, nó rudaí eile a thrachtann le
+athruithe san bunachar sonraí.
+Cinntigh go bhfuil an scéal seo d'intinn agat, is go díghlasálfaidh tú an bunachar sonraí nuair a bhfuil
+do chuid cothabháile críochnaithe.",
+"unlockdbtext"  => "Dá díghlasálfá an bunachar sonraí, beidh ceat ag gach úsáideoirí aris
+na leathanaigh a chur in eagar, a sainroghanna a athrú, a liostaí faire a athrú, agus rudaí eile
+a dhéanamh a thrachtann le athruithe san bunachar sonraí.
+Cinntigh go bhfuil an scéal seo d'intinn agat.",
+"lockconfirm"   => "Sea, is mian liom an bunachar sonraí a ghlasáil.",
+"unlockconfirm" => "Sea, is mian liom an bunachar sonraí a dhíghlasáil.",
+"lockbtn"       => "Glasáil an bunachar sonraí",
+"unlockbtn"     => "Díghlasáil an bunachar sonraí",
+"locknoconfirm" => "Níor mharcáil tú an bosca daingnithe.",
+"lockdbsuccesssub" => "D'éirigh le glasáil an bhunachair sonraí",
+"unlockdbsuccesssub" => "D'éirigh le díghlasáil an bhunachair sonraí",
+"lockdbsuccesstext" => "Glasáladh an bunachar sonraí Vicipéide.
+<br />Cuimhnigh nach mór duit é a dhíghlasáil tar éis do chuid cothabháil.",
+"unlockdbsuccesstext" => "Díghlasáladh an bunachar sonraí Vicipéide.",
+
+# Make sysop
+'makesysoptitle'       => 'Déan oibreoir córais de húsáideoir',
+'makesysoptext'         => 'Úsáideann maorlathaigh an fhoirm seo chun riarthóirí a dhéanamh de ghnáthúsáideoirí.
+Iontráil ainm an úsáideora sa bosca seo agus brúigh an cnaipe chun riarthóir a dhéanamh den úsáideoir',
+'makesysopname'         => 'Ainm an úsáideora:',
+'makesysopsubmit'       => 'Déan oibreoir córais den úsáideoir seo',
+'makesysopok'     => "Is oibreoir córais atá in <b>Úsáideoir \"$1\" anois.</b>",
+'makesysopfail'         => "<b>Níor rinneadh oibreoir córais den Úsáideoir \"$1\". (Ar iontráil tú an ainm go ceart?)</b>",
+'setbureaucratflag' => 'Athraigh an brat maotharlach',
+'bureaucratlog'         => 'Liosta_maotharlach',
+'bureaucratlogentry'    => "Tá na cearta don úsáideoir \"$1\" athraithe bheith \"$2\"",
+'rights'                       => 'Cearta:',
+'set_user_rights'       => 'Athraigh na cearta úsáideora',
+'user_rights_set'       => "<b>Leasaíodh na cearta úsáideora do \"$1\"</b>",
+'set_rights_fail'       => "<b>Níorbh fhéidir na cearta úsáideora do \"$1\" a athrú. (Ar iontráil tú an ainm go ceart?)</b>",
+'makesysop'     => 'Déan oibreoir córais de húsáideoir',
+'already_sysop'     => 'Is oibreoir córais é an usáideoir seo cheana féin',
+'already_bureaucrat' => 'Is maorlathach é an úsáideoir seo cheana féin',
+'already_steward'   => 'Is maor é an úsáideoir seo cheana féin',
+
+# Validation
+'val_yes' => 'Is ea',
+'val_no' => 'Ní hea',
+'val_of' => '$1 as $2',
+'val_revision' => 'Leasú',
+'val_time' => 'Am',
+'val_user_stats_title' => 'Forbhreathnú bailíochtaithe an úsáideora $1',
+'val_my_stats_title' => 'M\'fhorbhreathnú bailíochtaithe',
+'val_list_header' => '<th>#</th><th>Ábhar</th><th>Réimse</th><th>Gníomh</th>',
+'val_add' => 'Cuir leis',
+'val_del' => 'Scrios',
+'val_show_my_ratings' => 'Taispeáin mo chuid bailíochtuithe',
+'val_revision_number' => 'Leasú #$1',
+'val_warning' => '<b>Ná hathraigh rud ar bith anseo <i>go deo</i> muna bhfuil comhaontú
+
+<i>dearfa</i> ann cheana féin ón comhphobal!</b>',
+'val_rev_for' => 'Leasuithe do $1',
+'val_details_th_user' => 'Úsáideoir $1',
+'val_validation_of' => 'Bailíochtú do "$1"',
+'val_revision_of' => 'Leasú ar $1',
+'val_revision_changes_ok' => 'Stóráladh do chuid meastachán!',
+'val_rev_stats' => 'Féach ar an staidreamh bailíochtaithe do "$1" <a href="$2">anseoe</a>',
+'val_revision_stats_link' => 'sonraí',
+'val_iamsure' => 'Gliogáil an ticbhosca seo más mian leat é a dhéanamh go fírinneach!',
+'val_details_th' => '<sub>Úsáideoir</sub> \\ <sup>Ábhar</sup>',
+
+'val_clear_old' => 'Glan mo chuid sonraí bailíochtaithe níos sine do $1',
+'val_merge_old' => 'Úsáid mo measúnacht roimhe seo nuair atá roghnaithe \'Gan tuairim\'',
+'val_form_note' => '<b>Leid:</b> Má chumaiscítear do chuid sonraí, athreofar
+gach sainrogha ina chuir tú <i>gan tuairim</i> don leagan ailt a roghnaíonn
+tú bheith an luach is an trácht atá ag an t-athrú is déanach ina thóg tú
+tuairim. Mar shampla, más maith leat rogha amháin do athrú níos nuaí a
+hathrú, ach ba mhaith leat do roghanna eile don alt a chosaint, ná roghnaigh
+rud ar bith ach amháin an rogha ba mhaith leat a <i>athrú</i>, agus le
+cumaisc líonfar na roghanna eile de réir na roghanna a raibh agat roimhe ré.',
+'val_noop' => 'Gan tuairim',
+'val_topic_desc_page' => 'Tionscadal:Téamaí bailíochtaithe',
+'val_votepage_intro' => 'Athraigh an téacs seo <a href="{{SERVER}}{{localurl:MediaWiki:Val_votepage_intro}}">anseo</a>!',
+'val_percent' => '<b>$1%</b><br>($2 de $3 pointí<br>a rinne $4 úsáideoirí)',
+'val_percent_single' => '<b>$1%</b><br>($2 de $3 pointí<br>a rinne aon úsáideoir)',
+'val_total' => 'Iomlán',
+'val_version' => 'Leagan',
+'val_tab' => 'Bailíochtaigh',
+'val_this_is_current_version' => 'is é seo an t-eagrán is déanaí',
+'val_version_of' => "Leagan ó $1" ,
+'val_table_header' => "<tr><th>Rang</th>$1<th
+
+colspan=4>Tuairim</th>$1<th>Trácht</th></tr>\n",
+'val_stat_link_text' => 'Staitistic bhailíochta don alt seo',
+'val_view_version' => 'Féach ar an leagan seo',
+'val_validate_version' => 'Bailíochtaigh an leagan seo',
+'val_user_validations' => 'Bhailíochtaigh an úsáideoir seo $1 leathanaigh.',
+'val_no_anon_validation' => 'Caithfidh tú bheith logáilte isteach chun alt a bhailíochtú.',
+'val_validate_article_namespace_only' => 'Ní féidir leathanaigh a bhailíochtú ach amháin ailt. <i>Níl</i> an leathanach seo in ainmspás na n-alt.',
+'val_validated' => 'Tá an bhailíocht críochnaithe.',
+'val_article_lists' => 'Líosta ailt atá déanta bailí',
+'val_page_validation_statistics' => 'Staitisticí bhailíochta ailt do $1',
+
+# Move page
+#
+"movepage"      => "Athainmnigh an leathanach",
+"movepagetext"  => "Úsáid an foirm seo thíos chun leathanach a hathainmniú. Aistreofar a chuid
+stair go léir chuig an teideal nua.
+Déanfar leathanach athsheolaidh den sean-theideal chuig an teideal nua.
+Ní athreofar naisc chuig sean-teidil an leathanaigh. Bí cinnte go ndéanfá
+[[Speisialta:Maintenance|cuardach]] ar athsheolaidh dubáilte nó briste.
+Tá tú freagrach i cinnteach go leanann naisc chuig an pointe a bhfuil siad ag aimsiú ar.
+
+Tabhair faoi deara '''nach''' n-athainmneofar an leathanach má tá leathanach
+ann cheana féin faoin teideal nua, mura bhfuil sé folamh nó athsheoladh nó mura bhfuil aon
+stair athraithe aige cheana. Ciallaíonn sé sin go féidir leat leathanach a athainmniú ar ais
+chuig an áit ina raibh sé roimhe má dhéanfá botún, agus ní féidir leat leathanach atá ann a fhorscriobh ar.
+
+<b>AIRE!</b>
+Is athrú tábhachtach é athainmniú má tá leathanach coitianta i gceist;
+cinntigh go dtuigeann tú na iarmhairtí go léir roimh a leanfá.",
+"movepagetalktext" => "Aistreofar an leathanach phlé leis, má tá sin ann:
+*'''muna''' bhfuil tú ag aistriú an leathanach trasna ainmspásanna,
+*'''muna''' bhfuil leathanach phlé neamhfholamh ann leis an teideal nua, nó
+*'''muna''' bhaineann tú an marc den bosca anseo thíos.
+
+Sna scéil sin, caithfidh tú an leathanach a aistrigh nó a báigh leis na lámha má tá sin an rud atá uait.",
+"movearticle"   => "Athainmnigh an leathanach",
+"movenologin"   => "Níl tú logáilte isteach",
+"movenologintext" => "Ní mór duit bheith i d'úsáideoir cláraithe agus <a href=\"" .
+  "{{localurle:Speisialta:Userlogin}}\">logáilte isteach</a>
+chun leathanach a hathainmniú.",
+"newtitle"      => "Go teideal nua",
+"movepagebtn"   => "Athainmnigh an leathanach",
+"pagemovedsub"  => "D'éirigh leis an athainmniú",
+"pagemovedtext" => "D'athainmníodh an leathanach \"[[$1]]\" chuig \"[[$2]]\".",
+"articleexists" => "Tá leathanach leis an teideal seo ann fós, nó níl an
+teideal a rinne tú rogha air ina theideal bailí.
+Toghaigh teideal eile le do thoil.",
+"talkexists"    => "D'athainmníodh an leathanach é féin go rathúil, ach ní raibh sé ar a chumas an
+leathanach phlé a hathainmniú dá bharr go bhfuil ceann ann cheana féin ag an teideal nua.
+Báigh tusa féin iad, le do thoil.",
+"movedto"       => "athainmnithe go",
+"movetalk"      => "Athainmnigh an leathanach \"phlé\" freisin, má bhfuil an leathanach sin ann.",
+"talkpagemoved" => "D'athainmníodh an leathanach phlé frithiontráil.",
+"talkpagenotmoved" => "<strong>Níor</strong> athainmníodh an leathanach phlé frithiontráil.",
+'1movedto2'         => "D'athainmníodh $1 bheith $2",
+'1movedto2_redir' => "D'athainmníodh $1 bheith $2 thar athsheoladh",
+'movelogpage' => 'Athainmnigh loga',
+'movelogpagetext' => 'Liosta is ea seo thíos de leathanaigh athainmnithe.',
+'movereason'   => 'Cúis',
+'revertmove'   => 'athúsáid',
+'delete_and_move' => 'Scrios agus athainmnigh',
+'delete_and_move_text' =>
+'==Tá scrios riachtanach==
+
+Tá an t-alt "[[$1]]" ann cheana féin, a bhíodh ceaptha mar ainm nua don athainmniú. Ar
+mhaith leat é a scrios chun áit a dhéanamh don athainmniú?',
+'delete_and_move_reason' => 'Scriosta chun áit a dhéanamh d\'athainmniú',
+'selfmove' => "Tá an ainm céanna ag an bhfoinse mar atá ar an ainm sprice; ní féidir leathanach a athainmniú bheith é féin.",
+'immobile_namespace' => "Saghas speisialta leathanach atá ann san ainm sprice; ní féidir leathanaigh a athainmniú san ainmspás sin.",
+
+#Export
+
+"export"       => "Easportáil leathanaigh",
+"exporttext"    => "Is féidir leat an téacs agus stair athraithe de leathanach áirithe a heasportáil,
+fillte i bpíosa XML; is féidir leat ansin é a iompórtáil isteach vicí eile atá le na bogearraí MediaWiki
+air, nó is féidir leat é a coinniú do do chuid shiamsa féin.",
+"exportcuronly" => "Ná cuir san áireamh ach an leagan láithreach; ná cuir an stair iomlán ann",
+
+# Namespace 8 related
+
+"allmessages"   => "Teachtaireachtaí córais",
+"allmessagestext"   => "Liosta is ea seo de theachtaireachtaí córais atá le fáil san ainmspás MediaWiki: .",
+'allmessagesnotsupportedUI' => 'Níl tacaíocht ag Speisialta:AllMessages maidir le do theanga
+comhéadáin phearsanta don suíomh seo.',
+'allmessagesnotsupportedDB' => 'Níl aon tacaíocht anseo do Speisialta:AllMessages dá bharr
+go bhfuil wgUseDatabaseMessages druidte.',
+
+# Thumbnails
+
+'thumbnail-more'       => 'Méadaigh',
+'missingimage'   => "<b>Íomhá ar iarraidh</b><br /><i>$1</i>\n",
+'filemissing'          => 'Comhad ar iarraidh',
+
+# Special:Import
+'import'       => 'Iompórtáil leathanaigh',
+'importinterwiki' => 'Iompórtáil trasna vicíonna',
+'importtext'    => 'Easportáil an comhad ón bhfoinse-vicí le do thoil (le húsáid na tréithe
+Speisialta:Export), sábháil ar do dhíosca é agus uaslódáil anseo é.',
+'importfailed'  => "Theip ar an iompórtáil: $1",
+'importnotext'  => 'Folamh nó gan téacs',
+'importsuccess' => "D'eirigh leis an iompórtáil!",
+'importhistoryconflict' => 'Tá stair athraithe contrártha ann cheana féin (is dócha go
+uaslódáladh an leathanach seo roimh ré)',
+'importnosources' => 'Níl aon fhoinse curtha i leith d\'iompórtáil trasna vicíonna, agus
+ní féidir uaslódála staire díreacha a dhéanamh faoi láthair.',
+
+# Keyboard access keys for power users
+'accesskey-search' => 'c', # Cuardaigh
+'accesskey-minoredit' => 'm', # Mionathrú
+'accesskey-save' => 's', # Sábháil
+'accesskey-preview' => 'r', # Reamhamharc
+'accesskey-diff' => 'd', # Difríocht
+'accesskey-compareselectedversions' => 'l', # Leagain
+
+# tooltip help for some actions, most are in Monobook.js
+'tooltip-search' => 'Cuardaigh ar {{SITENAME}} [alt-c]',
+'tooltip-minoredit' => 'Déan mionathrú den athrú seo [alt-m]',
+'tooltip-save' => 'Sábháil do chuid athruithe [alt-s]',
+'tooltip-preview' => 'Réamhamharc ar do chuid athruithe; úsáid an gné seo roimh a shábhálaíonn tú! [alt-r]',
+'tooltip-compareselectedversions' => 'Féach na difríochtaí idir an dhá leagain roghnaithe den leathanach seo. [alt-l]',
+'tooltip-watch' => 'Cuir an leathanach seo ar do liosta faire [alt-f]',
+'tooltip-diff' => 'Taispeáin na difríochtaí áirithe a rinne tú don téacs [alt-d]',
+
+
+# stylesheets
+
+'Monobook.css' => '/* athraigh an comhad seo chun an craiceann MonoBook a athrú don suíomh ar fad */',
+#'Monobook.js' => '/* athraigh an comhad seo chun rudaí js sa craiceann MonoBook a hathrú */',
+
+# Metadata
+'nodublincore' => 'Míchumasaítear meitea-shonraí Dublin Core RDF ar an freastalaí seo.',
+'nocreativecommons' => 'Míchumasaítear meitea-shonraí Creative Commons RDF ar an freastalaí seo.',
+'notacceptable' => 'Ní féidir leis an freastalaí vicí na sonraí a chur ar fáil i bhformáid atá inléite ag do chliant.',
+
+# Attribution
+
+'anonymous' => "Úsáideoir(í) gan ainm ar {{SITENAME}}",
+'siteuser' => "Úsáideoir $1 ag {{SITENAME}}", #FIXME - genitive needed here
+'lastmodifiedby' => "Leasaigh $2 an leathanach seo go déanaí ag $1.",
+'and' => 'agus',
+'othercontribs' => "Bunaithe ar saothair le $1.",
+'others' => 'daoine eile',
+'siteusers' => "Úsáideoir(í) ag {{SITENAME}}", #FIXME - genitive needed here
+'creditspage' => 'Creidiúintí leathanaigh',
+'nocredits' => 'Níl aon eolas creidiúna le fáil don leathanach seo.',
+
+# Spam protection
+
+'spamprotectiontitle' => 'Scagaire in aghaidh ríomhphost dramhála',
+'spamprotectiontext' => 'Chuir an scagaire dramhála bac ar an leathanach a raibh tú ar
+iarradh sábháil. Is dócha gur nasc chuig suíomh seachtrach ba chúis leis.',
+'spamprotectionmatch' => 'Truicear ár scagaire dramhála ag an téacs seo a leanas: $1',
+'subcategorycount' => "Tá $1 fo-chatagóirí sa chatagóir seo.",
+'subcategorycount1' => "Tá fó-chatagóir amháin sa chatagóir seo.",
+'categoryarticlecount' => "Tá $1 ailt sa chatagóir seo.",
+'categoryarticlecount1' => "Tá alt amháin sa chatagóir seo.",
+'usenewcategorypage' => "1\n\nScríobh \"0\" mar an chéad litir chun an leagan amach nua
+
+chatagóire a mhíchumasú.",
+
+# Info page
+"infosubtitle" => "Eolas don leathanach",
+"numedits" => "Méid athruithe (alt): $1",
+"numtalkedits" => "Méid athruithe (leathanach phlé): $1",
+"numwatchers" => "Méid féachnóirí: $1",
+"numauthors" => "Méid údair ar leith (alt): $1",
+"numtalkauthors" => "Méid údair ar leith (leathanach phlé): $1",
+
+# Math options
+
+'mw_math_png' => "Déan PNG-íomhá gach uair",
+'mw_math_simple' => "Déan HTML má tá sin an-easca, nó PNG ar mhodh eile",
+'mw_math_html' => "Déan HTML más féidir, nó PNG ar mhodh eile",
+'mw_math_source' => "Fág mar cló TeX (do teacsleitheoirí)",
+'mw_math_modern' => "Inmholta do líonleitheoirí nua",
+'mw_math_mathml' => 'MathML más féidir (turgnamhach)',
+
+# Patrolling
+'markaspatrolleddiff'   => "Marcáil bheith patrólaithe",
+'markaspatrolledlink'   => "<div class='patrollink'>[$1]</div>",
+'markaspatrolledtext'   => "Marcáil go bhfuil an alt seo patrólaithe",
+'markedaspatrolled'     => "Marcáil bheith patrólaithe",
+'markedaspatrolledtext' => "Marcáladh an athrú áirithe seo bheith patrólaithe.",
+'rcpatroldisabled'      => "Mhíchumasaíodh Patról na n-Athruithe is Déanaí",
+'rcpatroldisabledtext'  => "Tá an tréith Patról na n-Athruithe is Déanaí míchumasaithe faoi láthair.",
+
+# Monobook.js: tooltips and access keys for monobook
+'Monobook.js' => '/* leideanna uirlisí agus cnaipí rochtana */
+ta = new Object();
+ta[\'pt-userpage\'] = new Array(\'.\',\'Mo leathanach úsáideora\');
+ta[\'pt-anonuserpage\'] = new Array(\'.\',\'Leathanach úsáideora don IP ina dhéanann tú do chuid athruithe\');
+ta[\'pt-mytalk\'] = new Array(\'n\',\'Mo leathanach phlé\');
+ta[\'pt-anontalk\'] = new Array(\'n\',\'Plé maidir le na hathruithe a dhéantar ón seoladh IP seo\');
+ta[\'pt-preferences\'] = new Array(\'\',\'Mo chuid sainroghanna\');
+ta[\'pt-watchlist\'] = new Array(\'l\',\'Liosta de na leathanaigh a dhéanann tú faire ar maidir  le athruithe\');
+ta[\'pt-mycontris\'] = new Array(\'y\',\'Liosta de mo chuid dréachtaí\');
+ta[\'pt-login\'] = new Array(\'o\',\'Moltar duit logáil isteach, ach níl sé riachtanach.\');
+ta[\'pt-anonlogin\'] = new Array(\'o\',\'Moltar duit logáil isteach, ach níl sé riachtanach.\');
+ta[\'pt-logout\'] = new Array(\'o\',\'Logáil amach\');
+ta[\'ca-talk\'] = new Array(\'t\',\'Plé maidir leis an leathanach ábhair\');
+ta[\'ca-edit\'] = new Array(\'e\',\'Is féidir leat an leathanach seo a athrú. Más é do thoil é, bain úsáid as an cnaipe réamhamhairc roimh sábháil a dhéanamh.\');
+ta[\'ca-addsection\'] = new Array(\'+\',\'Cuir trácht leis an plé seo..\');
+ta[\'ca-viewsource\'] = new Array(\'e\',\'Tá an leathanach seo glasáilte. Is féidir leat a fhoinse a fheiceáil.\');
+ta[\'ca-history\'] = new Array(\'h\',\'Leagain stairiúla den leathanach seo.\');
+ta[\'ca-protect\'] = new Array(\'=\',\'Glasáil an leathanach seo\');
+ta[\'ca-delete\'] = new Array(\'d\',\'Scrios an leathanach seo\');
+ta[\'ca-undelete\'] = new Array(\'d\',\'Díscrios na hathruithe a rinneadh don leathanach seo roimh a scriosadh é\');
+ta[\'ca-move\'] = new Array(\'m\',\'Athainmnigh an leathanach\');
+ta[\'ca-nomove\'] = new Array(\'\',\'Níl an cead riachtanach agat chun an leathanach a athainmniú\');
+ta[\'ca-watch\'] = new Array(\'w\',\'Cuir an leathanach seo ar do liosta faire\');
+ta[\'ca-unwatch\'] = new Array(\'w\',\'Bain an leathanach seo as do liosta faire\');
+ta[\'search\'] = new Array(\'f\',\'Cuardaigh sa vicí seo\');
+ta[\'p-logo\'] = new Array(\'\',\'Príomhleathanach\');
+ta[\'n-mainpage\'] = new Array(\'z\',\'Tabhair cuairt ar an bPríomhleathanach\');
+ta[\'n-portal\'] = new Array(\'\',\'Maidir leis an tionscadal, cad is féidir leat a dhéanamh, conas achmhainní a fháil\');
+ta[\'n-currentevents\'] = new Array(\'\',\'Faigh eolas cúlrach maidir le chursaí reatha\');
+ta[\'n-recentchanges\'] = new Array(\'r\',\'Liosta de na hathruithe is déanaí sa vicí.\');
+ta[\'n-randompage\'] = new Array(\'x\',\'Lódáil leathanach fánach\');
+ta[\'n-help\'] = new Array(\'\',\'An áit chun cabhair a fháil.\');
+ta[\'n-sitesupport\'] = new Array(\'\',\'Tabhair tacaíocht duinn\');
+ta[\'t-whatlinkshere\'] = new Array(\'j\',\'Liosta de gach leathanach sa vicí a nascaíonn chuig an leathanach seo\');
+ta[\'t-recentchangeslinked\'] = new Array(\'k\',\'Na hathruithe is déanaí ar leathanaigh a nascaíonn chuig an leathanach seo\');
+ta[\'feed-rss\'] = new Array(\'\',\'Fotha RSS don leathanach seo\');
+ta[\'feed-atom\'] = new Array(\'\',\'Fotha Atom don leathanach seo\');
+ta[\'t-contributions\'] = new Array(\'\',\'Féach ar an liosta dréachtaí a rinne an t-úsáideoir seo\');
+ta[\'t-emailuser\'] = new Array(\'\',\'Cuir teachtaireacht chuig an úsáideoir seo\');
+ta[\'t-upload\'] = new Array(\'u\',\'Comhaid íomhá nó meáin a uaslódáil\');
+ta[\'t-specialpages\'] = new Array(\'q\',\'Liosta de gach leathanach speisialta\');
+ta[\'ca-nstab-main\'] = new Array(\'c\',\'Féach ar an leathanach ábhair\');
+ta[\'ca-nstab-user\'] = new Array(\'c\',\'Féach ar an leathanach úsáideora\');
+ta[\'ca-nstab-media\'] = new Array(\'c\',\'Féach ar an leathanach meáin\');
+ta[\'ca-nstab-special\'] = new Array(\'\',\'Is leathanach speisialta é seo, ní féidir leat an leathanach é fhéin a athrú.\');
+ta[\'ca-nstab-wp\'] = new Array(\'a\',\'Féach ar an leathanach thionscadail\');
+ta[\'ca-nstab-image\'] = new Array(\'c\',\'Féach ar an leathanach íomhá\');
+ta[\'ca-nstab-mediawiki\'] = new Array(\'c\',\'Féach ar an teachtaireacht córais\');
+ta[\'ca-nstab-template\'] = new Array(\'c\',\'Féach ar an teimpléad\');
+ta[\'ca-nstab-help\'] = new Array(\'c\',\'Féach ar an leathanach cabhrach\');
+ta[\'ca-nstab-category\'] = new Array(\'c\',\'Féach ar an leathanach catagóire\');',
+
+# image deletion
+'deletedrevision' => 'Scriosadh an sean-leagan $1.',
+
+# browsing diffs
+'previousdiff' => '← An difríocht roimhe seo',
+'nextdiff' => 'An difríocht i ndiadh seo →',
+
+'imagemaxsize' => 'Cuir an teorann seo ar na íomhánna atá le fáil ar leathanaigh cuir síos íomhánna: ',
+'thumbsize'    => 'Méid mionshamhla : ',
+'showbigimage' => 'Íoslódáil leagan ardtaifigh ($1x$2, $3 kb)',
+
+'newimages' => 'Gailearaí na n-íomhánna nua',
+'noimages'  => 'Níl aon rud le feiscint.',
+
+# short names for language variants used for language conversion links.
+# to disable showing a particular link, set it to 'disable', e.g.
+# 'variantname-zh-sg' => 'disable',
+'variantname-zh-cn' => 'cn',
+'variantname-zh-tw' => 'tw',
+'variantname-zh-hk' => 'hk',
+'variantname-zh-sg' => 'sg',
+'variantname-zh' => 'zh',
+
+'variantname-is' => 'is',
+'variantname-iz' => 'iz',
+
+# labels for User: and Title: on Special:Log pages
+'specialloguserlabel' => 'Úsáideoir: ',
+'speciallogtitlelabel' => 'Teideal: ',
+
+'passwordtooshort' => 'Tá d\'fhocal faire ró-ghearr. Caithfidh go bhfuil $1 carachtar ann ar a laghad.',
+
+# Media Warning
+'mediawarning' => '\'\'\'Aire\'\'\': Tá seans ann go bhfuil cód mailíseach sa comhad seo - b\'fheidir go gcuirfear do chóras i gcontúirt dá rithfeá é.
+<hr>',
+
+'fileinfo' => '$1KB, saghas MIME: <code>$2</code>',
+
+# Metadata
+'metadata' => 'Meiteasonraí',
+
+# Exif tags
+'exif-imagewidth' =>'Leithead',
+'exif-imagelength' =>'Airde',
+'exif-bitspersample' =>'Gíotáin sa chomhpháirt',
+'exif-compression' =>'Scéim comhbhrúite',
+'exif-photometricinterpretation' =>'Comhbhrú picteilíní',
+'exif-orientation' =>'Treoshuíomh',
+'exif-samplesperpixel' =>'Líon na gcomhpháirt',
+'exif-planarconfiguration' =>'Eagar na sonraí',
+'exif-ycbcrsubsampling' =>'Cóimheas foshamplála de Y i gcoinne C',
+'exif-ycbcrpositioning' =>'Suí Y agus C',
+'exif-xresolution' =>'Taifeach íomhá i dtreo an leithid',
+'exif-yresolution' =>'Taifeach íomhá i dtreo an airde',
+'exif-resolutionunit' =>'Aonad an taifigh X agus Y',
+'exif-stripoffsets' =>'Suíomh na sonraí íomhá',
+'exif-rowsperstrip' =>'Líon na rónna sa stráice',
+'exif-stripbytecounts' =>'Bearta sa stráice comhbhrúite',
+'exif-jpeginterchangeformat' =>'Aischló don SOI JPEG',
+'exif-jpeginterchangeformatlength' =>'Bearta sonraí JPEG',
+'exif-transferfunction' =>'Feidhm aistrithe',
+'exif-whitepoint' =>'Crómatacht na bpointí bán',
+'exif-primarychromaticities' =>'Crómatachta na bpríomhacht',
+'exif-ycbcrcoefficients' =>'Comhéifeachtaí mhaitrís trasfhoirmithe an dathspáis',
+'exif-referenceblackwhite' =>'Péire luachanna tagartha don dubh is don bán',
+'exif-datetime' =>'Dáta agus am athrú an chomhaid ',
+'exif-imagedescription' =>'Íomhátheideal',
+'exif-make' =>'Déantóir an ceamara',
+'exif-model' =>'Déanamh an ceamara',
+'exif-software' =>'Na bogearraí a úsáideadh',
+'exif-artist' =>'Údar',
+'exif-copyright' =>'Úinéir an chóipchirt',
+'exif-exifversion' =>'Leagan EXIF',
+'exif-flashpixversion' =>'Leagan Flashpix atá á thacú',
+'exif-colorspace' =>'Dathspás',
+'exif-componentsconfiguration' =>'Ciall le gach giota',
+'exif-compressedbitsperpixel' =>'Modh chomhbhrú na n-íomhánna',
+'exif-pixelydimension' =>'Leithead bailí don íomhá',
+'exif-pixelxdimension' =>'Airde bailí don íomhá',
+'exif-makernote' =>'Nótaí an déantóra',
+'exif-usercomment' =>'Nótaí an úsáideora',
+'exif-relatedsoundfile' =>'comhad gaolmhara fuaime',
+'exif-datetimeoriginal' =>'Dáta agus am ghiniúint na sonraí',
+'exif-datetimedigitized' =>'Dáta agus am digitithe',
+'exif-subsectime' =>'Foshoicindí DateTime',
+'exif-subsectimeoriginal' =>'Foshoicindí DateTimeOriginal',
+'exif-subsectimedigitized' =>'Foshoicindí DateTimeDigitized',
+'exif-exposuretime' =>'Am nochta',
+'exif-fnumber' =>'Uimhir F',
+'exif-exposureprogram' =>'Clár nochta',
+'exif-spectralsensitivity' =>'Íogaireacht an speictrim',
+'exif-isospeedratings' =>'Grádú ISO luais',
+'exif-oecf' =>'Fachtóir optaileictreonach tiontaithe',
+'exif-shutterspeedvalue' =>'Luas nochta',
+'exif-aperturevalue' =>'Cró',
+'exif-brightnessvalue' =>'Gile',
+'exif-exposurebiasvalue' =>'Laobh nochta',
+'exif-maxaperturevalue' =>'Cró tíre uasmhéideach',
+'exif-subjectdistance' =>'Fad ón ábhar',
+'exif-meteringmode' =>'Modh meadarachta',
+'exif-lightsource' =>'Foinse solais',
+'exif-flash' =>'Splanc',
+'exif-focallength' =>'Fad fócasach an lionsa',
+'exif-subjectarea' =>'Achar an ábhair',
+'exif-flashenergy' =>'Splanfhuinneamh',
+'exif-spatialfrequencyresponse' =>'Freagairt minicíochta spáis',
+'exif-focalplanexresolution' =>'Taifeach an plána fócasaigh X',
+'exif-focalplaneyresolution' =>'Taifeach an plána fócasaigh Y',
+'exif-focalplaneresolutionunit' =>'Aonad taifigh an plána fócasaigh',
+'exif-subjectlocation' =>'Suíomh an ábhair',
+'exif-exposureindex' =>'Innéacs nochta',
+'exif-sensingmethod' =>'Modh braite',
+'exif-filesource' =>'Foinse comhaid',
+'exif-scenetype' =>'Cineál radhairc',
+'exif-cfapattern' =>'Patrún CFA',
+'exif-customrendered' =>'Íomháphróiseáil saincheaptha',
+'exif-exposuremode' =>'Modh nochta',
+'exif-whitebalance' =>'Bánchothromaíocht',
+'exif-digitalzoomratio' =>'Cóimheas zúmála digiteaí',
+'exif-focallengthin35mmfilm' =>'Fad fócasach i scannán 35 mm',
+'exif-scenecapturetype' =>'Cineál gabhála radhairc',
+'exif-gaincontrol' =>'Rialú radhairc',
+'exif-contrast' =>'Codarsnacht',
+'exif-saturation' =>'Sáithiú',
+'exif-sharpness' =>'Géire',
+'exif-devicesettingdescription' =>'Cur síos ar socruithe gléis',
+'exif-subjectdistancerange' =>'Raon fada ón ábhar',
+'exif-imageuniqueid' =>'Aitheantas uathúil an íomhá',
+'exif-gpsversionid' =>'Leagan clibe GPS',
+'exif-gpslatituderef' =>'Domhan-leithead Thuaidh no Theas',
+'exif-gpslatitude' =>'Domhan-leithead',
+'exif-gpslongituderef' =>'Domhanfhad Thoir nó Thiar',
+'exif-gpslongitude' =>'Domhanfhad',
+'exif-gpsaltituderef' =>'Tagairt airde',
+'exif-gpsaltitude' =>'Airde',
+'exif-gpstimestamp' =>'Am GPS (clog adamhach)',
+'exif-gpssatellites' =>'Satailítí úsáidte don tomhas',
+'exif-gpsstatus' =>'Stádas an ghlacadóra',
+'exif-gpsmeasuremode' =>'Modh tomhais',
+'exif-gpsdop' =>'Beachtas tomhais',
+'exif-gpsspeedref' =>'Aonad luais',
+'exif-gpsspeed' =>'Luas an ghlacadóra GPS',
+'exif-gpstrackref' =>'Tagairt don treo gluaiseachta',
+'exif-gpstrack' =>'Treo gluaiseachta',
+'exif-gpsimgdirectionref' =>'Tagairt do treo an íomhá',
+'exif-gpsimgdirection' =>'Treo an íomhá',
+'exif-gpsmapdatum' =>'Sonraí suirbhéireachta geodasaí a úsáideadh',
+'exif-gpsdestlatituderef' =>'Tagairt don domhan-leithead sprice',
+'exif-gpsdestlatitude' =>'Domhan-leithead sprice',
+'exif-gpsdestlongituderef' =>'Tagairt don domhanfhad sprice',
+'exif-gpsdestlongitude' =>'Domhanfhad sprice',
+'exif-gpsdestbearingref' =>'Tagairt don treo-uillinn sprice',
+'exif-gpsdestbearing' =>'Treo-uillinn sprice',
+'exif-gpsdestdistanceref' =>'Tagairt don fad ón áit sprice',
+'exif-gpsdestdistance' =>'Fad ón áit sprice',
+'exif-gpsprocessingmethod' =>'Ainm an modha próiseála GPS',
+'exif-gpsareainformation' =>'Ainm an cheantair GPS',
+'exif-gpsdatestamp' =>'Dáta GPS',
+'exif-gpsdifferential' =>'Ceartú difreálach GPS',
+
+# Make & model, can be wikified in order to link to the camera and model name
+
+'exif-make-value' => '$1',
+'exif-model-value' =>'$1',
+'exif-software-value' => '$1',
+
+# Exif attributes
+
+'exif-compression-1' => 'Neamh-chomhbhrúite',
+'exif-compression-6' => 'JPEG',
+
+'exif-photometricinterpretation-1' => 'RGB',
+'exif-photometricinterpretation-6' => 'YCbCr',
+
+'exif-orientation-1' => 'Gnáth', // 0th row: top; 0th column: left
+'exif-orientation-2' => 'Iompaithe go cothrománach', // 0th row: top; 0th column: right
+'exif-orientation-3' => 'Rothlaithe trí 180°', // 0th row: bottom; 0th column: right
+'exif-orientation-4' => 'Iompaithe go hingearach', // 0th row: bottom; 0th olumn: left
+'exif-orientation-5' => 'Rothlaithe trí 90° CCW agus iompaithe go hingearach', // 0th row: left; 0th column: top
+'exif-orientation-6' => 'Rothlaithe trí 90° CW', // 0th row: right; 0th column: top
+'exif-orientation-7' => 'Rothlaithe trí 90° CW agus iompaithe go hingearach', // 0th row: right; 0th column: bottom
+'exif-orientation-8' => 'Rothlaithe trí 90° CCW', // 0th row: left; 0th column: bottom
+
+'exif-planarconfiguration-1' => 'Formáid shmutánach',
+'exif-planarconfiguration-2' => 'Formáid phlánach',
+
+'exif-colorspace-1' => 'sRGB',
+'exif-colorspace-ffff.h' => 'FFFF.H',
+
+'exif-componentsconfiguration-0' => 'níl a leithéid ann',
+'exif-componentsconfiguration-1' => 'Y',
+'exif-componentsconfiguration-2' => 'Cb',
+'exif-componentsconfiguration-3' => 'Cr',
+'exif-componentsconfiguration-4' => 'R',
+'exif-componentsconfiguration-5' => 'G',
+'exif-componentsconfiguration-6' => 'B',
+
+'exif-exposureprogram-0' => 'Gan sainiú',
+'exif-exposureprogram-1' => 'Leis na lámha',
+'exif-exposureprogram-2' => 'Gnáthchlár',
+'exif-exposureprogram-3' => 'Tosaíocht nochta',
+'exif-exposureprogram-4' => 'Tosaíocht cró',
+'exif-exposureprogram-5' => 'Clár cúise (laofa do doimhneacht réimse)',
+'exif-exposureprogram-6' => 'Clár gnímh (laofa do cróluas tapaidh)',
+'exif-exposureprogram-7' => 'Modh portráide (do grianghraif i ngar don ábhar,
+le cúlra as fócas)',
+'exif-exposureprogram-8' => 'Modh tírdhreacha (do grianghraif tírdhreacha le
+cúlra i bhfócas)',
+
+'exif-meteringmode-0' => 'Anaithnid',
+'exif-meteringmode-1' => 'Meán',
+'exif-meteringmode-2' => 'MeánUalaitheDonLár',
+'exif-meteringmode-3' => 'Spota',
+'exif-meteringmode-4' => 'Ilspotach',
+'exif-meteringmode-5' => 'Patrún',
+'exif-meteringmode-6' => 'Páirteach',
+'exif-meteringmode-255' => 'Eile',
+
+'exif-lightsource-0' => 'Anaithnid',
+'exif-lightsource-1' => 'Solas lae',
+'exif-lightsource-2' => 'Fluaraiseach',
+'exif-lightsource-3' => 'Tungstan (solas gealbhruthach)',
+'exif-lightsource-4' => 'Splanc',
+'exif-lightsource-9' => 'Aimsir breá',
+'exif-lightsource-10' => 'Aimsir scamallach',
+'exif-lightsource-11' => 'Scáth',
+'exif-lightsource-12' => 'Solas lae fluaraiseach (D 5700 â€“ 7100K)',
+'exif-lightsource-13' => 'Solas bán lae fluaraiseach (N 4600 â€“ 5400K)',
+'exif-lightsource-14' => 'Solas fuar bán fluaraiseach (W 3900 â€“ 4500K)',
+'exif-lightsource-15' => 'Solas bán fluaraiseach (WW 3200 â€“ 3700K)',
+'exif-lightsource-17' => 'Gnáthsholas A',
+'exif-lightsource-18' => 'Gnáthsholas B',
+'exif-lightsource-19' => 'Gnáthsholas C',
+'exif-lightsource-20' => 'D55',
+'exif-lightsource-21' => 'D65',
+'exif-lightsource-22' => 'D75',
+'exif-lightsource-23' => 'D50',
+'exif-lightsource-24' => 'Tungstan stiúideó ISO',
+'exif-lightsource-255' => 'Foinse eile solais',
+
+'exif-sensingmethod-1' => 'Gan sainiú',
+'exif-sensingmethod-2' => 'Braiteoir aonshliseach ceantair datha',
+'exif-sensingmethod-3' => 'Braiteoir dháshliseach ceantair datha',
+'exif-sensingmethod-4' => 'Braiteoir tríshliseach ceantair datha',
+'exif-sensingmethod-5' => 'Braiteoir dathsheicheamhach ceantair',
+'exif-sensingmethod-7' => 'Braiteoir trílíneach',
+'exif-sensingmethod-8' => 'Braiteoir dathsheicheamhach línte',
+
+'exif-filesource-3' => 'DSC',
+
+'exif-scenetype-1' => 'Grianghraf a rinneadh go díreach',
+
+'exif-customrendered-0' => 'Gnáthphróiseas',
+'exif-customrendered-1' => 'Próiseas saincheaptha',
+
+'exif-exposuremode-0' => 'Nochtadh uathoibríoch',
+'exif-exposuremode-1' => 'Nochtadh láimhe',
+'exif-exposuremode-2' => 'Brac uathoibríoch',
+
+'exif-whitebalance-0' => 'Bánchothromaíocht uathoibríoch',
+'exif-whitebalance-1' => 'Bánchothromaíocht láimhe',
+
+'exif-scenecapturetype-0' => 'Gnáth',
+'exif-scenecapturetype-1' => 'Tírdhreach',
+'exif-scenecapturetype-2' => 'Portráid',
+'exif-scenecapturetype-3' => 'Radharc oíche',
+
+'exif-gaincontrol-0' => 'Dada',
+'exif-gaincontrol-1' => 'Íosneartúchán suas',
+'exif-gaincontrol-2' => 'Uasneartúchán suas',
+'exif-gaincontrol-3' => 'Íosneartúchán síos',
+'exif-gaincontrol-4' => 'Uasneartúchán síos',
+
+'exif-contrast-0' => 'Gnáth',
+'exif-contrast-1' => 'Bog',
+'exif-contrast-2' => 'Crua',
+
+'exif-saturation-0' => 'Gnáth',
+'exif-saturation-1' => 'Sáithiúchán íseal',
+'exif-saturation-2' => 'Ard-sáithiúchán',
+
+'exif-sharpness-0' => 'Gnáth',
+'exif-sharpness-1' => 'Bog',
+'exif-sharpness-2' => 'Crua',
+
+'exif-subjectdistancerange-0' => 'Anaithnid',
+'exif-subjectdistancerange-1' => 'Macra',
+'exif-subjectdistancerange-2' => 'Radharc teann',
+'exif-subjectdistancerange-3' => 'Cianradharc',
+
+// Pseudotags used for GPSLatitudeRef and GPSDestLatitudeRef
+'exif-gpslatitude-n' => 'Domhan-leithead thuaidh',
+'exif-gpslatitude-s' => 'Domhan-leithead theas',
+
+// Pseudotags used for GPSLongitudeRef and GPSDestLongitudeRef
+'exif-gpslongitude-e' => 'Domhanfhad Thoir',
+'exif-gpslongitude-w' => 'Domhanfhad Thiar',
+
+'exif-gpsstatus-a' => 'Tomhas ar siúl',
+'exif-gpsstatus-v' => 'Tomhas dodhéanta',
+
+'exif-gpsmeasuremode-2' => 'Tomhas déthoiseach',
+'exif-gpsmeasuremode-3' => 'Tomhas tríthoiseach',
+
+// Pseudotags used for GPSSpeedRef and GPSDestDistanceRef
+'exif-gpsspeed-k' => 'Ciliméadair san uair',
+'exif-gpsspeed-m' => 'Mílte san uair',
+'exif-gpsspeed-n' => 'Muirmhílte',
+
+// Pseudotags used for GPSTrackRef, GPSImgDirectionRef and GPSDestBearingRef
+'exif-gpsdirection-t' => 'Fíorthreo',
+'exif-gpsdirection-m' => 'Treo maighnéadach',
+
+# external editor support
+'edit-externally' => 'Athraigh an comhad seo le feidhmchlár seachtrach',
+'edit-externally-help' => 'Féach ar na
+
+[http://meta.wikimedia.org/wiki/Help:External_editors treoracha cumraíochta] (as Béarla)
+
+le tuilleadh eolais.',
+
+# 'all' in various places, this might be different for inflicted languages
+'recentchangesall' => 'gach',
+'imagelistall' => 'gach',
+'watchlistall1' => 'gach',
+'watchlistall2' => 'gach',
+
+# E-mail address confirmation
+'confirmemail' => 'Deimhnigh do sheoladh ríomhphoist',
+'confirmemail_text' => "Tá sé de dhíth an an vicí seo do sheoladh ríomhphoist a
+
+bhailíochtú sula úsáideann tú na gnéithe ríomhphoist. Gníomhachtaigh an cnaipe seo thíos
+
+chun teachtaireacht deimhnithe a sheoladh chuig do chuntas ríomhphoist. Beidh nasc ann sa
+
+comhad ina mbeidh cód áirithe; lódáil an nasc i do bhrabhsálaí chun deimhniú go bhfuil do
+
+sheoladh ríomhphoist bailí.",
+'confirmemail_send' => 'Seol cód deimhnithe',
+'confirmemail_sent' => 'Seoladh teachtaireacht deimhnithe.',
+'confirmemail_sendfailed' => 'Níorbh fhéidir an teachtaireacht deimhnithe a sheoladh. Seiceáil nach bhfuil caractair neamh-bhailí ann sa seoladh.',
+'confirmemail_invalid' => 'Cód deimhnithe neamh-bhailí. B\'fhéidir gur chuaidh an cód as feidhm.',
+'confirmemail_success' => 'Deimhníodh do sheoladh ríomhphoist. Is féidir leat logáil
+
+isteach anois agus sult a bhaint as an vicí.',
+'confirmemail_loggedin' => 'Deimhníodh do sheoladh ríomhphoist.',
+'confirmemail_error' => 'Tharlaigh botún éigin le sabháil do dheimhniú.',
+
+'confirmemail_subject' => 'Deimhniú seolaidh ríomhphoist as {{SITENAME}}',
+'confirmemail_body' => "Chláraigh duine éigin an cuntas \"$2\" le húsáid an seolaidh
+
+ríomhphoist seo ar {{SITENAME}} - is dócha gur rinne tú féin é seo, ón seoladh IP $1.
+
+Chun deimhniú a dhéanamh gur leatsa é an cuntas seo, agus chun gnéithe ríomhphoist a chur
+
+i ngníomh ag {{SITENAME}}, oscail an nasc seo i do bhrabhsalaí:
+
+$3
+
+*Muna* bhfuil tú an duine atá i gceist, ná roghnaigh an nasc. Rachfaidh an cód deimhnithe
+
+seo as feidhm ag $4.
+",
+
+# Inputbox extension, may be useful in other contexts as well
+'tryexact' => 'Déan iarracht ar meaitseáil cruinn',
+'searchfulltext' => 'Cuardaigh sa téacs iomlán',
+'createarticle' => 'Cruthaigh alt',
+
+# Scary transclusion
+'scarytranscludedisabled' => '[Díchumasaíodh trasáireamh idir vicíonna]',
+'scarytranscludefailed' => '[Theip leis an iarradh teimpléid do $1; tá brón orainn]',
+'scarytranscludetoolong' => '[Tá an URL ró-fhada; tá brón orainn]',
+
+);
+
+require_once( "LanguageUtf8.php" );
+
+class LanguageGa extends LanguageUtf8 {
+
+       function getNamespaces() {
+               global $wgNamespaceNamesGa;
+               return $wgNamespaceNamesGa;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsGa;
+               return $wgQuickbarSettingsGa;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesGa;
+               return $wgSkinNamesGa;
+       }
+
+       function getDateFormats() {
+               global $wgDateFormatsGa;
+               return $wgDateFormatsGa;
+       }
+
+       /**
+        * Get a namespace key by value, case insensetive.
+        *
+        * @param string $text
+        * @return mixed An integer if $text is a valid value otherwise false
+        */
+       function getNsIndex( $text ) {
+               $ns = $this->getNamespaces();
+
+               foreach ( $ns as $i => $n ) {
+                       if ( strcasecmp( $n, $text ) == 0)
+                               return $i;
+               }
+
+               if ( strcasecmp( 'Plé_í­omhá', $text) == 0) return NS_IMAGE_TALK;
+               if ( strcasecmp( 'Múnla', $text) == 0) return NS_TEMPLATE;
+               if ( strcasecmp( 'Múnla', $text) == 0) return NS_TEMPLATE;
+               if ( strcasecmp( 'Plé_múnla', $text) == 0) return NS_TEMPLATE_TALK;
+               if ( strcasecmp( 'Rang', $text) == 0) return NS_CATEGORY;
+               if ( strcasecmp( 'Catagóir', $text) == 0) return NS_CATEGORY_TALK;
+
+               return false;
+       }
+
+
+       function getMessage( $key ) {
+       global $wgAllMessagesGa;
+               if( isset( $wgAllMessagesGa[$key] ) ) {
+                       return $wgAllMessagesGa[$key];
+               } else {
+                       return parent::getMessage( $key );
+               }
+       }
+
+       function getAllMessages() {
+               global $wgAllMessagesGa;
+               return $wgAllMessagesGa;
+       }
+
+       function getMagicWords() {
+               global $wgMagicWordsGa;
+               return $wgMagicWordsGa;
+       }
+
+       # Convert day names
+       # Invoked with {{GRAMMAR:transformation|word}}
+       function convertGrammar( $word, $what ) {
+               switch ( $case ) {
+               case 'ainmlae':
+                       switch ($word) {
+                       case 'an Domhnach':
+                               $word = 'Dé Domhnaigh'; break;
+                       case 'an Luan':
+                               $word = 'Dé Luain'; break;
+                       case 'an Mháirt':
+                               $word = 'Dé Mháirt'; break;
+                       case 'an Chéadaoin':
+                               $word = 'Dé Chéadaoin'; break;
+                       case 'an Déardaoin':
+                               $word = 'Déardaoin'; break;
+                       case 'an Aoine':
+                               $word = 'Dé hAoine'; break;
+                       case 'an Satharn':
+                               $word = 'Dé Sathairn'; break;
+                       }
+               }
+               return $word;
+       }
+
+}
+
+?>
diff --git a/languages/LanguageGem_alsatian.php b/languages/LanguageGem_alsatian.php
new file mode 100644 (file)
index 0000000..068e1f9
--- /dev/null
@@ -0,0 +1,23 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+/*
+<Melancholie> for the moment it would be the best if LanguageAls.php would be
+              the same like LanguageDe.php. That would help us a lot at als.
+<Melancholie> at the moment all is in English
+<TimStarling> ok
+<Melancholie> great
+<TimStarling> I'll make a stub language file that fetches everything from de
+<Melancholie> cool
+*/
+
+include_once( "LanguageDe.php" );
+
+class LanguageGem_alsatian extends LanguageDe {
+       /* Inherit everything. */
+}
+
+?>
diff --git a/languages/LanguageGu.php b/languages/LanguageGu.php
new file mode 100644 (file)
index 0000000..3e1c93f
--- /dev/null
@@ -0,0 +1,33 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+require_once( 'LanguageUtf8.php' );
+
+class LanguageGu extends LanguageUtf8 {
+       var $digitTransTable = array(
+               '0' => '૦',
+               '1' => '૧',
+               '2' => '૨',
+               '3' => '૩',
+               '4' => '૪',
+               '5' => '૫',
+               '6' => '૬',
+               '7' => '૭',
+               '8' => '૮',
+               '9' => '૯'
+       );
+
+       function formatNum( $number ) {
+               global $wgTranslateNumerals;
+               if( $wgTranslateNumerals ) {
+                       return strtr( $number, $this->digitTransTable );
+               } else {
+                       return $number;
+               }
+       }
+}
+
+?>
diff --git a/languages/LanguageHe.php b/languages/LanguageHe.php
new file mode 100644 (file)
index 0000000..b457634
--- /dev/null
@@ -0,0 +1,780 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+require_once("LanguageUtf8.php");
+
+/* private */ $wgNamespaceNamesHe = array(
+       NS_MEDIA          => "Media",
+       NS_SPECIAL        => "מיוחד",
+       NS_MAIN           => "",
+       NS_TALK           => "שיחה",
+       NS_USER           => "משתמש",
+       NS_USER_TALK      => "שיחת_משתמש",
+       NS_PROJECT        => $wgMetaNamespace,
+       NS_PROJECT_TALK   => "שיחת_" . $wgMetaNamespace,
+       NS_IMAGE          => "תמונה",
+       NS_IMAGE_TALK     => "שיחת_תמונה",
+       NS_MEDIAWIKI      => "MediaWiki",
+       NS_MEDIAWIKI_TALK => "שיחת_MediaWiki",
+       NS_TEMPLATE       => "תבנית",
+       NS_TEMPLATE_TALK  => "שיחת_תבנית",
+       NS_HELP           => "עזרה",
+       NS_HELP_TALK      => "שיחת_עזרה",
+       NS_CATEGORY       => "קטגוריה",
+       NS_CATEGORY_TALK  => "שיחת_קטגוריה",
+) + $wgNamespaceNamesEn;
+
+/* Custom namespaces for portal and portal_talk */
+$wgExtraNamespaces = array(
+       100 => "פורטל",
+       101 => "שיחת_פורטל");
+
+/* private */ $wgQuickbarSettingsHe = array(
+       "ללא", "קבוע משמאל", "קבוע מימין", "צף משמאל"
+);
+
+/* private */ $wgSkinNamesHe = array(
+       'standard' => "רגיל",
+       'nostalgia' => "נוסטלגי",
+       'cologneblue' => "מים כחולים",
+       'smarty' => "Paddington",
+       'montparnasse' => "Montparnasse",
+) + $wgSkinNamesEn;
+
+
+
+/* private */ $wgBookstoreListHe = array(
+       "מיתוס" => "http://www.mitos.co.il/ ",
+       "ibooks" => "http://www.ibooks.co.il/",
+       "Barnes & Noble" => "http://search.barnesandnoble.com/bookSearch/isbnInquiry.asp?isbn=$1",
+       "Amazon.com" => "http://www.amazon.com/exec/obidos/ISBN=$1"
+);
+
+
+/* private */ $wgAllMessagesHe = array(
+
+# User Toggles
+#
+
+"tog-underline" => "סמן קישורים בקו תחתי",
+"tog-highlightbroken" => "סמן קישורים לדפים שלא נכתבו באדום (או: סימן שאלה)",
+"tog-justify"  => "ישר פסקאות",
+"tog-hideminor" => "הסתר שינויים משניים ברשימת השינויים האחרונים",
+"tog-usenewrc" => "רשימת שינויים אחרונים משופרת (לא מתאים לכל דפדפן)",
+"tog-numberheadings" => "מספר ראשי-פרקים אוטומטית",
+"tog-showtoolbar" => "Show edit toolbar",
+"tog-editondblclick" => "ערוך דפים בלחיצה כפולה (דורש ג'אווה סקריפט)",
+"tog-editsection"=>"Enable section editing via [edit] links",
+"tog-editsectiononrightclick"=>"Enable section editing by right clicking<br /> on section titles (JavaScript)",
+"tog-showtoc"=>"Show table of contents<br />(for articles with more than 3 headings",
+"tog-rememberpassword" => "זכור את הסיסמא שלי בפעמים הבאות",
+"tog-editwidth" => "תיבת העריכה ברוחב מלא",
+"tog-watchdefault" => "עקוב אחרי מאמרים שערכתי או יצרתי",
+"tog-minordefault" => "הגדר כל פעולת עריכה כמשנית אם לא צויין אחרת",
+"tog-previewontop" => "הצג תצוגה מקדימה לפני קופסת העריכה (או: אחריה)",
+"tog-nocache" => "נטרל משיכת דפים מזכרון המטמון שבשרת",
+
+# Dates
+#
+
+'sunday' => "ראשון",
+'monday' => "שני",
+'tuesday' => "שלישי",
+'wednesday' => "רביעי",
+'thursday' => "חמישי",
+'friday' => "שישי",
+'saturday' => "שבת",
+'january' => "ינואר",
+'february' => "פברואר",
+'march' => "מרץ",
+'april' => "אפריל",
+'may_long' => "מאי",
+'june' => "יוני",
+'july' => "יולי",
+'august' => "אוגוסט",
+'september' => "ספטמבר",
+'october' => "אוקטובר",
+'november' => "נובמבר",
+'december' => "דצמבר",
+'jan' => "ינו'",
+'feb' => "פבר'",
+'mar' => "מרץ",
+'apr' => "אפר'",
+'may' => "מאי",
+'jun' => "יוני",
+'jul' => "יולי",
+'aug' => "אוג'",
+'sep' => "ספט'",
+'oct' => "אוק'",
+'nov' => "נוב'",
+'dec' => "דצמ'",
+# Bits of text used by many pages:
+#
+"linktrail"            => "/^([a-z]+)(.*)\$/sD",
+"mainpage"             => "עמוד ראשי",
+"about"                        => "אודות",
+"aboutsite"      => "אודות ויקיפדיה",
+"aboutpage"            => "ויקיפדיה:אודות",
+'article' => 'מאמר', #????
+"help"                 => "עזרה",
+"helppage"             => "ויקיפדיה:עזרה",
+"bugreports"   => "דווח על באגים",
+"bugreportspage" => "ויקיפדיה:דווח_על_באגים",
+"faq"                  => "שאלות ותשובות",
+"faqpage"              => "ויקיפדיה:שאלות_ותשובות",
+"edithelp"             => "עזרה לעריכה",
+"edithelppage" => "ויקיפדיה:איך_עורכים_דף",
+"cancel"               => "בטל",
+"qbfind"               => "חפש",
+"qbbrowse"             => "דפדף",
+"qbedit"               => "ערוך",
+"qbpageoptions" => "אפשרויות דף",
+"qbpageinfo"   => "מידע על הדף",
+"qbmyoptions"  => "האפשרויות שלי",
+"mypage"               => "הדף שלי",
+"mytalk"               => "דף השיחה שלי",
+"currentevents" => "-",
+"errorpagetitle" => "שגיאה",
+"returnto"             => "חזור ל-$1",
+"tagline"              => "מתוך ויקיפדיה, האנציקלופדיה החופשית.",
+"whatlinkshere"        => "דפים המקושרים לכאן",
+"help"                 => "עזרה",
+"search"               => "חפש",
+"history"              => "גירסאות קודמות",
+"history_short" => "גירסאות קודמות",
+"printableversion" => "גירסה להדפסה",
+"edit"                 => "עריכה",
+"editthispage" => "ערוך דף זה",
+"deletethispage" => "מחק דף זה",
+"protectthispage" => "הפוך דף זה למוגן",
+"unprotectthispage" => "הסר הגנה מדף זה",
+"newpage" => "דף חדש",
+"talkpage"             => "שוחח על דף זה",
+"articlepage"  => "צפה במאמר",
+"subjectpage"  => "צפה בנושא", # For compatibility
+'talk' => 'שיחה',
+'toolbox' => 'Toolbox',
+"userpage" => "צפה בדף המשתמש",
+"wikipediapage" => "צפה בדף המטא",
+"imagepage" =>         "צפה בדף התמונה",
+"viewtalkpage" => "צפה בדף השיחה",
+"otherlanguages" => "שפות אחרות",
+"redirectedfrom" => "(הופנה מ - $1)",
+"lastmodified" => "שונה לאחרונה ב $1.",
+"viewcount"            => "דף זה נצפה $1 פעמים.",
+"printsubtitle" => "(מ - {{SERVER}})",
+"protectedpage" => "דף מוגן",
+"administrators" => "ויקיפדיה:מפעיל_מערכת",
+"sysoptitle"   => "דרושה הרשאת מפעיל מערכת",
+"sysoptext"            => "בכדי לבצע פעולה זו דרושת הרשאת מפעיל. ראה $1.",
+"developertitle" => "דרושה הרשאת מפתח מערכת",
+"developertext"        => "בכדי לבצע פעולה זו דרושת הרשאת מפתח, ראה $1.",
+
+"nbytes"               => "$1 בתים",
+"go"                   => "לך",
+"ok"                   => "אישור",
+"sitetitle"            => "ויקיפדיה",
+"sitesubtitle" => "האנציקלופדיה החופשית",
+"retrievedfrom" => "מקור: $1",
+"newmessages" => "יש לך $1",
+"newmessageslink" => "הודעות חדשות",
+"editsection" => "עריכה",
+
+# Main script and global functions
+#
+"nosuchaction" => "אין פעולה כזו",
+"nosuchactiontext" => "תוכנת ויקיפדיה אינה מכירה את הפעולה המצויינת ב-URL.",
+"nosuchspecialpage" => "אין דף מיוחד בשם זה",
+"nospecialpagetext" => "ביקשת דף מיוחד שאינו מוכר למערכת ויקיפדיה.",
+
+# General errors
+#
+"error"                        => "שגיאה",
+"databaseerror" => "שגיאת בסיס-נתונים",
+"dberrortext"  => "ארעה שגיאת תחביר בשאילתא לבסיס-הנתונים.
+השאילתה האחרונה שבוצעה לבסיס-הנתונים היתה:
+<blockquote><tt>$1</tt></blockquote>
+מהפונקציה \"<tt>$2</tt>\".
+בסיס-הנתונים החזיר את השגיאה: \"<tt>$3: $4</tt>\" ",
+"noconnect"            => "לא הצליח נסיון ההתחברות לבסיס-הנתונים על $1",
+"nodb"                 => "לא ניתן לבחור את בסיס-הנתונים $1",
+"readonly"             => "בסיס-הנתונים נעול",
+"enterlockreason" => "הזן סיבה לנעילת בסיס-הנתונים, וכלול הערכה לגבי מתי הנעילה תשוחרר.",
+"readonlytext" => "בסיס-נתונים זה של ויקיפדיה נעול ברגע זה להזנת נתונים ושנויים. ככל הנראה מדובר בתחזוקה שותפת, שלאחריה הוא יחזור לפעולתו הרגילה.
+מפעיל המערכת שנעל אותו סיפק את ההסבר הבא:
+$1",
+"missingarticle" => "בסיס-הנתונים לא מצא את הטקסט של דף שאותו הוא אמור היה למצוא, בשם \"$1\".
+זוהי אינה שגיאת בסיס-נתונים, אבל סביר להניח שמדובר בבאג בתוכנה.
+אנא דווח זאת למפעיל מערכת, תוך שמירת פרטי ה-URL.",
+"internalerror" => "שגיאה פנימית",
+"filecopyerror" => "העתקת \"$1\" ל-\"$2\" לא הצליחה.",
+"filerenameerror" => "שינוי השם של \"$1\" ל-\"$2\" לא הצליח.",
+"filedeleteerror" => "מחיקת \"$1\" לא הצליחה.",
+"filenotfound" => "הקובץ \"$1\" לא נמצא.",
+"unexpected"   => "ערך לא צפוי: \"$1\"=\"$2\"",
+"formerror"            => "שגיאה: לא יכול לשלוח טופס.",
+"badarticleerror" => "לא ניתן לבצע פעולה זו בדף זה.",
+"cannotdelete" => "מחיקת הדף או קובץ התמונה לא הצליחה. (יתכן שנמחקה כבר על-ידי מישהו אחר)",
+"badtitle"             => "כותרת שגויה",
+"badtitletext" => "כותרת הדף המבוקש היתה לא-חוקית, ריקה, קישור ויקי פנימי, או פנים שפה שגוי.",
+"perfdisabled" => "שירות זה הופסק זמנית בזמן שעות העומס בכדי לא לפגוע בביצועי המערכת, הוא יחזור בין השעות 02:00 ו-14:00(UTC). עמכם הסליחה!",
+
+# Login and logout pages
+#
+"logouttitle"  => "יציאה מהחשבון",
+"logouttext"   => "יצאת עתה מהחשבון. את/ה יכול/ה להמשיך ולעשות שימוש בויקיפדיה בצורה אנונימית, או שתוכל/י לשוב ולהכנס לאתר שנית עם שם משתמש זהה או אחר. \n",
+
+"welcomecreation" => "<b>ברוך הבא $1!</b>, חשבונך נפתח. אל תשכח להתאים את הגדרות המשתמש שלך.",
+"loginpagetitle" => "כניסת משתמש",
+"yourname"             => "שם משתמש",
+"yourpassword" => "סיסמא",
+"yourpasswordagain" => "הקש סיסמא שנית",
+"newusersonly" => " (רק אם את/ה משתמש חדש)",
+"remembermypassword" => "זכור את הסיסמא שלי בפעם הבאה.",
+"loginproblem" => "<b>ארעה שגיאה בכניסה לאתר. </b><br />!נסה שנית",
+"alreadyloggedin" => "<strong> משתמש $1, כבר ביצעת כניסה לאתר!</strong><br />\n",
+
+"login"                        => "כניסה לחשבון",
+"userlogin"            => "כניסה לחשבון",
+"logout"               => "יציאה מהחשבון",
+"userlogout"   => "יציאה מהחשבון",
+"notloggedin"  => "לא בחשבון",
+"createaccount"        => "צור משתמש חדש",
+"badretype"            => "הסיסמאות שהזנת אינן מתאימות.",
+"userexists"   => "שם המשתמש שבחרת נמצא בשימוש. אנא בחר/י שם אחר.",
+"youremail"            => "כתובת הדואר האלקטרוני שלך",
+"yournick"             => "בחר כינוי (לחתימות)",
+"emailforlost" => "אם תשכח/י את סיסמתך, תוכל/י לבקש שסיסמא חדשה תשלח לך לכתובת הדואר האלקטרוני.",
+"loginerror"   => "שגיאה בכניסה לאתר",
+"noname"               => "לא הזנת שם משתמש חוקי",
+"loginsuccesstitle" => "הכניסה הצליחה",
+"loginsuccess" => "נכנסת לויקיפדיה בשם \"$1\".",
+"nosuchuser"   => "אין משתמש בשם \"$1\".
+וודא/י שהאיות נכון, או השתמש/י בטופס שלהלן ליצור חשבון משתמש חדש.",
+"wrongpassword"        => "הסיסמא שהקלדת שגויה. אנא נסה/י שנית.",
+"mailmypassword" => "שלחו לי סיסמא חדשה",
+"passwordremindertitle" => "תזכורת סיסמא מויקיפדיה",
+"passwordremindertext" => "מישהו (ככה\"נ את/ה, מכתובת IP מספר $1) ביקש/ה שנשלח לך סיסמת ויקיפדיה חדשה.
+הסיסמא עבור משתמש \"$2\" היא עתה \"$3\".
+עליך להכנס לאתר ולשנות את סיסמתך בהקדם האפשרי.",
+"noemail"              => "לא רשומה כתובת דואר אלקטרוני עבור משתמש  \"$1\".",
+"passwordsent" => "סיסמא חדשה נשלחה לכתובת הדואר האלקטרוני הרשומה עבור \"$1\".
+אנא הכנס חזרה לאתר אחרי שתקבל אותה.",
+
+# Edit pages
+#
+"summary"              => "תקציר",
+"minoredit"            => "זהו שינוי משני",
+"watchthis"            => "עקוב אחר דף זה",
+"savearticle"  => "שמור דף",
+"preview"              => "תצוגה מקדימה",
+"showpreview"  => "הראה תצוגה מקדימה",
+"blockedtitle" => "המשתמש חסום",
+"blockedtext"  => "שם המשתמש או כתובת ה-IP שלך נחסמו על-ידי $1.
+הסיבה שניתנה היא:<br />''$2''<p>אתה יכול ליצור קשר עם $1 או אחד מ[[ויקיפדיה:מפעילי_מערכת]] כדי לדון בחסימה.",
+"newarticle"   => "(חדש)",
+"newarticletext" => "כתוב כאן את הטקסט עבור הדף החדש:",
+"anontalkpagetext" => " ---- ''זהו דף שיחה של משתמש/ת שאין לו/ה חשבון במערכת ומזוהה רק לפי כתובת ה-IP שלו/ה. יתכן ודף זה ישותף עם משתמשים אנונימיים אחרים''",
+"noarticletext" => "(אין עדיין טקסט בדף זה)",
+"updated"              => "(מעודכן)",
+"note"                 => "<strong>הערה:</strong>",
+"previewnote"  => "זכור שזו רק תצוגה מקדימה, והדף עדיין לא נשמר!",
+"previewconflict" => "תצוגה מקדימה זו מציגה כיצד יראה הטקסט בחלון העריכה העליון אם תבחר לשמור אותו.",
+"editing"              => "עורך את $1",
+"editconflict" => "התנגשות עריכה: $1",
+"explainconflict" => "משתמש אחר שינה את הדף מאז שהתחלת לערוך אותו.
+חלון העריכה העליון מכיל את הטקסט בדף כפי שהוא עתה.
+השינויים שלך מוצגים בחלון העריכה התחתון.
+עליך למזג את שינוייך לתוך הטקסט הקיים.
+<b>רק</b> הטקסט בחלון העריכה העליון ישמר כשתלחץ על \"שמור\".",
+"yourtext"             => "הטקסט שלך",
+"storedversion" => "גירסה שמורה",
+"editingold"   => "<strong>זהירות: את/ה עורך/ת גירסה לא עדכנית של הדף הזה.
+אם תשמור/י, כל השינויים שנעשו מאז גירסה זו יאבדו. </strong>",
+"yourdiff"             => "הבדלים",
+"copyrightwarning" => "אנא שים/י לב שכל תרומה לויקיפידיה מוצאת לאור תחת הרשיון לשימוש חופשי במסמכים של GNU (ראה $1 לפרטים). אם אינך רוצה שעבודתך תהיה זמינה לעריכה על ידי אחרים, ותופץ לעיני כל, אל תפרסם/י אותה פה. כמו-כן, את/ה מבטיח/ה לנו כי את/ה כתבת את הטקסט הזה בעצמך, או העתקת אותו ממקור שאינו מוגן על-ידי זכויות יוצרים.
+<strong> אל תעשו שימוש בחומר המוגן בזכויות יוצרים ללא רשות! </strong>",
+"longpagewarning" => "<strong>אזהרה: גודל דף זה הוא $1 קילובייט. בדפדפנים מסוימים יהיו בעיות בעריכת דף הגדול מ32 קילובייט. אנא שיקלו לחלק דף זה לדפים קטנים יותר</strong>",
+"readonlywarning" => "<strong>אזהרה: בסיס-הנתונים ננעל לצורך תחזוקה. אי אפשר לשמור את העריכות בזמן זה. אתם יכולים להשתמש בעורך חיצוני עד שתסוים התחזוקה. אנו מתנצלים על התקלה.</strong>",
+"protectedpagewarning" => "<strong>אזהרה: דף זה הוא דף מוגן וניתן לעריכה רק על ידי מפעילים, אנא ודאו שאתם פועלים לפי העקרונות לעריכת דפים אלו</strong>",
+
+
+# History pages
+#
+"revhistory"   => "היסטוריית שינויים",
+"nohistory"            => "אין היסטוריית שינויים עבור דף זה",
+"revnotfound"  => "גירסה זו לא נמצאה",
+"revnotfoundtext" => "הגירסה הישנה של דף זה לא נמצאה. אנא בדוק/י את כתובת הקישור \n",
+"loadhist"             => "טוען את היסטוריית השינויים של הדף",
+"currentrev"   => "גירסה נוכחית",
+"revisionasof" => "גירסה מתאריך $1",
+"cur"                  => "נוכ",
+"next"                 => "הבא",
+"last"                 => "אחרון",
+"orig"                 => "מקור",
+"histlegend"   => "מקרא: (נוכ) = הבדלים עם הגירסה הנוכחית, (אחרון) = הבדלים עם הגירסה הקודמת, מ = שינוי משני",
+
+# Diffs
+#
+"difference"   => "(הבדלים בין גירסאות)",
+"loadingrev"   => "טוען גירסה להצגת הבדלים",
+"lineno"               => "שורה $1:",
+"editcurrent"  => "ערוך גירסה נוכחית של הדף",
+
+# Search results
+#
+"searchresults" => "תוצאות חיפוש",
+
+"searchresulttext" => "למידע נוסף על חיפוש בויקיפדיה, ראה [[ויקיפדיה:חיפוש|חיפוש בויקיפדיה]].",
+"searchquery"  => "לחיפוש \"$1\"",
+"badquery"             => "שגיאה בניסוח שאילתא.",
+"badquerytext" => " לא הצלחנו לבצע את השאילתא. ככל הנראה כיוון שניסית לחפש מילה בעלת פחות משלוש אותיות. חיפוש כזה עדיין אינו נתמך במערכת. יתכן גם ששגית בהקלדת השאילתא לדוגמה \"דג וגם וגם משקל\".
+אנא נסה שאילתא אחרת.",
+"matchtotals"  => "לחיפוש \"$1\" נמצאו $2 מאמרים עם כותרות תואמות ו$3 מאמרים עם תוכן תואם",
+"titlematches" => "כותרות מאמרים תואמות",
+"notitlematches" => "אין כותרות מאמרים תואמות",
+"textmatches"  => "מאמרים עם תוכן תואם",
+"notextmatches"        => "אין מאמרים עם תוכן תואם",
+"prevn"                        => "$1 הקודמים",
+"nextn"                        => "$1 הבאים",
+"viewprevnext" => "צפה ב - ($1) ($2) ($3).",
+"showingresults" => "מציג <b>$1</b> תוצאות ממספר #$2:",
+"showingresultsnum" => "מציג <b>$1</b> תוצאות ממספר #$2:",
+"nonefound"            => "לא נמצאו מאמרים עם תוכן תואם, אנא ודאו שהיקשתם את החיפוש נכונה. אם אכן הקשתם נכונה אז נסו אולי לחפש נושא כללי יותר.",
+"powersearch" => "חפש",
+"powersearchtext" => "
+חפש במרחבי שם:<br />
+$1<br />
+$2 הצג גם דפי הפנייה
+$3 $9",
+"blanknamespace" => "(ראשי)",
+
+
+# Preferences page
+#
+"preferences"  => "העדפות",
+"prefsnologin" => "לא נרשמת באתר",
+"prefsnologintext"     => "עליך להיכנס לחשבון כדי לשנות העדפות משתמש",
+"prefslogintext" => "נכנסת בשם \"$1\", מספרך הסידורי הוא $2.",
+"prefsreset"   => "העדפותיך שוחזרו מברירת המחדל.",
+"qbsettings"   => "הגדרות סרגל מהיר",
+"changepassword" => "שנה סיסמא",
+"skin"                 => "רקע",
+"math"                 => "תצוגת נוסחאות מתמטיות",
+"math_failure"         => "עיבוד הנוסחה נכשל",
+"math_unknown_error"   => "שגיאה לא ידועה",
+"math_unknown_function"        => "פונקציה לא מוכרת",
+"math_lexing_error"    => "שגיאת לקסינג",
+"math_syntax_error"    => "שגיאת תחביר",
+"saveprefs"            => "שמור העדפות",
+"resetprefs"   => "שחזר ברירת מחדל",
+"oldpassword"  => "סיסמא ישנה",
+"newpassword"  => "סיסמא חדשה",
+"retypenew"            => "הקלד סיסמא חדשה שנית",
+"textboxsize"  => "גודל תיבת טקסט",
+"rows"                 => "שורות",
+"columns"              => "עמודות",
+"searchresultshead" => "הגדרות לתוצאות החיפוש",
+"resultsperpage" => "מס' תוצאות בעמוד",
+"contextlines" => "שורות לכל תוצאה",
+"contextchars" => "מס' תווי קונטקסט בשורה",
+"stubthreshold" => "סף להצגת מאמרים קצרים (קצרמרים)",
+"recentchangescount" => "מס' שינויים שיוצגו בדף שינויים אחרונים",
+"savedprefs"   => "העדפותיך נשמרו.",
+"timezonetext" => "הפרש השעות בינך לבין השרת (UTC).",
+"localtime"    => "זמן מקומי",
+"timezoneoffset" => "הפרש",
+"servertime"   => "השעה הנוכחית בשרת היא",
+"guesstimezone" => "מלא מהדפדפן",
+"emailflag"            => "הסתר כתובת דואר-אלקטרוני ממשתמשים אחרים.",
+
+# Recent changes
+#
+"changes" => "שינויים",
+"recentchanges" => "שינויים אחרונים",
+"recentchangestext" => "עקבו אחר השינויים האחרונים בויקיפדיה בדף זה.",
+"rcloaderr"            => "טוען שינויים אחרונים",
+"rcnote"               => "להלן <b>$1</b> השינויים האחרונים שבוצעו ב-$2 הימים האחרונים:",
+"rcnotefrom"   => "להלן <b>$1</b> השינויים האחרונים שבוצעו החל מתאריך <b>$2</b>:",
+"rclistfrom"   => "הצג שינויים חדשים החל מ-$1",
+# "rclinks"            => "הצג $1 שינויים אחרונים ב-$2 השעות האחרונות / $3 הימים האחרונים",
+"rclinks"              => "הצג $1 שינויים אחרונים ב-$2 הימים האחרונים.",
+"rchide"               => "ב-$4 טפסים; $1 שינויים משניים; $2 מרחבי שמות מיוחדים; $3 שינויים כפולים.",
+"diff"                 => "הבדל",
+"hist"                 => "היסטוריה",
+"hide"                 => "הסתר",
+"show"                 => "הצג",
+"tableform"            => "טבלה",
+"listform"             => "רשימה",
+"nchanges"             => "$1 שינויים",
+"minoreditletter" => "מ",
+"newpageletter" => "ח",
+
+# Upload
+#
+"upload"               => "העלה קובץ לשרת",
+"uploadbtn"            => "העלה קובץ",
+"uploadlink"   => "העלה תמונות",
+"reupload"             => "העלה שנית",
+"reuploaddesc" => "חזור לטופס העלאת קבצים לשרת.",
+"uploadnologin" => "לא נכנסת לאתר",
+"uploadnologintext"    => "עליך להיכנס לחשבון במערכת כדי להעלות קובץ",
+"uploaderror"  => "שגיאה בהעלאת הקובץ",
+"uploadtext"   => "'''עצור!''' לפני שאתה מעלה קובץ אנא וודא שקראת ופעלת לפי נהלי השימוש בתמונות של ויקיפדיה.
+
+השתמש בטופס שלהלן להעלות קובץ תמונה חדש לשימוש במאמר שלך.
+במרבית הדפדנים תראה כפתור \"Browse...\", שיפתח את חלון פתיחת הקבצים הסטנדרטי של מערכת ההפעלה שלך.
+בחירת קובץ תציג את שמו בשדה הטקסט שליד הכפתור.
+עליך גם לסמן את התיבה בה אתה מצהיר שאינך מפר זכויות יוצרים בהעלתך את הקובץ לשרת.
+לחץ על כפתור \"העלה קובץ\" כדי לסיים את ההעלאה.
+התהליך עלול לקחת זמן מה אם אתה גולש בקישור אינטרנט איטי.
+
+הפורמט המועדף הוא JPEG לתצלומים, PNG לאיורים, שרטוטים וסמלים, ו-OGG לקבצי קול.
+
+אנא תן לקובץ שם המייצג היטב את תוכנו כדי למנוע בלבול.
+כדי לכלול את התמונה במאמר, צור קישור מסוג
+'''<nowiki>[[image:file.jpg]]</nowiki>''' או '''<nowiki>[[image:file.png|alt text]]</nowiki>'''
+או '''<nowiki>[[media:file.ogg]]</nowiki>''' לקבצי קול.
+
+שימו לב בבקשה שבדומה לדפי ויקיפדיה אחרים, אחרים רשאים לערוך או למחוק קבצים שהעלית לשרת אם הם/ן חושבים/ות שהדבר משרת את האנציקלופדיה. ושאת/ה עלול להחסם מלבצע העלאות קבצים אם תעשה פעולות לא חוקיות כנגד המערכת.",
+"uploadlog"            => "יומן העלאות קבצים",
+"uploadlogpage" => "יומן_העלאות",
+"uploadlogpagetext" => "להלן רשימה של העלאות הקבצים האחרונות שבוצעו.
+כל הזמנים לפי שעון השרת (UTC).
+<ul>
+</ul>
+",
+"filename"             => "שם הקובץ",
+"filedesc"             => "תקציר",
+"copyrightpage" => "ויקיפדיה:זכויות_יוצרים",
+"copyrightpagename" => "זכויות היוצרים של ויקיפדיה",
+"uploadedfiles"        => "קבצים שהועלו",
+"ignorewarning"        => "התעלם מהאזהרה ושמור את הקובץ בכל זאת.",
+"minlength"            => "שמות של קובצי תמונה צריכים להיות בני שלושה תווים לפחות.",
+"badfilename"  => "שם התמונה שונה ל - \"$1\".",
+"badfiletype"  => "\".$1\" אינו פורמט מומלץ לשמירת תמונות.",
+"largefile"            => "מומלץ שגודל התמונה לא יחרוג מ-100 קילובייט.",
+"successfulupload" => "העלאת הקובץ הצליחה",
+"fileuploaded" => "הקובץ \"$1\" הועלה לשרת בהצלחה. אנא השתמש/י בקישור זה: ($2) כדי לעבור לדף התיאור והזן/י בו פרטים אודות הקובץ כדוגמת: מהיכן הגיע, מתי נוצר ועל ידי מי, וכל פרט אחר שאת/ה יודע/ת לגביו. תודה.",
+"uploadwarning" => "אזהרת העלאת קבצים",
+"savefile"             => "שמור קובץ",
+"uploadedimage" => "העלתי את הקובץ \"[[$1]]\"",
+
+# Image list
+#
+"imagelist"            => "רשימת תמונות",
+"imagelisttext"        => "להלן רשימה של $1 תמונות, ממוינות $2:",
+"getimagelist" => "מושך את רשימת התמונות",
+"ilsubmit"             => "חפש",
+"showlast"             => "הצג $1 תמונות אחרונות ממוינות $2",
+"byname"               => "לפי שם",
+"bydate"               => "לפי תאריך",
+"bysize"               => "לפי גודל",
+"imgdelete"            => "מחק",
+"imgdesc"              => "תיאור",
+"imglegend"            => "מקרא: (תיאור) הצג/ערוך תיאור התמונה.",
+"imghistory"   => "היסטורית קובץ תמונה",
+"revertimg"            => "חזור",
+"deleteimg"            => "מחק",
+"deleteimgcompletely"          => "מחק",
+"imghistlegend" => "מקרא (נוכ) = זו התמונה הנוכחית, (מחק) = מחק גירסה ישנה זו, (חזור) חזור לגירסה ישנה זו.
+<br /><i>הקש על תאריך לראות את התמונה שהועלתה בתאריך זה</i>.",
+"imagelinks"   => "קישורי תמונות",
+"linkstoimage" => "הדפים הבאים משתמשים בתמונה זו:",
+"nolinkstoimage" => "אין דפים המשתמשים בתמונה זו.",
+
+# Statistics
+#
+"statistics"   => "סטטיסטיקות",
+"sitestats"            => "סטטיסטיקות האתר",
+"userstats"            => "סטטיסטיקות משתמשים",
+"sitestatstext" => "בבסיס-הנתונים יש <b>$1</b> דפים בסך הכל.
+אלה כוללים דפי \"שיחה\", דפים על ויקיפדיה, \"קצרמרים\", הפניות, ודפים אחרים שלא נחשבים כמאמרים אנציקלופדיים.
+אם מפחיתים את אלה, ישנם <b>$2</b> דפים שככל הנראה הינם מאמרים לכל דבר.<p>
+מאז ששודרגה התוכנה (8/7/2003) בוצעו <b>$3</b> צפיות בדפים, ו-<b>$4</b> עריכות.
+כלומר בממוצע <b>$5</b> עריכות לדף, ו-<b>$6</b> צפיות לכל עריכה.",
+"userstatstext" => "ישנם <b>$1</b> משתמשים רשומים.
+<b>$2</b> מתוכם הם מפעילי מערכת (ראה $3).",
+
+# Maintenance Page
+#
+"maintenance"          => "דף תחזוקה",
+"maintnancepagetext"   => "דף זה מכיל מספר כלים שימושים לתחזוקה יומיומית. חלק מהפעולות הללו מעלות מאוד את העומס על בסיס-הנתונים. אנו מבקשים שלא תרעננו את הדף לאחר כל תיקון שאתם מבצעים ;-)",
+"maintenancebacklink"  => "חזרה לדף התחזוקה",
+"disambiguations"      => "דפי רב-משמעות",
+"disambiguationspage"  => "ויקיפדיה:דפי_רב_משמעות",
+"disambiguationstext"  => "המאמרים שלהלן מצביעים אל <i>דפי רב-משמעות</i>. תפקיד דפים אלה הוא להפנות לדף הנושא הרלוונטי.<br />אנו מתייחסים לדף כרב-משמעות אם מצביע אליו $1.<br />קישורים המגיעים אל דף ממרחבי שם אחרים <i>אינם</i> מוצגים כאן.",
+"doubleredirects"      => "הפניות כפולות",
+"doubleredirectstext"  => "<b>שים לב:</b> רשימה זו עלולה לכלול דפים שנמצאו בטעות. זאת אומרת, שבדפים שנמצאו ישנו טקסט נוסף עם קישורים מתחת ל-#REDIRECT הראשון.<br />\nכל שורה מכילה קישור להפנייה הראשונה והשנייה, וכן את שורת הטקסט הראשונה של ההפניה השניה, שלרוב נמצא בה היעד האמיתי של ההפניה, אליו אמורה ההפניה הראשונה להצביע.",
+"brokenredirects"      => "הפניות לא תקינות",
+"brokenredirectstext"  => "ההפניות שלהלן מצביעות למאמרים שאינם קיימים:",
+"selflinks"            => "דפים המקושרים לעצמם",
+"selflinkstext"                => "הדפים שלהלן מקושרים אל עצמם, הם לא אמורים לעשות זאת.",
+"mispeelings"           => "דפים עם שגיאות כתיב",
+"mispeelingstext"               => "בדפים הבאים קיימות שגיאות כתיב נפוצות, רשימה של שגיאות אלו נמצאת ב-$1. הכתיב הנכון עשוי להיות מוצג (כך).",
+"mispeelingspage"       => "רשימת שגיאות כתיב נפוצות",
+"missinglanguagelinks"  => "קישורים חסרים בין שפות",
+"missinglanguagelinksbutton"    => "מצא קישורי שפה חסרים עבור",
+"missinglanguagelinkstext"      => "מאמרים אלו <i>לא</i> מקושרים למאמרים הדומים להם ב-$1. הפניות, ותתי-דפים <i>אינם</i> מוצגים.",
+
+
+# Miscellaneous special pages
+#
+"orphans"              => "מאמרים יתומים",
+"lonelypages"  => "מאמרים יתומים",
+"unusedimages" => "תמונות לא משומשות",
+"popularpages" => "מאמרים פופולריים",
+"nviews"               => "$1 צפיות",
+"wantedpages"  => "דפים מבוקשים",
+"nlinks"               => "$1 קישורים",
+"allpages"             => "כל הדפים",
+"randompage"   => "מאמר אקראי",
+"shortpages"   => "מאמרים קצרים",
+"longpages"            => "מאמרים ארוכים",
+"listusers"            => "רשימת משתמשים",
+"specialpages" => "דפים מיוחדים",
+"spheading"            => "דפים מיוחדים",
+"protectpage"  => "הפוך דף למוגן",
+"recentchangeslinked" => "שינויים בדפים המקושרים",
+"rclsub"               => "(לדפים המקושרים מ-\"$1\")",
+"debug"                        => "נפה שגיאות",
+"newpages"             => "מאמרים חדשים",
+"movethispage" => "העבר דף זה",
+"unusedimagestext" => "<p>שים לב בבקשה שאתרים אחרים כדוגמת
+ויקיפדיות בשפות אחרות עשויות לבצע קישור לתמונה באמצעות הפניה ישירה לכתובתה, ולכן עלולות להופיע כאן תמונות שנמצאות בשימוש שותף.",
+"booksources"  => "משאבי ספרות חיצוניים",
+"booksourcetext" => "להלן רשימה של קישורים לאתרים אחרים המוכרים ספרים חדשים ויד-שניה, ושבהם עשוי להיות מידע נוסף לגבי ספרים שאת/ה מחפש/ת. לויקיפדיה אין קשר לעסקים אלה, ואין לראות ברשימה זו המלצה, פרסום או עידוד לעשות שימוש באתרים אלו ספציפית.",
+
+# Email this user
+
+#
+"mailnologin"  => "אין כתובת לשליחה",
+"mailnologintext" => "עליך להיכנס לחשבון ולהגדיר לעצמך כתובת דואר אלקטרוני תקינה (בהעדפות המשתמש) כדי לשלוח דואר למשתמש אחר.",
+"emailuser"            => "שלח דואר-אלקטרוני למשתמש זה",
+"emailpage"            => "שלח דואר למשתמש",
+"emailpagetext"        => "אם המשתמש הזין כתובת דואר-אלקטרוני חוקית בהעדפותיו האישיות, הטופס שלהלן ישלח אליו הודעת דואר אחת. כתובת הדואר האלקטרוני שהזנת בהעדפותיך האישיות תופיע בשדה ה-\"מאת\" של הדואר כדי שהמשתמש יוכל לענות.",
+"noemailtitle" => "אין כתובת דואר-אלקטרוני",
+"noemailtext"  => "משתמש זה לא הזין כתובת דואר-אלקטרוני חוקית או בחר שלא לקבל דואר אלקטרוני ממשתמשים אחרים.",
+"emailfrom"            => "מאת",
+"emailto"              => "אל",
+"emailsubject" => "נושא",
+"emailmessage" => "הודעה",
+"emailsend"            => "שלח",
+"emailsent"            => "הדואר נשלח",
+"emailsenttext" => "הודעת הדואר האלקטרוני שלך נשלחה.",
+
+# Watchlist
+#
+"watchlist"            => "רשימת המעקב שלי",
+"watchlistsub" => "(עבור משתמש \"$1\")",
+"nowatchlist"  => "אין לך דפים ברשימת המעקב.",
+"watchnologin" => "לא נכנסת לאתר",
+"watchnologintext"     => "כדי לערוך את רשימת המעקב, עליך להיכנס לחשבון במערכת",
+"addedwatch"   => "הדף הוסף לרשימת המעקב",
+"addedwatchtext" => "הדף הוסף לרשימת המעקב. הוא יפויע ברשימת המעקב שלך וגם יהיה מודגש בדף שינויים אחרונים.
+<p>אם ברצונך להסיר את הדף מרשימת המעקב, לחץ/י על \"הפסק לעקוב\" ברשימה שבצד הדף.",
+"removedwatch" => "הדף הוסר מרשימת המעקב",
+"removedwatchtext" => "הדף \"$1\" הוסר מרשימת המעקב שלך.",
+"watchthispage"        => "עקוב אחר דף זה",
+"unwatchthispage" => "הפסק לעקוב",
+"notanarticle" => "זהו אינו מאמר",
+
+# Delete/protect/revert
+#
+"deletepage"   => "מחק דף",
+"confirm"              => "אשר",
+"excontent" => "תוכן היה: '$1'",
+"exbeforeblank" => "תוכן לפני שהורק היה: '$1'",
+"exblank" => "הדף היה ריק",
+"confirmdelete" => "אשר מחיקת הדף",
+"deletesub"            => "(מוחק את \"$1\")",
+"historywarning" => "אזהרה! לדף זה שהינך עומד/ת למחוק יש היסטוריית שינויים:",
+
+"confirmdeletetext" => "אתה עומד למחוק דף או תמונה יחד עם כל ההיסטוריה שלה מבסיס-הנתונים.
+אנא אשר שאכן זה מה שאתה מתכוון לעשות, ושאתה מבין את התוצאות של מעשה כזה, ושאתה מבצע אותו בהתאם ל[[ויקיפדיה:נהלים]].",
+"actioncomplete" => "הפעולה בוצעה",
+"deletedtext"  => "\"$1\" נמחק.
+ראה $2 לרשימת המחיקות האחרונות.",
+"deletedarticle" => "מחקתי את \"$1\"",
+"dellogpage"   => "יומן_מחיקות",
+"dellogpagetext" => "להלן רשימה של המחיקות האחרונות שבוצעו.
+כל הזמנים המוצגים עם לפי שעון השרת (UTC).
+
+<ul>
+</ul>
+",
+"deletionlog"  => "יומן מחיקות",
+"reverted"             => "שוחזר לגירסה קודמת",
+"deletecomment"        => "סיבת המחיקה",
+"imagereverted" => "שיחזור לגירסה קודמת הצליח.",
+"rollback"             => "גלגל עריכות אחורנית",
+"rollbacklink" => "גלגל אחורנית",
+"cantrollback" => "לא יכול לגלגל אחורנית, הגירסה הראשונה של דף זה נכתבה על ידי משתמש זה",
+"revertpage"   => "שוחזר לעריכה אחרונה על ידי $1",
+
+# Undelete
+"undelete" => "שחזר דף מחוק",
+"undeletepage" => "צפה ושחזר דפים מחוקים",
+"undeletepagetext" => "הדפים שלהלן נמחקו אך עדיין בארכיון ואפשר לשחזר אותם. הארכיון מנוקה מעת לעת.",
+"undeletearticle" => "שחזר מאמר מחוק",
+"undeleterevisions" => "$1 גירסאות נשמרו בארכיון",
+"undeletehistory" => "אם תשחזר את הדף, כל הגירסאות ישוחזרו בדף ההיסטוריה שלו.
+אם כבר יש דף חדש באותו שם, הגירסאות והשינויים יופיעו בהיסטוריה קודמת, והגירסה הנוכחית לא תוחלף אוטומטית.",
+"undeleterevision" => ".מחקתי גירסאות החל מ-$1",
+"undeletebtn" => "שחזר!",
+"undeletedarticle" => "\"$1\" שוחזר",
+"undeletedtext"   => "המאמר [[$1]] שוחזר בהצלחה.
+ראה את [[ויקיפדיה:יומן_מחיקות]] לרשימה של מחיקות ושיחזורים אחרונים.",
+
+# Contributions
+#
+"contributions"        => "תרומות המשתמש",
+"mycontris" => "התרומות שלי",
+"contribsub"   => "עבור $1",
+"nocontribs"   => "לא נמצאו שינויים המתאימים לקריטריונים אלו.",
+"ucnote"               => "להלן <b>$1</b> השינויים האחרונים שביצע משתמש זה ב-<b>$2</b> הימים האחרונים:",
+"uclinks"              => "צפה ב-$1 השינויים האחרונים; צפה ב-$2 הימים האחרונים",
+"uctop"                => "(אחרון)" ,
+
+# What links here
+#
+"whatlinkshere"        => "דפים המקושרים לכאן",
+"notargettitle" => "אין דף מטרה",
+"notargettext" => "לא ציינת דף מטרה או משתמש לגביו תבוצע פעולה זו.",
+"linklistsub"  => "(רשימת קישורים)",
+"linkshere"            => "הדפים שלהלן מקושרים לכאן:",
+"nolinkshere"  => "אין דפים המקושרים לכאן.",
+"isredirect"   => "דף הפנייה",
+
+# Block/unblock IP
+#
+"blockip"              => "חסום כתובת IP",
+"blockiptext"  => "השתמש בטופס שלהלן בכדי לחסום הרשאות כתיבה מכתובת IP ספציפית.
+חסימת משתמש צריכה להתבצע אך ורק בכדי למנוע ונדליזם, ובהתאם ל-[[ויקיפדיה:נהלים]]. פרט את הסיבה הספציפית למטה. (לדוגמה - ציין דפים ספציפיים שהושחתו על ידי המשתמש)",
+"ipaddress"            => "כתובת IP",
+"ipbreason"            => "סיבה",
+"ipbsubmit"            => "חסום כתובת זו",
+"badipaddress" => ".כתובת ה-IP אינה כתובה נכון",
+"blockipsuccesssub" => "החסימה הצליחה",
+"blockipsuccesstext" => "הכתובת \"$1\" נחסמה.
+<br />ראה את [[מיוחד:רשימת כתובות IP חסומות|רשימת הכתובות החסומות]] כדי לצפות בחסימות",
+"unblockip"            => "שחרר כתובת IP",
+"unblockiptext"        => "השתמש בטופס שלהלן בכדי להחזיר הרשאות כתיבה לכתובת IP חסומה.",
+"ipusubmit"            => "שחרר כתובת זו",
+"ipusuccess"   => "הכתובת \"$1\" שוחררה",
+"ipblocklist"  => "רשימת כתובות IP חסומות",
+"blocklistline"        => "$1, $2 חסם את $3 ($4)",
+"blocklink"            => "חסום",
+"unblocklink"  => "שחרר חסימה",
+"contribslink" => "תרומות המשתמש",
+
+# Developer tools
+#
+"lockdb"               => "נעל בסיס-נתונים",
+"unlockdb"             => "שחרר בסיס-נתונים מנעילה",
+"lockdbtext"   => "נעילת בסיס-הנתונים תמנע ממשתמשים את האפשרות לערוך דפים, לשנות את העדפותיהם, את רשימות המעקב שלהם, ופעולות אחרות הדורשות ביצוע שינויים בבסיס-הנתונים
+אנא אשר/י שזה מה שאת/ה מתכוון/ת לעשות, ושתשחרר/י את בסיס-הנתונים מנעילה כאשר פעולת התחזוקה תסתיים.",
+"unlockdbtext" => "שחרור בסיס-הנתונים מנעילה יחזיר למשתמשים את היכולת לערוך דפים, לשנות את העדפותיהם, לערוך את רשימות המעקב שלהם, ולבצע פעולות אחרות הדורשות ביצוע שינויים בבסיס-הנתונים
+אנא אשר/י שזה מה שבכוונתך לעשות.",
+"lockconfirm"  => "כן, אני באמת רוצה לנעול את בסיס-הנתונים.",
+"unlockconfirm"        => "כן, אני באמת רוצה לשחרר את בסיס-הנתונים מנעילה.",
+"lockbtn"              => "נעל בסיס-נתונים",
+"unlockbtn"            => "שחרר בסיס-נתונים מנעילה",
+"locknoconfirm" => "לא סימנת את תיבת האישור.",
+"lockdbsuccesssub" => "נעילת בסיס-הנתונים הצליחה",
+"unlockdbsuccesssub" => "שוחררה הנעילה מבסיס-הנתונים",
+"lockdbsuccesstext" => "בסיס-הנתונים של ויקיפדיה ננעל.
+<br />זכור לשחרר את הנעילה לאחר שפעולת התחזוקה הסתיימה.",
+"unlockdbsuccesstext" => "שוחררה הנעילה מבסיס-הנתונים של ויקיפדיה",
+
+# Move page
+#
+"movepage"             => "העבר דף",
+"movepagetext" => "שימוש בטופס שלהלן ישנה את שמו של דף, ויעביר את כל ההיסטוריה שלו לשם חדש.
+השם הישן יהפוך לדף הפניה אל הדף עם השם החדש.
+קישורים לשם הישן לא ישונו, וודא/י לבצע [[מיוחד:תחזוקה|בדיקה]] שאין הפניות כפולות, או מקולקלות.
+את/ה אחראי/ת לוודא שכל הקישורים ממשיכים להצביע למקום שאליו הם אמורים להצביע.
+
+שים/י לב: הדף '''לא''' יועבר אם כבר יש דף תחת השם החדש, אלא אם הדף הזה ריק, או שהוא הפנייה, ואין לו היסטוריה של שינויים. משמעות הדבר, שאפשר לשנות חזרה את שמו של דף לשם המקורי, אם נעשתה טעות, ולא ימחק דף קיים במערכת.
+
+<b>אזהרה!</b>
+שינוי זה עשוי להיות שינוי דרסטי ובלתי צפוי לדף פופולרי;
+אנא וודא/י שאת/ה מבין/ה את השלכות המעשה לפני שאת/ה ממשיך/ה.",
+"movepagetalktext" => "אם קיים לדף זה דף שיחה, הוא יועבר אוטומטית '''אלא אם:'''
+*הדף מועבר ממרחב שם אחד לשני,
+*קיים דף שיחה שאינו ריק תחת השם החדש אליו מועבר הדף, או
+*הורדת את הסימון בתיבה שלהלן.
+
+במקרים אלה, תצטרך/י להעביר או לשלב את הדפים באופן ידני אם תרצה/י.",
+"movearticle"  => "העבר דף",
+"movenologin"  => "לא נכנסת לאתר",
+"movenologintext" => "עליך להיכנס לחשבון במערכת כדי להעביר דף",
+"newtitle"             => "לשם החדש",
+"movepagebtn"  => "העבר דף",
+"pagemovedsub" => "ההעברה הצליחה",
+"pagemovedtext" => "הדף [[$1]] הועבר ל [[$2]]",
+"articleexists" => "קיים כבר דף עם אותו שם, או שהשם שבחרת אינו חוקי.
+אנא  בחר/י שם אחר.",
+"talkexists"   => "הדף עצמו הועבר בהצלחה, אבל דף השיחה לא הועבר כיוון שקיים כבר דף שיחה במיקום החדש. אנא מזג/י אותם ידנית.",
+"movedto"              => "הועבר ל",
+"movetalk"             => "העבר גם את דף השיחה, אם קיים.",
+"talkpagemoved" => "דף השיחה המשוייך הועבר גם כן.",
+"talkpagenotmoved" => "דף השיחה המשוייך <strong>לא</strong> הועבר.",
+
+# Math
+
+'mw_math_png' =>  "תמיד הצג כ-PNG",
+'mw_math_simple' => "HTML אם פשוט, אחרת PNG",
+'mw_math_html' => "HTML אם אפשר, אחרת PNG",
+'mw_math_source' => "השאר כקוד TeX",
+'mw_math_modern' => "מומלץ לדפדפנים עדכניים",
+'mw_math_mathml' => 'MathML',
+
+);
+
+class LanguageHe extends LanguageUtf8 {
+
+       function getDefaultUserOptions () {
+               $opt = Language::getDefaultUserOptions();
+               $opt["quickbar"]=2;
+               return $opt;
+       }
+
+       function getBookstoreList() {
+               global $wgBookstoreListHe ;
+               return $wgBookstoreListHe ;
+       }
+
+       function getNamespaces() {
+               global $wgNamespaceNamesHe;
+               return $wgNamespaceNamesHe;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsHe;
+               return $wgQuickbarSettingsHe;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesHe;
+               return $wgSkinNamesHe;
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesHe;
+               if(array_key_exists($key, $wgAllMessagesHe))
+                       return $wgAllMessagesHe[$key];
+               else
+                       return parent::getMessage($key);
+       }
+
+       function isRTL() { return true; }
+
+       function fallback8bitEncoding() { return "iso8859-8"; }
+
+}
+
+?>
diff --git a/languages/LanguageHi.php b/languages/LanguageHi.php
new file mode 100644 (file)
index 0000000..5270458
--- /dev/null
@@ -0,0 +1,190 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+require_once( "LanguageUtf8.php" );
+
+/* private */ $wgNamespaceNamesHi = array(
+       NS_MEDIA          => 'Media',
+       NS_SPECIAL        => 'विशेष',
+       NS_MAIN           => '',
+       NS_TALK           => 'वार्ता',
+       NS_USER           => 'सदस्य',
+       NS_USER_TALK      => 'सदस्य_वार्ता',
+       NS_PROJECT        => $wgMetaNamespace,
+       NS_PROJECT_TALK   => $wgMetaNamespace . '_वार्ता',
+       NS_IMAGE          => 'चित्र',
+       NS_IMAGE_TALK     => 'चित्र_वार्ता',
+       NS_MEDIAWIKI      => 'MediaWiki',
+       NS_MEDIAWIKI_TALK => 'MediaWiki_talk',
+       NS_TEMPLATE       => 'Template',
+       NS_TEMPLATE_TALK  => "Template_talk",
+       NS_CATEGORY       => 'श्रेणी',
+       NS_CATEGORY_TALK  => 'श्रेणी_वार्ता',
+) + $wgNamespaceNamesEn;
+
+
+/* private */ $wgAllMessagesHi = array(
+
+# Dates
+#
+'sunday' => "रविवार",
+'monday' => "सोमवार",
+'tuesday' => "मंगलवार",
+'wednesday' => "बुधवार",
+'thursday' => "गुरुवार",
+'friday' => "शुक्रवार",
+'saturday' => "शनिवार",
+'january' => "जनवरी",
+'february' => "फरवरी",
+'march' => "मार्च",
+'april' => "अप्रैल",
+'may_long' => "मई",
+'june' => "जून",
+'july' => "जुलाई",
+'august' => "अगस्त",
+'september' => "सितम्बर",
+'october' => "अक्टूबर",
+'november' => "नवम्बर",
+'december' => "दिसम्बर",
+'jan' => "जनवरी",
+'feb' => "फरवरी",
+'mar' => "मार्च",
+'apr' => "अप्रैल",
+'may' => "मई",
+'jun' => "जून",
+'jul' => "जुलाई",
+'aug' => "अगस्त",
+'sep' => "सितम्बर",
+'oct' => "अक्टूबर",
+'nov' => "नवम्बर",
+'dec' => "दिसम्बर",
+
+# Bits of text used by many pages:
+#
+"linktrail"            => "/^([a-z]+)(.*)\$/sD",
+"mainpage"             => "मुख्य पृष्ठ",
+"about"                        => "अबाउट",
+"aboutsite"             => "विकिपीडिया के बारे में",
+"aboutpage"            => "विकिपीडिया:अबाउट",
+"help"                 => "सहायता",
+"helppage"             => "विकिपीडिया:सहायता",
+"bugreports"           => "Bug reports",
+"bugreportspage"        => "विकिपीडिया:Bug_reports",
+"faq"                  => "FAQ",
+"faqpage"              => "विकिपीडिया:FAQ",
+"edithelp"             => "Editing help",
+"edithelppage"         => "विकिपीडिया:How_does_one_edit_a_page",
+"cancel"               => "Cancel",
+"qbfind"               => "Find",
+"qbbrowse"             => "Browse",
+"qbedit"               => "Edit",
+"qbpageoptions"         => "Page options",
+"qbpageinfo"           => "Page info",
+"qbmyoptions"          => "My options",
+"mypage"               => "मेरा पृष्ठ",
+"mytalk"               => "मेरी बातें",
+"currentevents"         => "Current events",
+"errorpagetitle"        => "Error",
+"returnto"             => "लौटें $1.",
+"tagline"                      => "From Wikipedia, the free encyclopedia.",
+"whatlinkshere"                => "Pages that link here",
+"help"                 => "सहायता ",
+"search"               => "खोज ",
+"go"                   => "जायें",
+"history"              => "Older versions",
+"printableversion"      => "Printable version",
+"editthispage"         => "इस पृष्ठ को बदलें",
+"deletethispage"        => "इस पृष्ठ को हटायें",
+"protectthispage"       => "इस पृष्ठ को सुरक्षित करें",
+"unprotectthispage"     => "इस पृष्ठ को असुरक्षित करें",
+"newpage"               => "नया पृष्ठ ",
+"talkpage"             => "इस पृष्ठ के बारे में बात करें",
+"articlepage"          => "लेख देखें",
+"subjectpage"          => "विषय देखें", # For compatibility
+"userpage"              => "सदस्य पृष्ठ देखें",
+"wikipediapage"         => "मेटा पृष्ठ देखें",
+"imagepage"             => "चित्र पृष्ठ देखें",
+"viewtalkpage"          => "चर्चा देखें",
+"otherlanguages"        => "अन्य भाषायें",
+"redirectedfrom"        => "($1 से भेजा गया)",
+"lastmodified"         => "अन्तिम परिवर्तन $1.",
+"viewcount"            => "यह पृष्ठ $1 बार देखा गया है",
+"printsubtitle"         => "(From {{SERVER}})",
+"protectedpage"         => "सुरक्षित पृष्ठ",
+"administrators"        => "विकिपीडिया:प्रबन्धक",
+"sysoptitle"           => "sysop आवश्यक है",
+"sysoptext"            => "आप जो करना चाहते हैं‌ उसे केवल \"sysop\" स्तर के सदस्य कर सकते हैं. $1 देखें.",
+"developertitle"        => "Developer आवश्यक है",
+"developertext"        => "आप जो करना चाहते हैं‌ उसे केवल \"developer\" स्तर के सदस्य कर सकते हैं. $1 देखें.",
+"nbytes"               => "$1 bytes",
+"go"                   => "Go",
+"ok"                   => "OK",
+"sitetitle"            => "विकिपीडिया ",
+"sitesubtitle"         => "निःशुल्क ज्ञान संग्रह ",
+"retrievedfrom"         => "\"$1\" से लिया गया",
+"newmessages"           => "आपके लिये $1 हैं.",
+"newmessageslink"       => "नये सन्देश",
+
+# Main script and global functions
+#
+"nosuchaction" => "ऐसा कोई कार्य नहीं है",
+"nosuchactiontext" => "विकिपीडिया सौफ़्टवेयर में इस URL द्वारा निर्धारित कोई क्रिया नही है",
+"nosuchspecialpage" => "ऐसा कोई विशेष पृष्ठ नहीं है",
+"nospecialpagetext" => "आपने ऐसा विशेष पृष्ठ मांगा है जो विकिपीडिया सौफ़्टवेयर में नहीं है.",
+
+# General errors
+# ........
+
+"welcomecreation" => "<h2>स्वागतम्‌, $1!</h2><p>आपका अकाउन्ट बना दिया गया है.
+Don't forget to personalize your wikipedia preferences.",
+
+"loginpagetitle" => "User login",
+"yourname"             => "आपका नाम",
+"yourpassword" => "आपका पासवर्ड ",
+"yourpasswordagain" => "पासवर्ड दुबारा लिखें",
+
+## ....... more messages .....
+);
+
+class LanguageHi extends LanguageUtf8 {
+       var $digitTransTable = array(
+               "0" => "०",
+               "1" => "१",
+               "2" => "२",
+               "3" => "३",
+               "4" => "४",
+               "5" => "५",
+               "6" => "६",
+               "7" => "७",
+               "8" => "८",
+               "9" => "९"
+       );
+
+       function getNamespaces() {
+               global $wgNamespaceNamesHi;
+               return $wgNamespaceNamesHi;
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesHi;
+               if(array_key_exists($key, $wgAllMessagesHi))
+                       return $wgAllMessagesHi[$key];
+               else
+                       return parent::getMessage($key);
+       }
+
+       function formatNum( $number ) {
+               global $wgTranslateNumerals;
+               if( $wgTranslateNumerals ) {
+                       return strtr( $number, $this->digitTransTable );
+               } else {
+                       return $number;
+               }
+       }
+
+}
+
+?>
diff --git a/languages/LanguageHu.php b/languages/LanguageHu.php
new file mode 100644 (file)
index 0000000..226a7cc
--- /dev/null
@@ -0,0 +1,1063 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+#
+# Hungarian localisation for MediaWiki
+#
+
+require_once("LanguageUtf8.php");
+
+if($wgMetaNamespace === FALSE)
+       $wgMetaNamespace = str_replace( " ", "_", $wgSitename );
+
+# suffixed project name (Wikipédia -> Wikipédiá) -- ról, ba, k
+$wgSitenameROL = $wgSitename . "ról";
+$wgSitenameBA = $wgSitename . "ba";
+$wgSitenameK = $wgSitename . "k";
+if( 0 == strcasecmp( "Wikipédia", $wgSitename ) ) {
+       $wgSitenameROL = "Wikipédiáról";
+       $wgSitenameBA  = "Wikipédiába";
+       $wgSitenameK   = "Wikipédiák";
+
+} elseif( 0 == strcasecmp( "Wikidézet", $wgSitename ) ) {
+       $wgSitenameROL = "Wikidézetről";
+       $wgSitenameBA  = "Wikidézetbe";
+       $wgSitenameK   = "Wikidézetek";
+
+} elseif( 0 == strcasecmp( "Wikiszótár", $wgSitename ) ) {
+       $wgSitenameROL = "Wikiszótárról";
+       $wgSitenameBA  = "Wikiszótárba";
+       $wgSitenameK   = "Wikiszótárak";
+
+} elseif( 0 == strcasecmp( "Wikikönyvek", $wgSitename ) ) {
+       $wgSitenameROL = "Wikikönyvekről";
+       $wgSitenameBA  = "Wikikönyvekbe";
+       $wgSitenameK   = "Wikikönyvek";
+}
+
+/* private */ $wgNamespaceNamesHu = array(
+       NS_MEDIA                        => "Média",
+       NS_SPECIAL                      => "Speciális",
+       NS_MAIN                         => "",
+       NS_TALK                         => "Vita",
+       NS_USER                         => "User",
+       NS_USER_TALK            => "User_vita",
+       NS_PROJECT                      => $wgMetaNamespace,
+       NS_PROJECT_TALK         => $wgMetaNamespace . "_vita",
+       NS_IMAGE                        => "Kép",
+       NS_IMAGE_TALK           => "Kép_vita",
+       NS_MEDIAWIKI            => "MediaWiki",
+       NS_MEDIAWIKI_TALK       => "MediaWiki_vita",
+       NS_TEMPLATE                     => "Sablon",
+       NS_TEMPLATE_TALK        => "Sablon_vita",
+       NS_HELP                         => "Segítség",
+       NS_HELP_TALK            => "Segítség_vita",
+       NS_CATEGORY                     => "Kategória",
+       NS_CATEGORY_TALK        => "Kategória_vita"
+) + $wgNamespaceNamesEn;
+
+/* Inherit default options; make specific changes via
+   custom getDefaultUserOptions() if needed. */
+
+/* private */ $wgQuickbarSettingsHu = array(
+       "Nincs", "Fix baloldali", "Fix jobboldali", "Lebegő baloldali"
+);
+
+/* private */ $wgSkinNamesHu = array(
+       'standard' => "Alap",
+       'nostalgia' => "Nosztalgia",
+       'cologneblue' => "Kölni kék"
+) + $wgSkinNamesEn;
+
+
+/* private */ $wgDateFormatsHu = array(
+#      "Mindegy",
+);
+
+/* private */ $wgAllMessagesHu = array(
+
+# User Toggles
+#
+
+"tog-underline" => "Linkek aláhúzása",
+"tog-highlightbroken" => "Törött linkek <a href=\"\" class=\"new\">így</a> (alternatíva: így<a href=\"\" class=\"internal\">?</a>).",
+"tog-justify"  => "Bekezdések teljes szélességű tördelése",
+"tog-hideminor" => "Apró változtatások elrejtése a recent changes-ben",
+"tog-usenewrc" => "Modern változások listája (nem minden böngészőre)",
+"tog-numberheadings" => "Címsorok automatikus számozása",
+"tog-showtoolbar" => "Show edit toolbar",
+"tog-editsection"=>"Linkek az egyes szakaszok szerkesztéséhez",
+"tog-editsectiononrightclick"=>"Egyes szakaszok szerkesztése a szakaszcímre klikkeléssel (Javascript)",
+"tog-showtoc"=>"Három fejezetnél többel rendelkező cikkeknél mutasson tartalomjegyzéket",
+"tog-rememberpassword" => "Jelszó megjegyzése a használatok között",
+"tog-editwidth" => "Teljes szélességű szerkesztőterület",
+"tog-editondblclick" => "Lapon duplakattintásra szerkesztés (JavaScript)",
+"tog-watchdefault" => "Figyelje az új és a megváltoztatott cikkeket",
+"tog-minordefault" => "Alapból minden szerkesztést jelöljön aprónak",
+"tog-previewontop" => "Előnézet a szerkesztőterület előtt és nem utána",
+"tog-nocache" => "Lapok gyorstárazásának letiltása",
+
+
+# Dates
+#
+
+'sunday' => "vasárnap",
+'monday' => "hétfő",
+'tuesday' => "kedd",
+'wednesday' => "szerda",
+'thursday' => "csütörtök",
+'friday' => "péntek",
+'saturday' => "szombat",
+'january' => "január",
+'february' => "február",
+'march' => "március",
+'april' => "április",
+'may_long' => "május",
+'june' => "június",
+'july' => "július",
+'august' => "augusztus",
+'september' => "szeptember",
+'october' => "október",
+'november' => "november",
+'december' => "december",
+'jan' => "Jan",
+'feb' => "Feb",
+'mar' => "Már",
+'apr' => "Ápr",
+'may' => "Máj",
+'jun' => "Jún",
+'jul' => "Júl",
+'aug' => "Aug",
+'sep' => "Sep",
+'oct' => "Okt",
+'nov' => "Nov",
+'dec' => "Dec",
+
+# Bits of text used by many pages:
+#
+"categories"   => "Lapkategóriák",
+"category"             => "kategória",
+"category_header" => "Cikkek a(z) \"$1\" kategóriában",
+"subcategories" => "Alkategóriák",
+"linktrail"            => "/^((?:[a-z]|á|é|í|ú|ó|ö|ü|ő|ű|Á|É|Í|Ó|Ú|Ö|Ü|Ő|Ű)+)(.*)\$/sD",
+"mainpage"             => "Kezdőlap",
+"mainpagetext" => "Wiki szoftver sikeresen telepítve.",
+"about"                        => "Névjegy",
+"aboutsite"      => "A {{SITENAME}}ROL",
+"aboutpage"            => "{{ns:project}}:Névjegy",
+"help"                 => "Segítség",
+"helppage"             => "{{ns:project}}:Segítség",
+"bugreports"   => "Hibajelentés",
+"bugreportspage" => "{{ns:project}}:Hibajelentések",
+"faq"                  => "GyIK",
+"faqpage"              => "{{ns:project}}:GyIK",
+"edithelp"             => "Segítség a szerkesztéshez",
+"edithelppage" => "{{ns:project}}:Hogyan_szerkessz_egy_lapot",
+"cancel"               => "Vissza",
+"qbfind"               => "Keresés",
+"qbbrowse"             => "Böngészés",
+"qbedit"               => "Szerkeszt",
+"qbpageoptions" => "Lapbeállítások",
+"qbpageinfo"   => "Lapinformáció",
+"qbmyoptions"  => "Beállításaim",
+"mypage"               => "Lapom",
+"mytalk"               => "Vitám",
+"currentevents" => "Friss események",
+"errorpagetitle" => "Hiba",
+"returnto"             => "Vissza a $1 cikkhez.",
+"tagline"              => "A Wikipediából, a szabad enciklopédiából.",
+"whatlinkshere"        => "Lapok, melyek ide mutatnak",
+"help"                 => "Segítség",
+"search"               => "Keresés",
+"go"                   => "Menj!",
+"history"              => "Laptörténet",
+"printableversion" => "Nyomtatható változat",
+"editthispage" => "Szerkeszd ezt a lapot",
+"deletethispage" => "Lap törlése",
+"protectthispage" => "Védelem a lapnak",
+"unprotectthispage" => "Védelem megszüntetése",
+"newpage"              => "Új lap",
+"talkpage"             => "Lap megbeszélése",
+"postcomment"  => "Üzenethagyás",
+"articlepage"  => "Szócikk megtekintése",
+"subjectpage"  => "Témalap megtekintése", # For compatibility
+"userpage"             => "Felhasználói lap",
+"wikipediapage" => "Metalap",
+"imagepage"    => "Képlap",
+"viewtalkpage" => "Beszélgetés megtekintése",
+"otherlanguages" => "Egyéb nyelvek",
+"redirectedfrom" => "(Átirányítva $1 cikkből)",
+"lastmodified" => "A lap utolsó módosítása $1.",
+"viewcount"            => "Ezt a lapot eddig $1 alkalommal látogatták.",
+"printsubtitle" => "(From {{SERVER}})",
+"protectedpage" => "Védett lap",
+"administrators" => "{{ns:project}}:Adminisztrátorok",
+"sysoptitle"   => "Sysop hozzáférés szükséges",
+"sysoptext"            => "Az általad kért tevékenységet csak \"sysopok\" végezhetik el.
+Lásd $1.",
+"developertitle" => "Developer access required",
+"developertext"        => "The action you have requested can only be
+performed by users with \"developer\" status.
+See $1.",
+"nbytes"               => "$1 byte",
+"go"                   => "Menj",
+"ok"                   => "OK",
+"sitetitle"            => "{{SITENAME}}",
+"sitesubtitle" => "A szabad enciklopédia",
+"retrievedfrom" => "Retrieved from \"$1\"",
+"newmessages"  => "$1 van.",
+"newmessageslink" => "Új üzeneted",
+"editsection"  => "szerkesztés",
+"toc"                  => "Tartalomjegyzék",
+"showtoc"              => "mutat",
+"hidetoc"              => "elrejt",
+"thisisdeleted" => "$1 megnézése vagy helyreállítása?",
+"restorelink"  => "$1 törölt szerkesztés",
+
+# Main script and global functions
+#
+"nosuchaction" => "Nincs ilyen tevékenység",
+"nosuchactiontext" => "Az URL által megadott tevékenységet a {{SITENAME}}
+software nem ismeri fel",
+"nosuchspecialpage" => "Nincs ilyen speciális lap",
+"nospecialpagetext" => "Olyan speciális lapot kértél amit a {{SITENAME}}
+software nem ismer fel.",
+
+# General errors
+#
+"error"        => "Hiba",
+"databaseerror" => "Adatbázis hiba",
+"dberrortext"  => "Adatbázis formai hiba történt.
+Az utolsó lekérési próbálkozás az alábbi volt:
+<blockquote><tt>$1</tt></blockquote>
+a \"<tt>$2</tt>\" függvényből.
+A MySQL hiba \"<tt>$3: $4</tt>\".",
+"dberrortextcl" => "Egy adatbázis lekérés formai hiba történt.
+Az utolsó lekérési próbálkozás:
+\"$1\"
+a \"$2\" függvényből történt.
+A MySQL hiba \"$3: $4\".\n",
+"noconnect"            => "Nem tudok a $1 adatbázis gépre csatlakozni",
+"nodb"                 => "Nem tudom elérni a $1 adatbázist",
+"cachederror"  => "Ez a kért cikk egy régebben elmentett példánya, lehetséges, hogy nem tartalmazza a legújabb módosításokat.",
+"readonly"             => "Adatbázis lezárva",
+"enterlockreason" => "Add meg a lezárás indoklását valamint egy becslést,
+hogy mikor kerül a lezárás feloldásra",
+"readonlytext" => "A {{SITENAME}} adatbázis jelenleg le van zárva az új
+szócikkek és módosítások elől, valószínűleg adatbázis karbantartás miatt,
+aminek a végén minden visszaáll a régi kerékvágásba.
+Az adminisztrátor aki a lezárást elvégezte az alábbi magyarázatot adta:
+<p>$1",
+"missingarticle" => "Az adatbázis nem találta meg egy létező lap szövegét,
+aminek a neve \"$1\".
+
+<p>Ennek oka általában egy olyan régi link kiválasztása, ami egy
+már törölt lap történetére hivatkozik.
+
+<p>Ha nem erről van szó akkor lehetséges, hogy programozási hibát
+találtál a software-ben. Kérlek értesíts erről egy adminisztrátort,
+és jegyezd fel neki az URL-t (pontos webcímet) is.",
+"internalerror" => "Belső hiba",
+"filecopyerror" => "Nem tudom a \"$1\" file-t a \"$2\" névre másolni.",
+"filerenameerror" => "Nem tudom a \"$1\" file-t \"$2\" névre átnevezni.",
+"filedeleteerror" => "Nem tudom a \"$1\" file-t letörölni.",
+"filenotfound" => "Nem találom a \"$1\" file-t.",
+"unexpected"   => "Váratlan érték: \"$1\"=\"$2\".",
+"formerror"            => "Hiba: nem tudom a formot elküldeni",
+"badarticleerror" => "Ez a tevékenység nem végezhető ezen a lapon.",
+"cannotdelete" => "Nem tudom a megadott lapot vagy képet törölni. (Talán már valaki más törölte.)",
+"badtitle"             => "Hibás cím",
+"badtitletext" => "A kért cím helytelen, üres vagy hibásan hivatkozik
+egy nyelvek közötti vagy wikik közötti címre.",
+"perfdisabled"         => "Bocsánat! Ez a lehetőség időszakosan nem elérhető
+mert annyira lelassítja az adatbázist, hogy senki nem tudja a
+wikit használni.",
+"perfdisabledsub" => "Íme $1 egy elmentett másolata:",
+
+# Login and logout pages
+#
+"logouttitle"  => "Kilépés",
+"logouttext"   => "Kiléptél.
+Folytathatod a {{SITENAME}} használatát név nélkül, vagy beléphetsz
+újra vagy másik felhasználóként.\n",
+
+"welcomecreation" => "<h2>Üdvözöllek, $1!</h2><p>A felhasználói környezeted
+létrehoztam.
+Ne felejtsd el átnézni a személyes {{SITENAME}} beállításaidat.",
+
+"loginpagetitle" => "Belépés",
+"yourname"             => "A felhasználói neved",
+"yourpassword" => "Jelszavad",
+"yourpasswordagain" => "Jelszavad ismét",
+"newusersonly" => " (csak új felhasználóknak)",
+"remembermypassword" => "Jelszó megjegyzése a használatok között.",
+"loginproblem" => "<b>Valami probléma van a belépéseddel.</b><br />Kérlek próbáld ismét!",
+"alreadyloggedin" => "<strong>Kedves $1, már be vagy lépve!</strong><br />\n",
+
+"login"                        => "Belépés",
+"userlogin"            => "Belépés",
+"logout"               => "Kilépés",
+"userlogout"   => "Kilépés",
+"notloggedin"  => "Nincs belépve",
+"createaccount"        => "Új felhasználó készítése",
+"createaccountmail"    => "eMail alapján", /* FIXME??? */
+"badretype"            => "A két jelszó eltér egymástól.",
+"userexists"   => "A név amit megadtál már létezik. Kérlek, adj meg más nevet.",
+"youremail"            => "Az emailed*",
+"yournick"             => "A beceneved (aláírásokhoz)",
+"emailforlost" => "* Az email cím megadása nem kötelező, viszont lehetővé
+teszi másoknak, hogy kapcsolatba lépjenek veled a weblapon keresztül
+anélkül, hogy a címedet megtudnák. Segítségedre lehet akkor is, ha
+elfelejted a jelszavadat.",
+"loginerror"   => "Belépési hiba.",
+"noname"               => "Nem adtál meg érvényes felhasználói nevet.",
+"loginsuccesstitle" => "Sikeres belépés",
+"loginsuccess" => "Beléptél a {{SITENAME}}BA \"$1\"-ként.",
+"nosuchuser"   => "Nincs olyan felhasználó hogy \"$1\".
+Ellenőrizd a gépelést, vagy készíts új nevet a fent látható űrlappal.",
+"wrongpassword"        => "A megadott jelszó helytelen.",
+"mailmypassword" => "Küldd el nekem a jelszavamat emailben",
+"passwordremindertitle" => "{{SITENAME}} jelszó emlékeztető",
+"passwordremindertext" => "Valaki (vélhetően te, a $1 IP számról)
+azt kérte, hogy küldjük el a jelszavadat.
+A jelszavad a \"$2\" felhasználóhoz most \"$3\".
+Lépj be, és változtasd meg a jelszavad.",
+"noemail"      => "Nincs a \"$1\" felhasználóhoz email felvéve.",
+"passwordsent" => "Az új jelszót elküldtük \"$1\" email címére.
+Lépj be a levélben található adatokkal.",
+
+# Edit pages
+#
+"summary"              => "Összefoglaló",
+"subject"              => "Téma/főcím",
+"minoredit"            => "Ez egy apró változtatás",
+"watchthis"            => "Figyeld a szócikket",
+"savearticle"  => "Lap mentése",
+"preview"              => "Előnézet",
+"showpreview"  => "Előnézet megtekintése",
+"blockedtitle" => "A felhasználó le van tiltva",
+"blockedtext"  => "A felhasználói neved vagy IP számod $1 letiltotta.
+Az indoklás:<br />''$2''
+<p>Felveheted a kapcsolatot $1 adminnal vagy bármely más
+[[{{ns:project}}:adminisztrátorok|adminisztrátorral]] hogy megvitasd a letiltást.",
+"whitelistedittitle" => "A szerkesztéshez be kell lépned",
+"whitelistedittext" => "A szócikkek szerkesztéséhez [[Special:Userlogin|be kell lépned]].",
+"whitelistreadtitle" => "Az olvasáshoz be kell lépned",
+"whitelistreadtext" => "[[Special:Userlogin|Be kell lépned]] ahhoz, hogy cikkeket tudj olvasni.",
+"whitelistacctitle" => "Nem készíthetsz új bejelentkezési kódot",
+"whitelistacctext" => "Ahhoz, hogy ezen a Wikin új nevet regisztrálj [[Special:Userlogin|be kell lépned]] a szükséges engedélyszinttel.",
+"accmailtitle" => "Jelszó elküldve.",
+"accmailtext"  => "'$1' jelszavát elküldtük $2 címre.",
+"newarticle"   => "(Új)",
+"newarticletext" =>
+"Egy olyan lapra jutottál ami még nem létezik.
+A lap létrehozásához kezdd el írni a szövegét lenti keretbe
+(a [[{{ns:project}}:Segítség|segítség]] lapon lelsz további
+információkat).
+Ha tévedésből jöttél ide, csak nyomd meg a böngésző '''Vissza/Back'''
+gombját.",
+"anontalkpagetext" => "
+---- ''Ez egy olyan anonim felhasználó vitalapja, aki még nem készített magának nevet vagy azt nem használta. Ezért az [[IP szám]]át használjuk az azonosítására. Az IP számokon számos felhasználó osztozhat az idők folyamán. Ha anonim felhasználó vagy és úgy érzed, hogy értelmetlen megjegyzéseket írnak neked akkor [[Speciális:Belépés|készíts magadnak egy nevet vagy lépj be]] hogy megakadályozd más anonim felhasználókkal való keveredést.'' ",
+"noarticletext" => "(Ez a lap jelenleg nem tartalmaz szöveget)",
+"updated"              => "(Frissítve)",
+"note"                 => "<strong>Megjegyzés:</strong> ",
+"previewnote"  => "Ne felejtsd el, hogy ez csak egy előnézet, és nincs elmentve!",
+"previewconflict" => "Ez az előnézet a felső szerkesztőablakban levő
+szövegnek megfelelő képet mutatja, ahogy az elmentés után kinézne.",
+"editing"              => "$1 szerkesztés alatt",
+"editingsection"       => "$1 szerkesztés alatt (szakasz)",
+"editingcomment"       => "$1 szerkesztés alatt (üzenet)",
+"editconflict" => "Szerkesztési ütközés: $1",
+"explainconflict" => "Valaki megváltoztatta a lapot azóta,
+mióta szerkeszteni kezdted.
+A felső szövegablak tartalmazza a szöveget, ahogy az jelenleg létezik.
+A módosításaid az alsó ablakban láthatóak.
+Át kell vezetned a módosításaidat a felső szövegbe.
+<b>Csak</b> a felső ablakban levő szöveg kerül elmentésre akkor, mikor
+a \"Lap mentését\" választod.<br />",
+"yourtext"             => "A te szöveged",
+"storedversion" => "A tárolt változat",
+"editingold"   => "<strong>VIGYÁZAT! A lap egy elavult
+változatát szerkeszted.
+Ha elmented, akkor az ezen változat után végzett összes
+módosítás elvész.</strong>",
+"yourdiff"             => "Eltérések",
+"copyrightwarning" => "Kérlek vedd figyelembe hogy minden
+{{SITENAME}}BA küldött anyag a GNU Szabad Dokumentum Licenc alatti
+publikálásnak számít (lásd $1 a részletekért).
+Ha nem akarod, hogy az írásod könyörtelenül módosíthassák vagy
+tetszés szerint terjesszék, akkor ne küldd be ide.<br />
+A beküldéssel együtt azt is garantálod hogy mindezt saját
+magad írtad, vagy másoltad be egy szabadon elérhető vagy
+közkincs (public domain) forrásból.
+<strong>ENGEDÉLY NÉLKÜL NE KÜLDJ BE JOGVÉDETT ANYAGOKAT!</strong>",
+"longpagewarning" => "<strong>FIGYELEM: Ez a lap $1 kilobyte hosszú;
+néhány böngészőnek problémái vannak a 32KB körüli vagy nagyobb lapok
+szerkesztésével.
+Fontold meg a lap kisebb szakaszokra bontását.</strong>",
+"readonlywarning" => "<strong>FIGYELEM: Az adatbázis karbantartás miatt le van zárva,
+ezért a módosításaidat most nem lehetséges elmenteni. Érdemes a szöveget
+kimásolni és elmenteni egy szövegszerkesztőben a későbbi mentéshez.</strong>",
+"protectedpagewarning" => "<strong>FIGYELEM: A lap lezárásra került és ilyenkor
+csak a Sysop jogú adminisztrátorok tudják szerkeszteni. Ellenőrizd, hogy
+betartod a [[Project:Zárt_lapok_irányelve|zárt lapok irányelvét]].</strong>",
+
+# History pages
+#
+"revhistory"   => "Változások története",
+"nohistory"            => "Nincs szerkesztési történet ehhez a laphoz.",
+"revnotfound"  => "A változat nem található",
+"revnotfoundtext" => "A lap általad kért régi változatát nem találom.
+Kérlek ellenőrizd az URL-t amivel erre a lapra jutottál.\n",
+"loadhist"             => "Laptörténet beolvasása",
+"currentrev"   => "Aktuális változat",
+"revisionasof" => "$1 változat",
+"cur"                  => "akt",
+"next"                 => "köv",
+"last"                 => "előző",
+"orig"                 => "eredeti",
+"histlegend"   => "Jelmagyarázat: (akt) = eltérés az aktuális változattól,
+(előző) = eltérés az előző változattól,
+Legend: (cur) = difference with current version,
+A = Apró változtatás",
+
+# Diffs
+#
+"difference"   => "(Változatok közti eltérés)",
+"loadingrev"   => "különbségképzéshez olvasom a változatokat",
+"lineno"               => "Sor $1:",
+"editcurrent"  => "A lap aktuális változatának szerkesztése",
+
+# Search results
+#
+"searchresults" => "A keresés eredménye",
+"searchresulttext" => "További információkkal a keresésről [[Project:Keresés|Keresés a {{SITENAME}}]] szolgál.",
+"searchquery"  => "A \"$1\" kereséshez",
+"badquery"             => "Hibás formájú keresés",
+"badquerytext" => "Nem tudjuk a kérésedet végrehajtani.
+Ennek oka valószínűleg az, hogy három betűnél rövidebb
+karaktersorozatra próbáltál keresni, ami jelenleg nem lehetséges.
+Lehet az is hogy elgépelted a kifejezést, például \"hal and and mérleg\".
+Kérlek próbálj másik kifejezést keresni.",
+"matchtotals"  => "A \"$1\" keresés $2 címszót talált és
+$3 szócikk szövegét.",
+"nogomatch"            => "Nincs pontosan ezzel megegyező címszó,
+próbálom a keresést a cikkek szövegében.",
+"titlematches" => "Címszó egyezik",
+"notitlematches" => "Nincs egyező címszó",
+"textmatches"  => "Szócikk szövege egyezik",
+"notextmatches"        => "Nincs szócikk szöveg egyezés",
+"prevn"                        => "előző $1",
+"nextn"                        => "következő $1",
+"viewprevnext" => "Nézd ($1) ($2) ($3).",
+"showingresults" => "Lent látható <b>$1</b> találat, az eleje #<b>$2</b>.",
+"showingresultsnum" => "Lent látható <b>$3</b> találat, az eleje #<b>$2</b>.",
+"nonefound"            => "<strong>Megyjegyzés</strong>: a sikertelen keresések
+gyakori oka olyan szavak keresése (pl. \"have\" és \"from\") amiket a
+rendszer nem indexel fel, vagy több független keresési szó szerepeltetése
+(csak minden megadott szót tartalmazó találatok jelennek meg a
+végeredményben).",
+"powersearch" => "Keresés",
+"powersearchtext" => "
+Keresés a névterekben:<br />
+$1<br />
+$2 Átirányítások listája &nbsp; Keresés:$3 $9",
+"searchdisabled" => "<p>Elnézésed kérjük, de a teljes szöveges keresés terhelési okok miatt átmenetileg nem használható. Ezidő alatt használhatod a lenti Google keresést, mely viszont lehetséges, hogy nem teljesen friss adatokkal dolgozik.</p>",
+"blanknamespace" => "(Alap)",
+
+# Preferences page
+#
+"preferences"  => "Beállítások",
+"prefsnologin" => "Nem vagy belépve",
+"prefsnologintext"     => "Ahhoz hogy a
+beállításaidat rögzíthesd [[Speciális:Belépés|be kell lépned]].",
+"prefslogintext" => "Be vagy lépve \"$1\" néven.
+A belső azonosítód $2.",
+"prefsreset"   => "A beállítások törlődtek a tárolóból vett értékekre.",
+"qbsettings"   => "Gyorsmenü beállítások",
+"changepassword" => "Jelszó változtatása",
+# látvány? bőr?!
+"skin"                 => "Skin",
+"math"                 => "Képletek megjelenítése",
+"dateformat"   => "Dátum formátuma",
+"math_failure" => "Értelmezés sikertelen",
+"math_unknown_error"   => "ismertlen hiba",
+"math_unknown_function"        => "ismeretlen függvény ",
+"math_lexing_error"    => "lexing error",
+"math_syntax_error"    => "formai hiba",
+"saveprefs"            => "Beállítások mentése",
+"resetprefs"   => "Beállítások törlése",
+"oldpassword"  => "Régi jelszó",
+"newpassword"  => "Új jelszó",
+"retypenew"            => "Új jelszó mégegyszer",
+"textboxsize"  => "Szövegdoboz méretei",
+"rows"                 => "Sor",
+"columns"              => "Oszlop",
+"searchresultshead" => "Keresési eredmények beállításai",
+"resultsperpage" => "Laponként mutatott találatok száma",
+"contextlines" => "Találatonként mutatott sorok száma",
+# FIXME, what is that?
+"contextchars" => "Characters of context per line",
+"stubthreshold" => "Csonkok kijelzésének küszöbértéke",
+"recentchangescount" => "Címszavak száma a friss változtatásokban",
+"savedprefs"   => "A beállításaidat letároltam.",
+"timezonetext" => "Add meg az órák számát, amennyivel a helyi
+idő a GMT-től eltér (Magyarországon nyáron 2, télen 1).",
+"localtime"            => "Helyi idő",
+"timezoneoffset" => "Eltérés",
+"servertime"   => "A server ideje most",
+"guesstimezone" => "Töltse ki a böngésző",
+"emailflag"            => "Email küldés letiltása más userektől",
+"defaultns"            => "Alapértelmezésben az alábbi névterekben keressünk:",
+
+# Recent changes  'legutóbbi változtatások', 'friss v.'
+#
+
+"changes"              => "változtatás",
+"recentchanges" => "Friss változtatások",
+"recentchangestext" => "Ezen a lapon követheted a {{SITENAME}} történt legutóbbi
+változtatásokat. [[{{ns:project}}:Üdvözlünk_látogató|Üdvözlünk, látogató]]!
+Légy szíves ismerkedj meg az alábbi lapokkal: [[{{ns:project}}:GyIK|{{SITENAME}} GyIK]],
+[[{{ns:project}}:Irányelvek]] (különösen az [[{{ns:project}}:Elnevezési szokások|elnevezési szokásokat]],
+a [[{{ns:project}}:Semleges nézőpont|semleges nézőpontot]]), és a
+[[{{ns:project}}:Legelterjedtebb baklövések|legelterjedtebb baklövéseket]].
+Ha azt szeretnéd hogy a Wikipedia sikeres legyen akkor nagyon fontos, hogy
+soha ne add hozzá mások [[{{ns:project}}:Copyright|jogvédett és nem felhasználható]]
+anyagait.
+A jogi problémák komolyan árthatnak a projektnek ezért kérünk arra, hogy ne tegyél
+ilyet.",
+"rcloaderr"            => "Friss változtatások betöltése",
+"rcnote"               => "Lentebb az utolsó <strong>$2</strong> nap <strong>$1</strong> változtatása látható.",
+"rcnotefrom"   => "Lentebb láthatóak a <b>$2</b> óta történt változások (<b>$1</b>-ig).",
+"rclistfrom"   => "Az új változtatások kijelzése $1 után",
+# "rclinks"            => "Show last $1 changes in last $2 hours / last $3 days",
+# "rclinks"            => "Show last $1 changes in last $2 days.",
+# azért kell a 'db' mert ha nincs egy sem, akkor üres $3, és hülyén néz ki.
+"rclinks"              => "Az utolsó $1 változtatás látszik az elmúlt $2 napon; $3 db apró módosítással",
+"rchide"               => "$4 formában; $1 apró módosítás; $2 másodlagos névtér; $3 többszörös módosítás.",
+"rcliu"                        => "; $1 módosítás ismert userektől",
+"diff"                 => "eltér",
+"hist"                 => "történet",
+"hide"                 => "rejt",
+"show"                 => "mutat",
+"tableform"            => "tábla",
+"listform"             => "lista",
+"nchanges"             => "$1 módosítás",
+"minoreditletter" => "A",
+"newpageletter" => "Ú",
+
+# Upload
+#
+"upload"               => "File felküldése",
+"uploadbtn"            => "File felküldés",
+"uploadlink"   => "Kép felküldése",
+"reupload"             => "Újraküldés",
+"reuploaddesc" => "Visszatérés a felküldési űrlaphoz.",
+"uploadnologin" => "Nincs belépve",
+"uploadnologintext"    => "Ahhoz hogy file-okat tudj
+felküldeni [[Speciális:Belépés|logged in]]
+to upload files.",
+"uploaderror"  => "Felküldési hiba",
+"uploadtext"   => "'''ÁLLJ!''' Mielőtt bármit felküldesz ide
+győződj meg róla hogy elolvastad és követed a
+[[Project:Képhasználati_irányelvek|képhasználati irányelveket]].
+
+A régebben felküldött képek megnézéséhez vagy kereséséhez
+nézd meg a [[Speciális:Képlista|felküldött képek listáját]].
+A felküldések és törlések naplója a
+[[Project:Upload_log|felküldési naplóban]] található.
+
+Az alábbi űrlapot használd a cikkeidet illusztráló új kép felküldéséhez.
+A legtöbb büngészőben látsz egy \"Böngészés...\" (Browse) gombot
+aminek segítségével a rendszered file-jai között keresgélhetsz.
+
+A file-t kiválasztva az bekerül a gomb melletti mezőbe.
+Ezután be kell jelölnöd a kis pipát amivel igazolod hogy a felküldéssel
+nem sértesz meg semmilyen szerzői jogot.
+A \"Felküldés\" gombbal fejezheted be a küldést.
+Ez lassú internet kapcsolat esetén eltarthat egy kis ideig.
+
+A javasolt formátumok JPG a fotókhoz, PNG a rajzokhoz és
+ikon jellegű képekhez és OGG a hanganyagokhoz.
+Kérünk arra, hogy a file-jaidnak jellemző, beszélő nevet adj hogy
+elkerüld a félreértéseket. A képet a cikkbe a
+'''<nowiki>[[kép:file.jpg]]</nowiki>''' vagy
+'''<nowiki>[[kép:file.png|leírás]]</nowiki>'''
+formában használhatod és '''<nowiki>[[media:file.ogg]]</nowiki>''' formában
+a hanganyagokat.
+
+Kérünk hogy vedd figyelembe azt, hogy mint minden {{SITENAME}}
+lap esetében bárki szerkesztheti vagy törölheti a felküldésedet
+ha úgy ítéli meg, hogy az hasznos a lexikonnak, vagy letiltásra
+kerülhetsz a felküldési lehetőségről ha visszaélsz a rendszerrel.",
+"uploadlog"            => "felküldési napló",
+"uploadlogpage" => "Felküldési_napló",
+"uploadlogpagetext" => "Lentebb látható a legutóbbi felküldések listája.
+Minden időpont a server idejében (UTC) van megadva.
+<ul>
+</ul>
+",
+"filename"             => "Filenév",
+"filedesc"             => "Összefoglaló",
+"filestatus"   => "Szerzői jogi állapot",
+"filesource"   => "Forrás",
+"copyrightpage" => "{{ns:project}}:Copyright",
+"copyrightpagename" => "{{SITENAME}} copyright",
+"uploadedfiles"        => "Felküldött file-ok",
+"ignorewarning"        => "Mentés a figyelmeztetés figyelmen kívül hagyásával.",
+"minlength"            => "A kép nevének legalább három betűből kell állnia.",
+"badfilename"  => "A kép új neve \"$1\".",
+"badfiletype"  => "\".$1\" nem javasolt képformátumnak.",
+"largefile"            => "Javasolt hogy a képek mérete ne haladja meg a 100 kilobyte-ot.",
+"successfulupload" => "Sikeresen felküldve",
+"fileuploaded" => "A \"$1\" file felküldése sikeres volt.
+kérlek a ($2) linken add meg a file leírását és az információkat a
+file-ról, mint például hogy honnan való, mikor és ki készítette, vagy bármi
+más információ amit meg tudsz adni.",
+"uploadwarning" => "Felküldési figyelmeztetés",
+"savefile"             => "File mentése",
+"uploadedimage" => "\"[[$1]]\" felküldve",
+
+# Image list
+#
+"imagelist"            => "Képlista",
+"imagelisttext"        => "Lentebb látható $1 $2 rendezett kép.",
+"getimagelist" => "képlista lehívása",
+"ilsubmit"             => "Keresés",
+"showlast"             => "Az utolsó $1 kép $2.",
+"byname"               => "név szerint",
+"bydate"               => "dátum szerint",
+"bysize"               => "méret szerint",
+"imgdelete"            => "töröl",
+"imgdesc"              => "leírás",
+"imglegend"            => "Jelmagyarázat: (leírás) = kép leírás megtekintés/szerkesztés.",
+"imghistory"   => "Kép története",
+"revertimg"            => "régi",
+"deleteimg"            => "töröl",
+"deleteimgcompletely"          => "töröl",
+"imghistlegend" => "Jelmagyarázat: (akt) = ez az aktuális kép,
+(töröl) = ezen régi változat törlése,
+(régi) = visszaállás erre a régi változatra.
+<br /><i>Klikkelj a dátumra hogy megnézhesd az akkor felküldött képet</i>.",
+"imagelinks"   => "Kép hivatkozások",
+"linkstoimage" => "Az alábbi lapok hivatkoznak erre a képre:",
+"nolinkstoimage" => "Erre a képre nem hivatkozik lap.",
+
+# Statistics
+#
+"statistics"   => "Statisztika",
+"sitestats"            => "Server statisztika",
+"userstats"            => "User statisztika",
+"sitestatstext" => "Az adatbázisban összesen <b>$1</b> lap található.
+Ebben benne vannak a \"vita\" lapok, a {{SITENAME}}ROL szóló lapok, a
+minimális \"csonk\" lapok, átirányítások és hasonlók amik vélhetően nem
+számítanak igazi szócikkeknek.
+Ezeket nem számítva <b>$2</b> lapunk van ami valószínűleg igazi szócikknek
+számít.<p>
+A magyar {{SITENAME}} indítása óta (2003 júl 8) <b>$3</b> alkalommal néztek meg
+lapokat a rendszeren, és <b>$4</b> alkalommal szerkesztett valaki lapot.
+Ezek alapján átlagosan egy lapot <b>$5</b> alkalommal szerkesztettek, és
+szerkesztésenként <b>$6</b> alkalommal nézték meg.",
+"userstatstext" => "Jelenleg <b>$1</b> regisztrált felhasználónk van.
+Ebből <b>$2</b> darab adminisztrátor (lásd $3).",
+
+# Maintenance Page
+#
+"maintenance"  => "Karbantartás",
+"maintnancepagetext" => "Ezen a lapon a mindennapi karbantartáshoz hasznos dologkat lelsz. Mivel ezek az adatbázist a szokásosnál jobban terhelik kérlek ne nyomj minden kijavított cikk után reloadot ;-)",
+"maintenancebacklink" => "Vissza a karbantartás lapra",
+"disambiguations" => "Egyértelműsítő lapok",
+"disambiguationspage" => "{{ns:project}}:Egyértelműsítő lapok",
+"disambiguationstext"  => "The following articles link to a <i>disambiguation page</i>. They should link to the appropriate topic instead.<br />A page is treated as dismbiguation if it is linked from $1.<br />Links from other namespaces are <i>not</i> listed here.",
+"doubleredirects"      => "Double Redirects",
+"doubleredirectstext"  => "<b>Attention:</b> This list may contain false positives. That usually means there is additional text with links below the first #REDIRECT.<br />\nEach row contains links to the first and second redirect, as well as the first line of the second redirect text, usually giving the \"real\" taget article, which the first redirect should point to.",
+"brokenredirects"      => "Broken Redirects",
+"brokenredirectstext"  => "The following redirects link to a non-existing article.",
+"selflinks"    => "Pages with Self Links",
+"selflinkstext"        => "The following pages contain a link to themselves, which they should not.",
+"mispeelings"           => "Pages with misspellings",
+"mispeelingstext"      => "The following pages contain a common misspelling, which are listed on $1. The correct spelling might be given (like this).",
+"mispeelingspage"      => "{{ns:project}}:Gyakori elírások listája",
+"missinglanguagelinks"  => "Missing Language Links",
+"missinglanguagelinksbutton"    => "Find missing language links for",
+"missinglanguagelinkstext"      => "These articles do <i>not</i> link to their counterpart in $1. Redirects and subpages are <i>not</i> shown.",
+
+
+# Miscellaneous special pages
+#
+"orphans"              => "Árva lapok",
+"lonelypages"  => "Árva lapok",
+"unusedimages" => "Nem használt képek",
+"popularpages" => "Népszerű lapok",
+"nviews"               => "$1 megnézés",
+# FIXME
+"wantedpages"  => "Wanted pages",
+"nlinks"               => "$1 link",
+"allpages"             => "Minden lap",
+"randompage"   => "Lap találomra",
+"shortpages"   => "Rövid lapok",
+"longpages"            => "Hosszú lapok",
+"listusers"            => "Felhasználók",
+"specialpages" => "Speciális lapok",
+"spheading"            => "Speciális lapok",
+"protectpage"  => "Protect page",
+"recentchangeslinked" => "Kapcsolódó változtatások",
+# FIXME: possible context?
+"rclsub"               => "(a \"$1\" lapról hivatkozott lapok)",
+"debug"                        => "Debug",
+"newpages"             => "Új lapok",
+"ancientpages" => "Ősi szócikkek",
+"intl"                 => "Nyelvek közötti linkek",
+"movethispage" => "Mozgasd ezt a lapot",
+"unusedimagestext" => "<p>Vedd figyelembe azt hogy más
+lapok - mint például a nemzetközi {{SITENAME}}K - közvetlenül
+hivatkozhatnak egy file URL-jére, ezért szerepelhet itt annak
+ellenére hogy aktívan használják.",
+"booksources"  => "Könyvforrások",
+"booksourcetext" => "Lentebb néhány hivatkozás található olyan lapokra,
+ahol új vagy használt könyveket árusítanak, vagy további információkkal
+szolgálhatnak az általad vizsgált könyvről.
+A {{SITENAME}} semmilyen módon nem áll kapcsolatba ezen cégekkel és
+ezt a listát semmiképpen ne tekintsd bármiféle ajánlásnak.",
+# FIXME: huh?
+"alphaindexline" => "$1 -> $2",
+
+# Email this user
+#
+"mailnologin"  => "Nincs feladó",
+"mailnologintext" => "Ahhoz hogy másoknak emailt küldhess
+[[Speciális:Belépés|be kell jelentkezned]]
+és meg kell adnod egy érvényes email címet a [[Speciális:Beállítások|beállításaidban]].",
+"emailuser"            => "E-mail küldése ezen felhasználónak",
+"emailpage"            => "E-mail küldése",
+"emailpagetext"        => "Ha ez a felhasználó megadott egy érvényes email
+címet, akokr ezen űrlap segítségével tudsz neki emailt küldeni.
+Az általad a beállításaid között megadott email címed fog feladóként
+szerepelni, hogy a címzett válaszolni tudjon.",
+"noemailtitle" => "Nincs email cím",
+"noemailtext"  => "Ez a felhasználó nem adott meg email címet, vagy
+nem kíván másoktól leveleket kapni.",
+"emailfrom"            => "Feladó",
+"emailto"              => "Cím",
+"emailsubject" => "Téma",
+"emailmessage" => "Üzenet",
+"emailsend"            => "Küldés",
+"emailsent"            => "E-mail elküldve",
+"emailsenttext" => "Az email üzenetedet elküldtem.",
+
+# Watchlist
+#
+"watchlist"            => "Figyelőlistám",
+"watchlistsub" => "(\"$1\" user)",
+"nowatchlist"  => "Nincs lap a figyelőlistádon.",
+"watchnologin" => "Nincs belépve",
+"watchnologintext"     => "Ahhoz hogy figyelőlistád lehessen [[Speciál:Belépés|be kell lépned]].",
+"addedwatch"   => "Figyelőlistához hozzáfűzve",
+"addedwatchtext" => "A \"$1\" lapot hozzáadtam a <a href=\"" .
+  "{{localurle:Speciális:Figyelőlista}}\">figyelőlistádhoz</a>.
+Ezután minden a lapon vagy annak vitalapján történő változást ott fogsz
+látni, és a lap <b>vastagon</b> fog szerepelni a <a href=\"" .
+  "{{localurle:Speciális:Friss_változtatások}}\">friss változtatások</a>
+lapon, hogy könnyen észrevehető legyen.</p>
+
+<p>Ha később el akarod távolítani a lapot a figyelőlistádról, akkor ezt az
+oldalmenü \"Figyelés vége\" pontjával teheted meg.",
+"removedwatch" => "Figyelőlistáról eltávolítva",
+"removedwatchtext" => "A \"$1\" lapot eltávolítottam a figyelőlistáról.",
+"watchthispage"        => "Lap figyelése",
+"unwatchthispage" => "Figyelés vége",
+"notanarticle" => "Nem szócikk",
+"watchdetails" => "($1 lap figyelése a vitalapokon kívül,
+$2 lap változott az adott határokon belül,
+$3...
+[$4 teljes lista áttekintés és szerkesztés].)",
+"watchmethod-recent" => "a figyelt lapokon belüli legfrissebb szerkesztések",
+"watchmethod-list" => "a legfrissebb szerkesztésekben található figyelt lapok",
+"removechecked" => "A kijelölt lapok eltávolítása a figyelésből",
+"watchlistcontains" => "A figyelőlistád $1 lapot tartalmaz.",
+"watcheditlist" => "Íme a figyelőlistádban található lapok
+betűrendes listája. Jelöld ki azokat a lapokat, amiket el
+szeretnél távolítani, és válaszd a 'Kijelöltek eltávolítása'
+gombot a lap alján.",
+"removingchecked" => "A kért lapok eltávolítása a figyelőlistáról...",
+"couldntremove" => "'$1' nem távolítható el...",
+"iteminvalidname" => "Probléma a '$1' elemmel: érvénytelen név...",
+"wlnote" => "Lentebb az utolsó <b>$2</b> óra $1 változtatása látható.",
+"wlshowlast" => "Módosítások az utolsó $1 órában $2 napon $3",
+
+# Delete/protect/revert
+#
+"deletepage"   => "Delete page",
+"confirm"              => "Confirm",
+"excontent"    => "content was: '$1'",
+"exbeforeblank" => "content before blanking was: '$1'",
+"exblank"              => "page was empty",
+"confirmdelete" => "Confirm delete",
+"deletesub"            => "(Deleting \"$1\")",
+"historywarning" => "Warning: The page you are about to delete has a history: ",
+"confirmdeletetext" => "You are about to permanently delete a page
+or image along with all of its history from the database.
+Please confirm that you intend to do this, that you understand the
+consequences, and that you are doing this in accordance with
+[[Wikipedia:Policy]].",
+"actioncomplete" => "Action complete",
+"deletedtext"  => "\"$1\" has been deleted.
+See $2 for a record of recent deletions.",
+"deletedarticle" => "deleted \"$1\"",
+"dellogpage"   => "Deletion_log",
+"dellogpagetext" => "Below is a list of the most recent deletions.
+All times shown are server time (UTC).
+<ul>
+</ul>
+",
+"deletionlog"  => "deletion log",
+"reverted"             => "Reverted to earlier revision",
+"deletecomment"        => "Reason for deletion",
+"imagereverted" => "Revert to earlier version was successful.",
+"rollback"             => "Roll back edits",
+"rollbacklink" => "rollback",
+"rollbackfailed" => "Rollback failed",
+"cantrollback" => "Cannot revert edit; last contributor is only author of this article.",
+"alreadyrolled"        => "Cannot rollback last edit of [[$1]]
+by [[User:$2|$2]] ([[User talk:$2|Talk]]); someone else has edited or rolled back the article already.
+
+Last edit was by [[User:$3|$3]] ([[User talk:$3|Talk]]). ",
+#   only shown if there is an edit comment
+"editcomment" => "The edit comment was: \"<i>$1</i>\".",
+"revertpage"   => "Reverted to last edit by $1",
+
+# Undelete
+"undelete" => "Restore deleted page",
+"undeletepage" => "View and restore deleted pages",
+"undeletepagetext" => "The following pages have been deleted but are still in the archive and
+can be restored. The archive may be periodically cleaned out.",
+"undeletearticle" => "Restore deleted article",
+"undeleterevisions" => "$1 revisions archived",
+"undeletehistory" => "If you restore the page, all revisions will be restored to the history.
+If a new page with the same name has been created since the deletion, the restored
+revisions will appear in the prior history, and the current revision of the live page
+will not be automatically replaced.",
+"undeleterevision" => "Deleted revision as of $1",
+"undeletebtn" => "Restore!",
+"undeletedarticle" => "restored \"$1\"",
+"undeletedtext"   => "The article [[$1]] has been successfully restored.
+See [[Wikipedia:Deletion_log]] for a record of recent deletions and restorations.",
+
+# Contributions
+#
+"contributions"        => "User közreműködései",
+"mycontris" => "Közreműködéseim",
+"contribsub"   => "$1 cikkhez",
+"nocontribs"   => "Nem találtam a feltételnek megfelelő módosítást.",
+"ucnote"               => "Lentebb <b>$1</b> módosításai láthatóak az elmúlt <b>$2</b> napban.",
+"uclinks"              => "View the last $1 changes; view the last $2 days.",
+"uctop"                        => " (top)",
+
+# What links here
+#
+"whatlinkshere"        => "Mi hivatkozik erre",
+"notargettitle" => "Nincs cél",
+"notargettext" => "Nem adtál meg lapot vagy usert keresési célpontnak.",
+"linklistsub"  => "(Linkek )",
+"linkshere"            => "Az alábbi lapok hivatkoznak erre:",
+"nolinkshere"  => "Erre a lapra senki nem hivatkozik.",
+"isredirect"   => "átirányítás",
+
+# Block/unblock IP
+#
+#FIXME:
+"blockip"              => "Block IP address",
+"blockiptext"  => "Use the form below to block write access
+from a specific IP address.
+This should be done only only to prevent vandalism, and in
+accordance with [[Wikipedia:Policy|Wikipedia policy]].
+Fill in a specific reason below (for example, citing particular
+pages that were vandalized).",
+"ipaddress"            => "IP Address",
+"ipbreason"            => "Reason",
+"ipbsubmit"            => "Block this address",
+"badipaddress" => "The IP address is badly formed.",
+"blockipsuccesssub" => "Block succeeded",
+"blockipsuccesstext" => "The IP address \"$1\" has been blocked.
+<br />See [[Speciális:Ipblocklist|IP block list]] to review blocks.",
+"unblockip"            => "Unblock IP address",
+"unblockiptext"        => "Use the form below to restore write access
+to a previously blocked IP address.",
+"ipusubmit"            => "Unblock this address",
+"ipusuccess"   => "IP address \"$1\" unblocked",
+"ipblocklist"  => "List of blocked IP addresses",
+"blocklistline"        => "$1, $2 blocked $3 ($4)",
+"blocklink"            => "block",
+"unblocklink"  => "unblock",
+"contribslink" => "contribs",
+"autoblocker"  => "Autoblocked because you share an IP address with \"$1\". Reason \"$2\".",
+"blocklogpage" => "Block_log",
+"blocklogentry"        => 'blocked "$1"',
+"blocklogtext" => "This is a log of user blocking and unblocking actions. Automatically
+blocked IP addresses are not be listed. See the [[Special:Ipblocklist|IP block list]] for
+the list of currently operational bans and blocks.",
+"unblocklogentry"      => 'unblocked "$1"',
+
+# Developer tools
+#
+"lockdb"               => "Lock database",
+"unlockdb"             => "Unlock database",
+"lockdbtext"   => "Locking the database will suspend the ability of all
+users to edit pages, change their preferences, edit their watchlists, and
+other things requiring changes in the database.
+Please confirm that this is what you intend to do, and that you will
+unlock the database when your maintenance is done.",
+"unlockdbtext" => "Unlocking the database will restore the ability of all
+users to edit pages, change their preferences, edit their watchlists, and
+other things requiring changes in the database.
+Please confirm that this is what you intend to do.",
+"lockconfirm"  => "Yes, I really want to lock the database.",
+"unlockconfirm"        => "Yes, I really want to unlock the database.",
+"lockbtn"              => "Lock database",
+"unlockbtn"            => "Unlock database",
+"locknoconfirm" => "You did not check the confirmation box.",
+"lockdbsuccesssub" => "Database lock succeeded",
+
+"unlockdbsuccesssub" => "Database lock removed",
+"lockdbsuccesstext" => "The Wikipedia database has been locked.
+<br />Remember to remove the lock after your maintenance is complete.",
+"unlockdbsuccesstext" => "The Wikipedia database has been unlocked.",
+
+# Move page
+#
+"movepage"             => "Lap mozgatása",
+"movepagetext" => "A lentebb található űrlap segítségével legetséges
+egy lapot átnevezni, és átmozgatni a teljes történetével együtt egy
+új névre.
+A régi név átirányítássá válik az új címszóra.
+A régi címszóra hivatkozások nem változnak meg;
+[[Speciális:Karbantartás|győződj meg arról]] hogy nem hagysz
+magad után a régi címszóra hivatkozó linkeket. A te feladatod
+biztosítani hogy a linkek oda mutassanak, ahova kell nekik.
+
+Vedd figyelembe azt hogy az átnevezés '''nem''' történik meg
+akkorr, ha már létezik olyan nevű lap, kivéve ha az üres,
+átirányítás vagy nincs szerkesztési története. Ez azt jelenti
+hogy vissza tudsz nevezni egy tévedésből átnevezett lapot, de
+nem tudsz egy már létező aktív lapot felülírni.
+
+<b>FIGYELEM!</b>
+Egy népszerű lap esetén ez egy drasztikus és váratlan változás;
+mielőtt átnevezel valamit győződj meg arról hogy tudatában vagy a következményeknek.",
+"movepagetalktext" => "A laphoz tartozó vitalap automatikusan átneveződik '''kivéve ha:'''
+* A lapot névterek között mozgatod át,
+* Már létezik egy nem üres vitalap az új helyen,
+* Nem jelölöd be a lenti pipát.
+
+Ezen esetekben a vita lapot külön, kézzel kell átnevezned a kívánságaid
+szerint.",
+"movearticle"  => "Lap mozgatás",
+"movenologin"  => "Nincs belépve",
+"movenologintext" => "Ahhoz hogy mozgass egy lapot [[Speciális:Belépés|be kell lépned]].",
+"newtitle"             => "Az új névre",
+"movepagebtn"  => "Lap mozgatása",
+"pagemovedsub" => "Átmozgatás sikeres",
+"pagemovedtext" => "A \"[[$1]]\" lapot átmozgattam a \"[[$2]]\" névre.",
+"articleexists" => "Ilyen névvel már létezik lap, vagy az általad
+választott név érvénytelen.
+Kérlek válassz egy másik nevet.",
+"talkexists"   => "A lap átmozgatása sikerült, de a hozzá tartozó
+vitalapot nem tudtam átmozgatni mert már létezik egy egyező nevű
+lap az új helyen. Kérlek gondoskodj a két lap összefűzéséről.",
+"movedto"              => "átmozgatva",
+"movetalk"             => "Mozgasd a \"vita\" lapokat is ha lehetséges.",
+"talkpagemoved" => "A laphoz tartozó vita lap is átmozgatásra került.",
+"talkpagenotmoved" => "A laphoz tartozó vita lap <strong>nem került</strong> átmozgatásra.",
+
+"export"               => "Lapok exportálása",
+"exporttext"   => "Egy adott lap vagy lapcsoport szövegét és változtatásait
+tudod egyfajta XML-be exportálni; ezt használhatod egy másik MediaWiki alapú
+rendszerbe való importálásra, átalakításra vagy a saját szórakoztatásodra.",
+"exportcuronly"        => "Csak a legfrissebb állapot, teljes laptörténet nélkül",
+
+# Namespace 8 related
+
+"allmessages"  => "All_messages",
+"allmessagestext"      => "Ez a MediaWiki: névtérben elérhető összes üzenet listája",
+
+# Math
+
+'mw_math_png' => "Mindig készítsen PNG-t",
+'mw_math_simple' => "HTML ha nagyon egyszerű, egyébként PNG",
+'mw_math_html' => "HTML ha lehetséges, egyébként PNG",
+'mw_math_source' => "Hagyja TeX formában (szöveges böngészőknek)",
+'mw_math_modern' => "Modern böngészőknek ajánlott beállítás",
+'mw_math_mathml' => 'MathML',
+);
+
+class LanguageHu extends LanguageUtf8 {
+
+       function getNamespaces() {
+               global $wgNamespaceNamesHu;
+               return $wgNamespaceNamesHu;
+       }
+
+       function getNsIndex( $text ) {
+               global $wgNamespaceNamesHu;
+
+               foreach ( $wgNamespaceNamesHu as $i => $n ) {
+                       if ( 0 == strcasecmp( $n, $text ) ) { return $i; }
+               }
+               # Compatbility with old names:
+               if( 0 == strcasecmp( "Special", $text ) ) { return -1; }
+               if( 0 == strcasecmp( "Wikipedia", $text ) ) { return 4; }
+               if( 0 == strcasecmp( "Wikipedia_talk", $text ) ) { return 5; }
+               return false;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsHu;
+               return $wgQuickbarSettingsHu;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesHu;
+               return $wgSkinNamesHu;
+       }
+
+       function getDateFormats() {
+               global $wgDateFormatsHu;
+               return $wgDateFormatsHu;
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesHu;
+               if(array_key_exists($key, $wgAllMessagesHu))
+                       return $wgAllMessagesHu[$key];
+               else
+                       return parent::getMessage($key);
+       }
+
+       function fallback8bitEncoding() {
+               return "iso8859-2";
+       }
+
+       # localised date and time
+       function date( $ts, $adj = false ) {
+               if ( $adj ) { $ts = $this->userAdjust( $ts ); }
+
+               $d = substr( $ts, 0, 4 ) . ". " .
+               $this->getMonthName( substr( $ts, 4, 2 ) ) . " ".
+                       (0 + substr( $ts, 6, 2 )) . ".";
+               return $d;
+       }
+
+       function timeanddate( $ts, $adj = false ) {
+               return $this->date( $ts, $adj ) . ", " . $this->time( $ts, $adj );
+       }
+
+       function formatNum( $number ) {
+               global $wgTranslateNumerals;
+               return $wgTranslateNumerals ? strtr($number, '.,', ',.' ) : $number;
+       }
+
+}
+
+?>
diff --git a/languages/LanguageIa.php b/languages/LanguageIa.php
new file mode 100644 (file)
index 0000000..7c6187f
--- /dev/null
@@ -0,0 +1,885 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+/** TODO: fixme */
+/* private */ $wgNamespaceNamesIa = array(
+       NS_MEDIA          => "Media",
+       NS_SPECIAL        => "Special",
+       NS_MAIN           => "",
+       NS_TALK           => "Discussion",
+       NS_USER           => "Usator",
+       NS_USER_TALK      => "Discussion_Usator",
+       NS_PROJECT        => "Wikipedia",
+       NS_PROJECT_TALK   => "Discussion_Wikipedia",
+       NS_IMAGE          => "Imagine",
+       NS_IMAGE_TALK     => "Discussion_Imagine",
+       NS_MEDIAWIKI      => "MediaWiki",
+       NS_MEDIAWIKI_TALK => "Discussion_MediaWiki",
+       NS_TEMPLATE       => "Template",
+       NS_TEMPLATE_TALK  => "Template_talk"
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgQuickbarSettingsIa = array(
+       "Necun", "Fixe a sinistra", "Fixe a dextera", "Flottante a sinistra"
+);
+
+/* private */ $wgSkinNamesIa = array(
+       'cologneblue' => "Blau Colonia",
+) + $wgSkinNamesEn;
+
+
+/* private */ $wgAllMessagesIa = array(
+
+# User Toggles
+#
+
+"tog-underline" => "Sublinear ligamines",
+"tog-highlightbroken" => "Formatar ligamines rupte <a href=\"\" class=\"new\">assi</a> (alternativemente: assi<a href=\"\" class=\"internal\">?</a>).",
+"tog-justify"  => "Justificar paragraphos",
+"tog-hideminor" => "Occultar modificationes recente minor",
+"tog-usenewrc" => "Modificationes recente meliorate (non functiona in tote le navigatores)",
+"tog-numberheadings" => "Numerar titulos automaticamente",
+"tog-showtoolbar" => "Show edit toolbar",
+"tog-rememberpassword" => "Recordar contrasigno inter sessiones (usa cookies)",
+"tog-editwidth" => "Cassa de redaction occupa tote le largor del fenestra",
+"tog-editondblclick" => "Duple clic pro modificar un pagina (usa JavaScript)",
+"tog-watchdefault" => "Poner articulos nove e modificate sub observation",
+"tog-minordefault" => "Marcar modificationes initialmente como minor",
+"tog-previewontop" => "Monstrar previsualisation ante le cassa de edition e non post illo",
+
+# dates
+#
+
+'sunday' => 'dominica',
+'monday' => 'lunedi',
+'tuesday' => 'martedi',
+'wednesday' => 'mercuridi',
+'thursday' => 'jovedi',
+'friday' => 'venerdi',
+'saturday' => 'sabbato',
+'january' => 'januario',
+'february' => 'februario',
+'march' => 'martio',
+'april' => 'april',
+'may_long' => 'maio',
+'june' => 'junio',
+'july' => 'julio',
+'august' => 'augusto',
+'september' => 'septembre',
+'october' => 'octobre',
+'november' => 'novembre',
+'december' => 'decembre',
+'jan' => 'jan',
+'feb' => 'feb',
+'mar' => 'mar',
+'apr' => 'apr',
+'may' => 'mai',
+'jun' => 'jun',
+'jul' => 'jul',
+'aug' => 'aug',
+'sep' => 'sep',
+'oct' => 'oct',
+'nov' => 'nov',
+'dec' => 'dec',
+
+
+# Bits of text used by many pages:
+#
+"linktrail"            => "/^([a-z]+)(.*)\$/sD",
+"mainpage"             => "Frontispicio",
+"about"                        => "A proposito",
+"aboutsite"      => "A proposito de Wikipedia",
+"aboutpage"            => "Wikipedia:A_proposito",
+"help"                 => "Adjuta",
+"helppage"             => "Wikipedia:Adjuta",
+"bugreports"   => "Reportos de disfunctiones",
+"bugreportspage" => "Wikipedia:Reportos_de_disfunctiones",
+"faq"                  => "Questiones frequente",
+"faqpage"              => "Wikipedia:Questiones_frequente",
+"edithelp"             => "Adjuta al edition",
+"edithelppage" => "Wikipedia:Como_editar_un_pagina",
+"cancel"               => "Cancellar",
+"qbfind"               => "Trovar",
+"qbbrowse"             => "Foliar",
+"qbedit"               => "Modificar",
+"qbpageoptions" => "Optiones de pagina",
+"qbpageinfo"   => "Info del pagina",
+"qbmyoptions"  => "Mi optiones",
+"mypage"               => "Mi pagina",
+"mytalk"               => "Mi discussion",
+"currentevents" => "Actualitates",
+"errorpagetitle" => "Error",
+"returnto"             => "Retornar a $1.",
+"tagline"              => "De Wikipedia, le encyclopedia libere.",
+"whatlinkshere"        => "Referentias a iste pagina",
+"help"                 => "Adjuta",
+"search"               => "Recercar",
+"go"           => "Ir",
+"history"              => "Chronologia",
+"printableversion" => "Version imprimibile",
+"editthispage" => "Modificar iste pagina",
+"deletethispage" => "Eliminar iste pagina",
+"protectthispage" => "Proteger iste pagina",
+"unprotectthispage" => "Disproteger iste pagina",
+"newpage" => "Nove pagina",
+"talkpage"             => "Discuter iste pagina",
+"articlepage"  => "Vider article",
+"subjectpage"  => "Vider subjecto", # For compatibility
+"userpage" => "Vider pagina del usator",
+"wikipediapage" => "Vider metapagina",
+"imagepage" =>         "Vider pagina de imagine",
+"viewtalkpage" => "Vider discussion",
+"otherlanguages" => "Altere linguas",
+"redirectedfrom" => "(Redirigite de $1)",
+"lastmodified" => "Ultime modification: $1.",
+"viewcount"            => "Iste pagina esseva accessate $1 vices.",
+"printsubtitle" => "(De {{SERVER}})",
+"protectedpage" => "Pagina protegite",
+"administrators" => "Wikipedia:Administratores",
+"sysoptitle"   => "Reservate a Sysops",
+"sysoptext"            => "Solo usatores con status de \"sysop\"
+pote effectuar iste action.
+Vide $1.",
+"developertitle" => "Reservate a disveloppatores",
+"developertext"        => "Solo usatores con status de \"developer\"
+pote effectuar iste action.
+Vide $1.",
+"nbytes"               => "$1 bytes",
+"go"                   => "Ir",
+"ok"                   => "OK",
+"sitetitle"            => "Wikipedia",
+"sitesubtitle" => "Le encyclopedia libere",
+"retrievedfrom" => "Recuperate de \"$1\"",
+"newmessages" => "Tu ha $1.",
+"newmessageslink" => "messages nove",
+
+# Main script and global functions
+#
+"nosuchaction" => "Action inexistente",
+"nosuchactiontext" => "Le action specificate in le URL non es
+recognoscite per le systema de Wikipedia.",
+"nosuchspecialpage" => "Pagina special inexistente",
+"nospecialpagetext" => "
+Tu demandava un pagina special que non es
+recognoscite per le systema de Wikipedia.",
+
+# General errors
+#
+"error"                        => "Error",
+"databaseerror" => "Error de base de datos",
+"dberrortext"  => "Occurreva un error de syntaxe in le consulta al base de datos.
+Le ultime demanda inviate al base de datos esseva:
+<blockquote><tt>$1</tt></blockquote>
+de intra le function \"<tt>$2</tt>\".
+MySQL retornava le error \"<tt>$3: $4</tt>\".",
+"noconnect"            => "Impossibile connecter al base de datos a $1",
+"nodb"                 => "Impossibile selectionar base de datos $1",
+"readonly"             => "Base de datos blocate",
+"enterlockreason" => "Describe le motivo del blocage, includente un estimation
+de quando illo essera terminate",
+"readonlytext" => "Actualmente le base de datos de Wikipedia es blocate pro nove
+entratas e altere modificationes, probabilemente pro mantenentia
+routinari del base de datos, post le qual illo retornara al normal.
+Le administrator responsabile dava iste explication:
+<p>$1",
+"missingarticle" => "Le base de datos non trovava le texto de un pagina
+que illo deberea haber trovate, a saper \"$1\".
+Isto non es un error de base de datos, mais probabilemente
+un disfunction in le systema.
+Per favor reporta iste occurrentia a un administrator,
+indicante le URL.",
+"internalerror" => "Error interne",
+"filecopyerror" => "Impossibile copiar file \"$1\" a \"$2\".",
+"filerenameerror" => "Impossibile renominar file \"$1\" a \"$2\".",
+"filedeleteerror" => "Impossibile eliminar file \"$1\".",
+"filenotfound" => "Impossibile trovar file \"$1\".",
+"unexpected"   => "Valor impreviste: \"$1\"=\"$2\".",
+"formerror"            => "Error: impossibile submitter formulario",
+"badarticleerror" => "Iste action non pote esser effectuate super iste pagina.",
+"cannotdelete" => "Impossibile eliminar le pagina o imagine specificate. (Illo pote ja haber essite eliminate per un altere persona.)",
+"badtitle"             => "Titulo incorrecte",
+"badtitletext" => "Le titulo de pagina demandate esseva invalide, vacue, o
+un titulo interlinguistic o interwiki incorrectemente ligate.",
+"perfdisabled" => "Pardono! Iste functionalitate es temporarimente inactivate durante
+horas de grande affluentia de accessos pro motivo de performance;
+retorna inter 02:00 e 14:00 UTC e tenta de nove.",
+
+# Login and logout pages
+#
+"logouttitle"  => "Fin de session",
+"logouttext"   => "Tu claudeva tu session.
+Tu pote continuar a usar Wikipedia anonymemente, o initiar un
+nove session como le mesme o como un altere usator.\n",
+
+"welcomecreation" => "<h2>Benvenite, $1!</h2>
+<p>Tu conto de usator esseva create.
+Non oblida personalisar Wikipedia secundo tu preferentias.",
+
+"loginpagetitle" => "Aperir session",
+"yourname"             => "Tu nomine de usator",
+"yourpassword" => "Tu contrasigno",
+"yourpasswordagain" => "Confirmar contrasigno",
+"newusersonly" => " (solmente pro nove usatores)",
+"remembermypassword" => "Recordar contrasigno inter sessiones.",
+"loginproblem" => "<b>Occurreva problemas pro initiar tu session.</b><br />Tenta de nove!",
+"alreadyloggedin" => "<strong>Usator $1, tu session ja es aperte!</strong><br />\n",
+
+"login"                        => "Aperir session",
+"userlogin"            => "Aperir session",
+"logout"               => "Clauder session",
+"userlogout"   => "Clauder session",
+"createaccount"        => "Crear nove conto",
+"badretype"            => "Le duo contrasignos que tu scribeva non coincide.",
+"userexists"   => "Le nomine de usator que tu selectionava ja es in uso. Per favor selectiona un nomine differente.",
+"youremail"            => "Tu e-mail",
+"yournick"             => "Tu pseudonymo (pro signaturas)",
+"emailforlost" => "Si tu oblida tu contrasigno, tu pote demandar un nove contrasigno via e-mail.",
+"loginerror"   => "Error in le apertura del session",
+"noname"               => "Tu non specificava un nomine de usator valide.",
+"loginsuccesstitle" => "Session aperte con successo",
+"loginsuccess" => "Tu es identificate in Wikipedia como \"$1\".",
+"nosuchuser"   => "Non existe usator registrate con le nomine \"$1\".
+Verifica le orthographia, o usa le formulario infra pro crear un nove conto de usator.",
+"wrongpassword"        => "Le contrasigno que tu scribeva es incorrecte. Per favor tenta de nove.",
+"mailmypassword" => "Demandar un nove contrasigno via e-mail",
+"passwordremindertitle" => "Nove contrasigno in Wikipedia",
+"passwordremindertext" => "Alcuno (probabilemente tu, con adresse de IP $1)
+
+demandava inviar te un nove contrasigno pro Wikipedia.
+Le contrasigno pro le usator \"$2\" ora es \"$3\".
+Nos consilia que tu initia un session e cambia le contrasigno le plus tosto possibile.",
+"noemail"              => "Non existe adresse de e-mail registrate pro le usator \"$1\".",
+"passwordsent" => "Un nove contrasigno esseva inviate al adresse de e-mail
+registrate pro \"$1\".
+Per favor initia un session post reciper lo.",
+
+# Edit pages
+#
+"summary"              => "Summario",
+"minoredit"            => "Iste es un modification minor",
+"watchthis"            => "Poner iste articulo sub observation",
+"savearticle"  => "Salvar articulo",
+"preview"              => "Previsualisar",
+"showpreview"  => "Monstrar previsualisation",
+"blockedtitle" => "Le usator es blocate",
+"blockedtext"  => "Tu nomine de usator o adresse de IP ha essite blocate per $1.
+Le motivo presentate es iste:<br />''$2''<p>Tu pote contactar $1 o un del altere
+[[Wikipedia:administratores|administratores]] pro discuter le bloco.",
+"newarticle"   => "(Nove)",
+"newarticletext" =>
+"Tu ha sequite un ligamine a un pagina que ancora non existe.
+Pro crear un nove pagina, comencia a scriber in le cassa infra.
+(Vide le [[Wikipedia:Adjuta|pagina de adjuta]] pro plus information.)
+Si tu es hic per error, simplemente clicca le button '''Retornar''' de tu navigator.",
+"anontalkpagetext" => "---- ''Iste es le pagina de discussion pro un usator anonyme qui ancora non ha create un conto o qui non lo usa. Consequentemente nos debe usar le [[adresse de IP]] numeric pro identificar le/la. Un tal adresse de IP pote esser usate in commun per varie personas. Si tu es un usator anonyme e senti que commentarios irrelevante ha essite dirigite a te, per favor [[Special:Userlogin|crea un conto o aperi un session]] pro evitar futur confusiones con altere usatores anonyme.'' ",
+"noarticletext" => "(Actualmente il non ha texto in iste pagina)",
+"updated"              => "(Actualisate)",
+"note"                 => "<strong>Nota:</strong> ",
+"previewnote"  => "Rememora te que isto es solmente un previsualisation, tu modificationes ancora non ha essite salvate!",
+"previewconflict" => "Iste previsualisation reflecte le apparentia final del texto in le area de redaction superior
+si tu opta pro salvar lo.",
+"editing"              => "Modification de $1",
+"editconflict" => "Conflicto de edition: $1",
+"explainconflict" => "Alcuno ha modificate iste pagina post que tu
+ha comenciate a modificar lo.
+Le area de texto superior contine le texto del pagina tal como illo existe actualmente.
+Tu modificationes es monstrate in le area de texto inferior.
+Tu debera incorporar tu modificationes al texto existente.
+<b>Solmente</b> le texto del area superior essera salvate
+quando tu premera \"Salvar pagina\".<br />",
+"yourtext"             => "Tu texto",
+"storedversion" => "Version immagazinate",
+"editingold"   => "<strong>ADVERTIMENTO: In iste momento tu modifica
+un version obsolete de iste pagina.
+Si tu lo salvara, tote le modificationes facite post iste revision essera perdite.</strong>",
+"yourdiff"             => "Differentias",
+"copyrightwarning" => "Nota que tote le contributiones a Wikipedia es
+considerate public secundo le terminos del Licentia de Documentation Libere GNU
+(vide plus detalios in $1).
+Si tu non vole que tu scripto sia modificate impietosemente e redistribuite
+a voluntate, alora non lo edita hic.<br />
+Additionalmente, tu nos garanti que tu es le autor de tu contributiones,
+o que tu los ha copiate de un ressource libere de derectos.
+<strong>NON USA MATERIAL COPERITE PER DERECTOS DE AUTOR (COPYRIGHT) SIN AUTORISATION EXPRESSE!</strong>",
+"longpagewarning" => "ADVERTIMENTO: Iste pagina ha $1 kilobytes de longitude;
+alcun navigatores pote presentar problemas in editar
+paginas de approximatemente o plus de 32kb.
+Considera fragmentar le pagina in sectiones minor.",
+
+# History pages
+#
+"revhistory"   => "Chronologia de versiones",
+"nohistory"            => "Iste pagina non ha versiones precedente.",
+"revnotfound"  => "Revision non trovate",
+"revnotfoundtext" => "Impossibile trovar le version anterior del pagina que tu ha demandate.
+Verifica le URL que tu ha usate pro accessar iste pagina.\n",
+"loadhist"             => "Carga del chronologia del pagina",
+"currentrev"   => "Revision currente",
+"revisionasof" => "Revision de $1",
+"cur"                  => "actu",
+"next"                 => "sequ",
+"last"                 => "prec",
+"orig"                 => "orig",
+"histlegend"   => "Legenda: (actu) = differentia del version actual,
+(prec) = differentia con le version precedente, M = modification minor",
+
+# Diffs
+#
+"difference"   => "(Differentia inter revisiones)",
+"loadingrev"   => "carga del revision pro diff",
+"lineno"               => "Linea $1:",
+"editcurrent"  => "Modificar le version actual de iste pagina",
+
+# Search results
+#
+"searchresults" => "Resultatos del recerca",
+"searchresulttext" => "Pro plus information super le recerca de {{SITENAME}}, vide [[Project:Recerca|Recerca in {{SITENAME}}]].",
+"searchquery"  => "Pro le consulta \"$1\"",
+"badquery"             => "Consulta de recerca mal formate",
+"badquerytext" => "Impossibile processar tu consulta.
+Probabilemente tu ha tentate recercar un parola con minus
+de tres litteras de longitude, situation que le systema non
+permitte. Es equalmente possibile que tu ha committite un
+error syntactic in le consulta, per exemplo,
+\"pisce and and squama\".
+Reformula tu consulta.",
+"matchtotals"  => "Le consulta \"$1\" coincide con le titulos de $2 articulos
+e le texto de $3 articulos.",
+"nogomatch" => "Non existe un pagina con iste titulo exacte, io recurre al recerca de texto integral. ",
+"titlematches" => "Coincidentias con titulos de articulos",
+"notitlematches" => "Necun coincidentia",
+"textmatches"  => "Coincidentias con textos de articulos",
+"notextmatches"        => "Necun coincidentia",
+"prevn"                        => "$1 precedentes",
+"nextn"                        => "$1 sequentes",
+"viewprevnext" => "Vider ($1) ($2) ($3).",
+"showingresults" => "Monstra de <b>$1</b> resultatos a partir de nº <b>$2</b>.",
+"nonefound"            => "<strong>Nota</strong>: recercas frustrate frequentemente
+es causate per le inclusion de vocabulos commun como \"que\" e \"illo\",
+que non es includite in le indice, o per le specification de plure
+terminos de recerca (solmente le paginas que contine tote le terminos
+de recerca apparera in le resultato).",
+"powersearch" => "Recercar",
+"powersearchtext" => "
+Recerca in contextos :<br />
+$1<br />
+$2 Listar redireciones &nbsp; Recercar pro $3 $9",
+
+
+# Preferences page
+#
+"preferences"  => "Preferentias",
+"prefsnologin" => "Session non aperte",
+"prefsnologintext"     => "Tu debe [[Special:Userlogin|aperir un session]]
+pro definir tu preferentias.",
+"prefslogintext" => "Tu es identificate como \"$1\".
+Tu numero interne de ID es $2.",
+"prefsreset"   => "Tu preferentias salvate previemente ha essite restaurate.",
+"qbsettings"   => "Configuration del barra de utensiles",
+"changepassword" => "Cambiar contrasigno",
+"skin"                 => "Apparentia",
+"math"                 => "Exhibition de formulas",
+"math_failure"         => "Impossibile analysar",
+"math_unknown_error"   => "error incognite",
+"math_unknown_function"        => "function incognite ",
+"math_lexing_error"    => "error lexic",
+"math_syntax_error"    => "error syntactic",
+"saveprefs"            => "Salvar preferentias",
+"resetprefs"   => "Restaurar preferentias",
+"oldpassword"  => "Contrasigno actual",
+"newpassword"  => "Nove contrasigno",
+"retypenew"            => "Confirmar nove contrasigno",
+"textboxsize"  => "Dimensiones del cassa de texto",
+"rows"                 => "Lineas",
+"columns"              => "Columnas",
+"searchresultshead" => "Configuration del resultatos de recerca",
+"resultsperpage" => "Coincidentias per pagina",
+"contextlines" => "Lineas per coincidentia",
+"contextchars" => "Characteres de contexto per linea",
+"stubthreshold" => "Limite pro exhibition residual",
+"recentchangescount" => "Quantitate de titulos in modificationes recente",
+"savedprefs"   => "Tu preferentias ha essite salvate.",
+"timezonetext" => "Scribe le differentia de horas inter tu fuso horari
+e illo del servitor (UTC).",
+"localtime"    => "Hora local",
+"timezoneoffset" => "Differentia de fuso horari",
+"emailflag"            => "Non reciper e-mail de altere usatores",
+
+# Recent changes
+#
+"changes" => "modificationes",
+"recentchanges" => "Modificationes recente",
+"recentchangestext" => "Seque le plus recente modificationes a Wikipedia in iste pagina.
+[[Wikipedia:Benvenite,_novicios|Benvenite, novicios]]!
+Per favor lege equalmente iste paginas: [[wikipedia:Questiones_frequente|Questiones frequente super Wikipedia]],
+[[Wikipedia:Politicas e directivas|Politica de Wikipedia]]
+(specialmente [[wikipedia:Conventiones de nomenclatura|conventiones de nomenclatura]],
+[[wikipedia:Neutralitate e objectivitate|neutralitate e objectivitate]]),
+e [[wikipedia:Le passos false plus commun|le passos false plus commun]].
+
+Si tu vole que Wikipedia habe successo, es multo importante que tu non
+include material protegite per [[wikipedia:Copyright|derectos de autor]].
+Le aspectos legal connexe poterea prejudicar gravemente le projecto,
+alora per favor non lo face.",
+"rcloaderr"            => "Carga del modificationes recente",
+"rcnote"               => "Infra es le <strong>$1</strong> ultime modificationes in le <strong>$2</strong> ultime dies.",
+"rcnotefrom"   => "infra es le modificationes a partir de <b>$2</b> (usque a <b>$1</b>).",
+"rclistfrom"   => "Monstrar nove modificationes a partir de $1",
+# "rclinks"            => "Monstrar le $1 ultime modificationes in le $2 ultime horas / $3 ultime dias",
+"rclinks"              => "Monstrar le $1 ultime modificationes in le $2 ultime days.",
+"rchide"               => "in forma de $4; $1 modificationes minor; $2 contextos secundari; $3 modificationes multiple.",
+"diff"                 => "diff",
+"hist"                 => "prec",
+"hide"                 => "occultar",
+"show"                 => "monstrar",
+"tableform"            => "tabella",
+"listform"             => "lista",
+"nchanges"             => "$1 modificationes",
+"minoreditletter" => "M",
+"newpageletter" => "N",
+
+# Upload
+#
+"upload"               => "Cargar file",
+"uploadbtn"            => "Cargar file",
+"uploadlink"   => "Cargar imagines",
+"reupload"             => "Recargar",
+"reuploaddesc" => "Retornar al formulario de carga.",
+"uploadnologin" => "Session non aperte",
+"uploadnologintext"    => "Tu debe [[Special:Userlogin|aperir un session]]
+pro poter cargar files.",
+"uploaderror"  => "Error de carga",
+"uploadtext"   => "'''STOP!''' Ante cargar files al servitor,
+prende cognoscentia del
+[[Project:Image_use_policy|politica de Wikipedia super le uso de imagines]],
+e assecura te de respectar lo.
+
+Pro vider o recercar imagines cargate previemente,
+vade al [[Special:Imagelist|lista de imagines cargate]].
+Cargas e eliminationes es registrate in le
+[[Project:Upload_log|registro de cargas]].
+
+Usa le formulario infra pro cargar nove files de imagine pro
+illustrar tu articulos.
+In le major parte del navigatores, tu videra un button \"Browse...\",
+que facera apparer le cassa de dialogo de apertura de files
+standard de tu systema de operation. Selectiona un file pro
+inserer su nomine in le campo de texto adjacente al button.
+Tu debe additionalmente marcar le quadrato con le qual tu
+declara que tu non viola derectos de autor per medio del carga
+del file.
+Preme le button \"Cargar\" pro initiar le transmission.
+Le carga pote prender alcun tempore si tu connexion al Internet
+es lente.
+
+Le formatos preferite es JPEG pro imagines photographic,
+PNG pro designos e altere imagines iconic, e OGG pro sonos.
+Per favor, attribue nomines descriptive a tu files pro evitar
+confusion.
+Pro includer le imagine in un articulo, usa un ligamine in
+le forma '''<nowiki>[[image:file.jpg]]</nowiki>''' o
+'''<nowiki>[[image:file.png|texto alternative]]</nowiki>''' o
+'''<nowiki>[[media:file.ogg]]</nowiki>''' pro sonos.
+
+Nota que, justo como occurre con le paginas de Wikipedia, alteros
+pote modificar o eliminar le files cargate si illes considera que
+isto beneficia le encyclopedia, e tu pote haber tu derecto
+de carga blocate si tu abusa del systema.",
+"uploadlog"            => "registro de cargas",
+"uploadlogpage" => "Registro_de_cargas",
+"uploadlogpagetext" => "Infra es un lista del plus recente cargas de files.
+Tote le tempores monstrate es in le fuso horari del servitor (UCT).
+<ul>
+</ul>
+",
+"filename"             => "Nomine del file",
+"filedesc"             => "Description",
+"copyrightpage" => "Wikipedia:Copyright",
+"copyrightpagename" => "Wikipedia e derectos de autor (copyright)",
+"uploadedfiles"        => "Files cargate",
+"ignorewarning"        => "Ignorar advertimentos e salvar le file totevia.",
+"minlength"            => "Le nomines de imagines debe haber al minus tres litteras.",
+"badfilename"  => "Le nomine del imagine esseva cambiate a \"$1\".",
+"badfiletype"  => "\".$1\" non es un formato de file de imagine recommendate.",
+"largefile"            => "Es recommendabile que le imagines non excede 100kb.",
+"successfulupload" => "Carga complete",
+"fileuploaded" => "File \"$1\" cargate sin problemas.
+Per favor clicca hic: ($2) pro accessar le pagina de description
+e fornir information super le file, tal como su origine,
+quando illo esseva create e per qui, e toto plus que tu sape
+a su proposito.",
+"uploadwarning" => "Advertimento de carga",
+"savefile"             => "Salvar file",
+"uploadedimage" => "\"[[$1]]\" cargate",
+
+# Image list
+#
+"imagelist"            => "Lista de imagines",
+"imagelisttext"        => "Infra es un lista de $1 imagines ordinate $2.",
+"getimagelist" => "recuperation del lista de imagines",
+"ilsubmit"             => "Recercar",
+"showlast"             => "Monstrar le ultime $1 imagines ordinate $2.",
+"byname"               => "per nomine",
+"bydate"               => "per data",
+"bysize"               => "per dimension",
+"imgdelete"            => "elim",
+"imgdesc"              => "desc",
+"imglegend"            => "Legenda: (desc) = monstrar/modificar description del imagine.",
+"imghistory"   => "Chronologia del imagine",
+"revertimg"            => "rev",
+"deleteimg"            => "elim",
+"deleteimgcompletely"          => "elim",
+"imghistlegend" => "Legend: (actu) = iste es le imagine actual, (elim) = elimina
+iste version antique, (rev) = reverte a iste version antique.
+<br /><i>Clica super le data pro vider le imagine cargate in ille die.</i>",
+"imagelinks"   => "Ligamines al imagine",
+"linkstoimage" => "Le paginas sequente se liga a iste imagine:",
+"nolinkstoimage" => "Necun pagina se liga a iste imagine.",
+
+# Statistics
+#
+"statistics"   => "Statisticas",
+"sitestats"            => "Statisticas de accesso",
+"userstats"            => "Statisticas de usator",
+"sitestatstext" => "Le base de datos contine un total de <b>$1</b> paginas.
+Iste numero include paginas de \"discussion\", paginas super Wikipedia, paginas de \"residuo\"
+minime, paginas de redirection, e alteres que probabilemente non se qualifica como articulos.
+A parte de istes, il ha <b>$2</b> paginas que probabilemente es
+articulos legitime.<p>
+Il habeva un total de <b>$3</b> visitas a paginas, e <b>$4</b> modificationes de paginas
+desde le actualisation del systema (20 de julio 2002).
+Isto representa un media de <b>$5</b> modificationes per pagina, e <b>$6</b> visitas per modification.",
+"userstatstext" => "Il ha <b>$1</b> usatores registrate,
+del quales <b>$2</b> es administratores (vide $3).",
+
+# Maintenance Page
+#
+"maintenance"          => "Pagina de mantenentia",
+"maintnancepagetext"   => "Iste pagina include plure utensiles commode pro le mantenentia quotidian del encyclopedia.
+Alcunes del functiones tende a tensionar le base de datos, pro isto per favor
+non preme \"Reload\" post cata item reparate. ;-)",
+"maintenancebacklink"  => "Retornar al pagina de mantenentia",
+"disambiguations"      => "Paginas de disambiguation",
+"disambiguationspage"  => "Wikipedia:Ligamines_a_paginas_de_disambiguation",
+"disambiguationstext"  => "Le articulos sequente se liga a un <i>pagina de disambiguation</i>.
+Illos deberea ligar se directemente al topico appropriate.<br />
+Un pagina es tractate como un pagina de disambiguation si existe un ligamine
+a illo in $1. Ligamines de altere contextos <i>non</i> es listate hic.",
+"doubleredirects"      => "Redirectiones duple",
+"doubleredirectstext"  => "<b>Attention:</b> Iste lista pote continer items false.
+Illo generalmente significa que il ha texto additional con ligamines sub le prime #REDIRECT.<br />
+Cata linea contine ligamines al prime e secunde redirection, assi como le prime linea del
+secunde texto de redirection, generalmente exhibiente le articulo scopo \"real\",
+al qual le prime redirection deberea referer se.",
+"brokenredirects"      => "Redirectiones van",
+"brokenredirectstext"  => "Le redirectiones sequente se liga a articulos inexistente.",
+"selflinks"            => "Paginas con ligamines circular",
+"selflinkstext"                => "Le paginas sequente contine un ligamine a se mesme, lo que non se recommenda.",
+"mispeelings"           => "Paginas con errores orthographic",
+"mispeelingstext"               => "Le paginas sequente contine un error orthographic commun, que es listate in $1. Illo debe esser substituite per le orthographia correcte (assi).",
+"mispeelingspage"       => "Lista de errores orthographic commun",
+"missinglanguagelinks"  => "Ligamines interlinguistic absente",
+"missinglanguagelinksbutton"    => "Trovar ligamines interlinguistic mancante pro",
+"missinglanguagelinkstext"      => "Iste articulos <i>non</i> se liga a lor equivalentes in $1. Redirectiones e subpaginas <i>non</i> es monstrate.",
+
+
+# Miscellaneous special pages
+#
+"orphans"              => "Paginas orphanas",
+"lonelypages"  => "Paginas orphanas",
+"unusedimages" => "Imagines non usate",
+"popularpages" => "Paginas popular",
+"nviews"               => "$1 visitas",
+"wantedpages"  => "Paginas plus demandate",
+"nlinks"               => "$1 ligamines",
+"allpages"             => "Tote le paginas",
+"randompage"   => "Pagina aleatori",
+"shortpages"   => "Paginas curte",
+"longpages"            => "Paginas longe",
+"listusers"            => "Lista de usatores",
+"specialpages" => "Paginas special",
+"spheading"            => "Paginas special",
+"protectpage"  => "Proteger pagina",
+"recentchangeslinked" => "Modificationes correlate",
+"rclsub"               => "(a paginas ligate a partir de \"$1\")",
+"debug"                        => "Reparar disfunctiones",
+"newpages"             => "Nove paginas",
+"movethispage" => "Mover iste pagina",
+"unusedimagestext" => "<p>Nota que altere sitos del web
+tal como le Wikipedias international pote ligar se a un imagine
+con un URL directe, e consequentemente illos pote esser listate
+hic malgrado esser in uso active.",
+"booksources"  => "Fornitores de libros",
+"booksourcetext" => "Infra es un lista de ligamines a altere sitos que
+vende libros nove e usate, e pote haber information ulterior super
+libros que tu cerca.
+Wikipedia non es associate a iste interprisas, e iste lista
+non debe esser interpretate como alcun appoio special.",
+
+# Email this user
+#
+"mailnologin"  => "Necun adresse de invio",
+"mailnologintext" => "Tu debe [[Special:Userlogin|aperir un session]]
+e haber un adresse de e-mail valide in tu [[Special:Preferences|preferentias]]
+pro inviar e-mail a altere usatores.",
+"emailuser"            => "Inviar e-mail a iste usator",
+"emailpage"            => "Inviar e-mail al usator",
+"emailpagetext"        => "Si iste usator forniva un adresse de e-mail valide in
+su preferentias de usator, le formulario infra le/la inviara un message.
+Le adresse de e-mail que tu forniva in tu preferentias de usator apparera
+como le adresse del expeditor del e-mail, a fin que le destinatario
+pote responder te.",
+"noemailtitle" => "Necun adresse de e-mail",
+"noemailtext"  => "Iste usator non ha specificate un adresse de e-mail valide,
+o ha optate pro non reciper e-mail de altere usatores.",
+"emailfrom"            => "De",
+"emailto"              => "A",
+"emailsubject" => "Subjecto",
+"emailmessage" => "Message",
+"emailsend"            => "Inviar",
+"emailsent"            => "E-mail inviate",
+"emailsenttext" => "Tu message de e-mail ha essite inviate.",
+
+# Watchlist
+#
+"watchlist"            => "Paginas sub observation",
+"watchlistsub" => "(pro usator \"$1\")",
+"nowatchlist"  => "Tu non ha paginas sub observation.",
+"watchnologin" => "Session non aperte",
+"watchnologintext"     => "Tu debe [[Special:Userlogin|aperir un session]]
+pro modificar tu lista de paginas sub observation.",
+"addedwatch"   => "Ponite sub observation",
+"addedwatchtext" => "Le pagina \"$1\" es ora in tu <a href=\"" .
+  "{{localurle:Special:Watchlist}}\">lista de paginas sub observation</a>.
+Modificationes futur a iste pagina e su pagina de discussion associate essera listate la,
+e le pagina apparera <b>in nigretto</b> in le <a href=\"" .
+  "{{localurle:Special:Recentchanges}}\">lista de modificationes recente</a> pro
+facilitar su identification.</p>
+
+<p>Si tu vole cessar le obsevation de iste pagina posteriormente, clicca \"Cancellar observation\" in le barra de navigation.",
+"removedwatch" => "Observation cancellate",
+"removedwatchtext" => "Le pagina \"$1\" non es plus sub observation.",
+"watchthispage"        => "Poner iste pagina sub observation",
+"unwatchthispage" => "Cancellar observation",
+"notanarticle" => "Non es un articulo",
+
+# Delete/protect/revert
+#
+"deletepage"   => "Eliminar pagina",
+"confirm"              => "Confirmar",
+"confirmdelete" => "Confirmar elimination",
+"deletesub"            => "(Elimination de \"$1\")",
+"confirmdeletetext" => "Tu es a puncto de eliminar permanentemente un pagina
+o imagine del base de datos, conjunctemente con tote su chronologia de versiones.
+Per favor, confirma que, si tu intende facer lo, tu comprende le consequentias,
+e tu lo face de accordo con [[Wikipedia:Policy]].",
+"actioncomplete" => "Action complete",
+"deletedtext"  => "\"$1\" ha essite eliminate.
+Vide $2 pro un registro de eliminationes recente.",
+"deletedarticle" => "\"$1\" eliminate",
+"dellogpage"   => "Registro_de_eliminationes",
+"dellogpagetext" => "Infra es un lista del plus recente eliminationes.
+Tote le horas es in le fuso horari del servitor (UTC).
+<ul>
+</ul>
+",
+"deletionlog"  => "registro de eliminationes",
+"reverted"             => "Revertite a revision anterior",
+"deletecomment"        => "Motivo del elimination",
+"imagereverted" => "Reversion con successo a version anterior.",
+"rollback"             => "Revocar modificationes",
+"rollbacklink" => "revocar",
+"cantrollback" => "Impossibile revocar le modification; le ultime contribuente es le unic autor de iste articulo.",
+"revertpage"   => "Revertite al ultime modification per $1",
+
+# Undelete
+"undelete" => "Restaurar pagina eliminate",
+"undeletepage" => "Vider e restaurar paginas eliminate",
+"undeletepagetext" => "Le paginas sequente ha essite eliminate mais ancora es in le archivo e
+pote esser restaurate. Le archivo pote esser evacuate periodicamente.",
+"undeletearticle" => "Restaurar articulo eliminate",
+"undeleterevisions" => "$1 revisiones archivate",
+"undeletehistory" => "Si tu restaura un pagina, tote le revisiones essera restaurate al chronologia.
+Si un nove pagina con le mesme nomine ha essite create post le elimination, le revisiones
+restaurate apparera in le chronologia anterior, e le revision currente del pagina in vigor
+non essera automaticamente substituite.",
+"undeleterevision" => "Revision eliminate in $1",
+"undeletebtn" => "Restautar!",
+"undeletedarticle" => "\"$1\" restaurate",
+"undeletedtext"   => "Le articulo [[$1]] ha essite restaurate con successo.
+Vide [[Wikipedia:Registro_de_eliminationes]] pro un registro de eliminationes e restaurationes recente.",
+
+# Contributions
+#
+"contributions"        => "Contributiones de usator",
+"mycontris" => "Mi contributiones",
+"contribsub"   => "Pro $1",
+"nocontribs"   => "Necun modification ha essite trovate secundo iste criterios.",
+"ucnote"               => "Infra es le <b>$1</b> ultime modificationes de iste usator in le <b>$2</b> ultime dies.",
+"uclinks"              => "Vider le $1 ultime modificationes; vider le $2 ultime dies.",
+"uctop"                => " (alto)" ,
+
+# What links here
+#
+"whatlinkshere"        => "Referentias a iste pagina",
+"notargettitle" => "Sin scopo",
+"notargettext" => "Tu non ha specificate un pagina o usator super le qual
+executar iste function.",
+"linklistsub"  => "(Lista de ligamines)",
+"linkshere"            => "Le paginas sequente se liga a iste pagina:",
+"nolinkshere"  => "Necun pagina se liga a iste.",
+"isredirect"   => "pagina de redirection",
+
+# Block/unblock IP
+#
+"blockip"              => "Blocar adresse IP",
+"blockiptext"  => "Usa le formulario infra pro blocar le accesso de scriptura
+a partir de un adresse IP specific.
+Isto debe esser facite solmente pro impedir vandalismo, e de
+accordo con le [[Wikipedia:Policy|politica de Wikipedia]].
+Scribe un motivo specific infra (per exemplo, citante paginas
+specific que ha essite vandalisate).",
+"ipaddress"            => "Adresse IP",
+"ipbreason"            => "Motivo",
+"ipbsubmit"            => "Blocar iste adresse",
+"badipaddress" => "Adresse IP mal formate.",
+"blockipsuccesssub" => "Blocage con successo",
+"blockipsuccesstext" => "Le adresse IP \"$1\" ha essite blocate.
+<br />Vide [[Special:Ipblocklist|Lista de IPs blocate]] pro revider le blocages.",
+"unblockip"            => "Disblocar adresse IP",
+"unblockiptext"        => "Usa le formulario infra pro restaurar le accesso de scriptura
+a un adresse de IP blocate previemente.",
+"ipusubmit"            => "Disbloca iste adresse",
+"ipusuccess"   => "Adresse IP \"$1\" disblocate",
+"ipblocklist"  => "Lista de adresses IP blocate",
+"blocklistline"        => "$1, $2 ha blockate $3 ($4)",
+"blocklink"            => "blocar",
+"unblocklink"  => "disblocar",
+"contribslink" => "contributiones",
+
+# Developer tools
+#
+"lockdb"               => "Blocar base de datos",
+"unlockdb"             => "Disblocar base de datos",
+"lockdbtext"   => "Le blocage del base de datos suspendera le capacitate de tote
+le usatores de modificar paginas, modificar lor preferentias e listas de paginas sub observation,
+e altere actiones que require modificationes in le base de datos.
+Per favor confirma que iste es tu intention, e que tu disblocara le
+base de datos immediatemente post completar tu mantenentia.",
+"unlockdbtext" => "Le disblocage del base de datos restaurara le capacitate de tote
+le usatores de modificar paginas, modificar lor preferentias e listas de paginas sub observation,
+e altere actiones que require modificationes in le base de datos.
+Per favor confirma que iste es tu intention.",
+"lockconfirm"  => "Si, io realmente vole blocar le base de datos.",
+"unlockconfirm"        => "Si, io realmente vole disblocar le base de datos.",
+"lockbtn"              => "Blocar base de datos",
+"unlockbtn"            => "Disblocar base de datos",
+"locknoconfirm" => "Tu non ha marcate le quadrato de confirmation.",
+"lockdbsuccesssub" => "Base de datos blocate con successo",
+"unlockdbsuccesssub" => "Base de datos disblocate con successo",
+"lockdbsuccesstext" => "Le base de datos de Wikipedia ha essite blocate.
+<br />Rememora te de disblocar lo post completar tu mantenentia.",
+"unlockdbsuccesstext" => "Le base de datos de Wikipedia ha essite disblocate.",
+
+# Move page
+#
+"movepage"             => "Mover pagina",
+"movepagetext" => "Per medio del formulario infra tu pote renominar un pagina,
+movente tote su chronologia al nove nomine.
+Le titulo anterior devenira un pagina de redirection al nove titulo.
+Le ligamines al pagina anterior non essera modificate;
+assecura te de verificar le apparition de redirectiones duple o van.
+Tu es responsabile pro assecurar que le ligamines continua a punctar a ubi illos deberea.
+
+Nota que le pagina '''non''' essera movite si ja existe un pagina
+sub le nove titulo, salvo si illo es vacue o un redirection e non
+ha un chronologia de modificationes passate. Isto significa que tu
+pote renominar un pagina a su titulo original si tu lo ha renominate
+erroneemente, e que tu non pote superscriber un pagina existente.
+
+<b>ADVERTIMENTO!</b>
+Isto pote esser un cambio drastic e inexpectate pro un pagina popular;
+per favor assecura te que tu comprende le consequentias de isto
+ante proceder.",
+"movepagetalktext" => "Le pagina de discussion associate, si existe, essera automaticamente movite conjunctemente con illo '''a minus que''':
+*Tu move le pagina trans contextos,
+*Un pagina de discussion non vacue ja existe sub le nove nomine, o
+*Tu dismarca le quadrato infra.
+
+Il tal casos, tu debera mover o fusionar le pagina manualmente si desirate.",
+"movearticle"  => "Mover pagina",
+"movenologin"  => "Session non aperte",
+"movenologintext" => "Tu debe esser un usator registrate e [[Special:Userlogin|aperir un session]]
+pro mover un pagina.",
+"newtitle"             => "Al nove titulo",
+"movepagebtn"  => "Mover pagina",
+"pagemovedsub" => "Pagina movite con successo",
+"pagemovedtext" => "Pagina \"[[$1]]\" movite a \"[[$2]]\".",
+"articleexists" => "Un pagina con iste nomine ja existe, o le
+nomine selectionate non es valide.
+Per favor selectiona un altere nomine.",
+"talkexists"   => "Le pagina mesme ha essite movite con successo, mais le
+pagina de discussion associate non ha essite movite proque ja existe un sub le
+nove titulo. Per favor fusiona los manualmente.",
+"movedto"              => "movite a",
+"movetalk"             => "Mover le pagina de \"discussion\" tamben, si applicabile.",
+"talkpagemoved" => "Le pagina de discussion correspondente tamben ha essite movite.",
+"talkpagenotmoved" => "Le pagina de discussion correspondente <strong>non</strong> ha essite movite.",
+
+# Math
+
+'mw_math_png' => "Sempre produce PNG",
+'mw_math_simple' => "HTML si multo simple, alteremente PNG",
+'mw_math_html' => "HTML si possibile, alteremente PNG",
+'mw_math_source' => "Lassa lo como TeX (pro navigatores in modo texto)",
+'mw_math_modern' => "Recommendate pro navigatores moderne",
+'mw_math_mathml' => 'MathML',
+
+);
+
+require_once( "LanguageUtf8.php" );
+
+class LanguageIa extends LanguageUtf8 {
+
+       function getNamespaces() {
+               global $wgNamespaceNamesIa;
+               return $wgNamespaceNamesIa;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsIa;
+               return $wgQuickbarSettingsIa;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesIa;
+               return $wgSkinNamesIa;
+       }
+
+       function date( $ts, $adj = false ) {
+               if ( $adj ) { $ts = $this->userAdjust( $ts ); }
+
+               $d = $this->getMonthAbbreviation( substr( $ts, 4, 2 ) ) .
+                 " " . (0 + substr( $ts, 6, 2 )) . ", " .
+                 substr( $ts, 0, 4 );
+               return $d;
+       }
+
+       function timeanddate( $ts, $adj = false ) {
+               return $this->time( $ts, $adj ) . " " . $this->date( $ts, $adj );
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesIa, $wgAllMessagesEn;
+               $m = $wgAllMessagesIa[$key];
+
+               if ( "" == $m ) { return $wgAllMessagesEn[$key]; }
+               else return $m;
+       }
+
+}
+
+?>
diff --git a/languages/LanguageId.php b/languages/LanguageId.php
new file mode 100644 (file)
index 0000000..2b6b28d
--- /dev/null
@@ -0,0 +1,1212 @@
+<?php
+#
+# This localisation is originally based on a file kindly donated by the folks at MIMOS
+# http://www.asiaosc.org/enwiki/page/Knowledgebase_Home.html
+#
+
+
+require_once( "LanguageUtf8.php" );
+
+/* private */ $wgNamespaceNamesId = array(
+       NS_MEDIA            => "Media",
+       NS_SPECIAL          => "Istimewa",
+       NS_MAIN             => "",
+       NS_TALK             => "Bicara",
+       NS_USER             => "Pengguna",
+       NS_USER_TALK        => "Bicara_Pengguna",
+       NS_PROJECT          => $wgMetaNamespace,
+       NS_PROJECT_TALK     => "Pembicaraan_" . $wgMetaNamespace,
+       NS_IMAGE            => "Gambar",
+       NS_IMAGE_TALK       => "Pembicaraan_Gambar",
+       NS_MEDIAWIKI        => "MediaWiki",
+       NS_MEDIAWIKI_TALK   => "Pembicaraan_MediaWiki",
+       NS_TEMPLATE         => "Templat",
+       NS_TEMPLATE_TALK    => "Pembicaraan_Templat",
+       NS_HELP             => "Bantuan",
+       NS_HELP_TALK        => "Pembicaraan_Bantuan",
+       NS_CATEGORY         => "Kategori",
+       NS_CATEGORY_TALK    => "Pembicaraan_Kategori"
+) + $wgNamespaceNamesEn;
+
+# For backwards compatibility: some talk namespaces were
+# changed in 1.4.4 from their previous values, here:
+$wgNamespaceAlternatesId = array(
+       NS_IMAGE_TALK       => "Gambar_Pembicaraan",
+       NS_MEDIAWIKI_TALK   => "MediaWiki_Pembicaraan",
+       NS_TEMPLATE_TALK    => "Templat_Pembicaraan",
+       NS_HELP_TALK        => "Bantuan_Pembicaraan",
+       NS_CATEGORY_TALK    => "Kategori_Pembicaraan"
+);
+
+/* private */ $wgQuickbarSettingsId = array(
+       "Tidak ada", "Tetap sebelah kiri", "Tetap sebelah kanan", "Mengambang sebelah kiri"
+);
+
+/* private */ $wgSkinNamesId = array(
+       'standard'    => "Standar",
+) + $wgSkinNamesEn;
+
+# Validation types
+$wgValidationTypesId = array (
+       '0' => "Gaya tulisan|Sangat buruk|Sangat baik|5",
+       '1' => "Legalitas|Ilegal|Legal|5",
+       '2' => "Kelengkapan|Stub|Sangat lengkap|5",
+       '3' => "Fakta|Meragukan|Kuat|5",
+       '4' => "Layak untuk 1.0 (Cetak)|Tidak|Ya|2",
+       '5' => "Layak untuk 1.0 (CD)|Tidak|Ya|2"
+);
+
+/* private */ $wgDateFormatsId = array();
+
+/* private */ $wgBookstoreListId = array(
+       # Local bookstores
+       "Gramedia Cyberstore (via Google)" => 'http://www.google.com/search?q=%22ISBN+:+$1%22+%22product_detail%22+site:www.gramediacyberstore.com+OR+site:www.gramediaonline.com+OR+site:www.kompas.com&hl=id',
+       "Bhinneka.com bookstore" => 'http://www.bhinneka.com/Buku/Engine/search.asp?fisbn=$1',
+
+       //# Default (EN) Bookstores
+       //"AddALL" => "http://www.addall.com/New/Partner.cgi?query=$1&type=ISBN",
+       //"PriceSCAN" => "http://www.pricescan.com/books/bookDetail.asp?isbn=$1",
+       //"Barnes & Noble" => "http://search.barnesandnoble.com/bookSearch/isbnInquiry.asp?isbn=$1",
+       //"Amazon.com" => "http://www.amazon.com/exec/obidos/ISBN=$1"
+) + $wgBookstoreListEn;
+
+/* private */ $wgAllMessagesId = array(
+# User preference toggles
+
+'tog-underline' => 'Garisbawahi pautan',
+'tog-highlightbroken' => 'Beri tanda pautan yang berpaut ke topik kosong <a href="" class="new">seperti ini</a> (alternatif: seperti ini<a href="" class="internal">?</a>)',
+'tog-justify'   => 'Ratakan paragraf',
+'tog-hideminor' => 'Sembunyikan suntingan kecil dalam perubahan terbaru',
+'tog-usenewrc' => 'Tampilkan perubahan terbaru dalam tampilan yang lebih baik (tidak untuk semua browser)',
+'tog-numberheadings' => 'Beri nomor judul secara otomatis',
+'tog-showtoolbar' => 'Tampilkan batang alat penyuntingan',
+'tog-editondblclick' => 'Sunting halaman dengan klik ganda (JavaScript)',
+'tog-editsection'=> 'Sunting bagian melalui pautan [edit]',
+'tog-editsectiononrightclick' => 'Sunting bagian dengan mengklik kanan<br />judul bagian (JavaScript)',
+'tog-showtoc' => 'Tampilkan daftar isi<br />(untuk artikel yang mempunyai lebih dari 3 judul)',
+'tog-rememberpassword' => 'Ingat kata sandi pada setiap sesi',
+'tog-editwidth' => 'Kotak sunting memiliki lebar penuh',
+'tog-watchdefault' => 'Tambahkan halaman yang Anda sunting ke daftar pemantauan',
+'tog-minordefault' => 'Tandai semua suntingan sebagai suntingan kecil secara baku',
+'tog-previewontop' => 'Tampilkan pratilik sebelum kotak sunting dan bukan sesudahnya',
+'tog-previewonfirst' => 'Tampilkan pratilik pada suntingan pertama',
+'tog-nocache' => 'Matikan cache halaman',
+'tog-fancysig' => 'Tanda tangan teks murni',
+
+# dates
+'sunday' => 'Minggu',
+'monday' => 'Senin',
+'tuesday' => 'Selasa',
+'wednesday' => 'Rabu',
+'thursday' => 'Kamis',
+'friday' => "Jumat",
+'saturday' => 'Sabtu',
+'january' => 'Januari',
+'february' => 'Februari',
+'march' => 'Maret',
+'april' => 'April',
+'may_long' => 'Mei',
+'june' => 'Juni',
+'july' => 'Juli',
+'august' => 'Agustus',
+'september' => 'September',
+'october' => 'Oktober',
+'november' => 'November',
+'december' => 'Desember',
+'jan' => 'Jan',
+'feb' => 'Feb',
+'mar' => 'Mar',
+'apr' => 'Apr',
+'may' => 'Mei',
+'jun' => 'Jun',
+'jul' => 'Jul',
+'aug' => 'Agt',
+'sep' => 'Sep',
+'oct' => 'Okt',
+'nov' => 'Nov',
+'dec' => 'Des',
+# Bits of text used by many pages:
+#
+"categories" => "Kategori",
+"category" => "kategori",
+"category_header" => "Artikel dalam kategori \"$1\"",
+"subcategories" => "Subkategori",
+
+"linktrail" => "/^([a-z]+)(.*)\$/sD",
+"mainpage" => "Halaman Utama",
+"mainpagetext" => "Perangkat lunak wiki berhasil dipasang.",
+"mainpagedocfooter" => "Silakan lihat [http://meta.wikipedia.org/wiki/MediaWiki_i18n dokumentasi tentang kastamisasi antarmuka] dan [http://meta.wikipedia.org/wiki/MediaWiki_User%27s_Guide petunjuk pengguna] untuk bantuan pemakaian dan konfigurasi.",
+
+'portal' => 'Portal Komunitas',
+'portal-url' => 'Project:Portal_Komunitas',
+"about" => "Tentang",
+"aboutsite" => "Tentang {{SITENAME}}",
+"aboutpage" => "Project:Tentang",
+'article' => 'Artikel',
+"help" => "Bantuan",
+"helppage" => "Help:Isi",
+"bugreports" => "Laporan Bug",
+"bugreportspage" => "Project:Laporan_Bug",
+"sitesupport" => "-", # "-" untuk mematikan
+"sitesupport-url" => "Project:Sumbangan",
+"faq" => "FAQ",
+"faqpage" => "Project:FAQ",
+"edithelp" => "Bantuan penyuntingan",
+"newwindow" => "(terbuka dalam jendela baru)",
+"edithelppage" => "Help:Penyuntingan",
+"cancel" => "Batalkan",
+"qbfind" => "Cari",
+"qbbrowse" => "Lihat-lihat",
+"qbedit" => "Sunting",
+"qbpageoptions" => "Pilihan halaman",
+"qbpageinfo" => "Informasi halaman",
+"qbmyoptions" => "Pilihan saya",
+"qbspecialpages" => "Halaman istimewa",
+"mypage" => "Halaman saya",
+"moredotdotdot" => "Lebih lanjut...",
+"mytalk" => "Pembicaraan saya",
+"anontalk" => "Pembicaraan IP ini",
+'navigation' => 'Navigasi',
+"currentevents" => "Kejadian Terkini",
+'currentevents-url' => 'Kejadian Terkini',
+"disclaimers" => "Penyangkalan",
+"disclaimerpage" => "Project:Penyangkalan_Umum",
+"errorpagetitle" => "Kesalahan",
+"returnto" => "Kembali ke $1.",
+"tagline" => "Dari {{SITENAME}}",
+"whatlinkshere" => "Halaman yang berpaut ke sini",
+"help" => "Bantuan",
+"search" => "Cari",
+"go" => "Tampil",
+"history" => "Sejarah halaman",
+'history_short' => 'Sejarah',
+'info_short' => 'Informasi',
+"printableversion" => "Versi untuk dicetak",
+'edit' => 'Sunting',
+"editthispage" => "Sunting halaman ini",
+'delete' => 'Hapus',
+"deletethispage" => "Hapus halaman ini",
+"undelete_short" => "Undelete",
+'protect' => 'Lindungi',
+"protectthispage" => "Lindungi halaman ini",
+'unprotect' => 'Hilangkan Perlindungan',
+"unprotectthispage" => "Hilangkan perlindungan",
+"newpage" => "(buat) Halaman baru",
+"talkpage" => "Diskusikan halaman ini",
+'specialpage' => 'Halaman Istimewa',
+'personaltools' => 'Alat pribadi',
+"postcomment" => "Kirim komentar",
+"addsection" => "+",
+"articlepage" => "Lihat artikel",
+"subjectpage" => "Halaman subjek",
+'talk' => 'Diskusi',
+'toolbox' => 'Kotak peralatan',
+"userpage" => "Lihat halaman pengguna",
+"wikipediapage" => "Lihat halaman meta",
+"imagepage" => "Lihat halaman gambar",
+"viewtalkpage" => "Lihat diskusi",
+"otherlanguages" => "Bahasa lain",
+"redirectedfrom" => "(Dialihkan dari $1)",
+"lastmodified" => "Halaman ini terakhir diubah pada $1.",
+"viewcount" => "Halaman ini telah diakses sebanyak $1 kali.",
+"copyright" => "Isi tersedia dibawah $1.",
+"poweredby" => "{{SITENAME}} berjalan dibawah [http://www.mediawiki.org/ MediaWiki], sebuah engine wiki open-source.",
+"printsubtitle" => "(Dari {{SERVER}})",
+"protectedpage" => "Halaman yang dilindungi",
+"administrators" => "Project:Administrator",
+"sysoptitle" => "Akses Sysop Diperlukan",
+"sysoptext" => "Tindakan yang Anda minta hanya dapat dilakukan oleh pengguna dengan status \"sysop\". Lihat $1.",
+"developertitle" => "Akses Pengembang Diperlukan",
+"developertext" => "Tindakan yang Anda minta hanya dapat dilakukan oleh pengguna dengan status \"pengembang\". Lihat $1.",
+"nbytes" => "$1 byte",
+"ok" => "OK",
+"sitetitle" => "{{SITENAME}}",
+"pagetitle" => "$1 - {{SITENAME}}",
+"sitesubtitle" => "Ensiklopedi Bebas",
+"retrievedfrom" => "Diperoleh dari \"$1\"",
+"newmessages" => "Anda mendapatkan $1.",
+"newmessageslink" => "pesan baru",
+"editsection" => "sunting",
+"toc" => "Daftar isi",
+"showtoc" => "tampilkan",
+"hidetoc" => "sembunyikan",
+"thisisdeleted" => "Lihat atau kembalikan $1?",
+"restorelink" => "$1 suntingan dihapus",
+'feedlinks' => 'Feed:',
+'sitenotice' => '-', # the equivalent to wgSiteNotice
+
+# Short words for each namespace, by default used in the 'article' tab in monobook
+'nstab-main' => 'Artikel',
+'nstab-user' => 'Halaman pengguna',
+'nstab-media' => 'Media',
+'nstab-special' => 'Istimewa',
+'nstab-wp' => 'Tentang',
+'nstab-image' => 'Gambar',
+'nstab-mediawiki' => 'Pesan',
+'nstab-template' => 'Templat',
+'nstab-help' => 'Bantuan',
+'nstab-category' => 'Kategori',
+
+# Main script and global functions
+#
+"nosuchaction" => "Tidak Ada Tindakan Tersebut",
+"nosuchactiontext" => "Tindakan yang dispesifikasikan oleh URL tersebut tidak dikenal oleh wiki.",
+"nosuchspecialpage" => "Tidak Ada Halaman Istimewa Tersebut",
+"nospecialpagetext" => "Anda telah meminta halaman istimewa yang tidak dikenal oleh wiki.",
+
+# General errors
+#
+"error" => "Kesalahan",
+"databaseerror" => "Kesalahan Basis Data",
+"dberrortext" => "Ada kesalahan sintaks pada permintaan basis data. Kesalahan ini mungkin menandakan adanya bug dalam perangkat lunak. Permintaan basis data yang terakhir adalah: <blockquote><tt>$1</tt></blockquote> dari dalam fungsi \"<tt>$2</tt>\". Kesalahan MySQL \"<tt>$3: $4</tt>\".",
+"dberrortextcl" => "Ada kesalahan sintaks pada permintaan basis data. Permintaan basis data yang terakhir adalah: \"$1\" dari dalam fungsi \"$2\". Kesalahan MySQL \"$3: $4\".\n",
+"noconnect" => "Maaf! wiki ini mengalami masalah teknis dan tidak dapat menghubungi basis data.",
+"nodb" => "Tidak dapat memilih basis data $1",
+"cachederror" => "Berikut ini adalah salinan cache dari halaman yang diminta, yang mungkin tidak up-to-date.",
+'laggedslavemode'   => 'Peringatan: Halaman mungkin tidak berisi perubahan terbaru.',
+"readonly" => "Basis data dikunci",
+"enterlockreason" => "Masukkan alasan penguncian, termasuk perkiraan kapan kunci akan dibuka",
+"readonlytext" => "Basis data sedang dikunci terhadap masukan baru. Administrator yang melakukan penguncian memberikan penjelasan sebagai berikut: <p>$1",
+"missingarticle" => "Basis data tidak menemukan teks bagi halaman yang seharusnya mempunyai teks, yaitu halaman \"$1\".\n\n<p>Ini biasanya disebabkan karena diff yang kadaluwarsa atau karena pautan sejarah kepada halaman telah dihapus.\n\n<p>Jika ini bukan sebabnya, Anda mungkin menemukan bug dalam perangkat lunak. Silakan laporkan hal ini kepada administrator, dengan mencantumkan URL halaman yang bermasalah tersebut",
+"internalerror" => "Kesalahan internal",
+"filecopyerror" => "Tidak dapat menyalin file \"$1\" ke \"$2\".",
+"filerenameerror" => "Tidak dapat mengubah nama file \"$1\" menjadi \"$2\".",
+"filedeleteerror" => "Tidak dapat menghapus file \"$1\".",
+"filenotfound" => "Tidak dapat menemukan file \"$1\".",
+"unexpected" => "Nilai di luar jangkauan: \"$1\"=\"$2\".",
+"formerror" => "Kesalahan: Tidak dapat mengirimkan formulir",
+"badarticleerror" => "Tindakan ini tidak dapat dilaksanakan di halaman ini.",
+"cannotdelete" => "Tidak dapat menghapus halaman atau gambar yang telah ditentukan.",
+"badtitle" => "Judul Tidak Sah",
+"badtitletext" => "Judul halaman yang diminta tidak sah, kosong, atau judul antarbahasa atau antarwiki yang salah sambung.",
+"perfdisabled" => "Maaf! fitur ini dimatikan sementara karena fitur ini memperlambat pengkalan data sampai-sampai basis data tidak dapat digunakan lagi.",
+"perfdisabledsub" => "Ini adalah salinan tersimpan dari $1:",
+"perfcached" => "Data berikut ini diambil dari cache dan mungkin tidak up-to-date:",
+"wrong_wfQuery_params" => "Parameter salah ke wfQuery()<br />Fungsi: $1<br />Kueri: $2",
+"viewsource" => "Lihat sumber",
+"protectedtext" => "Halaman ini telah dikunci untuk menghindari penyuntingan; ada beberapa alasan mengapa hal ini terjadi, silakan lihat [[Project:Halaman_dilindungi]].\n\nAnda dapat melihat dan menyalin sumber halaman ini:",
+'sqlhidden' => '(Kueri SQL disembunyikan)',
+
+# Login and logout pages
+#
+"logouttitle" => "Pengguna Logout",
+"logouttext" => "Anda telah logout dari sistem. Anda dapat terus menggunakan {{SITENAME}} secara anonim, atau Anda dapat login lagi sebagai pengguna yang sama atau pengguna yang lain. Perhatikan bahwa beberapa halaman mungkin masih terus menunjukkan bahwa Anda masih login sampai Anda membersihkan cache browser Anda\n",
+
+"welcomecreation" => "== Selamat datang, $1! ==
+
+Akun Anda telah dibuat. Jangan lupa mengatur konfigurasi {{SITENAME}} Anda.",
+
+"loginpagetitle" => "Pengguna Login",
+"yourname" => "Nama pengguna",
+"yourpassword" => "Kata sandi",
+"yourpasswordagain" => "Ulangi kata sandi",
+"newusersonly" => "(hanya pengguna baru)",
+"remembermypassword" => "Selalu ingat kata sandi.",
+"loginproblem" => "<b>Ada masalah dengan data login Anda.</b><br />Silakan coba lagi!",
+"alreadyloggedin" => "<strong>Pengguna $1, Anda sudah login!</strong><br />\n",
+
+"login" => "Login",
+"loginprompt" => "Anda harus mengaktifkan cookies untuk dapat login ke {{SITENAME}}.",
+"userlogin" => "Login",
+"logout" => "Logout",
+"userlogout" => "Logout",
+"notloggedin" => "Belum login",
+"createaccount" => "Buka akun baru",
+"createaccountmail" => "melalui e-mail",
+"badretype" => "Kata sandi yang Anda masukkan salah.",
+"userexists" => "Nama pengguna yang Anda masukkan telah dipakai. Silakan pilih nama yang lain.",
+"youremail" => "e-mail Anda*",
+"yourrealname" => "Nama asli Anda*",
+'yourlanguage'  => 'Bahasa antarmuka',
+'yourvariant'  => 'Varian bahasa',
+"yournick" => "Nama samaran (untuk tanda tangan)",
+"emailforlost" => "Isian yang bertanda * tidak harus diisi. Walaupun demikian, dengan memberikan alamat e-mail Anda, orang lain dapat menghubungi Anda melalui situs web tanpa perlu memberikan alamat e-mail Anda kepada mereka, dan e-mail Anda juga dapat digunakan untuk mendapatkan kata sandi yang baru (dengan cara dikirimkan ke alamat e-mail Anda) apabila Anda lupa kata sandi Anda.<br /><br />Nama asli, jika Anda memberikannya, akan digunakan untuk memberikan pengenalan atas kerja Anda.",
+'prefs-help-realname' => '* <strong>Nama asli</strong> (tidak wajib): jika Anda memberikannya, nama asli Anda akan digunakan untuk memberi pengenalan atas hasil kerja Anda.<br />',
+'prefs-help-email' => '* <strong>Email</strong> (tidak wajib): Memungkinkan orang lain untuk menghubungi Anda melalui website tanpa perlu memberikan alamat email Anda kepada mereka, dan juga dapat digunakan untuk mengirimkan kata sandi baru jika Anda lupa password Anda.',
+"loginerror" => "Gagal Login",
+"nocookiesnew" => "Akun pengguna telah dibuat, tetapi Anda belum login. {{SITENAME}} menggunakan cookies untuk login penggunanya. Cookies pada browser Anda dimatikan. Silakan aktifkan cookies dan login kembali dengan nama pengguna dan kata sandi Anda.",
+"nocookieslogin" => "{{SITENAME}} menggunakan cookies untuk login penggunanya. Cookies pada browser Anda dimatikan. Silakan aktifkan cookies dan coba lagi.",
+"noname" => "Nama pengguna yang Anda masukkan tidak sah.",
+"loginsuccesstitle" => "Login Berhasil",
+"loginsuccess" => "Berhasil login ke {{SITENAME}} sebagai \"$1\".",
+"nosuchuser" => "Tidak ada pengguna dengan nama \"$1\". Periksalah ejaan Anda, atau gunakan formulir di bawah ini untuk membuka akun baru.",
+'nosuchusershort' => "Tidak ada pengguna dengan nama \"$1\". Periksalah ejaan Anda.",
+"wrongpassword" => "Kata sandi yang Anda masukkan salah. Silakan coba lagi.",
+"mailmypassword" => "e-mailkan kata sandi baru",
+"passwordremindertitle" => "Peringatan Kata Sandi dari {{SITENAME}}",
+"passwordremindertext" => "Seseorang (mungkin Anda, dari alamat IP $1) meminta kami mengirimkan kata sandi {{SITENAME}} yang baru. Kata sandi untuk pengguna \"$2\" sekarang adalah \"$3\". Anda disarankan segera melakukan login dan mengganti kata sandi.",
+
+"noemail" => "Tidak ada alamat e-mail yang tercatat untuk pengguna \"$1\".",
+"passwordsent" => "Kata sandi baru telah dikirimkan kepada e-mail yang didaftarkan untuk \"$1\". Silakan login kembali setelah menerima e-mail tersebut.", #Please log in again after you receive it.",
+"loginend" => " ",
+"mailerror" => "Kesalahan dalam mengirimkan e-mail: $1",
+'acct_creation_throttle_hit' => 'Maaf, Anda telah membuat $1 akun. Anda tidak dapat membuat akun lagi.',
+
+# Edit page toolbar
+"bold_sample" => "Teks ini akan dicetak tebal",
+"bold_tip" => "Cetak tebal",
+"italic_sample" => "Teks ini akan dicetak miring",
+"italic_tip" => "Cetak miring",
+"link_sample" => "Judul pautan",
+"link_tip" => "Pautan internal",
+"extlink_sample" => "http://www.contoh.com/ judul pautan",
+"extlink_tip" => "Pautan eksternal (ingat awalan http:// )",
+"headline_sample" => "Teks headline",
+"headline_tip" => "Headline level 2",
+"math_sample" => "Masukkan rumus di sini",
+"math_tip" => "Rumus matematika (LaTeX)",
+"nowiki_sample" => "Teks ini tidak akan diformat",
+"nowiki_tip" => "Abaikan pemformatan wiki",
+"image_sample" => "Contoh.jpg",
+"image_tip" => "Gambar embedded",
+"media_sample" => "Contoh.ogg",
+"media_tip" => "Pautan file media",
+"sig_tip" => "Tanda tangan Anda dengan tanda waktu",
+"hr_tip" => "Garis horisontal (gunakan dengan hemat)",
+"infobox" => "Klik sebuah tombol untuk mendapatkan teks contoh",
+# alert box shown in browsers where text selection does not work, test e.g. with mozilla or konqueror
+"infobox_alert" => "Silakan masukkan teks yang ingin diformat.\\n Teks tersebut akan ditampilkan di infobox untuk penyalinan dan penempelan.\\nContoh:\\n$1\\nakan menjadi:\\n$2",
+
+# Edit pages
+#
+"summary" => "Ringkasan",
+"subject" => "Subjek/headline",
+"minoredit" => "Ini adalah suntingan kecil.",
+"watchthis" => "Pantau artikel ini",
+"savearticle" => "Simpan halaman<br />",
+"preview" => "Pratilik",
+"showpreview" => "Tampilkan pratilik",
+"blockedtitle" => "Pengguna Diblokir",
+"blockedtext" => "Nama pengguna atau alamat IP Anda telah diblokir oleh $1. Alasannya karena :<br />$2<p>Anda dapat menghubungi [[Project:Administrators|para administrator]] untuk membicarakan blokir ini.\n\nPerhatikan bahwa Anda tidak dapat menggunakan fasilitas \"e-mail pengguna ini\" kecuali Anda mempunyai sebuah alamat e-mail yang sah dan alamat e-mail tersebut tercatat di dalam [[Special:Preferences|konfigurasi Anda]].\n\nAlamat IP Anda adalah $3. Sertakan alamat IP ini pada setiap pertanyaan yang Anda buat",
+"whitelistedittitle" => "Login Diperlukan untuk Menyunting",
+"whitelistedittext" => "Anda harus [[Special:Userlogin|login]] untuk dapat menyunting artikel.",
+"whitelistreadtitle" => "Login Diperlukan untuk Membaca",
+"whitelistreadtext" => "Anda harus [[Special:Userlogin|login]] untuk dapat membaca artikel.",
+"whitelistacctitle" => "Anda Tidak Diperbolehkan untuk Membuat Akun",
+"whitelistacctext" => "Untuk dapat membuat akun dalam Wiki ini, Anda harus [[Special:Userlogin|login]] dan mempunyai izin yang tepat.",
+"loginreqtitle" => "Login Diperlukan",
+"loginreqtext" => "Anda harus [[Special:Userlogin|login]] untuk dapat melihat halaman lainnya.",
+"accmailtitle" => "Kata Sandi Dikirimkan",
+"accmailtext" => "Kata sandi untuk '$1' telah dikirimkan ke $2.",
+"newarticle" => "(Baru)",
+"newarticletext" => "Anda mengikuti pautan ke halaman yang belum ada.\nUntuk membuat halaman tersebut, ketiklah isi halaman di kotak di bawah ini\n(lihat [[Project:Bantuan|halaman bantuan]] untuk informasi lebih lanjut).\nJika Anda tanpa sengaja sampai ke halaman ini, klik tombol '''back''' di browser anda.",
+"talkpagetext" => "<!-- MediaWiki:talkpagetext -->",
+"anontalkpagetext" => "---- ''Ini adalah halaman diskusi seorang pengguna anonim yang belum membuat akun atau tidak menggunakannya. Karena Ia tidak membuat akun, kami terpaksa harus memakai [[alamat IP]]-nya untuk mengenalinya. Alamat IP seperti ini dapat dipakai oleh beberapa pengguna yang berbeda. Jika Anda adalah seorang pengguna anonim dan merasa mendapatkan komentar-komentar miring, silakan [[Special:Userlogin|membuat akun atau login]] untuk menghindari kerancuan dengan pengguna anonim lain di lain waktu.'' ",
+"noarticletext" => "(Tidak ada teks dalam halaman ini)",
+'clearyourcache' => "'''Catatan:''' Setelah menyimpan konfigurasi, Anda perlu membersihkan cache browser Anda untuk melihat perubahan: '''Mozilla / Firefox:''' ''Ctrl-Shift-R'', '''IE:''' ''Ctrl-F5'', '''Safari:''' ''Cmd-Shift-R'', '''Konqueror:''' ''F5''.", 
+'usercssjsyoucanpreview' => "<strong>Tips:</strong> Gunakan tombol 'Tampilkan pratilik' untuk menguji css/js baru Anda sebelum menyimpannya.", #<strong>Tip:</strong> Use the 'Show preview' button to test your new css/js before saving.
+'usercsspreview' => "'''Ingatlah bahwa yang Anda lihat hanyalah pratilik CSS Anda, dan bahwa pratilik tersebut belum disimpan!'''", #'''Remember that you are only previewing your user css, it has not yet been saved!'''
+'userjspreview' => "'''Ingatlah bahwa yang Anda lihat hanyalah pratilik JavaScript Anda, dan bahwa pratilik tersebut belum disimpan!'''", #'''Remember that you are only testing/previewing your user javascript, it has not yet been saved!'''
+"updated" => "(Diperbarui)",
+"note" => "<strong>Catatan:</strong> ",
+"previewnote" => "Ingatlah bahwa ini hanyalah pratilik yang belum disimpan!",
+"previewconflict" => "Pratilik ini mencerminkan teks pada bagian atas sebagaimana Ia akan terlihat bila Anda menyimpannya.",
+"editing" => "Menyunting $1",
+"editconflict" => "Konflik penyuntingan: $1",
+"explainconflict" => "Orang lain telah menyunting halaman ini sejak Anda mulai menyuntingnya. Bagian atas teks ini mengandung teks halaman saat ini. Perubahan yang Anda lakukan ditunjukkan pada bagian bawah teks. Anda hanya perlu menggabungkan perubahan Anda dengan teks yang telah ada. <b>Hanya</b> teks pada bagian atas halamanlah yang akan disimpan apabila Anda menekan \"Simpan halaman\".\n<p>",
+"yourtext" => "Teks Anda",
+"storedversion" => "Versi tersimpan",
+'nonunicodebrowser' => "<strong>PERINGATAN: Browser Anda tidak mendukung Unicode, silakan ganti browser Anda sebelum menyunting artikel.</strong>",
+"editingold" => "<strong>PERINGATAN: Anda menyunting revisi lama suatu halaman. Jika Anda menyimpannya, perubahan-perubahan yang dibuat sejak revisi ini akan hilang.</strong>",
+"yourdiff" => "Perbedaan",
+"copyrightwarning" => "Perhatikan bahwa semua sumbangan terhadap {{SITENAME}} dianggap dilisensikan di bawah lisensi $2 (lihat $1 untuk informasi lebih lanjut). Jika Anda tidak menginginkan tulisan Anda disunting dan disebarkan ke halaman web yang lain, jangan kirimkan artikel Anda ke sini.<br /> Anda juga berjanji bahwa ini adalah hasil karya Anda sendiri, atau Anda menyalinnya dari sumber milik umum atau sumber bebas yang lain. <p><strong>JANGAN KIRIMKAN KARYA YANG DILINDUNGI HAK CIPTA TANPA IZIN!</strong></p> <p><strong>JANGAN SALIN ARTIKEL DARI HALAMAN WEB LAIN.</strong></p> ",
+'copyrightwarning2' => "Perhatikan bahwa semua sumbangan terhadap {{SITENAME}} dapat disunting, diubah, atau dihapus oleh penyumbang lainnya. Jika Anda tidak ingin artikel anda disunting, jangan kirimkan artikel Anda ke sini.<br /> Anda juga berjanji bahwa ini adalah hasil karya Anda sendiri, atau disalin dari sumber milik umum atau sumber bebas yang lain (lihat $1 untuk informasi lebih lanjut).<strong>JANGAN KIRIMKAN KARYA YANG DILINDUNGI HAK CIPTA TANPA IZIN!</strong>",
+"longpagewarning" => "<strong>PERINGATAN: Halaman ini panjangnya adalah $1 kilobyte; beberapa browser mungkin mengalami masalah dalam menyunting halaman yang panjangnya 32 kB atau lebih. Pertimbangkan memecah halaman menjadi beberapa halaman kecil.</strong>",
+"readonlywarning" => "<strong>PERINGATAN: Basis data sedang dikunci karena pemeliharaan, sehingga saat ini Anda tidak akan dapat menyimpan hasil penyuntingan Anda. Anda mungkin perlu memindahkan hasil penyuntingan Anda ini ke tempat lain untuk disimpan belakangan.</strong>",
+"protectedpagewarning" => "<strong>PERINGATAN:  Halaman ini telah dikunci sehingga hanya pemakai dengan status sysop saja yang dapat menyuntingnya. Pastikan Anda mengikuti [[Project:Petunjuk_halaman_dilindungi|aturan halaman yang dilindungi]].</strong>",
+'templatesused' => 'Templat yang digunakan di halaman ini:',
+
+# History pages
+#
+"revhistory" => "Sejarah revisi",
+"nohistory" => "Tidak ada sejarah penyuntingan untuk halaman ini",
+"revnotfound" => "Revisi tidak ditemukan",
+"revnotfoundtext" => "Revisi lama halaman yang Anda minta tidak dapat ditemukan. Silakan periksa URL yang digunakan untuk mengakses halaman ini.\n", #"The old revision of the page you asked for could not be found. Please check the URL you used to access this page.\n",
+"loadhist" => "Memuat halaman sejarah",
+"currentrev" => "Revisi sekarang",
+"revisionasof" => "Revisi per $1",
+'revisionasofwithlink'  => 'Revisi per $1; $2<br />$3 | $4',
+'previousrevision'      => '←Revisi yang lebih tua',
+'nextrevision'          => 'Revisi yang lebih baru→',
+'currentrevisionlink'   => 'lihat revisi sekarang',
+"cur" => "kini",
+"next" => "berikut",
+"last" => "akhir",
+"orig" => "asli",
+"histlegend" => "Cara membandingkan: tandai radio button versi-versi yang ingin dibandingkan, lalu tekan ENTER atau tombol di bawah.<br />Legenda: (kini) = perbedaan dengan versi sekarang, (akhir) = perbedaan dengan versi sebelumnya, m = suntingan kecil",
+'history_copyright' => '-',
+
+# Diffs
+#
+"difference" => "(Perbedaan antarrevisi)",
+"loadingrev" => "memuat revisi untuk dibandingkan",
+"lineno" => "Baris $1:",
+"editcurrent" => "Sunting versi sekarang dari halaman ini",
+'selectnewerversionfordiff' => 'Pilih sebuah versi yang lebih baru untuk perbandingan',
+'selectolderversionfordiff' => 'Pilih sebuah versi yang lebih tua untuk perbandingan',
+'compareselectedversions' => 'Bandingkan versi terpilih',
+
+# Search results
+#
+"searchresults" => "Hasil Pencarian",
+"searchresulttext" => "Untuk informasi lebih lanjut tentang pencarian di {{SITENAME}}, lihat [[Project:Pencarian|Mencari {{SITENAME}}]].",
+"searchquery" => "Untuk kueri \"$1\"",
+"badquery" => "Format kueri pencarian salah",
+"badquerytext" => "Kami tidak dapat memproses kueri Anda. Hal ini mungkin disebabkan karena Anda mencoba mencari kata yang panjangnya kurang dari tiga huruf, yang masih belum didukung oleh sistem ini. Hal ini juga dapat disebabkan oleh kesalahan pengetikan ekspresi, misalnya \"fish and and scales\". Silakan coba kueri yang lain.",
+"matchtotals" => "Kueri \"$1\" cocok dengan $2 judul halaman dan teks dari $3 artikel.",
+"nogomatch" => "Tidak ada halaman dengan judul persis seperti ini, mencoba pencarian full text.",
+"titlematches" => "Judul artikel yang cocok",
+"notitlematches" => "Tidak ada judul halaman yang cocok",
+"textmatches" => "Teks artikel yang cocok",
+"notextmatches" => "Tidak ada teks halaman yang cocok",
+"prevn" => "$1 sebelumnya",
+"nextn" => "$1 berikutnya",
+"viewprevnext" => "Lihat ($1) ($2) ($3).",
+"showingresults" => "Di bawah ditampilkan sampai <b>$1</b> hasil pencarian, dimulai dari #<b>$2</b>.",
+"showingresultsnum" => "Di bawah ditampilkan <b>$3</b> hasil pencarian, dimulai dari #<b>$2</b>.",
+"nonefound" => "'''Catatan''': Kegagalan pencarian biasanya disebabkan oleh pencarian kata-kata umum, seperti \"have\" and \"from\", yang biasanya tidak diindeks, atau dengan menentukan lebih dari satu aturan pencarian (hanya halaman yang mengandung semua aturan pencarianlah yang akan ditampilkan dalam hasil pencarian)",
+"powersearch" => "Cari",
+"powersearchtext" => "Cari dalam namespace :<br />$1<br />$2 Juga tampilkan peralihan   Cari $3 $9",
+"searchdisabled" => '<p style="margin: 1.5em 2em 1em">Pencarian {{SITENAME}} dimatikan sementara karena masalah performa. Dalam pada itu, Anda dapat mencari melalui Google. <span style="font-size: 89%; display: block; margin-left: .2em">Perhatikan bahwa hasil pencarian Google mungkin out-of-date.</span></p>", #"<p>Sorry! Full text search has been disabled temporarily, for performance reasons. In the meantime, you can use the Google search below, which may be out of date.</p>',
+'googlesearch' => '
+<div style="margin-left: 2em">
+
+<!-- Google search -->
+<div style="width:130px;float:left;text-align:center;position:relative;top:-8px"><a href="http://www.google.com/" style="paddin
+:0;background-image:none"><img src="http://www.google.com/logos/Logo_40wht.gif" alt="Google" style="border:none" /></a></div>
+
+<form method="get" action="http://www.google.com/search" style="margin-left:135px">
+  <div>
+    <input type="hidden" name="domains" value="{{SERVER}}" />
+    <input type="hidden" name="num" value="50" />
+    <input type="hidden" name="hl" value="id" />
+    <input type="hidden" name="ie" value="$2" />
+    <input type="hidden" name="oe" value="$2" />
+    
+    <input type="text" name="q" size="31" maxlength="255" value="$1" />
+    <input type="submit" name="btnG" value="Mesin Cari Google" />
+  </div>
+  <div style="font-size:90%">
+    <input type="radio" name="sitesearch" id="gwiki" value="{{SERVER}}" checked="checked" /><label for="gwiki">{{SITENAME}}</label>
+    <input type="radio" name="sitesearch" id="gWWW" value="" /><label for="gWWW">WWW</label>
+  </div>
+</form>
+
+</div>',
+"blanknamespace" => "(Utama)",
+
+# Preferences page
+#
+"preferences" => "Konfigurasi",
+"prefsnologin" => "Belum login",
+"prefsnologintext" => "Anda harus [[Special:Userlogin|login]] untuk menetapkan konfigurasi Anda.",
+"prefslogintext" => "Anda telah login sebagai \"$1\".\nNomor ID Anda adalah $2.\n\nLihat [[Project:Bantuan Konfigurasi]] untuk cara mengatur konfigurasi Anda.",
+
+"prefsreset" => "Konfigurasi telah dikembalikan ke asal dari storage.",
+"qbsettings" => "Pengaturan quickbar",
+"changepassword" => "Ganti kata sandi",
+"skin" => "Skin",
+"math" => "Penggambaran math",
+"dateformat" => "Format tanggal",
+"math_failure" => "Gagal memparse",
+"math_unknown_error" => "Kesalahan yang tidak diketahui",
+"math_unknown_function" => "fungsi yang tidak diketahui ",
+"math_lexing_error" => "kesalahan lexing",
+"math_syntax_error" => "kesalahan sintaks",
+"math_image_error" => "Konversi PNG gagal; periksa apakah latex, dvips, gs, dan convert terinstal dengan benar",
+"math_bad_tmpdir" => "Tidak dapat menulisi atau membuat direktori sementara math",
+"math_bad_output" => "Tidak dapat menulisi atau membuat direktori keluaran math",
+"math_notexvc" => "Executable texvc hilang; silakan lihat math/README untuk cara konfigurasi.",
+'prefs-personal' => 'Data pengguna',
+'prefs-rc' => 'Tampilan perubahan terbaru dan stub',
+'prefs-misc' => 'Pengaturan macam-macam',
+"saveprefs" => "Simpan konfigurasi",
+"resetprefs" => "Pengaturan baku",
+"oldpassword" => "Kata sandi lama",
+"newpassword" => "Kata sandi baru",
+"retypenew" => "Ketikkan lagi kata sandi yang baru",
+"textboxsize" => "Ukuran kotak teks",
+"rows" => "Baris",
+"columns" => "Kolom",
+"searchresultshead" => "Pengaturan hasil pencarian",
+"resultsperpage" => "Hasil pencarian per halaman",
+"contextlines" => "Baris ditampilkan per hasil",
+"contextchars" => "Karakter untuk konteks per baris",
+"stubthreshold" => "Threshold tampilan stub",
+"recentchangescount" => "Jumlah judul dalam perubahan terbaru",
+"savedprefs" => "Konfigurasi Anda telah disimpan",
+'timezonelegend' => 'Daerah waktu',
+"timezonetext" => "Masukkan perbedaan waktu (dalam jam) antara waktu setempat dengan waktu server (UTC).",
+"localtime" => "Waktu setempat",
+"timezoneoffset" => "Perbedaan",
+"servertime" => "Waktu server sekarang adalah",
+"guesstimezone" => "Isikan dari browser",
+"emailflag" => "Matikan e-mail dari pengguna lain",
+"defaultns" => "Cari dalam namespace berikut ini secara baku:",
+'default' => 'baku',
+
+# User levels special page
+#
+
+# switching pan
+'editgroup' => 'Sunting Kelompok',
+'addgroup' => 'Tambah Kelompok',
+
+'editusergroup' => 'Sunting Kelompok Pengguna',
+
+# group editing
+'savegroup' => 'Simpan Kelompok',
+
+# user groups editing
+'saveusergroups' => 'Simpan Kelompok Pengguna',
+
+# Recent changes
+#
+"changes" => "perubahan",
+"recentchanges" => "Perubahan Terbaru",
+'recentchanges-url' => 'Special:Recentchanges',
+"recentchangestext" => "Temukan perubahan terbaru dalam wiki di halaman ini.",
+"rcloaderr" => "Memuat perubahan terbaru",
+"rcnote" => "Di bawah ini adalah <strong>$1</strong> perubahan terakhir dalam <strong>$2</strong> hari terakhir.",
+"rcnotefrom" => "Di bawah ini adalah perubahan sejak <b>$2</b> (ditampilkan sampai <b>$1</b> perubahan).",
+"rclistfrom" => "Tampilkan perubahan baru sejak $1",
+# "rclinks" => "Show last $1 changes in last $2 hours / last $3 days",
+# "rclinks" => "Show last $1 changes in last $2 days.",
+"showhideminor" => "$1 suntingan kecil | $2 bot | $3 pengguna yang login | $4 suntingan diperiksa",
+"rclinks" => "Tampilkan $1 perubahan terakhir dalam $2 hari terakhir<br />$3",
+"rchide" => "dalam bentuk $4; $1 suntingan kecil; $2 namespace sekunder; $3 suntingan berganda.",
+"rcliu" => "; $1 penyuntingan dari pengguna yang login",
+"diff" => "beda",
+"hist" => "sejarah",
+"hide" => "sembunyikan",
+"show" => "tampilkan",
+"tableform" => "tabel",
+"listform" => "daftar",
+"nchanges" => "$1 perubahan",
+"minoreditletter" => "m",
+"newpageletter" => "B",
+'sectionlink' => '→',
+
+# Upload
+#
+"upload" => "Unggah",
+"uploadbtn" => "Unggahkan file",
+"uploadlink" => "Unggahkan gambar",
+"reupload" => "Unggahkan ulang",
+"reuploaddesc" => "Kembali ke formulir pengunggahan",
+"uploadnologin" => "Belum login",
+"uploadnologintext" => "Anda harus <a href=\"{{localurl:Special:Userlogin}}\">login</a> untuk dapat mengunggahkan file.",
+"uploaderror" => "Kesalahan Pengunggahan",
+"uploadtext" => "'''STOP!''' Sebelum Anda mengunggahkan di sini, pastikan bahwa Anda telah membaca dan menaati [[Special:Image_use_policy|kebijaksanaan penggunaan gambar]].\n\nJika ada sebuah file dalam wiki yang mempunyai nama yang sama dengan file yang akan Anda unggahkan, file tersebut akan ditimpa tanpa peringatan dengan file yang akan Anda unggahkan. Jadi, kecuali Anda ingin memperbarui sebuah file, Anda sangat disarankan untuk memeriksa apakah sudah ada file dengan nama yang sama dengan file yang akan Anda unggahkan.\n\nUntuk melihat atau mencari gambar-gambar yang telah diunggahkan, silakan kunjungi [[Special:Imagelist|daftar gambar yang diunggahkan]]}}. Semua pengunggahan dan penghapusan dicatat dalam [[Project:Catatan_Unggah|catatan pengunggahan]].\n\nGunakan formulir berikut ini untuk mengunggahkan file gambar baru untuk dipakai dalam mengilustrasikan artikel Anda. Pada kebanyakan browser, Anda akan melihat tombol \"Browse...\", yang akan menampilkan dialog buka file sistem operasi Anda. Memilih sebuah file akan mengisikan namanya dalam kotak teks di sebelah tombol tersebut. Anda juga harus memberi tanda cek pada kotak cek, menandakan bahwa Anda tidak melanggar hak cipta apapun dengan mengunggahkan file tersebut. Tekan tombol \"Unggah\" untuk menyelesaikan proses pengunggahan. Proses ini mungkin akan memakan waktu agak lama jika Anda memiliki koneksi internet yang lambat. <p>Format file yang disukai adalah JPEG untuk foto, PNG untuk gambar dan simbol, dan OGG untuk suara. Mohon beri nama file Anda secara deskriptif untuk menghindari kebingungan. Untuk memasukkan sebuah gambar ke dalam artikel, gunakan link dalam bentuk '''<nowiki>[[{{ns:6}}:file.jpg]]</nowiki>''' atau '''<nowiki>[[{{ns:6}}:file.png|teks alternatif]]</nowiki>''' atau '''<nowiki>[[{{ns:-2}}:file.ogg]]</nowiki>''' untuk suara.\n\nMohon diperhatikan bahwa sebagaimana dengan halaman {{SITENAME}} yang lain, orang lain dapat menyunting atau menghapus file Anda jika mereka menganggap hal itu perlu, dan Anda juga dapat diblokir bila Anda menyalahgunakan sistem.",
+
+"uploadlog" => "catatan pengunggahan",
+"uploadlogpage" => "Catatan_Unggah",
+"uploadlogpagetext" => "Di bawah ini adalah daftar terkini file yang diunggahkan. Semua waktu yang ditunjukkan adalah waktu server (UTC).",
+"filename" => "Nama file",
+"filedesc" => "Ringkasan",
+"filestatus" => "Status hak cipta",
+"filesource" => "Sumber",
+"copyrightpage" => "Project:Hak_Cipta",
+"copyrightpagename" => "Hak cipta {{SITENAME}}",
+"uploadedfiles" => "File yang telah diunggahkan",
+"ignorewarning" => "Abaikan peringatan dan simpan file",
+"minlength" => "Nama gambar sekurang-kurangnya harus tiga huruf.",
+'illegalfilename' => 'Nama file "$1" mengandung karakter yang tidak diizinkan dalam judul halaman. Silakan ubah nama file tersebut dan cobalah mengunggahkannya kembali.',
+"badfilename" => "Nama gambar telah diubah menjadi \"$1\".",
+"badfiletype" => "\".$1\" ialah format file gambar yang tidak diizinkan.",
+"largefile" => "Ukuran gambar disarankan tidak melebihi 100k.",
+'emptyfile' => 'File yang Anda unggahkan kelihatannya kosong. Hal ini mungkin disebabkan karena adanya kesalahan ketik pada nama file. Silakan pastikan apakah Anda benar-benar ingin mengunggahkan file ini.',
+'fileexists' => 'Sebuah file dengan nama tersebut telah ada, silakan periksa $1 jika Anda ragu-ragu apakah Anda ingin mengubahnya.',
+"successfulupload" => "Berhasil diunggahkan",
+"fileuploaded" => "File \"$1\" berhasil diunggahkan. Silakan ikuti pautan berikut: $2 ke halaman deskripsi dan isikan informasi tentang file tersebut, seperti dari mana file tersebut berasal, kapan file itu dibuat dan oleh siapa, dan informasi lain yang Anda ketahui.",
+"uploadwarning" => "Peringatan pengunggahan",
+"savefile" => "Simpan file",
+"uploadedimage" => "mengunggahkan \"[[$1]]\"",
+"uploaddisabled" => "Maaf, pengunggahan dimatikan.",
+'uploadcorrupt' => 'File tersebut rusak atau ekstensinya salah. Silakan periksa file tersebut dan unggahkanlah kembali.',
+
+# Image list
+#
+"imagelist" => "Daftar Gambar",
+"imagelisttext" => "Di bawah ini adalah daftar gambar yang telah diurutkan $2.",
+"getimagelist" => "memperoleh daftar gambar",
+"ilsubmit" => "Cari",
+"showlast" => "Tampilkan $1 gambar terakhir yang telah diurutkan $2.",
+"byname" => "berdasarkan nama",
+"bydate" => "berdasarkan tanggal",
+"bysize" => "berdasarkan ukuran",
+"imgdelete" => "hapus",
+"imgdesc" => "desc",
+"imglegend" => "Legenda: (desc) = lihat/sunting deskripsi gambar.",
+"imghistory" => "Sejarah gambar",
+"revertimg" => "revert",
+"deleteimg" => "hapus",
+'deleteimgcompletely' => 'Hapus semua revisi',
+"imghistlegend" => "Legend: (kini) = ini adalah gambar yang sekarang, (hapus) = hapus versi lama ini, (rv) = kembalikan ke versi lama ini. <br /><i>Klik pada tanggal untuk melihat gambar yang diunggahkan pada tanggal tersebut</i>.",
+"imagelinks" => "Pautan gambar",
+"linkstoimage" => "Halaman-halaman berikut berpaut ke gambar ini:",
+"nolinkstoimage" => "Tidak ada halaman yang berpaut ke gambar ini.",
+"sharedupload" => "File ini adalah unggahan bersama yang mungkin juga dipakai oleh proyek lain.",
+
+# Statistics
+#
+"statistics" => "Statistik",
+"sitestats" => "Statistik situs",
+"userstats" => "Statistik pengguna",
+"sitestatstext" => "Ada sejumlah <b>$1</b> halaman dalam basis data. Ini termasuk halaman \"pembicaraan\", halaman tentang {{SITENAME}}, halaman minimum \"stub\", peralihan halaman, dan halaman-halaman lain yang mungkin bukan artikel. Selain itu, ada <b>$2</b> halaman yang mungkin adalah artikel yang sah.<p> Ada sejumlah <b>$3</b> penampilan halaman, dan sejumlah <b>$4</b> penyuntingan sejak wiki ini dimulai. Ini berarti rata-rata <b>$5</b> suntingan per halaman, dan <b>$6</b> penampilan per penyuntingan.",
+"userstatstext" => "Ada <b>$1</b> pengguna terdaftar. <b>$2</b> diantaranya adalah administrator (lihat $3).",
+
+# Maintenance Page
+#
+"maintenance" => "Halaman Pemeliharaan",
+"maintnancepagetext" => "Halaman ini mengandung beberapa peralatan untuk pemeliharaan harian. Kebanyakan fungsi yang terdapat di sini cenderung membebani basis data, jadi mohon jangan tekan tombol 'reload' setelah melakukan perbaikan ;-)",
+"maintenancebacklink" => "Kembali ke halaman pemeliharaan",
+"disambiguations" => "Halaman Disambiguation",
+"disambiguationspage" => "Project:Pautan_ke_halaman_disambiguation",
+"disambiguationstext" => "Halaman-halaman berikut ini berpaut ke sebuah <i>halaman disambiguation</i>. Halaman-halaman tersebut seharusnya berpaut ke topik-topik yang tepat.<br />Satu halaman dianggap sebagai disambiguation apabila halaman tersebut disambung dari $1.<br />Pautan dari namespace lain <i>tidak</i> terdaftar di sini.",
+"doubleredirects" => "Peralihan Halaman Berganda",
+"doubleredirectstext" => "Setiap baris mengandung pautan ke peralihan pertama dan kedua, dan juga baris pertama dari teks peralihan kedua, yang biasanya memberikan artikel tujuan yang \"sesungguhnya\", yang seharusnya ditunjuk oleh peralihan yang pertama.",
+"brokenredirects" => "Peralihan Halaman Rusak",
+"brokenredirectstext" => "Peralihan halaman berikut berpaut ke halaman yang tidak ada",
+"selflinks" => "Halaman-Halaman dengan Pautan Sendiri",
+"selflinkstext" => "Halaman-halaman berikut mengandung pautan ke dirinya sendiri, yang seharusnya tidak diizinkan.",
+"mispeelings" => "Halaman-Halaman dengan Kesalahan Ejaan",
+"mispeelingstext" => "Halaman-halaman berikut mengandung kesalahan ejaan yang didaftar di $1. Ejaan yang benar mungkin diberikan (seperti ini).",
+"mispeelingspage" => "Daftar kesalahan ejaan yang umum",
+"missinglanguagelinks" => "Pautan bahasa yang hilang",
+"missinglanguagelinksbutton" => "Cari pautan bahasa yang hilang untuk",
+"missinglanguagelinkstext" => "Halaman ini <i>tidak</i> menyambung ke halaman rekannya di $1. Peralihan dan sub halaman <i>tidak</i> ditunjukkan.",
+
+
+# Miscellaneous special pages
+#
+"orphans" => "Halaman Yatim",
+'geo' => 'Koordinat GEO',
+'validate' => 'Sahkan halaman',
+"lonelypages" => "Halaman Yatim",
+'uncategorizedpages' => 'Halaman Tak Berkategori',
+'uncategorizedcategories' => 'Kategori Tak Berkategori',
+"unusedimages" => "Gambar yang Tidak Digunakan",
+"popularpages" => "Halaman Populer",
+"nviews" => "$1 penampilan",
+"wantedpages" => "Halaman yang Diinginkan",
+"nlinks" => "$1 pautan",
+"allpages" => "Semua Halaman",
+'nextpage' => 'Halaman berikutnya ($1)',
+"randompage" => "Sembarang Halaman",
+'randompage-url'=> 'Special:Randompage',
+"shortpages" => "Halaman Pendek",
+"longpages" => "Halaman Panjang",
+"deadendpages" => "Halaman Buntu",
+"listusers" => "Daftar Pengguna",
+"specialpages" => "Halaman Istimewa",
+"spheading" => "Halaman Istimewa untuk Semua Pengguna",
+"protectpage" => "Lindungi halaman",
+"recentchangeslinked" => "Perubahan terkait",
+"rclsub" => "(untuk halaman yang berpaut dari \"$1\")",
+"debug" => "Debug",
+"newpages" => "Halaman Baru",
+"ancientpages" => "Artikel Tua",
+"intl" => "Pautan Antarbahasa",
+'move' => 'Pindahkan',
+"movethispage" => "Pindahkan halaman ini",
+"unusedimagestext" => "<p>Perhatikan bahwa situs web lain mungkin dapat berpaut ke sebuah file gambar secara langsung, dan file-file gambar seperti itu mungkin terdapat dalam daftar ini meskipun masih digunakan oleh situs web lain.",
+"booksources" => "Sumber Buku",
+'categoriespagetext' => 'Kategori-kategori berikut ada dalam wiki.',
+'data'  => 'Data',
+"booksourcetext" => "Di bawah ini adalah daftar pautan ke situs lain yang menjual buku baru dan bekas, dan mungkin juga mempunyai informasi lebih lanjut mengenai buku yang sedang Anda cari. {{SITENAME}} tidak berkepentingan dengan situs-situs web di atas, dan daftar ini seharusnya tidak dianggap sebagai sebuah dukungan.",
+"isbn" => "ISBN",
+"rfcurl" =>  "http://www.faqs.org/rfcs/rfc$1.html",
+'pubmedurl' =>  'http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?cmd=Retrieve&db=pubmed&dopt=Abstract&list_uids=$1',
+"alphaindexline" => "$1 ke $2",
+"version" => "Versi",
+'log' => 'Catatan-Catatan',
+'alllogstext' => 'Tampilan gabungan catatan pengunggahan, penghapusan, perlindungan, pemblokiran, dan sysop. Anda dapat melakukan pembatasan tampilan dengan memilih jenis catatan, nama pengguna, atau nama halaman.',
+
+# Special:Allpages
+'nextpage'          => 'Halaman berikutnya ($1)',
+'allarticles'       => 'Semua artikel',
+'allpagesprev'      => 'Sebelumnya',
+'allpagesnext'      => 'Selanjutnya',
+'allpagessubmit'    => 'Go',
+
+# Email this user
+#
+"mailnologin" => "Tidak ada alamat e-mail",
+"mailnologintext" => "Anda harus [[Special:Userlogin|login]] dan mempunyai alamat e-mail yang sah di dalam [[Special:Preferences|konfigurasi]] untuk mengirimkan e-mail kepada pengguna lain.",
+
+"emailuser" => "e-mail pengguna ini",
+"emailpage" => "e-mail pengguna",
+"emailpagetext" => "Jika pengguna ini memasukkan alamat e-mail yang sah dalam konfigurasinya, formulir dibawah ini akan mengirimkan sebuah e-mail. Alamat e-mail yg terdapat pada konfigurasi Anda akan muncul sebagai alamat \"From\" dalam e-mail tersebut, sehingga penerima dapat membalas e-mail tersebut.",
+
+"usermailererror" => "Kesalahan objek mail: ",
+"defemailsubject" => "e-mail {{SITENAME}}",
+"noemailtitle" => "Tidak Ada Alamat e-mail",
+
+"noemailtext" => "Pengguna ini tidak memasukkan alamat e-mail yang sah, atau memilih untuk tidak menerima e-mail dari pengguna yang lain.",
+
+"emailfrom" => "Dari",
+"emailto" => "Ke",
+"emailsubject" => "Perihal",
+"emailmessage" => "Pesan",
+"emailsend" => "Kirimkan",
+"emailsent" => "e-mail terkirim",
+"emailsenttext" => "e-mail Anda telah dikirimkan.",
+
+# Watchlist
+#
+"watchlist" => "Daftar Pemantauan",
+"watchlistsub" => "(untuk pengguna \"$1\")",
+"nowatchlist" => "Daftar pemantauan Anda kosong.",
+"watchnologin" => "Belum login",
+"watchnologintext" => "Anda harus [[Special:Userlogin|login]] untuk mengubah daftar pemantauan.",
+"addedwatch" => "Telah Ditambahkan ke Daftar Pemantauan",
+"addedwatchtext" => "Halaman \"$1\" telah ditambahkan ke [[Special:Watchlist|daftar pemantauan]]. Pada masa yang akan datang, semua perubahan pada halaman tersebut berikut halaman pembicaraannya akan didaftar di sini, dan halaman tersebut akan <b>dicetak tebal</b> dalam [[Special:Recentchanges|daftar perubahan terbaru]] supaya lebih mudah dilihat.\n\n<p>Apabila nanti Anda ingin menghapus halaman dari daftar pemantauan, klik \"Berhenti memantau\" pada batang sebelah.",
+"removedwatch" => "Telah Dihapus dari Daftar Pemantauan",
+"removedwatchtext" => "Halaman \"$1\" telah dihapus dari daftar pemantauan.",
+'watch' => 'Pantau',
+"watchthispage" => "Tambahkan ke daftar pemantauan",
+'unwatch' => 'Berhenti memantau',
+"unwatchthispage" => "Berhenti memantau",
+"notanarticle" => "Bukan sebuah artikel",
+"watchnochange" => "Tidak ada item-item yang Anda pantau telah berubah dalam jangka waktu yang ditampilkan.",
+"watchdetails" => "($1 halaman dipantau [tidak termasuk halaman pembicaraan]; $2 halaman berubah sejak cutoff; $3... [$4 lihat dan sunting daftar lengkap].)",
+"watchmethod-recent"=> "periksa daftar perubahan terbaru terhadap halaman yang dipantau",
+"watchmethod-list" => "periksa halaman yang dipantau terhadap perubahan terbaru",
+"removechecked" => "Hapus item yang diberi tanda cek dari daftar pemantauan",
+"watchlistcontains" => "Daftar pemantauan Anda berisi $1 halaman.",
+"watcheditlist" => "Berikut ini adalah daftar halaman-halaman yang Anda pantau. Untuk menghapus halaman dari daftar pemantauan Anda, berikan tanda cek pada kotak cek di sebelah judul halaman yang ingin Anda hapus, lalu klik tombol 'hapus yang dicek' yang terletak di bagian bawah layar.",
+"removingchecked" => "Menghapus item-item yang diminta dari daftar pemantauan Anda...",
+"couldntremove" => "Tidak dapat menghapus item '$1'...",
+"iteminvalidname" => "Ada masalah dengan item '$1' (namanya tidak sah)...",
+"wlnote" => "Di bawah ini adalah daftar $1 perubahan terakhir dalam <b>$2</b> jam terakhir.",
+"wlshowlast" => "Tampilkan $1 jam $2 hari $3 terakhir",
+"wlsaved" => "Ini adalah versi tersimpan dari daftar pemantauan Anda.",
+
+# Delete/protect/revert
+#
+"deletepage" => "Hapus halaman",
+"confirm" => "Konfirmasikan",
+"excontent" => "isi sebelumnya: '$1'",
+"exbeforeblank" => "isi sebelum dikosongkan: '$1'",
+"exblank" => "halaman kosong",
+"confirmdelete" => "Konfirmasi Penghapusan",
+"deletesub" => "(Menghapus \"$1\")",
+"historywarning" => "Peringatan: Halaman yang ingin Anda hapus mempunyai sejarah:",
+"confirmdeletetext" => "Anda akan menghapus halaman atau gambar ini secara permanen berikut semua sejarahnya dari basis data.  Pastikan bahwa Anda memang ingin berbuat demikian, mengetahui segala akibatnya, dan apa yang Anda lakukan ini adalah sejalan dengan [[Project:Kebijaksanaan|kebijaksanaan Wikipedia]].",
+"actioncomplete" => "Proses selesai",
+"deletedtext" => "\"$1\" telah dihapus. Lihat $2 untuk catatan terkini halaman yang telah dihapus.",
+"deletedarticle" => "menghapus \"$1\"",
+"dellogpage" => "Catatan_Penghapusan",
+"dellogpagetext" => "Di bawah ini adalah daftar terkini halaman yang telah dihapus. Semua waktu yang ditunjukkan adalah waktu server (UTC).",
+"deletionlog" => "catatan penghapusan",
+"reverted" => "Dikembalikan ke revisi sebelumnya",
+"deletecomment" => "Alasan penghapusan",
+"imagereverted" => "Berhasil mengembalikan ke revisi sebelumnya",
+"rollback" => "Rollback penyuntingan",
+'rollback_short' => 'Rollback',
+"rollbacklink" => "rollback",
+"rollbackfailed" => "Gagal Melakukan Rollback",
+"cantrollback" => "Tidak dapat mengembalikan penyuntingan; pengguna terakhir adalah satu-satunya penulis artikel ini.",
+"alreadyrolled" => "Tidak dapat melakukan rollback terhadap penyuntingan terakhir dari [[$1]] oleh [[Pengguna:$2|$2]] ([[Bicara_pengguna:$2|Pembicaraan); orang lain telah mengedit atau menlakukan rollback terhadap artikel tersebut.\n\nEdit terakhir oleh [[Pengguna:$3|$3]] ([[Bicara_pengguna:$3|Pembicaraan]]).",
+"editcomment" => "Komentar penyuntingan adalah: \"<i>$1</i>\".",
+"revertpage" => "Dikembalikan oleh $1",
+'sessionfailure' => 'Kelihatannya ada masalah dengan sesi login Anda; tindakan ini dibatalkan sebagai pencegahan terhadap pembajakan sesi. Silakan tekan "back", lalu reload-lah halaman yang sebelumnya Anda kunjungi, dan cobalah tindakan tersebut sekali lagi.',
+"protectlogpage" => "Catatan_Perlindungan",
+"protectlogtext" => "Di bawah ini adalah daftar catatan perlindungan/penghilangan perlindungan halaman. Lihat [[Project:Halaman_dilindungi]] untuk informasi lebih lanjut.",
+"protectedarticle" => "melindungi [[$1]]",
+"unprotectedarticle" => "menghilangkan perlindungan [[$1]]",
+"protectsub" =>"(Melindungi \"$1\")",
+"confirmprotecttext" => "Apakah Anda benar-benar ingin melindungi halaman ini?",
+"confirmprotect" => "Konfirmasi Perlindungan",
+'protectmoveonly' => 'Lindungi dari perpindahan saja',
+"protectcomment" => "Alasan perlindungan",
+"unprotectsub" =>"(Menghilangkan perlindungan terhadap \"$1\")",
+"confirmunprotecttext" => "Apakah Anda benar-benar ingin menghilangkan perlindungan terhadap halaman ini?",
+"confirmunprotect" => "Konfirmasi Penghilangan Perlindungan",
+"unprotectcomment" => "Alasan penghilangan perlindungan",
+
+# Undelete
+"undelete" => "Kembalikan Halaman yang Telah Dihapus",
+"undeletepage" => "Lihat dan Kembalikan Halaman yang Telah Dihapus",
+"undeletepagetext" => "Halaman-halaman berikut ini telah dihapus tapi masih ada di dalam arsip dan dapat dikembalikan. Arsip tersebut mungkin akan dibersihkan secara berkala.",
+"undeletearticle" => "Kembalikan halaman yang telah dihapus",
+"undeleterevisions" => "$1 revisi diarsipkan",
+"undeletehistory" => "Jika Anda mengembalikan halaman tersebut, semua revisi akan dikembalikan ke dalam sejarah. Jika sebuah halaman baru dengan nama yang sama telah dibuat sejak penghapusan, revisi yang telah dikembalikan akan kelihatan dalam sejarah dahulu, dan revisi terkini halaman tersebut tidak akan ditimpa secara otomatis.",
+"undeleterevision" => "Revisi yang telah dihapus per $1",
+"undeletebtn" => "Kembalikan!",
+"undeletedarticle" => "\"$1\" telah dikembalikan",
+'undeletedrevisions' => "$1 revisi telah dikembalikan",
+"undeletedtext" => "Halaman [[$1]] berhasil dikembalikan. Lihat [[Project:Catatan/Penghapusan]] untuk catatan terkini penghapusan dan pengembalian halaman.",
+
+# Contributions
+#
+"contributions" => "Sumbangan Pengguna",
+"mycontris" => "Sumbangan saya",
+"contribsub" => "Untuk $1",
+"nocontribs" => "Tidak ada perubahan yang cocok dengan kriteria-kriteria ini.",
+"ucnote" => "Di bawah ini adalah <b>$1</b> perubahan terakhir pengguna dalam <b>$2</b> hari terakhir.",
+"uclinks" => "Tampilkan $1 perubahan terbaru; tampilkan $2 hari terakhir",
+"uctop" => " (atas)" ,
+'newbies' => 'pengguna baru',
+
+# What links here
+#
+"whatlinkshere" => "Pautan ke halaman ini",
+"notargettitle" => "Tidak Ada Sasaran",
+"notargettext" => "Anda tidak menentukan halaman atau pengguna tujuan fungsi ini.",
+"linklistsub" => "(Daftar pautan)",
+"linkshere" => "Halaman-halaman berikut ini berpaut ke sini:",
+"nolinkshere" => "Tidak ada halaman yang berpaut ke sini.",
+"isredirect" => "halaman peralihan",
+
+# Block/unblock IP
+#
+"blockip" => "Blokir IP",
+"blockiptext" => "Gunakan formulir di bawah untuk memblokir kemampuan menulis sebuah alamat IP atau pengguna tertentu. Ini perlu dilakukan untuk mencegah vandalisme, dan sejalan dengan [[Project:Kebijaksanaan|kebijaksanaan Wikipedia]]. Masukkan alasan Anda di bawah (contohnya mengambil halaman tertentu yang telah dirusak).",
+"ipaddress" => "Alamat IP atau pengguna",
+"ipbexpiry" => "Kadaluwarsa",
+"ipbreason" => "Alasan",
+"ipbsubmit" => "Kirimkan",
+"badipaddress" => "Format alamat IP atau nama pengguna salah.",
+"blockipsuccesssub" => "Pemblokiran sukses",
+"blockipsuccesstext" => "Alamat IP atau pengguna \"$1\" telah diblokir. <br />Lihat [[Special:Ipblocklist|Daftar IP dan pengguna diblokir]] untuk melihat kembali pemblokiran.",
+"unblockip" => "Hilangkan blokir terhadap alamat IP atau pengguna",
+"unblockiptext" => "Gunakan formulir di bawah untuk mengembalikan kemampuan menulis sebuah alamat IP atau pengguna yang sebelumnya telah diblokir.",
+"ipusubmit" => "Hilangkan blokir terhadap alamat ini",
+"ipusuccess" => "Blokir terhadap alamat IP atau pengguna \"$1\" telah dihilangkan",
+"ipblocklist" => "Daftar Alamat IP dan Pengguna yang Diblokir",
+"blocklistline" => "$1, $2 memblokir $3 ($4)",
+"blocklink" => "blokir",
+"unblocklink" => "hilangkan blokir",
+"contribslink" => "sumbangan",
+"autoblocker" => "Diblokir secara otomatis karena Anda berbagi alamat IP dengan \"$1\". Alasan \"$2\".",
+"blocklogpage" => "Catatan_Pemblokiran",
+"blocklogentry" => 'memblokir "$1" dengan waktu kadaluwarsa pada $2',
+"blocklogtext" => "Ini adalah catatan tindakan pemblokiran dan penghilangan blokir terhadap pengguna. Alamat IP yang diblokir secara otomatis tidak terdapat di dalam daftar ini. Lihat [[Special:Ipblocklist|daftar alamat IP yang diblokir]] untuk daftar blokir terkini yang efektif.",
+"unblocklogentry" => 'menghilangkan blokir "$1"',
+"range_block_disabled" => "Kemampuan sysop dalam membuat blokir blok IP dimatikan.",
+"ipb_expiry_invalid" => "Waktu kadaluwarsa tidak sah.",
+"ip_range_invalid" => "Blok IP tidak sah.\n",
+"proxyblocker" => "Pemblokir proxy",
+"proxyblockreason" => "Alamat IP Anda telah diblokir karena alamat IP Anda adalah proxy terbuka. Silakan hubungi penyedia jasa internet Anda atau dukungan teknis dan beritahukan mereka masalah keamanan serius ini.",
+"proxyblocksuccess" => "Selesai.\n",
+'sorbs' => 'SORBS DNSBL',
+'sorbsreason' => 'Alamat IP anda terdaftar sebagai proxy terbuka di [http://www.sorbs.net SORBS] DNSBL.',
+'sorbs_create_account_reason' => 'Alamat IP anda terdaftar sebagai proxy terbuka di [http://www.sorbs.net SORBS] DNSBL. Anda tidak dapat membuat akun.',
+
+# Make sysop
+"makesysoptitle" => "Buat Seorang Pengguna Menjadi Sysop",
+"makesysoptext" => "Formulir ini digunakan oleh para birokrat untuk menjadikan pengguna biasa menjadi seorang administrator. Ketikkan nama pengguna yang dimaksud dalam kotak dan tekan tombol untuk menjadikan pengguna tersebut seorang administrator",
+"makesysopname" => "Nama pengguna:",
+"makesysopsubmit" => "Jadikan sysop",
+"makesysopok" => "<b>Pengguna \"$1\" sekarang adalah seorang sysop</b>",
+"makesysopfail" => "<b>Pengguna \"$1\" tidak dapat dijadikan sysop. (Apakah Anda mengetikkan namanya dengan benar?)</b>",
+"setbureaucratflag" => "Atur flag birokrat",
+"bureaucratlog" => "Catatan_Birokrat",
+'rightslogtext' => 'Ini adalah catatan perubahan terhadap hak-hak pengguna.',
+"bureaucratlogentry" => "Hak-hak pengguna \"$1\" diatur \"$2\"",
+"rights" => "Hak-hak:",
+"set_user_rights" => "Atur hak-hak pengguna",
+"user_rights_set" => "<b>Hak-hak pengguna \"$1\" diperbarui</b>",
+"set_rights_fail" => "<b>Hak-hak pengguna \"$1\" tidak dapat diatur. (Apakah Anda mengetikkan namanya dengan benar?)</b>",
+"makesysop" => "Buat Seorang Pengguna Menjadi Sysop",
+
+# Developer tools
+#
+"lockdb" => "Kunci Basis Data",
+"unlockdb" => "Buka Kunci Basis Data",
+"lockdbtext" => "Mengunci basis data akan menghentikan kemampuan semua pengguna dalam menyunting halaman, mengubah konfigurasi pengguna, menyunting daftar pemantauan mereka, dan hal-hal lain yang memerlukan perubahan terhadap basis data. Pastikan bahwa ini adalah yang ingin Anda lakukan, dan bahwa Anda akan membuka kunci basis data setelah pemeliharaan selesai.",
+"unlockdbtext" => "Membuka kunci basis data akan mengembalikan kemampuan semua pengguna dalam menyunting halaman, mengubah konfigurasi pengguna, menyunting daftar pemantauan mereka, dan hal-hal lain yang memerlukan perubahan terhadap basis data.  Pastikan bahwa ini adalah yang ingin Anda lakukan.",
+"lockconfirm" => "Ya, saya memang ingin mengunci basis data.",
+"unlockconfirm" => "Ya, saya memang ingin membuka kunci basis data.",
+"lockbtn" => "Kunci basis data",
+"unlockbtn" => "Buka kunci basis data",
+"locknoconfirm" => "Anda tidak memberikan tanda cek pada kotak konfirmasi.",
+"lockdbsuccesssub" => "Penguncian basis data berhasil",
+"unlockdbsuccesssub" => "Pembukaan kunci basis data berhasil",
+"lockdbsuccesstext" => "Basis data telah dikunci. <br />Pastikan Anda membuka kuncinya setelah pemeliharaan selesai.",
+"unlockdbsuccesstext" => "Kunci basis data telah dibuka.",
+
+# Validation
+'val_clear_old' => 'Hapus data pengesahan saya yang lainnya untuk $1',
+'val_merge_old' => 'Gunakan penilaian saya sebelumnya jika saya memilih \'Abstain\'',
+'val_form_note' => '<b>Petunjuk:</b> Menggabungkan data Anda berarti bahwa untuk revisi pengesahan yang Anda pilih, semua pilihan Anda yang <i>Abstain</i> akan diganti dengan pilihan dan komentar dari revisi yang paling baru yang mana untuk pilihan tersebut Anda tidak abstain. Sebagai contoh, jika Anda ingin mengganti pilihan tunggal dengan revisi yang lebih baru, tetapi tidak ingin mengganti pilihan Anda yang lainnya untuk revisi artikel ini, pilih pilihan mana yang ingin anda ubah, dan penggabungan akan mengisi pilihan lainnya dengan pilihan Anda sebelumnya.',
+'val_noop' => 'Abstain',
+'val_percent' => '<b>$1%</b><br />($2 dari $3 poin<br />oleh $4 pengguna)',
+'val_percent_single' => '<b>$1%</b><br />($2 dari $3 poin<br />oleh seorang pengguna)',
+'val_total' => 'Total',
+'val_version' => 'Versi',
+'val_tab' => 'Pengesahan',
+'val_this_is_current_version' => 'ini adalah versi terbaru',
+'val_version_of' => "Version of $1",
+'val_table_header' => "<tr><th>Kelas</th>$1<th colspan=4>Pendapat</th>$1<th>Komentar</th></tr>\n",
+'val_stat_link_text' => 'Statistik pengesahan artikel ini',
+'val_view_version' => 'Lihat versi ini',
+'val_validate_version' => 'Sahkan versi ini',
+'val_user_validations' => 'Penggung ini telah mengesahkan $1 halaman.',
+'val_no_anon_validation' => 'Anda harus login untuk dapat mengesahkan artikel.',
+'val_validate_article_namespace_only' => 'Hanya artikel saja yang dapat disahkan. Halaman ini <i>tidak</i> berada dalam namespace artikel.',
+'val_validated' => 'Pengesahan selesai.',
+'val_article_lists' => 'Daftar artikel yang telah disahkan',
+'val_page_validation_statistics' => 'Statistik pengesahan halaman untuk $1',
+
+# Move page
+#
+"movepage" => "Pindahkan Halaman",
+"movepagetext" => "Formulir di bawah ini digunakan untuk mengubah nama suatu halaman dan memindahkan semua data sejarah ke nama baru. Judul yang lama akan menjadi halaman peralihan menuju judul yang baru. Pautan kepada judul lama tidak akan berubah. Pastikan untuk memeriksa terhadap peralihan halaman yang rusak atau berganda setelah pemindahan. Anda bertanggung jawab untuk memastikan bahwa pautan terus menyambung ke halaman yang seharusnya.\n\nPerhatikan bahwa halaman '''tidak''' akan dipindah apabila telah ada halaman di pada judul yang baru, kecuali bila halaman tersebut kosong atau merupakan halaman peralihan dan tidak mempunyai sejarah penyuntingan. Ini berarti Anda dapat mengubah nama halaman kembali seperti semula apabila Anda membuat kesalahan, dan Anda tidak dapat menimpa halaman yang telah ada.\n\n<b>PERINGATAN!</b> Ini dapat mengakibatkan perubahan yang tak terduga dan drastis  bagi halaman yang populer. Pastikan Anda mengerti konsekuensi dari perbuatan ini sebelum melanjutkan.",
+"movepagetalktext" => "Halaman pembicaraan yang berkaitan, jika ada, juga akan dipindahkan secara otomatis '''kecuali apabila:'''\n*Anda memindahkan halaman melintasi namespace,\n*Sebuah halaman pembicaraan yang tidak kosong telah ada di bawah judul baru, atau\n*Anda tidak memberi tanda cek pada kotak cek di bawah ini.\n\nDalam kasus tersebut, apabila diinginkan, Anda dapat memindahkan atau menggabungkan halaman secara manual.",
+"movearticle" => "Pindahkan halaman",
+"movenologin" => "Belum login",
+"movenologintext" => "Anda harus menjadi pengguna terdaftar dan telah [[Special:Userlogin|login]] untuk memindahkan halaman.",
+"newtitle" => "Ke judul baru",
+"movepagebtn" => "Pindahkan halaman",
+"pagemovedsub" => "Pemindahan berhasil",
+"pagemovedtext" => "Halaman \"[[$1]]\" dipindahkan ke \"[[$2]]\".",
+"articleexists" => "Halaman dengan nama tersebut telah ada atau nama yang dipilih tidak sah. Silakan pilih nama lain.",
+"talkexists" => "Halaman tersebut berhasil dipindahkan, tetapi halaman pembicaraan dari halaman tersebut tidak dapat dipindahkan karena telah ada halaman pembicaraan pada judul yang baru. Silakan gabungkan halaman-halaman pembicaraan tersebut secara manual.",
+"movedto" => "dipindahkan ke",
+"movetalk" => "Pindahkan halaman \"pembicaraan\" juga, jika mungkin.",
+"talkpagemoved" => "Halaman pembicaraan yang berkaitan juga ikut dipindahkan.",
+"talkpagenotmoved" => "Halaman pembicaraan yang berkaitan <strong>tidak</strong> ikut dipindahkan.",
+"1movedto2" => "$1 dipindahkan ke $2",
+'1movedto2_redir' => '$1 dipindahkan ke $2 melalui peralihan',
+
+# Export
+
+"export" => "Ekspor Halaman",
+'exporttext'    => 'Anda dapat mengekspor teks dan sejarah penyuntingan suatu halaman tertentu atau sejumlah halaman terbungkus dalam XML tertentu. Di masa depan, hasil ekspor ini dapat diimpor di wiki lainnya yang menggunakan perangkat lunak MediaWiki, meskipun fitur impor belum tersedia dalam versi ini.\n\nUntuk mengekspor halaman-halaman artikel, masukkan judul-judul dalam kotak teks di bawah ini, satu judul per baris, dan pilih apakah anda ingin mengekspor versi sekarang dengan versi sebelumnya, dengan catatan sejarah halaman, atau hanya versi sekarang dengan catatan penyuntingan terakhir.\n\nJika Anda hanya ingin mengimpor versi sekarang, Anda juga dapat melakukan hal ini dengan lebih cepat dengan cara menggunakan pautan khusus, sebagai contoh: [[{{ns:Special}}:Export/Train]] untuk mengekspor artikel [[Train]].',
+"exportcuronly" => "Hanya ekspor revisi sekarang, bukan seluruh sejarah",
+
+# Namespace 8 related
+
+"allmessages" => "Semua Pesan Sistem",
+'allmessagesname' => 'Nama',
+'allmessagesdefault' => 'Teks baku',
+'allmessagescurrent' => 'Teks sekarang',
+'allmessagestext' => 'Ini adalah daftar semua pesan sistem yang tersedia dalam namespace MediaWiki:',
+'allmessagesnotsupportedUI' => 'Bahasa antarmuka Anda saat ini, <b>$1</b> tidak didukung oleh Istimewa:AllMessages di situs ini.',
+'allmessagesnotsupportedDB' => 'Istimewa:AllMessages tidak didukung karena wgUseDatabaseMessages dimatikan.',
+
+# Thumbnails
+
+"thumbnail-more" => "Perbesar",
+"missingimage" => "<b>Gambar hilang</b><br /><i>$1</i>\n",
+'filemissing' => 'File hilang',
+
+# Special:Import
+"import" => "Impor Halaman",
+"importtext" => "Silakan ekspor file dari wiki asal menggunakan utilitas Istimewa:Export, simpan ke disk, dan unggahkan ke sini.",
+"importfailed" => "Impor gagal: $1",
+"importnotext" => "Kosong atau tidak ada teks",
+"importsuccess" => "Impor sukses!",
+"importhistoryconflict" => "Terjadi konflik revisi sejarah (mungkin pernah mengimpor halaman ini sebelumnya)",
+
+# Keyboard access keys for power users
+'accesskey-search' => 'f',
+'accesskey-minoredit' => 'i',
+'accesskey-save' => 's',
+'accesskey-preview' => 'p',
+'accesskey-compareselectedversions' => 'v',
+
+# tooltip help for the main actions
+'tooltip-watch' => 'Tambahkan halaman ini ke daftar pemantauan Anda [alt-w]',
+'tooltip-search' => 'Cari dalam wiki ini [alt-f]',
+'tooltip-minoredit' => 'Tandai ini sebagai suntingan kecil [alt-i]',
+'tooltip-save' => 'Simpan perubahan Anda [alt-s]',
+'tooltip-preview' => 'Pratilik perubahan Anda -- mohon gunakan ini sebelum menyimpan! [alt-p]',
+'tooltip-compareselectedversions' => 'Lihat perbedaan antara dua versi halaman yang dipilih. [alt-v]',
+
+# stylesheets
+
+#'Monobook.css' => '/* edit this file to customize the monobook skin for the entire site */',
+#'Monobook.js' => '/* edit this file to change js things in the monobook skin */',
+
+# Metadata
+"nodublincore" => "Metadata Dublin Core RDF dimatikan di server ini.",
+"nocreativecommons" => "Metadata Creative Commons RDF dimatikan di server ini.",
+"notacceptable" => "Server wiki tidak dapat menyediakan data dalam format yang dapat dibaca oleh client Anda.",
+
+# Attribution
+
+"anonymous" => "Pengguna(-pengguna) anonim {{SITENAME}}",
+"siteuser" => "Pengguna {{SITENAME}} $1",
+"lastmodifiedby" => "Halaman ini terakhir kali diubah $1 oleh $2.",
+"and" => "dan",
+"othercontribs" => "Didasarkan pada karya $1.",
+'others' => 'lainnya',
+"siteusers" => "Pengguna(-pengguna) {{SITENAME}} $1",
+'creditspage' => 'Penghargaan halaman',
+'nocredits' => 'Tidak ada informasi penghargaan yang tersedia untuk halaman ini.',
+
+# Spam protection
+
+'spamprotectiontitle' => 'Filter Pencegah Spam',
+'spamprotectiontext' => 'Halaman yang ingin Anda simpan diblokir oleh filter spam. Ini mungkin disebabkan oleh pautan ke situs luar.\n\nAnda dapat memeriksa regular expression berikut terhadap pola-pola yang diblokir:',
+'spamprotectionmatch' => 'Teks berikut ini memancing filter spam kami: $1',
+'subcategorycount' => "Ada $1 subkategori dalam kategori ini.",
+'subcategorycount1' => "Ada $1 subkategori dalam kategori ini.",
+'categoryarticlecount' => "Ada $1 artikel dalam kategori ini.",
+'categoryarticlecount1' => "Ada $1 artikel dalam kategori ini.",
+'usenewcategorypage' => "1\n\nUbah karakter pertama menjadi \"0\" untuk mematikan tata letak halaman kategori yang baru.",
+'listingcontinuesabbrev' => " lanjut",
+
+# Info page
+"infosubtitle" => "Informasi halaman",
+"numedits" => "Jumlah penyuntingan (artikel): $1",
+"numtalkedits" => "Jumlah penyuntingan (halaman diskusi): $1",
+"numwatchers" => "Jumlah pengamat: $1",
+"numauthors" => "Jumlah pengarang yang berbeda (artikel): $1",
+"numtalkauthors" => "Jumlah pengarang yang berbeda (halaman diskusi): $1",
+
+# Math options
+'mw_math_png' => "Selalu buat PNG",
+'mw_math_simple' => "HTML jika sangat sederhana atau PNG",
+'mw_math_html' => "HTML jika mungkin atau PNG",
+'mw_math_source' => "Biarkan sebagai TeX (untuk browser teks)",
+'mw_math_modern' => "Disarankan untuk browser modern",
+'mw_math_mathml' => "MathML jika mungkin (percobaan)",
+
+# Patrolling
+'markaspatrolleddiff'   => "Tandai telah diperiksa",
+'markaspatrolledlink'   => "[$1]",
+'markaspatrolledtext'   => "Tandai artikel ini telah diperiksa",
+'markedaspatrolled'     => "Telah ditandai telah diperiksa",
+'markedaspatrolledtext' => "Revisi yang dipilih telah ditandai sebagai telah diperiksa",
+'rcpatroldisabled'      => "Recent Changes Patrol dimatikan",
+'rcpatroldisabledtext'  => "Fitur Recent Changes Patrol sedang dimatikan.",
+
+# Monobook.js: tooltips and access keys for monobook
+'Monobook.js' => '/* tooltips and access keys */
+ta = new Object();
+ta[\'pt-userpage\'] = new Array(\'.\',\'Halaman pengguna saya\');
+ta[\'pt-anonuserpage\'] = new Array(\'.\',\'Halaman pengguna IP Anda\');
+ta[\'pt-mytalk\'] = new Array(\'n\',\'Halaman pembicaraan saya\');
+ta[\'pt-anontalk\'] = new Array(\'n\',\'Diskusi tentang suntingan dari alamat IP ini\');
+ta[\'pt-preferences\'] = new Array(\'\',\'Konfigurasi saya\');
+ta[\'pt-watchlist\'] = new Array(\'l\',\'Daftar halaman yang Anda pantau.\');
+ta[\'pt-mycontris\'] = new Array(\'y\',\'Daftar sumbangan saya\');
+ta[\'pt-login\'] = new Array(\'o\',\'Anda disarankan untuk login, meskipun hal itu tidak diwajibkan.\');
+ta[\'pt-anonlogin\'] = new Array(\'o\',\'Anda disarankan untuk login, meskipun hal itu tidak diwajibkan.\');
+ta[\'pt-logout\'] = new Array(\'o\',\'Log out\');
+ta[\'ca-talk\'] = new Array(\'t\',\'Diskusi tentang artikel\');
+ta[\'ca-edit\'] = new Array(\'e\',\'Anda dapat menyunting halaman ini. Silakan gunakan tombol pratilik sebelum menyimpan.\');
+ta[\'ca-addsection\'] = new Array(\'+\',\'Tambahkan komentar ke diskusi ini.\');
+ta[\'ca-viewsource\'] = new Array(\'e\',\'Halaman ini dilindungi. Anda hanya dapat melihat sumbernya.\');
+ta[\'ca-history\'] = new Array(\'h\',\'Versi-versi sebelumnya dari halaman ini.\');
+ta[\'ca-protect\'] = new Array(\'=\',\'Lindungi halaman ini\');
+ta[\'ca-delete\'] = new Array(\'d\',\'Hapus halaman ini\');
+ta[\'ca-undelete\'] = new Array(\'d\',\'Kembalikan suntingan ke halaman ini sebelum halaman ini dihapus\');
+ta[\'ca-move\'] = new Array(\'m\',\'Pindahkan halaman ini\');
+ta[\'ca-watch\'] = new Array(\'w\',\'Tambahkan halaman ini ke daftar pemantauan Anda\');
+ta[\'ca-unwatch\'] = new Array(\'w\',\'Hapus halaman ini dari daftar pemantauan Anda\');
+ta[\'search\'] = new Array(\'f\',\'Cari dalam wiki ini\');
+ta[\'p-logo\'] = new Array(\'\',\'Halaman Utama\');
+ta[\'n-mainpage\'] = new Array(\'z\',\'Kunjungi Halaman Utama\');
+ta[\'n-portal\'] = new Array(\'\',\'Tentang proyek, apa yang dapat anda lakukan, di mana mencari sesuatu\');
+ta[\'n-currentevents\'] = new Array(\'\',\'Temukan informasi tentang kejadian terkini\');
+ta[\'n-recentchanges\'] = new Array(\'r\',\'Daftar perubahan terbaru dalam wiki.\');
+ta[\'n-randompage\'] = new Array(\'x\',\'Tampilkan sembarang halaman\');
+ta[\'n-help\'] = new Array(\'\',\'Tempat mencari bantuan.\');
+ta[\'n-sitesupport\'] = new Array(\'\',\'Dukung kami\');
+ta[\'t-whatlinkshere\'] = new Array(\'j\',\'Daftar semua halaman wiki yang berpaut ke sini\');
+ta[\'t-recentchangeslinked\'] = new Array(\'k\',\'Perubahan terbaru halaman-halaman yang berpaut dengan halaman ini\');
+ta[\'feed-rss\'] = new Array(\'\',\'RSS feed untuk halaman ini\');
+ta[\'feed-atom\'] = new Array(\'\',\'Atom feed untuk halaman ini\');
+ta[\'t-contributions\'] = new Array(\'\',\'Lihat daftar sumbangan pengguna ini\');
+ta[\'t-emailuser\'] = new Array(\'\',\'Kirimkan e-mail kepada pengguna ini\');
+ta[\'t-upload\'] = new Array(\'u\',\'Unggahkan gambar atau file media\');
+ta[\'t-specialpages\'] = new Array(\'q\',\'Daftar semua halaman istimewa\');
+ta[\'ca-nstab-main\'] = new Array(\'c\',\'Lihat halaman isi (artikel)\');
+ta[\'ca-nstab-user\'] = new Array(\'c\',\'Lihat halaman pengguna\');
+ta[\'ca-nstab-media\'] = new Array(\'c\',\'Lihat halaman media\');
+ta[\'ca-nstab-special\'] = new Array(\'\',\'Ini adalah halaman istimewa yang tidak dapat disunting.\');
+ta[\'ca-nstab-wp\'] = new Array(\'a\',\'Lihat halaman proyek\');
+ta[\'ca-nstab-image\'] = new Array(\'c\',\'Lihat halaman gambar\');
+ta[\'ca-nstab-mediawiki\'] = new Array(\'c\',\'Lihat pesan sistem\');
+ta[\'ca-nstab-template\'] = new Array(\'c\',\'Lihat templat\');
+ta[\'ca-nstab-help\'] = new Array(\'c\',\'Lihat halaman bantuan\');
+ta[\'ca-nstab-category\'] = new Array(\'c\',\'Lihat halaman kategori\');
+',
+
+# image deletion
+'deletedrevision' => 'Menghapus revisi tua $1.',
+
+# browsing diffs
+'previousdiff' => '← Ke diff sebelumnya',
+'nextdiff' => 'Ke diff selanjutnya →',
+
+'imagemaxsize' => 'Batasi gambar dalam halaman deskripsi gambar sampai: ',
+'showbigimage' => 'Download versi resolusi tinggi ($1x$2, $3 KB)',
+
+'newimages' => 'Galeri-Gambar Baru',
+'noimages'  => 'Tidak ada yang dilihat.',
+
+# labels for User: and Title: on Special:Log pages
+'specialloguserlabel' => 'Pengguna: ',
+'speciallogtitlelabel' => 'Judul: ',
+
+);
+
+class LanguageId extends LanguageUtf8 {
+
+       function getBookstoreList () {
+               global $wgBookstoreListId;
+               return $wgBookstoreListId;
+       }
+
+       function getNamespaces() {
+               global $wgNamespaceNamesId;
+               return $wgNamespaceNamesId;
+       }
+
+       function getNsIndex( $text ) {
+               global $wgNamespaceNamesId, $wgNamespaceAlternatesId;
+
+               foreach ( $wgNamespaceNamesId as $i => $n ) {
+                       if ( 0 == strcasecmp( $n, $text ) ) { return $i; }
+               }
+               foreach ( $wgNamespaceAlternatesId as $i => $n ) {
+                       if ( 0 == strcasecmp( $n, $text ) ) { return $i; }
+               }
+
+               # For backwards compatibility
+               global $wgNamespaceNamesEn;
+               foreach ( $wgNamespaceNamesEn as $i => $n ) {
+                       if ( 0 == strcasecmp( $n, $text ) ) { return $i; }
+               }
+               return false;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsId;
+               return $wgQuickbarSettingsId;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesId;
+               return $wgSkinNamesId;
+       }
+
+       function getDateFormats() {
+               global $wgDateFormatsId;
+               return $wgDateFormatsId;
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesId;
+               if( isset( $wgAllMessagesId[$key] ) ) {
+                       return $wgAllMessagesId[$key];
+               } else {
+                       return parent::getMessage( $key );
+               }
+       }
+
+       function formatNum( $number ) {
+               global $wgTranslateNumerals;
+               return $wgTranslateNumerals ? strtr($number, '.,', ',.' ) : $number;
+       }
+
+}
+
+?>
diff --git a/languages/LanguageIs.php b/languages/LanguageIs.php
new file mode 100644 (file)
index 0000000..9288486
--- /dev/null
@@ -0,0 +1,827 @@
+<?php
+/**
+ * @package MediaWiki
+ * @subpackage Language
+ */
+
+# Most of this was written by Ævar Arnfjörð Bjarmason <avarab@gmail.com>
+
+require_once( 'LanguageUtf8.php' );
+
+/* private */ $wgNamespaceNamesIs = array(
+       NS_MEDIA                => 'Miðill',
+       NS_SPECIAL              => 'Kerfissíða',
+       NS_MAIN                 => '',
+       NS_TALK                 => 'Spjall',
+       NS_USER                 => 'Notandi',
+       NS_USER_TALK            => 'Notandaspjall',
+       NS_PROJECT              => $wgMetaNamespace,
+       NS_PROJECT_TALK         => $wgMetaNamespace . 'spjall',
+       NS_IMAGE                => 'Mynd',
+       NS_IMAGE_TALK           => 'Myndaspjall',
+       NS_MEDIAWIKI            => 'Melding',
+       NS_MEDIAWIKI_TALK       => 'Meldingarspjall',
+       NS_TEMPLATE             => 'Snið',
+       NS_TEMPLATE_TALK        => 'Sniðaspjall',
+       NS_HELP                 => 'Hjálp',
+       NS_HELP_TALK            => 'Hjálparspjall',
+       NS_CATEGORY             => 'Flokkur',
+       NS_CATEGORY_TALK        => 'Flokkaspjall'
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgQuickbarSettingsIs = array(
+       'Sleppa', 'Fast vinstra megin', 'Fast hægra megin', 'Fljótandi til vinstri'
+);
+
+/* private */ $wgSkinNamesIs = array(
+       'standard'      => 'Klassískt',
+       'nostalgia'     => 'Gamaldags',
+       'cologneblue'   => 'Kölnarblátt',
+       'myskin'        => 'Mitt þema',
+) + $wgSkinNamesEn;
+
+/* private */ $wgDateFormatsIs = array(
+       'Sjálfgefið',
+       '15. janúar 2001 kl. 16:12',
+       '15. jan. 2001 kl. 16:12',
+       '16:12, 15. janúar 2001',
+       '16:12, 15. jan. 2001',
+       'ISO 8601' => '2001-01-15 16:12:34'
+);
+
+$wgMagicWordsIs = array(
+       MAG_REDIRECT             => array( 0,    '#redirect', '#tilvísun', '#TILVÍSUN' ), // MagicWord::initRegex() sucks
+) + $wgMagicWordsEn;
+
+#-------------------------------------------------------------------
+# Default messages
+#-------------------------------------------------------------------
+
+$wgAllMessagesIs = array(
+'linktrail' => '/^([áðéíóúýþæöa-z-–]+)(.*)$/sDu',
+'linkprefix'=> '/^(.*?)([áÁðÐéÉíÍóÓúÚýÝþÞæÆöÖA-Za-z-–]+)$/sDu',
+
+'1movedto2' => "$1 færð á $2",
+'1movedto2_redir' => "$1 færð á $2 yfir tilvísun",
+'Monobook.css' => "
+/* Stórir stafir í ýmsu */
+#p-personal ul { text-transform: inherit; } /* notandanfn, spjall, stillingar */
+.portlet h5 { text-transform: inherit;}     /* flakk, leit, verkfæri... */
+#p-cactions li a {text-transform: inherit;} /* notandasíða, spjall... */
+",
+'Monobook.js' => "/* tooltips and access keys */
+ta = new Object();
+ta['pt-userpage'] = new Array('.','Notendasíðan mín');
+ta['pt-anonuserpage'] = new Array('.','Notendasíðan fyrir IP töluna þína');
+ta['pt-mytalk'] = new Array('n','Spallsíðan mín');
+ta['pt-anontalk'] = new Array('n','Spjallsíðan fyrir þessa IP tölu');
+ta['pt-preferences'] = new Array('','Almennar stillingar');
+ta['pt-watchlist'] = new Array('l','Vaktlistinn.');
+ta['pt-mycontris'] = new Array('y','Listi yfir framlög þín');
+ta['pt-login'] = new Array('o','Þú ert hvattur/hvött til að innskrá þig, það er hinsvegar ekki nauðsynlegt.');
+ta['pt-anonlogin'] = new Array('o','Þú ert hvattur/hvött til að innskrá þig, það er hinsvegar ekki nauðsynlegt.');
+ta['pt-logout'] = new Array('o','Útskráning');
+ta['ca-talk'] = new Array('t','Spallsíða þessarar síðu');
+ta['ca-edit'] = new Array('e','Þú getur breytt síðu þessari, vinsamlegast notaðu „forskoða“ hnappinn áður en þú vistar');
+ta['ca-addsection'] = new Array('+','Viðbótarumræða.');
+ta['ca-viewsource'] = new Array('e','Síða þessi er vernduð, þú getur þó skoðað frumkóða hennar.');
+ta['ca-history'] = new Array('h','Eldri útgáfur af síðunni.');
+ta['ca-protect'] = new Array('=','Vernda þessa síðu');
+ta['ca-delete'] = new Array('d','Eyða þessari síðu');
+ta['ca-undelete'] = new Array('d','Endurvekja breytingar á síðu þessari fyrir en henni var tortímt');
+ta['ca-move'] = new Array('m','Færa þessa síðu');
+ta['ca-watch'] = new Array('w','Bæta þessari síðu við á vaktlistann');
+ta['ca-unwatch'] = new Array('w','Fjarlægja þessa síðu af vaktlistanum');
+ta['search'] = new Array('f','Leit');
+ta['p-logo'] = new Array('','Forsíða');
+ta['n-mainpage'] = new Array('z','Forsíða {{SITENAME}}');
+ta['n-portal'] = new Array('','Um verkefnið, hvernig er hægt að hjálpa og hvar á að byrja');
+ta['n-currentevents'] = new Array('','Líðandi stund');
+ta['n-recentchanges'] = new Array('r','Listi yfir nýlegar breytingar.');
+ta['n-randompage'] = new Array('x','Handahófsvalin síða');
+ta['n-help'] = new Array('','Efnisyfirlit yfir hjálparsíður.');
+ta['n-sitesupport'] = new Array('','Fjárframlagssíða Wikimedia');
+ta['t-whatlinkshere'] = new Array('j','Listi yfir síður sem tengjast í þessa');
+ta['t-recentchangeslinked'] = new Array('k','Nýlegar breitingar á ítengdum síðum');
+ta['feed-rss'] = new Array('','RSS fyrir þessa síðu');
+ta['feed-atom'] = new Array('','Atom fyrir þessa síðu');
+ta['t-contributions'] = new Array('','Sýna framlagslista þessa notanda');
+ta['t-emailuser'] = new Array('','Senda notanda þessum póst');
+ta['t-upload'] = new Array('u','Innhlaða myndum eða margmiðlunarskrám');
+ta['t-specialpages'] = new Array('q','Listi yfir kerfissíður');
+ta['ca-nstab-main'] = new Array('c','Sýna síðuna');
+ta['ca-nstab-user'] = new Array('c','Sýna notendasíðuna');
+ta['ca-nstab-media'] = new Array('c','Sýna margmiðlunarsíðuna');
+ta['ca-nstab-special'] = new Array('','Þetta er kerfissíða, þér er óhæft að breyta henni.');
+ta['ca-nstab-wp'] = new Array('a','Sýna verkefnasíðuna');
+ta['ca-nstab-image'] = new Array('c','Sýna myndasíðuna');
+ta['ca-nstab-mediawiki'] = new Array('c','Sýna kerfisskilaboðin');
+ta['ca-nstab-template'] = new Array('c','View the template');
+ta['ca-nstab-help'] = new Array('c','Sýna hjálparsíðuna');
+ta['ca-nstab-category'] = new Array('c','Sýna efnisflokkasíðuna');",
+'about' => "Um",
+'aboutpage' => "Project:Um",
+'aboutsite' => "Um {{SITENAME}}",
+'accmailtext' => "Lykilorðið fyrir „$1“ hefur verið sent á $2.",
+'accmailtitle' => "Lykilorð sent.",
+'acct_creation_throttle_hit' => "Fyrirgefðu, þú hefur nú þegar búið til $1 aðgang(a). Þú getur ekki búið til fleiri.",
+'actioncomplete' => "Aðgerð lokið",
+'addedwatch' => "Bætt á vaktlistann",
+'addedwatchtext' => "Síðunni „$1“ hefur verið bætt á [[Special:Watchlist|Vaktlistann]] þinn.
+Frekari breytingar á henni eða spallsíðu hennar munu verða sýndar þar.
+Þar að auki verður síða þessi '''feitletruð''' á [[Special:Recentchanges|Nýlegum breytingum]]
+svo auðveldara sé að sjá hana þar meðal fjöldans.
+
+<p>Til að fjarlægja síðu þessa af vaktlistanum þarft þú að ýta á tengilinn er merktur er „afvakta“.",
+'administrators' => "{{ns:4}}:Stjórnendur",
+'allmessages' => "Kerfismeldingar",
+'allmessagescurrent' => "Núverandi texti",
+'allmessagesdefault' => "Sjálfgefinn texti",
+'allmessagesname' => "Titill",
+'allmessagestext' => "Listi yfir meldingar í „{{ns:8}}“ nafnarýminu.",
+'allpages' => "Allar síður",
+'alphaindexline' => "$1 til $2",
+'alreadyloggedin' => "<strong>Notandinn $1 er þegar innskráður!</strong><br />",
+'ancientpages' => "Elstu síður",
+'anontalkpagetext' => "----Þetta er spjallsíða fyrir óskráðan notanda sem hefur ekki búið til aðgang enn þá eða notar hann ekki, slíkir notendur þekkjast á [[IP tala|IP tölu]] sinni. Það getur gerst að margir notendur deili sömu IP tölu þannig að athugasemdum sem beint er til eins notanda geta birst á spjallsíðu annars. [[Special:Userlogin|Skráðu þig sem notanda]] til að koma í veg fyrir svona misskilning.''",
+'apr' => "apr",
+'april' => "apríl",
+'articleexists' => "Annaðhvort er þegar til síða undir þessum titli,
+eða sá titill sem þú hefur valið er ekki gildur.
+Vinsamlegast veldu annan titil.",
+'aug' => "ágú",
+'august' => "ágúst",
+'badfilename' => "Skáarnafninu hefur verið breytt í „$1“.",
+'badquery' => "Illa sniðin leitarfyrirspurn",
+'badtitle' => "Ógildur titill",
+'badtitletext' => "Umbeðin síðutitill er ógildur.",
+'blanknamespace' => "(Aðalnafnrýmið)",
+'blockip' => "Banna notanda",
+'blockipsuccesstext' => "„$1“ hefur verið bannaður.<br />
+Sjá [[Special:Ipblocklist|bannaðar notendur og IP tölur]] fyrir yfirlit yfir núverandi bönn.",
+'blockiptext' => "Hægt er að hindra einstaka notendur eða IP tölur í að gera breytingar á {{SITENAME}}
+
+Útrennslutímar eru í stöðluðu GNU sniði sem farið er yfir í [http://www.gnu.org/software/tar/manual/html_chapter/tar_7.html tar handbókinni], Til dæmis „1 hour“, „2 days“, „next Wednesday“, „1 January 2017“ eða „indefinite“ og „infinite“ til að banna að eylífu, þetta ætti þó aðeins að vera notað á ódauðlegar verur þar sem um 150 ár ættu að duga jafnvel á þrjóskasta fólk.
+
+Sjá [[meta:Range blocks|Range blocks]] á meta fyrir yfirlit yfir [[CIDR]] tölur, [[{{ns:Special}}:Ipblocklist|bannaða notendur og IP tölur]] fyrir lista yfir þá sem nú eru bannaðir og [[{{ns:4}}:Bönnunarskrá|bönnunarskrá]] fyrir lista sem inniheldur einnig þá sem hafa verið bannaðir í fortíðinni.",
+'blocklink' => "banna",
+'blocklistline' => "$1, $2 bannaði $3 ($4)",
+'infiniteblock' => 'rennur út infinite', //fixme
+'expiringblock' => 'rennur út  $1',
+'blocklogpage' => "Bönnunarskrá",
+'blocklogtext' => "This is a log of user blocking and unblocking actions. Automatically
+blocked IP addresses are not be listed. See the [[Special:Ipblocklist|IP block list]] for
+the list of currently operational bans and blocks.",
+'bold_sample' => "Feitletraður texti",
+'bold_tip' => "Feitletraður texti",
+'booksources' => "Bókabúðir",
+'bureaucrattext' => "[[{{ns:4}}:Möppudýr|Möppudýrsréttindi]] eru skilyrði fyrir því að nota þessa kerfissíðu.",
+'bureaucrattitle' => "Möppudýrsréttinda þörf",
+'bydate' => "eftir dagsetningu",
+'byname' => "eftir nafni",
+'bysize' => "eftir stærð",
+'cachederror' => "Eftirfarandi er afrit af umbeðinni síðu og gæti því ekki verið nýjasta útgáfa hennar:",
+'cancel' => "Hætta við",
+'cantrollback' => "Ekki hægt að taka aftur breytingu, síðasti höfundur er eini höfundur þessarar síðu.",
+'categories' => "Flokkar",
+'category' => "flokkur",
+'category_header' => "Greinar í flokknum „$1“",
+'categoryarticlecount' => "Það eru $1 síður í þessum flokki.",
+'categoryarticlecount1' => "Það er $1 síða í þessum flokki.",
+'changepassword' => "Breyta lykilorði",
+'changes' => "Breytingar",
+'clearyourcache' => "'''Ath:''' Eftir að þú hefur vistað breytingar þarf að hreynsa flýtiskrár vafrarans til að sjá þær, í '''Mozilla / Firefox''' ''CTRL-Shift-R'', '''IE:''' ''CTRL-F5'', '''Safari:''' ''CMD-Shift-R'', '''Konqueror:''' ''F5''.",
+'columns' => "Dálkar",
+'compareselectedversions' => "Bera saman valdar útgáfur",
+'confirm' => "Staðfesta",
+'confirmdelete' => "Staðfesting á eyðingu",
+'confirmprotect' => "Verndunarstaðfesting",
+'confirmprotecttext' => "Ertu viss um að þú viljir vernda þessa síðu?",
+'confirmunprotect' => "Afverndunarstaðfesting",
+'confirmunprotecttext' => "Ertu viss um að þú viljir afvernda þessa síðu?",
+'contextchars' => "Stafir í samhengi á hverja línu",
+'contextlines' => "Línur á hverja niðurstöðu",
+'contribslink' => "framlög",
+'contribsub' => "Eftir $1",
+'contributions' => "Framlög notanda",
+'copyright' => "Efni síðunnar má nota undir $1.",
+'copyrightpage' => "Project:Höfundarréttur",
+'copyrightpagename' => "Höfundarréttarreglum {{SITENAME}}",
+'createaccount' => "Nýskrá",
+'createaccountmail' => "með netfangi",
+'cur' => "nú",
+'currentevents' => "Líðandi stund",
+'currentevents-url' => "Líðandi stund",
+'currentrev' => "Núverandi útgáfa",
+'currentrevisionlink' => "núverandi útgáfa",
+'databaseerror' => "Gagnagrunnsvilla",
+'dateformat' => "Tímasnið",
+'deadendpages' => "Botnlangar",
+'debug' => "Aflúsa",
+'dec' => "des",
+'december' => "desember",
+'defaultns' => "Leita í þessum nafnrýmum:",
+'defemailsubject' => "Varðandi {{SITENAME}}",
+'delete' => "Eyða",
+'deletecomment' => "Ástæða",
+'deletedarticle' => "tortímdi „$1“",
+'deletedtext' => "„$1“ hefur verið eytt. Sjá lista yfir nýlegar eyðingar í $2.",
+'deleteimg' => "eyða",
+'deleteimgcompletely' => "Eyða öllum útgáfum",
+'deletesub' => "(Eyði: „$1“)",
+'deletethispage' => "Eyða þessari síðu",
+'deletionlog' => "eyðingaskrá",
+'dellogpage' => "Eyðingaskrá",
+'diff' => "breyting",
+'difference' => "(Munur milli útgáfa)",
+'disambiguations' => "Aðgreiningarsíður",
+'disambiguationstext' => "The following pages link to a <i>disambiguation page</i>. They should link to the appropriate topic instead.<br />A page is treated as dismbiguation if it is linked from $1.<br />Links from other namespaces are <i>not</i> listed here.",
+'disclaimerpage' => "Project:Almennur fyrirvari",
+'disclaimers' => "Fyrirvarar",
+'edit' => "Breyta",
+'edithelp' => "Breytingarhjálp",
+'edithelppage' => "Hjálp:Breyta",
+'editing' => "Breyti $1",
+'editingcomment' => "Breyti $1 (bæti við athugasemd)",
+'editingold' => "<strong>ATH: Þú ert að breyta gamalli útgáfu þessarar síðu og munu allar breytingar sem gerðar hafa verið á henni frá þeirri útgáfu vera fjarlægðar ef þú vistar.</strong>",
+'editingsection' => "Breyti $1 (hluta)",
+'editsection' => "breyta",
+'editthispage' => "Breyta þessari síðu",
+'emailflag' => "Loka fyrir tölvupóst frá öðrum notendum",
+'emailforlost' => "Ekki er nauðsynlegt að gefa upp netfang. Ef þú gefur upp netfang getur fólk sent þér tölvupóst í gegnum {{SITENAME}} án þess að sjá netfangið þitt og þú getur fengið nýtt lykilorð sent ef það gleymist. Einnig er mögulegt fyrir nýja notendur að skrá sig með því að fylla bara út í reiti fyrir notendanafn og tölvupóst og smella svo á „með netfangi“ takkan, þá verður lykilorð sent á viðkomandi netfang.",
+'emailfrom' => "Frá",
+'emailmessage' => "Skilaboð",
+'emailpage' => "Senda tölvupóst",
+'emailpagetext' => "Hafi notandi þessi fyllt út gild tölvupóstfang í stillingum sínum er hægt að senda skilaboð til hans eða hennar hér. Póstfangið sem þú fylltir út í stillingum þínum mun byrtast í „From:“ hlutanum svo viðtakandinn geti svarað.",
+'emailsend' => "Senda",
+'emailsent' => "Sending tókst",
+'emailsenttext' => "Skilaboðin þín hafa verið send.",
+'emailsubject' => "Fyrirsögn",
+'emailto' => "Til",
+'emailuser' => "Senda þessum notanda tölvupóst",
+/* 'enterlockreason' => "Enter a reason for the lock, including an estimate
+of when the lock will be released", */
+'error' => "Villa",
+'errorpagetitle' => "Villa",
+'excontent' => "innihaldið var: '$1'",
+'explainconflict' => "Síðunni hefur verið breytt síðan þú byrjaðir að gera breytingar á henni, textinn í efri reitnum inniheldur núverandi útgáfu úr gagnagrunni og sá neðri inniheldur þína útgáfu, þú þarft hér að færa breytingar sem þú vilt halda úr neðri reitnum í þann efri og vista síðuna. <strong>Aðeins</strong> texti úr efri reitnum mun vera vistaður þegar þú vistar.",
+'export' => "XML útgáfa síðu",
+'exportcuronly' => "Aðeins núverandi útgáfu án breytingarskrá",
+'extlink_sample' => "http://www.example.com titill tengils",
+'extlink_tip' => "Ytri tengill (muna að setja http:// á undan)",
+'feb' => "feb",
+'february' => "febrúar",
+'feedlinks' => "Nippan:",
+'filedesc' => "Lýsing",
+'fileexists' => "Skrá með þessu nafni er þegar til, skoðaðu $1 ef þú ert óviss um hvort þú viljir breyta henni, ekki verður skrifað yfir gömlu skránna hlaðiru inn nýrri með sama nafni heldur verður núverandi útgáfa geymd í útgáfusögu.",
+'filename' => "Skráarnafn",
+'fileuploaded' => "Skránni „$1“ hefur verið bætt við á {{SITENAME}}.
+Fylgdu þessum tengli: $2 á lýsingarsíðu skráarinnar og fylltu út
+upplýsingar um skránna, svosem um uppruna hennar, höfund og aðrar
+upplýsingar um hana.",
+'friday' => "föstudagur",
+'go' => "Áfram",
+'guesstimezone' => "Fylla inn",
+'headline_sample' => "Fyrirsagnartexti",
+'headline_tip' => "Annars stigs fyrirsögn",
+'help' => "Hjálp",
+'helppage' => "Hjálp:Efnisyfirlit",
+'hide' => "Fela",
+'hidetoc' => "fela",
+'hist' => "breytingaskrá",
+'histlegend' => "Skýringar: (nú) = bera saman við núverandi útgáfu,
+(breyting) = bera saman við útgáfun á undan, M = minniháttar breyting.",
+'history' => "breytingaskrá",
+'history_short' => "Breytingaskrá",
+'historywarning' => "Athugið: Síðan sem þú ert um það bil að eyða á sér&nbsp;",
+'hr_tip' => "Lárétt lína (notist sparlega)",
+'ignorewarning' => "Hunsa viðvörun og vista þessa útgáfu.",
+'ilsubmit' => "Leita",
+'image_sample' => "Sýnishorn.jpeg",
+'image_tip' => "Setja inn mynd",
+'imagelinks' => "Myndatenglar",
+'imagelist' => "Skráalisti",
+'imagelisttext' => "Hér fyrir neðan er $1 skrám raðað $2.",
+'imgdelete' => "eyða",
+'imgdesc' => "lýsing",
+'imghistlegend' => "Skýringar: (nú) = bera saman við núverandi útgáfu,
+(breyting) = bera saman við útgáfun á undan, M = minniháttar breyting.
+
+Legend: (nú) = núverandi útgáfa,
+(eyða) = eyða þessari útgáfu, (nota) = nota þessa útgáfu í stað núverandi útgáfu.
+<br /><em>Fylgdu dagsetningartenglunum til að sjá mynd sem hlaðið var inn á þeim tíma</em>.",
+'imghistory' => "Breytingaskrá myndar",
+'imglegend' => "Skýringar: (lýsing) = sýna og/eða breyta lýsingu skráar.",
+'ipaddress' => "IP Tala/notendanafn",
+'ipbexpiry' => "Rennur út eftir",
+'ipblocklist' => "Bannaðar notendur og IP tölur",
+'ipbreason' => "Ástæða",
+'ipbsubmit' => "Banna notanda",
+'ipusubmit' => "Afbanna",
+'isredirect' => "tilvísun",
+'italic_sample' => "Skáletraður texti",
+'italic_tip' => "Skáletraður texti",
+'jan' => "jan",
+'january' => "janúar",
+'jul' => "júl",
+'july' => "júlí",
+'jun' => "jún",
+'june' => "júní",
+'last' => "breyting",
+'lastmodified' => "Þessari síðu var síðast breytt $1.",
+'lineno' => "Lína $1:",
+'link_sample' => "Titill tengils",
+'link_tip' => "Innri tengill",
+'linklistsub' => "(Listi yfir ítengdar síður)",
+'linkshere' => "Eftirfarandi síður tengjast hingað:",
+'linkstoimage' => "Eftirfarandi síður tengjast í mynd þessa:",
+'listingcontinuesabbrev' => " frh.",
+'listusers' => "Notendalisti",
+'localtime' => "Staðartími",
+'lockdb' => "Læsa gagnagrunninum",
+'login' => "Innskrá",
+'loginerror' => "Innskráningarvilla",
+'loginsuccess' => "Þú ert nú innskráð(ur) á {{SITENAME}} sem „$1“.",
+'loginsuccesstitle' => "Innskráning tókst",
+'logout' => "Útskráning",
+'logouttext' => "Þú hefur verið skráð(ur) út.
+Þú getur þó haldið áfram að nota {{SITENAME}} nafnlaust og þú getur skráð þig inn sem annar notandi. Athugaðu að sumar síður kunna að birtast líkt og þú sért ennþá innskráður, hægt er að koma í veg fyrir það með því að hreinsa biðminnið í vafranum.",
+'lonelypages' => "Munaðarlausar síður",
+'longpages' => "Langar síður",
+'mailmypassword' => "Senda nýtt lykilorð með tölvupósti",
+'mainpage' => "Forsíða",
+'maintenance' => "Viðhaldssíða",
+'makesysop' => "Veita stjórnandaréttindi",
+'makesysopname' => "Notandi:",
+'makesysopok' => "<strong>Notandanum „$1“ hefur verið veitt stjórnandastaða</strong>",
+'makesysopsubmit' => "Gera að stjórnanda",
+'makesysoptext' => "Kerfissíða þessi er notuð af möppudýrum til að veita venjulegum notendum stjórnendaréttindi.",
+'mar' => "mar",
+'march' => "mars",
+'math' => "Birting stærðfræðiformúlna",
+'math_sample' => "Formúlan setjist hér",
+'math_tip' => "LaTeX Stærðfræðiformúla",
+'may' => "maí",
+'may_long' => "maí",
+'media_sample' => "Sýnishorn.ogg",
+'media_tip' => "Tengill í margmiðlunarskrá",
+'minoredit' => "Minniháttar breyting",
+'missingimage' => "<b>Mynd vantar</b><br /><i>$1</i>",
+'monday' => "mánudagur",
+'move' => "Færa",
+'movearticle' => "Færa",
+'movenologin' => "Óinnskráð(ur)",
+'movenologintext' => "Þú verður að vera [[Kerfissíða:Userlogin|innskráð(ur)]] til  að geta fært síður.",
+'movepage' => "Færa síðu",
+'movepagebtn' => "Færa síðuna",
+'movepagetalktext' => "Spallsíða síðunnar verður sjálfkrafa færð með ef hún er til nema:
+* Þú sért að færa síðuna á milli nafnrýma
+* Spallsíða sé þegar til undir nýja nafninu
+* Þú veljir að færa hana ekki
+Í þeim tilfellum verður að færa hana handvirkt.",
+'movepagetext' => "Hér er hægt að endurnefna síðu, hún mun ásamt breytingarskrá hennar
+verða færð á nýja nafnið og núverandi staðsetning mun
+breytast í tilvísun sem vísa mun á nýju staðsetninguna,
+tenglar í núverandi nafn munu hinsvegar ekki breytast,
+athugaðu að þetta búi ekki til margfaldar
+tilvísanir, það er á þína ábyrgð að tryggja það að tenglar haldi áfram
+að vísa á rétta síðu.
+
+Athugaðu að síðan mun '''ekki''' verða færð ef það er þegar síða á nafninu
+sem þú hyggst færa hana á, nema síða sú sé tóm eða tilvísun sem á sér enga
+breytingarsögu. Þú getur þar með fært síðuna aftur til baka án þess að
+missa breytingarsöguna, en ekki fært hana venjulega síðu.
+
+'''Varúð:'''
+Vertu viss um að skilja afleiðingarnar af þessari aðgerð vel. Þetta gæti þýtt
+mjög rótækar breytingar á vinsælum síðum og valdið titringi hjá öðrum notendum.",
+'movetalk' => "Færa „Spjall“ síðuna líka ef við á.",
+'movethispage' => "Færa þessa síðu",
+'mw_math_html' => "HTML ef hægt er, annars PNG",
+'mw_math_mathml' => "MathML",
+'mw_math_modern' => "Mælt með fyrir nýja vafra",
+'mw_math_png' => "Alltaf birta PNG mynd",
+'mw_math_simple' => "HTML fyrir einfaldar jöfnur annars PNG",
+'mw_math_source' => "Sýna TeX jöfnu (fyrir textavafra)",
+'mycontris' => "Framlög",
+'mypage' => "Mín síða",
+'mytalk' => "Spjall",
+'navigation' => "Flakk",
+'newarticle' => "(Ný)",
+'newimages' => "Gallerí nýlegra skráa",
+'newmessages' => "Þér hafa borist $1.",
+'newmessageslink' => "ný skilaboð",
+'newpages' => "Nýjar síður",
+'newpassword' => "Nýja lykilorðið",
+'newtitle' => "Yfir á",
+'newusersonly' => " (aðeins fyrir nýja notendur)",
+'newwindow' => "(í nýjum glugga)",
+'nextdiff' => "Næsta breyting →",
+'nextn' => "næstu $1",
+'nextrevision' => "Næsta útgáfa→",
+'noarticletext' => "<div style=\"border: 1px solid #ccc; padding: 7px; background: white;\">'''Það er ekki enn grein undir þessu nafni á [[{{SITENAME}}]].'''
+* '''[{{SERVER}}{{localurl:{{NAMESPACE}}:{{PAGENAME}}|action=edit}} Skrifa grein undir nafninu „{{PAGENAME}}“]'''
+* [[{{ns:special}}:Search/{{PAGENAME}}|Leita að „{{PAGENAME}}“]] í öðrum greinum og síðum.
+* [[Wiktionary:is:{{NAMESPACE}}:{{PAGENAME}}|Fara á „{{PAGENAME}}“]] á Wiktionary, systurorðabókaverkefninu.
+</div>",
+'noemailtext' => "Notandi þessi hefur kosið að fá ekki tölvupóst frá öðrum notendum eða hefur ekki fyllt út netfang sitt í stillingum.",
+'noemailtitle' => "Ekkert póstfang",
+'nolinkshere' => "Engar síður tengjast hingað.",
+'nolinkstoimage' => "Engar síður tengja í hingað.",
+'noname' => "Ógilt notendanafn.",
+'nosuchuser' => "Enginn notandi er til undir nafninu „$1“.",
+'note' => "<strong>Athugið:</strong>",
+'notextmatches' => "Leitarorð fannst/fundust ekki í innihaldi greina",
+'notitlematches' => "Engir greinatitlar pössuðu við fyrirspurnina",
+'nov' => "nóv",
+'november' => "nóvember",
+'nowatchlist' => "Vaktlistinn er tómur.",
+'nowiki_sample' => "Innsetjið ósniðinn texta hér",
+'nowiki_tip' => "Hunsa wikisnið",
+'nstab-category' => "Efnisflokkur",
+'nstab-help' => "Hjálp",
+'nstab-image' => "Mynd",
+'nstab-main' => "Grein",
+'nstab-mediawiki' => "Skilaboð",
+'nstab-template' => "Forsnið",
+'nstab-user' => "Notandasíða",
+'nstab-wp' => "Um",
+'oct' => "okt",
+'october' => "október",
+'oldpassword' => "Gamla lykilorðið",
+'otherlanguages' => "Á öðrum tungumálum",
+'pagemovedsub' => "Færsla tókst",
+'pagemovedtext' => "Síðan „[[$1]]“ var færð yfir á „[[$2]]“.",
+'pagetitle' => "$1 - {{SITENAME}}",
+'perfcached' => "Eftirfarandi er afrit af umbeðinni síðu og gæti því ekki verið nýjasta útgáfa hennar:",
+'perfdisabled' => "Þessi síða hefur verið gerð óvirk þar sem notkun hennar veldur of miklu álagi á gagnagrunninum.",
+'personaltools' => "Tenglar",
+'portal' => "Samfélagsgátt",
+'portal-url' => "Project:Samfélagsgátt",
+'powersearch' => "Leita",
+'powersearchtext' => "Leita í eftirfarandi nafnrýmum :<br />
+$1<br />
+$2 Sýna tilvísarnir &nbsp; Leita að $3 $9",
+'preferences' => "Stillingar",
+'prefs-misc' => "Aðrar stillingar",
+'prefs-personal' => "Notendaupplýsingar",
+'prefs-rc' => "Nýlegar breytingar og stubbar",
+'prefslogintext' => "Notandanafn þitt er „[[Notandi:$1|$1]]“ ([[Notandaspjall:$1|Spjall]], [[Kerfissíða:Contributions/$1|framlög]]) og kenninúmerið þitt er $2.
+
+[[m:Help:Preferences|Stillingarhjálpin]] (á ensku)
+inniheldur útskýringu á valmöguleikunum.",
+'prefsnologintext' => "You must be [[Special:Userlogin|logged in]]
+to set user preferences.",
+'preview' => "Forskoða",
+'previewnote' => " Það sem sést hér er aðeins forskoðun og hefur ekki enn verið vistað.",
+'previousdiff' => "← Fyrri breyting",
+'previousrevision' => "←Fyrri útgáfa",
+'prevn' => "síðustu $1",
+'printableversion' => "Prentvæn útgáfa",
+'printsubtitle' => "(From {{SERVER}})",
+'protect' => "Vernda",
+'protectcomment' => "Ástæða",
+'protectedpagewarning' => "<!-- -->",
+'protectlogpage' => "Verndunarskrá",
+'protectpage' => "Vernda síðu",
+'protectsub' => "(Vernda „$1“)",
+'qbedit' => "Breyta",
+'qbsettings' => "Valblað",
+'randompage' => "Handahófsvalin síða",
+'rclinks' => "Sýna síðustu $1 breytingar síðustu $2 daga<br />$3",
+'rclistfrom' => "Sýna breytingar frá og með $1",
+'rclsub' => "(á síðum sem tengd er í frá „$1“)",
+'rcnote' => "Að neðan eru síðustu <strong>$1</strong> breytingar síðustu <strong>$2</strong> daga.",
+'recentchanges' => "Nýlegar breytingar",
+'recentchangescount' => "Fjöldi síðna á „nýlegum breytingum“",
+'recentchangeslinked' => "Skyldar breytingar",
+'redirectedfrom' => "(Tilvísun frá $1)",
+'remembermypassword' => "Muna.",
+'removechecked' => "Fjarlægja merktar síður af vaktlistanum",
+'removedwatch' => "Fjarlægt af vaktlistanum",
+'removedwatchtext' => "Síðan \"$1\" hefur verið fjarlægð af vaktlistanum.",
+'removingchecked' => "Fjarlægi umbeðnar síðu(r) af vaktlistanum...",
+'resetprefs' => "Endurstilla valmöguleika",
+'restorelink' => "$1 eydda(r) breyting(u/ar)",
+'resultsperpage' => "Niðurstöður á síðu",
+'retrievedfrom' => "Af „$1“",
+'returnto' => "Tilbaka: $1.",
+'retypenew' => "Endurtaktu nýja lykilorðið",
+'reupload' => "Endurinnhlaða",
+'reuploaddesc' => "Aftur á innhlaðningarformið.",
+'reverted' => "Breytt aftur til fyrri útgáfu",
+'revertimg' => "nota",
+'revertpage' => "Tók aftur breytingar $2, breytt til síðustu útgáfu $1",
+'revhistory' => "Útgáfusaga",
+'revisionasof' => "Útgáfa síðunnar kl. $1",
+'revisionasofwithlink' => "Útgáfa síðunnar kl. $1; $2<br />$3 | $4",
+'rfcurl' => "http://ftp.rhnet.is/pub/rfc/rfc$1.txt",
+'rollback' => "Taka aftur breytingar",
+'rollback_short' => "Afturtaka",
+'rollbackfailed' => "Afturtaka mistókst",
+'rollbacklink' => "afturtaka",
+'rows' => "Raðir",
+'saturday' => "laugardagur",
+'savearticle' => "Vista",
+'savedprefs' => "Stillingarnar þínar hafa verið vistaðar.",
+'savefile' => "Vista",
+'saveprefs' => "Vista stillingar",
+'search' => "Leit",
+'searchquery' => "Fyrir fyrirspurnina „$1“",
+'searchresults' => "Leitarniðurstöður",
+'searchresultshead' => "Leit",
+'searchresulttext' => "Fyrir frekari upplýsingar um leit á {{SITENAME}}, sjá $1.",
+'sep' => "sep",
+'september' => "september",
+'servertime' => "Tími netþjóns",
+'setbureaucratflag' => "Einnig möppudýr",
+'sharedupload' => "<br style=\"clear:both\">
+{| align=center width=50% cellpadding=3 cellspacing=3 style=\"border: solid #aaaaaa 1px; background: #f9f9f9; margin-bottom: 1em; font-size: 100%\"
+| [[Image:Commons-trans 135px ohne text.png|30px|Wikimedia Commons Logo]]
+|Skrá þessi er af [[Commons:Forsíða|Wikimedia Commons]], sjá '''[[Commons:Image:{{PAGENAME}}|skráarsíðuna þar]]''' fyrir leyfisupplýsingar og annað.
+|}",
+'shortpages' => "Stuttar síður",
+'show' => "Sýna",
+'showhideminor' => "$1 minniháttar breytingar | $2 breytingar eftir vélmenni | $3 breytingar eftir notendur | $4 patrolled edits",
+'showingresults' => "Sýni <strong>$1</strong> niðurstöður frá og með #<strong>$2</strong>.",
+'showingresultsnum' => "Sýni <strong>$1</strong> niðurstöður frá og með #<strong>$2</strong>.",
+'showlast' => "Sýna síðustu $1 skrár raðaðar $2.",
+'showpreview' => "Forskoða",
+'showtoc' => "sýna",
+'sig_tip' => "Undirskrift þín auk tímasetningu",
+'sitestats' => "Almenn tölfræði",
+'sitestatstext' => "Nú eru alls '''$1''' síður í gagnagrunninum,
+þar á meðal „spjall“ síður, síður er snúa að {{SITENAME}} verkefninu,
+„stubbar“, tilvísanir og annað efni er ekki telst til greina.
+Þar fyrir utan eru '''$2''' síður sem líklega teljast fullgildar greinar.
+
+'''$3''' síður hafa verið skoðaðar og '''$4''' breytingar hafa verið gerðar
+síðan vefurinn var settur up. Það reiknast sem '''$5''' breytingar
+á hverja síðu að meðaltali, og '''$6''' fléttingar fyrir hverja breytingu.",
+'sitesubtitle' => "Frjálsa alfræðiorðabókin",
+'sitesupport' => "Framlög",
+'sitetitle' => "Wikipedia",
+'skin' => "Þema",
+'spamprotectiontext' => "The page you wanted to save was blocked by the spam filter. This is probably caused by a link to an external site.
+
+You might want to check the following regular expression for patterns that are currently blocked:",
+'specialpage' => "Kerfissíða",
+'specialpages' => "Kerfissíður",
+'spheading' => "Almennar",
+'statistics' => "Tölfræði",
+'storedversion' => "Geymd útgáfa",
+'stubthreshold' => "Stubbamerkja allt undir",
+'subcategories' => "Undirflokkar",
+'subcategorycount' => "Það eru $1 undirflokkar í þessum flokki.",
+'subcategorycount1' => "Það er einn<!-- líka hægt að nota $1 til að fá heiltöluna (sem verður 1)--> undirflokkur í þessum flokki.",
+'subject' => "Fyrirsögn",
+'successfulupload' => "Innhlaðning tókst",
+'summary' => "Breytingar",
+'sunday' => "sunnudagur",
+'tagline' => "Úr Wikipedia, frjálsu alfræðiorðabókinni",
+'talk' => "Spjall",
+'talkpage' => "Ræða um þessa síðu",
+'talkpagenotmoved' => "Samsvarandi spjallsíða var <strong>ekki</strong> færð.",
+'templatesused' => "Snið notuð á síðunni:",
+'textboxsize' => "Breytingarflipinn",
+'textmatches' => "Leitarorð fannst/fundust í innihaldi eftirfarandi greina",
+'thisisdeleted' => "Endurvekja eða skoða $1?",
+'thursday' => "fimmtudagur",
+'timezonelegend' => "Tímabelti",
+'timezoneoffset' => "Hliðrun",
+'timezonetext' => "Hliðrun staðartíma frá UTC+0.",
+'titlematches' => "Titlar greina sem pössuðu við fyrirspurnina",
+'toc' => "Efnisyfirlit",
+'tog-editondblclick' => "Breyta síðu ef tvísmellt er á hlekkinn (JavaScript)",
+'tog-editsection' => "Leyfa breytingar á hluta síðna með [edit] hlekkjum",
+'tog-editsectiononrightclick' => "Leyfa breytingar á hluta síðna með því að  hægrismella á titla (JavaScript)",
+'tog-editwidth' => "Innsláttarsvæði hefur fulla breidd",
+'tog-hideminor' => "Fela minniháttar breytingar",
+'tog-highlightbroken' => "Sýna brotna hlekki <a href=\"\" class=\"new\">svona</a> (annars: svona<a href=\"\" class=\"internal\">?</a>).",
+'tog-justify' => "Jafna málsgreinar",
+'tog-minordefault' => "Láta breytingar vera sjálfgefnar sem minniháttar",
+'tog-nocache' => "Slökkva á flýtivistun síðna",
+'tog-numberheadings' => "Númera fyrirsagnir sjálfkrafa",
+'tog-previewontop' => "Setja prufuhnapp fyrir framan breytingahnapp",
+'tog-rememberpassword' => "Muna lykilorð",
+'tog-showtoc' => "Sýna efnisyfirlit",
+'tog-underline' => "Undirstrika hlekki",
+'tog-usenewrc' => "Endurbætt nýjar tengingar (ekki fyrir alla vafra)",
+'tog-watchdefault' => "Bæta síðum sem þú breytir við eftirlitslista",
+'toolbox' => "Verkfæri",
+'tooltip-compareselectedversions' => "Sjá breytingarnar á þessari grein á milli útgáfanna sem þú valdir. [alt-v]",
+'tooltip-minoredit' => "Merktu þessa breytingu sem minniháttar [alt-i]",
+'tooltip-preview' => "Forskoða breytingarnar, vinsamlegast gerðu þetta áður en þú vistar! [alt-p]",
+'tooltip-save' => "Vista breytingarnar [alt-s]",
+'tooltip-search' => "Leit á þessari Wiki [alt-f]",
+'tuesday' => "þriðjudagur",
+'unblockip' => "Afbanna notanda",
+'unblockiptext' => "Endurvekja skrifréttindi bannaðra notenda eða IP talna.",
+'unblocklink' => "afbanna",
+'uncategorizedcategories' => "Óflokkaðir flokkar",
+'uncategorizedpages' => "Óflokkaðar síður",
+'undelete' => "Endurvekja eydda síðu",
+'undelete_short' => "Endurvekja $1 breyting(u/ar)",
+'undeletearticle' => "Endurvekja eydda síðu",
+'undeletebtn' => "Endurvekja!",
+'undeletedtext' => "[[$1]] has been successfully restored.
+See [[Wikipedia:Deletion_log]] for a record of recent deletions and restorations.",
+'undeletepage' => "Skoða og endurvekja síður",
+'undeletepagetext' => "Eftirfarandi síðum hefur verið eitt en eru þó enn í gagnagrunninum og geta verið endurvaknar. Athugið að síður þessar eru reglulega fjarlægðar endanlega úr gagnagrunninum.",
+'undeleterevisions' => "$1 breyting(ar)",
+'unlockdb' => "Aflæsa gagnagrunninum",
+'unprotect' => "Afvernda",
+'unprotectcomment' => "Ástæða",
+'unprotectsub' => "(Afvernda „$1“)",
+'unusedimages' => "Munaðarlausar skrár",
+'unusedimagestext' => "<p>Please note that other web sites may link to an image with
+a direct URL, and so may still be listed here despite being
+in active use.",
+'unwatch' => "Afvakta",
+'upload' => "Innhlaða",
+'uploadbtn' => "Hlaða inn skrá",
+'uploadedimage' => "hlóð inn \"$1\"",
+'uploaderror' => "Villa í innhlaðningu",
+'uploadlog' => "innhlaðningarskrá",
+'uploadlogpage' => "Innhlaðningarskrá",
+'uploadnologin' => "Óinnskráð(ur)",
+'uploadnologintext' => "You must be [[Special:Userlogin|logged in]]
+to upload files.",
+'uploadtext' => "'''Áður en skrá er hlaðið inn''':
+* Notaðu [[JPEG]] skráarsniðið fyrir ljósmyndir, [[GIF]] fyrir hreyfimyndir, [[PNG]] fyrir aðrar myndir og [[Ogg Vorbis]] fyrir hljóðskrár.
+
+'''Eftir að skrá er hlaðið inn''':
+* Veittu nákvæmar upplýsingar um skránna á skráarsíðunni, t.d. um myndina (hvenær hún er tekin, hvar o.s.f.)
+* Gefðu upplýsingar um leyfið sem hún er undir, <code><nowiki>{{</nowiki>GFDL<nowiki>}}</nowiki></code> fyrir [[commons:Commons:Copyright tags#GNU Licenses|GNU FDL]] og <code><nowiki>{{</nowiki>Óhöfundaréttvarið<nowiki>}}</nowiki></code> ef hún er óvernduð af alþjóða höfundarlögum.
+
+<div align=center border=0 cellpadding=6 cellspacing=2 style=\"border: 3px solid red; background-color: #FFE4E1; margin-top:1em; margin-bottom:1em; padding:3px;\"><big>'''Helst ekki''' hlaða skrám inn hér heldur á [[commons:|Wikimedia Commons]]</big><br />
+Þá verður hún aðgengileg á '''öllum''' Wikimedia verkefnunum, ekki bara íslensku Wikipedia</div>",
+'uploadwarning' => "Aðvörun",
+'usercssjsyoucanpreview' => "<strong>Ath:</strong> Hægt er að nota „Forskoða“ hnappinn til að prófa CSS og JavaScript kóða áður en hann er vistaður.",
+'userlogin' => "Innskrá",
+'userlogout' => "Útskrá",
+'userstats' => "Notendatölfræði",
+'userstatstext' => "Það eru '''$1''' skráðir notendur, þar af eru '''$2''' eða '''$4%''' stjórnendur (sjá $3).",
+'version' => "Útgáfa",
+'viewprevnext' => "Skoða ($1) ($2) ($3).",
+'viewsource' => "Skoða wikikóða",
+'viewtalkpage' => "Skoða umræðu",
+'wantedpages' => "Eftirsóttar síður",
+'watch' => "Vakta",
+'val_tab' => 'Votta',
+'watchdetails' => "Fyrir utan spjallsíður eru $1 síða/síður á vaktlistanum þínum. Hægt er að
+[$4 sýna heildarlistann og breyta honum].",
+'watcheditlist' => "Þetta er listi yfir þínar vöktuðu síður raðað í
+stafrófsröð. Merktu við þær síður sem þú vilt fjarlægja
+af vaktlistanum og ýttu á 'fjarlægja merktar' takkan
+neðst á skjánum.",
+'watchlist' => "Vaktlistinn",
+'watchlistcontains' => "Á vaktlistanum eru $1 síður.",
+'watchlistsub' => "(fyrir notandan „$1“)",
+'watchmethod-list' => "leita að breytingum í vöktuðum síðum",
+'watchmethod-recent' => "kanna hvort nýlegar breytingar innihalda vaktaðar síður",
+'watchnochange' => "Engri síðu á vaktlistanum þínum hefur verið breytt á tilgreindu tímabili.",
+'watchnologin' => "Óinnskráð(ur)",
+'watchnologintext' => "Þú verður að vera [[Special:Userlogin|innskáð(ur)]] til að geta breytt vaktlistanum.",
+'watchthis' => "Vakta",
+'watchthispage' => "Vakta þessa síðu",
+'wednesday' => "miðvikudagur",
+'welcomecreation' => "<h2>Velkomin(n), $1!</h2><p>Aðgangurinn þinn hefur verið búinn til.
+Ekki gleyma að breyta Wikipedia stillingunum þínum.",
+'whatlinkshere' => "Hvað tengist hingað",
+'whitelistacctext' => "Til að geta búið til aðganga í þessu Wiki, verður þú að [[Special:Userlogin|innskrá]] og hafa viðkomandi réttindi.",
+'whitelistacctitle' => "Þér er óheimilt að skrá þig sem notanda.",
+'whitelistedittext' => "Þú verður að [[Special:Userlogin|skrá þig inn]] til að geta breytt síðum.",
+'whitelistedittitle' => "Þú verður að skrá þig inn til að geta breytt síðum.",
+'whitelistreadtext' => "Þú verður að [[Special:Userlogin|skrá þig inn]] til að lesa síður.",
+'whitelistreadtitle' => "Notandi verður að skrá sig inn til að geta lesið.",
+'wikipediapage' => "Sýna verkefnissíðu",
+'wlnote' => "Að neðan eru síðustu <b>$1</b> breytingar síðustu <b>$2</b> klukkutíma.",
+'wlsaved' => "Þetta er vistuð útgáfa af vaktlistanum þínum.",
+'wlshowlast' => "Sýna síðustu $1 klukkutíma, $2 daga, $3",
+'wrong_wfQuery_params' => "Incorrect parameters to wfQuery()<br />
+Function: $1<br />
+Query: $2",
+'wrongpassword' => "Uppgefið lykilorð er rangt. Vinsamlegast reyndu aftur.",
+'yourdiff' => "Mismunur",
+'youremail' => "Tölvupóstfangið þitt*",
+'yourlanguage' => "Viðmótstungumál",
+'yourname' => "Notendanafn",
+'yournick' => "Nafn (fyrir undirskriftir)",
+'yourpassword' => "Lykilorð",
+'yourpasswordagain' => "Lykilorð (aftur)",
+'yourrealname' => "Fullt nafn þitt*",
+'yourtext' => "Þinn texti",
+);
+
+#--------------------------------------------------------------------------
+# Internationalisation code
+#--------------------------------------------------------------------------
+
+class LanguageIs extends LanguageUtf8 {
+
+       function getNamespaces() {
+               global $wgNamespaceNamesIs;
+               return $wgNamespaceNamesIs;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsIs;
+               return $wgQuickbarSettingsIs;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesIs;
+               return $wgSkinNamesIs;
+       }
+
+       function getDateFormats() {
+               global $wgDateFormatsIs;
+               return $wgDateFormatsIs;
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesIs;
+               if( isset( $wgAllMessagesIs[$key] ) ) {
+                       return $wgAllMessagesIs[$key];
+               } else {
+                       return parent::getMessage( $key );
+               }
+       }
+
+       function getAllMessages() {
+               global $wgAllMessagesIs;
+               return $wgAllMessagesIs;
+       }
+
+       function getMagicWords() {
+               global $wgMagicWordsIs;
+               return $wgMagicWordsIs;
+       }
+
+       function date( $ts, $adj = false, $format = true) {
+               global $wgUser;
+               if ( $adj ) { $ts = $this->userAdjust( $ts ); } # Adjust based on the timezone setting.
+               $format = $this->dateFormat($format);
+
+               switch( $format ) {
+                       # 15. jan. 2001 kl. 16:12 || 16:12, 15. jan. 2001
+                       case '2': case '4': return (0 + substr( $ts, 6, 2 )) . '. ' .
+                               $this->getMonthAbbreviation( substr( $ts, 4, 2 ) ) . '. ' .
+                               substr($ts, 0, 4);
+                       # 2001-01-15 16:12:34
+                       case 'ISO 8601': return substr($ts, 0, 4). '-' . substr($ts, 4, 2). '-' .substr($ts, 6, 2);
+
+                       # 15. janúar 2001 kl. 16:12 || 16:12, 15. janúar 2001
+                       default: return (0 + substr( $ts, 6, 2 )) . '. ' .
+                               $this->getMonthName( substr( $ts, 4, 2 ) ) . ' ' .
+                               substr($ts, 0, 4);
+               }
+
+       }
+
+       function time($ts, $adj = false, $format = true) {
+               global $wgUser;
+               if ( $adj ) { $ts = $this->userAdjust( $ts ); } # Adjust based on the timezone setting.
+
+               $format = $this->dateFormat($format);
+
+               switch( $format ) {
+                       # 2001-01-15 16:12:34
+                       case 'ISO 8601': return substr( $ts, 8, 2 ) . ':' . substr( $ts, 10, 2 ) . ':' . substr( $ts, 12, 2 );
+                       default: return substr( $ts, 8, 2 ) . ':' . substr( $ts, 10, 2 );
+               }
+
+       }
+
+       function timeanddate( $ts, $adj = false, $format = true) {
+               global $wgUser;
+
+               $format = $this->dateFormat($format);
+
+               switch ( $format ) {
+                       # 16:12, 15. janúar 2001 || 16:12, 15. jan. 2001
+                       case '3': case '4': return $this->time( $ts, $adj, $format ) . ', ' . $this->date( $ts, $adj, $format );
+                       # 2001-01-15 16:12:34
+                       case 'ISO 8601': return $this->date( $ts, $adj, $format ) . ' ' . $this->time( $ts, $adj, $format );
+                       # 15. janúar 2001 kl. 16:12 || 15. jan. 2001 kl. 16:12
+                       default: return $this->date( $ts, $adj, $format ) . ' kl. ' . $this->time( $ts, $adj, $format );
+
+               }
+
+       }
+
+       /**
+        * The Icelandic number style uses dots where English would use commas
+        * and commas where English would use dots, e.g. 201.511,17 not 201,511.17
+        */
+       function formatNum( $number, $year = false ) {
+               return $year ? $number : strtr($this->commafy($number), '.,', ',.' );
+       }
+
+       function linkPrefixExtension() {
+               return true;
+       }
+}
+
+?>
diff --git a/languages/LanguageIt.php b/languages/LanguageIt.php
new file mode 100644 (file)
index 0000000..380697b
--- /dev/null
@@ -0,0 +1,747 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+/* private */ $wgNamespaceNamesIt = array(
+       NS_MEDIA            => 'Media',
+       NS_SPECIAL          => 'Speciale',
+       NS_MAIN             => '',
+       NS_TALK             => 'Discussione',
+       NS_USER             => 'Utente',
+       NS_USER_TALK        => 'Discussioni_utente',
+       NS_PROJECT          => $wgMetaNamespace,
+       NS_PROJECT_TALK     => 'Discussioni_'.$wgMetaNamespace,
+       NS_IMAGE            => 'Immagine',
+       NS_IMAGE_TALK       => 'Discussioni_immagine',
+       NS_MEDIAWIKI        => 'MediaWiki',
+       NS_MEDIAWIKI_TALK   => 'Discussioni_MediaWiki',
+       NS_TEMPLATE         => 'Template',
+       NS_TEMPLATE_TALK    => 'Discussioni_template',
+       NS_HELP             => 'Aiuto',
+       NS_HELP_TALK        => 'Discussioni_aiuto',
+       NS_CATEGORY         => 'Categoria',
+       NS_CATEGORY_TALK    => 'Discussioni_categoria'
+
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgQuickbarSettingsIt = array(
+       "Nessuno", "Fisso a sinistra", "Fisso a destra", "Fluttuante a sinistra"
+);
+
+
+/* private */ $wgAllMessagesIt = array(
+# User Toggles
+
+"tog-underline" => "Sottolinea links",
+"tog-highlightbroken" => "Evidenzia i links che puntano ad<br />articoli ancora da scrivere",
+"tog-justify"  => "Paragrafo: giustificato",
+"tog-hideminor" => "Nascondi le modifiche minori<br />nella pagina \"Modifiche recenti\"",
+"tog-usenewrc" => "Enhanced recent changes (not for all browsers)",
+"tog-numberheadings" => "Auto-numerazione dei<br />titoli di paragrafo",
+"tog-showtoolbar" => "Show edit toolbar",
+"tog-editondblclick" => "Doppio click per modificare l'articolo<br />(richiede JavaScript)",
+"tog-editsection"=>"Enable section editing via [edit] links",
+"tog-editsectiononrightclick"=>"Enable section editing by right clicking<br /> on section titles (JavaScript)",
+"tog-showtoc"=>"Show table of contents<br />(for articles with more than 3 headings)",
+"tog-rememberpassword" => "Ricorda la password<br />(non limitare a una sessione<br />- richiede uso di cookies)",
+"tog-editwidth" => "Casella di edizione ampliata<br />alla massima larghezza",
+"tog-watchdefault" => "Notifica articoli nuovi e modificati",
+"tog-minordefault" => "Indica ogni modifica come minore<br />(solo come predefinito)",
+"tog-previewontop" => "Show preview before edit box and not after it",
+"tog-nocache" => "Disable page caching",
+# dates
+'sunday' => 'Domenica',
+'monday' => 'Lunedì',
+'tuesday' => 'Martedì',
+'wednesday' => 'Mercoledì',
+'thursday' => 'Giovedì',
+'friday' => 'Venerdì',
+'saturday' => 'Sabato',
+'january' => 'Gennaio',
+'february' => 'Febbraio',
+'march' => 'Marzo',
+'april' => 'Aprile',
+'may_long' => 'Maggio',
+'june' => 'Giugno',
+'july' => 'Luglio',
+'august' => 'Agosto',
+'september' => 'Settembre',
+'october' => 'Ottobre',
+'november' => 'Novembre',
+'december' => 'Dicembre',
+'jan' => 'Gen',
+'feb' => 'Feb',
+'mar' => 'Mar',
+'apr' => 'Apr',
+'may' => 'Mag',
+'jun' => 'Giu',
+'jul' => 'Lug',
+'aug' => 'Ago',
+'sep' => 'Set',
+'oct' => 'Ott',
+'nov' => 'Nov',
+'dec' => 'Dic',
+
+
+# Bits of text used by many pages:
+#
+"linktrail"            => "/^([a-z]+)(.*)\$/sD",
+"mainpage"             => "Wikipedia",
+"about"                        => "A proposito di ",
+"aboutsite"      => "A proposito di Wikipedia",
+"aboutpage"            => "Wikipedia:About",
+"help"                 => "Aiuto",
+"helppage"             => "Wikipedia:Aiuto",
+"bugreports"   => "Malfunzionamenti",
+"bugreportspage" => "Wikipedia:Malfunzionamenti",
+"faq"                  => "FAQ",
+"faqpage"              => "Wikipedia:FAQ",
+"edithelp"             => "Guida",
+"edithelppage" => "Wikipedia:Come_scrivere_un_articolo",
+"cancel"               => "Cancella",
+"qbfind"               => "Trova",
+"qbbrowse"             => "Sfoglia",
+"qbedit"               => "Modifica",
+"qbpageoptions" => "Opzioni pagina",
+"qbpageinfo"   => "Informazioni sulla pagina",
+"qbmyoptions"  => "Le mie opzioni",
+"mypage"               => "La mia pagina",
+"mytalk"               => "Le mie discussioni",
+"currentevents" => "Attualità",
+"errorpagetitle" => "Errore",
+"returnto"             => "Torna a $1.",
+"tagline"              => "Da Wikipedia, l'enciclopedia libera.",
+"whatlinkshere"        => "Pagine che linkano questa",
+"help"                 => "Aiuto",
+"search"               => "Cerca",
+"history"              => "Versioni precedenti",
+"printableversion" => "Versione stampabile",
+"editthispage" => "Modifica articolo",
+"deletethispage" => "Cancella pagina",
+"protectthispage" => "Proteggi pagina",
+"unprotectthispage" => "Togli protezione",
+"talkpage"             => "Discussione",
+"articlepage"  => "Vedi articolo",
+"subjectpage"  => "Vedi articolo ", # For compatibility
+"userpage" => "Vedi pagina Utente",
+"wikipediapage" => "Vedi pagina meta ",
+"imagepage" =>         "Pagina immagine",
+"otherlanguages" => "Altre lingue",
+"redirectedfrom" => "(Reindirizzamento da $1)",
+"lastmodified" => "Ultima modifica il $1.",
+"viewcount"            => "Questo articolo è stato letto $1 volte.",
+"gnunote" => "Questa pagina è disponibile con licenza <a class=internal href='$wgScriptPath/GNU_FDL'>GNU FDL</a>.",
+"printsubtitle" => "(Articolo di {{SERVER}})",
+"protectedpage" => "Pagina protetta",
+"administrators" => "Wikipedia:Amministratori",
+"sysoptitle"   => "Riservato Sysop",
+"sysoptext"            => "Questa operazione può essere eseguita solo da Utenti con grado di \"sysop\".
+Vedi $1.",
+"developertitle" => "Riservato agli sviluppatori",
+"developertext"        => " Questa operazione può essere eseguita solo da Utenti con grado di \"developer\".
+Vedi $1.",
+"nbytes"               => "$1 bytes",
+"go"                   => "Vai",
+"ok"                   => "OK",
+"sitetitle"            => "Wikipedia",
+"sitesubtitle" => "L'Enciclopedia libera",
+"retrievedfrom" => "Ricavato da  \"$1\"",
+
+# Main script and global functions
+#
+"nosuchaction" => "Operazione non riconosciuta",
+"nosuchactiontext" => "L'operazione richiesta con la URL immessa non è stata riconosciuta dal software di Wikipedia",
+"nosuchspecialpage" => "Nessuna simile pagina speciale è disponibile",
+"nospecialpagetext" => "Hai richiesto una pagina speciale che non è stata riconosciuta dal software di Wikipedia, o che non è disponibile.",
+
+# General errors
+#
+"error"                        => "Errore",
+"databaseerror" => "Errore del database ",
+"dberrortext"  => "Errore di sintassi nella richiesta inoltrata al database.
+L'ultima richiesta inoltrata al database è stata:
+<blockquote><tt>$1</tt></blockquote>
+dalla funzione \"<tt>$2</tt>\".
+MySQL ha restituito un errore \"<tt>$3: $4</tt>\".",
+"noconnect"            => "Connessione al database fallita su $1",
+"nodb"                 => "Selezione del database $1 fallita",
+"readonly"             => "Accesso al database temporaneamente disabilitato",
+"enterlockreason" => "Fornisci una spiegazione sui motivi del blocco, includendo le probabili data ed ora di riattivazione o di rimozione del blocco.",
+"readonlytext" => "Il database di Wikipedia è al momento bloccato, e non consente nuove immissioni né modifiche, molto probabilmente per manutenzione server, nel qual caso il database sarà presto di nuovo completamente accessibile.<br />
+L'amministratore di sistema che ha imposto il blocco, ha lasciato questa nota:
+<p>:$1",
+"missingarticle" => "Il database non ha trovato il testo di una pagina, che invece avrebbe dovuto trovare, intitolata \"$1\".<br />
+Questo non è un errore del database, ma più probabilmente un problema del software.<br />
+Per favore, segnalate l'accaduto ad un amministratore di sistema, segnalando la URL e l'ora dell'incidente.",
+"internalerror" => "Errore interno",
+"filecopyerror" => "Non è stato possibile copiare il file \"$1\" come \"$2\".",
+"filerenameerror" => "Non è stato possibile rinominare il file \"$1\" in \"$2\".",
+"filedeleteerror" => "Non è stato possibile cancellare il file \"$1\".",
+"filenotfound" => " Non è stato possibile trovare il file \"$1\".",
+"unexpected"   => "Valore imprevisto: \"$1\"=\"$2\".",
+"formerror"            => "Errore: il modulo non è stato inviato correttamente",
+"badarticleerror" => "Questa operazione non è consentita su questa pagina.",
+"cannotdelete" => "Impossibile cancellare la pagina o l'immagine richiesta.",
+"badtitle"             => "Titolo non corretto",
+"badtitletext" => "La pagina richiesta non è disponibile, potrebbe essere non valida, vuota, o potrebbe trattarsi di un errore in un link interlinguistico o fra diverse versioni di Wikipedia.",
+"perfdisabled" => "Siamo davvero rammaricati, ma questa funzionalità è temporaneamente disabilitata durante le ore di maggiore accesso al database, per ragioni di accessibilità al resto del sito!<br />Torna fra le 02:00 e le 14:00 UTC e riprova.<br /><br />Grazie.",
+
+# Login and logout pages
+#
+"logouttitle"  => "Logout Utente",
+"logouttext"   => "Logout effettuato.
+Ora puoi continuare ad usare Wikipedia come utente anonimo (ma il tuo indirizzo IP resterà riconoscibile), oppure puoi nuovamente richiedere il login con il precedente username, oppure come uno diverso.\n",
+
+"welcomecreation" => "<h2>Benvenuto, $1!</h2><p>Il tuo account è stato creato con successo.<br />Grazie per aver scelto di far crescere Wikipedia con il tuo aiuto.<br />Per rendere Wikipedia più tua, e per usarla più scorrevolmente, non dimenticare di personalizzare le tue preferenze.",
+
+"loginpagetitle" => "Login",
+"yourname"             => "Il tuo  user name",
+"yourpassword" => "La tua  password",
+"yourpasswordagain" => "Ripeti la password",
+"newusersonly" => " (solo per nuovi Utenti)",
+"remembermypassword" => "Ricorda la mia password per più sessioni (richiede uso dei cookies).",
+"loginproblem" => "<b>Si è verificato un errore durante il tuo tentativo di login.</b><br />Riprova, sarai più fortunato!",
+"alreadyloggedin" => "<strong>Ehi, Utente $1, hai già fatto il login, sei già connesso al nostro server!</strong><br />\n",
+
+"login"                        => "Log in",
+"userlogin"            => "Log in",
+"logout"               => "Log out",
+"userlogout"   => "Log out",
+"createaccount"        => "Crea nuovo account",
+"badretype"            => "Le password che hai immesso non coincidono, sono diverse fra loro.",
+"userexists"   => "Siamo spiacenti.<br />Lo user name che hai scelto è già usato da un altro Utente.<br />Ti preghiamo perciò di voler scegliere uno user name diverso.",
+"youremail"            => "La tua e-mail",
+"yournick"             => "Il tuo diminutivo o soprannome (per le firme)",
+"emailforlost" => "Se per caso ti dimenticassi della tua password, ne potresti ricevere una nuova di zecca presso la casella e-mail che ci hai indicato.",
+"loginerror"   => "Errore di Login",
+"noname"               => "Lo user name indicato non è valido, non è possibile creare un account a questo nome.",
+"loginsuccesstitle" => "Login effettuato con successo!",
+"loginsuccess" => "Sei stato ammesso alla connessione al server di Wikipedia con il nome utente di \"$1\".",
+"nosuchuser"   => "Attenzione<br /><br />a seguito di verifica, non ci risulta alcun Utente con il nome di  \"$1\".<br /><br />
+Controlla per favore il nome digitato, oppure usa il modulo qui sotto per creare un nuovo user account.",
+"wrongpassword"        => "La password immessa non è corretta.<br /><br />Riprova, per favore.",
+"mailmypassword" => "Spediscimi una nuova password in posta elettronica",
+"passwordremindertitle" => "Servizio Password Reminder di Wikipedia",
+"passwordremindertext" => "Qualcuno (probabilmente tu, con indirizzo IP $1)
+ha richiesto l'invio di una nuova password per il login a Wikipedia.
+La password per l'Utente \"$2\" è ora \"$3\".
+Per evidenti ragioni di sicurezza, dovresti fare un log in il prima possibile, e cambiare la password immediatamente.",
+"noemail"              => "Nessuna casella e-mail risulta registrata per l'Utente \"$1\".",
+"passwordsent" => "Una nuova password è stata inviata alla casella e-mail registrata per l'Utente \"$1\".
+Per favore, fai subito un log in non appena la ricevi.",
+
+# Edit pages
+#
+"summary"              => "Oggetto",
+"minoredit"            => "Questa è una modifica minore",
+"watchthis"            => "Tieni d'occhio questo articolo",
+"savearticle"  => "Salva la pagina",
+"preview"              => "Anteprima",
+"showpreview"  => "Visualizza Anteprima",
+"blockedtitle" => "Questo User name corrisponde purtroppo ad un Utente che è stato disabilitato alla modifica degli articoli.",
+"blockedtext"  => "Il tuo User name o il tuo indirizzo IP sono stati bloccati da $1.<br />
+La motivazione del blocco è la seguente:<br />:''$2''<p>Se lo desideri, puoi contattare $1, o uno degli altri [[Wikipedia:administrators|amministratori]] per discutere del blocco.",
+"newarticle"   => "(Nuovo)",
+"newarticletext" => "Scrivi qui il tuo testo.",
+"noarticletext" => "(Questo articolo è vuoto, potresti gentilmente iniziare l'articolo, oppure richiedere la cancellazione di questa pagina)",
+"updated"              => "(Aggiornato)",
+"note"                 => "<strong>NOTA:</strong> ",
+"previewnote"  => "Tieni presente che questa è solo una ANTEPRIMA, e che la tua versione NON è ancora stata salvata!",
+"previewconflict" => "Questa anteprima rappresenta il testo nella casella di edizione di sopra, l'articolo apparirà in questa forma se sceglierai di salvare la pagina ora.",
+"editing"              => "Modifica di $1",
+"editconflict" => "Conflitto di edizione: $1",
+"explainconflict" => "Qualcun altro ha salvato una sua versione dell'articolo nel tempo in cui tu stavi preparando la tua versione.<br />
+La casella di modifica di sopra contiene il testo dell'articolo nella sua forma attuale (cioè il testo attualmente online). Le tue modifiche sono invece contenute nella casella di modifica inferiore.
+Dovrai inserire, se lo desideri, le tue modifiche nel testo esistente, e perciò scriverle nella casella di sopra.
+<b>Soltanto</b> il testo nella casella di sopra sarà salvato se premerai il bottone \"Salva\".<br />",
+"yourtext"             => "Il tuo testo",
+"storedversion" => "Versione in archivio",
+"editingold"   => "<strong>ATTENZIONE: Stai modificando una versione dell'articolo non aggiornata.<br />
+Se la salvi così, tutti i cambiamenti apportati dopo questa revisione verranno persi per sempre.</strong>",
+"yourdiff"             => "Differenze",
+"copyrightwarning" => "Nota, per favore, che tutti i contributi a Wikipedia si considerano rilasciati sotto licenza di tipo GNU Free Documentation License (vedi $1 per maggiori dettagli).
+Se non vuoi che il tuo testo possa essere modificato e ridistribuito da chiunque senza pietà e senza altri limiti, allora non inviarlo a Wikipedia, ma realizza piuttosto un tuo sito web personale.<br />
+Con l'invio di questo testo stai garantendo, a tua responsabilità, che il testo è stato scritto da te personalmente ed originalmente, oppure che è stato copiato da una fonte di publico dominio, o da una simile fonte, oppure che hai ottenuto espressa autorizzazione ad usare questo testo e che puoi dimostrarlo.
+<strong>NON USARE MATERIALE COPERTO DA DIRITTO DI AUTORE (COPYRIGHT - (c)) IN MANCANZA DI ESPRESSA AUTORIZZAZIONE!!!</strong>",
+
+
+# History pages
+#
+"revhistory"   => "Cronologia delle versioni di questa pagina.",
+"nohistory"            => "Cronologia delle versioni di questa pagina non reperibile.",
+"revnotfound"  => "Versione non trovata ",
+"revnotfoundtext" => "La versione precedente di questo articolo che hai richiesto, non è stata trovata.
+Controlla per favore la URL che hai usato per accedere a questa pagina.\n",
+"loadhist"             => "Caricamento cronologia di questa pagina",
+"currentrev"   => "Versione attuale",
+"revisionasof" => "Revisione $1",
+"cur"                  => "corr",
+"next"                 => "succ",
+"last"                 => "prec",
+"orig"                 => "orig",
+"histlegend"   => "Legend: (corr) = differenze con la versione corrente,
+(prec) = differenze con la versione precedente, M = modifica minore",
+
+# Diffs
+#
+"difference"   => "(Differenze fra le revisioni)",
+"loadingrev"   => "caricamento revisione per differenze",
+"lineno"               => "Riga $1:",
+"editcurrent"  => "Modifica la versione corrente di questa pagina",
+
+# Search results
+#
+"searchresults" => "Risultato della ricerca",
+"searchresulttext" => "Per maggiori informazioni sulla ricerca interna di {{SITENAME}}, vedi [[Project:Ricerca|Ricerca in {{SITENAME}}]].",
+"searchquery"  => "Richiesta \"$1\"",
+"badquery"             => "Richiesta mal inoltrata ",
+"badquerytext" => "La tua richiesta non ha potuto essere processata.
+Questo potrebbe dipendere dall'aver ricercato una parola di meno di tre caratteri.
+Oppure potresti aver scritto male la richiesta, per esempio \"pesce and and azzurro\".
+Per favore, riprova.",
+"matchtotals"  => "La ricerca per la voce \"$1\" ha trovato<br />$2 riscontri nei titoli degli articoli e<br />$3 riscontri nei testi degli articoli.",
+"titlematches" => "Nei titoli degli articoli",
+"notitlematches" => "Voce richiesta non trovata in titoli di articolo",
+"textmatches"  => "Nel testo degli articoli ",
+"notextmatches"        => "Voce richiesta non trovata in testi di articolo",
+"prevn"                        => "precedenti $1",
+"nextn"                        => "successivi $1",
+"viewprevnext" => "Vedi ($1) ($2) ($3).",
+"showingresults" => "Qui di seguito <b>$1</b> risultati, partendo dal numero #<b>$2</b>.",
+"nonefound"            => "<strong>Nota</strong>: la ricerca di parole troppo comuni, come \"avere\" o \"essere\", che non sono indicizzate, può causare un esito negativo, così come indicare più di un termine da ricercare (solo le pagine che contengano tutti i termini ricercati verrebbero infatti visualizzate fra i risultati).",
+"powersearch" => "Ricerca",
+"powersearchtext" => "
+Cerca fra i campi :<br />
+$1<br />
+$2 Elenca i redirects &nbsp; cerca per $3 $9",
+
+
+# Preferences page
+#
+"preferences"  => "Preferenze",
+"prefsnologin" => "Non hai eseguito il login",
+"prefsnologintext"     => "Devi avere eseguito il [[Special:Userlogin|login]]
+per poter personalizzare le tue preferenze.",
+"prefslogintext" => "Sei connesso a Wikipedia come \"$1\".
+Il tuo numero identificativo (ID) interno è $2.",
+"prefsreset"   => "Le tue Preferenze sono state ripescate dalla memoria di sistema del potente server di Wikipedia.",
+"qbsettings"   => "Settaggio barra menu",
+"changepassword" => "Cambia password",
+"skin"                 => "Aspetto",
+"saveprefs"            => "Salva preferenze",
+"resetprefs"   => "Resetta preferenze",
+"oldpassword"  => "Vecchia password",
+"newpassword"  => "Nuova password",
+"retypenew"            => "Riscrivi la nuova password",
+"textboxsize"  => "Dimensione della casella di edizione ",
+"rows"                 => "Righe",
+"columns"              => "Colonne",
+"searchresultshead" => "Settaggio preferenze di ricerca ",
+"resultsperpage" => "Risultati da visualizzare per pagina",
+"contextlines" => "Righe di testo per ciascun risultato",
+"contextchars" => "Caratteri per linea",
+"stubthreshold" => "Stub visualizzati",
+"recentchangescount" => "Numero titoli in \"modifiche recenti\" ",
+"savedprefs"   => "Le tue preferenze sono state salvate.",
+"timezonetext" => "Immetti il numero di ore di differenza fra la tua ora locale e la ora del server (UTC).",
+"localtime"    => "Ora Locale",
+"timezoneoffset" => "Offset",
+"emailflag"            => "Nascondi la mia e-mail<br />agli altri utenti",
+
+# Recent changes
+#
+"recentchanges" => "Ultime Modifiche",
+"recentchangestext" => "Segui in questa pagina le ultime modifiche apportate agli articoli di Wikipedia.
+[[Wikipedia:Welcome,_newcomers|Benvenuto]]!
+Leggi anche queste pagine: [[wikipedia:FAQ|Wikipedia FAQ]],
+[[Wikipedia:Policies and guidelines|la policy di Wikipedia]]
+(specialmente [[wikipedia:Convenzioni di nomenclatura| Convenzioni di nomenclatura]],
+[[wikipedia:Neutral point of view|oggettività e neutralità]]),
+e [[wikipedia:Most common Wikipedia faux pas|facili errori nell'uso di Wikipedia]].
+
+Se tieni al successo di questo progetto, è molto importante che eviti di immettere materiale coperto da diritti di autore ([[wikipedia:Copyrights|copyrights]]).
+Gli aspetti legali connessi potrebbero dare fastidio a noi ed a te personalmente, perciò controlla bene che quanto scrivi sia di [[pubblico dominio]], o prova ad ottenere le relative autorizzazioni, che in genere vengono concesse molto facilmente.",
+"rcloaderr"            => "Caricamento modifiche recenti ",
+"rcnote"               => "Qui di seguito sono elencate le ultime <strong>$1</strong> pagine modificate negli ultimi <strong>$2</strong> giorni.",
+"rcnotefrom"   => " Qui di seguito sono elencate le modifiche da <b>$2</b> (fino a <b>$1</b>).",
+"rclistfrom"   => "Mostra modifiche a partire da $1",
+# "rclinks"            => "Mostra le ultime $1 modifiche nelle ultime $2 ore / negli ultimi $3 giorni",
+"rclinks"              => " Mostra le ultime $1 modifiche negli ultimi $2 giorni.",
+"rchide"               => "in $4 form; $1 modifiche minori; $2 namespaces secondari; $3 modifiche multiple.",
+"diff"                 => "diff",
+"hist"                 => "cron",
+"hide"                 => "nascondi",
+"show"                 => "mostra",
+"tableform"            => "tabella",
+"listform"             => "elenco",
+"nchanges"             => "$1 modifiche",
+"minoreditletter" => "m",
+"newpageletter" => "N",
+
+# Upload
+#
+"upload"               => "Upload",
+"uploadbtn"            => "Upload",
+"uploadlink"   => "Upload immagini",
+"reupload"             => "Ri-upload",
+"reuploaddesc" => "Torna al modulo per lo upload.",
+"uploadnologin" => "Devi fare il login per eseguire questa operazione.",
+"uploadnologintext"    => "Devi eseguire [[Special:Userlogin|il login]]
+per fare lo upload di files.",
+"uploaderror"  => "Errore di Upload",
+"uploadtext"   => "'''FERMA!''' Prima di effettuare un upload su Wikipedia, accertati di avere ben letto e soprattutto compreso
+[[Project:Image_use_policy|le regole di Wikipedia sull'uso delle immagini]].
+
+Per visualizzare o cercare immagini precedentemente caricate su Wikipedia, vai alla [[Special:Imagelistlista delle immagini già caricate]].
+Uploads e cancellazioni delle immagini sono registrati nello
+[[Project:Upload_log|upload log]].
+
+Usa il modulo sottostante per caricare nuovi files immagine da utilizzare per arricchire ed illustrare i tuoi articoli.
+Sulla maggior parte dei browsers, dovresti vedere un bottone con la scritta \"Browse...\" (oppure \"Sfoglia...\", che aprirà una comune finestra di dialogo.<br />
+Scegliendo uno dei files sul tuo PC, il nome di questo file verrà scritto in automatico nella casella di testo a fianco al bottone.<p>
+'''Devi anche selezionare la casellina nella quale affermi che con questo upload non stai violando nessun copyright.'''
+
+Premi poi il bottone \"Upload\" per completare il caricamento.
+Il caricamento può richiedere qualche minuto se hai una connessione ad Internet lenta, o se l'immagine è eccessivamente pesante (sconsigliato).
+
+I formati immagine preferibili sono il JPEG per immagini fotografiche, il PNG
+per disegni ed altre immagini iconiche o simboliche, l' OGG per i suoni.
+Per cortesia, rinomina i tuoi files, prima di caricarli, usando un nome il più possibile descrittivo del contenuto, così da evitare confusioni.
+Per inserire poi la nuova immagine in un articolo, usa semplicemente un link nella forma
+'''<nowiki>[[image:file.jpg]]</nowiki>''' o
+'''<nowiki>[[image:file.png|alt text, testo alternativo]]</nowiki>''' o
+'''<nowiki>[[media:file.ogg]]</nowiki>''' per i suoni.
+
+Tieni presente che, come per tutte le pagine di Wikipedia, chiunque può modificare o sostituire o cancellare i tuoi files ove ritenga che ciò sia negli interessi della nostra enciclopedia. Tieni anche presente che, in caso di abuso, o di sovraccarico sul sistema, potresti essere bloccato (oltre ad essere perseguito per le connesse responsabilità).",
+"uploadlog"            => "upload log",
+"uploadlogpage" => "Upload_log",
+"uploadlogpagetext" => "Qui di seguito la lista degli ultimi files caricati sul server di Wikipedia.
+Tutti i tempi indicati sono calcolati sul fuso orario del server (UTC).
+<ul>
+</ul>
+",
+"filename"             => "Nome del file",
+"filedesc"             => "Oggetto",
+"copyrightpage" => "Wikipedia:Copyrights",
+"copyrightpagename" => "Wikipedia copyright",
+"uploadedfiles"        => "Files Caricati in Wikipedia",
+"ignorewarning"        => "Ignora le avvertenze e salva comunque il file.",
+"minlength"            => "I nomi dei file immagine debbono essere lunghi almeno tre caratteri, ma è preferibile usare nomi lumghi, purché descrittìvi.",
+"badfilename"  => "Il nome del file immagine è stato convertito in \"$1\".",
+"badfiletype"  => "\".$1\" non è un tipo di file raccomandato per le immagini, almeno ai nostri fini.",
+"largefile"            => "Il peso raccomandato per le immagini deve essere inferiore a 100kb.",
+"successfulupload" => "Caricamento completato",
+"fileuploaded" => "File \"$1\" correttamente caricato sul server.
+Segui questo link: ($2) per modificare la pagina di descrizione del file che hai appena caricato, e immetti subito le informazioni che ritieni opportune (cosa rappresenta, dove lo hai trovato, chi lo ha creato e quando, etc) oltre ad una nota circa la situazione di copyright sul file.<br />Non omettere la nota sul copyright, o il file verrebbe cancellato molto presto. ",
+"uploadwarning" => "Avviso di Upload",
+"savefile"             => "Salva file",
+"uploadedimage" => "caricato \"[[$1]]\"",
+
+# Image list
+#
+"imagelist"            => "Lista delle immagini",
+"imagelisttext"        => "Qui di seguito una lista di $1 immagini, ordinate per $2.",
+"getimagelist" => "ricerca nella lista delle immagini ",
+"ilsubmit"             => "Cerca",
+"showlast"             => "Lista di $1, fra le ultime immagini, ordinate per $2.",
+"byname"               => "nome",
+"bydate"               => "data",
+"bysize"               => "peso",
+"imgdelete"            => "canc",
+"imgdesc"              => "desc",
+"imglegend"            => "Legenda: (desc) = mostra/modifica descrizione immagine.",
+"imghistory"   => "Storia di questa immagine",
+"revertimg"            => "ripr",
+"deleteimg"            => "canc",
+"deleteimgcompletely"          => "canc",
+"imghistlegend" => "Legenda: (cur) = immagine corrente, (canc) = cancella questa vecchia versione, (ripr) = ripristina questa vecchia versione come versione attuale.
+<br /><i>Clicca su una data per vedere tutte le immagini che sono state caricate in quella data </i>.",
+"imagelinks"   => "Link alle immagini",
+"linkstoimage" => "Le pagine seguenti linkano questa immagine:",
+"nolinkstoimage" => "Nessuna pagina linka questa immagine.",
+
+# Statistics
+#
+"statistics"   => "Statistiche",
+"sitestats"            => "Statistiche del sito",
+"userstats"            => "Statistiche del nostro Wikipediano",
+"sitestatstext" => "Ci sono ben <b>$1</b> pagine nel database.
+Questa cifra comprende le pagine \"talk\" (discussione), pagine su Wikipedia, articoli esigui (\"stub\"), redirects, e altre pagine che probabilmente non andrebbero conteggiate fra gli articoli.
+Escludendo queste, ci sono ben  <b>$2</b> pagine che sono con buona probabilità propriamente degli articoli.<p>
+Ci sono state un totale di <b>$3</b> pagine viste, e <b>$4</b> modifiche agli articoli da quando il software è stato potenziato (Dicembre, 2002).
+Questa media rivela che ci sono state una media di  <b>$5</b> modifiche per ciascun articolo, e che l'articolo è stato letto <b>$6</b> volte per ciascuna modifica.",
+"userstatstext" => "Ci sono <b>$1</b> Utenti registrati ([[Wikipediani]]).
+<b>$2</b> di questi hanno il grado di amministratori (vedi $3).",
+
+# Maintenance Page
+#
+"maintenance"          => "Pagina manutenzioni",
+"maintnancepagetext"   => "In questa pagina sono elencati alcuni utili strumenti per una comoda manutenzione quotidiana della nostra enciclopedia. Alcune delle funzioni tendono a stressare il database, assorbendo molte risorse, perciò non fatene un uso continuo: non aggiornate le pagine (reload, refresh) subito dopo ogni singolo intervento. ;-)",
+"maintenancebacklink"  => "Torna alla pagina manutenzione",
+"disambiguations"      => "Disambiguation pages",
+"disambiguationspage"  => "Wikipedia:Links_to_disambiguating_pages",
+"disambiguationstext"  => "The following articles link to a <i>disambiguation page</i>. They should link to the appropriate topic instead.<br />A page is treated as dismbiguation if it is linked from $1.<br />Links from other namespaces are <i>not</i> listed here.",
+"doubleredirects"      => "Doppi Redirects",
+"doubleredirectstext"  => "<b>Attenzione:</b> Questa lista può talvolta contenere dei risultati non corretti. Ciò potrebbe magari accadere perchè vi sono del testo aggiuntivo o dei link dopo il tag #REDIRECT.<br />\nOgni riga contiene i link al primo ed al secondo redirect, oltre alla prima riga di testo del secondo redirect che di solito contiene il \"reale\" articolo di destinazione, quello al quale anche il primo redirect dovrebbe puntare.",
+"brokenredirects"      => "Redirects errati",
+"brokenredirectstext"  => "I seguenti redirects puntano ad articoli non ancora creati.",
+"selflinks"            => "Pagine con Auto-Links",
+"selflinkstext"                => "Le pagine seguenti contengono link che puntano a sé stesse, e in questo caso occorre eliminare questi auto-links.",
+"mispeelings"           => "Pagine con errori di ortografia ",
+"mispeelingstext"               => "Le pagine che seguono contengono errori comuni di ortografia, che sono elencati alla pagina $1. ",
+"mispeelingspage"       => "Lista di comuni errori di ortografia",
+"missinglanguagelinks"  => "Link interlinguistici mancanti",
+"missinglanguagelinksbutton"    => "Trova interlinks per ",
+"missinglanguagelinkstext"      => "Questi articoli <i>non</i> hanno link verso i corrispondenti articoli in $1. Redirects e sub-pagine <i>non</i> sono elencati.",
+
+
+# Miscellaneous special pages
+#
+"orphans"              => "Pagine orfane",
+"lonelypages"  => "Pagine solitarie",
+"unusedimages" => "Immagini non utilizzate",
+"popularpages" => "Pagine più viste",
+"nviews"               => "$1 visite",
+"wantedpages"  => "Articoli più richiesti",
+"nlinks"               => "$1 links",
+"allpages"             => "Tutte le pagine",
+"randompage"   => "Una pagina a caso",
+"shortpages"   => "Pagine corte",
+"longpages"            => "Pagine lunghe",
+"listusers"            => "Elenco degli Utenti",
+"specialpages" => "Pagine speciali",
+"spheading"            => "Pagine speciali",
+"protectpage"  => "Proteggi questa pagina ",
+"recentchangeslinked" => "Modifiche correlate",
+"rclsub"               => "(alle pagine linkate da \"$1\")",
+"debug"                        => "Debug",
+"newpages"             => "Pagine nuove",
+"movethispage" => "Sposta questa pagina",
+"unusedimagestext" => "<p>Nota che altri siti web, come la Wikipedia internazionale, potrebbero aver messo un link ad una immagine per mezzo di una URL diretta, perciò le immagini potrebbero essere listate qui, essendo inutilizzate in questa versione di Wikipedia, anche essendo magari in uso altrove.",
+"booksources"  => "Book sources",
+"booksourcetext" => "Below is a list of links to other sites that
+sell new and used books, and may also have further information
+about books you are looking for.
+Wikipedia is not affiliated with any of these businesses, and
+this list should not be construed as an endorsement.",
+
+# Email this user
+#
+"mailnologin"  => "No send address",
+"mailnologintext" => "Devi fare il  [[Special:Userlogin|login]]
+ed aver registrato una valida casella e-mail nelle tue [[Special:Preferences|preferenze]] per mandare posta elettronica ad altri Utenti.",
+"emailuser"            => "Manda una E-mail a questo Utente",
+"emailpage"            => "E-mail user",
+"emailpagetext"        => "Se questo Utente ha registrato una valida casella e-mail, il modulo qui sotto ti consentirà di scrivergli un solo messaggio.
+La e-mail che hai indicato nelle tue preferenze apparirà nel campo \"From\" della mail, così che il destinatario possa, solo se lo desidera però, risponderti.",
+"noemailtitle" => "Nessun indirizzo e-mail",
+"noemailtext"  => "Questo Utente non ha registrato alcuna casella e-mail, oppure ha scelto di non ricevere posta elettronica dagli altri Utenti.",
+"emailfrom"            => "Da",
+"emailto"              => "A",
+"emailsubject" => "Oggetto",
+"emailmessage" => "Messaggio",
+"emailsend"            => "Invia",
+"emailsent"            => "E-mail inviata",
+"emailsenttext" => "La tua e-mail è stata inviata.",
+
+# Watchlist
+#
+"watchlist"            => "Osservati Speciali",
+"watchlistsub" => "(per l'Utente \"$1\")",
+"nowatchlist"  => "Non hai indicato articoli da tenere d'occhio.",
+"watchnologin" => "Manca il login",
+"watchnologintext"     => "Devi prima fare il [[Special:Userlogin|login]]
+per modificare la tua lista di osservati speciali.",
+"addedwatch"   => "Aggiunto ai tuoi Osservati Speciali",
+"addedwatchtext" => " La pagina  \"$1\" è stata aggiunta alla tua <a href=\"" .
+  "{{localurle:Special:Watchlist}}\"> lista di osservati speciali </a>.
+Le future modifiche a questa pagina ed alla relativa pagina di discussione saranno elencate qui, e la pagina apparirà in <b>grassetto</b> nella pagina delle <a href=\"" .
+  "{{localurle:Special:Recentchanges}}\">modifiche recenti</a> per essere più facile da tener d'occhio.</p>
+
+<p>Se in seguito vorrai togliere questo articolo dalla tua lista di Osservati Speciali, clicca \" Smetti di seguire \" nella barra dei menu.",
+"removedwatch" => "Rimosso dalla lista degli Osservati Speciali",
+"removedwatchtext" => "La pagina  \"$1\" è stata rimossa dalla lista dei tuoi Osservati Speciali.",
+"watchthispage"        => "Segui questo articolo",
+"unwatchthispage" => "Smetti di seguire",
+"notanarticle" => "Non è un articolo",
+
+# Delete/protect/revert
+#
+"deletepage"   => "Cancella pagina",
+"confirm"              => "Conferma",
+"confirmdelete" => "Conferma cancellazione",
+"deletesub"            => "(Cancellazione di \"$1\")",
+"confirmdeletetext" => "Stai per cancellare permanentemente dal database una pagina o una immagine, insieme a tutta la sua cronologia.<p>
+Per cortesia, conferma che è tua intenzione procedere a tale cancellazione, conferma che hai piena consapevolezza delle conseguenze della tua azione, e conferma che la tua azione è pienamente ottemperante alle regole stabilite nella
+[[Wikipedia:Policy]].",
+"actioncomplete" => "Azione completata",
+"deletedtext"  => "La pagina \"$1\" è stata cancellata.
+Vedi $2 per un elenco delle pagine cancellate di recente.",
+"deletedarticle" => "Cancellata \"$1\"",
+"dellogpage"   => "Deletion_log",
+"dellogpagetext" => "Qui di seguito, un elenco delle pagine cancellate di recente.
+Tutti i tempi sono in ora del server (UTC).
+<ul>
+</ul>
+",
+"deletionlog"  => "deletion log",
+"reverted"             => "Ripristinata versione precedente",
+"deletecomment"        => "Motivazione della cancellazione ",
+"imagereverted" => "Versione precedente correttamente ripristinata.",
+"rollback"             => "Usa una revisione precedente",
+"cantrollback" => "Impossibile tornare ad una versione precedente: l'ultima modifica è stata apportata dall'unico utente che abbia lavorato a questo articolo.",
+"revertpage"   => "Riportata alla revisione precedente da $1",
+
+# Undelete
+"undelete" => "Recupera una pagina cancellata",
+"undeletepage" => "Vedi e recupera pagine cancellate ",
+"undeletepagetext" => "Le pagine qui di seguito indicate sono state cancellate, ma sono ancora in archivio e pertanto possono essere recuperate. L'archivio viene svuotato periodicamente.",
+"undeletearticle" => "Recupera un articolo cancellato",
+"undeleterevisions" => "$1 revisioni in archivio",
+"undeletehistory" => "Se recuperi questo articolo, tutte le sue revisioni verranno recuperate nella relativa cronologia.<br />
+Se una nuova pagina è stata creata con questo stesso nome dopo la cancellazione, le revisioni recuperate saranno inserite nella cronologia e la versione attualmente online della pagina non verrà modificata.",
+"undeleterevision" => "Cancellata revisione $1",
+"undeletebtn" => "RIPRISTINA!",
+"undeletedarticle" => "Recuperata \"$1\"",
+"undeletedtext"   => "La pagina [[$1]] è stata recuperata.
+Vedi [[Wikipedia:Deletion_log]] per un elenco delle pagine cancellate e recuperate di recente.",
+
+# Contributions
+#
+"contributions"        => "Contributi di questo Utente",
+"contribsub"   => "Per $1",
+"nocontribs"   => "Nessuna modifica trovata conformemente a questi criteri.",
+"ucnote"               => "Qui sotto troverai le ultime <b>$1</b> modifiche effettuate da questo Utente negli ultimi <b>$2</b> giorni.",
+"uclinks"              => "Vedi le ultime $1 modifiche; vedi gli ultimi $2 giorni.",
+"uctop"                => " (ultima per la pagina)" ,
+
+# What links here
+#
+"whatlinkshere"        => "Pagine che linkano questa",
+"notargettitle" => "Dati mancanti",
+"notargettext" => "Non hai specificato una pagina o un Utente in relazione al quale eseguire l'operazione richiesta.",
+"linklistsub"  => "(Lista di links)",
+"linkshere"            => "Le seguenti pagine contengono link che puntano qui:",
+"nolinkshere"  => "Nessuna pagina contiene links che puntano a questa.",
+"isredirect"   => "redirect ",
+
+# Block/unblock IP
+#
+"blockip"              => "Blocca indirizzo IP",
+"blockiptext"  => "Usa il modulo sottostante per bloccare l'accesso con diritto di scrittura da uno specifico indirizzo IP.<br />
+Questo blocco deve essere operato SOLO per prevenire atti di vandalismo, ed in stretta osservanza dei principi tutti della [[Wikipedia:Policy|policy di Wikipedia]].<br />Il blocco non può in nessun caso essere applicato per motivi ideologici.<p>
+Scrivi un motivo specifico per il quale questo indirizzo IP dovrebbe a tuo avviso essere bloccato (per esempio, cita i titoli di pagine eventualmente già oggetto di vandalismo editoriale).",
+"ipaddress"            => "Indirizzo IP (IP Address)",
+"ipbreason"            => "Motivazione",
+"ipbsubmit"            => "Blocca questo indirizzo IP",
+"badipaddress" => "L'indirizzo IP indicato non è corretto.",
+"blockipsuccesssub" => "Blocco eseguito",
+"blockipsuccesstext" => " L'indirizzo IP \"$1\" è stato bloccato.
+<br />Vedi [[Special:Ipblocklist|lista IP bloccati]].",
+"unblockip"            => " Sblocca indirizzo IP",
+"unblockiptext"        => "Usa il modulo sottostante per restituire il diritto di scrittura ad un indirizzo IP precedentemente bloccato.",
+"ipusubmit"            => "Sblocca questo indirizzo IP",
+"ipusuccess"   => "Indirizzo IP \"$1\" sbloccato",
+"ipblocklist"  => "Lista degli indirizzi IP bloccati",
+"blocklistline"        => "$1, $2 ha bloccato $3 ($4)",
+"blocklink"            => "blocca",
+"unblocklink"  => "sblocca",
+"contribslink" => "contributi",
+
+# Developer tools
+#
+"lockdb"               => "Blocca il database",
+"unlockdb"             => "Sblocca il database",
+"lockdbtext"   => "Bloccare il database sospenderà la possibilità per tutti gli Utenti di modificare le pagine o di crearne di nuove, di cambiare le loro preferenze, di modificare le loro liste di Osservati Speciali, ed in genere non consentirà a nessuno di eseguire operazioni che richiedano modifiche del database.<br /><br />
+Per cortesia, conferma che questo è effettivamente quanto tu intendi ora effettuare e, soprattutto, che il prima possibile sbloccherai nuovamente il database, ripristinandone la corretta funzionalità, non appena avrai terminato le tue manutenzioni.",
+"unlockdbtext" => "Sbloccare il database ripristinerà la possibilità per tutti gli Utenti di modificare le pagine o di crearne di nuove, di cambiare le loro preferenze, di modificare le loro liste di Osservati Speciali, ed in genere di eseguire operazioni che richiedano modifiche del database.
+Per cortesia, conferma che questo è effettivamente quanto tu intendi ora effettuare.",
+"lockconfirm"  => "Sì, effettivamente intendo, sotto la mia responsabilità, bloccare il database.",
+"unlockconfirm"        => " Sì, effettivamente intendo, sotto la mia responsabilità, sbloccare il database.",
+"lockbtn"              => "Blocca il database",
+"unlockbtn"            => "Sblocca il database",
+"locknoconfirm" => "Non hai spuntato la casellina di conferma.",
+"lockdbsuccesssub" => "Blocco del database eseguito",
+"unlockdbsuccesssub" => "Sblocco del database eseguito, rimosso blocco",
+"lockdbsuccesstext" => "Il database di Wikipedia è stato bloccato.
+<br />Ricordati di rimuovere il blocco non appena avrai terminatoi le tue manutenzioni.",
+"unlockdbsuccesstext" => " Il database di Wikipedia è stato sbloccato.",
+
+# Move page
+#
+"movepage"             => "Spostamento di pagina",
+"movepagetext" => "Con il modulo sottostante puoi rinominare una pagina, spostando anche tutta la sua cronologia al nuovo nome.
+Il vecchio titolo diverrà automaticamente un redirect che punta al nuovo titolo.
+I link alla vecchia pagina non saranno aggiornati (e punteranno quindi al redirect); accertati di [[Special:Manutenzioni|controllare con cura]] che non si creino doppi redirects o redirects interrotti.
+Resta nella tua responsabilità di accertarti che i link continuino a puntare verso dove devono dirigersi.
+
+Nota bene: la pagina '''non''' sarà spostata se vi fosse già un articolo con il nuovo nome, a meno che non sia una pagina vuota o un redirect, e sempre che non abbia cronologia. Questo significa che, se commetti un errore, puoi nuovamente rinominare una pagina col vecchio titolo, ma non puoi sovrascrivere una pagina già esistente.
+
+<b>ATTENZIONE!</b>
+Questo cambiamento drastico potrebbe creare inattesi contrattempi, specialmente se si tratta di una pagina molto visitata. Accertati di aver ben valutato le conseguenze dello spostamento, prima di procedere. Nel dubbio, contatta un Amministratore.",
+"movepagetalktext" => "La corrispondente pagina di discussione, se esiste, sarà spostata automaticamente insieme all'articolo, '''tranne che nei seguenti casi:'''
+*Spostamento della pagina fra i namespaces,
+*Una pagina di discussione (non vuota) già esiste per il nuovo nome, oppure
+*Hai deselezionato la casellina qui sotto.
+In questi casi, se lo ritieni opportuno, dovrai spostare o aggiungere manualmente la pagina di discussione.",
+"movearticle"  => "Rinomina articolo",
+"movenologin"  => "Non hai effettuato il login",
+"movenologintext" => "Devi essere un Utente registrato ed aver effettuato il [[Special:Userlogin|login]]
+per poter spostare una pagina.",
+"newtitle"             => "Al nuovo titolo di ",
+"movepagebtn"  => "Sposta questa pagina",
+"pagemovedsub" => "Spostamento effettuato con successo",
+"pagemovedtext" => "Pagina \"[[$1]]\" rinominata in \"[[$2]]\".",
+"articleexists" => "Una pagina con questo nome esiste già, oppure il nome che hai scelto non è valido.<br />
+Scegli, per cortesia, un titolo diverso per l'articolo.",
+"talkexists"   => "La pagina è stata spostata correttamente, ma non si è potuto spostare la pagina di discussione perché ne esiste già un'altra con il nuovo titolo. Per favore, modifica manualmente i contenuti delle due pagine discussione, così da mantenerle entrambe per non perdere potenzialmente interessanti riflessioni.",
+"movedto"              => "spostata a ",
+"movetalk"             => "Sposta anche la corrispondente pagina \"discussione\", se possibile.",
+"talkpagemoved" => "Anche la corrispondente pagina di discussione è stata spostata.",
+"talkpagenotmoved" => "La corrispondente pagina di discussione <strong>non è stata spostata</strong>."
+
+);
+
+require_once( "LanguageUtf8.php" );
+
+class LanguageIt extends LanguageUtf8 {
+
+       function getNamespaces() {
+               global $wgNamespaceNamesIt;
+               return $wgNamespaceNamesIt;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsIt;
+               return $wgQuickbarSettingsIt;
+       }
+
+       function date( $ts, $adj = false ) {
+               if ( $adj ) { $ts = $this->userAdjust( $ts ); }
+
+               $d = $this->getMonthAbbreviation( substr( $ts, 4, 2 ) ) .
+                 " " . (0 + substr( $ts, 6, 2 )) . ", " .
+                 substr( $ts, 0, 4 );
+               return $d;
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesIt;
+               if(array_key_exists($key, $wgAllMessagesIt))
+                       return $wgAllMessagesIt[$key];
+               else
+                       return parent::getMessage($key);
+       }
+
+       /**
+        * Italian numeric format is 201.511,17
+        */
+       function formatNum( $number, $year = false ) {
+               return $year ? $number : strtr($this->commafy($number), '.,', ',.' );
+       }
+
+}
+
+?>
diff --git a/languages/LanguageJa.php b/languages/LanguageJa.php
new file mode 100644 (file)
index 0000000..37dab45
--- /dev/null
@@ -0,0 +1,1926 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+global $IP;
+require_once( "LanguageUtf8.php" );
+
+/* private */ $wgNamespaceNamesJa = array(
+       NS_MEDIA          => "Media", /* Media */
+       NS_SPECIAL        => "特別", /* Special */
+       NS_MAIN           => "",
+       NS_TALK           => "ノート", /* Talk */
+       NS_USER           => "利用者", /* User */
+       NS_USER_TALK      => "利用者‐会話", /* User_talk */
+       NS_PROJECT        => $wgMetaNamespace, /* Wikipedia */
+       NS_PROJECT_TALK   => "{$wgMetaNamespace}‐ノート", /* Wikipedia_talk */
+       NS_IMAGE          => "画像", /* Image */
+       NS_IMAGE_TALK     => "画像‐ノート", /* Image_talk */
+       NS_MEDIAWIKI      => "MediaWiki", /* MediaWiki */
+       NS_MEDIAWIKI_TALK => "MediaWiki‐ノート", /* MediaWiki_talk */
+       NS_TEMPLATE       => "Template", /* Template */
+       NS_TEMPLATE_TALK  => "Template‐ノート", /* Template_talk */
+       NS_HELP           => "Help", /* Help */
+       NS_HELP_TALK      => "Help‐ノート", /* Help_talk */
+       NS_CATEGORY       => "Category", /* Category */
+       NS_CATEGORY_TALK  => "Category‐ノート" /* Category_talk */
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgQuickbarSettingsJa = array(
+       "なし", "左端", "右端", "ウィンドウの左上に固定"
+);
+
+/* private */ $wgSkinNamesJa = array(
+       'standard' => "標準",
+       'nostalgia' => "ノスタルジア",
+       'cologneblue' => "ケルンブルー",
+) + $wgSkinNamesEn;
+
+/* private */ $wgDateFormatsJa = array(
+       MW_DATE_DEFAULT => '2001年1月15日 16:12 (デフォルト)',
+       MW_DATE_ISO => '2001-01-15 16:12:34'
+);
+
+/* private */ $wgWeekdayAbbreviationsJa = array(
+       "日", "月", "火", "水", "木", "金", "土"
+);
+
+/* private */ $wgAllMessagesJa = array(
+
+# The navigation toolbar, int: is used here to make sure that the appropriate
+# messages are automatically pulled from the user-selected language file.
+
+/*
+The sidebar for MonoBook is generated from this message, lines that do not
+begin with * or ** are discarded, furthermore lines that do begin with ** and
+do not contain | are also discarded, but don't depend on this behaviour for
+future releases. Also note that since each list value is wrapped in a unique
+XHTML id it should only appear once and include characters that are legal
+XHTML id names.
+
+Note to translators: Do not include this message in the language files you
+submit for inclusion in MediaWiki, it should always be inherited from the
+parent class in order maintain consistency across languages.
+*/
+# 'sidebar' => '',
+
+# User preference toggles
+'tog-underline' => 'リンクの下線:',
+'tog-highlightbroken' => '未作成のページへのリンクをハイライトする',
+'tog-justify' => '段落を均等割り付けする',
+'tog-hideminor' => '最近更新したページから細部の編集を隠す',
+'tog-usenewrc' => '最近更新したページを拡張する(対応していないブラウザもあります)',
+'tog-numberheadings' => '見出しに番号を振る',
+'tog-showtoolbar' => '編集ボタンを表示する',
+'tog-editondblclick' => 'ダブルクリックで編集する (JavaScript)',
+'tog-editsection' => 'セクション編集用リンクを有効にする',
+'tog-editsectiononrightclick' => 'セクションタイトルの右クリックでセクション編集を行えるようにする (JavaScript)',
+'tog-showtoc' => '目次を表示する (4つ以上の見出しがあるページ)',
+'tog-rememberpassword' => 'セッションを越えてパスワードを記憶する',
+'tog-editwidth' => 'テキストボックスを横幅いっぱいに表示する',
+'tog-watchdefault' => '編集した記事をウォッチリストに追加する',
+'tog-minordefault' => '細部の編集をデフォルトでチェックする',
+'tog-previewontop' => 'プレビューをテキストボックスの前に配置する',
+'tog-previewonfirst' => '編集時にはじめからプレビューを表示する',
+'tog-nocache' => 'ページをキャッシュしない',
+'tog-enotifwatchlistpages' => 'ページが更新されたときにメールを受け取る',
+'tog-enotifusertalkpages' => '自分の会話ページが更新されたときにメールを受け取る',
+'tog-enotifminoredits' => '細部の編集でもメールを受け取る',
+'tog-enotifrevealaddr' => 'あなた以外に送られる通知メールにあなたのメールアドレスを記載する',
+'tog-shownumberswatching' => 'ページをウォッチしているユーザー数を表示する',
+'tog-fancysig' => '署名を自動的に利用者ページへリンクさせない',
+'tog-externaleditor' => '編集に外部アプリケーションを使う',
+'tog-externaldiff' => '差分表示に外部アプリケーションを使う',
+
+'underline-always' => '常に付ける',
+'underline-never' => '常に付けない',
+'underline-default' => 'ブラウザに従う',
+
+'skinpreview' => '(プレビュー)',
+
+# dates
+'sunday' => '日曜日',
+'monday' => '月曜日',
+'tuesday' => '火曜日',
+'wednesday' => '水曜日',
+'thursday' => '木曜日',
+'friday' => '金曜日',
+'saturday' => '土曜日',
+'january' => '1月',
+'february' => '2月',
+'march' => '3月',
+'april' => '4月',
+'may_long' => '5月',
+'june' => '6月',
+'july' => '7月',
+'august' => '8月',
+'september' => '9月',
+'october' => '10月',
+'november' => '11月',
+'december' => '12月',
+'jan' => '1月',
+'feb' => '2月',
+'mar' => '3月',
+'apr' => '4月',
+'may' => '5月',
+'jun' => '6月',
+'jul' => '7月',
+'aug' => '8月',
+'sep' => '9月',
+'oct' => '10月',
+'nov' => '11月',
+'dec' => '12月',
+# Bits of text used by many pages:
+#
+'categories' => 'カテゴリ',
+'category' => 'カテゴリ',
+'category_header' => 'カテゴリ: “$1”',
+'subcategories' => 'サブカテゴリ',
+
+
+'linktrail' => '/^$/sD',
+'linkprefix' => '/^(.*?)([a-zA-Z\\x80-\\xff]+)$/sD',
+'mainpage' => 'メインページ',
+'mainpagetext' => 'Wikiソフトウェアが正常にインストールされました。',
+'mainpagedocfooter' => '[http://meta.wikimedia.org/wiki/MediaWiki_localization インターフェイスの変更方法]や、そのほかの使い方・設定に関しては[http://meta.wikimedia.org/wiki/Help:Contents ユーザーズガイド]を参照してください。',
+
+'portal' => 'コミュニティ・ポータル',
+'portal-url' => 'Project:コミュニティ・ポータル',
+'about' => '解説',
+'aboutsite' => '{{SITENAME}}について',
+'aboutpage' => 'Project:About',
+'article' => '本文',
+'help' => 'ヘルプ',
+'helppage' => 'Help:Contents',
+'bugreports' => 'バグの報告',
+'bugreportspage' => 'Project:バグの報告',
+'sitesupport' => '寄付',
+'sitesupport-url' => 'Project:Site support',
+'faq' => 'FAQ',
+'faqpage' => '{{ns:4}}:FAQ',
+'edithelp' => '編集の仕方',
+'newwindow' => '(新しいウィンドウが開きます)',
+'edithelppage' => 'Help:編集の仕方',
+'cancel' => '中止',
+'qbfind' => '検索',
+'qbbrowse' => '閲覧',
+'qbedit' => '編集',
+'qbpageoptions' => '個人用ツール',
+'qbpageinfo' => 'ページ情報',
+'qbmyoptions' => 'オプション',
+'qbspecialpages' => '特別ページ',
+'moredotdotdot' => 'すべて表示する',
+'mypage' => 'マイ・ページ',
+'mytalk' => 'マイ・トーク',
+'anontalk' => 'このIPとの会話',
+'navigation' => 'ナビゲーション',
+
+# Metadata in edit box
+'metadata' => 'メタデータ',
+'metadata_page' => '{{ns:Project}}:Metadata',
+
+'currentevents' => '最近の出来事',
+'currentevents-url' => '最近の出来事',
+
+'disclaimers' => '免責事項',
+'disclaimerpage' => 'Project:免責事項',
+'errorpagetitle' => 'エラー',
+'returnto' => '$1 に戻る。',
+'tagline' => '出典: {{SITENAME}}',
+'whatlinkshere' => 'リンク元',
+'help' => 'ヘルプ',
+'search' => '検索',
+'go' => '表示',
+'history' => '履歴',
+'history_short' => '履歴',
+'info_short' => 'ページ情報',
+'printableversion' => '印刷用バージョン',
+'print' => 'Print',
+'edit' => '編集',
+'editthispage' => 'このページを編集',
+'delete' => '削除',
+'deletethispage' => 'このページを削除',
+'undelete_short1' => '削除済1版',
+'undelete_short' => '削除済$1版',
+'protect' => '保護',
+'protectthispage' => 'このページを保護',
+'unprotect' => '保護解除',
+'unprotectthispage' => 'ページ保護解除',
+'newpage' => '新規ページ',
+'talkpage' => 'このページのノート',
+'specialpage' => '特別ページ',
+'personaltools' => '個人用ツール',
+'postcomment' => '新規にコメントを投稿',
+'addsection' => '+',
+'articlepage' => '項目を表示',
+'subjectpage' => 'サブジェクト・ページ',
+'talk' => 'ノート',
+'views' => '表示',
+'toolbox' => 'ツールボックス',
+'userpage' => '利用者ページを表示',
+'wikipediapage' => '{{SITENAME}}ページを表示',
+'imagepage' => '画像のページを表示',
+'viewtalkpage' => 'ノートを表示',
+'otherlanguages' => '他の言語',
+'redirectedfrom' => '($1 から転送)',
+'lastmodified' => '最終更新 $1。',
+'viewcount' => 'このページは $1 回アクセスされました。',
+'copyright' => 'Content is available under $1.',
+'poweredby' => '{{SITENAME}} is powered by [http://www.mediawiki.org/ MediaWiki], an open source wiki engine.',
+'printsubtitle' => '(From {{SERVER}}/)',
+'protectedpage' => '保護されたページ',
+'administrators' => '{{ns:Project}}:管理者',
+
+'sysoptitle' => '管理者によるアクセスが必要',
+'sysoptext' => 'あなたの要求した処理は管理者のみが実行できます。
+$1を参照してください。',
+'developertitle' => '開発者によるアクセスが必要',
+'developertext' => 'あなたの要求した処理は開発者のみが実行できます。
+$1 を参照してください。',
+
+'badaccess' => '権限がありません',
+'badaccesstext' => 'あなたの要求した処理は "$2" の権限を持ったユーザーのみが実行できます。詳しくは $1 を参照してください。',
+
+'versionrequired' => 'MediaWiki Version $1 が必要',
+'versionrequiredtext' => 'このページの利用には MediaWiki Version $1 が必要です。[[{{ns:Special}}:Version]]を確認してください。',
+
+'nbytes' => '$1 バイト',
+'ok' => 'OK',
+'sitetitle' => '{{SITENAME}}',
+'pagetitle' => '$1 - {{SITENAME}}',
+'sitesubtitle' => '-',
+'retrievedfrom' => ' "$1" より作成',
+'newmessages' => '$1が届いています。',
+'newmessageslink' => '新しいメッセージ',
+'editsection' => '編集',
+'toc' => '目次',
+'showtoc' => '表示',
+'hidetoc' => '非表示',
+'thisisdeleted' => '$1 を参照または復帰する。',
+'restorelink1' => '削除された 1 編集',
+'restorelink' => '削除された $1 編集',
+'feedlinks' => 'Feed:',
+'sitenotice' => '-',
+
+# Short words for each namespace, by default used in the 'article' tab in monobook
+'nstab-main' => '本文',
+'nstab-user' => '利用者ページ',
+'nstab-media' => 'Media',
+'nstab-special' => '特別ページ',
+'nstab-wp' => '解説',
+'nstab-image' => '画像',
+'nstab-mediawiki' => '定型文',
+'nstab-template' => 'Template',
+'nstab-help' => 'Help',
+'nstab-category' => 'カテゴリ',
+
+# Main script and global functions
+#
+'nosuchaction' => 'そのような動作はありません',
+'nosuchactiontext' => 'このURIで指定された動作は{{SITENAME}}で認識できません。',
+'nosuchspecialpage' => 'そのような特別ページはありません',
+'nospecialpagetext' => '要求された特別ページは存在しません。有効な特別ページの一覧は[[{{ns:Special}}:Specialpages]]にあります。',
+
+# General errors
+#
+'error' => 'エラー',
+'databaseerror' => 'データベース・エラー',
+'dberrortext' => 'データベース検索の文法エラー。これは恐らくソフトウェアのバグを表しています。
+
+最後に実行を試みた問い合わせ: 
+<blockquote><tt>$1</tt></blockquote>
+
+from within function "<tt>$2</tt>". MySQL returned error "<tt>$3: $4</tt>".',
+'dberrortextcl' => 'A database query syntax error has occurred.
+The last attempted database query was:
+"$1"
+from within function "$2".
+MySQL returned error "$3: $4".
+',
+'noconnect' => '申し訳ありません。何らかの問題によりデータベースに接続できません。<br/>$1',
+'nodb' => 'データベース $1 を選択できません。',
+'cachederror' => 'あなたがアクセスしたページのコピーを保存したものを表示しています。また、コピーは更新されません。',
+'laggedslavemode' => '警告: ページに最新の編集が反映されていない可能性があります。反映されるまでしばらくお待ちください。',
+'readonly' => 'データベースはロックされています',
+'enterlockreason' => 'ロックする理由を入力してください。ロックが解除されるのがいつになるかの見積もりについても述べてください。',
+'readonlytext' => 'データベースは現在、新しいページの追加や編集を受け付けない「ロック状態」になっています。これはおそらく定期的なメンテナンスのためで、メンテナンス終了後は正常な状態に復帰します。データベースをロックした管理者は次のような説明をしています:
+
+$1
+
+----
+The database is currently locked to new entries and other modifications, probably for routine database maintenance, after which it will be back to normal. The administrator who locked it offered this explanation:
+
+$1',
+'missingarticle' => '<p>"$1" という題のページは見つかりませんでした。すでに削除された版を参照しようとしている可能性があります。これがソフトウェアのバグだと思われる場合は、URIと共に管理者に報告して下い。</p>
+<p>The database did not find the text of a page that it should have found, named "$1". This is usually caused by following an outdated diff or history link to a page that has been deleted. If this is not the case, you may have found a bug in the software. Please report this to an administrator, making note of the URL.</p>',
+
+
+'readonly_lag' => 'データベースはスレーブ・サーバがマスタ・サーバに同期するまで自動的にロックされています。しばらくお待ちください。
+
+The database has been automatically locked while the slave database servers catch up to the master.',
+'internalerror' => '内部処理エラー',
+'filecopyerror' => 'ファイル "$1" から "$2" のコピーに失敗しました。',
+'filerenameerror' => 'ファイル名を "$1" から "$2" へ変更できませんでした。',
+'filedeleteerror' => 'ファイル "$1" の削除に失敗しました。',
+'filenotfound' => 'ファイル "$1" が見つかりません。',
+'unexpected' => '値が異常です: $1 = "$2"',
+'formerror' => 'エラー: フォームの送信に失敗しました。',
+'badarticleerror' => 'このページでは要求された処理を行えません。',
+'cannotdelete' => '指定されたページ、または画像の削除に失敗しました。',
+'badtitle' => 'ページタイトルの間違い',
+'badtitletext' => '要求されたページは無効か、何もないか、正しくない inter-language または inter-wiki のタイトルです。',
+'perfdisabled' => 'この機能はデータベースの負荷を軽くするために現在使えなくなっています。',
+'perfdisabledsub' => 'ここには $1 のコピーを表示しています。',
+'perfcached' => '以下のデータはキャッシュであり、しばらく更新されていません。',
+'wrong_wfQuery_params' => 'Incorrect parameters to wfQuery()<br />
+Function: $1<br />
+Query: $2
+',
+'viewsource' => 'ソースを表示',
+'protectedtext' => 'このページは編集できないように保護されています。これにはいくつか理由があります。詳しくは[[{{ns:Project}}:保護されたページ]]をご覧ください。
+
+下にソースを表示しています。',
+
+'sqlhidden' => '(SQL query hidden)',
+
+# Login and logout pages
+#
+'logouttitle' => 'ユーザー ログアウト',
+'logouttext' => '<p><strong>ログアウトしました。</strong>このまま{{SITENAME}}を匿名で使い続けることができます。もう一度ログインして元の、あるいは別のユーザーとして使うこともできます。</p>
+<p>※いくつかのページはブラウザのキャッシュをクリアするまでログインしているかのように表示されることがあります。</p>',
+
+'welcomecreation' => '== $1 さん、ようこそ! ==
+あなたのアカウントができました。お好みに合わせて[[Special:Preferences|ユーザーオプション]]を変更することをお忘れなく。',
+
+
+'loginpagetitle' => 'ユーザー ログイン',
+'yourname' => 'あなたのユーザー名',
+'yourpassword' => 'あなたのパスワード',
+'yourpasswordagain' => 'パスワード再入力',
+'newusersonly' => '(新規ユーザーのみ)',
+'remembermypassword' => 'セッションを越えてパスワードを記憶する',
+'yourdomainname' => 'あなたのドメイン',
+'externaldberror' => '外部の認証データベースでエラーが発生たか、または外部アカウント情報の更新が許可されていません。',
+'loginproblem' => '<b>ログインでエラーが発生しました。</b><br />再度実行してください。',
+'alreadyloggedin' => '<strong>ユーザー $1 は、すでにログイン済みです。</strong><br />',
+
+'login' => 'ログイン',
+'loginprompt' => '{{SITENAME}}にログインするにはクッキーを有効にする必要があります。',
+'userlogin' => 'ログインまたはアカウント作成',
+'logout' => 'ログアウト',
+'userlogout' => 'ログアウト',
+'notloggedin' => 'ログインしていません',
+'createaccount' => '新規アカウント作成',
+'createaccountmail' => '電子メール経由',
+'badretype' => '両方のパスワードが一致しません。',
+'userexists' => 'そのユーザー名はすでに使われています。ほかの名前をお選びください。',
+'youremail' => 'メールアドレス*',
+'yourrealname' => 'あなたの本名*',
+'yourlanguage' => 'インターフェース言語',
+'yourvariant' => '字体変換',
+'yournick' => 'ニックネーム(署名用)',
+'email' => 'メールアドレス',
+'emailforlost' => '<nowiki>*</nowiki>マークの項目は任意です。メールアドレスを入力すると、他の人があなたのメールアドレスを知ることなくあなたにメールを送れるようになります。またパスワードを忘れた際にメールでパスワードの再発行を受けられます。本名を入力すると、ページ・クレジットに利用者名(アカウント名)の代わりに本名が表示されます。',
+'prefs-help-email-enotif' => 'このアドレスはあなたが有効にした各種メール通知の送信先としても利用されます。',
+'prefs-help-realname' => '* 本名 (任意): 本名を入力すると、ページ・クレジットに利用者名(アカウント名)の代わりに本名が表示されます。',
+'loginerror' => 'ログイン失敗',
+'prefs-help-email' => '* メールアドレス (任意): メールアドレスを入力すると、他のユーザーがあなたの利用者ページまたは会話ページから、あなたの身元を知ることなく、あなたに連絡が取れるようになります。',
+'nocookiesnew' => 'ユーザーのアカウントは作成されましたが、ログインしていません。{{SITENAME}}ではログインにクッキーを使います。あなたはクッキーを無効な設定にしているようです。クッキーを有効にしてから作成したユーザー名とパスワードでログインしてください。',
+'nocookieslogin' => '{{SITENAME}}ではログインにクッキーを使います。あなたはクッキーを無効な設定にしているようです。クッキーを有効にして、もう一度試してください。',
+'noname' => 'ユーザ名を正しく指定していません。',
+'loginsuccesstitle' => 'ログイン成功',
+'loginsuccess' => '{{SITENAME}} に "$1" としてログインしました。',
+'nosuchuser' => '"$1" というユーザーは見当たりません。綴りが正しいことを再度確認するか、下記のフォームを使ってアカウントを作成してください。',
+'nosuchusershort' => '"$1" というユーザーは見当たりません。綴りが正しいことを再度確認してください。',
+'wrongpassword' => 'パスワードが間違っています。再度入力してください。',
+'mailmypassword' => '新しいパスワードをメールで送る',
+'passwordremindertitle' => 'Password reminder from {{SITENAME}}',
+'passwordremindertext' => 'どなたか($1 のIPアドレスの使用者)が{{SITENAME}}のログイン用パスワードの再発行を依頼しました。
+
+ユーザー "$2" のパスワードを "$3" に変更しました。
+ログインして別のパスワードに変更してください。',
+'noemail' => 'ユーザー "$1" のメールアドレスは登録されていません。',
+'passwordsent' => '新しいパスワードを "$1" さんの登録済みメールアドレスに送信しました。メールを受け取ったら、再度ログインしてください。',
+'eauthentsent' => '指定されたメールアドレスにアドレス確認のためのメールを送信しました。このアカウントが本当にあなたのものであるか確認するため、あなたがメールの内容に従わない限り、その他のメールはこのアカウント宛には送信されません。',
+# 'loginend' => '',
+'mailerror' => 'メールの送信中にエラーが発生しました: $1',
+'acct_creation_throttle_hit' => 'あなたは既に $1 アカウントを作成しています。これ以上作成できません。',
+'emailauthenticated' => 'あなたのメールアドレスは $1 に認証されています。',
+'emailnotauthenticated' => 'あなたのメールアドレスは<strong>認証されていません</strong>。認証されるまで以下のいかなるメールも送られません。',
+'noemailprefs' => '<strong>メールアドレスが登録されていません</strong>。以下の機能は無効です。',
+'emailconfirmlink' => '電子メールアドレスを確認する',
+'invalidemailaddress' => '入力されたメールアドレスが正しい形式に従っていないため、受け付けられません。正しい形式で入力し直すか、メールアドレス欄を空にしてください。',
+
+# Edit page toolbar
+'bold_sample' => '強い強調(太字)',
+'bold_tip' => '強い強調(太字)',
+'italic_sample' => '弱い強調(斜体)',
+'italic_tip' => '弱い強調(斜体)',
+'link_sample' => '項目名',
+'link_tip' => '内部リンク',
+'extlink_sample' => 'http://www.example.com リンクのタイトル',
+'extlink_tip' => '外部リンク(http:// を忘れずにつけてください)',
+'headline_sample' => '見出し',
+'headline_tip' => '標準の見出し',
+'math_sample' => '\\\\int f(x)dx',
+'math_tip' => '数式 (LaTeX)',
+'nowiki_sample' => 'そのまま表示させたい文字を入力',
+'nowiki_tip' => '入力文字をそのまま表示',
+'image_sample' => 'Example.jpg',
+'image_tip' => '埋め込み画像([[画像:~]]に直してください)',
+'media_sample' => 'Example.mp3',
+'media_tip' => 'メディアファイル(音声)へのリンク',
+'sig_tip' => '時刻つきの署名',
+'hr_tip' => '水平線(利用は控えめに)',
+# 'infobox' => '',
+# alert box shown in browsers where text selection does not work, test e.g. with mozilla or konqueror
+# 'infobox_alert' => '',
+
+# Edit pages
+#
+'summary' => '編集内容の要約',
+'subject' => '題名・見出し',
+'minoredit' => 'これは細部の編集です',
+'watchthis' => 'ウォッチリストに追加',
+'savearticle' => '保存する',
+'preview' => 'プレビュー',
+'showpreview' => 'プレビューを実行',
+'showdiff' => '差分を表示',
+'blockedtitle' => '投稿ブロック',
+'blockedtext' => 'ご使用のユーザー名またはIPアドレスは $1 によって投稿をブロックされています。その理由は次の通りです。
+:$2
+
+$1 または他の[[Project:管理者|管理者]]にこの件についてメールで問い合わせることができます。ただし、[[Special:Preferences|オプション]]に正しい電子メールアドレスが登録されていない場合、「このユーザーにメールを送信」機能が使えないことに注意してください。あなたのIPアドレスは「$3」です。問い合わせを行う際には、このIPアドレスを必ず書いてください。',
+
+
+'whitelistedittitle' => '編集にはログインが必要',
+'whitelistedittext' => 'このページを編集するには[[Special:Userlogin|ログイン]]する必要があります。',
+'whitelistreadtitle' => '閲覧にはログインが必要',
+'whitelistreadtext' => 'このページを閲覧するには[[Special:Userlogin|ログイン]]する必要があります。',
+'whitelistacctitle' => 'アカウントの作成は許可されていません',
+'whitelistacctext' => '{{SITENAME}}のアカウントを作成するには、適切な権限を持ったユーザーで[[Special:Userlogin|ログイン]]する必要があります。',
+'loginreqtitle' => 'ログインが必要',
+# 'loginreqtext' => '',
+'accmailtitle' => 'パスワードを送信しました',
+'accmailtext' => '"$1" のパスワードを $2 に送信しました。',
+'newarticle' => '(新規)',
+'newarticletext' => 'ページを新規に作成するには新しい内容を書き込んでください。',
+'talkpagetext' => '<!-- MediaWiki:talkpagetext -->',
+'anontalkpagetext' => "----
+''これはアカウントをまだ作成していないか、あるいは使っていない匿名ユーザーのための会話ページです。{{SITENAME}}では匿名ユーザーの識別は利用者名の代わりに[[IPアドレス]]を用います。IPアドレスは何人かで共有されることがあります。もしも、あなたが匿名ユーザーで無関係なコメントがここに寄せられる場合は、[[Special:Userlogin|アカウントを作成するかログインして]]他の匿名ユーザーと間違えられないようにしてくださるようお願いします。",
+'noarticletext' => '({{SITENAME}}には現在この名前の項目はありません)',
+'clearyourcache' => "'''注意:''' 保存した後、ブラウザのキャッシュをクリアする必要があります。'''Mozilla / Firefox / Safari:''' [Shift] を押しながら [再読み込み] をクリック、または [Shift]-[Ctrl]-[R] (Macでは [Cmd]-[Shift]-[R]); '''IE:''' [Ctrl] を押しながら [更新] をクリック、または [Ctrl]-[F5]; '''Konqueror:''' [再読み込み] をクリック、または [F5]; '''Opera:''' 「ツール」→「設定」からキャッシュをクリア。",
+'usercssjsyoucanpreview' => '<strong>Tip:</strong> 「プレビューを実行」ボタンを使うと保存前に新しいスタイルシート・スクリプトをテストできます。',
+'usercsspreview' => "'''あなたはユーザスタイルシートをプレビューしています。まだ保存されていないので注意してください。'''",
+'userjspreview' => "'''あなたはユーザスクリプトをテスト・プレビューしています。まだ保存されていないので注意してください。'''",
+'updated' => '(更新)',
+'note' => '<strong>注釈:</strong> ',
+'previewnote' => 'これはプレビューです。まだ保存されていません!',
+'previewconflict' => 'このプレビューは、上の文章編集エリアの文章を保存した場合にどう見えるようになるかを示すものです。',
+'editing' => '$1 を編集中',
+'editingsection' => '$1 を編集中 (セクション)',
+'editingcomment' => '$1 を編集中 (新規コメント)',
+'editconflict' => '編集競合: $1',
+'explainconflict' => 'あなたがこのページを編集し始めた後に、他の誰かがこのページを変更しました。上側のテキストエリアは現在の最新の状態です。あなたの編集していた文章は下側のテキストエリアに示されています。編集していた文章を、上側のテキストエリアの文章に組み込んでください。<strong>上側のテキストエリアの内容だけ</strong>が、「{{int:Savearticle}}」をクリックした時に実際に保存されます。',
+'yourtext' => 'あなたの文章',
+'storedversion' => '保存された版',
+'nonunicodebrowser' => '<strong>警告: あなたの使用しているブラウザはUnicode互換ではありません。項目を編集する前にブラウザを変更してください。</strong>',
+'editingold' => '<strong>警告: あなたはこのページの古い版を編集しています。もしこの文章を保存すると、この版以降に追加された全ての変更が無効になってしまいます。</strong>',
+'yourdiff' => 'あなたの更新内容',
+'copyrightwarning' => "'''■投稿する前に以下を確認してください■'''
+* {{SITENAME}}に投稿された文書は、すべて$2(詳細は$1を参照)によって公開されることに同意してください。
+* あなたの文章が他人によって自由に編集、配布されることを望まない場合は、投稿を控えてください。
+* あなたの投稿する文章はあなた自身によって書かれたものであるか、パブリック・ドメインかそれに類する自由なリソースからの複製であることを約束してください。'''あなたが著作権を保持していない作品を許諾なしに投稿してはいけません!'''",
+'copyrightwarning2' => "'''■投稿する前に以下を確認してください■'''
+* あなたの文章が他人によって自由に編集、配布されることを望まない場合は、投稿を控えてください。
+* あなたの投稿する文章はあなた自身によって書かれたものであるか、パブリック・ドメインかそれに類する自由なリソースからの複製であることを約束してください(詳細は$1を参照)。'''あなたが著作権を保持していない作品を許諾なしに投稿してはいけません!'''",
+'longpagewarning' => "'''注意:''' このページのサイズは $1 キロバイトです。古いブラウザの一部に 32 キロバイト以上のページを編集すると問題が起きるものがあります。ページを節に分けることを検討してください。",
+'readonlywarning' => '<strong>警告: データベースがメンテナンスのためにロックされたため、今は編集結果を正しく保存できません。文章をカットアンドペーストしてローカルファイルとして保存し、後ほど保存をやり直してください。</strong>',
+'protectedpagewarning' => "'''警告:''' このページは保護されています。管理者しか編集できません。詳しくは[[Project:保護の方針|保護の方針]]を参照してください。",
+'templatesused' => 'このページで使われているテンプレート:',
+
+# History pages
+#
+'revhistory' => '改訂履歴',
+'nohistory' => 'このページには変更履歴がありません。',
+'revnotfound' => '要求された版が見つかりません。',
+'revnotfoundtext' => '要求されたこのページの旧版は見つかりませんでした。このページにアクセスしたURLをもう一度確認してください。
+
+The old revision of the page you asked for could not be found.
+Please check the URL you used to access this page.',
+'loadhist' => '変更履歴の読み込み中',
+'currentrev' => '最新版',
+'revisionasof' => '$1の版',
+'revisionasofwithlink' => '$1 の版; $2<br />$3 | $4',
+'previousrevision' => '←前の版',
+'nextrevision' => '次の版→',
+'currentrevisionlink' => '最新版を表示',
+'cur' => '最新版',
+'next' => '次の版',
+'last' => '前の版',
+'orig' => '最古版',
+'histlegend' => '凡例:(最新版)= 最新版との比較、(前の版)= 直前の版との比較、M = 細部の編集',
+'history_copyright' => '-',
+'deletedrev' => '[deleted]',
+'histfirst' => '最古',
+'histlast' => '最新',
+
+# Diffs
+#
+'difference' => '(版間での差分)',
+'loadingrev' => '差分をとるために古い版を読み込んでいます',
+'lineno' => '$1 行',
+'editcurrent' => 'このページの最新版を編集',
+'selectnewerversionfordiff' => '比較する新しい版を選択',
+'selectolderversionfordiff' => '比較する古い版を選択',
+'compareselectedversions' => '選択した版同士を比較',
+
+# Search results
+#
+'searchresults' => '検索結果',
+'searchresulttext' => '{{SITENAME}}の検索に関する詳しい情報は、[[{{ns:Project}}:検索]]をご覧ください。',
+'searchquery' => '問い合わせ: "$1"',
+'badquery' => 'おかしな形式の検索問い合わせ',
+'badquerytext' => '問い合わせを処理できませんでした。おそらく3文字未満の語を検索しようとしたためですが、まだ対応していません。例えば「魚 and and 大きさ」のように、表現を誤記しているのかもしれません。',
+'matchtotals' => '"$1" を検索し、 $2 の項目名及び $3 ページの本文と一致しました。',
+'nogomatch' => '[[$1|検索した名称のページ]]は存在しませんでした。全文検索を試みます。',
+'titlematches' => '項目名と一致',
+'notitlematches' => '項目名とは一致しませんでした',
+'textmatches' => 'ページ内本文と一致',
+'notextmatches' => 'ページ内本文とは一致しませんでした',
+'prevn' => '前 $1',
+'nextn' => '次 $1',
+'viewprevnext' => '($1)($2)($3) を見る',
+'showingresults' => '<b>$2</b> 件目から <b>$1</b> 件を表示しています。',
+'showingresultsnum' => '<b>$2</b> 件目から <b>$3</b> 件を表示しています。',
+'nonefound' => "'''※'''検索がうまくいかないのは、「ある」や「から」のような一般的な語で索引付けがされていないか、複数の検索語を指定している(全ての検索語を含むページだけが結果に示されます)などのためかもしれません。",
+'powersearch' => '検索',
+'powersearchtext' => '検索する名前空間 :<br />
+$1<br />
+$2リダイレクトを含める &nbsp; &nbsp; &nbsp; $3 $9',
+'searchdisabled' => '<p>全文検索はサーバー負荷の都合から、一時的に使用停止しています。元に戻るまでGoogleでの全文検索を利用してください。検索結果は少し古い内容となります。</p>',
+
+'googlesearch' => '<form method="get" action="http://www.google.com/search" id="googlesearch">
+<table>
+<tr><td>
+<a href="http://www.google.com/"><img src="http://www.google.com/logos/Logo_40wht.gif" border="0" alt="Google" /></a>
+</td><td>
+<input type="hidden" name="domains" value="{{SERVER}}" />
+<input type="hidden" name="ie" value="$2" />
+<input type="hidden" name="oe" value="$2" />
+<input type="text" name="q" size="31" maxlength="255" value="$1" />
+<input type="submit" name="btnG" value="$3" /><br />
+<small><input type="radio" name="sitesearch" value="" id="gWWW" style="vertical-align:middle"/><label for="gWWW">WWW</label>
+<input type="radio" name="sitesearch" value="{{SERVER}}" checked="checked" id="gwiki" style="vertical-align:middle"/><label for="gwiki">{{SERVER}}/</label></small>
+</td></tr>
+</table>
+</form>',
+
+'blanknamespace' => '(標準)',
+
+# Preferences page
+#
+'preferences' => 'オプション',
+'prefsnologin' => 'ログインしていません',
+'prefsnologintext' => 'ユーザーオプションを変更するためには、[[Special:Userlogin|ログイン]]する必要があります。',
+'prefslogintext' => 'あなたは "$1" としてログインしています。あなたのユーザー番号は $2 です。
+
+オプションの変更詳細については[[Project:オプションのヘルプ|オプションのヘルプ]]をご覧ください。',
+
+'prefsreset' => 'ユーザー設定は初期化されました。',
+'qbsettings' => 'クイックバー設定',
+'changepassword' => 'パスワード変更',
+'skin' => '外装',
+'math' => '数式の表記方法',
+'dateformat' => '日付の書式',
+'math_failure' => '構文解析失敗',
+'math_unknown_error' => '不明なエラー',
+'math_unknown_function' => '不明な関数',
+'math_lexing_error' => '字句解析エラー',
+'math_syntax_error' => '構文エラー',
+'math_image_error' => 'PNGへの変換に失敗しました。latex, dvips, gs, convertが正しくインストールされているか確認してください。',
+'math_bad_tmpdir' => 'TeX一時ディレクトリを作成または書き込みできません',
+'math_bad_output' => 'TeX出力用ディレクトリを作成または書き込みできません',
+'math_notexvc' => 'texvcプログラムが見つかりません。math/READMEを読んで正しく設定してください。',
+'prefs-personal' => '利用者の情報',
+'prefs-rc' => '最近更新とスタブの表示',
+'prefs-misc' => 'その他の設定',
+'saveprefs' => '設定の保存',
+'resetprefs' => '設定の初期化',
+'oldpassword' => '古いパスワード',
+'newpassword' => '新しいパスワード',
+'retypenew' => '新しいパスワードを再入力してください',
+'textboxsize' => '編集画面',
+'rows' => '縦',
+'columns' => '横',
+'searchresultshead' => '検索結果の表示',
+'resultsperpage' => '1ページあたりの表示件数',
+'contextlines' => '1件あたりの行数',
+'contextchars' => '1行あたりの文字数',
+'stubthreshold' => 'スタブ表示にする閾値',
+'recentchangescount' => '最近更新したページの表示件数',
+'savedprefs' => 'ユーザー設定を保存しました',
+'timezonelegend' => 'タイムゾーン',
+'timezonetext' => 'UTCとあなたの地域の標準時間との差を入力してください(日本国内は9:00)。',
+'localtime' => 'あなたの現在時刻',
+'timezoneoffset' => '時差¹',
+'servertime' => 'サーバの現在時刻',
+'guesstimezone' => '自動設定',
+'emailflag' => '他のユーザーからのメール送付を差し止める',
+'defaultns' => '標準で検索する名前空間:',
+'default' => 'デフォルト',
+'files' => '画像等',
+
+# User levels special page
+#
+
+# switching pan
+# 'groups-lookup-group' => '',
+# 'groups-group-edit' => '',
+# 'editgroup' => '',
+# 'addgroup' => '',
+
+'userrights-lookup-user' => 'ユーザーの所属グループの管理',
+'userrights-user-editname' => 'ユーザー名:',
+'editusergroup' => '編集',
+
+# group editing
+# 'groups-editgroup' => '',
+# 'groups-addgroup' => '',
+# 'groups-editgroup-preamble' => '',
+'groups-editgroup-name' => 'グループ名:',
+# 'groups-editgroup-description' => '',
+# 'savegroup' => '',
+# 'groups-tableheader' => '',
+# 'groups-existing' => '',
+# 'groups-noname' => '',
+# 'groups-already-exists' => '',
+# 'addgrouplogentry' => '',
+# 'changegrouplogentry' => '',
+# 'renamegrouplogentry' => '',
+
+# user groups editing
+#
+'userrights-editusergroup' => 'ユーザーの所属グループ',
+'saveusergroups' => 'ユーザーの所属グループを保存',
+'userrights-groupsmember' => '所属グループ:',
+'userrights-groupsavailable' => '有効なグループ:',
+'userrights-groupshelp' => 'このユーザーから削除したい、またはこのユーザーに追加したいグループを選択してください。選択されていないグループは変更されません。選択を解除するには [CTRL]+[左クリック] です。',
+# 'userrights-logcomment' => '',
+
+# Default group names and descriptions
+#
+# 'group-anon-name' => '',
+# 'group-anon-desc' => '',
+# 'group-loggedin-name' => '',
+# 'group-loggedin-desc' => '',
+# 'group-admin-name' => '',
+# 'group-admin-desc' => '',
+# 'group-bureaucrat-name' => '',
+# 'group-bureaucrat-desc' => '',
+# 'group-steward-name' => '',
+# 'group-steward-desc' => '',
+
+
+# Recent changes
+#
+'changes' => '更新',
+'recentchanges' => '最近更新したページ',
+'recentchanges-url' => 'Special:Recentchanges',
+'recentchangestext' => '最近付け加えられた変更はこのページで確認できます。',
+'rcloaderr' => '最近の更新情報をダウンロード中',
+'rcnote' => '以下は最近 <strong>$2</strong> 日間に編集された <strong>$1</strong> ページです。(<strong>N</strong>=新規項目、<strong>M</strong>=細部の編集、日時はオプションで未設定ならUTC)',
+'rcnotefrom' => '以下は <b>$2</b> までの更新です。(最大 <b>$1</b> 件)',
+'rclistfrom' => '$1以後現在までの更新を表示',
+'showhideminor' => '細部の編集を$1 | ボットによる編集を$2 | ログインユーザによる編集を$3 | パトロールされた編集を$4',
+'rclinks' => '最近 $2 日間の $1 件分を表示する<br />$3',
+'rchide' => 'in $4 form; $1 minor edits; $2 secondary namespaces; $3 multiple edits.',
+'rcliu' => '; $1 edits from logged in users',
+'diff' => '差分',
+'hist' => '履歴',
+'hide' => '隠す',
+'show' => '表示',
+'tableform' => '表',
+'listform' => '一覧',
+'nchanges' => '$1件の変更',
+'minoreditletter' => 'M',
+'newpageletter' => 'N',
+'sectionlink' => '→',
+'number_of_watching_users_RCview' => '[$1]',
+'number_of_watching_users_pageview' => '[$1人がウォッチしています]',
+
+# Upload
+#
+'upload' => 'アップロード',
+'uploadbtn' => 'アップロード',
+'uploadlink' => '画像のアップロード',
+'reupload' => '再アップロード',
+'reuploaddesc' => 'アップロードのフォームへ戻る',
+'uploadnologin' => 'ログインしていません',
+'uploadnologintext' => 'ファイルをアップロードするには[[Special:Userlogin|ログイン]]する必要があります。',
+'upload_directory_read_only' => 'アップロード先のディレクトリ ($1) にウェブサーバが書き込めません。',
+'uploaderror' => 'アップロード エラー',
+'uploadtext' => "ファイルを新しくアップロードする場合には、以下のフォームを利用してください。
+* 過去にアップロードされた画像は[[Special:Imagelist|{{int:Imagelist}}]]で閲覧したり探したりできます。
+* アップロードや削除は[[Special:Log|ログのページ]]に記録されます。
+* 「{{int:Uploadbtn}}」ボタンを押すと、アップロードが完了します。
+ページに画像を挿入するには '''<nowiki>[[{{ns:6}}:File.jpg]]</nowiki>''' や '''<nowiki>[[{{ns:6}}:File.png|thumb|代替テキスト]]</nowiki>''' といった書式を使います。画像ページではなくファイルに直接リンクするには '''<nowiki>[[{{ns:-2}}:File.ogg]]</nowiki>''' とします。",
+
+
+
+'uploadlog' => 'アップロードログ',
+'uploadlogpage' => 'アップロードログ',
+'uploadlogpagetext' => '以下は最近のファイルのアップロードのログです。',
+'filename' => 'ファイル名',
+'filedesc' => 'ファイルの概要',
+'filestatus' => '著作権情報',
+'filesource' => 'ファイルの出典',
+'copyrightpage' => '{{ns:Project}}:Copyrights',
+'copyrightpagename' => '{{SITENAME}}の著作権',
+'uploadedfiles' => 'アップロードされたファイル',
+'ignorewarning' => '警告を無視し、保存してしまう',
+'minlength' => 'ファイル名は3文字以上である必要があります。',
+'illegalfilename' => 'ファイル名 "$1" にページ・タイトルとして使えない文字が含まれています。ファイル名を変更してからもう一度アップロードしてください。',
+'badfilename' => 'ファイル名は "$1" へ変更されました。',
+'badfiletype' => '".$1" は推奨されているファイルフォーマットではありません。',
+'largefile' => 'ファイルサイズは $1 バイト以下に抑えることが推奨されています。このファイルは $2 バイトです。',
+'emptyfile' => 'あなたがアップロードしようとしているファイルは内容が空であるか、もしくはファイル名の指定が間違っています。もう一度、ファイル名が正しいか、あるいはアップロードしようとしたファイルであるかどうかを確認してください。',
+'fileexists' => 'この名前のファイルは既に存在しています。$1と置き換えるかどうかお確かめください。',
+'successfulupload' => 'アップロード成功',
+'fileuploaded' => 'ファイル "$1" は無事にアップロードされました。
+
+画像詳細ページ $2 に行き、ファイルについての情報―出典、製作者や時期、その他知っている情報を書き込んでください。
+
+この画像をページに貼り付ける際にはページ内に <tt><nowiki>[[</nowiki>{{ns:Image}}:$1|thumb|画像の説明]]</tt> を挿入してください。',
+'uploadwarning' => 'アップロード 警告',
+'savefile' => 'ファイルを保存',
+'uploadedimage' => '"$1" をアップロードしました。',
+'uploaddisabled' => '申し訳ありませんが、アップロードは現在使用できません。',
+'uploadscripted' => 'このファイルはウェブブラウザが誤って解釈してしまうおそれのあるHTMLまたはスクリプトコードを含んでいます。',
+'uploadcorrupt' => '指定したファイルは壊れているか拡張子が正しくありません。ファイルを確認の上再度アップロードをしてください。',
+'uploadvirus' => 'このファイルにはウイルスが含まれています!! &nbsp;詳細: $1',
+'sourcefilename' => 'ファイル名',
+'destfilename' => '掲載するファイル名',
+
+# Image list
+#
+'imagelist' => '画像リスト',
+'imagelisttext' => '$1 枚の画像を $2 に表示しています',
+'getimagelist' => '画像リストを取得',
+'ilsubmit' => '検索',
+'showlast' => '$2に $1 枚の画像を表示',
+'byname' => '名前順',
+'bydate' => '日付順',
+'bysize' => 'サイズ順',
+'imgdelete' => '削除',
+'imgdesc' => '詳細',
+'imglegend' => '凡例: (詳細)= 画像の詳細を表示/編集',
+'imghistory' => '画像の履歴',
+'revertimg' => '差戻',
+'deleteimg' => '削除',
+'deleteimgcompletely' => '全版削除',
+'imghistlegend' => '凡例:(最新)= 最新版の画像、(削除)= この版の画像を削除、(差戻)= この版の画像に差し戻す<br />
+<b>アップロードされた画像を見るには日付をクリックします。</b>',
+'imagelinks' => 'リンク',
+'linkstoimage' => 'この画像にリンクしているページの一覧:',
+'nolinkstoimage' => 'この画像にリンクしているページはありません。',
+'sharedupload' => 'このファイルは共有されており、他のプロジェクトで使用されている可能性があります。',
+'shareduploadwiki' => '詳しい情報は$1を参照してください。',
+'shareddescriptionfollows' => '-',
+'noimage' => 'このファイル名の画像はありません。$1。',
+'uploadnewversion' => '[$1 このファイルの新しいバージョンをアップロードする]',
+
+# Statistics
+#
+'statistics' => 'アクセス統計',
+'sitestats' => 'サイト全体の統計',
+'userstats' => 'ユーザー登録統計',
+'sitestatstext' => "データベース内には'''$1'''ページのデータがあります。この数字には「ノートページ」や「{{SITENAME}}関連のページ」、「書きかけのページ」、「リダイレクト」など、記事とはみなせないページが含まれています。これらを除いた、記事とみなされるページ数は約'''$2'''ページになります。
+
+ページの総閲覧回数は'''$3'''回です。また、'''$4'''回の編集が行われました。平均すると、1ページあたり'''$5'''回の編集が行われ、1編集あたり'''$6'''回閲覧されています。",
+
+'userstatstext' => "登録済みの利用者は'''$1'''人で、内'''$2'''人 ('''$4%''') が管理者権限を持っています。($3を参照)",
+
+# Maintenance Page
+#
+'maintenance' => 'メンテナンスページ',
+'maintnancepagetext' => 'このページには毎日のメンテナンスに便利なツールがあります。いくつかの機能はデータベースに負荷を与えるので、修正の度に再読み込みをしないでください。',
+'maintenancebacklink' => 'メンテナンスページに戻る',
+'disambiguations' => '曖昧さ回避ページ',
+'disambiguationspage' => 'Template:Disambig',
+'disambiguationstext' => '以下のページは<b>曖昧さ回避ページ</b>へリンクしています。これらのページはより適した主題のページへリンクされるべきです。<br />
+$1 にリンクしているページは曖昧さ回避ページと見なされます。',
+'doubleredirects' => '二重リダイレクト',
+'doubleredirectstext' => '以下はリダイレクトにリンクしているリダイレクトの一覧です。最も左のリダイレクトは二番目のリダイレクトが指している、恐らく「真に」リダイレクトしたいページを指すよう、変更されるべきです。',
+'brokenredirects' => '迷子のリダイレクト',
+'brokenredirectstext' => '以下は存在しないページにリンクしているリダイレクトです。',
+'selflinks' => '自己リンクのあるページ',
+'selflinkstext' => '以下のページは本来あるべきでない、自分自身へのリンクを含んでいます。',
+'mispeelings' => 'スペルミスのあるページ',
+'mispeelingstext' => 'The following pages contain a common misspelling, which are listed on $1. The correct spelling might be given (like this).',
+'mispeelingspage' => 'List of common misspellings',
+'missinglanguagelinks' => '言語間リンクのないページ',
+'missinglanguagelinksbutton' => '次の言語への言語間リンクのないページを検索',
+'missinglanguagelinkstext' => 'これらのページは $1 版へリンクしていません。リダイレクトとサブページは表示されません。',
+
+
+# Miscellaneous special pages
+#
+'orphans' => '孤立しているページ',
+'geo' => 'GEO coordinates',
+'validate' => 'ページの評価',
+'lonelypages' => '孤立しているページ',
+'uncategorizedpages' => 'カテゴリ未導入のページ',
+'uncategorizedcategories' => '上位カテゴリのないカテゴリ',
+'unusedcategories' => '未使用のカテゴリ',
+'unusedimages' => '使われていない画像',
+'popularpages' => '人気のページ',
+'nviews' => '$1 回表示',
+'wantedpages' => '投稿が望まれているページ',
+'mostlinked' => '最もリンクされているページ',
+'nlinks' => '$1 個のリンク',
+'allpages' => '全ページ',
+'randompage' => 'おまかせ表示',
+'randompage-url' => 'Special:Randompage',
+'shortpages' => '短いページ',
+'longpages' => '長いページ',
+'deadendpages' => '有効なページへのリンクがないページ',
+'listusers' => '登録ユーザーの一覧',
+'specialpages' => '特別ページ',
+'spheading' => '特別ページ',
+'restrictedpheading' => '制限された特別ページ',
+'protectpage' => 'ページの保護',
+'recentchangeslinked' => 'リンク先の更新',
+'rclsub' => '("$1" からリンクされているページ)',
+'debug' => 'デバッグ',
+'newpages' => '新しいページ',
+'ancientpages' => '更新されていないページ',
+'intl' => '言語間リンク',
+'move' => '移動',
+'movethispage' => 'このページを移動',
+'unusedimagestext' => '<p>他のウェブサイトがURLを直接用いて画像にリンクしている場合もあります。以下の画像一覧には、そのような形で利用されている画像が含まれている可能性があります。</p>',
+'unusedcategoriestext' => '以下のカテゴリページはどの項目・カテゴリからも使われていません。',
+
+'booksources' => '文献資料',
+'categoriespagetext' => '{{SITENAME}}には以下のカテゴリが存在します。',
+'data' => 'Data',
+'userrights' => 'ユーザー権限の管理',
+# 'groups' => '',
+
+'booksourcetext' => '以下のリストは、新本、古本などを販売している外部サイトへのリンクです。あなたがお探しの本について、更に詳しい情報が提供されている場合もあります。',
+'isbn' => 'ISBN',
+# 'rfcurl' => '',
+# 'pubmedurl' => '',
+'alphaindexline' => '$1―$2',
+'version' => 'バージョン情報',
+'log' => 'ログ',
+'alllogstext' => 'アップロード、削除、保護、投稿ブロック、権限変更のログがまとめて表示されています。ログの種類、実行した利用者、影響を受けたページ(利用者)による絞り込みができます。',
+
+# Special:Allpages
+'nextpage' => '次のページ($1)',
+'allpagesfrom' => '表示開始ページ:',
+'allarticles' => '全ページ',
+'allnonarticles' => '項目以外の全ページ',
+'allinnamespace' => '全ページ ($1 名前空間)',
+'allnotinnamespace' => '全ページ ($1 名前空間を除く)',
+'allpagesprev' => '前へ',
+'allpagesnext' => '次へ',
+'allpagessubmit' => '表示',
+
+# E this user
+#
+'mailnologin' => '送信先のアドレスがありません。',
+'mailnologintext' => '他のユーザーに宛てにメールを送信するためには、[[Special:Userlogin|ログイン]]し、あなたのメールアドレスを[[Special:Preference|ユーザーオプション]]に設定する必要があります。',
+'emailuser' => 'このユーザーにメールを送信',
+'emailpage' => 'メール送信ページ',
+'emailpagetext' => 'もしメールを送る先のユーザーが、有効なメールアドレスを
+ユーザーオプションに登録してあれば、下のフォームを通じてメールを送ることができます。
+あなたが登録したご自分のメールアドレスはFrom:の欄に自動的に組み込まれ、受け取った相手が
+返事を出せるようになっています。',
+'usermailererror' => 'メール送信時に以下のエラーが発生しました:',
+'defemailsubject' => '{{SITENAME}} (ja) e-mail',
+'noemailtitle' => '送り先のメールアドレスがありません。',
+'noemailtext' => 'このユーザーは有効なメールアドレスを登録していないか、メールを受け取りたくないというオプションを選択しています。',
+'emailfrom' => 'あなたのアドレス',
+'emailto' => 'あて先',
+'emailsubject' => '題名',
+'emailmessage' => '本文',
+'emailsend' => 'メール送信',
+'emailsent' => 'メールを送りました',
+'emailsenttext' => 'メールは無事送信されました。',
+
+# Watchlist
+#
+'watchlist' => 'ウォッチリスト',
+'watchlistsub' => '(ユーザー名 "$1")',
+'nowatchlist' => 'あなたのウォッチリストは空です。',
+'watchnologin' => 'ログインしていません',
+'watchnologintext' => 'ウォッチリストを変更するためには、[[Special:Userlogin|ログイン]]している必要があります。',
+'addedwatch' => 'ウォッチリストに追加しました',
+'addedwatchtext' => "ページ \"$1\" をあなたの[[Special:Watchlist|ウォッチリスト]]に追加しました。
+
+このページと、付属のノートのページに変更があった際にはそれをウォッチリストで知ることができます。また、[[Special:Recentchanges|最近更新したページ]]ではウォッチリストに含まれているページは'''ボールド体'''で表示され、見つけやすくなります。
+
+ウォッチリストから特定のページを削除したい場合には、サイドバーかタブにある \"ウォッチリストから削除\" のリンクをクリックしてください。",
+
+'removedwatch' => 'ウォッチリストから削除しました',
+'removedwatchtext' => 'ページ "$1" をウォッチリストから削除しました。',
+'watch' => 'ウォッチリストに追加',
+'watchthispage' => 'ウォッチリストに追加',
+'unwatch' => 'ウォッチリストから削除',
+'unwatchthispage' => 'ウォッチリストから削除',
+'notanarticle' => 'これは記事ではありません。',
+'watchnochange' => 'その期間内にウォッチリストにあるページはどれも編集されていません。',
+'watchdetails' => '* ウォッチリストに入っているページ数(ノート除く): $1
+* [[Special:Watchlist/edit|ウォッチリストの一覧・編集]]',
+'wlheader-enotif' => '* メール通知が有効になっています',
+'wlheader-showupdated' => "* あなたが最後に訪問したあとに変更されたページは'''ボールド体'''で表示されます",
+'watchmethod-recent' => 'ウォッチリストの中から最近編集されたものを抽出',
+'watchmethod-list' => '最近編集された中からウォッチしているページを抽出',
+'removechecked' => 'チェックした項目をウォッチリストから削除',
+'watchlistcontains' => 'あなたのウォッチリストには $1 ページ登録されています。',
+'watcheditlist' => 'ウォッチリストに登録しているページを文字コード順に表示しています。
+
+チェックボックスにチェックし、「ウォッチリストから削除」のボタンをクリックするとウォッチリストから削除されます。
+
+※ウォッチリストからページを削除すると、付随するノートページも削除されます。',
+'removingchecked' => '要求された項目をウォッチリストから削除しています:',
+'couldntremove' => '"$1" をウォッチリストから削除できません。',
+'iteminvalidname' => '"$1" をウォッチリストから削除できません。ページ名が不正です。',
+'wlnote' => '以下は最近 <strong>$2</strong> 時間に編集された <strong>$1</strong> ページです。',
+'wlshowlast' => '最近の [$1時間] [$2日間] [$3] のものを表示する',
+'wlsaved' => '現在、バックアップされたウォッチリストのみの表示となっています。',
+'wlhideshowown' => '自分の編集を$1',
+'wlshow' => '表示',
+'wlhide' => '隠す',
+
+'enotif_mailer' => '{{SITENAME}} Notification Mailer',
+'enotif_reset' => 'すべてのページを訪問済みにする',
+'enotif_newpagetext' => '(新規ページ)',
+'changed' => '変更',
+'created' => '作成',
+'enotif_subject' => '{{SITENAME}} のページ "$PAGETITLE" が $PAGEEDITOR によって$CHANGEDORCREATEDされました',
+'enotif_lastvisited' => '
+あなたが最後に閲覧してからの差分を見るには以下のURLにアクセスしてください:
+$1',
+'enotif_body' => 'Dear $WATCHINGUSERNAME,
+
+{{SITENAME}}のページ $PAGETITLE が $PAGEEDITDATE に
+$PAGEEDITOR によって$CHANGEDORCREATEDされました。
+現在の版を見るには次のURLにアクセスしてください:
+$PAGETITLE_URL
+$NEWPAGE
+
+編集内容の要約: $PAGESUMMARY ($PAGEMINOREDIT)
+
+投稿者:
+メール: $PAGEEDITOR_EMAIL
+ウィキ: $PAGEEDITOR_WIKI
+
+あなたがこのページを訪れない限り、これ以上の通知は送信されません。
+ウォッチリストからすべての通知フラグをリセットすることもできます。
+
+                         {{SITENAME}} 通知システム
+
+--
+ウォッチリストの設定を変更する:
+{{SERVER}}{{localurl:Special:Watchlist/edit}}
+
+助けが必要ですか:
+{{SERVER}}{{localurl:Help:Contents}}',
+
+
+
+
+
+
+
+
+
+# Delete/protect/revert
+#
+'deletepage' => 'ページ削除',
+'confirm' => '確認',
+'excontent' => "内容: '$1'",
+'excontentauthor' => "内容: '$1' (投稿者 $2 のみ)",
+'exbeforeblank' => "白紙化前の内容: '$1'",
+'exblank' => '白紙ページ',
+'confirmdelete' => '削除の確認',
+'deletesub' => '("$1" を削除)',
+'historywarning' => '警告: 削除しようとしているページには履歴があります:',
+'confirmdeletetext' => '指定されたページまたは画像は、その更新履歴と共にデータベースから永久に削除されようとしています。あなたが削除を望んでおり、それがもたらす帰結を理解しており、かつあなたのしようとしていることが[[Project:Policy|基本方針]]に即したものであることを確認してください。',
+'actioncomplete' => '完了しました',
+'deletedtext' => '"$1" は削除されました。最近の削除に関しては $2 を参照してください。',
+'deletedarticle' => '"$1" を削除しました。',
+'dellogpage' => '削除記録',
+'dellogpagetext' => '以下は最近の削除と復帰の記録です。',
+'deletionlog' => '削除記録',
+'reverted' => '以前のバージョンへの差し戻し (Reverted to earlier revision)',
+'deletecomment' => '削除の理由',
+'imagereverted' => '以前のバージョンへの差し戻しに成功しました。',
+'rollback' => 'Roll back edits',
+'rollback_short' => 'Rollback',
+'rollbacklink' => 'rollback',
+'rollbackfailed' => 'Rollback に失敗しました。',
+'cantrollback' => '投稿者がただ一人であるため、編集を差し戻せません。',
+'alreadyrolled' => 'ページ [[$1]] の [[User:$2|$2]] ([[User talk:$2|会話]] | [[Special:Contributions/$2|履歴]]) による編集の rollback に失敗しました。誰か他のユーザーが編集を行ったか rollback されたのかもしれません。
+
+このページの最後の編集は [[User:$3|$3]] ([[User talk:$3|会話]] | [[Special:Contributions/$3|履歴]]) によるものです。',
+
+#   only shown if there is an edit comment
+'editcomment' => '編集内容の要約: <i>$1</i>',
+'revertpage' => 'Reverted edit of $2, changed back to last version by $1',
+'sessionfailure' => 'あなたのログイン・セッションに問題が発生しました。この動作はセッションハイジャックを防ぐために取り消されました。ブラウザの「戻る」を押してからページを再読込し、もう一度送信してください。',
+'protectlogpage' => '保護記録',
+'protectlogtext' => '以下はページの保護・保護解除の一覧です。詳細は[[{{ns:Project}}:保護されたページ]]を参照してください。',
+'protectedarticle' => '"$1" を保護しました。',
+'unprotectedarticle' => '"$1" の保護を解除しました。',
+'protectsub' => '("$1" の保護)',
+'confirmprotecttext' => '本当にこのページを保護しますか?',
+'confirmprotect' => '保護の確認',
+'protectmoveonly' => '移動のみ差し止める',
+'protectcomment' => '保護の理由',
+'unprotectsub' => '("$1" の保護解除)',
+'confirmunprotecttext' => '本当にこのページの保護を解除しますか?',
+'confirmunprotect' => '保護解除の確認',
+'unprotectcomment' => '保護解除の理由',
+
+# Undelete
+'undelete' => '削除されたページを参照する',
+'undeletepage' => '削除された編集の参照と復帰',
+'undeletepagetext' => '以下のページは削除されていますが、アーカイブに残っているため、復帰できます。アーカイブは定期的に消去されます。',
+'undeletearticle' => '削除済みページの復帰',
+'undeleterevisions' => '($1 版が保存されています)',
+'undeletehistory' => 'ページの復帰を行うと、履歴にある全ての編集が復帰します。削除後に同じ名前のページが作成されている場合、削除以前の編集は新しい履歴の前に表示され、最新版は置き換わりません。',
+'undeleterevision' => '削除された $1 の版',
+'undeletebtn' => '復帰!',
+'undeletedarticle' => '"$1" を復帰しました。',
+'undeletedrevisions' => '$1 版を復帰',
+'undeletedtext' => '[[:$1|$1]]を無事復帰しました。最近の削除と復帰の記録は[[Special:Log/delete]]を参照してください。',
+
+# Namespace form on various pages
+'namespace' => '名前空間:',
+'invert' => '選択した名前空間を隠す',
+
+# Contributions
+#
+'contributions' => 'ユーザーの投稿記録',
+'mycontris' => '自分の投稿記録',
+'contribsub' => 'ユーザー名:$1',
+'nocontribs' => 'ユーザーの投稿記録は見つかりませんでした。',
+# 'ucnote' => '',
+# 'uclinks' => '',
+'uctop' => ' (top)',
+'newbies' => '新規ユーザー',
+'contribs-showhideminor' => '$1 minor edits',
+
+# What links here
+#
+'whatlinkshere' => 'リンク元',
+'notargettitle' => '対象となるページが存在しません',
+'notargettext' => '対象となるページ又はユーザーが指定されていません',
+'linklistsub' => 'リンクのリスト',
+'linkshere' => '指定したページは以下のページからリンクされています',
+'nolinkshere' => '指定されたページにリンクしているページはありません。',
+'isredirect' => 'リダイレクトページ',
+
+# Block/unblock IP
+#
+'blockip' => 'ユーザーのブロック',
+'blockiptext' => '指定されたIPアドレスからの投稿をブロックすることができます。投稿ブロックは荒らしを防ぐためであり、[[Project:Policy|{{SITENAME}}の基本方針]]に従っているべきです。明確な理由を以下に記入してください(例えば、荒らされたページを引用する)。',
+'ipaddress' => 'IPアドレス',
+'ipadressorusername' => 'IPアドレス / ユーザー名',
+'ipbexpiry' => '期間',
+'ipbreason' => '理由',
+'ipbsubmit' => 'このアドレスまたはユーザーを投稿ブロックする',
+'ipbother' => '期間 (その他のとき)',
+'ipboptions' => '2 hours:2 hours,1 day:1 day,3 days:3 days,1 week:1 week,2 weeks:2 weeks,1 month:1 month,3 months:3 months,6 months:6 months,1 year:1 year,無期限:infinite',
+'ipbotheroption' => 'その他',
+'badipaddress' => 'IPアドレスが異常です。',
+'blockipsuccesssub' => 'ブロックに成功しました。',
+'blockipsuccesstext' => 'IPアドレスまたはユーザー "$1" は投稿をブロックされました。<br/>
+[[Special:Ipblocklist|投稿ブロック中のユーザーやIPアドレス]]で確認できます。',
+'unblockip' => 'IPアドレスの投稿ブロックを解除する',
+'unblockiptext' => '以下のフォームでIPアドレスまたはユーザーの投稿ブロックを解除できます。',
+'ipusubmit' => 'このアドレスまたはユーザーの投稿ブロックを解除する',
+'ipusuccess' => 'IPアドレス "$1" の投稿ブロックが解除されました。',
+'ipblocklist' => '投稿ブロック中のユーザーやIPアドレス',
+'blocklistline' => '$1, $2 は $3 をブロック ($4)',
+'infiniteblock' => '無期限',
+'expiringblock' => '$1 に解除',
+'ipblocklistempty' => '投稿ブロック中のユーザーやIPアドレスはありません。',
+'blocklink' => 'block',
+'unblocklink' => 'ブロック解除',
+'contribslink' => '投稿記録',
+'autoblocker' => '投稿ブロックされているユーザー "$1" と同じIPアドレスのため、自動的にブロックされています。ブロックの理由は "$2" です。',
+'blocklogpage' => '投稿ブロック記録',
+'blocklogentry' => '"$1" を $2 ブロックしました',
+'blocklogtext' => 'このページは投稿ブロックと解除の記録です。自動的に投稿ブロックされたIPアドレスは一覧されていません。現時点で有効な投稿ブロックは[[Special:Ipblocklist|投稿ブロック中のユーザーやIPアドレス]]をご覧ください。',
+'unblocklogentry' => '"$1" をブロック解除しました',
+'range_block_disabled' => '広域ブロックは無効に設定されています。',
+'ipb_expiry_invalid' => '不正な期間です。',
+'ip_range_invalid' => '不正なIPアドレス範囲です。',
+'proxyblocker' => 'Proxy blocker',
+'proxyblockreason' => 'Your IP address has been blocked because it is an open proxy. Please contact your Internet service provider or tech support and inform them of this serious security problem.
+
+:あなたの使用しているIPアドレスはオープン・プロクシであるため投稿ブロックされています。あなたのインターネット・サービス・プロバイダ、もしくは技術担当者に連絡を取り、これが深刻なセキュリティ問題であることを伝えてください。',
+'proxyblocksuccess' => 'Done.
+',
+'sorbs' => 'SORBS DNSBL',
+'sorbsreason' => 'あなたのIPアドレスはオープンプロクシであると、[http://www.sorbs.net/ SORBS] DNSBLに掲載されています。',
+'sorbs_create_account_reason' => 'あなたのIPアドレスがオープンプロクシであると、[http://www.sorbs.net/ SORBS] DNSBLに掲載されているため、アカウントを作成できません。',
+
+
+# Developer tools
+#
+'lockdb' => 'データベースのロック',
+'unlockdb' => 'データベースのロック解除',
+'lockdbtext' => 'データベースをロックすると全てのユーザーはページを編集できなくなり、オプションを変更できなくなり、ウォッチリストを編集できなくなるなど、データベースに書き込む全ての作業ができなくなります。本当にデータベースをロックして良いかどうか確認してください。メンテナンスが終了したらロックを解除してください。',
+'unlockdbtext' => 'データベースのロックを解除することでユーザーはページを編集できるようになり、オプションを変更できるようになり、ウォッチリストを編集できるようになりなど、データベースに書き込む全ての作業ができるようになります。本当にデータベースのロックを解除していいかどうか確認してください。',
+'lockconfirm' => '本当にデータベースをロックする',
+'unlockconfirm' => 'ロックを解除する',
+'lockbtn' => 'ロック',
+'unlockbtn' => 'ロック解除',
+'locknoconfirm' => 'チェックボックスにチェックされていません。',
+'lockdbsuccesssub' => 'データベースはロックされました。',
+'unlockdbsuccesssub' => 'データベースのロックは解除されました',
+'lockdbsuccesstext' => 'データベースはロックされました。メンテナンスが終了したら忘れずにロックを解除しましょう。',
+'unlockdbsuccesstext' => 'データベースのロックは解除されました。',
+
+# Make sysop
+'makesysoptitle' => 'ユーザーを管理者にする',
+'makesysoptext' => 'このフォームは通常のユーザーを管理者にするために使用します。管理者にするユーザー名を入力し、このユーザーを管理者にするボタンを押してください。',
+'makesysopname' => 'ユーザー名:',
+'makesysopsubmit' => 'このユーザーを管理者にする',
+'makesysopok' => '<b>ユーザー "$1" を管理者にしました。</b>',
+'makesysopfail' => '<b>ユーザー "$1" を管理者にできませんでした。ユーザー名を正しく入力していたかどうか確認してください。</b>',
+'setbureaucratflag' => '"bureaucrat" フラグをセット',
+'setstewardflag' => 'Stewardフラグをセット',
+'bureaucratlog' => '権限変更記録',
+'rightslogtext' => '以下はユーザーの権限変更の一覧です。',
+'bureaucratlogentry' => '$1 の権限を "$2" から "$3" に変更しました。',
+'rights' => '権限:',
+'set_user_rights' => 'ユーザー権限の設定',
+'user_rights_set' => '<b>ユーザー "$1" の権限が更新されました</b>',
+'set_rights_fail' => '<b>ユーザー "$1" の権限を設定できませんでした。ユーザー名を正しく入力していたかどうか確認してください。</b>',
+'makesysop' => 'ユーザーを管理者にする',
+'already_sysop' => 'ユーザーは既に管理者です。',
+'already_bureaucrat' => 'ユーザーは既にビューロクラットです。',
+'already_steward' => 'ユーザーは既にStewardです。',
+
+# Validation
+'val_yes' => 'はい',
+'val_no' => 'いいえ',
+'val_of' => '$1点 ($2点中)',
+'val_revision' => '版',
+'val_time' => '時刻',
+'val_user_stats_title' => '$1による評価',
+'val_my_stats_title' => 'あなたの評価記録',
+'val_list_header' => '<th>#</th><th>評価基準</th><th>範囲</th><th>操作</th>',
+'val_add' => '追加',
+'val_del' => '削除',
+'val_show_my_ratings' => '自分の評価を表示',
+'val_revision_number' => '版 #$1',
+'val_warning' => "'''絶対に'''コミュニティの'''完全な合意無しに'''ここの記述を'''変更しないでください'''。",
+'val_rev_for' => '$1 を評価中',
+'val_details_th_user' => 'ユーザー $1',
+'val_validation_of' => '"$1" に対する評価',
+'val_revision_of' => '$1 の版',
+'val_revision_changes_ok' => 'あなたの評価が記録されました。',
+'val_rev_stats' => '"$1" に対する評価の一覧</a> <a href="$2">(この版)',
+'val_revision_stats_link' => '詳細',
+'val_iamsure' => 'これで採点する。',
+'val_details_th' => '<sub>ユーザー</sub>\<sup>評価基準</sup>',
+'val_clear_old' => '古い版に対する自分の評価を取り消す',
+'val_merge_old' => '"意見なし" とした箇所について以前の評価を引き継ぐ',
+'val_form_note' => "----
+'''ヒント:''' 「{{int:Val_merge_old}}」にチェックを入れると、このフォームで「意見なし」と選択した評価項目について、以前の版であなたが行った評価とコメントを引き継ぎます。つまり、あなたがこのページに対して、ある評価項目についてのみ評価を変更したい場合は、その評価項目でのみ、新しい評価値を選び、コメントを入力してください。そしてその他の評価項目を「意見なし」のままにしておけば、以前の評価がそのまま引き継がれます。",
+'val_noop' => '意見なし',
+'val_topic_desc_page' => 'Project:評価基準',
+'val_votepage_intro' => 'このテキストを[{{SERVER}}{{localurl:MediaWiki:Val_votepage_intro}} 編集してください]。',
+'val_percent' => '<b>$1%</b><br />($4名による<br />$3の評価のうち$2)',
+'val_percent_single' => '<b>$1%</b><br />(1名による<br />$3の評価のうち$2)',
+'val_total' => '合計',
+'val_version' => '版',
+'val_tab' => '評価',
+'val_this_is_current_version' => 'これは最新版です',
+'val_version_of' => '$1 の版',
+'val_table_header' => '<tr><th>クラス</th>$1<th colspan=4>提案</th>$1<th>コメント</th></tr>',
+'val_stat_link_text' => 'この項目に対する評価の一覧',
+'val_view_version' => 'この版を表示',
+'val_validate_version' => 'この版を評価する',
+'val_user_validations' => 'このユーザーは$1ページで評価をしています。',
+'val_no_anon_validation' => '評価をするには[[Special:Userlogin|ログイン]]する必要があります。',
+'val_validate_article_namespace_only' => "評価は標準名前空間に対してのみ可能です。このページは'''標準名前空間のページではありません'''。",
+'val_validated' => '評価を保存しました。',
+'val_article_lists' => '評価された項目',
+'val_page_validation_statistics' => '$1 に対する評価の一覧',
+
+# Move page
+#
+'movepage' => 'ページの移動',
+'movepagetext' => '下のフォームを利用すると、ページ名を変更し、その履歴も変更先へ移動することができます。古いページは変更先へのリダイレクトページとなります。ページの中身と変更前のページに張られたリンクは変わりません。ですから、二重になったり壊れてしまったリダイレクトをチェックする必要があります。
+
+変更先がすでに存在する場合には、履歴が移動元ページへのリダイレクトただ一つである場合を除いて、移動できません。つまり、間違えてページ名を変更した場合には元に戻せます。
+
+<strong>注意!</strong> よく閲覧されるページや、他の多くのページからリンクされているページを移動すると予期せぬ結果が起こるかもしれません。ページの移動に伴う影響をよく考えてから踏み切るようにしてください。',
+
+
+'movepagetalktext' => '付随するノートのページがある場合には、基本的には、一緒に移動されることになります。
+
+但し、以下の場合については別です。
+*名前空間をまたがる移動の場合
+*移動先に既に履歴のあるノートページが存在する場合
+*下のチェックボックスのチェックマークを消した場合
+
+これらの場合、ノートページを移動する場合には、別に作業する必要があります。',
+
+'movearticle' => '移動するページ',
+'movenologin' => 'ログインしていません',
+'movenologintext' => 'ページを移動するためには、ユーザー登録の上、[[Special:Userlogin|ログイン]]している必要があります。',
+'newtitle' => '新しいページ名',
+'movepagebtn' => 'ページを移動',
+'pagemovedsub' => '無事移動しました。',
+'pagemovedtext' => 'ページ "[[$1]]" は "[[$2]]" に移動しました。',
+'articleexists' => '指定された移動先には既にページが存在するか、名前が不適切です。',
+'talkexists' => 'ページ自身は移動されましたが、付随のノートページは移動先のページが存在したため移動できませんでした。手動で内容を統合してください。',
+'movedto' => '移動先:',
+'movetalk' => 'ノートページが付随する場合には、それも一緒に移動する',
+'talkpagemoved' => '付随のノートのページも移動しました。',
+'talkpagenotmoved' => '付随のノートのページは<strong>移動されませんでした。</strong>',
+'1movedto2' => '[[$1]] を [[$2]] へ移動',
+'1movedto2_redir' => '[[$1]] をこのページあてのリダイレクト [[$2]] へ移動',
+'movelogpage' => '移動記録',
+'movelogpagetext' => '以下は最近のページ移動の記録です。',
+'movereason' => '理由',
+'revertmove' => '差し戻し',
+'delete_and_move' => '削除して移動する',
+'delete_and_move_text' => '== 削除が必要です ==
+移動先 "[[$1]]" は既に存在しています。このページを移動のために削除しますか?',
+
+'delete_and_move_reason' => '移動のための削除',
+'selfmove' => '移動元と移動先のページ名が同じです。自分自身へは移動できません。',
+'immobile_namespace' => '移動先のページ名は特別なページです。その名前空間にページを移動することはできません。',
+
+# Export
+
+'export' => 'ページデータの書き出し',
+'exporttext' => 'ここでは単独のまたは複数のページのテキストと編集履歴をXMLの形で書き出すことができます。書き出されたXML文書はは他のMediaWikiで動いているウィキに取り込んだり、変換したり、個人的な楽しみに使ったりできます。
+
+ページデータを書き出すには下のテキストボックスに書き出したいページのタイトルを一行に一ページずつ記入してください。また編集履歴とともに全ての古い版を含んで書き出すのか、最新版のみを書き出すのか選択してください。
+
+後者のケースではリンクの形で使うこともできます。例: [[メインページ]]の最新版を取得するには[[{{ns:Special}}:Export/メインページ]]を使用します。',
+
+
+'exportcuronly' => 'すべての履歴を含ませずに、最新版のみを書き出す',
+
+# Namespace 8 related
+
+'allmessages' => '表示メッセージ一覧',
+'allmessagesname' => 'メッセージ名',
+'allmessagesdefault' => '既定の文章',
+'allmessagescurrent' => '現在の文章',
+'allmessagestext' => 'これはMediaWiki名前空間にある全てのシステムメッセージの一覧です。',
+'allmessagesnotsupportedUI' => 'このサイトでは、あなたの現在のインターフェイス言語 <b>$1</b> における {{ns:Special}}:Allmessages はサポートされていません。',
+'allmessagesnotsupportedDB' => 'wgUseDatabaseMessages が無効のため、{{ns:Special}}:Allmessages はサポートされません。',
+
+# Thumbnails
+
+'thumbnail-more' => '拡大',
+'missingimage' => '<b>Missing image</b><br /><i>$1</i>
+',
+'filemissing' => '<i>ファイルがありません</i>',
+
+# Special:Import
+'import' => 'ページデータの取り込み',
+'importinterwiki' => 'Transwikiインポート',
+'importtext' => '元となるウィキから {{ns:Special}}:Export を使ってXMLファイルを書き出し、それをここにアップロードしてください。',
+'importfailed' => '取り込みに失敗しました: $1',
+'importnotext' => '内容が空か、テキストがありません。',
+'importsuccess' => '取り込みに成功しました。',
+'importhistoryconflict' => '取り込み時にいくつかの版が競合しました(以前に同じページを取り込んでいませんか)。',
+'importnosources' => 'Transwikiの読み込み元が定義されていないため、履歴の直接アップロードは無効になっています。',
+'importnofile' => 'ファイルがアップロードされませんでした',
+'importuploaderror' => 'ファイルの取り込みに失敗しました。恐らく、許可されている最大ファイルサイズより大きなファイルをアップロードしようとしています。',
+
+# Keyboard access keys for power users
+'accesskey-search' => 'f',
+'accesskey-minoredit' => 'i',
+'accesskey-save' => 's',
+'accesskey-preview' => 'p',
+'accesskey-diff' => 'd',
+'accesskey-compareselectedversions' => 'v',
+
+# tooltip help for some actions, most are in Monobook.js
+'tooltip-search' => 'ウィキ内を検索 [alt-f]',
+'tooltip-minoredit' => 'この編集を細部の変更とマーク [alt-i]',
+'tooltip-save' => '編集を保存します。 [alt-s]',
+'tooltip-preview' => '編集結果を確認します。保存前に是非使用してください。 [alt-p]',
+'tooltip-diff' => 'あなたが編集した版の変更点を表示します。[alt-d]',
+'tooltip-compareselectedversions' => '選択された二つの版の差分を表示します。 [alt-v]',
+'tooltip-watch' => 'このページをウォッチリストへ追加します。 [alt-w]',
+
+# stylesheets
+'Monobook.css' => '/* edit this file to customize the monobook skin for the entire site */
+#bodyContent { font-size:118% }',
+#'Monobook.js' => '/* edit this file to change js things in the monobook skin */',
+
+# Metadata
+'nodublincore' => 'Dublin Core RDF metadata disabled for this server.',
+'nocreativecommons' => 'Creative Commons RDF metadata disabled for this server.',
+'notacceptable' => 'ウィキサーバーはあなたの使用しているクライアントが読める形式で情報を提供できません。',
+
+# Attribution
+
+'anonymous' => '{{SITENAME}}の匿名ユーザー',
+'siteuser' => '{{SITENAME}}のユーザー$1',
+'lastmodifiedby' => '最終更新は $2 による $1 の編集です。',
+'and' => 'および',
+'othercontribs' => '$1の版に基づきます。',
+'others' => 'その他のユーザー',
+'siteusers' => '{{SITENAME}}のユーザー$1',
+'creditspage' => 'ページ・クレジット',
+'nocredits' => 'このページには有効なクレジット情報がありません。',
+
+# Spam protection
+
+'spamprotectiontitle' => 'スパム防御フィルター',
+'spamprotectiontext' => 'あなたが保存しようとしたページはスパム・フィルターによって保存をブロックされました。これは主に外部サイトへのリンクが原因です。',
+'spamprotectionmatch' => '以下はスパム・フィルターによって検出されたテキストです: $1',
+'subcategorycount' => 'このカテゴリには $1 のサブカテゴリがあります。',
+'subcategorycount1' => 'このカテゴリには $1 のサブカテゴリがあります。',
+'categoryarticlecount' => 'このカテゴリには $1 の項目があります。',
+'categoryarticlecount1' => 'このカテゴリには $1 の項目があります。',
+'usenewcategorypage' => '1
+
+Set first character to "0" to disable the new category page layout.',
+'listingcontinuesabbrev' => ' の続き',
+
+# Info page
+'infosubtitle' => 'ページ情報',
+'numedits' => '編集数(項目): $1',
+'numtalkedits' => '編集数(ノート): $1',
+'numwatchers' => 'ウォッチしているユーザー数: $1',
+'numauthors' => '投稿者数(項目): $1',
+'numtalkauthors' => '投稿者数(ノート): $1',
+
+# Math options
+'mw_math_png' => '常にPNG',
+'mw_math_simple' => 'シンプルな数式はHTML、それ以外はPNG',
+'mw_math_html' => 'できる限りHTML、さもなければPNG',
+'mw_math_source' => 'TeXのままにする (テキストブラウザ向け)',
+'mw_math_modern' => '最近のブラウザで推奨',
+'mw_math_mathml' => '可能ならばMathMLを使う (実験中の機能)',
+
+# Patrolling
+'markaspatrolleddiff' => 'パトロール済みにする',
+'markaspatrolledlink' => "<div class='patrollink'>[$1]</div>",
+'markaspatrolledtext' => 'この項目をパトロール済みにする',
+'markedaspatrolled' => 'パトロール済みにしました',
+'markedaspatrolledtext' => '選択された編集をパトロール済みにしました。',
+'rcpatroldisabled' => 'RCパトロールが無効です',
+'rcpatroldisabledtext' => '最近更新されたページのパトロール機能は現在無効になっています。',
+
+# Monobook.js: tooltips and access keys for monobook
+'Monobook.js' => "/* tooltips and access keys */
+ta = new Object();
+ta['pt-userpage'] = new Array('.','自分の利用者ページ'); 
+ta['pt-anonuserpage'] = new Array('.','あなたのIPアドレス用の利用者ページ'); 
+ta['pt-mytalk'] = new Array('n','自分の会話ページ'); 
+ta['pt-anontalk'] = new Array('n','あなたのIPアドレスからなされた編集の会話ページ'); 
+ta['pt-preferences'] = new Array('','オプションの変更'); 
+ta['pt-watchlist'] = new Array('l','変更を監視しているページの一覧'); 
+ta['pt-mycontris'] = new Array('y','自分の投稿記録'); 
+ta['pt-login'] = new Array('o','ログインすることが推奨されますが、しなくても構いません。'); 
+ta['pt-anonlogin'] = new Array('o','ログインすることが推奨されますが、しなくても構いません。'); 
+ta['pt-logout'] = new Array('o','ログアウト'); 
+ta['ca-talk'] = new Array('t','項目のノート'); 
+ta['ca-edit'] = new Array('e','このページを編集できます。投稿の前に「プレビューを実行」ボタンを使ってください。'); 
+ta['ca-addsection'] = new Array('+','このページにコメントを加える'); 
+ta['ca-viewsource'] = new Array('e','このページは保護されています。ページのソースを閲覧できます。'); 
+ta['ca-history'] = new Array('h','このページの過去の版'); 
+ta['ca-protect'] = new Array('=','このページを保護'); 
+ta['ca-delete'] = new Array('d','このページを削除'); 
+ta['ca-undelete'] = new Array('d','削除されたページを復帰する'); 
+ta['ca-move'] = new Array('m','このページを移動'); 
+ta['ca-watch'] = new Array('w','このページをウォッチリストへ追加'); 
+ta['ca-unwatch'] = new Array('w','このページをウォッチリストから外す'); 
+ta['search'] = new Array('f','ウィキ内を検索'); 
+ta['p-logo'] = new Array('','メインページ'); 
+ta['n-mainpage'] = new Array('z','メインページに移動'); 
+ta['n-portal'] = new Array('','このプロジェクトについて、あなたのできることを探す場所です'); 
+ta['n-currentevents'] = new Array('','最近の出来事'); 
+ta['n-recentchanges'] = new Array('r','最近更新が行われたページの一覧'); 
+ta['n-randompage'] = new Array('x','ランダムに記事を選んで表示'); 
+ta['n-help'] = new Array('','ヘルプ・使い方'); 
+ta['n-sitesupport'] = new Array('','私たちをサポートしてください'); 
+ta['t-whatlinkshere'] = new Array('j','このページにリンクしているページの一覧'); 
+ta['t-recentchangeslinked'] = new Array('k','最近更新が行われたこのページのリンク先'); 
+ta['feed-rss'] = new Array('','このページのRSSフィード'); 
+ta['feed-atom'] = new Array('','このページのAtomフィード'); 
+ta['t-contributions'] = new Array('','ユーザーの投稿記録'); 
+ta['t-emailuser'] = new Array('','このユーザーにメールを送信'); 
+ta['t-upload'] = new Array('u','画像やメディアファイルをアップロード'); 
+ta['t-specialpages'] = new Array('q','特別ページの一覧'); 
+ta['ca-nstab-main'] = new Array('c','本文を表示'); 
+ta['ca-nstab-user'] = new Array('c','利用者ページを表示'); 
+ta['ca-nstab-media'] = new Array('c','メディアページを表示'); 
+ta['ca-nstab-special'] = new Array('','これは特別ページです。編集することはできません。'); 
+ta['ca-nstab-wp'] = new Array('a','{{SITENAME}}ページを表示'); 
+ta['ca-nstab-image'] = new Array('c','画像ページを表示'); 
+ta['ca-nstab-mediawiki'] = new Array('c','定型文を表示'); 
+ta['ca-nstab-template'] = new Array('c','テンプレートを表示'); 
+ta['ca-nstab-help'] = new Array('c','ヘルプページを表示'); 
+ta['ca-nstab-category'] = new Array('c','カテゴリページを表示');",
+
+# image deletion
+'deletedrevision' => '古い版 $1 を削除しました。',
+
+# browsing diffs
+'previousdiff' => '← 前の差分へ',
+'nextdiff' => '次の差分へ →',
+
+'imagemaxsize' => '画像ページで表示する画像の最大値:',
+'thumbsize' => 'サムネイルの大きさ:',
+'showbigimage' => '高解像度版をダウンロードする ($1x$2, $3 KB)',
+
+'newimages' => '新着画像ギャラリー',
+'noimages' => '画像がありません。',
+
+# short names for language variants used for language conversion links.
+# to disable showing a particular link, set it to 'disable', e.g.
+# 'variantname-zh-sg' => 'disable',
+'variantname-zh-cn' => '簡体 (中国)',
+'variantname-zh-tw' => '正字 (台湾)',
+'variantname-zh-hk' => '正字 (香港)',
+'variantname-zh-sg' => '簡体 (シンガポール)',
+'variantname-zh' => '無変換',
+
+# labels for User: and Title: on Special:Log pages
+'specialloguserlabel' => 'ユーザー名:',
+'speciallogtitlelabel' => 'タイトル:',
+
+'passwordtooshort' => 'パスワードが短すぎます。$1文字以上の文字列にしてください。',
+
+# Media Warning
+'mediawarning' => "'''警告:''' このファイルは悪意のあるコードを含んでいる可能性があり、実行するとコンピューターが危害を被る場合があります。
+----",
+
+'fileinfo' => '$1KB, MIMEタイプ: <code>$2</code>',
+
+# Metadata
+'metadata' => 'メタデータ',
+
+# Exif tags
+'exif-imagewidth' => '画像の幅',
+'exif-imagelength' => '画像の高さ',
+'exif-bitspersample' => 'ビット深度',
+'exif-compression' => '圧縮形式',
+'exif-photometricinterpretation' => '画素構成',
+'exif-orientation' => '画像方向',
+'exif-samplesperpixel' => 'コンポーネント数',
+'exif-planarconfiguration' => 'データ格納形式',
+'exif-ycbcrsubsampling' => 'YCCの画素構成(Cの間引き率)',
+'exif-ycbcrpositioning' => 'YCCの画素構成(YとCの位置)',
+'exif-xresolution' => '水平解像度',
+'exif-yresolution' => '垂直解像度',
+'exif-resolutionunit' => '解像度の単位',
+'exif-stripoffsets' => '画像データの場所',
+'exif-rowsperstrip' => 'ストリップのライン数',
+'exif-stripbytecounts' => 'ストリップのデータ量',
+'exif-jpeginterchangeformat' => 'JPEGのSOIへのオフセット',
+'exif-jpeginterchangeformatlength' => 'JPEGデータのバイト数',
+'exif-transferfunction' => '再生階調カーブ特性',
+'exif-whitepoint' => '参照白色点の色度座標値',
+'exif-primarychromaticities' => '原色の色度座標値',
+'exif-ycbcrcoefficients' => '色変換マトリックス係数',
+'exif-referenceblackwhite' => '参照黒色点値・参照白色点値',
+'exif-datetime' => 'ファイル変更日時',
+'exif-imagedescription' => '画像の説明',
+'exif-make' => '画像入力機器のメーカー',
+'exif-model' => '画像入力機器の機種',
+'exif-software' => 'ファームウェアのバージョン',
+'exif-artist' => '作成者',
+'exif-copyright' => '著作権者',
+'exif-exifversion' => 'EXIFバージョン',
+'exif-flashpixversion' => '対応フラッシュピックスバージョン',
+'exif-colorspace' => '色空間',
+'exif-componentsconfiguration' => '各コンポーネントの構成',
+'exif-compressedbitsperpixel' => '画像圧縮モード',
+'exif-pixelydimension' => '実効画像幅',
+'exif-pixelxdimension' => '実効画像高さ',
+'exif-makernote' => 'メーカーノート',
+'exif-usercomment' => 'ユーザーコメント',
+'exif-relatedsoundfile' => '関連音声ファイル',
+'exif-datetimeoriginal' => '画像データ生成日時',
+'exif-datetimedigitized' => 'デジタルデータ作成日時',
+'exif-subsectime' => 'ファイル変更日時 (秒未満)',
+'exif-subsectimeoriginal' => '画像データ生成日時 (秒未満)',
+'exif-subsectimedigitized' => 'デジタルデータ作成日時 (秒未満)',
+'exif-exposuretime' => '露出時間',
+'exif-fnumber' => 'F値',
+'exif-exposureprogram' => '露出プログラム',
+'exif-spectralsensitivity' => 'スペクトル感度',
+'exif-isospeedratings' => 'ISOスピードレート',
+'exif-oecf' => '光電変換関数',
+'exif-shutterspeedvalue' => 'シャッタースピード',
+'exif-aperturevalue' => '絞り値',
+'exif-brightnessvalue' => '明るさ',
+'exif-exposurebiasvalue' => '露出補正値',
+'exif-maxaperturevalue' => 'レンズ最小F値',
+'exif-subjectdistance' => '被写体距離',
+'exif-meteringmode' => '測光方式',
+'exif-lightsource' => '光源',
+'exif-flash' => 'フラッシュ',
+'exif-focallength' => 'レンズの焦点距離',
+'exif-subjectarea' => '主要被写体の位置',
+'exif-flashenergy' => 'フラッシュ強度',
+'exif-spatialfrequencyresponse' => '空間周波数応答',
+'exif-focalplanexresolution' => '水平方向の焦点面解像度',
+'exif-focalplaneyresolution' => '垂直方向の焦点面解像度',
+'exif-focalplaneresolutionunit' => '焦点面解像度の単位',
+'exif-subjectlocation' => '被写体の場所',
+'exif-exposureindex' => '露出インデックス',
+'exif-sensingmethod' => 'センサー方式',
+'exif-filesource' => 'ファイルソース',
+'exif-scenetype' => 'シーンタイプ',
+'exif-cfapattern' => 'CFAパターン',
+'exif-customrendered' => '画像処理',
+'exif-exposuremode' => '露出モード',
+'exif-whitebalance' => 'ホワイトバランス',
+'exif-digitalzoomratio' => 'デジタルズーム倍率',
+'exif-focallengthin35mmfilm' => 'レンズの焦点距離(35mmフィルム換算)',
+'exif-scenecapturetype' => '被写体の種別',
+'exif-gaincontrol' => 'ゲインコントロール',
+'exif-contrast' => 'コントラスト',
+'exif-saturation' => '彩度',
+'exif-sharpness' => 'シャープネス',
+'exif-devicesettingdescription' => '機器設定',
+'exif-subjectdistancerange' => '被写体距離の範囲',
+'exif-imageuniqueid' => 'ユニーク画像ID',
+'exif-gpsversionid' => 'GPSタグのバージョン',
+'exif-gpslatituderef' => '北緯/南緯',
+'exif-gpslatitude' => '緯度',
+'exif-gpslongituderef' => '東経/西経',
+'exif-gpslongitude' => '経度',
+'exif-gpsaltituderef' => '高度の基準',
+'exif-gpsaltitude' => '高度',
+'exif-gpstimestamp' => 'GPS時刻(原子時計)',
+'exif-gpssatellites' => '測位に用いた衛星信号',
+'exif-gpsstatus' => 'GPS受信機の状態',
+'exif-gpsmeasuremode' => 'GPS測位方法',
+'exif-gpsdop' => '測位精度',
+'exif-gpsspeedref' => '速度の単位',
+'exif-gpsspeed' => '速度',
+'exif-gpstrackref' => '進行方向の基準',
+'exif-gpstrack' => '進行方向',
+'exif-gpsimgdirectionref' => '撮影方向の基準',
+'exif-gpsimgdirection' => '撮影方向',
+'exif-gpsmapdatum' => '測地系',
+'exif-gpsdestlatituderef' => '目的地の北緯/南緯',
+'exif-gpsdestlatitude' => '目的地の緯度',
+'exif-gpsdestlongituderef' => '目的地の東経/西経',
+'exif-gpsdestlongitude' => '目的地の経度',
+'exif-gpsdestbearingref' => '目的地の方角の基準',
+'exif-gpsdestbearing' => '目的地の方角',
+'exif-gpsdestdistanceref' => '目的地までの距離の単位',
+'exif-gpsdestdistance' => '目的地までの距離',
+'exif-gpsprocessingmethod' => 'GPS処理方法',
+'exif-gpsareainformation' => 'GPSエリア名',
+'exif-gpsdatestamp' => 'GPS測位日時',
+'exif-gpsdifferential' => 'ディファレンシャル補正',
+
+# Make & model, can be wikified in order to link to the camera and model name
+
+'exif-make-value' => '$1',
+'exif-model-value' => '$1',
+'exif-software-value' => '$1',
+
+# Exif attributes
+
+'exif-compression-1' => '非圧縮',
+'exif-compression-6' => 'JPEG圧縮',
+
+'exif-photometricinterpretation-1' => 'RGB',
+'exif-photometricinterpretation-6' => 'YCbCr',
+
+'exif-orientation-1' => '通常',
+'exif-orientation-2' => '左右反転',
+'exif-orientation-3' => '180°回転',
+'exif-orientation-4' => '上下反転',
+'exif-orientation-5' => '反時計回りに90°回転 上下反転',
+'exif-orientation-6' => '時計回りに90°回転',
+'exif-orientation-7' => '時計回りに90°回転 上下反転',
+'exif-orientation-8' => '反時計回りに90°回転',
+
+'exif-planarconfiguration-1' => '点順次フォーマット',
+'exif-planarconfiguration-2' => '面順次フォーマット',
+
+'exif-xyresolution-i' => '$1 dpi',
+'exif-xyresolution-c' => '$1 dpc',
+
+'exif-colorspace-1' => 'sRGB',
+'exif-colorspace-ffff.h' => 'その他',
+
+'exif-componentsconfiguration-0' => 'なし',
+'exif-componentsconfiguration-1' => 'Y',
+'exif-componentsconfiguration-2' => 'Cb',
+'exif-componentsconfiguration-3' => 'Cr',
+'exif-componentsconfiguration-4' => 'R',
+'exif-componentsconfiguration-5' => 'G',
+'exif-componentsconfiguration-6' => 'B',
+
+'exif-exposureprogram-0' => '未定義',
+'exif-exposureprogram-1' => 'マニュアル',
+'exif-exposureprogram-2' => 'ノーマルプログラム',
+'exif-exposureprogram-3' => '露出優先',
+'exif-exposureprogram-4' => 'シャッター速度優先',
+'exif-exposureprogram-5' => 'クリエイティブプログラム',
+'exif-exposureprogram-6' => 'アクションプログラム',
+'exif-exposureprogram-7' => 'ポートレイトモード(近景)',
+'exif-exposureprogram-8' => 'ランドスケープモード(遠景)',
+
+'exif-subjectdistance-value' => '$1 メートル',
+
+'exif-meteringmode-0' => '不明',
+'exif-meteringmode-1' => '平均',
+'exif-meteringmode-2' => '中央重点',
+'exif-meteringmode-3' => 'スポット',
+'exif-meteringmode-4' => 'マルチスポット',
+'exif-meteringmode-5' => '分割測光',
+'exif-meteringmode-6' => '部分測光',
+'exif-meteringmode-255' => 'その他',
+
+'exif-lightsource-0' => '不明',
+'exif-lightsource-1' => '昼光',
+'exif-lightsource-2' => '蛍光灯',
+'exif-lightsource-3' => 'タングステン(白熱灯)',
+'exif-lightsource-4' => 'フラッシュ',
+'exif-lightsource-9' => '晴天',
+'exif-lightsource-10' => '曇天',
+'exif-lightsource-11' => '日陰',
+'exif-lightsource-12' => '昼光色蛍光灯 (D 5700 - 7100K)',
+'exif-lightsource-13' => '昼白色蛍光灯 (N 4600 - 5400K)',
+'exif-lightsource-14' => '白色蛍光灯 (W 3900 - 4500K)',
+'exif-lightsource-15' => '温白色蛍光灯 (WW 3200 - 3700K)',
+'exif-lightsource-17' => '標準光A',
+'exif-lightsource-18' => '標準光B',
+'exif-lightsource-19' => '標準光C',
+'exif-lightsource-20' => 'D55',
+'exif-lightsource-21' => 'D65',
+'exif-lightsource-22' => 'D75',
+'exif-lightsource-23' => 'D50',
+'exif-lightsource-24' => 'ISOスタジオタングステン',
+'exif-lightsource-255' => 'その他',
+
+'exif-focalplaneresolutionunit-2' => 'インチ',
+
+'exif-sensingmethod-1' => '未定義',
+'exif-sensingmethod-2' => '単板カラーセンサー',
+'exif-sensingmethod-3' => '2板カラーセンサー',
+'exif-sensingmethod-4' => '3板カラーセンサー',
+'exif-sensingmethod-5' => '色順次カラーセンサー',
+'exif-sensingmethod-7' => '3線リニアセンサー',
+'exif-sensingmethod-8' => '色順次リニアセンサー',
+
+'exif-filesource-3' => 'デジタルスチルカメラ',
+
+'exif-scenetype-1' => '直接撮影された画像',
+
+'exif-customrendered-0' => '通常',
+'exif-customrendered-1' => 'カスタム',
+
+'exif-exposuremode-0' => '自動',
+'exif-exposuremode-1' => 'マニュアル',
+'exif-exposuremode-2' => 'オートブラケット',
+
+'exif-whitebalance-0' => '自動',
+'exif-whitebalance-1' => 'マニュアル',
+
+'exif-scenecapturetype-0' => '標準',
+'exif-scenecapturetype-1' => '風景',
+'exif-scenecapturetype-2' => '人物',
+'exif-scenecapturetype-3' => '夜景',
+
+'exif-gaincontrol-0' => 'なし',
+'exif-gaincontrol-1' => '弱増感',
+'exif-gaincontrol-2' => '強増感',
+'exif-gaincontrol-3' => '弱減感',
+'exif-gaincontrol-4' => '強増感',
+
+'exif-contrast-0' => '標準',
+'exif-contrast-1' => '軟調',
+'exif-contrast-2' => '硬調',
+
+'exif-saturation-0' => '標準',
+'exif-saturation-1' => '低彩度',
+'exif-saturation-2' => '高彩度',
+
+'exif-sharpness-0' => '標準',
+'exif-sharpness-1' => '弱',
+'exif-sharpness-2' => '強',
+
+'exif-subjectdistancerange-0' => '不明',
+'exif-subjectdistancerange-1' => 'マクロ',
+'exif-subjectdistancerange-2' => '近景',
+'exif-subjectdistancerange-3' => '遠景',
+
+// Pseudotags used for GPSLatitudeRef and GPSDestLatitudeRef
+'exif-gpslatitude-n' => '北緯',
+'exif-gpslatitude-s' => '南緯',
+
+// Pseudotags used for GPSLongitudeRef and GPSDestLongitudeRef
+'exif-gpslongitude-e' => '東経',
+'exif-gpslongitude-w' => '西経',
+
+'exif-gpsstatus-a' => '測位中',
+'exif-gpsstatus-v' => '未測位',
+
+'exif-gpsmeasuremode-2' => '2次元測位',
+'exif-gpsmeasuremode-3' => '3次元測位',
+
+// Pseudotags used for GPSSpeedRef and GPSDestDistanceRef
+'exif-gpsspeed-k' => 'キロメートル毎時',
+'exif-gpsspeed-m' => 'マイル毎時',
+'exif-gpsspeed-n' => 'ノット',
+
+// Pseudotags used for GPSTrackRef, GPSImgDirectionRef and GPSDestBearingRef
+'exif-gpsdirection-t' => '真方位',
+'exif-gpsdirection-m' => '磁方位',
+
+# external editor support
+'edit-externally' => '外部アプリケーションを使ってこのファイルを編集する',
+'edit-externally-help' => '詳しい情報は[http://meta.wikimedia.org/wiki/Help:External_editors 外部エディタに関する説明(英語)]をご覧ください。',
+
+# 'all' in various places, this might be different for inflected languages
+'recentchangesall' => 'すべて',
+'imagelistall' => 'すべて',
+'watchlistall1' => 'すべて',
+'watchlistall2' => 'すべて',
+'namespacesall' => 'すべて',
+
+# E-mail address confirmation
+'confirmemail' => 'メールアドレスの確認',
+'confirmemail_text' => 'このウィキではメール通知を受け取る前にメールアドレスの確認が必要です。以下のボタンを押すと「{{int:Confirmemail_subject}}」という件名の確認メールがあなたのメールアドレスに送られます。メールには確認用コードを含むリンクが書かれています。そのリンクを開くことによってメールアドレスの正当性が確認されます。',
+'confirmemail_send' => '確認用コードを送信する',
+'confirmemail_sent' => '確認メールを送信しました。',
+'confirmemail_sendfailed' => '確認メールを送信できませんでした。メールアドレスに不正な文字が含まれていないかどうか確認してください。',
+'confirmemail_invalid' => '確認用コードが正しくありません。このコードは期限切れです。',
+'confirmemail_success' => 'あなたのメールアドレスは確認されました。ログインしてウィキを楽しんでください。',
+'confirmemail_loggedin' => 'あなたのメールアドレスは確認されました。',
+'confirmemail_error' => 'あなたの確認を保存する際に内部エラーが発生しました。',
+
+'confirmemail_subject' => '{{SITENAME}} e-mail address confirmation',
+'confirmemail_body' => 'どなたか(IPアドレス $1 の使用者)がこのメールアドレスを使用して
+{{SITENAME}} にアカウント "$2" を登録しました。
+
+このアカウントが本当にあなたのものであるか確認し、
+{{SITENAME}} のメール通知機能を有効にするために以下のURLにアクセスしてください:
+$3
+
+もし {{SITENAME}} について身に覚えがない場合は、リンクを開かないでください。
+確認用コードは  $4 に期限切れになります。
+
+-- 
+{{SITENAME}} メールアドレス確認システム
+{{SERVER}}/',
+
+
+
+
+# Inputbox extension, may be useful in other contexts as well
+'tryexact' => '一致する項目を検索',
+'searchfulltext' => '全文検索',
+'createarticle' => '項目を作成',
+
+# Scary transclusion
+'scarytranscludedisabled' => '[Interwiki transcluding is disabled]',
+'scarytranscludefailed' => '[Template fetch failed for $1; sorry]',
+'scarytranscludetoolong' => '[URL is too long; sorry]',
+
+# Trackbacks
+'trackbackbox' => '<div id="mw_trackbacks">
+この項目へのトラックバック:
+$1
+</div>',
+# 'trackback' => '',
+# 'trackbackexcerpt' => '',
+'trackbackremove' => ' ([$1 削除])',
+'trackbacklink' => 'トラックバック',
+'trackbackdeleteok' => 'トラックバックを削除しました。',
+
+'unit-pixel' => 'px',
+
+);
+
+class LanguageJa extends LanguageUtf8 {
+
+       function getNamespaces() {
+               global $wgNamespaceNamesJa;
+               return $wgNamespaceNamesJa;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsJa;
+               return $wgQuickbarSettingsJa;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesJa;
+               return $wgSkinNamesJa;
+       }
+
+       function getDateFormats() {
+               global $wgDateFormatsJa;
+               return $wgDateFormatsJa;
+       }
+       
+       function date( $ts, $adj = false, $format = true, $tc = false ) {
+               global $wgWeekdayAbbreviationsJa;
+               
+               if ( $adj ) { $ts = $this->userAdjust( $ts, $tc ); }
+               $datePreference = $this->dateFormat( $format );
+               
+               if( $datePreference == MW_DATE_ISO ) {
+                       $d = substr($ts, 0, 4). '-' . substr($ts, 4, 2). '-' .
+                                       substr($ts, 6, 2);
+                       return $d;
+               }
+               
+               $year = (int)substr( $ts, 0, 4 );
+               $month = (int)substr( $ts, 4, 2 );
+               $mday = (int)substr( $ts, 6, 2 );
+               $hour = (int)substr( $ts, 8, 2 );
+               $minute = (int)substr( $ts, 10, 2 );
+               $second = (int)substr( $ts, 12, 2 );
+               
+               $time = mktime( $hour, $minute, $second, $month, $mday, $year );
+               $date = getdate( $time );
+               
+               $d = $year . "年" .
+                               $this->getMonthAbbreviation( $month ) .
+                               $mday . "日 (" .
+                               $wgWeekdayAbbreviationsJa[ $date['wday'] ]. ")";
+               return $d;
+       }
+
+       function time( $ts, $adj = false, $format = true, $tc = false ) {
+               if ( $adj ) { $ts = $this->userAdjust( $ts, $tc ); }
+               $datePreference = $this->dateFormat( $format );
+               
+               $t = substr( $ts, 8, 2 ) . ":" . substr( $ts, 10, 2 );
+               if ( $datePreference == MW_DATE_ISO ) {
+                       $t .= ':' . substr( $ts, 12, 2 );
+               }
+               
+               return $t;
+       }
+
+       function timeanddate( $ts, $adj = false, $format = true, $tc = false ) {
+               return $this->date( $ts, $adj, $format, $tc ) . " " . $this->time( $ts, $adj, $format, $tc );
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesJa;
+               if(array_key_exists($key, $wgAllMessagesJa))
+                       return $wgAllMessagesJa[$key];
+               else
+                       return parent::getMessage($key);
+       }
+
+       function stripForSearch( $string ) {
+               # MySQL fulltext index doesn't grok utf-8, so we
+               # need to fold cases and convert to hex
+               global $wikiLowerChars;
+               $s = $string;
+
+               # Strip known punctuation ?
+               #$s = preg_replace( '/\xe3\x80[\x80-\xbf]/', '', $s ); # U3000-303f
+
+               # Space strings of like hiragana/katakana/kanji
+               $hiragana = '(?:\xe3(?:\x81[\x80-\xbf]|\x82[\x80-\x9f]))'; # U3040-309f
+               $katakana = '(?:\xe3(?:\x82[\xa0-\xbf]|\x83[\x80-\xbf]))'; # U30a0-30ff
+               $kanji = '(?:\xe3[\x88-\xbf][\x80-\xbf]'
+                       . '|[\xe4-\xe8][\x80-\xbf]{2}'
+                       . '|\xe9[\x80-\xa5][\x80-\xbf]'
+                       . '|\xe9\xa6[\x80-\x99])';
+                       # U3200-9999 = \xe3\x88\x80-\xe9\xa6\x99
+               $s = preg_replace( "/({$hiragana}+|{$katakana}+|{$kanji}+)/", ' $1 ', $s );
+
+               # Double-width roman characters: ff00-ff5f ~= 0020-007f
+               $s = preg_replace( '/\xef\xbc([\x80-\xbf])/e', 'chr((ord("$1") & 0x3f) + 0x20)', $s );
+               $s = preg_replace( '/\xef\xbd([\x80-\x99])/e', 'chr((ord("$1") & 0x3f) + 0x60)', $s );
+
+               # Do general case folding and UTF-8 armoring
+               return LanguageUtf8::stripForSearch( $s );
+       }
+
+       # Italic is not appropriate for Japanese script
+       # Unfortunately most browsers do not recognise this, and render <em> as italic
+       function emphasize( $text ) {
+               return $text;
+       }
+}
+
+?>
diff --git a/languages/LanguageKa.php b/languages/LanguageKa.php
new file mode 100644 (file)
index 0000000..978c06a
--- /dev/null
@@ -0,0 +1,38 @@
+<?php
+/** Kartuli (Georgian)
+  *
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+require_once( 'LanguageUtf8.php' );
+
+/* private */ $wgNamespaceNamesKa = array(
+       NS_MEDIA            => 'მედია',
+       NS_SPECIAL          => 'სპეციალური',
+       NS_MAIN             => '',
+       NS_TALK             => 'განხილვა',
+       NS_USER             => 'მომხმარებელი',
+       NS_USER_TALK        => 'მომხმარებელი_განხილვა',
+       NS_PROJECT          => 'ვიკიპედია',
+       NS_PROJECT_TALK     => 'ვიკიპედია_განხილვა',
+       NS_IMAGE            => 'სურათი',
+       NS_IMAGE_TALK       => 'სურათი_განხილვა',
+       NS_MEDIAWIKI        => 'მედიავიკი',
+       NS_MEDIAWIKI_TALK   => 'მედიავიკი_განხილვა',
+       NS_TEMPLATE         => 'თარგი',
+       NS_TEMPLATE_TALK    => 'თარგი_განხილვა',
+       NS_HELP             => 'დახმარება',
+       NS_HELP_TALK        => 'დახმარება_განხილვა',
+       NS_CATEGORY         => 'კატეგორია',
+       NS_CATEGORY_TALK    => 'კატეგორია_განხილვა'
+) + $wgNamespaceNamesEn;
+
+class LanguageKa extends LanguageUtf8 {
+       function getNamespaces() {
+               global $wgNamespaceNamesKa;
+               return $wgNamespaceNamesKa;
+       }
+}
+
+?>
diff --git a/languages/LanguageKm.php b/languages/LanguageKm.php
new file mode 100644 (file)
index 0000000..429a501
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+/** Khmer (ភាសាខ្មែរ)
+  *
+  * @package MediaWiki
+  * @subpackage Language
+  *
+  * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
+  */
+
+require_once( 'LanguageUtf8.php' );
+
+class LanguageKm extends LanguageUtf8 {
+       var $digitTransTable = array(
+               '0' => '០',
+               '1' => '១',
+               '2' => '២',
+               '3' => '៣',
+               '4' => '៤',
+               '5' => '៥',
+               '6' => '៦',
+               '7' => '៧',
+               '8' => '៨',
+               '9' => '៩'
+       );
+
+       function formatNum( $number ) {
+               global $wgTranslateNumerals;
+               if( $wgTranslateNumerals ) {
+                       return strtr( $number, $this->digitTransTable );
+               } else {
+                       return $number;
+               }
+       }
+}
+
+?>
diff --git a/languages/LanguageKn.php b/languages/LanguageKn.php
new file mode 100644 (file)
index 0000000..56fea08
--- /dev/null
@@ -0,0 +1,387 @@
+<?php
+/**
+ * Language file for Kannada.
+ * Mosty done by:
+ *   Hari Prasad Nadig <hpnadig@gmail.com>
+ *     http://en.wikipedia.org/wiki/User:Hpnadig
+ *   Ashwath Mattur <ashwatham@gmail.com>
+ *     http://en.wikipedia.org/wiki/User:Ashwatham
+ *
+ * Also see the Kannada Localisation Initiative at:
+ *      http://kannada.sourceforge.net/
+ *
+ * @package MediaWiki
+ * @subpackage Language
+ */
+
+require_once( 'LanguageUtf8.php' );
+
+/* private */ $wgAllMessagesKn = array(
+'jan' => 'ಜನವರಿ',
+'feb' => 'ಫೆಬ್ರುವರಿ',
+'mar' => 'ಮಾರ್ಚ್',
+'apr' => 'ಎಪ್ರಿಲ್',
+'may' => 'ಮೇ',
+'jun' => 'ಜೂನ್',
+'jul' => 'ಜುಲೈ',
+'aug' => 'ಆಗಸ್ಟ್',
+'sep' => 'ಸೆಪ್ಟೆಂಬರ್',
+'oct' => 'ಅಕ್ಟೋಬರ್',
+'nov' => 'ನವೆಂಬರ್',
+'dec' => 'ಡಿಸೆಂಬರ್',
+
+
+'1movedto2' => "$1 - $2 ಕ್ಕೆ ಸ್ಥಳಾಂತರಿಸಲಾಗಿದೆ",
+'1movedto2_redir' => "$1 - $2 ಕ್ಕೆ ರಿಡೈರೆಕ್ಟ್ ಮೂಲಕ ಸ್ಥಳಾಂತರಿಸಲಾಗಿದೆ",
+'about' => "ನಮ್ಮ ಬಗ್ಗೆ",
+'aboutpage' => "ವಿಕಿಪೀಡಿಯಾ:ನಮ್ಮ ಬಗ್ಗೆ",
+'accmailtext' => "'$1'ನ ಪ್ರವೇಶ ಪದ $2 ಗೆ ಕಳುಹಿಸಲಾಗಿದೆ",
+'accmailtitle' => "ಪ್ರವೇಶ ಪದ ಕಳುಹಿಸಲಾಯಿತು.",
+'acct_creation_throttle_hit' => "ಕ್ಷಮಿಸಿ, ನೀವಾಗಲೇ $1 ಖಾತೆಗಳನ್ನು ತೆರೆದಿದ್ದೀರಿ. ಇನ್ನು ಖಾತೆಗಳನ್ನು ತೆರೆಯಲಾಗುವುದಿಲ್ಲ.",
+'actioncomplete' => "ಕಾರ್ಯ ಸಂಪೂರ್ಣ",
+'addedwatch' => "ವೀಕ್ಷಣಾ ಪಟ್ಟಿಗೆ ಸೇರಿಸಲಾಯಿತು",
+'addedwatchtext' => "\"$1\" ಪುಟವನ್ನು ನಿಮ್ಮ [[Special:Watchlist|ವೀಕ್ಷಣಾಪಟ್ಟಿಗೆ]] ಸೇರಿಸಲಾಗಿದೆ. ಈ ಪುಟದ ಮತ್ತು ಇದರ ಚರ್ಚಾ ಪುಟದ ಮು೦ದಿನ ಬದಲಾವಣೆಗಳು ವೀಕ್ಷಣಾ ಪಟ್ಟಿಯಲ್ಲಿ ಕಾಣಸಿಗುತ್ತವೆ, ಮತ್ತು [[Special:Recentchanges|ಇತ್ತೀಚೆಗಿನ ಬದಲಾವಣೆಗಳ]] ಪಟ್ಟಿಯಲ್ಲಿ ಈ ಪುಟಗಳನ್ನು ದಪ್ಪಕ್ಷರಗಳಲ್ಲಿ ಕಾಣಿಸಲಾಗುವುದು.
+
+<p>ಈ ಪುಟವನ್ನು ವೀಕ್ಷಣಾ ಪಟ್ಟಿಯಿ೦ದ ತೆಗೆಯಬಯಸಿದಲ್ಲಿ, ಮೇಲ್ಪಟ್ಟಿಯಲ್ಲಿ ಕಾಣಿಸಿರುವ \"ವೀಕ್ಷಣಾ ಪುಟದಿ೦ದ ತೆಗೆ\" ಅನ್ನು ಕ್ಲಿಕ್ಕಿಸಿ.",
+'administrators' => "ವಿಕಿಪೀಡಿಯ:ನಿರ್ವಾಹಕರು",
+'alphaindexline' => "$1 ಇಂದ $2",
+'ancientpages' => "ಹಳೆಯ ಪುಟಗಳು",
+'and' => "ಮತ್ತು",
+'anontalk' => "ಈ ಐ.ಪಿ ಗೆ ಮಾತನಾಡಿ",
+'anonymous' => "ವಿಕಿಪೀಡಿಯಾದ ಅನಾಮಿಕ ಸದಸ್ಯರು",
+'apr' => "ಎಪ್ರಿಲ್",
+'article' => "ಲೇಖನ ಪುಟ",
+'articlepage' => "ಲೇಖನ ಪುಟವನ್ನು ವೀಕ್ಷಿಸಿ",
+
+
+'badarticleerror' => "ಈ ಪುಟದ ಮೇಲೆ ನೀವು ಪ್ರಯತ್ನಿಸಿದ ಕಾರ್ಯವನ್ನು ನಡೆಸಲಾಗದು.",
+'badfilename' => "ಚಿತ್ರದ ಹೆಸರನ್ನು $1 ಗೆ ಬದಲಾಯಿಸಲಾಗಿದೆ.",
+'badfiletype' => "\".$1\" ಚಿತ್ರಗಳಿಗೆ ಸೂಚಿತ ಫಾರ್ಮ್ಯಾಟ್ ಅಲ್ಲ.",
+'badretype' => "ನೀವು ಕೊಟ್ಟ ಪ್ರವೇಶಪದಗಳು ಬೇರೆಬೇರೆಯಾಗಿವೆ.",
+'badtitle' => "ಸರಿಯಿಲ್ಲದ ಹೆಸರು",
+'blockedtitle' => "ಈ ಸದಸ್ಯರನ್ನು ತಡೆ ಹಿಡಿಯಲಾಗಿದೆ.",
+'blockip' => "ಈ ಸದಸ್ಯನನ್ನು ತಡೆ ಹಿಡಿಯಿರಿ",
+'blockipsuccesssub' => "ತಡೆಹಿಡಿಯುವಿಕೆ ಯಶಸ್ವಿಯಾಯಿತು.",
+'blocklink' => "ತಡೆ ಹಿಡಿಯಿರಿ",
+'blocklogentry' => "\"$1\" ಅನ್ನು $2 ರ ಸಮಯದವರೆಗೆ ತಡೆಹಿಡಿಯಲಾಗಿದೆ",
+'blocklogpage' => "ತಡೆಹಿಡಿದ ಸದಸ್ಯರ ದಿನಚರಿ",
+'bold_sample' => "ದಪ್ಪಗಿನ ಅಚ್ಚು",
+'bold_tip' => "ದಪ್ಪಗಿನ ಅಚ್ಚು",
+'booksources' => "ಪುಸ್ತಕಗಳ ಮೂಲ",
+'brokenredirects' => "ಮುರಿದ ರಿಡೈರೆಕ್ಟ್‌ಗಳು",
+'bydate' => "ದಿನಾಂಕಕ್ಕನುಗುಣವಾಗಿ",
+'byname' => "ಹೆಸರಿಗನುಗುಣವಾಗಿ",
+'bysize' => "ಗಾತ್ರಕ್ಕನುಗುಣವಾಗಿ",
+
+'cancel' => "ವಜಾ ಮಾಡಿ",
+'cannotdelete' => "ಈ ಪುಟ ಅಥವಾ ಚಿತ್ರವನ್ನು ಅಳಿಸಲಾಗಲಿಲ್ಲ. (ಬೇರೊಬ್ಬ ಸದಸ್ಯರಿ೦ದ ಆಗಲೇ ಅಳಿಸಲ್ಪಟ್ಟಿರಬಹುದು.)",
+'categories' => "ವರ್ಗಗಳು",
+'categoriespagetext' => "ವಿಕಿಯಲ್ಲಿ ಈ ಕೆಳಗಿನ ವರ್ಗಗಳಿವೆ",
+'category' => "ವರ್ಗ",
+'category_header' => "\"$1\" ವರ್ಗದಲ್ಲಿರುವ ಲೇಖನಗಳು",
+'categoryarticlecount' => "ಈ ವರ್ಗದಲ್ಲಿ $1 ಲೇಖನಗಳಿವೆ.",
+'changepassword' => "ಪ್ರವೇಶ ಪದ ಬದಲಾಯಿಸಿ",
+'changes' => "ಬದಲಾವಣೆಗಳು",
+'compareselectedversions' => "ಆಯ್ಕೆ ಮಾಡಿದ ಆವೃತ್ತಿಗಳನ್ನು ಹೊಂದಾಣಿಕೆ ಮಾಡಿ ನೋಡಿ",
+'confirm' => "ಧೃಡಪಡಿಸು",
+'confirmdelete' => "ಅಳಿಸುವಿಕೆ ಧೃಡಪಡಿಸು",
+'confirmdeletetext' => "ಪುಟ ಅಥವಾ ಚಿತ್ರ ಮತ್ತು ಅದರ ಸ೦ಪೂರ್ಣ ಇತಿಹಾಸವನ್ನು ನೀವು ಶಾಶ್ವತವಾಗಿ ಅಳಿಸಿಹಾಕುತ್ತಿದ್ದೀರಿ. ಇದನ್ನು ನೀವು ಮಾಡಬಯಸುವಿರಿ, ಇದರ ಪರಿಣಾಮಗಳನ್ನು ಬಲ್ಲಿರಿ, ಮತ್ತು [[Wikipedia:Policy]] ನ ಅನುಸಾರ ಇದನ್ನು ಮಾಡುತ್ತಿದ್ದೀರಿ ಎ೦ದು ದೃಢಪಡಿಸಿ.",
+'confirmprotect' => "ಸಂರಕ್ಷಣೆ ಧೃಡಪಡಿಸಿ",
+'confirmprotecttext' => "ಈ ಪುಟವನ್ನು ನಿಜಕ್ಕೂ ಸ೦ರಕ್ಷಿಸಬಯಸುತ್ತೀರಾ?",
+'confirmunprotect' => "ಸ೦ರಕ್ಷಣೆ ತೆಗೆಯಬೇಕೆ೦ದು ದೃಢಪಡಿಸಿ",
+'confirmunprotecttext' => "ಈ ಪುಟದ ಸ೦ರಕ್ಷಣೆಯನ್ನು ನಿಜಕ್ಕೂ ತೆಗೆಯಬಯಸುತ್ತೀರಾ?",
+'contribslink' => "ಕಾಣಿಕೆಗಳು",
+'contribsub' => "$1 ಗೆ",
+'contributions' => "ಸದಸ್ಯರ ಕಾಣಿಕೆಗಳು",
+'copyright' => "ಇದು ಈ ಕಾಪಿರೈಟ್‌ನಲ್ಲಿ ಲಭ್ಯವಿದೆ $1.",
+'copyrightpage' => "ವಿಕಿಪೀಡಿಯ: ಕೃತಿಸ್ವಾಮ್ಯತೆಗಳು",
+'copyrightpagename' => "{{SITENAME}} ಕಾಪಿರೈಟ್",
+'createaccount' => "ಹೊಸ ಖಾತೆ ತೆರೆಯಿರಿ",
+'createaccountmail' => "ಇ-ಅಂಚೆಯ ಮೂಲಕ",
+'creditspage' => "ಪುಟದ ಗೌರವಗಳು",
+'cur' => "ಸದ್ಯದ",
+'currentevents' => "ಪ್ರಚಲಿತ",
+'currentrev' => "ಈಗಿನ ತಿದ್ದುಪಡಿ",
+
+
+'databaseerror' => "ಡೇಟಬೇಸ್ ದೋಷ",
+'dateformat' => "ದಿನಾಂಕದ ಫಾರ್ಮ್ಯಾಟ್",
+'deadendpages' => "ಕೊನೆಯಂಚಿನ ಪುಟಗಳು",
+'dec' => "ಡಿಸೆಂಬರ್",
+'defemailsubject' => "ವಿಕಿಪೀಡಿಯ ವಿ-ಅ೦ಚೆ",
+'delete' => "ಅಳಿಸಿ",
+'deletecomment' => "ಅಳಿಸುವುದರ ಕಾರಣ",
+'deletedarticle' => "\"$1\" ಅಳಿಸಲಾಯಿತು",
+'deletedtext' => "\"$1\" ಅನ್ನು ಅಳಿಸಲಾಯಿತು.
+ಇತ್ತೀಚೆಗಿನ ಅಳಿಸುವಿಕೆಗಳ ಪಟ್ಟಿಗಾಗಿ $2 ಅನ್ನು ನೋಡಿ.",
+'deleteimg' => "ಅಳಿಸಿ",
+'deletepage' => "ಪುಟವನ್ನು ಅಳಿಸಿ",
+'deletesub' => "(\"$1\" ಅನ್ನು ಅಳಿಸಲಾಗುತ್ತಿದೆ)",
+'deletethispage' => "ಈ ಪುಟವನ್ನು ಅಳಿಸಿ",
+'deletionlog' => "ಅಳಿಸುವಿಕೆ ದಿನಚರಿ",
+'developertext' => "\"ಡೆವೆಲಪರ್\" ಸ್ಥಾನದಲ್ಲಿರುವ ಸದಸ್ಯರು ಮಾತ್ರ ಈ ಕಾರ್ಯವನ್ನು ಮಾಡಬಲ್ಲರು. $1 ನೋಡಿ.",
+'diff' => "ವ್ಯತ್ಯಾಸ",
+'difference' => "(ಆವೃತ್ತಿಗಳ ನಡುವಿನ ವ್ಯತ್ಯಾಸ)",
+
+
+'edit' => "ಸಂಪಾದಿಸಿ",
+'editcurrent' => "ಈ ಪುಟದ ಪ್ರಸಕ್ತ ಆವೃತ್ತಿಯನ್ನು ಸ೦ಪಾದಿಸಿ",
+'edithelp' => "ಸಂಪಾದನೆಗೆ ಸಹಾಯ",
+'edithelppage' => "ಸಹಾಯ:ಸ೦ಪಾದನೆ",
+'editing' => "'$1' ಲೇಖನ ಬದಲಾಯಿಸಲಾಗುತ್ತಿದೆ",
+'editingold' => "<strong>ಎಚ್ಚರಿಕೆ: ಈ ಪುಟದ ಹಳೆಯ ಆವೃತ್ತಿಯನ್ನು ಬದಲಾಯಿಸುತ್ತಿದ್ದೀರಿ. ಈ ಬದಲಾವಣೆಗಳನ್ನು ಉಳಿಸಿದಲ್ಲಿ, ನ೦ತರದ ಆವೃತ್ತಿಗಳೆಲ್ಲವೂ ಕಳೆದುಹೋಗುತ್ತವೆ.</strong>",
+'editsection' => "ಬದಲಾಯಿಸಿ",
+'editthispage' => "ಈ ಪುಟವನ್ನು ಬದಲಾಯಿಸಿ",
+'emailfrom' => "ಇಂದ",
+'emailmessage' => "ಸಂದೇಶ",
+'emailpage' => "ಸದಸ್ಯರಿಗೆ ವಿ-ಅ೦ಚೆ ಕಳಿಸಿ",
+'emailsend' => "ಕಳುಹಿಸಿ",
+'emailsent' => "ಇ-ಅಂಚೆ ಕಳುಹಿಸಲಾಯಿತು",
+'emailsenttext' => "ನಿಮ್ಮ ವಿ-ಅ೦ಚೆ ಸ೦ದೇಶವನ್ನು ಕಳುಹಿಸಲಾಯಿತು.",
+'emailsubject' => "ವಿಷಯ",
+'emailto' => "ಗೆ",
+'emailuser' => "ಈ ಸದಸ್ಯರಿಗೆ ವಿ-ಅ೦ಚೆ ಕಳಿಸಿ",
+'error' => "ದೋಷ",
+'errorpagetitle' => "ದೋಷ",
+'exblank' => "ಪುಟ ಖಾಲಿ ಇತ್ತು",
+'export' => "ಪುಟಗಳನ್ನು ರಫ್ತು ಮಾಡಿ",
+
+
+'feb' => "ಫೆಬ್ರುವರಿ",
+'feedlinks' => "ಫೀಡ್:",
+'filecopyerror' => "\"$1\" ಫೈಲ್ ಅನ್ನು \"$2\" ಗೆ ನಕಲಿಸಲಾಗಲಿಲ್ಲ.",
+'filedeleteerror' => "\"$1\" ಫೈಲ್ ಅನ್ನು ಅಳಿಸಲಾಗಲಿಲ್ಲ.",
+'filedesc' => "ಸಾರಾಂಶ",
+'fileexists' => "ಈ ಹೆಸರಿನ ಫೈಲ್ ಆಗಲೇ ಅಸ್ತಿತ್ವದಲ್ಲಿದೆ. ಈ ಹೆಸರನ್ನು ಬದಲಾಯಿಸಲು ಇಚ್ಛೆಯಿಲ್ಲದಿದ್ದರೆ, ದಯವಿಟ್ಟು $1 ಅನ್ನು ಪರೀಕ್ಷಿಸಿ.",
+'filename' => "ಕಡತದ ಹೆಸರು",
+'filenotfound' => "\"$1\" ಫೈಲನ್ನು ಹುಡುಕಲಾಗಲಿಲ್ಲ.",
+'filesource' => "ಆಕರ",
+'fileuploaded' => "ಫೈಲ್ \"$1\" ಯಶಸ್ವಿಯಾಗಿ ಅಪ್‍ಲೋಡ್ ಆಯಿತು. ದಯವಿಟ್ಟು ಕೆಳಗಿನ ಸ೦ಪರ್ಕವನ್ನು ಕ್ಲಿಕ್ಕಿಸಿ ಈ ಫೈಲ್ ನ ಬಗ್ಗೆ ಮಾಹಿತಿಯನ್ನು ತು೦ಬಿಸಿ. ಉದಾಹರಣೆಗೆ: ಈ ಫೈಲ್ ಎಲ್ಲಿ೦ದ ಬ೦ದಿತು, ಯಾವಾಗ ಯಾರಿ೦ದ ಸೃಷ್ಟಿಯಾದದ್ದು, ಮತ್ತು ನಿಮಗೆ ತಿಳಿದಿರುವ ಇತರ ಯಾವುದೇ ಮಾಹಿತಿ.
+
+$2",
+'formerror' => "ದೋಷ: ಅರ್ಜಿ ಕಳುಹಿಸಲಾಗಲಿಲ್ಲ",
+
+
+'getimagelist' => "ಚಿತ್ರಗಳ ಪಟ್ಟಿಯನ್ನು ಪಡೆಯಲಾಗುತ್ತಿದೆ",
+'go' => "ಹೋಗು",
+
+
+'headline_sample' => "ಶಿರೋಲೇಖ",
+'help' => "ಸಹಾಯ",
+'helppage' => "ಸಹಾಯ:ಪರಿವಿಡಿ",
+'hide' => "ಅಡಗಿಸು",
+'hidetoc' => "ಅಡಗಿಸು",
+'hist' => "ಇತಿಹಾಸ",
+'history' => "ಪುಟದ ಚರಿತ್ರೆ",
+'history_short' => "ಇತಿಹಾಸ",
+
+
+'ignorewarning' => "ಎಚ್ಚರಿಕೆಯನ್ನು ಕಡೆಗಣಿಸಿ ಫೈಲನ್ನು ಉಳಿಸಿ.",
+'ilsubmit' => "ಹುಡುಕು",
+'imagelist' => "ಚಿತ್ರಗಳ ಪಟ್ಟಿ",
+'imagepage' => "ಚಿತ್ರದ ಪುಟವನ್ನು ವೀಕ್ಷಿಸಿ",
+'import' => "ಪುಟಗಳನ್ನು ಅಮದು ಮಾಡಿ",
+'importfailed' => "ಆಮದು ಯಶಸ್ವಿಯಾಗಲಿಲ್ಲ: $1",
+'importnotext' => "ಖಾಲಿ ಅಥವಾ ಯಾವುದೇ ಶಬ್ಧಗಳಿಲ್ಲ",
+'importsuccess' => "ಆಮದು ಯಶಸ್ವಿಯಾಯಿತು!",
+'info_short' => "ಮಾಹಿತಿ",
+'internalerror' => "ಆ೦ತರಿಕ ದೋಷ",
+'ipblocklist' => "ಬ್ಲಾಕ್ ಮಾಡಲಾದ ಐಪಿ ವಿಳಾಸಗಳ ಹಾಗೂ ಬಳಕೆಯ ಹೆಸರುಗಳ ಪಟ್ಟಿ",
+'ipbreason' => "ಕಾರಣ",
+'ipbsubmit' => "ಈ ಸದಸ್ಯರನ್ನು ತಡೆಹಿಡಿಯಿರಿ",
+
+'last' => "ಕೊನೆಯ",
+'lastmodified' => "ಈ ಪುಟವನ್ನು ಕೊನೆಯಾಗಿ $1 ರಂದು ಬದಲಾಯಿಸಲಾಗಿತ್ತು.",
+'lineno' => "$1 ನೇ ಸಾಲು:",
+'link_sample' => "ಸಂಪರ್ಕದ ಹೆಸರು",
+'link_tip' => "ಆಂತರಿಕ ಸಂಪರ್ಕ",
+'linklistsub' => "(ಸ೦ಪರ್ಕಗಳ ಪಟ್ಟಿ)",
+'linkstoimage' => "ಈ ಕೆಳಗಿನ ಪುಟಗಳು ಈ ಚಿತ್ರಕ್ಕೆ ಸಂಪರ್ಕ ಹೊಂದಿವೆ:",
+'listform' => "ಪಟ್ಟಿ",
+'listusers' => "ಸದಸ್ಯ್ರರ ಪಟ್ಟಿ",
+'login' => "ಲಾಗ್ ಇನ್",
+'loginerror' => "ಲಾಗಿನ್ ದೋಷ",
+'loginproblem' => "<b>ನಿಮ್ಮ ಲಾಗಿನ್ ನಲ್ಲಿ ತೊ೦ದರೆಯಾಯಿತು.</b><br />ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ!",
+'loginreqtitle' => "ಲಾಗಿನ್ ಆಗಬೇಕು",
+'loginsuccess' => "ನೀವು ಈಗ \"$1\" ಆಗಿ ವಿಕಿಪೀಡಿಯಕ್ಕೆ ಲಾಗಿನ್ ಆಗಿದ್ದೀರಿ.",
+'loginsuccesstitle' => "ಲಾಗಿನ್ ಯಶಸ್ವಿ",
+'logout' => "ಲಾಗ್ ಔಟ್",
+'logouttitle' => "ಸದಸ್ಯ ಲಾಗೌಟ್",
+'lonelypages' => "ಒಬ್ಬಂಟಿ ಪುಟಗಳು",
+'longpages' => "ಉದ್ದನೆಯ ಪುಟಗಳು",
+
+
+'mailmypassword' => "ಹೊಸ ಪ್ರವೇಶ ಪದವನ್ನು ಇ-ಅಂಚೆ ಮೂಲಕ ಕಳುಹಿಸಿ",
+'mainpagetext' => "ವಿಕಿ ತ೦ತ್ರಾ೦ಶವನ್ನು ಯಶಸ್ವಿಯಾಗಿ ಅನುಸ್ಥಾಪಿಸಲಾಯಿತು.",
+'maintenance' => "ನಿರ್ವಹಣಾ ಪುಟ",
+'maintenancebacklink' => "ನಿರ್ವಹಣಾ ಪುಟಕ್ಕೆ ಹಿ೦ದಿರುಗಿ",
+'makesysopname' => "ಸದಸ್ಯನ ಹೆಸರು:",
+'minlength' => "ಚಿತ್ರಗಳ ಹೆಸರಿನಲ್ಲಿ ಕನಿಷ್ಟ ಮೂರು ಅಕ್ಷರಗಳಿರಬೇಕು.",
+'minoredit' => "ಇದು ಚುಟುಕಾದ ಬದಲಾವಣೆ",
+'moredotdotdot' => "ಇನ್ನಷ್ಟು...",
+'move' => "ಸ್ಥಳಾಂತರಿಸಿ",
+'movearticle' => "ಪುಟವನ್ನು ಸ್ಥಳಾಂತರಿಸಿ",
+'movenologintext' => "ಪುಟವನ್ನು ಸ್ಥಳಾ೦ತರಿಸಲು ನೀವು ನೋ೦ದಾಯಿತ ಸದಸ್ಯರಾಗಿದ್ದು <a href=\"/wiki/Special:Userlogin\">ಲಾಗಿನ್</a> ಆಗಿರಬೇಕು.",
+'movepage' => "ಪುಟವನ್ನು ಸ್ಥಳಾಂತರಿಸಿ",
+'movepagebtn' => "ಪುಟವನ್ನು ಸ್ಥಳಾಂತರಿಸಿ",
+'movethispage' => "ಈ ಪುಟವನ್ನು ಸ್ಥಳಾಂತರಿಸಿ",
+'mycontris' => "ನನ್ನ ಕಾಣಿಕೆಗಳು",
+'mypage' => "ನನ್ನ ಪುಟ",
+'mytalk' => "ನನ್ನ ಚರ್ಚೆ",
+
+
+'navigation' => "ಸಂಚರಣೆ",
+'nchanges' => "$1 ಬದಲಾವಣೆಗಳು",
+'newarticle' => "(ಹೊಸತು)",
+'newmessages' => "ನಿಮಗೆ $1 ಇವೆ.",
+'newmessageslink' => "ಹೊಸ ಸಂದೇಶಗಳು",
+'newpage' => "ಹೊಸ ಪುಟ",
+'newpageletter' => "ಹೊ",
+'newpages' => "ಹೊಸ ಪುಟಗಳು",
+'newpassword' => "ಹೊಸ ಪ್ರವೇಶ ಪದ",
+'newusersonly' => " (ಹೊಸ ಸದಸ್ಯರು ಮಾತ್ರ)",
+'newwindow' => "(ಹೊಸ ಕಿಟಕಿಯನ್ನು ತೆರೆಯುತ್ತದೆ)",
+'next' => "ಮುಂದಿನದು",
+'nextn' => "ಮು೦ದಿನ $1",
+'nextpage' => "ಮು೦ದಿನ ಪುಟ ($1)",
+'nlinks' => "$1 ಸ೦ಪರ್ಕಗಳು",
+'noarticletext' => "(ಈ ಪುಟದಲ್ಲಿ ಸದ್ಯಕ್ಕೆ ಏನೂ ಇಲ್ಲ)",
+'nosuchuser' => "\"$1\" ಹೆಸರಿನ ಯಾವ ಸದಸ್ಯರೂ ಇಲ್ಲ.
+ಕಾಗುಣಿತವನ್ನು ಪರೀಕ್ಷಿಸಿ, ಅಥವಾ ಕೆಳಗಿನ ಫಾರ್ಮ್ ಅನ್ನು ಉಪಯೋಗಿಸಿ ಹೊಸ ಸದಸ್ಯತ್ವವನ್ನು ಸೃಷ್ಟಿಸಿ.",
+'note' => "<strong>ಸೂಚನೆ:</strong>",
+'notloggedin' => "ಲಾಗಿನ್ ಆಗಿಲ್ಲ",
+'nstab-category' => "ವರ್ಗ",
+'nstab-help' => "ಸಹಾಯ",
+'nstab-image' => "ಚಿತ್ರ",
+'nstab-main' => "ಲೇಖನ",
+'nstab-mediawiki' => "ಸಂದೇಶ",
+'nstab-special' => "ವಿಶೇಷ",
+'nstab-user' => "ಸದಸ್ಯರ ಪುಟ",
+'nstab-wp' => "ಬಗ್ಗೆ",
+
+
+'ok' => "ಸರಿ",
+'oldpassword' => "ಹಳೆಯ ಪ್ರವೇಶ ಪದ",
+'orphans' => "ಒಬ್ಬ೦ಟಿ ಪುಟಗಳು",
+'othercontribs' => "$1 ರ ಕೆಲಸವನ್ನು ಆಧರಿಸಿ.",
+'otherlanguages' => "ಇತರ ಭಾಷೆಗಳು",
+
+
+'pagemovedsub' => "ಸ್ಥಳಾ೦ತರಿಸುವಿಕೆ ಯಶಸ್ವಿಯಾಯಿತು",
+'popularpages' => "ಜನಪ್ರಿಯ ಪುಟಗಳು",
+'portal' => "ಸಮುದಾಯ ಪುಟ",
+'postcomment' => "ನಿಮ್ಮ ಮಾತನ್ನು ಲಗತ್ತಿಸಿ",
+'powersearch' => "ಹುಡುಕಿ",
+'preview' => "ಮುನ್ನೋಟ",
+'previewnote' => "ಇದು ಕೇವಲ ಮುನ್ನೋಟ, ಪುಟವನ್ನು ಇನ್ನೂ ಉಳಿಸಲಾಗಿಲ್ಲ ಎ೦ಬುದನ್ನು ಮರೆಯದಿರಿ!",
+'protect' => "ಸಂರಕ್ಷಿಸು",
+'protectcomment' => "ಸ೦ರಕ್ಷಿಸಲು ಕಾರಣ",
+'protectedpage' => "ಸ೦ರಕ್ಷಿತ ಪುಟ",
+
+
+'randompage' => "ಯಾದೃಚ್ಛಿಕ ಪುಟ",
+'rclinks' => "ಕೊನೆಯ $2 ದಿನಗಳಲ್ಲಿ ಮಾಡಿದ $1 ಕೊನೆಯ ಬದಲಾವಣೆಗಳನ್ನು ನೋಡಿ <br />$3",
+'rclistfrom' => "$1 ಇಂದ ಪ್ರಾರಂಭಿಸಿ ಮಾಡಲಾದ ಬದಲಾವಣೆಗಳನ್ನು ನೋಡಿ",
+'rcnote' => "ಕೊನೆಯ <strong>$2</strong> ದಿನಗಳಲ್ಲಿ ಮಾಡಿದ <strong>$1</strong> ಬದಲಾವಣೆಗಳು ಕೆಳಗಿನಂತಿವೆ.",
+'recentchanges' => "ಇತ್ತೀಚೆಗಿನ ಬದಲಾವಣೆಗಳು",
+'recentchangescount' => "ಇತ್ತೀಚೆಗಿನ ಬದಲಾವಣೆಗಳಲ್ಲಿರುವ ವಿಷಯಗಳ ಸಂಖ್ಯೆ",
+'recentchangeslinked' => "ಸಂಬಂಧಪಟ್ಟ ಬದಲಾವಣೆಗಳು",
+'recentchangestext' => "ವಿಕಿಗೆ ಮಾಡಲ್ಪಟ್ಟ ಇತ್ತೀಚಿನ ಬದಲಾವಣೆಗಳನ್ನು ಈ ಪುಟದಲ್ಲಿ ನೀವು ಕಾಣಬಹುದು.",
+'returnto' => "$1 ಗೆ ಹಿಂತಿರುಗಿ.",
+'rights' => "ಹಕ್ಕುಗಳು:",
+
+
+'savearticle' => "ಪುಟವನ್ನು ಉಳಿಸಿ",
+'savefile' => "ಕಡತವನ್ನು ಉಳಿಸಿ",
+'search' => "ಹುಡುಕು",
+'searchresults' => "ಶೋಧನೆಯ ಫಲಿತಾಂಶಗಳು",
+'shortpages' => "ಪುಟ್ಟ ಪುಟಗಳು",
+'show' => "ತೋರಿಸು",
+'showhideminor' => "ಚುಟುಕು ಬದಲಾವಣೆಗಳನ್ನು $1 | ಬಾಟ್‌ಗಳನ್ನು $2 | ಲಾಗಿನ್ ಆಗಿರುವ ಸದಸ್ಯರನ್ನು $3 | $4 patrolled edits",
+'showpreview' => "ಮುನ್ನೋಟ",
+'showtoc' => "ತೋರಿಸು",
+'sitestats' => "ತಾಣದ ಅಂಕಿಅಂಶಗಳು",
+'sitestatstext' => "ಒಟ್ಟು '''$1''' ಪುಟಗಳು ಡೇಟಾಬೇಸ್‌ನಲ್ಲಿವೆ.
+ಈ ಸಂಖ್ಯೆ \"ಚರ್ಚೆ\" ಪುಟಗಳನ್ನು, ವಿಕಿಪೀಡಿಯಾದ ಬಗೆಗಿನ ಪುಟಗಳನ್ನು, ಹಾಗೂ ಪುಟ್ಟ \"ಚುಟುಕು\" ಪುಟಗಳನ್ನೂ, ರೆಡೈರೆಕ್ಟ್ ಮಾಡಿದ ಪುಟಗಳನ್ನು ಹಾಗೂ ಬೇರೆಲ್ಲೂ ಸೇರಿಸಲಾಗದ ಕೆಲವು ಇತರೆ ಪುಟಗಳನ್ನು ಒಳಗೊಂಡಿದೆ.
+
+ಇವುಗಳನ್ನು ಬಿಟ್ಟು, ಒಟ್ಟು '''$2''' ಬಹುಶಃ ನಿಜವಾದ ಲೇಖನಗಳಿಂದ ಕೂಡಿದ ಪುಟಗಳಿವೆ.",
+'sitesubtitle' => "ಒಂದು ಮುಕ್ತ ವಿಶ್ವಕೋಶ",
+'sitesupport' => "ದೇಣಿಗೆ",
+'sitetitle' => "ವಿಕಿಪೀಡಿಯ",
+'specialpage' => "ವಿಶೇಷ ಪುಟ",
+'specialpages' => "ವಿಶೇಷ ಪುಟಗಳು",
+'spheading' => "ಎಲ್ಲಾ ಸದಸ್ಯರಿಗೂ ಇರುವ ವಿಶೇಷ ಪುಟಗಳು",
+'statistics' => "ಅಂಕಿ ಅಂಶಗಳು",
+'storedversion' => "ಈಗಾಗಲೇ ಉಳಿಸಲಾಗಿರುವ ಆವೃತ್ತಿ",
+'subcategories' => "ಉಪವಿಭಾಗಗಳು",
+'subcategorycount' => "ಒಟ್ಟು $1 ಉಪವಿಭಾಗಗಳು ಈ ವರ್ಗದಡಿ ಇವೆ.",
+'summary' => "ಸಾರಾಂಶ",
+
+
+'tableform' => "ಟೇಬಲ್",
+'talkpage' => "ಈ ಪುಟದ ಬಗ್ಗೆ ಚರ್ಚೆ ಮಾಡಿ",
+'timezonelegend' => "ಟೈಮ್ ಝೋನ್",
+'toc' => "ಪರಿವಿಡಿ",
+'toolbox' => "ಉಪಕರಣ",
+
+
+'uctop' => " (ಮೇಲಕ್ಕೆ)",
+'uncategorizedpages' => "ವರ್ಗ ಗೊತ್ತು ಮಾಡದ ಪುಟಗಳು",
+'unprotect' => "ಸಂರಕ್ಷಣೆ ತೆಗೆ",
+'unusedimages' => "ಉಪಯೋಗಿಸದ ಚಿತ್ರಗಳು",
+'unwatch' => "ವೀಕ್ಷಣಾ ಪಟ್ಟಿಯಿಂದ ತೆಗೆ",
+'upload' => "ಫೈಲ್ ಅಪ್ಲೋಡ್",
+'userlogin' => "ಲಾಗ್ ಇನ್",
+'userlogout' => "ಲಾಗ್ ಔಟ್",
+'userstats' => "ಸದಸ್ಯರ ಅಂಕಿ ಅಂಶ",
+'userstatstext' => "ಒಟ್ಟು '''$1''' ನೊಂದಾಯಿಸಿದ ಸದಸ್ಯರಿದ್ದಾರೆ. ಇವರಲ್ಲಿ '''$2''' ಮಂದಿ ನಿರ್ವಾಹಕರಿದ್ದಾರೆ ($3 ನೋಡಿ).",
+
+
+'version' => "ಆವೃತ್ತಿ",
+'viewsource' => "ಆಕರ ವೀಕ್ಷಿಸು",
+
+
+'wantedpages' => "ಬೇಕಾಗಿರುವ ಪುಟಗಳು",
+'watch' => "ವೀಕ್ಷಿಸಿ",
+'watchthis' => "ಈ ಪುಟವನ್ನು ವೀಕ್ಷಿಸಿ",
+'watchthispage' => "ಈ ಪುಟವನ್ನು ವೀಕ್ಷಿಸಿ",
+'whatlinkshere' => "ಇಲ್ಲಿಗೆ ಯಾವ ಸಂಪರ್ಕ ಕೂಡುತ್ತದೆ",
+
+
+'yourname' => "ನಿಮ್ಮ ಬಳಕೆಯ ಹೆಸರು",
+'yourpassword' => "ನಿಮ್ಮ ಪ್ರವೇಶಪದ",
+);
+
+class LanguageKn extends LanguageUtf8 {
+       var $digitTransTable = array(
+               '0' => '೦',
+               '1' => '೧',
+               '2' => '೨',
+               '3' => '೩',
+               '4' => '೪',
+               '5' => '೫',
+               '6' => '೬',
+               '7' => '೭',
+               '8' => '೮',
+               '9' => '೯'
+       );
+
+       function getMessage( $key ) {
+               global $wgAllMessagesKn;
+               if( array_key_exists( $key, $wgAllMessagesKn ) )
+                       return $wgAllMessagesKn[$key];
+               else
+                       return parent::getMessage($key);
+       }
+
+       function formatNum( $number ) {
+               global $wgTranslateNumerals;
+               if( $wgTranslateNumerals ) {
+                       return strtr( $number, $this->digitTransTable );
+               } else {
+                       return $number;
+               }
+       }
+}
+
+?>
diff --git a/languages/LanguageKo.php b/languages/LanguageKo.php
new file mode 100644 (file)
index 0000000..8395484
--- /dev/null
@@ -0,0 +1,724 @@
+<?php
+/** Korean (한국어)
+  *
+  * @package MediaWiki
+  * @subpackage Language
+  */
+require_once('LanguageUtf8.php');
+
+/* private */ $wgNamespaceNamesKo = array(
+       NS_MEDIA            => 'Media',
+       NS_SPECIAL        => '특수기능',
+       NS_MAIN      => '',
+       NS_TALK      => '토론',
+       NS_USER      => '사용자',
+       NS_USER_TALK    => '사용자토론',
+       NS_PROJECT        => $wgMetaNamespace,
+       NS_PROJECT_TALK     => "${wgMetaNamespace}토론",
+       NS_IMAGE            => '그림',
+       NS_IMAGE_TALK       => '그림토론',
+       NS_CATEGORY      => '분류',
+       NS_CATEGORY_TALK    => '분류토론',
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgQuickbarSettingsKo = array(
+       '없음', '왼쪽 붙박이', '오른쪽 붙박이', '왼쪽 떠다님'
+
+);
+
+/* private */ $wgSkinNamesKo = array(
+       'standard' => '보통',
+       'nostalgia' => '그리움',
+       'cologneblue' => '쾰른 파랑',
+) + $wgSkinNamesEn;
+
+
+/* private */ $wgBookstoreListKo = array(
+       'Aladdin.co.kr' => 'http://www.aladdin.co.kr/catalog/book.asp?ISBN=$1'
+) + $wgBookstoreListEn;
+
+
+
+# (Okay, I think I got it right now. This can be adjusted
+#  in the 'date' function down at the bottom. --Brion)
+#
+# Thanks. And it's usual that the time comes after dates.
+# So I've change the timeanddate function, just exchanged $time and $date
+# But you should check before you install it, 'cause I'm quite stupid about
+# the programming.
+#
+
+/* private */ $wgWeekdayAbbreviationsKo = array(
+       '日', '月', '火', '水', '木',
+       '金', '土'
+);
+
+# I'll leave this part in english, for it's more likely that
+# there will probably no Korean for the maintaining this site
+# in near future, and if any shows up, he would possibly speak
+# both Korean and English. And he can later koreanize this part.
+
+/* private */ $wgAllMessagesKo = array(
+
+# User Toggles
+
+'tog-underline' => '고리에 밑줄치기',
+'tog-highlightbroken' => '없는 문서로의 고리 돋보이기',
+'tog-justify' => '문단 정렬',
+'tog-hideminor' => '사소한 편집 최근 바뀜에서 숨기기',
+'tog-numberheadings' => '머릿글 번호 매기기',
+'tog-showtoolbar' => 'Show edit toolbar',
+'tog-rememberpassword' => '세션동안 암호 기억',
+'tog-editwidth' => '편집상자 너비 최대',
+# Dates
+
+'sunday' => '일요일',
+'monday' => '월요일',
+'tuesday' => '화요일',
+'wednesday' => '수요일',
+'thursday' => '목요일',
+'friday' => '금요일',
+'saturday' => '토요일',
+'january' => '1월',
+'february' => '2월',
+'march' => '3월',
+'april' => '4월',
+'may_long' => '5월',
+'june' => '6월',
+'july' => '7월',
+'august' => '8월',
+'september' => '9월',
+'october' => '10월',
+'november' => '11월',
+'december' => '12월',
+'jan' => '1',
+'feb' => '2',
+'mar' => '3',
+'apr' => '4',
+'may' => '5',
+'jun' => '6',
+'jul' => '7',
+'aug' => '8',
+'sep' => '9',
+'oct' => '10',
+'nov' => '11',
+'dec' => '12',
+# Bits of text used by many pages:
+#
+'subcategories' => '하위 분류',
+
+
+'mainpage'         => '대문',
+'about'                       => '소개',
+'aboutsite'      => '{{SITENAME}}란',
+'aboutpage'       => '{{ns:4}}:소개',
+'help'                 => '도움말',
+'helppage'         => '{{ns:4}}:도움말',
+'bugreports'  => '벌레 발견',
+'bugreportspage' => '{{ns:4}}:벌레_발견',
+'faq'           => '잦은질문(FAQ)',
+'faqpage'           => '{{ns:4}}:잦은질문(FAQ)',
+'edithelp'         => '편집 도움말',
+'edithelppage' => '{{ns:4}}:문서_편집_방법',
+'cancel'             => '취소',
+'qbfind'             => '찾기',
+
+# where does this 'browse' appear? I haven't seen it.
+# and therefore no idea what its function is.
+
+# (Select the Cologne Blue skin; it's a section header
+#  in the sidebar over 'main page', 'recent changes', etc.)
+
+'qbbrowse'         => '항해판',
+'qbedit'             => '고치기',
+'qbpageoptions' => '문서 기능',
+'qbpageinfo'  => '문서 정보',
+'qbmyoptions' => '자기 기능',
+'mypage'             => '자기 문서',
+'mytalk'             => '자기 토론',
+'currentevents' => '요즘의 화제',
+'errorpagetitle' => '오류',
+'returnto'         => '$1(으)로 돌아가기.',
+'tagline'           => '{{SITENAME}}, 우리 모두의 백과사전.',
+'whatlinkshere'       => '여길 가리키는 문서',
+'help'                 => '도움말',
+'search'             => '찾기',
+'history'           => '문서역사',
+'printableversion' => '인쇄용',
+'editthispage' => '문서 고치기',
+'deletethispage' => '문서 지우기',
+'protectthispage' => '문서 보호',
+'unprotectthispage' => '문서 보호 해제',
+'talkpage'         => '토론',
+'subjectpage' => '본 문서',
+'otherlanguages' => '다른 언어',
+'redirectedfrom' => '($1에서 넘어옴.)',
+'lastmodified' => '이 문서는 최근 $1에 바뀌었습니다.',
+
+'viewcount'       => '이 문서는 총 $1번 읽혔습니다.',
+'printsubtitle' => '({{SERVER}}에서)',
+'protectedpage' => '보호되는 문서',
+'administrators' => '{{ns:4}}:관리자',
+'sysoptitle'  => 'Sysop 권한 필요',
+'sysoptext'       => '해당 action은 \'Sysop\'만 실행할 수 있습니다.
+참조 $1.',
+'developertitle' => 'Developer 권한 필요',
+'developertext'       => '해당 action은 \'developer\'만 실행할 수 있습니다.
+참조 $1.',
+'nbytes'             => '$1 바이트',
+'go'             => '가기',
+'ok'             => '확인',
+'sitetitle'       => '{{SITENAME}}',
+'sitesubtitle' => '우리 모두의 백과사전',
+'retrievedfrom' => '\'$1\'에서',
+
+# Main script and global functions
+#
+'nosuchaction' => '그런 action은 없습니다.',
+'nosuchactiontext' => '{{SITENAME}} 무른모는 URL로 주어진 action을
+모릅니다.',
+'nosuchspecialpage' => '틀린 특수기능',
+'nospecialpagetext' => '{{SITENAME}}는 요청한 특수기능을
+모릅니다.',
+
+# Login and logout pages
+#
+'logouttitle' => '나옴',
+'logouttext'  => '{{SITENAME}}에서 나왔습니다.
+이대로 이름없이 {{SITENAME}}를 이용하거나, 방금 사용했던 또이름, 혹은 다른 또이름으로 들어가서 이용하세요.\n',
+
+'welcomecreation' => '<h2>$1 님, 환영합니다!</h2><p>또이름이 만들어 졌습니다.
+개인 맞춤에서 자잘한 환경들을 바꾸어 보세요.',
+
+'loginpagetitle' => '들어가기',
+'yourname'         => '또이름은',
+'yourpassword' => '암호는',
+'yourpasswordagain' => '암호 또 한번',
+'newusersonly' => ' (새내기 사용자)',
+'remembermypassword' => '세쎤동안 암호를 기억합니다.',
+'loginproblem' => '<b>들어가는 데 문제가 있습니다.</b><br />다시 해 보세요!',
+'alreadyloggedin' => '<strong>$1 님, 벌써 들어와 있습니다!</strong><br />\n',
+
+'login'                       => '들어가기',
+'userlogin'       => '들어가기',
+'logout'             => '나가기',
+'userlogout'  => '나오기',
+'createaccount'       => '또이름 새로 만들기',
+'badretype'       => '암호가 서로 다릅니다.',
+'userexists'  => '또이름이 벌써 사용중입니다. 다른 또이름을 지으세요.',
+'youremail'       => '당신의 누리편지',
+'yournick'         => '당신의 별명 (서명용)',
+'emailforlost' => '암호를 잊었을 때, 새 암호를 누리편지로 받을 수 있습니다.',
+'loginerror'  => '들어가기 오류',
+'noname'             => '또이름이 틀립니다.',
+'loginsuccesstitle' => '들어가기 성공',
+'loginsuccess' => '\'$1\' {{SITENAME}}에 들어왔습니다.',
+'nosuchuser'  => '\'$1\'란 또이름은 없습니다.'.
+'철자가 맞는지 확인하고, 아직 또이름이 없다면, 아래를 채워 또이름을 새로이 만드세요.',
+'wrongpassword'       => '암호가 틀립니다. 다시 시도하세요.',
+'mailmypassword' => '새 암호를 누리편지로 보냅니다.',
+'passwordremindertitle' => '{{SITENAME}}에서 보내는 새 암호',
+'passwordremindertext' => '누군가가 (IP $1 을 사용했던, 아마도 당신이)
+새 {{SITENAME}} 암호를 보내달라고 부탁했습니다.
+또이름 \'$2\'의 암호는 이제 \'$3\'입니다.
+새 암호로 {{SITENAME}}에 들어와서, 암호를 바꾸세요.',
+'noemail'           => '또이름 \'$1\'에 딸린 누리편지주소정보가 없습니다.',
+'passwordsent' => '\'$1\'의 새 암호를 누리편지로 보냈습니다.
+암호를 받고 다시 들어오세요.',
+
+# Edit pages
+#
+'summary'           => '바꾼내용 간추리기',
+'minoredit'       => '사소한 편집',
+'savearticle' => '저장',
+'preview'           => '미리보기',
+'showpreview' => '미리보기',
+'blockedtitle' => '사용자 접근금지',
+'blockedtext' => '$1 가 당신의 또이름이나 IP를 막았습니다.
+이유는 다음과 같습니다:<br />$2<p> 접근금지에 대해선 관리자와 상의하십시오.',
+'newarticle'  => '(새문서)',
+'newarticletext' => '새문서에 내용을 써 넣으세요.',
+'noarticletext' => '(현재 문서는 비어 있습니다.)',
+'updated'           => '(바뀜)',
+'note'                 => '<strong>주의:</strong> ',
+'previewnote' => '지금 미리보기로 보고 있는 내용은 아직 저장되지 않았습니다!',
+
+# when does this message show up? I have encountered it yet, I guess.
+# And what does it have to do with conflict? The message sound quite normal.
+# (I don't think it _can_ show up. It's only used if you preview and get
+# an edit conflict, but edit conflict is tripped only if you're saving.)
+'previewconflict' => 'This preview reflects the text in the upper
+text editing area as it will appear if you choose to save.',
+
+'editing'           => '$1 고쳐쓰기',
+'editconflict' => '고치기 충돌: $1',
+'explainconflict' => '문서를 고쳐쓰는 동안, 문서가 바뀌었습니다.
+위쪽이 바뀐 현재 문서이고, 아래쪽이 당신이 고쳐쓴 내용입니다.
+당신이 고쳐쓴 내용을 현재 문서에 다시 집어 넣어야 할 것입니다.
+지금 \'저장\'을 눌러도,
+<strong>오직</strong> 위쪽에 있는 내용만 저장됩니다.<br />',
+'yourtext'         => '당신이 고쳐쓴 것',
+'storedversion' => '바뀐 현재 문서',
+'editingold'  => '<strong>경고: 지금 옛날 버젼의 문서를 고치고 있습니다.
+만약, 지금 여기서 저장을 하면, 그 때 이후의 모든 버젼을 잃게 됩니다.</strong>',
+'yourdiff'         => '차이',
+'copyrightwarning' => '{{SITENAME}}에 당신이 기여한 것은 모두 GNU 자유 문서 사용허가서(GFDL)
+($1참조)에 따라 배포됩니다.
+당신이 써 넣은 내용이 제한없이 고쳐지고, 재배포되는 것이 싫다면, 저장하지 마십시오.에 반대할 때에는, 여기에 쓰지 마시길 바랍니다.<br />
+또한, 여기 써 넣은 내용을 스스로 썼음을, 혹은 모두에게 공개된 자료에서 빌어왔음을
+같이 약속해야 합니다.
+<strong>저작권의 보호를 받는 내용을 저작권자의 허가없이 보내지 마십시오!</strong>',
+
+
+# History pages
+#
+'revhistory'  => '바뀐역사',
+'nohistory'       => '이 문서는 역사가 없습니다.',
+'revnotfound' => '버젼 찾지 못함',
+'revnotfoundtext' => '요청한 이 문서의 옛 버젼을 찾지 못했습니다.
+이 문서에 접근할 때의 URL을 확인해 주십시오.\n',
+'loadhist'         => '문서역사를 받고 있습니다.',
+'currentrev'  => '현재 버젼',
+'revisionasof' => '$1 버젼',
+'cur'           => '현재',
+'next'                 => '다음',
+'last'                 => '이전',
+'orig'                 => '처음',
+'histlegend'  => '상세설명: (현재) = 현재 버젼과의 차이,
+(이전) = 바로 이전 버전과의 차이, 少 = 사소한 편집',
+
+# Diffs
+#
+'difference'  => '(버젼사이 차이)',
+'loadingrev'  => '버젼 차이를 받고 있습니다.',
+'lineno'             => '$1째 줄:',
+'editcurrent' => '현재 버전의 문서를 고칩니다.',
+
+# Search results
+#
+'searchresults' => '찾아본 결과',
+'searchresulttext' => '{{SITENAME}} 찾기에 대해 자세한 정보는 [[Project:찾기|{{SITENAME}} 찾기]] 를 보세요.',
+'searchquery' => '열쇠말 \'$1\'',
+'badquery'         => '좋지 않은 열쇠말',
+
+# I think we should enable the less-than-3-letter query in Korean.
+# One korean letter corresponds to one syllable. And when I do a search
+# in google or yahoo. The query I type in is mostly 3, 4 of letters
+# and it works. I'll leave this part in English. I'll wait for the
+# software to be developed to be compitable three letter search.
+
+# It's really 3 bytes, not 3 letters. Any Korean letter in UTF-8 encoding
+# is 3 bytes, so in theory it should work. However, searches for Korean
+# text don't work anyway. I'll have to bang it into shape... --Brion
+
+# Then, one and a half, am I right?
+
+'matchtotals' => '열쇠말 \'$1\'이 제목에 들어있는 문서는 $2개 이고,
+내용에 담고있는 문서는 $3개 입니다.',
+'titlematches' => '문서 제목 일치',
+'notitlematches' => '제목과 맞는 문서가 없습니다.',
+'textmatches' => '문서 내용 일치',
+'notextmatches'       => '내용에 열쇠말을 담고 있은 문서가 없습니다.',
+'prevn'                       => '이전 $1',
+'nextn'                       => '다음 $1',
+'viewprevnext' => '($1) ($2) 보기 ($3).',
+'showingresults' => '<b>$2</b>번 부터 <b>$1</b>개의 결과 입니다.',
+'powersearch' => '찾기',
+
+# Preferences page
+#
+'preferences' => '개인 맞춤',
+'prefsnologin' => '나와 있습니다.',
+'prefsnologintext'    => '[[Special:Userlogin|들어와]] 있을 때에만,
+# Special:Userlogin => 특수기능:들어가기 개인 환경을 맞출 수 있습니다.',
+'prefslogintext' => '당신은 \'$1\', 맞죠?
+당신의 내부 ID 번호는 $2입니다.',
+'prefsreset'  => '개인 맞춤을 보통으로 되돌렸습니다.',
+'qbsettings'  => '빨리가기 맞춤',
+'changepassword' => '암호 바꾸기',
+'skin'                 => '옷',
+'saveprefs'       => '맞춤 저장',
+'resetprefs'  => '맞춤 보통으로',
+'oldpassword' => '현재 암호',
+'newpassword' => '새 암호',
+'retypenew'       => '새 암호 또 한번',
+'textboxsize' => '문서상자 크기',
+'rows'                 => '줄수',
+'columns'           => '너비',
+'searchresultshead' => '찾기 결과 맞춤',
+'resultsperpage' => '쪽마다 보이는 결과',
+'contextlines' => '결과마다 보이는 줄수',
+'contextchars' => '줄수마다 보이는 글잣수',
+'stubthreshold' => '씨앗보기 문턱값',
+'recentchangescount' => '최근 바뀜에 보이는 항목 수',
+'savedprefs'  => '새 설정을 저장했습니다.',
+'timezonetext' => '현지 시간과 서버 시간(UTC)과 차이를 써 넣으세요.',
+'localtime'   => '현지 시각',
+'timezoneoffset' => '시간차',
+'emailflag'       => '다른 사용자에게서 누리편지 안 받음',
+
+# Recent changes
+#
+'recentchanges' => '최근 바뀜',
+'recentchangestext' => '아래 나열된 문서들이 최근에 바뀌었습니다.
+
+[[{{ns:4}}:새내기_환영|새내기, 환영합니다]]!
+새내기들은 다음 문서를 읽어 보세요.: [[{{ns:4}}:잦은질문(FAQ)|{{SITENAME}} 잦은질문(FAQ)]],
+[[{{ns:4}}:정책과 지침|{{SITENAME}} 정책]]
+(특별히 [[{{ns:4}}:제목달기 규칙|제목달기 규칙]],
+[[{{ns:4}}:중립적인 시각|중립적인 시각]]),
+그리고 [[{{ns:4}}:범하기_쉬운_실수|범하기 쉬운 실수]].
+
+{{SITENAME}}가 성공하려면, 여러분이 저작권에 저촉되는 내용을 이곳에 써 넣지 않는 것이
+매우 중요합니다.\' [[{{ns:4}}:저작권|저작권]].
+법적 문제가 프로젝트를 망칠 수 있습니다. 저작권에 유의해 주세요.
+또, [http://meta.wikipedia.org/wiki/Special:Recentchanges 최근 메타 토론]도
+읽어 보세요.',
+'rcloaderr'       => '최근 바뀜을 받고 있습니다.',
+'rcnote'             => '다음이 최근 <strong>$2</strong>일간 바뀐  <strong>$1</strong>개의 문서입니다.',
+'rclinks'           => '최근 $2일 동안에 바뀐 $1개의 문서를 봅니다.',
+
+'diff'                 => '차이',
+'hist'                 => '역사',
+'hide'                 => '숨김',
+'show'                 => '보임',
+'tableform'       => '표로',
+'listform'         => '목록으로',
+'nchanges'         => '$1개 바뀜',
+'minoreditletter' => '少',
+'newpageletter' => '新',
+
+# Upload
+#
+'upload'             => '올리기',
+'uploadbtn'       => '파일 올리기',
+'uploadlink'  => '그림 올리기',
+'reupload'         => '다시 올리기',
+'reuploaddesc' => '올리기 틀로 돌아감',
+'uploadnologin' => '나와있습니다.',
+'uploadnologintext'   => '{{SITENAME}}에 [[Special:Userlogin|들어와]] 있을 때에만
+# special:userlogin 특수기능:들어가기
+파일을 올릴 수 있습니다.',
+'uploaderror' => '올리기 오류',
+'uploadtext'  => "'''잠깐!''' 여기 그림을 올리기 전에,
+{{SITENAME}}의 [[Project:Image_use_policy|그림 사용 정책]]읽고 따라 주세요.
+
+이미 올라온 그림을 찾아 보려면, [[Special:Imagelist|올라온 그림 목록]]으로 가세요.
+# Special:Image list  특수기능:그림_목록
+그림을 올리거나 지우면 [[Project:올리기_기록|올리기 기록]]에 그 사실이 남습니다.
+# {{ns:4}}:올리기_기록 {{ns:4}}:올리기_기록
+
+밑에 있는 틀을 이용해서 문서에 담을 파일을 올리세요.
+대부분의 누리그물 훑개(browser)는, 아래 \'찾아보기...\' (영문 \'Browse...\') 단추로
+ 자기 컴퓨터의 파일을 찾게 해 줍니다.
+원하는 파일을 고르면, 단추 옆의 공간에 파일이름이 채워질 것입니다.
+또한, 저작권에 저촉되지 않는 파일을 올린다는 사실도
+확인해야 합니다.
+마지막으로, \'올리기\' 단추를 누르면 올라갑니다. 누리그물 연결이 느리면,
+시간이 걸릴 수 있습니다.
+
+{{SITENAME}}는 사진은 JPEG형식을, 보통 그림, 아이콘은 PNG형식을, 소리는
+OGG형식을 더 좋아합니다.
+이름은 햇갈리지 않고, 내용을 잘 나타내는 것으로 지어주세요. 그림을 문서에
+담을 때에는 '''[[image:file.jpg]]''' 또는 '''[[image:file.png|alt text]]'''
+처럼, 소리를 담을 때에는'''[[media:file.ogg]]'''처럼 써서 고리를 걸어주면
+됩니다.
+
+다른 사람들이 올린 파일을 고치거나 지울 수 있다는 것을 알아두십시오.
+또한, 시스템을 남용할 때에는, 파일 올리기가 금지될 수도 있습니다.
+",
+'uploadlog'       => '올리기 기록',
+'uploadlogpage' => '올리기_기록',
+'uploadlogpagetext' => '최근 올라온 그림 목록입니다.
+모든 시간은 서버 기준(UTC)입니다.
+<ul>
+</ul>
+',
+'filename'         => '파일이름',
+'filedesc'         => '짧은설명',
+'copyrightpage' => '{{ns:4}}:저작권',
+'copyrightpagename' => '{{SITENAME}} 저작권',
+'uploadedfiles'       => '파일 올리기',
+'ignorewarning'       => '경고 무시하고, 파일 저장',
+
+# three alphabets and how many for Korean character?
+'minlength'       => '그림이름은 두글자가 넘어야 합니다.',
+
+'badfilename' => '그림이름이 \'$1\'로 바뀌었습니다.',
+'badfiletype' => '\'.$1\' 형식은 권장하지 않습니다.',
+'largefile'       => '그림크기는 100k이하를 권장합니다.',
+'successfulupload' => '올리기 성공',
+'fileuploaded' => '\'$1\'가 올라갔습니다.
+다음 고리($2)를 따라 가서, 설명문서에 파일에 대한 정보를(어디서 구했는지,
+누가 언제 만들었는지, 또 그 이외 필요한 사항들을) 채우세요.',
+'uploadwarning' => '올리기 경고',
+'savefile'         => '파일 저장',
+'uploadedimage' => '\'[[$1]]\'를 올렸습니다.',
+
+# Image list
+#
+'imagelist'       => '그림 목록',
+'imagelisttext'       => '$2순으로 정리된 $1개의 그림입니다.',
+'getimagelist' => '그림 목록 가져오기',
+'ilsubmit'         => '찾기',
+'showlast'         => '$2순으로 이전 $1개의 그림 보이기',
+'byname'             => '이름',
+'bydate'             => '날짜',
+'bysize'             => '크기',
+'imgdelete'       => '지움',
+
+'imgdesc'           => '설명',
+'imglegend'       => '상세설명: (설명) = 그림 설명을 보입니다/고칩니다.',
+'imghistory'  => '그림역사',
+'revertimg'       => '돌림',
+'deleteimg'       => '지우기',
+'deleteimgcompletely'   => '지우기',
+'imghistlegend' => '상세설명: (현재) = 현재의 그림입니다, (지움) = 옛 버젼을 지웁니다, (돌림) = 옛 버젼으로 되돌려 놓습니다.
+<br /><i>특정 날짜에 올라온 그림을 보려면, 날짜를 찍어 주세요</i>.',
+'imagelinks'  => '그림고리',
+'linkstoimage' => '다음 문서들이 이 그림을 담고 있습니다:',
+'nolinkstoimage' => '이 그림을 담고 있는 문서는 없습니다.',
+
+# Statistics
+#
+'statistics'  => '통계',
+'sitestats'       => '누리터 통계',
+'userstats'       => '사용자 통계',
+'sitestatstext' => '이곳 정보창고(DB)에는 총 <b>$1</b>개의 문서가 있습니다.
+이 숫자는 \'토론\' 문서, {{SITENAME}} 자체에 관한 문서, 자라기를 기다리는 \'씨앗\' 문서,
+넘겨주기 문서, 그리고 아직 사전항목으로 부족한 문서들을 모두 포함한 것입니다.
+이들을 제외하면, <b>$2</b>개의 문서가 있습니다.<p>
+또, 무른모 업그레이드가 있었던 2002년 7월 20일 이래, 여러분은 총 <b>$3</b>번 문서를
+읽었고, <b>$4</b>번 고쳤습니다.
+따라서, 평균적으로 문서 하나가 <b>$5</b>번 바뀌었고, 한번 바뀔 때마다 <b>$6</b>번 읽힌
+셈이 됩니다.',
+'userstatstext' => '<b>$1</b>명의 사용자가 등록되어 있습니다.
+이 중 관리자는 <b>$2</b>명입니다.($3 참조)',
+
+
+# Miscellaneous special pages
+#
+'orphans'           => '외톨이 문서',
+'lonelypages' => '외톨이 문서',
+'unusedimages' => '안 쓰는 그림',
+'popularpages' => '인기있는 문서',
+'nviews'             => '$1 번 읽음',
+'wantedpages' => '필요한 문서',
+'nlinks'             => '$1개의 고리',
+'allpages'         => '모든 문서',
+'randompage'  => '아무거나',
+'shortpages'  => '짧은 문서',
+'longpages'       => '긴 문서',
+'listusers'       => '사용자들',
+'specialpages' => '특수기능문서',
+'spheading'       => '특수기능문서',
+'protectpage' => '보호된 문서',
+'recentchangeslinked' => '여기서 가리키는 문서',
+'rclsub'             => '(\'$1\'의 고리들이 가리키는)',
+'newpages'         => '새 문서',
+'movethispage' => '문서 옮기기',
+'unusedimagestext' => '<p>다음 그림중 어떤 것은, 다른 언어의 {{SITENAME}}등 다른
+누리터에서 URL바로걸기로 사용하고 있을 지도 모릅니다.',
+'booksources' => '외부 책방',
+'booksourcetext' => '새책이나 헌책을 파는 몇몇 누리터입니다. 찾고 있는 책의
+정보를 담고 있을 수 있습니다.
+{{SITENAME}}는 다음 중 어떤 기업과도 관련이 없으며,
+아래 목록이 상업적 광고로 오해되지 않기를 바랍니다.',
+
+# Email this user
+#
+'mailnologin' => '누리편지주소 없음',
+'mailnologintext' => '{{SITENAME}}에 [[Special:Userlogin|들어와]] 있을 때, 또,
+[[Special:Preferences|개인 맞춤]]에
+자기의 누리편지주소를 기억시켰을 때에만,
+다른 사용자에게 편지를 보낼 수 있습니다.',
+'emailuser'       => '사용자에게 편지쓰기',
+'emailpage'       => '누리편지 쓰기',
+'emailpagetext'       => '이 사용자가 개인맞춤에 옳바른 주소를 써 넣었다면,
+아래 틀을 이용하여 편지를 보낼 수 있습니다.
+이 사용자가 바로 답장할 수 있도록, 당신의 개인맞춤에 넣었던 주소가,
+\'보낸이\' 주소에 들어갑니다.',
+'noemailtitle' => '누리편지 없음',
+'noemailtext' => '이 사용자는 누리편지를 받지않음에 맞추어 놓았거나,
+옳바른 주소를 써 넣지 않았습니다.',
+'emailfrom'       => '보낸이',
+'emailto'           => '받는이',
+'emailsubject' => '제목',
+'emailmessage' => '편지내용',
+'emailsend'       => '보내기',
+'emailsent'       => '편지 보냄',
+'emailsenttext' => '누리편지를 보냈습니다.',
+
+# Watchlist
+#
+'watchlist'       => '눈여겨보기 목록',
+'watchlistsub' => '(\'$1\'의)',
+'nowatchlist' => '눈여겨보는 문서가 아직 없습니다.',
+'watchnologin' => '나와있습니다.',
+'watchnologintext'    => '[[Special:Userlogin|들어와]]
+있을 때에만 눈여겨보기 목록을 볼 수 있습니다.',
+'addedwatch'  => '눈여겨 봅니다.',
+'addedwatchtext' => '앞으로 \'$1\'문서와 딸린 토론를
+<a href=\'{{localurle:Special:Watchlist}}\'>눈여겨보기 목록</a>에서
+관찰할 수 있으며,<a href=\'{{localurle:Special:Recentchanges}}\'>최근 바뀜</a>에는 금방 눈에
+띄도록 <b>두터운 글씨체</b>로 나타납니다.</p>
+
+<p>더 이상 눈여겨 보지 않아도 될 때에는, 옆의 \'눈여겨 보지 않음\'을 누르면 됩니다.',
+'removedwatch' => '눈여겨 보지 않음',
+'removedwatchtext' => '\'$1\'를 더 이상 눈여겨 보지 않습니다.',
+'watchthispage'       => '눈여겨보기',
+'unwatchthispage' => '눈여겨 보지 않음',
+'notanarticle' => '문서가 아님',
+
+# Contributions
+#
+'contributions'       => '사용자 기여',
+'contribsub'  => '$1의',
+'nocontribs'  => '이 사용는 어디에도 기여하지 않았습니다.',
+'ucnote'             => '<b>$2</b>일 동안 이 사용자가 바꾼 <b>$1</b>개의 문서입니다.',
+'uclinks'           => '최근 $1개 보기; 최근 $2일 보기',
+
+# What links here
+#
+'whatlinkshere'       => '여길 가리키는 문서',
+'notargettitle' => '문서 없음',
+'notargettext' => '기능을 수행할 목표 문서나 목표 사용자를
+지정하지 않았습니다.',
+'linklistsub' => '(고리 목록)',
+'linkshere'       => '다음 문서들이 여기를 가리키고 있습니다.',
+'nolinkshere' => '어떤 문서도 이곳을 가리키지 않습니다.',
+'isredirect'  => '넘겨주기 문서',
+
+# Move page
+#
+'movepage'         => '문서 옮기기',
+'movepagetext' => '아래 틀을 채워 문서이름을 바꾸세요.
+문서역사도 함께 새문서로 갑니다.
+기존의 문서는 새이름의 문서로 넘겨주는 역할만 하는 넘겨주기 문서가 됩니다.
+기존 문서로의 고리도 바뀌지 않습니다. 딸린토론이 있어도, 옮기지
+않습니다.
+<b>경고!</b>
+인기있는 문서를 옮기면 예상치 못한 엄청난 결과를 가져올 수 있습니다.
+옮기는 것이 옳다는 확신이 들 때에만 진행하세요.',
+'movearticle' => '문서 옮기기',
+'movenologin' => '나와 있습니다.',
+'movenologintext' => '{{SITENAME}}에 [[Special:Userlogin|들어와]] 있을 때에만
+문서를 옮길 수 있습니다.',
+'newtitle'         => '새 이름',
+'movepagebtn' => '옮기기',
+'pagemovedsub' => '문서 옮김',
+'pagemovedtext' => '\'[[$1]]\'를 \'[[$2]]\'로 옮겼습니다.',
+'articleexists' => '그 이름의 문서가 이미 존재하거나, 새 이름이 옳바르지
+않습니다. 이름을 다시 지으세요.',
+'movedto'           => '새 이름',
+'movetalk'         => '딸린 \'토론\'도 함께 옮깁니다.',
+'talkpagemoved' => '딸린토론도 옮겼습니다.',
+'talkpagenotmoved' => '딸린토론은 옮기지 <strong>않았습니다</strong>.',
+
+# Spam protection
+
+'subcategorycount' => '이 분류에 $1 개의 하위분류가 있습니다.', #'There are $1 subcategories to this category.',
+'subcategorycount1' => '이 분류에 $1 개의 하위분류가 있습니다.', #'There is $1 subcategory to this category.',
+'categoryarticlecount' => '이 분류에 $1 개의 문서가 있습니다.', #'There are $1 articles in this category.',
+'categoryarticlecount1' => '이 분류에 $1 개의 문서가 있습니다.', #'There is $1 article in this category.',
+'listingcontinuesabbrev' => ' (계속)', #' cont.',
+
+);
+
+class LanguageKo extends LanguageUtf8 {
+
+       function getBookstoreList() {
+               global $wgBookstoreListKo;
+               return $wgBookstoreListKo;
+       }
+
+       function getNamespaces() {
+               global $wgNamespaceNamesKo;
+               return $wgNamespaceNamesKo;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsKo;
+               return $wgQuickbarSettingsKo;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesKo;
+               return $wgSkinNamesKo;
+       }
+
+       function date( $ts, $adj = false ) {
+               global $wgWeekdayAbbreviationsKo;
+               if ( $adj ) { $ts = $this->userAdjust( $ts ); }
+
+               # This is horribly inefficient; I need to rework this
+               $x = getdate(mktime(( (int)substr( $ts, 8, 2) ),
+                       (int)substr( $ts, 10, 2 ), (int)substr( $ts, 12, 2 ),
+                       (int)substr( $ts, 4, 2 ), (int)substr( $ts, 6, 2 ),
+                       (int)substr( $ts, 0, 4 )));
+
+               $d = substr( $ts, 0, 4 ) . "년 " .
+                       $this->getMonthAbbreviation( substr( $ts, 4, 2 ) ) . "월 " .
+                       (0 + substr( $ts, 6, 2 )) . "일 " .
+                       "(" . $wgWeekdayAbbreviationsKo[$x["wday"]] . ")";
+               return $d;
+       }
+
+       function timeanddate( $ts, $adj = false ) {
+               return $this->date( $ts, $adj ) . " " . $this->time( $ts, $adj );
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesKo;
+               return isset($wgAllMessagesKo[$key]) ? $wgAllMessagesKo[$key] : parent::getMessage($key);
+       }
+
+       function firstChar( $s ) {
+               preg_match( '/^([\x00-\x7f]|[\xc0-\xdf][\x80-\xbf]|' .
+               '[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xf7][\x80-\xbf]{3})/', $s, $matches);
+
+               if ( isset( $matches[1] ) ) {
+                       if ( strlen( $matches[1] ) != 3 ) {
+                               return $matches[1];
+                       }
+                       $code = (ord($matches[1]{0}) & 0x0f) << 12;
+                       $code |= (ord($matches[1]{1}) & 0x3f) << 6;
+                       $code |= (ord($matches[1]{2}) & 0x3f);
+                       if ( $code < 0xac00 || 0xd7a4 <= $code) {
+                               return $matches[1];
+                       } elseif ( $code < 0xb098 ) {
+                               return "\xe3\x84\xb1";
+                       } elseif ( $code < 0xb2e4 ) {
+                               return "\xe3\x84\xb4";
+                       } elseif ( $code < 0xb77c ) {
+                               return "\xe3\x84\xb7";
+                       } elseif ( $code < 0xb9c8 ) {
+                               return "\xe3\x84\xb9";
+                       } elseif ( $code < 0xbc14 ) {
+                               return "\xe3\x85\x81";
+                       } elseif ( $code < 0xc0ac ) {
+                               return "\xe3\x85\x82";
+                       } elseif ( $code < 0xc544 ) {
+                               return "\xe3\x85\x85";
+                       } elseif ( $code < 0xc790 ) {
+                               return "\xe3\x85\x87";
+                       } elseif ( $code < 0xcc28 ) {
+                               return "\xe3\x85\x88";
+                       } elseif ( $code < 0xce74 ) {
+                               return "\xe3\x85\x8a";
+                       } elseif ( $code < 0xd0c0 ) {
+                               return "\xe3\x85\x8b";
+                       } elseif ( $code < 0xd30c ) {
+                               return "\xe3\x85\x8c";
+                       } elseif ( $code < 0xd558 ) {
+                               return "\xe3\x85\x8d";
+                       } else {
+                               return "\xe3\x85\x8e";
+                       }
+               } else {
+                       return "";
+               }
+       }
+}
+
+?>
diff --git a/languages/LanguageKs.php b/languages/LanguageKs.php
new file mode 100644 (file)
index 0000000..082149b
--- /dev/null
@@ -0,0 +1,18 @@
+<?php
+/** Kashmiri language file ( कश्मीरी - (ﻚﺸﻤﻳﺮﻳ) )
+  *
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+require_once( 'LanguageUtf8.php' );
+
+class LanguageKs extends LanguageUtf8 {
+       #FIXME: inherit almost everything for now
+
+       function isRTL() {
+               return true;
+       }
+}
+
+?>
diff --git a/languages/LanguageKu.php b/languages/LanguageKu.php
new file mode 100644 (file)
index 0000000..074b5c7
--- /dev/null
@@ -0,0 +1,1650 @@
+<?php
+/** Kurdish language file ( كوردي )
+  *
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+require_once( "LanguageUtf8.php" );
+
+if ( $wgMetaNamespace == "Wikipedia" ) {
+       $wgMetaNamespace = "Wîkîpediya";
+}
+
+/* private */ $wgNamespaceNamesKu = array(
+       NS_MEDIA            => 'Medya',
+       NS_SPECIAL          => 'Taybet',
+       NS_MAIN             => '',
+       NS_TALK             => 'Nîqaş',
+       NS_USER             => 'Bikarhêner',
+       NS_USER_TALK        => 'Bikarhêner_nîqaş',
+       NS_PROJECT          => $wgMetaNamespace,
+       NS_PROJECT_TALK     => $wgMetaNamespace . '_nîqaş',
+       NS_IMAGE            => 'Wêne',
+       NS_IMAGE_TALK       => 'Wêne_nîqaş',
+       NS_MEDIAWIKI        => 'MediaWiki',
+       NS_MEDIAWIKI_TALK   => 'MediaWiki_nîqaş',
+       NS_TEMPLATE         => 'Şablon',
+       NS_TEMPLATE_TALK    => 'Şablon_nîqaş',
+       NS_HELP             => 'Alîkarî',
+       NS_HELP_TALK        => 'Alîkarî_nîqaş',
+       NS_CATEGORY         => 'Kategorî',
+       NS_CATEGORY_TALK    => 'Kategorî_nîqaş'
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgAllMessagesKy = array (
+
+# copied from wikipedia
+
+'1movedto2' => '$1 çû cihê $2',
+'1movedto2_redir' => '$1 çû cihê $2 ser redirect',
+'about' => 'Der barê',
+'aboutpage' => 'Wîkîpediya:Der barê',
+'aboutsite' => 'Der barê {{SITENAME}}',
+#'accesskey-compareselectedversions' => 'v',
+#'accesskey-diff' => 'd',
+#'accesskey-minoredit' => 'i',
+#'accesskey-preview' => 'p',
+#'accesskey-save' => 's',
+#'accesskey-search' => 'f',
+'accmailtext' => 'Şîfreya \'$1\' hat şandin ji $2 re.',
+'accmailtitle' => 'Şîfre hat şandin.',
+'acct_creation_throttle_hit' => 'Biborîne te hesab $1 vekirine. Tu êdî nikare hesabine din vekî.',
+'actioncomplete' => 'Çalakî temam',
+'addedwatch' => 'Hat îlawekirinî listeya şopandinê',
+/* 'addedwatchtext' => 'The page "$1" has been added to your [[Special:Watchlist|watchlist]].
+Future changes to this page and its associated Talk page will be listed there,
+and the page will appear \'\'\'bolded\'\'\' in the [[Special:Recentchanges|list of recent changes]] to
+make it easier to pick out.
+
+<p>If you want to remove the page from your watchlist later, click "Stop watching" in the sidebar.', */
+'addgroup' => 'Komê tevlî bike',
+#'addgrouplogentry' => 'Added group $2',
+#'addsection' => '+',
+'administrators' => 'Wîkîpediya:Koordînasyon',
+'affirmation' => 'Ez diyar dikim ku xwediya/ê mafên nivîsariya vê dosyayê destûra xwe ji bo weşandinê di bin şertên lîsansê GFDL de daye. Binihêre: $1.',
+'allarticles' => 'Hemû gotar',
+#'allinnamespace' => 'All pages ($1 namespace)',
+/* 'alllogstext' => 'Combined display of upload, deletion, protection, blocking, and sysop logs.
+You can narrow down the view by selecting a log type, the user name, or the affected page.', */
+'allmessages' => 'Hemû mesajên sîstemê',
+#'allmessagescurrent' => 'Current text',
+#'allmessagesdefault' => 'Default text',
+#'allmessagesname' => 'Name',
+#'allmessagesnotsupportedDB' => 'Special:AllMessages not supported because wgUseDatabaseMessages is off.',
+#'allmessagesnotsupportedUI' => 'Your current interface language <b>$1</b> is not supported by Special:AllMessages at this site. ',
+'allmessagestext' => 'Ev lîsteya hemû mesajên di namespace a MediaWiki: de ye.',
+#'allnonarticles' => 'All non-articles',
+#'allnotinnamespace' => 'All pages (not in $1 namespace)',
+'allpages' => 'Hemû rûpel',
+#'allpagesfrom' => 'Display pages starting at:',
+'allpagesnext' => 'Pêş',
+'allpagesprev' => 'Paş',
+'allpagessubmit' => 'Biçe',
+'alphaindexline' => '$1 heta $2',
+#'already_bureaucrat' => 'This user is already a bureaucrat',
+#'already_steward' => 'This user is already a steward',
+#'already_sysop' => 'This user is already an administrator',
+'alreadyloggedin' => '<strong>Bikarhêner $1, tu jixwe têketî!</strong><br />',
+/* 'alreadyrolled' => 'Cannot rollback last edit of [[$1]]
+by [[User:$2|$2]] ([[User talk:$2|Talk]]); someone else has edited or rolled back the page already.
+
+Last edit was by [[User:$3|$3]] ([[User talk:$3|Talk]]). ', */
+'ancientpages' => 'Gotarên kevintirîn',
+'and' => 'û',
+'anontalk' => 'Nîqaş ji bo vê IPê',
+'anontalkpagetext' => '----
+\'\'Ev rûpela nîqaşê ye ji bo bikarhênerên nediyarkirî ku hîn hesabekî xwe çênekirine an jî bikarnaînin. Ji ber vê yekê divê em wan bi [[IP address|navnîşana IP]] ya hejmarî nîşan bikin. Navnîşaneke IP dikare ji aliyê gelek kesan ve were bikaranîn. Heger tu bikarhênerekî nediyarkirî bî û bawerdikî ku nirxandinên bê peywend di der barê te de hatine kirin ji kerema xwe re [[Special:Userlogin|hesabekî xwe veke an jî têkeve Ensîklopediya Azad]] da ku tu xwe ji tevlîheviyên bi bikarhênerên din re biparêzî.\'\'',
+'anonymous' => 'Bikarhênera/ê nediyarkirî ya/yê wîkîpediyayê',
+'apr' => 'avr',
+'april' => 'avrêl',
+'article' => 'Gotar',
+'articleexists' => 'Rûpela bi vî navî heye, an navê ku te hilbijart derbas nabe. Navekî din hilbijêre.',
+'articlepage' => 'Li naveroka rûpelê binêre',
+'aug' => 'teb',
+'august' => 'tebax',
+#'autoblocker' => 'Autoblocked because you share an IP address with "$1". Reason "$2".',
+#'badaccess' => 'Permission error',
+/* 'badaccesstext' => 'The action you have requested is limited
+to users with the "$2" permission assigned.
+See $1.', */
+'badarticleerror' => 'Ev çalakî di vê rûpelê de nabe.',
+'badfilename' => 'Navê wêneyê hat guherandin û bû "$1".',
+'badfiletype' => 'Formata ".$1" naye tawsiye kirin. (Ji bo wêne .png û .jpg tên tawsiye kirin.)',
+'badipaddress' => 'Bikarhêner bi vî navî tune',
+#'badquery' => 'Badly formed search query',
+/* 'badquerytext' => 'We could not process your query.
+This is probably because you have attempted to search for a
+word fewer than three letters long, which is not yet supported.
+It could also be that you have mistyped the expression, for
+example "fish and and scales".
+Please try another query.', */
+'badretype' => 'Herdu şîfreyên ku te nivîsîn hevûdin nagirin.',
+'badtitle' => 'Sernivîsa nebaş',
+/* 'badtitletext' => 'The requested page title was invalid, empty, or
+an incorrectly linked inter-language or inter-wiki title.', */
+#'blanknamespace' => '(Main)',
+'blockedtext' => 'Navê bikarhêner an jî navnîşana IP ya te ji aliyê $1 hat bloke kirin. Sedema vê ev  e:<br />\'\'$2\'\'<p>Tu dikarî bi $1 an yek ji [{{ns:project}}:Koordînator|koordînatorên din]] re ser vê blokê nîqaş bikî.
+
+Têbînî: Tu nikarî fonksiyona "Ji vê bikarhêner re E-mail bişîne" bi kar bîne eger te navnîşana email a xwe di "[[Special:Preferences|Tercîhên min]]" de nenivîsand.
+
+Navnîşana te ya IP $3 ye. Ji kerema xwe eger pirsên te hebe vê navnîşanê bibêje.
+
+==Note to AOL users==
+Due to continuing acts of vandalism by one particular AOL user, Wikipedia often blocks AOL proxies. Unfortunately, a single proxy server may be used by a large number of AOL users, and hence innocent AOL users are often inadvertently blocked. We apologise for any inconvenience caused.
+
+If this happens to you, please email an administrator, using an AOL email address. Be sure to include the IP address given above.',
+'blockedtitle' => 'Bikarhêner hat bloke kirin',
+'blockip' => 'Bikarhêner asteng bike',
+'blockipsuccesssub' => 'Blok serkeftî',
+'blockipsuccesstext' => '"$1" hat asteng kirin.
+<br />Bibîne [[Special:Ipblocklist|Lîsteya IP\'yan hatî asteng kirin]] ji bo lîsteya blokan.',
+/* 'blockiptext' => 'Use the form below to block write access
+from a specific IP address or username.
+This should be done only only to prevent vandalism, and in
+accordance with [[Project:Policy|policy]].
+Fill in a specific reason below (for example, citing particular
+pages that were vandalized).', */
+'blocklink' => 'asteng bike',
+'blocklistline' => '$1, $2 $3 bloke kir ($4)',
+'blocklogentry' => '"$1" bloke kir',
+#'blocklogpage' => 'Block_log',
+/* 'blocklogtext' => 'This is a log of user blocking and unblocking actions. Automatically
+blocked IP addresses are not listed. See the [[Special:Ipblocklist|IP block list]] for
+the list of currently operational bans and blocks.', */
+'bold_sample' => 'Nivîsa qalind',
+'bold_tip' => 'Nivîsa qalind',
+'booksources' => 'Çavkaniyên pirtûkan',
+/* 'booksourcetext' => 'Below is a list of links to other sites that
+sell new and used books, and may also have further information
+about books you are looking for.
+{{SITENAME}} is not affiliated with any of these businesses, and
+this list should not be construed as an endorsement.', */
+'brokenredirects' => 'Ragihandinên jê bûye',
+#'brokenredirectstext' => 'The following redirects link to a non-existing pages.',
+'bugreports' => 'Raporên çewtiyan',
+#'bugreportspage' => 'Project:Bug_reports',
+#'bureaucratlog' => 'Bureaucrat_log',
+#'bureaucratlogentry' => 'Changed group membership for $1 from $2 to $3',
+'bydate' => 'li gor dîrokê',
+'byname' => 'li gor navê',
+'bysize' => 'li gor mezinayiyê',
+#'cachederror' => 'The following is a cached copy of the requested page, and may not be up to date.',
+'cancel' => 'Betal',
+#'cannotdelete' => 'Could not delete the page or file specified. (It may have already been deleted by someone else.)',
+#'cantrollback' => 'Cannot revert edit; last contributor is only author of this page.',
+'categories' => 'Kategoriyên rûpelan',
+'categoriespagetext' => 'Di vê wîkiyê de ev kategorî hene:',
+'category' => 'kategorî',
+'category_header' => 'Gotarên di kategoriya "$1" de',
+'categoryarticlecount' => 'Di vê kategoriyê de $1 gotar hene.',
+'categoryarticlecount1' => 'Di vê kategoriyê de $1 gotar heye.',
+#'changed' => 'changed',
+#'changegrouplogentry' => 'Changed group $2',
+'changepassword' => 'Şîfre biguherîne',
+'changes' => 'guherandin',
+#'clearyourcache' => "'''Note:''' After saving, you may have to bypass your browser's cache to see the changes. '''Mozilla / Firefox / Safari:''' hold down ''Shift'' while clicking ''Reload'', or press ''Ctrl-Shift-R'' (''Cmd-Shift-R'' on Apple Mac); '''IE:''' hold ''Ctrl'' while clicking ''Refresh'', or press ''Ctrl-F5''; '''Konqueror:''': simply click the ''Reload'' button, or press ''F5''; '''Opera''' users may need to completely clear their cache in ''Tools&rarr;Preferences''.",
+'columns' => 'stûn',
+'compareselectedversions' => 'Guhertoyan bide ber hev',
+'confirm' => 'Teyît bike',
+'confirmdelete' => 'Teyîda jêbirinê',
+/* 'confirmdeletetext' => 'You are about to permanently delete a page
+or image along with all of its history from the database.
+Please confirm that you intend to do this, that you understand the
+consequences, and that you are doing this in accordance with
+[[Project:Policy]].', */
+#'confirmemail' => 'Confirm E-mail address',
+'confirmemail_body' => 'Someone, probably you from IP address $1, has registered an
+account "$2" with this e-mail address on {{SITENAME}}.
+
+To confirm that this account really does belong to you and activate
+e-mail features on {{SITENAME}}, open this link in your browser:
+
+$3
+
+If this is *not* you, don\'t follow the link. This confirmation code
+will expire at $4.',
+#'confirmemail_error' => 'Something went wrong saving your confirmation.',
+#'confirmemail_invalid' => 'Invalid confirmation code. The code may have expired.',
+#'confirmemail_loggedin' => 'Your e-mail address has now been confirmed.',
+#'confirmemail_send' => 'Mail a confirmation code',
+#'confirmemail_sendfailed' => 'Could not send confirmation mail. Check address for invalid characters.',
+#'confirmemail_sent' => 'Confirmation e-mail sent.',
+#'confirmemail_subject' => '{{SITENAME}} e-mail address confirmation',
+#'confirmemail_success' => 'Your e-mail address has been confirmed. You may now log in and enjoy the wiki.',
+/* 'confirmemail_text' => 'This wiki requires that you validate your e-mail address
+before using e-mail features. Activate the button below to send a confirmation
+mail to your address. The mail will include a link containing a code; load the
+link in your browser to confirm that your e-mail address is valid.', */
+#'confirmprotect' => 'Confirm protection',
+#'confirmprotecttext' => 'Do you really want to protect this page?',
+#'confirmunprotect' => 'Confirm unprotection',
+#'confirmunprotecttext' => 'Do you really want to unprotect this page?',
+#'contextchars' => 'Context per line',
+#'contextlines' => 'Lines per hit',
+#'contribs-showhideminor' => '$1 minor edits',
+'contribslink' => 'tevkarî',
+'contribsub' => 'Ji bo $1',
+'contributions' => 'Tevkariyên vê bikarhêner',
+'copyright' => 'Naverok bin $1 (Lîsansa Belgekirina Azada GNU) tê weşandin.',
+'copyrightpage' => 'Wîkîpediya:Mafên nivîsanê',
+'copyrightpagename' => 'Mafên nivîsanê',
+'copyrightwarning' => '<div class="plainlinks" style="margin-top:1px;border-width:1px;border-style:solid;border-color:#aaaaaa;padding:2px;">
+{|border=0|
+|
+[[metawikipedia:Help:Special_characters|Nîşanên taybet]]:
+<charinsert>Ç ç </charinsert> ·
+<charinsert>Ê ê </charinsert> ·
+<charinsert>Πî </charinsert> ·
+<charinsert>Ş ş </charinsert> ·
+<charinsert>Û û </charinsert> ·
+<charinsert>&ndash; &mdash; </charinsert> ·
+<charinsert>[+] [[+]] {{+}} </charinsert> ·
+<charinsert>~ | °</charinsert> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+|<div class="plainlinks" dir="rtl" align="right">
+<charinsert>ئا  </charinsert> ·
+<charinsert>ڵ </charinsert> ·
+<charinsert>ڤ </charinsert> ·
+<charinsert>ۆ </charinsert> ·
+<charinsert>ێ </charinsert> ·
+<charinsert>ڕ </charinsert> ·
+<charinsert>ئه </charinsert> ·
+<charinsert>ه </charinsert>
+
+</div>
+|}
+</div>
+<b>BERHEMÊN MAFÊN WAN PARASTΠ(©) BÊ DESTÛR NEWEŞÎNE!</b>
+<div>Dîqat bike: Hemû tevkariyên Wîkîpediya di bin [[Lîsansa Belgekirina azada GNU]] de tên belav kirin.
+<div>Eger tu nexwazî ku nivîsên te bê dilrehmî bên guherandin û li gora keyfa herkesî bên belavkirin, li vir neweşîne.</div>
+<div>Tu soz didî ku te ev bi xwe nivîsand an jî ji çavkaniyekê azad an geliyane \'\'(public domain)\'\' girt.',
+/* 'copyrightwarning2' => 'Please note that all contributions to {{SITENAME}}
+may be edited, altered, or removed by other contributors.
+If you don\'t want your writing to be edited mercilessly, then don\'t submit it here.<br />
+You are also promising us that you wrote this yourself, or copied it from a
+public domain or similar free resource (see $1 for details).
+<strong>DO NOT SUBMIT COPYRIGHTED WORK WITHOUT PERMISSION!</strong>', */
+#'couldntremove' => 'Couldn\'t remove item \'$1\'...',
+'createaccount' => 'Hesabê nû çêke',
+'createaccountmail' => 'bi e-name',
+#'createarticle' => 'Create article',
+#'created' => 'created',
+#'creditspage' => 'Page credits',
+'cur' => 'ferq',
+'currentevents' => 'Bûyerên rojane',
+'currentevents-url' => 'Bûyerên rojane',
+'currentrev' => 'Revîzyona niha',
+#'currentrevisionlink' => 'view current revision',
+#'data' => 'Data',
+#'databaseerror' => 'Database error',
+#'dateformat' => 'Date format',
+/* 'dberrortext' => 'A database query syntax error has occurred.
+This may indicate a bug in the software.
+The last attempted database query was:
+<blockquote><tt>$1</tt></blockquote>
+from within function "<tt>$2</tt>".
+MySQL returned error "<tt>$3: $4</tt>".', */
+/* 'dberrortextcl' => 'A database query syntax error has occurred.
+The last attempted database query was:
+"$1"
+from within function "$2".
+MySQL returned error "$3: $4".
+', */
+'deadendpages' => 'Rûpelên bê dergeh',
+#'debug' => 'Debug',
+'dec' => 'ber',
+'december' => 'Berfanbar',
+#'default' => 'default',
+#'defaultns' => 'Search in these namespaces by default:',
+'defemailsubject' => 'Wîkîpediya e-name',
+'delete' => 'Jê bibe',
+#'delete_and_move' => 'Delete and move',
+#'delete_and_move_reason' => 'Deleted to make way for move',
+/* 'delete_and_move_text' => '==Deletion required==
+
+The destination article "[[$1]]" already exists. Do you want to delete it to make way for the move?', */
+'deletecomment' => 'Sedema jêbirinê',
+'deletedarticle' => '"$1" hat jêbirin',
+#'deletedrev' => '[deleted]',
+#'deletedrevision' => 'Deleted old revision $1.',
+'deletedtext' => '"$1" hat jêbirin. Ji bo qeyda rûpelên ku di dema nêzîk de hatin jêbirin binêre $2.',
+'deleteimg' => 'jêbibe',
+#'deleteimgcompletely' => 'Delete all revisions',
+'deletepage' => 'Rûpelê jê bibe',
+#'deletesub' => '(Deleting "$1")',
+'deletethispage' => 'Vê rûpelê jê bibe',
+#'deletionlog' => 'deletion log',
+#'dellogpage' => 'Deletion_log',
+#'dellogpagetext' => 'Below is a list of the most recent deletions.',
+#'destfilename' => 'Destination filename',
+/* 'developertext' => 'The action you have requested can only be
+performed by users with "developer" status.
+See $1.', */
+#'developertitle' => 'Developer access required',
+'diff' => 'cudahî',
+'difference' => '(Ferq nav revîzyonan)',
+'disambiguations' => 'Rûpelên cudakirinê',
+#'disambiguationspage' => 'Project:Links_to_disambiguating_pages',
+#'disambiguationstext' => 'The following pages link to a <i>disambiguation page</i>. They should link to the appropriate topic instead.<br />A page is treated as disambiguation if it is linked from $1.<br />Links from other namespaces are <i>not</i> listed here.',
+#'disclaimerpage' => 'Project:General_disclaimer',
+'disclaimers' => 'Ferexetname',
+#'doubleredirects' => 'Double Redirects',
+#'doubleredirectstext' => 'Each row contains links to the first and second redirect, as well as the first line of the second redirect text, usually giving the "real" target page, which the first redirect should point to.',
+/* 'eauthentsent' => 'A confirmation email has been sent to the nominated email address.
+Before any other mail is sent to the account, you will have to follow the instructions in the email,
+to confirm that the account is actually yours.', */
+'edit' => 'Biguherîne',
+#'edit-externally' => 'Edit this file using an external application',
+#'edit-externally-help' => 'See the [http://meta.wikimedia.org/wiki/Help:External_editors setup instructions] for more information.',
+#'editcomment' => 'The edit comment was: "<i>$1</i>".',
+'editconflict' => 'Têkçûna guherandinan: $1',
+#'editcurrent' => 'Edit the current version of this page',
+#'editgroup' => 'Edit Group',
+'edithelp' => 'Alîkarî ji bo guherandin',
+'edithelppage' => 'Wîkîpediya:Rûpeleke_çawa_biguherînim',
+'editing' => 'Biguherîne: "$1"',
+'editingcomment' => '$1 (şîrove) tê guherandin.',
+'editingold' => '<strong>HÎŞYAR: Tu ser revîsyoneke kevn a vê rûpelê dixebitî.
+Eger tu qeyd bikî, hemû guhertinên ji vê revîzyonê piştre winda dibin.
+</strong>',
+'editingsection' => 'Tê guherandin: $1 (beş)',
+'editsection' => 'biguherîne',
+'editthispage' => 'Vê rûpelê biguherîne',
+#'editusergroup' => 'Edit User Groups',
+#'email' => 'Email',
+#'emailauthenticated' => 'Your email address was authenticated on $1.',
+#'emailconfirmlink' => 'Confirm your e-mail address',
+#'emailflag' => 'Disable e-mail from other users',
+'emailforlost' => '* Nivîsandina navnîşana te \'\'ne mecbûrî\'\' ye. Lê eger tu navnîşana xwe binîvîsî, mirov dikare e-mailekê ji te re bişîne bêyî ku navnîşana te zanibe. Her wiha, eger tu şîfreya xwe ji bîr bikî, Wîkîpediya dikare şîfreya te bişîne ji vê navnîşana te re.',
+'emailfrom' => 'Ji',
+'emailmessage' => 'Name',
+/* 'emailnotauthenticated' => 'Your email address is <strong>not yet authenticated</strong>. No email
+will be sent for any of the following features.', */
+'emailpage' => 'E-name bikarhêner',
+/* 'emailpagetext' => 'If this user has entered a valid e-mail address in
+his or her user preferences, the form below will send a single message.
+The e-mail address you entered in your user preferences will appear
+as the "From" address of the mail, so the recipient will be able
+to reply.', */
+'emailsend' => 'Bişîne',
+#'emailsent' => 'E-mail sent',
+'emailsenttext' => 'E-nameya te hat şandin.',
+'emailsubject' => 'Mijar',
+#'emailto' => 'To',
+'emailuser' => 'Ji vê/î bikarhênerê/î re e-name bişîne',
+#'emptyfile' => 'The file you uploaded seems to be empty. This might be due to a typo in the file name. Please check whether you really want to upload this file.',
+/* 'enterlockreason' => 'Enter a reason for the lock, including an estimate
+of when the lock will be released', */
+'error' => 'Çewtî (Error)',
+'errorpagetitle' => 'Çewtî (Error)',
+#'exbeforeblank' => 'content before blanking was: \'$1\'',
+'exblank' => 'rûpel vala bû',
+'excontent' => 'Naveroka berê:',
+#'excontentauthor' => 'content was: \'$1\' (and the only contributor was \'$2\')',
+#'exif-aperturevalue' => 'Aperture',
+#'exif-artist' => 'Author',
+#'exif-bitspersample' => 'Bits per component',
+#'exif-brightnessvalue' => 'Brightness',
+#'exif-cfapattern' => 'CFA pattern',
+#'exif-colorspace' => 'Color space',
+#'exif-colorspace-1' => 'sRGB',
+#'exif-colorspace-ffff.h' => 'FFFF.H',
+#'exif-componentsconfiguration' => 'Meaning of each component',
+#'exif-componentsconfiguration-0' => 'does not exist',
+#'exif-componentsconfiguration-1' => 'Y',
+#'exif-componentsconfiguration-2' => 'Cb',
+#'exif-componentsconfiguration-3' => 'Cr',
+#'exif-componentsconfiguration-4' => 'R',
+#'exif-componentsconfiguration-5' => 'G',
+#'exif-componentsconfiguration-6' => 'B',
+#'exif-compressedbitsperpixel' => 'Image compression mode',
+#'exif-compression' => 'Compression scheme',
+#'exif-compression-1' => 'Uncompressed',
+#'exif-compression-6' => 'JPEG',
+#'exif-contrast' => 'Contrast',
+#'exif-contrast-0' => 'Normal',
+#'exif-contrast-1' => 'Soft',
+#'exif-contrast-2' => 'Hard',
+#'exif-copyright' => 'Copyright holder',
+#'exif-customrendered' => 'Custom image processing',
+#'exif-customrendered-0' => 'Normal process',
+#'exif-customrendered-1' => 'Custom process',
+#'exif-datetime' => 'File change date and time',
+#'exif-datetimedigitized' => 'Date and time of digitizing',
+#'exif-datetimeoriginal' => 'Date and time of data generation',
+#'exif-devicesettingdescription' => 'Device settings description',
+#'exif-digitalzoomratio' => 'Digital zoom ratio',
+#'exif-exifversion' => 'Exif version',
+#'exif-exposurebiasvalue' => 'Exposure bias',
+#'exif-exposureindex' => 'Exposure index',
+#'exif-exposuremode' => 'Exposure mode',
+#'exif-exposuremode-0' => 'Auto exposure',
+#'exif-exposuremode-1' => 'Manual exposure',
+#'exif-exposuremode-2' => 'Auto bracket',
+#'exif-exposureprogram' => 'Exposure Program',
+#'exif-exposureprogram-0' => 'Not defined',
+#'exif-exposureprogram-1' => 'Manual',
+#'exif-exposureprogram-2' => 'Normal program',
+#'exif-exposureprogram-3' => 'Aperture priority',
+#'exif-exposureprogram-4' => 'Shutter priority',
+#'exif-exposureprogram-5' => 'Creative program (biased toward depth of field)',
+#'exif-exposureprogram-6' => 'Action program (biased toward fast shutter speed)',
+#'exif-exposureprogram-7' => 'Portrait mode (for closeup photos with the background out of focus)',
+#'exif-exposureprogram-8' => 'Landscape mode (for landscape photos with the background in focus)',
+#'exif-exposuretime' => 'Exposure time',
+#'exif-filesource' => 'File source',
+#'exif-filesource-3' => 'DSC',
+#'exif-flash' => 'Flash',
+#'exif-flashenergy' => 'Flash energy',
+#'exif-flashpixversion' => 'Supported Flashpix version',
+#'exif-fnumber' => 'F Number',
+#'exif-focallength' => 'Lens focal length',
+#'exif-focallengthin35mmfilm' => 'Focal length in 35 mm film',
+#'exif-focalplaneresolutionunit' => 'Focal plane resolution unit',
+#'exif-focalplanexresolution' => 'Focal plane X resolution',
+#'exif-focalplaneyresolution' => 'Focal plane Y resolution',
+#'exif-gaincontrol' => 'Scene control',
+#'exif-gaincontrol-0' => 'None',
+#'exif-gaincontrol-1' => 'Low gain up',
+#'exif-gaincontrol-2' => 'High gain up',
+#'exif-gaincontrol-3' => 'Low gain down',
+#'exif-gaincontrol-4' => 'High gain down',
+#'exif-gpsaltitude' => 'Altitude',
+#'exif-gpsaltituderef' => 'Altitude reference',
+#'exif-gpsareainformation' => 'Name of GPS area',
+#'exif-gpsdatestamp' => 'GPS date',
+#'exif-gpsdestbearing' => 'Bearing of destination',
+#'exif-gpsdestbearingref' => 'Reference for bearing of destination',
+#'exif-gpsdestdistance' => 'Distance to destination',
+#'exif-gpsdestdistanceref' => 'Reference for distance to destination',
+#'exif-gpsdestlatitude' => 'Latitude destination',
+#'exif-gpsdestlatituderef' => 'Reference for latitude of destination',
+#'exif-gpsdestlongitude' => 'Longitude of destination',
+#'exif-gpsdestlongituderef' => 'Reference for longitude of destination',
+#'exif-gpsdifferential' => 'GPS differential correction',
+#'exif-gpsdirection-m' => 'Magnetic direction',
+#'exif-gpsdirection-t' => 'True direction',
+#'exif-gpsdop' => 'Measurement precision',
+#'exif-gpsimgdirection' => 'Direction of image',
+#'exif-gpsimgdirectionref' => 'Reference for direction of image',
+#'exif-gpslatitude' => 'Latitude',
+#'exif-gpslatitude-n' => 'North latitude',
+#'exif-gpslatitude-s' => 'South latitude',
+#'exif-gpslatituderef' => 'North or South Latitude',
+#'exif-gpslongitude' => 'Longitude',
+#'exif-gpslongitude-e' => 'East longitude',
+#'exif-gpslongitude-w' => 'West longitude',
+#'exif-gpslongituderef' => 'East or West Longitude',
+#'exif-gpsmapdatum' => 'Geodetic survey data used',
+#'exif-gpsmeasuremode' => 'Measurement mode',
+#'exif-gpsmeasuremode-2' => '2-dimensional measurement',
+#'exif-gpsmeasuremode-3' => '3-dimensional measurement',
+#'exif-gpsprocessingmethod' => 'Name of GPS processing method',
+#'exif-gpssatellites' => 'Satellites used for measurement',
+#'exif-gpsspeed' => 'Speed of GPS receiver',
+#'exif-gpsspeed-k' => 'Kilometres per hour',
+#'exif-gpsspeed-m' => 'Miles per hour',
+#'exif-gpsspeed-n' => 'Knots',
+#'exif-gpsspeedref' => 'Speed unit',
+#'exif-gpsstatus' => 'Receiver status',
+#'exif-gpsstatus-a' => 'Measurement in progress',
+#'exif-gpsstatus-v' => 'Measurement interoperability',
+#'exif-gpstimestamp' => 'GPS time (atomic clock)',
+#'exif-gpstrack' => 'Direction of movement',
+#'exif-gpstrackref' => 'Reference for direction of movement',
+#'exif-gpsversionid' => 'GPS tag version',
+#'exif-imagedescription' => 'Image title',
+#'exif-imagelength' => 'Height',
+#'exif-imageuniqueid' => 'Unique image ID',
+#'exif-imagewidth' => 'Width',
+#'exif-isospeedratings' => 'ISO speed rating',
+#'exif-jpeginterchangeformat' => 'Offset to JPEG SOI',
+#'exif-jpeginterchangeformatlength' => 'Bytes of JPEG data',
+#'exif-lightsource' => 'Light source',
+#'exif-lightsource-0' => 'Unknown',
+#'exif-lightsource-1' => 'Daylight',
+#'exif-lightsource-10' => 'Clody weather',
+#'exif-lightsource-11' => 'Shade',
+#'exif-lightsource-12' => 'Daylight fluorescent (D 5700 – 7100K)',
+#'exif-lightsource-13' => 'Day white fluorescent (N 4600 – 5400K)',
+#'exif-lightsource-14' => 'Cool white fluorescent (W 3900 – 4500K)',
+#'exif-lightsource-15' => 'White fluorescent (WW 3200 – 3700K)',
+#'exif-lightsource-17' => 'Standard light A',
+#'exif-lightsource-18' => 'Standard light B',
+#'exif-lightsource-19' => 'Standard light C',
+#'exif-lightsource-2' => 'Fluorescent',
+#'exif-lightsource-20' => 'D55',
+#'exif-lightsource-21' => 'D65',
+#'exif-lightsource-22' => 'D75',
+#'exif-lightsource-23' => 'D50',
+#'exif-lightsource-24' => 'ISO studio tungsten',
+#'exif-lightsource-255' => 'Other light source',
+#'exif-lightsource-3' => 'Tungsten (incandescent light)',
+#'exif-lightsource-4' => 'Flash',
+#'exif-lightsource-9' => 'Fine weather',
+#'exif-make' => 'Camera manufacturer',
+#'exif-make-value' => '$1',
+#'exif-makernote' => 'Manufacturer notes',
+#'exif-maxaperturevalue' => 'Maximum land aperture',
+#'exif-meteringmode' => 'Metering mode',
+#'exif-meteringmode-0' => 'Unknown',
+#'exif-meteringmode-1' => 'Average',
+#'exif-meteringmode-2' => 'CenterWeightedAverage',
+#'exif-meteringmode-255' => 'Other',
+#'exif-meteringmode-3' => 'Spot',
+#'exif-meteringmode-4' => 'MultiSpot',
+#'exif-meteringmode-5' => 'Pattern',
+#'exif-meteringmode-6' => 'Partial',
+#'exif-model' => 'Camera model',
+#'exif-model-value' => '$1',
+#'exif-oecf' => 'Optoelectronic conversion factor',
+#'exif-orientation' => 'Orientation',
+#'exif-orientation-1' => 'Normal',
+#'exif-orientation-2' => 'Flipped horizontally',
+#'exif-orientation-3' => 'Rotated 180°',
+#'exif-orientation-4' => 'Flipped vertically',
+#'exif-orientation-5' => 'Rotated 90° CCW and flipped vertically',
+#'exif-orientation-6' => 'Roatated 90° CW',
+#'exif-orientation-7' => 'Roateted 90° CW and flipped vertically',
+#'exif-orientation-8' => 'Rotated 90° CCW',
+#'exif-photometricinterpretation' => 'Pixel composition',
+#'exif-photometricinterpretation-1' => 'RGB',
+#'exif-photometricinterpretation-6' => 'YCbCr',
+#'exif-pixelxdimension' => 'Valind image height',
+#'exif-pixelydimension' => 'Valid image width',
+#'exif-planarconfiguration' => 'Data arrangement',
+#'exif-planarconfiguration-1' => 'chunky format',
+#'exif-planarconfiguration-2' => 'planar format',
+#'exif-primarychromaticities' => 'Chromaticities of primarities',
+#'exif-referenceblackwhite' => 'Pair of black and white reference values',
+#'exif-relatedsoundfile' => 'Related audio file',
+#'exif-resolutionunit' => 'Unit of X and Y resolution',
+#'exif-resolutionunit-2' => 'inches',
+#'exif-resolutionunit-3' => 'centimetres',
+#'exif-rowsperstrip' => 'Number of rows per strip',
+#'exif-samplesperpixel' => 'Number of components',
+#'exif-saturation' => 'Saturation',
+#'exif-saturation-0' => 'Normal',
+#'exif-saturation-1' => 'Low saturation',
+#'exif-saturation-2' => 'High saturation',
+#'exif-scenecapturetype' => 'Scene capture type',
+#'exif-scenecapturetype-0' => 'Standard',
+#'exif-scenecapturetype-1' => 'Landscape',
+#'exif-scenecapturetype-2' => 'Portrait',
+#'exif-scenecapturetype-3' => 'Night scene',
+#'exif-scenetype' => 'Scene type',
+#'exif-scenetype-1' => 'A directly photographed image',
+#'exif-sensingmethod' => 'Sensing method',
+#'exif-sensingmethod-1' => 'Undefined',
+#'exif-sensingmethod-2' => 'One-chip color area sensor',
+#'exif-sensingmethod-3' => 'Two-chip color area sensor',
+#'exif-sensingmethod-4' => 'Three-chip color area sensor',
+#'exif-sensingmethod-5' => 'Color sequential area sensor',
+#'exif-sensingmethod-7' => 'Trilinear sensor',
+#'exif-sensingmethod-8' => 'Color sequential linear sensor',
+#'exif-sharpness' => 'Sharpness',
+#'exif-sharpness-0' => 'Normal',
+#'exif-sharpness-1' => 'Soft',
+#'exif-sharpness-2' => 'Hard',
+#'exif-shutterspeedvalue' => 'Shutter speed',
+#'exif-software' => 'Software used',
+#'exif-software-value' => '$1',
+#'exif-spatialfrequencyresponse' => 'Spatial frequency response',
+#'exif-spectralsensitivity' => 'Spectral sensitivity',
+#'exif-stripbytecounts' => 'Bytes per compressed strip',
+#'exif-stripoffsets' => 'Image data location',
+#'exif-subjectarea' => 'Subject area',
+#'exif-subjectdistance' => 'Subject distance',
+#'exif-subjectdistancerange' => 'Subject distance range',
+#'exif-subjectdistancerange-0' => 'Unknown',
+#'exif-subjectdistancerange-1' => 'Macro',
+#'exif-subjectdistancerange-2' => 'Close view',
+#'exif-subjectdistancerange-3' => 'Distant view',
+#'exif-subjectlocation' => 'Subject location',
+#'exif-subsectime' => 'DateTime subseconds',
+#'exif-subsectimedigitized' => 'DateTimeDigitized subseconds',
+#'exif-subsectimeoriginal' => 'DateTimeOriginal subseconds',
+#'exif-transferfunction' => 'Transfer function',
+#'exif-usercomment' => 'User comments',
+#'exif-whitebalance' => 'White Balance',
+#'exif-whitebalance-0' => 'Auto white balance',
+#'exif-whitebalance-1' => 'Manual white balance',
+#'exif-whitepoint' => 'White point chromaticity',
+#'exif-xresolution' => 'Image resolution in width direction',
+#'exif-ycbcrcoefficients' => 'Color space transformation matrix coefficients',
+#'exif-ycbcrpositioning' => 'Y and C positioning',
+#'exif-ycbcrsubsampling' => 'Subsampling ratio of Y to C',
+#'exif-yresolution' => 'Image resolution in height direction',
+'explainconflict' => 'Ji dema te dest bi guherandinê kir heta niha kesekê/î din ev rûpel guherand.
+
+Jor guhartoya heyî tê dîtîn. Guherandinên te jêr tên nîşan dan. Divê tû wan bikî yek. Heke niha tomar bikî, <b>bi tene</b> nivîsara qutiya jor wê bê tomarkirin. <p>',
+#'export' => 'Export pages',
+#'exportcuronly' => 'Include only the current revision, not the full history',
+/* 'exporttext' => 'You can export the text and editing history of a particular page or
+set of pages wrapped in some XML. In the future, this may then be imported into another
+wiki running MediaWiki software, although there is no support for this feature in the
+current version.
+
+To export article pages, enter the titles in the text box below, one title per line, and
+select whether you want the current version as well as all old versions, with the page
+history lines, or just the current version with the info about the last edit.
+
+In the latter case you can also use a link, e.g. [[{{ns:Special}}:Export/Train]] for the
+article [[Train]].
+', */
+#'externaldberror' => 'There was either an external authentication database error or you are not allowed to update your external account.',
+'extlink_sample' => 'http://www.minak.com navê lînkê',
+'extlink_tip' => 'Lînka derve (http:// di destpêkê de ji bîr neke)',
+'faq' => 'Pirs û Bersîv (FAQ)',
+'faqpage' => 'Wîkîpediya:Pirs û Bersîv',
+'feb' => 'reş',
+'february' => 'reşemî',
+#'feedlinks' => 'Feed:',
+#'filecopyerror' => 'Could not copy file "$1" to "$2".',
+#'filedeleteerror' => 'Could not delete file "$1".',
+'filedesc' => 'Kurte',
+#'fileexists' => 'A file with this name exists already, please check $1 if you are not sure if you want to change it.',
+#'fileinfo' => '$1KB, MIME type: <code>$2</code>',
+#'filemissing' => 'File missing',
+'filename' => 'Navê dosyayê',
+'filenotfound' => 'Dosya bi navê "$1" nehat dîtin.',
+#'filerenameerror' => 'Could not rename file "$1" to "$2".',
+#'files' => 'Files',
+'filesource' => 'Çavkanî',
+#'filestatus' => 'Copyright status',
+'fileuploaded' => 'Barkirina dosyaya bi navê $1 serkeftî.
+Ji kerema xwe, biçe: $2 û agahî li der barê dosyayê binivîse (ji ku derê hat girtin, kîngê hat çêkirin, kê çêkir û hwd.)
+
+Heke ev dosya wêneyek be, bi vî rengî bi kar bîne:
+<br />
+<tt><nowiki>[[Wêne:$1|thumb|Binnivîs]]</nowiki></tt>',
+#'formerror' => 'Error: could not submit form',
+'friday' => 'În',
+#'geo' => 'GEO coordinates',
+#'getimagelist' => 'fetching file list',
+'go' => 'Gotar',
+#'group-admin-desc' => 'Trusted users able to block users and delete articles',
+#'group-admin-name' => 'Administrator',
+#'group-anon-desc' => 'Anonymous users',
+#'group-anon-name' => 'Anonymous',
+#'group-bureaucrat-desc' => 'The bureaucrat group is able to make sysops',
+#'group-bureaucrat-name' => 'Bureaucrat',
+#'group-loggedin-desc' => 'General logged in users',
+#'group-loggedin-name' => 'User',
+#'group-steward-desc' => 'Full access',
+#'group-steward-name' => 'Steward',
+#'groups' => 'User groups',
+#'groups-addgroup' => 'Add group',
+#'groups-already-exists' => 'A group of that name already exists',
+#'groups-editgroup' => 'Edit group',
+#'groups-editgroup-description' => 'Group description (max 255 characters):<br />',
+'groups-editgroup-name' => 'Group name:',
+/* 'groups-editgroup-preamble' => 'If the name or description starts with a colon, the
+remainder will be treated as a message name, and hence the text will be localised
+using the MediaWiki namespace', */
+#'groups-existing' => 'Existing groups',
+'groups-group-edit' => 'Existing groups:',
+#'groups-lookup-group' => 'Manage group rights',
+#'groups-noname' => 'Please specify a valid group name',
+#'groups-tableheader' => 'ID || Name || Description || Rights',
+#'guesstimezone' => 'Fill in from browser',
+'headline_sample' => 'Nivîsara sernameyê',
+'headline_tip' => 'Sername asta 2',
+'help' => 'Alîkarî',
+'helppage' => 'Wîkîpediya:Alîkarî',
+'hide' => 'veşêre',
+'hidetoc' => 'veşêre',
+'hist' => 'dîrok',
+#'histfirst' => 'Earliest',
+#'histlast' => 'Latest',
+'histlegend' => 'Legend: (ferq) = cudayî nav vê û versiyon a niha,
+(berê) = cudayî nav vê û yê berê vê, B = guhêrka biçûk',
+'history' => 'Dîroka rûpelê',
+#'history_copyright' => '-',
+'history_short' => 'Dîrok',
+#'historywarning' => 'Warning: The page you are about to delete has a history: ',
+'hr_tip' => 'Rastexêza berwarî (kêm bi kar bîne)',
+'ignorewarning' => 'Hişyarê qebûl neke û dosyayê qeyd bike.',
+#'illegalfilename' => 'The filename "$1" contains characters that are not allowed in page titles. Please rename the file and try uploading it again.',
+'ilsubmit' => 'Lêbigere',
+'image_sample' => 'Mînak.jpg',
+'image_tip' => 'Wêne li hundirê gotarê',
+'imagelinks' => 'Lînkên wêneyê',
+'imagelist' => 'Listeya wêneyan',
+#'imagelistall' => 'all',
+#'imagelisttext' => 'Below is a list of $1 files sorted $2.',
+#'imagemaxsize' => 'Limit images on image description pages to: ',
+#'imagepage' => 'View image page',
+#'imagereverted' => 'Revert to earlier version was successful.',
+#'imgdelete' => 'del',
+#'imgdesc' => 'desc',
+/* 'imghistlegend' => 'Legend: (cur) = this is the current file, (del) = delete
+this old version, (rev) = revert to this old version.
+<br /><i>Click on date to see the file uploaded on that date</i>.', */
+'imghistory' => 'Dîroka wêneyê',
+#'imglegend' => 'Legend: (desc) = show/edit image description.',
+#'immobile_namespace' => 'Destination title is of a special type; cannot move pages into that namespace.',
+#'import' => 'Import pages',
+#'importfailed' => 'Import failed: $1',
+#'importhistoryconflict' => 'Conflicting history revision exists (may have imported this page before)',
+#'importinterwiki' => 'Transwiki import',
+#'importnosources' => 'No transwiki import sources have been defined and direct history uploads are disabled.',
+'importnotext' => 'Vala an nivîs tune',
+#'importsuccess' => 'Import succeeded!',
+#'importtext' => 'Please export the file from the source wiki using the Special:Export utility, save it to your disk and upload it here.',
+'info_short' => 'Agahî',
+#'infobox' => 'Click a button to get an example text',
+#'infobox_alert' => 'Please enter the text you want to be formatted.\n It will be shown in the infobox for copy and pasting.\nExample:\n$1\nwill become:\n$2',
+#'infosubtitle' => 'Information for page',
+#'internalerror' => 'Internal error',
+#'intl' => 'Interlanguage links',
+/* 'invalidemailaddress' => 'The email address cannot be accepted as it appears to have an invalid
+format. Please enter a well-formatted address or empty that field.', */
+#'invert' => 'Invert selection',
+/* 'ip_range_invalid' => 'Invalid IP range.
+', */
+#'ipaddress' => 'IP Address',
+#'ipadressorusername' => 'IP Address or username',
+#'ipb_expiry_invalid' => 'Expiry time invalid.',
+#'ipbexpiry' => 'Expiry',
+#'ipblocklist' => 'List of blocked IP addresses and usernames',
+'ipboptions' => '2 hours,1 day,3 days,1 week,2 weeks,1 month,3 months,6 months,1 year,infinite',
+#'ipbother' => 'Other time',
+#'ipbotheroption' => 'other',
+'ipbreason' => 'Sedem',
+'ipbsubmit' => 'Vê bikarhêner bloke bike',
+#'ipusubmit' => 'Unblock this address',
+#'ipusuccess' => '"[[$1]]" unblocked',
+#'isbn' => 'ISBN',
+'isredirect' => 'rûpela ragihandinê',
+'italic_sample' => 'Nivîsa xwar (îtalîk)',
+'italic_tip' => 'Nivîsa xwar (îtalîk)',
+#'iteminvalidname' => 'Problem with item \'$1\', invalid name...',
+'jan' => 'rêb',
+'january' => 'Rêbendan',
+'jul' => 'tîr',
+'july' => 'Tîrmeh',
+'jun' => 'pşr',
+'june' => 'pûşper',
+#'laggedslavemode' => 'Warning: Page may not contain recent updates.',
+#'largefile' => 'It is recommended that images not exceed $1 bytes in size, this file is $2 bytes',
+'last' => 'berê',
+'lastmodified' => 'Ev rûpel carî dawî di $1 de hat guherandin.',
+#'lastmodifiedby' => 'This page was last modified $1 by $2.',
+'lineno' => 'Rêza $1:',
+'link_sample' => 'Navê lînkê',
+'link_tip' => 'Lînka hundir',
+'linklistsub' => '(Listeya lînkan)',
+'linkshere' => 'Di van rûpelên de lînkek ji vê re heye:',
+'linkstoimage' => 'Di van rûpelên de lînkek ji vê wêneyê re heye:',
+#'linktrail' => '/^([a-z]+)(.*)$/sD',
+'listform' => 'lîste',
+'listingcontinuesabbrev' => ' dewam',
+'listusers' => 'Lîsteya bikarhêneran',
+#'loadhist' => 'Loading page history',
+#'loadingrev' => 'loading revision for diff',
+#'localtime' => 'Local time',
+#'lockbtn' => 'Lock database',
+#'lockconfirm' => 'Yes, I really want to lock the database.',
+#'lockdb' => 'Lock database',
+#'lockdbsuccesssub' => 'Database lock succeeded',
+/* 'lockdbsuccesstext' => 'The database has been locked.
+<br />Remember to remove the lock after your maintenance is complete.', */
+/* 'lockdbtext' => 'Locking the database will suspend the ability of all
+users to edit pages, change their preferences, edit their watchlists, and
+other things requiring changes in the database.
+Please confirm that this is what you intend to do, and that you will
+unlock the database when your maintenance is done.', */
+#'locknoconfirm' => 'You did not check the confirmation box.',
+#'log' => 'Logs',
+'login' => 'Têkeve (login)',
+#'loginend' => '&nbsp;',
+'loginerror' => 'Çewtî (Login error)',
+'loginpagetitle' => 'Qeyda bikarhêner (User login)',
+'loginproblem' => '<b>Di qeyda te (login) de pirsgirêkek derket.</b><br />Careke din biceribîne!',
+'loginprompt' => '<b>Eger tu xwe nû qeyd bikî, nav û şîfreya xwe hilbijêre.</b> Ji bo xwe qeyd kirinê di Wîkîpediya de divê ku \'\'cookies\'\' gengaz be.',
+'loginreqtitle' => 'Têketin pêwîst e',
+'loginsuccess' => 'Tu niha di Wîkîpediya de qeydkirî yî wek "$1".',
+'loginsuccesstitle' => 'Têketin serkeftî!',
+'logout' => 'Derkeve (log out)',
+'logouttext' => 'Tu niha derketî (logged out).
+Tu dikarî wîkîpediyayê niha weke bikarhênerekî nediyarkirî bikarbînî, yan jî tu dikarî dîsa bi vî navê xwe yan navekî din wek bikarhêner têkevî wikipêdiyayê. Bila di bîra te de be ku gengaz e hin rûpel mîna ku tu hîn bi navê xwe qeyd kiriyî werin nîşandan, heta ku tu nîşanên çavlêgerandina (browser) xwe jênebî.',
+'logouttitle' => 'Derketina bikarhêner',
+'lonelypages' => 'Rûpelên sêwî',
+'longpages' => 'Rûpelên dirêj',
+'longpagewarning' => 'HIŞYAR: Drêjahiya vê rûpelê $1 kB (kilobayt) e, ev pir e. Dibe ku çend \'\'browser\'\'
+baş nikarin rûpelên ku ji 32 kB drêjtir in biguherînin. Eger tu vê rûpelê beş beş bikî gelo ne çêtir e?',
+#'mailerror' => 'Error sending mail: $1',
+'mailmypassword' => 'Şîfreyeke nû bi e-mail ji min re bişîne',
+'mailnologin' => 'Navnîşan neşîne',
+/* 'mailnologintext' => 'You must be [[Special:Userlogin|logged in]]
+and have a valid e-mail address in your [[Special:Preferences|preferences]]
+to send e-mail to other users.', */
+'mainpage' => 'Serûpel',
+/* 'mainpagedocfooter' => 'Please see [http://meta.wikipedia.org/wiki/MediaWiki_i18n documentation on customizing the interface]
+and the [http://meta.wikipedia.org/wiki/MediaWiki_User%27s_Guide User\'s Guide] for usage and configuration help.', */
+#'mainpagetext' => 'Wiki software successfully installed.',
+'maintenance' => 'Rûpela tamîratê (Maintenance)',
+#'maintenancebacklink' => 'Back to Maintenance Page',
+#'maintnancepagetext' => 'This page includes several handy tools for everyday maintenance. Some of these functions tend to stress the database, so please do not hit reload after every item you fixed ;-)',
+#'makesysop' => 'Make a user into a sysop',
+#'makesysopfail' => '<b>User "$1" could not be made into a sysop. (Did you enter the name correctly?)</b>',
+'makesysopname' => 'Navê bikarhêner:',
+#'makesysopok' => '<b>User "$1" is now a sysop</b>',
+#'makesysopsubmit' => 'Make this user into a sysop',
+/* 'makesysoptext' => 'This form is used by bureaucrats to turn ordinary users into administrators.
+Type the name of the user in the box and press the button to make the user an administrator', */
+#'makesysoptitle' => 'Make a user into a sysop',
+'mar' => 'adr',
+'march' => 'adar',
+#'markaspatrolleddiff' => 'Mark as patrolled',
+#'markaspatrolledlink' => '[$1]',
+#'markaspatrolledtext' => 'Mark this article as patrolled',
+#'markedaspatrolled' => 'Marked as patrolled',
+#'markedaspatrolledtext' => 'The selected revision has been marked as patrolled.',
+/* 'matchtotals' => 'The query "$1" matched $2 page titles
+and the text of $3 pages.', */
+#'math' => 'Math',
+#'math_bad_output' => 'Can\'t write to or create math output directory',
+#'math_bad_tmpdir' => 'Can\'t write to or create math temp directory',
+#'math_failure' => 'Failed to parse',
+#'math_image_error' => 'PNG conversion failed; check for correct installation of latex, dvips, gs, and convert',
+#'math_lexing_error' => 'lexing error',
+#'math_notexvc' => 'Missing texvc executable; please see math/README to configure.',
+#'math_sample' => 'Insert formula here',
+#'math_syntax_error' => 'syntax error',
+#'math_tip' => 'Mathematical formula (LaTeX)',
+#'math_unknown_error' => 'unknown error',
+#'math_unknown_function' => 'unknown function ',
+'may' => 'gul',
+'may_long' => 'gulan',
+#'media_sample' => 'Example.ogg',
+#'media_tip' => 'Media file link',
+/* 'mediawarning' => '\'\'\'Warning\'\'\': This file may contain malicious code, by executing it your system may be compromised.
+<hr>', */
+#'metadata' => 'Metadata',
+#'metadata_page' => 'Wikipedia:Metadata',
+#'minlength' => 'Image names must be at least three letters.',
+'minoredit' => 'Ev guheraniyekê biçûk e',
+'minoreditletter' => 'B',
+#'mispeelings' => 'Pages with misspellings',
+#'mispeelingspage' => 'List of common misspellings',
+#'mispeelingstext' => 'The following pages contain a common misspelling, which are listed on $1. The correct spelling might be given (like this).',
+/* 'missingarticle' => 'The database did not find the text of a page
+that it should have found, named "$1".
+
+This is usually caused by following an outdated diff or history link to a
+page that has been deleted.
+
+If this is not the case, you may have found a bug in the software.
+Please report this to an administrator, making note of the URL.', */
+/* 'missingimage' => '<b>Missing image</b><br /><i>$1</i>
+', */
+#'missinglanguagelinks' => 'Missing Language Links',
+#'missinglanguagelinksbutton' => 'Find missing language links for',
+#'missinglanguagelinkstext' => 'These pages do <i>not</i> link to their counterpart in $1. Redirects and subpages are <i>not</i> shown.',
+'monday' => 'duşem',
+'moredotdotdot' => 'Zêde...',
+'move' => 'Nav biguherîne',
+'movearticle' => 'Rûpelê bigerîne',
+'movedto' => 'bû',
+#'movelogpage' => 'Move log',
+#'movelogpagetext' => 'Below is a list of page moved.',
+'movenologin' => 'Xwe qeyd nekir',
+/* 'movenologintext' => 'You must be a registered user and [[Special:Userlogin|logged in]]
+to move a page.', */
+'movepage' => 'Vê rûpelê bigerîne',
+'movepagebtn' => 'Vê rûpelê bigerîne',
+'movepagetalktext' => 'Rûpela axaftinê (talk) giredayî ji vê rûpelê re wê bê gerandin jî.
+\'\'\'Îstisna:\'\'\'
+*You are moving the page across namespaces,
+*A non-empty talk page already exists under the new name, or
+*You uncheck the box below.
+
+In those cases, you will have to move or merge the page manually if desired.',
+/* 'movepagetext' => 'Using the form below will rename a page, moving all
+of its history to the new name.
+The old title will become a redirect page to the new title.
+Links to the old page title will not be changed; be sure to
+check for double or broken redirects.
+You are responsible for making sure that links continue to
+point where they are supposed to go.
+
+Note that the page will \'\'\'not\'\'\' be moved if there is already
+a page at the new title, unless it is empty or a redirect and has no
+past edit history. This means that you can rename a page back to where
+it was just renamed from if you make a mistake, and you cannot overwrite
+an existing page.
+
+<b>WARNING!</b>
+This can be a drastic and unexpected change for a popular page;
+please be sure you understand the consequences of this before
+proceeding.', */
+#'movereason' => 'Reason',
+'movetalk' => 'Rûpela "talk" (axaftin) jî bigerîne, eger gengaz be.',
+'movethispage' => 'Vê rûpelê bigerîne',
+#'mw_math_html' => 'HTML if possible or else PNG',
+#'mw_math_mathml' => 'MathML if possible (experimental)',
+#'mw_math_modern' => 'Recommended for modern browsers',
+#'mw_math_png' => 'Always render PNG',
+#'mw_math_simple' => 'HTML if very simple or else PNG',
+#'mw_math_source' => 'Leave it as TeX (for text browsers)',
+'mycontris' => 'Tevkariyên min',
+'mypage' => 'Rûpela min',
+'mytalk' => 'Rûpela nîqaşa min',
+#'namespace' => 'Namespace:',
+'navigation' => 'Navîgasyon',
+'nbytes' => '$1 bayt',
+'nchanges' => '$1 guherandin',
+'newarticle' => '(Nû)',
+'newarticletext' => '<div style="font-size:small;color:#003333;border-width:1px;border-style:solid;border-color:#aaaaaa;padding:3px">
+Ev rûpel hîn tune. Eger tu bixwazî vê rûpelê çêkî, dest bi nivîsandinê bike û piştre qeyd bike. \'\'\'Wêrek be\'\'\', biceribîne!<br />
+Ji bo alîkarî binêre: [[Wîkîpediya:Alîkarî|Alîkarî]].<br />
+Eger tu bi şaştî hatî, bizivire rûpela berê.
+</div>',
+'newbies' => 'ecemî',
+'newimages' => 'Pêşangeha wêneyên nû',
+'newmessages' => '$1 ji bo te heye.',
+'newmessageslink' => 'Nameyên nû',
+'newpage' => 'Rûpela nû',
+'newpageletter' => 'Nû',
+'newpages' => 'Rûpelên nû',
+'newpassword' => 'Şîfreya nû',
+#'newtitle' => 'To new title',
+'newusersonly' => '(ji bo bikarhênerên nû)',
+#'newwindow' => '(opens in new window)',
+'next' => 'pêş',
+#'nextdiff' => 'Next diff →',
+'nextn' => '$1 pêş',
+'nextpage' => 'Rûpela pêşî ($1)',
+#'nextrevision' => 'Newer revision→',
+'nlinks' => '$1 lînk',
+'noaffirmation' => 'Pêwîst e tu teyît bikî ku barkirin mafên nivîsanê îhlal neke.',
+'noarticletext' => '<div style="border: 1px solid #ccc; padding: 7px; background-color: #fff; color: #000">\'\'\'Di Wîkîpediyayê de rûpeleke bi vî navî hîn tune.\'\'\'
+* \'\'\'[{{SERVER}}{{localurl:{{NAMESPACE}}:{{PAGENAME}}|action=edit}} Dest bi nivîsandina gotara "{{PAGENAME}}" bike]\'\'\'
+* \'\'\'Heke te niha vê rûpelê çekiribe û niha xuya neke, vê demê dereng tê. Bisekine û rûpelê taze bike.\'\'\'
+* [[{{ns:special}}:Search/{{PAGENAME}}|Di nav gotarên din de li "{{PAGENAME}}" bigere]]
+* [http://ku.wiktionary.org/wiki/{{NAMESPACE}}:{{PAGENAME}} Di \'\'\'Wîkîferheng, ferhenga azad\'\'\' de li rûpela "{{PAGENAME}}" binihêre]
+</div>',
+'noconnect' => 'Bibexşîne! Çend pirsgrêkên teknîkî heye, girêdan ji pêşkêşvanê (suxrekirê, server) re niha ne gengaz e.',
+#'nocontribs' => 'No changes were found matching these criteria.',
+'nocookieslogin' => 'Ji bo qeydkirina bikarhêneran Wîkîpediya "cookies" bi kar tîne. Te fonksiyona "cookies" girt. Ji kerema xwe "cookies" gengaz bike û careke din biceribîne.',
+#'nocookiesnew' => 'The user account was created, but you are not logged in. {{SITENAME}} uses cookies to log in users. You have cookies disabled. Please enable them, then log in with your new username and password.',
+#'nocreativecommons' => 'Creative Commons RDF metadata disabled for this server.',
+#'nocredits' => 'There is no credits info available for this page.',
+#'nodb' => 'Could not select database $1',
+#'nodublincore' => 'Dublin Core RDF metadata disabled for this server.',
+'noemail' => 'Navnîşana bikarhênerê/î "$1" nehat tomar kirine.',
+/* 'noemailprefs' => '<strong>No email address has been specified</strong>, the following
+features will not work.', */
+/* 'noemailtext' => 'This user has not specified a valid e-mail address,
+or has chosen not to receive e-mail from other users.', */
+'noemailtitle' => 'Navnîşana e-name tune',
+'nogomatch' => 'Rûpeleke wek vî navî tune.
+
+Tu dixwazî <b><a href="$1" class="new">vê gotarê binivîsî</a></b> ?',
+#'nohistory' => 'There is no edit history for this page.',
+#'noimages' => 'Nothing to see.',
+'nolinkshere' => 'Ji hîç rûpel ji vê re lînk tune.',
+'nolinkstoimage' => 'Rûpeleke ku ji vê wêneyê re lînk dike tune.',
+'noname' => 'Navê ku te nivîsand derbas nabe.',
+/* 'nonefound' => '\'\'\'Note\'\'\': unsuccessful searches are
+often caused by searching for common words like "have" and "from",
+which are not indexed, or by specifying more than one search term (only pages
+containing all of the search terms will appear in the result).', */
+#'nonunicodebrowser' => '<strong>WARNING: Your browser is not unicode compliant, please change it before editing an article.</strong>',
+#'nospecialpagetext' => 'You have requested an invalid special page, a list of valid special pages may be found at [[{{ns:special}}:Specialpages]].',
+'nosuchaction' => 'Çalakiyek bi vê rengê tune',
+/* 'nosuchactiontext' => 'The action specified by the URL is not
+recognized by the wiki', */
+'nosuchspecialpage' => 'Rûpeleke taybet bi vê rengê tune',
+'nosuchuser' => 'Bikarhênera/ê bi navê "$1" tune. Navê rast binivîse an bi vê formê <b>hesabeke nû çêke</b>. (Ji bo hevalên nû "Têkeve" çênabe!)',
+#'nosuchusershort' => 'There is no user by the name "$1". Check your spelling.',
+#'notacceptable' => 'The wiki server can\'t provide data in a format your client can read.',
+'notanarticle' => 'Ne gotar e',
+/* 'notargettext' => 'You have not specified a target page or user
+to perform this function on.', */
+'notargettitle' => 'Hedef tune',
+'note' => '<strong>Not:</strong>',
+'notextmatches' => 'Di nivîsarê de nehat dîtin.',
+'notitlematches' => 'Di nav sernivîsan de nehat dîtin.',
+'notloggedin' => 'Xwe qeyd nekir (not logged in)',
+'nov' => 'ser',
+'november' => 'sermawez',
+#'nowatchlist' => 'You have no items on your watchlist.',
+'nowiki_sample' => 'Nivîs ku nebe formatkirin',
+#'nowiki_tip' => 'Ignore wiki formatting',
+'nstab-category' => 'Kategorî',
+'nstab-help' => 'Alîkarî',
+'nstab-image' => 'Wêne',
+'nstab-main' => 'Gotar',
+'nstab-media' => 'Medya',
+'nstab-mediawiki' => 'Mesaj',
+'nstab-special' => 'Taybet',
+'nstab-template' => 'Şablon',
+'nstab-user' => 'Bikarhêner',
+'nstab-wp' => 'Der barê',
+#'numauthors' => 'Number of distinct authors (article): $1',
+#'number_of_watching_users_RCview' => '[$1]',
+#'number_of_watching_users_pageview' => '[$1 watching user/s]',
+#'numedits' => 'Number of edits (article): $1',
+#'numtalkauthors' => 'Number of distinct authors (discussion page): $1',
+#'numtalkedits' => 'Number of edits (discussion page): $1',
+#'numwatchers' => 'Number of watchers: $1',
+#'nviews' => '$1 views',
+'oct' => 'kew',
+'october' => 'kewçêr',
+'ok' => 'Temam',
+'oldpassword' => 'Şîfreya kevn',
+'orig' => 'orîj',
+'orphans' => 'Rûpelên sêwî',
+#'othercontribs' => 'Based on work by $1.',
+'otherlanguages' => 'Zimanên din',
+#'others' => 'others',
+'pagemovedsub' => 'Gerandin serkeftî',
+'pagemovedtext' => 'Rûpela "[[$1]]" çû cihê "[[$2]]".',
+#'pagetitle' => '$1 - {{SITENAME}}',
+/* 'passwordremindertext' => 'Someone (probably you, from IP address $1)
+requested that we send you a new {{SITENAME}} login password.
+The password for user "$2" is now "$3".
+You should log in and change your password now.', */
+#'passwordremindertitle' => 'Password reminder from {{SITENAME}}',
+'passwordsent' => 'Ji navnîşana e-mail ku ji bo "$1" hat tomarkirin şîfreyekê nû hat şandin. Vê bistîne û dîsa têkeve.',
+#'passwordtooshort' => 'Your password is too short. It must have at least $1 characters.',
+#'perfcached' => 'The following data is cached and may not be completely up to date:',
+/* 'perfdisabled' => 'Sorry! This feature has been temporarily disabled
+because it slows the database down to the point that no one can use
+the wiki.', */
+#'perfdisabledsub' => 'Here\'s a saved copy from $1:',
+#'personaltools' => 'Personal tools',
+'popularpages' => 'Rûpelên populer',
+'portal' => 'Portala komê',
+'portal-url' => 'Wîkîpediya:Portala komê',
+'postcomment' => 'Şîroveyekê bişîne',
+#'poweredby' => '{{SITENAME}} is powered by [http://www.mediawiki.org/ MediaWiki], an open source wiki engine.',
+'powersearch' => 'Lêbigere',
+'powersearchtext' => 'Lêgerîn di nav cihên navan de:<br />
+$1<br />
+$2 Ragihandinan nîşan bide &nbsp; Lêbigere: $3 $9',
+'preferences' => 'Tercîhên min',
+#'prefs-help-email' => '² Email (optional): Enables others to contact you through your user or user_talk page without the need of revealing your identity.',
+#'prefs-help-email-enotif' => 'This address is also used to send you email notifications if you enabled the options.',
+#'prefs-help-realname' => '¹ Real name (optional): if you choose to provide it this will be used for giving you attribution for your work.',
+'prefs-misc' => 'Eyaren cuda',
+'prefs-personal' => 'Agahiyên bikarhênerê/î',
+#'prefs-rc' => 'Recent changes & stubs',
+'prefslogintext' => 'Te xwe wek "$1" qeyd kir.
+Numareya ID ya te ya întern $2 ye.
+
+Binêre [[Wîkîpediya:Alîkariya tercîhan]] ji bo alîkarî ser tercîhan.',
+'prefsnologin' => 'Xwe qeyd nekir',
+/* 'prefsnologintext' => 'You must be [[Special:Userlogin|logged in]]
+to set user preferences.', */
+#'prefsreset' => 'Preferences have been reset from storage.',
+'preview' => 'Pêşdîtin',
+/* 'previewconflict' => 'This preview reflects the text in the upper
+text editing area as it will appear if you choose to save.', */
+'previewnote' => 'Ji bîr neke ku ev bi tenê çavdêriyek e, ev rûpel hîn nehat qeyd kirin!',
+#'previousdiff' => '← Previous diff',
+#'previousrevision' => '←Older revision',
+'prevn' => '$1 paş',
+#'print' => 'Print',
+'printableversion' => 'Versiyon ji bo çapkirinê',
+'printsubtitle' => '(Ji http://ku.wikipedia.org)',
+'protect' => 'Biparêze',
+'protectcomment' => 'Sedema parastinê',
+'protectedarticle' => 'parastî [[$1]]',
+'protectedpage' => 'Rûpela parastî',
+'protectedpagewarning' => 'ŞIYARÎ:  Ev rûpel hat qefl kirin. Bi tenê bikarhênerên ku xwediyên mafan "sysop" ne dikarin vê rûpelê biguherînin. <br />
+Be sure you are following the
+<a href=\'/wiki/Wîkîpediya:Protected_page_guidelines\'>protected page
+guidelines</a>.',
+/* 'protectedtext' => 'This page has been locked to prevent editing; there are
+a number of reasons why this may be so, please see
+[[Project:Protected page]].
+
+You can view and copy the source of this page:', */
+#'protectlogpage' => 'Protection_log',
+/* 'protectlogtext' => 'Below is a list of page locks/unlocks.
+See [[Project:Protected page]] for more information.', */
+#'protectmoveonly' => 'Protect from moves only',
+'protectpage' => 'Rûpelê biparêze',
+#'protectsub' => '(Protecting "$1")',
+'protectthispage' => 'Vê rûpelê biparêze',
+#'proxyblocker' => 'Proxy blocker',
+#'proxyblockreason' => 'Your IP address has been blocked because it is an open proxy. Please contact your Internet service provider or tech support and inform them of this serious security problem.',
+'proxyblocksuccess' => 'Çêbû.',
+#'pubmedurl' => 'http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?cmd=Retrieve&db=pubmed&dopt=Abstract&list_uids=$1',
+'qbbrowse' => 'Bigere',
+'qbedit' => 'Biguherîne',
+'qbfind' => 'Bibîne',
+'qbmyoptions' => 'Rûpelên min',
+#'qbpageinfo' => 'Context',
+'qbpageoptions' => 'Ev rûpel',
+#'qbsettings' => 'Quickbar',
+'qbspecialpages' => 'Rûpelên taybet',
+'randompage' => 'Rûpela tesadufî',
+#'randompage-url' => 'Special:Random',
+#'range_block_disabled' => 'The sysop ability to create range blocks is disabled.',
+#'rchide' => 'in $4 form; $1 minor edits; $2 secondary namespaces; $3 multiple edits.',
+'rclinks' => '$1 guherandinên di $2 rojên dawî de nîşan bide<br />$3',
+'rclistfrom' => 'an jî guherandinên ji $1 şûnda nîşan bide.',
+#'rcliu' => '; $1 edits from logged in users',
+'rcloaderr' => 'Guherandinên dawî tên bar kirin',
+#'rclsub' => '(to pages linked from "$1")',
+'rcnote' => 'Jêr <strong>$1</strong> guherandinên dawî di <strong>$2</strong> rojên dawî de tên nîşan dan.',
+#'rcnotefrom' => 'Below are the changes since <b>$2</b> (up to <b>$1</b> shown).',
+#'rcpatroldisabled' => 'Recent Changes Patrol disabled',
+#'rcpatroldisabledtext' => 'The Recent Changes Patrol feature is currently disabled.',
+#'readonly' => 'Database locked',
+#'readonly_lag' => 'The database has been automatically locked while the slave database servers catch up to the master',
+/* 'readonlytext' => 'The database is currently locked to new
+entries and other modifications, probably for routine database maintenance,
+after which it will be back to normal.
+The administrator who locked it offered this explanation:
+$1', */
+/* 'readonlywarning' => '<strong>WARNING: The database has been locked for maintenance,
+so you will not be able to save your edits right now. You may wish to cut-n-paste
+the text into a text file and save it for later.</strong>', */
+'recentchanges' => 'Guherandinên dawî',
+#'recentchanges-url' => 'Special:Recentchanges',
+#'recentchangesall' => 'all',
+#'recentchangescount' => 'Titles in recent changes',
+'recentchangeslinked' => 'Guherandinên peywend',
+'recentchangestext' => '<div class="plainlinks" id="recentchangestable">
+{| width="100%" cellpadding="3"
+|----- valign="top"
+|
+{| width="100%" style="border: 3px solid #dfdfdf;"
+|-
+| align="right" | \'\'\'Alîkarî:\'\'\'&nbsp;
+| align="left" | [[Wîkîpediya:Alîkarî|Alîkarî]]
+|-----
+| align="right" | \'\'\'Wêne & Gotar:\'\'\'&nbsp;
+| align="left"  | [[Special:Newimages|Wêneyên nû]] | [[Special:Newpages|Gotarên nû]] |  [[Special:Lonelypages|sêwî]] | [[Special:Wantedpages|pêwîst]] | [[Wîkîpediya:Gotar ku ji bo hemû Wîkîpediyayan pêwîst in|1000 gotar]] | [[Special:Uncategorizedpages|bê kategorî]]
+|-----
+| align="right" valign="top" | \'\'\'Xwişkên Wîkîpediyayê:\'\'\'&nbsp;
+| align="left" | [http://commons.wikimedia.org/wiki/Special:Recentchanges Commons] | [http://ku.wiktionary.org/wiki/Special:Recentchanges Wîkîferheng] | [http://wikisource.org/wiki/Special:Recentchanges Wîkîçavkanî] | [http://ku.wikiquote.org/wiki/Special:Recentchanges Wikigotin] | [http://ku.wikibooks.org/wiki/Special:Recentchanges Wîkîpirtûk] | [http://meta.wikimedia.org/wiki/Special:Recentchanges Meta-Wiki] <small>[http://ku.wikipedia.org/w/wiki.phtml?title=MediaWiki:Recentchangestext&amp;action=edit vê biguherîne]</small>
+|}
+|}
+[[af:Recent Changes]]
+[[als:Special:Recentchanges]]
+[[an:Special:Recentchanges]]
+[[ar:Special:Recentchanges]]
+[[ast:Special:Recentchanges]]
+[[bg:Специални:Recentchanges]]
+[[bs:Special:Recentchanges]]
+[[ca:RecentChanges]]
+[[cs:Special:Recentchanges]]
+[[cy:Special:Recentchanges]]
+[[da:Speciel:Recentchanges]]
+[[de:Spezial:Recentchanges]]
+[[el:Special:Recentchanges]]
+[[en:Special:Recentchanges]]
+[[eo:Lastaj_Sxangxoj]]
+[[es:Cambios Recientes]]
+[[et:Recent Changes]]
+[[eu:Special:Recentchanges]]
+[[fa:%D9%88%DB%8C%DA%98%D9%87:Recentchanges]]
+[[fi:Toiminnot:Recentchanges]]
+[[fr:RecentChanges]]
+[[fy:Wiki:Recentchanges]]
+[[ga:Speisialta:Recentchanges]]
+[[gl:Special:Recentchanges]]
+[[he:מיוחד:Recentchanges]]
+[[hi:%E0%A4%B5%E0%A4%BF%E0%A4%B6%E0%A5%87%E0%A4%B7:Recentchanges]]
+[[hr:Special:Recentchanges]]
+[[hu:Speciális:Recentchanges]]
+[[ia:Special:Recentchanges]]
+[[id:Recent_Changes]]
+[[is:Special:Recentchanges]]
+[[it:Speciale:Recentchanges]]
+[[ja:特別:Recentchanges]]
+[[ka:Special:Recentchanges]]
+[[ko:특수기능:Recentchanges]]
+[[la:Recent_Changes]]
+[[lb:Special:Recentchanges]]
+[[mh:Special:Recentchanges]]
+[[ms:Special:Recentchanges]]
+[[na:Special:Recentchanges]]
+[[nds:Special:Recentchanges]]
+[[nl:Speciaal:Recentchanges]]
+[[no:Spesial:Recentchanges]]
+[[oc:Especial:Recentchanges]]
+[[pl:Specjalna:Recentchanges]]
+[[pt:Especial:Recentchanges]]
+[[rm:Special:Recentchanges]]
+[[ro:Special:Recentchanges]]
+[[ru:Special:Recentchanges]]
+[[sa:Special:Recentchanges]]
+[[simple:Special:Recentchanges]]
+[[sk:Špeciálne:Recentchanges]]
+[[sl:Posebno:Recentchanges]]
+[[sm:Special:Recentchanges]]
+[[sq:Special:Recentchanges]]
+[[sr:Посебно:Recentchanges]]
+[[sv:NyligenSkrivnaSidor]]
+[[tg:Special:Recentchanges]]
+[[to:Special:Recentchanges]]
+[[tr:Special:Recentchanges]]
+[[tt:Special:Recentchanges]]
+[[uk:Special:Recentchanges]]
+[[vi:Special:Recentchanges]]
+[[yi:Special:Recentchanges]]
+[[zh:Special:Recentchanges]]',
+'redirectedfrom' => '(Hat ragihandin ji $1)',
+'remembermypassword' => 'Şifreya min di her rûniştdemê de bîne bîra xwe.',
+#'removechecked' => 'Remove checked items from watchlist',
+#'removedwatch' => 'Removed from watchlist',
+#'removedwatchtext' => 'The page "$1" has been removed from your watchlist.',
+#'removingchecked' => 'Removing requested items from watchlist...',
+#'renamegrouplogentry' => 'Renamed group $2 to $3',
+#'resetprefs' => 'Reset',
+#'restorelink' => '$1 deleted edits',
+#'resultsperpage' => 'Hits per page',
+'retrievedfrom' => 'Ji "$1" hatiye standin.',
+'returnto' => 'Bizivire $1.',
+'retypenew' => 'Şîfreya nû careke din binîvîse',
+#'reupload' => 'Re-upload',
+#'reuploaddesc' => 'Return to the upload form.',
+#'reverted' => 'Reverted to earlier revision',
+#'revertimg' => 'rev',
+#'revertmove' => 'revert',
+'revertpage' => 'Guherandina $2 hat betal kirin, vegerand guhartoya dawî ya $1',
+'revhistory' => 'Dîroka revîzyonan',
+'revisionasof' => 'Revîzyon a $1',
+#'revisionasofwithlink' => 'Revision as of $1; $2<br />$3 | $4',
+'revnotfound' => 'Revîzyon nehat dîtin',
+/* 'revnotfoundtext' => 'The old revision of the page you asked for could not be found.
+Please check the URL you used to access this page.
+', */
+#'rfcurl' => 'http://www.faqs.org/rfcs/rfc$1.html',
+#'rights' => 'Rights:',
+#'rightslogtext' => 'This is a log of changes to user rights.',
+#'rollback' => 'Roll back edits',
+'rollback_short' => 'Bizivirîne paş',
+#'rollbackfailed' => 'Rollback failed',
+'rollbacklink' => 'bizivirîne paş',
+'rows' => 'Rêz',
+'saturday' => 'şemî',
+'savearticle' => 'Rûpelê tomar bike',
+'savedprefs' => 'Tercîhên te qeyd kirî ne.',
+'savefile' => 'Dosyayê tomar bike',
+#'savegroup' => 'Save Group',
+'saveprefs' => 'Tercîhan qeyd bike',
+#'saveusergroups' => 'Save User Groups',
+#'scarytranscludedisabled' => '[Interwiki transcluding is disabled]',
+'scarytranscludefailed' => '[Template fetch failed; sorry]',
+#'scarytranscludetoolong' => '[URL is too long; sorry]',
+'search' => 'Lêbigere',
+'searchdisabled' => '<p>Tu dikarî li Wîkîpediya bi Google an Yahoo! bigere. Têbînî: Dibe ku encamen lêgerîne ne yên herî nû ne.
+</p>',
+#'searchfulltext' => 'Search full text',
+'searchquery' => 'Ji bo query "$1"',
+'searchresults' => 'Encamên lêgerînê',
+'searchresultshead' => 'Eyarên encamên lêgerinê',
+'searchresulttext' => 'Ji bo zêdetir agahî der barê lêgerînê di Wîkîpediyayê de, binêre $1.',
+#'sectionlink' => '→',
+#'selectnewerversionfordiff' => 'Select a newer version for comparison',
+#'selectolderversionfordiff' => 'Select an older version for comparison',
+#'selflinks' => 'Pages with Self Links',
+#'selflinkstext' => 'The following pages contain a link to themselves, which they should not.',
+#'selfmove' => 'Source and destination titles are the same; can\'t move a page over itself.',
+'sep' => 'rez',
+'september' => 'rezber',
+#'servertime' => 'Server time',
+/* 'sessionfailure' => 'There seems to be a problem with your login session;
+this action has been canceled as a precaution against session hijacking.
+Please hit "back" and reload the page you came from, then try again.', */
+#'set_rights_fail' => '<b>User rights for "$1" could not be set. (Did you enter the name correctly?)</b>',
+#'set_user_rights' => 'Set user rights',
+#'setbureaucratflag' => 'Set bureaucrat flag',
+#'setstewardflag' => 'Set steward flag',
+#'shareddescriptionfollows' => '-',
+#'sharedupload' => 'This file is a shared upload and may be used by other projects.',
+'shortpages' => 'Rûpelên kurt',
+'show' => 'nîşan bide',
+'showbigimage' => 'Versyona mezin bibîne an daxe ($1x$2, $3 KB).',
+#'showdiff' => 'Show changes',
+'showhideminor' => 'an guherandinên biçûk $1 | bot $2 | bikarhênerên têketî $3 | guherandinên patrolkirî $4',
+'showingresults' => '<b>$1</b> encam, bi #<b>$2</b> dest pê dike.',
+'showingresultsnum' => '<b>$3</b> encam, bi #<b>$2</b> dest pê dike.',
+'showlast' => '$1 wêneyên dawî bi rêz kirî $2 nîşan bide.',
+'showpreview' => 'Pêşdîtin',
+'showtoc' => 'nîşan bide',
+'sig_tip' => 'Îmze û demxeya wext ya te',
+'sitestats' => 'Statîstîkên sîteyê',
+'sitestatstext' => 'Di \'\'database\'\' de <b>$1</b> rûpel hene. Tê de rûpelên nîqaşê, rûpelên der barê Wîkîpediyayê, rûpelên pir kurt (stub), rûpelên ragihandinê (redirect) û rûpelên din ku qey ne gotar in hene.
+
+Derve wan, \'\'\'$2\'\'\' rûpel hene ku qey \'\'\'gotarên rewa\'\'\' ne.
+
+Ji 28\'ê çileya 2004 heta roja îro <b>$4</b> carî rûpel hatin guherandin.
+
+----
+
+Fonksiyonên ku hîn rast naxebitin:
+*<b>$3</b> total page views and
+*<b>$5</b> average edits per page
+*<b>$6</b> views per edit.',
+'sitesubtitle' => 'Ensîklopediya azad',
+'sitesupport' => 'Ji bo Weqfa Wikimedia Beş',
+#'sitesupport-url' => 'Project:Site support',
+'sitetitle' => 'Wîkîpediya Kurdî',
+'siteuser' => 'Bikarhênera/ê $1 a/ê Wîkîpediyayê',
+'siteusers' => 'Bikarhênerên $1 yên Wîkîpediyayê',
+'skin' => 'Çerm',
+#'sorbs' => 'SORBS DNSBL',
+#'sorbsreason' => 'Your IP address is listed as an open proxy in the [http://www.sorbs.net SORBS] DNSBL.',
+#'sourcefilename' => 'Source filename',
+#'spamprotectionmatch' => 'The following text is what triggered our spam filter: $1',
+#'spamprotectiontext' => 'The page you wanted to save was blocked by the spam filter. This is probably caused by a link to an external site.',
+#'spamprotectiontitle' => 'Spam protection filter',
+#'speciallogtitlelabel' => 'Title: ',
+#'specialloguserlabel' => 'User: ',
+'specialpage' => 'Rûpela taybet',
+'specialpages' => 'Rûpelên taybet',
+'spheading' => 'Rûpelên taybet ji bo hemû bikarhêneran',
+#'sqlhidden' => '(SQL query hidden)',
+'statistics' => 'Statîstîk',
+'storedversion' => 'Versiyona qeydkirî',
+#'stubthreshold' => 'Threshold for stub display',
+'subcategories' => 'Binkategorî',
+'subcategorycount' => 'Di vê kategoriyê de $1 binkategorî hene.',
+'subcategorycount1' => 'Di vê kategoriyê de $1 binkategorî heye.',
+'subject' => 'Mijar/sernivîs',
+#'subjectpage' => 'View subject',
+'successfulupload' => 'Barkirin serkeftî',
+'summary' => 'Kurte û çavkanî',
+'sunday' => 'yekşem',
+'sysoptext' => 'Çalakiya ku te xwest bi tenê bikarhêneran bi mafên "sysop" dikarin çêkin.
+Binêre $1.',
+#'sysoptitle' => 'Sysop access required',
+'tableform' => 'tablo',
+'tagline' => 'Ji {{SITENAME}}',
+'talk' => 'Nîqaş',
+/* 'talkexists' => '\'\'\'The page itself was moved successfully, but the
+talk page could not be moved because one already exists at the new
+title. Please merge them manually.\'\'\'', */
+'talkpage' => 'Vê rûpelê nîqas bike',
+#'talkpagemoved' => 'The corresponding talk page was also moved.',
+#'talkpagenotmoved' => 'The corresponding talk page was <strong>not</strong> moved.',
+#'talkpagetext' => '<!-- MediaWiki:talkpagetext -->',
+#'templatesused' => 'Templates used on this page:',
+#'textboxsize' => 'Editing',
+'textmatches' => 'Dîtinên di nivîsara rûpelan de',
+#'thisisdeleted' => 'View or restore $1?',
+'thumbnail-more' => 'Mezin bike',
+'thumbsize' => 'Thumbnail size :',
+'thursday' => 'Pêncşem',
+#'timezonelegend' => 'Time zone',
+#'timezoneoffset' => 'Offset¹',
+#'timezonetext' => 'The number of hours your local time differs from server time (UTC).',
+'titlematches' => 'Dîtinên di sernivîsên gotaran de',
+'toc' => 'Tabloya Naverokê',
+#'tog-editondblclick' => 'Edit pages on double click (JavaScript)',
+#'tog-editsection' => 'Enable section editing via [edit] links',
+#'tog-editsectiononrightclick' => 'Enable section editing by right clicking<br /> on section titles (JavaScript)',
+#'tog-editwidth' => 'Edit box has full width',
+#'tog-enotifminoredits' => 'Send me an email also for minor edits of pages',
+#'tog-enotifrevealaddr' => 'Reveal my email address in notification mails',
+#'tog-enotifusertalkpages' => 'Send me an email when my user talk page is changed',
+#'tog-enotifwatchlistpages' => 'Send me an email on page changes',
+#'tog-externaldiff' => 'Use external diff by default',
+#'tog-externaleditor' => 'Use external editor by default',
+#'tog-fancysig' => 'Raw signatures (without automatic link)',
+#'tog-hideminor' => 'Hide minor edits in recent changes',
+#'tog-highlightbroken' => 'Format broken links <a href="" class="new">like this</a> (alternative: like this<a href="" class="internal">?</a>).',
+#'tog-justify' => 'Justify paragraphs',
+#'tog-minordefault' => 'Mark all edits minor by default',
+#'tog-nocache' => 'Disable page caching',
+#'tog-numberheadings' => 'Auto-number headings',
+#'tog-previewonfirst' => 'Show preview on first edit',
+#'tog-previewontop' => 'Show preview before edit box',
+#'tog-rememberpassword' => 'Remember across sessions',
+#'tog-shownumberswatching' => 'Show the number of watching users',
+#'tog-showtoc' => 'Show table of contents<br />(for pages with more than 3 headings)',
+#'tog-showtoolbar' => 'Show edit toolbar (JavaScript)',
+'tog-underline' => 'Underline links',
+#'tog-usenewrc' => 'Enhanced recent changes (JavaScript)',
+#'tog-watchdefault' => 'Add pages you edit to your watchlist',
+'toolbox' => 'Qutiya amûran',
+'tooltip-compareselectedversions' => 'Cudatiyên guhartoyên hilbijartî yên vê rûpelê bibîne. [alt-v]',
+#'tooltip-diff' => 'Show which changes you made to the text. [alt-d]',
+#'tooltip-minoredit' => 'Mark this as a minor edit [alt-i]',
+#'tooltip-preview' => 'Preview your changes, please use this before saving! [alt-p]',
+#'tooltip-save' => 'Save your changes [alt-s]',
+#'tooltip-search' => 'Search this wiki [alt-f]',
+#'tooltip-watch' => 'Add this page to your watchlist [alt-w]',
+#'tryexact' => 'Try exact match',
+'tuesday' => 'Sêşem',
+'uclinks' => '$1 guherandinên dawî; $2 rojên dawî',
+#'ucnote' => 'Below are this user\'s last <b>$1</b> changes in the last <b>$2</b> days.',
+'uctop' => ' (ser)',
+#'unblockip' => 'Unblock user',
+/* 'unblockiptext' => 'Use the form below to restore write access
+to a previously blocked IP address or username.', */
+'unblocklink' => 'betala astengê',
+'unblocklogentry' => 'astenga "$1" hat betal kirin',
+'uncategorizedcategories' => 'Kategoriyên bê kategorî',
+'uncategorizedpages' => 'Rûpelên bê kategorî',
+#'undelete' => 'Restore deleted page',
+#'undelete_short' => 'Undelete $1 edits',
+#'undelete_short1' => 'Undelete one edit',
+#'undeletearticle' => 'Restore deleted page',
+#'undeletebtn' => 'Restore!',
+#'undeletedarticle' => 'restored "[[$1]]"',
+#'undeletedrevisions' => '$1 revisions restored',
+/* 'undeletedtext' => '[[$1]] has been successfully restored.
+See [[Special:Log/delete]] for a record of recent deletions and restorations.', */
+/* 'undeletehistory' => 'If you restore the page, all revisions will be restored to the history.
+If a new page with the same name has been created since the deletion, the restored
+revisions will appear in the prior history, and the current revision of the live page
+will not be automatically replaced.', */
+#'undeletepage' => 'View and restore deleted pages',
+/* 'undeletepagetext' => 'The following pages have been deleted but are still in the archive and
+can be restored. The archive may be periodically cleaned out.', */
+#'undeleterevision' => 'Deleted revision as of $1',
+#'undeleterevisions' => '$1 revisions archived',
+#'underline-always' => 'Always',
+#'underline-default' => 'Browser default',
+#'underline-never' => 'Never',
+#'unexpected' => 'Unexpected value: "$1"="$2".',
+#'unlockbtn' => 'Unlock database',
+#'unlockconfirm' => 'Yes, I really want to unlock the database.',
+#'unlockdb' => 'Unlock database',
+#'unlockdbsuccesssub' => 'Database lock removed',
+#'unlockdbsuccesstext' => 'The database has been unlocked.',
+/* 'unlockdbtext' => 'Unlocking the database will restore the ability of all
+users to edit pages, change their preferences, edit their watchlists, and
+other things requiring changes in the database.
+Please confirm that this is what you intend to do.', */
+'unprotect' => 'Parastinê rake',
+'unprotectcomment' => 'Sedem ji bo rakirina parastinê',
+#'unprotectedarticle' => 'unprotected "[[$1]]"',
+#'unprotectsub' => '(Unprotecting "$1")',
+'unprotectthispage' => 'Parastina vê rûpelê rake',
+'unusedimages' => 'Wêneyên ku nayên bi kar anîn',
+/* 'unusedimagestext' => '<p>Please note that other web sites may link to an image with
+a direct URL, and so may still be listed here despite being
+in active use.</p>', */
+'unwatch' => 'Êdî neşopîne',
+#'unwatchthispage' => 'Stop watching',
+'updated' => '(Hat taze kirin)',
+'upload' => 'Wêneyê barbike',
+#'upload_directory_read_only' => 'The upload directory ($1) is not writable by the webserver.',
+'uploadbtn' => 'Dosyayê barbike',
+#'uploadcorrupt' => 'The file is corrupt or has an incorrect extension. Please check the file and upload again.',
+#'uploaddisabled' => 'Sorry, uploading is disabled.',
+'uploadedfiles' => 'Dosyayên bar kirî',
+'uploadedimage' => '"$1" barkirî',
+#'uploaderror' => 'Upload error',
+'uploadlink' => 'Wêneyê barbike',
+#'uploadlog' => 'upload log',
+#'uploadlogpage' => 'Upload_log',
+#'uploadlogpagetext' => 'Below is a list of the most recent file uploads.',
+#'uploadnewversion' => '[$1 Upload a new version of this file]',
+'uploadnologin' => 'Xwe qeyd nekir',
+'uploadnologintext' => 'Ji bo barkirina wêneyan divê ku tu <a href="{{localurl:Special:Userlogin}}">têkeve</a>.',
+#'uploadscripted' => 'This file contains HTML or script code that my be erroneously be interpreted by a web browser.',
+'uploadtext' => '\'\'\'STOP!\'\'\' Before you upload here, make sure to read and follow the [[Project:Image use policy|image use policy]]. To view or search previously uploaded images, go to the [[Special:Imagelist|list of uploaded images]]. Uploads and deletions are logged on the [[Project:Upload log|upload log]]. Use the form below to upload new image files for use in illustrating your pages. On most browsers, you will see a "Browse..." button, which will bring up your operating system\'s standard file open dialog. Choosing a file will fill the name of that file into the text field next to the button. You must also check the box affirming that you are not violating any copyrights by uploading the file. Press the "Upload" button to finish the upload. This may take some time if you have a slow internet connection. The preferred formats are JPEG for photographic images, PNG for drawings and other iconic images, and OGG for sounds. Please name your files descriptively to avoid confusion. To include the image in a page, use a link in the form \'\'\'<nowiki>[[{{ns:6}}:file.jpg]]</nowiki>\'\'\' or \'\'\'<nowiki>[[{{ns:6}}:file.png|alt text]]</nowiki>\'\'\' or \'\'\'<nowiki>[[{{ns:-2}}:file.ogg]]</nowiki>\'\'\' for sounds. Please note that as with wiki pages, others may edit or delete your uploads if they think it serves the project, and you may be blocked from uploading if you abuse the system.',
+#'uploadvirus' => 'The file contains a virus! Details: $1',
+'uploadwarning' => 'Hişyara barkirinê',
+/* 'usenewcategorypage' => '1
+
+Set first character to "0" to disable the new category page layout.', */
+#'user_rights_set' => '<b>User rights for "$1" updated</b>',
+#'usercssjsyoucanpreview' => '<strong>Tip:</strong> Use the \'Show preview\' button to test your new CSS/JS before saving.',
+#'usercsspreview' => '\'\'\'Remember that you are only previewing your user CSS, it has not yet been saved!\'\'\'',
+#'userexists' => 'The user name you entered is already in use. Please choose a different name.',
+#'userjspreview' => '\'\'\'Remember that you are only testing/previewing your user JavaScript, it has not yet been saved!\'\'\'',
+'userlogin' => 'Têkeve an hesabeke nû çêke',
+'userlogout' => 'Derkeve',
+#'usermailererror' => 'Mail object returned error: ',
+'userpage' => 'Rûpelê vê/vî bikarhênerê/î temaşe bike',
+#'userrights' => 'User rights management',
+#'userrights-editusergroup' => 'Edit user groups',
+#'userrights-groupsavailable' => 'Available groups:',
+/* 'userrights-groupshelp' => 'Select groups you want the user to be removed from or added to.
+Unselected groups will not be changed. You can deselect a group with CTRL + Left Click', */
+#'userrights-groupsmember' => 'Member of:',
+#'userrights-logcomment' => 'Changed group membership from $1 to $2',
+#'userrights-lookup-user' => 'Manage user groups',
+'userrights-user-editname' => 'Enter a username:',
+'userstats' => 'Statistîkên bikarhêneran',
+'userstatstext' => '<b>$1</b> bikarhênerên qeydkirî hene. Ji wan <b>$2</b> administrator/koordînator in. (Binêre $3).
+<br /><br />
+Ji bo statîstîkên din ser serûpelê biçe: <b>Statîstîk</b>',
+#'val_add' => 'Add',
+#'val_article_lists' => 'List of validated articles',
+#'val_clear_old' => 'Clear my older validation data',
+#'val_del' => 'Delete',
+#'val_details_th' => '<sub>User</sub> \ <sup>Topic</sup>',
+#'val_details_th_user' => 'User $1',
+#'val_form_note' => '\'\'\'Hint:\'\'\' Merging your data means that for the article revision you select, all options where you have specified \'\'no opinion\'\' will be set to the value and comment of the most recent revision for which you have expressed an opinion. For example, if you want to change a single option for a newer revision, but also keep your other settings for this article in this revision, just select which option you intend to \'\'change\'\', and merging will fill in the other options with your previous settings.',
+#'val_iamsure' => 'Check this box if you really mean it!',
+#'val_list_header' => '<th>#</th><th>Topic</th><th>Range</th><th>Action</th>',
+#'val_merge_old' => 'Use my previous assessment where selected \'No opinion\'',
+#'val_my_stats_title' => 'My validation overview',
+#'val_no' => 'No',
+#'val_no_anon_validation' => 'You have to be logged in to validate an article.',
+#'val_noop' => 'No opinion',
+#'val_of' => '$1 of $2',
+#'val_page_validation_statistics' => 'Page validation statistics for $1',
+#'val_percent' => '<b>$1%</b><br />($2 of $3 points<br />by $4 users)',
+#'val_percent_single' => '<b>$1%</b><br />($2 of $3 points<br />by one user)',
+#'val_rev_for' => 'Revisions for $1',
+#'val_rev_stats_link' => 'See the validation statistics for "$1" <a href="$2">here</a>',
+#'val_revision' => 'Revision',
+#'val_revision_changes_ok' => 'Your ratings have been stored!',
+#'val_revision_number' => 'Revision #$1',
+#'val_revision_of' => 'Revision of $1',
+#'val_revision_stats_link' => 'details',
+#'val_show_my_ratings' => 'Show my validations',
+#'val_stat_link_text' => 'Validation statistics for this article',
+#'val_tab' => 'Validate',
+/* 'val_table_header' => '<tr><th>Class</th>$1<th colspan=4>Opinion</th>$1<th>Comment</th></tr>
+', */
+#'val_this_is_current_version' => 'this is the latest version',
+#'val_time' => 'Time',
+#'val_topic_desc_page' => 'Project:Validation topics',
+#'val_total' => 'Total',
+#'val_user_stats_title' => 'Validation overview of user $1',
+#'val_user_validations' => 'This user has validated $1 pages.',
+#'val_validate_article_namespace_only' => 'Only articles can be validated. This page is <i>not</i> in the article namespace.',
+#'val_validate_version' => 'Validate this version',
+#'val_validated' => 'Validation done.',
+#'val_validation_of' => 'Validation of "$1"',
+#'val_version' => 'Version',
+#'val_version_of' => 'Version of $1',
+#'val_view_version' => 'View this revision',
+#'val_votepage_intro' => 'Change this text <a href="{{SERVER}}{{localurl:MediaWiki:Val_votepage_intro}}">here</a>!',
+#'val_warning' => '<b>Never, <i>ever</i>, change something here without <i>explicit</i> community consensus!</b>',
+#'val_yes' => 'Yes',
+#'validate' => 'Validate page',
+#'variantname-zh' => 'zh',
+#'variantname-zh-cn' => 'cn',
+#'variantname-zh-hk' => 'hk',
+#'variantname-zh-sg' => 'sg',
+#'variantname-zh-tw' => 'tw',
+'version' => 'Guherto',
+#'versionrequired' => 'Version $1 of MediaWiki required',
+#'versionrequiredtext' => 'Version $1 of MediaWiki is required to use this page. See [[Special:Version]]',
+'viewcount' => 'Ev rûpel $1 car hat xwestin.',
+'viewprevnext' => '($1) ($2) ($3).',
+#'views' => 'Views',
+'viewsource' => 'Çavkanî',
+'viewtalkpage' => 'Nîqaşê temaşe bike',
+'wantedpages' => 'Rûpelên ku tên xwestin',
+'watch' => 'Bişopîne',
+'watchdetails' => '* $1 pages watched not counting talk pages
+* [[Special:Watchlist/edit|Show and edit complete watchlist]]',
+/* 'watcheditlist' => 'Here\'s an alphabetical list of your
+watched content pages. Check the boxes of pages you want to remove from your watchlist and click the \'remove checked\' button
+at the bottom of the screen (deleting a content page also deletes the accompanying talk page and vice versa).', */
+'watchlist' => 'Lîsteya min ya şopandinê',
+#'watchlistall1' => 'all',
+#'watchlistall2' => 'all',
+'watchlistcontains' => 'Di lîsteya şopandina te de $1 rûpel hene.',
+'watchlistsub' => '(ji bo bikarhêner "$1")',
+#'watchmethod-list' => 'checking watched pages for recent edits',
+#'watchmethod-recent' => 'checking recent edits for watched pages',
+#'watchnochange' => 'None of your watched items were edited in the time period displayed.',
+'watchnologin' => 'Xwe qeyd nekir',
+/* 'watchnologintext' => 'You must be [[Special:Userlogin|logged in]]
+to modify your watchlist.', */
+'watchthis' => 'Vê gotarê bişopîne',
+'watchthispage' => 'Vê rûpelê bişopîne',
+'wednesday' => 'Çarşem',
+'welcomecreation' => '<h2>Bi xêr hatî, $1!</h2><p>Hesaba te hat afirandin. Tu dikarî niha tercîhên xwe eyar bikî.',
+'whatlinkshere' => 'Lînkên ji vê rûpelê re',
+#'whitelistacctext' => 'To be allowed to create accounts in this Wiki you have to [[Special:Userlogin|log]] in and have the appropriate permissions.',
+#'whitelistacctitle' => 'You are not allowed to create an account',
+#'whitelistedittext' => 'You have to [[Special:Userlogin|login]] to edit pages.',
+#'whitelistedittitle' => 'Login required to edit',
+#'whitelistreadtext' => 'You have to [[Special:Userlogin|login]] to read pages.',
+#'whitelistreadtitle' => 'Login required to read',
+'wikipediapage' => 'Rûpela meta temaşe bike',
+#'wlheader-enotif' => '* Email notification is enabled.',
+#'wlheader-showupdated' => '* Pages which have been changed since you last visited them are shown in \'\'\'bold\'\'\'',
+#'wlhide' => 'Hide',
+#'wlhideshowown' => '$1 my edits.',
+#'wlnote' => 'Below are the last $1 changes in the last <b>$2</b> hours.',
+#'wlsaved' => 'This is a saved version of your watchlist.',
+#'wlshow' => 'Show',
+#'wlshowlast' => 'Show last $1 hours $2 days $3',
+/* 'wrong_wfQuery_params' => 'Incorrect parameters to wfQuery()<br />
+Function: $1<br />
+Query: $2
+', */
+'wrongpassword' => 'Şifreya ku te nivîsand şaş e. Ji kerema xwe careke din biceribîne.',
+'yourdiff' => 'Cudahî',
+#'yourdomainname' => 'Your domain',
+'youremail' => 'E-maila te*',
+#'yourlanguage' => 'Language',
+'yourname' => 'Navê te wek bikarhêner (user name)',
+'yournick' => 'Leqeba te (ji bo îmza)',
+'yourpassword' => 'Şîfreya te (password)',
+'yourpasswordagain' => 'Şîfreya xwe careke din binîvîse',
+'yourrealname' => 'Navê te yê rastî*',
+'yourtext' => 'Nivîsara te',
+#'yourvariant' => 'Variant',
+);
+
+
+class LanguageKu extends LanguageUtf8 {
+       function getNamespaces() {
+               global $wgNamespaceNamesKu;
+               return $wgNamespaceNamesKu;
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesKu, $wgAllMessagesEn;
+               if( isset( $wgAllMessagesKu[$key] ) ) {
+                       return $wgAllMessagesKu[$key];
+               } else {
+                       return parent::getMessage( $key );
+               }
+       }
+}
+
+?>
diff --git a/languages/LanguageLa.php b/languages/LanguageLa.php
new file mode 100644 (file)
index 0000000..3dbf45a
--- /dev/null
@@ -0,0 +1,182 @@
+<?php
+/** Latin (lingua Latina)
+  *
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+/* private */ $wgNamespaceNamesLa = array(
+       NS_SPECIAL        => 'Specialis',
+       NS_MAIN           => '',
+       NS_TALK           => 'Disputatio',
+       NS_USER           => 'Usor',
+       NS_USER_TALK      => 'Disputatio_Usoris',
+       NS_PROJECT        => $wgMetaNamespace,
+       NS_PROJECT_TALK   => FALSE,  # Set in constructor
+       NS_IMAGE          => 'Imago',
+       NS_IMAGE_TALK     => 'Disputatio_Imaginis',
+       NS_MEDIAWIKI      => 'MediaWiki',
+       NS_MEDIAWIKI_TALK => 'Disputatio_MediaWiki',
+       NS_TEMPLATE       => 'Formula',
+       NS_TEMPLATE_TALK  => 'Disputatio_Formulae',
+       NS_HELP           => 'Auxilium',
+       NS_HELP_TALK      => 'Disputatio_Auxilii',
+       NS_CATEGORY       => 'Categoria',
+       NS_CATEGORY_TALK  => 'Disputatio_Categoriae',
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgQuickbarSettingsLa = array(
+       "Nullus", "Constituere a sinistra", "Constituere a dextra", "Innens a sinistra"
+);
+
+/* private */ $wgSkinNamesLa = array(
+       'standard' => 'Norma',
+       'nostalgia' => 'Nostalgia',
+       'cologneblue' => 'Caerulus Colonia'
+) + $wgSkinNamesEn;
+
+
+$wgAllMessagesLa = array(
+
+# User Toggles
+
+"tog-underline" => "Subscribere nexi",
+"tog-highlightbroken" => "Formare nexos fractos <a href=\"\" class=\"new\">sici</a> (alioqui: sic<a href=\"\" class=\"internal\">?</a>).",
+"tog-justify"  => "Saepire capites",
+"tog-hideminor" => "Celare mutationes recentes minores",
+"tog-usenewrc" => "Mutationes recentes amplificatae (non efficit in tota navigatra)",
+"tog-numberheadings" => "Numerare indices necessario",
+"tog-rememberpassword" => "Recordari tesserae inter conventa (uti cookies)",
+"tog-editwidth" => "Capsa recensitorum totam latitudinem habet",
+"tog-editondblclick" => "Premere bis ut paginam recensere (uti JavaScript)",
+"tog-watchdefault" => "Custodire res novas et mutatas",
+"tog-minordefault" => "Notare totas mutations ut minor",
+"tog-previewontop" => "Monstrare praevisus ante capsam recensiti, non post ipsam",
+
+# Dates
+
+'sunday' => 'dies Solis',
+'monday' => 'dies Lunae',
+'tuesday' => 'dies Martis',
+'wednesday' => 'dies Mercuri',
+'thursday' => 'dies Iovis',
+'friday' => 'dies Veneris',
+'saturday' => 'dies Saturni',
+'january' => 'Ianuarii',
+'february' => 'Februarii',
+'march' => 'Martii',
+'april' => 'Aprilis',
+'may_long' => 'Maii',
+'june' => 'Iunii',
+'july' => 'Iulii',
+'august' => 'Augusti',
+'september' => 'Septembri',
+'october' => 'Octobri',
+'november' => 'Novembri',
+'december' => 'Decembri',
+'jan' => 'ian',
+'feb' => 'feb',
+'mar' => 'mar',
+'apr' => 'apr',
+'may' => 'mai',
+'jun' => 'iun',
+'jul' => 'iul',
+'aug' => 'aug',
+'sep' => 'sep',
+'oct' => 'oct',
+'nov' => 'nov',
+'dec' => 'dec',
+
+# Math
+'mw_math_png' => "Semper vertere PNG",
+'mw_math_simple' => "HTML si admodum simplex, alioqui PNG",
+'mw_math_html' => "HTML si fieri potest, alioqui PNG",
+'mw_math_source' => "Stet ut TeX (pro navigatri texti)",
+'mw_math_modern' => "Commendatum pro navigatri recentes",
+'mw_math_mathml' => 'MathML',
+);
+
+require_once( "LanguageUtf8.php" );
+
+class LanguageLa extends LanguageUtf8 {
+       function LanguageLa() {
+               global $wgNamespaceNamesLa, $wgMetaNamespace;
+               LanguageUtf8::LanguageUtf8();
+               $wgNamespaceNamesLa[NS_PROJECT_TALK] = 'Disputatio_' .
+                       $this->convertGrammar( $wgMetaNamespace, 'genitive' );
+       }
+
+       function getNamespaces() {
+               global $wgNamespaceNamesLa;
+               return $wgNamespaceNamesLa;
+       }
+
+       function getNsIndex( $text ) {
+               global $wgNamespaceNamesLa;
+               global $wgMetaNamespace;
+
+               foreach ( $wgNamespaceNamesLa as $i => $n ) {
+                       if ( 0 == strcasecmp( $n, $text ) ) { return $i; }
+               }
+
+               # Backwards compatibility hacks
+               if( $wgMetaNamespace == 'Vicipaedia' || $wgMetaNamespace == 'Victionarium' ) {
+                       if( 0 == strcasecmp( 'Wikipedia', $text ) ) return NS_PROJECT;
+                       if( 0 == strcasecmp( 'Disputatio_Wikipedia', $text ) ) return NS_PROJECT_TALK;
+               }
+               return false;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsLa;
+               return $wgQuickbarSettingsLa;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesLa;
+               return $wgSkinNamesLa;
+       }
+
+       function date( $ts, $adj = false ) {
+               if ( $adj ) { $ts = $this->userAdjust( $ts ); }
+
+               $d = $this->getMonthAbbreviation( substr( $ts, 4, 2 ) ) .
+                 " " . (0 + substr( $ts, 6, 2 )) . ", " .
+                 substr( $ts, 0, 4 );
+               return $d;
+       }
+
+       function timeanddate( $ts, $adj = false ) {
+               return $this->time( $ts, $adj ) . " " . $this->date( $ts, $adj );
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesLa;
+               if( isset( $wgAllMessagesLa[$key] ) ) {
+                       return $wgAllMessagesLa[$key];
+               }
+               return parent::getMessage( $key );
+       }
+
+       /**
+        * Convert from the nominative form of a noun to some other case
+        *
+        * Just used in a couple places for sitenames; special-case as necessary.
+        * Rules are far from complete.
+        */
+       function convertGrammar( $word, $case ) {
+               switch ( $case ) {
+               case 'genitive':
+                       // 1st and 2nd declension singular only.
+                       $in  = array( '/a$/', '/u[ms]$/', '/tio$/' );
+                       $out = array( 'ae',   'i',        'tionis' );
+                       return preg_replace( $in, $out, $word );
+               default:
+                       return $word;
+               }
+       }
+
+}
+
+
+?>
diff --git a/languages/LanguageLi.php b/languages/LanguageLi.php
new file mode 100644 (file)
index 0000000..5d68f52
--- /dev/null
@@ -0,0 +1,908 @@
+<?php
+/** Limburgish (Limburgs)
+  *
+  * @package MediaWiki
+  * @subpackage Language
+  */
+/**
+ * @access private
+ */
+$wgNamespaceNamesLi = array(
+       NS_MEDIA                        => 'Media',
+       NS_SPECIAL                      => 'Speciaal',
+       NS_MAIN                         => '',
+       NS_TALK                         => 'Euverlik',
+       NS_USER                         => 'Gebroeker',
+       NS_USER_TALK            => 'Euverlik_gebroeker',
+       NS_PROJECT                      => $wgMetaNamespace,
+       NS_PROJECT_TALK         => 'Euverlik_Wikipedia',
+       NS_IMAGE                        => 'Aafbeilding',
+       NS_IMAGE_TALK           => 'Euverlik_afbeelding',
+       NS_MEDIAWIKI            => 'MediaWiki',
+       NS_MEDIAWIKI_TALK       => 'Euverlik_MediaWiki',
+       NS_TEMPLATE                     => 'Sjabloon',
+       NS_TEMPLATE_TALK        => 'Euverlik_sjabloon',
+       NS_HELP                         => 'Help',
+       NS_HELP_TALK            => 'Euverlik_help',
+       NS_CATEGORY                     => 'Kategorie',
+       NS_CATEGORY_TALK        => 'Euverlik_kategorie'
+
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgQuickbarSettingsLi = array(
+ "Oetgesjakeld", "Links vas", "Rechts vas", "Links zwevend"
+);
+
+/* private */ $wgSkinNamesLi = array(
+       'standard' => "Standaard",
+       'nostalgia' => "Nostalgie",
+       'cologneblue' => "Keuls blauw",
+) + $wgSkinNamesEn;
+
+/* private */ $wgAllMessagesLi = array(
+
+'sunday' => 'zondig',
+'monday' => 'moandig',
+'tuesday' => 'dinsdig',
+'wednesday' => 'woonsdig',
+'thursday' => 'donderdig',
+'friday' => 'vriedig',
+'saturday' => 'zoaterdig',
+'january' => 'januari',
+'february' => 'fibberwari',
+'march' => 'maart',
+'april' => 'april',
+'may_long' => 'mei',
+'june' => 'juni',
+'july' => 'juli',
+'august' => 'augustus',
+'september' => 'september',
+'october' => 'oktober',
+'november' => 'november',
+'december' => 'december',
+'jan' => 'jan',
+'feb' => 'feb',
+'mar' => 'mrt',
+'apr' => 'apr',
+'may' => 'mei',
+'jun' => 'jun',
+'jul' => 'jul',
+'aug' => 'aug',
+'sep' => 'sep',
+'oct' => 'okt',
+'nov' => 'nov',
+'dec' => 'dec',
+
+# Bits of text used by many pages:
+# Diverse stukjes tekst
+"linktrail" => "/^([àáèéìíòóùúâêîôûäöüïëça-z]+)(.*)$/sDu",
+"mainpage"  => "Hoofdpagina",
+"about"   => "Info",
+'aboutsite' => 'Euver {{SITENAME}}',
+"aboutpage"  => "Wikipedia:info",
+"help"   => "Help",
+"helppage"  => "Wikipedia:Help",
+"bugreports" => "Foutenrapportage",
+"bugreportspage" => "Wikipedia:Foutenrapportage",
+"faq"   => "FAQ",
+"faqpage"  => "Wikipedia:Veulgestjilde vroage",
+"edithelp"  => "Hulp bie bewirken",
+"edithelppage" => "Wikipedia:Instructies",
+"cancel"  => "Annulere",
+"qbfind"  => "Zeuke",
+"qbbrowse"  => "Bladere",
+"qbedit"  => "Bewirke",
+"qbpageoptions" => "Pagina-opties",
+"qbpageinfo" => "Pagina-informatie",
+"qbmyoptions" => "mien opties",
+"mypage"  => "mien gebroekerspagina",
+"mytalk"  => "mien euverlik",
+"currentevents" => "In het nuuis",
+"errorpagetitle" => "Fout",
+"returnto"  => "Truuk noa $1.",
+"whatlinkshere" => "Pagina's die hierheen verwijzen",
+"help"   => "Hulp",
+"search"  => "Zeuke",
+"history"  => "Veurgeschiedenis",
+"printableversion" => "Printer-vriendelijke versie",
+"editthispage" => "Pagina bewirke",
+"deletethispage" => "Verwiedere",
+"protectthispage" => "Beveilige",
+"unprotectthispage" => "Beveiliging opheffen",
+"talkpage"  => "euverlikpagina",
+"subjectpage" => "Artikel",
+"articlepage"   => "Artikel",
+"userpage" => "gebroekerspagina",
+"wikipediapage" => "Artikel",
+"imagepage" => "Beschrijvingspagina",
+"otherlanguages" => "Andere talen",
+"redirectedfrom" => "(Doorverwezen vanaf $1)",
+"lastmodified" => "Deze pagina werd het laatst gewijzigd op $1.",
+"viewcount"  => "Deze pagina werd $1 maal bekeken.",
+"printsubtitle" => "(Uit {{SERVER}})",
+"protectedpage" => "Beveiligde pagina",
+"administrators" => "Wikipedia:Systeembeheerders",
+"sysoptitle" => "Toegang alleen voor systeembeheerders",
+"sysoptext"  => "De gevraagde handeling kan enkel uitgevoerd worden door systeembeheerders. Zie $1.",
+"developertitle" => "Toegang alleen voor systeemontwikkelaars",
+"developertext" => "De gevraagde handeling kan enkel uitgevoerd worden door systeemontwikkelaars. Zie $1.",
+"nbytes"  => "$1 bytes",
+"go"   => "OK",
+"ok"   => "OK",
+"sitetitle"  => "Wikipedia",
+"sitesubtitle" => "De vrije encyclopedie",
+"retrievedfrom" => "Afkomstig van Wikipedia, de Vrije Encyclopedie. \"$1\"",
+
+# Main script and global functions
+# Algemene functies
+"nosuchaction" => "Gevraagde handeling bestjit neet",
+"nosuchactiontext" => "De door de URL gespecifieerde handeling wordt neet herkend door de Wikipedia software",
+"nosuchspecialpage" => "De gevraagde speciale pagina is onvindbaar",
+"nospecialpagetext" => "U heeft een speciale pagina aangevraagd die neet wordt herkend door de Wikipedia software",
+
+# General errors
+# Algemene foutmeldingen
+"error"   => "Fout",
+"databaseerror" => "Database fout",
+"dberrortext" => "Bie ut zeuke is un syntaxfout in de database opgetreden.
+Dit kan zijn veroorzaakt door een illegale zoekactie (zie $5),
+ of het duidt op een fout in de software.
+De laatste zoekpoging in de database was:
+<blockquote><tt>$1</tt></blockquote>
+vanuit de functie \"<tt>$2</tt>\".
+MySQL gaf the foutmelding \"<tt>$3: $4</tt>\".",
+"noconnect"  => "Verbinden met de database op $1 was neet mogelijk",
+"nodb"   => "Selectie van database $1 neet mogelijk",
+"readonly"  => "Database geblokeerd",
+"enterlockreason" => "Geef un reden veur de blokkiering en wielang ut waarschijnlijk git doere. De ingegeven reden zal aan de gebroekers getoond worden.",
+"readonlytext" => "De database van Wikipedia is momenteel gesloten voor nieuwe bewerkingen en wijzigingen, waarschijnlijk voor bestandsonderhoud.
+De verantwoordelijke systeembeheerder gaf hiervoor volgende reden op:
+<p>$1",
+"missingarticle" => "De database heeft een paginatekst (\"$1\") die het zou moeten vinden neet gevonden. Dit is geen fout in de database, maar waarschijnlijk in de software. Meld dit a.u.b. aan een beheerder, met vermelding van de URL.",
+"internalerror" => "Interne fout",
+"filecopyerror" => "Bestand \"$1\" naar \"$2\" kopiëren neet mogelijk.",
+"filerenameerror" => "Wijziging titel bestand \"$1\" in \"$2\" neet mogelijk.",
+"filedeleteerror" => "Kos bestjand \"$1\" neet weghoale.",
+"filenotfound" => "Kos bestjand \"$1\" neet vinge.",
+"unexpected" => "Onverwachte waarde: \"$1\"=\"$2\".",
+"formerror"  => "Fout: kos formulier neet verzenden",
+"badarticleerror" => "Deze handeling kan op deze pagina neet worden uitgevoerd.",
+"cannotdelete" => "Kos de pagina of afbeelding neet verwijderen.",
+"badtitle"              => "Ongeldige paginatitel",
+"badtitletext"  => "De opgevraagde pagina is neet beschikbaar of leeg.",
+"perfdisabled" => "Om te veurkomme dat de database weurt euverbelast is deze pagina allein tusje 03:00 en 15:00 (West-Europese zomertied) beschikbaar.",
+
+# Login and logout pages
+# Aanmelden en afmelden
+"logouttitle" => "Afmelden gebroeker",
+"logouttext" => "U bent nu afgemeld.
+U kan Wikipedia anoniem blijven gebruiken, of u opnieuw aanmelden onder dezelfde of onder een andere naam.\n",
+
+"welcomecreation" => "<h2>Welkom, $1!</h2><p>Uw gebroekersprofiel is aangemaakt. U kan nu uw persoonlijke voorkeuren instellen.",
+
+"loginpagetitle" => "gebroekersnaam",
+"yourname"  => "Uw gebroekersnaam",
+"yourpassword" => "Uw wachtwoord",
+"yourpasswordagain" => "Wachtwoord opnieuw ingeven",
+"newusersonly" => " (alleen nieuwe gebroekers)",
+"remembermypassword" => "mien wachtwoord onthouden voor latere sessies.",
+"loginproblem" => "<b>Er is een probleem met het aanmelden.</b><br />Probeer het opnieuw a.u.b.",
+"alreadyloggedin" => "<strong>gebroeker $1, u bent al aangemeld.</strong><br />\n",
+
+"login"   => "Aanmelden",
+"userlogin"  => "Aanmelden",
+"logout"  => "Afmelden",
+"userlogout" => "Afmelden",
+"createaccount" => "Nieuw gebroekersprofiel aanmaken.",
+"badretype"  => "De ingevoerde wachtwoorden verschillen van elkaar.",
+"userexists" => "De gebroekersnaam die u heeft ingevoerd is al in gebruik. Gelieve een andere naam te kiezen.",
+"youremail"  => "Uw e-mailadres",
+"yournick"  => "Uw bijnaam (voor handtekeningen)",
+"emailforlost" => "Als u uw wachtwoord bent vergeten kun u een nieuw naar uw e-mailadres laten opsturen.",
+"loginerror" => "Inlogfout",
+"noname"  => "U dient een gebroekersnaam op te geven.",
+"loginsuccesstitle" => "Aanmelden gelukt.",
+"loginsuccess" => "U bent nu aangemeld bij Wikipedia als \"$1\".",
+"nosuchuser" => "Er bestaat geen gebroeker met de naam \"$1\". Controleer uw spelling, of gebruik onderstaand formulier om een nieuw gebroekersprofiel aan te maken.",
+"wrongpassword" => "Het ingegeven wachtwoord is neet juist. Probeer het opnieuw.",
+"mailmypassword" => "Stuur mij een nieuw wachtwoord op",
+"passwordremindertitle" => "Herinnering wachtwoord Wikipedia Li",
+"passwordremindertext" => "Iemand (waarschijnlijk uzelf) vanaf IP-adres $1 heeft verzocht u een nieuw wachtwoord voor Wikipedia toe te zenden. Het nieuwe wachtwoord voor gebroeker \"$2\" is \"$3\". Advies: nu aanmelden en uw wachtwoord wijzigigen.",
+"noemail"  => "Er is geen e-mailadres geregistreerd voor \"$1\".",
+"passwordsent" => "Er is een nieuw wachtwoord verzonden naar het e-mailadres wat geregistreerd staat voor \"$1\".
+Gelieve na ontvangst opnieuw aan te melden.",
+
+# Edit pages
+# Pagina bewerken
+"summary"  => "Samenvatting",
+"minoredit"  => "Dit is un kleine verangering",
+"watchthis" => "Volg dees pagina",
+"savearticle" => "Pagina opsjloan",
+"preview"  => "Noakieke",
+"showpreview" => "Toon bewerking ter controle",
+"blockedtitle" => "gebroeker is geBlokkierd",
+"blockedtext" => "Uw gebroekersnaam of IP-adres is door $1 geBlokkierd. De opgegeven reden:<br />$2<p>. U kunt voor euverlik contact opnemen met de [[Wikipedia:Systeembeheerders|systeembeheerders]].",
+"newarticle" => "(Nieuw)",
+"newarticletext" => "Verwijder dit en beschrijf hier de nieuwe pagina.",
+"noarticletext" => "(Deze pagina bevat momenteel geen tekst)",
+"updated"  => "(Bijgewerkt)",
+"note"   => "<strong>Opmerking:</strong> ",
+"previewnote" => "Let op: dit is een controlepagina; uw tekst is nog neet opgeslagen!",
+"previewconflict" => "Deze versie toont hoe de tekst in het bovenste veld eruit gaat zien wanneer u zou opslaan.",
+"editing"  => "Bewerkingspagina: $1",
+"editconflict" => "Bewerkingsconflict: $1",
+"explainconflict" => "Iemand anders heeft deze pagina gewijzigd nadat u aan deze bewerking bent begonnen. Het bovenste tekstveld toont de huidige versie van de pagina. U zal uw eigen wijzigingen moeten integreren in die tekst. Alleen de tekst in het bovenste veld wordt bewaard wanneer u kiest voor \"Pagina opslaan\".<br />",
+"yourtext"  => "Uw tekst",
+"storedversion" => "Opgesjlage versie",
+"editingold" => "<strong>WAARSCHUWING: U bent bezig een oude versie van deze pagina te bewerken. Wanneer u uw bewerking opslaat, gaan alle wijzigingen die na deze versie gedaan zijn verloren.</strong>",
+"yourdiff"  => "Wijzigingen",
+"copyrightwarning" => "Opgelet: Alle bijdragen aan Wikipedia worden geacht te zijn vrijgegeven onder de GNU Free Documentation License. Als u neet wil dat uw tekst door anderen naar believen bewerkt en verspreid kan worden, kies dan neet voor 'Pagina Opslaan'.<br /> Hierbij belooft u ons tevens dat u deze tekst zelf hebt geschreven, of overgenomen uit een vrije, openbare bron.<br /> <strong>GEBRUIK GEEN MATERIAAL DAT BESCHERMD WORDT DOOR AUTEURSRECHT, TENZIJ JE DAARTOE TOESTEMMING HEBT!</strong>",
+
+
+# History pages
+# Geschiedenis pagina's
+"revhistory" => "Bewirkingsgeschiedenis",
+"nohistory"  => "Deze pagina hèt nog gein bewirkinge ondergaan.",
+"revnotfound" => "Wieziging neet gevonge",
+"revnotfoundtext" => "De opgevroagde ouwe versie van deze pagina is onvindbaar. Controleer a.u.b. de URL die u gebruikte om naar deze pagina te gaan.\n",
+"loadhist"  => "Bezig met het laden van de paginageschiedenis",
+"currentrev" => "Huidige versie",
+"revisionasof" => "Versie op $1",
+"cur"   => "huidig",
+"next"   => "volgende",
+"last"   => "vorige",
+"orig"   => "orig",
+"histlegend" => "Verklaring afkortingen: (wijz) = verschil met huidige versie, (vorige) = verschil met voorgaande versie, K = kleine wijziging",
+
+# Diffs
+# Verschil
+"difference" => "(Verschil tussen bewerkingen)",
+"loadingrev" => "bezig paginaversie te laden",
+"lineno"  => "Regel $1:",
+"editcurrent" => "De huidige versie van deze pagina bewerken",
+
+# Search results
+# Zoek resultaten
+"searchresults" => "Zoekresultaten",
+"searchresulttext" => "Voor meer informatie over zoeken op Wikipedia: zie $1.",
+"searchquery" => "Voor zoekopdracht \"$1\"",
+"badquery"  => "Slecht geformuleerde zoekopdracht",
+"badquerytext" => "Uw zoekopdracht kon neet worden uitgevoerd. Dit komt wellicht doordat u heeft geprobeerd een woord van minder dan drie letters te zoeken; dat wordt door de software neet ondersteund. Het is ook mogelijk dat u de zoekterm verkeerd hebt ingetypt, zoals bij \"vissen en en schubben\".",
+"matchtotals" => "De zoekterm \"$1\" is gevonden in $2 paginatitels en in de tekst van $3 pagina's.",
+"titlematches" => "Overeenkomst met volgende titels",
+"notitlematches" => "Geen enkele paginatitel gevonden met de opgegeven zoekterm",
+"textmatches" => "Overeenkomst met artikel inhoud",
+"notextmatches" => "Geen artikel gevonden met opgegeven zoekterm",
+"prevn"   => "vorige $1",
+"nextn"   => "volgende $1",
+"viewprevnext" => "($1) ($2) ($3) bekijken.",
+"showingresults" => "Hieronder de resultaten <b>$1</b> beginnend met #<b>$2</b>.",
+"nonefound"  => "<strong>Merk op:</strong> wanneer een zoekopdracht mislukt komt dat vaak door gebruik van (in het Engels) veel voorkomende woorden zoals \"of\" en \"be\", die neet geïndexeerd zijn, of door verschillende zoektermen tegelijk op te geven (u krijgt dan alleen in pagina's waaarin alle opgegeven termen voorkomen).",
+"powersearch" => "Zoeken",
+"powersearchtext" => "
+ Zoek in naamruimten :<br />
+$1<br />
+$2 Toon redirects   Zoek: $3 $9",
+
+# Preferences page
+# Voorkeuren
+"preferences" => "Voorkeuren",
+"prefsnologin" => "Niet aangemeld",
+"prefsnologintext" => "U dient [[Special:Userlogin|aangemeld]] te zijn om voorkeuren te kunnen instellen.",
+"prefslogintext" => "U bent aangemeld als \"$1\". Uw interne identificatienummer is $2.",
+"prefsreset" => "Standaardvoorkeuren hersteld.",
+"qbsettings" => "Menubalkinstellingen",
+"changepassword" => "Wachtwoord wijzigen",
+"skin"   => "Wikipedia-Uiterlijk",
+"saveprefs"  => "Voorkeuren opslaan",
+"resetprefs" => "Standaardvoorkeuren herstellen",
+"oldpassword" => "Huidig wachtwoord",
+"newpassword" => "Nieuw wachtwoord",
+"retypenew"  => "Voer het nieuwe wachtwoord nogmaals in",
+"textboxsize" => "Afmetingen tekstveld",
+"rows"   => "Regels",
+"columns"  => "Kolommen",
+"searchresultshead" => "Instellingen voor zoekresultaten",
+"resultsperpage" => "Aantal per bladzijde te tonen zoekresultaten",
+"contextlines" => "Aantal regels per gevonden pagina",
+"contextchars" => "Aantal tekens van de context per regel",
+"stubthreshold" => "Grootte waaronder een pagina als 'stub' wordt aangegeven",
+"recentchangescount" => "Aantal titels in liest recente wijzigingen",
+"savedprefs" => "Uw voorkeuren zijn opgeslagen.",
+"timezonetext" => "De tied van de server is UTC (Coordinated Universal Time) Geef aan hoeveel uur de plaatselijke tied in uw woonplaats verschilt met die van de server. Voor o.a. België en Nederland: +1 (+2 zomertied); voor Suriname en voor de Nederlandse Antillen: -4; voor Zuid-Afrika: +2.",
+"localtime" => "Plaatselijke tied",
+"timezoneoffset" => "tiedsverschil",
+"emailflag"  => "E-mail ontvangen van andere gebruiken uitschakelen",
+
+# Recent changes
+# Recente wijzigingen
+"recentchanges" => "Recente wijzigingen",
+"recentchangestext" => "Deze pagina toont de meest recente wijzigingen aan Wikipedia.
+Mocht u hier nieuw zijn, dan welkom bij Wikipedia! Bekijk AUB de volgende pagina's eens: [[Wikipedia:Veel gestelde vragen|Veel gestelde vragen]], [[Wikipedia:Instructies|Instructies]], [[Wikipedia:Objectiviteit|Objectiviteit]] en [[Wikipedia:Wat je neet moet doen|Wat je NIET moet doen]].
+Als u pagina's wilt verwijderen, ga naar [[Wikipedia:Te verwijderen pagina's|Te verwijderen pagina's]], als u iets wilt bediscussiëren, ga naar [[Wikipedia:euverlik gewenst|euverlik gewenst]]. Er is ook een email-liest voor WikipediaNL: [http://www.wikipedia.org/mailman/listinfo/wikinl-l WikiNL-l].
+<br />Om Wikipedia te laten slagen is het erg belangrijk '''geen''' materiaal toe te voegen waarop iemand anders auteursrechten heeft, tenzij u daartoe toestemming heeft. De wettelijke gevolgen van inbreuk op de rechten van anderen zouden de hele onderneming zwaar kunnen schaden.",
+"rcloaderr"  => "Meest recente wijzigingen laden",
+"rcnote"  => "Hieronder zijn de <strong>$1</strong> laatste wijzigingen gedaan in de laatste <strong>$2</strong> dagen.",
+"rcnotefrom"  => "Veranderingen sinds <b>$2</b> (met een maximum van <b>$1</b> veranderingen).",
+"rclistfrom"  => "Toon de veranderingen beginnend vanaf $1",
+# "rclinks"  => "Bekijk de $1 laatste wijzigingen in de laatste $2 uren / laatste $3 dagen.",
+"rclinks"  => "Bekijk de $1 laatste wijzigingen in de laatste $2 dagen.",
+"rchide"  => "in $4 vorm; $1 kleine wijzigingen; $2 wijzigingen op speciale pagina's zoals euverlik- en gebroekerspagina's; $3 meervoudige wijzigingen.",
+"diff"   => "wijz",
+"hist"   => "hist",
+"hide"   => "verberg",
+"show"   => "toon",
+"tableform"  => "tabel",
+"listform"  => "liest",
+"nchanges"  => "$1 wijzigingen",
+"minoreditletter" => "K",
+"newpageletter" => "N",
+
+# Upload
+#
+"upload"  => "Upload",
+"uploadbtn"  => "upload bestand",
+"uploadlink" => "upload afbeelding",
+"reupload"  => "Opnieuw uploaden",
+"reuploaddesc" => "Terug naar het uploadformulier.",
+"uploadnologin" => "Niet aangemeld",
+"uploadnologintext" => "U dient [[Special:Userlogin|aangemeld te zijn]]
+om bestanden te uploaden.",
+"uploaderror" => "upload fout",
+"uploadtext" => "<strong>STOP!</strong> Voor u iets hier upload,
+wees zeker dat het in overeenkomst is met het Wikipedia
+[[Wikipedia:Beleid_voor_gebruik_van_afbeeldingen|afbeeldingsbeleid]].
+
+Om de reeds ge-uploade bestanden te bekijken of te zoeken ga naar de . [[Special:Imagelist|liest van ge-uploade bestanden]].
+Uploads en verwijderingen worden bijgehouden in het
+[[Special:Log/upload|upload logboek]].
+
+Gebroek het onderstaande formulier om bestanden zoals afbeeldingen en geluidsbestanden die relevant zijn voor uw artikel te u-loaden. Bij de meeste browers zoals 'Internet Explorer' en 'Mozilla' zult u een \"Bladeren...\" of \"Browse..\" knop zien die een standaard dialoogscherm van uw bestuuringssysteem oproept. Kiest u een bestand, dan zal het ingevuld worden in het veld naast de \"Bladeren...\" knop. U dient ook het vakje aan te vinken waarmee u bevestigt dat er geen schending van auteursrechten plaatsvindt door het gebruik van dat bestand. Vul het veld \"Omschrijving\" in. Druk op de \"Upload\" knop om het uploaden te voltooien. Dit kan even duren als u een langzame internetverbinding gebruikt.
+
+Gebroek bij voorkeur JPEG voor foto's, PNG voor tekeningen en dergelijke en OGG voor geluid.
+Geef uw bestanden een duidelijk omschrijvende naam om verwarring te voorkomen. Om het bestand in een pagina te laten verschijnen, kunt u het volgende doen;  <b><nowiki>[[afbeelding:uw_foto.jpg]]</nowiki></b> of <b><nowiki>[[afbeelding:uw_logo.png|alt text]]</nowiki></b> of <b><nowiki>[[media:uw_geluid.ogg]]</nowiki></b> voor audio.
+
+Vergeet neet dat net als met andere pagina's op Wikipedia anderen de ge-uploade bestanden kunnen verwijderen indien men denkt dat dat in het voordeel van het project is. Bij misbruik van dit systeem kan u de toegang tot Wikipedia ontzegd worden.",
+"uploadlog"  => "upload logboek",
+"uploadlogpage" => "Upload_logboek",
+"uploadlogpagetext" => "Hieronder de liest met de meest recent ge-uploade bestanden. Alle tieden zijn servertied (UTC).
+<ul>
+</ul>
+",
+"filename"  => "Bestandsnaam",
+"filedesc"  => "Beschrijving",
+"copyrightpage" => "Wikipedia:Auteursrechten",
+"copyrightpagename" => "Wikipedia auteursrechten",
+"uploadedfiles" => "Ge-uploade bestanden",
+"ignorewarning" => "Negeer de waarschuwing en sla het bestand op.",
+"minlength"  => "De naam van het bestand moet uit ten minste drie tekens bestaan.",
+"badfilename" => "De naam van het bestand is gewijzigd in \"$1\".",
+"badfiletype" => "\".$1\" is geen aanbevolen afbeeldings bestandsformaat.",
+"largefile"  => "Aanbeveling: maak afbeeldingen neet groter dan 100k",
+"successfulupload" => "De upload was succesvol",
+"fileuploaded" => "<b>Het uploaden van bestand \"$1\" is geslaagd.</b> Gelieve deze link naar de omschrijvingspagina te volgen: ($2). Vul daar informatie in over dit bestand, bijvoorbeeld de oorsprong, wanneer en door wie het gemaakt is en wat u verder er nog over te vertellen heeft.",
+"uploadwarning" => "Upload waarschuwing ",
+"savefile"  => "Bestand opslaan",
+"uploadedimage" => "heeft ge-upload: \"[[$1]]\"",
+
+# Image list
+# Afbeeldingsliest
+"imagelist"  => "liest van afbeeldingen",
+"imagelisttext" => "Hier volgt een liest met $1 afbeeldingen geordend $2.",
+"getimagelist" => "liest van afbeeldingen ophalen",
+"ilsubmit"  => "Zoek",
+"showlast"  => "Toon de laatste $1 afbeeldingen geordend $2.",
+"byname"  => "op naam",
+"bydate"  => "op datum",
+"bysize"  => "op grootte",
+"imgdelete"  => "verw",
+"imgdesc"  => "besc",
+"imglegend"  => "Verklaring: (besc) = toon/verander beschrijving van de afbeelding, (verw) = verwijdering de afbeelding.",
+"imghistory" => "Geschiedenis van de afbeelding",
+"revertimg"  => "rev",
+"deleteimg"  => "verw",
+"imghistlegend" => "Verklaring: (cur)= huidige afbeelding, (verw) = verwijder de oude versie, (rev) = breng oude versie terug.<br />
+<i>Klik op de datum om de afbeeldingen die ge-upload zijn op die datum te zien</i>.",
+"imagelinks" => "Afbeeldingsverwijzingen",
+"linkstoimage" => "Deze afbeelding wordt gebruikt op de volgende pagina's:",
+"nolinkstoimage" => "Geen enkele pagina gebruikt deze afbeelding.",
+
+# Statistics
+# Statistieken
+"statistics" => "Statistieken",
+"sitestats"  => "Statistieken betreffende Wikipedia LI",
+"userstats"  => "Statistieken betreffende gebroekers",
+"sitestatstext" => "Er zijn <b>$1</b> pagina's in de database. Hierbij zijn inbegrepen \"euverlik\" pagina's, pagina's over Wikipedia, extreem korte \"stub\" pagina's, redirects, en diverse andere pagina's die waarschijnlijk neet als artikel moeten worden geteld. Na uitsluiting daarvan, is er een geschat aantal van <b>$2</b> artikels.<p>
+Er is in totaal $3 maal een pagina bekeken, en $4 maal een pagina bewerkt. Dat geeft een gemiddelde van $5 bewerkingen per pagina, en $6 paginabezoeken per wijziging.",
+"userstatstext" => "Er zijn momenteel $1 geregistreerde gebroekers; hiervan zijn er $2 systeembeheerders (zie $3).",
+
+# Maintenance Page
+#
+"maintenance"           => "Onderhoudspagina",
+"maintnancepagetext"    => "Op deze pagina vindt u een aantal handige zoekopdrachten om kleine alledaagse problemen in de Wikipedia te verhelpen. Sommige van deze zoekopdrachten vormen een grote belasting voor de database; ga dus neet na elke paar pagina's die u hersteld heeft, de pagina opnieuw laden.",
+"maintenancebacklink"   => "Terug naar de Onderhoudspagina",
+"disambiguations"       => "Doorverwijspagina's",
+"disambiguationspage"   => "Wikipedia:Doorverwijspagina",
+"disambiguationstext"   => "De onderstaande artikelen verwijzen naar een [[Wikipedia:Doorverwijspagina|doorverwijspagina]]. Deze zouden waarschijnlijk direct naar de onderwerpspagina moeten verwijzen. <br />Als doorverwijspagina's worden die pagina's beschouwd waar vanaf $1 naar verwezen wordt.<br />Opmerking: Deze liest toont alleen pagina's vanuit de hoofdnaamruimte, en dus neet euverlikpagina's, Wikipedia:pagina's en dergelijke.",
+"doubleredirects"       => "Dubbele redirects",
+"doubleredirectstext"   => "<b>Let op:</b> Er kunnen in deze liest redirects staan die er neet in thuishoren. Dat komt over het algemeen doordat er na de #REDIRECT nog andere links op de pagina staan.<br />\nOp elke regel vindt u de eerste redirectpagina, de tweede redirectpagina en de eerste regel van de tweede redirectpagina. Normaal gesproken bevat deze laatste de pagina waar de eerste redirect naartoe zou moeten verwijzen.",
+"brokenredirects"       => "Gebroken redirects",
+"brokenredirectstext"   => "De onderstaande redirectpagina's bevatten een redirect naar een neet-bestaande pagina.",
+"selflinks"             => "Pagina's die naar zichzelf verwijzen",
+"selflinkstext"         => "De volgende pagina's verwijzen naar zichzelf, wat neet hoort te gebeuren.",
+"mispeelings"           => "Pagina's met spelfouten",
+"mispeelingstext"       => "De volgende pagina's bevatten een veel voorkomende spel- of typfout, die staat aangegeven op de liest in $1. Daar staat meestal ook (tussen haakjes) de juiste spelling.",
+"mispeelingspage"       => "Veel voorkomende spelfouten",
+"missinglanguagelinks"  => "Ontbrekende taallinks",
+"missinglanguagelinksbutton"    => "Vind ontbrekende taallinks voor",
+"missinglanguagelinkstext"      => "De onderstaande artikelen bevatten geen taallink naar een overeenkomende pagina in de taal \"$1\".",
+
+# Miscellaneous special pages
+# Diverse speciale pagina's
+"orphans"  => "Weespagina's",
+"lonelypages" => "Weespagina's",
+"unusedimages" => "Ongebruikte afbeeldingen",
+"popularpages" => "Populaire artikels",
+"nviews"  => "$1 keer bekeken",
+"wantedpages" => "Gewenste pagina's",
+"nlinks"  => "$1 verwijzingen",
+"allpages"  => "Alle pagina's",
+"randompage" => "Willekeurig artikel",
+"shortpages" => "Korte artikels",
+"longpages"  => "Lange artikels",
+"listusers"  => "liest van gebroekers",
+"specialpages" => "Speciale pagina's",
+"spheading"  => "Speciale pagina's",
+"protectpage" => "Beveilig pagina",
+"recentchangeslinked" => "Volg links",
+"rclsub"  => "(van pagina's waarnaar \"$1\" verwijst)",
+"debug"   => "Bugreparatie",
+"newpages"  => "Nieuwe pagina's",
+"movethispage" => "Verplaats deze pagina",
+"unusedimagestext" => "<p>Let op! Het zou kunnen dat er via een directe link verwezen wordt naar een afbeelding, bijvoorbeeld vanuit een anderstalige Wikipedia. Het is daarom mogelijk dat een afbeelding hier vermeld staat terwijl het wel degelijk gebruikt wordt.",
+"booksources" => "Boekwinkels",
+"booksourcetext" => "Hieronder is een liest van externe websites die boeken verkopen en ook verdere informatie hierover kunnen verstekken. Via een ISBN-nummer in een artikel kan u via deze pagina een werk opzoeken. <p>Deze dienst is enkel ter uwer informatie. Wikipedia heeft <u>geen enkele</u> relatie met deze websites.",
+
+# Email this user
+# E-mail deze gebroeker
+"mailnologin" => "Geen e-mailadres gekend voor deze gebroeker",
+"mailnologintext" => "U dient [[Special:Userlogin|aangemeld te zijn]]
+en een geldig e-mailadres in uw [[Special:Preferences|voorkeuren]]
+to send e-mail to other users.",
+"emailuser"  => "E-mail deze gebroeker",
+"emailpage"  => "E-mail gebroeker",
+"emailpagetext" => "Indien deze gebroeker een geldig e-mailadres heeft opgegeven dan kan u via dit formulier een bericht verzenden. Het e-mailadres dat u heeft opgegeven bij uw voorkeuren zal als afzender gebruikt worden.",
+"noemailtitle" => "Geen e-mailadres gekend voor deze gebroeker",
+"noemailtext" => "Deze gebroeker heeft geen geldig e-mailadres opgegeven of heeft deze functie uitgeschakelt.",
+"emailfrom"  => "Van",
+"emailto"  => "Aan",
+"emailsubject" => "Onderwerp",
+"emailmessage" => "Bericht",
+"emailsend"  => "Verstuur bericht",
+"emailsent"  => "E-mail versturen",
+"emailsenttext" => "Uw bericht is verzonden.",
+
+# Watchlist
+# Volgliest
+"watchlist"  => "Volgliest",
+"watchlistsub" => "(van gebroeker \"$1\")",
+"nowatchlist" => "Er staat neets op uw volgliest.",
+"watchnologin" => "U bent neet aangemeld",
+"watchnologintext" => "Om uw volgliest te veranderen dient u eerst [[Special:Userlogin|aangemeld]]
+te zijn.",
+"addedwatch" => "Toegevoegd aan volgliest",
+"addedwatchtext" => "De pagina \"$1\" is aan uw [[Special:Watchlist|volgliest]] toegevoegd.
+Toekomstige wijzigingen aan deze pagina en euverlikpagina zullen hier vermeld worden.
+Ook zullen deze pagina's in het <b>vet</b> verschijnen in de [[Special:Recentchanges|liest van recente wijzigingen]] zodat u ze eenvoudiger kan opmerken.
+
+Indien u een pagina wenst te verwijderen van uw volgliest klik dan op \"Van volgliest verwijderen\" in de menubalk.",
+"removedwatch" => "Van volgliest verwijderen",
+"removedwatchtext" => "De pagina \"$1\" is van uw volgliest verwijderd.",
+"watchthispage" => "Volg deze pagina",
+"unwatchthispage" => "Niet meer volgen",
+"notanarticle" => "Is geen artikel",
+
+
+# Delete/protect/revert
+# Verwijderen/beschermen/annuleren
+"deletepage" => "Pagina verwijderen",
+"confirm"  => "Bevestig",
+"confirmdelete" => "Bevestig verwijdering",
+"deletesub"  => "(Verwijderen \"$1\")",
+"confirmdeletetext" => "U bent staat op het punt een pagina of afbeelding voorgoed te verwijderen. Dit verwijdert alle inhoud en geschiedenis van de database. Bevestig hieronder dat dit inderdaad uw bedoeling is, dat u de gevolgen begrijpt, en dat uw verwijdering overeenkomt met de [[Wikipedia:Instructies]].",
+
+"actioncomplete" => "Actie voltooid",
+"deletedtext" => "\"$1\" is verwijderd. Zie $2 voor een overzicht van recente verwijderingen.",
+"deletedarticle" => "\"$1\" is verwijderd",
+"dellogpage" => "Logboek_verwijderde_pagina's", # This one needs the underscores!
+"dellogpagetext" => "Hieronder ziet u een liest van de meest recentelijk verwijderde pagina's en afbeeldingen. Alle tieden zijn servertied, UTC-0.",
+"deletionlog" => "Logboek verwijderde pagina's",
+"reverted"  => "Eerdere versie hersteld",
+"deletecomment" => "Reden voor verwijdering",
+"imagereverted" => "De omzetting naar de oudere versie is geslaagd.",
+"rollback"      => "Wijzigingen ongedaan maken",
+"rollbacklink"  => "Terugdraaien",
+"cantrollback"  => "Ongedaan maken van wijzigingen onmogelijk: Dit artikel heeft slechts 1 auteur.",
+"revertpage"    => "Hersteld tot de versie na de laatste wijziging door $1.",
+
+# Undelete
+"undelete" => "Verwijderde pagina terugplaatsen",
+"undeletepage" => "Verwijderde pagina's bekijken en terugplaatsen",
+"undeletepagetext" => "De onderstaande pagina's zijn verwijderd, maar bevinden zich nog steeds in het archief, en kunnen teruggeplaatst worden.",
+"undeletearticle" => "Verwijderde pagina terugplaatsen",
+"undeleterevisions" => "$1 versies in het archief",
+"undeletehistory" => "Als u een pagina terugplaatst, worden alle versies als oude versies teruggeplaatst. Als er al een nieuwe pagina met dezelfde naam is aangemaakt, zullen deze versies als oude versies worden teruggeplaatst, maar de huidige versie neet gewijzigd worden.",
+"undeleterevision" => "Verwijderde versie van $1",
+"undeletebtn" => "Terugplaatsen!",
+"undeletedarticle" => "\"$1\" is teruggeplaatst.",
+"undeletedtext" =>"Het artikel [[$1]] is teruggeplaatst. Zie [[Wikipedia:Logboek verwijderde pagina's]] voor een liest van de meest recente verwijderingen en terugplaatsingen.",
+
+# Contributions
+# Bijdragen
+"contributions" => "Bijdragen per gebroeker",
+"contribsub" => "Veur $1",
+"nocontribs" => "Gein wijzigingen gevonden die aan de gestelde criteria voldoen.",
+"ucnote"  => "Hieonger zeet ger de litste <b>$1</b> wijzigingen van deze gebroeker in de laatste <b>$2</b> dagen.",
+"uclinks"  => "Bekijk de laatste <b>$1</b> veranderingen; bekijk de laatste <b>$2</b> dagen.",
+"uctop" => " (litste wijziging)",
+
+# What links here
+# Wat linkt hier
+"whatlinkshere" => "Links noa deze pagina",
+"notargettitle" => "Gein doelpagina",
+"notargettext" => "Ger hubt neet gezag veur welleke pagina ger deze functie wilt bekieke.",
+"linklistsub" => "(liest van verwiezingen)",
+"linkshere"  => "De volgende pagina's verwiezen hienoatoe:",
+"nolinkshere" => "Gin enkele pagina verwiest hieheen.",
+"isredirect" => "redirect pagina",
+
+# Block/unblock IP
+#
+"blockip"  => "Blokkier IP-adres",
+"blockiptext" => "Gebroek het onderstaande formulier om schrijftoegang van een bepaald IP-adres te verbieden. Dit mag enkel gedaan worden om vandalisme te voorkomen en moet in overeenstemming zijn met de [[Wikipedia:spelregels|spelregels]] van Wikipedia. Vul een specifieke reden in.",
+"ipaddress"  => "IP-adres",
+"ipbreason"  => "Reden",
+"ipbsubmit"  => "Blokkier dit IP-adres",
+"badipaddress" => "Het IP-adres heeft een ongeldige opmaak.",
+"blockipsuccesssub" => "Blokkering gelukt",
+"blockipsuccesstext" => "Het IP-adres \"$1\" is geBlokkierd.<br />
+Zie de [[Special:Ipblocklist|liest van geBlokkierde IP-adressen]].",
+"unblockip"  => "De-Blokkier IP-adres",
+"unblockiptext" => "Gebroek het onderstaande formulier om terug schrijftoegang te geven aan een geBlokkierd IP-adres.",
+"ipusubmit"  => "De-Blokkier dit IP-adres.",
+"ipusuccess" => "Het IP-adres \"$1\" is gedeBlokkierd.",
+"ipblocklist" => "Liest van geblokkierde IP-adressen.",
+"blocklistline" => "Op $1 blokkierde $2 ut adres $3 ($4)",
+"blocklink"  => "Blokkier",
+"unblocklink" => "de-Blokkier",
+"contribslink" => "bijdragen",
+
+# Developer tools
+# Ontwikkelingsgereedsschap
+"lockdb"  => "Blokkier de database",
+"unlockdb"  => "De-Blokkier de database",
+"lockdbtext" => "Waarschuwing: De database blokkeren heeft tot gevolg dat geen enkele gebroeker meer in staat is de pagina's te bewerken, hun voorkeuren te wijzigen of iets anders te doen waarvoor er wijzigingen in de database nodig zijn.",
+"unlockdbtext" => "Het de-blokkeren van de database zal de gebroekers de mogelijkheid geven om wijzigingen aan pagina's op te slaan, hun voorkeuren te wijzigen en alle andere bewerkingen waarvoor er wijzigingen in de database nodig zijn. Is dit inderdaad wat u wilt doen?.",
+"lockconfirm" => "Ja, ik wil de database blokkeren.",
+"unlockconfirm" => "Ja, ik wil de database de-blokkeren.",
+"lockbtn"  => "Blokkier de database",
+"unlockbtn"  => "De-Blokkier de database",
+"locknoconfirm" => "U heeft neet het vakje aangevinkt om uw keuze te bevestigen.",
+"lockdbsuccesssub" => "Blokkering database succesvol",
+"unlockdbsuccesssub" => "Blokkering van de database opgeheven",
+"lockdbsuccesstext" => "De database van Wikipedia LI is geblokkierd.
+Vergeet neet de database opnieuw te de-blokkeren zodra u klaar bent met uw onderhoud.",
+"unlockdbsuccesstext" => "Blokkering van de database van Wikipedia LI is opgeheven.",
+
+# Move page
+# Verplaats pagina
+"movepage"  => "Verplaats pagina",
+"movepagetext" => "Door middel van het onderstaande formulier kan u de titel van een pagina hernoemen. De voorgeschiedenis van de oude pagina zal deze van de nieuwe worden. De oude titel zal automatisch een doorverwijzing worden naar de nieuwe. U kunt een dergelijke hernoeming alleen doen plaatsvinden, als er geen pagina bestaat met de nieuwe naam, of als er slechts een redirect zonder verdere geschiedenis is.",
+"movepagetalktext" => "De biebeheurende euverlikpagina weurt auch verplaatsjt, mer '''neet''' in de volgende gevallen:
+* Als de pagina naar een andere naamruimte wordt verplaatst
+* Als er al een neet-lege euverlikpagina bestaat onder de andere naam
+* Als u de onderstaande radiobox neet aangevinkt laat",
+"movearticle" => "Verplaatsj pagina",
+"movenologin" => "Neet aangemeld",
+"movenologintext" => "U dient [[Special:Userlogin|aangemeld]]
+te zijn om een pagina te verplaatsen.",
+"newtitle"  => "Noa de nuuje titel",
+"movepagebtn" => "Verplaatsj pagina",
+"pagemovedsub" => "De verplaatsjing is gelukt",
+"pagemovedtext" => "Pagina \"[[$1]]\" verplaatst naar \"[[$2]]\".",
+"articleexists" => "D'r is al un pagina mit deze titel of de titel is ongeldig. <br />Gelieve een andere titel te kiezen.",
+"talkexists" => "De pagina zelf is verplaatst, maar de euverlikpagina kon neet worden verplaatst, omdat de doeltitel al een neet-lege euverlikpagina had. Combineer de euverlikpagina's a.u.b. handmatig.",
+"movedto"  => "verplaatsjt noa",
+"movetalk"  => "Verplaatsj \"euverlik\" pagina auch indien aanwezig.",
+"talkpagemoved" => "De bieheurende euverlikpagina is auch verplaatsjt.",
+"talkpagenotmoved" => "De bijheurende euverlikpagina is <strong>neet</strong> verplaatsjt.",
+
+
+# Update from wikipedia
+'accmailtext' => "'t Wachwaord veur '$1' is nao $2 versjtuurd.",
+'accmailtitle' => "Wachwaord versjtuurd.",
+'acct_creation_throttle_hit' => "Sorry, de höbs al $1 accounts aangemak. De kins d'r gein mië aanmake.",
+'addgroup' => "Groep toevoge",
+'allarticles' => "Alle artikele",
+'alllogstext' => "Gecombinierde wiergaaf van uploads, verwiederinge, besjerminge, blokkieringe, en sysop logs.
+De kins ouch 'n log type, de gebroekersname of de betriffende pazjena selectiere.",
+'allmessages' => "Alle systeemberichte",
+'allmessagescurrent' => "Huidige tèks",
+'allmessagesdefault' => "Default tèks",
+'allmessagesname' => "Naom",
+'allmessagesnotsupportedDB' => "Special:AllMessages neet ongersjteund omdat wgUseDatabaseMessages oet (off) sjtèt.",
+'allmessagesnotsupportedUI' => "Dien huidige interface taol <b>$1</b> weurt bie dees site neet ongerstjeund doer Special:AllMessages.",
+'allmessagestext' => "Dit is 'n liest van alle systeemberichte besjikbaar in de MediaWiki: naomroemde.",
+'allpagesnext' => "Volgende",
+'allpagesprev' => "Vurrige",
+'alphaindexline' => "$1 nao $2",
+'ancientpages' => "Awdste pazjena's",
+'and' => "en",
+'anontalk' => "Euverlik veur dit IP adres",
+'anontalkpagetext' => "----''Dit is de euverlikpazjena veur 'ne anonieme gebroeker dae nog gein account haet aangemak of dae 't neet gebroek. Daorom gebroeke v'r 't [[IP adres]] om de gebroeker te identificere. Dat adres kint weure gedeild doer miedere gebroekers. As e 'ne anonieme gebroeker bis en de höbs 't geveul dat 'r onrillevante commentare aan dich gericht zint, kins e 't biste [[Special:Userlogin|'n account crëere of inlogge]] om toekomstige verwarring mit angere anonieme gebroekers te veurkomme.''",
+'anonymous' => "Anonieme gebroeker(s) van Wikipedia",
+'article' => "Contentpazjena",
+'autoblocker' => "Omdas e 'n IP addres deils mit \"$1\" (rede \"$2\") bis e automatisch geblokkierd.",
+'blocklogentry' => "\"$1\" geblokkierd veur de tied van $2",
+'blocklogpage' => "Blokkier log",
+'blocklogtext' => "Dit is 'n log van 't blokkieringe van gebroekers. Automatisch geblokkierde IP adresse sjtón hie neet bie. Zuug de [[Special:Ipblocklist|IP blokkier liest]] vuur de liest van op dit mement akteve blokkieringe.",
+'bold_sample' => "Vètte tèks",
+'bold_tip' => "Vètte tèks",
+'bureaucratlogentry' => "Rechte vuur gebroeker \"$1\" op \"$2\" gesjtèld",
+'cachederror' => "Dit is 'n gecachete kopie van de gevraogde pazjena, en is mesjien neet gans up to date.",
+'categories' => "Kattegorië",
+'category' => "Kattegorie",
+'category_header' => "Artikele in kategorie \"$1\"",
+'categoryarticlecount' => "D'r zunt $1 artikele in dees kategorie.",
+'categoryarticlecount1' => "D'r is $1 artikel in dees kategorie.",
+'changes' => "verangeringe",
+'clearyourcache' => "'''Mèrk op:''' Nao 't opsjlaon, kins e diene browsercache wisse om de verangeringe te zeen: '''Mozilla / Firefox:''' ''Ctrl-Shift-R'', '''Internet Explorer:''' ''Ctrl-F5'', '''Safari:''' ''Cmd-Shift-R'', '''Konqueror''' ''F5''.",
+'compareselectedversions' => "Vergeliek geselecteerde versies",
+'confirmemail_body' => "Someone, probably you from IP address $1, has registered an
+account \"$2\" with this e-mail address on {{SITENAME}}.
+
+To confirm that this account really does belong to you and activate
+e-mail features on {{SITENAME}}, open this link in your browser:
+
+$3
+
+If this is *not* you, don't follow the link. This confirmation code
+will expire at $4.",
+'confirmprotect' => "Bevèstig besjerme",
+'confirmprotecttext' => "Wits e zeker das e dees pazjena wils besjerme?",
+'confirmunprotect' => "Bevèstig vriegaeve van besjèrming",
+'confirmunprotecttext' => "Wits e zeker das de besjèrming van dees pazjena wils vriegaeve?",
+'copyright' => "De inhawd is besjikbaar onger de $1.",
+'copyrightwarning2' => "Mèrk op dat alle biedraag aan {{SITENAME}} kinne weure verangerd, aangepas of weggehaold doer anger luui. As e neet wils dat dien tèks zoemer kint weure aangepas mos e 't hie neet plaatsje.<br />
+De beluifs os auch das e dees tèks zelf höbs gesjreve, of gekopieerd van 'n [[public domain]] of vergeliekbare vrieë bron (zuug $1 vuur details).
+<strong>HIE GEIN AUTEURSRECHTELIK BESJERMD WERK ZONGER TOESJTUMMING!</strong>",
+'couldntremove' => "Kos item '$1' neet wisse...",
+'createaccountmail' => "per e-mail",
+'creditspage' => "Sjrievers van dees pazjena",
+'currentevents-url' => "In 't nuuis",
+'currentrevisionlink' => "zuug huidige versie",
+'dateformat' => "Datumformaat",
+'deadendpages' => "Doedlaupende pazjena's",
+'default' => "sjtandaard",
+'defaultns' => "Zeuk sjtandaard in dees naomroemdes:",
+'delete' => "Wisse",
+'deletedrevision' => "Aw versie $1 gewist.",
+'deleteimgcompletely' => "Wis al versies",
+'edit' => "Bewirk",
+'editcomment' => "'t Edit commentaor waor: \"<i>$1</i>\".",
+'editingcomment' => "Bewirk $1 (commentaar)",
+'editingsection' => "Bewirke van sectie van $1",
+'editsection' => "bewirk",
+'emptyfile' => "'t Besjtand das e höbs geupload is laeg. Dit kump waorsjienliek doer 'n tiepfout in de besjtandsnaom. Kiek estebleef of se dit besjtand wirkelik wils uploade.",
+'exbeforeblank' => "inhawd veur 't wisse waor:",
+'exblank' => "pazjena waor laeg",
+'excontent' => "inhawd waor:",
+'export' => "Exportier pazjena's",
+'extlink_sample' => "http://www.example.com link titel",
+'extlink_tip' => "Externe link (mit de http:// prefix)",
+'fileexists' => "D'r is al e besjtand mit dees naam, bekiek $1 of se dat besjtand mesjien wils vervange.",
+'filemissing' => "Besjtand ontbrik",
+'filesource' => "Bron",
+'geo' => "GEO coördinate",
+'groups-editgroup-name' => "Group name:",
+'groups-group-edit' => "Existing groups:",
+'guesstimezone' => "Invulle van browser",
+'hidetoc' => "verberg",
+'history_short' => "Historie",
+'imagemaxsize' => "Bepèrk plaetsjes op de besjrievingspazjena's van aafbeildinge tot:",
+'ipboptions' => "2 hours,1 day,3 days,1 week,2 weeks,1 month,3 months,6 months,1 year,infinite",
+'italic_sample' => "Italic tèks",
+'italic_tip' => "Italic tèks",
+'lastmodifiedby' => "Dees pazjena is 't litst verangert op $1 doer $2.",
+'link_sample' => "Link titel",
+'link_tip' => "Interne link",
+'loginreqtext' => "De mos [[special:Userlogin|inglogge]] om anger pazjenas te bekieke.",
+'longpagewarning' => "WAARSJUWING: Dees pazjena is $1 kilobytes lang; 'n aantal browsers kint probleme höbbe mit 't verangere van pazjena's in de buurt van of grotter as 32 kB. Kiek of se sjtukke van de pazjena mesjiens kins verplaatsje nao 'n nuui pazjena.",
+'mailerror' => "Fout bie 't versjture van mail: $1",
+'mainpagetext' => "Wiki software succesvol geïnsjtalleerd.",
+'math' => "Mattemetik rendere",
+'math_bad_output' => "Kin neet sjrieve nao de output directory veur mattematik",
+'math_tip' => "Wiskundige formule (LaTeX)",
+'math_unknown_error' => "onbekènde fout",
+'math_unknown_function' => "onbekènde functie",
+'missingimage' => "<b>Plaetsje neet besjikbaar</b><br /><i>$1</i>",
+'moredotdotdot' => "Miè...",
+'move' => "Verplaatsj",
+'mw_math_html' => "HTML woe meugelik en angesj PNG",
+'mw_math_mathml' => "MathML woe meugelik (experimenteil)",
+'mw_math_modern' => "Aangeroaje vuur nuui browsers",
+'mw_math_png' => "Ummer PNG rendere",
+'mw_math_simple' => "HTML in erg simpele gevalle en angesj PNG",
+'mw_math_source' => "Laot de TeX code sjtaon (vuur tèksbrowsers)",
+'mycontris' => "Mien biedraag",
+'namespace' => "Naamruumde:",
+'navigation' => "Navegatie",
+'newimages' => "Nuui plaetjes",
+'newmessages' => "De höbs $1.",
+'newmessageslink' => "nuui berichte",
+'newpage' => "Nuui pazjena",
+'newwindow' => "(in nuui venster)",
+'nextdiff' => "Gank nao de volgende diff →",
+'nextpage' => "Volgende pazjena ($1)",
+'nogomatch' => "Inne pazjena mit exak dees titel besjtit neet, probeer noe alle teks doer te zeuke.",
+'noimages' => "Niks te zeen.",
+'nonunicodebrowser' => "<strong>WAARSJUWING: Diene browser is voldit neet aan de unicode sjtandaarde, gebroek estebleef inne angere browser veurdas e artikele gis bewirke.</strong>",
+'nstab-category' => "Kategorie",
+'nstab-image' => "Aafbeilding",
+'nstab-main' => "Artikel",
+'nstab-mediawiki' => "Berich",
+'nstab-template' => "Sjabloon",
+'nstab-user' => "Gebroeker",
+'nstab-wp' => "Euver",
+'perfcached' => "De volgende data is gecachet en is mesjien neet gans up to date:",
+'perfdisabledsub' => "Hie is 'n opgesjlage kopie van $1:",
+'personaltools' => "Persoenlike hulpmiddele",
+'portal' => "Gebroekersportaal",
+'portal-url' => "Wikipedia:Gebroekersportaal",
+'poweredby' => "{{SITENAME}} dreit op [http://www.mediawiki.org/ MediaWiki], 'n vriej software wiki.",
+'prefs-misc' => "Anger insjtèllinge",
+'prefs-personal' => "Gebroekersinfo",
+'prefs-rc' => "Recènte verangeringe en weergaaf van sjtumpkes",
+'previousdiff' => "← Gank nao de vurrige diff",
+'previousrevision' => "←Awwer versie",
+'protect' => "Besjerm",
+'protectcomment' => "Rede veur besjerming",
+'protectedarticle' => "$1 besjermd",
+'protectedpagewarning' => "WAARSJUWING:  Dees pazjena is besjermd zoedat ze allein doer gebroekers mit administratorrechte kint weure verangerd.",
+'protectedtext' => "Dizze pazjena is besjermd om bewirkinge te veurkomme; d'r zint 'n aantal meugelike redene hieveur.
+<!-- Zuug ouch [[Project:Protected page]]. -->
+
+De kins de brontèks van dees pazjena bekieke en kopiëre:",
+'protectmoveonly' => "Besjerm allein taege verplaatsje",
+'protectsub' => "(Besjerme van \"$1\")",
+'proxyblockreason' => "Dien IP adres is geblokkierd omdat 't 'n ôpe proxy is. Contactier estebleef diene internet service provider of technische ongersjteuning en informeer ze van dit sirrieuze veiligheidsprebleim.",
+'proxyblocksuccess' => "Klaor.",
+'qbspecialpages' => "Speciaal pazjena's",
+'readonlywarning' => "WAARSJUWING: De database is vasgezèt veur ongerhoud, dus op 't mement kins e dien verangeringe neet opsjlaon. De kins dien tèks 't biste opsjlaon in 'n tèksbesjtand om 't later hie nog es te prebere.",
+'removechecked' => "Verwieder aangevinkde pazjena's van dien volgliest",
+'removingchecked' => "Pazjena's van volgliest aafgehaold...",
+'restorelink' => "$1 verwiederde versies",
+'scarytranscludefailed' => "[Template fetch failed; sorry]",
+'showbigimage' => "Download versie met hoege resolutie ($1x$2, $3 kB)",
+'showhideminor' => "$1 klein verangeringe | $2 bots | $3 ingelogde gebroekers | $4 patrolled edits",
+'showingresultsnum' => "Hieonger de <b>$3</b> resultate vanaaf #<b>$2</b>.",
+'siteuser' => "Wikipedia gebroeker $1",
+'siteusers' => "Wikipedia gebroekers(s) $1",
+'specialpage' => "Speciaal Pazjena",
+'subcategories' => "Subkattegorië",
+'subcategorycount' => "Dees kategorie haet $1 subkategorieë.",
+'subcategorycount1' => "Dees kategorie haet $1 subkategorie.",
+'tagline' => "Van {{SITENAME}}",
+'talk' => "Euverlik",
+'templatesused' => "Sjablone gebroek in dees pazjena:",
+'thisisdeleted' => "$1 bekieke of trökzètte?",
+'thumbnail-more' => "Vergroete",
+'thumbsize' => "Thumbnail size :",
+'timezonelegend' => "Tiedzone",
+'toc' => "Inhawd",
+'tog-editondblclick' => "Bewirk pazjena's bie 'ne dubbelklik (JavaScript)",
+'tog-editsection' => "Bewirke van secties via [bewirke] links",
+'tog-editsectiononrightclick' => "Sècties bewirke mit inne rechtermoesklik op sèctietitels (JavaScript)",
+'tog-editwidth' => "Edit boks haet de vol breidte",
+'tog-fancysig' => "Rauwe signature (zonger automatische link)",
+'tog-hideminor' => "Verbèrg klein bewirking bie recènte verangeringe",
+'tog-highlightbroken' => 'Formatteer gebraoke links <a href="" class="new">op dees meneer</a> (angesj: zoe<a href="" class="internal">?</a>).',
+'tog-justify' => "Paragrafe oetvulle",
+'tog-minordefault' => "Merkeer sjtandaard alle bewirke as klein",
+'tog-nocache' => "Pazjena cache oetzitte",
+'tog-numberheadings' => "Köpkes automatisch nummere",
+'tog-previewonfirst' => "Preview laote zien bie de iesjte bewirking",
+'tog-rememberpassword' => "Paswoerd onthawwe bie 't aafmèlde",
+'tog-showtoc' => "Inhawdsopgaaf vuur pazjena's mit mië as 3 köpkes",
+'tog-showtoolbar' => "Laot edit toolbar zeen",
+'tog-underline' => "Links ongersjtreipe",
+'tog-usenewrc' => "Oetgebreide recènte vervangeringe (neet vuur alle browsers)",
+'tog-watchdefault' => "Voog pazjena's die se bewirks toe aan dien volgliest",
+'toolbox' => "Gereidsjapskis",
+'tooltip-compareselectedversions' => "Bekiek de versjille tusje de twie geselectierde versies van dees pazjena. [alt-v]",
+'tooltip-minoredit' => "Markeer dit as 'n kleine verangering [alt-i]",
+'tooltip-preview' => "Bekiek dien verangeringe verdas e ze definnetief opsjleus! [alt-p]",
+'tooltip-save' => "Bewaar dien verangeringe [alt-s]",
+'tooltip-search' => "Doerzeuk dizze wiki [alt-f]",
+'tooltip-watch' => "Voog dees pazjena toe aan dien volgliest [alt-w]",
+'uncategorizedcategories' => "Ongekattegoriseerde kattegorië",
+'uncategorizedpages' => "Ongekattegoriseerde pazjena's",
+'unprotect' => "Besjerming opheffe",
+'unprotectcomment' => "Rede veur opheffe van besjerming",
+'unprotectedarticle' => "besjerming van $1 opgeheve",
+'unprotectsub' => "(Besjerming van \"$1\" opheve)",
+'unwatch' => "Sjtop volge",
+'usenewcategorypage' => '1
+
+Set first character to "0" to disable the nuui layout veur kategorieë.',
+'userrights-user-editname' => 'Enter a username:',
+
+'val_tab' => "Valideer",
+'val_this_is_current_version' => "dit is de litste versie",
+'val_total' => "Totaal",
+'val_user_validations' => "Deze gebroeker haet $1 pazjena's gevalideerd.",
+'val_validate_article_namespace_only' => "Allein artikele kinne weure gevalideerd. Dees pazjena bevink zich <i>neet</i> in de artikel naomroemde.",
+'val_validate_version' => "Valideer dees versie",
+'val_validated' => "Gevalideerd.",
+'val_version' => "Versie",
+'val_version_of' => "Versie van $1",
+'val_view_version' => "Bekiek dees versie",
+'validate' => "Valideer pazjena",
+'version' => "Versie",
+'viewsource' => "Bekiek brontèks",
+'viewtalkpage' => "Bekiek euverlik",
+'watch' => "Volg",
+'watchlistcontains' => "Diene volgliest bevat $1 pazjena's.",
+'watchmethod-list' => "controlere van gevolgde pazjena's veur recènte verangeringe",
+'watchmethod-recent' => "Controleer recènte verangere veur gevolgde pazjena's",
+'watchnochange' => "Gein van dien gevolgde items is aangepas in dees periode.",
+'wlnote' => "Hieonger de litste $1 verangeringe van de litste <b>$2</b> oer.",
+'wlsaved' => "Dit is 'n opgesjlage versie van dien volgliest.",
+'wlshowlast' => "Toen litste $1 oere $2 daag $3",
+'yourlanguage' => "Taol van de gebroekersinterface",
+'yourrealname' => "Dien echte naam*",
+'yourvariant' => "Taalvariant",
+);
+
+require_once( "LanguageUtf8.php" );
+
+class LanguageLi extends LanguageUtf8 {
+
+       function getNamespaces() {
+               global $wgNamespaceNamesLi;
+               return $wgNamespaceNamesLi;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsLi;
+               return $wgQuickbarSettingsLi;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesLi;
+               return $wgSkinNamesLi;
+       }
+
+       function date( $ts, $adj = false ) {
+               if ( $adj ) { $ts = $this->userAdjust( $ts ); }
+
+               $d = (0 + substr( $ts, 6, 2 )) . " " .
+               $this->getMonthAbbreviation( substr( $ts, 4, 2 ) ) . " " .
+               substr( $ts, 0, 4 );
+               return $d;
+       }
+
+       function timeanddate( $ts, $adj = false ) {
+               return $this->date( $ts, $adj ) . " " . $this->time( $ts, $adj );
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesLi;
+               if( isset( $wgAllMessagesLi[$key] ) ) {
+                       return $wgAllMessagesLi[$key];
+               } else {
+                       return parent::getMessage( $key );
+               }
+       }
+}
+?>
diff --git a/languages/LanguageLo.php b/languages/LanguageLo.php
new file mode 100644 (file)
index 0000000..ff8b07b
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+/** Lao (ພາສາລາວ)
+  *
+  * @package MediaWiki
+  * @subpackage Language
+  *
+  * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
+  */
+
+require_once( 'LanguageUtf8.php' );
+
+class LanguageLo extends LanguageUtf8 {
+       var $digitTransTable = array(
+               '0' => '໐',
+               '1' => '໑',
+               '2' => '໒',
+               '3' => '໓',
+               '4' => '໔',
+               '5' => '໕',
+               '6' => '໖',
+               '7' => '໗',
+               '8' => '໘',
+               '9' => '໙'
+       );
+
+       function formatNum( $number ) {
+               global $wgTranslateNumerals;
+               if( $wgTranslateNumerals ) {
+                       return strtr( $number, $this->digitTransTable );
+               } else {
+                       return $number;
+               }
+       }
+}
+
+?>
diff --git a/languages/LanguageLt.php b/languages/LanguageLt.php
new file mode 100644 (file)
index 0000000..252b92a
--- /dev/null
@@ -0,0 +1,418 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+require_once( "LanguageUtf8.php" );
+
+
+/* private */ $wgQuickbarSettingsLt = array(
+       "Nerodyti", "Fiksuoti kairėje", "Fiksuoti dešinėje", "Plaukiojantis kairėje"
+);
+
+/* private */ $wgSkinNamesLt = array(
+       'standard' => "Standartinė",
+       'nostalgia' => "Nostalgija",
+       'cologneblue' => "Kiolno Mėlyna",
+       'davinci' => "Da Vinči",
+) + $wgSkinNamesEn;
+
+$wgAllMessagesLt = array(
+'january' => "Sausio",
+'february' => "Vasario",
+'march' => "Kovo",
+'april' => "Balandžio",
+'may_long' => "Gegužės",
+'june' => "Birželio",
+'july' => "Liepos",
+'august' => "Rugpjūčio",
+'september' => "Rugsėjo",
+'october' => "Spalio",
+'november' => "Lapkričio",
+'december' => "Gruodžio",
+
+'jan' => "Sau",
+'feb' => "Vas",
+'mar' => "Kov",
+'apr' => "Bal",
+'may' => "Geg",
+'jun' => "Bir",
+'jul' => "Lie",
+'aug' => "Rgp",
+'sep' => "Rgs",
+'oct' => "Spa",
+'nov' => "Lap",
+'dec' => "Gru",
+
+'sunday' => "Sekmadienis",
+'monday' => "Pirmadienis",
+'tuesday' => "Antradienis",
+'wednesday' => "Trečiadienis",
+'thursday' => "Ketvirtadienis",
+'friday' => "Penktadienis",
+'saturday' => "Šeštadienis",
+
+'1movedto2' => "Straipsnis '$1' pervadintas į '$2'",
+'Monobook.js' => "/* tooltips and access keys */
+ta = new Object();
+ta['pt-userpage'] = new Array('.','Mano vartotojo puslapis');
+ta['pt-anonuserpage'] = new Array('.','Vartotojo puslapis jūsų ip ardesui');
+ta['pt-mytalk'] = new Array('n','Mano diskusijų puslapis');
+ta['pt-anontalk'] = new Array('n','Diskusijos apie pakeitimus, darytus naudojant šį IP adresą');
+ta['pt-preferences'] = new Array('','Mano nustatymai');
+ta['pt-watchlist'] = new Array('l','Sąrašas straipsnių, kuriuos jūs pasirinkote stebėti.');
+ta['pt-mycontris'] = new Array('y','Mano darytų keitimų sąrašas');
+ta['pt-login'] = new Array('o','Rekomenduojame prisijungti, nors tai nėra privaloma.');
+ta['pt-anonlogin'] = new Array('o','Rekomenduojame prisijungti, nors tai nėra privaloma.');
+ta['pt-logout'] = new Array('o','Atsijungti');
+ta['ca-talk'] = new Array('t','Diskusijos apie šį straipsnį');
+ta['ca-edit'] = new Array('e','Jūs galite redaguoti šį straipsnį. Nepamirškite peržiūrėti pakeitimų prieš užsaugodami.');
+ta['ca-addsection'] = new Array('+','Pradėti naują temą diskusijose.');
+ta['ca-viewsource'] = new Array('e','Puslapis yra užrakintas. Galite tik pažiūrėti turinį.');
+ta['ca-history'] = new Array('h','Ankstesnės puslapio versijos.');
+ta['ca-protect'] = new Array('=','Uždrausti šį puslapį');
+ta['ca-delete'] = new Array('d','Ištrinti šį puslapį');
+ta['ca-undelete'] = new Array('d','Atstatyti puslapį su visais darytais keitimais');
+ta['ca-move'] = new Array('m','Pervadinti straipsnį');
+ta['ca-watch'] = new Array('w','Pridėti straipsnį į stebimųjų sąrašą');
+ta['ca-unwatch'] = new Array('w','Išimti straipsnį iš stebimųjų sąrašo');
+ta['search'] = new Array('f','Ieškoti lietuviškoje Wikipedijoje');
+ta['p-logo'] = new Array('','Į pradinį puslapį');
+ta['n-mainpage'] = new Array('z','Apsilankykite pradiniame puslapyje');
+ta['n-portal'] = new Array('','About the project, what you can do, where to find things');
+ta['n-currentevents'] = new Array('','Find background information on current events');
+ta['n-recentchanges'] = new Array('r','Sąrašas paskutinių keitimų.');
+ta['n-randompage'] = new Array('x','Parinkti atsitiktinį straipsnį');
+ta['n-help'] = new Array('','Vieta, kur rasite rūpimus atsakymus.');
+ta['n-sitesupport'] = new Array('','Aukokite projektui');
+ta['t-whatlinkshere'] = new Array('j','Sąrašas straipsnių, rodančių į čia');
+ta['t-recentchangeslinked'] = new Array('k','Paskutiniai keitimai straipsniuose, pasiekiamuose iš šio straipsnio');
+ta['feed-rss'] = new Array('','RSS feed for this page');
+ta['feed-atom'] = new Array('','Atom feed for this page');
+ta['t-contributions'] = new Array('','Pažiūrėti vartotojo įnašą - darytus keitimus');
+ta['t-emailuser'] = new Array('','Siųsti el.laišką vartotojui');
+ta['t-upload'] = new Array('u','Įdėti paveikslėlį ar media failą');
+ta['t-specialpages'] = new Array('q','Specialiųjų puslapių sąrašas');
+ta['ca-nstab-main'] = new Array('c','Pereiti į straipsnio turinį');
+ta['ca-nstab-user'] = new Array('c','Rodyti vartotojo puslapį');
+ta['ca-nstab-media'] = new Array('c','Rodyti media puslapį');
+ta['ca-nstab-special'] = new Array('','Šis puslapis yra specialusis - jo negalima redaguoti.');
+ta['ca-nstab-wp'] = new Array('a','Rodyti projekto puslapį');
+ta['ca-nstab-image'] = new Array('c','Rodyti paveikslėlio puslapį');
+ta['ca-nstab-mediawiki'] = new Array('c','Rodyti sisteminį pranešimą');
+ta['ca-nstab-template'] = new Array('c','Rodyti šabloną');
+ta['ca-nstab-help'] = new Array('c','Rodyti pagalbos puslapį');
+ta['ca-nstab-category'] = new Array('c','Rodyti kategorijos puslapį');",
+'about' => "Apie",
+'aboutsite'      => "Apie Wikipediją",
+'accmailtext' => "Vartotojo '$1' slaptažodis nusiųstas į $2.",
+'accmailtitle' => "Slaptažodis išsiųstas.",
+'actioncomplete' => "Veiksmas atliktas",
+'addedwatch' => "Pridėta prie Stebimų",
+'addedwatchtext' => "Straipsnis \"$1\" pridėtas į [[Special:Watchlist|stebimųjų sąrašą]].
+Būsimi straipsnio bei atitinkamo diskusijų puslapio pakeitimai bus rodomi stebimųjų puslapių sąraše,
+taip pat bus '''paryškinti''' [[Special:Recentchanges|naujausių keitimų sąraše]] kad išsiskirtų iš kitų straipsnių.
+
+<p>Jei bet kuriuo metu užsinorėtumėte nustoti stebėti straipsnį, spustelkite \"nebestebėti\" viršutiniame meniu.",
+'administrators' => "Wikipedia:Administrators",
+'allmessages' => "Visi sistemos tekstai bei pranešimai",
+'allmessagestext' => "Čia pateikiami visi sisteminiai tekstai bei pranešimai, esantys MediaWiki: vardų ervėje.",
+'allpages' => "Visi straipsniai",
+'alphaindexline' => "Nuo $1 iki $2",
+'alreadyloggedin' => "<strong>Jūs jau esate prisijungęs kaip vartotojas User $1!</strong><br />",
+'alreadyrolled' => "Nepavyko atmesti paskutinio [[User:$2|$2]] ([[User talk:$2|Diskusijos]]) daryto straipsnio [[$1]] keitimo; kažkas jau pakeitė straipsnį arba suspėjo pirmas atmesti keitimą.
+
+Paskutimas keitimas darytas vartotojo [[User:$3|$3]] ([[User talk:$3|Diskusijos]]).",
+'ancientpages' => "Seniausi straipsniai",
+'anontalk' => "Šio IP diskusijų puslapis",
+'articleexists' => "Straipsnis tokiu pavadinimu jau egzistuoja
+arba pasirinktas vardas yra neteisingas.
+Pasirinkite kitą pavadinimą.",
+'articlepage' => "Rodyti straipsnį",
+'autoblocker' => "Automatinis užblokavimas, nes dalinatės IP adresu su vartotoju \"$1\". Priežastis - \"$2\".",
+'badfiletype' => "\".$1\" yra nerekomenduojamas paveikslėlio bylos formatas.",
+'badretype' => "Įvesti slaptažodžiai nesutampa.",
+'blockip' => "Blokuoti vartotoją",
+'blockipsuccesssub' => "Užblokavimas pavyko",
+'blocklink' => "blokuoti",
+'bold_sample' => "Paryškintas tekstas",
+'bold_tip' => "Paryškinti tekstą",
+'booksources' => "Knygų paieška",
+'brokenredirects' => "Peradresavimai į niekur",
+'brokenredirectstext' => "Žemiau išvardinti peradresavimo puslapiai rodo į neegzistuojančius straipsnius.",
+'bugreports' => "Pranešti apie klaidą",
+'cancel' => "Atšaukti",
+'cannotdelete' => "Nepavyko ištrinti nurodyto straipsnio ar paveikslėlio. (Gali būti, kad kažkas kitas ištrynė pirmas)",
+'categories' => "Kategorijos",
+'category' => "kategorija",
+'category_header' => "Kategorijos \"$1\" straipsniai",
+'categoryarticlecount' => "Kategorijoje straipsnių - $1",
+'changepassword' => "Pakeisti slaptažodį",
+'compareselectedversions' => "Palyginti pasirinktas versijas",
+'confirm' => "Tvirtinu",
+'confirmdelete' => "Trynimo veiksmo patvirtinimas",
+'confirmdeletetext' => "Jūs pasirinkote ištrinti straipsnį ar paveikslėlį
+kartu su visa istorija iš duomenų bazės.
+Prašome patvirtinti kad jūs norite tai padaryti,
+žinote kokios yra veiksmo pasekmės,
+ir kad jūs tai darote nenusižengdamas
+[[Wikipedia:Policy|Wikipedijos Politikai]].",
+'confirmprotect' => "Užrakinimo patvirtinimas",
+'confirmprotecttext' => "Ar jūs tikrai norite užrakinti šį straipsnį?",
+'confirmunprotect' => "Atrakinimo patvirtinimas",
+'confirmunprotecttext' => "Ar tikrai norite atrakinti šį straipsnį?",
+'contribslink' => "įnašas",
+'contributions' => "Vartotojo indėlis",
+'copyright' => "Turinys pateikiamas su $1 licenzija.",
+'copyrightpage' => "Wikipedia:Copyrights",
+'copyrightpagename' => "Wikipedia copyright",
+'copyrightwarning' => "Atkreipkite dėmesį, kad viskam, kas patenka į Wikipediją, yra taikoma GNU Laisvos Documentacijos Licenzija
+(detaliau - $1).
+Jei nepageidaujate, kad jūsų įvestas turinys būtų negailestingai redaguojamas ir platinamas, nerašykite čia.<br />
+Jūs taip pat pasižadate, kad tai jūsų pačių rašytas turinys arba kopijuotas iš viešų ar panašių nemokamų šaltinių.
+<strong>NEKOPIJUOKITE AUTORINĖMIS TEISĖMIS APSAUGOTŲ DARBŲ BE LEIDIMO!</strong>",
+'createaccount' => "Sukurti vartotoją",
+'currentevents' => "-",
+'currentrev' => "Dabartinė versija",
+'dateformat' => "Datos formatas",
+'deadendpages' => "Straipsniai-aklavietės",
+'defaultns' => "Pagal nutylėjimą ieškoti šiose vardų erdvėse:",
+'defemailsubject' => "Wikipedia e-mail",
+'delete' => "trinti",
+'deletecomment' => "Trynimo priežastis",
+'deletedarticle' => "ištrinta \"$1\"",
+'deletesub' => "(Trinama \"$1\")",
+'deletethispage' => "Ištrinti straipsnį",
+'difference' => "(Skirtumai tarp versijų)",
+'disambiguations' => "Nukreipiamieji puslapiai",
+'disambiguationspage' => "Wikipedia:Links_to_disambiguating_pages",
+'disambiguationstext' => "Žemiau išvardinti straipsniai, rodantys į <i>nukreipiamuosius puslapius</i>. Nuorodos turėtų būti patikslintos kad rodytų į konkretų straipsnį.<br />Puslapis skaitomas nukreipiamuoju, jei nuoroda į jį yra $1.<br />",
+'disclaimerpage' => "Wikipedia:General_disclaimer",
+'disclaimers' => "Jokių Garantijų",
+'doubleredirects' => "Dvigubi peradresavimai",
+'editconflict' => "Išpręskite konfliktą: $1",
+'edithelp' => "Kaip Redaguoti",
+'editing' => "Taisomas straipsnis - $1",
+'editingsection' => "Taisomas straipsnis - $1 (skyrius)",
+'editingcomment' => "Taisomas straipsnis - $1 (comment)",
+'editingold' => "<strong>ĮSPĖJIMAS: Jūs keičiate ne naujausią puslapio versiją.
+Jei išsaugosite savo keitimus, prieš tai daryti pakeitimai pradings.</strong>",
+'editsection' => "taisyti",
+'editthispage' => "Taisyti straipsnį",
+'emailforlost' => "* Elektroninio pašto adresas nėra privalomas. Tačiau jei įvesite, kiti vartotojai galės siųsti jums laiškus nesužinodami adreso. Taip pat pašto adresas gelbsti pamiršus slaptažodį.",
+'emailuser' => "Rašyti laišką",
+'excontent' => "buvęs turinys: '$1'",
+'export' => "Eksportuoti puslapius",
+'extlink_sample' => "http://www.pavyzdys.lt Nuorodos pavadinimas",
+'extlink_tip' => "Išorinė nuoroda (nepamirškite http:// prefikso)",
+'tagline'       => "Straipsnis iš Wikipedijos, laisvosios enciklopedijos",
+'go' => "Rodyk",
+'headline_sample' => "Skyriaus Pavadinimas",
+'headline_tip' => "Skyriaus pavadinimas (2-o lygio)",
+'help' => "Pagalba",
+'helppage' => "Help:Contents",
+'hide' => "paslėpti",
+'hidetoc' => "slėpti",
+'hist' => "ist",
+'history' => "Straipsnio istorija",
+'history_short' => "Istorija",
+'hr_tip' => "Horizontali linija (nepernaudoti)",
+'image_sample' => "Pavyzdys.jpg",
+'image_tip' => "Įdėti paveiksėlį",
+'imagelist' => "Paveikslėlių sąrašas",
+'ipblocklist' => "Blokuotų IP adresų bei vartotojų sąrašas",
+'italic_sample' => "Tekstas kursyvu",
+'italic_tip' => "Išskirti kursyvu",
+'lastmodified' => "Paskutinį kartą keista $1.",
+'lineno' => "Eilutė $1:",
+'link_sample' => "Straipsnio pavadinimas",
+'link_tip' => "Vidinė nuoroda",
+'linklistsub' => "(Nuorodų sąrašas)",
+'linktrail' => "/^([a-z]+)(.*)\$/sD",
+'listusers' => "Vartotojų sąrašas",
+'login' => "Prisijungti",
+'loginprompt' => "Norėdami prisijungti prie Wikipedijos, privalote įsijungti '''cookies''' savo naršyklėje.",
+'loginsuccess' => "Šiuo metu jūs prisijungęs prie Wikipedijos kaip \"$1\".",
+'loginsuccesstitle' => "Sėkmingai prisijungėte",
+'logout' => "Atsijungti",
+'logouttext' => "Jūs atsijungėte nuo Wikipedijos.
+Galite toliau naudoti Wikipediją anonimiškai arba prisijunkite iš naujo tuo pačiu ar kitu vartotoju.<br />
+P.S.:  kai kuriuose puslapiuose ir toliau gali rodyti lyg būtumėte prisijungęs iki tol, kol išvalysite savo naršyklės išsaugotas puslapių kopijas",
+'lonelypages' => "Vieniši straipsniai",
+'longpages' => "Ilgiausi puslapiai",
+'mailmypassword' => "Siųsti naują slaptažodį paštu",
+'mainpage' => "Pradžia",
+'maintenance' => "Įrankių puslapis",
+'math_sample' => "Įveskite formulę",
+'math_tip' => "Matematinė formulė (LaTeX formatu)",
+'minoredit' => "Smulkus pataisymas",
+'minoreditletter' => "S",
+'move' => "Pervadinti",
+'movethispage' => "Pervadinti straipsnį",
+'mycontris' => "Mano įnašas",
+'mytalk' => "mano diskusijos",
+'navigation' => "Navigacija",
+'nbytes' => "$1 B",
+'newarticletext' => "Jūs patekote į neegzistuojančio straipsnio puslapį.
+Norėdami sukurti straipsnį, pradėkite žemiau esančiame įvedimo lauke
+(daugiau informacijos [[Wikipedia:Help|pagalbos puslapyje]]).
+Jei patekote čia per klaidą, paprasčiausiai spustelkite  naršyklės mygtuką 'atgal' ('''back''').",
+'newpages' => "Naujausi straipsniai",
+'newusersonly' => " (tik naujiems vartotojams)",
+'nextn' => "sekančius $1",
+'nlinks' => "$1 k.",
+'note' => "<strong>Pastaba:</strong>",
+'notloggedin' => "Neprisijungęs",
+'nowatchlist' => "Neturite nei vieno stebimo straipsnio.",
+'nstab-category' => "Kategorija",
+'nstab-help' => "Pagalba",
+'nstab-main' => "Straipsnis",
+'nstab-template' => "Šablonas",
+'otherlanguages' => "Kitomis kalbomis",
+'perfcached' => "Rodoma išsaugota duomenų kopija, todėl duomenys gali būti ne patys naujausi:",
+'preferences' => "Nustatymai",
+'prefslogintext' => "Jūs esate prisijungęs kaip \"$1\".
+Jūsų vidinis numeris yra $2.",
+'preview' => "Peržiūra",
+'previewnote' => "Nepamirškite, kad tai tik peržiūra, pakeitimai dar nėra išsaugoti!",
+'prevn' => "ankstesnius $1",
+'printableversion' => "Versija spausdinimui",
+'qbspecialpages' => "Specialieji puslapiai",
+'randompage' => "Atsitiktinis straipsnis",
+'rchide' => "in $4 form; smulkių pataisymų - $1; $2 secondary namespaces; $3 multiple edits.",
+'rclinks' => "Rodyti paskutinius $1 pakeitimų per paskutiniąsias $2 dienas(ų); $3",
+'rclistfrom' => "Rodyti pakeitimus pradedant $1",
+'rclsub' => "(straipsnių, pasiekiamų iš \"$1\")",
+'rcnote' => "Pateikiamas <strong>$1</strong> paskutinių pakeitimų sąrašas per paskutiniąsias <strong>$2</strong> dienas(ų).",
+'rcnotefrom' => "Žemiau yra pakeitimai pradedant <b>$2</b> (rodoma ne daugiau <b>$1</b> pakeitimų).",
+'recentchanges' => "Naujausi keitimai",
+'recentchangeslinked' => "Susiję keitimai",
+'recentchangestext' => "Naujausių Wikipedijos straipsnių pataisymų bei keitimų sąrašas.",
+'redirectedfrom' => "(Nukreipta iš puslapio $1)",
+'remembermypassword' => "Atsiminti slaptažodį.",
+'removechecked' => "Išmesti pažymėtus straipsnius iš stebimų sąrašo",
+'removedwatch' => "Išmesta iš stebimų",
+'removedwatchtext' => "Straipsnis \"$1\" išmestas iš jūsų stebimų straipsnių sąrašo.",
+'removingchecked' => "Pasirinkti straipsniai išmetami iš stebimų sąrašo...",
+'retrievedfrom' => "Rodomas puslapis \"$1\"",
+'returnto' => "Grįžti į $1.",
+'retypenew' => "Pakartokite naują slaptažodį",
+'revertpage' => "Atmestas $2 pakeitimas, grąžinta paskutinė versija (vartotojo $1 keitimas)",
+'revisionasof' => "$1 versija",
+'rollback_short' => "Atmesti",
+'rollbacklink' => "atmesti",
+'savearticle' => "Išsaugoti",
+'search' => "Paieška",
+'shortpages' => "Trumpiausi straipsniai",
+'show' => "rodyti",
+'showhideminor' => "$1 smulkius pataisymus | $2 bots | $3 logged in users | $4 patrolled edits",
+'showingresults' => "Rodoma <b>$1</b> rezultatų pradedant #<b>$2</b>.",
+'showpreview' => "Kaip atrodys",
+'showtoc' => "rodyti",
+'sitestats' => "Tinklalapio statistika",
+'sitestatstext' => "Duomenų bazėje šiuo metu esančių puslapių - '''$1'''.
+Į šį skaičių įeina diskusijų puslapiai, pagalbiniai Wikipedijos puslapiai, peradresavimo puslapiai ir kiti, neskaičiuojami kaip straipsniai.
+Be šių puslapių, tikrų straipsnių yra apie '''$2'''.
+
+Nuo wiki pradžios yra '''$3''' puslapių peržiūrų, ir '''$4''' puslapių redagavimų.
+Taigi vidutiniškai kiekvienas puslapis keistas '''$5''' kartų, o žiūrėtas '''$6''' kartų.",
+'sitesupport' => "Aukojimai",
+'sitetitle' => "Wikipedia",
+'specialpage' => "Specialusis Puslapis",
+'specialpages' => "Specialieji puslapiai",
+'spheading' => "Specialieji visiems vartotojams prieinami puslapiai",
+'statistics' => "Statistika",
+'subcategorycount' => "Kategorijoje esančių kategorijų - $1",
+'summary' => "Komentaras",
+'talk' => "Diskusijos",
+'talkpage' => "Aptarti straipsnį",
+'toc' => "Turinys",
+'toolbox' => "Įrankiai",
+'tooltip-compareselectedversions' => "Žiūrėti dviejų pasirinktų puslapio versijų skirtumus. [alt-v]",
+'tooltip-minoredit' => "Pažymėti keitimą kaip smulkų [alt-i]",
+'tooltip-preview' => "Pakeitimų peržiūra, labai prašome pažiūrėti prieš išsaugant! [alt-p]",
+'tooltip-save' => "Išsaugoti pakeitimus [alt-s]",
+'tooltip-search' => "Ieškoti lietuviškame wiki [alt-f]",
+'unusedimages' => "Nenaudojami paveikslėliai",
+'unwatch' => "Nebe stebėti",
+'unwatchthispage' => "Nustoti stebėti",
+'upload' => "Įdėti failą",
+'uploadedimage' => "įdėta \"[[$1]]\"",
+'userlogin' => "Prisijungti",
+'userlogout' => "Atsijungti",
+'userpage' => "Vartotojo puslapis",
+'userstats' => "Vartotojų statistika",
+'userstatstext' => "Šiuo metu registruotų vartotojų - '''$1'''.
+Iš jų administratoriaus teises turi - '''$2''' (žr. $3).",
+'viewprevnext' => "Žiūrėti ($1) ($2) ($3).",
+'viewsource' => "Žiūrėti kodą",
+'wantedpages' => "Trokštamiausi straipsniai",
+'watch' => "Stebėti",
+'watchdetails' => "(stebimų straipsnių - $1, neskaitant diskusijų puslapių;
+šiuo metu pasirinkote žiūrėti $2 pakeitimus;
+$3...
+[$4 parodyti ir redaguoti pilną sąrašą].)",
+'watcheditlist' => "Žemiau pateiktame stebimų straipsnių sąraše
+pažymėkite varneles prie straipsnių,
+kurių nebenorite stebėti ir spauskite apačioje
+esantį mygtuką 'Išmesti iš stebimų'.",
+'watchlist' => "Stebimi straipsniai",
+'watchlistcontains' => "Straipsnių jūsų stebimųjų straipsnių sąraše - $1.",
+'watchlistsub' => "(vartotojo \"$1\")",
+'watchmethod-list' => "ieškoma naujausių keitimų stebimuose puslapiuose",
+'watchnochange' => "Pasirinktu laikotarpiu nebuvo redaguotas nei vienas stebimas straipsnis.",
+'watchthis' => "Stebėti straipsnį",
+'watchthispage' => "Stebėti puslapį",
+'whatlinkshere' => "Susiję straipsniai",
+'wlnote' => "Rodomi paskutiniai $1 pakeitimai, padaryti per paskutines <b>$2</b> valandas.",
+'wlshowlast' => "Rodyti paskutinių $1 valandų, $2 dienų ar $3 pakeitimus",
+'wrongpassword' => "Įvestas neteisingas slaptažodis. Pamėginkite dar kartą.",
+'youremail' => "Elektroninio pašto adresas*",
+'yourname' => "Jūsų vartotojo vardas",
+'yournick' => "Jūsų slapyvardis (parašams)",
+'yourpassword' => "Pasirinktas slaptažodis",
+'yourpasswordagain' => "Pakartokite slaptažodį",
+);
+
+#--------------------------------------------------------------------------
+# Internationalisation code
+#--------------------------------------------------------------------------
+
+class LanguageLt extends LanguageUtf8  {
+       # Inherent default user options unless customization is desired
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsLt;
+               return $wgQuickbarSettingsLt;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesLt;
+               return $wgSkinNamesLt;
+       }
+
+       function fallback8bitEncoding() {
+               return "windows-1257";
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesLt;
+
+               if(array_key_exists($key, $wgAllMessagesLt))
+                       return $wgAllMessagesLt[$key];
+               else
+                       return parent::getMessage($key);
+       }
+
+       function getAllMessages() {
+               global $wgAllMessagesLt;
+               return $wgAllMessagesLt;
+       }
+
+       function formatNum( $number ) {
+               return strtr($number, '.,', ',.' );
+       }
+
+}
+?>
diff --git a/languages/LanguageMk.php b/languages/LanguageMk.php
new file mode 100644 (file)
index 0000000..fa2436e
--- /dev/null
@@ -0,0 +1,1226 @@
+<?php
+/** Macedonian (Македонски)
+ * @package MediaWiki
+ * @subpackage Language
+ */
+
+/* private */ $wgNamespaceNamesMk = array(
+       NS_MEDIA                        =>      'Медија',
+       NS_SPECIAL                      =>      'Специјални',
+       NS_MAIN                         =>      '',
+       NS_TALK                         =>      'Разговор',
+       NS_USER                         =>      'Корисник',
+       NS_USER_TALK                    =>      'Корисник_разговор',
+       NS_PROJECT                      =>      $wgMetaNamespace,
+       NS_PROJECT_TALK                 =>      $wgMetaNamespace . '_разговор',
+       NS_IMAGE                        =>      'Слика',
+       NS_IMAGE_TALK                   =>      'Слика_разговор',
+       NS_MEDIAWIKI                    =>      'МедијаВики',
+       NS_MEDIAWIKI_TALK               =>      'МедијаВики_разговор',
+       NS_TEMPLATE                     =>      'Шаблон',
+       NS_TEMPLATE_TALK                =>      'Шаблон_разговор',
+       NS_HELP                         =>      'Помош',
+       NS_HELP_TALK                    =>      'Помош_разговор',
+       NS_CATEGORY                     =>      'Категорија',
+       NS_CATEGORY_TALK                =>      'Категорија_разговор',
+);
+
+
+/* private */ $wgQuickbarSettingsMk = array(
+       "Без мени", "Фиксирано лево", "Фиксирано десно", "Пловечко лево"
+);
+
+/* private */ $wgSkinNamesMk = array(
+       'standard'                      =>      'Класика',
+       'nostalgia'                     =>      'Носталгија',
+       'cologneblue'                   =>      'Келнско сино',
+       'davinci'                       =>      'ДаВинчи',
+       'mono'                          =>      'Моно',
+       'monobook'                      =>      'Monobook',
+       'myskin'                        =>      'Моја маска',
+       'chick'                         =>      'Шик'
+) + $wgSkinNamesEn;
+
+/* private */ $wgDateFormatsMk = array(
+ "Без преференции",
+ "Јануари 15, 2001",
+ "15 Јануари 2001",
+ "2001 Јануари 15",
+ "2001-01-15"
+);
+
+/* private */ $wgMagicWordsMk = array(
+       MAG_REDIRECT                    =>      array( 0, '#redirect', '#пренасочување', '#види' ),
+       MAG_NOTOC                       =>      array( 0, '__NOTOC__', '__БЕЗСОДРЖИНА__' ),
+       MAG_FORCETOC                    =>      array( 0, '__FORCETOC__', '__СОСОДРЖИНА__' ),
+       MAG_TOC                         =>      array( 0, '__TOC__', '__СОДРЖИНА__' ),
+       MAG_NOEDITSECTION               =>      array( 0, '__NOEDITSECTION__' , '__БЕЗ_УРЕДУВАЊЕ_НА_СЕКЦИИ__'),
+       MAG_START                       =>      array( 0, '__START__' , '__ПОЧЕТОК__' ),
+       MAG_CURRENTMONTH                =>      array( 1, 'CURRENTMONTH', 'СЕГАШЕНМЕСЕЦ' ),
+       MAG_CURRENTMONTHNAME            =>      array( 1, 'CURRENTMONTHNAME', 'СЕГАШЕНМЕСЕЦИМЕ' ),
+       MAG_CURRENTMONTHNAMEGEN         =>      array( 1, 'CURRENTMONTHNAMEGEN', 'СЕГАШЕНМЕСЕЦИМЕРОД' ),
+       MAG_CURRENTMONTHABBREV          =>      array( 1, 'CURRENTMONTHABBREV', 'СЕГАШЕНМЕСЕЦСКР' ),
+       MAG_CURRENTDAY                  =>      array( 1, 'CURRENTDAY', 'СЕГАШЕНДЕН' ),
+       MAG_CURRENTDAYNAME              =>      array( 1, 'CURRENTDAYNAME', 'СЕГАШЕНДЕНИМЕ' ),
+       MAG_CURRENTYEAR                 =>      array( 1, 'CURRENTYEAR', 'СЕГАШНАГОДИНА' ),
+       MAG_CURRENTTIME                 =>      array( 1, 'CURRENTTIME', 'СЕГАШНОВРЕМЕ' ),
+       MAG_NUMBEROFARTICLES            =>      array( 1, 'NUMBEROFARTICLES', 'БРОЈСТАТИИ' ),
+       MAG_PAGENAME                    =>      array( 1, 'PAGENAME', 'СТРАНИЦА' ),
+       MAG_PAGENAMEE                   =>      array( 1, 'PAGENAMEE', 'СТРАНИЦАИ' ),
+       MAG_NAMESPACE                   =>      array( 1, 'NAMESPACE', 'ИМЕПРОСТОР' ),
+       MAG_SUBST                       =>      array( 0, 'SUBST:', 'ЗАМЕСТ:' ),
+       MAG_MSGNW                       =>      array( 0, 'MSGNW:', 'ИЗВЕШТNW:' ),
+       MAG_END                         =>      array( 0, '', '__КРАЈ__' ),
+       MAG_IMG_THUMBNAIL               =>      array( 1, 'thumbnail', 'thumb', 'мини' ),
+       MAG_IMG_RIGHT                   =>      array( 1, 'right', 'десно', 'д' ),
+       MAG_IMG_LEFT                    =>      array( 1, 'left', 'лево', 'л' ),
+       MAG_IMG_NONE                    =>      array( 1, 'none', 'н' ),
+       MAG_IMG_WIDTH                   =>      array( 1, "$1px", "$1пкс" , "$1п" ),
+       MAG_IMG_CENTER                  =>      array( 1, 'center', 'centre', 'центар', 'ц' ),
+       MAG_IMG_FRAMED                  =>      array( 1, 'framed', 'enframed', 'frame', 'рамка', 'ворамка' ),
+       MAG_INT                         =>      array( 0, 'INT:' ),
+       MAG_SITENAME                    =>      array( 1, 'SITENAME', 'ИМЕНАСАЈТ' ),
+       MAG_NS                          =>      array( 0, 'NS:' ),
+       MAG_LOCALURL                    =>      array( 0, 'LOCALURL:', 'ЛОКАЛНААДРЕСА:' ),
+       MAG_LOCALURLE                   =>      array( 0, 'LOCALURLE:', 'ЛОКАЛНААДРЕСАИ:' ),
+       MAG_SERVER                      =>      array( 0, 'SERVER', 'СЕРВЕР' ),
+       MAG_GRAMMAR                     =>      array( 0, 'GRAMMAR:', 'ГРАМАТИКА:' ),
+       MAG_NOTITLECONVERT              =>      array( 0, '__NOTITLECONVERT__', '__NOTC__'),
+       MAG_NOCONTENTCONVERT            =>      array( 0, '__NOCONTENTCONVERT__', '__NOCC__'),
+       MAG_CURRENTWEEK                 =>      array( 1, 'CURRENTWEEK', 'СЕГАШНАСЕДМИЦА'),
+       MAG_CURRENTDOW                  =>      array( 1, 'CURRENTDOW' ),
+       MAG_REVISIONID                  =>      array( 1, 'REVISIONID' ),
+);
+
+global $wgRightsText;
+
+/* private */ $wgAllMessagesMk = array(
+
+# User preference toggles
+       'tog-underline'                 =>      'Потцртај ги врските',
+       'tog-highlightbroken'           =>      'Покажи ги невалидните врски <a href="" class="new">вака</a> (алтернативно: вака<a href="" class="internal">?</a>).',
+       'tog-justify'                   =>      'Двостранично порамнување на параграфите',
+       'tog-hideminor'                 =>      'Сокриј ги ситните уредувања во скорешните промени',
+       'tog-usenewrc'                  =>      'Подобри ги скорешните промени (JavaScript)',
+       'tog-numberheadings'            =>      'Нумерирај ги заглавијата',
+       'tog-showtoolbar'               =>      'Алатник за уредување (JavaScript)',
+       'tog-editondblclick'            =>      'Уредување при двојно кликнување (JavaScript)',
+       'tog-editsection'               =>      'Овозможи уредување на секција преку (уредување) врски',
+       'tog-editsectiononrightclick'   =>      'Овозможи уредување при десен клик<br /> на насловите на секциите (JavaScript)',
+       'tog-showtoc'                   =>      'Покажи содржина<br />(за страници со повеќе од 3 заглавија)',
+       'tog-rememberpassword'          =>      'Запомни ја шифрата меѓу сесиите',
+       'tog-editwidth'                 =>      'Максимална ширина на кутијата за уредување',
+       'tog-watchdefault'              =>      'Додади ги страниците што ги уредуваш во набљудувани страници',
+       'tog-minordefault'              =>      'Обележи ги сите уредувања како ситни по основно',
+       'tog-previewontop'              =>      'Прикажи го прегледот пред кутијата за уредување, а не после неа',
+       'tog-previewonfirst'            =>      'Прикажи преглед на прво уредување',
+       'tog-nocache'                   =>      'Без складирање на страниците',
+       'tog-enotifwatchlistpages'      =>      'Испрати ми е-пошта при промена на страницата',
+       'tog-enotifusertalkpages'               =>      'Испрати ми е-пошта при промена на мојата страница за разговор',
+       'tog-enotifminoredits'          =>      'Испрати ми е-пошта за ситни промени на страници, истотака',
+       'tog-enotifrevealaddr'          =>      'Откриј ја мојата е-поштенска адреса во пораките за известување',
+       'tog-shownumberswatching'               =>      'Прикажи го бројот на корисници кои набљудуваат',
+       'tog-fancysig'                  =>      'Без променување на потписот во врска кон корисничката страница',
+       'tog-externaleditor'            =>      'Користи надворешен уредувач по основно',
+       'tog-externaldiff'              =>      'Користи надворешна програма за разлики по основно',
+
+       'sunday'                        =>      'Недела',
+       'monday'                        =>      'Понеделник',
+       'tuesday'                       =>      'Вторник',
+       'wednesday'                     =>      'Среда',
+       'thursday'                      =>      'Четврток',
+       'friday'                        =>      'Петок',
+       'saturday'                      =>      'Сабота',
+       'january'                       =>      'Јануари',
+       'february'                      =>      'Февруари',
+       'march'                         =>      'Март',
+       'april'                         =>      'Април',
+       'may_long'                      =>      'Мај',
+       'june'                          =>      'Јуни',
+       'july'                          =>      'Јули',
+       'august'                        =>      'Август',
+       'september'                     =>      'Септември',
+       'october'                       =>      'Октомври',
+       'november'                      =>      'Ноември',
+       'december'                      =>      'Декември',
+       'jan'                           =>      'Јан',
+       'feb'                           =>      'Фев',
+       'mar'                           =>      'Мар',
+       'apr'                           =>      'Апр',
+       'may'                           =>      'Мај',
+       'jun'                           =>      'Јун',
+       'jul'                           =>      'Јул',
+       'aug'                           =>      'Авг',
+       'sep'                           =>      'Сеп',
+       'oct'                           =>      'Окт',
+       'nov'                           =>      'Ное',
+       'dec'                           =>      'Дек',
+
+       "categories"                    =>      "Категории",
+       "category"                      =>      "категорија",
+       "category_header"               =>      "Статии во категорија \"$1\"",
+       "subcategories"                 =>      "Подкатегории",
+       'linktrail'                     =>      "/^((?:[a-z]|а|б|в|г|д|ѓ|е|ж|з|ѕ|и|ј|к|л|љ|м|н|њ|о|п|р|с|т|ќ|у|ф|х|ц|ч|џ|ш)+)(.*)$/sD",
+       'mainpage'                      =>      'Почетна страна',
+       'mainpagetext'                  =>      'Вики софтверот е успешно инсталиран.',
+       'mainpagedocfooter'             =>      'Ве молиме, видете ја [http://meta.wikimedia.org/wiki/MediaWiki_i18n документацијата] и [http://meta.wikimedia.org/wiki/MediaWiki_User%27s_Guide водичот] за подетална информација односно МедијаВики. Актуелната верзија на македонската јазична датотека можете да најдете на [http://meta.wikimedia.org/wiki/LanguageMk.php Мета].',
+       'portal'                        =>      'Портал на заедница',
+       'portal-url'                    =>      'Project:Портал',
+       'about'                         =>      'За',
+       'aboutsite'                     =>      'За {{SITENAME}}',
+       'aboutpage'                     =>      'Project:За {{SITENAME}}',
+       'article'                       =>      'Статија',
+       'help'                          =>      'Помош',
+       'helppage'                      =>      'Help:Помош',
+       'bugreports'                    =>      'Извештаи за грешки',
+       'bugreportspage'                =>      'Project:Извештаи за грешки',
+       'sitesupport'                   =>      'Донации',
+       'sitesupport-url'               =>      'Project:Поддршка',
+       'faq'                           =>      'ЧПП',
+       'faqpage'                       =>      'Project:ЧПП',
+       'edithelp'                      =>      'Помош за менување',
+       'newwindow'                     =>      '(се отвара во нов прозорец)',
+       'edithelppage'                  =>      'Help:Како се уредуваат страници',
+       'cancel'                        =>      'Откажи',
+       'qbfind'                        =>      'Најди',
+       'qbbrowse'                      =>      'Прелистај',
+       'qbedit'                        =>      'Уреди',
+       'qbpageoptions'                 =>      'Оваа страница',
+       'qbpageinfo'                    =>      'Содржина',
+       'qbmyoptions'                   =>      'Мои страници',
+       'qbspecialpages'                =>      'Специјални страници',
+       'moredotdotdot'                 =>      'Повеќе...',
+       'mypage'                        =>      'Моја страница',
+       'mytalk'                        =>      'Моја дискусија',
+       'anontalk'                      =>      'Разговор за тоа IP',
+       'navigation'                    =>      'Навигација',
+
+       'metadata'                      =>      '<b>Метаподатоци</b> (за објаснување видете <a href="$1">овде</a>)',
+       'metadata_page'                 =>      'Википедија:Метаподатоци',
+       'currentevents'                 =>      'Тековни настани',
+       'currentevents-url'             =>      'Тековни настани',
+       'disclaimers'                   =>      'Услови на употреба',
+       'disclaimerpage'                =>      "Project:Услови_на_употреба",
+       'errorpagetitle'                =>      "Грешка",
+       'returnto'                      =>      "Врати се на $1.",
+       'tagline'                       =>      "Од {{SITENAME}}",
+       'whatlinkshere'                 =>      'Страници кои носат овде',
+       'help'                          =>      'Помош',
+       'search'                        =>      'Пребарување',
+       'go'                            =>      'Оди',
+       "history"                       =>      'Историја на страницата',
+       'history_short'                 =>      'Историја',
+       'info_short'                    =>      'Информација',
+       'printableversion'              =>      'Верзија погодна за печатење',
+       'edit'                          =>      'Уреди',
+       'editthispage'                  =>      'Уреди ја оваа страница',
+       'delete'                        =>      'Избриши',
+       'deletethispage'                =>      'Избриши ја оваа страница',
+       'undelete_short1'               =>      'Враќање на едно избришано уредување',
+       'undelete_short'                =>      'Враќање на $1 избришани уредувања',
+       'protect'                       =>      'Заштити',
+       'protectthispage'               =>      'Заштити ја оваа страница',
+       'unprotect'                     =>      'Отстрани ја заштитата',
+       'unprotectthispage'             =>      'Отстрани ја заштитата на оваа страница',
+       'newpage'                       =>      'Нова страница',
+       'talkpage'                      =>      'Дискутирај за оваа страница',
+       'specialpage'                   =>      'Специјална страница',
+       'personaltools'                 =>      'Лични алатки',
+       'postcomment'                   =>      'Испрати коментар',
+       'addsection'                    =>      '+',
+       'articlepage'                   =>      'Види статија',
+       'subjectpage'                   =>      'Види тема',
+       'talk'                          =>      'Разговор',
+       'views'                         =>      'Прегледи',
+       'toolbox'                       =>      'Алатник',
+       'userpage'                      =>      'Види ја страницата на корисникот',
+       'wikipediapage'                 =>      'Види мета страница',
+       'imagepage'                     =>              'Види страница со слики',
+       'viewtalkpage'                  =>      'Види разговори',
+       'otherlanguages'                =>      'Други јазици',
+       'redirectedfrom'                =>      '(Пренасочено од $1)',
+       'lastmodified'                  =>      'Оваа страница последен пат е изменета на $1.',
+       'viewcount'                     =>      'Оваа страница била посетена $1 пати.',
+       'copyright'                     =>      'Сите тесктови се достапни под условите на $1.',
+       'poweredby'                     =>      "{{SITENAME}} е покренувано од [http://www.mediawiki.org/ MediaWiki], open source wiki engine.",
+       'printsubtitle'                 =>      "(Од {{SERVER}})",
+       'protectedpage'                 =>      'Заштитена страница',
+       'administrators'                =>      "Project:Администратори",
+       'sysoptitle'                    =>      'Се бара администраторски пристап',
+       'sysoptext'                     =>      "Бараната функција може да ја изврши само корисник со статус \"администратор\". Види $1.",
+       'developertitle'                =>      'Се бара развивачки пристап',
+       'developertext'                 =>      "Бараната функција може да ја изврши само корисник со статус \"развивач\". Види $1.",
+       'nbytes'                        =>      '$1 бајти',
+       'ok'                            =>      'Во ред',
+       'sitetitle'                     =>      "{{SITENAME}}",
+       'pagetitle'                     =>      "$1 - {{SITENAME}}",
+       'sitesubtitle'                  =>      'Слободна Енциклопедија',
+       'retrievedfrom'                 =>      "Преземено од \"$1\"",
+       'newmessages'                   =>      "Имате $1.",
+       'newmessageslink'               =>      'нови пораки',
+       'editsection'                   =>      'промени',
+       'toc'                           =>      'Содржина',
+       'showtoc'                       =>      'прикажи',
+       'hidetoc'                       =>      'скриј',
+       'thisisdeleted'                 =>      "Погледни или врати $1?",
+       'restorelink'                   =>      "$1 избришани промени",
+       'feedlinks'                     =>      'Feed:',
+       'sitenotice'                    =>      '-',
+
+       'nstab-main'                    =>      'Статија',
+       'nstab-user'                    =>      'Корисник',
+       'nstab-media'                   =>      'Медија',
+       'nstab-special'                 =>      'Специјална страница',
+       'nstab-wp'                      =>      'За',
+       'nstab-image'                   =>      'Слика',
+       'nstab-mediawiki'               =>      'МедијаВики',
+       'nstab-template'                =>      'Шаблон',
+       'nstab-help'                    =>      'Помош',
+       'nstab-category'                =>      'Категорија',
+
+       'nosuchaction'                  =>      'Не постои таква функција',
+       'nosuchactiontext'              =>      'Функцијата од УРЛ-то не е подржана од Вики',
+       'nosuchspecialpage'             =>      'Не постои таква специјална страница',
+       'nospecialpagetext'             =>      'Баравте невалидна [[Special:Specialpages|специјална страница]]. ', # FIXME
+
+       'error'                         =>      'Грешка',
+       'databaseerror'                 =>      '',
+       'dberrortext'                   =>      "Грешка во синтаксата на барањето. Најверојатно имате грешка во прашањето кон базата (види $5), или пронајдовте грешка во софтверот. Последниот прашалник кон базата беше: <blockquote><tt>$1</tt></blockquote> од функцијата \"<tt>$2</tt>\". MySQL ја врати следната грешка \"<tt>$3: $4</tt>\".",
+       'dberrortextcl'                 =>      "Грешка во прашалникот кон базата. Последниот прашалник кон базата беше: \"$1\" од функцијата \"$2\". MySQL ја врати следната грешка \"$3: $4\".\n",
+       'noconnect'                     =>      'Грешка! Вики има некои технички проблеми и неможе да пристапи кон серверот. <br /> $1',
+       'nodb'                          =>      "Неможам да изберам база $1",
+       'cachederror'                   =>      'Следува зачувана копија на бараната страница, која можеби е застарена.',
+       'laggedslavemode'               =>      'Предупредување: Страницата може да не ги содржи скорешните ажурирања.',
+       'readonly'                      =>      'Базата е заклучена',
+       'enterlockreason'               =>      'Внесете причина за заклучувањето, вклулувајќи и време на отклучување (приближно)',
+       'readonlytext'                  =>      "Базата е моментално затворена за нови статии и други модификации, најверојатно за рутинска проверка, по која ќе се врати во нормалната состојба. Администраторот кој ја заклучи го понуди следното објаснување: <p>$1",
+       'missingarticle'                =>      "Базата не го најде текстот што требаше да го најде, \"$1\". <p>Најчеста причина е застарен diff или врска кон страница која била избришана. <p>Доколку причина е нешто друго, можеби најдовте грешка во софтверот. Ве молиме пријавете го ова на администраторот, наведувајќи ја URL адресата.",
+       'internalerror'                 =>      'Внатрешна грешка',
+       'filecopyerror'                 =>      "Неможам да ја копирам датотеката \"$1\" во \"$2\".",
+       'filerenameerror'               =>      "Неможам да ја преименувам датотеката \"$1\" во \"$2\".",
+       'filedeleteerror'               =>      "Неможам да ја избришам датотеката \"$1\".",
+       'filenotfound'                  =>      "Неможам да ја најдам датотеката \"$1\".",
+       'unexpected'                    =>      "Неочекувана вредност: \"$1\"=\"$2\".",
+       'formerror'                     =>      'Грешка: неможам да го испратам формуларот',
+       'badarticleerror'               =>      'Оваа акција неможе да се спроведе на наведената страница.',
+       'cannotdelete'                  =>      'Неможам да ја избришам страницата или сликата. (Можеби е веќе избришана од некој друг.)',
+       'badtitle'                      =>      'Лош наслов',
+       'badtitletext'                  =>      "Бараниот наслов е грешан, празен или погрешно поврзан inter-language (меѓујазичен) или inter-wik (интер-вики)i наслов.",
+       'perfdisabled'                  =>      'Грешка! Оваа можност е привремено исклучена бидејќи ја успорува базата до ниво кога никој неможе да го користи вики.',
+       'perfdisabledsub'               =>      "Еве зачувана копија од $1:",
+       'perfcached'                    =>      'Следните податоци се кеширани и може да не бидат целосно ажурирани:',
+       'wrong_wfQuery_params'          =>      "Грешни параметри до wfQuery()<br /> Функција: $1<br /> Прашалник: $2",
+       'viewsource'                    =>      'Види код',
+       'protectedtext'                 =>      "Оваа страница е заклучена; има повеќе причини за тоа, ве молиме погледнете ја [[Project:Заштитена_страница]].",
+       'sqlhidden'                     =>      '(Скриен SQL прашалник)',
+
+       'logouttitle'                   =>      '',
+       'logouttext'                    =>      "Сега си одјавен.<br /> Можеш да продолжиш да го користиш {{SITENAME}} анонимно, или можеш да се најавиш под истото или различно корисничко име. Некои страници може да продолжат да се прикажуваат како да сте најавени, се додека не го исчистите кеш-от на вашиот пребарувач\n",
+       'welcomecreation'               =>      "== Добредојде, $1! == Сега сте регистрирани. Не заборавај да ги промениш прилагодувањата за {{SITENAME}}.",
+       'loginpagetitle'                =>      'Најавување',
+       'yourname'                      =>      'Корисничко име',
+       'yourpassword'                  =>      'Лозинка',
+       'yourpasswordagain'             =>      'Повторно лозинка',
+       'newusersonly'                  =>      ' (само нови корисници)',
+       'remembermypassword'            =>      'Запамти ја лозинката за повеќе сесии.',
+       'loginproblem'                  =>      '<b>Има проблем со вашето најавување.</b><br />Обидете се повторно!',
+       'alreadyloggedin'               =>      "<strong>Корисник $1, веќе сте најавени!</strong><br />\n",
+       "login"                         =>      "Најавување",
+       "loginprompt"                   =>      "Морате да користите колачиња за да се најавите на {{SITENAME}}.",
+       "userlogin"                     =>      "Најави се",
+       "logout"                        =>      "Одјави се",
+       "userlogout"                    =>      "Одјави се",
+       "notloggedin"                   =>      "Не сте најавени",
+       "createaccount"                 =>      "Регистрирај се",
+       "createaccountmail"             =>      "по е-пошта",
+       "badretype"                     =>      "Внесените лозинки не се исти.",
+       "userexists"                    =>      "Корисничкото име што го внесовте веќе се користи. Изберете друго име.",
+       "youremail"                     =>      "Вашата е-пошта*",
+       "yournick"                      =>      "Вашиот надимак (за потпис)",
+       "emailforlost"                  =>      "* Внесувањето на е-поштенска адреса не е задолжително. Сепак, тоа помага на други корисници да стапат во контакт со вас преку сајтот без да им ја кажувате е-поштенската адреса, исто така помага ако ја заборавите лозинката.",
+       "loginerror"                    =>      "Грешка во најавувањето",
+       'prefs-help-email-enotif'       =>      'Оваа адреса истотака се користи за испраќање на известувања по е-пошта доколку ја имате дозволено таа можност.',
+       'prefs-help-realname'           =>      '* Вистинско име (опција). Доколку изберете да го дадете вашето име, тоа може да се искористи за давање на заслуги за вашата работа.',
+       'loginerror'                    =>      'Грешка при најавување',
+       'prefs-help-email'              =>      '* Е-пошта (опционално): Им овозможува на другите да контактираат со вас преку вашата корисничка страница или вашата страница за дискусија, без да биде потребно да го откриете вашиот идентитет.',
+       "nocookiesnew"                  =>      "Регистрирани сте, но не сте најавени. {{SITENAME}} користи колачиња за најавување на корисници. Вие имате забрането користење на колачиња. Ве молиме активирајте ги, па потоа најавете се со вашето корисничко име и лозинка.",
+       "nocookieslogin"                =>      "{{SITENAME}} користи колачиња за најавување на корисници. Вие имате забрането користење на колачиња. Ве молиме активирајте ги и обидете се повторно.",
+       "noname"                        =>      "Внесовте грешно корисничко име.",
+       "loginsuccesstitle"             =>      "Успешно најавување",
+       "loginsuccess"                  =>      "Сега сте најавени на {{SITENAME}} како \"$1\".",
+       "nosuchuser"                    =>      "Нема корисник со името \"$1\". Проверете ја синтаксата, или искористете го долниот формулар да се регистрирате.",
+       'nosuchusershort'               =>      "Нема корисник со името \"$1\". Проверете ја синтаксата.",
+       "wrongpassword"                 =>      "Внесовте погрешна лозинка. Обидете се повторно.",
+       "mailmypassword"                =>      "Испрати ми по пошта нова лозинка",
+       "passwordremindertitle"         =>      "Потсетник за лозинка од {{SITENAME}}",
+       "passwordremindertext"          =>      "Некој (најверојатно вие, од IP адреса $1) побара да ви испратиме нова {{SITENAME}} лозинка. Лозинката за корисникот \"$2\" сега е \"$4\". Треба да се најавите и да ја промените лозинката сега. Сега можете да се логирате со оваа привремена позинка, која е валидна само за едно логирање. Можете да продолжите да ја користите старата лозинка ако ја памтите или да поставите нова. {{SERVER}}{{localurl:Special:Userlogin|wpName=$3&wpPassword=$4&returnto=Special:Preferences}}",
+       "noemail"                       =>      "Нема внесено е-поштенска адреса за корисникот \"$1\".",
+       "passwordsent"                  =>      "Нова лозинка е испратена на корисникот \"$1\". Најавете се повторно откако ќе ја примите пораката.",
+       "loginend"                      =>      "",
+       'eauthentsent'                  =>      "Е-пошта е испратена на назначената е-поштенска адреса. Пред било која пошта да се прати на сметката, ќе мората да ги следите инструкциите во е-поштата, за да потврдите дека таа е навистина ваша.",
+       'loginend'                      =>      '&nbsp;',
+       'mailerror'                     =>      "Грешка при испраќање на е-поштата: $1",
+       'acct_creation_throttle_hit'    =>      'Извинете, веќе имате создадено $1 сметки. Не можете да создавате повеќе.',
+       'emailauthenticated'            =>      'Автентичноста на вашата е-поштенска адреса е проверена на $1.',
+       'emailnotauthenticated'         =>      'Автентичноста на вашата е-поштенска адреса <strong>сеуште не е проверена</strong>. Нема да биде испратена е-пошта за никоја од следните содржини.',
+       'noemailprefs'                  =>      '<strong>Не беше наведена е-поштенска адреса</strong>, следните содржини нема да работат.',
+       'emailconfirmlink'              =>      'Потврдете ја вашата е-поштенска адреса',
+       'invalidemailaddress'           =>      'Е-поштенската адреса не може да биде прифатена бидејќи има невалиден формат. Ве молиме, внесете валиден формат или испразнете го тоа поле.',
+
+       "bold_sample"                   =>      "Задебелен текст",
+       "bold_tip"                      =>      "Закосен текст",
+       "italic_sample"                 =>      "Закосен текст",
+       "italic_tip"                    =>      "Закосен текст",
+       "link_sample"                   =>      "Наслов на врска",
+       "link_tip"                      =>      "Внатрешна врска",
+       "extlink_sample"                =>      "http://www.example.com наслов на врска",
+       "extlink_tip"                   =>      "Надворешена врска (користи http:// префикс)",
+       "headline_sample"               =>      "Наслов",
+       "headline_tip"                  =>      "Ниво 2 наслов",
+       "math_sample"                   =>      "Овде вметни формула",
+       "math_tip"                      =>      "Математичка формула (LaTeX)",
+       "nowiki_sample"                 =>      "Овде внеси неформатиран текст",
+       "nowiki_tip"                    =>      "Игнорирај вики форматирање",
+       "image_sample"                  =>      "пример.jpg",
+       "image_tip"                     =>      "Вметната слика",
+       "media_sample"                  =>      "пример.mp3",
+       "media_tip"                     =>      "Врска кон мултимедијална датотека",
+       "sig_tip"                       =>      "Вашиот потпис со време",
+       "hr_tip"                        =>      "Хоризонтална линија",
+       "infobox"                       =>      "Кликни на копче за да добиеш пробен текст",
+       'infobox_alert'                 =>      "Ве молиме, додадете го текстот што сакате да биде форматиран.\\n Тој ќе биде покажан во инфокутијата од кадешто ќе можете да го изберете.\\nПример:\\n$1\\nќе стане:\\n$2",
+
+       "summary"                       =>      "Заклучок",
+       "subject"                       =>      "Наслов",
+       "minoredit"                     =>      "Ова е ситна промена",
+       "watchthis"                     =>      "Набљудувај ја оваа страница",
+       "savearticle"                   =>      "Зачувај страница",
+       "preview"                       =>      "Прегледај",
+       "showpreview"                   =>      "Прегледај",
+       "blockedtitle"                  =>      "Корисникот е блокиран",
+       "blockedtext"                   =>      "Вашето корисничко име или IP адреса беше блокирано од $1 заради:<br />''$2''<p>Можеш да контактираш со $1 или еден од дргуите [[Project:Администратори|администратори]] за блокадата. Забелешка: Неможете да ја користите \"е-пошта до корисникот\" опцијата ако немате внесено валидна адреса во вашите [[Special:Прилагодувања|прилагодувања]]. Вашата IP адреса е $3. Ве молиме вклучете ја оваа адреса во сите барања што ќе ги приложите.",
+       "whitelistedittitle"            =>      "Морате да бидете најавени за менување на статии",
+       "whitelistedittext"             =>      "Морате да се [[Special:Userlogin|најавите]] за да менувате статии.",
+       "whitelistreadtitle"            =>      "Мора да сте најавени за да читате статии",
+       "whitelistreadtext"             =>      "Мора да сте [[Special:Userlogin|најавени]] за да читате статии.",
+       "whitelistacctitle"             =>      "Немате дозвола да додавате корисници",
+       "whitelistacctext"              =>      "За да можете да додавате корисници во ова Вики мора да се [[Special:Userlogin|најавите]] и да имате соодветна дозвола.",
+       "accmailtitle"                  =>      "Лозинката е испратена.",
+       "accmailtext"                   =>      "Лозинката за '$1' е испратена на $2.",
+       "newarticle"                    =>      "(Нова)",
+       "newarticletext"                =>      "Кликнавте врска која води до страница која сеуште не постои. За да ја креирате страницата, почете со типкање во долното прозорче (видете ја страницата за [[Project:Help|помош]] за повеќе информации). Ако сте овде по грешка, само кликнете го '''назад''' копчето во вашиот пребарувач.",
+       'talkpagetext'                  =>      '<!-- МедијаВики:talkpagetext -->',
+       "anontalkpagetext"              =>      "---- ''Ова е страница за разговор за анонимен корисник кој сеуште не е регистриран или не ја користи. Затоа мораме да ја користиме неговата нумеричка [[IP адреса]] за идентификација. Една IP може да биде делена од повеќе корисници. Ако сте анонимен корисник и сметате дека ирелевантни коментари се насочени кон вас, ве молиме [[Special:Userlogin|Регистрирајте или најавете се]] за да избегнете забуна со други корисници.'' ",
+       "noarticletext"                 =>      "(Моментално нема текст на оваа страница)",
+       'clearyourcache'                =>      "'''Забелешка:''' По зачувување морате да го исчистите кешот на вашиот прелистувач за да ги видите промените: '''Mozilla / Firefox:''' ''Ctrl-Shift-R'', '''IE:''' ''Ctrl-F5'', '''Safari:''' ''Cmd-Shift-R'', '''Konqueror''' ''F5''.",
+       'usercssjsyoucanpreview'        =>      "<strong>Совет:</strong> Користете го копчето Прегледај за да го испробате новиот CSS/JS код пред зачувувањето.",
+       'usercsspreview'                =>      "'''Запомнете дека ова е само преглед на вашиот CSS код, и страницата сеуште не е зачувана!'''",
+       'userjspreview'                 =>      "'''Запомнете дека ова е само преглед на вашиот JavaScript код, и страницата сеуште не е зачувана!'''",
+       "updated"                       =>      "(Освежено)",
+       "note"                          =>      "<strong>Забелешка:</strong> ",
+       "previewnote"                   =>      "Запомнете дека ова е само преглед, и страницата сеуште не е зачувана!",
+       "previewconflict"               =>      "Овој преглед го прикажува текстот од внесен во горниот дел како ќе изгледа кога ќе се зачува страницата.",
+       "editing"                       =>      "Уредување на $1",
+       "editconflict"                  =>      "Конфликтни уредувања: $1",
+       "explainconflict"               =>      "Некој друг ја променил страницата откако почнавте да ја менувате. Горниот дел за тест ја содржи страницата како што сега постои. Вашите промени се прикажани во долниот дел. Ќе морате да ги споите вашите промени со постоечкиот текст. <b>Само</b> текстот во горниот дел ќе биде зачуван кога ќе кликнете на \"Зачувај\".\n<p>",
+       "yourtext"                      =>      "Ваш текст",
+       "storedversion"                 =>      "Зачувана верзија",
+       'nonunicodebrowser'             =>      "<strong>ПРЕДУПРЕДУВАЊЕ: Вашиот прелистувач не Уникод компатибилен, ве молиме променете го пред да уредувате статија.</strong>",
+       "editingold"                    =>      "<strong>ПРЕДУПРЕДУВАЊЕ: Менувате застарена ревизија на оваа страница Ако ја зачувате, сите промени по оваа ревизија ќе се изгубат.</strong>\n",
+       "yourdiff"                      =>      "Разлики",
+       "copyrightwarning"              =>      "Сите придонеси до {{SITENAME}} се претпоставува дека се издадени под GNU Free Documentation License (види $1 за детали). Ако не сакате вашиот текст да биде менуван и редистрибуиран слободно, не го испраќајте овде.<br /> Исто така потврдувате дека текстот сте го напишале сами, или сте го копирале од јавен домен или сличен слободен извор. <strong>НЕ ПРАЌАЈТЕ ЗАШТИТЕНИ ТЕКСТОВИ БЕЗ ДОЗВОЛА!</strong>",
+       'copyrightwarning2'             =>      "Ве молиме, имајте во предвид дека сите придонеси кон {{SITENAME}} можат да бидат уредувани, менувани или отстранети од други корисници. Ако не сакате вашиот текст да биде менуван и редистрибуиран слободно, не го испраќајте овде.<br /> Исто така потврдувате дека текстот сте го напишале сами, или сте го копирале од јавен домен или сличен слободен извор (видет $1 за детали). <strong>НЕ ПРАЌАЈТЕ ЗАШТИТЕНИ ТЕКСТОВИ БЕЗ ДОЗВОЛА!</strong>",
+       "longpagewarning"               =>      "ПРЕДУПРЕДУВАЊЕ: Оваа страница е $1 килобајти долга; некои пребарувачи може да имаат проблеми со менување на страни подолги од 32kb. Размислете за разделување на страницата во помали делови.",
+       "readonlywarning"               =>      "ЗАБЕЛЕШКА: Базата е заклучена заради проверка, па нема да можете да ги зачувате вашите промени сега. Пробајте да го зачувате текстот локално и да го пратите подоцна.",
+       "protectedpagewarning"          =>      "ПРЕДУПРЕДУВАЊЕ: Оваа страница е заклучена па само корисници со администраторски привилегии може да ја менуваат. Прочитајте го [[Project:Protected_page_guidelines|упатството за заштитени страници]].",
+       'templatesused'                 =>      'Шаблони користени на оваа страница:',
+
+       'revhistory'                    =>      'Историја на ревизии',
+       'nohistory'                     =>      'Нема историја на ревизии за оваа страница.',
+       "revnotfound"                   =>      "Ревизијата не е најдена",
+       "revnotfoundtext"               =>      "Старата ревизија на оваа страница неможе да се најде. Проверете ја URL адресата што ја користевте за пристап до оваа страница.\n",
+       "loadhist"                      =>      "Се вчитува историјата за страницата",
+       "currentrev"                    =>      "Моментална ревизија",
+       "revisionasof"                  =>      "Ревизија од $1",
+       'revisionasofwithlink'          =>      'Ревизија од $1; $2<br />$3 | $4',
+       'previousrevision'              =>      '←Претходна ревизија',
+       'nextrevision'                  =>      'Следна ревизија→',
+       'currentrevisionlink'           =>      'види ја тековната ревизија',
+       "cur"                                   =>      "мом",
+       "next"                          =>      "следна",
+       "last"                          =>      "последна",
+       "orig"                          =>      "ориг",
+       "histlegend"                    =>      "Легенда: (мом) = разлика со моменталната ревизија, (последна) = разлика со претходната ревизија, С = ситна промена",
+       'history_copyright'             =>      '-',
+       'deletedrev'                    =>      '[избришана]',
+
+       "difference"                    =>      "(Разлика меѓу ревизии)",
+       "loadingrev"                    =>      "се вчитува ревизијата за diff",
+       "lineno"                        =>      "Линија $1:",
+       "editcurrent"                   =>      "Промени ја моментална верзија на оваа страница",
+       'selectnewerversionfordiff'     =>      'Изберете понова верзија за споредба',
+       'selectolderversionfordiff'     =>      'Изберете постара верзија за споредба',
+       'compareselectedversions'       =>      'Споредете ги избраните верзии',
+
+       "searchresults"                 =>      "Резултати од пребарувањето",
+       "nogomatch"                     =>      "Не постои страница со тој наслов, пробувам целосно барање на текстови.",
+       "titlematches"                  =>      "Соодветни наслови на статии",
+       "notitlematches"                =>      "Нема соодветни наслови на статии",
+       "textmatches"                   =>      "Соодветни текстови во статии",
+       "notextmatches"                 =>      "Нема соодветни текстови во статии",
+       "prevn"                         =>      "претходни $1",
+       "nextn"                         =>      "следни $1",
+       "viewprevnext"                  =>      "Види ($1) ($2) ($3).",
+       "showingresults"                =>      "Прикажувам под <b>$1</b> резултати почнувајќи од #<b>$2</b>.",
+       "showingresultsnum"             =>      "Прикажувам под <b>$3</b> резултати во #<b>$2</b>.",
+       "nonefound"                     =>      "<strong>Забелешка</strong>: неуспешни барања најчесто се предизвикани од барање на чести зборови како \"има\" и \"од\", кои не се индексираат, или со внесување на повеќе од еден критериуми (само страници кои ги содржат сите барани зборови се прикажуваат).",
+       "powersearch"                   =>      "Барај",
+       "powersearchtext"               =>      "Барај во имиња :<br />$1<br />$2 Листа пренасочува Барај $3 $9",
+       "searchdisabled"                =>      "<p>Целосно барање на текстови е привремено исклучено, заради подобри перформанси. Во меѓувреме, можете да барате преку Google (подолу), што може да даде застарени резултати.</p>",
+       'googlesearch'                  =>      '<form method="get" action="http://www.google.com/search" id="googlesearch">
+ <input type="hidden" name="domains" value="{{SERVER}}" />
+ <input type="hidden" name="num" value="50" />
+ <input type="hidden" name="ie" value="$2" />
+ <input type="hidden" name="oe" value="$2" />
+
+ <input type="text" name="q" size="31" maxlength="255" value="$1" />
+ <input type="submit" name="btnG" value="$3" />
+ <div>
+ <input type="radio" name="sitesearch" id="gwiki" value="{{SERVER}}" checked="checked" /><label for="gwiki">{{SITENAME}}</label>
+ <input type="radio" name="sitesearch" id="gWWW" value="" /><label for="gWWW">WWW</label>
+ </div>
+</form>',
+       "blanknamespace"                =>      "(Главна)",
+
+       "preferences"                   =>      "Прилагодувања",
+       "prefsnologin"                  =>      "Не сте најавени",
+       "prefsnologintext"              =>      "Мора да бидете [[Special:Userlogin|најавени]] за промена на прилагодувањата.",
+       "prefslogintext"                =>      "Најавени сте како \"$1\". Вашиот внатрешен идентификационен број е $2. Видете [[Project:User preferences help]] за помош околу опциите.",
+       'prefsreset'                    =>      'Стандардните прилагодувања се воспоставени.',
+       "qbsettings"                    =>      "Лента за брз избор",
+       "changepassword"                        =>      "Промени лозинка",
+       "skin"                          =>      "Маска",
+       "math"                          =>      "Прикажување",
+       "dateformat"                    =>      "Приказ на време",
+       "math_failure"                  =>      "Неможам да парсирам",
+       "math_unknown_error"            =>      "непозната грешка",
+       "math_unknown_function"         =>      "непозната функција",
+       "math_lexing_error"             =>      "лексичка грешка",
+       "math_syntax_error"             =>      "синтаксна грешка",
+       "math_image_error"              =>      "неуспешна PNG конверзија",
+       'math_bad_tmpdir'               =>      'Невозможно е создавањето на привремен директориум за математичките операции',
+       'math_bad_output'               =>      'Невозможно е создавањето на аутпут директориум за математичките операции',
+       'math_notexvc'                  =>      'Недостасува извршната датотека texvc; ве молиме видете math/README за подесувања.',
+       'prefs-personal'                =>      'Кориснички податоци',
+       'prefs-rc'                      =>      'Скорешни промени и патрлоци',
+       'prefs-misc'                    =>      'Разно',
+       "saveprefs"                     =>      "Запамти прилагодувања",
+       "resetprefs"                    =>      "Ресетирај прилагодувања",
+       "oldpassword"                   =>      "Стара лозинка",
+       "newpassword"                   =>      "Нова лозинка",
+       "retypenew"                     =>      "Повторно внесување на нова лозинка",
+       "textboxsize"                   =>      "Димензии на кутија за текст",
+       "rows"                          =>      "Редови",
+       "columns"                       =>      "Колони",
+       "searchresultshead"             =>      "Опции за резултати од пребарувања",
+       "resultsperpage"                =>      "Резултати по страница",
+       "contextlines"                  =>      "Линии по резултати",
+       "contextchars"                  =>      "Карактери од содржината по линија",
+       "stubthreshold"                 =>      "Определување на патрлоци до",
+       "recentchangescount"            =>      "Број на наслови во скорешни промени",
+       "savedprefs"                    =>      "Вашите прилагодувања се зачувани.",
+       "timezonetext"                  =>      "Внесете колку часови вашето локално време се разликува од серверското време (UTC).",
+       "localtime"                     =>      "Прикажување локално време",
+       "timezoneoffset"                =>      "Отстапка",
+       "servertime"                    =>      "Серверското време е",
+       "guesstimezone"                 =>      "Пополни од пребарувачот",
+       "emailflag"                     =>      "Оневозможи е-пошта од други корисници",
+       "defaultns"                     =>      "Барај во овие namespaces по основно:",
+       'default'                       =>      'по основно',
+       'files'                         =>      'Датотеки',
+       'groups-lookup-group'           =>      'Управување со групни права',
+       'groups-group-edit'             =>      'Постоечки групи: ',
+       'editgroup'                     =>      'Уреди група',
+       'addgroup'                      =>      'Додади група',
+       'userrights-lookup-user'        =>      'Управувај со кориснички групи',
+       'userrights-user-editname'      =>      'Внеси корисничко име: ',
+       'editusergroup'                 =>      'Уреди кориснички групи',
+
+       'groups-editgroup'              =>      'Уреди група',
+       'groups-addgroup'               =>      'Додади група',
+       'groups-editgroup-preamble'     =>      'Ако името на описот почнува со колона, остатокот ќе биде третиран како име на порака, и затоа ќе биде локализиран со МедијаВики namespace',
+       'groups-editgroup-name'         =>      'Име на група: ',
+       'groups-editgroup-description'  =>      'Опис на група (макс. 255 знаци):<br />',
+       'savegroup'                     =>      'Зачувај група',
+       'groups-tableheader'            =>      'ID || Име || Опис || Права',
+       'groups-existing'               =>      'Постоечки групи',
+       'groups-noname'                 =>      'Ве молиме определете валидно име на група',
+       'groups-already-exists'         =>      'Група со тоа име веќе постои',
+       'addgrouplogentry'              =>      'Додадена група $2',
+       'changegrouplogentry'           =>      'Изменета група $2',
+       'renamegrouplogentry'           =>      'Преименувана група $2 во $3',
+
+       'userrights-editusergroup'      =>      'Уреди кориснички групи',
+       'saveusergroups'                =>      'Зачувај кориснички групи',
+       'userrights-groupsmember'       =>      'Член на:',
+       'userrights-groupsavailable'    =>      'Достапни групи:',
+       'userrights-groupshelp'         =>      'Изберете групи од кои сакате да го отстраните корисникот или да го додадете. Групите што не се избрани нема да бидат променети. Можете да деселектирате група со CTRL + лев клик',
+       'userrights-logcomment'         =>      'Изменето членството на групата од $1 до $2',
+
+       'group-anon-name'               =>      'Анонимен',
+       'group-anon-desc'               =>      'Анонимни корисници',
+       'group-loggedin-name'           =>      'Корисник',
+       'group-loggedin-desc'           =>      'Обични најавени корисници',
+       'group-admin-name'              =>      'Администратор',
+       'group-admin-desc'              =>      'Корисници кои можат да блокираат корисници и да бришат статии',
+       'group-bureaucrat-name'         =>      'Бирократ',
+       'group-bureaucrat-desc'         =>      'Бирократската група може да создава корисници со sysop права',
+       'group-steward-name'            =>      'Стјуард',
+       'group-steward-desc'            =>      'Целосен пристап',
+
+       "changes"                       =>      "промени",
+       "recentchanges"                 =>      "Скорешни промени",
+       'recentchanges-url'             =>      'Special:Recentchanges',
+       "recentchangestext"             =>      "Забележи ги најновите промени на викито на оваа страница.",
+       "rcloaderr"                     =>      "Вчитување на скорешни промени",
+       "rcnote"                        =>      "Подолу се последните <strong>$1</strong> промени во последните <strong>$2</strong> дена.",
+       "rcnotefrom"                    =>      "Подолу се промените од <b>$2</b> (се прикажуваат до <b>$1</b>).",
+       "rclistfrom"                    =>      "Прикажи нови промени почнувајќи од $1",
+       "showhideminor"                 =>      "$1 ситни промени | $2 бота | $3 најавени корисници ",
+       "rclinks"                       =>      "Прикажи последни $1 промени во последните $2 дена<br />$3",
+       "rchide"                        =>      "во $4 форма; $1 ситни промени; $2 секундарни namespaces; $3 повеќекратни промени.",
+       "rcliu"                         =>      "; $1 промени од најавени корисници",
+       "diff"                          =>      "diff",
+       "hist"                          =>      "ист",
+       "hide"                          =>      "скриј",
+       "show"                          =>      "прикажи",
+       "tableform"                     =>      "табела",
+       "listform"                      =>      "листа",
+       "nchanges"                      =>      "$1 промени",
+       "minoreditletter"               =>      "с",
+       "newpageletter"                 =>      "Н",
+       'sectionlink'                   =>      '→',
+       'number_of_watching_users_RCview' =>    '[$1]',
+       'number_of_watching_users_pageview' =>  '[$1 корисници кои набљудуваат]',
+
+       "upload"                        =>      "Подигни датотека",
+       "uploadbtn"                     =>      "Подигни датотека",
+       "uploadlink"                    =>      "Подигни слика",
+       "reupload"                      =>      "Повторно подигни",
+       "reuploaddesc"                  =>      "Врати се во формуларот за подигнување.",
+       "uploadnologin"                 =>      "Не сте најавени",
+       'uploadnologintext'             =>      "Морате да бидете [[Special:Userlogin|најавени]] за да подигнувате датотеки.",
+       'upload_directory_read_only'    =>      'The upload directory ($1) is not writable by the webserver.',
+       "uploaderror"                   =>      "Грешка во подигнувањето",
+       'uploadtext'                    =>      "Користете го долниот формулар за да подигнете нови датотеки, да гледате или пребарувате претходно подигнати слики одете на [[Special:Imagelist|листата на подигнати датотеки]], подигнувањата и бришењата се истотака запишани во [[Special:Log|дневникот на проектот]]. Истотака морате да го штиклирате полето дека не прекршувате некои авторски права со подигнување на датотеката. Притиснете го \"Подигни датотека\" копчето за да го завршите подигнувањето. За да внесете слика во страница, користете врска во обликот '''<nowiki>[[{{ns:6}}:file.jpg]]</nowiki>''','''<nowiki>[[{{ns:6}}:file.png|alt text]]</nowiki>''' или '''<nowiki>[[{{ns:-2}}:file.ogg]]</nowiki>''' за директно поврзување со датотеката.",
+       "uploadlog"                     =>      "дневник за подигнувањата",
+       "uploadlogpage"                 =>      "Дневник на подигнувањата",
+       "uploadlogpagetext"             =>      "Подолу е листа на најновите подигнувања на датотеки.",
+       "filename"                      =>      "Име",
+       "filedesc"                      =>      "Опис",
+       "filestatus"                    =>      "Авторски права",
+       "filesource"                    =>      "Извор",
+       'copyrightpage'                 =>      "Project:Copyrights",
+       'copyrightpagename'             =>      "{{SITENAME}} авторско право",
+       "uploadedfiles"                 =>      "Пратени датотеки",
+       "ignorewarning"                 =>      "Игнорирај предупредувања и зачувај ја датотеката.",
+       "minlength"                     =>      "Имињата на сликите мораат да имаат барем три букви.",
+       'illegalfilename'               =>      'Името на датотеката "$1" содржи знаци што не се дозволени во наслов на страници. Ве молиме преименувајте ја датотеката и подигнете ја пак.',
+       "badfilename"                   =>      "Имете на сликата е променето во \"$1\".",
+       "badfiletype"                   =>      "\".$1\" не е препорачано име за слика.",
+       "largefile"                     =>      "Се препорачува сликата да не биде поголема од 100k.",
+       'emptyfile'                     =>      'Датотеката што ја подигнавте е празна. Ова може да е поради грешка во името на датотеката. Ве молиме проверете дали навистина сакате да ја подигнета оваа датотека.',
+       'fileexists'                    =>      'Датотека со ова име веќе постои, проверете $1 ако не сте сигурни дали сакате да го промените.',
+       "successfulupload"              =>      "Успешно подигнување",
+       "fileuploaded"                  =>      "Датотеката \"$1\" е успешно подигната. Ве молиме следете ја оваа врска: ($2) до страницата за опис и пополнете ги информациите за датотеката, како од каде дојде, кога е направена и од кого и било што друго што знаете за неа.",
+       "uploadwarning"                 =>      "Предупредување за подигнување",
+       "savefile"                      =>      "Зачувај",
+       "uploadedimage"                 =>      "пратено \"$1\"",
+       "uploaddisabled"                =>      "Извинете, подигнувањето е забрането.",
+       'uploadscripted'                =>      'Датотеката содржи HTML код или скрипта што може да биде погрешно интерпретира од прелистувачот.',
+       'uploadcorrupt'                 =>      'Датотеката е повредена или има неточна наставка. Ве молиме проверете ја датотеката и подигнете повторно.',
+       'uploadvirus'                   =>      'Оваа датотека содржи вирус! Детално: $1',
+       'sourcefilename'                =>      'Изворно име',
+       'destfilename'                  =>      'Целно име',
+
+       "imagelist"                     =>      "Листа на слики",
+       "imagelisttext"                 =>      "Подолу е листа на $1 подредени слики $2.",
+       "getimagelist"                  =>      "вчитување на листата",
+       "ilshowmatch"                   =>      "Прикажи ги сите слики со имиња",
+       "ilsubmit"                      =>      "Барај",
+       "showlast"                      =>      "Прикажи последни $1 подредени слики $2.",
+       "all"                           =>      "сите",
+       "byname"                        =>      "по име",
+       "bydate"                        =>      "по време",
+       "bysize"                        =>      "по големина",
+       "imgdelete"                     =>      "избр",
+       "imgdesc"                       =>      "опис",
+       "imglegend"                     =>      "Легенда: (опис) = прикажи/промени го описот за сликата.",
+       "imghistory"                    =>      "Историја на слики",
+       "revertimg"                     =>      "врт",
+       "deleteimg"                     =>      "избр",
+       'deleteimgcompletely'           =>      'Избриши ги сите ревизии',
+       "imghistlegend"                 =>      "Легенда: (мом) = ова е моменталната слика, (избр) = ја брише оваа стара верзија, (врт) = врати кон оваа стара верзија. <br /><i>Кликни на датум за да ги видиш сите слики пратени на тој датум</i>.",
+       "imagelinks"                    =>      "Врски кон слики",
+       "linkstoimage"                  =>      "Следните страници покажуваат кон оваа слика:",
+       "nolinkstoimage"                =>      "Нема страници кои покажуваат кон оваа слика.",
+       'sharedupload'                  =>      'Оваа датотека е заедничка и може да се користи од други проекти.',
+       'shareduploadwiki'              =>      'Ве молиме видете го [описот на датотеката $1] за понатамошна информација.',
+       'noimage'                       =>      'Не постои датотека со тоа име, можете [$1 да го подигнете]',
+       'uploadnewversion'              =>      '[$1 Подигни нова верзија на оваа датотека]',
+
+       "statistics"                    =>      "Статистики",
+       "sitestats"                     =>      "Статистики за сајтот",
+       "userstats"                     =>      "Статистики за корисници",
+       "sitestatstext"                 =>      "Има вкупно '''$1''' страници во базата. Оваа бројка вклучува \"разговор\" страници, страници за {{SITENAME}}, минимални \"патрлок\" страници, пренасочувања, и други кои најверојатно не се сметаат за статии. Брз нив, има '''$2''' стрници кои се вистински артикли. Има вкупно '''$3''' прегледи на страници, и '''$4''' промени на страници откако овој софтвер беше надграден (20 Јули, 2002). Тоа се сведува на '''$5''' просечни менувања по страница, и '''$6''' прегледувања по страница.",
+       "userstatstext"                 =>      "Има вкупно '''$1''' регистрирани корисници. '''$2''' од нив се администратори (види $3).",
+
+       "maintenance"                   =>      "Страница за одржување",
+       "maintnancepagetext"            =>      "Оваа страница вклучува неколку корисни алатки за секојдневно одржување. Некои од овие функции ја користат базата интензивно, па ве молиме не вчитувате повторно по секој елемент што сте го поправиле ;-)",
+       "maintenancebacklink"           =>      "Назад до страницата за одржување",
+       "disambiguations"               =>      "Нејасни страници",
+       "disambiguationspage"           =>      "Project:Links_to_disambiguating_pages",
+       "disambiguationstext"           =>      "Следните статии покажуваат кон <i>нејасна страница</i>. Тие треба да покажуваат кон соодветниот наслов.<br />Страница се третира како нејасно ако е поврзана од $1.<br />Врски од други namespaces <i>НЕ</i> се листаат овде.",
+       "doubleredirects"               =>      "Двојни пренасочувања",
+       "doubleredirectstext"           =>      "Секој ред содржи врски кон првото и второто пренасочување, којашто обично ја посочува <i>вистинската</i> целна страница кон кое првото пренасочување би требало да насочува",
+       "brokenredirects"               =>      "Прекинати пренасочувања",
+       "brokenredirectstext"           =>      "Следните пренасочувања покажуваат кон непостоечка статија.",
+       "selflinks"                     =>      "Страници со врски кон самите себеси",
+       "selflinkstext"                 =>      "Следните страници содржат врска кон самите себеси, што не е дозволено.",
+       "mispeelings"                   =>      "Страници со правописни грешни",
+       "mispeelingstext"               =>      "Следните статии содржат типични правописни грешки, кои се наведени во $1. Точниот правопис може да биде даден (вака).",
+       "mispeelingspage"               =>      "Листа на типични правописни грешки",
+       "missinglanguagelinks"          =>      "Непостоечки врски кон јазици",
+       "missinglanguagelinksbutton"    =>      "Најди непостоечки врски кон јазици за",
+       "missinglanguagelinkstext"      =>      "Следните статии <i>НЕ</i> поврзуваат кон нивната соодветна статија во $1. Пренасочувања и подстраници <i>НЕ</i> се прикажуваат.",
+
+       "orphans"                       =>      "Напуштени страници",
+       'geo'                           =>      'ГЕО координати',
+       'validate'                      =>      'Валидирај ја страницата',
+       "lonelypages"                   =>      "Осамени страници",
+       'uncategorizedpages'            =>      'Некатегоризирани страници',
+       'uncategorizedcategories'       =>      'Некатегоризирани категории',
+       "unusedimages"                  =>      "Некористени слики",
+       "popularpages"                  =>      "Популарни страници",
+       "nviews"                        =>      "$1 прегледувања",
+       "wantedpages"                   =>      "Барани страници",
+       "nlinks"                        =>      "$1 врски",
+       "allpages"                      =>      "Сите страници",
+       "randompage"                    =>      "Случајна страница",
+       'randompage-url'                =>      'Special:Random',
+       "shortpages"                    =>      "Кратки страници",
+       "longpages"                     =>      "Долги страници",
+       "deadendpages"                  =>      "Ќорсокак страници",
+       "listusers"                     =>      "Листа на корисници",
+       "specialpages"                  =>      "Специјални страници",
+       "spheading"                     =>      "Специјални страници за сите корисници",
+       'restrictedpheading'            =>      'Специјални страници со ограничен пристап',
+       "protectpage"                   =>      "Заштитени страници",
+       "recentchangeslinked"           =>      "Поврзани промени",
+       "rclsub"                        =>      "(до страници поврзани од \"$1\")",
+       "debug"                         =>      "Чистење од бубачки",
+       "newpages"                      =>      "Нови страници",
+       "ancientpages"                  =>      "Најстари статии",
+       "intl"                          =>      "Меѓујазични врски",
+       'move'                          =>      'Премести',
+       "movethispage"                  =>      "Премести ја оваа страница",
+       "unusedimagestext"              =>      "<p>Имајте во предвид дека други веб локации може да имаат врска кон слика со директна URL, па може сеуште да се прикажуваат иако активно се користат.",
+       "booksources"                   =>      "Книжари",
+       "booksourcetext"                =>      "Подолу е листа на сите врски од други веб локации кои продаваат нови или користени книги, и може да имаат повеќе информации за книгите што ги барате. {{SITENAME}} не е поврзан со ниеден од овие бизниси, и оваа листа не треба да се толкува како потврда.",
+       'categoriespagetext'            =>      'Следните категории постојат во вики.',
+       'data'                          =>      'Податоци',
+       'userrights'                    =>      'Управување со кориснички права',
+       'groups'                        =>      'Кориснички групи',
+       'isbn'                          =>      'ISBN',
+       'rfcurl'                        =>      'http://www.faqs.org/rfcs/rfc$1.html',
+       'pubmedurl'                     =>      'http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?cmd=Retrieve&db=pubmed&dopt=Abstract&list_uids=$1',
+       'alphaindexline'                =>      "$1 во $2",
+       "version"                       =>      "Верзија",
+       'log'                           =>      'Дневници',
+       'alllogstext'                   =>      'Комбиниран приказ на дневници на подигнувања, бришења, заштита, блокирање и администраторски. Можете да го стесните прегледот преку избор на вид на дневник, име на корисник, или односната страница.',
+
+       'nextpage'                      =>      'Следна страница ($1)',
+       'allpagesfrom'                  =>      'Прикажи страници кои започнуваат од:',
+       'allarticles'                   =>      'Сите статии',
+       'allnonarticles'                =>      'Сите не-статии',
+       'allinnamespace'                =>      'Сите страници ($1 namespace)',
+       'allnotinnamespace'             =>      'Сите страници (не во $1 namespace)',
+       'allpagesprev'                  =>      'Претходна',
+       'allpagesnext'                  =>      'Следна',
+       'allpagessubmit'                =>      'Оди',
+
+       "mailnologin"                   =>      "Нема адреса за праќање",
+       'mailnologintext'               =>      "Мора да бидете [[Special:Userlogin|најавен]] и да имате валидна е-поштенска адреса во вашите [[Special:Preferences|прилагодувања]] за да подигнување е-пошта до други корисници.",
+       "emailuser"                     =>      "Е-пошта до овој корисник",
+       "emailpage"                     =>      "Е-пошта до корисник",
+       "emailpagetext"                 =>      "Ако овој корисник внесол валидна е-адреса во неговите или нејзините прилагодувања, долниот формулар ќе прати една порака. Е-поштенската адреса што ја внесовте во вашите прилагодувања ќе се прикаже во \"Од\" полето на пораката, со што примачот ќе може да ви одговори.",
+       "usermailererror"               =>      "Настана следната грешка: ",
+       "defemailsubject"               =>      "{{SITENAME}} е-пошта",
+       "noemailtitle"                  =>      "Нема е-поштенска адреса",
+       "noemailtext"                   =>      "Овој корисник нема наведено валидна е-поштенска адреса, или избрал да не прима е-пошта од други корисници.",
+       "emailfrom"                     =>      "Од",
+       "emailto"                       =>      "До",
+       "emailsubject"                  =>      "Тема",
+       "emailmessage"                  =>      "Порака",
+       "emailsend"                     =>      "Прати",
+       "emailsent"                     =>      "Е-поштата е пратена",
+       "emailsenttext"                 =>      "Вашата е-пошта е пратена.",
+
+
+       'watchlist'                     =>      'Мои набљудувани страници',
+       'watchlistsub'                  =>      "(за корисник \"$1\")",
+       'nowatchlist'                   =>      'Немате елементи во вашите набљудувани страници.',
+       'watchnologin'                  =>      'Не сте најавени',
+       'watchnologintext'              =>      "Мора да бидете [[Special:Userlogin|најавени]] за да се модифицира вашиот список на набљудувани страници.",
+       'addedwatch'                    =>      'Додадено во набљудувани страници',
+       'addedwatchtext'                =>      "Страницата\"$1\" е додадена во вашите [[Special:Watchlist|набљудувани страници]]. Идните промени на оваа страница и поврзаните со неа Страници за разговор ќе бидат прикажани овде и страницата ќе се прикаже '''задебелена''' во [[Special:Recentchanges|листата на скорешни промени]] за да можете полесно да ја изберете. <p>Ако подоцна сакате да ја отстраните страницата од набљудувани страници, кликнете на \"Престани набљудување\" .",
+       'removedwatch'                  =>      'Отстрани ја страницата од набљудувани страници',
+       'removedwatchtext'              =>      "Страницата \"$1\" е отстранета од набљудувани страници.",
+       'watch'                         =>      'Набљудувај',
+       'watchthispage'                 =>      'Набљудувај ја оваа страница',
+       'unwatch'                       =>      'Престани набљудување ',
+       'unwatchthispage'               =>      'Престани набљудување',
+       'notanarticle'                  =>      'Не е страница',
+       'watchnochange'                 =>      'Ниедна од вашите нављудувани страници не беше уредувана во прикажаниот период.',
+       'watchdetails'                  =>      "($1 страници набљудувани без да се бројат страниците за разговор; $2 уредувани страници во избраното време; $3... <a href='$4'>прикажи и уреди ја целосната листа</a>.)",
+       'watchmethod-recent'            =>      'Проверување на скорешните уредувања на набљудуваните страници',
+       'watchmethod-list'              =>      'Проверување на скорешните уредувања на набљудуваните страници',
+       'removechecked'                 =>      'Отстрани ги означените елементи од набљудувани страници',
+       'watchlistcontains'             =>      "Вие набљудувате $1 страници.",
+       'watcheditlist'                 =>      'Ова е азбучна листа на вашите набљудувани страници. Означети ги полињата на страниците кои сакате да ги остраните од вашата листа и кликнете го \'Отстрани избрано\' копчето на дното на екранот (бришење на страница исто така ги брише и поврзаните статии за разговор, и обратно).',
+       'removingchecked'               =>      'Отстранување на избраните елементи од списокот...',
+       'couldntremove'                 =>      "Не може да се отстрани елементот '$1'...",
+       'iteminvalidname'               =>      "Проблем со елементот '$1', невалидно име...",
+       'wlnote'                        =>      'Подолу се последните $1 промени во последните <b>$2</b> часа.',
+       'wlshowlast'                    =>      'Прикажи последни $1 часа $2 денови $3',
+       'wlsaved'                       =>      'Ова е зачувана верзија од листата на набљудувани страници.',
+       'wlhideshowown'                 =>      '$1 на моите уредувања.',
+       'wlshow'                        =>      'Прикажи',
+       'wlhide'                        =>      'Криј',
+       'deletepage'                    =>      'Избриши ја страницата',
+       'confirm'                       =>      'Потврди',
+       'excontent'                     =>      "содржината беше: '$1'",
+       'excontentauthor'               =>      "содржината беше: '$1' (и единствениот автор беше '$2')",
+       'exbeforeblank'                 =>      "содржината пред бришењето беше: '$1'",
+       'exblank'                       =>      'страницата беше празна',
+       'confirmdelete'                 =>      'Потврди го бришењето',
+       'deletesub'                     =>      "(Бришам \"$1\")",
+       'historywarning'                =>      'Предупредување: Страницата која сакате да ја избришете има историја: ',
+       'confirmdeletetext'             =>      "На пат сте трајно да избришете страница или слика заедно со нејзината историја од базата на податоци. Ве молиме потврдете дека имате намера да го направите ова, и дека ги разбирате последиците, и дека го правите ова во согласност со [[Project:Википедија политика|нашата политика на однесување]].",
+       'actioncomplete'                =>      'Дејството беше извршено',
+       'deletedtext'                   =>      "\"$1\" беше избришана. Видете $2 за досие на скорешните бришења.",
+       'deletedarticle'                =>      "избришано \"[[$1]]\"",
+       'dellogpage'                    =>      'Дневник на бришењата',
+       'dellogpagetext'                =>      'Подолу е листа на последните бришења.',
+       'deletionlog'                   =>      'дневник на бришењата',
+       'reverted'                      =>      'Вратено на претходната ревизија',
+       'deletecomment'                 =>      'Причина за бришење',
+       'imagereverted'                 =>      'Враќањето на претходната верзија е успешно.',
+       'rollback'                      =>      'Врати промени',
+       'rollback_short'                =>      'Врати',
+       'rollbacklink'                  =>      'Врати',
+       'rollbackfailed'                =>      'Враќањето беше неуспешно',
+       'cantrollback'                  =>      'Не може да се врати последната промена, последниот автор е истовремено и единствен.',
+       'alreadyrolled'                 =>      "Не може да се врати последната верзија [[$1]] од [[Корисник:$2|$2]] ([[Корисник разговор:$2|Talk]]); некој веќе ја уредил или ги вратил промените на страницата. Последното уредување беше на [[Корисник:$3|$3]] ([[Корисник разговор:$3|Talk]]). ",
+
+       'editcomment'                   =>      "Коментарот на уредувањето беше: \"<i>$1</i>\".",
+       'revertpage'                    =>      "Отстрането уредување на $2, вратено на последната верзија од $1",
+       'sessionfailure'                =>      'There seems to be a problem with your login session; this action has been canceled as a precaution against session hijacking. Please hit "back" and reload the page you came from, then try again.',
+       'protectlogpage'                =>      'Дневник на заштитата',
+       'protectlogtext'                =>      "Подолу е листа на отклучувања/заклучувања на страницата. Видете [[Project:Заштитена страница]] за повеќе информации.",
+       'protectedarticle'              =>      "заштитена \"[[$1]]\"",
+       'unprotectedarticle'            =>      "отстранета заштита на \"[[$1]]\"",
+       'protectsub'                    =>      "(Заштитување \"$1\")",
+       'confirmprotecttext'            =>      'Дали навистина сакате да ја заштитите оваа страница?',
+       'confirmprotect'                =>      'Потврдете ја заштитата',
+       'protectmoveonly'               =>      'Заштити само од преместувања',
+       'protectcomment'                =>      'Причина за заштитување',
+       'unprotectsub'                  =>      "(Отстранување на заштитата на \"$1\")",
+       'confirmunprotecttext'          =>      'Дали навистина сакате да ја отстраните заштитата на оваа страница?',
+       'confirmunprotect'              =>      'Потврдете го отстранувањето на заштитата',
+       'unprotectcomment'              =>      'Причина за отстранување на заштитата',
+
+       'undelete'                      =>      'Врати ја избришаната страница',
+       'undeletepage'                  =>      'Погледај и врати ги избришаните страници',
+       'undeletepagetext'              =>      'Следните страници се избришани, но се сеуште во архивата и можат да бидат обновени. Архивата може периодично да се чисти.',
+       'undeletearticle'               =>      'Обновување на избришана страница',
+       'undeleterevisions'             =>      "$1 архивирани ревизии",
+       'undeletehistory'               =>      'Ако ја обновите страницата, сите ревизии ќе бидат вратени во историјата. Ако нова страница со исто име е создадена по бришењето, обновените ревизии ќе се појават во претходната историја, и тековната ревизија на постоечката страница нема да биде автоматски заменета.',
+       'undeleterevision'              =>      "Избришана ревизија од $1",
+       'undeletebtn'                   =>      'Обнови!',
+       'undeletedarticle'              =>      "обновена \"[[$1]]\"",
+       'undeletedrevisions'            =>      "$1 обновени ревизии",
+       'undeletedtext'                 =>      "[[$1]] беше успешно обновена. Видете [[Special:Дневник на бришења]] за досие на скорешните бришења и обновувања.",
+
+       'namespace'                     =>      'Namespace:',
+       'invert'                        =>      'Инверзен избор',
+
+       'contributions'                 =>      'Придонеси',
+       'mycontris'                     =>      'Мои придонеси',
+       'contribsub'                    =>      "За $1",
+       'nocontribs'                    =>      'Не се пронајдени промени што одговараат на овој критериум.',
+       'ucnote'                        =>      "Подолу се последните <b>$1</b> промени на корисникот, во последните <b>$2</b> дена.",
+       'uclinks'                       =>      "Гледај ги последните $1 промени; гледај ги последните $2 дена.",
+       'uctop'                         =>      ' (врв)' ,
+       'newbies'                       =>      'новајлија',
+
+       'whatlinkshere'                 =>      'Што е поврзано со ова',
+       'notargettitle'                 =>      'Нема цел',
+       'notargettext'                  =>      'Не одредивте целна страна или корисник на кој би се применила функцијата.',
+       'linklistsub'                   =>      '(Листа на врски)',
+       'linkshere'                     =>      'Следните страници се поврзани овде:',
+       'nolinkshere'                   =>      'Ниедна страница не е поврзана овде.',
+       'isredirect'                    =>      'пренасочувачка страница',
+
+       'blockip'                       =>      'Блокирај го корисникот',
+       'blockiptext'                   =>      "Користете го долниот формулар да ги забраните правото на пишување на одредена IP адреса или корисничко име. Ова треба единствено да се прави за да се спречи вандализам, и во согласност со [[Project:Википедија политика|политиката]]. Пополни конкретна причина подолу (на пример, цитирање на конкретни страници што биле вандализирани).",
+       'ipaddress'                     =>      'IP адреса',
+       'ipadressorusername'            =>      'IP адреса или корисничко име',
+       'ipbexpiry'                     =>      'Истек на рокот',
+       'ipbreason'                     =>      'Причина',
+       'ipbsubmit'                     =>      'Блокирај го овој корисник',
+       'badipaddress'                  =>      'Невалидна IP адреса',
+       'blockipsuccesssub'             =>      'Успешно блокирање',
+       'blockipsuccesstext'            =>      "\"$1\" беше блокиран. <br />Видете [[Special:Ipblocklist|листа на блокирани IP]] за преглед на блокирањата.",
+       'unblockip'                     =>      'Деблокирај корисник',
+       'unblockiptext'                 =>      'Користете го долниот формулар да го обновите правото на пишување на претходно блокирана IP адреса или корисничко име.',
+       'ipusubmit'                     =>      'Деблокирај ја оваа адреса',
+       'ipusuccess'                    =>      "\"[[$1]]\" деблокиран",
+       'ipblocklist'                   =>      'Листа на блокирани IP адреси и кориснички имиња',
+       'blocklistline'                 =>      "$1, $2 го блокираше $3 ($4)",
+       'infiniteblock' => 'истекува на infinite', //fixme
+       'expiringblock' => 'истекува на $1',
+       'blocklink'                     =>      'блокирај',
+       'unblocklink'                   =>      'деблокирај',
+       'contribslink'                  =>      'придонеси',
+       'autoblocker'                   =>      "Автоматски сте блокирани бидејќи делите IP адреса со \"$1\". Причина \"$2\".",
+       'blocklogpage'                  =>      'Дневник на блокирања',
+       'blocklogentry'                 =>      'блокиран "[[$1]]" со истек на рокот $2',
+       'blocklogtext'                  =>      'Ова е дневник на блокирањата и деблокирањата, извршени од овој корисник. Автоматски блокираните IP адреси не се наведени. Видете [[Special:Ipblocklist|листа на блокирани IP]] за листа на тековни забрани и блокирања.',
+       'unblocklogentry'               =>      'деблокиран "$1"',
+       'range_block_disabled'          =>      'Можноста на администраторите да задаваат интервали за IP адресите е исклучена.',
+       'ipb_expiry_invalid'            =>      'Невалиден истек на рок.',
+       'ip_range_invalid'                      =>      "Невалиден интервал за IP адреси .\n",
+       'proxyblocker'                  =>      'Прокси блокирач',
+       'proxyblockreason'              =>      'Вашата IP адреса е блокирана бидејќи е отворено прокси. Ве молиме контактирајте со вашиот доставувач на Интернет услуги или техничката поддршка и информирајте ги за овој сериозен безбедносен проблем.',
+       'proxyblocksuccess'             =>      "Готово.\n",
+       'sorbs'                         =>      'SORBS DNSBL',
+       'sorbsreason'                   =>      'Вашата IP адреса е запишана како отворено прокси во [http://www.sorbs.net SORBS] DNSBL.',
+
+       'lockdb'                        =>      'Заклучи ја базата',
+       'unlockdb'                      =>      'Отклучи ја базата',
+       'lockdbtext'                    =>      'Заклучувањето на базата ќе им ја укине можноста на сите корисници да уредуваат страници, да ги менуваат нивните прилагодувања, да ги уредуваат нивните листи на набљудувани страници, и се останато што бара промени во базата. Ве молиме потврдете дека ова е вашата намера, и дека ќе ја отклучите базата кога ќе ја завршите работата околу нејзиното одржување.',
+       'unlockdbtext'                  =>      'Отклучувањето на базата ќе им ја обнови можноста на сите корисници да уредуваат страници, да ги менуваат нивните прилагодувања, да ги уредуваат нивните листи на набљудувани страници, и се останато што бара промени во базата. Ве молиме потврдете дека ова е вашата намера.',
+       'lockconfirm'                   =>      'Да, навистина сакам да ја заклучам базата.',
+       'unlockconfirm'                 =>      'Да, навистина сакам да ја отклучам базата.',
+       'lockbtn'                       =>      'Заклучи ја базата',
+       'unlockbtn'                     =>      'Отклучи ја базата',
+       'locknoconfirm'                 =>      'Не ја потврдивте вашата намера.',
+       'lockdbsuccesssub'              =>      'Базата е заклучена',
+       'unlockdbsuccesssub'            =>      'Базата е отклучена',
+       'lockdbsuccesstext'             =>      'Базата е заклучена. <br />Сетете се да ја отклучите кога ќе завршите со нејзиното одржување.',
+       'unlockdbsuccesstext'           =>      'Базата е отклучена.',
+
+       'makesysoptitle'                =>      'Претвори корисник во администратор',
+       'makesysoptext'                 =>      'Овој формулар е користен од бирократи, за претворање на обични корисници во администратори. Напишете го името на корисникот во полето и притиснете го копчето да го претворите корисникот во администратор',
+       'makesysopname'                 =>      'Име на корисникот:',
+       'makesysopsubmit'               =>      'Претвори го овој корисник во администратор',
+       'makesysopok'                   =>      "<b>Корисникот \"$1\" е сега администратор</b>",
+       'makesysopfail'                 =>      "<b>Корисникот \"$1\" не може да биде претворен во администратор. (Дали го внесовте правилно името?)</b>",
+       'setbureaucratflag'             =>      'Кревање на "бирократ" флег',
+       'setstewardflag'                =>      'Кревање на "стјуард" флег',
+       'bureaucratlog'                 =>      'Дневник на бирократите',
+       'rightslogtext'                 =>      'Ова дневник на промени на кориснички права.',
+       'bureaucratlogentry'            =>      "Промена на групното членство на $1 од $2 кон $3",
+       'rights'                        =>      'Права:',
+       'set_user_rights'               =>      'Давање на кориснички права',
+       'user_rights_set'               =>      "<b>Корисничките права на \"$1\" се променети</b>",
+       'set_rights_fail'               =>      "<b> Корисничките права на \"$1\" не се променети. (Дали го внесовте правилно името?)</b>",
+       'makesysop'                     =>      'Претвори корисник во администратор',
+       'already_sysop'                 =>      'Овој корисник веќе е администратор',
+       'already_bureaucrat'            =>      'Овој корисник веќе е бирократ',
+       'already_steward'               =>      'Овој корисник веќе е стјуард',
+
+       'val_yes'                       =>      'Да',
+       'val_no'                        =>      'Не',
+       'val_of'                        =>      '$1 of $2',
+       'val_revision'                  =>      'Ревизија',
+       'val_time'                      =>      'Време',
+       'val_user_stats_title'          =>      'Validation overview of user $1',
+       'val_my_stats_title'            =>      'My validation overview',
+       'val_list_header'               =>      '<th>#</th><th>Тема</th><th>Range</th><th>Акција</th>',
+       'val_add'                       =>      'Додај',
+       'val_del'                       =>      'Избриши',
+       'val_warning'                   =>      '<b>Никогаш, <i>повеќе</i>, не менувај нешто овде без <i>изрична</i> согласност на заедницата!</b>',
+       'val_revision_stats_link'       =>      '(<a href="$1">детали</a>)',
+       'val_noop'                      =>      'Без мислење',
+       'val_percent'                   =>      '<b>$1%</b><br />($2 од $3 точки<br />од $4 корисници)',
+       'val_percent_single'            =>      '<b>$1%</b><br />($2 од $3 точки<br />од еден корисник)',
+       'val_total'                     =>      'Вкупно',
+       'val_version'                   =>      'Верзија',
+       'val_this_is_current_version'   =>      'ова е последната верзија',
+       'val_version_of'                =>      "Верзија од $1" ,
+       'val_table_header'              =>      "<tr><th>Class</th>$1<th colspan=4>Opinion</th>$1<th>Comment</th></tr>\n",
+       'val_view_version'              =>      'Преглед на ревизијата',
+       'val_no_anon_validation'        =>      'Морате да бидете најавени за да валидирате статија.',
+
+       'movepage'                      =>      'Премести ја страницата',
+       'movepagetext'                  =>      'Со користењето на долниот формулар можете да преименувате страница, преместувајќи ја целата нејзина историја на новото име. Стариот наслов ќе стане страница за пренасочување кон новиот наслов. Врските кон стариот наслов на страницата нема да бидат сменети; проверете дали постојат двојни или прекинати пренасочувања. Вие сте одговорни да осигурате дека врските ќе продолжат да насочуваат таму за каде се предвидени. Имајте во предвид дека страницата НЕМА да биде преместена ако постои страница со новиот наслов, освен ако е празна или ако е пренасочување и нема историја на минати уредувања. <b>ПРЕДУПРЕДУВАЊЕ!</b> Ова може да биде драстична и неочекувана промена за популарна страница; осигурајте се дека сте ги разбрале последиците од ова пред да продолжите.',
+       'movepagetalktext'              =>      'Соодветната страница за разговор, доколку постои, ќе биде автоматски преместена заедно со неа, освен ако: *Ја преместувате страницата преку namespaces, *Непразна страница за разговор веќе постои за новиот наслов, или *Не сте го одштиклирале долното поле. Во тие случаи, вие ќе треба да ја преместите или споите страницата рачно, доколку сакате.',
+       'movearticle'                   =>      'Премести ја страницата',
+       'movenologin'                   =>      'Не сте најавени',
+       'movenologintext'               =>      "Мора да бидете регистриран корисник и [[Special:Userlogin|најавен]] да преместите страница.",
+       'newtitle'                      =>      'Кон новиот наслов',
+       'movepagebtn'                   =>      'Премести ја страницата',
+       'pagemovedsub'                  =>      'Преместувањето успеа',
+       'pagemovedtext'                 =>      "Страницата \"[[$1]]\" е преместена на \"[[$2]]\".",
+       'articleexists'                 =>      'Страница со тоа име веќе постои, или името што го избравте не е валидно. Ве молиме изберете друго име.',
+       'talkexists'                    =>      'Самата страница беше преместена успешно, но страницата за разговор не можеше да биде преместена бидејќи веќе постои таква на новиот наслов. Ве молиме спојте ги рачно.',
+       'movedto'                       =>      'преместена како',
+       'movetalk'                      =>      'Премести ја и страницата за разговор, ако е возможно.',
+       'talkpagemoved'                 =>      'Соодветната страница за разговор беше исто така преместена.',
+       'talkpagenotmoved'              =>      'Соодветната страница за разговор <strong>не беше</strong> преместена.',
+       '1movedto2'                     =>      "[[$1]] преместена како [[$2]]",
+       '1movedto2_redir'               =>      '[[$1]] преместена како [[$2]] преку пренасочување',
+       'movelogpage'                   =>      'Дневник на преместувања',
+       'movelogpagetext'               =>      'Подолу е листа на преместени страници.',
+       'movereason'                    =>      'Причина',
+       'revertmove'                    =>      'врати',
+       'delete_and_move'               =>      'Избриши и премести',
+       'delete_and_move_text'          =>      '==Потребно бришење== Целната статија "[[$1]]" веќе постои. Дали сакате да ја избришете за да ослободите место за преместувањето?',
+       'delete_and_move_reason'        =>      'Избришано за да се ослободи место за преместувањето',
+       'selfmove'                      =>      "Страницата не може да биде преместена бидејќи целниот наслов се совпаѓа со првобитниот наслов.",
+       'immobile_namespace'            =>      "Целниот наслов е од специјален тип; не може да се преместуваат страници во тој namespace.",
+       'export'                        =>      'Извезување на страници',
+       'exporttext'                    =>      'Тука можете да извезете како XML текст, така и историјата на една или повеќе страници. Добиените податоци може да: *ги искористите во друг сајт, кој го користи софтверот на МедијаВики *ги обработувате или *едноставно да ги искористите за сопствени потреби, To export article pages, enter the titles in the text box below, one title per line, and select whether you want the current version as well as all old versions, with the page history lines, or just the current version with the info about the last edit. In the latter case you can also use a link, e.g. [[{{ns:Special}}:Export/Train]] for the article [[Train]].',
+       'exportcuronly'                 =>      'Вклучи ја само тековната ревизија, не целосната историја',
+
+       'allmessages'                   =>      'Сите системски пораки',
+       'allmessagesname'               =>      'Име',
+       'allmessagesdefault'            =>      'Текст по основно',
+       'allmessagescurrent'            =>      'Сегашен текст',
+       'allmessagestext'               =>      'Ова е листа на сите системски пораки досапни во МедијаВики: namespace.',
+       'allmessagesnotsupportedUI'     =>      'Моменталниот интерфејс јазик <b>$1</b> не е поддржан од Special:AllMessages на овој сајт. ',
+       'allmessagesnotsupportedDB'     =>      'Special:AllMessages не е поддржан бидејќи wgUseDatabaseMessages е исклучен.',
+
+       'thumbnail-more'                =>      'Зголеми',
+       'missingimage'                  =>      "<b>Сликата недостасува</b><br /><i>$1</i>\n",
+       'filemissing'                   =>      'Датотеката недостасува',
+
+       'import'                        =>      'Увезување на страници',
+       'importtext'                    =>      'Ве молиме извезете ја датотеката од изворното вики со користење на Special:Export алатката, зачувајте ја на вашиот диск и подигнете ја овде.',
+       'importfailed'                  =>      "Увозот не успеа: $1",
+       'importnotext'                  =>      'Празно или без текст',
+       'importsuccess'                 =>      'Увозот успеа!',
+       'importhistoryconflict'         =>      'Постои ревизија од историјата, која противречи со оваа (можно е страницата веќе да вила внесена)',
+
+       'accesskey-search'              =>      'f',
+       'accesskey-minoredit'           =>      'i',
+       'accesskey-save'                =>      's',
+       'accesskey-preview'             =>      'p',
+       'accesskey-diff'                =>      'd',
+       'accesskey-compareselectedversions'     =>      'v',
+
+       'tooltip-search'                =>      'Пребарај на вики [alt-f]',
+       'tooltip-minoredit'             =>      'Обележи ја промената како ситна [alt-i]',
+       'tooltip-save'                  =>      'Зачувај ги твоите промени [alt-s]',
+       'tooltip-preview'               =>      'Прегледај ги твоите промени, ве молиме користете го ова пред зачувување! [alt-p]',
+       'tooltip-diff'                  =>      'Покажи кои промени ги направи во текстот. [alt-d]',
+       'tooltip-compareselectedversions'       =>      'Видете ги разликите меѓу двете избрани верзии на страницата. [alt-v]',
+       'tooltip-watch'                 =>      'Додај ја оваа страница во набљудувани страници [alt-w]',
+
+       'Monobook.css'                  =>      '/* преку уредување на оваа датотека можете да ја прилагодите Monobook маската за целиот сајт */',
+
+       'nodublincore'                  =>      'Dublin Core RDF metadata disabled for this server.',
+       'nocreativecommons'                     =>      'Creative Commons RDF metadata disabled for this server.',
+       'notacceptable'                 =>      'The wiki server can\'t provide data in a format your client can read.',
+
+       'anonymous'                     =>      "Анонимен корисник од {{SITENAME}}",
+       'siteuser'                      =>      "корисник на {{SITENAME}} $1",
+       'lastmodifiedby'                =>      "Оваа страница последен пат беше променета $1 од $2.",
+       'and'                           =>      'и',
+       'othercontribs'                 =>      "Засновано на делото на $1.",
+       'others'                        =>      'други',
+       'siteusers'                     =>      "корисници на {{SITENAME}} $1",
+       'creditspage'                   =>      'Библиографија и извори',
+       'nocredits'                     =>      'Не постојат библиографија и извори за оваа страница.',
+
+       'spamprotectiontitle'           =>      'Филтер за заштита од спам',
+       'spamprotectiontext'            =>      'Страницата која сакавте да ја зачувате беше блокирана од филтерот за спам. Ова најверојатно е предизвикано од врска кон надворешен сајт.',
+       'spamprotectionmatch'           =>      'Следниот текст е она што го предизвика нашиот филтер за спам: $1',
+       'subcategorycount'              =>      "Постојат $1 подкатегории во оваа категорија.",
+       'subcategorycount1'             =>      "Постои $1 подкатегорија во оваа категорија.",
+       'categoryarticlecount'          =>      "Постојат $1 статии во оваа категорија.",
+       'categoryarticlecount1'         =>      "Постои $1 статија во оваа категорија.",
+       'usenewcategorypage'            =>      "1\n\nSet first character to \"0\" to disable the new category page layout.",
+       'listingcontinuesabbrev'        =>      " продолжи",
+
+       'infosubtitle'                  =>      'Информација за страницата',
+       'numedits'                      =>      'Број на уредувања (статија): $1',
+       'numtalkedits'                  =>      'Број на уредувања (страница за разговор): $1',
+       'numwatchers'                   =>      'Број на набљудувачи: $1',
+       'numauthors'                    =>      'Број на различни автори (статија): $1',
+       'numtalkauthors'                =>      'Број на различни автори (страница за разговор): $1',
+
+       'mw_math_png'                   =>      'Секогаш исцртувај во PNG',
+       'mw_math_simple'                =>      'HTML ако е многу едноставно ако не во PNG',
+       'mw_math_html'                  =>      'HTML ако е можно ако не PNG',
+       'mw_math_source'                =>      'Остави го како TeX (за теx прелистувачите)',
+       'mw_math_modern'                =>      'Препорачливо за современи прелистувачи',
+       'mw_math_mathml'                =>      'MathML ако е можно (експериментално)',
+
+       'markaspatrolleddiff'           =>      "Означи како проверена ревизија",
+       'markaspatrolledlink'           =>      "[$1]",
+       'markaspatrolledtext'           =>      "Означи ја ревизијата како проверена",
+       'markedaspatrolled'             =>      "Проверена ревизија",
+       'markedaspatrolledtext'         =>      "Избраната ревизија е означена како проверена.",
+       'rcpatroldisabled'              =>      "Патролирањето е деактивирано",
+       'rcpatroldisabledtext'          =>      "Патролирањето на Скорешните промени е деактивирано.",
+
+'Monobook.js'                  =>      '/* tooltips and access keys */
+ta = new Object();
+ta[\'pt-userpage\'] = new Array(\'.\',\'Мојата корисничка страница\');
+ta[\'pt-anonuserpage\'] = new Array(\'.\',\'Корисничка страница за IP адресата од која уредувате\');
+ta[\'pt-mytalk\'] = new Array(\'n\',\'Мојата страница за разговор \');
+ta[\'pt-anontalk\'] = new Array(\'n\',\'Разговор за уредувањата од оваа IP адреса\');
+ta[\'pt-preferences\'] = new Array(\'\',\'Мои прилагодувања\');
+ta[\'pt-watchlist\'] = new Array(\'l\',\'Листа на страници кои сте избрале да ги набљудувате.\');
+ta[\'pt-mycontris\'] = new Array(\'y\',\'Листа на моите придонеси\');
+ta[\'pt-login\'] = new Array(\'o\',\'Ве охрабруваме да се најавите, иако тоа не е задолжително.\');
+ta[\'pt-anonlogin\'] = new Array(\'o\',\'Ве охрабруваме да се најавите, иако тоа не е задолжително.\');
+ta[\'pt-logout\'] = new Array(\'o\',\'Одјавете се\');
+ta[\'ca-talk\'] = new Array(\'t\',\'Разговор за страницата\');
+ta[\'ca-edit\'] = new Array(\'e\',\'Можете да ја уредите оваа страница. Ве молиме користете го копчето за преглед пред зачувување.\');
+ta[\'ca-addsection\'] = new Array(\'+\',\'Додадете коментар во овој разговор.\');
+ta[\'ca-viewsource\'] = new Array(\'e\',\'Оваа страница е заштитена. Можете да го видите изворниот код.\');
+ta[\'ca-history\'] = new Array(\'h\',\'Претходни верзии на оваа страница.\');
+ta[\'ca-protect\'] = new Array(\'=\',\'Заштитете ја оваа страница\');
+ta[\'ca-delete\'] = new Array(\'d\',\'Избришете ја оваа страница\');
+ta[\'ca-undelete\'] = new Array(\'d\',\'Обновете ги уредувањата направени на оваа страница што постоеле пред да биде избришана\');
+ta[\'ca-move\'] = new Array(\'m\',\'Преместете ја оваа страница\');
+ta[\'ca-watch\'] = new Array(\'w\',\'Додајте ја оваа страница во набљудувани страници\');
+ta[\'ca-unwatch\'] = new Array(\'w\',\'Отстранете ја оваа страница од набљудувани страници\');
+ta[\'search\'] = new Array(\'f\',\'Пребарајте го викито\');
+ta[\'p-logo\'] = new Array(\'\',\'Почетна страна\');
+ta[\'n-mainpage\'] = new Array(\'z\',\'Посетете ја почетната страна\');
+ta[\'n-portal\'] = new Array(\'\',\'За проектот, што можете да направите, каде да најдете некои работи\');
+ta[\'n-currentevents\'] = new Array(\'\',\'Најдете информации за тековните настани\');
+ta[\'n-recentchanges\'] = new Array(\'r\',\'Листа на скорешни промени на викито.\');
+ta[\'n-randompage\'] = new Array(\'x\',\'Случајна страница\');
+ta[\'n-help\'] = new Array(\'\',\'Место каде што може да дознаете.\');
+ta[\'n-sitesupport\'] = new Array(\'\',\'Поддржете ја Википедија\');
+ta[\'t-whatlinkshere\'] = new Array(\'j\',\'Листа на сите вики страници поврзани овде\');
+ta[\'t-recentchangeslinked\'] = new Array(\'k\',\'Скорешни промени поврзани од оваа страница\');
+ta[\'feed-rss\'] = new Array(\'\',\'RSS feed за страницата\');
+ta[\'feed-atom\'] = new Array(\'\',\'Atom feed за страницата\');
+ta[\'t-contributions\'] = new Array(\'\',\'Видете ја листата на придонеси на овој корисник\');
+ta[\'t-emailuser\'] = new Array(\'\',\'Пратете е-пошта на овој корисник\');
+ta[\'t-upload\'] = new Array(\'u\',\'Подигнете слики или медија датотеки\');
+ta[\'t-specialpages\'] = new Array(\'q\',\'Листа на сите специјални страници\');
+ta[\'ca-nstab-main\'] = new Array(\'c\',\'Видете ја основната страница\');
+ta[\'ca-nstab-user\'] = new Array(\'c\',\'Видете ја корисничката страница\');
+ta[\'ca-nstab-media\'] = new Array(\'c\',\'Видете ја медија страницата\');
+ta[\'ca-nstab-special\'] = new Array(\'\',\'Ова е специјална страница, не можете да ја уредувате оваа страница.\');
+ta[\'ca-nstab-wp\'] = new Array(\'a\',\'Видете ја проектната страница\');
+ta[\'ca-nstab-image\'] = new Array(\'c\',\'Видете ја страницата на сликата\');
+ta[\'ca-nstab-mediawiki\'] = new Array(\'c\',\'Видете ја системската порака\');
+ta[\'ca-nstab-template\'] = new Array(\'c\',\'Видете го шаблонот\');
+ta[\'ca-nstab-help\'] = new Array(\'c\',\'Видете ја помошната страница\');
+ta[\'ca-nstab-category\'] = new Array(\'c\',\'Видете ја страницата со категории\');
+',
+
+       'deletedrevision'               =>      'Избришана стара ревизија $1.',
+       'previousdiff'                  =>      '← Претходна разлика',
+       'nextdiff'                      =>      'Следна разлика →',
+       'imagemaxsize'                  =>      'Ограничи ги сликите на нивните описни страници до: ',
+       'thumbsize'                     =>      'Thumbnail големина : ',
+       'showbigimage'                  =>      'Преземете ја верзијата со висока резолуција ($1x$2, $3 KB)',
+       'newimages'                     =>      'Галерија на нови слики',
+       'noimages'                      =>      'Нема ништо.',
+       'specialloguserlabel'           =>      'Корисник: ',
+       'speciallogtitlelabel'          =>      'Наслов: ',
+       'passwordtooshort'              =>      'Вашата лозинка е прекратка. Мора да има најмалку $1 знаци.',
+
+       'mediawarning'                  =>      '\'\'\'Предупредување\'\'\': This file may contain malicious code, by executing it your system may be compromised. <hr>',
+       'fileinfo'                      =>      '$1KB, MIME type: <code>$2</code>',
+
+       'metadata'                      =>      'Метаподатоци',
+
+       'edit-externally'                       =>      'Уредете ја оваа датотека со надворешна апликација',
+       'edit-externally-help'                  =>      'Видете [http://meta.wikimedia.org/wiki/Help:External_editors setup instructions] за повеќе информации.',
+
+       'recentchangesall'                      =>      'сите',
+       'imagelistall'                          =>      'сите',
+       'watchlistall1'                         =>      'сите',
+       'watchlistall2'                         =>      'сите',
+       'namespacesall'                 =>      'сите',
+);
+
+
+require_once( 'LanguageUtf8.php' );
+
+class LanguageMk extends LanguageUtf8 {
+       /**
+        * Exports $wgNamespaceNamesMk
+        * @return array
+        */
+       function getNamespaces() {
+               global $wgNamespaceNamesMk;
+               return $wgNamespaceNamesMk;
+       }
+
+       /**
+        * Exports $wgQuickbarSettingsMk
+        * @return array
+        */
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsMk;
+               return $wgQuickbarSettingsMk;
+       }
+
+       /**
+        * Exports $wgSkinNamesMk
+        * @return array
+        */
+       function getSkinNames() {
+               global $wgSkinNamesMk;
+               return $wgSkinNamesMk;
+       }
+
+       /**
+        * Exports $wgValidationTypesMk
+        * @return array
+        */
+       function getValidationTypes() {
+               global $wgValidationTypesMk;
+               return $wgValidationTypesMk;
+       }
+
+       /**
+        * Exports $wgDateFormatsMk
+        * @return array
+        */
+       function getDateFormats() {
+               global $wgDateFormatsMk;
+               return $wgDateFormatsMk;
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesMk;
+               if ( isset( $wgAllMessagesMk[$key] ) ) {
+                       return $wgAllMessagesMk[$key];
+               } else {
+                       return parent::getMessage( $key );
+               }
+       }
+
+       /**
+        * Exports $wgMagicWordsMk
+        * @return array
+        */
+       function getMagicWords() {
+               global $wgMagicWordsMk;
+               return $wgMagicWordsMk;
+       }
+}
+?>
diff --git a/languages/LanguageMl.php b/languages/LanguageMl.php
new file mode 100644 (file)
index 0000000..edf8df3
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+/** Malayalam (മലയാളം)
+  *
+  * @package MediaWiki
+  * @subpackage Language
+  *
+  * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
+  */
+
+require_once( 'LanguageUtf8.php' );
+
+class LanguageMl extends LanguageUtf8 {
+       var $digitTransTable = array(
+               '0' => '൦',
+               '1' => '൧',
+               '2' => '൨',
+               '3' => '൩',
+               '4' => '൪',
+               '5' => '൫',
+               '6' => '൬',
+               '7' => '൭',
+               '8' => '൮',
+               '9' => '൯'
+       );
+
+       function formatNum( $number ) {
+               global $wgTranslateNumerals;
+               if( $wgTranslateNumerals ) {
+                       return strtr( $number, $this->digitTransTable );
+               } else {
+                       return $number;
+               }
+       }
+}
+
+?>
diff --git a/languages/LanguageMs.php b/languages/LanguageMs.php
new file mode 100644 (file)
index 0000000..ec103e0
--- /dev/null
@@ -0,0 +1,860 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+# This localisation is based on a file kindly donated by the folks at MIMOS
+# http://www.asiaosc.org/enwiki/page/Knowledgebase_Home.html
+
+/* private */ $wgNamespaceNamesMs = array(
+       NS_MEDIA          => "Media",
+       NS_SPECIAL        => "Istimewa", #Special
+       NS_MAIN           => "",
+       NS_TALK           => "Perbualan",#Talk
+       NS_USER           => "Pengguna",#User
+       NS_USER_TALK      => "Perbualan_Pengguna",#User_talk
+       NS_PROJECT        => "Wikipedia",#Wikipedia
+       NS_PROJECT_TALK   => "Perbualan_Wikipedia",#Wikipedia_talk
+       NS_IMAGE          => "Imej",#Image
+       NS_IMAGE_TALK     => "Imej_Perbualan",#Image_talk
+       NS_MEDIAWIKI      => "MediaWiki",
+       NS_MEDIAWIKI_TALK => "MediaWiki_Perbualan",
+       NS_TEMPLATE       => "Template",
+       NS_TEMPLATE_TALK  => "Template_talk"
+
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgQuickbarSettingsMs = array(
+       "Tiada", "Tetap sebelah kiri", "Tetap sebelah kanan", "Berubah-ubah sebelah kiri"
+);
+
+/* private */ $wgDateFormatsMs = array(
+#      "Tiada pilihan", # "No preference",
+);
+
+/* private */ $wgAllMessagesMs = array(
+
+# User Toggles
+
+"tog-underline" => "Pautan bergaris", #"Underline links",
+"tog-highlightbroken" => "Pautan bertanda ke topik kosong",
+#TODO: <a href=\"\" class=\"new\">like this</a> (alternative: like this<a href=\"\" class=\"internal\">?</a>)
+"tog-justify"  => "Justifikasikan perenggan", #"Justify paragraphs",
+"tog-hideminor" => "Sembunyi perubahan minor dalam perubahan terkini", #"Hide minor edits in recent changes",
+"tog-usenewrc" => "Peningkatan terbaru (bukan untuk semua pelayar)",
+"tog-numberheadings" => "Auto-number headings",
+"tog-showtoolbar" => "Show edit toolbar",
+"tog-editsection"=>"Papar pautan untuk sunting seksyen individu",
+"tog-showtoc"=>"Papar jadual kandungan bagi rencana melebihi 3 tajuk",# "Show table of contents for articles with more than 3 headings",
+"tog-rememberpassword" => "Ingat kata laluan bagi setiap sessi", #"Remember password across sessions",
+"tog-editwidth" => "Kotak sunting telah lebar", #"Edit box has full width",
+"tog-editondblclick" => "Sunting halaman dengan klik berganda (JavaScript)", #"Edit pages on double click (JavaScript)"
+"tog-watchdefault" => "Tambah halaman yang anda sunting pada senarai perhati",# "Add pages you edit to your watchlist",
+"tog-minordefault" => "Tanda semua suntingan ringkas secara ingkar",# "Mark all edits minor by default"
+"tog-previewontop" => "Papar pratonton sebelum kotak sunting dan bukan selepasnya", #Show preview before edit box and not after it",
+"tog-nocache" => "Matikan simpanan laman",
+
+# Dates
+
+'sunday' => 'Ahad',
+'monday' => 'Isnin',
+'tuesday' => 'Selasa',
+'wednesday' => 'Rabu',
+'thursday' => 'Khamis',
+'friday' => 'Jumaat',
+'saturday' => 'Sabtu',
+'january' => 'Januari',
+'february' => 'Februari',
+'march' => 'Mac',
+'april' => 'April',
+'may_long' => 'Mei',
+'june' => 'Jun',
+'july' => 'Julai',
+'august' => 'Ogos',
+'september' => 'September',
+'october' => 'Oktober',
+'november' => 'November',
+'december' => 'Disember',
+'jan' => 'Jan',
+'feb' => 'Feb',
+'mar' => 'Mac',
+'apr' => 'Apr',
+'may' => 'May',
+'jun' => 'Jun',
+'jul' => 'Jul',
+'aug' => 'Aug',
+'sep' => 'Sep',
+'oct' => 'Okt',
+'nov' => 'Nov',
+'dec' => 'Dis',
+
+
+# Bits of text used by many pages:
+#
+"linktrail"            => "/^([a-z]+)(.*)\$/sD",
+"mainpage"             => "Laman Utama Pangkalan Pengetahuan", #"Knowledgebase Home",
+"mainpagetext"         => "Aturcara Wiki berjaya dipasang.",
+"about"                        => "Maklumat",
+"aboutsite"             => "Maklumat Wikipedia",
+"aboutpage"            => "Wikipedia:Perihal", #"Wikipedia:About",
+"help"                 => "Bantuan",
+"helppage"             => "Wikipedia:Bantuan",
+"bugreports"           => "Laporan Pepijat",
+"bugreportspage"        => "Wikipedia:Laporan Pepijat",
+"faq"                  => "FAQ",
+"faqpage"              => "Wikipedia:FAQ",
+"edithelp"             => "Menyunting bantuan",
+"edithelppage"         => "Wikipedia:Cara menyunting halaman",
+"cancel"               => "Batal",
+"qbfind"               => "Cari",
+"qbbrowse"             => "Baca sepintas lalu", #"Browse",
+"qbedit"               => "Sunting",
+"qbpageoptions"         => "Pilihan halaman",
+"qbpageinfo"           => "Maklumat halaman",
+"qbmyoptions"          => "Pilihan saya",
+"mypage"               => "Halaman saya",
+"mytalk"               => "Perbualan saya",
+"currentevents"         => "Status Terkini",
+"errorpagetitle"        => "Ralat",
+"returnto"             => "Kembali ke $1.", #"Return to $1.",
+"tagline"                      => "Dari Wikipedia, ensaiklopedia bebas", # "From Wikipedia, the free encylcopedia
+"whatlinkshere"                => "Halaman yang dihubungkan ke sini", #"Pages that link here",
+"help"                 => "Bantuan",
+"search"               => "Cari",
+"go"                   => "Pergi",
+"history"              => "Versi terdahulu",
+"printableversion"      => "Versi untuk dicetak",
+"editthispage"         => "Sunting halaman ini",
+"deletethispage"        => "Buang halaman ini", #"Delete this page",
+"protectthispage"       => "Lindungi halaman ini", #"Protect this page",
+"unprotectthispage"     => "Nyah lindung halaman ini", #"Unprotect this page",
+"newpage"               => "(cipta) Halaman baru", # (create) "New page"
+"talkpage"             => "Bincang halaman ini",
+"articlepage"          => "Lihat rencana",# "View article",
+"subjectpage"          => "Halaman subjek",
+"userpage"              => "Lihat laman pengguna",# "View user page",
+"wikipediapage"         => "Lihat laman meta",# "View meta page",
+"imagepage"             => "Papar halaman imej",
+"viewtalkpage"          => "Lihat perbincangan",# "View discussion",
+"otherlanguages"        => "Lain-lain bahasa",
+"redirectedfrom"        => "(Dialih dari $1)", #"(Redirected from $1)",
+"lastmodified"         => "Halaman ini diubah kali terakhir pada $1.", #"The page was last modified $1.",
+"viewcount"            => "Halaman ini telah diakses sebanyak $1 kali.", #"This page has been accessed $1 times.",
+"printsubtitle"         => "(From {{SERVER}})",
+"protectedpage"         => "Halaman yang dilindungi", #"Protected page",
+"administrators"        => "Istimewa:Listadministrators", #"Special:Listadministrators",
+"sysoptitle"           => "Kemasukan sysop diperlukan", #"Sysop access required",
+"sysoptext"            => "Hanya <a href=\"" .
+  "{{localurle:Istimewa:Listadministrators}}\">Sistem Pentadbir</a>
+yang boleh melakukannya.", #"Only the <a href=\"{{localurle:Special:Listadministrators}}\">administrators</a>can do that.",
+"developertitle"        => "Kemasukan pembangun diperlukan", # "Developer access required",
+"developertext"                => "Tindakan/arahan yg di minta/diperlukanhanya boleh di tunjukan oleh pengguna dengan status \"developer\".
+Lihat $1.", # "The action you have requested can only be performed by users with \"developer\" status.See $1.",
+"nbytes"               => "$1 bait",
+"go"                   => "Pergi",
+"ok"                   => "OK",
+"sitetitle"            => "Wikipedia",
+"sitesubtitle"         => "Ensaiklopedia Bebas",
+"retrievedfrom"         => "Diperolehi daripada \"$1\"", #"Retrieved from \"$1\"",
+"newmessages"           => "Anda ada $1.",
+"newmessageslink"       => "pesanan baru",
+"editsection"           =>"sunting",
+"toc"                   => "Jadual kandungan",
+"showtoc"               => "tunjuk",
+"hidetoc"               => "sorok",
+
+# Main script and global functions
+#
+"nosuchaction"         => "Tiada tindakan tersebut", #"No such action",
+"nosuchactiontext"      => "Tindakan yang dispesifikasikan oleh URL tersebut tidak dikenalpasti oleh perisian Wikipedia.", #"The action specified by the URL is not recognized by the Wikipedia software",
+"nosuchspecialpage"     => "Tiada halaman istimewa tersebut", #"No such special page",
+"nospecialpagetext"     => "Anda telah meminta halaman istimewa yang tidak dikenalpasti oleh perisian Wikipedia.", #"You have requested a special page that is not recognized by the Wikipedia software.",
+
+# General errors        =>Ralat umum
+#
+"error"                        => "Ralat",
+"databaseerror"         => "Ralat pangkalan data", #"Database error",
+"dberrortext"          => "Berlaku ralat sintaksis pada permintaan pangkalan data.
+Percubaan terakhir permintaan pangkalan data ialah :
+<blockquote><tt>$1</tt></blockquote>
+from within function \"<tt>$2</tt>\".
+MySQL returned error \"<tt>$3: $4</tt>\".",
+"dberrortextcl"        => "Berlaku ralat sintaksis pada permintaan pangkalan data.
+Percubaan terakhir permintaan pangkalan data ialah :
+\"$1\"
+from within function \"$2\".
+MySQL returned error \"$3: $4\".\n",
+"noconnect"            => "Tidak dapat menghubungkan ke DB oleh $1", #"Could not connect to DB on $1",
+"nodb"                 => "Tidak dapat memilih pangkalan data $1", #"Could not select database $1",
+"readonly"             => "Pangkalan data dikunci", #"Database locked",
+"enterlockreason"       => "Masukan sebab/alasan untuk dikunci,
+termasuk anggaran apabila kunci telah di buka",
+"readonlytext"         => "Pangkalan data Wikipedia sedang di kunci kepada
+kemasukan baru.
+Pentadbir yang menutup
+memberikan penjelasan berikut:
+<p>$1",
+# "missingarticle" => "The database did not find the text of a page that it should have found, named \"$1\".
+# This is usually caused by following an outdated diff or history link to a page that has been deleted.
+"internalerror" => "Ralat dalaman", # Internal error",
+"filecopyerror" => "Tidak dapat menyalin fail \"$1\" kepada \"$2\".", #Could not copy file \"$1\" to \"$2\".",
+"filerenameerror" => "Tidak dapat menukar nama fail \"$1\" kepada \"$2\".", #Could not rename file \"$1\" to \"$2\".",
+"filedeleteerror" => "Tidak dapat memadamkan fail \"$1\".", #Could not delete file \"$1\".",
+"filenotfound" => "Tidak dapat mencari fail \"$1\".",  #Could not find file \"$1\".",
+"unexpected"   => "Nilai di luar jangkaan: \"$1\"=\"$2\".", # Unexpected value: \"$1\"=\"$2\".",
+"formerror"            => "Ralat: Tidak dapat  menghantar borang", #Error: could not submit form",
+"badarticleerror" => "Arahan ini tidak boleh dilaksanakan di halaman ini.", #This action cannot be performed on this page.",
+"cannotdelete" => "Tidak dapat menghilangkan halaman atau imej yang telah ditetapkan.",
+"badtitle"             => "Tajuk tidak sesuai", #Bad title",
+"badtitletext"         => "Tajuk halaman yang diminta tidak sah, kosong atau salah sambungan dengan antara-bahasa atau tajuk antara-wiki.", #The requested page title was invalid, empty, or an incorrectly linked inter-language or inter-wiki title.",
+"perfdisabled" => "Maaf! keupayaan ini dilumpuhkan seketika kerana ia melambatkan pengkalan data sehingga tidak dapat digunakan.", # "Sorry! This feature has been temporarily disabled because it slows the database down to the point that no one can use the wiki.",
+"perfdisabledsub"       => "Di sini merupakan salinan yang tersimpan di $1:", # "Here's a saved copy from $1:",
+
+# Login and logout pages
+#
+"logouttitle"  => "Pengguna Keluar", #User logout
+"logouttext"   => "Anda telah keluar dari sistem.
+Anda boleh terus membaca maklumat, tetapi tidak boleh mengemaskininya atau anda boleh masuk semula sebagai pengguna yang sama atau pengguna berbeza.\n",
+
+"welcomecreation" => "<h2>Selamat datang, $1!</h2><p>Akaun anda telah dibuka.
+Sila kemaskini konfigurasi butir-butir diri anda.", #"<h2>Welcome, $1!</h2><p>Your account has been created.Don't forget to personalize your preferences.",
+
+"loginpagetitle" => "Pengguna Masuk", #User login
+"yourname"      => "Nama Pengguna", #Your user name",
+"yourpassword"  => "Kata Laluan", #Your password",
+"yourpasswordagain" => "Ulang Kata Laluan", #Retype password",
+"newusersonly"  => "(Hanya pengguna baru)", # (new users only)",
+"remembermypassword" => "Sentiasa ingatan kata laluan.", # Remember my password across sessions.",
+"loginproblem" => "<b>Terdapat masalah dengan data kemasukan.</b><br />Cuba semula!", # There has been a problem with your login.</b><br />Try again!",
+"alreadyloggedin" => "<strong>Pengguna $1, anda telah berjaya masuk!</strong><br />\n",
+
+"login"                        => "Masuk", #Log in
+"userlogin"            => "Laluan masuk", #Log in
+"logout"               => "Keluar",
+"userlogout"   => "Laluan Keluar", #Log out
+"notloggedin"  => "Not logged in",
+"createaccount"        => "Buka akaun baru", #Create new account",
+"badretype"            => "Kata laluan yang dimasukkan adalah salah.", #The passwords you entered do not match.",
+"userexists"   => "Nama pengguna yang dimasukkan telah digunakan.Sila gunakan nama lain.",
+"youremail"            => "Email anda", #Your e-mail",
+"yournick"             => "Nama samaran (untuk pengenalan)", #Your nickname (for signatures)",
+"emailforlost" => "Sekiranya terlupa kata laluan, anda boleh dapatkan
+yang baru yang akan
+diemail ke email
+anda.",
+"loginerror"   => "Salah masuk", #Login error",
+"noname"               => "Nama pengguna tidak sah.", #You have not specified a valid user name.",
+"loginsuccesstitle" => "Berjaya masuk",  #Login successful",
+"loginsuccess" => "Berjaya masuk dalam Wikipedia sebagai \"$1\".",  #You are now logged in to Wikipedia as \"$1\".",
+"nosuchuser"   => "Tiada pengguna seperti nama \"$1\". #There is no user by the name \"$1\".
+Periksa ejaan, atau guna borang di bawah untuk membuka akaun baru.",
+"wrongpassword"        => "Kata laluan yang dimasukan adalah salah.Sila cuba semula.",
+"mailmypassword" => "Emailkan kata laluan baru", #Mail me a new password",
+"passwordremindertitle" => "Peringatan kata laluan dari Wikipedia", #Password reminder from Wikipedia",
+"passwordremindertext" => "Seseorang (mungkin anda, dari alamat IP $1) #IP  Someone (probably you, from IP address $1)
+meminta di hantar kata laluan Wikipedia yang baru.#requested that we send you a new Wikipedia login password.
+Kata laluan untuk pengguna \"$2\" ialah \"$3\". #The password for user \"$2\" is now \"$3\".
+Anda perlu masuk semula dan tukar kata laluan dengan segera.",  #You should log in and change your password now.",
+"noemail"              => "Tiada alamat email yang direkodkan untuk pengguna \"$1\".",
+"passwordsent" => "Kata laluan baru telah di emailkan kepada email yang
+didaftarkan untuk \"$1\".
+Sila masuk setelah menerima email tersebut.", #Please log in again after you receive it.",
+
+# Edit pages
+#
+"summary"              => "Ringkasan", #"Summary",
+"minoredit"            => "Hanya sedikit pengemaskinian dilakukan.","This is a minor edit.",
+"watchthis"            => "Watch this article",
+"savearticle"  => "Simpan", #"Save page",
+"preview"              => "Papar", #"Preview",
+"showpreview"  => "Tunjuk Paparan", #"Show preview",
+"blockedtitle" => "Pengguna diblok", #"User is blocked",
+"blockedtext"  => "Kata nama anda atau alamat IP telah diblok oleh $1.
+Alasannya kerana :<br />$2<p>Anda boleh menghubungi sistem admin untuk
+membincangkan sebab-sebabnya.",
+"newarticle"   => "(Baru)", #"(New)",
+"newarticletext" =>
+"Letakkan teks anda
+di sini
+untuk
+halaman baru.",
+"anontalkpagetext" => "---- ''This is the discussion page for an anonymous user who has not created an account yet or who does not use it. We therefore have to use the numerical [[IP address]] to identify him/her. Such an IP address can be shared by several users. If you are an anonymous user and feel that irrelevant comments have been directed at you, please [[Special:Userlogin|create an account or log in]] to avoid future confusion with other anonymous users.'' ",
+"noarticletext" => "(Tidak ada teks dalam halaman ini)",
+"updated"              => "(Dikemaskini)", #"(Updated)",
+"note"                 => "<strong>Nota:</strong> ",
+"previewnote"  => "Ingatan bahawa ini hanyalah paparan, belum disimpan lagi!", #"Remember that this is only a preview, and has not yet been saved!",
+"previewconflict" => "Paparan ini ada kaitan dengan teks pada bahagian atas dan
+akan terpapar apabila anda memilih untuk menyimpannya.",
+"editing"              => "Menyunting $1", #"Editing $1",
+"editingsection"       => "Menyunting $1 (section)",
+"editingcomment"       => "Menyunting $1 (comment)",
+"editconflict" => "Sunting konflik", #"Edit conflict: $1",
+"explainconflict" => "Orang lain telah mengemaskini halaman ini sejak anda
+mula mengemaskininya.
+Bahagian atas teks mengandungi halaman teks yang terkini.
+Perubahan yang anda lakukan akan ditunjukkan pada bahagian bawah teks.
+Anda hanya perlu mencantumkan perubahan-perubahan dalam teks.
+<b>Hanya</b> teks pada bahagian atas akan hanya disimpan apabila anda
+menekan \"Simpan halaman\".<br />",
+"yourtext"             => "Teks anda", #"Your text",
+"storedversion" => "Simpan versi", #"Stored version",
+"editingold"   => "<strong>AMARAN: Anda mengemaskini halaman revisi yang ketinggalan tarikh.
+Jika anda menyimpannya,
+sebarang perubahan yang dibuat sejak revisi ini akan hilang.</strong>",
+"yourdiff"             => "Perbezaan", #"Differences",
+"copyrightwarning" => "Semua sumbangan terhadap Wikipedia adalah
+tertakluk di bawah GNU Free Documentation License
+(lihat $1 untuk maklumat lebih lanjut).
+Jika anda tidak mahu tulisan anda disunting dan/atau disebarkan ke halaman
+web percuma yang lain, jangan hantarnya ke sini.
+Anda juga perlu akui bahawa ini adalah hasil tulisan anda sendiri, atau anda
+menyalinnya daripada domain awam atau mana-mana sumber percuma yang sama.
+<p><strong>JANGAN HANTAR SEBARANG KARYA HAK CIPTA ORANG LAIN TANPA KEBENARAN.</strong></p> <p><strong>JANGAN SALIN DARIPADA HALAMAN WEB YANG LAIN.</strong></p> ",
+"longpagewarning" => "<strong>WARNING: This page is $1 kilobytes long; some
+browsers may have problems editing pages approaching or longer than 32kb.
+Please consider breaking the page into smaller sections.</strong>",
+"readonlywarning" => "<strong>WARNING: The database has been locked for maintenance,
+so you will not be able to save your edits right now. You may wish to cut-n-paste
+the text into a text file and save it for later.</strong>",
+"protectedpagewarning" => "<strong>WARNING:  This page has been locked so that only
+users with sysop privileges can edit it. Be sure you are following the
+[[Project:Protected_page_guidelines|protected page guidelines]].</strong>",
+
+# History pages
+#
+"revhistory"   => "Sejarah revisi", #"Revision history",
+"nohistory"            => "Tidak ada sejarah kemaskini untuk halaman ini", #"There is no edit history for this page.",
+"revnotfound"  => "Revisi tidak dijumpai", #"Revision not found",
+"revnotfoundtext" => "Revisi lama untuk halaman ini yang anda minta tidak dapat dijumpai.
+Sila semak URL yang digunakan untuk mengakses halaman ini.\n", #"The old revision of the page you asked for could not be found. Please check the URL you used to access this page.\n",
+"loadhist"             => "Muatturun halaman sejarah", #"Loading page history",
+"currentrev"   => "Revisi terkini", #"Current revision",
+"revisionasof" => "Revisi sebagai $1", #"Revision as of $1",
+"cur"                  => "cur",
+"next"                 => "next",
+"last"                 => "last",
+"orig"                 => "orig",
+"histlegend"   => "Lagenda: (cur) = perbezaan dengan versi terkini,
+(last) = perbezaan dengan versi terdahulu", #"Legend: (cur) = difference with current version,(last) = difference with preceding version",
+
+# Diffs
+#
+"difference"   => "Perbezaan antara revisi", #"(Difference between revisions)",
+"loadingrev"   => "muatturun revisi diff", #"loading revision for diff",
+"lineno"               => "Baris $1:", #"Line $1:",
+"editcurrent"  => "Sunting versi terkini untuk halaman ini", #"Edit the current version of this page",
+
+# Search results
+#
+"searchresults" => "Hasil Carian",
+"searchresulttext" => "Untuk maklumat lanjut tentang carian dalam {{SITENAME}}, lihat [[Project:Carian|Carian Dalam {{SITENAME}}]].", "searchquery"    => "Untuk kueri \"$1\"", #"For query \"$1\"",
+"badquery"             => "Format kueri carian salah", #"Badly formed search query",
+"badquerytext" => "Kami tidak dapat memproses kueri anda.
+Ini mungkin disebabkan anda cuba mencari perkataan yang kurang
+daripada tiga huruf, yang mana masih belum disokong oleh sistem ini.
+Ataupun anda tersalah taip ekspresi untuk kueri,
+contohnya \"fish and and scales\".
+Sila cuba kueri yang lain.",
+"matchtotals"  => "Kueri \"$1\" sepadan dengan tajuk halaman $2 dan teks
+halaman $3.", #"The query \"$1\" matched $2 page titles and the text of $3 pages.",
+"nogomatch" => "No page with this exact title exists, trying full text search.",
+"titlematches" => "Tajuk artikel yang sepadan", #"Article title matches",
+"notitlematches" => "Tiada tajuk halaman yang sepadan", #"No page title matches",
+"textmatches"  => "Teks artikel yang sepadan", #"Article text matches",
+"notextmatches"        => "Tiada teks halaman yang sepadan", #No page text matches",
+"prevn"                        => "sebelum $1", #"previous $1",
+"nextn"                        => "selepas $1", #"next $1",
+"viewprevnext" => "Papar ($1) ($2) ($3).", #"View ($1) ($2) ($3).",
+"showingresults" => "Di bawah menunjukkan <b>$1</b> hasil carian bermula dengan #<b>$2</b>.", #"Showing below <b>$1</b> results starting with #<b>$2</b>.",
+"showingresultsnum" => "Di bawah menunjukkan <b>$3</b> hasil carian bermula dengan #<b>$2</b>.", #"Showing below <b>$3</b> results starting with #<b>$2</b>.",
+"nonefound"            => "<strong>Nota</strong>:Kegagalan enjin carian
+biasanya disebabkan pencarian perkataan seperti \"have\" and \"from\",
+yang mana bukan dalam senarai indeks atau dengan dikhususkan lebih dari
+satu istilah carian(hanya halaman).", # "<strong>Note</strong>: unsuccessful searches are often caused by searching for common words like \"have\" and \"from\",which are not indexed, or by specifying more than one search term (only pages containing all of the search terms will appear in the result).",
+"powersearch" => "Cari", #"Search",
+"powersearchtext" => "
+Search in namespaces :<br />
+$1<br />
+$2 List redirects &nbsp; Search for $3 $9",
+
+
+# Preferences page
+#
+"preferences"  => "Konfigurasi", #"Preferences",
+"prefsnologin" => "Belum mendaftar masuk", #"Not logged in",
+"prefsnologintext"     => "Anda mesti [[Istimewa:Userlogin|mendaftar masuk]]
+untuk tetapkan butir-butir diri anda.", #"You must be <a href=\"" .
+"prefslogintext" => "Anda telah masuk sebagai \"$1\".
+Nombor ID anda ialah $2.",
+
+
+"prefsreset"   => "Konfigurasi telah diubah ke asal dari storan", #"Preferences have been reset from storage.",
+"qbsettings"   => "Konfigurasi quickbar", #"Quickbar settings",
+"changepassword" => "Tukar kata laluan", #"Change password",
+"skin"                 => "Skin",
+"math"                 => "Rendering math",
+"dateformat"   => "Date format",
+"math_failure"         => "Failed to parse",
+"math_unknown_error"   => "unknown error",
+"math_unknown_function"        => "unknown function ",
+"math_lexing_error"    => "lexing error",
+"math_syntax_error"    => "syntax error",
+"saveprefs"            => "Simpan konfigurasi", #"Save preferences",
+"resetprefs"   => "Ubah konfigurasi ke asal", #"Reset preferences",
+"oldpassword"  => "Kata laluan lama", #"Old password",
+"newpassword"  => "Kata laluan baru", #"New password",
+"retypenew"            => "Taip semula kata laluan baru", #"Retype new password",
+"textboxsize"  => "Dimensi kotak teks", #"Editing",
+"rows"                 => "Baris", #"Rows",
+"columns"              => "Lajur", #"Columns",
+"searchresultshead" => "Konfigurasi hasil carian", #"Search result settings",
+"resultsperpage" => "Bilangan capaian untuk satu halaman", #"Hits to show per page",
+"contextlines" => "Bilangan baris untuk satu capaian", #"Lines to show per hit",
+"contextchars" => "Bilangan aksara konteks untuk satu baris", #"Characters of context per line",
+"stubthreshold" => "Threshold for stub display",
+"recentchangescount" => "Bilangan tajuk dalam perubahan terkini", #"Number of titles in recent changes",
+"savedprefs"   => "Konfigurasi butir-butir diri anda telah disimpan", #"Your preferences have been saved.",
+"timezonetext" => "Masukkan perbezaan jam antara waktu
+tempatan anda dengan waktu pelayan (UTC).", #"Enter number of hours your local time differs from server time (Kuala Lumpur, which is GMT+8).",
+"localtime"    => "Waktu tempatan", #"Local time",
+"timezoneoffset" => "Imbang", #"Offset",
+"servertime"   => "Server time is now",
+"guesstimezone" => "Fill in from browser",
+"emailflag"            => "Halang e-mail daripada pengguna lain", #"Disable e-mail from other users",
+"defaultns"            => "Search in these namespaces by default:",
+
+# Recent changes
+#
+"changes" => "perubahan",
+"recentchanges" => "Perubahan Terkini",
+"recentchangestext" => "Kenalpasti perubahan terkini dalam Wikipedia di halaman ini.
+[[Wikipedia:Selamat datang,_pengguna baru|Selamat datang, pengguna baru]]!
+Sila lihat halaman-halaman ini: [[Wikipedia:FAQ|Wikipedia FAQ]],
+[[Wikipedia:Polisi dan garis panduan|Polisi Wikipedia]]
+(terutamanya [[Wikipedia:Konvensyen penamaan|konvensyen penamaan]],
+[[Wikipedia:Pandangan semulajadi|pandangan semulajadi]]),
+dan [[Wikipedia: Kesalahan biasa Wikipedia|kesalahan biasa Wikipedia]].
+
+Jika anda mahu melihat Wikipedia berjaya, adalah sangat penting anda
+tidak memasukkan material [[Wikipedia:Hak cipta|hak cipta]] orang lain.
+Perkara ini boleh memusnahkan laman web ini,
+jadi sila patuhi amaran ini.",
+"rcloaderr"            => "Muatturun perubahan terkini", #"Loading recent changes",
+"rcnote"               => "Di bawah adalah <strong>$1</strong> kemaskini terakhir dalam <strong>$2</strong> hari lepas.", #"Below are the last <strong>$1</strong> changes in last <strong>$2</strong> days.",
+"rcnotefrom"   => "Below are the changes since <b>$2</b> (up to <b>$1</b> shown).",
+"rclistfrom"   => "Show new changes starting from $1",
+# "rclinks"            => "Show last $1 changes in last $2 hours / last $3 days",
+# "rclinks"            => "Show last $1 changes in last $2 days.",
+"rclinks"              => "Tunjuk $1 kemaskini terakhir dalam $2 hari lepas.", #"Show last $1 changes in last $2 days.",
+"rchide"               => "dalam $4 bentuk; $1 perubahan kecil; $2 ruang nama kedua; $3 perubahan berganda.",  #"in $4 form; $1 minor edits; $2 secondary namespaces; $3 multiple edits.",
+"rcliu"                        => "; $1 edits from logged in users",
+"diff"                 => "diff",
+"hist"                 => "hist",
+"hide"                 => "hide",
+"show"                 => "show",
+"tableform"            => "table",
+"listform"             => "list",
+"nchanges"             => "$1 changes",
+"minoreditletter" => "m",
+"newpageletter" => "B",
+
+# Upload
+#
+"upload"               => "Muatnaik",
+"uploadbtn"            => "Muatnaik fail", #"Upload file",
+"uploadlink"   => "Muatnaik imej", #"Upload images",
+"reupload"             => "Muatnaik semula", #"Re-upload",
+"reuploaddesc" => "Kembali ke borang muatnaik", #"Return to the upload form.",
+"uploadnologin" => "Tidak mendaftar masuk", #"Not logged in",
+"uploadnologintext"    => "Anda mesti [[Istimewa:Userlogin|pengguna]]
+untuk muatnaik fail.",
+"uploaderror"  => "Muatnaik ralat", #"Upload error",
+"uploadlog"            => "muatnaik log", #"upload log",
+"uploadlogpage" => "Muatnaik_log", #"Upload_log",
+"uploadlogpagetext" => "Di bawah ini adalah senarai terkini fail yang dimuatnaik.
+Semua waktu yang ditunjukkan adalah waktu pelayan (UTC).
+<ul>
+</ul>
+",
+"filename"             => "Filename",
+"filedesc"             => "Ringkasan", #"Summary",
+"copyrightpage" => "Wikipedia:Hak cipta",
+"copyrightpagename" => "Hak cipta Wikipedia",
+"uploadedfiles"        => "Fail yang telah dimuatnaik", #"Uploaded files",
+"ignorewarning"        => "Abaikan amaran dan simpan fail sahaja", #"Ignore warning and save file anyway.",
+"minlength"            => "Nama imej mesti sekurang-kurangnya tiga huruf.", #"Image names must be at least three letters.",
+"badfilename"  => "Nama imej telah ditukar kepada \"$1\".", #"Image name has been changed to \"$1\".",
+"badfiletype"  => "\".$1\" ialah fail format imej yg tidak di sarankan.",
+"largefile"            => "Disarankan agar saiz imej tidak melebihi 100k.",
+"successfulupload" => "Berjaya dimuaturun",    #"Successful upload",
+"fileuploaded" => "Fail \"$1\" berjaya dimuaturun.
+Sila patuhi pautan : ($2) pada halaman deskripsi dan isikan maklumat
+tentang fail tersebut, seperti fail itu dari mana, bila ia dibuat dan
+oleh siapa, dan lain-lain yang anda ketahui.",
+"uploadwarning" => "Amaran muaturun", # Upload warning",
+"savefile"             => "Simpan fail", #"Save file",
+"uploadedimage" => "Telah dimuaturun \"[[$1]]\"",     #"uploaded \"$1\"",
+
+# Image list
+#
+"imagelist"    => "Senarai imej",   #"Image list",
+"imagelisttext"        => "Di bawah ialah senarai imej yang telah diasingkan $2.", #"Below is a list of $1 images sorted $2.",
+"getimagelist" => "senarai imej yang diperolehi",    #"fetching image list",
+"ilsubmit"             => "Carian", #"Search",
+"showlast"             => "Paparan imej terakhir $1 yang telah diasingkan $2.", #"Show last $1 images sorted $2.",
+"byname"               => "mengikut nama",   #"by name",
+"bydate"               => "mengikut tarikh", #by date",
+"bysize"               => "mengikut saiz",  #"by size",
+"imgdelete"            => "del",
+"imgdesc"              => "desc",
+"imglegend"            => "Lagenda: (desc) = papar/sunting deskripsi imej.", #"Legend: (desc) = show/edit image description.",
+"imghistory"   => "Sejarah imej",  #"Image history",
+"revertimg"            => "rev",
+"deleteimg"            => "del",
+"deleteimgcompletely"          => "del",
+"imghistlegend" => "Legend: (cur) = this is the current image, (del) = delete
+this old version, (rev) = revert to this old version.
+<br /><i>Click on date to see image uploaded on that date</i>.",
+"imagelinks"   => "Pautan imej",  #"Image links",
+"linkstoimage" => "Halaman berikut berpaut pada imej ini:", #"The following pages link to this image:",
+"nolinkstoimage" => "Tiada halaman yang berpaut pada imej ini.",   #"There are no pages that link to this image.",
+
+# Statistics
+#
+"statistics"   => "Statistik", #"Statistics",
+"sitestats"            => "Laman statistik",    #"Site statistics",
+"userstats"            => "Statistik pengguna",  #"User statistics",
+"sitestatstext" => "Terdapat <b>$1</b> jumlah halaman dalam pangkalan data.
+Ini termasuk halaman \"talk\", halaman tentang Wikipedia, halaman minimum \"stub\",
+alih semula dan lain-lain yang mungkin tidak termasuk dalam
+halaman penuh.
+Selain itu, terdapat halaman <b>$2</b> yang mungkin halaman penuh. <p>
+Terdapat sejumlah <b>$3</b> halaman yang disiarkan, dan sejumlah <b>$4</b>
+halaman yang telah diedit sejak ia dihasilkan.
+Ini menjadikan <b>$5</b> purata halaman yang disunting, dan <b>$6</b> paparan yang disunting.",
+"userstatstext" => "Terdapat <b>$1<b/> pengguna berdaftar.
+<b>$2<b/> daripadanya adalah pentadbir (lihat $3).",
+
+# Maintenance Page
+#
+"maintenance"          => "Halaman penyelenggaraan",  #"Maintenance page",
+"maintnancepagetext"   => "Halaman ini termasuk beberapa peralatan untuk penyelenggaraan setiap hari.  Terdapat sesetengah fungsi yang berkecenderungan untuk mengganggu pangkalan data, jadi tolong jangan tekan kekunci 'reload' selepas membuat pembetulan;-)",
+"maintenancebacklink"  => "Kembali ke halaman penyelenggaran", #"Back to Maintenance Page",
+"disambiguations"      => "Halaman yang tidak samar", #"Disambiguation pages",
+"disambiguationspage"  => "Wikipedia:Pautan_ke_halaman_yang_tidak_samar",    #"Wikipedia:Links_to_disambiguating_pages",
+"disambiguationstext"  => "Halaman-halaman yang berikutnya bersambung ke satu <i>halaman yang tidak samar</i>. Halaman-halaman tersebut sepatutnya bersambung ke topik-topik yang berkenaan.<br />Satu halaman dianggap sebagai tidak samar jika ia disambung dari $1.<br />Pautan dari ruang nama yang lain <i>tidak</i> tersenarai di sini.",
+"doubleredirects"      => "Peralihan Halaman Berganda", #"Double Redirects",
+"doubleredirectstext"  => "<b>Perhatian:</b> Senarai ini mungkin tidak tepat. Ini biasanya bermaksud terdapat tambahan teks dengan pautan di bawah #REDIRECT yang pertama.<br />\nSetiap baris mengandungi pautan kepada peralihan halaman yang pertama dan kedua, sebagaimana baris pertama bagi teks peralihan halaman kedua, biasanya memberikan halaman sasaran \"sebenar\" yang sepatutnya peralihan pertama disambungkan.",
+"brokenredirects"      => "Peralihan Halaman Rosak", #"Broken Redirects",
+"brokenredirectstext"  => "Peralihan halaman berikut bersambung ke satu halaman yang tidak wujud", #"The following redirects link to a non-existing page.",
+"selflinks"            => "Halaman-halaman dengan pautan sendiri", #"Pages with Self Links",
+"selflinkstext"                => "Halaman-halaman berikut mengandungi pautan ke mereka sendiri, yang sepatutnya tidak berlaku.", #"The following pages contain a link to themselves, which they should not.",
+"mispeelings"           => "Halaman-halaman yang mempunyai kesilapan ejaan", #"Pages with misspellings",
+"mispeelingstext"               => "Halaman-halaman berikut mengandungi kesilapan ejaan, yang disenaraikan di $1. Ejaan yang betul mungkin diberi (seperti ini).", # "The following pages contain a common misspelling, which are listed on $1. The correct spelling might be given (like this).",
+"mispeelingspage"       => "Senarai kesilapan ejaan", #"List of common misspellings",
+"missinglanguagelinks"  => "Pautan bahasa yang hilang", #"Missing Language Links",
+"missinglanguagelinksbutton"    => "Cari pautan bahasa yang hilang untuk", #"Find missing language links for",
+"missinglanguagelinkstext"      => "Halaman ini <i>tidak boleh</i> berpaut pada bahagian pusingan dalam $1. Mengarah semula dan sub halaman <i>tidak</i>akan  ditunjukkan.",
+
+
+# Miscellaneous special pages
+#
+"orphans"      => "Halaman orphaned", #"Orphaned pages",
+"lonelypages"  => "Halaman orphaned", #"Orphaned pages",
+"unusedimages" => "Imej tidak digunakan",
+"popularpages" => "Halaman Popular",
+"nviews"               => "Dipamerkan $1", #"$1 views",
+"wantedpages"  => "Halaman dikehendaki",
+"nlinks"               => "Pautan $1",  #"$1 links",
+"allpages"             => "Halaman Keseluruhan",
+"randompage"   => "Halaman Rawak",
+"shortpages"   => "Halaman Ringkas",
+"longpages"            => "Halaman Lengkap",
+"listusers"            => "Senarai Pengguna",
+"specialpages" => "Halaman Istimewa",
+"spheading"            => "Halaman Istimewa", #"Special pages",
+"protectpage"  => "Halaman dilindungi",
+"recentchangeslinked" => "Pautan pilihan",
+"rclsub"               => "(Untuk halaman yang berpaut dari \"$1\")",   #"(to pages linked from \"$1\")",
+"debug"                        => "Pepijat",   #"Debug",
+"newpages"             => "Halaman Baru",
+"ancientpages"         => "Oldest articles",
+"intl"         => "Interlanguage links",
+"movethispage" => "Pindah halaman ini",
+"unusedimagestext" => "<p>Sila ambil perhatian laman web
+yang lain mungkin boleh berpaut secara
+terus dengan URL, dan mungkin masih di
+senaraikan selain masih aktif digunakan.",
+"booksources"  => "Sumber buku",
+"booksourcetext" => "Di bawah ini merupakan senarai untuk ke
+pautan lain yang menjual buku baru dan yang telah digunakan,
+dan mungkin mempunyai maklumat lanjut tentang buku yang anda sedang cari.
+Wikipedia tidak bergabung dengan mana-mana perniagaan di atas,
+dan senarai ini sepatutnya tidak ditafsirkan sebagai sokongan.",
+"alphaindexline" => "$1 to $2",
+
+# Email this user
+#
+"mailnologin"  => "Tidak dibenarkan hantar alamat", #"No send address",
+"mailnologintext" => "Anda mesti [[Istimewa:Userlogin|logged in]] dan mempunyai alamat email yang sah di [[Istimewa:Preferences|preferences]] untuk menghantar email kepada pengguna lain.",
+#"You must be <a href=\"{{localurle:Special:Userlogin}}\">logged in</a> and have a valid e-mail address in your <#a href=\"{{localurle:Special:Preferences}}\">preferences</a> to send e-mail to other users.",
+
+"emailuser"            => "E-mail pengguna ini", #"E-mail this user",
+"emailpage"            => "E-mail pengguna", #"E-mail user",
+"emailpagetext"        => "Sekiranya pengguna ini memasuki alamat email yang sah dalam kecenderungan pengguna, borang dibawah akan menghantar satu pesanan. Alamat email yg diisi pada kecenderungan pengguna akan muncul seperti \"From\"alamat email, jadi penerima boleh membalas email tersebut.",
+
+#"If this user has entered a valid e-mail address in is user preferences, the form below will send a single message.
+#The e-mail address you entered in your user preferences will appear as the \"From\" address of the mail, so the recipient wi#ll be able to reply.",
+
+"noemailtitle" => "Tiada alamat email", #"No e-mail address",
+
+"noemailtext"  => "Pengguna ini tidak mengkhususkan alamat email yang sah, atau telah memilih untuk tidak mendapat email dari pengguna yang lain.",
+#"This user has not specified a valid e-mail address, or has chosen not to receive e-mail from other users.",
+
+"emailfrom"            => "Daripada", #"From",
+"emailto"              => "Kepada",  #"To",
+"emailsubject" => "Perkara",  #"Subject",
+"emailmessage" => "Mesej", #"Message",
+"emailsend"            => "Hantar", #"Send",
+"emailsent"            => "Email dihantar", #"E-mail sent",
+"emailsenttext" => "Email anda telah dihantar.", #"Your e-mail message has been sent.",
+
+# Watchlist
+#
+"watchlist"            => "Senarai Pilihan",
+"watchlistsub" => "( untuk pengguna \"$1\")",   #"(for user \"$1\")",
+"nowatchlist"  => "Tiada apa-apa dalam senarai pilihan.",    #"You have no items on your watchlist.",
+"watchnologin" => "Tidak memasuki sistem", #"Not logged in",
+"watchnologintext"     => "Anda mesti [[Istimewa:Userlogin|mendaftar masuk]]
+untuk mengubah senarai pilihan.",
+"addedwatch"   => "Tambah ke senarai pilihan",
+"addedwatchtext" => "Halaman \"$1\" telah ditambah pada <a href=\"".
+  "{{localurle:Istimewa:Watchlist}}\">senarai pilihan</a>.
+Perubahan halaman dan gabungan halaman Perbualan pada masa akan datang
+akan disenaraikan di sini, dan halaman itu akan muncul <b>bolded</b> dalam <a href=\"".
+ "{{localurle:Istimewa:Recentchanges}}\">senarai perubahan terkini</a>
+ supaya lebih mudah dibawa keluar.</p>
+
+<p>Sekiranya anda ingin menghapuskan halaman dalam senarai pilihan kemudian, klik \"Berhenti dari senarai pilihan\" pada bar disebelah.",
+"removedwatch" => "Keluarkan dari senarai pilihan",   #"Removed from watchlist",
+"removedwatchtext" => "Halaman \"$1\"telah dikeluarkan dari senarai pilihan.",
+"watchthispage"        => "Tambah ke senarai pilihan",
+"unwatchthispage" => "Berhenti dari senarai pilihan", #"Stop watching",
+"notanarticle" => "Not a page",
+
+# Delete/protect/revert
+#
+"deletepage"   => "Keluarkan halaman", #"Delete page",
+"confirm"              => "Sah", #"Confirm",
+"excontent" => "Kandungan dahulu: '$1'",
+"exbeforeblank" => "kandungan sebelum dikosongankan adalah: '$1'",
+"exblank" => "laman kosong",
+"confirmdelete" => "Sah keluarkan", #"Confirm delete",
+"deletesub"            => "(Keluarkan \"$1\")", #"(Deleting \"$1\")",
+"historywarning" => "Amaran: Laman yang anda ingin padamkan mempunyai sejarah:",
+"confirmdeletetext" => "Anda akan mengeluarkan terus halaman atau
+imej ini dengan semua sejarahnya dari pangkalan data.  Sila pastikan
+yang anda memang mahu berbuat demikian, bahawa anda faham segala
+akibatnya, dan apa yang anda lakukan ini adalah mengikut
+[[Wikipedia:Polisi]].",
+"actioncomplete" => "Proses selesai", #"Action complete",
+"deletedtext"  => "\"$1\" telah dikeluarkan.
+Lihat $2 untuk rekod terkini halaman yang telah dikeluarkan.",
+"deletedarticle" => "telah dikeluarkan", #"deleted \"$1\"",
+"dellogpage"   => "Log_penghapusan", #"Deletion_log",
+"dellogpagetext" => "Di bawah ini adalah senarai terkini halaman yang telah dikeluarkan.
+Semua waktu yang ditunjukkan adalah waktu pelayan (UTC).
+<ul>
+</ul>
+",
+"deletionlog"  => "Log penghapusan", #"deletion log",
+"reverted"             => "Kembali kepada rujukan yang sebelumnya", #"Reverted to earlier revision",
+"deletecomment"        => "Sebab penghapusan", #"Reason for deletion",
+"imagereverted" => "Kembali kepada rujukan yang sebelumnya berjaya", #"Revert to earlier version was successful.",
+"rollback"             => "Sunting kembali asal",
+"rollbacklink" => "kembali asal",
+"rollbackfailed" => "gagal kembali asal",
+"cantrollback" => "Cannot revert edit; last contributor is only author of this article.",
+"alreadyrolled"        => "Cannot rollback last edit of [[$1]]
+by [[User:$2|$2]] ([[User talk:$2|Talk]]); someone else has edited or rolled back the article already.
+
+Last edit was by [[User:$3|$3]] ([[User talk:$3|Talk]]). ",
+#   only shown if there is an edit comment
+"editcomment" => "The edit comment was: \"<i>$1</i>\".",
+"revertpage"   => "Kembali kesuntingan akhir oleh $1",
+
+# Undelete
+"undelete" => "Masukkan semula halaman yang telah dikeluarkan", #"Restore deleted page",
+"undeletepage" => "Papar dan masukkan semula halaman yang telah dikeluarkan", #"View and restore deleted pages",
+"undeletepagetext" => "Halaman-halaman berikutnya telah dikeluarkan tapi masih ada di dalam capaian dan boleh dimasukkan semula. Capaian tersebut mungkin akan dikemaskini secara berkala", #"The following pages have been deleted but are still in the archive and can be restored. The archive may be periodically cleaned out.",
+"undeletearticle" => "Masukkan semula halaman yang telah dikeluarkan", #"Restore deleted article",
+"undeleterevisions" => "$1 revisi dicapai", #"$1 revisions archived",
+"undeletehistory" => "Jika anda masukkan semula halaman tersebut,
+semua revisi akan dimasukkan semula ke dalam sejarah.
+Jika satu halaman telah dibuat dengan nama yang sama setelah penghapusan,
+revisi yang telah dimasukkan semula akan kelihatan dalam sejarah dahulu,
+dan revisi terkini bagi halaman baru tidak akan digantikan secara automatik.", #"If you restore the page, all revisions will be restored to the history.If a new page with the same name has been created since the deletion, the restored revisions will appear in the prior history, and the current revision of the live page will not be automatically replaced.",
+"undeleterevision" => "Revisi yang telah dikeluarkan seperti $1", #"Deleted revision as of $1",
+"undeletebtn" => "Masukkan semula!", #"Restore!",
+"undeletedarticle" => "telah dimasukkan", #"restored \"$1\"",
+"undeletedtext"   => "Halaman [[$1]] telah berjaya dimasukkan semula.
+Lihat [[Wikipedia:Log_penghapusan]] untuk rekod terkini penghapusan dan kemasukan semula halaman.",
+
+# Contributions
+#
+"contributions"        => "Sumbangan pengguna", #"User contributions",
+"mycontris" => "Sumbangan saya", #"My contributions",
+"contribsub"   => "Untuk $1", #"For $1",
+"nocontribs"   => "Tidak ada sebarang perubahan yang sepadan dengan kriteria-kriteria ini.", #"No changes were found matching these criteria.",
+"ucnote"               => "Di bawah ini adalah <b>$1</b> perubahan terakhir pengguna dalam tempoh <b>$2</b> hari lepas.", #"Below are this user's last <b>$1</b> changes in the last <b>$2</b> days.",
+"uclinks"              => "Paparkan $1 perubahan terkini; paparkan $2 hari lepas", #"View the last $1 changes; view the last $2 days.",
+"uctop"                => " (top)" ,
+
+# What links here
+#
+"whatlinkshere"        => "Pautan ke halaman ini",
+"notargettitle" => "Tiada sasaran", #"No target",
+"notargettext" => "Anda tidak menspesifikasikan halaman
+atau pengguna sasaran untuk melaksanakan fungsi ini.",
+"linklistsub"  => "(Senarai pautan)", #"(List of links)",
+"linkshere"            => "Halaman-halaman berikut mempunyai pautan ke sini:", #"The following pages link to here:",
+"nolinkshere"  => "Tiada halaman mempunyai pautan ke sini.", #"No pages link to here.",
+"isredirect"   => "alih semula halaman", #"redirect page",
+
+# Block/unblock IP
+#
+"blockip"              => "Blok IP", #"Block IP",
+"blockiptext"  => "Gunakan borang di bawah untuk blok
+capaian kemaskini daripada alamat IP atau pengguna tertentu.
+Ini perlu dilakukan untuk mencegah vandalisme,
+dan mengikut [[Wikipedia:Polisi|Polisi Wikipedia]].
+Masukkan alasan anda di bawah (contohnya mengambil
+halaman tertentu yang telah dirosakkan).",
+"ipaddress"            => "Alamat IP atau pengguna", #"IP Address or Username",
+"ipbreason"            => "Alasan", #"Reason",
+"ipbsubmit"            => "Hantar", #"Submit",
+"badipaddress" => "Alamat IP atau pengguna ini dalam format yang tidak betul.", #"The IP address or username is badly formed.",
+"blockipsuccesssub" => "Pemblokan berjaya", #"Block succeeded",
+"blockipsuccesstext" => "Alamat IP atau pengguna \"$1\" telah diblok.
+<br />Lihat [[Istimewa:Ipblocklist|IP and user block list]] untuk semak pemblokan.", #"The IP address or username \"$1\" has been blocked.
+"unblockip"            => "Lepaskan semula alamat IP atau pengguna dari diblok", #"Unblock IP address or user",
+"unblockiptext"        => "Gunakan borang di bawah untuk masukkan semula
+capaian kemaskini ke alamat IP atau pengguna yang telah diblok sebelumnya.",
+"ipusubmit"            => "Lepaskan semula alamat ini dari diblok", #"Unblock this address",
+"ipusuccess"   => "Alamat IP atau pengguna \"$1\" dilepaskan dari diblok", #"IP address or user \"$1\" unblocked",
+"ipblocklist"  => "Senarai alamat IP dan pengguna yang diblok", #"List of blocked IP addresses and users",
+"blocklistline"        => "$1, $2 blok $3 ($4)",
+"blocklink"            => "blok", #"block",
+"unblocklink"  => "lepaskan dari diblok", #"unblock",
+"contribslink" => "contribs",
+
+# Developer tools
+#
+"lockdb"               => "Kunci pangkalan data", #"Lock database",
+"unlockdb"             => "Buka semula pangkalan data dari dikunci", #"Unlock database",
+"lockdbtext"   => "Mengunci pangkalan data akan menghalang pengguna dari
+menyunting halaman, menukar konfigurasi pengguna, sunting senarai pilihan mereka,
+dan lain-lain perkara yang melibatkan kemaskini terhadap pangkalan data.
+Sila pastikan anda mahu berbuat demikian, dan anda akan buka semula pangkalan
+data apabila penyelenggaraan telah selesai.",
+"unlockdbtext" => "Membuka semula pangkalan data dari dikunci akan
+membolehkan pengguna mengedit halaman, menukar konfigurasi pengguna,
+menyunting senarai pilihan mereka dan lain-lain perkara yang melibatkan
+kemaskini terhadap pangkalan data.  Sila pastikan anda mahu berbuat demikian.",
+"lockconfirm"  => "Ya, saya memang mahu mengunci pangkalan data ini.", #"Yes, I really want to lock the database.",
+"unlockconfirm"        => "Ya, saya memang mahu membuka semula pangkalan data ini dari dikunci.", #"Yes, I really want to unlock the database.",
+"lockbtn"              => "Kunci pangkalan data", #"Lock database",
+"unlockbtn"            => "Buka semula pangkalan data dari dikunci", #"Unlock database",
+"locknoconfirm" => "Anda tidak semak semula kotak pengesahan.", #"You did not check the confirmation box.",
+"lockdbsuccesssub" => "Penguncian pangkalan data berjaya", #"Database lock succeeded",
+"unlockdbsuccesssub" => "Kunci pangkalan data telah dihapuskan", #"Database lock removed",
+"lockdbsuccesstext" => "Pangkalan data Wikipedia telah dikunci.
+<br />Pastikan anda membukanya semula dari dikunci setelah penyelenggaraan selesai.",
+"unlockdbsuccesstext" => "Pangkalan data Wikipedia telah dibuka semula dari dikunci.", #"The Wikipedia database has been unlocked.",
+
+# Move page
+#
+"movepage"     => "Alih Halaman",  #"Move page",
+"movepagetext" => "Borang di bawah digunakan untuk menukar halaman,
+mengalihkan semua data kepada nama baru.
+Tajuk yang lama akan terus dialih kepada tajuk yang baru.
+Pautan kepada tajuk yang lama tidak akan berubah, dan halaman
+perbualan tidak akan dikeluarkan sekiranya perlu.
+
+
+
+
+
+
+
+
+
+<b>AMARAN!</b>
+Ini menjadikan perubahan yang tidak dijangka dan drastik
+bagi halaman popular.  Sila pastikan anda faham selok
+belok borang ini sebelum anda teruskan.",
+"movepagetalktext" => "The associated talk page, if any, will be automatically moved along with it '''unless:'''
+*You are moving the page across namespaces,
+*A non-empty talk page already exists under the new name, or
+*You uncheck the box below.
+
+In those cases, you will have to move or merge the page manually if desired.",
+"movearticle"  => "Alih halaman", #"Move page",
+"movenologin"  => "Tidak masuk sistem", #"Not logged in",
+"movenologintext" => "Anda mesti menjadi pengguna berdaftar dan [[Istimewa:Userlogin|logged in]]
+untuk mengalihkan halaman.",
+"newtitle"     => "Tajuk baru",   #"To new title",
+"movepagebtn"  => "Alih halaman", #"Move page",
+"pagemovedsub" => "Pengalihan berjaya",  #"Move succeeded",
+"pagemovedtext" => "Halaman \"[[$1]]\" ditukar kepada \"[[$2]]\".",   #"Page \"[[$1]]\" moved to \"[[$2]]\".",
+"articleexists" => "Halaman dengan nama tersebut telah wujud,
+atau nama yang dipilih tidak sah.
+Sila pilih nama lain.",
+"talkexists"   => "The page itself was moved successfully, but the
+talk page could not be moved because one already exists at the new
+title. Please merge them manually.",
+"movedto"              => "Tukar kepada",  #"moved to",
+"movetalk"             => "Tukar halaman \"perbualan\", sekiranya sesuai.",   #"Move \"talk\" page as well, if applicable.",
+"talkpagemoved" => "Halaman perbualan yang sama turut dialihkan.",    #"The corresponding talk page was also moved.",
+"talkpagenotmoved" => "Halaman perbualan yang sama <strong>not</strong> turut dialihkan.",
+# Math
+       'mw_math_png' => "Sentiasa lakar PNG", # "Always render PNG",
+       'mw_math_simple' => "HTML jika ringkas atau PNG", # "HTML if very simple or else PNG",
+       'mw_math_html' => "HTML jika boleh atau PNG", # "HTML if possible or else PNG",
+       'mw_math_source' => "Biarkan sebagai TeX (untuk pelayar teks)", # "Leave it as TeX (for text browsers)",
+       'mw_math_modern' => "Dicadang untuk pelayar moden", # "Recommended for modern browsers"
+       'mw_math_mathml' => 'MathML',
+
+);
+
+require_once( "LanguageUtf8.php" );
+
+class LanguageMs extends LanguageUtf8 {
+
+       function getNamespaces() {
+               global $wgNamespaceNamesMs;
+               return $wgNamespaceNamesMs;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsMs;
+               return $wgQuickbarSettingsMs;
+       }
+
+       function getDateFormats() {
+               global $wgDateFormatsMs;
+               return $wgDateFormatsMs;
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesMs;
+               if( isset( $wgAllMessagesMs[$key] ) ) {
+                       return $wgAllMessagesMs[$key];
+               } else {
+                       return parent::getMessage( $key );
+               }
+       }
+}
+
+?>
diff --git a/languages/LanguageNds.php b/languages/LanguageNds.php
new file mode 100644 (file)
index 0000000..f7d8f18
--- /dev/null
@@ -0,0 +1,1310 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+#
+# Low Saxon (Plattdüütsch) localisation for MediaWiki
+#
+# This file is encoded in UTF-8, no byte order mark.
+# For compatibility with Latin-1 installations, please
+# don't add literal characters above U+00ff.
+#
+require_once( 'LanguageUtf8.php' );
+
+# See Language.php for notes.
+
+if($wgMetaNamespace === FALSE)
+       $wgMetaNamespace = str_replace( ' ', '_', $wgSitename );
+
+/* private */ $wgNamespaceNamesNds = array(
+       NS_MEDIA            => 'Media',
+       NS_SPECIAL          => 'Spezial',
+       NS_MAIN             => '',
+       NS_TALK             => 'Diskuschoon',
+       NS_USER             => 'Bruker',
+       NS_USER_TALK        => 'Bruker_Diskuschoon',
+       NS_PROJECT          => $wgMetaNamespace,
+       NS_PROJECT_TALK     => $wgMetaNamespace . '_Diskuschoon',
+       NS_IMAGE            => 'Bild',
+       NS_IMAGE_TALK       => 'Bild_Diskuschoon',
+       NS_MEDIAWIKI        => 'MediaWiki',
+       NS_MEDIAWIKI_TALK   => 'MediaWiki_Diskuschoon',
+       NS_TEMPLATE         => 'Vörlaag',
+       NS_TEMPLATE_TALK    => 'Vörlaag_Diskuschoon',
+       NS_HELP             => 'Hülp',
+       NS_HELP_TALK        => 'Hülp_Diskuschoon',
+       NS_CATEGORY         => 'Kategorie',
+       NS_CATEGORY_TALK    => 'Kategorie_Diskuschoon'
+);
+
+/* private */ $wgQuickbarSettingsNds = array(
+       'Keen', 'Links, fast', 'Rechts, fast', 'Links, sweven'
+);
+
+# Note to translators:
+#   Please include the English words as synonyms.  This allows people
+#   from other wikis to contribute more easily.
+#
+/* private */ $wgMagicWordsNds = array(
+#   ID                                 CASE  SYNONYMS
+       MAG_REDIRECT             => array( 0,    '#redirect',                   '#wiederleiden'          ),
+       MAG_NOTOC                => array( 0,    '__NOTOC__',                   '__KEENINHOLTVERTEKEN__' ),
+       MAG_FORCETOC             => array( 0,    '__FORCETOC__',                '__WIESINHOLTVERTEKEN__' ),
+       MAG_TOC                  => array( 0,    '__TOC__',                     '__INHOLTVERTEKEN__'     ),
+       MAG_NOEDITSECTION        => array( 0,    '__NOEDITSECTION__',           '__KEENÄNNERNLINK__'     ),
+       MAG_START                => array( 0,    '__START__'                                             ),
+       MAG_CURRENTMONTH         => array( 1,    'CURRENTMONTH',                'AKTMAAND'               ),
+       MAG_CURRENTMONTHNAME     => array( 1,    'CURRENTMONTHNAME',            'AKTMAANDNAAM'           ),
+       MAG_CURRENTDAY           => array( 1,    'CURRENTDAY',                  'AKTDAG'                 ),
+       MAG_CURRENTDAYNAME       => array( 1,    'CURRENTDAYNAME',              'AKTDAGNAAM'             ),
+       MAG_CURRENTYEAR          => array( 1,    'CURRENTYEAR',                 'AKTJOHR'                ),
+       MAG_CURRENTTIME          => array( 1,    'CURRENTTIME',                 'AKTTIED'                ),
+       MAG_NUMBEROFARTICLES     => array( 1,    'NUMBEROFARTICLES',            'ARTIKELTALL'            ),
+       MAG_CURRENTMONTHNAMEGEN  => array( 1,    'CURRENTMONTHNAMEGEN',         'AKTMAANDNAAMGEN'        ),
+       MAG_PAGENAME             => array( 1,    'PAGENAME',                    'SIETNAAM'               ),
+       MAG_PAGENAMEE            => array( 1,    'PAGENAMEE',                   'SIETNAAME'              ),
+       MAG_NAMESPACE            => array( 1,    'NAMESPACE',                   'NAAMRUUM'               ),
+       MAG_SUBST                => array( 0,    'SUBST:'                                                ),
+       MAG_MSGNW                => array( 0,    'MSGNW:'                                                ),
+       MAG_END                  => array( 0,    '__END__',                     '__ENN__'                ),
+       MAG_IMG_THUMBNAIL        => array( 1,    'thumbnail', 'thumb',          'duum'                   ),
+       MAG_IMG_RIGHT            => array( 1,    'right',                       'rechts'                 ),
+       MAG_IMG_LEFT             => array( 1,    'left',                        'links'                  ),
+       MAG_IMG_NONE             => array( 1,    'none',                        'keen'                   ),
+       MAG_IMG_WIDTH            => array( 1,    '$1px',                        '$1px'                   ),
+       MAG_IMG_CENTER           => array( 1,    'center', 'centre',            'merrn'                  ),
+       MAG_IMG_FRAMED           => array( 1,    'framed', 'enframed', 'frame', 'rahmt'                  ),
+       MAG_INT                  => array( 0,    'INT:'                                                  ),
+       MAG_SITENAME             => array( 1,    'SITENAME',                    'STEEDNAAM'              ),
+       MAG_NS                   => array( 0,    'NS:',                         'NR:'                    ),
+       MAG_LOCALURL             => array( 0,    'LOCALURL:',                   'STEEDURL:'              ),
+       MAG_LOCALURLE            => array( 0,    'LOCALURLE:',                  'STEEDURLE:'             ),
+       MAG_SERVER               => array( 0,    'SERVER',                      'SERVER'                 ),
+       MAG_GRAMMAR              => array( 0,    'GRAMMAR:',                    'GRAMMATIK:'             )
+);
+
+/* private */ $wgSkinNamesNds = array(
+       'standard'      => 'Klassik',
+       'nostalgia'     => 'Nostalgie',
+       'cologneblue'   => 'Kölsch Blau',
+       'smarty'        => 'Paddington',
+       'chick'         => 'Küken'
+) + $wgSkinNamesEn;
+
+
+/* private */ $wgBookstoreListNds = array(
+       'Verteken vun leverbore Böker' => 'http://www.buchhandel.de/sixcms/list.php?page=buchhandel_profisuche_frameset&suchfeld=isbn&suchwert=$1=0&y=0',
+       'abebooks.de'                   => 'http://www.abebooks.de/servlet/BookSearchPL?ph=2&isbn=$1',
+       'Amazon.de'                     => 'http://www.amazon.de/exec/obidos/ISBN=$1',
+       'Lehmanns Fachbuchhandlung'     => 'http://www.lob.de/cgi-bin/work/suche?flag=new&stich1=$1',
+);
+
+
+
+/* private */ $wgAllMessagesNds = array(
+# Schalter för de Brukers
+'tog-underline'               => 'Verwies ünnerstrieken',
+'tog-highlightbroken'         => 'Verwies op leddige Sieten hervörheven',
+'tog-justify'                 => 'Text as Blocksatz',
+'tog-hideminor'               => 'Kene lütten Ännern in letzte Ännern wiesen',
+'tog-usenewrc'                => 'Erwiederte letzte Ännern (nich för alle Browser bruukbor)',
+'tog-numberheadings'          => 'Överschrieven automatsch nummereern',
+'tog-showtoolbar'             => 'Editeer-Warktüüchlist wiesen',
+'tog-editondblclick'          => 'Sieten mit Dubbelklick bearbeiden (JavaScript)',
+'tog-editsection'             => 'Links för dat Bearbeiden vun en Afsatz wiesen',
+'tog-editsectiononrightclick' => 'En Afsatz mit en Rechtsklick bearbeiden (Javascript)',
+'tog-showtoc'                 => 'Wiesen vun\'n Inholtsverteken bi Sieten mit mehr as dree Överschriften',
+'tog-rememberpassword'        => 'Duersam Inloggen',
+'tog-editwidth'               => 'Text-Ingaavfeld mit vulle Breed',
+'tog-watchdefault'            => 'Op niege un ännerte Sieten oppassen',
+'tog-minordefault'            => 'Alle Ännern as lütt markeern',
+'tog-previewontop'            => 'Vörschau vör dat Editeerfinster wiesen',
+'tog-previewonfirst'          => 'Vörschau bi\'n eersten Ännern wiesen',
+'tog-nocache'                 => 'Sietencache deaktiveern',
+# Dates
+'sunday'    => 'Sünndag',
+'monday'    => 'Maandag',
+'tuesday'   => 'Dingsdag',
+'wednesday' => 'Merrweek',
+'thursday'  => 'Dunnersdag',
+'friday'    => 'Freedag',
+'saturday'  => 'Sünnavend',
+'january'   => 'Januar',
+'february'  => 'Februar',
+'march'     => 'März',
+'april'     => 'April',
+'may_long'  => 'Mai',
+'june'      => 'Juni',
+'july'      => 'Juli',
+'august'    => 'August',
+'september' => 'September',
+'october'   => 'Oktober',
+'november'  => 'November',
+'december'  => 'Dezember',
+'jan'       => 'Jan',
+'feb'       => 'Feb',
+'mar'       => 'Mär',
+'apr'       => 'Apr',
+'may'       => 'Mai',
+'jun'       => 'Jun',
+'jul'       => 'Jul',
+'aug'       => 'Aug',
+'sep'       => 'Sep',
+'oct'       => 'Okt',
+'nov'       => 'Nov',
+'dec'       => 'Dez',
+
+
+# Textdelen, de vun vele Sieten bruukt warrn:
+#
+'categories'            => 'Sietenkategorien',
+'category'              => 'Kategorie',
+'category_header'       => 'Sieten in de Kategorie $1',
+'subcategories'         => 'Ünnerkategorien',
+'linktrail'                        => '/^((?:ä|ö|ü|ß|[a-z])+)(.*)$/sD',
+'mainpage'                      => 'Hööftsiet',
+'mainpagetext'          => 'De Wiki-Software is mit Spood installeert worrn.',
+'mainpagedocfooter'     => 'Kiek de [http://meta.wikipedia.org/wiki/MediaWiki_i18n Dokumentatschoon för dat Anpassen vun de Brukerböversiet]
+un dat [http://meta.wikipedia.org/wiki/MediaWiki_User%27s_Guide Brukerhandbook] för Hülp to de Bruuk un Konfiguratschoon.',
+'portal'                        => '{{SITENAME}}-Portal',
+'portal-url'                      => '{{ns:4}}:Portal',
+'about'                               => 'Över',
+'aboutsite'             => 'Över {{SITENAME}}',
+'aboutpage'                     => '{{ns:4}}:Över_{{SITENAME}}',
+'article'               => 'Artikel',
+'help'                          => 'Hülp',
+'helppage'                      => '{{ns:4}}:Hülp',
+'bugreports'               => 'Kontakt',
+'bugreportspage'        => '{{ns:4}}:Kontakt',
+'sitesupport'           => 'Gaven',
+'faq'                                   => 'Faken stellte Fragen',
+'faqpage'                       => '{{ns:project}}:Faken stellte Fragen',
+'newwindow'                     => '(apent sik in en nieg Finster)',
+'edithelp'                          => 'Bearbeidenshülp',
+'edithelppage'           => '{{ns:project}}:Editeerhülp',
+'cancel'                              => 'Afbreken',
+'qbfind'                              => 'Finnen',
+'qbbrowse'                          => 'Blädern',
+'qbedit'                        => 'Ännern',
+'qbpageoptions'         => 'Sietenoptschonen',
+'qbpageinfo'               => 'Sietendaten',
+'qbmyoptions'           => 'Instellen',
+'qbspecialpages'               => 'Spezialsieten',
+'moredotdotdot'         => 'Mehr...',
+'mypage'                              => 'Mien Siet',
+'mytalk'                              => 'Mien Diskuschoon',
+'anontalk'                          => 'Diskuschoonssiet vun disse IP',
+'navigation'            => 'Navigatschoon',
+'currentevents'         => 'Aktuell Schehn',
+'currentevents-url'     => '{{ns:4}}:Aktuell Schehn',
+'disclaimers'           => 'Lizenzbestimmen',
+'disclaimerpage'                      => '{{ns:4}}:Lizenzbestimmen',
+'errorpagetitle'        => 'Fehler',
+'returnto'                      => 'Trüch to $1.',
+'tagline'               => 'ut {{SITENAME}}, de fre\'e Wetensdatenbank',
+'whatlinkshere'         => 'Wat wiest hierher',
+'help'                          => 'Hülp',
+'search'                        => 'Söök',
+'history'                            => 'Historie',
+'history_short'         => 'Historie',
+'info_short'               => 'Informatschoon',
+'printableversion'      => 'Druckversion',
+'editthispage'          => 'Siet bearbeiden',
+'delete'                => 'wegsmieten',
+'deletethispage'        => 'Disse Siet wegsmieten',
+'undelete_short'        => 'Weerholen',
+'protect'               => 'Schulen',
+'protectthispage'       => 'Siet schulen',
+'unprotect'             => 'Freegeven',
+'unprotectthispage'     => 'Schuul opheben',
+'newpage'               => 'Niege Siet',
+'talkpage'                          => 'Diskuschoon',
+'specialpage'           => 'Spezialsiet',
+'personaltools'         => 'Persönliche Warktüüch',
+'postcomment'           => 'Kommentar hentofögen',
+'addsection'            => '+',
+'articlepage'             => 'Artikel',
+'subjectpage'             => 'Bedrap ankieken',
+'toolbox'               => 'Warktüüch',
+'wikipediapage'         => 'Meta-Text',
+'userpage'              => 'Brukersiet',
+'imagepage'             => 'Bildsiet',
+'viewtalkpage'          => 'Diskuschoon',
+'otherlanguages'        => 'Annere Spraken',
+'redirectedfrom'        => '(Wiederleiden vun $1)',
+'lastmodified'           => 'Disse Siet is toletzt üm $1 ännert worrn.',
+'viewcount'                        => 'Disse Siet is $1 Maal opropen worrn.',
+'copyright'             => 'De Inholt is verfögbor ünner de $1.',
+'poweredby'                 => '{{SITENAME}} bruukt [http://www.mediawiki.org/ MediaWiki], en Wiki-Software mit apen Borntext.',
+'printsubtitle'         => '(Vun {{SERVER}})',
+'protectedpage'         => 'Schulte Sieten',
+'administrators'        => '{{ns:4}}:Administratern',
+'sysoptitle'               => 'Sysop-Togang notwennig',
+'sysoptext'                     => 'Dissen Vörgang kann ut Sekerheitsgrünnen blots vun Brukern mit „Sysop“-Rechten dörföhrt warrn. Kiek ok $1.',
+'developertitle'        => 'Entwickler-Togang notwennig',
+'developertext'         => 'Dissen Vörgang kann ut Sekerheitsgrünnen blots vun Brukern mit „Entwickler“-Rechten dörföhrt warrn. Kiek ok $1.',
+'nbytes'                              => '$1 Bytes',
+'go'                                     => 'Los',
+'ok'                                    => 'OK',
+'sitetitle'                        => '{{SITENAME}}',
+'sitesubtitle'          => 'De fre\'e Nokieksel',
+'pagetitle'                        => '$1 - {{SITENAME}}',
+
+'retrievedfrom'         => 'Vun „$1“',
+'newmessages'           => 'Du hest $1.',
+'newmessageslink'       => 'niege Norichten',
+'editsection'           => 'bearbeiden',
+'toc'                   => 'Inholtsverteken',
+'showtoc'               => 'wiesen',
+'hidetoc'               => 'Nich wiesen',
+'thisisdeleted'         => 'Ankieken oder weerholen vun $1?',
+'restorelink'           => '$1 löscht Bearbeidensvörgäng',
+'feedlinks'             => 'Feed:',
+
+# Kortwöör för elkeen Namespace, ünner annern vun MonoBook bruukt
+'nstab-main'            => 'Artikel',
+'nstab-user'            => 'Brukersiet',
+'nstab-media'           => 'Media',
+'nstab-special'         => 'Spezial',
+'nstab-wp'              => 'Över',
+'nstab-image'           => 'Bild',
+'nstab-mediawiki'       => 'Noricht',
+'nstab-template'        => 'Vörlaag',
+'nstab-help'            => 'Hülp',
+'nstab-category'        => 'Kategorie',
+
+# Editeer-Warktüüchleist
+'bold_sample'           => 'Fetten Text',
+'bold_tip'              => 'Fetten Text',
+'italic_sample'         => 'Kursiven Text',
+'italic_tip'            => 'Kursiven Text',
+'link_sample'           => 'Link-Text',
+'link_tip'              => 'Internen Link',
+'extlink_sample'        => 'http://www.bispeel.com Link-Text',
+'extlink_tip'           => 'Externen Link (http:// is wichtig)',
+'headline_sample'       => 'Evene 2 Överschrift',
+'headline_tip'          => 'Evene 2 Överschrift',
+'math_sample'           => 'Formel hier infögen',
+'math_tip'              => 'Mathematsche Formel (LaTeX)',
+'nowiki_sample'         => 'Unformateerten Text hier infögen',
+'nowiki_tip'            => 'Unformateerten Text',
+'image_sample'          => 'Bispeel.jpg',
+'image_tip'             => 'Bild-Verwies',
+'media_sample'          => 'Bispeel.mp3',
+'media_tip'             => 'Mediendatei-Verwies',
+'sig_tip'               => 'Dien Signatur mit Tiedstempel',
+'hr_tip'                => 'Waagrechte Lien (sporsam bruken)',
+
+# Hööft-Script un globale Funktschonen
+#
+'nosuchaction'           => 'Disse Aktschoon gifft dat nich',
+'nosuchactiontext'      => 'Disse Aktschoon warrt vun de MediaWiki-Software nich ünnerstütt',
+'nosuchspecialpage'     => 'Disse Spezialsiet gifft dat nich',
+'nospecialpagetext'     => 'Disse Spezialsiet warrt vun de MediaWiki-Software nich ünnerstütt',
+
+# Generelle Fehlers
+#
+'error'                 => 'Fehler',
+'databaseerror'         => 'Fehler in de Datenbank',
+'dberrortext'             => 'Dor weer en Syntaxfehler in de Datenbankaffraag.
+De letzte Datenbankaffraag weer:
+
+<blockquote><tt>$1</tt></blockquote>
+
+ut de Funktschoon <tt>$2</tt>.
+MySQL mell den Fehler <tt>$3: $4</tt>.',
+'dberrortextcl'         => 'Dor weer en Syntaxfehler in de Datenbankaffraag.
+De letzte Datenbankaffraag weer: $1 ut de Funktschoon <tt>$2</tt>.
+MySQL mell den Fehler: <tt>$3: $4</tt>.',
+'noconnect'                           => 'De Software kunn keen Verbinnen to de Datenbank op $1 opnehmen',
+'nodb'                                    => 'De Software kunn de Datenbank $1 nich utwählen',
+'cachederror'           => 'Disse Siet is en Kopie ut\'n Cache un is mööglicherwies nich aktuell.',
+'readonly'              => 'Datenbank is sparrt',
+'enterlockreason'       => 'Giff den Grund an, worüm de Datenbank sparrt warrn schall un taxeer, wo lang de Sparr duert',
+'readonlytext'              => 'De {{SITENAME}}-Datenbank is för enige Tied sparrt, to\'n Bispeel wegen Pleegarbeiden. Versöök dat later noch eenmal.',
+'missingarticle'        => 'De Text för de Siet \'$1\' kunn nich in de Datenbank funnen warrn. Dat is wohrschienlich en Fehler in de Software. Bitte mell dat an enen Administrater un giff ok den Sietennaam an.',
+'internalerror'         => 'Internen Fehler',
+'filecopyerror'         => 'De Software kunn Datei \'$1\' nich no \'$2\' kopeern.',
+'filerenameerror'       => 'De Software kunn Datei \'$1\' nich no \'$2\' ümnömen.',
+'filedeleteerror'       => 'De Software kunn Datei \'$1\' nich löschen.',
+'filenotfound'              => 'De Software kunn Datei \'$1\' nich finnen.',
+'unexpected'            => 'Unvermodten Weert: \'$1\'=\'$2\'.',
+'formerror'                           => 'Fehler: De Software kunn dat Formular nich verarbeiden',
+'badarticleerror'       => 'Disse Aktschoon kann op disse Siet nich anwennt warrn.',
+'cannotdelete'          => 'De Software kunn de spezifizeerte Siet nich löschen. (Mööglicherwies is de al vun en annern löscht worrn.)',
+'badtitle'              => 'Ungülligen Titel',
+'badtitletext'             => 'De Titel vun de födderte Siet weer ungüllig, leddig, oder en ungülligen Spraaklink vun en annern Wiki.',
+'perfdisabled'          => 'Disse Funktschoon is wegen Överlast vun de Servers för enige Tied deaktiveert. Versöök dat doch twüschen 02:00 un 14:00 UTC noch eenmal<br />(Aktuelle Servertied: '.date('H:i:s').' UTC).',
+'perfdisabledsub'       => 'Hier is en spiekerte Kopie vun $1:',
+'perfcached'            => 'Disse Daten kamen ut den Cache un sünd mööglicherwies nich aktuell:',
+'wrong_wfQuery_params'  => 'Falschen Parameter för wfQuery()<br />
+Funktschoon: $1<br />
+Query: $2
+',
+'viewsource'            => 'Borntext ankieken',
+'protectedtext'         => 'Disse Siet is för dat Bearbeiden sparrt. Dorför kann dat verschedene Grünn geven; kiek [[{{ns:4}}:Schulte Sieten]].
+
+Du kannst den Borntext vun disse Siet ankieken un kopeern:',
+
+
+# Login- un Logoutsieten
+#
+'logouttitle'             => 'Bruker-Afmellen',
+'logouttext'            => 'Du büst nu afmellt. Du kannst {{SITENAME}} nu anonym wiederbruken oder di ünner en annern Brukernaam weer anmellen.',
+
+'welcomecreation'       => '<h2>Willkomen, $1!</h2><p>Dien Brukerkonto is nu inricht.
+Vergeet nich, dien [[Special:Preferences|Instellen]] antopassen.',
+
+'loginpagetitle'        => 'Bruker-Anmellen',
+'yourname'                      => 'Dien Brukernaam',
+'yourpassword'           => 'Dien Password',
+'yourpasswordagain'     => 'Password nochmal ingeven',
+'newusersonly'          => ' (blots för niege Liddmaten)',
+'remembermypassword'    => 'Duersam inloggen',
+'loginproblem'           => '<b>Dor weer en Problem mit dien Anmellen.</b><br />Versöök dat noch eenmal!',
+'alreadyloggedin'       => '<strong>Bruker $1, du büst al anmellt!</strong><br />',
+
+'login'                         => 'Anmellen',
+'loginprompt'           => 'Üm sik bi {{SITENAME}} antomellen, musst du Cookies aktiveert hebben.',
+'userlogin'                     => 'Anmellen',
+'logout'                              => 'Afmellen',
+'userlogout'               => 'Afmellen',
+'notloggedin'           => 'Nich anmellt',
+'createaccount'         => 'Nieg Brukerkonto anleggen',
+'createaccountmail'     => 'över E-Mail',
+'badretype'                        => 'De beiden Passwöör stimmt nich övereen.',
+'userexists'               => 'Dissen Brukernaam is al vergeven. Bitte wähl en annern.',
+'youremail'                     => 'Dien E-Mail (kene Plicht) *',
+'yournick'                          => 'Dien Ökelnaam (för dat Ünnerschrieven)',
+'yourrealname'                  => 'Dien echten Naam (kene Plicht)',
+'yourlanguage'           => 'Snittstellenspraak',
+'yourvariant'           => 'Dien Spraak',
+'emailforlost'          => 'Wenn du dien Password vergeten hest, kann en nieg Password an dien E-Mail-Adress send warrn.',
+// FIXME: following should be split to 'prefs-help-realname' & 'prefs-help-email'
+#'prefs-help-userdata'   => '* <strong>E-Mail</strong> (kene Plicht): Wenn du en E-Mailadress angiffst, könen annere di E-Mails sennen,
+#ahn dat diene Adress no buten künnig warrt. Wenn du dien ol Password vergeten hest,
+#kannst du ok blots denn en nieg Passwort kriegen, wenn du en E-Mailadress angeven hest.',
+'loginerror'               => 'Fehler bi dat Anmellen',
+'noname'                              => 'Du muttst en Brukernaam angeven.',
+'loginsuccesstitle'     => 'Anmellen hett Spood',
+'loginsuccess'           => 'Du büst nu as „$1“ bi {{SITENAME}} anmellt.',
+'nosuchuser'               => 'De Brukernaam „$1“ existeert nich.
+Prööv de Schrievwies oder mell di as niegen Bruker an.',
+'nosuchusershort'             => 'De Brukernaam „$1“ existeert nich. Prööv de Schrievwies.',
+'wrongpassword'         => 'Dat Password is falsch. Bitte versöök dat nochmal.',
+'mailmypassword'        => 'En nieg Password sennen',
+'passwordremindertitle' => '{{SITENAME}} Password',
+'passwordremindertext'  => 'Een (IP-Adress $1) hett üm en nieg Password för dat Anmellen bi {{SITENAME}} beed.
+Dat Password för Bruker „$2“ is nu „$3“. Bitte mell di nu an un änner dien Password.',
+'noemail'                       => 'Bruker „$1“ hett kene E-Mail-Adress angeven.',
+'passwordsent'           => 'En nieg Password is an de E-Mail-Adress vun Bruker „$1“ send worrn. Mell di an, wenn du dat Password kriegt hest.',
+'loginend'                          => ' ',
+'mailerror'             => 'Fehler bi dat Sennen vun de E-Mail: $1',
+'acct_creation_throttle_hit' => 'Du hest al $1 Brukerkontos anleggt. Du kannst nich noch mehr anleggen.',
+
+
+# Sieten ännern
+#
+'summary'                      => 'Tosamenfaten',
+'subject'                => 'Bedrap',
+'minoredit'                  => 'Blots lütte Ännern.',
+'watchthis'              => 'Op disse Siet oppassen',
+'savearticle'                  => 'Siet spiekern',
+'preview'                       => 'Vörschau',
+'showpreview'               => 'Vörschau wiesen',
+'blockedtitle'            => 'Bruker is blockt',
+'blockedtext'                  => 'Dien Brukernaam oder dien IP-Adress is vun $1 blockt worrn.
+As Grund is angeven:<br />$2<p>Wenn du över den Block spreken willst, kontakteer den Administrater.',
+'whitelistedittitle'     => 'üm de Siet to Bearbeiden is dat neudig anmellt to ween',
+'whitelistedittext'      => 'Du muttst di [[Special:Userlogin|hier anmellen]] üm Sieten bearbeiden to könen.',
+'whitelistreadtitle'     => 'üm to Lesen is dat neudig anmellt to ween',
+'whitelistreadtext'      => 'Du muttst di [[Special:Userlogin|hier anmellen]] üm Sieten lesen to könen.',
+'whitelistacctitle'      => 'Du hest nich de Rechten en Konto antoleggen',
+'whitelistacctext'       => 'Üm in dissen Wiki Kontos anleggen to könen muttst du di [[Special:Userlogin|hier anmellen]] un de neudigen Rechten hebben.',
+'loginreqtitle'              => 'Anmellen neudig',
+'loginreqtext'              => 'Du muttst di [[Special:Userlogin|anmellen]], üm annere Sieten ankieken to könen.',
+'accmailtitle'           => 'Passwort is send worrn.',
+'accmailtext'            => 'Dat Passwort vun $1 is an $2 send worrn.',
+'newarticle'                    => '(Nieg)',
+'newarticletext'         => 'Hier den Text vun de niegen Siet indregen. Jümmer in ganze Sätz schrieven un kene Texten vun annern, de enen Oorheverrecht ünnerliggt, hierher kopeern.',
+'anontalkpagetext'       => "---- ''Dit is de Diskuschoonssiet vun en nich anmellt Bruker. Wi mööt hier de numerische [[IP-Adress]]
+verwennen, üm den Bruker to identifizeern. So en Adress kann vun verscheden Brukern bruukt warrn. Wenn du en anonymen Bruker büst un meenst,
+dat disse Kommentaren nich an di richt sünd, denn [[Special:Userlogin|mell di doch an]], dormit dat Problem nich mehr besteiht.''",
+'noarticletext'          => '(Disse Siet hett in\'n Momang kenen Text)',
+'usercsspreview'         => "'''Denk doran, dat du blots en Vörschau vun dien CSS ankiekst, dat is noch nich spiekert!'''",
+'userjspreview'          => "'''Denk doran, dat du blots en Vörschau vun dien JS ankiekst, dat is noch nich spiekert!'''",
+'clearyourcache'         => "'''Denk doran:''' No den Spiekern muttst du dien Browser noch seggen, de niege Version to laden: '''Mozilla/Firefox:''' ''Strg-Shift-R'', '''IE:''' ''Strg-F5'', '''Safari:''' ''Cmd-Shift-R'', '''Konqueror:''' ''F5''.",
+'usercssjsyoucanpreview' => '<strong>Tipp:</strong> Bruuk den Vörschau-Knoop, üm dien nieg CSS/JS vör dat Spiekern to testen.',
+'updated'                       => '(Ännert)',
+'note'                          => '<strong>Henwies:</strong> ',
+'previewnote'                   => 'Dit is blots en Vörschau, de Siet is noch nich spiekert!',
+'previewconflict'        => 'Disse Vörschau wiest den Inholt vun dat Textfeld baven; so warrt de Siet utseihn, wenn du nu spiekerst.',
+'editing'                       => 'Ännern vun $1',
+'editingsection'                => 'Ännern vun $1 (Afsatz)',
+'editingcomment'                => 'Ännern vun $1 (Kommentar)',
+'editconflict'            => 'Konflikt bi dat Bearbeiden: $1',
+'explainconflict'        => 'En anner Bruker hett disse Siet ännert, no de Tied dat du anfungen hest, de Siet to bearbeiden.
+Dat Textfeld baven wiest de aktuelle Siet.
+Dat Textfeld nerrn wiest diene Ännern.
+Föög diene Ännern in dat Textfeld baven in.
+
+<b>Blots</b> de Text in dat Textfeld baven warrt spiekert, wenn du op Spiekern klickst!<br />',
+'yourtext'                      => 'Dien Text',
+'storedversion'          => 'Spiekerte Version',
+'nonunicodebrowser'      => '<strong>Wohrscho: Dien Browser ünnerstütt keen Unicode, wähl en annern Browser, wenn du en Siet ännern wullst.</strong>',
+'editingold'                    => '<strong>Wohrscho: Du bearbeidst en ole Version vun disse Siet.
+Wenn du spiekerst, warrn alle niegeren Versionen överschrieven.</strong>',
+'yourdiff'                      => 'Ünnerscheed',
+'copyrightwarning'       => "
+<b><big>Kopeer kene Websieten</big>, de nich dien egen sünd un bruuk <big>kene Warken, de enen Oorheverrecht ünnerliggt,</big>
+ahn Verlööv vun de Copyright-Inhebbers!</b>
+<p>Du giffst hiermit dien Tosaag, dat du dien Text <strong>sülvst verfaat</strong> hest, dat de Text Gemeengood
+(<strong>„Public Domain“</strong>) is, oder dat de <strong>Copyright-Inhebber</strong> sien <strong>Tostimmen</strong> geven hett.
+Wenn dissen Text al an annere Steed apentlich maakt is, schriev dat ok op de Diskuschoonssiet, sünst kann dat passeern, dat en annern dat weer löscht,
+vun wegen dat he denkt, dat weer en Brook vun dat Oorheverrecht.
+
+<p><i>Denk doran, dat alle {{SITENAME}}-Bidreeg automatsch ünner de „GNU Fre'e Dokumentatschoonslizenz“ steiht.
+Wenn du nich wullst, dat dien Arbeid hier vun annern ännert un verbreed warrt, denn klick nich op Spiekern.</i>",
+'longpagewarning'        => '<strong>Wohrscho: Disse Siet is $1 KB groot; en poor Browser köönt Probleme hebben, Sieten to bearbeiden, de grötter as 32 KB sünd.
+Bedenk of disse Siet vilicht in lüttere Afsnitten opdeelt warrn kann.</strong>',
+'readonlywarning'        => '<strong>Wohrscho: De Datenbank is wiel dat Ännern vun de
+Siet för Pleegarbeiden sparrt worrn, so dat du de Siet en Stoot nich
+spiekern kannst. Seker di den Text un versöök later weer de Ännern to spiekern.</strong>',
+'protectedpagewarning'   => '<strong>Wohrscho: Disse Siet is sparrt worrn, so dat blots
+Bruker mit Sysop-Rechten doran arbeiden könnt. Kiek ok bi de [[Project:Schulte Sieten|Regeln för schulte Sieten]].</strong>',
+'copyrightwarning2'      => 'Dien Text, de du op {{SITENAME}} stellen wullst, könnt vun elkeen ännert oder wegmaakt warrn.
+Wenn du dat nich wullst, dröffst du dien Text hier nich apentlich maken.<br />
+
+Du bestätigst ok, dat du den Text sülvst schreven hest oder ut en „Public Domain“-Born oder en annere fre\'e Born kopeert hest (Kiek ok $1 för Details).
+<strong>Kopeer kene Warken, de enen Oorheverrecht ünnerliggt, ahn Verlööv vun de Copyright-Inhebbers!</strong>',
+
+# Sietenhistorie
+#
+'revhistory'            => 'Fröhere Versionen',
+'nohistory'                     => 'Dor sünd kene fröheren Versionen vun disse Siet.',
+'revnotfound'            => 'Kene fröheren Versionen funnen',
+'revnotfoundtext'      => 'De Version vun disse Siet, no de du söökst, kunn nich funnen warrn. Prööv de URL vun disse Siet.',
+'loadhist'                      => 'Lade List mit freuhere Versionen',
+'currentrev'              => 'Aktuelle Version',
+'revisionasof'          => 'Version vun\'n $1',
+'revisionasofwithlink'  => 'Version vun\'n $1; $2<br />$3 | $4',
+'nextrevision'          => '←Nächstjüngere Version',
+'previousrevision'      => 'Nächstöllere Version→',
+'cur'                           => 'Aktuell',
+'next'                          => 'Tokamen',
+'last'                          => 'Letzte',
+'orig'                                  => 'Original',
+'histlegend'              => 'Ünnerscheed-Utwahl: De Boxen vun de wünschten
+Versionen markeern un \'Enter\' drücken oder den Knoop nerrn klicken/alt-v.<br />
+Legende:
+(Aktuell) = Ünnerscheed to de aktuelle Version,
+(Letzte) = Ünnerscheed to de vörige Version,
+L = Lütte Ännern',
+
+# Ünnerscheed
+#
+'difference'                   => '(Ünnerscheed twüschen Versionen)',
+'loadingrev'                    => 'laad Versionen üm Ünnerscheden to wiesen',
+'lineno'                                => 'Lien $1:',
+'editcurrent'                 => 'De aktuelle Version vun disse Siet bearbeiden',
+'selectnewerversionfordiff' => 'En niegere Version för en Vergliek utwählen',
+'selectolderversionfordiff' => 'En öllere Version för en Vergliek utwählen',
+'compareselectedversions'   => 'Wählte Versionen verglieken',
+
+# Söök
+#
+'searchresults'     => 'Söökresultaten',
+'searchresulttext'  => 'För mehr Informatschonen över {{SITENAME}}, kiek [[{{ns:4}}:Söök|{{SITENAME}} dörsöken]].',
+'searchquery'         => 'För de Söökanfraag „$1“',
+'badquery'                      => 'Falsche Söökanfraag',
+'badquerytext'       => 'De Söökanfraag kunn nich verarbeid warrn.
+Sachts hest du versöökt, en Word to söken, dat kötter as twee Bookstaven is.
+Dit funktschoneert in\'n Momang noch nich.
+Mööglicherwies hest du ok de Anfraag falsch formuleert, to\'n Bispeel \'Lohn un un Stüern\'. Versöök en anners formuleerte Anfraag.',
+'matchtotals'         => 'De Anfraag „$1“ stimmt mit $2 Sietenöverschriften un den Text vun $3 Sieten överein.',
+'nogomatch'         => 'Dor existeert kene Siet mit dissen Naam. Versöök de Vulltextsöök oder legg de Siet <a href=\'$1\'>nieg</a> an. ',
+'titlematches'       => 'Övereenstimmen mit Överschriften',
+'notitlematches'    => 'Kene Övereenstimmen',
+'textmatches'           => 'Övereenstimmen mit Texten',
+'notextmatches'     => 'Kene Övereenstimmen',
+'prevn'                         => 'vörige $1',
+'nextn'                           => 'tokamen $1',
+'viewprevnext'       => 'Wies ($1) ($2) ($3).',
+'showingresults'    => 'Hier sünd <b>$1</b> Resultaten, anfungen mit #<b>$2</b>.',
+'showingresultsnum' => 'Hier sünd <b>$3</b> Resultaten, anfungen mit #<b>$2</b>.',
+'nonefound'                    => '<strong>Henwies</strong>:
+Söökanfragen ahn Spood hebbt faken de Oorsaak, dat no kotte oder gemeene Wöör söökt warrt, de nich indizeert sünd.',
+'powersearch'       => 'Söök',
+'powersearchtext'   => '
+Söök in Naamrüüm:<br />
+
+
+$1<br />
+$2 Wies ok Wiederleiden   Söök no $3 $9',
+'searchdisabled'    => '<p>De Vulltextsöök is wegen Överlast en Stoot deaktiveert. In disse Tied kannst du disse Google-Söök verwennen,
+de aver nich jümmer den aktuellsten Stand weerspegelt.<p>',
+'blanknamespace'     => '(Hööft-)',
+
+# Instellen
+#
+'preferences'          => 'Instellen',
+'prefsnologin'       => 'Nich anmellt',
+'prefsnologintext'   => 'Du muttst [[Special:Userlogin|anmellt]] ween, üm dien Instellen to ännern.',
+'prefslogintext'     => 'Du büst anmellt as „$1“.
+Dien interne ID-Nummer is $2.',
+'prefsreset'            => 'Instellen sünd op Standard trüchsett.',
+'qbsettings'         => 'Sietenliest',
+'changepassword'     => 'Password ännern',
+'skin'                          => 'Utsehn vun de Steed',
+'math'                          => 'TeX',
+'dateformat'         => 'Datumsformat',
+'math_failure'          => 'Parser-Fehler',
+'math_unknown_error'    => 'Unbekannten Fehler',
+'math_unknown_function' => 'Unbekannte Funktschoon ',
+'math_lexing_error'      => '\'Lexing\'-Fehler',
+'math_syntax_error'      => 'Syntaxfehler',
+'saveprefs'                     => 'Instellen spiekern',
+'resetprefs'            => 'Instellen trüchsetten',
+'oldpassword'           => 'Ool Password',
+'newpassword'          => 'Nieg Password',
+'retypenew'                     => 'Nieg Password (nochmal)',
+'textboxsize'          => 'Textfeld-Grött',
+'rows'                              => 'Regen',
+'columns'                       => 'Spalten',
+'searchresultshead'  => 'Söökresultaten',
+'resultsperpage'     => 'Treffer pro Siet',
+'contextlines'          => 'Lienen pro Treffer',
+'contextchars'          => 'Teken pro Lien',
+'stubthreshold'      => 'Kotte Sieten markeeren bet',
+'recentchangescount' => 'Antall „Letzte Ännern“',
+'savedprefs'            => 'Dien Instellen sünd spiekert.',
+'timezonelegend'     => 'Tiedrebeet',
+'timezonetext'          => 'Giff de Antall vun de Stünnen an, de twüschen dien Tiedrebeet un UTC liggen.',
+'localtime'             => 'Oortstied',
+'timezoneoffset'     => 'Ünnerscheed',
+'servertime'         => 'Aktuelle Tied op den Server',
+'guesstimezone'      => 'Ut den Browser övernehmen',
+'emailflag'                     => 'Kene E-Mail vun annere Bruker kriegen',
+'defaultns'                     => 'In disse Naamrüüm schall standardmatig söökt warrn:',
+
+# letzte Ännern
+#
+'changes'            => 'Ännern',
+'recentchanges'      => 'Letzte Ännern',
+'recentchangestext'  => '
+Disse Siet warrt wiel dat Laden automatsch aktualiseert. Wiest warrn Sieten, de toletzt bearbeid worrn sünd, dorto de Tied un de Naam vun de Autor.',
+'rcloaderr'                     => 'Laad Letzte Ännern',
+'rcnote'                        => 'Hier sünd de letzten <b>$1</b> Ännern vun de letzten <b>$2</b> Daag. (<b>N</b> - Niege Sieten; <b>L</b> - Lütte Ännern)',
+'rcnotefrom'            => 'Dit sünd de Ännern siet <b>$2</b> (bet to <b>$1</b> wiest).',
+'rclistfrom'            => 'Wies niege Ännern siet $1',
+'rclinks'                         => 'Wies de letzten $1 Ännern; wies de letzten $2 Daag.',
+'diff'                          => 'Ünnerscheed',
+'hist'                              => 'Versionen',
+'hide'                          => 'Nich wiesen',
+'show'                          => 'Wiesen',
+'tableform'                     => 'Tabell',
+'listform'                       => 'List',
+'nchanges'                       => '$1 Ännern',
+'minoreditletter'    => 'L',
+'newpageletter'      => 'N',
+
+
+# Upload
+#
+'upload'                        => 'Hoochladen',
+'uploadbtn'                    => 'Datei hoochladen',
+'uploadlink'            => 'Biller hoochladen',
+'reupload'                      => 'Nieg hoochladen',
+'reuploaddesc'          => 'Trüch to de Hoochladen-Siet.',
+'uploadnologin'     => 'Nich anmellt',
+'uploadnologintext'     => 'Du muttst [[Spezial:Userlogin|anmellt ween]] üm Datein hoochladen to könen.',
+'uploaderror'         => 'Fehler bi dat Hoochladen',
+'uploadtext'           => "
+Üm hoochladene Biller to söken un antokieken,
+geih to de [[Special:Imagelist|List vun hoochladene Biller]].
+
+Bruuk dat Formular, üm niege Biller hoochtoladen un disse in Sieten to bruken.
+In de mehrsten Browser warrt en „Durchsuchen“-Feld wiest, dat en Standard-Dateidialog apent.
+Wähl de Datei ut, de du hoochladen wullst. De Dateinaam warrt denn in dat Textfeld wiest.
+Bestätig dann den Copyright-Henwies.
+Toletzt muttst du den „Hoochladen“-Knopp klicken.
+Dat kann en Stoot duern, sünnerlich bi en langsamen Internet-Verbinnen.
+
+För Fotos is dat JPEG-Format, för Grafiken un Symbolen dat PNG-Format best.
+Üm en Bild in en Siet to bruken, schriev an Stell vun dat Bild
+'''[[Bild:datei.jpg]]''' oder
+'''[[Bild:datei.jpg|Beschrieven]]'''.
+
+Denk doran, dat, lieks as bi de annern Sieten, annere Bruker dien Datein löschen oder ännern könen.',
+'uploadlog'                => 'Datei-Logbook',
+'uploadlogpage'     => 'Datei-Logbook',
+'uploadlogpagetext' => 'Hier is de List vun de letzten hoochladenen Datein.
+Alle Tieden sünd UTC.
+
+<ul>
+
+</ul>",
+'filename'                      => 'Dateinaam',
+'filedesc'                      => 'Beschrieven',
+'filestatus'        => 'Copyright-Status',
+'filesource'        => 'Born',
+'copyrightpage'     => '{{ns:4}}:Copyright',
+'copyrightpagename' => '{{SITENAME}} Copyright',
+'uploadedfiles'         => 'Hoochladene Datein',
+'ignorewarning'         => 'Warnen ignoreern un Datei liekers spiekern.',
+'minlength'             => 'Bilddatein möten tominnst dree Bookstaven hebben.',
+'badfilename'           => 'De Bildnaam is in „$1“ ännert worrn.',
+'badfiletype'           => '„.$1“ is keen anratenswert Dateiformat.',
+'largefile'             => 'Kene Biller över 100 KByte hoochladen.',
+'emptyfile'                    => 'De hoochladene Datei is leddig. De Grund kann en Tippfehler in de Dateinaam ween. Kontrolleer, of du de Datei redig hoochladen wullst.',
+'fileexists'            => 'En Datei mit dissen Naam existeert al, prööv $1, wenn du di nich seker büst of du dat ännern wullst.',
+'successfulupload'  => 'Datei hoochladen hett Spood',
+'fileuploaded'       => 'Dat Hoochladen vun de Datei „$1“ hett Spood.
+Disse ($2) Link föhrt to de Bildsiet. Dor kann indregen warrn, woneem dat Bild kummt, welkeen dat wann mookt hett un wenn neudig, welkeen Copyright-Status dat Bild hett.',
+'uploadwarning'     => 'Wohrscho',
+'savefile'                      => 'Datei spiekern',
+'uploadedimage'     => '„$1“ hoochladen',
+'uploadcorrupt'     => 'De Datei is korrupt oder hett en falsch Ennen. Datei pröven un nieg hoochladen.',
+'filemissing'           => 'Datei fehlt',
+
+# Billerlist
+#
+'imagelist'               => 'Billerlist',
+'imagelisttext'       => 'Hier is en List vun $1 Biller, sorteert $2.',
+'getimagelist'          => 'Billerlist laden',
+'ilsubmit'                        => 'Söök',
+'showlast'                      => 'Wies de letzten $1 Biller, sorteert $2.',
+'byname'                        => 'no Naam',
+'bydate'                        => 'no Datum',
+'bysize'                        => 'no Grött',
+'imgdelete'                    => 'Löschen',
+'imgdesc'                         => 'Beschrieven',
+'imglegend'                     => 'Legende: (Beschrieven) = Wies/Änner Bildbeschrieven.',
+'imghistory'          => 'Bild-Versionen',
+'revertimg'                     => 'trüchsetten',
+'deleteimg'                    => 'Löschen',
+'deleteimgcompletely'   => 'Löschen',
+'imghistlegend'       => 'Legende: (cur) = Dit is dat aktuelle Bild, (Löschen) = lösch
+disse ole Version, (Trüchsetten) = bruuk weer disse ole Version.',
+'imagelinks'            => 'Bildverwiesen',
+'linkstoimage'          => 'Disse Sieten bruukt dat Bild:',
+'nolinkstoimage'      => 'Kene Siet bruukt dat Bild.',
+'sharedupload'        => 'Disse Datei is en Datei, de mööglicherwies ok vun annere Wikis bruukt warrt.',
+
+
+# Statistik
+#
+'statistics'            => 'Statistik',
+'sitestats'                     => 'Sietenstatistik',
+'userstats'                     => 'Brukerstatistik',
+'sitestatstext'       => 'Dat gifft allens tosamen <b>$1</b> Sieten in de Datenbank.
+Dat slött Diskuschoonsieten, Sieten över {{SITENAME}}, extrem kotte Artikels, Wiederleiden un annere Sieten in, de nich as Artikel gelten köönt.
+Disse utnommen, gifft dat <b>$2</b> Sieten, de as Artikel gelten könen.<p>
+
+
+De Lüüd hebbt <b>$3</b>× Sieten oprufen, un <b>$4</b>× Sieten ännert.
+Dorut ergeven sik <b>$5</b> Ännern pro Siet, un <b>$6</b> Ankieken pro Ännern.',
+'userstatstext'       => 'Dat gifft <b>$1</b> registreert Bruker.
+Dorvun hebbt <b>$2</b> Administrater-Rechten (kiek $3).',
+
+# Maintenance Page
+#
+'maintenance'                           => 'Pleegsieten',
+'maintnancepagetext'            => 'Disse Siet bargt en Reeg praktische Funktschoonen för de dägliche Pleeg vun {{SITENAME}}. En poor vun disse Funktschonen könen de Datenbank bannig in Anspröök nehmen, also nich no elk Ännern nieg laden ;-)',
+'maintenancebacklink'           => 'Trüch to de Pleegsieten',
+'disambiguations'               => 'Begreepklorensieten',
+'disambiguationspage'        => '{{ns:4}}:Begreepkloren',
+'disambiguationstext'           => 'Disse Sieten wiest no en <i>Begreepklorensiet</i>. Se schallen staats dat no de Siet wiesen, de egentlich meent is.<br />En Siet warrt as Begreepklorensiet ansehn, wenn $1 op se verwiest.<br />Verwiesen ut Naamrüüm sünd hier <i>nich</i> oplist.',
+'doubleredirects'                  => 'Dubbelte Wiederleiden',
+'doubleredirectstext'        => '<b>Wohrscho:</b> Disse List kann „falsche Positive“ bargen.
+Dat passeert denn, wenn en Wiederleiden blangen de Wiederleiden-Verwies noch mehr Text mit annere Verwiesen hett.
+De schallen denn löscht warrn. Elk Reeg wiest de eerste un tweete Wiederleiden un de eerste Reeg Text ut de Siet,
+to den vun den tweeten Wiederleiden wiest warrt, un to den de eerste Wiederleiden mehrst wiesen schall.',
+'brokenredirects'            => 'Kaputte Wiederleiden',
+'brokenredirectstext'          => 'Disse Wiederleiden wiesen to en Siet, de nich existeert',
+'selflinks'                             => 'Sieten, de op sik sülvst wiesen',
+'selflinkstext'                     => 'Disse Sieten wiesen op sik sülvst, wat se nich schallt.',
+'mispeelings'                => 'Sieten mit falsch schrevene Wöör',
+'mispeelingstext'            => 'Op disse Sieten kümmt falsch schrevene Wöör vör, de op $1 as falsch defineert sünd.
+In Klammern angevene Wöör geven de korrekte Schrievwies weer.',
+'mispeelingspage'            => 'List vun Tippfehlern',
+'missinglanguagelinks'       => 'Fehlende Spraakverwiesen',
+'missinglanguagelinksbutton' => 'Wies fehlende Spraakverwiesen no',
+'missinglanguagelinkstext'   => 'Disse Sieten hebbt <i>kenen</i> Verwies to ehr Gegenpart in $1. Wiederleiden un Ünnersieten warrn <i>nich</i> wiest.',
+
+
+# Verscheden Spezialsieten
+#
+'orphans'                              => 'Weetsieten',
+'geo'                       => 'GEO-Koordinaten',
+'validate'                            => 'Siet valideern',
+'lonelypages'                   => 'Weetsieten',
+'uncategorizedpages'        => 'Unkategoriseerte Sieten',
+'uncategorizedcategories'       => 'Unkategoriseerte Kategorien',
+'unusedimages'                  => 'Weetbiller',
+'popularpages'                  => 'Faken opropene Sieten',
+'nviews'                            => '$1 Affragen',
+'wantedpages'                   => 'Wünschte Sieten',
+'nlinks'                                => '$1 Verwies',
+'allpages'                            => 'Alle Sieten',
+'randompage'                    => 'Tofällige Siet',
+'randompage-url'          => 'Special:Randompage',
+'shortpages'                 => 'Kotte Sieten',
+'longpages'                     => 'Lange Sieten',
+'listusers'                          => 'Brukerlist',
+'specialpages'                  => 'Spezialsieten',
+'spheading'                             => 'Spezialsieten för alle Bruker',
+'protectpage'               => 'Siet schulen',
+'recentchangeslinked'     => 'Verlinkte Sieten',
+'rclsub'                                => '(op Artikel vun „$1“)',
+'debug'                                 => 'Fehlerkorregeern',
+'newpages'                              => 'Niege Sieten',
+'ancientpages'            => 'Öllste Sieten',
+'move'                    => 'Schuven',
+'movethispage'                  => 'Siet schuven',
+'unusedimagestext'        => 'Denk doran, dat annere Wikis mööglicherwies en poor vun disse Biller bruken.',
+'booksources'               => 'Bookhannel',
+'categoriespagetext'      => 'Disse Kategorien existeern in dissen Wiki',
+'data'                     => 'Daten',
+'booksourcetext'          => 'Dit is en List mit Links to Internetsieten, de niege un bruukte Böker verkööpt.
+Dor kann dat ok mehr Informatschonen över de Böker geven, de di interesseert.
+{{SITENAME}} is mit kenen vun disse Höker warflich verbunnen.',
+'alphaindexline'          => '$1 bet $2',
+'log'                           => 'Logböker',
+'alllogstext'               => 'Kombineerte Ansicht vun Hoochlaad-, Lösch-, Schuul-, Block- un Sysop-Logböker.
+Du kannst de List kötter maken, wenn du den Logtyp, den Brukernaam oder de de Siet angiffst.',
+
+
+# E-Mail an'n Bruker
+#
+'mailnologin'             => 'Du büst nich anmellt.',
+'mailnologintext'       => 'Du muttst [[Spezial:Userlogin|anmellt ween]] un en güllige E-Mail-Adress hebben, dormit du en annern Bruker en E-Mail sennen kannst.',
+'emailuser'                     => 'E-Mail an dissen Bruker',
+'emailpage'                     => 'E-Mail an Bruker',
+'emailpagetext'         => 'Wenn disse Bruker en güllige E-Mail-Adress angeven hett, kannst du em mit den nerrn stahn Formular en E-Mail sennen. As Afsenner warrt de E-Mail-Adress ut dien Instellen indregen, dormit de Bruker di antern kann.',
+'usermailererror'       => 'Dat Mail-Objekt hett en Fehler trüchgeven: ',
+'defemailsubject'       => '{{SITENAME}} E-Mail',
+'noemailtitle'          => 'Kene E-Mail-Adress',
+'noemailtext'             => 'Disse Bruker hett kene güllige E-Mail-Adress angeven, oder will kene E-Mail vun annere Bruker sennt kriegen.',
+'emailfrom'                 => 'Vun',
+'emailto'                       => 'An',
+'emailsubject'          => 'Bedrap',
+'emailmessage'                 => 'Noricht',
+'emailsend'                     => 'Sennen',
+'emailsent'                        => 'E-Mail afsennt',
+'emailsenttext'         => 'Dien E-Mail is afsennt worrn.',
+
+# Special:Allpages
+'nextpage'          => 'tokamen Siet ($1)',
+'allarticles'       => 'Alle Artikels',
+'allpagesprev'      => 'vörig',
+'allpagesnext'      => 'tokamen',
+'allinnamespace' => 'Alle Sieten ($1 Naamruum)',
+'allpagessubmit'    => 'Los',
+
+# Oppasslist
+#
+'watchlist'                     => 'Oppasslist',
+'watchlistsub'           => '(för Bruker „$1“)',
+'nowatchlist'           => 'Du hest kene Indreeg op dien Oppasslist.',
+'watchnologin'            => 'Du büst nich anmellt',
+'watchnologintext'      => 'Du muttst [[Spezial:Userlogin|anmellt]] ween, wenn du dien Oppasslist ännern willst.',
+'addedwatch'            => 'To de Oppasslist hentofögt',
+'addedwatchtext'        => 'De Siet „$1“ is to dien <a href=\'{{localurle:Spezial:Watchlist}}\'>Oppasslist</a> hentofögt worrn.
+Ännern, de in Tokumst an disse Siet un an de toheurige Diskuschoonssiet mookt warrn, sünd dorop list un de Siet is op de
+<a href=\'{{localurle:Spezial:Recentchanges}}\'>List vun de letzten Ännern</a> fett markeert. Wenn du de Siet nich mehr op dien Oppasslist
+hebben wullst, klick op „Nich mehr oppassen“ in de Linklist.',
+'removedwatch'           => 'De Siet is nich mehr op de Oppasslist',
+'removedwatchtext'      => 'De Siet „$1“ is nich mehr op de Oppasslist.',
+'watchthispage'         => 'Op Siet oppassen',
+'unwatchthispage'       => 'Nich mehr oppassen',
+'notanarticle'           => 'Keen Artikel',
+'watchnochange'         => 'Kene Siet, op de du oppasst, is in den wiesten Tiedruum bearbeid worrn.',
+'watchdetails'          => '($1 Sieten sünd op de Oppasslist (ahn Diskuschoonssieten);
+$2 Sieten werrn in de instellte Tied bearbeid;
+$3... [$4 komplette List wiesen un bearbeiden].)',
+'watchmethod-recent'    => 'letzte Ännern no Oppasslist pröven',
+'watchmethod-list'      => 'Oppasslist no letzte Ännern pröven',
+'removechecked'         => 'Markeerte Indreeg löschen',
+'watchlistcontains'     => 'Dien Oppasslist bargt $1 Sieten.',
+'watcheditlist'         => 'Hier is ene alphabetsche List vun de Sieten op de du oppasst. Markeer de Sieten, de vun de Oppasslist löscht warrn schallt un klick den \'markeerte Indreeg löschen\'-Knoop.',
+'removingchecked'       => 'Indreeg warrt vun de Oppasslist löscht...',
+'couldntremove'         => 'De Indrag \'$1\' kann nich löscht warrn...',
+'iteminvalidname'       => 'Problem mit den Indrag \'$1\', ungülligen Naam...',
+'wlnote'                => 'Nerrn steiht de letzten Ännern vun de letzten <b>$2</b> Stünnen.',
+'wlshowlast'            => 'Wies de letzten $1 Stünnen $2 Daag $3',
+'wlsaved'                               => 'Dit is en spiekerte Version vun dien Oppasslist.',
+
+# löschen/schulen/trüchsetten
+#
+'deletepage'               => 'Siet löschen',
+'confirm'                            => 'Bestätigen',
+'excontent'             => "Olen Inholt: '$1'",
+'exbeforeblank'         => "Inholt vör dat Leddigmaken vun de Siet: '$1'",
+'exblank'               => 'Siet weer leddig',
+'confirmdelete'         => 'Löschen bestätigen',
+'deletesub'                     => '(Lösche „$1“)',
+'historywarning'        => 'Wohrscho: De Siet, de du versöökst to löschen, hett en Versionshistorie: ',
+'confirmdeletetext'     => 'Du büst dorbi, en Siet oder en Bild un alle ölleren Versionen duersam ut de Datenbank to löschen.
+Segg to, dat du över de Folgen Bescheed weetst un dat du in Övereenstimmen mit uns [[{{ns:4}}:Leidlienen|Leidlienen]] hannelst.',
+'actioncomplete'        => 'Aktschoon beennt',
+'deletedtext'           => '„$1“ is löscht.
+In $2 kannst du en List vun de letzten Löschen finnen.',
+'deletedarticle'        => '„$1“ löscht',
+'dellogpage'            => 'Lösch-Logbook',
+'dellogpagetext'        => 'Hier is en List vun de letzten Löschen (UTC).
+
+<ul>
+
+</ul>
+',
+'deletionlog'             => 'Lösch-Logbook',
+'reverted'                          => 'Op en ole Version trüchsett',
+'deletecomment'         => 'Grund vun de Löschen',
+'imagereverted'         => 'Op en ole Version trüchsett.',
+'rollback'              => 'Trüchnahm vun de Ännern',
+'rollback_short'        => 'Trüchnehmen',
+'rollbacklink'          => 'Trüchnehmen',
+'rollbackfailed'        => 'Trüchnahm hett kenen Spood',
+'cantrollback'          => 'De Ännern kann nich trüchnahmen warrn; de letzte Autor is de eenzige.',
+'alreadyrolled'         => 'Dat Trüchnehmen vun de Ännern an de Siet [[$1]] vun [[User:$2|$2]]
+([[User_talk:$2|Diskuschoonssiet]]) is nich mööglich, vun wegen dat dor en annere Ännern oder Trüchnahm ween is.
+
+De letzte Ännern is vun [[User:$3|$3]]
+([[User talk:$3|Diskuschoon]])',
+#   blots wiesen wenn dor en Ännerkommentar is
+'editcomment'           => 'De Ännerkommentar weer: <i>$1</i>.',
+'revertpage'            => 'Weerholt to de letzte Ännern vun $1',
+
+# Weerholen
+'undelete'              => 'Löschte Siet weerholen',
+'undeletepage'          => 'Löschte Sieten weerholen',
+'undeletepagetext'      => 'Disse Sieten sünd löscht worrn, aver jümmer noch
+spiekert un könnt weerholt warrn.',
+'undeletearticle'       => 'Löschte Siet weerholen',
+'undeleterevisions'     => '$1 Versionen archiveert',
+'undeletehistory'       => 'Wenn du disse Siet weerholst, warrt ok alle olen Versionen weerholt. Wenn siet dat Löschen en nieg Siet mit lieken
+Naam schreven worrn is, warrt de weerholten Versionen as ole Versionen vun disse Siet wiest.',
+'undeleterevision'      => 'Löschte Version vun de $1',
+'undeletebtn'           => 'Weerholen!',
+'undeletedarticle'      => '„$1“ weerholt',
+'undeletedtext'         => 'De Siet [[$1]] is mit Spood weerholt worrn.',
+
+# Bidreeg
+#
+'contributions'         => 'Brukerbidreeg',
+'mycontris'             => 'Mien Bidreeg',
+'contribsub'               => 'För $1',
+'nocontribs'               => 'Kene Ännern för disse Kriterien funnen.',
+'ucnote'                       => 'Dit sünd de letzten <b>$1</b> Bidreeg vun de Bruker in de letzten <b>$2</b> Doog.',
+'uclinks'                          => 'Wies de letzten $1 Bidreeg; wies de letzten $2 Daag.',
+'uctop'                         => ' (aktuell)',
+'newbies'               => 'Niegling',
+
+# Wat wiest hier hen
+#
+'whatlinkshere'         => 'Wat wiest hierher',
+'notargettitle'         => 'Kene Siet angeven',
+'notargettext'           => 'Du hest nich angeven, op welke Siet du disse Funktschoon anwennen willst.',
+'linklistsub'             => '(List vun de Verwiesen)',
+'linkshere'                     => 'Disse Sieten wiesen hierher:',
+'nolinkshere'             => 'Kene Siet wiest hierher.',
+'isredirect'               => 'Wiederleiden',
+
+# Blocken/nich mehr blocken vun IPs
+#
+'blockip'                            => 'IP-Adress blocken',
+'blockiptext'           => 'Bruuk dat Formular, üm en IP-Adress to blocken.
+Dit schall blots maakt warrn, üm Vandalismus to vermasseln, aver jümmer in Övereenstimmen mit uns [[{{ns:4}}:Leidlienen|Leidlienen]].
+Ok den Grund för dat Blocken indregen.',
+'ipaddress'                     => 'IP-Adress',
+'ipbreason'                     => 'Grund',
+'ipbsubmit'                        => 'Adress blocken',
+'badipaddress'          => 'De IP-Adress hett en falsch Format.',
+'blockipsuccesssub'     => 'Blocken hett Spood',
+'blockipsuccesstext'    => 'De IP-Adress „$1“ is nu blockt.
+
+<br />Op de [[Special:Ipblocklist|IP-Blocklist]] is en List vun alle Blocks to finnen.',
+'unblockip'                     => 'IP-Adress freegeven',
+'unblockiptext'              => 'Bruuk dat Formular, üm en blockte IP-Adress freetogeven.',
+'ipusubmit'                     => 'Disse Adress freegeven',
+'ipusuccess'               => 'IP-Adress „$1“ is freegeven',
+'ipblocklist'           => 'List vun blockte IP-Adressen',
+'blocklistline'              => '$1, $2 hett $3 blockt ($4)',
+'blocklink'                     => 'blocken',
+'unblocklink'             => 'freegeven',
+'contribslink'           => 'Bidreeg',
+'autoblocker'           => 'Automatisch Block, vun wegen dat du en IP-Adress bruukst mit „$1“. Grund: „$2“.',
+
+# Entwickler-Warktüüch
+#
+'lockdb'                        => 'Datenbank sparren',
+'unlockdb'                          => 'Datenbank freegeven',
+'lockdbtext'               => 'Mit de Sparr vun de Datenbank warrt alle Ännern an de Brukerinstellen, Oppasslisten, Sieten un so wieder verhinnert.
+Schall de Datenbank redig sparrt warrn?',
+'unlockdbtext'          => 'Dat Beennen vun de Datenbank-Sparr maakt alle Ännern weer mööglich.
+Schall de Datenbank-Sparr redig beennt warrn?',
+'lockconfirm'           => 'Ja, ik will de Datenbank sparren.',
+'unlockconfirm'         => 'Ja, ik will de Datenbank freegeven.',
+'lockbtn'                            => 'Datenbank sparren',
+'unlockbtn'                        => 'Datenbank freegeven',
+'locknoconfirm'         => 'Du hest dat Bestätigungsfeld nich markeert.',
+'lockdbsuccesssub'      => 'Datenbanksparr hett Spood',
+'unlockdbsuccesssub'    => 'Datenbankfreegaav hett Spood',
+'lockdbsuccesstext'     => 'De {{SITENAME}}-Datenbank is sparrt.
+<br />Du muttst de Datenbank weer freegeven, wenn de Pleegarbeiden beennt sünd.',
+'unlockdbsuccesstext'   => 'De {{SITENAME}}-Datenbank is weer freegeven.',
+
+# Siet schuven
+#
+'movepage'                           => 'Siet schuven',
+'movepagetext'              => 'Mit dissen Formular kannst du en Siet ümnömen, tosamen mit allen Versionen. De ole Titel warrt to den niegen wiederleid. Verwies op den olen Titel warrn nich ännert un de Diskuschoonssiet warrt ok nich mitschuven.',
+'movepagetalktext'      => "De tohören Diskuschoonssiet warrt, wenn een dor is, mitschuuvt, '''mit disse Utnahmen:''
+* Du schuuvst de Siet in en annern Naamruum oder
+* dat existeert al en Diskuschoonssiet mit dissen Naam, oder
+* du wählst de nerrn stahn Optschoon af
+
+In disse Fäll muttst du de Siet, wenn du dat wullst, vun Hand schuven.",
+'movearticle'           => 'Siet schuven',
+'movenologin'           => 'Du büst nich anmellt',
+'movenologintext'       => 'Du muttst en registreert Bruker un
+[[Special:Userlogin|anmellt]] ween,
+üm en Siet to schuven.',
+'newtitle'                     => 'To niegen Titel',
+'movepagebtn'             => 'Siet schuven',
+'pagemovedsub'              => 'Schuven hett Spood',
+'pagemovedtext'         => 'Siet „[[$1]]“ no „[[$2]]“ schuuvt.',
+'articleexists'         => 'Ünner dissen Naam existeert al en Siet.
+Bitte wähl en annern Naam.',
+'talkexists'            => 'Dat Schuven vun de Siet sülvst hett Spood, aver dat Schuven vun de
+Diskuschoonssiet nich, vun wegen dat dor al en Siet mit dissen Titel existeert. De Inholt muss vun Hand anpasst warrn.',
+'movedto'                       => 'schuven no',
+'1movedto2_redir'       => '$1 schuven no $2 över Wiederleiden',
+'movetalk'                   => 'De Diskuschoonssiet ok schuven, wenn mööglich.',
+'talkpagemoved'         => 'De Diskuschoonssiet is ok schuven worrn.',
+'talkpagenotmoved'      => 'De Diskuschoonssiet is <strong>nich</strong> schuven worrn.',
+
+'export'                => 'Sieten exporteern',
+'exporttext'            => 'Du kannst de Text un de Bearbeidenshistorie vun een oder mehr Sieten no XML exporteern. Dat Resultat kann in en annern Wiki mit WikiMedia-Software inspeelt warrn, bearbeid oder archiveert warrn.',
+'exportcuronly'         => 'Blots de aktuelle Version vun de Siet exporteern',
+'missingimage'          => '<b>Bild fehlt</b><br /><i>$1</i>',
+
+#Tooltips:
+'tooltip-watch'         => 'Op disse Siet oppassen. [alt-w]',
+'tooltip-search'        => 'Söken [alt-f]',
+'tooltip-minoredit'     => 'Disse Ännern as lütt markeern. [alt-i]',
+'tooltip-save'          => 'Ännern spiekern [alt-s]',
+'tooltip-preview'       => 'Vörschau vun de Ännern an disse Siet. Bruuk dat vör dat Spiekern. [alt-p]',
+'tooltip-compareselectedversions' => 'Ünnerscheed twüschen twee utwählte Versionen vun disse Siet verglieken. [alt-v]',
+
+#Tastatur-Shortcuts
+'accesskey-search'                  => 'f',
+'accesskey-minoredit'               => 'i',
+'accesskey-save'                    => 's',
+'accesskey-preview'                 => 'p',
+'accesskey-compareselectedversions' => 'v',
+
+'makesysoptitle'        => 'Maak en Bruker to en Administrater',
+'makesysoptext'         => 'Disse Mask warrt vun Bürokraten bruukt, üm normale Bruker to Administratern to maken.',
+'makesysopname'         => 'Naam vun de Bruker:',
+'makesysopsubmit'       => 'Maak dissen Bruker to en Administrater',
+'makesysopok'           => '<b>Bruker „$1“ is nu en Administrater.</b>',
+'makesysopfail'         => '<b>Bruker „$1“ kunn nich to en Administrater maakt warrn. (Is de Naam richtig schreven?)</b>',
+'makesysop'             => 'Maak en Bruker to en Administrater',
+'setbureaucratflag'     => 'Bürokraten-Flagg setten',
+'bureaucratlog'         => 'Bürokraten-Logbook',
+'bureaucratlogentry'       => 'Rechten för Bruker „$1“ op „$2“ sett',
+'rights'                        => 'Rechten:',
+'set_user_rights'             => 'Brukerrechten setten',
+'user_rights_set'       => '<b>Brukerrechten för „$1“ aktualiseert</b>',
+'set_rights_fail'             => '<b>Brukerrechten för „$1“ kunnen nich sett warrn. (Is de Naam richtig schreven?)</b>',
+'1movedto2'                        => '$1 is no $2 schuven worrn',
+'allmessages'                    => 'Alle MediaWiki-Norichten',
+'allmessagestext'             => 'Dit is en List vun alle mööglichen Norichten in den MediaWiki-Naamruum.',
+'thumbnail-more'               => 'vergröttern',
+'and'                                   => 'un',
+'rchide'                        => 'in $4 form; $1 lütte Ännern; $2 sekundäre Naamrüüm; $3 mehrfache Ännern.',
+'showhideminor'                 => 'lütte Ännern $1 | $2 bots | $3 logged in users | $4 patrolled edits',
+'rcliu'                               => '$1 Ännern dör inloggte Bruker',
+'uploaddisabled'               => 'Dat Hoochladen is deaktiveert.',
+'deadendpages'                  => 'Sackstraatsieten',
+'intl'                          => 'Interwiki-Links',
+'version'                            => 'Version',
+'protectlogpage'               => 'Sietenschuul-Logbook',
+'protectlogtext'        => 'Dit is en List vun de blockten Sieten. Kiek [[{{ns:4}}:Schulte Sieten]] för mehr Informatschonen.',
+'protectedarticle'      => 'Siet $1 schuult',
+'unprotectedarticle'    => 'Siet $1 freegeven',
+'protectsub'            =>'(Sparren vun „$1“)',
+'confirmprotecttext'    => 'Schall disse Siet redig schuult warrn?',
+'ipbexpiry'                        => 'Aflöptied',
+'blocklogpage'                  => 'Brukerblock-Logbook',
+'blocklogentry'         => 'block [[User:$1]] - ([[Special:Contributions/$1|Bidreeg]]) för en Tiedruum vun: $2',
+'blocklogtext'                  => 'Dit is en Logbook över Blocks un Freegaven vun Brukern. Automatisch blockte IP-Adressen sünd nich opföhrt.
+Kiek [[Special:Ipblocklist|IP-Blocklist]] för en List vun den blockten Brukern.',
+'unblocklogentry'             => 'Block vun [[User:$1]] ophoven',
+'range_block_disabled'   => 'De Mööglichkeit, ganze Adressrüüm to sparren, is nich aktiveert.',
+'ipb_expiry_invalid'       => 'De angeven Aflöptied is ungüllig.',
+'ip_range_invalid'           => 'Ungüllig IP-Addressrebeet.',
+'confirmprotect'        => 'Sparr bestätigen',
+'protectcomment'        => 'Grund för de Sparr',
+'unprotectsub'                  => '(Beennen vun de Sparr vun „$1“)',
+'confirmunprotecttext'  => 'Schall de Sparr vun disse Siet redig beennt warrn?',
+'confirmunprotect'           => 'De Sparr beennen',
+'unprotectcomment'           => 'Grund för dat Beennen vun de Sparr',
+'proxyblocker'          => 'Proxyblocker',
+'proxyblockreason'      => 'Dien IP-Adress is blockt, vun wegen dat se en apenen Proxy is.
+Kontakteer dien Provider oder diene Systemtechnik un informeer se över dat möögliche Sekerheitsproblem.',
+'proxyblocksuccess'     => 'Fardig.',
+'math_image_error'           => 'dat Konverteern no PNG hett kenen Spood.',
+'math_bad_tmpdir'       => 'Kann dat Temporärverteken för mathematsche Formeln nich anleggen oder beschrieven.',
+'math_bad_output'             => 'Kann dat Teelverteken för mathematsche Formeln nich anleggen oder beschrieven.',
+'math_notexvc'                  => 'Dat texvc-Programm kann nich funnen warrn. Kiek ok math/README.',
+'prefs-personal'        => 'Brukerdaten',
+'prefs-rc'              => 'Letzte Ännern un Wiesen vun kotte Sieten',
+'prefs-misc'            => 'Verscheden Instellen',
+'import'                => 'Sieten importeern',
+'importtext'            => 'Exporteer de Siet vun dat Utgangswiki mit Special:Export un laad de Datei denn över disse Siet weer hooch.',
+'importfailed'          => 'Import hett kenen Spood: $1',
+'importnotext'          => 'Leddig oder keen Text',
+'importsuccess'                => 'Import hett Spood!',
+'importhistoryconflict' => 'Dor sünd al öllere Versionen, de mit dissen kollideert. (Mööglicherwies is de Siet al vörher importeert worrn)',
+'isbn'                                  => 'ISBN',
+'rfcurl'                              => 'http://www.faqs.org/rfcs/rfc$1.html',
+'siteuser'              => '{{SITENAME}}-Bruker $1',
+'siteusers'             => '{{SITENAME}}-Bruker $1',
+'watch'                 => 'Oppassen',
+'unwatch'               => 'nich mehr oppassen',
+'edit'                  => 'ännern',
+'talk'                  => 'Diskuschoon',
+'infobox'               => 'Klick en Knoop, üm en Bispeeltext wiest to kriegen.',
+'infobox_alert'         => 'Giff den Text in, den du formateert hebben wullst.\He warrt denn in de Infobox wiest un du kannst den Text denn kopeern.\Bispeel:\$1\warrt to\$2',
+'nocookiesnew'          => 'De Brukertogang is anleggt, aver du büst nich inloggt. {{SITENAME}} bruukt för disse Funktschoon Cookies, aktiveer de Cookies un logg di denn mit dien nieg Brukernaam un den Password in.',
+'nocookieslogin'        => '{{SITENAME}} bruukt Cookies för dat Inloggen vun de Bruker. Du hest Cookies deaktiveert, aktiveer de Cookies un versöök dat noch eenmal.',
+'subcategorycount'      => 'Disse Kategorie hett $1 Ünnerkategorien.',
+'subcategorycount1'     => 'To disse Kategorie höört $1 Ünnerkategorie.',
+'categoryarticlecount'  => 'To disse Kategorie höört $1 Sieten.',
+'categoryarticlecount1' => 'To disse Kategorie höört $1 Siet.',
+
+# Math
+'mw_math_png'           => 'Jümmer as PNG dorstellen',
+'mw_math_simple'        => 'Eenfach TeX as HTML dorstellen, sünst PNG',
+'mw_math_html'          => 'Wenn mööglich as HTML dorstellen, sünst PNG',
+'mw_math_source'        =>'As TeX laten (för Textbrowser)',
+'mw_math_modern'        => 'Anratenswert för moderne Browser',
+'mw_math_mathml'        => 'MathML (experimentell)',
+
+# Infosiet
+'infosubtitle'          => 'Informatschonen för de Siet',
+'numedits'              => 'Antall vun Ännern (Siet): $1',
+'numtalkedits'          => 'Antall vun Ännern (Diskuschoonssiet): $1',
+'numwatchers'           => 'Antall vun Oppassers: $1',
+'numauthors'            => 'Antall vun verschedene Autoren (Siet): $1',
+'numtalkauthors'        => 'Antall vun verschedene Autoren (Diskuschoonssiet): $1',
+
+# Tooltip help for some actions, most are in Monobook.js
+'tooltip-search'        => 'In dissen Wiki söken [alt-f]',
+'tooltip-minoredit'     => 'Dit as en lütt Ännern markeern [alt-i]',
+'tooltip-save'          => 'Dien Ännern spiekern [alt-s]',
+'tooltip-preview'       => 'Vörschau för dien Ännern, bruuk dat vör dat Spiekern. [alt-p]',
+'tooltip-compareselectedversions' => 'De Ünnerscheed twüschen de twee wählten Versionen vun disse Siet ankieken. [alt-v]',
+
+# Stilvörlagen
+
+'Monobook.css'          => '/* disse Datei editeern üm den Monobook-Skin för de ganze Siet antopassen */',
+#'Monobook.js'          => '/* disse Datei editeern üm js-Saken in den Monobook-Skin to ännern */',
+
+# Monobook.js: tooltips and access keys for monobook
+'Monobook.js'           => '/* Tooltips un Togriepslötel */
+ta = new Object();
+ta[\'pt-userpage\'] = new Array(\'.\',\'Mien Brukersiet\');
+ta[\'pt-anonuserpage\'] = new Array(\'.\',\'De Brukersiet för de IP-Adress ünner de du schriffst\');
+ta[\'pt-mytalk\'] = new Array(\'n\',\'Mien Diskuschoonssiet\');
+ta[\'pt-anontalk\'] = new Array(\'n\',\'Diskuschoon över Ännern vun disse IP-Adress\');
+ta[\'pt-preferences\'] = new Array(\'\',\'Mien Instellen\');
+ta[\'pt-watchlist\'] = new Array(\'l\',\'Mien Oppasslist\');
+ta[\'pt-mycontris\'] = new Array(\'y\',\'List vun mien Bidreeg\');
+ta[\'pt-login\'] = new Array(\'o\',\'Du kannst di geern anmellen, dat is aver nich neudig, üm Sieten to bearbeiden.\');
+ta[\'pt-anonlogin\'] = new Array(\'o\',\'Du kannst di geern anmellen, dat is aver nich neudig, üm Sieten to bearbeiden.\');
+ta[\'pt-logout\'] = new Array(\'o\',\'Afmellen\');
+ta[\'ca-talk\'] = new Array(\'t\',\'Diskuschoon över disse Siet\');
+ta[\'ca-edit\'] = new Array(\'e\',\'Du kannst disse Siet ännern. Bruuk dat vör dat Spiekern.\');
+ta[\'ca-addsection\'] = new Array(\'+\',\'En Kommentar to disse Diskuschoonssiet hentofögen.\');
+ta[\'ca-viewsource\'] = new Array(\'e\',\'Disse Siet is schuult. Du kannst den Borntext ankieken.\');
+ta[\'ca-history\'] = new Array(\'h\',\'Historie vun disse Siet.\');
+ta[\'ca-protect\'] = new Array(\'=\',\'Disse Siet schulen\');
+ta[\'ca-delete\'] = new Array(\'d\',\'Disse Siet löschen\');
+ta[\'ca-undelete\'] = new Array(\'d\',\'Weerholen vun de Siet, so as se vör dat löschen ween is\');
+ta[\'ca-move\'] = new Array(\'m\',\'Disse Siet schuven\');
+ta[\'ca-watch\'] = new Array(\'w\',\'Disse Siet to de Oppasslist hentofögen\');
+ta[\'ca-unwatch\'] = new Array(\'w\',\'Disse Siet vun de Oppasslist löschen\');
+ta[\'search\'] = new Array(\'f\',\'In dissen Wiki söken\');
+ta[\'p-logo\'] = new Array(\'\',\'Hööftsiet\');
+ta[\'n-mainpage\'] = new Array(\'z\',\'Besöök de Hööftsiet\');
+ta[\'n-portal\'] = new Array(\'\',\'över dat Projekt, wat du doon kannst, woans du de Saken finnen kannst\');
+ta[\'n-currentevents\'] = new Array(\'\',\'Achtergrünn to aktuellen Schehn finnen\');
+ta[\'n-recentchanges\'] = new Array(\'r\',\'List vun de letzten Ännern in dissen Wiki.\');
+ta[\'n-randompage\'] = new Array(\'x\',\'Tofällige Siet\');
+ta[\'n-help\'] = new Array(\'\',\'Hier kriegst du Hülp.\');
+ta[\'n-sitesupport\'] = new Array(\'\',\'Gaven\');
+ta[\'t-whatlinkshere\'] = new Array(\'j\',\'Wat wiest hierher\');
+ta[\'t-recentchangeslinked\'] = new Array(\'k\',\'Verlinkte Sieten\');
+ta[\'feed-rss\'] = new Array(\'\',\'RSS-Feed för disse Siet\');
+ta[\'feed-atom\'] = new Array(\'\',\'Atom-Feed för disse Siet\');
+ta[\'t-contributions\'] = new Array(\'\',\'List vun de Bidreeg vun dissen Bruker\');
+ta[\'t-emailuser\'] = new Array(\'\',\'En E-Mail an dissen Bruker sennen\');
+ta[\'t-upload\'] = new Array(\'u\',\'Biller oder Mediendatein hoochladen\');
+ta[\'t-specialpages\'] = new Array(\'q\',\'List vun alle Spezialsieten\');
+ta[\'ca-nstab-main\'] = new Array(\'c\',\'Siet ankieken\');
+ta[\'ca-nstab-user\'] = new Array(\'c\',\'Brukersiet ankieken\');
+ta[\'ca-nstab-media\'] = new Array(\'c\',\'Mediensiet ankieken\');
+ta[\'ca-nstab-special\'] = new Array(\'\',\'Dit is en Spezialsiet, du kannst disse Siet nich ännern.\');
+ta[\'ca-nstab-wp\'] = new Array(\'a\',\'Portalsiet ankieken\');
+ta[\'ca-nstab-image\'] = new Array(\'c\',\'Bildsiet ankieken\');
+ta[\'ca-nstab-mediawiki\'] = new Array(\'c\',\'Systemnorichten ankieken\');
+ta[\'ca-nstab-template\'] = new Array(\'c\',\'Vörlaag ankieken\');
+ta[\'ca-nstab-help\'] = new Array(\'c\',\'Hülpsiet ankieken\');
+ta[\'ca-nstab-category\'] = new Array(\'c\',\'Kategoriesiet ankieken\');',
+
+# Billerlöschen
+'deletedrevision' => 'Löschte ole Version $1.',
+
+# Ünnerscheed ankieken
+'previousdiff'                          => '← Geih to den vörigen Ünnerscheed',
+'nextdiff'                              => 'Geih to den tokamen Ünnerscheed →',
+
+'imagemaxsize'                          => 'Biller op de Bildbeschrievensiet begrenzen op: ',
+'showbigimage'                          => 'Version mit högere Oplösen dolladen ($1x$2, $3 KB)',
+
+'newimages'                             => 'Galeree vun niege Biller',
+
+
+# Validatschoon
+'val_clear_old'                         => 'Maak mien annere Validatschoonsdaten för $1 weg.',
+'val_merge_old'                         => 'Bruuk mien vörige Bewerten, wo „Keen Meenen“ wählt is.',
+'val_form_note'                         => '<b>Henwies:</b> Tosamenfögen vun dien Daten meent, dat för disse
+wählte Artikelrevision alle Optschonen, bi de du „Keen Meenen“ angeven hest,
+op den Wert un den Kommentar sett warrn, de du ok för de jüngste Revision angeven hest.
+To\'n Bispeel, wenn du en enkelt Optschoon för en jüngere Revision ännern wullst, aver ok dien annere Instellen
+för dissen Artikel in disse Revision beholen wullst, denn wähl de Optschoon, die du ännern wullst un Tosamenfögen
+sett de annern Optschonen mit dien vörige Instellen.',
+'val_noop'                              => 'Keen Meenen',
+'val_percent'                           => '<b>$1 %</b><br />($2 vun $3 Punkten<br />by $4 Brukers)',
+'val_percent_single'                    => '<b>$1 %</b><br />($2 vun $3 Punkten<br />by een Bruker)',
+'val_total'                             => 'All',
+'val_version'                           => 'Version',
+'val_tab'                               => 'Valideern',
+'val_this_is_current_version'           => 'Dit is de aktuelle Version',
+'val_version_of'                        => 'Version vun $1' ,
+'val_table_header'                      => '<tr><th>Klass</th>$1<th colspan=4>Meenen</th>$1<th>Kommentar</th></tr>',
+'val_stat_link_text'                    => 'Validatschoonsstatistik för dissen Artikel',
+'val_view_version'                      => 'Disse Version ankieken',
+'val_validate_version'                  => 'Disse Version valideern',
+'val_user_validations'                  => 'Dit Bruker hett $1 Sieten valideert.',
+'val_no_anon_validation'                => 'Du muttst inloggt ween, üm en Artikel to valideern.',
+'val_validate_article_namespace_only'   => 'Blots Artikels könt valideert warrn. Disse Siet is <i>nich</i> in de Artikel-Naamruum.',
+'val_validated'                         => 'Validatschoon fardig.',
+'val_article_lists'                     => 'List vun valideerte Artikels',
+'val_page_validation_statistics'        => 'Sietenvalideer-Statistik för $1',
+
+# Schalttafel
+'editgroup'                             => 'Grupp bearbeiden',
+'addgroup'                              => 'Grupp hentofögen',
+
+'editusergroup'                         => 'Brukergruppen bearbeiden',
+
+# Gruppen bearbeiden
+'savegroup'                             => 'Grupp spiekern',
+
+# Brukergruppen bearbeiden
+'saveusergroups'                        => 'Brukergruppen spiekern',
+
+# Metadata
+'nodublincore'                          => 'Dublin-Core-RDF-Metadaten sünd för dissen Server nich aktiveert.',
+'nocreativecommons'                     => 'Creative-Commons-RDF-Metadaten sünd för dissen Server nich aktiveert.',
+'notacceptable'                         => 'Dat Wiki-Server kann kene Daten in enen Format levern, dat dien Klient lesen kann.',
+
+# Attributschoon
+
+'anonymous'                             => 'Anonyme Bruker vun {{SITENAME}}',
+'siteuser'                              => '{{SITENAME}}-Bruker $1',
+'lastmodifiedby'                        => 'Disse Siet weer dat letzte Maal $1 vun $2 ännert.',
+'othercontribs'                         => 'Grünnt op Arbeid vun $1.',
+'others'                                => 'annere',
+'siteusers'                             => '{{SITENAME}}-Bruker $1',
+'creditspage'                           => 'Sieten-Autoren',
+'nocredits'                             => 'Dor is keen Autorenlist för disse Siet verfögbor.',
+
+# Spamschild
+
+'spamprotectiontitle'                   => 'Spamschild',
+'spamprotectiontext'                    => 'De Siet, de du spiekern wullst, weer vun de Spamschild blockt. Dat kann vun en Link to en externe Siet kamen.',
+'spamprotectionmatch'                   => 'Dit Text hett den Spamschild utlöst: $1',
+'usenewcategorypage'                    => '1Sett dat eerste Teken op \'0\' üm dat niege Kategoriesieten-Utsehn to aktiveern.',
+'listingcontinuesabbrev'                => ' wieder',
+
+# Patrolleern
+'markaspatrolleddiff'       => 'As patrolleert markeern',
+'markaspatrolledlink'       => '[$1]',
+'markaspatrolledtext'       => 'Disse Siet as patrolleert markeern',
+'markedaspatrolled'         => 'As patrolleert markeert',
+'markedaspatrolledtext'     => 'Disse Revision is as patrolleert markeert.',
+'rcpatroldisabled'          => 'Letzte-Ännern-Patrol nich aktiveert',
+'rcpatroldisabledtext'      => 'De Letzte-Ännern-Patrol-Funktschoon is in\'n Momang nich aktiveert.',
+
+# Naamruum 8
+
+'allmessages'                   => 'Alle Systemnorichten',
+'allmessagestext'                 => 'Dit is en List vun alle Systemnorichten, de in de MediaWiki:-Naamruum verfögbor sünd.',
+'allmessagesnotsupportedUI' => 'Dien aktuelle Snittstellenspraak <b>$1</b> warrt vun Special:AllMessages op disse Steed nich ünnerstütt. ',
+'allmessagesnotsupportedDB' => 'Special:AllMessages is nich ünnerstütt, vun wegen dat wgUseDatabaseMessages utstellt is.',
+
+);
+
+class LanguageNds extends LanguageUtf8 {
+
+       function getBookstoreList() {
+               global $wgBookstoreListNds;
+               return $wgBookstoreListNds;
+       }
+
+       function getNamespaces() {
+               global $wgNamespaceNamesNds;
+               return $wgNamespaceNamesNds;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsNds;
+               return $wgQuickbarSettingsNds;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesNds;
+               return $wgSkinNamesNds;
+       }
+
+       function date( $ts, $adj = false ) {
+               if ( $adj ) { $ts = $this->userAdjust( $ts ); }
+
+               $d = (0 + substr( $ts, 6, 2 )) . '. ' .
+               $this->getMonthAbbreviation( substr( $ts, 4, 2 ) ) .
+                 ' ' .
+                 substr( $ts, 0, 4 );
+               return $d;
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesNds;
+               if( isset( $wgAllMessagesNds[$key] ) ) {
+                       return $wgAllMessagesNds[$key];
+               } else {
+                       return parent::getMessage( $key );
+               }
+       }
+
+       function formatNum( $number, $year = false ) {
+               return $year ? $number : strtr($this->commafy($number), '.,', ',.' );
+       }
+}
+
+?>
diff --git a/languages/LanguageNl.php b/languages/LanguageNl.php
new file mode 100644 (file)
index 0000000..10116e5
--- /dev/null
@@ -0,0 +1,800 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+#
+# Nederlands localisation for MediaWiki
+#
+# This file is encoded in UTF-8, no byte order mark.
+# For compatibility with Latin-1 installations, please
+# don't add literal characters above U+00ff.
+#
+
+require_once( "LanguageUtf8.php" );
+
+/* private */ $wgNamespaceNamesNl = array(
+       NS_MEDIA                        => "Media",
+       NS_SPECIAL                      => "Speciaal",
+       NS_MAIN                         => "",
+       NS_TALK                         => "Overleg",
+       NS_USER                         => "Gebruiker",
+       NS_USER_TALK            => "Overleg_gebruiker",
+       NS_PROJECT                      => $wgMetaNamespace,
+       NS_PROJECT_TALK         => "Overleg_$wgMetaNamespace",
+       NS_IMAGE                        => "Afbeelding",
+       NS_IMAGE_TALK           => "Overleg_afbeelding",
+       NS_MEDIAWIKI            => "MediaWiki",
+       NS_MEDIAWIKI_TALK       => "Overleg_MediaWiki",
+       NS_TEMPLATE                     => "Sjabloon",
+       NS_TEMPLATE_TALK        => "Overleg_sjabloon",
+       NS_HELP                         => "Help",
+       NS_HELP_TALK            => "Overleg_help",
+       NS_CATEGORY                     => "Categorie",
+       NS_CATEGORY_TALK        => "Overleg_categorie"
+
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgQuickbarSettingsNl = array(
+ "Uitgeschakeld", "Links vast", "Rechts vast", "Links zwevend"
+);
+
+/* private */ $wgSkinNamesNl = array(
+       'standard' => "Standaard",
+       'nostalgia' => "Nostalgie",
+       'cologneblue' => "Keuls blauw",
+) + $wgSkinNamesEn;
+
+
+
+/* private */ $wgAllMessagesNl = array(
+# User Toggles
+
+"tog-underline" => "Links onderstrepen",
+"tog-highlightbroken" => "Links naar lege pagina's laten oplichten",
+"tog-justify" => "Paragrafen uitvullen",
+"tog-hideminor" => "Kleine wijzigingen verbergen in recente wijzigingen",
+"tog-usenewrc" => "Gebruik de uitgebreide Recente Wijzigingen-pagina (niet op alle browsers mogelijk)",
+"tog-numberheadings" => "Koppen automatisch nummeren",
+"tog-showtoolbar" => "Show edit toolbar",
+"tog-editondblclick" => "Dubbelklikken levert bewerkingspagina (vereist JavaScript)",
+"tog-editsection" => "Maak het bewerken van deelpagina's mogelijk",
+"tog-showtoc" => "Geef een inhoudsopgave (van pagina's met minstens 3 tussenkoppen)",
+"tog-rememberpassword" => "Wachtwoord onthouden",
+"tog-editwidth" => "Bewerkingsveld over volle breedte",
+"tog-watchdefault" => "Artikelen die u wijzigt automatisch volgen",
+"tog-minordefault" => "Maak 'kleine' veranderingen mijn standaard",
+"tog-previewontop" => "Toon controlepagina boven bewerkingsveld",
+"tog-nocache" => "Gebruik geen caching",
+
+# Dates
+'sunday' => 'zondag',
+'monday' => 'maandag',
+'tuesday' => 'dinsdag',
+'wednesday' => 'woensdag',
+'thursday' => 'donderdag',
+'friday' => 'vrijdag',
+'saturday' => 'zaterdag',
+'january' => 'januari',
+'february' => 'februari',
+'march' => 'maart',
+'april' => 'april',
+'may_long' => 'mei',
+'june' => 'juni',
+'july' => 'juli',
+'august' => 'augustus',
+'september' => 'september',
+'october' => 'oktober',
+'november' => 'november',
+'december' => 'december',
+'jan' => 'jan',
+'feb' => 'feb',
+'mar' => 'mrt',
+'apr' => 'apr',
+'may' => 'mei',
+'jun' => 'jun',
+'jul' => 'jul',
+'aug' => 'aug',
+'sep' => 'sep',
+'oct' => 'okt',
+'nov' => 'nov',
+'dec' => 'dec',
+
+
+# Bits of text used by many pages:
+# Diverse stukjes tekst
+"categories" => "Rubrieken",
+"category" => "rubriek",
+"category_header" => "Artikelen in rubriek \"$1\"",
+"subcategories" => "Onderrubrieken",
+"linktrail" => "/^((?:[a-z]|ä|ö|ü|ï|ë|é|è|à)+)(.*)\$/sD",
+"mainpage"  => "Hoofdpagina",
+"mainpagetext" => "Installatie van de Wiki software geslaagd.",
+"about"   => "Info",
+"aboutsite"      => "Over {{SITENAME}}",
+"aboutpage"  => "{{ns:4}}:info",
+"help"   => "Help",
+"helppage"  => "{{ns:4}}:Help",
+"bugreports" => "Foutenrapportage",
+"sitesupport" => "Financieel bijdragen",
+"bugreportspage" => "{{ns:4}}:Foutenrapportage",
+"faq"   => "FAQ",
+"faqpage"  => "{{ns:4}}:Veel gestelde vragen",
+"edithelp"  => "Hulp bij bewerken",
+"edithelppage" => "{{ns:4}}:Instructies",
+"cancel"  => "Annuleren",
+"qbfind"  => "Zoeken",
+"qbbrowse"  => "Bladeren",
+"qbedit"  => "Bewerken",
+"qbpageoptions" => "Pagina-opties",
+"qbpageinfo" => "Pagina-informatie",
+"qbmyoptions" => "Mijn opties",
+"mypage"  => "Mijn gebruikerspagina",
+"mytalk"  => "Mijn overleg",
+"currentevents" => "In het nieuws",
+"errorpagetitle" => "Fout",
+"returnto"  => "Terugkeren naar $1.",
+"tagline"       => " ",
+"whatlinkshere" => "Pagina's die hierheen verwijzen",
+"help"   => "Help",
+"search"  => "Zoeken",
+"go" => "Ga naar pagina",
+"history"  => "Voorgeschiedenis",
+"printableversion" => "Printer-vriendelijke versie",
+"editthispage" => "Pagina bewerken",
+"deletethispage" => "Verwijderen",
+"protectthispage" => "Beveiligen",
+"unprotectthispage" => "Beveiliging opheffen",
+"newpage" => "Nieuwe pagina",
+"talkpage"  => "Overlegpagina",
+"postcomment" => "Schrijf commentaar",
+"subjectpage" => "Artikel",
+"articlepage"   => "Artikel",
+"userpage" => "Gebruikerspagina",
+"wikipediapage" => "Artikel",
+"imagepage" => "Beschrijvingspagina",
+"viewtalkpage" => "Bekijk de overlegpagina",
+"otherlanguages" => "Andere talen",
+"redirectedfrom" => "(Doorverwezen vanaf $1)",
+"lastmodified" => "De laatste wijziging op deze pagina vond plaats op $1.",
+"viewcount"  => "Deze pagina werd $1 maal bekeken. ",
+"printsubtitle" => "(Uit {{SERVER}})",
+"protectedpage" => "Beveiligde pagina",
+"administrators" => "{{ns:4}}:Systeembeheerders",
+"sysoptitle" => "Toegang alleen voor systeembeheerders",
+"sysoptext"  => "De gevraagde handeling kan enkel uitgevoerd worden door systeembeheerders. Zie $1.",
+"developertitle" => "Toegang alleen voor systeemontwikkelaars",
+"developertext" => "De gevraagde handeling kan enkel uitgevoerd worden door systeemontwikkelaars. Zie $1.",
+"nbytes"  => "$1 bytes",
+"go"   => "OK",
+"ok"   => "OK",
+"sitetitle"  => "<span style=\"text-transform: none\">{{SITENAME}} NL</span>", # Okay, HERE's an ugly hack. There should be a cleaner way to do this.
+"sitesubtitle" => "De vrije encyclopedie",
+"retrievedfrom" => "Afkomstig van {{SITENAME}} NL, de Vrije Encyclopedie. \"$1\"",
+"newmessages" => "U heeft $1.",
+"newmessageslink" => "een nieuw bericht",
+"editsection" => "bewerken",
+"toc" => "Inhoud",
+"showtoc" => "Tonen",
+"hidetoc" => "Niet tonen",
+"thisisdeleted" => "$1 bekijken of terugbrengen?",
+"restorelink" => "$1 verwijderde versies",
+
+# Main script and global functions
+# Algemene functies
+"nosuchaction" => "Gevraagde handeling bestaat niet",
+"nosuchactiontext" => "De door de URL gespecifieerde handeling wordt niet herkend door de {{SITENAME}} software",
+"nosuchspecialpage" => "De gevraagde speciale pagina is onvindbaar",
+"nospecialpagetext" => "U heeft een speciale pagina aangevraagd die niet wordt herkend door de {{SITENAME}} software",
+
+# General errors
+# Algemene foutmeldingen
+"error"   => "Fout",
+"databaseerror" => "Database fout",
+"dberrortext" => "Bij het zoeken is een syntaxfout in de database opgetreden.
+De laatste zoekpoging in de database was:
+<blockquote><tt>$1</tt></blockquote>
+vanuit de functie \"<tt>$2</tt>\".
+MySQL gaf the foutmelding \"<tt>$3: $4</tt>\".",
+"dberrortextcl" => "Bij het opvragen van de database is een syntaxfout opgetreden. De laatste opdracht was:
+\"$1\"
+Vanuit de functie \"$2\"
+MySQL gaf de volgende foutmelding: \"$3: $4\".\n",
+"noconnect"  => "De database is momenteel niet bereikbaar.",
+"nodb"   => "Selectie van database $1 niet mogelijk",
+"cachederror" => "Hieronder wordt een versie uit de cache getoond. Dit is mogelijk niet de meest recente versie.",
+"readonly"  => "Database geblokeerd",
+"enterlockreason" => "Geef een reden voor de blokkering en hoelang het waarschijnlijk gaat duren. De ingegeven reden zal aan de gebruikers getoond worden.",
+"readonlytext" => "De database van {{SITENAME}} is momenteel gesloten voor nieuwe bewerkingen en wijzigingen, waarschijnlijk voor bestandsonderhoud.
+De verantwoordelijke systeembeheerder gaf hiervoor volgende reden op:
+<p>$1",
+"missingarticle" => "De database heeft een paginatekst (\"$1\") die het zou moeten vinden niet gevonden. Dit kan betekenen dat u een oude versie hebt proberen op te halen van een pagina die inmiddels verdwenen is. Indien dit niet het geval is, dan is er waarschijnlijk een fout in de software. Meld dit a.u.b. aan een beheerder, met vermelding van de URL.",
+"internalerror" => "Interne fout",
+"filecopyerror" => "Bestand \"$1\" naar \"$2\" kopiëren niet mogelijk.",
+"filerenameerror" => "Wijziging titel bestand \"$1\" in \"$2\" niet mogelijk.",
+"filedeleteerror" => "Kon bestand \"$1\" niet verwijderen.",
+"filenotfound" => "Kon bestand \"$1\" niet vinden.",
+"unexpected" => "Onverwachte waarde: \"$1\"=\"$2\".",
+"formerror"  => "Fout: kon formulier niet verzenden",
+"badarticleerror" => "Deze handeling kan op deze pagina niet worden uitgevoerd.",
+"cannotdelete" => "Kon de pagina of afbeelding niet verwijderen.",
+"badtitle"              => "Ongeldige paginatitel",
+"badtitletext"  => "De opgevraagde pagina is niet beschikbaar of leeg.",
+"perfdisabled" => "Om overbelasting van het systeem te voorkomen, is deze optie momenteel niet bruikbaar.",
+"perfdisabledsub" => "We kunnen u wel onderstaande kopie van $1 tonen; deze is echter mogelijk niet up-to-date.",
+
+# Login and logout pages
+# Aanmelden en afmelden
+"logouttitle" => "Afmelden gebruiker",
+"logouttext" => "U bent nu afgemeld.
+U kunt {{SITENAME}} anoniem blijven gebruiken, of u opnieuw aanmelden onder dezelfde of onder een andere naam.\n",
+
+"welcomecreation" => "<h2>Welkom, $1!</h2><p>Uw gebruikersprofiel is aangemaakt. U kunt nu uw persoonlijke voorkeuren instellen.",
+
+"loginpagetitle" => "Gebruikersnaam",
+"yourname"  => "Uw gebruikersnaam",
+"yourpassword" => "Uw wachtwoord",
+"yourpasswordagain" => "Wachtwoord opnieuw ingeven",
+"newusersonly" => " (alleen nieuwe gebruikers)",
+"remembermypassword" => "Mijn wachtwoord onthouden voor latere sessies.",
+"loginproblem" => "<b>Er is een probleem met het aanmelden.</b><br />Probeer het opnieuw a.u.b.",
+"alreadyloggedin" => "<strong>Gebruiker $1, u bent al aangemeld.</strong><br />\n",
+
+"login"   => "Aanmelden & Inschrijven",
+"userlogin"  => "Aanmelden",
+"logout"  => "Afmelden",
+"userlogout" => "Afmelden",
+"notloggedin" => "Niet aangemeld",
+"createaccount" => "Nieuw gebruikersprofiel aanmaken",
+"createaccountmail" => "per email",
+"badretype"  => "De ingevoerde wachtwoorden verschillen van elkaar.",
+"userexists" => "De gebruikersnaam die u heeft ingevoerd is al in gebruik. Gelieve een andere naam te kiezen.",
+"youremail"  => "Uw e-mailadres",
+"yournick"  => "Uw bijnaam (voor handtekeningen)",
+"emailforlost" => "Het opgeven van een e-mailadres is niet verplicht.<br />Enkel als er een email-adres beschikbaar is, kunt u een nieuw wachtwoord aanvragen indien u het oude vergeten bent.<br />Een emailadres geeft andere gebruikers de mogelijkheid u een email te sturen via een formulier. U kunt die functie eventueel uitzetten via de voorkeuren.",
+"loginerror" => "Inlogfout",
+"noname"  => "U dient een gebruikersnaam op te geven.",
+"loginsuccesstitle" => "Aanmelden gelukt.",
+"loginsuccess" => "U bent nu aangemeld bij {{SITENAME}} NL als \"$1\".",
+"nosuchuser" => "Er bestaat geen gebruiker met de naam \"$1\". Controleer uw spelling, of gebruik onderstaand formulier om een nieuw gebruikersprofiel aan te maken.",
+"wrongpassword" => "Het ingegeven wachtwoord is niet juist. Probeer het opnieuw.",
+"mailmypassword" => "Stuur mij een nieuw wachtwoord op",
+"passwordremindertitle" => "Herinnering wachtwoord {{SITENAME}} NL",
+"passwordremindertext" => "Iemand (waarschijnlijk uzelf) vanaf IP-adres $1 heeft verzocht u een nieuw wachtwoord voor {{SITENAME}} NL toe te zenden. Het nieuwe wachtwoord voor gebruiker \"$2\" is \"$3\". Advies: nu aanmelden en uw wachtwoord wijzigigen.",
+"noemail"  => "Er is geen e-mailadres geregistreerd voor \"$1\".",
+"passwordsent" => "Er is een nieuw wachtwoord verzonden naar het e-mailadres wat geregistreerd staat voor \"$1\".
+Gelieve na ontvangst opnieuw aan te melden.",
+
+# Edit pages
+# Pagina bewerken
+"summary"  => "Samenvatting",
+"subject" => "Onderwerp",
+"minoredit"  => "Dit is een kleine wijziging",
+"watchthis" => "Volg deze pagina",
+"savearticle" => "Pagina opslaan",
+"preview"  => "Nakijken",
+"showpreview" => "Toon bewerking ter controle",
+"blockedtitle" => "Gebruiker is geblokkeerd",
+"blockedtext" => "Uw gebruikersnaam of IP-adres is door $1 geblokkeerd. De opgegeven reden:<br />$2<p>. Elke computer die verbonden is met het internet krijgt een [[ip-adres]] toegewezen van zijn [[internetprovider]]. In veel gevallen krijgt een gebruiker regelmatig een ander ip-adres toegewezen. Het het door u gebruikte ip-adres is recent gebruikt door u of iemand anders voor bewerkingen die in overtreding zijn van de [[{{ns:4}}:Toch een paar regels|regels]] van {{SITENAME}}.<p>U kunt voor overleg contact opnemen met de [[{{ns:4}}:Systeembeheerders|systeembeheerders]] via [http://wikinl.sol3.info/wikinl_info.html#email wikinl-l-owner@wikipedia.org een formulier].",
+"whitelistedittitle" => "Aanmelden verplicht",
+"whitelistedittext" => "Om dit artikel te kunnen wijzigen, moet u [[Speciaal:Userlogin|ingelogd]] zijn.",
+"whitelistreadtitle" => "Aanmelden verplicht",
+"whitelistreadtext" => "Om dit artikel te kunnen lezen, moet u [[Speciaal:Userlogin|ingelogd]] zijn.",
+"whitelistacctitle" => "Creatie account niet toegestaan",
+"whitelistacctext" => "Nieuwe accounts kunnen slechts worden aangemaakt door bepaalde geregistreerde gebruikers",
+"accmailtitle" => "Wachtwoord verzonden.",
+"accmailtext" => "Het wachtwoord voor '$1' is verzonden naar $2.",
+"newarticle" => "(Nieuw)",
+"newarticletext" => "Er bestaat nog geen artikel over dit onderwerp.<br />Als u wilt, kunt u hieronder een nieuw artikel schrijven.<br />Was dit niet de bedoeling, gebruik dan de 'Terug' knop van uw browser.<p>WAARSCHUWING: Let er goed op dat uw tekst vrij van auteursrechten is, bijvoorbeeld omdat u het zelf geschreven heeft. Neem geen teksten over uit boeken, tijdschriften of andere websites tenzij u zeker weet dat deze vrij van auteursrechten zijn.",
+"anontalkpagetext" => "<hr>Deze overlegpagina hoort bij een anonieme gebruiker die hetzij geen loginnaam heeft, hetzij deze niet gebruikt. We gebruiken daarom het IP-adres ter identificatie. Het kan echter zijn dat meerdere personen hetzelfde IP-adres gebruiken. Het kan daarom zijn dat u hier berichten ontvangt die niet voor u bedoeld zijn. Mocht u dat willen voorkomen, dan kunt u [[Speciaal:Userlogin|een gebruikersnaam aanvragen of u aanmelden]].",
+"noarticletext" => "(Deze pagina bevat momenteel geen tekst)",
+"updated"  => "(Bijgewerkt)",
+"note"   => "<strong>Opmerking:</strong> ",
+"previewnote" => "Let op: dit is een controlepagina; uw tekst is nog niet opgeslagen!",
+"previewconflict" => "Deze versie toont hoe de tekst in het bovenste veld eruit gaat zien wanneer u zou opslaan.",
+"editing"  => "Bewerkingspagina: $1",
+"editingsection"  => "Bewerkingspagina: $1 (deelpagina)",
+"editingcomment"  => "Bewerkingspagina: $1 (nieuwe opmerking)",
+"editconflict" => "Bewerkingsconflict: $1",
+"explainconflict" => "Iemand anders heeft deze pagina gewijzigd nadat u aan deze bewerking bent begonnen. Het bovenste tekstveld toont de huidige versie van de pagina. U zal uw eigen wijzigingen moeten integreren in die tekst. Alleen de tekst in het bovenste veld wordt bewaard wanneer u kiest voor \"Pagina opslaan\".<br />",
+"yourtext"  => "Uw tekst",
+"storedversion" => "Opgeslagen versie",
+"editingold" => "<strong>WAARSCHUWING: U bent bezig een oude versie van deze pagina te bewerken. Wanneer u uw bewerking opslaat, gaan alle wijzigingen die na deze versie gedaan zijn verloren.</strong>",
+"yourdiff"  => "Wijzigingen",
+"copyrightwarning" => "Opgelet: Alle bijdragen aan {{SITENAME}} worden geacht te zijn vrijgegeven onder de GNU Free Documentation License. Als u niet wil dat uw tekst door anderen naar believen bewerkt en verspreid kan worden, kies dan niet voor 'Pagina Opslaan'.<br /> Hierbij belooft u ons tevens dat u deze tekst zelf hebt geschreven, of overgenomen uit een vrije, openbare bron.<br /> <strong>GEBRUIK GEEN MATERIAAL DAT BESCHERMD WORDT DOOR AUTEURSRECHT, TENZIJ JE DAARTOE TOESTEMMING HEBT!</strong>",
+"longpagewarning" => "<strong>Waarschuwing! Deze pagina is $1 kilobyte lang. Pagina's langer dan 32 kb zorgen voor problemen op sommige browsers. Het is daarom waarschijnlijk een goed idee deze pagina in meerdere pagina's te splitsen.</strong>",
+"readonlywarning" => "<strong>Waarschuwing! De database is op dit moment in onderhoud; het is daarom niet mogelijk op dit moment pagina's te wijzigen. Wij adviseren u de tekst op uw eigen computer op te slaan en later opnieuw te proberen deze pagina te bewerken.</strong>",
+"protectedpagewarning" => "<strong>Waarschuwing! U staat op het punt een beveiligde pagina te wijzigen. Gewone gebruikers kunnen deze pagina niet bewerken.</strong>",
+
+# History pages
+# Geschiedenis pagina's
+"revhistory" => "Bewerkingsgeschiedenis",
+"nohistory"  => "Deze pagina heeft nog geen bewerkingen ondergaan.",
+"revnotfound" => "Wijziging niet gevonden",
+"revnotfoundtext" => "De opgevraagde oude versie van deze pagina is onvindbaar. Controleer a.u.b. de URL die u gebruikte om naar deze pagina te gaan.\n",
+"loadhist"  => "Bezig met het laden van de paginageschiedenis",
+"currentrev" => "Huidige versie",
+"revisionasof" => "Versie op $1",
+"cur"   => "huidig",
+"next"   => "volgende",
+"last"   => "vorige",
+"orig"   => "orig",
+"histlegend" => "Verklaring afkortingen: (wijz) = verschil met huidige versie, (vorige) = verschil met voorgaande versie, K = kleine wijziging",
+
+# Diffs
+# Verschil
+"difference" => "(Verschil tussen bewerkingen)",
+"loadingrev" => "bezig paginaversie te laden",
+"lineno"  => "Regel $1:",
+"editcurrent" => "De huidige versie van deze pagina bewerken",
+
+# Search results
+# Zoekresultaten
+"searchresults" => "Zoekresultaten",
+"searchresulttext" => "Voor meer informatie over zoeken op {{SITENAME}}: zie [[Project:Zoeken|Zoeken op {{SITENAME}}]].",
+"searchquery" => "Voor zoekopdracht \"$1\"",
+"badquery"  => "Slecht geformuleerde zoekopdracht",
+"badquerytext" => "Uw zoekopdracht kon niet worden uitgevoerd. Dit kan komen doordat u geprobeerd hebt om een 'woord' van 1 letter te zoeken, of 1 van de <a HREF=\"http://nl.wikipedia.org/wiki/{{ns:4}}:Verboden_woorden\">Verboden woorden</a>.",
+"matchtotals" => "De zoekterm \"$1\" is gevonden in $2 paginatitels en in de tekst van $3 pagina's.",
+"nogomatch" => "Er bestaat geen pagina met deze titel, op zoek naar pagina's waarin de tekst voorkomt.",
+"titlematches" => "Overeenkomst met volgende titels",
+"notitlematches" => "Geen enkele paginatitel gevonden met de opgegeven zoekterm",
+"textmatches" => "Overeenkomst met artikel inhoud",
+"notextmatches" => "Geen artikel gevonden met opgegeven zoekterm",
+"prevn"   => "vorige $1",
+"nextn"   => "volgende $1",
+"viewprevnext" => "($1) ($2) ($3) bekijken.",
+"showingresults" => "Hieronder <b>$1</b> resultaten vanaf nummer <b>$2</b>.",
+"showingresultsnum" => "Hieronder <b>$3</b> resultaten vanaf nummer <b>$2</b>.",
+"nonefound"  => "<strong>Merk op:</strong> wanneer een zoekopdracht mislukt komt dat vaak door gebruik van veel voorkomende woorden zoals \"de\" en \"het\", die niet geïndexeerd zijn, of door verschillende zoektermen tegelijk op te geven (u krijgt dan alleen in pagina's waaarin alle opgegeven termen voorkomen).
+
+Het kan natuurlijk dat er gewoon nog geen artikel aanwezig op {{SITENAME}} NL over dit onderwerp. Mogelijk is het aanwezig in een andere taal. Zoek met de <a HREF=\"http://pliny.wikipedia.org/tools/wikisearch.php\">multi-wikipedia zoeker</a> in de andere {{SITENAME}}'s, of buiten {{SITENAME}} in een <a href=\"http://encyclopedie.zoekhulp.nl/?refer=Wikipedia.nl\">andere encyclopedie</a>. Wanneer u gevonden heeft wat u zocht, kunt u wellicht daarover een artikel schrijven op {{SITENAME}} NL, zodat de volgende die zoekt wat u zocht het wel kan vinden.
+",
+"powersearch" => "Zoeken",
+"powersearchtext" => "
+ Zoek in naamruimten :<br />
+$1<br />
+$2 Toon redirects &nbsp; Zoek: $3 $9",
+"searchdisabled" => "Wegens een overbelasting van de server zijn sommige functies die het systeem extra belasten tijdelijk niet beschikbaar.
+ Hierdoor is in de interne zoekfunctie van {{SITENAME}} (vermoedelijk) niet beschikbaar voor onbepaalde duur.<p>
+Via google kunt u zoeken op {{SITENAME}}.
+<p> U zal niet alle artikels kunnen vinden maar het zal niet veel schelen.
+Als u zoekt via google op {{SITENAME}} zal u ook treffers vinden op {{SITENAME}} die geen artikels zijn.
+{{SITENAME}} heeft bij de meeste artikels ook een \"overlegpagina\" en diverse soorten dienstpagina's.
+Enkel de pagina's die geen prefix (zoals {{ns:4}}:, Gebruiker: of Overleg:) hebben zijn artikels.
+",
+"blanknamespace" => "(encyclopedie)",
+
+# Preferences page
+# Voorkeuren
+"preferences" => "Voorkeuren",
+"prefsnologin" => "Niet aangemeld",
+"prefsnologintext" => "U dient [[Special:Userlogin|aangemeld]] te zijn om voorkeuren te kunnen instellen.",
+"prefslogintext" => "U bent aangemeld als \"$1\". Uw interne identificatienummer is $2.
+
+Een beschrijving van de verschillende opties staat op [[{{ns:4}}:Voorkeuren]].",
+"prefsreset" => "Standaardvoorkeuren hersteld.",
+"qbsettings" => "Menubalkinstellingen",
+"changepassword" => "Wachtwoord wijzigen",
+"skin" => "{{SITENAME}}-Uiterlijk",
+"math" => "Wiskundige formules",
+"math_failure" => "Wiskundige formule niet begrijpelijk",
+"math_unknown_error" => "Onbekende fout in formule",
+"math_unknown_function" => "Onbekende functie in formule",
+"math_lexing_error" => "Lexicografische fout in formule",
+"math_syntax_error" => "Syntax-fout in formule",
+# "dateformat" => "Wijze van tonen datum",
+# Not used in nl, kept here for reference if we want to change it
+"saveprefs"  => "Voorkeuren opslaan",
+"resetprefs" => "Standaardvoorkeuren herstellen",
+"oldpassword" => "Huidig wachtwoord",
+"newpassword" => "Nieuw wachtwoord",
+"retypenew"  => "Voer het nieuwe wachtwoord nogmaals in",
+"textboxsize" => "Afmetingen tekstveld",
+"rows"   => "Regels",
+"columns"  => "Kolommen",
+"searchresultshead" => "Instellingen voor zoekresultaten",
+"resultsperpage" => "Aantal per bladzijde te tonen zoekresultaten",
+"contextlines" => "Aantal regels per gevonden pagina",
+"contextchars" => "Aantal tekens van de context per regel",
+"stubthreshold" => "Grootte waaronder een pagina als 'stub' wordt aangegeven",
+"recentchangescount" => "Aantal titels in lijst recente wijzigingen",
+"savedprefs" => "Uw voorkeuren zijn opgeslagen.",
+"timezonetext" => "De tijd van de server is UTC (Coordinated Universal Time) Geef aan hoeveel uur de plaatselijke tijd in uw woonplaats verschilt met die van de server. Voor o.a. België en Nederland: +1 (+2 zomertijd); voor Suriname en voor de Nederlandse Antillen: -4; voor Zuid-Afrika: +2.",
+"localtime" => "Plaatselijke tijd",
+"timezoneoffset" => "Tijdsverschil",
+"servertime" => "De locale tijd van de {{SITENAME}}-server:",
+"guesstimezone" => "Vanuit de browser toe te voegen",
+"emailflag" => "E-mail ontvangen van andere gebruikers uitschakelen",
+"defaultns" => "Naamruimten om direct in te zoeken:",
+
+# Recent changes
+# Recente wijzigingen
+"changes" => "wijzigingen",
+"recentchanges" => "Recente wijzigingen",
+"recentchangestext" => "Deze pagina toont de laatste aanpassingen aan artikelen van {{SITENAME}} NL. <br />
+Ben je hier nieuw? Lees dan ook [[{{ns:4}}:Welkom voor nieuwelingen|Welkom voor nieuwelingen]] -- Wil je een pagina verwijderd hebben? Ga dan naar [[{{ns:4}}:Te verwijderen pagina's|Te verwijderen pagina's]] -- Wil je iets met andere gebruikers overleggen? Ga naar [[{{ns:4}}:Overleg gewenst|Overleg gewenst]] of meld je aan voor de discussielijst [http://mail.wikipedia.org/mailman/listinfo/wikinl-l WikiNL-l] -- Zin in een gezellige babbel? Kom naar de [[{{ns:4}}:De kroeg|De kroeg]] of doe mee op ons nieuwe [http://chat.wikipedia.be Wiki-chatkanaal].<p>
+Om {{SITENAME}} te laten slagen is het erg belangrijk geen materiaal toe te voegen waarop iemand anders auteursrechten heeft, tenzij je daartoe toestemming hebt. De wettelijke gevolgen van inbreuk op de rechten van anderen zouden de hele onderneming grote schade kunnen toebrengen.",
+"rcloaderr"  => "Meest recente wijzigingen laden",
+"rcnote"  => "Hieronder zijn de <strong>$1</strong> laatste wijzigingen gedaan in de laatste <strong>$2</strong> dagen.",
+"rcnotefrom"  => "Veranderingen sinds <b>$2</b> (met een maximum van <b>$1</b> veranderingen).",
+"rclistfrom"  => "Toon de veranderingen vanaf $1",
+"rclinks"  => "Bekijk de $1 laatste wijzigingen in de laatste $2 dagen - $3 kleine wijzigingen.",
+"rchide"  => "in $4 vorm; $1 kleine wijzigingen; $2 wijzigingen op speciale pagina's zoals overleg- en gebruikerspagina's; $3 meervoudige wijzigingen.",
+"rcliu" => "- $1 edits van geregistreerde gebruikers",
+"diff"   => "wijz",
+"hist"   => "hist",
+"hide"   => "verberg",
+"show"   => "toon",
+"tableform"  => "tabel",
+"listform"  => "lijst",
+"nchanges"  => "$1 wijzigingen",
+"minoreditletter" => "K",
+"newpageletter" => "N",
+
+# Upload
+#
+"upload"  => "Upload",
+"uploadbtn"  => "upload bestand",
+"uploadlink" => "upload afbeelding",
+"reupload"  => "Opnieuw uploaden",
+"reuploaddesc" => "Terug naar het uploadformulier.",
+"uploadnologin" => "Niet aangemeld",
+"uploadnologintext" => "U dient [[Speciaal:Userlogin|aangemeld te zijn]]
+om bestanden te uploaden.",
+"uploaderror" => "upload fout",
+"uploadtext" => "'''STOP!''' Voor u iets hier upload,
+wees zeker dat het in overeenkomst is met het {{SITENAME}} NL
+[[Project:Beleid_voor_gebruik_van_afbeeldingen|afbeeldingsbeleid]].
+
+Om de reeds ge-uploade bestanden te bekijken of te zoeken ga naar de
+[[Speciaal:Imagelist|lijst van ge-uploade bestanden]].
+Uploads en verwijderingen worden bijgehouden in het
+[[Project:Upload_logboek|upload logboek]].
+
+Gebruik het onderstaande formulier om bestanden zoals afbeeldingen en geluidsbestanden die relevant zijn voor uw artikel te u-loaden. Bij de meeste browers zoals 'Internet Explorer' en 'Mozilla' zult u een \"Bladeren...\" of \"Browse..\" knop zien die een standaard dialoogscherm van uw bestuuringssysteem oproept. Kiest u een bestand, dan zal het ingevuld worden in het veld naast de \"Bladeren...\" knop. U dient ook het vakje aan te vinken waarmee u bevestigt dat er geen schending van auteursrechten plaatsvindt door het gebruik van dat bestand. Vul het veld \"Omschrijving\" in. Druk op de \"Upload\" knop om het uploaden te voltooien. Dit kan even duren als u een langzame internetverbinding gebruikt.
+
+Gebruik bij voorkeur JPEG voor foto's, PNG voor tekeningen en dergelijke en OGG voor geluid.
+Geef uw bestanden een duidelijk omschrijvende naam om verwarring te voorkomen. Om het bestand in een pagina te laten verschijnen, kunt u het volgende doen;  '''<nowiki>[[afbeelding:uw_foto.jpg]]</nowiki>''' of '''<nowiki>[[afbeelding:uw_logo.png|alt text]]</nowiki>''' of '''<nowiki>[[media:uw_geluid.ogg]]</nowiki>''' voor audio.
+
+Vergeet niet dat net als met andere pagina's op {{SITENAME}} anderen de ge-uploade bestanden kunnen verwijderen indien men denkt dat dat in het voordeel van het project is. Bij misbruik van dit systeem kan u de toegang tot {{SITENAME}} NL ontzegd worden.",
+"uploadlog"  => "upload logboek",
+"uploadlogpage" => "Upload_logboek",
+"uploadlogpagetext" => "Hieronder de lijst met de meest recent ge-uploade bestanden. Alle tijden zijn servertijd (UTC).
+<ul>
+</ul>
+",
+"filename"  => "Bestandsnaam",
+"filedesc"  => "Beschrijving",
+"filestatus" => "Auteursrechtensituatie",
+"filesource" => "Auteur/bron",
+"copyrightpage" => "{{ns:4}}:Auteursrechten",
+"copyrightpagename" => "{{SITENAME}} NL auteursrechten",
+"uploadedfiles" => "Ge-uploade bestanden",
+"ignorewarning" => "Negeer de waarschuwing en sla het bestand op.",
+"minlength"  => "De naam van het bestand moet uit ten minste drie tekens bestaan.",
+"badfilename" => "De naam van het bestand is gewijzigd in \"$1\".",
+"badfiletype" => "\".$1\" is geen aanbevolen afbeeldings bestandsformaat.",
+"largefile"  => "Aanbeveling: maak afbeeldingen niet groter dan 100k",
+"successfulupload" => "De upload was succesvol",
+"fileuploaded" => "<b>Het uploaden van bestand \"$1\" is geslaagd.</b> Gelieve deze link naar de omschrijvingspagina te volgen: ($2). Vul daar informatie in over dit bestand, bijvoorbeeld de oorsprong, wanneer en door wie het gemaakt is en wat u verder er nog over te vertellen heeft.",
+"uploadwarning" => "Upload waarschuwing ",
+"savefile"  => "Bestand opslaan",
+"uploadedimage" => "heeft ge-upload: \"[[$1]]\"",
+"uploaddisabled" => "Uploads zijn op deze server niet mogelijk.",
+
+# Image list
+# Afbeeldingslijst
+"imagelist"  => "Lijst van afbeeldingen",
+"imagelisttext" => "Hier volgt een lijst met $1 afbeeldingen geordend $2.",
+"getimagelist" => "Lijst van afbeeldingen ophalen",
+"ilsubmit"  => "Zoek",
+"showlast"  => "Toon de laatste $1 afbeeldingen geordend $2.",
+"byname"  => "op naam",
+"bydate"  => "op datum",
+"bysize"  => "op grootte",
+"imgdelete"  => "verw",
+"imgdesc"  => "besc",
+"imglegend"  => "Verklaring: (besc) = toon/verander beschrijving van de afbeelding, (verw) = verwijdering de afbeelding.",
+"imghistory" => "Geschiedenis van de afbeelding",
+"revertimg"  => "rev",
+"deleteimg"  => "verw",
+"deleteimgcompletely"  => "verw",
+"imghistlegend" => "Verklaring: (cur)= huidige afbeelding, (verw) = verwijder de oude versie, (rev) = breng oude versie terug.<br />
+<i>Klik op de datum om de afbeeldingen die ge-upload zijn op die datum te zien</i>.",
+"imagelinks" => "Afbeeldingsverwijzingen",
+"linkstoimage" => "Deze afbeelding wordt gebruikt op de volgende pagina's:",
+"nolinkstoimage" => "Geen enkele pagina gebruikt deze afbeelding.",
+
+# Statistics
+# Statistieken
+"statistics" => "Statistieken",
+"sitestats"  => "Statistieken betreffende {{SITENAME}} NL",
+"userstats"  => "Statistieken betreffende gebruikers",
+"sitestatstext" => "Er zijn <b>$1</b> pagina's in de database. Hierbij zijn inbegrepen \"Overleg\" pagina's, pagina's over {{SITENAME}}, extreem korte \"stub\" pagina's, redirects, en diverse andere pagina's die waarschijnlijk niet als artikel moeten worden geteld. Na uitsluiting daarvan, is er een geschat aantal van <b>$2</b> artikels.<p>
+Er is in totaal $3 maal een pagina bekeken, en $4 maal een pagina bewerkt. Dat geeft een gemiddelde van $5 bewerkingen per pagina, en $6 paginabezoeken per wijziging.",
+"userstatstext" => "Er zijn momenteel $1 geregistreerde gebruikers; hiervan zijn er $2 systeembeheerders (zie $3).",
+
+# Maintenance Page
+#
+"maintenance"           => "Onderhoudspagina",
+"maintnancepagetext"    => "Op deze pagina vindt u een aantal handige zoekopdrachten om kleine alledaagse problemen in de {{SITENAME}} te verhelpen. Sommige van deze zoekopdrachten vormen een grote belasting voor de database; ga dus niet na elke paar pagina's die u hersteld heeft, de pagina opnieuw laden.",
+"maintenancebacklink"   => "Terug naar de Onderhoudspagina",
+"disambiguations"       => "Doorverwijspagina's",
+"disambiguationspage"   => "{{ns:4}}:Doorverwijspagina",
+"disambiguationstext"   => "De onderstaande artikelen verwijzen naar een [[{{ns:4}}:Doorverwijspagina|doorverwijspagina]]. Deze zouden waarschijnlijk direct naar de onderwerpspagina moeten verwijzen. <br />Als doorverwijspagina's worden die pagina's beschouwd waar vanaf $1 naar verwezen wordt.<br />Opmerking: Deze lijst toont alleen pagina's vanuit de hoofdnaamruimte, en dus niet Overlegpagina's, {{ns:4}}:pagina's en dergelijke.",
+"doubleredirects"       => "Dubbele redirects",
+"doubleredirectstext"   => "<b>Let op:</b> Er kunnen in deze lijst redirects staan die er niet in thuishoren. Dat komt over het algemeen doordat er na de #REDIRECT nog andere links op de pagina staan.<br />\nOp elke regel vindt u de eerste redirectpagina, de tweede redirectpagina en de eerste regel van de tweede redirectpagina. Normaal gesproken bevat deze laatste de pagina waar de eerste redirect naartoe zou moeten verwijzen.",
+"brokenredirects"       => "Gebroken redirects",
+"brokenredirectstext"   => "De onderstaande redirectpagina's bevatten een redirect naar een niet-bestaande pagina.",
+"selflinks"             => "Pagina's die naar zichzelf verwijzen",
+"selflinkstext"         => "De volgende pagina's verwijzen naar zichzelf, wat niet hoort te gebeuren.",
+"mispeelings"           => "Pagina's met spelfouten",
+"mispeelingstext"       => "De volgende pagina's bevatten een veel voorkomende spel- of typfout, die staat aangegeven op de lijst in $1. Daar staat meestal ook (tussen haakjes) de juiste spelling.",
+"mispeelingspage"       => "Veel voorkomende spelfouten",
+"missinglanguagelinks"  => "Ontbrekende taallinks",
+"missinglanguagelinksbutton"    => "Vind ontbrekende taallinks voor",
+"missinglanguagelinkstext"      => "De onderstaande artikelen bevatten geen taallink naar een overeenkomende pagina in de taal \"$1\".",
+
+# Miscellaneous special pages
+# Diverse speciale pagina's
+"orphans"  => "Weespagina's",
+"lonelypages" => "Weespagina's",
+"unusedimages" => "Ongebruikte afbeeldingen",
+"popularpages" => "Populaire artikels",
+"nviews"  => "$1 keer bekeken",
+"wantedpages" => "Gewenste pagina's",
+"nlinks"  => "$1 verwijzingen",
+"allpages"  => "Alle pagina's",
+"randompage" => "Willekeurig artikel",
+"shortpages" => "Korte artikels",
+"longpages"  => "Lange artikels",
+"listusers"  => "Lijst van gebruikers",
+"specialpages" => "Speciale pagina's",
+"spheading"  => "",
+"protectpage" => "Beveilig pagina",
+"recentchangeslinked" => "Volg links",
+"rclsub"  => "(van pagina's waarnaar \"$1\" verwijst)",
+"debug"   => "Bugreparatie",
+"newpages"  => "Nieuwe artikels",
+"ancientpages" => "Oudste artikels",
+#"intl" => "Taallinks",  -  not active yet
+"movethispage" => "Verplaats deze pagina",
+"unusedimagestext" => "<p>Let op! Het zou kunnen dat er via een directe link verwezen wordt naar een afbeelding, bijvoorbeeld vanuit een anderstalige {{SITENAME}}. Het is daarom mogelijk dat een afbeelding hier vermeld staat terwijl het wel degelijk gebruikt wordt.",
+"booksources" => "Boekhandels",
+"booksourcetext" => "Hieronder is een lijst van externe websites die boeken verkopen en ook verdere informatie hierover kunnen verstekken. Via een ISBN-nummer in een artikel kunt u via deze pagina een werk opzoeken. <p>Deze dienst is enkel ter uwer informatie. {{SITENAME}} NL heeft <u>geen enkele</u> relatie met deze websites.",
+"alphaindexline" => "$1 tot $2",
+
+# Email this user
+# E-mail deze gebruiker
+"mailnologin" => "Geen verzendadres beschikbaar",
+"mailnologintext" => "U dient [[Speciaal:Userlogin|aangemeld te zijn]]
+en een geldig e-mailadres in uw [[Speciaal:Preferences|voorkeuren]]
+te vermelden om deze functie te kunnen gebruiken.",
+"emailuser"  => "E-mail deze gebruiker",
+"emailpage"  => "E-mail gebruiker",
+"emailpagetext" => "Indien deze gebruiker een geldig e-mailadres heeft opgegeven dan kunt u via dit formulier een bericht verzenden. Het e-mailadres dat u heeft opgegeven bij uw voorkeuren zal als afzender gebruikt worden.",
+"noemailtitle" => "Geen e-mailadres gekend voor deze gebruiker",
+"noemailtext" => "Deze gebruiker heeft geen geldig e-mailadres opgegeven of heeft deze functie uitgeschakelt.",
+"emailfrom"  => "Van",
+"emailto"  => "Aan",
+"emailsubject" => "Onderwerp",
+"emailmessage" => "Bericht",
+"emailsend"  => "Verstuur bericht",
+"emailsent"  => "E-mail versturen",
+"emailsenttext" => "Uw bericht is verzonden.",
+
+# Watchlist
+# Volglijst
+"watchlist"  => "Volglijst",
+"watchlistsub" => "(van gebruiker \"$1\")",
+"nowatchlist" => "Er staat niets op uw volglijst.",
+"watchnologin" => "U bent niet aangemeld",
+"watchnologintext" => "Om uw volglijst te veranderen dient u eerst [[Speciaal:Userlogin|aangemeld]]
+te zijn.",
+"addedwatch" => "Toegevoegd aan volglijst",
+"addedwatchtext" => "De pagina \"$1\" is aan uw <a href=\"" .
+  "{{localurle:Speciaal:Watchlist}}\">volglijst</a> toegevoegd.
+Toekomstige wijzigingen aan deze pagina en overlegpagina zullen hier vermeld worden.
+Ook zullen deze pagina's in het <b>vet</b> verschijnen in de <a href=\"" .
+  "{{localurle:Speciaal:Recentchanges}}\">lijst van recente wijzigingen</a> zodat u ze eenvoudiger kunt opmerken.</p>
+
+<p>Indien u een pagina wenst te verwijderen van uw volglijst klik dan op \"Van volglijst verwijderen\" in de menubalk.",
+"removedwatch" => "Van volglijst verwijderen",
+"removedwatchtext" => "De pagina \"$1\" is van uw volglijst verwijderd.",
+"watchthispage" => "Volg deze pagina",
+"unwatchthispage" => "Niet meer volgen",
+"notanarticle" => "Is geen artikel",
+"watchnochange" => "Geen van de pagina's op uw volglijst is in deze periode gewijzigd",
+"watchdetails" => "Er staan $1 pagina's op uw volglijst (overlegpagina's niet meegeteld.
+In de aangegeven periode zijn $2 pagina's gewijzigd.
+$3. ([$4 Toon mijn volledige volglijst].)",
+"watchmethod-recent" => "Bij de recent gewijzigde pagina's gezocht naar gevolgde pagina's",
+"watchmethod-list" => "Bij de gevolgde pagina's naar wijzigingen bekeken",
+"removechecked" => "Verwijderen",
+"watchlistcontains" => "U heeft $1 pagina's op uw volglijst",
+"watcheditlist" => "Hier is een lijst van alle pagina's op uw volglijst.
+Vink de vakjes aan voor de pagina's die u wilt verwijderen, en druk dan
+op 'Verwijderen' onderaan deze pagina.",
+"removingchecked" => "De aangegeven pagina's worden van uw volglijst verwijderd.",
+"couldntremove" => "Verwijdering van '$1' onmogelijk.",
+"iteminvalidname" => "Incorrecte naam '$1'",
+"wlnote" => "Getoond worden de laatste $1 wijzigingen in de laatste $2 uur.",
+"wlshowlast" => "Toon de laatste $1 uur $2 dagen $3",
+
+# Delete/protect/revert
+# Verwijderen/beschermen/annuleren
+"deletepage" => "Pagina verwijderen",
+"confirm"  => "Bevestig",
+"excontent" => "De inhoud was: '$1'",
+"exbeforeblank" => "Voor leegmaking was de inhoud: '$1'",
+"exblank" => "Dit was een lege pagina.",
+"confirmdelete" => "Bevestig verwijdering",
+"deletesub"  => "(Verwijderen \"$1\")",
+"historywarning" => "Waarschuwing: Deze pagina heeft een voorgeschiedenis. Overtuig uzelf ervan dat geen van de oudere versies een te behouden pagina is.",
+"confirmdeletetext" => "U bent staat op het punt een pagina of afbeelding voorgoed te verwijderen. Dit verwijdert alle inhoud en geschiedenis van de database. Bevestig hieronder dat dit inderdaad uw bedoeling is, dat u de gevolgen begrijpt, en dat uw verwijdering overeenkomt met de [[{{ns:4}}:Instructies]].",
+"actioncomplete" => "Actie voltooid",
+"deletedtext" => "\"$1\" is verwijderd. Zie $2 voor een overzicht van recente verwijderingen.",
+"deletedarticle" => "\"$1\" is verwijderd",
+"dellogpage" => "Logboek_verwijderde_pagina's", # This one needs the underscores!
+"dellogpagetext" => "Hieronder ziet u een lijst van de meest recentelijk verwijderde pagina's en afbeeldingen. Alle tijden zijn servertijd, UTC-0.",
+"deletionlog" => "Logboek verwijderde pagina's",
+"reverted"  => "Eerdere versie hersteld",
+"deletecomment" => "Reden voor verwijdering",
+"imagereverted" => "De omzetting naar de oudere versie is geslaagd.",
+"rollback"      => "Wijzigingen ongedaan maken",
+"rollbacklink"  => "Terugdraaien",
+"rollbackfailed" => "Ongedaan maken van wijzigingen mislukt.",
+"cantrollback"  => "Ongedaan maken van wijzigingen onmogelijk: Dit artikel heeft slechts 1 auteur.",
+// "allreadyrolled" => "[[Gebruiker:$3|$3]] heeft de pagina [[$1]] bewerkt na de laatste bewerking door [[Gebruiker:$2|$2]].",
+"editcomment"   => "Commentaar bij de wijziging: <i>$1</i>",
+"revertpage"    => "Hersteld tot de versie na de laatste wijziging door $1.",
+
+# Undelete
+"undelete" => "Verwijderde pagina terugplaatsen",
+"undeletepage" => "Verwijderde pagina's bekijken en terugplaatsen",
+"undeletepagetext" => "De onderstaande pagina's zijn verwijderd, maar bevinden zich nog steeds in het archief, en kunnen teruggeplaatst worden.",
+"undeletearticle" => "Verwijderde pagina terugplaatsen",
+"undeleterevisions" => "$1 versies in het archief",
+"undeletehistory" => "Als u een pagina terugplaatst, worden alle versies als oude versies teruggeplaatst. Als er al een nieuwe pagina met dezelfde naam is aangemaakt, zullen deze versies als oude versies worden teruggeplaatst, maar de huidige versie niet gewijzigd worden.",
+"undeleterevision" => "Verwijderde versie van $1",
+"undeletebtn" => "Terugplaatsen!",
+"undeletedarticle" => "\"$1\" is teruggeplaatst.",
+"undeletedtext" =>"Het artikel [[$1]] is teruggeplaatst. Zie [[{{ns:4}}:Logboek verwijderde pagina's]] voor een lijst van de meest recente verwijderingen en terugplaatsingen.",
+
+# Contributions
+# Bijdragen
+"contributions" => "Bijdragen per gebruiker",
+"mycontris" => "Mijn bijdragen",
+"contribsub" => "Voor $1",
+"nocontribs" => "Geen wijzigingen gevonden die aan de gestelde criteria voldoen.",
+"ucnote"  => "Hieronder ziet u de laatste <b>$1</b> wijzigingen van deze gebruiker in de laatste <b>$2</b> dagen.",
+"uclinks"  => "Bekijk de laatste <b>$1</b> veranderingen; bekijk de laatste <b>$2</b> dagen.",
+"uctop" => " (laatste wijziging)",
+
+# What links here
+# Wat linkt hier
+"whatlinkshere" => "Referenties",
+"notargettitle" => "Geen doelpagina",
+"notargettext" => "U hebt niet gezegd voor welke pagina u deze functie wilt bekijken.",
+"linklistsub" => "(lijst van verwijzingen)",
+"linkshere"  => "De volgende pagina's verwijzen hiernaartoe:",
+"nolinkshere" => "Geen enkele pagina verwijst hierheen.",
+"isredirect" => "redirect pagina",
+
+# Block/unblock IP
+#
+"blockip"  => "Gebruiker blokkeren",
+"blockiptext" => "Gebruik het onderstaande formulier om een bepaald IP-adres of een bepaalde gebruikersnaam de schrijftoegang te ontnemen. Gebruik deze optie spaarzaam! Het is bedoeld om vandalisme te voorkomen. Misbruik van deze mogelijkheid kan tot gevolg hebben dat uw systeembeheerderschap wordt weggenomen. Vul hieronder een specifieke reden in.",
+"ipaddress"  => "IP-adres of gebruikersnaam",
+"ipbreason"  => "Reden",
+"ipbsubmit"  => "Blokkeer deze gebruiker",
+"badipaddress" => "Geen bestaande gebruikersnaam of geldig IP-adres",
+"blockipsuccesssub" => "Blokkering gelukt",
+"blockipsuccesstext" => "\"$1\" is geblokkeerd.<br />
+Zie de [[speciaal:Ipblocklist|Lijst van geblokkeerde IP-adressen]].",
+"unblockip"  => "De-blokkeer gebruiker",
+"unblockiptext" => "Gebruik het onderstaande formulier om terug schrijftoegang te geven aan een geblokkeerde gebruiker of IP-adres.",
+"ipusubmit"  => "De-blokkeer deze gebruiker.",
+"ipusuccess" => "\"$1\" is gedeblokkeerd.",
+"ipblocklist" => "Lijst van geblokkeerde gebruikers en IP-adressen.",
+"blocklistline" => "Op $1 blokkeerde $2: $3 ($4)",
+"blocklink"  => "blokkeer",
+"unblocklink" => "de-blokkeer",
+"contribslink" => "bijdragen",
+"autoblocker" => "U werd geblokkeerd omdat uw IP-adres overeenkomt met dat van \"$1\". Deze gebruiker werd geblokkeerd met als reden: \"$2\".",
+
+# Developer tools
+# Ontwikkelingsgereedsschap
+"lockdb"  => "Blokkeer de database",
+"unlockdb"  => "De-blokkeer de database",
+"lockdbtext" => "Waarschuwing: De database blokkeren heeft tot gevolg dat geen enkele gebruiker meer in staat is de pagina's te bewerken, hun voorkeuren te wijzigen of iets anders te doen waarvoor er wijzigingen in de database nodig zijn.",
+"unlockdbtext" => "Het de-blokkeren van de database zal de gebruikers de mogelijkheid geven om wijzigingen aan pagina's op te slaan, hun voorkeuren te wijzigen en alle andere bewerkingen waarvoor er wijzigingen in de database nodig zijn. Is dit inderdaad wat u wilt doen?.",
+"lockconfirm" => "Ja, ik wil de database blokkeren.",
+"unlockconfirm" => "Ja, ik wil de database de-blokkeren.",
+"lockbtn"  => "Blokkeer de database",
+"unlockbtn"  => "De-blokkeer de database",
+"locknoconfirm" => "U heeft niet het vakje aangevinkt om uw keuze te bevestigen.",
+"lockdbsuccesssub" => "Blokkering database succesvol",
+"unlockdbsuccesssub" => "Blokkering van de database opgeheven",
+"lockdbsuccesstext" => "De database van {{SITENAME}} NL is geblokkeerd.
+Vergeet niet de database opnieuw te de-blokkeren zodra u klaar bent met uw onderhoud.",
+"unlockdbsuccesstext" => "Blokkering van de database van {{SITENAME}} NL is opgeheven.",
+
+# Move page
+# Verplaats pagina
+"movepage"  => "Verplaats pagina",
+"movepagetext" => "Door middel van het onderstaande formulier kunt u de titel van een pagina hernoemen. De voorgeschiedenis van de oude pagina zal deze van de nieuwe worden. De oude titel zal automatisch een doorverwijzing worden naar de nieuwe. U kunt een dergelijke hernoeming alleen doen plaatsvinden, als er geen pagina bestaat met de nieuwe naam, of als er slechts een redirect zonder verdere geschiedenis is.",
+"movepagetalktext" => "De bijbehorende overlegpagina wordt ook verplaatst, maar '''niet''' in de volgende gevallen:
+* Als de pagina naar een andere naamruimte wordt verplaatst
+* Als er al een niet-lege Overlegpagina bestaat onder de andere naam
+* Als u de onderstaande radiobox niet aangevinkt laat",
+"movearticle" => "Verplaats pagina",
+"movenologin" => "Niet aangemeld",
+"movenologintext" => "U dient [[Speciaal:Userlogin|aangemeld]]
+te zijn om een pagina te verplaatsen.",
+"newtitle"  => "Naar de nieuwe titel",
+"movepagebtn" => "Verplaats pagina",
+"pagemovedsub" => "De verplaatsing was succesvol",
+"pagemovedtext" => "Pagina \"[[$1]]\" is verplaatst naar \"[[$2]]\".",
+"articleexists" => "Er is reeds een pagina met deze titel of de titel is ongeldig. <br />Gelieve een andere titel te kiezen.",
+"talkexists" => "De pagina zelf is verplaatst, maar de Overlegpagina kon niet worden verplaatst, omdat de doeltitel al een niet-lege overlegpagina had. Combineer de overlegpagina's a.u.b. handmatig.",
+"movedto"  => "verplaatst naar",
+"movetalk"  => "Verplaats \"Overleg\" pagina ook indien aanwezig.",
+"talkpagemoved" => "De bijhorende overlegpagina is ook verplaatst.",
+"talkpagenotmoved" => "De bijhorende overlegpagina is <strong>niet</strong> verplaatst.",
+
+# Math
+'mw_math_png' => "Altijd als PNG weergeven",
+'mw_math_simple' => "HTML voor eenvoudige formules, anders PNG",
+'mw_math_html' => "HTML indien mogelijk, anders PNG",
+'mw_math_source' => "Laat de TeX broncode staan (voor tekstbrowsers)",
+'mw_math_modern' => "Aanbevolen methode voor recente browsers",
+'mw_math_mathml' => 'MathML',
+);
+
+class LanguageNl extends LanguageUtf8 {
+
+       function getNamespaces() {
+               global $wgNamespaceNamesNl;
+               return $wgNamespaceNamesNl;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsNl;
+               return $wgQuickbarSettingsNl;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesNl;
+               return $wgSkinNamesNl;
+       }
+
+       function date( $ts, $adj = false ) {
+               if ( $adj ) { $ts = $this->userAdjust( $ts ); }
+
+               $d = (0 + substr( $ts, 6, 2 )) . " " .
+               $this->getMonthAbbreviation( substr( $ts, 4, 2 ) ) . " " .
+               substr( $ts, 0, 4 );
+               return $d;
+       }
+
+       function timeanddate( $ts, $adj = false ) {
+               return $this->date( $ts, $adj ) . " " . $this->time( $ts, $adj );
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesNl;
+               if( isset( $wgAllMessagesNl[$key] ) ) {
+                       return $wgAllMessagesNl[$key];
+               } else {
+                       return parent::getMessage( $key );
+               }
+       }
+
+       function formatNum( $number, $year = false ) {
+               return $year ? $number : strtr( $this->commafy( $number ), '.,', ',.' );
+       }
+}
+
+?>
diff --git a/languages/LanguageNn.php b/languages/LanguageNn.php
new file mode 100644 (file)
index 0000000..6ef8dbe
--- /dev/null
@@ -0,0 +1,1804 @@
+<?php
+/** Norwegian (Nynorsk)
+  *
+  * @license http://www.gnu.org/copyleft/fdl.html GNU Free Documentation License
+  * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
+  *
+  * @author Olve Utne
+  * @author Guttorm Flatabø
+  * @link http://meta.wikimedia.org/w/index.php?title=LanguageNn.php&action=history
+  * @link http://nn.wikipedia.org/w/index.php?title=Brukar:Dittaeva/LanguageNn.php&action=history
+  *
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+require_once( 'LanguageUtf8.php' );
+
+if($wgMetaNamespace === FALSE)
+       $wgMetaNamespace = str_replace( ' ', '_', $wgSitename );
+
+/* private */ $wgNamespaceNamesNn = array(
+       NS_MEDIA          => 'Filpeikar',
+       NS_SPECIAL        => 'Spesial',
+       NS_MAIN           => '',
+       NS_TALK           => 'Diskusjon',
+       NS_USER           => 'Brukar',
+       NS_USER_TALK      => 'Brukardiskusjon',
+       NS_PROJECT        => $wgMetaNamespace,
+       NS_PROJECT_TALK   => $wgMetaNamespace . '-diskusjon',
+       NS_IMAGE          => 'Fil',
+       NS_IMAGE_TALK     => 'Fildiskusjon',
+       NS_MEDIAWIKI      => 'MediaWiki',
+       NS_MEDIAWIKI_TALK => 'MediaWiki-diskusjon',
+       NS_TEMPLATE       => 'Mal',
+       NS_TEMPLATE_TALK  => 'Maldiskusjon',
+       NS_HELP           => 'Hjelp',
+       NS_HELP_TALK      => 'Hjelpdiskusjon',
+       NS_CATEGORY       => 'Kategori',
+       NS_CATEGORY_TALK  => 'Kategoridiskusjon'
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgQuickbarSettingsNn = array(
+       'Ingen', 'Venstre', 'Høgre', 'Flytande venstre', 'Flytande høgre'
+);
+
+/* private */ $wgSkinNamesNn = array(
+       'standard'        => 'Klassisk',
+       'nostalgia'       => 'Nostalgi',
+       'cologneblue'     => 'Kölnerblå',
+       'myskin'          => 'MiDrakt'
+) + $wgSkinNamesEn;
+
+/* private */ $wgDateFormatsNn = array(
+       'Standard',
+       '15. januar 2001 kl. 16:12',
+       '15. jan. 2001 kl. 16:12',
+       '16:12, 15. januar 2001',
+       '16:12, 15. jan. 2001',
+       'ISO 8601' => '2001-01-15 16:12:34'
+);
+
+/* private */ $wgBookstoreListNn = array(
+       'Bibsys'       => 'http://ask.bibsys.no/ask/action/result?kilde=biblio&fid=isbn&lang=nn&term=$1',
+       'BokBerit'     => 'http://www.bokberit.no/annet_sted/bocker/$1.html',
+       'Bokkilden'    => 'http://www.bokkilden.no/ProductDetails.aspx?ProductId=$1',
+       'Haugenbok'    => 'http://www.haugenbok.no/resultat.cfm?st=hurtig&isbn=$1',
+       'Akademika'    => 'http://www.akademika.no/sok.php?isbn=$1',
+       'Gnist'        => 'http://www.gnist.no/sok.php?isbn=$1',
+       'Amazon.co.uk' => 'http://www.amazon.co.uk/exec/obidos/ISBN=$1',
+       'Amazon.de'    => 'http://www.amazon.de/exec/obidos/ISBN=$1',
+       'Amazon.com'   => 'http://www.amazon.com/exec/obidos/ISBN=$1'
+);
+
+# Note to translators:
+#   Please include the English words as synonyms.  This allows people
+#   from other wikis to contribute more easily.
+#
+/* private */ $wgMagicWordsNn = array(
+#   ID                                 CASE  SYNONYMS
+       MAG_REDIRECT             => array( 0,    '#redirect', '#omdiriger'                                              ),
+       MAG_NOTOC                => array( 0,    '__NOTOC__', '__INGAINNHALDSLISTE__', '__INGENINNHOLDSLISTE__'         ),
+       MAG_FORCETOC             => array( 0,    '__FORCETOC__', '__ALLTIDINNHALDSLISTE__', '__ALLTIDINNHOLDSLISTE__'   ),
+       MAG_TOC                  => array( 0,    '__TOC__', '__INNHALDSLISTE__', '__INNHOLDSLISTE__'                    ),
+       MAG_NOEDITSECTION        => array( 0,    '__NOEDITSECTION__', '__INGABOLKENDRING__', '__INGABOLKREDIGERING__', '__INGENDELENDRING__'),
+       MAG_CURRENTMONTH         => array( 1,    'CURRENTMONTH', 'MÅNADNO', 'MÅNEDNÅ'                                   ),
+       MAG_CURRENTMONTHNAME     => array( 1,    'CURRENTMONTHNAME', 'MÅNADNONAMN', 'MÅNEDNÅNAVN'                       ),
+       MAG_CURRENTMONTHABBREV   => array( 1,    'CURRENTMONTHABBREV', 'MÅNADNOKORT', 'MÅNEDNÅKORT'                     ),
+       MAG_CURRENTDAY           => array( 1,    'CURRENTDAY', 'DAGNO', 'DAGNÅ'                                         ),
+       MAG_CURRENTDAYNAME       => array( 1,    'CURRENTDAYNAME', 'DAGNONAMN', 'DAGNÅNAVN'                             ),
+       MAG_CURRENTYEAR          => array( 1,    'CURRENTYEAR', 'ÅRNO', 'ÅRNÅ'                                          ),
+       MAG_CURRENTTIME          => array( 1,    'CURRENTTIME', 'TIDNO', 'TIDNÅ'                                        ),
+       MAG_NUMBEROFARTICLES     => array( 1,    'NUMBEROFARTICLES', 'INNHALDSSIDETAL', 'INNHOLDSSIDETALL'              ),
+       MAG_NUMBEROFFILES        => array( 1,    'NUMBEROFFILES', 'FILTAL'                                              ),
+       MAG_PAGENAME             => array( 1,    'PAGENAME', 'SIDENAMN', 'SIDENAVN'                                     ),
+       MAG_PAGENAMEE            => array( 1,    'PAGENAMEE', 'SIDENAMNE', 'SIDENAVNE'                                  ),
+       MAG_NAMESPACE            => array( 1,    'NAMESPACE', 'NAMNEROM', 'NAVNEROM'                                    ),
+       MAG_SUBST                => array( 0,    'SUBST:', 'LIMINN:'                                                    ),
+       MAG_MSGNW                => array( 0,    'MSGNW:', 'IKWIKMELD:'                                                 ),
+       MAG_END                  => array( 0,    '__END__', '__SLUTT__'                                                 ),
+       MAG_IMG_THUMBNAIL        => array( 1,    'thumbnail', 'thumb', 'mini', 'miniatyr'                               ),
+       MAG_IMG_RIGHT            => array( 1,    'right', 'høgre', 'høyre'                                              ),
+       MAG_IMG_LEFT             => array( 1,    'left', 'venstre'                                                      ),
+       MAG_IMG_NONE             => array( 1,    'none', 'ingen'                                                        ),
+       MAG_IMG_WIDTH            => array( 1,    '$1px', '$1pk'                                                         ),
+       MAG_IMG_CENTER           => array( 1,    'center', 'centre', 'sentrum'                                          ),
+       MAG_IMG_FRAMED           => array( 1,    'framed', 'enframed', 'frame', 'ramme'                                 ),
+       MAG_SITENAME             => array( 1,    'SITENAME', 'NETTSTADNAMN'                                             ),
+       MAG_NS                   => array( 0,    'NS:', 'NR:'                                                           ),
+       MAG_LOCALURL             => array( 0,    'LOCALURL:', 'LOKALLENKJE:', 'LOKALLENKE:'                             ),
+       MAG_LOCALURLE            => array( 0,    'LOCALURLE:', 'LOKALLENKJEE:', 'LOKALLENKEE:'                          ),
+       MAG_SERVER               => array( 0,    'SERVER', 'TENAR', 'TJENER'                                            ),
+       MAG_SERVERNAME           => array( 0,    'SERVERNAME', 'TENARNAMN', 'TJENERNAVN'                                ),
+       MAG_SCRIPTPATH           => array( 0,    'SCRIPTPATH', 'SKRIPTSTI'                                              ),
+       MAG_GRAMMAR              => array( 0,    'GRAMMAR:', 'GRAMMATIKK:'                                              ),
+       MAG_NOTITLECONVERT       => array( 0,    '__NOTITLECONVERT__', '__NOTC__'                                       ),
+       MAG_NOCONTENTCONVERT     => array( 0,    '__NOCONTENTCONVERT__', '__NOCC__'                                     ),
+       MAG_CURRENTWEEK          => array( 1,    'CURRENTWEEK', 'VEKENRNO', 'UKENRNÅ'                                   ),
+       MAG_CURRENTDOW           => array( 1,    'CURRENTDOW', 'VEKEDAGNRNO', 'UKEDAGNRNÅ'                              ),
+       MAG_REVISIONID           => array( 1,    'REVISIONID', 'VERSJONSID'                                             )
+) + $wgMagicWordsEn;
+
+
+#-------------------------------------------------------------------
+# Default messages
+#-------------------------------------------------------------------
+
+/* private */ $wgAllMessagesNn = array(
+# User preference toggles
+'tog-underline'           => 'Strek under lenkjer:',
+'tog-highlightbroken'     => 'Vis lenkjer til tomme sider <a href="" class="new">slik</a> (alternativt slik<a href="" class="internal">?</a>)',
+'tog-justify'            => 'Blokkjusterte avsnitt',
+'tog-hideminor'           => 'Skjul uviktige endringar på «siste endringar»',
+'tog-usenewrc'            => 'Utvida funksjonalitet på «siste endringar» (JavaScript)',
+'tog-numberheadings'      => 'Vis nummererte overskrifter',
+'tog-showtoolbar'         => 'Vis endringsknappar (JavaScript)',
+'tog-editondblclick'      => 'Endre sider med dobbelklikk (JavaScript)',
+'tog-editsection'         => 'Endre avsnitt med hjelp av [endre]-lenkje',
+'tog-editsectiononrightclick' => 'Endre avsnitt med å høgreklikke på avsnittsoverskrift (JavaScript)',
+'tog-showtoc'             => 'Vis innhaldsliste (for sider med meir enn tre bolkar)',
+'tog-rememberpassword'    => 'Hugs passordet til neste gong',
+'tog-editwidth'           => 'Gjev endringsboksen full breidd',
+'tog-watchdefault'        => 'Legg sider eg endrar i overvakingslista mi',
+'tog-minordefault'        => 'Merk endringar som «uviktige» som standard',
+'tog-previewontop'        => 'Vis førehandsvisinga føre endringsboksen',
+'tog-previewonfirst'      => 'Førehandsvis første endring',
+'tog-nocache'             => 'Ikkje bruk nettlesaren sitt mellomlager (cache)',
+'tog-enotifwatchlistpages' => 'Send e-post når dei overvaka sidene mine blir endra',
+'tog-enotifusertalkpages' => 'Send e-post når brukarsida mi blir endra',
+'tog-enotifminoredits'    => 'Send e-post òg for uviktige endringar',
+'tog-enotifrevealaddr'    => 'Vis e-postadressa mi i endrings-e-post',
+'tog-shownumberswatching' => 'Vis kor mange som overvakar sida',
+'tog-fancysig'            => 'Signatur utan automatisk lenkje',
+'tog-externaleditor'      => 'Eksternt handsamingsprogram som standard',
+'tog-externaldiff'        => 'Eksternt skilnadprogram som standard',
+
+'underline-always'        => 'Alltid',
+'underline-never'         => 'Aldri',
+'underline-default'       => 'Nettlesarstandard',
+
+'skinpreview'             => '(førehandsvis)',
+
+# Dates
+'sunday'                  => 'søndag',
+'monday'                  => 'måndag',
+'tuesday'                 => 'tysdag',
+'wednesday'               => 'onsdag',
+'thursday'                => 'torsdag',
+'friday'                  => 'fredag',
+'saturday'                => 'laurdag',
+'january'                 => 'januar',
+'february'                => 'februar',
+'march'                   => 'mars',
+'april'                   => 'april',
+'may_long'                => 'mai',
+'june'                    => 'juni',
+'july'                    => 'juli',
+'august'                  => 'august',
+'september'               => 'september',
+'october'                 => 'oktober',
+'november'                => 'november',
+'december'                => 'desember',
+'jan'                     => 'jan',
+'feb'                     => 'feb',
+'mar'                     => 'mar',
+'apr'                     => 'apr',
+'may'                     => 'mai',
+'jun'                     => 'jun',
+'jul'                     => 'jul',
+'aug'                     => 'aug',
+'sep'                     => 'sep',
+'oct'                     => 'okt',
+'nov'                     => 'nov',
+'dec'                     => 'des',
+
+# Bits of text used by many pages:
+'categories'              => 'Kategoriar',
+'category'                => 'kategori',
+'category_header'         => 'Artiklar i kategorien «$1»',
+'subcategories'           => 'Underkategoriar',
+
+'linktrail'              => '/^([æøåa-z]+)(.*)$/sD',
+'mainpage'               => 'Hovudside',
+'mainpagetext'           => 'MediaWiki er no installert.',
+'mainpagedocfooter'       => 'Sjå [http://meta.wikipedia.org/wiki/MediaWiki_localization dokumentasjon for å tilpasse brukargrensesnittet] og [http://meta.wikipedia.org/wiki/Help:Contents brukarmanualen] for bruk og konfigurasjonshjelp.',
+
+'portal'                 => 'Brukarportal',
+'portal-url'             => 'Project:Brukarportal',
+'about'                          => 'Om',
+'aboutsite'               => 'Om {{SITENAME}}',
+'aboutpage'              => 'Project:Om',
+'article'                 => 'Innhaldsside',
+'help'                   => 'Hjelp',
+'helppage'               => 'Help:Innhald',
+'bugreports'             => 'Feilmeldingar',
+'bugreportspage'          => 'Project:Feilmeldingar',
+'sitesupport'             => 'Gåver',
+'sitesupport-url'         => 'Project:Gåver',
+'faq'                    => 'OSS',
+'faqpage'                => 'Project:OSS',
+'edithelp'               => 'Hjelp til endring',
+'newwindow'              => '(blir opna i eit nytt vindauge)',
+'edithelppage'           => 'Help:Endring',
+'cancel'                 => 'Avbryt',
+'qbfind'                 => 'Finn',
+'qbbrowse'               => 'Bla gjennom',
+'qbedit'                 => 'Endre',
+'qbpageoptions'           => 'Denne sida',
+'qbpageinfo'             => 'Samanheng',
+'qbmyoptions'            => 'Sidene mine',
+'qbspecialpages'         => 'Spesialsider',
+'moredotdotdot'                  => 'Meir...',
+'mypage'                 => 'Sida mi',
+'mytalk'                 => 'Diskusjonssida mi',
+'anontalk'               => 'Diskusjonside for denne IP-adressa',
+'navigation'              => 'Navigering',
+
+# Metadata in edit box
+'metadata'                => '<b>Metadata</b> (for forklaring, sjå <a href="$1">her</a>)',
+'metadata_page'           => 'Project:Metadata',
+
+'currentevents'           => 'Aktuelt',
+'currentevents-url'       => 'Aktuelt',
+
+'disclaimers'             => 'Vilkår',
+'disclaimerpage'             => 'Project:Vilkår',
+'errorpagetitle'          => 'Feil',
+'returnto'                       => 'Attende til $1.',
+'tagline'                        => 'Frå {{SITENAME}}',
+'whatlinkshere'                  => 'Sider med lenkjer hit',
+'help'                   => 'Hjelp',
+'search'                 => 'Søk',
+'go'                     => 'Vis',
+'history'                => 'Sidehistorikk',
+'history_short'           => 'Historikk',
+'info_short'             => 'Informasjon',
+'printableversion'        => 'Utskriftsversjon',
+'print'                   => 'Skriv ut',
+'edit'                    => 'Endre',
+'editthispage'           => 'Endre sida',
+'delete'                  => 'Slett',
+'deletethispage'          => 'Slett side',
+'undelete_short1'         => 'Attopprett 1 endring',
+'undelete_short'          => 'Attopprett $1 endringar',
+'protect'                 => 'Vern',
+'protectthispage'         => 'Vern denne sida',
+'unprotect'               => 'fjern vern',
+'unprotectthispage'       => 'Fjern vern av denne sida',
+'newpage'                 => 'Ny side',
+'talkpage'               => 'Drøft sida',
+'specialpage'             => 'Spesialside',
+'personaltools'           => 'Personlege verktøy',
+'postcomment'             => 'Legg til kommentar',
+'addsection'              => '+',
+'articlepage'            => 'Vis innhaldsside',
+'subjectpage'            => 'Vis emne', # For compatibility
+'talk'                    => 'Diskusjon',
+'views'                   => 'Visningar',
+'toolbox'                 => 'Verktøy',
+'userpage'                => 'Vis brukarside',
+'wikipediapage'           => 'Vis prosjektside',
+'imagepage'               => 'Vis filside',
+'viewtalkpage'            => 'Vis diskusjon',
+'otherlanguages'          => 'På andre språk',
+'redirectedfrom'          => '(Omdirigert frå $1)',
+'lastmodified'           => 'Sist endra $1.',
+'viewcount'              => 'Vist $1 gonger.',
+'copyright'              => 'Innhaldet er utgjeve under $1.',
+'poweredby'              => '{{SITENAME}} bruker [http://www.mediawiki.org/ MediaWiki] som er fri wikiprogramvare.',
+'printsubtitle'           => '(frå {{SERVER}})',
+'protectedpage'           => 'Verna side',
+'administrators'          => '{{ns:4}}:Administratorar',
+'sysoptitle'             => 'Administratortilgang trengst',
+'sysoptext'                      => 'Funksjonen kan berre utførast av administratorar. Sjå $1.',
+'developertitle'          => 'Utviklartilgang trengst.',
+'developertext'                  => 'Funksjonen kan berre utførast av administratorar med utviklartilgang. Sjå $1.',
+'badaccess'               => 'Tilgangsfeil',
+'badaccesstext'           => 'Handlinga du har prøvd å få utført kan berre utførast av brukarar med «$2»-tilgang. Sjå $1.',
+'versionrequired'         => 'MediaWiki versjon $1 trengst',
+'versionrequiredtext'     => 'For å bruke denne sida trengst MediaWiki versjon $1. Sjå [[{{ns:special}}:Version]]',
+'nbytes'                 => '$1 byte',
+'ok'                     => 'OK',
+'sitetitle'              => '{{SITENAME}}',
+'pagetitle'              => '$1 - {{SITENAME}}',
+'sitesubtitle'           => 'Det frie oppslagsverket',
+'retrievedfrom'           => 'Henta frå «$1»',
+'newmessages'             => 'Du har $1.',
+'newmessageslink'         => 'nye meldingar',
+'editsection'             => 'endre',
+'toc'                     => 'Innhaldsliste',
+'showtoc'                 => 'vis',
+'hidetoc'                 => 'gøym',
+'thisisdeleted'           => 'Sjå eller attopprett $1?',
+'restorelink1'            => 'ein sletta versjon',
+'restorelink'             => '$1 sletta versjonar',
+'feedlinks'               => 'Mating:',
+'sitenotice'             => '-', # the equivalent to wgSiteNotice
+
+# Short words for each namespace, by default used in the 'article' tab in monobook
+'nstab-main'              => 'Innhaldsside',
+'nstab-user'              => 'Brukarside',
+'nstab-media'             => 'Filside',
+'nstab-special'           => 'Spesial',
+'nstab-wp'                => 'Prosjektside',
+'nstab-image'             => 'Fil',
+'nstab-mediawiki'         => 'Systemmelding',
+'nstab-template'          => 'Mal',
+'nstab-help'              => 'Hjelp',
+'nstab-category'          => 'Kategori',
+
+# Main script and global functions
+#
+'nosuchaction'           => 'Funksjonen finst ikkje',
+'nosuchactiontext'        => 'Wikiprogramvaren kjenner ikkje att funksjonen som er spesifisert i nettadressa',
+'nosuchspecialpage'       => 'Ei slik spesialside finst ikkje',
+'nospecialpagetext'       => 'Du har bede om ei spesialside som ikkje finst, liste over spesialsider er [[Special:Specialpages|her]].',
+
+# General errors
+#
+'error'                          => 'Feil',
+'databaseerror'           => 'Databasefeil',
+'dberrortext'            => 'Det oppstod ein syntaksfeil i databaseførespurnaden. Dette kan tyde på ein feil i programvaren. Den sist prøvde førespurnaden var: <blockquote><tt>$1</tt></blockquote> frå funksjonen «<tt>$2</tt>». MySQL returnerte feilen «<tt>$3: $4</tt>».',
+'dberrortextcl'           => 'Det oppstod ein syntaksfeil i databaseførespurnaden. Den sist prøvde førespurnaden var: «$1» frå funksjonen "$2".
+MySQL returnerte feilen «$3: $4».',
+'noconnect'              => 'Wikien har tekniske problem og kunne ikkje kople til databasen.<br />$1',
+'nodb'                   => 'Kunne ikkje velja databasen $1',
+'cachederror'            => 'Det følgjande er ein lagra kopi av den ønska sida, og er ikkje nødvendigvis oppdatert.',
+'laggedslavemode'          => 'Åtvaring: Det er mogleg at sida ikkje er heilt oppdatert.',
+'readonly'                       => 'Databasen er skriveverna',
+'enterlockreason'         => 'Skriv ein grunn for vernet, inkludert eit overslag for kva tid det vil bli oppheva',
+'readonlytext'           => 'Databasen er akkurat no skriveverna, truleg for rutinemessig vedlikehald. Administratoren som verna han har gjeve denne forklaringa:<p>$1',
+'missingarticle'          => 'Databasen fann ikkje teksten til ei side med namnet «$1» som han skulle ha funne.
+
+Dette skjer oftast fordi du følgde ei lenkje til ei oppføring som har vorte sletta.
+Sletta oppføringar kan vanlegvis attopprettast.
+
+Dersom dette ikkje er tilfellet kan du ha funne ein feil i programvaren. Gje melding om dette til ein administrator, med adressa åt sida.',
+'readonly_lag'            => 'Databasen er mellombels skriveverna for at databasetenarane skal kunna synkronisere seg mot kvarandre',
+'internalerror'           => 'Intern feil',
+'filecopyerror'           => 'Kunne ikkje kopiere fila frå «$1» til «$2».',
+'filerenameerror'         => 'Kunne ikkje døype om fila frå «$1» til «$2».',
+'filedeleteerror'         => 'Kunne ikkje slette fila «$1».',
+'filenotfound'           => 'Kunne ikkje finne fila «$1».',
+'unexpected'             => 'Uventa verdi: «$1»=«$2».',
+'formerror'              => 'Feil: Kunne ikkje sende skjema',
+'badarticleerror'         => 'Handlinga kan ikkje utførast på denne sida.',
+'cannotdelete'           => 'Kunne ikkje slette fila. (Ho kan vera sletta av andre.)',
+'badtitle'               => 'Feil i tittelen',
+'badtitletext'           => 'Den ønska tittelen var ulovleg, tom eller feil lenka frå ei anna wiki.',
+'perfdisabled'            => 'Beklagar! Denne funksjonen er mellombels deaktivert for å spara tenarkapasitet.',
+'perfdisabledsub'         => 'Her er ein lagra kopi frå $1:',
+'perfcached'              => 'Det følgjande er frå mellomlageret åt tenaren og er ikkje nødvendigvis oppdatert.',
+'wrong_wfQuery_params'    => 'Feil parameter gjevne til wfQuery()<br />Funksjon: $1<br />Førespurnad: $2',
+'viewsource'              => 'Vis kjeldetekst',
+'protectedtext'           => 'Denne sida er verna for endring. Det kan vera fleire grunnar til dette, sjå [[{{ns:4}}:Verna side]].
+
+Du kan sjå og kopiere kjeldeteksten til denne sida:',
+'sqlhidden'               => '(SQL-førespurnaden er gøymd)',
+
+# Login and logout pages
+#
+'logouttitle'            => 'Logg ut',
+'logouttext'             => 'Du er no utlogga. Avhengig av innstillingane på tenaren kan nettlesaren no brukast anonymt på {{SITENAME}};
+du kan logge inn att med same kontoen eller ein annan brukar kan logge inn. Ver merksam på at nokre sider kan fortsetje å bli viste som om du er innlogga inntil du tømmer mellomlageret til nettlesaren din.',
+'welcomecreation'         => '== Hjarteleg velkommen til {{SITENAME}}, [[user:$1|$1]]! ==
+
+Brukarkontoen din har vorte oppretta. Det er tilrådd at du skriv litt om deg sjølv på [[user:$1|brukarsida di]] og ser gjennom [[special:preferences|brukarinnstillingane dine]].',
+'loginpagetitle'          => 'Logg inn',
+'yourname'                       => 'Brukarnamn',
+'yourpassword'           => 'Passord',
+'yourpasswordagain'       => 'Skriv opp att passordet',
+'newusersonly'           => ' (berre nye brukarar)',
+'remembermypassword'      => 'Hugs passordet.',
+'yourdomainname'          => 'Domenet ditt',
+'externaldberror'         => 'Det var anten ein ekstern databasefeil i tilgjengekontrollen, eller du har ikkje løyve til å oppdatere den eksterne kontoen din.',
+'loginproblem'           => '<b>Du vart ikkje innlogga.</b><br />Prøv om att!',
+'alreadyloggedin'         => '<strong>Brukar $1, du er allereie innlogga!</strong><br />',
+'login'                          => 'Logg inn',
+'loginprompt'             => 'Nettlesaren din må godta informasjonskapslar for at du skal kunna logge inn.',
+'userlogin'              => 'Lag brukarkonto / logg inn',
+'logout'                 => 'Logg ut',
+'userlogout'             => 'Logg ut',
+'notloggedin'            => 'Ikkje innlogga',
+'createaccount'                  => 'Opprett ny konto',
+'createaccountmail'      => 'over e-post',
+'badretype'              => 'Passorda du skreiv inn er ikkje like.',
+'userexists'             => 'Brukarnamnet er allereie i bruk. Vel eit nytt.',
+'youremail'              => 'E-postadresse*',
+'yourrealname'           => 'Namn*',
+'yourlanguage'           => 'Språk for brukargrensesnittet',
+'yourvariant'             => 'Språkvariant',
+'yournick'                       => 'Kallenamn (for signaturar)',
+'email'                   => 'E-post',
+'emailforlost'           => 'Felt merkte med ei stjerne (*) er valfrie. E-postadressa gjer det mogleg for andre brukarar å ta kontakt med deg utan at du offentleggjer ho. Ho kan òg bli brukt til å sende deg nytt passord. Namnet ditt, dersom du vel å fylle ut dette feltet, vil bli brukt til å godskrive arbeid du har gjort.<br /><br />',
+'prefs-help-email-enotif' => 'Denne adressa blir også brukt til å sende deg endringsmeldingar dersom du har valt å ta den funksjonen i bruk.',
+'prefs-help-realname'     => '* Namn (valfritt): Om du vel å fylle ut dette feltet, vil informasjonen bli brukt til å godskrive arbeid du har gjort.',
+'loginerror'             => 'Innloggingsfeil',
+'prefs-help-email'        => '* E-post (valfritt): Gjer det mogleg for andre brukarar å ta kontakt med deg utan at du offentleggjer adressa.',
+'nocookiesnew'           => 'Brukarkontoen vart oppretta, men du er ikkje innlogga. {{SITENAME}} bruker informasjonskapslar for å logge inn brukarar,
+nettlesaren din er innstilt for ikkje å godta desse. Etter at du har endra innstillingane slik at nettlesaren godtek informasjonskapslar, kan du logge inn med det nye brukarnamnet og passordet ditt.',
+'nocookieslogin'         => '{{SITENAME}} bruker informasjonskapslar for å logge inn brukarar, nettlesaren din er innstilt for ikkje å godta desse.
+Etter at du har endra innstillingane slik at nettlesaren godtek informasjonskapslar kan du prøve å logge inn på nytt.',
+'noname'                 => 'Du har ikkje oppgjeve gyldig brukarnamn.',
+'loginsuccesstitle'       => 'Du er no innlogga',
+'loginsuccess'           => 'Du er no innlogga som «$1».',
+'nosuchuser'             => 'Det finst ikkje nokon brukar med brukarnamnet «$1». Sjekk at du har skrive rett eller bruk skjemaet under til å opprette ein ny konto.',
+'nosuchusershort'         => 'Det finst ikkje nokon brukar med brukarnamnet «$1». Sjekk at du har skrive rett.',
+'wrongpassword'                  => 'Du har oppgjeve eit ugyldig passord. Prøv om att.',
+'mailmypassword'          => 'Send meg nytt passord',
+'passwordremindertitle'   => 'Nytt passord til {{SITENAME}}',
+'passwordremindertext'    => 'Nokon (truleg du, frå IP-adressa $1) bad oss sende deg eit nytt passord til {{SITENAME}}. Passordet for brukaren «$2» er no «$3». Du bør logge inn og endre passordet så snart som råd.',
+'noemail'                        => 'Det er ikkje registrert noka e-postadresse åt brukaren «$1».',
+'passwordsent'           => 'Eit nytt passord er sendt åt e-postadressa registrert på brukaren «$1».',
+'eauthentsent'            => 'Ein stadfestings-e-post er sendt til den oppgjevne e-postadressa. For at adressa skal kunna brukast, må du følgje instruksjonane i e-posten for å stadfeste at ho faktisk tilhøyrer deg.',
+'loginend'               => '&nbsp;',
+'mailerror'               => 'Ein feil oppstod ved sending av e-post: $1',
+'acct_creation_throttle_hit' => 'Beklagar, du har allereie laga $1 brukarkontoar. Du har ikkje høve til å laga fleire.',
+'emailauthenticated'      => 'E-postadressa di vart stadfest $1.',
+'emailnotauthenticated'   => 'E-postadressa di er <strong>enno ikkje stadfest</strong>. Dei følgjande funksjonane kan ikkje bruke ho.',
+'noemailprefs'            => '<strong>Du har ikkje oppgjeve noko e-postadresse</strong>, dei følgjande funksjonane vil ikkje verke.',
+'emailconfirmlink'        => 'Stadfest e-post-adressa di',
+'invalidemailaddress'     => 'E-postadressa kan ikkje brukast sidan ho er feil oppbygd. Skriv ei rett oppbygd adresse eller tøm feltet.',
+
+# Edit page toolbar
+'bold_sample'             => 'Halvfeit skrift',
+'bold_tip'                => 'Halvfeit skrift',
+'italic_sample'           => 'Kursivskrift',
+'italic_tip'              => 'Kursivskrift',
+'link_sample'             => 'Lenkjetittel',
+'link_tip'                => 'Intern lenkje',
+'extlink_sample'          => 'http://www.eksempel.no lenkjetittel',
+'extlink_tip'             => 'Ekstern lenkje (hugs http:// prefiks)',
+'headline_sample'         => 'Overskriftstekst',
+'headline_tip'            => '2. nivå-overskrift',
+'math_sample'             => 'Skriv formel her',
+'math_tip'                => 'Matematisk formel (LaTeX)',
+'nowiki_sample'           => 'Skriv uformatert tekst her',
+'nowiki_tip'              => 'Sjå bort frå wikiformatering',
+'image_sample'            => 'Eksempel.jpg',
+'image_tip'               => 'Bilete eller lenkje til filomtale',
+'media_sample'            => 'Eksempel.ogg',
+'media_tip'               => 'Filpeikar',
+'sig_tip'                 => 'Signaturen din med tidsstempel',
+'hr_tip'                  => 'Vassrett line',
+'infobox'                 => 'Klikk på ein knapp for å få eksempeltekst',
+# alert box shown in browsers where text selection does not work, test e.g. with mozilla or konqueror
+'infobox_alert'           => 'Skriv inn teksten du vil ha formatert.\n Han vil bli vist i boksen slik at han kan kopierast og limast inn.\nEksempel:\n$1\nblir til:\n$2',
+
+# Edit pages
+#
+'summary'                => 'Samandrag',
+'subject'                => 'Emne/overskrift',
+'minoredit'              => 'Uviktig endring',
+'watchthis'              => 'Overvak side',
+'savearticle'            => 'Lagre',
+'preview'                => 'Førehandsvising',
+'showpreview'            => 'Førehandsvis',
+'showdiff'                => 'Vis skilnad',
+'blockedtitle'           => 'Brukaren er blokkert',
+'blockedtext'            => 'Brukarnamnet ditt eller IP-adressa di er blokkert frå endring, av $1. Denne grunnen vart gjeven:<br />\'\'$2\'\'<p>Du kan kontakte $1 eller ein annan [[Project:Administratorar|administrator]] for å diskutere blokkeringa.
+
+Ver merksam på at du ikkje kan bruke «send e-post åt brukar»-funksjonen så lenge du ikkje har ei gyldig e-postadresse registrert i [[Special:Preferences|innstillingane dine]].
+
+IP-adressa di er $3. Legg henne ved eventuelle førespurnader.',
+'whitelistedittitle'      => 'Du lyt logge inn for å gjera endringar',
+'whitelistedittext'       => 'Du lyt [[{{ns:-1}}:Userlogin|logge inn]] for å endre sider.',
+'whitelistreadtitle'      => 'Du lyt logge inn for å lesa',
+'whitelistreadtext'       => 'Du lyt [[{{ns:-1}}:Userlogin|logge inn]] for å lesa sider.',
+'whitelistacctitle'       => 'Du har ikkje løyve til å laga brukarkonto',
+'whitelistacctext'        => 'For å laga brukarkontoar på denne wikien lyt du [[{{ns:-1}}:Userlogin|logge inn]] og ha rett type tilgang',
+'loginreqtitle'                  => 'Innlogging trengst',
+'loginreqtext'           => 'Du lyt [[{{ns:-1}}:Userlogin|logge inn]] for å lesa andre sider.',
+'accmailtitle'            => 'Passord er sendt.',
+'accmailtext'             => 'Passordet for «$1» er vorte sendt til $2.',
+'newarticle'             => '(Ny)',
+'newarticletext'          => '\'\'\'{{SITENAME}} har ikkje noka side med namnet {{PAGENAME}} enno.\'\'\'
+* For å laga ei slik side kan du skrive i boksen under og klikke på «Lagre». Endringane vil vera synlege med det same.
+* Om du er ny her er det tilrådd å sjå på [[Project:Retningsliner|retningsliner]] og [[Help:Innhald|hjelp]] først.
+* Om du lagrar ei testside, vil du ikkje kunne slette ho sjølv. Ver difor venleg og bruk [[Project:Sandkasse|sandkassa]] til å eksperimentere.
+* Dersom du ikkje ønskjer å endre sida, kan du utan risiko klikke på \'\'\'attende\'\'\'-knappen i nettlesaren din.',
+'talkpagetext'            => '<!-- MediaWiki:talkpagetext -->',
+'anontalkpagetext'        => '---- \'\'Dette er ei diskusjonsside for ein anonym brukar som ikkje har logga inn på eigen brukarkonto. Vi er difor nøydde til å bruke den numeriske IP-adressa knytt til internettoppkoplinga åt brukaren. Same IP-adressa kan vera knytt til fleire brukarar. Om du er ein anonym brukar og meiner at du har fått irrelevante kommentarar på ei slik side, [[{{ns:-1}}:Userlogin|logg inn]] slik at vi unngår framtidige forvekslingar med andre anonyme brukarar.\'\'',
+'noarticletext'           => '\'\'\'Sida «{{PAGENAME}}» finst ikkje på {{SITENAME}} enno.\'\'\'
+* Klikk på \'\'\'[{{SERVER}}{{localurl:{{NAMESPACE}}:{{PAGENAME}}|action=edit}} endre]\'\'\' for å opprette sida.',
+'clearyourcache'          => '\'\'\'Merk:\'\'\' Etter lagring vil det kanskje vera naudsynt at nettlesaren omgår mellomlageret sitt for at endringane skal tre i kraft. \'\'\'Mozilla og Firefox:\'\'\' trykk \'\'Ctrl-Shift-R\'\', \'\'\'Internet Explorer:\'\'\' \'\'Ctrl-F5\'\', \'\'\'Safari:\'\'\' \'\'Cmd-Shift-R\'\', \'\'\'Konqueror:\'\'\' \'\'F5\'\'.',
+'usercssjsyoucanpreview'  => '<strong>Tip:</strong> Bruk «Førehandsvis»-knappen for å teste den nye CSS- eller JS-koden din føre du lagrar.',
+'usercsspreview'          => '\'\'\'Hugs at du berre testar ditt eige CSS, det har ikkje vorte lagra enno!\'\'\'',
+'userjspreview'           => '\'\'\'Hugs at du berre testar ditt eige JavaScript, det har ikkje vorte lagra enno!!\'\'\'',
+'updated'                => '(Oppdatert)',
+'note'                   => '<strong>Merk:</strong> ',
+'previewnote'            => 'Hugs at dette berre er ei førehandsvising og at teksten ikkje er lagra!',
+'previewconflict'         => 'Dette er ei førehandsvising av teksten i endringsboksen over, slik han vil sjå ut om du lagrar han',
+'editing'                => 'Endrar $1',
+'editingsection'          => 'Endrar $1 (bolk)',
+'editingcomment'          => 'Endrar $1 (kommentar)',
+'editconflict'           => 'Endringskonflikt: $1',
+'explainconflict'         => 'Nokon annan har endra teksten sidan du byrja å skrive. Den øvste boksen inneheld den noverande teksten. Skilnaden mellom den lagra versjonen og din endra versjon er viste under. Versjonen som du har endra er i den nedste boksen. Du lyt flette endringane dine saman med den noverande teksten. <strong>Berre</strong> teksten i den øvste tekstboksen vil bli lagra når du klikkar på «Lagre».<br />',
+'yourtext'               => 'Teksten din',
+'storedversion'           => 'Den lagra versjonen',
+'nonunicodebrowser'       => '<strong>ÅTVARING: Nettlesaren din støttar ikkje «Unicode». For å omgå problemet blir teikn utanfor ASCII-standarden viste som heksadesimale kodar. Det vil vera ein fordel om du byter nettlesar. Sjå [[hjelp:unicode]] for meir informasjon.</strong><br />',
+'editingold'             => '<strong>ÅTVARING: Du endrar ein gammal versjon av denne sida. Om du lagrar ho, vil alle endringar gjorde etter denne versjonen bli overskrivne.</strong> (Men dei kan hentast fram att frå historikken.)<br />',
+'yourdiff'               => 'Skilnad',
+'copyrightwarning'        => 'Merk deg at alle bidrag til {{SITENAME}} er å rekne som utgjevne under $2 (sjå $1 for detaljar). Om du ikkje vil ha teksten endra og kopiert under desse vilkåra, kan du ikkje leggje han her.<br />
+Teksten må du ha skrive sjølv, eller kopiert frå ein ressurs som er kompatibel med vilkåra eller ikkje verna av opphavsrett.
+
+<strong>LEGG ALDRI INN MATERIALE SOM ANDRE HAR OPPHAVSRETT TIL UTAN LØYVE FRÅ DEI!</strong>',
+'copyrightwarning2'       => 'Merk deg at alle bidrag til {{SITENAME}} kan bli endra, omskrive og fjerna av andre bidragsytarar. Om du ikkje vil ha teksten endra under desse vilkåra, kan du ikkje leggje han her.<br />
+Teksten må du ha skrive sjølv eller ha kopiert frå ein ressurs som er kompatibel med vilkåra eller ikkje verna av opphavsrett (sjå $1 for detaljar).
+
+<strong>LEGG ALDRI INN MATERIALE SOM ANDRE HAR OPPHAVSRETT TIL UTAN LØYVE FRÅ DEI!</strong>',
+'longpagewarning'         => '<strong>ÅTVARING: Denne sida er $1 KB lang; nokre nettlesarar kan ha problem med å handsama endringar av sider som nærmar seg eller er lengre enn 32 KB. Du bør vurdere å dele opp sida i mindre bolkar.</strong><br />',
+'readonlywarning'         => '<strong>ÅTVARING: Databasen er skriveverna på grunn av vedlikehald, difor kan du ikkje lagre endringane dine akkurat no. Det kan vera lurt å  kopiere teksten din åt ei tekstfil, så du kan lagre han her seinare.</strong><br />',
+'protectedpagewarning'    => '<strong>ÅTVARING: Denne sida er verna, slik at berre administratorar kan endre ho.</strong><br />',
+'templatesused'                  => 'Malar brukte på denne sida:',
+
+# History pages
+#
+'revhistory'             => 'Historikk',
+'nohistory'              => 'Det finst ikkje nokon historikk for denne sida.',
+'revnotfound'            => 'Fann ikkje versjonen',
+'revnotfoundtext'         => 'Den gamle versjonen av sida du spurde etter finst ikkje. Sjekk nettadressa du brukte for å komma deg åt denne sida.',
+'loadhist'               => 'Lastar historikk',
+'currentrev'             => 'Noverande versjon',
+'revisionasof'           => 'Versjonen frå $1',
+'revisionasofwithlink'    => 'Versjon frå $1; $2<br />$3 | $4',
+'previousrevision'        => '←Eldre versjon',
+'nextrevision'            => 'Nyare versjon→',
+'currentrevisionlink'     => 'Vis noverande versjon',
+'cur'                    => 'no',
+'next'                   => 'neste',
+'last'                   => 'førre',
+'orig'                   => 'orig',
+'histlegend'             => 'Merk av for dei versjonane du vil samanlikne og trykk [Enter] eller klikk på knappen nedst på sida.<br />Forklaring: (no) = skilnad frå den noverande versjonen, (førre) = skilnad frå den førre versjonen, <b>u</b> = uviktig endring',
+'history_copyright'       => '-',
+'deletedrev'              => '[sletta]',
+'histfirst'               => 'Første',
+'histlast'                => 'Siste',
+
+# Diffs
+#
+'difference'             => '(Skilnad mellom versjonar)',
+'loadingrev'             => 'lastar versjon for å sjå skilnad',
+'lineno'                 => 'Line $1:',
+'editcurrent'            => 'Endre den noverande versjonen av denne sida',
+'selectnewerversionfordiff' => 'Vel ein nyare versjon for samanlikning',
+'selectolderversionfordiff' => 'Vel ein eldre versjon for samanlikning',
+'compareselectedversions' => 'Samanlikn valde versjonar',
+
+# Search results
+#
+'searchresults'           => 'Søkjeresultat',
+'searchresulttext'        => 'For meir info om søkjefunksjonen i {{SITENAME}}, sjå [[Help:Søk|Hjelp]].',
+'searchquery'            => 'Du søkte etter «$1» <a href="/wiki/Spesial:Allpages/$1">[Indeks]</a>',
+'badquery'               => 'Feil utforma førespurnad',
+'badquerytext'           => 'Vi kunne ikkje svara på denne førespurnaden &mdash; Truleg fordi du prøvde å søkje etter eit ord med færre enn tre bokstavar, noko som ikkje er mogleg enno. Det kan òg vera du skreiv feil... Prøv om att.',
+'matchtotals'            => 'Førespurnaden «$1» gav treff på $2 sidetitlar og på teksten på $3 sider.',
+'nogomatch'               => '* \'\'\'{{SITENAME}} har ikkje noka side med [[$1|dette namnet]].\'\'\'
+* <big>\'\'\'Du kan [[$1|opprette ho no]]\'\'\'</big>.<br />
+(Men du bør søkje etter andre namnevariasjonar først, slik at du ikkje lagar ei side som allereie finst under eit anna namn!)',
+'titlematches'           => 'Sidetitlar med treff på førespurnaden',
+'notitlematches'          => 'Ingen sidetitlar hadde treff på førespurnaden',
+'textmatches'            => 'Sider med treff på førespurnaden',
+'notextmatches'                  => 'Ingen sider hadde treff på førespurnaden',
+'prevn'                          => 'førre $1',
+'nextn'                          => 'neste $1',
+'viewprevnext'           => 'Vis ($1) ($2) ($3).',
+'showingresults'          => 'Nedanfor er opp til <strong>$1</strong> resultat som byrjar med nummer <strong>$2</strong> viste.',
+'showingresultsnum'       => 'Nedanfor er <strong>$3</strong> resultat som byrjar med nummer <strong>$2</strong> viste.',
+'nonefound'               => '\'\'\'Merk\'\'\': søk utan resultat kan komma av at du leitar etter alminnelege engelske ord som ikkje blir indekserte, eller det kan komma av at du har gjeve meir enn eitt søkjeord (berre sider som inneheld alle søkjeorda vil bli funne).',
+'powersearch'             => 'Søk',
+'powersearchtext'         => 'Søk i namnerom:<br />$1<br />$2<br />List omdirigeringar &nbsp; Søk etter: $3 $9',
+'searchdisabled'          => 'Søkjefunksjonen på {{SITENAME}} er deaktivert på grunn av for stort press på tenarane akkurat no. I mellomtida kan du søkje gjennom Google eller Yahoo! Ver merksam på at registra deira kan vera utdaterte.',
+'blanknamespace'        => '(Hovud)',
+
+# Preferences page
+#
+'preferences'          => 'Innstillingar',
+'prefsnologin'          => 'Ikkje innlogga',
+'prefsnologintext'         => 'Du lyt vera [[Special:Userlogin|innlogga]] for å endre brukarinnstillingane dine.',
+'prefslogintext'        => 'Du er innlogga som «$1». Det interne ID-nummeret ditt er $2.
+
+Sjå [[Help:Brukarinnstillingar|Hjelp]] for ei forklaring på dei ulike innstillingane.',
+'prefsreset'           => 'Innstillingane er tilbakestilte til siste lagra versjon.',
+'qbsettings'           => 'Snøggmeny',
+'changepassword'        => 'Skift passord',
+'skin'                 => 'Drakt',
+'math'                 => 'Matematiske formlar',
+'dateformat'            => 'Datoformat',
+'math_failure'             => 'Klarte ikkje å tolke formelen',
+'math_unknown_error'   => 'ukjend feil',
+'math_unknown_function'        => 'ukjend funksjon ',
+'math_lexing_error'        => 'lexerfeil',
+'math_syntax_error'        => 'syntaksfeil',
+'math_image_error'         => 'PNG-konverteringa var mislukka; sjekk at latex, dvips, gs, og convert er rett installerte',
+'math_bad_tmpdir'          => 'Kan ikkje skrive til eller laga mellombels mattemappe',
+'math_bad_output'          => 'Kan ikkje skrive til eller laga mattemappe',
+'math_notexvc'         => 'Manglar texvc-program; sjå math/README for konfigurasjon.',
+'prefs-personal'        => 'Brukaropplysningar',
+'prefs-rc'              => 'Siste endringar og spirer',
+'prefs-misc'            => 'Andre',
+'saveprefs'                    => 'Lagre',
+'resetprefs'           => 'Rull attende',
+'oldpassword'          => 'Gammalt passord',
+'newpassword'          => 'Nytt passord',
+'retypenew'                    => 'Nytt passord om att',
+'textboxsize'          => 'Endring',
+'rows'                         => 'Rekkjer',
+'columns'                      => 'Kolonnar',
+'searchresultshead'     => 'Søk',
+'resultsperpage'        => 'Resultat per side',
+'contextlines'         => 'Liner per resultat',
+'contextchars'         => 'Teikn per line i resultatet',
+'stubthreshold'         => 'Grense (byte) for vising av spirer',
+'recentchangescount'    => 'Tal titlar på «siste endringar»',
+'savedprefs'           => 'Brukarinnstillingane er lagra.',
+'timezonelegend'        => 'Tidssone',
+'timezonetext'         => 'Tal timar lokal tid skil seg frå tenaren si tid.',
+'localtime'                => 'Lokaltid',
+'timezoneoffset'        => 'Skilnad',
+'servertime'           => 'Tenartid',
+'guesstimezone'         => 'Hent tidssone frå nettlesaren',
+'emailflag'            => 'Ikkje godtak e-post frå andre brukarar',
+'defaultns'            => 'Søk som standard i desse namneromma:',
+'default'              => 'standard',
+'files'                 => 'Filer',
+
+# User levels special page
+#
+
+# switching pan
+'groups-lookup-group'   => 'Administrer gruppetilgang',
+'groups-group-edit'     => 'Eksisterande grupper: ',
+'editgroup'             => 'Endre gruppe',
+'addgroup'              => 'Legg til gruppe',
+
+'userrights-lookup-user' => 'Administrer brukargrupper',
+'userrights-user-editname' => 'Skriv inn brukarnamn: ',
+'editusergroup'         => 'Endre brukargrupper',
+
+# group editing
+'groups-editgroup'      => 'Endre gruppe',
+'groups-addgroup'       => 'Legg til gruppe',
+'groups-editgroup-preamble' => 'Dersom namnet eller skildringa byrjar med ein kolon så vil resten bli tolka som eit systemmeldingsnamn og dermed bli omsett gjennom MediaWiki-namnerommet.',
+'groups-editgroup-name' => 'Gruppenamn: ',
+'groups-editgroup-description' => 'Gruppeskildring (maks 255 teikn):<br />',
+'savegroup'             => 'Lagre gruppe',
+'groups-tableheader'        => 'ID || Namn || Skildring || Tilgang',
+'groups-existing'           => 'Grupper',
+'groups-noname'             => 'Gje eit gyldig gruppenamn',
+'groups-already-exists'     => 'Det er allereie ei gruppe med det namnet',
+'addgrouplogentry'          => 'La til gruppe $2',
+'changegrouplogentry'       => 'Endra gruppe $2',
+'renamegrouplogentry'       => 'Endra namnet på $2 til $3',
+
+# user groups editing
+#
+'userrights-editusergroup' => 'Endre brukargrupper',
+'saveusergroups'        => 'Lagre brukargrupper',
+'userrights-groupsmember' => 'Medlem av:',
+'userrights-groupsavailable' => 'Tilgjengelege grupper:',
+'userrights-groupshelp' => 'Vel grupper du vil at brukaren skal fjernast frå eller leggjast til. Grupper som ikkje er valde vil ikkje bli endra. Du kan velja vekk ei gruppe med [CTRL + venstreklikk]',
+'userrights-logcomment' => 'Endra gruppemedlemskap frå $1 til $2',
+
+# Default group names and descriptions
+#
+'group-anon-name'       => 'Anonym',
+'group-anon-desc'       => 'Anonyme brukarar',
+'group-loggedin-name'   => 'Brukar',
+'group-loggedin-desc'   => 'Standard innlogga brukarar',
+'group-admin-name'      => 'Administrator',
+'group-admin-desc'      => 'Truverdige brukarar som kan blokkera brukartilgang og sletta sider',
+'group-bureaucrat-name' => 'Byråkrat',
+'group-bureaucrat-desc' => 'Administratorar som kan gje andre brukarar administratortilgang',
+'group-steward-name'    => 'Stuert',
+'group-steward-desc'    => 'Full tilgang',
+
+# Recent changes
+#
+'changes'               => 'endringar',
+'recentchanges'         => 'Siste endringar',
+'recentchanges-url'     => 'Special:Recentchanges',
+'recentchangestext'     => 'På denne sida ser du dei sist endra sidene i {{SITENAME}}.',
+'rcloaderr'            => 'Lastar sist endra sider',
+'rcnote'               => 'Nedanfor er dei siste <strong>$1</strong> endringane gjort dei siste <strong>$2</strong> dagane.',
+'rcnotefrom'           => 'Nedanfor er endringane frå <b>$2</b> inntil <b>$1</b> viste.',
+'rclistfrom'           => 'Vis nye endringar frå $1',
+'showhideminor'         => '$1 uviktige endringar | $2 bottar | $3 innlogga brukarar | $4 patruljerte endringar',
+'rclinks'              => 'Vis siste $1 endringar dei siste $2 dagane<br />$3',
+'rchide'               => 'i $4 form; $1 uviktige endringar; $2 andre namnerom; $3 meir enn éi endring.',
+'rcliu'                        => '; $1 endringar av innlogga brukarar',
+'diff'                 => 'skil',
+'hist'                 => 'hist',
+'hide'                 => 'gøym',
+'show'                 => 'vis',
+'tableform'            => 'tabell',
+'listform'             => 'liste',
+'nchanges'             => '$1 endringar',
+'minoreditletter'       => 'u',
+'newpageletter'         => 'n',
+'sectionlink'           => '→',
+'number_of_watching_users_RCview'     => '[$1]',
+'number_of_watching_users_pageview'     => '[$1 brukar(ar) overvakar]',
+
+# Upload
+#
+'upload'               => 'Last opp fil',
+'uploadbtn'            => 'Last opp fil',
+'uploadlink'           => 'Last opp fil',
+'reupload'             => 'Nytt forsøk',
+'reuploaddesc'         => 'Attende til opplastingsskjemaet.',
+'uploadnologin'         => 'Ikkje innlogga',
+'uploadnologintext'        => 'Du lyt vera [[Special:Userlogin|innlogga]] for å kunna laste opp filer.',
+'upload_directory_read_only' => 'Opplastingsmappa ($1) er skriveverna.',
+'uploaderror'          => 'Feil under opplasting av fil',
+'uploadtext'           => 'Dette er sida til å laste opp filer. Nyleg opplasta filer finn du på [[Special:Imagelist|filsida]]. Opplastingar og slettingar [[Special:Log|blir loggført]].
+
+* For å bruke eit bilete på ei side, skriv inn ei lenkje av dette slaget: <tt><nowiki>[[{{ns:6}}:Eksempelbilete.jpg]]</nowiki></tt> eller <tt><nowiki>[[{{ns:6}}:Eksempelbilete.png|bilettekst]]</nowiki></tt>, eller <tt><nowiki>[[{{ns:-2}}:Eksempelfil.ogg]]</nowiki></tt> for lydar og andre filer. For å leggje inn eit bilete som miniatyr, skriv <tt><nowiki>[[{{ns:6}}:Eksempelbilete.jpg|mini|Bilettekst]]</nowiki></tt>. Sjå [[Help:Biletsyntaks|biletesyntaks-hjelp]] for meir informasjon.
+* Om du lastar opp ei fil med same namn som ei eksisterande fil vil du bli beden om å stadfeste, og den eksisterande fila vil ikkje bli sletta.
+
+Sjå [[Help:Laste opp fil|hjelp for filopplasting]] for meir informasjon om korleis dette skjemaet verkar og korleis ein bruker filer på wikisider.
+
+For å laste opp ei fil bruker du «Bla gjennom...» eller «Browse...»-knappen som opnar ein standarddialog for val av fil. Når du vel ei fil, vil namnet på denne fila dukke opp i tekstfeltet ved sida av knappen. Skriv inn \'\'\'all\'\'\' nødvendig informasjon i \'\'Samandrag\'\'-feltet, kryss av at du ikkje bryt nokon sin opphavsrett, og klikk til slutt på \'\'Last opp fil\'\'.',
+'uploadlog'             => 'opplastingslogg',
+'uploadlogpage'         => 'Opplastingslogg',
+'uploadlogpagetext'     => 'Dette er ei liste over filer som nyleg er lasta opp.',
+'filename'             => 'Filnamn',
+'filedesc'             => 'Samandrag',
+'filestatus'            => 'Opphavsrettsstatus',
+'filesource'            => 'Kjelde',
+'copyrightpage'         => '{{ns:4}}:Opphavsrett',
+'copyrightpagename'     => '{{SITENAME}} opphavsrett',
+'uploadedfiles'                => 'Filer som er opplasta',
+'ignorewarning'                => 'Sjå bort frå åtvaringa og lagre fila likevel.',
+'minlength'            => 'Namnet på fila må ha minst tre teikn.',
+'illegalfilename'      => 'Filnamnet «$1» inneheld teikn som ikkje er tillatne i sidetitlar. Skift namn på fila og prøv på nytt.',
+'badfilename'          => 'Namnet på fila har vorte endra til «$1».',
+'badfiletype'          => 'Filformatet «.$1» er ikkje tillete.',
+'largefile'                    => 'Det er frårådd å bruke filer som er større enn $1 byte, denne fila er $2 byte.',
+'emptyfile'            => 'Det ser ut til at fila du lasta opp er tom. Dette kan komma av ein skrivefeil i filnamnet. Sjekk og tenk etter om du verkeleg vil laste opp fila.',
+'fileexists'           => 'Ei fil med dette namnet finst allereie, sjekk $1 om du ikkje er sikker på om du vil endre namnet.',
+'successfulupload'      => 'Opplastinga er ferdig',
+'fileuploaded'         => 'Fila «$1» er opplasta. Følg lenkja «$2» åt sida med skildring og fyll ut informasjon om fila &mdash; slik som kvar ho kom frå, kva tid ho vart laga og av kven, og andre ting du veit om fila.',
+'uploadwarning'         => 'Opplastingsåtvaring',
+'savefile'                     => 'Lagre fil',
+'uploadedimage'         => 'Lasta opp «[[$1]]»',
+'uploaddisabled'        => 'Beklagar, funksjonen for opplasting er deaktivert på denne nettenaren.',
+'uploadscripted'        => 'Fila inneheld HTML- eller skriptkode som feilaktig kan bli tolka og køyrd av nettlesarar.',
+'uploadcorrupt'         => 'Fila er øydelagd eller har feil etternamn. Sjekk fila og prøv på nytt.',
+'uploadvirus'           => 'Fila innheld virus! Detaljar: $1',
+'sourcefilename'        => 'Filsti',
+'destfilename'          => 'Målfilnamn',
+
+# Image list
+#
+'imagelist'                    => 'Filliste',
+'imagelisttext'                => 'Her er ei liste med $1 filer sorterte $2.',
+'getimagelist'         => 'hentar filliste',
+'ilsubmit'             => 'Søk',
+'showlast'             => 'Vis dei siste $1 filene sorterte $2.',
+'byname'               => 'etter namn',
+'bydate'               => 'etter dato',
+'bysize'               => 'etter storleik',
+'imgdelete'            => 'slett',
+'imgdesc'              => 'skildring',
+'imglegend'            => 'Forklaring: (skildring) = vis/endre filskildring.',
+'imghistory'           => 'Filhistorikk',
+'revertimg'            => 'rulltb',
+'deleteimg'            => 'slett',
+'deleteimgcompletely'  => 'Slett alle versjonar av fila',
+'imghistlegend'         => 'Forklaring: (no) = dette er den noverande versjonen av fila, (slett) = slett denne versjonen, (rulltb) = tilbake til denne versjonen.<br /><i>Klikk på ein dato for å sjå fila som vart opplasta då</i>.',
+'imagelinks'           => 'Fillenkjer',
+'linkstoimage'         => 'Dei følgjande sidene har lenkjer til denne fila:',
+'nolinkstoimage'        => 'Det finst ikkje noka side med lenkje til denne fila.',
+'sharedupload'          => 'Denne fila er ei delt opplasting og kan brukast av andre prosjekt.',
+'shareduploadwiki'      => 'Sjå [$1 filskildringssida] for meir informasjon.',
+'noimage'               => 'Det finst ikkje noka fil med dette namnet, men du kan [$1 laste ho opp]',
+'uploadnewversion'      => '[$1 Last opp ny versjon av denne fila]',
+
+# Statistics
+#
+'statistics'           => 'Statistikk',
+'sitestats'            => '{{SITENAME}}-statistikk',
+'userstats'            => 'Brukarstatistikk',
+'sitestatstext'         => 'Det er i alt \'\'\'$1\'\'\' sider i databasen. Dette inkluderer diskusjonssider, sider om {{SITENAME}}, småsider,
+omdirigeringssider, og andre som truleg ikkje kan kallast innhaldssider. Om ein ser bort frå desse sidene, er det \'\'\'$2\'\'\' sider som truleg er innhaldssider.
+
+Alle sidene er vortne viste \'\'\'$3\'\'\' gonger og endra \'\'\'$4\'\'\' gonger sidan programvaren vart installert. Det vil seie at kvar side gjennomsnittleg har vorte endra \'\'\'$5\'\'\' gonger, og vist \'\'\'$6\'\'\' gonger per endring.',
+'userstatstext'         => '{{SITENAME}} har \'\'\'$1\'\'\' registrerte brukarar. \'\'\'$2\'\'\' (eller \'\'\'$4%\'\'\') av desse er administratorar (sjå $3).',
+
+# Maintenance Page
+#
+'maintenance'          => 'Vedlikehaldsside',
+'maintnancepagetext'   => 'På denne sida er det ulike verktøy for å halde {{SITENAME}} ved like. Nokre av desse funksjonane er harde for databasen (dei tar lang tid), så lat vera å oppdatere sida kvar gong du har retta ein enkelt ting',
+'maintenancebacklink'  => 'Attende til vedlikehaldssida',
+'disambiguations'      => 'Fleirtydingssider',
+'disambiguationspage'  => 'Template:Fleirtyding',
+'disambiguationstext'  => 'Dei følgjande artiklane har lenkjer til <i>artiklar med fleirtydige titlar</i>. Dei burde heller lenkje til ein ikkje-fleirtydig  tittel i staden.<br />Ein artikkeltittel blir handsama som fleirtydig om han har lenkjer frå $1.<br />Lenkjer frå andre namnerom er <i>ikkje</i> opprekna her.',
+'doubleredirects'      => 'Doble omdirigeringar',
+'doubleredirectstext'  => 'Kvar line inneheld lenkjer til den første og den andre omdirigeringa, og den første lina frå den andre omdirigeringsteksten. Det gjev som regel den «rette» målartikkelen, som den første omdirigeringa skulle ha peikt på.',
+'brokenredirects'          => 'Blindvegsomdirigeringar',
+'brokenredirectstext'  => 'Dei følgjande omdirigeringane viser til ei side som ikkje finst.',
+'selflinks'            => 'Sider som viser til seg sjølve',
+'selflinkstext'                => 'Dei følgjande sidene inneheld tilvisingar til seg sjølve, og det bør dei ikkje.',
+'mispeelings'           => 'Sider med stavefeil',
+'mispeelingstext'       => 'Dei følgjande sidene inneheld ein av dei vanlege stavefeila som er lista på $1. Den rette stavemåten kan bli attgjeven i parentes etter feilstavinga (slik).',
+'mispeelingspage'       => 'Liste over vanlege stavefeil',
+'missinglanguagelinks'  => 'Manglande språklenkjer',
+'missinglanguagelinksbutton' => 'Finn manglande språklenkjer for',
+'missinglanguagelinkstext' => 'Desse innhaldssidene har <i>ikkje</i> lenkjer til den same sida på $1. Omdirigeringar og undersider er <i>ikkje</i> viste.',
+
+# Miscellaneous special pages
+#
+'orphans'              => 'Foreldrelause sider',
+'geo'                  => 'GEO-koordinat',
+'validate'             => 'Vurdér side',
+'lonelypages'          => 'Foreldrelause sider',
+'uncategorizedpages'   => 'Ikkje kategoriserte sider',
+'uncategorizedcategories' => 'Ikkje kategoriserte kategoriar',
+'unusedcategories'      => 'Ubrukte kategoriar',
+'unusedimages'         => 'Ubrukte filer',
+'popularpages'         => 'Populære sider',
+'nviews'               => '$1 visingar',
+'wantedpages'          => 'Etterspurde sider',
+'mostlinked'            => 'Sider mest lenkja til',
+'nlinks'               => '$1 lenkjer',
+'allpages'             => 'Alle sider',
+'randompage'           => 'Tilfeldig side',
+'randompage-url'        => 'Special:Random',
+'shortpages'           => 'Korte sider',
+'longpages'            => 'Lange sider',
+'deadendpages'          => 'Blindvegsider',
+'listusers'            => 'Brukarliste',
+'specialpages'         => 'Spesialsider',
+'spheading'            => 'Spesialsider for alle brukarar',
+'restrictedpheading'    => 'Spesialsider med avgrensa tilgang',
+
+'protectpage'          => 'Vern side',
+'recentchangeslinked'   => 'Relaterte endringar',
+'rclsub'               => '(til sider med lenkje frå «$1»)',
+'debug'                        => 'Feilsøk',
+'newpages'             => 'Nye sider',
+'ancientpages'         => 'Eldste sider',
+'intl'                 => 'Språklenkjer',
+'move'                  => 'Flytt',
+'movethispage'         => 'Flytt side',
+'unusedimagestext'      => '<p>Merk deg at andre internettsider kan ha lenkjer til filer som er lista her. Dei kan difor vera i aktiv bruk.</p>',
+'unusedcategoriestext'  => 'Dei følgjande kategorisidene er oppretta, sjølv om ingen artikkel eller kategori brukar dei.',
+
+'booksources'          => 'Bokkjelder',
+'categoriespagetext'    => 'Wikien har følgjande kategoriar.',
+'data'                  => 'Data',
+'userrights'            => 'Administrering av brukartilgang',
+'groups'                => 'Brukargrupper',
+'booksourcetext'        => 'Her er ei liste over lenkjer til internettsider som låner ut og/eller sel nye og/eller brukte bøker, og som kanskje har meir informasjon om bøker du leitar etter. {{SITENAME}} er ikkje nødvendigvis assosiert med nokon av desse sidene, og lista er <b>ikkje</b> å rekne som ei spesifikk tilråding om å bruke dei.',
+'isbn'                 => 'ISBN',
+'rfcurl'                => 'http://www.ifi.uio.no/doc/rfc/rfc$1.txt',
+'pubmedurl'             => 'http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?cmd=Retrieve&db=pubmed&dopt=Abstract&otool=bibsys&list_uids=$1',
+'alphaindexline'        => '$1 til $2',
+'version'              => 'Versjon',
+'log'                   => 'Loggar',
+'alllogstext'          => 'Kombinert vising av opplastings-, slette-, verne-, blokkerings- og administrator-loggar. Du kan avgrense visinga ved å velja loggtype, brukarnamn, og/eller sidnamn.',
+
+# Special:Allpages
+'nextpage'              => 'Neste side ($1)',
+'allpagesfrom'          => 'Vis sider frå:',
+'allarticles'           => 'Alle innhaldssider',
+'allnonarticles'        => 'Alle sider som ikkje er innhaldssider',
+'allinnamespace'        => 'Alle sider ($1 namnerom)',
+'allnotinnamespace'     => 'Alle sider (ikkje i $1-namnerommet)',
+'allpagesprev'          => 'Førre',
+'allpagesnext'          => 'Neste',
+'allpagessubmit'        => 'Vis',
+
+# Email this user
+#
+'mailnologin'          => 'Inga avsendaradresse',
+'mailnologintext'       => 'Du lyt vera [[Special:Userlogin|innlogga]] og ha ei gyldig e-postadresse sett i [[Special:Preferences|brukarinnstillingane]] for å sende e-post åt andre brukarar.',
+'emailuser'            => 'Send e-post åt denne brukaren',
+'emailpage'            => 'Send e-post åt brukar',
+'emailpagetext'                => 'Om denne brukaren har gjeve ei gyldig e-postadresse i brukarinnstillingane sine, vil dette skjemaet sende ei enkel melding. E-postadressa di frå brukarinnstillingane dine vil vera synleg i «Frå»-feltet i denne e-posten, slik at mottakaren kan svara deg.',
+'usermailererror'       => 'E-post systemet gav feilmelding: ',
+'defemailsubject'       => '{{SITENAME}} e-post',
+'noemailtitle'         => 'Inga e-postadresse',
+'noemailtext'          => 'Denne brukaren har ikkje oppgjeve ei gyldig e-postadresse, eller har valt å ikkje opne for e-post frå andre brukarar.',
+'emailfrom'            => 'Frå',
+'emailto'              => 'Åt',
+'emailsubject'         => 'Emne',
+'emailmessage'         => 'Melding',
+'emailsend'            => 'Send',
+'emailsent'            => 'E-posten er sendt',
+'emailsenttext'         => 'E-posten er sendt.',
+
+# Watchlist
+#
+'watchlist'            => 'Overvakingsliste',
+'watchlistsub'         => '(for brukar «$1»)',
+'nowatchlist'          => 'Du har ikkje noko i overvakingslista di.',
+'watchnologin'         => 'Ikkje innlogga',
+'watchnologintext'         => 'Du lyt vera [[Special:Userlogin|innlogga]] for å kunna endre overvakingslista.',
+'addedwatch'           => 'Lagt til overvakingslista',
+'addedwatchtext'        => 'Sida «$1» er lagt til [[Special:Watchlist|overvakingslista]] di. Framtidige endringar av denne sida og den tilhøyrande diskusjonssida vil bli oppførde her, og sida vil vera \'\'\'utheva\'\'\' på «[[Special:Recentchanges|siste endringar]]» for å gjera deg merksam på henne.
+
+Om du seinere vil fjerne sida frå overvakingslista, klikk på «Fjern overvaking» på den aktuelle sida.',
+'removedwatch'         => 'Fjerna frå overvakingslista',
+'removedwatchtext'      => 'Sida «$1» er fjerna frå overvakingslista.',
+'watch'                 => 'Overvak',
+'watchthispage'                => 'Overvak denne sida',
+'unwatch'               => 'Fjern overvaking',
+'unwatchthispage'       => 'Fjern overvaking',
+'notanarticle'         => 'Ikkje innhaldsside',
+'watchnochange'         => 'Ingen av sidene i overvakingslista er endra i den valde perioden.',
+'watchdetails'          => 'Du har $1 sider i overvakingslista di (diskusjonssider ikkje medrekna); du kan [[Special:Watchlist/edit|vise og endre den fullstendige lista]].',
+'wlheader-enotif'       => '* Funksjonen for endringsmeldingar per e-post er på.',
+'wlheader-showupdated'  => '* Sider som har vorte endra sidan du sist såg på dei er \'\'\'utheva\'\'\'',
+'watchmethod-recent'    => 'sjekkar siste endringar for dei overvaka sidene',
+'watchmethod-list'      => 'sjekkar om dei overvaka sidene er vortne endra i det siste',
+'removechecked'         => 'Fjern dei valde sidene frå overvakingslista',
+'watchlistcontains'     => 'Overvakingslista inneheld $1 sider.',
+'watcheditlist'         => 'Dette er ei alfabetisk liste over sider du overvakar. For å fjerne sider frå lista må du velja dei sidene du vil fjerne og klikke på «Fjern overvaking»-knappen nedst på sida.',
+'removingchecked'       => 'Fjernar dei valde sidene frå overvakingslista ...',
+'couldntremove'         => 'Kunne ikkje fjerne «$1»...',
+'iteminvalidname'       => 'Problem med «$1», ugyldig namn...',
+'wlnote'                => 'Nedanfor er dei siste $1 endringane dei siste <b>$2</b> timane.',
+'wlshowlast'               => 'Vis siste $1 timar $2 dagar $3',
+'wlsaved'                      => 'Dette er ein mellomlagra versjon av overvakingslista di.',
+'wlhideshowown'         => '$1 eigne endringar.',
+'wlshow'                => 'Vis',
+'wlhide'                => 'Gøym',
+
+'enotif_mailer'         => '{{SITENAME}}-endringsmeldingssendar',
+'enotif_reset'          => 'Merk alle sider som vitja',
+'enotif_newpagetext'    => 'Dette er ei ny side.',
+'changed'               => 'endra',
+'created'               => 'oppretta',
+'enotif_subject'        => '{{SITENAME}}-sida $PAGETITLE har vorte $CHANGEDORCREATED av $PAGEEDITOR',
+'enotif_lastvisited'    => 'Sjå $1 for alle endringane sidan siste vitjing.',
+'enotif_body'           => 'Hei $WATCHINGUSERNAME,
+
+{{SITENAME}}-sida $PAGETITLE har vorte $CHANGEDORCREATED $PAGEEDITDATE av $PAGEEDITOR, sjå $PAGETITLE_URL for den gjeldande versjonen.
+
+$NEWPAGE
+
+Bidragytaren sitt endringssamandrag: $PAGESUMMARY $PAGEMINOREDIT
+
+Du kan kontakte bidragsytaren gjennom:
+e-post: $PAGEEDITOR_EMAIL , eller
+wiki: $PAGEEDITOR_WIKI
+
+Du får ikkje fleire endringsmeldingar om denne sida før du har vitja henne på nytt. Du kan også tilbakestille endringsmeldingsstatus for alle sidene på overvakingslista di.
+
+             Helsing din overvakande {{SITENAME}}-endringsmeldingssystemven
+
+--
+For å endre innstillingane for overvakingslista di, gå til
+{{SERVER}}{{localurl:Special:Watchlist/edit}}
+
+For hjelp og meir informasjon:
+{{SERVER}}{{localurl:Hjelp:Overvaking}}',
+
+# Delete/protect/revert
+#
+'deletepage'           => 'Slett side',
+'confirm'              => 'Stadfest',
+'excontent'             => 'innhaldet var: «$1»',
+'excontentauthor'       => 'innhaldet var: «$1» (og den einaste bidragsytaren var «[[{{ns:2}}:$2|$2]]»)',
+'exbeforeblank'         => 'innhaldet før sida vart tømd var: «$1»',
+'exblank'               => 'sida var tom',
+'confirmdelete'         => 'Stadfest sletting',
+'deletesub'            => '(Slettar «$1»)',
+'historywarning'        => 'Åtvaring: Sida du held på å slette har ein historikk: ',
+'confirmdeletetext'     => 'Du held på å varig slette ei side eller eit bilete saman med heile den tilhøyrande historikken frå databasen. Stadfest at du verkeleg vil gjera dette, at du skjønner konsekvensane, og at du gjer dette i tråd med [[Project:Retningsliner|retningslinene]].',
+'actioncomplete'        => 'Ferdig',
+'deletedtext'          => '«$1» er sletta. Sjå $2 for eit oversyn over dei siste slettingane.',
+'deletedarticle'        => 'sletta «[[$1]]»',
+'dellogpage'           => 'Slettelogg',
+'dellogpagetext'        => 'Her er ei liste over dei siste slettingane.',
+'deletionlog'          => 'slettelogg',
+'reverted'             => 'Attenderulla til ein tidlegare versjon',
+'deletecomment'                => 'Grunn for sletting',
+'imagereverted'         => 'Attenderulling av tidlegare versjon ferdig.',
+'rollback'             => 'Rull attende endringar',
+'rollback_short'        => 'Rull attende',
+'rollbacklink'         => 'rull attende',
+'rollbackfailed'        => 'Kunne ikkje rulle attende',
+'cantrollback'         => 'Kan ikkje rulle attende fordi den siste brukaren er den einaste forfattaren.',
+'alreadyrolled'                => 'Kan ikkje rulle attende den siste endringa av [[$1]] gjort av [[{{ns:2}}:$2|$2]] ([[{{ns:3}}:$2|brukardiskusjon]]) fordi nokon andre allereie har endra sida att eller fjerna endringa.
+
+Den siste endringa vart gjort av [[{{ns:2}}:$3|$3]] ([[{{ns:3}}:$3|brukardiskusjon]]).',
+# only shown if there is an edit comment
+'editcomment'           => 'Samandraget for endringa var: "<i>$1</i>".',
+'revertpage'           => 'Attenderulla endring gjort av [[{{ns:2}}:$2|$2]] til tidlegare versjon endra av [[{{ns:2}}:$1|$1]]',
+'sessionfailure'        => 'Det ser ut til å vera eit problem med innloggingsøkta di. Handlinga er vorten avbroten for å vera føre var mot kidnapping av økta. Bruk attendeknappen i nettlesaren din og prøv om att.',
+'protectlogpage'        => 'Vernelogg',
+'protectlogtext'        => 'Dette er ei liste over sider som er vortne verna eller har fått fjerna vern. Sjå [[{{ns:4}}:Verna side]] for meir info.',
+'protectedarticle'      => 'verna «[[$1]]»',
+'unprotectedarticle'    => 'fjerna vern av «[[$1]]»',
+'protectsub'            => '(Vernar «$1»)',
+'confirmprotecttext'    => 'Er du sikker på at du vil verne denne sida?',
+'confirmprotect'        => 'Stadfest vern',
+'protectmoveonly'       => 'Berre vern mot flytting',
+'protectcomment'        => 'Grunn til verning',
+'unprotectsub'          => '(Fjernar vern av «$1»)',
+'confirmunprotecttext'  => 'Er du sikker på at du vil fjerne vernet av denne sida?',
+'confirmunprotect'      => 'Stadfest fjerning av vern',
+'unprotectcomment'      => 'Grunn til fjerning av vern',
+
+# Undelete
+'undelete'              => 'Attopprett ei sletta side',
+'undeletepage'          => 'Sjå og attopprett sletta sider',
+'undeletepagetext'      => 'Dei følgjande sidene er sletta, men dei finst enno i arkivet og kan attopprettast. Arkivet blir periodevis sletta.',
+'undeletearticle'       => 'Attopprett sletta side',
+'undeleterevisions'     => '$1 versjonar arkiverte',
+'undeletehistory'       => 'Om du attopprettar sida, vil alle versjonane i historikken også bli attoppretta. Dersom ei ny side med same namnet er oppretta sidan den gamle sida vart sletta, vil dei attoppretta versjonane dukke opp i historikken, og den nyaste versjonen vil bli verande som han er.',
+'undeleterevision'      => 'Sletta versjon frå $1',
+'undeletebtn'           => 'Attopprett!',
+'undeletedarticle'      => 'attoppretta «[[$1]]»',
+'undeletedrevisions'    => '$1 versjonar attoppretta',
+'undeletedtext'         => 'Sida [[$1]] er attoppretta. Sjå [[Special:Log/delete]] for oversyn over nylege slettingar og attopprettingar.',
+
+ # Namespace form on various pages
+'namespace'             => 'Namnerom:',
+'invert'                => 'Vreng val',
+
+# Contributions
+#
+'contributions'                => 'Brukarbidrag',
+'mycontris'             => 'Eigne bidrag',
+'contribsub'           => 'For $1',
+'nocontribs'           => 'Det vart ikkje funne nokon endringar gjorde av denne brukaren.',
+'ucnote'               => 'Her er dei siste <b>$1</b> endringane frå denne brukaren dei siste <b>$2</b> dagane.',
+'uclinks'              => 'Vis dei siste $1 endringane; vis dei siste $2 dagane.',
+'uctop'                        => ' (øvst)' ,
+'newbies'               => 'ferskingar',
+'contribs-showhideminor' => '$1 uviktige endringar',
+
+# What links here
+#
+'whatlinkshere'                => 'Lenkjer hit',
+'notargettitle'         => 'Inkje mål',
+'notargettext'         => 'Du har ikkje spesifisert noka målside eller nokon brukar å bruke denne funksjonen på.',
+'linklistsub'          => '(Liste over lenkjer)',
+'linkshere'            => 'Desse sidene har lenkjer hit:',
+'nolinkshere'          => 'Inga side har lenkje hit.',
+'isredirect'           => 'omdirigeringsside',
+
+# Block/unblock IP
+#
+'blockip'              => 'Blokker brukar',
+'blockiptext'          => 'Bruk skjemaet nedanfor for å blokkere skrivetilgangen frå ei spesifikk IP-adresse eller brukarnamn. Dette bør berre gjerast for å hindre hærverk, og i samsvar med [[Project:Retningsliner|retningslinene]]. Skriv grunngjeving nedanfor (t.d. med sitat frå sider som er vortne utsette for hærverk). Opphørstid for blokkeringa skriv ein med GNU standardformat, som er skildra i [http://www.gnu.org/software/tar/manual/html_chapter/tar_7.html tar manualen] (engelsk), t.d. «1 hour», «2 days», «next Wednesday», «1 January 2017». Alternativt kan ei blokkering vera «indefinite» (ikkje fastsett) eller «infinite» (uendeleg).
+
+For informasjon om korleis ein kan blokkere seriar av IP-adresser, sjå [http://meta.wikimedia.org/wiki/Range_blocks] (engelsk). For å oppheve blokkering, sjå  [[Special:Ipblocklist|blokkeringslista]].',
+'ipaddress'                    => 'IP-adresse',
+'ipadressorusername'    => 'IP-adresse eller brukarnamn',
+'ipbreason'            => 'Grunngjeving',
+'ipbsubmit'            => 'Blokker denne brukaren',
+'ipbother'              => 'Anna tid',
+'ipboptions'            => '2 timar:2 hours,1 dag:1 day,3 dagar:3 days,1 veke:1 week,2 veker:2 weeks,1 månad:1 month,3 månader:3 months,6 månader:6 months,1 år:1 year,endelaus:infinite',
+'ipbotheroption'        => 'anna tid',
+'badipaddress'         => 'IP-adressa var ugyldig eller brukarblokkering er deaktivert på tenaren.',
+'blockipsuccesssub'     => 'Blokkering utført',
+'blockipsuccesstext'    => '«[[User:$1|$1]]» er blokkert.<br />Sjå [[Special:Ipblocklist|blokkeringslista]] for alle blokkeringar.',
+'unblockip'            => 'Opphev blokkering',
+'unblockiptext'                => 'Bruk skjemaet nedanfor for å oppheve blokkeringa av ein tidlegare blokkert brukar.',
+'ipusubmit'            => 'Opphev blokkering',
+'ipusuccess'           => '«[[$1]]» har fått oppheva blokkeringa',
+'ipblocklist'          => 'Blokkerte IP-adresser og brukarnamn',
+'blocklistline'                => '$1, $2 blokkerte $3 ($4)',
+'infiniteblock'         => 'uendeleg opphørstid',
+'expiringblock'         => '$1 opphørstid',
+'ipblocklistempty'      => 'Blokkeringslista er tom.',
+'blocklink'            => 'blokker',
+'unblocklink'          => 'opphev blokkering',
+'contribslink'         => 'bidrag',
+'autoblocker'          => 'Automatisk blokkert fordi du deler IP-adresse med [[{{ns:2}}:$1|$1]]. Grunngjeving gjeve for blokkeringa av $1 var: «$2».',
+'blocklogpage'         => 'Blokkeringslogg',
+'blocklogentry'                => 'Blokkerte «[[$1]]» med opphørstid $2',
+'blocklogtext'         => 'Dette er ein logg over blokkeringar og oppheving av blokkeringar gjorde av [[{{ns:4}}:Administratorar|administratorar]].
+IP-adresser som blir automatisk blokkerte er ikkje lista her. Sjå [[{{ns:-1}}:Ipblocklist|blokkeringslista]] for alle aktive blokkeringar.',
+'unblocklogentry'      => 'oppheva blokkering av «$1»',
+'range_block_disabled' => 'Funksjonen for blokkering av IP-adresse-seriar er deaktivert på tenaren.',
+'ipb_expiry_invalid'   => 'Ugyldig opphørstid.',
+'ip_range_invalid'     => 'Ugyldig IP-adresseserie.',
+'proxyblocker'         => 'Proxy-blokkerar',
+'proxyblockreason'     => 'Du er blokkert frå å endre fordi IP-adressa di tilhøyrer ein open mellomtenar (proxy). Du bør kontakte internettleverandøren din eller kundesørvis og gje dei beskjed, ettersom dette er eit alvorleg sikkerheitsproblem.',
+'proxyblocksuccess'    => 'Utført.',
+'sorbs'         => 'SORBS DNSBL',
+'sorbsreason'   => 'IP-adressa di er lista som ein open mellomtenar i [http://www.sorbs.net SORBS DNSBL].
+
+Dersom du er feilaktig blokkert kan http://www.sorbs.net/faq/retest.shtml vera til hjelp for å få IP-adressa di fjerna frå svartelista.',
+'sorbs_create_account_reason' => 'IP-adressa di er lista som ein open mellomtenar i [http://www.sorbs.net SORBS] DNSBL, og difor får du ikkje registrert deg.',
+
+# Developer tools
+#
+'lockdb'               => 'Skrivevern (lock) database',
+'unlockdb'             => 'Opphev skrivevern (unlock) av databasen',
+'lockdbtext'           => 'Å skriveverne databasen vil gjere det umogleg for alle brukarar å endre sider, brukarinnstillingar, overvakingslister og andre ting som krev endringar i databasen. Stadfest at du ønskjer å gjera dette, og at du vil låse opp databasen att når vedlikehaldet er ferdig.',
+'unlockdbtext'         => 'Å oppheva skrivevernet på databasen fører til at alle brukarar kan endre sider, brukarinnstillingar, overvakingslister og andre ting som krev endringar i databasen att. Stadfest at du ønskjer å gjera dette.',
+'lockconfirm'          => 'Ja, eg vil verkeleg skriveverne databasen.',
+'unlockconfirm'                => 'Ja, eg vil verkeleg oppheva skrivevernet på databasen.',
+'lockbtn'              => 'Skrivevern databasen',
+'unlockbtn'            => 'Opphev skrivevern på databasen',
+'locknoconfirm'         => 'Du har ikkje stadfest handlinga.',
+'lockdbsuccesssub'      => 'Databasen er no skriveverna',
+'unlockdbsuccesssub'    => 'Srivevernet på databasen er no oppheva',
+'lockdbsuccesstext'     => 'Databasen er no skriveverna. <br />Hugs å oppheve skrivevernet når du er ferdig med vedlikehaldet.',
+'unlockdbsuccesstext'   => 'Skrivevernet er oppheva.',
+
+# Make sysop
+'makesysoptitle'       => 'Gjer brukar om til administrator',
+'makesysoptext'                => 'Dette skjemaet kan brukast av byråkratar til å gjera vanlege brukarar om til administratorar. Skriv inn namnet på brukaren i tekstboksen og trykk på knappen for å gjere brukaren om til administrator',
+'makesysopname'                => 'Brukarnamn:',
+'makesysopsubmit'      => 'Gjer brukaren om til administrator',
+'makesysopok'          => '<b>Brukaren «$1» er no administrator</b>',
+'makesysopfail'                => '<b>Brukaren «$1» kunne ikkje gjerast om til administrator. (Skreiv du brukarnamnet rett?)</b>',
+'setbureaucratflag'     => 'Gje byråkrat-tilgang',
+'setstewardflag'        => 'Gje stuert-tilgang',
+'bureaucratlog'         => 'Tilgangslogg',
+'rightslogtext'         => 'Dette er ein logg over endringar av brukartilgang.',
+'bureaucratlogentry'   => 'Endra gruppemedlemskap for «[[$1]]» frå «$2» til «$3»',
+'rights'               => 'Tilgang:',
+'set_user_rights'      => 'Set brukartilgang',
+'user_rights_set'      => '<b>Brukartilgang for «$1» er oppdatert</b>',
+'set_rights_fail'      => '<b>Brukartilgang for «$1» kunne ikkje setjast. (Skreiv du brukarnamnet rett?)</b>',
+'makesysop'             => 'Gje brukar administratortilgang',
+'already_sysop'         => 'Denne brukaren har allereie administratortilgang',
+'already_bureaucrat'    => 'Denne brukaren har allereie byråkrat-tilgang',
+'already_steward'       => 'Denne brukaren har allereie stuert-tilgang',
+
+# Validation
+'val_yes'               => 'Ja',
+'val_no'                => 'Nei',
+'val_of'                => '$1 av $2',
+'val_revision'          => 'Versjon',
+'val_time'              => 'Tid',
+'val_user_stats_title'  => 'Vurderingsoversikt for brukar $1',
+'val_my_stats_title'    => 'Mi vurderingsoversikt',
+'val_list_header'       => '<th>nr.</th><th>Emne</th><th>Målestokk</th><th>Handling</th>',
+'val_add'               => 'Legg til',
+'val_del'               => 'Slett',
+'val_show_my_ratings'   => 'Vis vurderingane mine',
+'val_revision_number'   => 'Versjons-ID $1',
+'val_warning'           => 'Endringar må berre skje i samsvar med konsensus i brukarsamfunnet!',
+'val_rev_for'           => 'Versjonar for $1',
+'val_details_th_user'   => 'Brukar $1',
+'val_validation_of'     => 'Vurdering av «$1»',
+'val_revision_of'       => 'Versjon $1',
+'val_revision_changes_ok' => 'Dine vurderingar er lagra!',
+'val_revision_stats_link' => 'detaljar',
+'val_iamsure'           => 'Kryss av dersom du verkeleg meiner det (det er ingen veg attende)!',
+'val_details_th'        => '<sub>Brukar</sub> \\ <sup>Emne</sup>',
+'val_clear_old'         => 'Slett dei førre vurderingsdataa mine for denne sida',
+'val_merge_old'         => 'Bruk den tidlegare vurderinga mi der eg har vald «Inga meining»',
+'val_form_note'         => '\'\'\'Merk:\'\'\' Å slå saman val betyr at for alle val du ikkje har spesifisert \'\'Inga meining\'\' i den innhaldssideversjonen du held på med, så blir val og kommentarar henta inn frå siste versjonen der du har gjort noko val. Om du til dømes berre vil endre eitt val i ein nyare versjon men behalde resten slik det var tidlegare, så endrar du berre dette valet og samanslåinga vil fylle inn resten slik det var.',
+'val_noop'              => 'Inga meining',
+'val_topic_desc_page'   => 'Project:Vurderingsemne',
+'val_votepage_intro'    => 'Du kan <a href="{{SERVER}}{{localurl:MediaWiki:Val_votepage_intro}}">endra denne teksten</a>!',
+'val_percent'           => '<b>$1%</b><br />($2 av $3 poeng<br />av $4 brukarar)',
+'val_percent_single'    => '<b>$1%</b><br />($2 av $3 poeng<br />av ein brukar)',
+'val_total'             => 'Total',
+'val_version'           => 'Versjon',
+'val_tab'               => 'Vurder',
+'val_this_is_current_version' => 'dette er den siste versjonen',
+'val_version_of'        => 'Versjon frå $1' ,
+'val_table_header'      => '<tr><th>Type</th>$1<th colspan=4>Meining</th>$1<th>Kommentar</th></tr>',
+'val_stat_link_text'    => 'Vurderingsstatistikk for denne innhaldssida',
+'val_view_version'      => 'Vis denne versjonen',
+'val_validate_version'  => 'Vurder denne versjonen',
+'val_user_validations'  => 'Denne brukaren har vurdert $1 sider.',
+'val_no_anon_validation' => 'Du må vera innlogga for å vurdere innhaldssider.',
+'val_validate_article_namespace_only' => 'Berre innhaldssider kan vurderast. Denne sida er <i>ikkje</i> i namnerommet til innhaldssidene.',
+'val_validated'         => 'Vurderinga er ferdig.',
+'val_article_lists'     => 'Liste over vurderte innhaldssider',
+'val_page_validation_statistics' => 'Vurderingsstatistikk for $1',
+
+# Move page
+#
+'movepage'             => 'Flytt side',
+'movepagetext'         => 'Ved å bruke skjemaet nedanfor kan du få omdøypt ei side og flytt heile historikken til det nye namnet. Den gamle tittelen vil bli ei omdirigeringsside til den nye tittelen. Lenkjer til den gamle tittelen vil ikkje bli endra. Pass på å sjekke for doble eller dårlege omdirigeringar. Du er ansvarleg for at alle lenkjene stadig peiker dit det er meininga at dei skal peike.
+
+Merk at sida \'\'\'ikkje\'\'\' kan flyttast dersom det allereie finst ei side med den nye tittelen. Du kan likevel flytte ei side attende dit ho vart flytt frå dersom du gjer ein feil, så lenge den sida du flytter attende til ikkje er vorten endra sidan flyttinga.
+
+<b>ÅTVARING!</b> Dette kan vera ei drastisk og uventa endring for ei populær side; ver sikker på at du skjønner konsekvensane av dette før du fortset.',
+'movepagetalktext'      => 'Den tilhøyrande diskusjonssida, om ho finst, vil automatisk bli flytt med sida \'\'\'med mindre:\'\'\'
+*Du flytter sida til eit anna namnerom,
+*Ei diskusjonsside som ikkje er tom allereie finst under det nye namnet, eller
+*Du fjernar merkinga i boksen nedanfor.
+
+I desse falla lyt du flytte eller flette saman sida manuelt. Om det ikkje er mogleg for deg å gjera dette kan du kontakte ein [[{{ns:4}}:Administratorar|administrator]], men <b>ikkje</b> bruk klipp-og-lim metoden sidan dette ikkje tek vare på endringshistorikken.',
+'movearticle'          => 'Flytt side',
+'movenologin'          => 'Ikkje innlogga',
+'movenologintext'       => 'Du lyt vera registrert brukar og vera [[Special:Userlogin|innlogga]] for å flytte ei side.',
+'newtitle'             => 'Til ny tittel',
+'movepagebtn'          => 'Flytt side',
+'pagemovedsub'         => 'Flyttinga er gjennomført',
+'pagemovedtext'         => 'Sida «[[$1]]» er flytt til «[[$2]]».',
+'articleexists'         => 'Ei side med det namnet finst allereie, eller det namnet du har valt er ikkje gyldig. Vel eit anna namn.',
+'talkexists'           => '\'\'\'Innhaldssida vart flytt, men diskusjonssida som høyrer til kunne ikkje flyttast fordi det allereie finst ei side med den nye tittelen. Du lyt flette dei saman manuelt. Dersom det ikkje er mogleg for deg å gjera dette kan du kontakte ein <a href="{{localurl:Project:Administratorar}}">administrator</a> &#8212; men <b>ikkje</b> bruk klipp-og-lim metoden sidan dette ikkje tek vare på endringshistorikken.\'\'\'',
+'movedto'              => 'er flytt til',
+'movetalk'             => 'Flytt diskusjonssida òg om ho finst.',
+'talkpagemoved'         => 'Diskusjonssida som høyrer til vart òg flytt.',
+'talkpagenotmoved'      => 'Diskusjonssida som høyrer til vart <strong>ikkje</strong> flytt.',
+'1movedto2'                    => '«[[$1]]» flytt til «[[$2]]»',
+'1movedto2_redir'       => '«[[$1]]» flytt over omdirigering til «[[$2]]»',
+'movelogpage'           => 'Flyttelogg',
+'movelogpagetext'       => 'Under er ei liste over sider som er flytte.',
+'movereason'            => 'Grunngjeving',
+'revertmove'            => 'attende',
+'delete_and_move'       => 'Slett og flytt',
+'delete_and_move_text'  => '== Sletting påkrevd ==
+
+Målsida «[[$1]]» finst allereie. Vil du slette ho for å gje rom for flytting?',
+'delete_and_move_reason' => 'Sletta for å gje rom for flytting',
+'selfmove'              => 'Kjelde- og måltitlane er like; kan ikkje flytte sida over seg sjølv.',
+'immobile_namespace'    => 'Måltittelen høyrer til eit namnerom som gjer at sida ikkje kan flyttast dit.',
+
+# Export
+'export'               => 'Eksporter sider',
+'exporttext'           => 'Du kan eksportere teksten og endringshistorikken til ei side eller ein serie sider, pakka inn i litt XML. I framtida kan det hende at dette att kan bli importert til ei anna wiki som brukar MediaWiki-programvaren, men det er det ikkje støtte for dette i denne versjonen av MediaWiki.
+
+For å eksportere sider, skriv tittelen i tekstboksen nedanfor, ein tittel per line, og vel om du vil ha med alle versjonane eller berre siste versjon.
+
+Dersom du berre vil ha den siste versjonen kan du òg bruke ei lenkje, t.d. [[{{ns:Special}}:Export/MediaWiki]] for [[MediaWiki]] sida.',
+'exportcuronly'                => 'Berre eksporter siste versjonen, ikkje med heile historikken.',
+
+# Namespace 8 related
+'allmessages'          => 'Systemmeldingar',
+'allmessagesname' => 'Namn',
+'allmessagesdefault' => 'Standardtekst',
+'allmessagescurrent' => 'Noverande tekst',
+'allmessagestext'      => 'Dette er ei liste over systemmeldingar i MediaWiki-namnerommet.',
+'allmessagesnotsupportedUI' => 'Det gjeldande språket for grensesnittet <b>$1</b>, støttar ikkje {{ns:-1}}:Allmessages.',
+'allmessagesnotsupportedDB' => '{{ns:-1}}:Allmessages er ikkje støtta fordi "wgUseDatabaseMessages" ikkje er aktivert på tenaren.',
+
+# Thumbnails
+'thumbnail-more'       => 'Forstørr',
+'missingimage'         => '<b>Bilete manglar</b><br /><i>$1</i>',
+'filemissing'           => 'Fil manglar',
+
+# Special:Import
+'import'                   => 'Importer sider',
+'importinterwiki'       => 'Transwikiimport',
+'importtext'           => 'Du må først eksportere sida du vil importere til ei fil som du lagrar på maskina di, deretter kan du laste ho inn her.
+For å eksportere bruker du [[{{ns:-1}}:Export|eksportsida]] på kjeldewikien; hugs at kjelda òg må bruke MediaWiki-programvaren.',
+'importfailed'         => 'Importeringa var mislukka: $1',
+'importnotext'         => 'Tom eller ingen tekst',
+'importsuccess'                => 'Importeringa er ferdig!',
+'importhistoryconflict' => 'Det kan vera at det er konflikt i historikken (kanskje sida vart importert før)',
+'importnosources'       => 'Ingen kjelder for transwikiimport er oppgjevne og funksjonen for opplasting av historikk er deaktivert.',
+
+# Keyboard access keys for power users
+'accesskey-search'      => 'f',
+'accesskey-minoredit'   => 'i',
+'accesskey-save'        => 's',
+'accesskey-preview'     => 'p',
+'accesskey-diff'        => 'd',
+'accesskey-compareselectedversions' => 'v',
+
+# tooltip help for some actions, most are in Monobook.js
+'tooltip-search'        => 'Søk i {{SITENAME}} [alt-f]',
+'tooltip-minoredit'     => 'Merk dette som ei uviktig endring [alt-i]',
+'tooltip-save'          => 'Lagre endringane dine [alt-s]',
+'tooltip-preview'       => 'Førehandsvis endringane dine, bruk denne funksjonen før du lagrar! [alt-p]',
+'tooltip-diff'          => 'Vis skilnaden mellom din versjon og lagra versjon, utan å lagre. [alt-d]',
+'tooltip-compareselectedversions' => 'Sjå endringane mellom dei valde versjonane av denne sida. [alt-v]',
+'tooltip-watch'         => 'Legg denne sida til i overvakingslista di [alt-w]',
+
+# Metadata
+'nodublincore'          => 'Funksjonen for Dublin Core RDF metadata er deaktivert på denne tenaren.',
+'nocreativecommons'     => 'Funksjonen for Creative Commons RDF er deaktivert på denne tenaren.',
+'notacceptable'         => 'Wikitenaren kan ikkje gje data i noko format som programmet ditt kan lesa.',
+
+# Attribution
+'anonymous'             => 'Anonym(e) brukar(ar) av {{SITENAME}}',
+'siteuser'              => '{{SITENAME}} brukar $1',
+'lastmodifiedby'        => 'Denne sida vart sist endra $1 av $2.',
+'and'                   => 'og',
+'othercontribs'         => 'Basert på arbeid av $1.',
+'others'                => 'andre',
+'siteusers'             => '{{SITENAME}} brukar(ar) $1',
+'creditspage'           => 'Sidegodskriving',
+'nocredits'             => 'Det finst ikkje ikkje nokon godskrivingsinformasjon for denne sida.',
+
+# Spam protection
+'spamprotectiontitle'   => 'Filter for vern mot reklame',
+'spamprotectiontext'    => 'Sida du prøvde å lagre vart blokkert av filteret for vern mot reklame (spam). Dette skjedde truleg på grunn av ei ekstern lenkje.',
+'spamprotectionmatch'   => 'Den følgjande teksten utløyste reklamefilteret: $1',
+'subcategorycount'      => 'Det er $1 underkategoriar av denne kategorien.',
+'subcategorycount1'     => 'Det er $1 underkategori av denne kategorien.',
+'categoryarticlecount'  => 'Det er $1 innhaldssider i denne kategorien.',
+'categoryarticlecount1' => 'Det er $1 innhaldsside i denne kategorien.',
+'usenewcategorypage'    => '1
+
+Skriv "0" som første bokstav for å slå av den nye kategoriutsjånaden.',
+'listingcontinuesabbrev' => ' vidare',
+
+# Info page
+'infosubtitle'          => 'Informasjon om side',
+'numedits'              => 'Tal endringar (innhaldsside): $1',
+'numtalkedits'          => 'Tal endringar (diskusjonsside): $1',
+'numwatchers'           => 'Tal brukarar som overvakar: $1',
+'numauthors'            => 'Tal ulike bidragsytarar (innhaldsside): $1',
+'numtalkauthors'        => 'Tal ulike bidragsytarar (diskusjonsside): $1',
+
+# Math options
+'mw_math_png'           => 'Vis alltid som PNG',
+'mw_math_simple'        => 'HTML om svært enkel, elles PNG',
+'mw_math_html'          => 'HTML om mogleg, elles PNG',
+'mw_math_source'        => 'Behald som TeX (for tekst-nettlesarar)',
+'mw_math_modern'        => 'Tilrådd for moderne nettlesarar',
+'mw_math_mathml'        => 'MathML dersom mogleg (eksperimentell)',
+
+# Patrolling
+'markaspatrolleddiff'   => 'Merk som patruljert',
+'markaspatrolledlink'   => '[$1]',
+'markaspatrolledtext'   => 'Merk denne innhaldssida som patruljert',
+'markedaspatrolled'     => 'Merk som patruljert',
+'markedaspatrolledtext' => 'Den valde versjonen er vorten merkt som patruljert.',
+'rcpatroldisabled'      => 'Siste-endringar-patruljering er deaktivert',
+'rcpatroldisabledtext'  => 'Patruljeringsfunksjonen er deaktivert.',
+
+# stylesheets
+'Monobook.js'           => '/*
+<pre>
+*/
+/* verktøytips og snøggtastar */
+ta = new Object();
+ta[\'pt-userpage\']             = new Array(\'.\',\'Brukarsida mi\');
+ta[\'pt-anonuserpage\']         = new Array(\'.\',\'Brukarsida for ip-adressa du endrar under\');
+ta[\'pt-mytalk\']               = new Array(\'n\',\'Diskusjonssida mi\');
+ta[\'pt-anontalk\']             = new Array(\'n\',\'Diskusjon om endringar gjorde av denne ip-adressa\');
+ta[\'pt-preferences\']          = new Array(\'\',\'Innstillingane mine\');
+ta[\'pt-watchlist\']            = new Array(\'l\',\'Liste over sidene du overvakar.\');
+ta[\'pt-mycontris\']            = new Array(\'y\',\'Liste over bidraga mine\');
+ta[\'pt-login\']                = new Array(\'o\',\'Det er ikkje obligatorisk å logga inn, men medfører mange fordelar.\');
+ta[\'pt-anonlogin\']            = new Array(\'o\',\'Det er ikkje obligatorisk å logga inn, men medfører mange fordelar.\');
+ta[\'pt-logout\']               = new Array(\'o\',\'Logg ut\');
+ta[\'ca-talk\']                 = new Array(\'t\',\'Diskusjon om innhaldssida\');
+ta[\'ca-edit\']                 = new Array(\'e\',\'Du kan endre denne sida. Bruk førehandsvisings-knappen før du lagrar.\');
+ta[\'ca-addsection\']           = new Array(\'+\',\'Legg til ein bolk på denne diskusjonssida.\');
+ta[\'ca-viewsource\']           = new Array(\'e\',\'Denne sida er verna, men du kan sjå kjeldeteksten.\');
+ta[\'ca-history\']              = new Array(\'h\',\'Eldre versjonar av denne sida.\');
+ta[\'ca-protect\']              = new Array(\'=\',\'Vern denne sida\');
+ta[\'ca-delete\']               = new Array(\'d\',\'Slett denne sida\');
+ta[\'ca-undelete\']             = new Array(\'d\',\'Attopprett denne sida\');
+ta[\'ca-move\']                 = new Array(\'m\',\'Flytt denne sida\');
+ta[\'ca-watch\']                = new Array(\'w\',\'Legg denne sida til i overvakingslista di\');
+ta[\'ca-unwatch\']              = new Array(\'w\',\'Fjern denne sida frå overvakingslista di\');
+ta[\'search\']                  = new Array(\'f\',\'Søk gjennom denne wikien\');
+ta[\'p-logo\']                  = new Array(\'\',\'Hovudside\');
+ta[\'n-mainpage\']              = new Array(\'z\',\'Gå til hovudsida\');
+ta[\'n-portal\']                = new Array(\'\',\'Om prosjektet, kva du kan gjera, kvar du finn saker og ting\');
+ta[\'n-currentevents\']         = new Array(\'\',\'Aktuelt\');
+ta[\'n-recentchanges\']         = new Array(\'r\',\'Liste over dei siste endringane som er gjort på wikien.\');
+ta[\'n-randompage\']            = new Array(\'x\',\'Vis ei tilfeldig side\');
+ta[\'n-help\']                  = new Array(\'\',\'Hjelp til å bruke alle funksjonane.\');
+ta[\'n-sitesupport\']           = new Array(\'\',\'Støtt oss!\');
+ta[\'t-whatlinkshere\']         = new Array(\'j\',\'Liste over alle wikisidene som har lenkjer hit\');
+ta[\'t-recentchangeslinked\']   = new Array(\'k\',\'Siste endringar på sider denne sida lenkjer til\');
+ta[\'feed-rss\']                = new Array(\'\',\'RSS-mating for denne sida\');
+ta[\'feed-atom\']               = new Array(\'\',\'Atom-mating for denne sida\');
+ta[\'t-contributions\']         = new Array(\'\',\'Sjå liste over bidrag frå denne brukaren\');
+ta[\'t-emailuser\']             = new Array(\'\',\'Send ein e-post til denne brukaren\');
+ta[\'t-upload\']                = new Array(\'u\',\'Last opp filer\');
+ta[\'t-specialpages\']          = new Array(\'q\',\'Liste over spesialsider\');
+ta[\'ca-nstab-main\']           = new Array(\'c\',\'Vis innhaldssida\');
+ta[\'ca-nstab-user\']           = new Array(\'c\',\'Vis brukarsida\');
+ta[\'ca-nstab-media\']          = new Array(\'c\',\'Direktelenkje (filpeikar) til fil\');
+ta[\'ca-nstab-special\']        = new Array(\'\',\'Dette er ei spesialside, du kan ikkje endre ho.\');
+ta[\'ca-nstab-wp\']             = new Array(\'c\',\'Vis prosjektside\');
+ta[\'ca-nstab-image\']          = new Array(\'c\',\'Vis filside\');
+ta[\'ca-nstab-mediawiki\']      = new Array(\'c\',\'Vis systemmelding\');
+ta[\'ca-nstab-template\']       = new Array(\'c\',\'Vis mal\');
+ta[\'ca-nstab-help\']           = new Array(\'c\',\'Vis hjelpeside\');
+ta[\'ca-nstab-category\']       = new Array(\'c\',\'Vis kategoriside\');
+/*
+</pre>
+*/
+',
+
+# image deletion
+'deletedrevision'      => 'Slett gammal versjon $1.',
+
+# browsing diffs
+'previousdiff'         => '← Gå til førre skilnaden',
+'nextdiff'             => 'Gå til neste skilnaden →',
+'imagemaxsize'         => 'Avgrens bilete på filsider til (pikslar): ',
+'thumbsize'            => 'Miniatyrstørrelse: ',
+'showbigimage'         => 'Last ned høgoppløysingsversjon ($1x$2, $3 KB)',
+'newimages'            => 'Filgalleri',
+
+# labels for User: and Title: on Special:Log pages
+'specialloguserlabel'  => 'Brukar: ',
+'speciallogtitlelabel' => 'Tittel: ',
+
+'passwordtooshort'     => 'Passordet er for kort. Det må vera minst $1 teikn langt.',
+
+# Media Warning
+'mediawarning'         => '\'\'\'Åtvaring\'\'\': Denne fila kan innehalda skadelege program, ved å opna ho kan systemet ditt ta skade.
+<hr>',
+
+'fileinfo'             => '$1KB, MIME-type: <code>$2</code>',
+
+# Metadata
+'metadata'             => 'Metadata',
+
+# Exif tags
+'exif-imagewidth'      => 'Breidd',
+'exif-imagelength'     => 'Høgd',
+'exif-bitspersample'   => 'Bitar per komponent',
+'exif-compression'     => 'Komprimeringsteknikk',
+'exif-photometricinterpretation' => 'Pikselsamansetjing',
+'exif-orientation'     => 'Retning',
+'exif-samplesperpixel' => 'Tal komponentar',
+'exif-planarconfiguration' => 'Dataarrangement',
+'exif-ycbcrpositioning' => 'Y- og C-posisjon',
+'exif-xresolution'     => 'Oppløysing i breidda',
+'exif-yresolution'     => 'Oppløysing i høgda',
+'exif-resolutionunit'  => 'Eining for X- og Y-oppløysing',
+'exif-jpeginterchangeformatlength' => 'Byte JPEG-data',
+'exif-referenceblackwhite' => 'Svart og kvitt referanseverdipar',
+'exif-datetime'        => 'Dato og tid endra',
+'exif-imagedescription' => 'Tittel',
+'exif-make'            => 'Kameraprodusent',
+'exif-model'           => 'Kameramodell',
+'exif-software'        => 'Programvare brukt',
+'exif-artist'          => 'Skapar',
+'exif-copyright'       => 'Opphavsrettsleg eigar',
+'exif-exifversion'     => 'Exif-versjon',
+'exif-flashpixversion' => 'Støtta Flashpix versjon',
+'exif-colorspace'      => 'Fargerom',
+'exif-pixelydimension'  => 'Gyldig biletbreidd',
+'exif-pixelxdimension'  => 'Gyldig bilethøgd',
+'exif-makernote'        => 'Produsentnotat',
+'exif-usercomment'      => 'Brukarkommentarar',
+'exif-relatedsoundfile' => 'Tilknytt lydfil',
+'exif-datetimeoriginal' => 'Dato og tid laga',
+'exif-datetimedigitized' => 'Dato og tid digitalisert',
+'exif-subsectime'       => 'Dato og tid subsekund',
+'exif-subsectimeoriginal' => 'Dato og tid laga subsekund',
+'exif-subsectimedigitized' => 'Dato og tid digitalisert subsekund',
+'exif-exposuretime'     => 'Eksponeringstid',
+'exif-fnumber'          => 'F-nummer',
+'exif-exposureprogram'  => 'Eksponeringsprogram',
+'exif-isospeedratings'  => 'Lysfølsemd (ISO)',
+'exif-shutterspeedvalue' => 'Lukkarfart',
+'exif-aperturevalue'    => 'Blendartal',
+'exif-brightnessvalue'  => 'Lysstyrke',
+'exif-exposurebiasvalue' => 'Exposure bias',
+'exif-subjectdistance'  => 'Motivavstand',
+'exif-meteringmode'     => 'Lysmålarmodus',
+'exif-lightsource'      => 'Lyskjelde',
+'exif-flash'            => 'Blits',
+'exif-focallength'      => 'Linsefokallengd',
+'exif-subjectarea'      => 'Motivområde',
+'exif-flashenergy'      => 'Blitsstyrke',
+'exif-focalplaneresolutionunit' => 'Oppløysingseining for fokalplanet',
+'exif-subjectlocation'  => 'Motivplassering',
+'exif-exposureindex'    => 'Eksponeringsindeks',
+'exif-sensingmethod'    => 'Sensor',
+'exif-filesource'       => 'Filkjelde',
+'exif-scenetype'        => 'Scenetype',
+'exif-cfapattern'       => 'CFA-mønster',
+'exif-exposuremode'     => 'Eksponeringsmodus',
+'exif-whitebalance'     => 'Kvitbalanse',
+'exif-digitalzoomratio' => 'Digital zoom-rate',
+'exif-focallengthin35mmfilm' => '(Tilsvarande) brennvidd ved 35 mm film',
+'exif-scenecapturetype' => 'Motivtype',
+'exif-gaincontrol'      => 'Scene control',
+'exif-contrast'         => 'Kontrast',
+'exif-saturation'       => 'Metting',
+'exif-sharpness'        => 'Skarpleik',
+'exif-subjectdistancerange' => 'Motivavstandsområde',
+'exif-imageuniqueid'    => 'Unik bilete-ID',
+'exif-gpsversionid'     => 'GPS-merke-versjon',
+'exif-gpslatituderef'   => 'Nordleg eller sørleg breiddegrad',
+'exif-gpslatitude'      => 'Breiddegrad',
+'exif-gpslongituderef'  => 'Austleg eller vestleg lengdegrad',
+'exif-gpslongitude'     => 'Lengdegrad',
+'exif-gpsaltituderef'   => 'Høgdereferanse',
+'exif-gpsaltitude'      => 'Høgd over havet',
+'exif-gpstimestamp'     => 'GPS-tid (atomklokke)',
+'exif-gpssatellites'    => 'Satellittar brukt for å måle',
+'exif-gpsstatus'        => 'GPS-Mottakarstatus',
+'exif-gpsmeasuremode'   => 'Målemodus',
+'exif-gpsdop'           => 'Målepresisjon',
+'exif-gpsspeedref'      => 'Fartsmåleining',
+'exif-gpsspeed'         => 'Fart på GPS-mottakar',
+'exif-gpstrackref'      => 'Referanse for rørsleretning',
+'exif-gpstrack'         => 'Rørsleretning',
+'exif-gpsimgdirectionref' => 'Referanse for retning åt biletet',
+'exif-gpsimgdirection'  => 'Retninga åt biletet',
+'exif-gpsmapdatum'      => 'Geodetisk kartleggingsdata brukt',
+'exif-gpsdestlatituderef' => 'Referanse for målbreiddegrad',
+'exif-gpsdestlatitude'  => 'Målbreiddegrad',
+'exif-gpsdestlongituderef' => 'Referanse for mållengdegrad',
+'exif-gpsdestlongitude' => 'Mållengdegrad',
+'exif-gpsdestdistanceref' => 'Referanse for avstand til mål',
+'exif-gpsdestdistance'  => 'Avstand til mål',
+'exif-gpsprocessingmethod' => 'Namn på GPS-handsamingsmetode',
+'exif-gpsareainformation'  => 'Namn på GPS-område',
+'exif-gpsdatestamp'     => 'GPS-dato',
+'exif-gpsdifferential'  => 'GPS differential correction',
+
+# Exif attributes
+'exif-compression-1'    => 'Ukomprimert',
+
+'exif-orientation-1'    => 'Normal', // 0th row: top; 0th column: left
+'exif-orientation-2'    => 'Spegla vassrett', // 0th row: top; 0th column: right
+'exif-orientation-3'    => 'Rotert 180°', // 0th row: bottom; 0th column: right
+'exif-orientation-4'    => 'Spegla loddrett', // 0th row: bottom; 0th column: left
+'exif-orientation-5'    => 'Rotert 90° motsols og spegla vassrett', // 0th row: left; 0th column: top
+'exif-orientation-6'    => 'Rotert 90° medsols', // 0th row: right; 0th column: top
+'exif-orientation-7'    => 'Rotert 90° medsols og spegla loddrett', // 0th row: right; 0th column: bottom
+'exif-orientation-8'    => 'Rotert 90° motsols', // 0th row: left; 0th column: bottom
+
+'exif-componentsconfiguration-0' => 'finst ikkje',
+
+'exif-exposureprogram-0' => 'Ikkje bestemt',
+'exif-exposureprogram-1' => 'Manuelt',
+'exif-exposureprogram-2' => 'Normalt program',
+'exif-exposureprogram-3' => 'Blendarprioritet',
+'exif-exposureprogram-4' => 'Lukkarprioritet',
+'exif-exposureprogram-5' => 'Kreativt program (mest mogleg skarpt)',
+'exif-exposureprogram-6' => 'Handlingsprogram (med vekt på snøgg lukkar)',
+'exif-exposureprogram-7' => 'Portrettmodus (for nærbilete med uskarp bakgrunn)',
+'exif-exposureprogram-8' => 'Landskapsmodus (for landskapsbilete med skarp bakgrunn)',
+
+'exif-subjectdistance-value' => '$1 meter',
+
+'exif-meteringmode-0' => 'Ukjent',
+'exif-meteringmode-1' => 'Snittmåling',
+'exif-meteringmode-2' => 'Snittmåling med vekt på midten',
+'exif-meteringmode-3' => 'Punktmåling',
+'exif-meteringmode-4' => 'Fleirpunktsmåling',
+'exif-meteringmode-5' => 'Mønster',
+'exif-meteringmode-6' => 'Delvis',
+'exif-meteringmode-255' => 'Annan',
+
+'exif-lightsource-0' => 'Ukjent',
+'exif-lightsource-1' => 'Dagslys',
+'exif-lightsource-2' => 'Fluorescerande',
+'exif-lightsource-4' => 'Blits',
+'exif-lightsource-9' => 'Fint vêr',
+'exif-lightsource-10' => 'Overskya vêr',
+'exif-lightsource-11' => 'Skugge',
+'exif-lightsource-12' => 'Fluorescerande dagslys (D 5700 – 7100K)',
+'exif-lightsource-13' => 'Dag, kvitt, fluorescerande (N 4600 – 5400K)',
+'exif-lightsource-14' => 'Kjølig, kvitt, fluorescerande (W 3900 – 4500K)',
+'exif-lightsource-15' => 'Kvitt fluorescerande (WW 3200 – 3700K)',
+'exif-lightsource-17' => 'Standardlys A',
+'exif-lightsource-18' => 'Standardlys B',
+'exif-lightsource-19' => 'Standardlys C',
+'exif-lightsource-255' => 'Anna lyskjelde',
+
+'exif-focalplaneresolutionunit-2' => 'tommar',
+
+'exif-sensingmethod-1' => 'Ikkje bestemt',
+'exif-sensingmethod-2' => 'Einbrikka fargeområdesensor',
+'exif-sensingmethod-3' => 'Tobrikka fargeområdesensor',
+'exif-sensingmethod-4' => 'Trebrikka fargeområdesensor',
+'exif-sensingmethod-7' => 'Trilinær sensor',
+
+'exif-scenetype-1'     => 'Direkte fotografert bilete',
+
+'exif-customrendered-0' => 'Normal prosess',
+'exif-customrendered-1' => 'Tilpassa prosess',
+
+'exif-exposuremode-0'   => 'Autoeksponert',
+'exif-exposuremode-1'   => 'Manuelt eksponert',
+
+'exif-whitebalance-0'   => 'Automatisk kvitbalanse',
+'exif-whitebalance-1'   => 'Manuell kvitbalanse',
+
+'exif-scenecapturetype-0' => 'Standard',
+'exif-scenecapturetype-1' => 'Landskap',
+'exif-scenecapturetype-2' => 'Portrett',
+'exif-scenecapturetype-3' => 'Nattscene',
+
+'exif-gaincontrol-0'      => 'Ingen',
+
+'exif-contrast-0'         => 'Normal',
+'exif-contrast-1'         => 'Mjuk',
+'exif-contrast-2'         => 'Hard',
+
+'exif-saturation-0'       => 'Normal',
+'exif-saturation-1'       => 'Låg metting',
+'exif-saturation-2'       => 'Høg metting',
+
+'exif-sharpness-0'        => 'Normal',
+'exif-sharpness-1'        => 'Mjuk',
+'exif-sharpness-2'        => 'Hard',
+
+'exif-subjectdistancerange-0' => 'Ukjent',
+'exif-subjectdistancerange-1' => 'Makro',
+'exif-subjectdistancerange-2' => 'Nært',
+'exif-subjectdistancerange-3' => 'Fjernt',
+
+// Pseudotags used for GPSLatitudeRef and GPSDestLatitudeRef
+'exif-gpslatitude-n'      => 'Nordleg breiddegrad',
+'exif-gpslatitude-s'      => 'Sørleg breiddegrad',
+
+// Pseudotags used for GPSLongitudeRef and GPSDestLongitudeRef
+'exif-gpslongitude-e'     => 'Austleg lengdegrad',
+'exif-gpslongitude-w'     => 'Vestleg lengdegrad',
+
+'exif-gpsstatus-a'        => 'Måling pågår',
+
+'exif-gpsmeasuremode-2'   => 'todimensjonalt målt',
+'exif-gpsmeasuremode-3'   => 'tredimensjonalt målt',
+
+// Pseudotags used for GPSSpeedRef and GPSDestDistanceRef
+'exif-gpsspeed-k'         => 'Kilometer per time',
+'exif-gpsspeed-m'         => 'Engelsk mil per time',
+'exif-gpsspeed-n'         => 'Knop',
+
+// Pseudotags used for GPSTrackRef, GPSImgDirectionRef and GPSDestBearingRef
+'exif-gpsdirection-t'     => 'Verkeleg retning',
+'exif-gpsdirection-m'     => 'Magnetisk retning',
+
+# external editor support
+'edit-externally'         => 'Endre denne fila med eit eksternt program',
+'edit-externally-help'    => 'Sjå [[Help:Eksterne program|instruksjonane]] for meir informasjon.',
+
+# 'all' in various places, this might be different for inflicted languages
+'recentchangesall'        => 'alle',
+'imagelistall'            => 'alle',
+'watchlistall1'           => 'alle',
+'watchlistall2'           => 'alle',
+'namespacesall'           => 'alle',
+
+# E-mail address confirmation
+'confirmemail'            => 'Stadfest e-postadresse',
+'confirmemail_text'       => '{{SITENAME}} krev at du stadfester e-postadressa di
+før du får brukt funksjonar knytt til e-post. Klikk på knappen under for å sende ei stadfestingsmelding
+til adressa di. E-posten kjem med ei lenkje som har ein kode; opne
+lenkja i nettlesaren din for å stadfeste at e-postadressa di er gyldig.',
+'confirmemail_send'       => 'Send stadfestingsmelding',
+'confirmemail_sent'       => 'Stadfestingsmelding er sendt.',
+'confirmemail_sendfailed' => 'Kunne ikkje sende stadfestingsmelding. Sjå til at adressa ikkje har ugyldige bokstavar.',
+'confirmemail_invalid'    => 'Feil stadfestingskode. Koden er kanskje for forelda.',
+'confirmemail_success'    => 'E-postadressa di er stadfest. Du kan no logge inn og kose deg med {{SITENAME}}.',
+'confirmemail_loggedin'   => 'E-postadressa di er stadfest.',
+'confirmemail_error'      => 'Noko gjekk gale når stadfestinga di skulle lagrast.',
+
+'confirmemail_subject'    => 'Stadfesting av e-postadresse frå {{SITENAME}}',
+'confirmemail_body'       => 'Nokon, truleg du, frå IP-adressa $1, har registrert kontoen «$2» med di e-postadresse på {{SITENAME}}.
+
+For å stadfeste at denne kontoen faktisk høyrer til deg og for å slå på
+funksjonar tilknytt e-post på {{SITENAME}} må du opne denne lenkja i nettlesaren din:
+
+$3
+
+Dersom dette *ikkje* er deg, må du ikkje opne lenkja. Denne stadfestingskoden
+blir forelda $4.',
+
+# Inputbox extension, may be useful in other contexts as well
+'tryexact'               => 'Prøv nøyaktig treff',
+'searchfulltext'         => 'Søk i all tekst',
+'createarticle'          => 'Lag side',
+
+# Scary transclusion
+'scarytranscludedisabled' => '[Interwiki transcluding is disabled]',
+'scarytranscludefailed'   => '[Henting av mal for $1 gjekk ikkje, beklagar]',
+'scarytranscludetoolong'  => '[Nettadressa er for lang, beklagar]',
+
+# Trackbacks
+'trackbackbox'           => "<div id='mw_trackbacks'>
+Attendelenkjer for denne sida:<br />
+$1
+</div>
+",
+'trackback' => "; $4$5 : [$2 $1]\n",
+'trackbackexcerpt' => "; $4$5 : [$2 $1]: <nowiki>$3</nowiki>\n",
+'trackbackremove' => ' ([$1 Slett])',
+'trackbacklink' => 'Attendelenkje',
+'trackbackdeleteok' => 'Attendelenkja vart sletta.',
+
+'unit-pixel' => 'px',
+
+);
+
+class LanguageNn extends LanguageUtf8 {
+
+       function getNamespaces() {
+               global $wgNamespaceNamesNn;
+               return $wgNamespaceNamesNn;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsNn;
+               return $wgQuickbarSettingsNn;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesNn;
+               return $wgSkinNamesNn;
+       }
+
+       function getDateFormats() {
+               global $wgDateFormatsNn;
+               return $wgDateFormatsNn;
+       }
+
+       function getBookstoreList() {
+               global $wgBookstoreListNn ;
+               return $wgBookstoreListNn ;
+       }
+
+       function getMagicWords() {
+               global $wgMagicWordsNn;
+               return $wgMagicWordsNn;
+       }
+
+       function time($ts, $adj = false, $format = true) {
+               global $wgUser;
+               if ( $adj ) { $ts = $this->userAdjust( $ts ); } # Adjust based on the timezone setting.
+
+               $format = $this->dateFormat($format);
+
+               switch( $format ) {
+                       # 2001-01-15 16:12:34
+                       case 'ISO 8601': return substr( $ts, 8, 2 ) . ':' . substr( $ts, 10, 2 ) . ':' . substr( $ts, 12, 2 );
+                       default: return substr( $ts, 8, 2 ) . ':' . substr( $ts, 10, 2 );
+               }
+
+       }
+
+       function date( $ts, $adj = false, $format = true) {
+               global $wgUser;
+               if ( $adj ) { $ts = $this->userAdjust( $ts ); } # Adjust based on the timezone setting.
+               $format = $this->dateFormat($format);
+
+               switch( $format ) {
+                       # 15. jan. 2001 kl. 16:12 || 16:12, 15. jan. 2001
+                       case '2': case '4': return (0 + substr( $ts, 6, 2 )) . '. ' .
+                               $this->getMonthAbbreviation( substr( $ts, 4, 2 ) ) . '. ' .
+                               substr($ts, 0, 4);
+                       # 2001-01-15 16:12:34
+                       case 'ISO 8601': return substr($ts, 0, 4). '-' . substr($ts, 4, 2). '-' .substr($ts, 6, 2);
+
+                       # 15. januar 2001 kl. 16:12 || 16:12, 15. januar 2001
+                       default: return (0 + substr( $ts, 6, 2 )) . '. ' .
+                               $this->getMonthName( substr( $ts, 4, 2 ) ) . ' ' .
+                               substr($ts, 0, 4);
+               }
+
+       }
+
+       function timeanddate( $ts, $adj = false, $format = true) {
+               global $wgUser;
+
+               $format = $this->dateFormat($format);
+
+               switch ( $format ) {
+                       # 16:12, 15. januar 2001 || 16:12, 15. jan. 2001
+                       case '3': case '4': return $this->time( $ts, $adj, $format ) . ', ' . $this->date( $ts, $adj, $format );
+                       # 2001-01-15 16:12:34
+                       case 'ISO 8601': return $this->date( $ts, $adj, $format ) . ' ' . $this->time( $ts, $adj, $format );
+                       # 15. januar 2001 kl. 16:12 || 15. jan. 2001 kl. 16:12
+                       default: return $this->date( $ts, $adj, $format ) . ' kl. ' . $this->time( $ts, $adj, $format );
+               }
+
+       }
+
+       var $digitTransTable = array(
+               ',' => "\xc2\xa0",
+               '.' => ','
+       );
+
+       function formatNum( $number, $year = false ) {
+               return $year ? $number : strtr($this->commafy($number), $this->digitTransTable);
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesNn;
+               if( isset( $wgAllMessagesNn[$key] ) ) {
+                       return $wgAllMessagesNn[$key];
+               } else {
+                       return parent::getMessage( $key );
+               }
+       }
+
+}
+
+?>
diff --git a/languages/LanguageNo.php b/languages/LanguageNo.php
new file mode 100644 (file)
index 0000000..c93365e
--- /dev/null
@@ -0,0 +1,994 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+/* private */ $wgNamespaceNamesNo = array(
+       NS_MEDIA          => "Medium",
+       NS_SPECIAL        => "Spesial",
+       NS_MAIN           => "",
+       NS_TALK           => "Diskusjon",
+       NS_USER           => "Bruker",
+       NS_USER_TALK      => "Brukerdiskusjon",
+       NS_PROJECT        => "Wikipedia",
+       NS_PROJECT_TALK   => "Wikipedia-diskusjon",
+       NS_IMAGE          => "Bilde",
+       NS_IMAGE_TALK     => "Bildediskusjon",
+       NS_MEDIAWIKI      => "MediaWiki",
+       NS_MEDIAWIKI_TALK => "MediaWiki-diskusjon",
+       NS_TEMPLATE       => "Mal",
+       NS_TEMPLATE_TALK  => "Maldiskusjon",
+       NS_HELP           => "Hjelp",
+       NS_HELP_TALK      => "Hjelpdiskusjon",
+       NS_CATEGORY       => "Kategori",
+       NS_CATEGORY_TALK  => "Kategoridiskusjon",
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgQuickbarSettingsNo = array(
+       "Ingen", "Fast venstre", "Fast høyre", "Flytende venstre"
+);
+
+/* private */ $wgSkinNamesNo = array(
+       'standard' => "Standard",
+       'nostalgia' => "Nostalgi",
+       'cologneblue' => "Kölnerblå"
+) + $wgSkinNamesEn;
+
+
+/* private */ $wgBookstoreListNo = array(
+       "Antikvariat.net" => "http://www.antikvariat.net/",
+       "Bibsys" => "http://www.bibsys.no/",
+       "Bokkilden" => "http://www.bokkilden.no/",
+       "Haugenbok" => "http://www.haugenbok.no/",
+       "Mao.no" => "http://www.mao.no/"
+);
+
+/* private */ $wgAllMessagesNo = array(
+
+# User Toggles
+
+"tog-underline" => "Strek under lenker",
+"tog-highlightbroken" => "Røde lenker til tomme sider",
+"tog-justify"  => "Blokkjusterte avsnitt",
+"tog-hideminor" => "Skjul mindre redigeringer i siste endringer",
+"tog-usenewrc" => "Forbedret siste endringer (ikke for alle nettlesere)",
+"tog-numberheadings" => "Nummerer overskrifter",
+"tog-showtoolbar" => "Show edit toolbar",
+"tog-editondblclick" => "Rediger sider med dobbeltklikk (JavaScript)",
+"tog-editsection"=>"Rediger avsnitt ved hjelp av [rediger]-lenke",
+"tog-editsectiononrightclick"=>"Rediger avsnitt ved å høyreklikke<br /> på avsnittsoverskrift (JavaScript)",
+"tog-showtoc"=>"Vis innholdsfortegnelse<br />(for artikler med mer enn tre avsnitt)",
+"tog-rememberpassword" => "Husk passordet til neste gang",
+"tog-editwidth" => "Redigeringsboksen har full bredde",
+"tog-watchdefault" => "Overvåk nye og endrede artikler",
+"tog-minordefault" => "Marker i utgangspunktet alle redigeringer som mindre",
+"tog-previewontop" => "Vis forhåndsvisningen foran redigeringsboksen, og ikke etter den",
+"tog-nocache" => "Ikke husk sidene ved neste besøk",
+
+# Dates
+#
+
+'sunday' => 'søndag',
+'monday' => 'mandag',
+'tuesday' => 'tirsdag',
+'wednesday' => 'onsdag',
+'thursday' => 'torsdag',
+'friday' => 'fredag',
+'saturday' => 'lørdag',
+'january' => 'januar',
+'february' => 'februar',
+'march' => 'mars',
+'april' => 'april',
+'may_long' => 'mai',
+'june' => 'juni',
+'july' => 'juli',
+'august' => 'august',
+'september' => 'september',
+'october' => 'oktober',
+'november' => 'november',
+'december' => 'desember',
+'jan' => 'jan',
+'feb' => 'feb',
+'mar' => 'mar',
+'apr' => 'apr',
+'may' => 'mai',
+'jun' => 'jun',
+'jul' => 'jul',
+'aug' => 'aug',
+'sep' => 'sep',
+'oct' => 'okt',
+'nov' => 'nov',
+'dec' => 'des',
+
+# Bits of text used by many pages:
+#
+"categories" => "Sidekategorier",
+"category" => "kategori",
+"category_header" => "Artikler i kategorien \"$1\"",
+"subcategories" => "Underkategorier",
+
+"linktrail"            => "/^((?:[a-z]|æ|ø|å)+)(.*)\$/sD",
+"mainpage"             => "Hovedside",
+"mainpagetext" => "Wiki-programvare er nå installert.",
+"about"                        => "Om",
+"aboutsite"      => "Om Wikipedia",
+"aboutpage"            => "Wikipedia:Om",
+"help"                 => "Hjelp",
+"helppage"             => "Wikipedia:Hjelp",
+"bugreports"   => "Feilmeldinger",
+"bugreportspage" => "Wikipedia:Feilmeldinger",
+"sitesupport"   => "Donasjoner",
+"faq"                  => "OSS",
+"faqpage"              => "Wikipedia:OSS",
+"edithelp"             => "Hjelp til redigering",
+"edithelppage" => "Wikipedia:Hvordan_redigere",
+"cancel"               => "Avbryt",
+"qbfind"               => "Finn",
+"qbbrowse"             => "Søk",
+"qbedit"               => "Rediger",
+"qbpageoptions" => "Sideinnstillinger",
+"qbpageinfo"   => "Sideinformasjon",
+"qbmyoptions"  => "Egne innstillinger",
+"mypage"               => "Egen side",
+"mytalk"               => "Egen diskusjonsside",
+"currentevents" => "Aktuelt",
+"errorpagetitle" => "Feil",
+"returnto"             => "Tilbake til $1.",
+"tagline"              => "Fra Wikipedia, den frie encyklopedi.",
+"whatlinkshere"        => "Lenker hit",
+"help"                 => "Hjelp",
+"search"               => "Søk",
+"go"           => "Utfør",
+"history"              => "Historikk",
+"printableversion" => "Utskriftsversjon",
+"editthispage" => "Rediger side",
+"deletethispage" => "Slett side",
+"protectthispage" => "Beskytt",
+"unprotectthispage" => "Fjern beskyttelse",
+"newpage" => "Ny side",
+"talkpage"             => "Diskuter side",
+"postcomment"   => "Tilføy en kommentar",
+"articlepage"  => "Vis artikkel",
+"subjectpage"  => "Vis emne", # For compatibility
+"userpage" => "Brukerside",
+"wikipediapage" => "Metaside",
+"imagepage" =>         "Billedside",
+"viewtalkpage" => "Vis diskusjon",
+"otherlanguages" => "Andre språk",
+"redirectedfrom" => "(Omdirigert fra $1)",
+"lastmodified" => "Sist endret $1.",
+"viewcount"            => "Denne siden er vist $1 ganger.",
+"printsubtitle" => "(fra {{SERVER}})",
+"protectedpage" => "Beskyttet side",
+"administrators" => "Wikipedia:Administratorer",
+"sysoptitle"   => "Sysop-rettigheter kreves",
+"sysoptext"            => "Funksjonen kan kun utføres av brukere med \"sysop\"-status.
+Se $1.",
+"developertitle" => "Utviklerrettigheter kreves.",
+"developertext"        => "Funksjonen kan kun utføres av brukere med \"utvikler\"-status.
+Se $1.",
+"nbytes"               => "$1 bytes",
+"go"                   => "Utfør",
+"ok"                   => "OK",
+"sitetitle"            => "Wikipedia",
+"sitesubtitle" => "Den frie encyklopedi",
+"retrievedfrom" => "Hentet fra \"$1\"",
+"newmessages" => "Du har $1.",
+"newmessageslink" => "nye meldinger",
+"editsection"=>"rediger",
+"toc" => "Innholdsfortegnelse",
+"showtoc" => "vis",
+"hidetoc" => "skjul",
+"thisisdeleted" => "Se eller gjenopprett $1?",
+"restorelink" => "$1 slettede endringer",
+
+# Main script and global functions
+#
+"nosuchaction" => "Funksjonen finnes ikke",
+"nosuchactiontext" => " Wikipedia-programvaren klarer ikke å
+gjenkjenne funksjonen som er spesifisert i URL-en",
+"nosuchspecialpage" => "En slik spesialside finnes ikke",
+"nospecialpagetext" => "Du har bedt om en spesialside som Wikipedia-programvaren ikke
+klarer å gjenkjenne.",
+
+# General errors
+#
+"error"                        => "Feil",
+"databaseerror" => "Databasefeil",
+"dberrortext"  => "Det har skjedd en syntaksfeil i databasen.
+Den sist forsøkte forespørsel var:
+<blockquote><tt>$1</tt></blockquote>
+fra funksjonen \"<tt>$2</tt>\".
+MySQL returnerte feilen \"<tt>$3: $4</tt>\".",
+"dberrortextcl" => "Det har skjedd en syntaksfeil i databasen.
+Den sist forsøkte forespørselen var:
+\"$1\"
+fra funksjonen \"$2\".
+MySQL returnerte feilen \"$3: $4\".\n",
+"noconnect"            => "Kunne ikke koble til databasen på $1",
+"nodb"                 => "Kunne ikke velge databasen $1",
+"cachederror"  => "Det følgende er en lagret kopi av den ønskede siden, og er ikke nødvendigvis oppdatert.",
+"readonly"             => "Databasen er skrivebeskyttet",
+"enterlockreason" => "Skriv en begrunnelse for skrivebeskyttelsen, inkludert et estimat på når den vil bli opphevet",
+"readonlytext" => "Databasen er for øyeblikket skrivebeskyttet for nye sider og andre modifikasjoner, sannsynligvis for rutinemessig vedlikehold. Administratoren som stengte den har gitt denne forklaringen:
+<p>$1",
+"missingarticle" => "Databasen fant ikke teksten på en side den skulle ha funnet, med navnet \"$1\".
+Dette er ikke en databasefeil, men sannsynligvis en programfeil
+Send en rapport om dette til en administrator, oppgi adresse til siden.",
+"internalerror" => "Intern feil",
+"filecopyerror" => "Kunne ikke kopiere filen \"$1\" til \"$2\".",
+"filerenameerror" => "Kunne ikke omdøpe filen \"$1\" til \"$2\".",
+"filedeleteerror" => "Kunne ikke slette filen \"$1\".",
+"filenotfound" => "Kunne ikke finne filen \"$1\".",
+"unexpected"   => "Uventet verdi: \"$1\"=\"$2\".",
+"formerror"            => "Feil: Kunne ikke sende skjema",
+"badarticleerror" => "Handlingen kan ikke utføres på denne siden.",
+"cannotdelete" => "Kunne ikke slette filen. (den kan være slettet av noen andre.)",
+"badtitle"             => "Feil tittel",
+"badtitletext" => "Den ønskede tittel var ulovlig, tom eller er galt lenket fra en Wikipedia på et annet språk.",
+"perfdisabled" => "Beklager! Denne funksjon er midlertidig avbrutt av vedlikeholdsgrunner.",
+"perfdisabledsub" => "Her er en lagret kopi fra $1:",
+"viewsource" => "Vis kildekode",
+"protectedtext" => "Denne siden er sperret for å hindre redigering; det
+kan være flere grunner til dette, se
+[[Wikipedia:Beskyttet side]].
+
+Du kan se og kopiere kildekoden til denne siden:",
+
+# Login and logout pages
+#
+"logouttitle"  => "Logg ut",
+"logouttext"   => "Du er nå logget ut.
+Du kan fortsette å bruke Wikipedia anonymt, eller du kan logge inn
+igjen med samme konto eller med en annen en.\n",
+
+"welcomecreation" => "<h2>Hjertelig velkommen til Wikipedia, $1!</h2><p>Vi har opprettet din brukerkonto.
+Hvis du vil, kan du personliggjøre brukerinnstillingene.",
+
+"loginpagetitle" => "Logg inn",
+"yourname"             => "Brukernavn",
+"yourpassword" => "Passord",
+"yourpasswordagain" => "Gjenta passord",
+"newusersonly" => " (kun nye brukere)",
+"remembermypassword" => "Husk passordet til neste gang.",
+"loginproblem" => "<b>Du ble ikke logget inn.</b><br />Prøv igjen!",
+"alreadyloggedin" => "<strong>Bruker $1 er allerede logget inn!</strong><br />\n",
+
+
+"login"                        => "Logg inn",
+"userlogin"            => "Logg inn",
+"logout"               => "Logg ut",
+"userlogout"   => "Logg ut",
+"notloggedin"  => "Ikke innlogget",
+"createaccount"        => "Opprett ny konto",
+"badretype"            => "Passordene var ikke like.",
+"userexists"   => "Brukernavnet er allerede i bruk. Velg et nytt.",
+"youremail"            => "E-postadresse",
+"yournick"             => "Økenavn (for signaturer)",
+"emailforlost" => "Hvis du glemmer passordet, kan du få et nytt sendt til din e-postadresse.",
+"loginerror"   => "Innloggingsfeil",
+"noname"               => "Du har ikke oppgitt et gyldig brukernavn.",
+"loginsuccesstitle" => "Du er nå innlogget",
+"loginsuccess" => "Du er nå innlogget som \"$1\".",
+"nosuchuser"   => "Det eksisterer ingen bruker \"$1\".
+Sjekk stavemåten, eller opprett en ny konto.",
+"wrongpassword"        => "Du har oppgitt et ugyldig passord. Prøv igjen.",
+"mailmypassword" => "Send nytt passord.",
+"passwordremindertitle" => "Nytt passord til Wikipedia",
+"passwordremindertext" => "Noen (antagelig deg, fra IP-adressen $1)
+ba oss sende deg et nytt passord til Wikipedia..
+Passord for bruker \"$2\" er nå \"$3\".
+Du bør logge inn og endre passordet nå.",
+"noemail"              => "Det er ikke registrert noen e-postadresse på bruker \"$1\".",
+"passwordsent" => "Et nytt passord har blitt sendt til e-postadressen registrert på bruker \"$1\".
+Logg inn når du har mottatt det nye passordet.",
+
+# Edit pages
+#
+"summary"              => "Beskrivelse",
+"subject"              => "Overskrift",
+"minoredit"            => "Mindre endring",
+"watchthis"            => "Overvåk side",
+"savearticle"  => "Lagre siden",
+"preview"              => "Forhåndsvisning",
+"showpreview"  => "Forhåndsvisning",
+"blockedtitle" => "Brukeren er blokkert",
+"blockedtext"  => "Ditt brukernavn eller din IP-adresse er blokkert av $1.
+Følgende begrunnelse ble gitt:<br />''$2''<p>Du kan kontakte $1 eller en annen
+[[Wikipedia:Administratorer|administrator]] for å diskutere utestengelsen.",
+"newarticle"   => "(Ny)",
+"newarticletext" =>
+"Artikkelen inneholder ingen tekst.
+Du kan begynne på en artikkel ved å skrive i boksen under
+(se [[Wikipedia:Hjelp|hjelpsiden]] for mere informasjon).
+Hvis du ikke vil redigere siden, klikk på '''tilbake''' i nettleseren.",
+"anontalkpagetext" => "---- ''Dette er en diskusjonsside for en anonym bruker som ikke har opprettet en konto eller ikke bruker den. Vi er derfor nødt til å bruke den numeriske IP-adressen til å identifisere ham eller henne. En IP-adresse kan være delt mellom flere brukere. Hvis du er en anonym bruker og synes at du har fått irrelevante kommentarer på en slik side, [[Spesial:Innlogging|logg på]] så vi unngår fremtidige forvekslinger med andre anonyme brukere.'' ",
+"noarticletext" => "(Det er for øyeblikket ingen tekst på denne siden.)",
+"updated"              => "(Oppdatert)",
+"note"                 => "<strong>Note:</strong> ",
+"previewnote"  => "Husk at dette kun er en forhåndsvisning og at teksten ikke er lagret!",
+"previewconflict" => "Slik vil teksten i redigeringsvinduet se ut hvis du lagrer den",
+"editing"              => "Redigerer $1",
+"editingsection"       => "Redigerer $1 (seksjon)",
+"editingcomment"       => "Redigerer $1 (kommentar)",
+"editconflict" => "Redigeringskonflikt: $1",
+"explainconflict" => "Noen andre har endret teksten siden du begynte å redigere.
+Den øverste boksen inneholder den nåværende tekst.
+Dine endringer vises i den nederste boksen.
+Du er nødt til å flette dine endringer sammen med den nåværende teksten.
+<b>Kun</b> teksten i den øverste tekstboksen vil bli lagret når du
+trykker \"Lagre siden\".<br />",
+"yourtext"             => "Din tekst",
+"storedversion" => "Den lagrede versjonen",
+"editingold"   => "<strong>ADVARSEL: Du redigerer en gammel versjon
+av denne siden.
+Hvis du lagrer den, vil alle endringer foretatt siden denne revisjonen bli
+overskrevet.</strong>",
+"yourdiff"             => "Forskjeller",
+"copyrightwarning" => "Legg merke til at alle bidrag til Wikipedia er
+å betrakte som utgitt under GNU fri dokumentasjonslisens
+(se $1 for detaljer).
+Hvis du ikke vil ha teksten redigert uten nåde og kopiert etter
+forgodtbefinnende, kan du ikke legge den her.<br />
+Du lover oss også at du skrev teksten selv eller kopierte fra en
+ressurs som ikke er beskyttet av opphavsrett.
+
+<strong>LEGG ALDRI MATERIALE HER SOM ER BESKYTTET AV ANDRES OPPHAVSRETT UTEN
+DERES TILLATELSE!</strong>",
+"longpagewarning" => "<strong>ADVARSEL: Denne siden er $1 kilobyte lang; noen
+nettlesere kan ha problemer med å redigere sider som nærmer seg eller
+er lengre enn 32kb. Overvei om ikke siden kan deles opp i mindre deler.</strong>",
+"readonlywarning" => "<strong>ADVARSEL: Databasen er låst på grunn av vedlikehold,
+så du kan ikke lagre dine endringer akkurat nå. Det kan være en god idé å
+kopiere teksten din til en tekstfil, så du kan lagre den til senere.</strong>",
+"protectedpagewarning" => "<strong>ADVARSEL: Denne siden er låst, så kun administratorer
+kan redigere den. Sørg for at du følger
+[[Project:Retningslinjer_for_beskyttede_sider|retningslinjer for beskyttede sider]].</strong>",
+
+# History pages
+#
+"revhistory"   => "Historikk",
+"nohistory"            => "Det er ingen historikk for denne siden.",
+"revnotfound"  => "Versjonen er ikke funnet",
+"revnotfoundtext" => "Den gamle versjonen av den siden du spurte etter, finnes ikke. Kontroller den URL-en du brukte for å få adgang til denne siden.\n",
+"loadhist"             => "Laster historikk",
+"currentrev"   => "Nåværende versjon",
+"revisionasof" => "Versjonen fra $1",
+"cur"                  => "nå",
+"next"                 => "neste",
+"last"                 => "forrige",
+"orig"                 => "original",
+"histlegend"   => "Forklaring: (nå) = forskjell fra den nåværende
+versjonen, (forrige) = forskjell fra den forrige versjonen, M = mindre endring",
+
+# Diffs
+#
+"difference"   => "(Forskjeller mellom versjoner)",
+"loadingrev"   => "laster versjon for å se forskjeller",
+"lineno"               => "Linje $1:",
+"editcurrent"  => "Rediger den nåværende versjonen av denne siden",
+
+# Search results
+#
+"searchresults" => "Søkeresultater",
+"searchresulttext" => "For mer informasjon om søking i Wikipedia, se
+$1.",
+"searchquery"  => "For forespørsel \"$1\"",
+"badquery"             => "Galt utformet forespørsel",
+"badquerytext" => "Vi kunne ikke utføre forespørselen.
+Det er sannsynligvis fordi du har forsøkt å søke etter et ord med
+færre enn tre bokstaver, hvilket ikke støttes ennå.
+Det kan også være du har skrevet feil.
+Prøv igjen.",
+"matchtotals"  => "Forespørselen \"$1\" ga treff på $2 artikkeltitler
+og på teksten i $3 artikler.",
+"nogomatch" => "Ingen sider med akkurat denne tittelen eksisterer, prøver
+fulltekstsøking i stedet. ",
+"titlematches" => "Artikkeltitler med treff på forespørselen",
+"notitlematches" => "Ingen artikkeltitler hadde treff på forespørselen",
+"textmatches"  => "Artikkeltekster med treff på forespørselen",
+"notextmatches"        => "Ingen artikkeltekster hadde treff på forespørselen",
+"prevn"                        => "forrige $1",
+"nextn"                        => "neste $1",
+"viewprevnext" => "Vis ($1) ($2) ($3).",
+"showingresults" => "Nedenfor vises <b>$1</b> resultater som starter med
+nummer <b>$2</b>.",
+"showingresultsnum" => "Nedenfor vises <b>$3</b> resultater som starter med nummer <b>$2</b>.",
+"nonefound"            => "<strong>NB</strong>: søk uten resultat skyldes
+at man søker etter alminnelige ord som \"har\" og \"fra\",
+som ikke er indeksert, eller ved å spesifisere mer enn et søkeord (da kun
+sider som inneholder alle søkeordene vil bli funnet).",
+"powersearch" => "Søk",
+"powersearchtext" => "
+Søk i navnerom :<br />
+$1<br />
+$2 List opp omdirigeringer   Søk etter $3 $9",
+"searchdisabled" => "<p>Søkefunksjonen er midlertidig avbrutt på grunn av
+for stort press på tjeneren; vi håper vi kan sette den på igjen når vi har
+oppgradert programvaren. I mellomtiden kan du søke via Google:</p>",
+"blanknamespace" => "(Hoved)",
+
+# Preferences page
+#
+"preferences"  => "Innstillinger",
+"prefsnologin" => "Ikke logget inn",
+"prefsnologintext"     => "Du må være [[Spesial:Userlogin|logget inn]]
+for å endre brukerinnstillingene.",
+"prefslogintext" => "Du logget inn som \"$1\".
+Ditt interne ID-nummer er $2.
+
+Se [[Wikipedia:Hvordan stille inn brukerinnstillinger]] for en forklaring på de forskjellige brukerinnstillingene.",
+"prefsreset"   => "Brukerinnstillingene er tilbakestilt.",
+"qbsettings"   => "Brukerinnstillinger for hurtigmeny",
+"changepassword" => "Skift passord",
+"skin"                 => "Utseende",
+"math"                 => "Vis matematiske formler",
+"dateformat"   => "Datoformat",
+"math_failure"         => "Feil i matematikken",
+"math_unknown_error"   => "ukjent feil",
+"math_unknown_function"        => "ukjent funksjon ",
+"math_lexing_error"    => "lexerfeil",
+"math_syntax_error"    => "syntaksfeil",
+"saveprefs"            => "Lagre brukerinnstillinger",
+"resetprefs"   => "Tilbakestill brukerinnstillinger",
+"oldpassword"  => "Gammelt passord",
+"newpassword"  => "Nytt passord",
+"retypenew"            => "Gjenta nytt passord",
+"textboxsize"  => "Tekstboks-størrelse",
+"rows"                 => "Rekker",
+"columns"              => "Kolonner",
+"searchresultshead" => "Brukerinnstillinger for søkeresultater",
+"resultsperpage" => "Resultater per side",
+"contextlines" => "Linjer per resultat",
+"contextchars" => "Tegn per linje i resultatet",
+"stubthreshold" => "Grense for visning av småartikler",
+"recentchangescount" => "Antall titler på siden \"siste endringer\"",
+"savedprefs"   => "Brukerinnstillingene er lagret.",
+"timezonetext" => "Tast inn antall timer lokal tid er forskjellig
+fra tjenerens tid.",
+"localtime"    => "Lokaltid",
+"timezoneoffset" => "Forskjell",
+"servertime"   => "Tjenerens tid er nå",
+"guesstimezone" => "Hent tidssone fra nettleseren",
+"emailflag"    => "Ikke ta imot e-post fra andre brukere",
+"defaultns"            => "Søk som standard i disse navnerom:",
+
+# Recent changes
+#
+"changes" => "endringer",
+"recentchanges" => "Siste endringer",
+# This is the default text, and can be overriden by editing [[Wikipedia::Recentchanges]]
+"recentchangestext" => "Se de sist endrede sider i Wikipedia på denne siden.",
+"rcloaderr"            => "Laster sist endrede sider",
+"rcnote"               => "Nedenfor er de siste <strong>$1</strong> endringer i de
+siste <strong>$2</strong> dagene.",
+"rcnotefrom"   => "Nedenfor er endringene fra <b>$2</b> inntil <b>$1</b> vist.",
+"rclistfrom"   => "Vis nye endringer med start fra $1",
+"rclinks"              => "Vis seneste $1 endringer i de siste $2 dager; $3 mindre endringer.",
+"rchide"               => "i $4 form; $1 mindre endringer; $2 andre navnerom; $3 mer enn én redigering.",
+"rcliu"                        => "; $1 redigeringer fra brukere som er logget inn",
+"diff"                 => "forskjell",
+"hist"                 => "historikk",
+"hide"                 => "skjul",
+"show"                 => "vis",
+"tableform"            => "tabell",
+"listform"             => "liste",
+"nchanges"             => "$1 endringer",
+"minoreditletter" => "M",
+"newpageletter" => "N",
+
+# Upload
+#
+"upload"               => "Last opp fil",
+"uploadbtn"            => "Last opp fil",
+"uploadlink"   => "Last opp fil",
+"reupload"             => "Last opp fil igjen",
+"reuploaddesc" => "Tilbake til skjemaet for å laste opp filer.",
+"uploadnologin" => "Ikke logget inn",
+"uploadnologintext"    => "Du må være [[Spesial:Userlogin|logget inn]]
+for å kunne laste opp filer.",
+"uploaderror"  => "Feil under opplasting av fil",
+"uploadtext"   => "'''STOPP!''' Før du laster opp filer her,
+vær sikker på du har lest og følger Wikipedias
+[[Project:Retningslinjer for billedbruk|retningslinjer for billedbruk]].
+
+For å se eller søke i bilder som tidligere er lastet opp,
+gå til [[Spesial:Imagelist|listen over bilder]].
+Opplasting og slettinger er registrert i
+[[Project:Upload_log|loggen over opplastede filer]].
+
+Bruk skjemaet nedenunder til å laste opp nye bilder som kan brukes
+til å illustrere dine artikler.
+På de fleste nettlesere vil du se en \"Browse...\"-knapp eller en
+\"Bla igjennom...\"-knapp, som vil
+bringe deg til operativsystemets standarddialog for å åpne filer.
+Når du velger en fil, vil navnet på filen dukke opp i tekstfeltet
+ved siden av knappen.
+Du må også verifisere at du ikke bryter noens opphavsrett.
+Det gjør du ved å krysse av i boksen.
+Trykk på \"Last opp\"-knappen for å laste opp filen.
+Dette kan godt ta litt tid hvis du har en langsom internettforbindelse.
+
+De foretrukne formatene er JPEG til fotografiske bilder, PNG
+til tegninger og andre små bilder, og OGG til lyd.
+Sørg for å gi filen et beskrivende navn for å unngå
+forvirring om innholdet.
+For å bruke bildet i en artikkel, bruk en lenke av dette slaget:
+
+'''<nowiki>[[bilde:fil.jpg]]</nowiki>''' eller
+'''<nowiki>[[bilde:fil.png|alternativ tekst]]</nowiki>''' eller
+'''<nowiki>[[medium:fil.ogg]]</nowiki>''' for lyd.
+
+Legg merke til at akkurat som med Wikipedia-sider, kan andre gjerne
+redigere eller
+slette de filene du har lastet opp, hvis de mener det hjelper encyklopedien, og
+du kan bli blokkert fra å laste opp hvis du misbruker systemet.",
+"uploadlog"            => "opplastingslogg",
+"uploadlogpage" => "Upload_log",
+"uploadlogpagetext" => "Her er en liste med de filene som er lastet
+opp sist. Alle de viste tidene er tjenerens tid (UTC).
+<ul>
+</ul>
+",
+"filename"             => "Filnavn",
+"filedesc"             => "Beskrivelse",
+"copyrightpage" => "Wikipedia:Opphavsrett",
+"copyrightpagename" => "Wikipedia opphavsrett",
+"uploadedfiles"        => "Filer som er lastet opp",
+"ignorewarning"        => "Ignorer advarselen og lagre filen likevel.",
+"minlength"            => "Navnet på filen må bestå av minst tre bokstaver.",
+"badfilename"  => "Navnet på filen er blitt endret til \"$1\".",
+"badfiletype"  => "\".$1\" er ikke et av de anbefalte filformatene.",
+"largefile"            => "Det anbefales at filer ikke er større enn 100kb.",
+"successfulupload" => "Opplastingen er gjennomført",
+"fileuploaded" => "Filen \"$1\" er lastet opp med.
+Følg denne lenken: ($2) til siden med beskrivelse og fyll ut
+informasjon omkring filen, slik som hvor den kom fra, når den er laget
+og av hvem, og andre ting du vet om filen.",
+"uploadwarning" => "Opplastingsadvarsel",
+"savefile"             => "Lagre fil",
+"uploadedimage" => "Lastet opp \"[[$1]]\"",
+"uploaddisabled" => "Beklager, muligheten for opplasting er deaktivert på denne tjeneren.",
+
+# Image list
+#
+"imagelist"            => "Billedliste",
+"imagelisttext"        => "Her er en liste med $1 bilder sortert $2.",
+"getimagelist" => "henter billedliste",
+"ilsubmit"             => "Søk",
+"showlast"             => "Vis de siste $1 bilder sortert $2.",
+"byname"               => "etter navn",
+"bydate"               => "etter dato",
+"bysize"               => "etter størrelse",
+"imgdelete"            => "slett",
+"imgdesc"              => "beskrivelse",
+"imglegend"            => "Forklaring: (beskrivelse) = vis/rediger bildebeskrivelse.",
+"imghistory"   => "Billedhistorikk",
+"revertimg"            => "gjenopprett",
+"deleteimg"            => "slett",
+"deleteimgcompletely"          => "slett",
+"imghistlegend" => "Forklaring: (nå) = dette er det nåværende bilde,
+(slett) = slett denne gamle versjonen, (gjenopprett) = gjenopprett en gammel versjon.
+<br /><i>Klikk på en dato for å se bildet som ble lastet opp da</i>.",
+"imagelinks"   => "Billedlenker",
+"linkstoimage" => "De følgende sider har lenker til dette bildet:",
+"nolinkstoimage" => "Det er ingen sider som har lenker til dette bildet.",
+
+# Statistics
+#
+"statistics"   => "Statistikk",
+"sitestats"            => "Wikipedia-statistikk",
+"userstats"            => "Brukerstatistikk",
+"sitestatstext" => "Der er i alt <b>$1</b> sider i databasen.
+Dette inkluderer diskusjonssider, sider om Wikipedia,
+omdirigeringssider, og andre som sikkert ikke kvalifiserer til å være artikler.
+Hvis man ekskluderer disse, er det <b>$2</b> sider som sannsynligvis er
+ordinære artikler.<p>
+Der har i alt vært <b>$3</b> viste sider, og <b>$4</b> redigeringer av sider
+siden programvaren ble oppdatert (25. september 2002).
+Det vil si at det har vært <b>$5</b> gjennomsnittlige redigeringer per side,
+og <b>$6</b> visninger per redigering.",
+"userstatstext" => "Der er  <b>$1</b> registrerte brukere.
+<b>$2</b> av disse er administratorer (se $3).",
+
+# Maintenance Page
+#
+"maintenance"          => "Vedlikeholdsside",
+"maintnancepagetext"   => "På denne siden er det forskjellige
+verktøyer for å vedlikeholde Wikipedia. Noen av disse funksjonene er
+harde for databasen (de tar lang tid), så la være å oppdatere siden
+hver gang du har rettet en enkelt ting",
+"maintenancebacklink"  => "Tilbake til vedlikeholdssiden",
+"disambiguations"      => "Artikler med flertydige titler",
+"disambiguationspage"  => "Wikipedia:Lenker til artikler med flertydige titler",
+"disambiguationstext"  => "De følgende artikler har lenker til
+<i>artikler med flertydige titler</i>. De burde ha lenke til en ikke-flertydig
+tittel i stedet.<br />En artikkel blir behandlet som flertydig hvis den har
+lenker fra $1.<br />Lenker fra andre navnerom er <i>ikke</i> listet her.",
+"doubleredirects"      => "Dobbelte omdirigeringer",
+"doubleredirectstext"  => "<b>NB:</b> Denne listen kan inneholde gale
+resultater. Det er som regel fordi siden inneholder ekstra tekst under den
+første #REDIRECT.<br />\nHver linje inneholder lenker til den første og den
+anden omdirigeringen, og den første linjen fra den andre omdirigeringsteksten.
+Det gir som regel den \"riktige\" målartikkelen, som den første omdirigeringen
+skulle ha pekt på.",
+"brokenredirects"      => "Dårlige omdirigeringer",
+"brokenredirectstext"  => "De følgende omdirigeringer peker på en side som
+ikke eksisterer.",
+"selflinks"            => "Sider som henviser til seg selv",
+"selflinkstext"                => "De følgende sider inneholder henvisninger til seg selv,
+men det burde de ikke.",
+"mispeelings"           => "Sider med stavefeil",
+"mispeelingstext"               => "De følgende sider inneholder en av de
+alminnelige stavefeilene som er listet på $1. Den korrekte stavemåte kan
+angis i paranteser etter den feilaktige stavemåten (som dette).",
+"mispeelingspage"       => "Liste over alminnelige stavefeil",
+"missinglanguagelinks"  => "Manglende språklenker",
+"missinglanguagelinksbutton"    => "Finn manglende språklenker for",
+"missinglanguagelinkstext"      => "Disse artiklene har <i>ikke</i> noen
+lenker til den samme artikkel i $1. Omdirigeringer og underartikler er
+<i>ikke</i> vist.",
+
+
+# Miscellaneous special pages
+#
+"orphans"              => "Foreldreløse sider",
+"lonelypages"  => "Foreldreløse sider",
+"unusedimages" => "Ubrukte bilder",
+"popularpages" => "Populære sider",
+"nviews"               => "$1 visninger",
+"wantedpages"  => "Etterspurte sider",
+"nlinks"               => "$1 lenker",
+"allpages"             => "Alle sider",
+"randompage"   => "Tilfeldig side",
+"shortpages"   => "Korte sider",
+"longpages"            => "Lange sider",
+"listusers"            => "Brukerliste",
+"specialpages" => "Spesialsider",
+"spheading"            => "Spesialsider for alle brukere",
+"protectpage"  => "Beskytt side",
+"recentchangeslinked" => "Relaterte endringer",
+"rclsub"               => "(til sider med lenke fra \"$1\")",
+"debug"                        => "Fiks feil",
+"newpages"             => "Nye sider",
+"ancientpages"         => "Eldste sider",
+"intl"         => "Språklenker",
+"movethispage" => "Flytt side",
+"unusedimagestext" => "<p>Legg merke til at andre internettsider
+slik som de andre internasjonale Wikipediaene kanskje har lenker til et bilde med
+en direkte URL, og kan være listet opp her, selv om det er
+i aktiv bruk.",
+"booksources"  => "Bokkilder",
+"booksourcetext" => "Her er en liste over lenker til steder som
+låner ut og/eller selger nye og brukte bøker, og som kanskje også har
+ytterligere informasjon om bøker du leter etter.
+Wikipedia er ikke assosiert med noen av disse stedene,
+og denne listen skal ikke sees på som en anbefaling av disse.",
+"alphaindexline" => "$1 til $2",
+
+# Email this user
+#
+"mailnologin"  => "Ingen avsenderadresse",
+"mailnologintext" => "Du må være [[Spesial:Userlogin|logget inn]]
+og ha en gyldig e-postadresse satt i [[Spesial:Preferences|brukerinnstillingene]]
+for å sende e-post til andre brukere.",
+"emailuser"            => "E-post til denne brukeren",
+"emailpage"            => "E-post til bruker",
+"emailpagetext"        => "Hvis denne brukeren har oppgitt en gyldig e-postadresse i
+sine brukerinnstillinger, vil dette skjemaet sende en enkelt
+beskjed.
+Den e-postadressen du har satt i brukerinnstillingene dine, vil dukke opp
+i \"Fra\"-feltet på denne e-posten, så mottageren er i stand til å svare.",
+"noemailtitle" => "Ingen e-postadresse",
+"noemailtext"  => "Denne brukeren har ikke oppgitt en gyldig e-postadresse,
+eller har valgt å ikke motta e-post fra andre brukere.",
+"emailfrom"            => "Fra",
+"emailto"              => "Til",
+"emailsubject" => "Emne",
+"emailmessage" => "Beskjed",
+"emailsend"            => "Send",
+"emailsent"            => "E-posten sendt",
+"emailsenttext" => "E-postbeskjeden er sendt.",
+
+# Watchlist
+#
+"watchlist"            => "Overvåkningsliste",
+"watchlistsub" => "(for bruker \"$1\")",
+"nowatchlist"  => "Du har ingenting i overvåkningslisten.",
+"watchnologin" => "Ikke logget inn",
+"watchnologintext"     => "Du må være [[Spesial:Userlogin|logget inn]]
+for å kunne endre overvåkningslisten.",
+"addedwatch"   => "Tilføyd til overvåkningslisten",
+"addedwatchtext" => "Siden \"$1\" er tilføyd <a href=\"" .
+  "{{localurle:Spesial:Watchlist}}\">overvåkningslisten</a>.
+Fremtidige endringer til denne siden og den tilhørende diskusjonssiden vil
+bli listet opp her, og siden vil fremstå <b>fremhevet</b> i <a href=\"" .
+  "{{localurle:Spesial:Recentchanges}}\">listen med de siste
+endringene</a> for å gjøre det lettere å finne den.</p>
+
+<p>Hvis du senere vil fjerne siden fra overvåkningslisten, klikk
+\"Fjern overvåkning\" ute i siden.",
+"removedwatch" => "Fjernet fra overvåkningslisten",
+"removedwatchtext" => "Siden \"$1\" er fjernet fra
+overvåkningslisten.",
+"watchthispage"        => "Overvåk side",
+"unwatchthispage" => "Fjern overvåkning",
+"notanarticle" => "Ikke en artikkel",
+"watchnochange" => "Ingen av sidene i overvåkningslisten er endret i den valgte perioden.",
+"watchdetails" => "($1 sider i overvåkningslisten, fratrukket alle diskusjonssidene;
+$2 totalt antall sider endret i den valgte perioden;
+$3...
+[$4 vis og rediger den komplette listen].)",
+"watchmethod-recent" => "sjekker siste endringer for sider i overvåkningslisten",
+"watchmethod-list" => "sjekker siste endringer for sider i overvåkningslisten",
+"removechecked" => "Fjern valgte sider fra overvåkningslisten",
+"watchlistcontains" => "Overvåkningslisten inneholder $1 sider.",
+"watcheditlist" => "Her er en alfabetisk liste over sidene i overvåkningslisten.
+Velg de sidene du vil fjerne fra overvåkningslisten
+og klikk på 'fjern valgte sider fra overvåkningslisten'-knappen
+i bunnen av skjermen.",
+"removingchecked" => "Fjerner de valgte sidene fra overvåkningslisten ...",
+"couldntremove" => "Kunne ikke fjerne '$1'...",
+"iteminvalidname" => "Problem med '$1', ugyldig navn...",
+"wlnote" => "Nedenfor er de siste $1 endringer i de siste <b>$2</b> timer.",
+
+
+# Delete/protect/revert
+#
+"deletepage"   => "Slett side",
+"confirm"              => "Bekreft",
+"excontent" => "innholdet var: '$1'",
+"exbeforeblank" => "innholdet før siden ble tømt var: '$1'",
+"exblank" => "siden var tom",
+"confirmdelete" => "Bekreft sletting",
+"deletesub"            => "(Sletter \"$1\")",
+"historywarning" => "Advarsel: Siden du holder på å slette har en historikk: ",
+"confirmdeletetext" => "Du holder på å permanent slette en side
+eller et bilde sammen med hele den tilhørende historikken fra databasen.
+Bekreft at du virkelig vil gjøre dette, at du forstår
+konsekvensene, og at du gjør dette i overensstemmelse med
+[[Wikipedia:Retningslinjer]].",
+"actioncomplete" => "Gjennomført",
+"deletedtext"  => "\"$1\" er slettet.
+Se $2 for en oversikt over de nyeste slettinger.",
+"deletedarticle" => "slettet \"$1\"",
+"dellogpage"   => "Slettingslogg",
+"dellogpagetext" => "Her er en liste over de nyeste slettinger.
+Alle tider er serverens tid (UTC).
+<ul>
+</ul>
+",
+"deletionlog"  => "slettingslogg",
+"reverted"             => "Gjenopprettet en tidligere versjon",
+"deletecomment"        => "Begrunnelse for sletting",
+"imagereverted" => "Gjenopprettelse av en tidligere versjon gjennomført.",
+"rollback"             => "Fjern redigeringer",
+"rollbacklink" => "fjern redigering",
+"rollbackfailed" => "Kunne ikke fjerne redigeringen",
+"cantrollback" => "Kan ikke fjerne redigering;
+den siste brukeren er den eneste forfatteren.",
+"alreadyrolled"        => "Kan ikke fjerne den siste redigeringen av [[$1]]
+foretatt av [[Bruker:$2|$2]] ([[Brukerdiskusjon:$2|diskusjon]]);
+en annen har allerede redigert siden eller fjernet redigeringen.
+
+Den siste redigeringen er foretatt av [[Bruker:$3|$3]] ([[Brukerdiskusjon:$3|diskusjon]]). ",
+#   only shown if there is an edit comment
+"editcomment" => "Kommentaren til redigeringen var: \"<i>$1</i>\".",
+"revertpage"   => "Gjenopprettet siden til tidligere versjon redigert av $1",
+"protectlogpage" => "Beskyttelseslogg",
+"protectlogtext" => "Her er en liste over sider som er blitt beskyttet eller har fått fjernet beskyttelsen.
+Se [[Wikipedia:Beskyttet side]] for mer informasjon.",
+"protectedarticle" => "beskyttet [[$1]]",
+"unprotectedarticle" => "fjernet beskyttelse for [[$1]]",
+
+# Undelete
+"undelete" => "Gjenopprett en slettet side",
+"undeletepage" => "Se og gjenopprett slettede sider",
+"undeletepagetext" => "De følgende sider er slettet, men de finnes
+stadig i arkivet og kan gjenopprettes. Arkivet blir periodevis slettet.",
+"undeletearticle" => "Gjenopprett slettet artikkel",
+"undeleterevisions" => "$1 revisjoner arkivert",
+"undeletehistory" => "Hvis du gjenoppretter siden, vil alle de historiske
+revisjoner også bli gjenopprettet. Hvis en ny side med det samme navnet
+er opprettet siden denne ble slettet, vil de gjenopprettede revisjonene
+dukke opp i den tidligere historikken, og den nyeste revisjonen vil forbli
+på siden.",
+"undeleterevision" => "Slettet versjon fra $1",
+"undeletebtn" => "Gjenopprett!",
+"undeletedarticle" => "gjenopprettet \"$1\"",
+"undeletedtext"   => "Artikkelen [[$1]] er gjenopprettet.
+Se [[Wikipedia:Slettingslogg]] for en oversikt over nylige
+slettinger og gjenopprettelser.",
+
+# Contributions
+#
+"contributions"        => "Brukerbidrag",
+"mycontris" => "Egne bidrag",
+"contribsub"   => "For $1",
+"nocontribs"   => "Ingen endringer er funnet som passer disse kriteriene.",
+
+"ucnote"       => "Her er denne brukerens siste <b>$1</b> endringer i de
+siste <b>$2</b> dagene.",
+"uclinks"      => "Vis de siste $1 endringene; vis de siste $2 dagene.",
+"uctop"                => " (topp)" ,
+
+# What links here
+#
+"whatlinkshere"        => "Lenker hit",
+"notargettitle" => "Intet mål",
+"notargettext" => "Du har ikke spesifisert en målside eller bruker
+å utføre denne funksjonen på.",
+"linklistsub"  => "(Liste over lenker)",
+"linkshere"    => "De følgende sider har lenker hit:",
+"nolinkshere"  => "Ingen sider har lenker hit.",
+"isredirect"   => "omdirigeringsside",
+
+# Block/unblock IP
+#
+"blockip"              => "Blokker IP-adresse",
+"blockiptext"  => "Bruk skjemaet nedenunder for å blokkere skriveadgangen
+fra en spesifikk IP-adresse.
+Dette må kun gjøres for at forhindre vandalisme, og i
+overensstemmelse med [[Wikipedia:Retningslinjer|retningslinjene]].
+Fyll ut en spesiell begrunnelse nedenunder (for eksempel med et sitat fra
+sider som har vært utsatt for vandalisme).",
+"ipaddress"            => "IP-adresse",
+"ipbreason"            => "Begrunnelse",
+"ipbsubmit"            => "Blokker denne adressen",
+"badipaddress" => "IP-adressen er galt utformet.",
+"blockipsuccesssub" => "Blokkering utført",
+"blockipsuccesstext" => "IP-adressen \"$1\" er blokkert.
+<br />Se [[Spesial:Ipblocklist|IP-blokkeringslisten]] for alle blokkeringer.",
+"unblockip"            => "Opphev blokkeringen av IP-adresse",
+"unblockiptext"        => "Bruk skjemaet nedenunder for å gjenopprette skriveadgangen
+for en tidligere blokkert IP-adresse.",
+"ipusubmit"            => "Opphev blokkeringen av denne adresse",
+"ipusuccess"   => "IP-adressen \"$1\" har fått opphevet blokkeringen",
+"ipblocklist"  => "Liste over blokkerte IP-adresser",
+"blocklistline"        => "$1, $2 blokkerte $3 ($4)",
+"blocklink"            => "blokker",
+"unblocklink"  => "opphev blokkering",
+"contribslink" => "bidrag",
+"autoblocker"  => "Automatisk blokkert fordi du deler IP-adresse med \"$1\". Begrunnelse \"$2\".",
+
+# Developer tools
+#
+"lockdb"               => "Lås database",
+"unlockdb"             => "Lås opp database",
+"lockdbtext"   => "Å låse databasen vil avbryte alle brukere fra å kunne
+redigere sider, endre deres innstillinger, redigere deres
+overvåkningsliste, og andre ting som krever endringer i databasen.
+Bekreft at du har til hensikt å gjøre dette, og at du vil
+låse opp databasen når vedlikeholdet er utført.",
+"unlockdbtext" => "Å låse opp databasen vil si at alle brukere igjen
+kan redigere sider, endre sine innstillinger, redigere sin
+overvåkningsliste, og andre ting som krever endringer i databasen.
+Bekreft at du har til hensikt å gjøre dette.",
+"lockconfirm"  => "Ja, jeg vil virkelig låse databasen.",
+"unlockconfirm"        => "Ja, jeg vil virkelig låse opp databasen.",
+"lockbtn"              => "Lås databasen",
+"unlockbtn"            => "Lås opp databasen",
+"locknoconfirm" => "Du har ikke bekreftet handlingen.",
+"lockdbsuccesssub" => "Databasen er nå låst",
+"unlockdbsuccesssub" => "Databasen er nå låst opp",
+"lockdbsuccesstext" => "Wikipedia-databasen er låst.
+<br />Husk å fjerne låsen når du er ferdig med vedlikeholdet.",
+"unlockdbsuccesstext" => "Wikipedia-databasen er låst opp.",
+
+# Move page
+#
+"movepage"             => "Flytt side",
+"movepagetext" => "Når du bruker skjemaet nedenunder, vil du få omdøpt en
+side og flyttet hele historikken til det nye navnet.
+Den gamle tittelen vil bli en omdirigeringsside til den nye tittelen.
+Lenker til den gamle tittelen vil ikke bli endret. Sørg for å
+sjekke for dobbelte eller dårlige omdirigeringer.
+Du er ansvarlig for at alle lenker stadig peker dit det er
+meningen de skal peke.
+
+Legg merke til at siden '''ikke''' kan flyttes hvis det allerede finnes en side
+med den nye tittelen, med mindre den siden er tom eller er en omdirigering
+uten noen historikk. Det betyr at du kan flytte en side tilbake dit
+den kom fra hvis du gjør en feil.
+
+<b>ADVARSEL!</b>
+Dette kan være en drastisk og uventet endring for en populær side;
+vær sikker på at du forstår konsekvensene av dette før du
+fortsetter.",
+"movepagetalktext" => "Den tilhørende diskusjonssiden, hvis det finnes en,
+vil automatisk bli flyttet med siden '''med mindre:'''
+*Du flytter siden til et annet navnerom,
+*En ikke-tom diskusjonsside allerede eksisterer under det nye navnet, eller
+*Du fjerner markeringen i boksen nedenunder.
+
+I disse tilfellene er du nødt til å flytte eller flette sammen siden manuelt.",
+"movearticle"  => "Flytt side",
+"movenologin"  => "Ikke logget inn",
+"movenologintext" => "Du må være registrert bruker og være [[Spesial:Userlogin|logget på]]
+for å flytte en side.",
+"newtitle"             => "Til ny tittel",
+"movepagebtn"  => "Flytt side",
+"pagemovedsub" => "Flytting gjennomført",
+"pagemovedtext" => "Siden \"[[$1]]\" er flyttet til \"[[$2]]\".",
+"articleexists" => "En side med det navnet eksisterer allerede, eller det
+navnet du har valgt, er ikke gyldig. Velg et annet navn.",
+"talkexists"   => "Siden ble flyttet korrekt, men den tilhørende
+diskusjonssiden kunne ikke flyttes, fordi det allerede eksisterer en
+med den nye tittelen. Du er nødt til å flette dem sammen manuelt.",
+"movedto"              => "flyttet til",
+"movetalk"             => "Flytt også diskusjonssiden, hvis den eksisterer.",
+"talkpagemoved" => "Den tilhørende diskusjonssiden ble også flyttet.",
+"talkpagenotmoved" => "Den tilhørende diskusjonssiden ble
+<strong>ikke</strong> flyttet.",
+# Math
+'mw_math_png' => "Vis alltid som PNG",
+'mw_math_simple' => "HTML hvis veldig enkel, ellers PNG",
+'mw_math_html' => "HTML hvis mulig, ellers PNG",
+'mw_math_source' => "Behold som TeX (for tekst-nettlesere)",
+'mw_math_modern' => "Anbefalt for moderne nettlesere",
+'mw_math_mathml' => 'MathML',
+
+);
+
+require_once( "LanguageUtf8.php" );
+
+class LanguageNo extends LanguageUtf8 {
+
+       function getBookstoreList () {
+               global $wgBookstoreListNo ;
+               return $wgBookstoreListNo ;
+       }
+
+       function getNamespaces() {
+               global $wgNamespaceNamesNo;
+               return $wgNamespaceNamesNo;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsNo;
+               return $wgQuickbarSettingsNo;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesNo;
+               return $wgSkinNamesNo;
+       }
+
+
+       function date( $ts, $adj = false ) {
+               if ( $adj ) { $ts = $this->userAdjust( $ts ); }
+
+               $d = (0 + substr( $ts, 6, 2 )) . ". " .
+                 $this->getMonthAbbreviation( substr( $ts, 4, 2 ) ) . " " .
+                 substr( $ts, 0, 4 );
+               return $d;
+       }
+
+       function time( $ts, $adj = false ) {
+               if ( $adj ) { $ts = $this->userAdjust( $ts ); }
+
+               $t = substr( $ts, 8, 2 ) . ":" . substr( $ts, 10, 2 );
+               return $t;
+       }
+
+       function timeanddate( $ts, $adj = false ) {
+               return $this->date( $ts, $adj ) . " kl." . $this->time( $ts, $adj );
+       }
+
+       function formatNum( $number ) {
+               global $wgTranslateNumerals;
+               return $wgTranslateNumerals ? strtr($number, '.,', ',.' ) : $number;
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesNo;
+               if( isset( $wgAllMessagesNo[$key] ) ) {
+                       return $wgAllMessagesNo[$key];
+               } else {
+                       return parent::getMessage( $key );
+               }
+       }
+}
+
+?>
diff --git a/languages/LanguageNon.php b/languages/LanguageNon.php
new file mode 100644 (file)
index 0000000..069c7eb
--- /dev/null
@@ -0,0 +1,14 @@
+<?php
+/** Old Norse (Norrǿna)
+  *
+  * Defaults to Icelandic instead of English.
+  *
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+require_once( 'LanguageIs.php' );
+
+class LanguageNon extends LanguageIs {}
+
+?>
diff --git a/languages/LanguageNv.php b/languages/LanguageNv.php
new file mode 100644 (file)
index 0000000..26bacb2
--- /dev/null
@@ -0,0 +1,115 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+# Navajo language file
+# No messages at the moment, just all the other stuff
+
+require_once( "LanguageUtf8.php" );
+
+if($wgMetaNamespace === FALSE)
+       $wgMetaNamespace = str_replace( ' ', '_', $wgSitename );
+
+/* private */ $wgNamespaceNamesNv = array(
+       NS_MEDIA            => 'Media',
+       NS_SPECIAL          => 'Special',
+       NS_MAIN             => '',
+       NS_TALK             => 'Naaltsoos_baa_yinísht\'į́',
+       NS_USER             => 'Choinish\'įįhí',
+       NS_USER_TALK        => 'Choinish\'įįhí_baa_yinísht\'į́',
+       NS_PROJECT          => 'Wikiibíídiiya',
+       NS_PROJECT_TALK     => 'Wikiibíídiiya_baa_yinísht\'į́',
+       NS_IMAGE            => 'E\'elyaaígíí',
+       NS_IMAGE_TALK       => 'E\'elyaaígíí_baa_yinísht\'į́',
+       NS_MEDIAWIKI        => 'MediaWiki',
+       NS_MEDIAWIKI_TALK   => 'MediaWiki_baa_yinísht\'į́',
+       NS_TEMPLATE         => 'Template',
+       NS_TEMPLATE_TALK    => 'Template_talk',
+       NS_HELP             => 'Aná\'álwo\'',
+       NS_HELP_TALK        => 'Aná\'álwo\'_baa_yinísht\'į́',
+       NS_CATEGORY         => 'T\'ááłáhági_át\'éego',
+       NS_CATEGORY_TALK    => 'T\'ááłáhági_át\'éego_baa_yinísht\'į́'
+);
+
+/* private */ $wgQuickbarSettingsNv = array(
+       'None', 'Fixed left', 'Fixed right', 'Floating left'
+);
+
+/* private */ $wgSkinNamesNv = array(
+       'mono' => 'Łáa\'ígíí',
+       'monobook' => 'NaaltsoosŁáa\'ígíí'
+) + $wgSkinNamesEn;
+
+
+/* private */ $wgDateFormatsNv = array(
+#      'No preference',
+);
+
+/* private */ $wgWeekdayNamesNv = array(
+       'Damóogo', 'Damóo biiskání', 'Damóodóó naakiską́o', 'Damóodóó tágí jį́', 'Damóodóó dį́į́\' yiską́o',
+       'Nda\'iiníísh', 'Yiską́ damóo'
+);
+
+/* private */ $wgMonthNamesNv = array(
+       'Yas Niłt\'ees', 'Atsá Biyáázh', 'Wóózhch\'į́į́d', 'T\'ą́ą́chil', 'T\'ą́ą́tsoh', 'Ya\'iishjááshchilí',
+       'Ya\'iishjáástsoh', 'Bini\'ant\'ą́ą́ts\'ózí', 'Bini\'ant\'ą́ą́tsoh', 'Ghąąjį', 'Níłch\'its\'ósí',
+       'Níłch\'itsoh'
+);
+
+/* private */ $wgMonthAbbreviationsNv = array(
+       'Ynts', 'Atsb', 'Wozh', 'Tchi', 'Ttso', 'Yjsh', 'Yjts', 'Btsz',
+       'Btsx', 'Ghąj', 'Ntss', 'Ntsx'
+);
+
+#--------------------------------------------------------------------------
+# Internationalisation code
+#--------------------------------------------------------------------------
+
+class LanguageNv extends LanguageUtf8 {
+
+       function getNamespaces() {
+               global $wgNamespaceNamesNv;
+               return $wgNamespaceNamesNv;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsNv;
+               return $wgQuickbarSettingsNv;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesNv;
+               return $wgSkinNamesNv;
+       }
+
+       function getDateFormats() {
+               global $wgDateFormatsNv;
+               return $wgDateFormatsNv;
+       }
+
+       function getMonthName( $key ) {
+               global $wgMonthNamesNv;
+               return $wgMonthNamesNv[$key-1];
+       }
+
+       /* by default we just return base form */
+       function getMonthNameGen( $key ) {
+               return $this->getMonthName( $key );
+       }
+
+       function getMonthAbbreviation( $key ) {
+               global $wgMonthAbbreviationsNv;
+               return @$wgMonthAbbreviationsNv[$key-1];
+       }
+
+       function getWeekdayName( $key ) {
+               global $wgWeekdayNamesNv;
+               return $wgWeekdayNamesNv[$key-1];
+       }
+
+
+}
+
+?>
diff --git a/languages/LanguageOc.php b/languages/LanguageOc.php
new file mode 100644 (file)
index 0000000..b45f588
--- /dev/null
@@ -0,0 +1,871 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+require_once( "LanguageUtf8.php" );
+
+/* private */ $wgNamespaceNamesOc = array(
+       NS_SPECIAL        => "Especial",
+       NS_MAIN           => "",
+       NS_TALK           => "Discutir",
+       NS_USER           => "Utilisator",
+       NS_USER_TALK      => "Discutida_Utilisator",
+       NS_PROJECT        => "Oiquipedià",
+       NS_PROJECT_TALK   => "Discutida_Oiquipedià",
+       NS_IMAGE          => "Image",
+       NS_IMAGE_TALK     => "Discutida_Image",
+       NS_MEDIAWIKI      => "MediaWiki",
+       NS_MEDIAWIKI_TALK => "MediaWiki_talk",
+       NS_TEMPLATE       => "Template",
+       NS_TEMPLATE_TALK  => "Template_talk"
+
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgQuickbarSettingsOc = array(
+       "Cap", "Esquèr", "Drech", "Flotejant a esquèr"
+);
+
+/* private */ $wgSkinNamesOc = array(
+       'standard' => "Normal",
+       'nostalgia' => "Nostalgia",
+       'cologneblue' => "Còlonha Blau",
+) + $wgSkinNamesEn;
+
+
+/* private */ $wgBookstoreListOc = array(
+       "Amazon.fr" => "http://www.amazon.fr/exec/obidos/ISBN=$1"
+);
+
+/* private */ $wgAllMessagesOc = array(
+
+# User Toggles
+
+"tog-underline" => "Ligams solinhats",
+"tog-highlightbroken" => "Ligams sus los subjèctes non creats aparéisson en rog",
+"tog-justify" => "Paragrafes justificats",
+"tog-hideminor" => "Amagar las <i>Cambiadas recentas</i> minoras",
+"tog-usenewrc" => "Cambiadas recentas melhorats<br /> (non per tots los navigaires)",
+"tog-numberheadings" => "Numerotacion automatica de los títols",
+"tog-showtoolbar" => "Show edit toolbar",
+"tog-editondblclick" => "Editar paginas amb un doble clic (JavaScript)",
+"tog-editsection"      => "Éditer une section via les liens [éditer]", //Looxix (Enable section editing via [edit] links)
+"tog-editsectiononrightclick"  => "Éditer une section en cliquant à droite<br /> sur le titre de la section", // Looxix
+"tog-showtoc"  => "Afficher la table des matières<br /> (pour les articles ayant plus de 3 sections)",
+"tog-rememberpassword" => "Se souvenir de mon mot de passe (cookie)",
+"tog-editwidth" => "La fenêtre d'édition s'affiche en pleine largeur",
+"tog-watchdefault" => "Suivre les articles que je crée ou modifie",
+"tog-minordefault" => "Mes modifications sont considérées<br /> comme mineures par défaut",
+"tog-previewontop" => "La prévisualisation s'affiche au<br /> dessus de la boite de rédaction",
+"tog-nocache" => "Désactiver le cache des pages", // Looxix "Disable page caching"
+
+# Dates
+#
+
+'sunday' => 'dimenge',
+'monday' => 'diluns',
+'tuesday' => 'dimarts',
+'wednesday' => 'dimèrcres',
+'thursday' => 'dijòus',
+'friday' => 'divendres',
+'saturday' => 'dissabte',
+'january' => 'janvièir',
+'february' => 'febrièr',
+'march' => 'març',
+'april' => 'abril',
+'may_long' => 'mai',
+'june' => 'junh',
+'july' => 'julhet',
+'august' => 'agost',
+'september' => 'setembre',
+'october' => 'octòbre',
+'november' => 'novembre',
+'december' => 'decembre',
+'jan' => 'jan',
+'feb' => 'feb',
+'mar' => 'mar',
+'apr' => 'abr',
+'may' => 'mai',
+'jun' => 'jun',
+'jul' => 'jul',
+'aug' => 'ago',
+'sep' => 'set',
+'oct' => 'oct',
+'nov' => 'nov',
+'dec' => 'dec',
+
+
+# Bits of text used by many pages:
+#
+"categories"   => "Catégories de la page", // Looxix "Page categories",
+"category"     => "catégorie",                        // Looxix "category",
+"category_header" => "Articles dans la catégorie \"$1\"", // Looxix "Articles in category \"$1\"",
+"subcategories"        => "Sous-catégories", // Looxix "Subcategories",
+
+
+"linktrail"     => "/^([a-zàâçéèêîôû]+)(.*)\$/sD",
+"mainpage"      => "Accueil",
+"mainpagetext"  => "Logiciel Wikipédia installé.",
+"about"         => "À propos",
+"aboutsite"     => "À propos de Wikipédia",
+"aboutpage"     => "Wikipédia:À propos",
+"help"          => "Aide",
+"helppage"      => "Wikipédia:Aide",
+"bugreports"    => "Rapport d'erreurs",
+"bugreportspage" => "Wikipédia:Rapport d'erreurs",
+"sitesupport"   => "Participer en faisant un don",
+
+"faq"           => "FAQ",
+"faqpage"       => "Wikipédia:FAQ",
+"edithelp"      => "Aide",
+"edithelppage"  => "Wikipédia:Comment éditer une page",
+"cancel"        => "Annuler",
+"qbfind"        => "Rechercher",
+"qbbrowse"      => "Défiler",
+"qbedit"        => "Éditer",
+"qbpageoptions" => "Page d'option",
+"qbpageinfo"    => "Page d'information",
+"qbmyoptions"   => "Mes options",
+"mypage"        => "Ma page",
+"mytalk"        => "Ma page de discussion",
+"currentevents" => "Actualités",
+"errorpagetitle" => "Erreur",
+"returnto"      => "Revenir à la page $1.",
+"tagline"       => "Un article de Wikipédia, l'encyclopédie libre.",
+"whatlinkshere" => "Références à cette page",
+"help"          => "Aide",
+"search"        => "Rechercher",
+"history"       => "Historique",
+"printableversion" => "Version imprimable",
+"editthispage"  => "Modifier cette page",
+"deletethispage" => "Supprimer cette page",
+"protectthispage" => "Protéger cette page",
+"unprotectthispage" => "Déprotéger cette page",
+"newpage"       => "Nouvelle page",
+"talkpage"      => "Page de discussion",
+"postcomment"  => "Ajouter un commentaire", // Looxix "Post a comment",
+"articlepage"  => "Voir l'article",
+"subjectpage"   => "Page sujet",
+"userpage"      => "Page utilisateur",
+"wikipediapage" => "Page méta",
+"imagepage"     => "Page image",
+"viewtalkpage"  => "Page de discussion",
+"otherlanguages" => "Autres langues",
+"redirectedfrom" => "(Redirigé depuis $1)",
+"lastmodified"  => "Dernière modification de cette page : $1.",
+"viewcount"     => "Cette page a été consultée $1 fois.",
+"printsubtitle" => "(de {{SERVER}})",
+"protectedpage" => "Page protégée",
+"administrators" => "Wikipédia:Administrateurs",
+"sysoptitle"    => "Accès administrateur requis",
+"sysoptext"     => "L'action que vous avez tentée ne peut être effectuée que par un utilisateur ayant le statut d'\"administrateur\".
+Voir $1.",
+"developertitle" => "Accès développeur requis",
+"developertext" => "L'action que vous avez tentée ne peut être effectuée que par un utilisateur ayant le statut de \"développeur\".
+Voir $1.",
+"nbytes"        => "$1 octets",
+"go"            => "Consulter",                        // Looxix "OK",
+"ok"            => "OK",
+"sitetitle"     => "Wikipédia",
+"sitesubtitle"  => "L'encyclopédie libre",
+"retrievedfrom" => "Récupérée de \"$1\"",
+"newmessages"   => "Vous avez des $1.",
+"newmessageslink" => "nouveaux messages",
+"editsection"  => "modifier",
+"toc"          => "Sommaire",                  // Looxix "Table"
+"showtoc"      => "montrer",                   // Looxix
+"hidetoc"      => "cacher",                    // Looxix
+"thisisdeleted" => "Afficher ou restaurer $1?",        // Looxix "View or restore $1?"
+"restorelink"  => "$1 modifications effacées",                // Looxix "$1 deleted edits"
+
+# Main script and global functions
+#
+"nosuchaction" => "Action inconnue",
+"nosuchactiontext" => "L'action spécifiée dans l'Url n'est pas reconnue par le logiciel Wikipédia.",
+"nosuchspecialpage" => "Page spéciale inexistante",
+"nospecialpagetext" => "Vous avez demandé une page spéciale qui n'est pas reconnue par le logiciel Wikipédia.",
+
+# General errors
+#
+"error"                => "Erreur",
+"databaseerror" => "Erreur base de données",
+"dberrortext"  => "Erreur de syntaxe dans la base de données. La dernière requête traitée par la base de données était :
+<blockquote><tt>$1</tt></blockquote>
+depuis la fonction \"<tt>$2</tt>\".
+MySQL a renvoyé l'erreur \"<tt>$3: $4</tt>\".",
+"noconnect"    => "Désolé ! Suite à des problèmes techniques, il est impossible de se connecter à la base de données pour le moment.", //"Connexion impossible à la base de données sur $1",
+"nodb"         => "Sélection impossible de la base de données $1",
+"cachederror"  => "Ceci est une copie de la page demandée et peut ne pas être à jour", // Looxix
+"readonly"     => "Mises à jour bloquées sur la base de données",
+"enterlockreason" => "Indiquez la raison du blocage, ainsi qu'une estimation de la durée de blocage ",
+"readonlytext" => "Les ajouts et mises à jour sur la base de données Wikipédia sont actuellement bloqués, probablement pour permettre la maintenance de la base, après quoi, tout rentrera dans l'ordre. Voici la raison pour laquelle l'administrateur a bloqué la base :
+<p>$1",
+"missingarticle" => "La base de données n'a pas pu trouver le texte d'une page existante, dont le titre est \"$1\".
+Ce n'est pas une erreur de la base de données, mais plus probablement un bogue du logiciel Wikipédia.
+Veuillez rapporter cette erreur à un administrateur, en lui indiquant l'adresse de la page fautive.",
+"internalerror" => "Erreur interne",
+"filecopyerror" => "Impossible de copier \"$1\" vers \"$2\".",
+"filerenameerror" => "Impossible de renommer \"$1\" en \"$2\".",
+"filedeleteerror" => "Impossible de supprimer \"$1\".",
+"filenotfound" => "Fichier \"$1\" introuvable.",
+"unexpected"   => "Valeur inattendue : \"$1\"=\"$2\".",
+"formerror"    => "Erreur: Impossible de soumettre le formulaire",
+"badarticleerror" => "Cette action ne peut pas être effectuée sur cette page.",
+"cannotdelete" => "Impossible de supprimer la page ou l'image indiquée.",
+
+"badtitle"     => "Mauvais titre", // Looxix "Bad title",
+"badtitletext" => "Le titre de la page demandée est invalide, vide ou le lien interlangue est invalide", // Looxix
+"perfdisabled" => "Désolé ! Cette fonctionnalité est temporairement désactivée
+car elle ralentit la base de données à un point tel que plus personne
+ne peut utiliser le wiki.", // Looxix
+"perfdisabledsub" => "Ceci est une copie de sauvegarde de $1:", // Looxix
+"viewsource"   => "Voir le texte source",
+"protectedtext"        => "Cette page a été bloquée pour empêcher sa modification. Consultez [[Wikipédia:Page protégée]] pour voir les différentes raisons possibles.", // Looxix
+
+# Login and logout pages
+#
+"logouttitle"  => "Déconnexion",
+"logouttext"   => "Vous êtes à présent déconnecté(e).
+Vous pouvez continuer à utiliser Wikipédia de façon anonyme, ou vous reconnecter, éventuellement sous un autre nom.\n",
+
+"welcomecreation" => "<h2>Bienvenue, $1!</h2><p>Votre compte d'utilisateur a été créé.
+N'oubliez pas de personnaliser votre Wikipédia en consultant la page Préférences.",
+
+"loginpagetitle"     => "Votre identifiant",
+"yourname"           => "Votre nom d'utilisateur",
+"yourpassword"       => "Votre mot de passe",
+"yourpasswordagain"  => "Entrez à nouveau votre mot de passe",
+"newusersonly"       => " (nouveaux utilisateurs uniquement)",
+"remembermypassword" => "Se souvenir de mon mot de passe (cookie)",
+"loginproblem"       => "<b>Problème d'identification.</b><br />Essayez à nouveau !",
+"alreadyloggedin"    => "<strong>Utilisateur $1, vous êtes déjà identifié !</strong><br />\n",
+
+"login"         => "Identification",
+"userlogin"     => "Identification",
+"logout"        => "Déconnexion",
+"userlogout"    => "Déconnexion",
+"createaccount" => "Créer un nouveau compte",
+"createaccountmail"    => "par courriel", // Looxix "by eMail",
+"badretype"     => "Les deux mots de passe que vous avez saisis ne sont pas identiques.",
+"userexists"    => "Le nom d'utilisateur que vous avez saisi est déjà utilisé. Veuillez en choisir un autre.",
+"youremail"     => "Mon adresse électronique",
+"yournick"      => "Mon surnom (pour les signatures)",
+"emailforlost"  => "Si vous égarez votre mot de passe, vous pouvez demander à ce qu'un nouveau vous soit envoyé à votre adresse électronique.",
+"loginerror"    => "Problème d'identification",
+"noname"        => "Vous n'avez pas saisi de nom d'utilisateur.",
+"loginsuccesstitle" => "Identification réussie.",
+"loginsuccess"  => "Vous êtes actuellement connecté(e) sur Wikipédia en tant que \"$1\".",
+"nosuchuser"    => "L'utilisateur \"$1\" n'existe pas.
+Vérifiez que vous avez bien orthographié le nom, ou utilisez le formulaire ci-dessous pour créer un nouveau compte utilisateur.",
+"wrongpassword" => "Le mot de passe est incorrect. Essayez à nouveau.",
+"mailmypassword" => "Envoyez-moi un nouveau mot de passe",
+"passwordremindertitle" => "Votre nouveau mot de passe sur Wikipédia",
+"passwordremindertext" => "Quelqu'un (probablement vous) ayant l'adresse IP $1 a demandé à ce qu'un nouveau mot de passe vous soit envoyé pour votre accès à Wikipédia.
+Le mot de passe de l'utilisateur \"$2\" est à présent \"$3\".
+Nous vous conseillons de vous connecter et de modifier ce mot de passe dès que possible.",
+"noemail"  => "Aucune adresse électronique n'a été enregistrée pour l'utilisateur \"$1\".",
+"passwordsent" => "Un nouveau mot de passe a été envoyé à l'adresse électronique de l'utilisateur \"$1\".
+Veuillez vous identifier dès que vous l'aurez reçu.",
+
+# Edit pages
+#
+"summary"      => "Résumé",
+"subject"      => "Sujet/titre", // Looxix "Subject/headline",
+"minoredit"    => "Modification mineure.",
+"watchthis"    => "Suivre cet article",
+"savearticle"  => "Sauvegarder",
+"preview"      => "Prévisualiser",
+"showpreview"  => "Prévisualisation",
+"blockedtitle" => "Utilisateur bloqué",
+"blockedtext"  => "Votre compte utilisateur ou votre adresse IP ont été bloqués par $1 pour la raison suivante :<br />$2<p> Vous pouvez contacter l'administrateur pour en discuter.",
+"whitelistedittitle" => "Login requis pour rédiger", // Looxix "Login required to edit",
+"whitelistedittext" => "Vous devez être [[Special:Userlogin|connecté]] pour pouvoir rédiger", // Looxix
+"whitelistreadtitle" => "Login requis pour lire", // Looxix "Login required to read",
+"whitelistreadtext" => "Vous devez être [[Special:Userlogin|connecté]] pour pouvoir lire les articles", // Looxix
+"whitelistacctitle" => "Vous n'êtes pas autorisé à créer un compte", // Looxix
+"whitelistacctext" => "Pour pouvoir créer un compte sur ce Wiki vous devez être [[Special:Userlogin|connecté]] et avoir les permissions appropriées", // Looxix
+"accmailtitle" => "Mot de passe envoyé.", // Looxix "Password sent.",
+"accmailtext" => "Le mot de passe de '$1' a été envoyé à $2.", // Looxix
+
+"newarticle"   => "(Nouveau)",
+"newarticletext" => "Saisissez ici le texte de votre article.",
+"anontalkpagetext" => "---- ''Ceci est la page de discussion pour un utilisateur anonyme qui n'a pas encore créé un compte ou qui ne l'utilise pas. Pour cette raison, nous devons utiliser l'[[adresse IP]] numérique pour l'identifier. Une adresse de ce type peut être partagée entre plusieurs utilisateurs. Si vous êtes un utilisateur anonyme et si vous constatez que des commentaires qui ne vous concernent pas vous ont été adressés, vous pouvez [[Special:Userlogin|créer un compte ou vous connecter]] afin d'éviter toute future confusion à l'avenir.",
+"noarticletext" => "(Il n'y a pour l'instant aucun texte sur cette page)",
+"updated"      => "(Mis à jour)",
+"note"         => "<strong>Note :</strong> ",
+"previewnote"  => "Attention, ce texte n'est qu'une prévisualisation et n'a pas encore été sauvegardé !",
+"previewconflict" => "La prévisualisation montre le texte de cette page tel qu'il apparaîtra une fois sauvegardé.",
+"editing"      => "modification de $1",
+"editconflict" => "Conflit de modification : $1",
+"explainconflict" => "<b>Cette page a été sauvegardée après que vous avez commencé à la modifier.
+La zone d'édition supérieure contient le texte tel qu'il est enregistré actuellement dans la base de données. Vos modifications apparaissent dans la zone d'édition inférieure. Vous allez devoir apporter vos modifications au texte existant. Seul le texte de la zone supérieure sera sauvegardé.<br />",
+"yourtext"     => "Votre texte",
+"storedversion" => "Version enregistrée",
+"editingold"   => "<strong>Attention : vous êtes en train de modifier une version obsolète de cette page. Si vous sauvegardez, toutes les modifications effectuées depuis cette version seront perdues.</strong>",
+"yourdiff"  => "Différences",
+"copyrightwarning" => "Toutes les contributions à Wikipédia sont considérées comme publiées sous les termes de la GNU Free Documentation Licence, une licence de documentation libre (Voir $1 pour plus de détails). Si vous ne désirez pas que vos écrits soient édités et distribués à volonté, ne les envoyez pas. De même, merci de ne contribuer qu'en apportant vos propres écrits ou des écrits issus d'une source libre de droits. <b>N'UTILISEZ PAS DE TRAVAUX SOUS COPYRIGHT SANS AUTORISATION EXPRESSE !</b>",
+"longpagewarning" => "<strong>AVERTISSEMENT : cette page a une longueur de $1 ko;
+quelques navigateurs gèrent mal les pages approchant ou dépassant 32 ko lors de leur rédaction.
+Peut-être serait-il mieux que vous divisiez la page en sections plus petites.</strong>", // Panoramix
+"readonlywarning" => "<strong>AVERTISSEMENT : cette page a été bloquée pour maintenance,
+vous ne pourrez donc pas sauvegarder vos modifications maintenant. Vous pouvez copier le texte dans un fichier et le sauver pour plus tard.</strong>", // Looxix
+"protectedpagewarning" => "<strong>AVERTISSEMENT : cette page a été bloquée.
+Seuls les utilisateurs ayant le statut d'administrateur peuvent la modifier. Soyez certain que
+vous suivez les [[Project:Page protégée|directives concernant les pages protégées]].</strong>", // Looxix
+
+# History pages
+#
+"revhistory"   => "Versions précédentes",
+"nohistory"    => "Il n'existe pas d'historique pour cette page.",
+"revnotfound"  => "Version introuvable",
+"revnotfoundtext" => "La version précédente de cette page n'a pas pu être retrouvée. Vérifiez l'URL que vous avez utilisée pour accéder à cette page.\n",
+
+"loadhist"     => "Chargement de l'historique de la page",
+"currentrev"   => "Version actuelle",
+"revisionasof" => "Version du $1",
+"cur"    => "actu",
+"next"   => "suiv",
+"last"   => "dern",
+"orig"   => "orig",
+"histlegend" => "Légende : (actu) = différence avec la version actuelle ,
+(dern) = différence avec la version précédente, M = modification mineure",
+
+#  Diffs
+#
+"difference" => "(Différences entre les versions)",
+"loadingrev" => "chargement de l'ancienne version pour comparaison",
+"lineno"  => "Ligne $1:",
+"editcurrent" => "Modifier la version actuelle de cette page",
+
+
+# Search results
+#
+"searchresults" => "Résultat de la recherche",
+"searchresulttext" => "Pour plus d'informations sur la recherche dans {{SITENAME}}, voir [[Project:Recherche|Chercher dans {{SITENAME}}]].",
+"searchquery" => "Pour la requête \"$1\"",
+"badquery"  => "Requête mal formulée",
+"badquerytext" => "Nous n'avons pas pu traiter votre requête.
+Vous avez probablement recherché un mot d'une longueur inférieure
+à trois lettres, ce qui n'est pas encore possible. Vous avez
+aussi pu faire une erreur de syntaxe, telle que \"poisson et
+et écailles\".
+Veuillez essayer une autre requête.",
+"matchtotals" => "La requête \"$1\" correspond à $2 titre(s)
+d'article et au texte de $3 article(s).",
+"nogomatch" => "Aucune page avec ce titre n'existe, essai avec la recherche complète.", // Looxix
+"titlematches" => "Correspondances dans les titres",
+"notitlematches" => "Aucun titre d'article ne contient le(s) mot(s) demandé(s)",
+"textmatches" => "Correspondances dans les textes",
+"notextmatches" => "Aucun texte d'article ne contient le(s) mot(s) demandé(s)",
+"prevn"   => "$1 précédents",
+"nextn"   => "$1 suivants",
+"viewprevnext" => "Voir ($1) ($2) ($3).",
+"showingresults" => "Affichage de <b>$1</b> résultats à partir du #<b>$2</b>.",
+"showingresultsnum" => "Affichage de <b>$3</b> résultats à partir du #<b>$2</b>.", // Looxix
+"nonefound"  => "<strong>Note</strong>: l'absence de résultat est souvent due à l'emploi de termes de recherche trop courants, comme \"à\" ou \"de\",
+qui ne sont pas indexés, ou à l'emploi de plusieurs termes de recherche (seules les pages
+contenant tous les termes apparaissent dans les résultats).",
+"powersearch" => "Recherche",
+"powersearchtext" => "
+Rechercher dans les espaces :<br />
+$1<br />
+$2 Inclure les page de redirections   Rechercher $3 $9",
+"blanknamespace" => "(Principal)",     // FIXME FvdP: trad de "(Main)"
+
+# Preferences page
+#
+"preferences"       => "Préférences",
+"prefsnologin"      => "Non connecté",
+"prefsnologintext"  => "Vous devez être [[Special:Userlogin|connecté]]
+pour modifier vos préférences d'utilisateur.",
+"prefslogintext" => "Je suis connecté(e) en tant que $1 avec le numéro d'utilisateur $2.
+
+Voir [[Wikipédia:Aide pour les préférences]] pour les explications concernant les options.", // Looxix
+"prefsreset"        => "Les préférences ont été rétablies à partir de la version enregistrée.",
+"qbsettings"        => "Personnalisation de la barre outils",
+"changepassword"    => "Modification du mot de passe",
+"skin"              => "Apparence",
+"math"                 => "Rendu des maths",   // Looxix "Rendering math",
+"dateformat"           => "Format de date",    // Looxix "Date format",
+"math_failure"         => "Erreur math",       // Looxix "Failure toparse",
+"math_unknown_error"   => "erreur indéterminée",   // FvdP+Looxix "unknown error",
+"math_unknown_function"        => "fonction inconnue", // Looxix "unknown function ",
+"math_lexing_error"    => "erreur lexicale",   // Looxxi "lexing error",
+"math_syntax_error"    => "erreur de syntaxe", // Looxix "syntax error",
+"saveprefs"         => "Enregistrer les préférences",
+"resetprefs"        => "Rétablir les préférences",
+"oldpassword"       => "Ancien mot de passe",
+"newpassword"       => "Nouveau mot de passe",
+"retypenew"         => "Confirmer le nouveau mot de passe",
+"textboxsize"       => "Taille de la fenêtre d'édition",
+"rows"              => "Rangées",
+"columns"           => "Colonnes",
+"searchresultshead" => "Affichage des résultats de recherche",
+"resultsperpage"    => "Nombre de réponses par page",
+"contextlines"      => "Nombre de lignes par réponse",
+"contextchars"      => "Nombre de caractères de contexte par ligne",
+"stubthreshold"     => "Taille minimale des articles courts",
+"recentchangescount" => "Nombre de titres dans les modifications récentes",
+"savedprefs"        => "Les préférences ont été sauvegardées.",
+"timezonetext"      => "Si vous ne précisez pas de décalage horaire, c'est l'heure de l'Europe de l'ouest qui sera utilisée.",
+"localtime"         => "Heure locale",
+"timezoneoffset"    => "Décalage horaire",
+"servertime"       => "Heure du serveur", //Looxix (Server time is now)
+"guesstimezone"     => "Utiliser la valeur du navigateur", //Looxix (Fill in from browser)
+"emailflag"         => "Ne pas recevoir de courrier électronique<br /> des autres utilisateurs",
+"defaultns"         => "Par défaut, rechercher dans ces espaces :", //Looxix (Search in these namespaces by default)
+
+# Recent changes
+#
+"changes"      => "modifications",
+"recentchanges" => "Modifications récentes",
+"recentchangestext" => "Suivez sur cette page les dernières modifications de Wikipédia.
+[[Wikipédia:Bienvenue|Bienvenue]] aux nouveaux participants !
+Jetez un coup d'\x{0153}il sur ces pages : [[Wikipédia:FAQ|foire aux questions]],
+[[Wikipédia:Recommandations et règles à suivre|recommandations et règles à suivre]]
+(notamment [[Wikipédia:Règles de nommage|conventions de nommage]],
+[[Wikipédia:La neutralité de point de vue|la neutralité de point de vue]]),
+et [[Wikipédia:Les faux-pas les plus courants|les faux-pas les plus courants]].
+
+Si vous voulez que Wikipédia connaisse le succès, merci de ne pas y inclure pas de matériaux protégés par des [[Wikipédia:Copyright|copyrights]]. La responsabilité juridique pourrait en effet compromettre le projet. ",
+"rcloaderr"  => "Chargement des dernières modifications",
+"rcnote"  => "Voici les <strong>$1</strong> dernières modifications effectuées au cours des <strong>$2</strong> derniers jours.",
+"rcnotefrom"   => "Voici les modifications effectuées depuis le <strong>$2</strong> (<b>$1</b> au maximum).",
+"rclistfrom"   => "Afficher les nouvelles modifications depuis le $1.",
+# "rclinks"  => "Afficher les $1 dernières modifications effectuées au cours des $2 dernières heures / $3 derniers jours",
+# "rclinks"  => "Afficher les $1 dernières modifications effectuées au cours des $2 derniers jours.",
+"rclinks"      => "Afficher les $1 dernières modifications effectuées au cours des $2 derniers jours; $3 modifications mineures.",   // Looxix
+"rchide"  => "in $4 form; $1 modifications mineures; $2 espaces secondaires; $3 modifications multiples.", // FIXME
+"diff"            => "diff",
+"hist"            => "hist",
+"hide"            => "cacher",
+"show"            => "montrer",
+"tableform"       => "table",
+"listform"        => "liste",
+"nchanges"        => "$1 modification(s)",
+"minoreditletter" => "M",
+"newpageletter"   => "N",
+
+# Upload
+#
+"upload"       => "Copier sur le serveur",
+"uploadbtn"    => "Copier un fichier",
+"uploadlink"   => "Copier des images",
+"reupload"     => "Copier à nouveau",
+"reuploaddesc" => "Retour au formulaire.",
+
+"uploadnologin" => "Non connecté(e)",
+"uploadnologintext" => "Vous devez être [[Special:Userlogin|connecté]]
+pour copier des fichiers sur le serveur.",
+"uploaderror"  => "Erreur",
+"uploadtext"   => "'''STOP !''' Avant de copier votre fichier sur le serveur,
+prenez connaissance des [[Project:règles d'utilisation des images|règles d'utilisation des images]] de Wikipédia et assurez-vous que vous les respectez.<br />N'oubliez pas de remplir la [[Project:Page de description d'une image|page de description de l'image]] quand celle-ci sera sur le serveur.
+
+Pour voir les images déjà placées sur le serveur ou pour effectuer une recherche parmi celles-ci,
+allez à la [[Special:Imagelist|liste des images]].
+Les uploads et les suppressions sont listés dans le [[Project:Journal_des_uploads|journal des uploads]].
+
+Utilisez le formulaire ci-dessous pour copier sur le serveur de nouvelles images destinées à illustrer vos articles.
+Sur la plupart des navigateurs, vous verrez un bouton \"Browse...\" qui ouvre la fenêtre de dialogue standard de votre système d'exploitation pour l'ouverture des fichiers.
+Sélectionnez un fichier, son nom apparaîtra dans le champ situé à côté du bouton.
+Vous devez également confirmer, en cochant la case prévue à cet effet, que la copie de ce fichier ne viole aucun copyright.
+Cliquez sur le bouton \"Envoyer\" pour terminer.
+Si votre connexion est lente, l'opération peut prendre un certain temps.
+
+Les formats recommandés sont JPEG pour les photos, PNG
+pour les dessins et les autres images, et OGG pour les fichiers sonores.
+Donnez à vos fichiers des noms descriptifs clairs, afin d'éviter toute confusion.
+Pour incorporer l'image dans un article, placez dans celui-ci un lien rédigé comme suit:
+'''<nowiki>[[image:nom_du_fichier.jpg]]</nowiki>''' ou
+'''<nowiki>[[image:nom_du_fichier.png|autre texte]]</nowiki>''' ou
+'''<nowiki>[[media:nom_du_fichier.ogg]]</nowiki>''' pour les sons.
+
+N'oubliez pas que, comme toutes les pages de Wikipédia, les fichiers que vous copiez peuvent être modifiés ou supprimés par les autres utilisateurs s'ils estiment que cela est dans l'intérêt de l'encyclopédie. Sachez aussi que votre accès au serveur peut être bloqué si vous faites un mauvais usage du système.",
+"uploadlog"  => "log d'upload",                // FIXME
+"uploadlogpage" => "Log_d'upload",     // FIXME
+"uploadlogpagetext" => "Voici la liste des derniers fichiers copiés sur le serveur.
+L'heure indiquée est celle du serveur (UTC).
+<ul>
+</ul>
+",
+"filename"  => "Nom",
+"filedesc"  => "Description",
+"copyrightpage" => "Wikipédia:Copyright",
+"copyrightpagename" => "licence Wikipédia",
+"uploadedfiles" => "Fichiers copiés",
+"ignorewarning" => "Ignorer l'avertissement et copier le fichier quand même.",
+"minlength"  => "Les noms des images doivent comporter au moins trois lettres.",
+"badfilename" => "L'image a été renommée \"$1\".",
+"badfiletype" => "\".$1\" n'est pas un format recommandé pour les fichiers images.",
+"largefile"  => "La taille maximale conseillée pour les images est de 100Ko.",
+"successfulupload" => "Copie réussie",
+"fileuploaded" => "Le fichier \"$1\" a été copié sur le serveur.
+Suivez ce lien: ($2) pour accéder à la page de description, et donner des informations sur le fichier, par exemple son origine, sa date de création, son auteur, ou tout autre renseignement en votre possession.",
+"uploadwarning" => "Attention !",
+"savefile"  => "Sauvegarder le fichier",
+"uploadedimage" => " \"[[$1]]\" copié sur le serveur",
+
+# Image list
+#
+"imagelist"  => "Liste des images",
+"imagelisttext" => "Voici une liste de $1 images classées $2.",
+"getimagelist" => "Récupération de la liste des images",
+"ilsubmit"  => "Chercher",
+"showlast"  => "Afficher les $1 dernières images classées $2.",
+"byname"  => "par nom",
+"bydate"  => "par date",
+"bysize"  => "par taille",
+"imgdelete"  => "suppr",
+"imgdesc"  => "descr",
+"imglegend"  => "Légende: (descr) = afficher/modifier la description de l'image.",
+"imghistory" => "Historique de l'image",
+"revertimg"  => "rétab",
+"deleteimg"  => "suppr",
+"deleteimgcompletely"  => "suppr",
+"imghistlegend" => "Légende: (actu) = ceci est l'image actuelle, (suppr) = supprimer
+cette ancienne version, (rétab) = rétablir cette ancienne version.
+<br /><i>Cliquez sur la date pour voir l'image copiée à cette date</i>.",
+"imagelinks" => "Liens vers l'image",
+"linkstoimage" => "Les pages ci-dessous comportent un lien vers cette image:",
+"nolinkstoimage" => "Aucune page ne comporte de lien vers cette image.",
+
+# Statistics
+
+"statistics" => "Statistiques",
+"sitestats"  => "Statistiques du site",
+"userstats"  => "Statistiques utilisateur",
+"sitestatstext" => "La base de données contient actuellement <b>$1</b> pages.
+
+Ce chiffre inclut les pages \"discussion\", les pages relatives à Wikipédia, les pages minimales (\"bouchons\"),  les pages de redirection, ainsi que d'autres pages qui ne peuvent sans doute pas être considérées comme des articles.
+Si l'on exclut ces pages, il reste <b>$2</b> pages qui sont probablement de véritables articles.<p>
+<b>$3</b> pages ont été consultées et <b>$4</b> pages modifiées
+
+depuis la mise à jour du logiciel (31 octobre 2002).
+Cela représente une moyenne de <b>$5</b> modifications par page et de <b>$6</b> consultations pour une modification.",
+"userstatstext" => "Il y a <b>$1</b> utilisateurs enregistrés.
+Parmi ceux-ci, <b>$2</b> ont le statut d'administrateur (voir $3).",
+
+
+# Maintenance Page
+#
+"maintenance"          => "Page de maintenance",
+"maintnancepagetext"   => "Cette page inclut plusieurs utilitaires pour la maintenance quotidienne. Certains de ces outils ont tendance à charger la base de données; ne rechargez pas la page a chaque modification.",
+"maintenancebacklink"  => "Retour à la page de maintenance",
+"disambiguations"      => "Pages d'homonymie",
+"disambiguationspage"  => "Wikipédia:Liens_aux_pages_d'homonymie",
+"disambiguationstext"  => "Les articles suivants sont liés à une <i>page d'homonymie</i>. Or, ils devraient être liés au sujet.<br />Une page est considérée comme page d'homonymie si elle est liée à partir de $1.<br />Les liens à partir d'autres <i>espaces</i> ne sont pas pris en compte.",
+"doubleredirects"      => "Double redirection",
+"doubleredirectstext"  => "<b>Attention:</b> cette liste peut contenir des \"faux positifs\". Dans ce cas, c'est probablement la page du premier #REDIRECT contient aussi du texte.<br />Chaque ligne contient les liens à la 1re et 2e page de redirection, ainsi que la première ligne de cette dernière, qui donne normalement la \"vraie\" destination. Le premier #REDIRECT devrait lier vers cette destination.",
+"brokenredirects"      => "Redirections cassées",
+"brokenredirectstext"  => "Ces redirections mènent a une page qui n'existe pas.",
+"selflinks"            => "Page avec un lien circulaire",
+"selflinkstext"                => "Les pages suivantes contiennent un lien vers elles-mêmes, ce qui n'est pas permis.",
+"mispeelings"           => "Pages avec fautes d'orthographe",
+"mispeelingstext"               => "Les pages suivantes contiennent une faute d'orthographe courante (la liste de celles-ci est sur $1). L'orthographe correcte est peut-être (ceci).",
+"mispeelingspage"       => "Liste de fautes d'orthographe courantes",
+"missinglanguagelinks"  => "Liens inter-langues manquants",
+"missinglanguagelinksbutton"    => "Je n'ai pas trouvé de lien/langue pour cette page",
+"missinglanguagelinkstext"      => "Ces articles ne lient pas à leur 'contrepartie' in $1. Les redirections et les liens ne sont pas affichés.",
+
+
+# Miscellaneous special pages
+#
+"orphans"       => "Pages orphelines",
+"lonelypages"   => "Pages orphelines",
+"unusedimages"  => "Images orphelines",
+"popularpages"  => "Pages les plus consultées",
+"nviews"        => "$1 consultations",
+"wantedpages"   => "Pages les plus demandées",
+"nlinks"        => "$1 références",
+"allpages"      => "Toutes les pages",
+"randompage"    => "Une page au hasard",
+"shortpages"    => "Articles courts",
+"longpages"     => "Articles longs",
+"listusers"     => "Liste des participants",
+"specialpages"  => "Pages spéciales",
+"spheading"     => "Pages spéciales",
+"protectpage"   => "Protéger la page",
+"recentchangeslinked" => "Suivi des liens",
+"rclsub"        => "(des pages liées à \"$1\")",
+"debug"         => "Déboguer",
+"newpages"      => "Nouvelles pages",
+"ancientpages" => "Articles les plus anciens", // Looxix
+// "intl"                  => "Liens inter-langues",
+"movethispage"  => "Déplacer la page",
+"unusedimagestext" => "<p>N'oubliez pas que d'autres sites, comme certains Wikipédias non francophones, peuvent contenir un lien direct vers cette image, et que celle-ci peut être placée dans cette liste alors qu'elle est en réalité utilisée.",
+"booksources"   => "Ouvrages de référence",
+"booksourcetext" => "Voici une liste de liens vers d'autres sites qui vendent des livres neufs et d'occasion et sur lesquels vous trouverez peut-être des informations sur les ouvrages que vous cherchez. Wikipédia n'étant liée à aucune de ces sociétés, elle n'a aucunement l'intention d'en faire les objets d'une préférence particulière.",
+"alphaindexline" => "$1 à $2",
+
+# Email this user
+#
+"mailnologin" => "Pas d'adresse",
+"mailnologintext" => "Vous devez être [[Special:Userlogin|connecté]]
+et avoir indiqué une adresse électronique valide dans vos [[Special:Preferences|préférences]]
+pour pouvoir envoyer un message à un autre utilisateur.",
+"emailuser"  => "Envoyer un message à cet utilisateur",
+"emailpage"  => "Email user",
+"emailpagetext" => "Si cet utilisateur a indiqué une adresse électronique valide dans ses préférences, le formulaire ci-dessous lui enverra un message.
+L'adresse électronique que vous avez indiquée dans vos préférences apparaîtra dans le champ \"Expéditeur\" de votre message, afin que le destinataire puisse vous répondre.",
+"noemailtitle" => "Pas d'adresse électronique",
+"noemailtext" => "Cet utilisateur n'a pas spécifié d'adresse électronique valide ou a choisi de ne pas recevoir de courrier électronique des autres utilisateurs.",
+
+"emailfrom"  => "Expéditeur",
+"emailto"  => "Destinataire",
+"emailsubject" => "Objet",
+"emailmessage" => "Message",
+"emailsend"  => "Envoyer",
+"emailsent"  => "Message envoyé",
+"emailsenttext" => "Votre message a été envoyé.",
+
+# Watchlist
+#
+"watchlist"    => "Liste de suivi",
+"watchlistsub" => "(pour l'utilisateur \"$1\")",
+"nowatchlist"  => "Votre liste de suivi ne contient aucun article.",
+"watchnologin" => "Non connecté",
+"watchnologintext" => "Vous devez être [[Special:Userlogin|connecté]]
+pour modifier votre liste.",
+"addedwatch"   => "Ajouté à la liste",
+"addedwatchtext" => "La page \"$1\" a été ajoutée à votre <a href=\"" .
+               "{{localurle:Special:Watchlist}}\">liste de suivi</a>.
+Les prochaines modifications de cette page et de la page discussion associée seront répertoriées ici, et la page apparaîtra <b>en gras</b> dans la <a href=\"" .
+               "{{localurle:Special:Recentchanges}}\">liste des modifications récentes</a> pour être repérée plus facilement.</p>
+
+<p>Pour supprimer cette page de votre liste de suivi, cliquez sur \"Ne plus suivre\" dans le cadre de navigation.",
+"removedwatch" => "Supprimée de la liste de suivi",
+"removedwatchtext" => "La page \"$1\" a été supprimée de votre liste de suivi.",
+"watchthispage"        => "Suivre cette page",
+"unwatchthispage" => "Ne plus suivre",
+"notanarticle" => "Aucun article",
+"watchnochange" => "Aucune des pages que vous suivez n'a été modifiée pendant la période affichée.", // Looxix
+"watchdetails" => "Vous suivez $1 pages, sans compter les pages de discussion.  [$4 Afficher et modifier la liste complète].", // Looxix
+"watchmethod-recent" => "vérification des modifications récentes des pages suivies", // Looxix
+"watchmethod-list" => "vérification des pages suivies pour des modifications récentes", // Looxix
+
+"removechecked" => "Retirer de la liste de suivi les articles sélectionnés", // Looxix
+"watchlistcontains" => "Votre liste de suivi contient $1 pages", // Looxix
+"watcheditlist" => "Ceci est votre liste de suivi par ordre alphabétique. Sélectionnez les pages que vous souhaitez retirer de la liste et cliquez le bouton \"retirer de la liste de suivi\" en bas de l'écran.", // Looxix
+"removingchecked" => "Les articles sélectionnés sont retirés de votre liste de suivi...", // Looxix
+"couldntremove" => "Impossible de retirer l'article '$1'...", // Looxix "Couldn't remove item '$1'...",
+"iteminvalidname" => "Problème avec l'article '$1': les nom est invalide...", // Looxix
+"wlnote" => "Ci-dessous se trouve les $1 dernières modifications depuis les <b>$2</b> dernières heures.", // Looxix
+
+
+# Delete/protect/revert
+#
+"deletepage"   => "Supprimer une page",
+"confirm"      => "Confirmer",
+"excontent"    => "contenant '$1'",
+"exbeforeblank" => "le contenu avant effacement était :'$1'",
+"exblank"      => "page vide",
+"confirmdelete" => "Confirmer la suppression",
+"deletesub"    => "(Suppression de \"$1\")",
+"historywarning" => "Attention: La page que vous êtes sur le point de supprimer à un historique: ",
+"confirmdeletetext" => "Vous êtes sur le point de supprimer définitivement de la base de données une page
+ou une image, ainsi que toutes ses versions antérieures.
+Veuillez confirmer que c'est bien là ce que vous voulez faire, que vous en comprenez les conséquences et que vous faites cela en accord avec les [[Wikipédia:Recommandations Et Règles à  Suivre|recommandations et règles à suivre]].",
+"actioncomplete" => "Suppression effectuée",
+"deletedtext"  => "\"$1\" a été supprimé.
+Voir $2 pour une liste des suppressions récentes.",
+"deletedarticle" => "effacement de \"$1\"",
+"dellogpage"   => "Trace des effacements",
+"dellogpagetext" => "Voici la liste des suppressions récentes.
+L'heure indiquée est celle du serveur (UTC).
+<ul>
+</ul>
+",
+"deletionlog"  => "trace des effacements",
+"reverted"     => "Rétablissement de la version précédente",
+"deletecomment" => "Motif de la suppression",
+"imagereverted" => "La version précédente a été rétablie.",
+"rollback"     => "révoquer modifications",
+"rollbacklink" => "révoquer",
+"rollbackfailed" => "La révocation a échoué",
+"cantrollback" => "Impossible de révoquer: dernier auteur est le seul à avoir modifié cet article",
+"alreadyrolled"        => "Impossible de révoquer la dernière modification de [[$1]]
+par  [[User:$2|$2]] ([[User talk:$2|Talk]]); quelqu'un d'autre à déjà modifer ou révoquer l'article.
+
+La dernière modificaion était de [[User:$3|$3]] ([[User talk:$3|Talk]]). ", //Looxix
+
+#   only shown if there is an edit comment
+"editcomment" => "Le résumé de la modification était: \"<i>$1</i>\".", //Looxix
+"revertpage"   => "restitution de la dernière modification de $1",
+
+# Undelete
+#
+"undelete"     => "Restaurer la page effacée",
+"undeletepage" => "Voir et restaurer la page effacée",
+"undeletepagetext" => "Ces pages ont été effacées et se trouvent dans la corbeille, elles sont toujours dans la base de donnée et peuvent être restaurées.
+La corbeille peut être effacée périodiquement.",
+
+"undeletearticle" => "Restaurer les articles effacés",
+"undeleterevisions" => "$1 révisions archivées", // Looxix "$1 revisions archived",
+"undeletehistory" => "Si vous restaurez la page, toutes les révisions seront restaurées dans l'historique.
+Si une nouvelle page avec le même nom a été crée depuis la suppression,
+les révisions restaurées apparaîtront dans l'historique antérieur et la version courante ne sera pas automatiquement remplacée.", // Looxix
+"undeleterevision" => "Version effacée ($1)", // Looxix "Deleted revision as of $1",
+"undeletebtn"  => "Restaurer !", // Looxix "Restore!",
+"undeletedarticle" => "restauré \"$1\"",      // FvdP "restored \"$1\""
+"undeletedtext"   => "L'article [[$1]] a été restauré avec succès.
+Voir [[Wikipedia:Trace des effacements]] pour la liste des suppressions et des restaurations récentes.", // Looxix
+# Contributions
+#
+"contributions"        => "Contributions",
+"mycontris"    => "Mes contributions",
+"contribsub"   => "Pour $1",
+"nocontribs"   => "Aucune modification correspondant à ces critères n'a été trouvée.",
+"ucnote"       => "Voici les <b>$1</b> dernières modifications effectuées par cet utilisateur au cours des <b>$2</b> derniers jours.",
+"uclinks"      => "Afficher les $1 dernières modifications; afficher les $2 derniers jours.",
+"uctop"                => " (dernière)",      // FvdP " (top)"
+
+# What links here
+#
+"whatlinkshere" => "Pages liées",
+"notargettitle" => "Pas de cible",
+"notargettext" => "Indiquez une page cible ou un utilisateur cible.",
+"linklistsub"  => "(Liste de liens)",
+"linkshere"    => "Les pages ci-dessous contiennent un lien vers celle-ci:",
+"nolinkshere"  => "Aucune page ne contient de lien vers celle-ci.",
+"isredirect"   => "page de redirection",
+
+# Block/unblock IP
+#
+"blockip"      => "Bloquer une adresse IP",
+"blockiptext"  => "Utilisez le formulaire ci-dessous pour bloquer l'accès en écriture à partir d'une adresse IP donnée.
+Une telle mesure ne doit être prise que pour empêcher le vandalisme et en accord avec [[Wikipédia:Recommandations et règles à suivre|recommandations et règles à suivre]].
+Donnez ci-dessous une raison précise (par exemple en indiquant les pages qui ont été vandalisées).",
+"ipaddress"    => "Adresse IP",
+"ipbreason"    => "Motif",
+"ipbsubmit"    => "Bloquer cette adresse",
+"badipaddress" => "L'adresse IP n'est pas correcte.",
+"blockipsuccesssub" => "Blocage réussi",
+"blockipsuccesstext" => "L'adresse IP \"$1\" a été bloquée.
+<br />Vous pouvez consulter sur cette [[Special:Ipblocklist|page]] la liste des adresses IP bloquées.",
+"unblockip"    => "Débloquer une adresse IP",
+"unblockiptext" => "Utilisez le formulaire ci-dessous pour rétablir l'accès en écriture
+à partir d'une adresse IP précédemment bloquée.",
+"ipusubmit"    => "Débloquer cette adresse",
+"ipusuccess"   => "Adresse IP \"$1\" débloquée",
+"ipblocklist"  => "Liste des adresses IP bloquées",
+"blocklistline" => "$1, $2 a bloqué $3 ($4)",
+"blocklink"    => "bloquer",
+"unblocklink"  => "débloquer",
+"contribslink" => "contribs",
+"autoblocker"  => "Autobloqué parce que vous partagez un adresse IP avec \"$1\". Raison : \"$2\".", // Looxix
+
+
+# Developer tools
+#
+"lockdb"  => "Verrouiller la base",
+"unlockdb"  => "Déverrouiller la base",
+"lockdbtext" => "Le verrouillage de la base de données empêchera tous les utilisateurs de modifier des pages, de sauvegarder leurs préférences, de modifier leur liste de suivi et d'effectuer toutes les autres opérations nécessitant des modifications dans la base de données.
+Veuillez confirmer que c'est bien là ce que vous voulez faire et que vous débloquerez la base dès que votre opération de maintenance sera terminée.",
+"unlockdbtext" => "Le déverrouillage de la base de données permettra à nouveau à tous les utilisateurs de modifier des pages, de mettre à jour leurs préférences et leur liste de suivi, ainsi que d'effectuer les autres opérations nécessitant des modifications dans la base de données.
+Veuillez confirmer que c'est bien là ce que vous voulez faire.",
+"lockconfirm" => "Oui, je confirme que je souhaite verrouiller la base de données.",
+"unlockconfirm" => "Oui, je confirme que je souhaite déverrouiller la base de données.",
+
+"lockbtn"  => "Verrouiller la base",
+"unlockbtn"  => "Déverrouiller la base",
+"locknoconfirm" => "Vous n'avez pas coché la case de confirmation.",
+"lockdbsuccesssub" => "Verrouillage de la base réussi.",
+"unlockdbsuccesssub" => "Base déverrouillée.",
+"lockdbsuccesstext" => "La base de données de Wikipédia est verrouillée.
+
+<br />N'oubliez pas de la déverrouiller lorsque vous aurez terminé votre opération de maintenance.",
+"unlockdbsuccesstext" => "La base de données de Wikipédia est déverrouillée.",
+
+# Move page
+#
+"movepage"  => "Déplacer un article",
+"movepagetext" => "Utilisez le formulaire ci-dessous pour renommer un article, en déplaçant toutes ses versions antérieures vers le nouveau nom.
+Le titre précédent deviendra une page de redirection vers le nouveau titre.
+Les liens vers l'ancien titre ne seront pas modifiés et la page discussion, si elle existe, ne sera pas déplacée.<br />
+<b>ATTENTION !</b>
+Il peut s'agir d'un changement radical et inattendu pour un article souvent consulté;
+assurez-vous que vous en comprenez bien les conséquences avant de procéder.",
+"movepagetalktext" => "La page de discussion associé, si présente, sera automatiquement déplacée avec '''sauf si:'''
+*Vous déplacez une page vers un autre espace,
+*Une page de discussion existe déjà avec le nouveau nom, ou
+*Vous avez désélectionné le bouton ci-dessous.
+
+Dans ce cas, vous devrez déplacer ou fusionner la page manuellement si vous le désirez.", // Looxix
+
+"movearticle"  => "Déplacer l'article",
+"movenologin"  => "Non connecté",
+"movenologintext" => "Pour pouvoir déplacer un article, vous devez être [[Special:Userlogin|connecté]]
+en tant qu'utilisateur enregistré.",
+"newtitle"     => "Nouveau titre",
+"movepagebtn"  => "Déplacer l'article",
+"pagemovedsub" => "Déplacement réussi",
+"pagemovedtext" => "L'article \"[[$1]]\" a été déplacé vers \"[[$2]]\".",
+"articleexists" => "Il existe déjà un article portant ce titre, ou le titre que vous avez choisi n'est pas valide.
+Veuillez en choisir un autre.",
+"talkexists"   => "La page elle-même a été déplacée avec succès, mais
+la page de discussion n'a pas pu être déplacée car il en existait déjà une
+sous le nouveau nom. S'il vous plait, fusionnez les manuellement.", // Looxix
+
+"movedto"  => "déplacé vers",
+"movetalk"  => "Déplacer aussi la page \"discussion\", s'il y a lieu.",
+"talkpagemoved" => "La page discussion correspondante a également été déplacée.",
+"talkpagenotmoved" => "La page discussion correspondante n'a <strong>pas</strong> été déplacée.",
+
+# Math
+
+'mw_math_png' => "Totjorn produsir una image PNG",
+'mw_math_simple' => "HTML si plan simpla, senon PNG",
+'mw_math_html' => "HTML si possibla, senon PNG",
+'mw_math_source' => "Laissar lo còdi TeX del origina",
+'mw_math_modern' => "Per los navigaire modèrn",
+'mw_math_mathml' => 'MathML',
+
+);
+
+class LanguageOc extends LanguageUtf8{
+
+       function getBookstoreList () {
+               global $wgBookstoreListOc ;
+               return $wgBookstoreListOc ;
+       }
+
+       function getNamespaces() {
+               global $wgNamespaceNamesOc;
+               return $wgNamespaceNamesOc;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsOc;
+               return $wgQuickbarSettingsOc;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesOc;
+               return $wgSkinNamesOc;
+       }
+
+       function date( $ts, $adj = false ) {
+               if ( $adj ) { $ts = $this->userAdjust( $ts ); }
+
+               $d = (0 + substr( $ts, 6, 2 )) . " " .
+                 $this->getMonthAbbreviation( substr( $ts, 4, 2 ) ) .
+                 " " . substr( $ts, 0, 4 );
+               return $d;
+       }
+
+       function timeanddate( $ts, $adj = false ) {
+               return $this->date( $ts, $adj ) . " à " . $this->time( $ts, $adj );
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesOc, $wgAllMessagesEn;
+               $m = $wgAllMessagesOc[$key];
+
+               if ( "" == $m ) { return $wgAllMessagesEn[$key]; }
+               else return $m;
+
+       }
+}
+
+?>
diff --git a/languages/LanguageOr.php b/languages/LanguageOr.php
new file mode 100644 (file)
index 0000000..b19db6a
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+/** Oriya (ଓଡ଼ିଆ)
+  *
+  * @package MediaWiki
+  * @subpackage Language
+  *
+  * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
+  */
+
+require_once( 'LanguageUtf8.php' );
+
+class LanguageOr extends LanguageUtf8 {
+       var $digitTransTable = array(
+               '0' => '୦',
+               '1' => '୧',
+               '2' => '୨',
+               '3' => '୩',
+               '4' => '୪',
+               '5' => '୫',
+               '6' => '୬',
+               '7' => '୭',
+               '8' => '୮',
+               '9' => '୯',
+       );
+
+       function formatNum( $number ) {
+               global $wgTranslateNumerals;
+               if( $wgTranslateNumerals ) {
+                       return strtr( $number, $this->digitTransTable );
+               } else {
+                       return $number;
+               }
+       }
+}
+
+?>
diff --git a/languages/LanguageOs.php b/languages/LanguageOs.php
new file mode 100644 (file)
index 0000000..1c416cf
--- /dev/null
@@ -0,0 +1,268 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+# Ossetic stub localization; default to Russian instead of English.
+# See language.txt
+
+require_once( "LanguageRu.php" );
+
+if($wgMetaNamespace === FALSE)
+       $wgMetaNamespace = str_replace( ' ', '_', $wgSitename );
+
+/* private */ $wgNamespaceNamesOs = array(
+       NS_MEDIA            => 'Media', //чтоб не писать "Мультимедия"
+       NS_SPECIAL          => 'Сæрмагонд',
+       NS_MAIN             => '',
+       NS_TALK             => 'Дискусси',
+       NS_USER             => 'Архайæг',
+       NS_USER_TALK        => 'Архайæджы_дискусси',
+       NS_PROJECT          => $wgMetaNamespace,
+       NS_PROJECT_TALK     => 'Дискусси_'+$wgMetaNamespace,
+       NS_IMAGE            => 'Ныв',
+       NS_IMAGE_TALK       => 'Нывы_тыххæй_дискусси',
+       NS_MEDIAWIKI        => 'MediaWiki',
+       NS_MEDIAWIKI_TALK   => 'Дискусси_MediaWiki',
+       NS_TEMPLATE         => 'Шаблон',
+       NS_TEMPLATE_TALK    => 'Шаблоны_тыххæй_дискусси',
+       NS_HELP             => 'Æххуыс',
+       NS_HELP_TALK        => 'Æххуысы_тыххæй_дискусси',
+       NS_CATEGORY         => 'Категори',
+       NS_CATEGORY_TALK    => 'Категорийы_тыххæй_дискусси',
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgQuickbarSettingsOs = array(
+       'Ма равдис', 'Галиуырдыгæй', 'Рахизырдыгæй', 'Рахизырдыгæй ленккæнгæ'
+ );
+
+/* private */ $wgSkinNamesOs = array(
+       'standard' => 'Стандартон',
+       'nostalgia' => 'Æнкъард',
+       'cologneblue' => 'Кёльны æрхæндæг',
+       'davinci' => 'Да Винчи',
+       'mono' => 'Моно',
+       'monobook' => 'Моно-чиныг',
+       'myskin' => 'Мæхи',
+       'chick' => 'Карк'
+ ) + $wgSkinNamesEn;
+
+/* private */ $wgAllMessagesOs = array(
+'titlematches' => 'Статьяты сæргæндты æмцаутæ',
+'toc' => 'Сæргæндтæ',
+'addedwatch' => "Дæ цæст кæмæ дарыс, уыцы статьятæм бафтыд.",
+'allarticles' => "Æппæт статьятæ",
+'allmessages' => "Æппæт техникон фыстытæ",
+'allpages' => "Æппæт фæрстæ",
+'allpagesnext' => "дарддæр",
+'allpagesprev' => "фæстæмæ",
+'alphaindexline' => "$1 (уыдоны ’хсæн цы статьятæ ис, фен) $2",
+'ancientpages' => "Зæронддæр фæрстæ",
+'and' => "æмæ",
+'articlepage' => "Фен статья",
+'blanknamespace' => "(Сæйраг)",
+'bold_sample' => "Ацы текст бæзджын суыдзæн",
+'bold_tip' => "Бæзджын текст",
+'bydate' => "рæстæгмæ гæсгæ",
+'byname' => "номмæ гæсгæ",
+'bysize' => "асмæ гæсгæ",
+'categories' => "Категоритæ",
+'categoriespagetext' => "Мæнæ ахæм категоритæ ирон Википедийы ис.",
+'category' => "категори",
+'category_header' => "Категори \"$1\"",
+'categoryarticlecount' => "Ацы категорийы мидæг $1 статьяйы ис.",
+'categoryarticlecount1' => "Ацы категорийы мидæг $1 статья ис.",
+'contributions' => "Йæ бавæрд",
+'createaccountmail' => "адрисмæ гæсгæ",
+'currentevents' => "Ног хабæрттæ",
+'currentevents-url' => "Xabar",
+'diff' => "хицæн.",
+'edit' => "Баив æй",
+'editsection' => "баив æй",
+'emailpage' => "Электронон фыстæг йæм барвит",
+'error' => "Рæдыд",
+'errorpagetitle' => "Рæдыд",
+'exblank' => "фарс афтид уыдис",
+'filename' => "Файлы ном",
+'go' => "Статьямæ",
+'headline_sample' => "Ам сæргонды текст уæд",
+'help' => "Æххуыс",
+'hide' => "бамбæхс",
+'hidetoc' => "бамбæхс",
+'hist' => "лог",
+'histlegend' => "Куыд æй æмбарын: (нырыккон) = нырыккон версийæ хъауджыдæрдзинад, (раздæры) = раздæры версийæ хъауджыдæрдзинад, Ч = чысыл ивддзинад.",
+'history_short' => "Истори",
+'ilsubmit' => "Агур",
+'imagelist' => "Нывты номхыгъд",
+'imghistory' => "Нывы ивддзинæдты лог",
+'importnotext' => "Афтид у кæнæ текст дзы нæй",
+'internalerror' => "Мидæг рæдыд",
+'intl' => "Æндæр æвзæгтæм æрвитæнтæ",
+'ipbreason' => "Аххос",
+'largefile' => "Сæдæ килобайтæй стырдæр файлтæ æгæр дынджыр сты.",
+'last' => "раздæры",
+'lastmodified' => "<span style=\"white-space: normal;\">Кæд æмæ ацы статьяйы ссардтай рæдыд, уæд сраст æй кæн: ацы фарсы уæлæ ис æрвитæн «баив æй».
+<br /> Ацы фарс фæстаг хатт ивд æрцыд: $1.</span>",
+'lineno' => "Рæнхъ $1:",
+'linklistsub' => "(Æрвитæнты номхыгъд)",
+'linkstoimage' => "Ацы нывæй чи пайда кæны, ахæм статьятæ:",
+'listform' => "номхыгъд",
+'listusers' => "Архайджыты номхыгъд",
+'localtime' => "Бынатон рæстæг",
+'login' => "Дæхи бавдис системæйæн",
+'loginpagetitle' => "Дæхи бацамон системæйæн",
+'loginsuccess' => "Ныр та Википедийы архайыс $1, зæгъгæ, ахæм номæй.",
+'logout' => "Номсусæг суын",
+'logouttitle' => "Номсусæг суын",
+'lonelypages' => "Сидзæр фæрстæ",
+'longpages' => "Даргъ фæрстæ",
+'mailnologintext' => "Фыстæгтæ æрвитынмæ хъуамæ [[Special:Userlogin|системæйæн дæхи бавдисай]] æмæ дæ бæлвырд электронон посты адрис [[Special:Preferences|ныффыссай]].",
+'mainpage' => "Сæйраг фарс",
+'makesysopname' => "Архайæджы ном:",
+'minoredit' => "Ай чысыл ивддзинад у.",
+'monday' => "Къуырисæр",
+'move' => "Ном баив",
+'movearticle' => "Статьяйы ном баив",
+'movenologin' => "Системæйæн дæхи нæ бавдыстай",
+'mycontris' => "Дæ бавæрд",
+'mypage' => "Дæхи фарс",
+'mytalk' => "Дæумæ цы дзурынц",
+'navigation' => "хъæугæ æрвитæнтæ",
+'nbytes' => "$1 байт(ы)",
+'nchanges' => "$1 ивддзинад(ы)",
+'newarticle' => "(Ног)",
+'newimages' => "Ног нывты галерей",
+'newmessages' => "Райстай $1.",
+'newmessageslink' => "ног фыстæгтæ",
+'newpage' => "Ног фарс",
+'newpageletter' => "Н",
+'newpages' => "Ног фæрстæ",
+'newpassword' => "Новый пароль",
+'newtitle' => "Ног ном",
+'newusersonly' => "(æрмæст ног архайджытæн)",
+'nextn' => "$1 размæ",
+'nlinks' => "$1 æрвитæн(ы)",
+'nowatchlist' => "Иу статьямæ дæр дæ цæст нæ дарыс.",
+'nstab-image' => "Ныв",
+'nstab-mediawiki' => "Фыстаг",
+'nstab-special' => "Сæрмагонд фарс",
+'nstab-template' => "Шаблон",
+'nstab-user' => "Архайæджы фарс",
+'otherlanguages' => "Æндæр æвзæгтыл",
+'others' => "æндæртæ",
+'portal' => "Архайджыты æхсæнад",
+'prevn' => "$1 фæстæмæ",
+'printableversion' => "Мыхурмæ верси",
+'printsubtitle' => "(Æрмæг ист æрцыд мæнæ ацы сайтæй: {{SERVER}})",
+'qbfind' => "Агур",
+'qbspecialpages' => "Сæрмагонд фæрстæ",
+'randompage' => "Æнæбары æвзæрст фарс",
+'rclinks' => "Фæстаг $1 ивддзинæдтæ (афæстаг $2 боны дæргъы чи ’рцыдысты) равдис;
+$3",
+'rcnote' => "Дæлдæр нымад сты афæстаг <strong>$2</strong> боны дæргъы конд <strong>$1</strong> ивддзинад(ы).",
+'recentchanges' => "Фæстаг ивддзинæдтæ",
+'recentchangeslinked' => "Баст ивддзинæдтæ",
+'recentchangestext' => "Ацы фарсыл ирон Википедийы фæстаг ивддзинæдтæ фенæн ис.",
+'revhistory' => "Ивддзинæдты истори",
+'rights' => "Бартæ",
+'saturday' => "Сабат",
+'savearticle' => "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Афтæ!&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;",
+'savefile' => "Бавæр æй",
+'search' => "агур",
+'searchresults' => "Цы ссардæуы",
+'shortpages' => "Цыбыр фæрстæ",
+'showpreview' => "&nbsp;&nbsp;Фен уал æй&nbsp;&nbsp;",
+'showtoc' => "равдис",
+'sitesubtitle' => "Сæрибар энциклопеди",
+'show' => "равдис",
+'showhideminor' => "$1 чысыл ивддзинæдтæ | $2 роботтæ | $3 регистрацигонд архайджыты | $4 дæ цæст кæмæ дарыс, уыдон.<br />",
+'showpreview' => "&nbsp;&nbsp;Фен уал æй&nbsp;&nbsp;",
+'specialpage' => "Сæрмагонд фарс",
+'specialpages' => "Сæрмагонд фæрстæ",
+'spheading' => "Сæрмагонд фæрстæ",
+'subcategories' => "Дæлкатегоритæ",
+'subcategorycount' => "Ацы категорийы мидæг $1 дæлкатегорийы ис.",
+'subcategorycount1' => "Ацы категорийы мидæг $1 дæлкатегори ис.",
+'sunday' => "Хуыцаубон",
+'tableform' => "таблицæ",
+'tagline' => "Сæрибар энциклопеди Википедийы æрмæг.",
+'talk' => "Дискусси",
+'talkpage' => "Ацы фарсы тыххæй ныхас",
+'textmatches' => "Статьяты æмцаутæ",
+'thursday' => "Цыппарæм",
+'timezonelegend' => "Сахаты таг",
+'timezoneoffset' => "Хъауджыдæрдзинад",
+'titlematches' => "Статьяты сæргæндты æмцаутæ",
+'toc' => "Сæргæндтæ",
+'tog-underline' => "Æрвитæнты бын хахх",
+'toolbox' => "мигæнæнтæ",
+'tuesday' => "Дыццæг",
+'uctop' => "(уæле баззад)",
+'userlogin' => "Системæйæн дæхи бавдис",
+'userlogout' => "Номсусæг суын",
+'userpage' => "Ацы архайæджы фарс фен",
+'userstatstext' => "Регистрацигонд æрцыдысты <b>$1</b> архайджыты, уыдонæй <b>$2</b> — админтæ (кæс $3).",
+'wantedpages' => "Хъæугæ фæрстæ",
+'watch' => "Дæ цæст æрдар",
+'watchdetails' => "($1 фæрстæм дæ цæст дарыс, дискусситы фæстæмæ; $3... [$4 Æххæст номхыгъд фен].)",
+'watchlist' => "Дæ цæст кæмæ дарыс, уыцы фæрстæ",
+'watchlistcontains' => "Дæ цæст $1 фæрстæм дарыс.",
+'watchlistsub' => "$1, зæгъгæ, уыцы архайæгæн",
+'watchnologin' => "Системæйæн дæхи нæ бавдыстай",
+'watchnologintext' => "Ацы номхыгъд ивынмæ <a href=\"{{localurle:Специальные:Userlogin}}\">хъуамæ дæхи бавдисай системæйæн</a>.",
+'watchthis' => "Ацы фарсмæ дæ цæст æрдар",
+'watchthispage' => "Ацы фарсмæ дæ цæст æрдар",
+'wednesday' => "Æртыццæг",
+'welcomecreation' => "<h2>Æгас цу, $1!</h2><p>Регистрацигонд æрцыдтæ.",
+'whatlinkshere' => "Цавæр æрвитæнтæ цæуынц ардæм",
+'wlnote' => "Дæлæ афæстаг <b>$2</b> сахаты дæргъы цы $1 ивддзинад(ы) æрцыди, уыдон.",
+'wlshowlast' => "Фæстæг $1 сахаты, $2 боны дæргъы; $3.",
+'youremail' => "Дæ электронон посты адрис",
+'yourlanguage' => "Техникон фыстыты æвзаг",
+'yourname' => "Дæ ном кæнæ фæсномыг",
+'yourrealname' => "Дæ æцæг ном*",
+
+);
+
+class LanguageOs extends LanguageRu {
+       function LanguageOs() {
+               global $wgNamespaceNamesOs, $wgMetaNamespace;
+               LanguageUtf8::LanguageUtf8();
+       }
+
+       function getNamespaces() {
+               global $wgNamespaceNamesOs;
+               return $wgNamespaceNamesOs;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsOs;
+               return $wgQuickbarSettingsOs;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesOs;
+               return $wgSkinNamesOs;
+       }
+
+       function getDateFormats() {
+               global $wgDateFormatsRu;
+               return $wgDateFormatsRu;
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesOs;
+               return isset($wgAllMessagesOs[$key]) ? $wgAllMessagesOs[$key] : parent::getMessage($key);
+       }
+
+       function fallback8bitEncoding() {
+               return "windows-1251";
+       }
+
+       function formatNum( $number ) {
+               global $wgTranslateNumerals;
+               return $wgTranslateNumerals ? strtr($number, '.,', ', ' ) : $number;
+       }
+
+}
+?>
diff --git a/languages/LanguagePa.php b/languages/LanguagePa.php
new file mode 100644 (file)
index 0000000..3a55efe
--- /dev/null
@@ -0,0 +1,477 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+# Punjabi (Gurmukhi)
+# This file is dual-licensed under GFDL and GPL.
+#
+# See: http://bugzilla.wikimedia.org/show_bug.cgi?id=1478
+
+require_once('LanguageUtf8.php');
+
+/* private */ $wgNamespaceNamesPa = array(
+       NS_MEDIA                => 'ਮੀਡੀਆ',
+       NS_SPECIAL              => 'ਖਾਸ',
+       NS_MAIN                 => '',
+       NS_TALK                 => 'ਚਰਚਾ',
+       NS_USER                 => 'ਮੈਂਬਰ',
+       NS_USER_TALK            => 'ਮੈਂਬਰ_ਚਰਚਾ',
+       NS_PROJECT              => $wgMetaNamespace, /* Wikipedia?: ਵਿਕਿਪੀਡਿਆ */
+       NS_PROJECT_TALK         => $wgMetaNamespace . '_ਚਰਚਾ',
+       NS_IMAGE                => 'ਤਸਵੀਰ',
+       NS_IMAGE_TALK           => 'ਤਸਵੀਰ_ਚਰਚਾ',
+       NS_MEDIAWIKI            => 'ਮੀਡੀਆਵਿਕਿ',
+       NS_MEDIAWIKI_TALK       => 'ਮੀਡੀਆਵਿਕਿ_ਚਰਚਾ',
+       NS_TEMPLATE             => 'ਨਮੂਨਾ',
+       NS_TEMPLATE_TALK        => 'ਨਮੂਨਾ_ਚਰਚਾ',
+       NS_HELP                 => 'ਮਦਦ',
+       NS_HELP_TALK            => 'ਮਦਦ_ਚਰਚਾ',
+       NS_CATEGORY             => 'ਸ਼੍ਰੇਣੀ',
+       NS_CATEGORY_TALK        => 'ਸ਼੍ਰੇਣੀ_ਚਰਚਾ'
+);
+
+/* private */ $wgQuickbarSettingsPa = array(
+       'ਕੋਈ ਨਹੀਂ', 'ਸਥਿਰ ਖੱਬੇ', 'ਸਥਿਰ ਸੱਜਾ', 'ਤੈਰਦਾ ਖੱਬੇ'
+);
+
+/* private */ $wgSkinNamesPa = array(
+       'standard'      => 'ਮਿਆਰੀ',
+) + $wgSkinNamesEn;
+
+#-------------------------------------------------------------------
+# Default messages
+#-------------------------------------------------------------------
+
+/* private */ $wgAllMessagesPa = array(
+# Bits of text used by many pages:
+#
+
+# Dates
+'sunday'               => 'ਐਤਵਾਰ',
+'monday'               => 'ਸੋਮਵਾਰ',
+'tuesday'              => 'ਮੰਗਲਵਾਰ',
+'wednesday'            => 'ਬੁਧਵਾਰ',
+'thursday'             => 'ਵੀਰਵਾਰ',
+'friday'               => 'ਸ਼ੁੱਕਰਵਾਰ',
+'saturday'             => 'ਸ਼ਨੀਚਰਵਾਰ',
+'january'              => 'ਜਨਵਰੀ',
+'february'             => 'ਫ਼ਰਵਰੀ',
+'march'                        => 'ਮਾਰਚ',
+'april'                        => 'ਅਪ੍ਰੈਲ',
+'may_long'             => 'ਮਈ',
+'june'                 => 'ਜੂਨ',
+'july'                 => 'ਜੁਲਾਈ',
+'august'               => 'ਅਗਸਤ',
+'september'            => 'ਸਤੰਬਰ',
+'october'              => 'ਅਕਤੂਬਰ',
+'november'             => 'ਨਵੰਬਰ',
+'december'             => 'ਦਸੰਬਰ',
+'jan'                  => 'ਜਨਵਰੀ',
+'feb'                  => 'ਫ਼ਰਵਰੀ',
+'mar'                  => 'ਮਾਰਚ',
+'apr'                  => 'ਅਪ੍ਰੈਲ',
+'may'                  => 'ਮਈ',
+'jun'                  => 'ਜੂਨ',
+'jul'                  => 'ਜੁਲਾਈ',
+'aug'                  => 'ਅਗਸਤ',
+'sep'                  => 'ਸਤੰਬਰ',
+'oct'                  => 'ਅਕਤੂਬਰ',
+'nov'                  => 'ਨਵੰਬਰ',
+'dec'                  => 'ਦਸੰਬਰ',
+
+'categories'   => 'ਸ਼੍ਰੇਣੀਆਂ',
+'category'             => 'ਸ਼੍ਰੇਣੀ',
+'category_header'      => 'ਸ਼੍ਰੇਣੀ \'$1\' ਵਾਲੇ ਲੇਖ',
+'subcategories'        => 'ਉਪਸ਼੍ਰੇਣੀਆਂ',
+
+'linktrail'            => '/^([ਁਂਃਅਆਇਈਉਊਏਐਓਔਕਖਗਘਙਚਛਜਝਞਟਠਡਢਣਤਥਦਧਨਪਫਬਭਮਯਰਲਲ਼ਵਸ਼ਸਹ਼ਾਿੀੁੂੇੈੋੌ੍ਖ਼ਗ਼ਜ਼ੜਫ਼ੰੱੲੳa-z]+)(.*)$/sDu',
+'mainpage'             => 'ਮੁੱਖ ਪੰਨਾ',
+'mainpagetext' => 'ਵਿਕਿ ਸਾਫ਼ਟਵੇਅਰ ਚੰਗੀ ਤਰ੍ਹਾਂ ਇੰਸਟਾਲ ਹੋ ਗਿਆ ਹੈ',
+
+# NOTE: To turn off 'Community portal' in the title links,
+# set 'portal' => '-'
+
+'portal'               => 'ਸਮੂਹ ਦ੍ਵਾਰ',
+'portal-url'           => 'Project:ਸਮੂਹ ਦ੍ਵਾਰ',
+'about'                => 'ਜਾਣਕਾਰੀ',
+'aboutsite'            => '{{SITENAME}} ਬਾਰੇ',
+'aboutpage'            => 'Project:ਜਾਣਕਾਰੀ',
+'article'              => 'ਵਿਸ਼ਾ-ਵਸਤੂ ਵਾਲਾ ਪੰਨਾ',
+'help'         => 'ਮਦਦ',
+'helppage'             => 'ਮਦਦ:ਵਿਸ਼ਾ-ਵਸਤੂ',
+'bugreports'           => 'ਖਾਮੀ ਸੂਚਨਾ',
+'bugreportspage'       => 'Project:ਖਾਮੀ_ਸੂਚਨਾ',
+'sitesupport'          => 'ਦਾਨ',
+'sitesupport-url'      => 'Project:ਦਾਨ',
+'faq'                  => 'ਪ੍ਰਸ਼ਨਾਵਲੀ - FAQ',
+'faqpage'              => 'Project:ਪ੍ਰਸ਼ਨਾਵਲੀ',
+'edithelp'             => 'ਬਦਲਾਵ ਮਦਦ',
+'newwindow'            => '(ਨਵੀਂ window ਵਿੱਚ ਖੁੱਲੇਗਾ)',
+'edithelppage' => 'ਮਦਦ:ਬਦਲਾਵ',
+'cancel'               => 'ਰੱਦ ਕਰੋ',
+'qbfind'               => 'ਲੱਭੋ',
+'qbbrowse'             => 'ਵੇਖੋ - Browse',
+'qbedit'               => 'ਬਦਲੋ',
+'qbpageoptions'        => 'ਪੰਨਾ ਵਿਕਲਪ - Options',
+'qbpageinfo'           => 'ਪੰਨਾ ਜਾਣਕਾਰੀ',
+'qbmyoptions'          => 'ਮੇਰੇ ਵਿਕਲਪ',
+'qbspecialpages'       => 'ਖਾਸ ਪੰਨੇ',
+'moredotdotdot'        => 'ਹੋਰ...',
+'mypage'               => 'ਮੇਰਾ ਪੰਨਾ',
+'mytalk'               => 'ਮੇਰੀ ਚਰਚਾ',
+'anontalk'             => 'ਇੱਸ ਆਈ-ਪੀ (IP) ਦੀ ਚਰਚਾ',
+'navigation'           => 'ਨੈਵੀਗੇਸ਼ੱਨ',
+
+'currentevents'        => '-',
+
+
+'disclaimers'          => 'ਡਿਸਕਲੇਮਰ',
+'disclaimerpage'       => 'Project:General_disclaimer',
+'errorpagetitle'       => 'ਗਲਤੀ',
+'returnto'             => 'ਵਾਪਿਸ ਪਰਤੋ: $1.',
+'tagline'              => '{{SITENAME}} ਤੋਂ',
+'whatlinkshere'        => 'ਪੰਨੇ ਜੋ ਇੱਥੇ ਜੁੜਦੇ ਹਨ',
+'help'         => 'ਮਦਦ',
+'search'               => 'ਖੋਜ',
+'go'                   => 'ਜਾਓ',
+'history'              => 'ਪੁਰਾਣੇ ਆਵਰਤਣ',
+'history_short'        => 'ਇਤਿਹਾਸ',
+'info_short'           => 'ਸੂਚਨਾ',
+'printableversion'     => 'ਛਾਪਣ-ਯੋਗ ਆਵਰਤਣ',
+'edit'         => 'ਬਦਲੋ',
+'editthispage' => 'ਇਸ ਪੰਨੇ ਨੂੰ ਬਦਲੋ',
+'delete'               => 'ਹਟਾਓ',
+'deletethispage'       => 'ਇਸ ਪੰਨੇ ਨੂੰ ਹਟਾਓ',
+'undelete_short'       => '$1 ਬਦਲਾਵ ਮੁੜ ਵਾਪਿਸ ਲਿਆਓ',
+'undelete_short1'      => '1 ਬਦਲਾਵ ਮੁੜ ਵਾਪਿਸ ਲਿਆਓ',
+'protect'              => 'ਰੱਖਿਆ ਕਰੋ',
+'protectthispage'      => 'ਇਸ ਪੰਨੇ ਦੀ ਰੱਖਿਆ ਕਰੋ',
+'unprotect'            => 'ਅਸੁਰੱਖਿਅਤ ਕਰੋ',
+'unprotectthispage'    => 'ਇਸ ਪੰਨੇ ਨੂੰ ਅਸੁਰੱਖਿਅਤ ਕਰੋ',
+'newpage'              => 'ਨਵਾਂ ਪੰਨਾ',
+'talkpage'             => 'ਇਸ ਪੰਨੇ ਤੇ ਚਰਚਾ ਕਰੋ',
+'specialpage'          => 'ਖ਼ਾਸ ਪੰਨਾ',
+'personaltools'        => 'ਨਿਜੀ ਔਜ਼ਾਰ',
+'postcomment'          => 'ਆਪਨੇ ਵਿਚਾਰ ਪੇਸ਼ ਕਰੋ',
+'articlepage'          => 'ਵਿਸ਼ਾ-ਵਸਤੂ ਵਾਲਾ ਪੰਨਾ ਵੇਖੋ',
+'subjectpage'          => 'ਵਿਸ਼ਾ ਵੇਖੋ',
+'talk'         => 'ਚਰਚਾ',
+'toolbox'              => 'ਔਜ਼ਾਰ-ਡੱਬਾ',
+'userpage'             => 'ਮੈਂਬਰ ਦਾ ਪੰਨਾ ਵੇਖੋ',
+'wikipediapage'        => 'ਪਰਿਯੋਜਨਾ (project) ਵਾਲਾ ਪੰਨਾ ਵੇਖੋ',
+'imagepage'            => 'ਤਸਵੀਰ ਵਾਲਾ ਪੰਨਾ ਵੇਖੋ',
+'viewtalkpage' => 'ਚਰਚਾ ਵਾਲਾ ਪੰਨਾ ਵੇਖੋ ',
+'otherlanguages'       => 'ਬਾਕੀ ਭਾਸ਼ਾਵਾਂ',
+'redirectedfrom'       => '($1 ਤੋਂ ਭੇਜਿਆ ਗਿਆ ਹੈ)',
+'lastmodified' => 'ਅਖੀਰਲਾ ਬਦਲਾਵ $1',
+'viewcount'            => 'ਇਹ ਪੰਨਾ $1 ਵਾਰ ਵੇਖਿਆ ਗਿਆ ਹੈ',
+'copyright'            => 'ਵਿਸ਼ਾ-ਵਸਤੂ $1 ਤਹਿਤ ਉਪਲੱਬਧ ਹੈ',
+'poweredby'            => '{{SITENAME}} is powered by [http://www.mediawiki.org/ MediaWiki], an open source wiki engine.',
+'printsubtitle'        => '({{SERVER}} ਤੋਂ)',
+'protectedpage'        => 'ਸੁਰੱਖਿਅਤ ਪੰਨਾ',
+'administrators'       => 'Project:ਪ੍ਰਸ਼ਾਸਕ',
+'sysoptitle'           => 'Sysop ਦਰਜਾ ਹੋਣਾ ਚਾਹੀਦਾ ਹੈ',
+'sysoptext'            => 'ਜੋ ਤੁਸੀਂ ਕਰਨਾ ਚਾਹ ਰਹੇ ਹੋ, ਓਹ ਸਿਰਫ਼ \'sysop\' ਦਰਜੇ ਵਾਲੇ ਮੈਂਬਰ ਹੀ ਕਰ ਸਕਦੇ ਹਨ. ਹੋਰ ਜਾਣਕਾਰੀ ਲਈ ਵੇਖੋ: $1',
+'developertitle'       => 'Developer ਦਰਜਾ ਹੋਣਾ ਚਾਹੀਦਾ ਹੈ',
+'developertext'        => 'ਜੋ ਤੁਸੀਂ ਕਰਨਾ ਚਾਹ ਰਹੇ ਹੋ, ਓਹ ਸਿਰਫ਼ \'developer\' ਦਰਜੇ ਵਾਲੇ ਮੈਂਬਰ ਹੀ ਕਰ ਸਕਦੇ ਹਨ. ਹੋਰ ਜਾਣਕਾਰੀ ਲਈ ਵੇਖੋ: $1',
+'nbytes'               => '$1 ਬਾਈਟ',
+'go'                   => 'ਜਾਓ',
+'ok'                   => 'ਠੀਕ ਹੈ',
+'sitetitle'            => '{{SITENAME}}',
+'pagetitle'            => '$1 - {{SITENAME}}',
+'sitesubtitle' => 'ਇੱਕ ਆਜ਼ਾਦ ਵਿਸ਼ਵਕੌਸ਼', # FIXME
+'retrievedfrom'        => '\'$1\' ਤੋਂ ਪ੍ਰਾਪਤ ਕੀਤਾ ਗਿਆ ਹੈ',
+'newmessages'          => 'ਤੁਹਾਡੇ ਲਈ $1 ਹਨ',
+'newmessageslink'      => 'ਨਵੇਂ ਸੰਦੇਸ਼',
+'editsection'          => 'ਬਦਲੋ',
+'toc'                  => 'ਵਿਸ਼ਾ-ਸੂਚੀ',
+'showtoc'              => 'ਦਿਖਾਓ',
+'hidetoc'              => 'ਛੁਪਾਓ',
+'thisisdeleted'        => 'ਵੇਖੋ ਜਾਂ ਮੁੜ ਵਾਪਿਸ ਲਿਆਓ $1?',
+'restorelink'          => '$1 deleted edits',
+'feedlinks'            => 'Feed:',
+'sitenotice'           => '',
+
+# Short words for each namespace, by default used in the 'article' tab in monobook
+'nstab-main'           => 'ਲੇਖ',
+'nstab-user'           => 'ਮੈਂਬਰ ਦਾ ਪੰਨਾ',
+'nstab-media'          => 'ਮੀਡੀਆ',
+'nstab-special'        => 'ਖਾਸ',
+'nstab-wp'             => 'ਜਾਣਕਾਰੀ',
+'nstab-image'          => 'ਤਸਵੀਰ',
+'nstab-mediawiki'      => 'ਸੰਦੇਸ਼',
+'nstab-template'       => 'ਨਮੂਨਾ',
+'nstab-help'           => 'ਮਦਦ',
+'nstab-category'       => 'ਸ਼੍ਰੇਣੀ',
+
+# Main script and global functions
+#
+'nosuchaction' => 'ਅਜੇਹੀ ਕੋਈ ਕਿਰਿਆ ਨਹੀਂ ਹੈ',
+'nosuchactiontext'     => 'URL ਦੁਵਾਰਾ ਕੀਤੀ ਗਈ ਕਿਰਿਆ (action) ਤੋਂ ਵਿਕਿ ਸੋਫ਼ਟਵੇਅਰ ਜਾਣੂ ਨਹੀਂ ਹੈ',
+'nosuchspecialpage'    => 'ਅਜੇਹਾ ਕੋਈ ਖਾਸ ਪੰਨਾ ਨਹੀਂ ਹੈ',
+'nospecialpagetext'    => 'ਤੁਸੀਂ ਇੱਕ ਖਾਸ ਪੰਨੇ ਦੀ ਮੰਗ ਕੀਤੀ ਹੈ ਜਿਸ ਤੋਂ ਵਿਕਿ ਸੋਫ਼ਟਵੇਅਰ ਜਾਣੂ ਨਹੀਂ ਹੈ',
+
+# General errors
+#
+'error'                => 'ਗਲਤੀ',
+'databaseerror'        => 'ਡਾਟਾਬੇਸ ਨਾਲ ਸੰਬੰਧਤ ਗਲਤੀ',
+'dberrortext'          => 'ਡਾਟਾਬੇਸ ਪੁੱਛਗਿੱਛ ਦੀ ਵਾਕ-ਰਚਨਾ ਵਿਚ ਕੋਈ ਗਲਤੀ ਹੋ ਗਈ ਹੈ।
+ਇਹ ਕਿਸੇ ਖੋਜ ਬਾਰੇ ਗਲਤ ਪੁੱਛਗਿੱਛ ਦੇ ਕਾਰਨ ਹੋ ਸਕਦਾ ਹੈ($5 ਦੇਖੋ),
+ਜਾਂ ਸ਼ਾਇਦ ਸੌਫ਼ਟਵੇਅਰ ਵਿਚ ਕੋਈ ਖ਼ਰਾਬੀ ਹੋ ਸਕਦੀ ਹੈ।
+ਪਿਛਲੀ ਵਾਰ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਗਈ ਡਾਟਾਬੇਸ ਪੁੱਛਗਿੱਛ ਇਹ ਸੀ:
+<blockquote><tt>$1</tt></blockquote>
+\'<tt>$2</tt>\'ਇਸ ਫ਼ੰਕਸ਼ਨ ਦੇ ਵਿਚੋਂ।
+MySQL ਨੇ \'<tt>$3: $4</tt>\'ਗਲਤੀ ਦਿਖਾਈ।',
+'dberrortextcl' => 'ਡਾਟਾਬੇਸ ਪੁੱਛਗਿੱਛ ਦੀ ਵਾਕ-ਰਚਨਾ ਵਿਚ ਕੋਈ ਗਲਤੀ ਹੋ ਗਈ ਹੈ।
+ਪਿਛਲੀ ਵਾਰ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਗਈ ਡਾਟਾਬੇਸ ਪੁੱਛਗਿੱਛ ਇਹ ਸੀ:
+<blockquote><tt>$1</tt></blockquote>
+\'$2\'ਇਸ ਫ਼ੰਕਸ਼ਨ ਦੇ ਵਿਚੋਂ।
+MySQL ਨੇ \'$3: $4\'ਗਲਤੀ ਦਿਖਾਈ।\n',
+'noconnect'            => 'ਮਾਫ਼ ਕਰਨਾ! ਵਿਕਿ ਨੂੰ ਕੁਝ ਤਕਨੀਕੀ ਮੁਸ਼ਕਲਾਂ ਦਾ ਸਾਹਮਣਾ ਕਰਨਾ ਪੈ ਰਿਹਾ ਹੈ, ਅਤੇ ਇਹ ਡਾਟਾਬੇਸ ਸਰਵਰ ਨਾਲ ਸੰਪਰਕ ਨਹੀਂ ਬਣਾ ਸਕਦਾ ਹੈ। <br />$1',
+'nodb'         => 'ਡਾਟਾਬੇਸ $1 ਨੂੰ ਚੁਣ ਨਹੀਂ ਸਕਿਆ',
+'internalerror'        => 'ਅੰਦਰੂਨੀ ਗਲਤੀ',
+'filecopyerror'        => 'ਫ਼ਾਈਲ \'$1\' ਨੂੰ ਫ਼ਾਈਲ \'$2\' ਤੇ ਨਕਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ',
+'filerenameerror'      => 'ਫ਼ਾਈਲ \'$1\' ਦਾ ਨਾਮ \'$2\' ਨਹੀਂ ਕੀਤਾ ਜਾ ਸੱਕਿਆ',
+'filedeleteerror'      => 'ਫ਼ਾਈਲ \'$1\' ਨੂੰ ਨਹੀਂ ਹਟਾਇਆ ਜਾ ਸੱਕਿਆ',
+'filenotfound' => 'ਫ਼ਾਈਲ \'$1\' ਨਹੀਂ ਲੱਭੀ ਜਾ ਸਕੀ',
+'unexpected'           => 'Unexpected value: \'$1\'=\'$2\'.',
+'formerror'            => 'Error: could not submit form',
+'badarticleerror'      => 'ਇਹ ਕਿਰਿਆ ਇਸ ਪੰਨੇ ਤੇ ਸੰਪੰਨ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ',
+'cannotdelete' => 'ਪੰਨੇ ਜਾਂ ਤਸਵੀਰ ਨੂੰ ਨਹੀਂ ਹਟਾ ਸੱਕਿਆ ਗਿਆ (ਇਹ ਸ਼ਾਇਦ ਪਿਹਲਾਂ ਹੀ ਕਿਸੇ ਦੁਆਰਾ ਹਟਾ ਦਿੱਤਾ ਗਿਆ ਹੈ)',
+'badtitle'             => 'ਗਲਤ ਸਿਰਲੇਖ',
+'viewsource'           => 'ਸ੍ਰੋਤ ਦੇਖੋ',
+'protectedtext'        => 'This page has been locked to prevent editing; there are
+a number of reasons why this may be so, please see
+[[{{ns:4}}:Protected page]].
+
+You can view and copy the source of this page:',
+
+# Login and logout pages
+#
+'logouttitle'          => 'ਮੈਂਬਰ ਲਾਗ ਆਊਟ',
+'logouttext'           => 'ਹੁਣ ਤੁਸੀਂ ਲਾਗ ਆਊਟ ਹੋ ਚੁੱਕੇ ਹੋ। ਹੁਣ ਤੁਸੀਂ ਅਗਿਆਤ ਰੂਪ ਵਿੱਚ
+ {{SITENAME}} ਦੀ ਵਰਤੋਂ ਕਰ ਸਕਦੇ ਹੋ ਜਾਂ ਓਹੀ ਮੈਂਬਰ
+ਜਾਂ ਕਿਸੇ ਹੋਰ ਮੈਂਬਰ ਦੇ ਰੂਪ ਵਿੱਚ ਲਾਗ ਇਨ ਕਰ ਸਕਦੇ ਹੋ।
+Note that some pages may continue to be displayed as if you were
+still logged in, until you clear your browser cache\n',
+
+'welcomecreation'      => '== ਜੀ ਆਇਆਂ ਨੂੰ, $1! ==
+
+ਤੁਹਾਡਾ ਖਾਤਾ ਬਣਾ ਦਿੱਤਾ ਗਿਆ ਹੈ, ਆਪਣੀਆਂ {{SITENAME}} ਪਸੰਦਾਂ (preferences) ਨੂੰ ਬਦਲਣਾ ਨਾ ਭੁਲਣਾ।',
+
+'loginpagetitle'       => 'ਮੈਂਬਰ ਲਾਗ ਇਨ',
+'yourname'             => 'ਤੁਹਾਡਾ ਨਾਮ',
+'yourpassword' => 'ਤੁਹਾਡਾ ਪਾਸਵਰਡ',
+'yourpasswordagain'    => 'ਪਾਸਵਰਡ ਦੌਬਾਰਾ ਲਿੱਖੋ',
+'newusersonly' => '(ਸਿਰਫ਼ ਨਵੇਂ ਮੈਂਬਰਾਂ ਲਈ)',
+'remembermypassword'   => 'ਅੱਗੋਂ ਲਈ ਮੇਰਾ ਪਾਸਵਰਡ ਯਾਦ ਰੱਖੋ',
+'loginproblem' => '<b>ਤੁਹਾਡੇ ਲਾਗ ਇਨ ਵਿੱਚ ਕੁਝ ਸਮੱਸਿਆ ਹੈ,</b><br />ਦੌਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ!',
+'alreadyloggedin'      => '<strong>$1, ਤੁਸੀਂ ਪਿਹਲਾਂ ਹੀ ਲਾਗ ਇਨ ਹੋ ਚੁੱਕੇ ਹੋ!</strong><br />\n',
+
+'login'                => 'ਲਾਗ ਇਨ',
+'loginprompt'          => '{{SITENAME}} ਵਿਚ ਲਾੱਗ-ਇਨ ਕਰਨ ਲਈ ਤੁਹਾਡੀਆਂ cookies enabled ਹੋਣੀਆਂ ਚਾਹੀਦੀਆਂ ਹਨ।',
+'userlogin'            => 'ਨਵਾਂ ਖਾਤਾ ਬਨਾਓ ਜਾਂ ਲਾਗ ਇਨ ਕਰੋ',
+'logout'               => 'ਲਾਗ ਆਊਟ',
+'userlogout'           => 'ਲਾਗ ਆਊਟ',
+'notloggedin'          => 'ਲਾਗ ਇਨ ਨਹੀਂ ਹੈ',
+'createaccount'        => 'ਨਵਾਂ ਖਾਤਾ ਬਣਾਓ',
+'createaccountmail'    => 'ਈ-ਮੇਲ (email) ਰਾਹੀਂ',
+'badretype'            => 'ਪਾਸਵਰਡ ਇਕ ਦੂਜੇ ਨਾਲ ਮੇਲ ਨਹੀਂ ਖਾਂਦੇ',
+'userexists'           => 'ਇਹ ਨਾਮ ਪਿਹਲਾਂ ਹੀ ਵਰਤੋਂ ਵਿੱਚ ਹੈ, ਕਿਰਪਾ ਕਰਕੇ ਕਿਸੇ ਹੋਰ ਨਾਮ ਦੀ ਵਰਤੋਂ ਕਰੋ',
+'youremail'            => '* ਤੁਹਾਡਾ ਈ-ਮੇਲ (email)',
+'yourrealname' => '* ਤੁਹਾਡਾ ਨਾਮ',
+'yourlanguage' => 'Interface language',
+'yourvariant'          => 'Language variant',
+'yournick'             => 'ਤੁਹਾਡਾ ਉਪਨਾਮ (ਦਸਤਖ਼ਤ ਲਈ)',
+'emailforlost' => 'Star (*) ਨਿਸ਼ਾਨ ਲੱਗੇ ਖਾਨਿਆਂ ਵਿੱਚ ਭਰਨਾ ਲਾਜ਼ਮੀ ਨਹੀਂ ਹੈ.
+ਜੇ ਤੁਸੀਂ ਈ-ਮੇਲ ਦਿੰਦੇ ਹੋ ਤਾਂ ਬਿਨਾਂ ਤੁਹਾਡੇ ਅਸਲੀ ਈ-ਮੇਲ ਨੂੰ ਜਾਣੇ, ਇਸ website ਦੁਆਰਾ ਲੋਕ ਤੁਹਾਨੂੰ ਸੰਪੰਰਕ ਕਰ ਸਕਦੇ ਹਨ
+ਅਤੇ ਜੇ ਕਦੀ ਤੁਸੀਂ ਆਪਣਾ ਪਾਸਵਰਡ ਭੁੱਲ ਜਾਓ, ਤਾਂ ਇਸ ਈ-ਮੇਲ ਤੇ ਤੁਹਾਨੂੰ ਨਵਾਂ ਪਾਸਵਰਡ ਭੇਜਿਆ ਜਾ ਸਕਦਾ ਹੈ. <br /><br />ਤੁਹਾਡਾ ਅਸਲੀ ਨਾਮ, ਜੇ ਤੁਸੀਂ ਇੱਥੇ ਦਿੰਦੇ ਹੋ, ਤੁਹਾਡੇ ਕੰਮ ਨੂੰ attribution ਦੇਣ ਲਈ ਵਰਤਿਆ ਜਾਵੇਗਾ',
+'prefs-help-realname'  => '* <strong>ਅਸਲੀ ਨਾਮ</strong> (ਗੈਰ-ਜ਼ਰੂਰੀ): ਜੇ ਤੁਸੀਂ ਭਰਦੇ ਹੋ, ਤਾਂ ਤੁਹਾਡੇ ਕੰਮ ਨੂੰ attribution ਦੇਣ ਲਈ ਵਰਤਿਆ ਜਾਵੇਗਾ<br />',
+'prefs-help-email'     => '* <strong>ਈ-ਮੇਲ</strong> (ਗੈਰ-ਜ਼ਰੂਰੀ): ਜੇ ਭਰਦੇ ਹੋ ਤਾਂ ਬਿਨਾਂ ਤੁਹਾਡੇ ਅਸਲੀ ਈ-ਮੇਲ ਨੂੰ ਜਾਣੇ, ਇਸ website ਦੁਆਰਾ ਲੋਗ ਤੁਹਾਨੂੰ ਸੰਪੰਰਕ ਕਰ ਸਕਦੇ ਹਨ
+ਅਤੇ ਜੇ ਕਦੀ ਤੁਸੀਂ ਆਪਣਾ ਪਾਸਵਰਡ ਭੁੱਲ ਜਾਓ, ਤਾਂ ਇਸ ਈ-ਮੇਲ ਤੇ ਤੁਹਾਨੂੰ ਨਵਾਂ ਪਾਸਵਰਡ ਭੇਜਿਆ ਜਾ ਸਕਦਾ ਹੈ.',
+'loginerror'           => 'ਲਾਗ ਇਨ ਵਿੱਚ ਗਲਤੀ',
+'noname'               => 'ਤੁਸੀਂ ਮੈਂਬਰ ਦਾ ਨਾਮ ਸਹੀ ਨਹੀਂ ਦੱਸਿਆ.',
+'loginsuccesstitle'    => 'ਲਾਗ ਇਨ ਕਾਮਯਾਬ ਰਿਹਾ',
+'loginsuccess' => 'ਹੁਣ ਤੁਸੀਂ {{SITENAME}} ਵਿੱਚ \'$1\' ਨਾਮ ਨਾਲ ਲਾਗ ਇਨ ਹੋ',
+'nosuchuser'           => '\'$1\' ਨਾਮ ਦਾ ਕੋਈ ਮੈਂਬਰ ਨਹੀਂ ਹੈ.
+ਕਿਰਪਾ ਕਰਕੇ ਨਾਮ ਸਹੀ ਲਿੱਖੋ ਜਾਂ ਨੀਚੇ ਦਿੱਤੇ ਗਏ ਫ਼ਾਰਮ ਦੀ ਵਰਤੋਂ ਕਰਕੇ ਇੱਕ ਨਵਾਂ ਖਾਤਾ ਬਣਾ ਲਓ.',
+'wrongpassword'        => 'ਦਿੱਤਾ ਗਿਆ ਪਾਸਵਰਡ ਗਲਤ ਹੈ, ਕਿਰਪਾ ਕਰਕੇ ਦੋਬਾਰਾ ਯਤਨ ਕਰੋ',
+'mailmypassword'       => 'ਮੈਨੂੰ ਇੱਕ ਨਵਾਂ ਪਾਸਵਰਡ ਈ-ਮੇਲ ਰਾਹੀਂ ਭੇਜ ਦਿਓ',
+'passwordremindertitle'        => '{{SITENAME}} ਵਲੋਂ ਪਾਸਵਰਡ ਯਾਦਦਹਾਣੀ-ਪੱਤ੍ਰ (Password Reminder from {{SITENAME}})',
+'passwordremindertext' => 'ਕਿਸੇ ਨੇ (ਸ਼ਾਯਿਦ ਤੁਸੀਂ ਹੀ, $1 IP address ਤੋਂ)
+ {{SITENAME}} ਲਾਗ ਇਨ ਦਾ ਨਵਾਂ ਪਾਸਵਰਡ ਭੇਜਣ ਦੀ ਮੰਗ ਕੀਤੀ ਸੀ.
+ਮੈਂਬਰ \'$1\' ਦਾ ਹੁਣ ਨਵਾਂ ਪਾਸਵਰਡ \'$3\' ਹੈ.
+ਕਿਰਪਾ ਕਰਕੇ {{SITENAME}} ਵਿੱਚ ਲਾਗ ਇਨ ਕਰਕੇ ਹੁਣੇ ਆਪਣਾ ਪਾਸਵਰਡ ਬਦਲ ਲਓ.\n<br /><br />
+Someone (probably you, from IP address $1)
+requested that we send you a new {{SITENAME}} login password.
+The password for user \'$2\' is now \'$3\'.
+You should log in and change your password now.',
+'noemail'              => 'ਮੈਂਬਰ \'$1\' ਲਈ ਕੋਈ ਈ-ਮੇਲ ਅਡ੍ਰੈੱਸ ਨਹੀਂ ਹੈ',
+'passwordsent' => '\'$1\' ਮੈਂਬਰ ਦੇ ਈ-ਮੇਲ ਅਡ੍ਰੈੱਸ ਤੇ ਇੱਕ ਨਵਾਂ ਪਾਸਵਰਡ ਭੇਜ ਦਿੱਤਾ ਗਿਆ ਹੈ.
+ਪਾਸਵਰਡ ਮਿਲੱਣ ਤੋਂ ਬਾਅਦ ਕਿਰਪਾ ਲਾਗ ਇਨ ਜ਼ਰੂਰ ਕਰੋ.',
+'loginend'             => ' ',
+'mailerror'            => 'ਮੇਲ (mail) $1 ਭੇਜਣ ਵਿੱਚ ਸਮੱਸਿਆ ਆ ਗਈ ਹੈ',
+'acct_creation_throttle_hit'   => 'ਮਾਫ਼ੀ ਚਾਹੁੰਦੇ ਹਾਂ, ਤੁਸੀਂ ਪਿਹਲਾਂ ਹੀ $1 ਖਾਤੇ ਬਣਾ ਚੁੱਕੇ ਹੋ. ਤੁਸੀਂ ਇਸਤੋਂ ਜ਼ਿਆਦਾ ਨਹੀਂ ਬਣਾ ਸੱਕਦੇ ਹੋ',
+
+# Edit page toolbar
+'bold_sample'          =>'ਬੋਲਡ ਅੱਖਰ',
+'bold_tip'             =>'ਬੋਲਡ ਅੱਖਰ',
+'italic_sample'        =>'ਇਟੈਲਿਕ ਅੱਖਰ',
+'italic_tip'           =>'ਇਟੈਲਿਕ ਅੱਖਰ',
+'link_sample'          =>'Link title',
+'link_tip'             =>'ਅੰਦਰੂਨੀ ਕੜੀ',
+'extlink_tip'          =>'ਬਾਹਰੀ ਕੜੀ (ਪਹਿਲਾਂ http:// ਲਗਾਉਣਾ ਯਾਦ ਰੱਖੋ)',
+'math_tip'             =>'ਗਣਿਤ ਦਾ ਫਾਰਮੂਲਾ (LaTeX)',
+
+# Edit pages
+#
+'summary'              => 'ਸਾਰ',
+'subject'              => 'ਵਿਸ਼ਾ',
+'minoredit'            => 'ਇਹ ਇਕ ਮਾਮੂਲੀ ਬਦਲਾਵ ਹੈ',
+'watchthis'            => 'ਇਸ ਪੰਨੇ ਤੇ ਨਜ਼ਰ ਰਖੋ',
+'savearticle'          => 'ਪੱਕਾ ਕਰ ਦਿਓ',
+'preview'              => 'ਝਲਕ',
+'showpreview'          => 'ਝਲਕ ਦਿਖਾਓ',
+'blockedtitle' => 'ਮੈਂਬਰ ਤੇ ਰੋਕ ਲਗਾ ਦਿੱਤੀ ਗਈ ਹੈ',
+'blockedtext'          => 'ਤੁਹਾਡੇ ਮੈਂਬਰ ਨਾਮ ਜਾਂ IP address ਉੱਤੇ $1 ਦੁਆਰਾ ਰੋਕ ਲਗਾ ਦਿੱਤੀ ਗਈ ਹੈ.
+ਕਾਰਣ ਹੈ:<br />\'\'$2\'\'<p>ਇਸ ਰੋਕ ਦੇ ਬਾਰੇ ਵਿੱਚ ਚਰਚਾ ਕਰਨ ਲਈ
+$1 ਜਾਂ ਕਿਸੇ ਵੀ ਹੋਰ [[{{ns:4}}:ਪ੍ਰਸ਼ਾਸਕ]]
+ਨੂੰ ਸੰਪੰਰਕ ਕਰੋ. ਧਿਆਨ ਦਿਓ ਕਿ ਤੁਸੀਂ ਓਹਨਾਂ ਚਿਰ \'ਇਸ ਮੈਂਬਰ ਨੂੰ ਈ-ਮੇਲ ਕਰੋ\' ਸੁਵੀਧਾ ਦੀ ਵਰਤੋਂ
+ਨਹੀਂ ਕਰ ਸਕਦੇ, ਜਦੋਂ ਤੱਕ ਕਿ ਤੁਸੀਂ [[Special:Preferences|preferences]]
+ਵਿੱਚ ਆਪਣਾ ਈ-ਮੇਲ ਨਹੀਂ ਦਿੰਦੇ. ਤੁਹਾਡਾ IP address ਹੈ $3.
+ਕਿਰਪਾ ਕਰਕੇ ਪੁਛ-ਗਿੱਛ ਕਰਦੇ ਵਕਤ ਇਸ IP address ਦੀ ਵਰਤੋਂ ਜ਼ਰੂਰ ਕਰੋ.',
+'whitelistedittitle'   => 'ਬਦਲਾਵ ਕਰਨ ਲਈ ਲਾੱਗ-ਇਨ ਹੋਣਾ ਜ਼ਰੂਰੀ ਹੈ',
+'whitelistedittext'    => 'ਤੁਹਾਨੂੰ ਲੇਖਾਂ ਵਿੱਚ ਬਦਲਾਵ ਕਰਨ ਲਈ [[Special:Userlogin|login]] ਕਰਨਾ ਜ਼ਰੂਰੀ ਹੈ',
+'whitelistreadtitle'   => 'ਪੜ੍ਹਨ ਲਈ ਲਾੱਗ-ਇਨ ਕਰਨਾ ਜ਼ਰੂਰੀ ਹੈ',
+'whitelistreadtext'    => 'ਤੁਹਾਨੂੰ ਲੇਖ ਪੜਨ ਲਈ [[Special:Userlogin|login]] ਕਰਨਾ ਜ਼ਰੂਰੀ ਹੈ',
+'whitelistacctitle'    => 'ਤੁਹਾਨੂੰ ਖਾਤਾ ਬਨਾਓਣ ਦੀ ਅਨੁਮਤੀ ਨਹੀਂ ਹੈ',
+'whitelistacctext'     => 'ਇਸ ਵਿਕਿ ਵਿੱਚ ਖਾਤਾ ਬਨਾਓਣ ਲਈ ਤੁਹਾਨੂੰ [[Special:Userlogin|login]] ਕਰਨਾ ਜ਼ਰੂਰੀ ਹੈ ਅਤੇ ਨਾਲ ਹੀ ਉਪ੍ਯੁਕਤ ਅਨੁਮਤੀ ਵੀ ਹੋਣੀ ਚਾਹੀਦੀ ਹੈ',
+'loginreqtitle'        => 'ਲਾਗ ਇਨ ਜ਼ਰੂਰੀ ਹੈ',
+'loginreqtext' => 'ਬਾਕੀ ਦੇ ਲੇਖ ਵੇਖਣ ਲਈ [[Special:Userlogin|login]] ਕਰਨਾ ਜ਼ਰੂਰੀ ਹੈ',
+'accmailtitle' => 'ਪਾਸਵਰਡ ਭੇਜ ਦਿੱਤਾ ਗਿਆ ਹੈ',
+'accmailtext'          => '\'$1\' ਦਾ ਪਾਸਵਰਡ $2 ਨੂੰ ਭੇਜ ਦਿੱਤਾ ਗਿਆ ਹੈ',
+'newarticle'           => '(ਨਵਾਂ ਲੇਖ)',
+'newarticletext'       => '
+ਤੁਸੀਂ ਅਜੇਹੇ ਪੰਨੇ ਤੇ ਪੁੱਜ ਗਏ ਹੋ ਜੋ ਅਜੇ ਲਿੱਖਿਆ ਨਹੀਂ ਗਿਆ ਹੈ.
+ਜੇ ਤੁਸੀਂ ਇਸ ਪੰਨੇ ਨੂੰ ਬਨਾਣਾ ਚਾਹੁੰਦੇ ਹੋ, ਤਾਂ ਹੇਠਾਂ ਦਿੱਤੀ
+ਥਾਂ ਵਿੱਚ ਲਿੱਖਣਾ ਸ਼ੁਰੂ ਕਰ ਦਿਓ(ਹੋਰ ਜਾਣਕਾਰੀ ਲਈ ਵੇਖੋ [[Project:Help|help page]]).
+ਜੇ ਤੁਸੀਂ ਗਲਤੀ ਨਾਲ ਇੱਥੇ ਆ ਗਏ ਹੋ, ਤਾਂ ਆਪਣੇ browser ਦਾ \'\'\'back\'\'\' button ਦਬਾਓ',
+'noarticletext'        => '(ਅਜੇ ਇਹ ਪੰਨਾ ਖਾਲੀ ਹੈ)',
+'usercssjsyoucanpreview'       => '<strong>ਨਸੀਹਤ:</strong>CSS/JS ਵਿੱਚ ਕੀਤੇ ਗਏ ਬਦਲਾਵ  ਨੂੰ ਪੱਕਾ ਕਰਨ ਤੋਂ ਪਿਹਲਾਂ, \'ਝਲਕ ਦਿਖਾਓ\' button ਦਾ ਇਸਤੇਮਾਲ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ',
+'usercsspreview'       => '\'\'\'ਯਾਦ ਰੱਖੋ ਕਿ ਤੁਸੀਂ ਆਪਣੀ CSS ਦੀ ਸਿਰਫ਼ ਝਲਕ ਵੇਖ ਰਹੇ ਹੋ, ਅਜੇ ਇਸਨੂੰ ਪੱਕਾ ਨਹੀਂ ਕੀਤਾ ਗਿਆ ਹੈ!\'\'\'',
+'userjspreview'        => '\'\'\'ਯਾਦ ਰੱਖੋ ਕਿ ਤੁਸੀਂ ਆਪਣੀ javascript ਦੀ ਸਿਰਫ਼ ਝਲਕ ਵੇਖ ਰਹੇ ਹੋ, ਅਜੇ ਇਸਨੂੰ ਪੱਕਾ ਨਹੀਂ ਕੀਤਾ ਗਿਆ ਹੈ!\'\'\'',
+'updated'              => '(ਅੱਪਡੇਟ (update) ਹੋ ਗਿਆ ਹੈ)',
+'note'         => '<strong>ਧਿਆਨ ਦਿਓ:</strong> ',
+'previewnote'          => 'ਯਾਦ ਰੱਖੋ ਕਿ ਇਹ ਸਿਰਫ਼ ਇਕ ਝਲਕ ਹੈ, ਅਜੇ ਇਸਨੂੰ ਪੱਕਾ ਨਹੀਂ ਕੀਤਾ ਗਿਆ ਹੈ!',
+'editing'              => 'ਬਦਲ ਰਹੇ ਹਾਂ: $1',
+'editconflict' => 'ਬਦਲਾਵ ਮੱਤਭੇਦ: $1',
+'yourdiff'             => 'ਅੰਤਰ (Differences)',
+
+# History pages
+#
+'revhistory'           => 'ਸੋਧ ਦਾ ਇਤਿਹਾਸ',
+'nohistory'            => 'ਇਸ ਪੰਨੇ ਲਈ ਤਬਦੀਲ਼ੀ ਦਾ ਕੋਈ ੲਤਿਹਾਸ ਨਹੀਂ ਹੈ.',
+'revnotfound'          => 'ਸੋਧ ਨਹੀਂ ਮਿਲੀ',
+'loadhist'             => 'ਪੰਨੇ ਦਾ ਇਤਿਹਾਸ ਲੋਡ ਹੋ ਰਿਹਾ ਹੈ',
+'currentrev'           => 'ਮੌਜੂਦਾ ਸੰਸ਼ੋਧਨ',
+'cur'                  => 'ਮੌਜੂਦਾ',
+'next'         => 'ਅਗਲਾ',
+'last'         => 'ਪਿਛਲਾ',
+'orig'         => 'ਅਸਲ',
+
+# Diffs
+#
+'editcurrent'          => 'ਇਸ ਪੰਨੇ ਦੇ ਮੌਜੂਦਾ ਰੁਪਾਂਤਰ ਵਿਚ ਤਬਦੀਲੀ ਕਰੋ',
+'selectnewerversionfordiff'    => 'ਆਪਸ ਵਿਚ ਮਿਲਾਉਣ ਲਈ ਨਵਾਂ ਰੁਪਾਂਤਰ ਚੁਣੋ',
+'selectolderversionfordiff'    => 'ਆਪਸ ਵਿਚ ਮਿਲਾਉਣ ਲਈ ਪੁਰਾਣਾ ਰੁਪਾਂਤਰ ਚੁਣੋ',
+'compareselectedversions'      => 'ਚੁਣੇ ਹੋਏ ਰਪਾਂਤਰਾਂ ਨੂੰ ਆਪਸ ਵਿਚ ਮਿਲਾਓ',
+
+# Search results
+#
+'searchdisabled'       => '<p>ਮੁਆਫ਼ੀ ਚਾਹੁੰਦੇ ਹਾਂ! Full text search, performance reasons ਕਰਕੇ ਕੁੱਝ ਦੇਰ ਲਈ ਬੰਦ ਕਰ ਦਿੱਤੀ ਗਈ ਹੈ. ਇਸ ਦਰਮਿਆਨ, ਚਾਹੋ ਤਾਂ ਤੁਸੀਂ Google search ਦੀ ਵਰਤੋਂ ਕਰ ਸਕਦੇ ਹੋ, ਜੋ ਕਿ ਹੋ ਸਕਦਾ ਹੈ ਪੂਰਾਣੀ ਹੋ ਚੁੱਕੀ ਹੋਵੇ</p>',
+
+# Recent changes
+#
+'changes'              => 'ਬਦਲਾਵ',
+'recentchanges'        => 'ਹਾਲ ਵਿੱਚ ਹੋਏ ਬਦਲਾਵ',
+'rcnote'               => 'ਪਿੱਛਲੇ <strong>$2</strong> ਦਿਨਾਂ ਵਿੱਚ ਹੋਏ <strong>$1</strong> ਬਦਲਾਵ:',
+'rclistfrom'           => '$1 ਤੋਂ ਸ਼ੁਰੂ ਹੋਣ ਵਾਲੇ ਨਵੇਂ ਬਦਲਾਵ ਦਿਖਾਓ',
+'rclinks'              => 'ਪਿੱਛਲੇ $2 ਦਿਨਾਂ ਵਿੱਚ ਹੋਏ $1 ਬਦਲਾਵ ਦਿਖਾਓ<br />$3',
+'hide'         => 'ਛੁਪਾਓ',
+'show'         => 'ਦਿਖਾਓ',
+'listform'             => 'ਸੂਚੀ',
+'nchanges'             => '$1 ਬਦਲਾਵ',
+
+# tooltip help for some actions, most are in Monobook.js
+'tooltip-watch'        => 'ਇਸ ਪੰਨੇ ਨੂੰ ਆਪਣੀ watchlist ਵਿੱਚ ਜਮਾਂ ਕਰੋ[alt-w]',
+'tooltip-search'       => 'ਇਸ ਵਿਕਿ ਵਿੱਚ ਲੱਭੋ [alt-f]',
+'tooltip-minoredit'    => 'ਮਾਮੂਲੀ ਬਦਲਾਵ ਦੀ ਨਿਸ਼ਾਨੀ ਲਗਾਓ (Mark this as a minor edit) [alt-i]',
+'tooltip-save' => 'ਕੀਤੇ ਗਏ ਬਦਲਾਵ ਪੱਕੇ ਕਰੋ [alt-s]',
+'tooltip-preview'      => 'ਕੀਤੇ ਗਏ ਬਦਲਾਵਾਂ ਦੀ ਝਲਕ ਵੇਖੋ, ਕਿਰਪਾ ਕਰਕੇ ਪੱਕਾ ਕਰਨ ਤੋਂ ਪਿਹਲਾਂ ਇਸਦੀ ਵਰਤੋਂ ਜ਼ਰੂਰ ਕਰੋ! [alt-p]',
+
+# Attribution
+
+'lastmodifiedby'       => 'ਇਹ ਪੰਨਾ ਅਖੀਰਲੀ ਵਾਰ $1 ਨੂੰ $2 ਦੁਆਰਾ ਬਦਲਿਆ ਗਿਆ ਸੀ',
+'and'                  => 'ਅਤੇ',
+'othercontribs'        => '$1 ਦੁਆਰਾ ਕੰਮ ਤੇ ਅਧਾਰਤ।',
+
+# Info page
+'infosubtitle' => 'ਪੰਨੇ ਸੰਬੰਧੀ ਸੂਚਨਾ',
+'numedits'             => 'ਤਬਦੀਲੀਆਂ ਦੀ ਗਿਣਤੀ (ਲੇਖ ਵਿਚਾਲੇ): ',
+'numtalkedits' => 'ਤਬਦੀਲੀਆਂ ਦੀ ਗਿਣਤੀ (ਚਰਚਾ-ਪੰਨੇ ਵਿਚਾਲੇ): ',
+);
+
+#--------------------------------------------------------------------------
+# Internationalisation code
+#--------------------------------------------------------------------------
+
+class LanguagePa extends LanguageUtf8 {
+
+       function getNamespaces() {
+               global $wgNamespaceNamesPa;
+               return $wgNamespaceNamesPa;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsPa;
+               return $wgQuickbarSettingsPa;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesPa;
+               return $wgSkinNamesPa;
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesPa;
+               if( isset( $wgAllMessagesPa[$key] ) ) {
+                       return $wgAllMessagesPa[$key];
+               } else {
+                       return parent::getMessage( $key );
+               }
+       }
+
+       var $digitTransTable = array(
+               '0' => '੦',
+               '1' => '੧',
+               '2' => '੨',
+               '3' => '੩',
+               '4' => '੪',
+               '5' => '੫',
+               '6' => '੬',
+               '7' => '੭',
+               '8' => '੮',
+               '9' => '੯'
+       );
+
+       function formatNum( $number ) {
+               global $wgTranslateNumerals;
+               if( $wgTranslateNumerals ) {
+                       return strtr( $number, $this->digitTransTable );
+               } else {
+                       return $number;
+               }
+       }
+}
+?>
diff --git a/languages/LanguagePl.php b/languages/LanguagePl.php
new file mode 100644 (file)
index 0000000..0ba0d5e
--- /dev/null
@@ -0,0 +1,990 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+require_once("LanguageUtf8.php");
+
+# FIXME: Lots of hardcoded Wikipedia-related text needs to be cleaned up.
+
+# Yucky hardcoding hack as polish grammar need tweaking :o)
+switch( $wgMetaNamespace ) {
+case 'Wikipedia':
+       $wgMetaTalkNamespace = 'Dyskusja_Wikipedii'; break;
+case 'Wikisłownik':
+       $wgMetaTalkNamespace = 'Wikidyskusja'; break;
+case 'Wikicytaty':
+       $wgMetaTalkNamespace = 'Dyskusja_Wikicytatów'; break;
+default:
+       $wgMetaTalkNamespace = 'Dyskusja_'.$wgMetaNamespace;
+}
+
+/* private */ $wgNamespaceNamesPl = array(
+       NS_MEDIA            => "Media",
+       NS_SPECIAL          => "Specjalna",
+       NS_MAIN             => "",
+       NS_TALK             => "Dyskusja",
+       NS_USER             => "Wikipedysta",
+       NS_USER_TALK        => "Dyskusja_Wikipedysty",
+       NS_PROJECT          => $wgMetaNamespace,
+       NS_PROJECT_TALK     => $wgMetaTalkNamespace,   // see above
+       NS_IMAGE            => "Grafika",
+       NS_IMAGE_TALK       => "Dyskusja_grafiki",
+       NS_MEDIAWIKI        => "MediaWiki",
+       NS_MEDIAWIKI_TALK   => "Dyskusja_MediaWiki",
+       NS_TEMPLATE         => "Szablon",
+       NS_TEMPLATE_TALK    => "Dyskusja_szablonu",
+       NS_HELP             => "Pomoc",
+       NS_HELP_TALK        => "Dyskusja_pomocy",
+       NS_CATEGORY         => "Kategoria",
+       NS_CATEGORY_TALK    => "Dyskusja_kategorii"
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgQuickbarSettingsPl = array(
+       "Brak", "Stały, z lewej", "Stały, z prawej", "Unoszący się, z lewej"
+);
+
+/* private */ $wgAllMessagesPl = array(
+# User Toggles
+
+"tog-underline" => "Podkreślenie linków",
+"tog-highlightbroken" => "<a href=\"\" class=\"new\">Podświetl</a> linki pustych stron (alternatywa: znak zapytania<a href=\"\" class=\"internal\">?</a>).",
+"tog-justify" => "Wyrównuj tekst artykułu w kolumnie",
+"tog-hideminor" => "Ukryj drobne zmiany w \"Ostatnich zmianach\"",
+"tog-usenewrc" => "Konsolidacja ostatnich zmian (JavaScript)",
+"tog-numberheadings" => "Automatyczna numeracja nagłówków",
+"tog-showtoolbar" => "Show edit toolbar",
+"tog-editondblclick" => "Podwójne kliknięcie rozpoczyna edycję (JavaScript)",
+"tog-editsection" => "Możliwość edycji poszczególnych sekcji strony",
+"tog-editsectiononrightclick" => "Kliknięcie prawym klawiszem na tytule sekcji<br />rozpoczyna jej edycję (JavaScript)",
+"tog-showtoc" =>  "Spis treści (na stronach zawierających więcej niż 3 nagłówki)",
+"tog-rememberpassword" => "Pamiętaj hasło między sesjami",
+"tog-editwidth" => "Obszar edycji o pełnej szerokości",
+"tog-watchdefault" => "Obserwuj strony, które będę edytować",
+"tog-minordefault" => "Wszystkie zmiany zaznaczaj domyślnie jako drobne",
+"tog-previewontop" => "Pokazuj podgląd przed oknem edycji",
+"tog-nocache" => "Wyłącz pamięć podręczną",
+
+# Dates
+'sunday' => "niedziela",
+'monday' => "poniedziałek",
+'tuesday' => "wtorek",
+'wednesday' => "środa",
+'thursday' => "czwartek",
+'friday' => "piątek",
+'saturday' => "sobota",
+'january' => "styczeń",
+'february' => "luty",
+'march' => "marzec",
+'april' => "kwiecień",
+'may_long' => "maj",
+'june' => "czerwiec",
+'july' => "lipiec",
+'august' => "sierpień",
+'september' => "wrzesień",
+'october' => "październik",
+'november' => "listopad",
+'december' => "grudzień",
+'january-gen' => "stycznia",
+'february-gen' => "lutego",
+'march-gen' => "marca",
+'april-gen' => "kwietnia",
+'may-gen' => "maja",
+'june-gen' => "czerwca",
+'july-gen' => "lipca",
+'august-gen' => "sierpnia",
+'september-gen' => "września",
+'october-gen' => "października",
+'november-gen' => "listopada",
+'december-gen' => "grudnia",
+'jan' => "sty",
+'feb' => "lut",
+'mar' => "mar",
+'apr' => "kwi",
+'may' => "maj",
+'jun' => "cze",
+'jul' => "lip",
+'aug' => "sie",
+'sep' => "wrz",
+'oct' => "paź",
+'nov' => "lis",
+'dec' => "gru",
+
+# Bits of text used by many pages:
+#
+"categories" => "Kategorie stron",
+"category" => "kategoria",
+"category_header" => "Artykuły w kategorii \"$1\"",
+"subcategories" => "Podkategorie",
+"linktrail" => "/^([a-z]+)(.*)\$/sD",
+"mainpage" => "Strona główna",
+"mainpagetext" => "Instalacja oprogramowania powiodła się.",
+"about" => "O Wikipedii",
+"aboutsite"      => "O Wikipedii",
+"aboutpage" => "{{ns:4}}:O_Wikipedii",
+"help" => "Pomoc",
+"helppage" => "{{ns:4}}:Pomoc",
+"bugreports" => "Raport o błędach",
+"bugreportspage" => "{{ns:4}}:Błędy",
+"sitesupport" => "Dary pieniężne",
+"faq" => "FAQ",
+"faqpage" => "{{ns:4}}:FAQ",
+"edithelp" => "Pomoc w edycji",
+"edithelppage" => "{{ns:4}}:Jak_edytować_stronę",
+"cancel" => "Anuluj",
+"qbfind" => "Znajdź",
+"qbbrowse" => "Przeglądanie",
+"qbedit" => "Edycja",
+"qbpageoptions" => "Opcje strony",
+"qbpageinfo" => "O stronie",
+"qbmyoptions" => "Moje opcje",
+"mypage" => "Moja strona",
+"mytalk" => "Moja dyskusja",
+"currentevents" => "-",
+"errorpagetitle" => "Błąd",
+"returnto" => "Wróć do strony: $1.",
+"tagline"       => "Z Wikipedii, wolnej encyklopedii.",
+"whatlinkshere" => "Strony, które odwołują się do tej",
+"help" => "Pomoc",
+"search" => "Szukaj",
+"go" => "OK",
+"history" => "Historia strony",
+"printableversion" => "Wersja do druku",
+"editthispage" => "Edytuj",
+"deletethispage" => "Usuń",
+"protectthispage" => "Zabezpiecz",
+"unprotectthispage" => "Odbezpiecz",
+"newpage" => "Nowa strona",
+"talkpage" => "Dyskusja",
+"postcomment" => "Skomentuj",
+"articlepage" => "Strona artykułu",
+"subjectpage" => "Strona dyskutowana", # for compatibility
+"userpage" => "Strona wikipedysty",
+"wikipediapage" => "Strona metaartykułu",
+"imagepage" =>  "Strona grafiki",
+"viewtalkpage" => "Strona dyskusji",
+"otherlanguages" => "Wersja",
+"redirectedfrom" => "(Przekierowano z $1)",
+"lastmodified" => "Tę stronę ostatnio zmodyfikowano o $1;",
+"viewcount" => "Tę stronę obejrzano $1 razy;",
+"printsubtitle" => "(z {{SERVER}})",
+"protectedpage" => "Strona zabezpieczona",
+"administrators" => "{{ns:4}}:Administratorzy",
+"sysoptitle" => "Wymagane prawa dostępu administratora",
+"sysoptext" => "Ta operacja może być wykonana tylko przez
+użytkowania o statusie \"administrator\".
+Zobacz $1.",
+"developertitle" => "Wymagane prawa dostępu Programisty",
+"developertext" => "Ta operacja może być wykonana tylko przez
+użytkownika o prawach \"Programisty\".
+Zobacz $1.",
+"nbytes" => "$1 bajtów",
+"go" => "OK",
+"ok" => "OK",
+"sitetitle" => "{{SITENAME}}",
+"sitesubtitle" => "Wolna Encyklopedia",
+"retrievedfrom" => "Źródło: \"$1\"",
+"newmessages" => "Masz $1.",
+"newmessageslink" => "Nowe wiadomości",
+"editsection" => "Edytuj",
+"toc" => "Spis treści",
+"showtoc" => "pokaż",
+"hidetoc" => "schowaj",
+"thisisdeleted" => "Pokaż/odtwórz $1",
+"restorelink" => "skasowane wersje (w sumie $1)",
+
+# Main script and global functions
+#
+"nosuchaction" => "Nie ma takiej operacji",
+"nosuchactiontext" => "Oprogramowanie Wikipedii nie rozpoznaje
+operacji takiej jak podana w URL",
+"nosuchspecialpage" => "Nie ma takiej strony specjalnej",
+"nospecialpagetext" => "Oprogramowanie Wikipedii nie rozpoznaje takiej
+specjalnej strony.",
+
+# General errors
+#
+"error" => "Błąd",
+"databaseerror" => "Błąd bazy danych",
+"dberrortext" => "Wystąpił błąd składni w zapytaniu do bazy danych.
+Ostatnie, nieudane zapytanie to:
+<blockquote><tt>$1</tt></blockquote>
+wysłane przez funkcję \"<tt>$2</tt>\".
+MySQL zgłosił błąd \"<tt>$3: $4</tt>\".",
+"dberrortextcl" => "Wystąpił błąd składni w zapytaniu do bazy danych.
+Ostatnie, nieudane zapytanie to:
+\"$1\"
+wywołane zostało przez funkcję \"$2\".
+MySQL zgłosił błąd \"$3: $4\".\n",
+"noconnect" => "{{SITENAME}} ma chwilowo problemy techniczne. Nie można połączyć się z serwerem bazy danych. Przepraszamy!",
+"nodb" => "Nie można odnaleźć bazy danych $1",
+"cachederror" => "Poniższy tekst strony jest kopią znajdującą się w pamięci podręcznej i może być już niekatualny.",
+"readonly" => "Baza danych jest zablokowana",
+"enterlockreason" => "Podaj powód zablokowania bazy oraz szacunkowy czas
+jej odblokowania",
+"readonlytext" => "Baza danych Wikipedii jest w tej chwili zablokowana
+- nie można wprowadzać nowych artykułów ani modyfikować istniejących. Powodem
+są prawdopodobnie czynności administracyjne. Po ich zakończeniu przywrócona
+zostanie pełna funkcjonalność bazy.
+Administrator, który zablokował bazę, podał następujące wyjaśnienie:
+<p>$1",
+"missingarticle" => "Oprogramowanie nie odnalazło tekstu strony,
+która powinna się znajdować w bazie, tzn. strony \"$1\".
+<p>Zazwyczaj zdarza się to, gdy wybrane zostanie łącze
+do skasowanej strony, np. w starszej wersji innej ze stron.
+<p>Inne okoliczności świadczyłyby o tym, że w oprogramowaniu jest błąd.
+W takim przypadku zgłoś, proszę, ten fakt administratorowi
+podając także powyższy adres.",
+"internalerror" => "Błąd wewnętrzny",
+"filecopyerror" => "Nie można skopiować pliku \"$1\" do \"$2\".",
+"filerenameerror" => "Nie można zmienić nazwy pliku \"$1\" na \"$2\".",
+"filedeleteerror" => "Nie można skasować pliku \"$1\".",
+"filenotfound" => "Nie można znaleźć pliku \"$1\".",
+"unexpected" => "Niespodziewana wartość: \"$1\"=\"$2\".",
+"formerror" => "Błąd: nie można wysłać formularza",
+"badarticleerror" => "Dla tej strony ta operacja nie może być wykonana.",
+"cannotdelete" => "Nie można skasować podanej strony lub obrazka.",
+"badtitle" => "Niepoprawny tytuł",
+"badtitletext" => "Podano niepoprawny tytuł strony. Prawdopodobnie zawiera
+znaki, których użycie jest zabronione lub jest pusty.",
+"perfdisabled" => "By odciążyć serwer w godzinach szczytu czasowo zablokowaliśmy
+wykonanie tej czynności. Wróć proszę i spróbuj jeszcze raz między 02.00 a 14.00
+czasu UTC. Przepraszamy!",
+"viewsource" => "Tekst źródłowy",
+"protectedtext" => "Wyłączono możliwość edycji tej strony; istnieje kilka powodów
+dla których jest to robione - zobacz [[{{ns:4}}:Strona_zabezpieczona]]
+
+Tekst źródłowy strony można w dalszym ciągu podejrzeć i skopiować.",
+
+# Login and logout pages
+#
+"logouttitle" => "Wylogowanie użytkownika",
+"logouttext" => "Wylogowano Cię.
+Możesz kontynuować pracę z Wikipedią jako niezarejestrowany użytkownik
+albo zalogować się ponownie jako ten sam lub inny użytkownik.\n",
+
+"welcomecreation" => "<h2>Witaj, $1!</h2><p>Właśnie utworzyliśmy dla Ciebie konto.
+Nie zapomnij dostosować <i>preferencji</i>.",
+
+"loginpagetitle" => "User login",
+"yourname" => "Twój login",
+"yourpassword" => "Twoje hasło",
+"yourpasswordagain" => "Powtórz hasło",
+"newusersonly" => " (tylko nowi użytkownicy)",
+"remembermypassword" => "Pamiętaj moje hasło między sesjami.",
+"loginproblem" => "<b>Są problemy z Twoim logowaniem.</b><br />Spróbuj ponownie!",
+"alreadyloggedin" => "<strong>$1, jesteś już zalogowany!</strong><br />\n",
+
+"login" => "Zaloguj mnie",
+"userlogin" => "Logowanie",
+"logout" => "Wyloguj mnie",
+"userlogout" => "Wylogowanie",
+"notloggedin" => "Brak logowania",
+"createaccount" => "Załóż nowe konto",
+"badretype" => "Wprowadzone hasła różnią się między sobą.",
+"userexists" => "Wybrana przez Ciebie nazwa użytkownika jest już zajęta. Wybierz, proszę, inną.",
+"youremail" => "Twój e-mail*",
+"yournick" => "Twój podpis",
+"emailforlost" => "* Wpisanie adresu e-mailowego nie jest obowiązkowe. Pozwala to jednak innym użytkownikom skontaktowanie się z Tobą bez jawnej znajomości Twojego adresu. Przyda się także, gdy zapomnisz hasła - możesz wtedy poprosić o przesłanie nowego na podany adres.",
+"loginerror" => "Błąd logowania",
+"noname" => "To nie jest poprawna nazwa użytkownika.",
+"loginsuccesstitle" => "Udane logowanie",
+"loginsuccess" => "Zalogowano Cię do Wikipedii jako \"$1\".",
+"nosuchuser" => "Nie ma użytkowniku nazywającego się \"$1\".
+Sprawdź pisownię lub użyj poniższego formularza by utworzyć nowe konto.",
+"wrongpassword" => "Podane przez Ciebie hasło jest nieprawidłowe. Spróbuj jeszcze raz.",
+"mailmypassword" => "Wyślij mi nowe hasło",
+"passwordremindertitle" => "{{SITENAME}} przypomina o haśle",
+"passwordremindertext" => "Ktoś (prawdopodobnie Ty, spod adresu $1)
+poprosił od nas o wysłanie nowego hasła dostępu do Wikipedii.
+Aktualne hasło dla użytkownika \"$2\" to \"$3\".
+Najlepiej będzie jak zalogujesz się teraz i od razu zmienisz hasło.",
+"noemail" => "W bazie nie ma adresu e-mailowego dla użytkownika \"$1\".",
+"passwordsent" => "Nowe hasło zostało wysłane na adres e-mailowy użytkownika \"$1\"
+Po otrzymaniu go zaloguj się ponownie.",
+
+# Edit pages
+#
+"summary" => "Opis zmian",
+"subject" => "Temat/nagłówek",
+"minoredit" => "To jest drobna zmiana.",
+"watchthis" => "Obserwuj",
+"savearticle" => "Zapisz",
+"preview" => "Podgląd",
+"showpreview" => "Podgląd",
+"blockedtitle" => "Użytkownik jest zablokowany",
+"blockedtext" => "Twoje konto lub adres IP zostały zablokowane przez $1.
+Podany powód to:<br />$2.<p>W celu wyjaśnienia sprawy zablokowania możesz się skontaktować z $1 lub innym
+[[{{ns:4}}:Administratorzy|administratorem]].",
+"newarticle" => "(Nowy)",
+"newarticletext" => "Nie ma jeszcze artykułu o tym tytule. W poniższym polu można wpisać pierwszy jego fragment. Jeśli nie to było Twoim zamiarem, wciśnij po prostu ''Wstecz''.",
+"anontalkpagetext" => "---- ''To jest strona dyskusyjna dla użytkowników
+anonimowych - takich, którzy nie mają jeszcze swojego konta na Wikipedii lub
+nie chcą go w tej chwili używać. By ich identyfikować używamy [[IP|numerów IP]].
+Jeśli jesteś anonimowym użytkownikiem i wydaje Ci się, że zamieszczone tu komentarze
+nie są skierowane do Ciebie, [[Specjalna:Userlogin|utwórz proszę konto i/albo zaloguj się]]
+- dzięki temu unikniesz w przyszłości podobnych nieporozumień.'' ",
+"noarticletext" => "(Nie ma jeszcze artykułu o tym tytule. Wybierz ''Edytuj'' by go rozpocząć.)",
+"updated" => "(Zmodyfikowano)",
+"note" => "<strong>Uwaga:</strong> ",
+"previewnote" => "To jest tylko podgląd - artykuł nie został jeszcze zapisany!",
+"previewconflict" => "Wersja podglądana odnosi się do tekstu
+z górnego pola edycji. Tak będzie wyglądać strona jeśli zdecydujesz się ją zapisać.",
+"editing" => "Edytujesz \"$1\"",
+"editingsection" => "Edytujesz \"$1\" (fragment)",
+"editingcomment" => "Edytujesz \"$1\" (komentarz)",
+"editconflict" => "Konflikt edycji: $1",
+"explainconflict" => "Ktoś zdążył wprowadzić swoją wersję artykułu
+w trakcie Twojej edycji.
+Górne pole edycji zawiera tekst strony aktualnie zapisany w bazie danych.
+Twoje zmiany znajdują się w dolnym polu edycji.
+By wprowadzić swoje zmiany musisz zmodyfikować tekst z górnego pola.
+<b>Tylko</b> tekst z górnego pola będzie zapisany w bazie gdy wciśniesz
+\"Zapisz\".<br />",
+"yourtext" => "Twój tekst",
+"storedversion" => "Zapisana wersja",
+"editingold" => "<strong>OSTRZEŻENIE: Edytujesz inną niż bieżąca wersję tej strony.
+Jeśli zapiszesz ją wszystkie późniejsze zmiany zostaną skasowane.</strong>",
+"yourdiff" => "Różnice",
+"copyrightwarning" => "Proszę pamiętać o tym, że przyjmuje się, iż wszelki
+wkład do Wikipedii jest udostępniany na zasadach <i>GNU Free Documentation License</i>
+(szczegóły w $1).  <br />Jeśli nie chcesz, żeby Twój tekst był dowolnie zmieniany przez każdego i rozpowszechniany bez ograniczeń, nie umieszczaj go w Wikipedii.  Niniejszym jednocześnie oświadczasz, że ten tekst jest Twoim dziełem lub pochodzi z materiałów dostępnych na zasadach <i>public domain</i> albo
+licencji <i>GNU Free Documentation License</i> lub kompatybilnej.
+<br /><strong>PROSZĘ NIE UŻYWAĆ BEZ POZWOLENIA MATERIAŁÓW OBJĘTYCH PRAWEM
+AUTORSKIM!</strong>",
+"longpagewarning" => "<strong>UWAGA: Ta strona ma $1 kilobajt-y/-ów; w przypadku niektórych
+przeglądarek mogą wystąpić problemy w edycji stron mających więcej niż 32 kilobajty.
+Jeśli to możliwe, spróbuj podzielić tekst na mniejsze części.</strong>",
+"readonlywarning" => "<strong>UWAGA: Baza danych została chwilowo zablokowana do celów
+administracyjnych. Nie można więc na razie zapisać nowej wersji
+artykułu. Proponujemy przenieść jej tekst do prywatnego pliku
+(wytnij/wklej) i zachować na później.</strong>",
+"protectedpagewarning" => "<strong>UWAGA: Modyfikacja tej strony została zablokowana.
+Mogą ją edytować jedynie użytkownicy z prawami administracyjnymi.
+Upewnij się, że postępujesz zgodnie z
+[[Project:Blokowanie_stron|zasadami dotyczącymi zablokowanych stron]].</strong>",
+
+
+# History pages
+#
+"revhistory" => "Historia modyfikacji",
+"nohistory" => "Ta strona nie ma swojej historii edycji.",
+"revnotfound" => "Wersja nie została odnaleziona",
+"revnotfoundtext" => "Ta (starsza) wersja strony nie może zostać odnaleziona.
+Sprawdź proszę URL użyty przez Ciebie by uzyskać dostęp do tej strony.\n",
+"loadhist" => "Pobieranie historii tej strony",
+"currentrev" => "Aktualna wersja",
+
+"revisionasof" => "Wersja z dnia $1",
+"cur" => "bież",
+"next" => "następna",
+"last" => "poprz",
+"orig" => "oryginał",
+"histlegend" => "Legenda: (bież) = różnice z wersją bieżącą,
+(poprz) = różnice z wersją poprzedzającą, M = drobne zmiany",
+
+# Diffs
+#
+"difference" => "(Różnice między wersjami)",
+"loadingrev" => "pobieranie wersji w celu porównania",
+"lineno" => "Linia $1:",
+"editcurrent" => "Edytuj bieżącą wersję tej strony",
+
+# Search results
+#
+"searchresults" => "Wyniki wyszukiwania",
+"searchresulttext" => "Aby dowiedzieć się więcej o przeszukiwaniu Wikipedii, zobacz [[Project:Przeszukiwanie|Przeszukiwanie Wikipedii]].",
+"searchquery" => "Dla zapytania \"$1\"",
+"badquery" => "Źle sformułowane zapytanie",
+"badquerytext" => "Nie można zrealizować Twojego zapytania.
+Prawdopodobna przyczyna to obecność słowa krótszego niż trzyliterowe.
+Spróbuj, proszę, innego zapytania.",
+"matchtotals" => "Zapytanie \"$1\", liczba znalezionych tytułów: $2,
+liczba znalezionych artykułów: $3.",
+"nogomatch" => "Nie istnieją strony o dokładnie takim tytule. Spróbuj pełnego przeszukiwania. ",
+"titlematches" => "Znaleziono w tytułach:",
+"notitlematches" => "Nie znaleziono w tytułach",
+"textmatches" => "Znaleziono na stronach:",
+"notextmatches" => "Nie znaleziono w tekście stron",
+"prevn" => "poprzednie $1",
+"nextn" => "następne $1",
+"viewprevnext" => "Zobacz ($1) ($2) ($3).",
+"showingresults" => "Oto lista <b>$1</b> pozycji, poczynając od numeru <b>$2</b>.",
+"showingresultsnum" => "Oto lista <b>$3</b> pozycji, poczynając od numeru <b>$2</b>.",
+"nonefound" => "<strong>Uwaga</strong>: brak rezultatów wyszukiwania
+spowodowany jest bardzo często szukaniem najpopularniejszych słów, takich jak
+\"jest\" czy \"nie\", które nie są indeksowane, albo z powodu podania w
+zapytaniu więcej niż jednego słowa (na liście odnalezionych stron znajdą się
+tylko te, które zawierają wszystkie podane słowa).",
+"powersearch" => "Szukaj",
+"powersearchtext" => "
+Szukaj w przestrzeniach nazw :<br />
+$1<br />
+$2 Pokaż przekierowania   Szukany tekst $3 $9",
+"searchdisabled" => "<p>Ze względu na duże obciążenie serwera wyszukiwanie
+w treści artykułów zostało czasowo wyłączone; mamy nadzieję, że
+po zbliżającej się modyfikacji sprzętu możliwość ta zostanie przywrócona.
+W międzyczasie polecamy wyszukiwanie za pomocą Google:</p>
+
+",
+"blanknamespace" => "(Główna)",
+
+
+# Preferences page
+#
+"preferences" => "Preferencje",
+"prefsnologin" => "Brak logowania",
+"prefsnologintext" => "Musisz się [[Specjalna:Userlogin|zalogować]]
+przez zmianą swoich preferencji.",
+"prefslogintext" => "Zalogowano Cię jako \"$1\". Twój numer identyfikacyjny to $2.
+
+Zobacz [[{{ns:4}}:Preferencje]], aby poznać znaczenie poszczególnych opcji.",
+"prefsreset" => "Preferencje domyślne zostały odtworzone.",
+"qbsettings" => "Pasek szybkiego dostępu",
+"changepassword" => "Zmiana hasła",
+"skin" => "Skórka",
+"math" => "Prezentacja wzorów matematycznych",
+"math_failure" => "Parser nie umiał rozpoznać",
+"math_unknown_error" => "nieznany błąd",
+"math_unknown_function" => "nieznana funkcja ",
+"math_lexing_error" => "błąd leksera",
+"math_syntax_error" => "błąd składni",
+"saveprefs" => "Zapisz preferencje",
+"resetprefs" => "Preferencje domyślne",
+"oldpassword" => "Stare hasło",
+"newpassword" => "Nowe hasło",
+"retypenew" => "Powtórz nowe hasło",
+"textboxsize" => "Wymiary pola edycji",
+"rows" => "Wiersze",
+"columns" => "Kolumny",
+"searchresultshead" => "Ustawienia wyszukiwarki",
+"resultsperpage" => "Liczba wyników na stronie",
+"contextlines" => "Pierwsze wiersze artykułu",
+"contextchars" => "Litery kontekstu w linijce",
+"stubthreshold" => "Maksymalny rozmiar artykułu prowizorycznego",
+"recentchangescount" => "Liczba pozycji na liście ostatnich zmian",
+"savedprefs" => "Twoje preferencje zostały zapisane.",
+"timezonetext" => "Podaj liczbę godzin różnicy między Twoim czasem,
+a czasem uniwersalnym (UTC). Np. dla Polski jest to liczba \"2\" (czas letni)
+lub \"1\" (czas zimowy).",
+"localtime" => "Twój czas",
+"timezoneoffset" => "Różnica",
+"servertime" => "Aktualny czas serwera",
+"guesstimezone" => "Pobierz z przeglądarki",
+"emailflag" => "Nie chcę otrzymywać e-maili od innych użytkowników",
+"defaultns" => "Przeszukuj następujące przestrzenie nazw domyślnie:",
+
+# Recent changes
+#
+"changes" => "zmian-a/-y",
+"recentchanges" => "Ostatnie zmiany",
+"recentchangestext" => "Ta strona przedstawia historię ostatnich zmian w polskiej Wikipedii.
+
+[[{{ns:4}}:Powitanie nowicjuszy|Witaj]]! Jeśli jesteś tu po raz pierwszy, zapoznaj się, proszę, z tymi stronami: [[{{ns:4}}:FAQ|{{SITENAME}} FAQ]], [[{{ns:4}}:Zasady i wskazówki|polityka Wikipedii]] (a zwłaszcza [[{{ns:4}}:Nazewnictwo|konwencje nazywania stron]], [[{{ns:4}}:Neutralny punkt widzenia|neutralny punkt widzenia]]) oraz [[{{ns:4}}:Najczęstsze nieporozumienia|najczęstsze nieporozumienia]].
+
+Jeśli zależy Ci na dalszym rozwoju Wikipedii, nie dodawaj materiałów zastrzeżonych prawami autorskimi. Złamanie tej zasady mogłyby narazić projekt Wikipedii na poważne konsekwencje prawne.  Zobacz także [http://meta.wikipedia.org/wiki/Special:Recentchanges ostatnie zmiany na stronach dyskusyjnych projektu].",
+"rcloaderr" => "Ładuję ostatnie zmiany",
+"rcnote" => "To ostatnie <strong>$1</strong> zmian dokonanych na Wikipedii w ciągu ostatnich <strong>$2</strong> dni.",
+"rcnotefrom" => "Poniżej pokazano zmiany dokonane po <b>$2</b> (nie więcej niż <b>$1</b> pozycji).",
+"rclistfrom" => "Pokaż nowe zmiany począwszy od $1",
+"rclinks" => "Wyświetl ostatnie $1 zmian w ciągu ostatnich $2 dni.",
+"rchide" => "in $4 form; $1 drobnych zmian; $2 innych przestrzeni nazw; $3 wielokrotnych edycji.",
+"diff" => "różn",
+"hist" => "hist",
+"hide" => "schowaj",
+"show" => "pokaż",
+"tableform" => "tabelka",
+"listform" => "lista",
+"nchanges" => "$1 zmian",
+"minoreditletter" => "M",
+"newpageletter" => "N",
+
+# Upload
+#
+"upload" => "Prześlij plik",
+"uploadbtn" => "Prześlij plik",
+"uploadlink" => "Prześlij obrazki",
+"reupload" => "Prześlij ponownie",
+"reuploaddesc" => "Wróć do formularza wysyłki.",
+"uploadnologin" => "Brak logowania",
+"uploadnologintext" => "Musisz się [[Specjalna:Userlogin|zalogować]]
+przed przesłaniem pików.",
+"uploaderror" => "Błąd przesyłki",
+"uploadtext" => "'''STOP!''' Zanim prześlesz plik,
+przeczytaj [[Project:Zasady_dołączania_plików|zasady dołączania plików]]
+i upewnij się, że przesyłając pozostaniesz z
+nimi w zgodzie.
+
+Jeśli chcesz przejrzeć lub przeszukać dotychczas przesłane pliki,
+przejdź do [[Specjalna:Imagelist|listy dołączonych plików]].
+Wszystkie przesyłki i skasowania są odnotowane na
+specjalnych wykazach ([[Project:Dołączone|dołączone]],
+[[Project:Usunięte|usunięte]]).
+
+By przesłać nowy plik mający zilustrować Twój artykuł skorzystaj
+z poniższego formularza.
+W przypadku większości przeglądarek zobaczysz przycisk ''Browse...''
+albo ''Przeglądaj...'', który umożliwi Ci otworzenie standardowego
+okienka wyboru pliku. Wybranie pliku spowoduje umieszczenie jego nazwy
+w polu tekstowym obok przycisku.
+Musisz także zaznaczając odpowiednie pole, potwierdzić, że przesyłając
+plik nie naruszasz niczyich praw autorskich.
+Przesyłka rozpocznie się po naciśnięciu ''Prześlij plik''.
+Może zająć kilka chwil, zwłaszcza jeśli masz wolne połączenie z internetem.
+
+Preferowane formaty to JPEG dla zdjęć fotograficznych, PNG dla rysunków
+i obrazków o charakterze ikon oraz OGG dla dźwięków.
+Aby uniknąć nieporozumień nadawaj plikom nazwy związane z zawartością.
+Aby umieścić obrazek w artykule, użyj linku w postaci
+'''<nowiki>[[grafika:obrazek.jpg]]</nowiki>''' lub
+'''<nowiki>[[grafika:obrazek.png|opcjonalny tekst]]</nowiki>'''.
+Dla plików dźwiękowych link będzie miał postać '''<nowiki>[[media:file.ogg]]</nowiki>'''.
+
+Pamiętaj, proszę, że tak jak w przypadku zwykłych stron Wikipedii,
+inni użytkownicy mogą edytować lub kasować przesłane przez Ciebie pliki,
+jeśli stwierdzą, że to będzie lepiej służyć całemu projektowi.
+Twoje prawo do przesyłania może zostać Ci odebrane, jeśli nadużyjesz systemu.",
+"uploadlog" => "Wykaz przesyłek",
+"uploadlogpage" => "Dołączone",
+"uploadlogpagetext" => "Oto lista ostatnio przesłanych plików.
+Wszystkie czasy odnoszą się do strefy czasu uniwersalnego (UTC).
+<ul>
+</ul>
+",
+"filename" => "Plik",
+"filedesc" => "Opis",
+"copyrightpage" => "{{ns:4}}:Prawa_autorskie",
+"copyrightpagename" => "prawami autorskimi Wikipedii",
+"uploadedfiles" => "Przesłane pliki",
+"ignorewarning" => "Zignoruj ostrzeżenie i prześlij plik.",
+"minlength" => "Nazwa obrazku musi mieć co najmniej trzy litery.",
+"badfilename" => "Nazwę obrazku zmieniona na \"$1\".",
+"badfiletype" => "\".$1\" nie jest zalecanym formatem pliku.",
+"largefile" => "Zalecane jest aby rozmiar pliku z obrazkiem nie był większy niż 100 kilobajtów.",
+"successfulupload" => "Wysyłka powiodła się",
+"fileuploaded" => "Plik \"$1\" został pomyślnie przesłany.
+Przejdź, proszę, do strony opisu pliku ($2) i podaj dotyczące go informacje
+takie jak: pochodzenie pliku, kiedy i przez kogo został utworzony
+i cokolwiek co wiesz o pliku, a wydaje Ci się ważne.",
+"uploadwarning" => "Ostrzeżenie o przesyłce",
+"savefile" => "Zapisz plik",
+"uploadedimage" => "przesłano \"[[$1]]\"",
+"uploaddisabled" => "Przepraszamy! Możliwość przesyłania plików na ten serwer została wyłączona.",
+
+# Image list
+#
+"imagelist" => "Lista plików",
+"imagelisttext" => "To jest lista $1 plików posortowanych $2.",
+"getimagelist" => "pobieranie listy plików",
+"ilsubmit" => "Szukaj",
+"showlast" => "Pokaż ostatnie $1 plików posortowane $2.",
+"byname" => "według nazwy",
+"bydate" => "według daty",
+"bysize" => "według rozmiaru",
+"imgdelete" => "usuń",
+"imgdesc" => "opisz",
+"imglegend" => "Legenda: (opisz) = pokaż/edytuj opis pliku.",
+"imghistory" => "Historia pliku",
+"revertimg" => "przywróć",
+"deleteimg" => "usuń",
+"deleteimgcompletely" => "usuń",
+"imghistlegend" => "Legenda: (bież) = to jest obecny plik, (usuń) = usuń
+tę starszą wersję, (przywróć) = przywróć tę starszą wersję.
+<br /><i>Kliknij na datę aby zobaczyć jakie pliki przesłano tego dnia</i>.",
+"imagelinks" => "Linki do pliku",
+"linkstoimage" => "Oto strony odwołujące się do tego pliku:",
+"nolinkstoimage" => "Żadna strona nie odwołuje się do tego pliku.",
+
+# Statistics
+#
+"statistics" => "Statystyka",
+"sitestats" => "Statystyka artykułów",
+"userstats" => "Statystyka użytkowników",
+"sitestatstext" => "W bazie danych jest w sumie <b>$1</b> stron.
+Ta liczba uwzględnia strony <i>Dyskusji</i>, strony na temat samej Wikipedii,
+strony typu <i>stub</i> (prowizoryczne), strony przekierowujące, oraz inne, które trudno
+uznać za artykuły. Wyłączając powyższe, jest prawdopodobnie <b>$2</b> stron, które można uznać
+za artykuły.<p>
+Było w sumie <b>$3</b> odwiedzin oraz <b>$4</b> edycji od kiedy dokonano
+upgrade'u oprogramowania (22 listopada 2002).
+Daje to średnio <b>$5</b> edycji na jedną stronę i <b>$6</b> odwiedzin na jedną edycję.",
+"userstatstext" => "Jest <b>$1</b> zarejestrowanych użytkowników.
+Spośród nich <b>$2</b> ma status administratora (zobacz $3).",
+
+# Maintenance Page
+#
+"maintenance" => "Prosta administracja",
+"maintnancepagetext" => "Na tej stronie zgrupowano kilka użytecznych narzędzi
+pomagających w prostej administracji. Niektóre z nich obciążają bazę danych, proszę
+więc, by ich nie nadużywać.",
+"maintenancebacklink" => "Powrót do strony prostej administracji",
+"disambiguations" => "Strony ujednoznaczniające",
+"disambiguationspage" => "{{ns:4}}:Strony_ujednoznaczniające",
+"disambiguationstext" => "Poniższe artykuły odwołują się do <i>stron
+ujednoznaczniających</i>, a powinny odwoływać się bezpośrednio do hasła
+związanego z treścią artykułu.<br />Strona uznawana jest za ujednoznaczniającą
+jeśli odwołuje się do niej $1.<br />Linki z innych przestrzeni nazw <i>nie</i>
+zostały tu uwzględnione.",
+"doubleredirects" => "Podwójne przekierowania",
+"doubleredirectstext" => "<b>Uwaga:</b> Na tej liście mogą znajdować się
+przekierowania pozorne. Oznacza to, że poniżej pierwszej linii artykułu,
+zawierającej \"#REDIRECT ...\", może znajdować się dodatkowy tekst.<br />Każdy
+wiersz listy zawiera odwołania do pierwszego i drugiego przekierowania oraz
+pierwszą linię tekstu drugiego przekierowania. Umożliwia to w większości
+przypadków odnalezienie właściwego artykułu, do którego powinno się
+przekierowywać.",
+"brokenredirects" => "Zerwane przekierowania",
+"brokenredirectstext" => "Poniższe przekierowania wskazują na nieistniejące artykuły.",
+"selflinks" => "Strony zawierające odwołania do siebie samych",
+"selflinkstext" => "Poniższe strony zawierają odnośniki do samych siebie
+(co nie powinno mieć miejsca).",
+
+"mispeelings" => "Strony z błędami pisowni",
+"mispeelingstext" => "Poniższe strony zawierają najczęstsze błędy
+pisowni (ich listę można znaleźć w $1). Poprawna pisownia może być podana obok w
+nawiasach.",
+"mispeelingspage" => "Lista najczęstszych błędów pisowni",
+"missinglanguagelinks" => "Brakujące odnośniki do innych wersji językowych",
+"missinglanguagelinksbutton" => "Znajdź brakujące odnośniki, wersja",
+"missinglanguagelinkstext" => "Dla wielu artykułów istnieje wersja $1.
+Artykuły umieszczone na poniższej liście <i>nie</i> odnoszą się do swojego
+odpowiednika w tym języku. Na tej liście <i>pominięto</i> podstrony oraz przekierowania.",
+
+# Miscellaneous special pages
+#
+"orphans" => "Porzucone strony",
+"lonelypages" => "Porzucone strony",
+"unusedimages" => "Nie używane pliki",
+"popularpages" => "Najpopularniejsze strony",
+"nviews" => "odwiedzono $1 razy",
+"wantedpages" => "Najpotrzebniejsze strony",
+"nlinks" => "$1 linków",
+"allpages" => "Wszystkie strony",
+"randompage" => "Losuj stronę",
+"shortpages" => "Najkrótsze strony",
+"longpages" => "Najdłuższe strony",
+"listusers" => "Lista użytkowników",
+"specialpages" => "Strony specjalne",
+"spheading" => "Strony specjalne",
+"protectpage" => "Zabezpiecz stronę",
+"recentchangeslinked" => "Zmiany w dolinkowanych",
+"rclsub" => "(dla stron dolinkowanych do \"$1\")",
+"debug" => "Odpluskwianie",
+"newpages" => "Nowe strony",
+"ancientpages" => "Najstarsze strony",
+"movethispage" => "Przenieś",
+"unusedimagestext" => "<p>Pamiętaj, proszę, że inne witryny,
+np. Wikipedie w innych językach, mogą odwoływać się do tych plików
+używając bezpośrednio URL. Dlatego też niektóre z plików mogą się znajdować
+na tej liście mimo, że żadna strona tej Wikipedii nie odwołuje się do nich.",
+"booksources" => "Książki",
+"booksourcetext" => "Oto lista linków do innych witryn,
+które pośredniczą w sprzedaży nowych i używanych książek i mogą podać
+informacje o książkach, których szukasz.
+{{SITENAME}} nie jest stowarzyszona z żadnym ze sprzedawców,
+
+a ta lista nie powinna być interpretowana jako świadectwo udziału w zyskach.",
+"alphaindexline" => "$1 --> $2",
+
+# Email this user
+#
+"mailnologin" => "Brak adresu",
+"mailnologintext" => "Musisz się [[Specjalna:Userlogin|zalogować]]
+i mieć wpisany aktualny adres e-mailowy w swoich [[Specjalna:Preferences|preferencjach]],
+aby móc wysłać e-mail do innych użytkowników.",
+"emailuser" => "Wyślij e-mail do tego użytkownika",
+"emailpage" => "Wyślij e-mail do użytkownika",
+"emailpagetext" => "Jeśli ten użytkownik wpisał poprawny adres e-mailowy
+w swoich preferencjach, to poniższy formularz umożliwi Ci wysłanie jednej wiadomości.
+Adres e-mailowy, który został przez Ciebie wprowadzony w Twoich preferencjach
+pojawi się w polu \"Od\"; dzięki temu odbiorca będzie mógł Ci odpowiedzieć.",
+"noemailtitle" => "Brak adresu e-mailowego",
+"noemailtext" => "Ten użytkownik nie podał poprawnego adresu e-mailowego,
+albo zadecydował, że nie chce otrzymywać e-maili od innych użytkowników.",
+"emailfrom" => "Od",
+"emailto" => "Do",
+"emailsubject" => "Temat",
+"emailmessage" => "Wiadomość",
+"emailsend" => "Wyślij",
+"emailsent" => "Wiadomość została wysłana",
+"emailsenttext" => "Twoja wiadomość została wysłana.",
+
+# Watchlist
+#
+"watchlist" => "Obserwowane",
+"watchlistsub" => "(dla użytkownika \"$1\")",
+"nowatchlist" => "Nie ma żadnych pozycji na liście obserwowanych przez Ciebie stron.",
+"watchnologin" => "Brak logowania",
+"watchnologintext" => "Musisz się [[Specjalna:Userlogin|zalogować]]
+przed modyfikacją listy obserwowanych artykułów.",
+"addedwatch" => "Dodana do listy obserwowanych",
+"addedwatchtext" => "Strona \"$1\" została dodana do Twojej <a href=\"" .
+  "{{localurle:Specjalna:Watchlist}}\">listy obserwowanych</a>.
+Na tej liście znajdzie się rejestr przyszłych zmian tej strony i stowarzyszonej z nią strony Dyskusji,
+a nazwa samej strony zostanie <b>wytłuszczona</b> na <a href=\"" .
+  "{{localurle:Specjalna:Recentchanges}}\">liście ostatnich zmian</a> aby
+łatwiej było Ci sam fakt zmiany zauważyć.</p>
+
+<p>Jeśli chcesz usunąć stronę ze swojej listy obserwowanych, kliknij na
+\"Przestań obserwować\".",
+"removedwatch" => "Usunięto z listy obserwowanych",
+"removedwatchtext" => "Strona \"$1\" została usunięta z Twojej listy obserwowanych.",
+"watchthispage" => "Obserwuj",
+"unwatchthispage" => "Przestań obserwować",
+"notanarticle" => "To nie artykuł",
+
+
+"watchnochange" => "Żadna z obserwowanych stron nie była edytowana w podanym okresie.",
+"watchdetails" => "(Liczba obserwowanych przez Ciebie stron: $1, nie licząc stron dyskusji;
+liczba stron edytowanych od ostatniej cezury: $2;
+$3...
+[$4 pokaż i edytuj pełną listę].)",
+"watchmethod-recent" => "poszukiwanie ostatnich zmian wśród obserwowanych stron",
+"watchmethod-list" => "poszukiwanie obserwowanych stron wśród ostatnich zmian",
+"removechecked" => "Usuń zaznaczone pozycje z listy obserwowanych",
+"watcheditlist" => "Oto alfabetyczna lista obserwowanych stron.
+Zaznacz, które z nich mamy usunąć z listy i kliknij przycisk
+
+<i>Usuń...</i> znajdujący się na dole strony.",
+"removingchecked" => "Usuwamy zaznaczone pozycje z listy obserwowanych...",
+"couldntremove" => "Nie można było usunąć pozycji '$1'...",
+"iteminvalidname" => "Problem z pozycją '$1', niepoprawna nazwa...",
+"wlnote" => "Poniżej pokazano zmiany dokonane w ciągu ostatnich <b>$2</b> godzin (maksymalna liczba pozycji: $1).",
+
+# Delete/protect/revert
+#
+"deletepage" => "Usuń stronę",
+"confirm" => "Potwierdź",
+"excontent" => "Zawartość strony '$1'",
+"exbeforeblank" => "Poprzednia zawartość pustej strony '$1'",
+"exblank" => "Strona była pusta",
+"confirmdelete" => "Potwierdź usunięcie",
+"deletesub" => "(Usuwanie \"$1\")",
+"historywarning" => "Uwaga: Strona, którą chcesz skasować ma starsze wersje; oto ",
+"confirmdeletetext" => "Zamierzasz trwale usunąć stronę
+lub plik z bazy danych razem z dotyczącą ich historią.
+Potwierdź, proszę, swoje zamiary, tzn., że rozumiesz konsekwencje,
+i że robisz to w zgodzie z
+[[{{ns:4}}:Zasady i wskazówki|zasadami Wikipedii]].",
+"actioncomplete" => "Operacja wykonana",
+
+"deletedtext" => "Usunięto \"$1\".
+Rejestr ostatnio dokonanych kasowań możesz obejrzeć tutaj: $2.",
+"deletedarticle" => "usunięto \"$1\"",
+"dellogpage" => "Usunięte",
+"dellogpagetext" => "To jest lista ostatnio wykonanych kasowań.
+Podane czasy odnoszą się do strefy czasu uniwersalnego (UTC).
+<ul>
+</ul>
+",
+"deletionlog" => "rejestr usunięć",
+"reverted" => "Przywrócono starszą wersję",
+"deletecomment" => "Powód usunięcia",
+"imagereverted" => "Przywrócenie wcześniejszej wersji powiodło się.",
+"rollback" => "Cofnij edycję",
+"rollbacklink" => "cofnij",
+"rollbackfailed" => "Nie udało się cofnąć zmiany",
+"cantrollback" => "Nie można cofnąć edycji; jest tylko jedna wersja tej strony.",
+"alreadyrolled" => "Nie można cofnąć ostatniej zmiany strony [[$1]],
+której autorem jest [[Wikipedysta:$2|$2]] ([[Dyskusja_wikipedysty:$2|Dyskusja]]).
+Ktoś inny zdążył już to zrobić lub wprowadził własne poprawki do treści strony.
+Autorem ostatniej zmiany jest teraz [[Wikipedysta:$3|$3]] ([[Dyskusja_wikipedysty:$3|Dyskusja]]).",
+# only shown if there is an edit comment
+"editcomment" => "Opisano ją następująco: \"<i>$1</i>\".",
+"revertpage" => "Przywrócono przedostatnią wersję, jej autor to $1",
+
+# Undelete
+#
+"undelete" => "Odtwórz skasowaną stronę",
+"undeletepage" => "Odtwarzanie skasowanych stron",
+"undeletepagetext" => "Poniższe strony zostały skasowane, ale ich kopia wciąż
+znajduje się w archiwum.<br /><b>Uwaga:</b> archiwum co jakiś czas także jest kasowane!",
+"undeletearticle" => "Odtwórz skasowaną stronę",
+"undeleterevisions" => "Liczba zarchiwizowanych wersji: $1",
+"undeletehistory" => "Odtworzenie strony spowoduje przywrócenie także jej
+wszystkich poprzednich wersji. Jeśli od czasu skasowania ktoś utworzył nową stronę
+o tej nazwie, odtwarzane wersje znajdą się w jej historii, a obecna wersja
+pozostanie bez zmian.",
+"undeleterevision" => "Skasowano wersję z $1",
+"undeletebtn" => "Odtwórz!",
+"undeletedarticle" => "odtworzono \"$1\"",
+"undeletedtext" => "Pomyślnie odtworzono stronę [[$1]].
+Zobacz [[{{ns:4}}:Usunięte]], jeśli chcesz przejrzeć rejestr ostatnio
+skasowanych i odtworzonych stron.",
+
+# Contributions
+#
+"contributions" => "Wkład użytkownika",
+"mycontris" => "Moje edycje",
+"contribsub" => "Dla użytkownika $1",
+"nocontribs" => "Brak zmian odpowiadających tym kryteriom.",
+
+"ucnote" => "Oto lista ostatnich <b>$1</b> zmian dokonanych przez
+użytkownika w ciągu ostatnich <b>$2</b> dni.",
+"uclinks" => "Zobacz ostatnie $1 zmian; zobacz ostatnie $2 dni.",
+"uctop" => " (jako ostatnia)",
+
+# What links here
+#
+"whatlinkshere" => "Linkujące",
+"notargettitle" => "Wskazywana strona nie istnieje",
+"notargettext" => "Nie podano strony albo użytkownika, dla których
+ta operacja ma być wykonana.",
+"linklistsub" => "(Lista linków)",
+"linkshere" => "Do tej strony odwołują się następujące inne strony:",
+"nolinkshere" => "Do tej strony nie odwołuje się żadna inna.",
+"isredirect" => "strona przekierowująca",
+
+# Block/unblock IP
+#
+"blockip" => "Zablokuj adres IP",
+"blockiptext" => "Użyj poniższego formularza aby zablokować prawo
+zapisu spod określonego adresu IP.
+Powinno się to robić jedynie by zapobiec wandalizmowi, a zarazem
+w zgodzie z [[{{ns:4}}:Zasady i wskazówki|zasadami Wikipedii]].
+Podaj powód (np. umieszczając nazwy stron, na których dopuszczono
+się wandalizmu).",
+"ipaddress" => "Adres IP",
+"ipbreason" => "Powód",
+"ipbsubmit" => "Zablokuj ten adres",
+"badipaddress" => "Adres IP jest źle utworzony.",
+"blockipsuccesssub" => "Zablokowanie powiodło się",
+"blockipsuccesstext" => "Adres IP \"$1\" został zablokowany.
+<br />Przejdź do [[Specjalna:Ipblocklist|Listy zablokowanych adresów IP]] by przejrzeć blokady.",
+"unblockip" => "Odblokuj adres IP",
+"unblockiptext" => "Użyj poniższego formularza by przywrócić prawa zapisu
+dla poprzednio zablokowanego adresu IP.",
+"ipusubmit" => "Odblokuj ten adres",
+"ipusuccess" => "Adress IP \"$1\" został odblokowany",
+"ipblocklist" => "Lista zablokowanych adresów IP",
+"blocklistline" => "$1, $2 zablokował $3 ($4)",
+"blocklink" => "zablokuj",
+"unblocklink" => "odblokuj",
+"contribslink" => "wkład",
+
+# Developer tools
+#
+"lockdb" => "Zablokuj bazę danych",
+"unlockdb" => "Odblokuj bazę danych",
+"lockdbtext" => "Zablokowanie bazy danych uniemożliwi wszystkim użytkownikom
+edycję stron, zmianę preferencji, edycję list obserwowanych artykułów oraz inne
+czynności wymagające dostępu do bazy danych.
+Potwierdź, proszę, że to jest zgodne z Twoimi zamiarami, i że odblokujesz
+bazę danych, gdy tylko zakończysz zadania administracyjne.",
+"unlockdbtext" => "Odblokowanie bazy danych umożliwi wszystkim użytkownikom
+edycję stron, zmianę preferencji, edycję list
+obserwowanych artykułów oraz inne czynności związane ze zmianami w bazie danych.
+Potwierdź, proszę, że to jest zgodne z Twoimi zamiarami.",
+"lockconfirm" => "Tak, naprawdę chcę zablokować bazę danych.",
+"unlockconfirm" => "Tak, naprawdę chcę odblokować bazę danych.",
+"lockbtn" => "Zablokuj bazę danych",
+"unlockbtn" => "Odblokuj bazę danych",
+"locknoconfirm" => "Nie zaznaczyłeś pola potwierdzenia.",
+"lockdbsuccesssub" => "Baza danych została pomyślnie zablokowana",
+"unlockdbsuccesssub" => "Blokada bazy danych usunięta",
+"lockdbsuccesstext" => "Baza danych Wikipedii została zablokowana.
+<br />Pamiętaj usunąć blokadę po zakończeniu spraw administracyjnych.",
+"unlockdbsuccesstext" => "Baza danych Wikipedii została odblokowana.",
+
+# Move page
+#
+"movepage" => "Przenieś stronę",
+"movepagetext" => "Za pomocą poniższego formularza zmienisz nazwę strony,
+przenosząc jednocześnie jej historę.
+Pod starym tytułem zostanie umieszczona strona przekierowująca.
+Linki do starego tytułu pozostaną niezmienione.
+Upewnij się, że uwzględniasz podwójne
+lub zerwane przekierowania. Odpowiadasz za to, żeby linki odnosiły
+się do właściwych artykułów!
+
+Strona '''nie''' będzie przeniesiona jeśli:
+*jest pusta i nigdy nie była edytowana
+*jest stroną przekierowującą
+*strona o nowej nazwie już istnieje
+
+<b>UWAGA!</b>
+Może to być drastyczna lub nieprzewidywalna zmiana w przypadku popularnych stron;
+upewnij się co do konsekwencji tej operacji zanim się na nią zdecydujesz.",
+"movepagetalktext" => "Odpowiednia strona dyskusji, jeśli istnieje, będzie
+przeniesiona automatycznie, pod warunkiem, że:
+*nie przenosisz strony do innej przestrzeni nazw
+*nie istnieje strona dyskusji o nowej nazwie
+W takich przypadkach tekst dyskusji trzeba przenieść, i ewentualnie połączyć
+z istniejącym, ręcznie.
+Możesz też zrezygnować z przeniesienia dyskusji (poniższy <i>checkbox</i>).",
+"movearticle" => "Przenieś stronę",
+"movenologin" => "Brak logowania",
+"movenologintext" => "Musisz być zarejestrowanym i [[Specjalna:Userlogin|zalogowanym]]
+użytkownikiem aby móc przenieść stronę.",
+"newtitle" => "Nowy tytuł",
+"movepagebtn" => "Przenieś stronę",
+"pagemovedsub" => "Przeniesienie powiodło się",
+"pagemovedtext" => "Strona \"[[$1]]\" została przeniesiona do \"[[$2]]\".",
+"articleexists" => "Strona o podanej nazwie już istnieje albo
+wybrana przez Ciebie nazwa nie jest poprawna.
+Wybierz, proszę, nową nazwę.",
+"movedto" => "przeniesiono do",
+"movetalk" => "Przenieś także stronę <i>Dyskusji</i>, jeśli to możliwe.",
+"talkpagemoved" => "Odpowiednia strona z <i>Dyskusją</i> także została przeniesiona.",
+"talkpagenotmoved" => "Odpowiednia strona z <i>Dyskusją</i> <strong>nie</strong> została przeniesiona.",
+# Math
+'mw_math_png' => "Zawsze jako PNG",
+'mw_math_simple' => "HTML dla prostych, dla reszty PNG",
+'mw_math_html' => "Spróbuj HTML; jeśli zawiedzie, to PNG",
+'mw_math_source' => "Pozostaw w TeXu (tekst)",
+'mw_math_modern' => "HTML, dla nowszych przeglądarek",
+'mw_math_mathml' => 'MathML'
+
+);
+
+class LanguagePl extends LanguageUtf8 {
+
+       function getNamespaces() {
+               global $wgNamespaceNamesPl;
+               return $wgNamespaceNamesPl;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsPl;
+               return $wgQuickbarSettingsPl;
+       }
+
+       function getMonthNameGen( $key ) {
+               global $wgMonthNamesGenEn;
+               return wfMsg( $wgMonthNamesGenEn[$key-1] );
+       }
+
+       function date( $ts, $adj = false ) {
+               if ( $adj ) { $ts = $this->userAdjust( $ts ); }
+
+               $d = (0 + substr( $ts, 6, 2 )) .
+                 " " . $this->getMonthAbbreviation( substr( $ts, 4, 2 ) ) .
+                 " " . substr( $ts, 0, 4 );
+               return $d;
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesPl;
+               if(array_key_exists($key, $wgAllMessagesPl))
+                       return $wgAllMessagesPl[$key];
+               else
+                       return parent::getMessage($key);
+       }
+
+       # Check for Latin-2 backwards-compatibility URLs
+       function fallback8bitEncoding() {
+               return "iso-8859-2";
+       }
+
+       var $digitTransTable = array(
+               ',' => "\xc2\xa0", // @bug 2749
+               '.' => ','
+       );
+
+       function formatNum( $number ) {
+               global $wgTranslateNumerals;
+               return $wgTranslateNumerals ? strtr($number, $this->digitTransTable ) : $number;
+       }
+}
+
+?>
diff --git a/languages/LanguagePs.php b/languages/LanguagePs.php
new file mode 100644 (file)
index 0000000..ea5fa1b
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+# Stub for Pashto
+
+require_once( "LanguageUtf8.php" );
+
+class LanguagePs extends LanguageUtf8 {
+
+       function getDefaultUserOptions() {
+               $opt = Language::getDefaultUserOptions();
+               $opt["quickbar"] = 2; # Right-to-left
+               $opt["underline"] = 0; # Underline is hard to read in Arabic script
+               return $opt;
+       }
+
+       # For right-to-left language support
+       function isRTL() {
+               return true;
+       }
+}
+
+?>
diff --git a/languages/LanguagePt.php b/languages/LanguagePt.php
new file mode 100644 (file)
index 0000000..00ad827
--- /dev/null
@@ -0,0 +1,899 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+# NOTE: To turn off "Current Events" in the sidebar,
+# set "currentevents" => "-"
+
+# The names of the namespaces can be set here, but the numbers
+# are magical, so don't change or move them!  The Namespace class
+# encapsulates some of the magic-ness.
+#
+# This translation was made by Yves Marques Junqueira
+# and Rodrigo Calanca Nishino from Portuguese Wikipedia
+#
+/* private */ $wgNamespaceNamesPt = array(
+       NS_MEDIA                => "Media",
+       NS_SPECIAL              => "Especial",
+       NS_MAIN                 => "",
+       NS_TALK                 => "Discussão",
+       NS_USER                 => "Usuário",
+       NS_USER_TALK    => "Usuário_Discussão",
+       NS_PROJECT      => $wgMetaNamespace,
+       NS_PROJECT_TALK   => "{$wgMetaNamespace}_Discussão",
+       NS_IMAGE                => "Imagem",
+       NS_IMAGE_TALK           => "Imagem_Discussão",
+       NS_MEDIAWIKI    => "MediaWiki",
+       NS_MEDIAWIKI_TALK   => "MediaWiki_Discussão",
+       NS_TEMPLATE     => "Predefinição",
+       NS_TEMPLATE_TALK        => "Predefinição_Discussão",
+       NS_HELP         => "Ajuda",
+       NS_HELP_TALK    => "Ajuda_Discussão",
+       NS_CATEGORY             => "Categoria",
+       NS_CATEGORY_TALK        => "Categoria_Discussão"
+
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgQuickbarSettingsPt = array(
+       "Nada", "Fixado �  esquerda", "Fixado �  direita", "Flutuando �  Esquerda"
+);
+
+/* private */ $wgSkinNamesPt = array(
+       'standard' => "Padrão",
+       'nostalgia' => "Nostalgia",
+       'cologneblue' => "Azul Colonial"
+) + $wgSkinNamesEn;
+
+/* private */ $wgDateFormatsPt = array(
+#      "Sem preferência",
+);
+
+/* private */ $wgAllMessagesPt = array(
+# User Toggles
+"tog-underline" => "Sublinha links",
+"tog-highlightbroken" => "Formata links quebrados <a href=\"\" class=\"new\"> como isto </a> (alternative: como isto<a href=\"\" class=\"internal\">?</a>).",
+"tog-justify"   => "Justifica parágrafos",
+"tog-hideminor" => "Esconder edições secundárias em mudanças recentes",
+"tog-usenewrc" => "Mudanças recentes melhoradas(nem todos os navegadores)",
+"tog-numberheadings" => "Auto-numerar cabeçalhos",
+"tog-showtoolbar" => "Mostrar barra de edição",
+"tog-editondblclick" => "Editar páginas quando houver clique duplo(JavaScript)",
+"tog-editsection"=>"Habilitar seção de edição via links [edit]",
+"tog-editsectiononrightclick"=>"Habilitar seção de edição por clique <br /> com o botão direito no título da seção (JavaScript)",
+"tog-showtoc"=>"Mostrar Tabela de Conteúdos<br />(para artigos com mais de 3 cabeçalhos)",
+"tog-rememberpassword" => "Lembra senha entre sessões",
+"tog-editwidth" => "Caixa de edição com largura completa",
+"tog-watchdefault" => "Observa artigos novos e modificados",
+"tog-minordefault" => "Marca todas as edições como secundárias, por padrão",
+"tog-previewontop" => "Mostrar Previsão antes da caixa de edição ao invés de ser após",
+"tog-nocache" => "Desabilitar caching de página",
+# Dates
+'sunday' => 'Domingo',
+'monday' => 'Segunda',
+'tuesday' => 'Terça-Feira',
+'wednesday' => 'Quarta-Feira',
+'thursday' => 'Quinta-Feira',
+'friday' => 'Sexta-Feira',
+'saturday' => 'Sábado',
+'january' => 'Janeiro',
+'february' => 'Fevereiro',
+'march' => 'Março',
+'april' => 'Abril',
+'may_long' => 'Maio',
+'june' => 'Junho',
+'july' => 'Julho',
+'august' => 'Agosto',
+'september' => 'Setembro',
+'october' => 'Outubro',
+'november' => 'Novembro',
+'december' => 'Dezembro',
+'jan' => 'Jan',
+'feb' => 'Fev',
+'mar' => 'Mar',
+'apr' => 'Abr',
+'may' => 'Mai',
+'jun' => 'Jun',
+'jul' => 'Jul',
+'aug' => 'Ago',
+'sep' => 'Set',
+'oct' => 'Out',
+'nov' => 'Nov',
+'dec' => 'Dez',
+
+
+# Bits of text used by many pages:
+#
+"categories" => "Page categories",
+
+"category" => "category",
+"category_header" => "Articles in category \"$1\"",
+"subcategories" => "Subcategories",
+
+"linktrail"     => "/^([a-z]+)(.*)\$/sD",
+"mainpage"      => "Página principal",
+"mainpagetext"  => "Software Wiki instalado com sucesso.",
+"about"         => "Sobre",
+"aboutsite"      => "Sobre a {{SITENAME}}",
+"aboutpage"     => "{{ns:4}}:Sobre",
+"help"          => "Ajuda",
+"helppage"      => "{{ns:4}}:Ajuda",
+"bugreports"    => "Reportagem de 'bugs'",
+"bugreportspage" => "{{ns:4}}:Reportag_Bug",
+"faq"           => "FAQ",
+"faqpage"       => "{{ns:4}}:FAQ",
+"edithelp"      => "Ajuda de edição",
+"edithelppage"  => "{{ns:4}}:Como_editar_uma_página",
+"cancel"        => "Cancela",
+"qbfind"        => "Procura",
+"qbbrowse"      => "Folhear",
+"qbedit"        => "Editar",
+"qbpageoptions" => "Opções de página",
+"qbpageinfo"    => "Informação de página",
+"qbmyoptions"   => "Minhas opções",
+"mypage"        => "Minha página",
+"mytalk"        => "Minha discussão",
+"currentevents" => "Eventos atuais",
+"errorpagetitle" => "Erro",
+"returnto"      => "Retorna para $1.",
+"tagline"       => "Origem: {{SITENAME}}, a enciclopédia livre.",
+"whatlinkshere" => "Páginas que se ligam a essa",
+"help"          => "Ajuda",
+"search"        => "Busca",
+"go"        => "Vai",
+"history"       => "Histórico",
+"printableversion" => "Versão para impressão",
+"editthispage"  => "Editar esta página",
+"deletethispage" => "Apagar esta página",
+"protectthispage" => "Proteger esta página",
+"unprotectthispage" => "Desproteger esta página",
+"newpage" => "Nova página",
+"talkpage"      => "Discutir esta página",
+"postcomment"   => "Post a comment",
+"articlepage"   => "Ver atigo",
+"subjectpage"   => "Ver assunto", # For compatibility
+"userpage" => "Ver página de usuário",
+"wikipediapage" => "Ver meta página",
+"imagepage" =>  "Ver página de imagens",
+"viewtalkpage" => "Ver discussões",
+"otherlanguages" => "Outras línguas",
+"redirectedfrom" => "(Redirecionado de $1)",
+"lastmodified"  => "Está página foi modificada pela última vez em $1.",
+"viewcount"     => "Esta página foi acessada $1 vezes.",
+"printsubtitle" => "(De {{SERVER}})",
+"protectedpage" => "Página protegida",
+"administrators" => "{{ns:4}}:Administradores",
+"sysoptitle"    => "Acesso de OpSys necessário",
+"sysoptext"     => "A ação que você requisitou só pode ser
+executada por usuários com status de \"opsys\".
+Veja $1.",
+"developertitle" => "Acesso de desenvolvedor necessário",
+"developertext" => "A ação que você requisitou só pode ser
+executada por usuários com status de \"desenvolvedor\".
+Veja $1.",
+"nbytes"        => "$1 bytes",
+"go"            => "vai",
+"ok"            => "OK",
+"sitetitle"     => "{{SITENAME}}",
+"sitesubtitle"  => "A enciclopédia livre",
+"retrievedfrom" => "Retirado de  \"$1\"",
+"newmessages" => "You have $1.",
+"newmessageslink" => "novas mensagens",
+"editsection"=>"editar",
+"toc" => "Conteúdo",
+"showtoc" => "mostrar",
+"hidetoc" => "esconder",
+
+# Main script and global functions
+#
+"nosuchaction"  => "Ação não existente",
+"nosuchactiontext" => "A ação especificada pela URL não é
+reconhecida pelo programa da {{SITENAME}}",
+"nosuchspecialpage" => "Não exista esta página especial",
+"nospecialpagetext" => "Você requisitou uma página especial que não é
+reconhecida pelo software da {{SITENAME}}.",
+
+# General errors
+#
+"error"         => "Erro",
+"databaseerror" => "Erro no banco de dados",
+"dberrortext"   => "Um erro de sintaxe de busca no banco de dados ocorreu.
+A última tentativa de busca no banco de dados foi:
+<blockquote><tt>$1</tt></blockquote>
+na função \"<tt>$2</tt>\".
+MySQL retornou o erro \"<tt>$3: $4</tt>\".",
+"dberrortextcl" => "Um erro de sintaxe de pesquisa no banco
+de dados ocorreu.
+A última tentativa de pesquisa no banco de dados foi:
+\"$1\"
+com a função\"$2\".
+MySQL retornou o erro \"$3: $4\".\n",
+"noconnect"     => "Desculpe! O wiki está passando por algumas
+dificuldades técnicas, e não pode contatar o servidor de bando de dados.",
+"nodb"          => "Não foi possível selecionar o banco de dados $1",
+"cachederror"       => "O que segue é uma cópia em cache da página
+solicitada, e pode não estar atualizada.",
+"readonly"      => "Banco de dados somente para leitura",
+"enterlockreason" => "Entre com um motivo para trancá-lo, incluindo uma estimativa de quando poderá novamente ser escrito",
+"readonlytext"  => "O Banco-de-dados da {{SITENAME}} está atualmente bloqueado para novos
+artigos e outras modificações, provávelmente por uma manutenção rotineira no Bando de Dados,
+mais tarde voltará ao normal.
+
+O administrador que fez o bloqueio oferece a seguinte explicação:
+<p>$1",
+"missingarticle" => "O Banco-de-Dados não encontrou o texto de uma página
+que deveria ser encontrado, chamado \"$1\".
+
+<p>Isto é geralmente causado pela procura de um diff antigo ou um histórico que leva a uma página que foi deletada.
+
+<p>Se isto não for o caso, você pode ter encontrado um bug no software.
+Por favor, comunique isto ao administrador, tenha nota da URL.",
+"internalerror" => "Erro Interno",
+"filecopyerror" => "Não foi possível copiar o arquivo \"$1\" para \"$2\".",
+"filerenameerror" => "Não foi possível renomear o arquivo \"$1\" para \"$2\"",
+"filedeleteerror" => "Não foi possível deletar o arquivo \"$1\".",
+"filenotfound"  => "Não foi possível encontrar o arquivo \"$1\".",
+"unexpected"    => "Valor não esperado: \"$1\"=\"$2\".",
+"formerror"     => "Erro: Não foi possível enviar o formulário",
+"badarticleerror" => "Esta acção não pode ser performada nesta página.",
+"cannotdelete"  => "Não foi possível excluir página ou imagem especificada. (Ela já pode ter sido deletada por alguém.)",
+"badtitle"      => "Título ruim",
+"badtitletext"  => "O título de pagina requisitado era inválido, vazio, ou
+uma ligação incorreta de inter-linguagem ou título inter-wiki .",
+"perfdisabled" => "Desculpe! Esta opção foi temporariamente desabilitada
+porque tornava o banco de dados lento demais a ponto de impossibilitar o wiki.",
+"perfdisabledsub" => "Aqui está uma cópia salva de $1:",
+
+# Login and logout pages
+#
+"logouttitle"   => "Saída de utilizador",
+"logouttext"    => "Você agora não está mais autenticado.
+Você pode continuar a usar a {{SITENAME}} anonimamente, ou pode se autenticar
+novamente como o mesmo utilizador ou como um utilizador diferente.\n",
+
+"welcomecreation" => "<h2>Bem-vindo, $1!</h2><p>Sua conta foi criada.
+Não se esqueça de personalizar suas preferências na {{SITENAME}}.",
+
+"loginpagetitle" => "Login de usuário",
+"yourname"      => "Seu nome de usuário",
+"yourpassword"  => "Sua senha",
+"yourpasswordagain" => "Redigite sua senha",
+"newusersonly"  => " (somente novos usuários)",
+"remembermypassword" => "Lembrar de minha senha em outras sessões.",
+"loginproblem"  => "<b>Houve um problema com a sua autenticação.</b><br />Tente novamente!",
+"alreadyloggedin" => "<strong>Utilizador $1, você já está autenticado!</strong><br />\n",
+
+"login"         => "Entrar",
+"userlogin"     => "Entrar",
+"logout"        => "Sair",
+"userlogout"    => "sair",
+"notloggedin"   => "Não-logado",
+"createaccount" => "Criar nova conta",
+"createaccountmail" => "por e-Mail",
+"badretype"     => "As senhas que você digitou não são iguais.",
+"userexists"    => "O nome de usuário que você digitou já existe. Por favor, escolha um nome diferente.",
+"youremail"     => "Seu e-mail*",
+"yournick"      => "Seu apelido (para assinaturas)",
+"emailforlost"  => "* Colocar o endereço de e-mail é opcional.  Mas permite que as pessoas entrem em contato com você sem que você tenha que revelar seu e-mail �  elas, e também é útil se você se esquecer da sua senha.",
+"loginerror"    => "Erro de autenticação",
+"noname"        => "Você não colocou um nome de usuário válido.",
+"loginsuccesstitle" => "Login bem sucedido",
+"loginsuccess"  => "Agora você está logado na {{SITENAME}} como \"$1\".",
+"nosuchuser"    => "Não há nenhum usuário com o nome \"$1\".
+Verifique sua grafia, ou utilize o formulário a baixo para criar uma nova conta de usuário.",
+"wrongpassword" => "A senha que você entrou é inválida. Por favor tente novamente.",
+"mailmypassword" => "Envie uma nova senha por e-mail",
+"passwordremindertitle" => "Lembrador de senhas da {{SITENAME}}",
+"passwordremindertext" => "Alguém (provavelmente você, do endereço de IP $1)
+solicitou que nós lhe enviássemos uma nova senha para login.
+A senha para o usuário \"$2\" é a partir de agora \"$3\".
+Você pode realizar um login e mudar sua senha agora.",
+"noemail"       => "Não há nenhum e-Mail associado ao usuário \"$1\".",
+"passwordsent"  => "Uma nova senha está sendo enviada para o endereço de e-Mail
+registrado para \"$1\".
+Por favor, reconecte-se ao recebê-lo.",
+
+# Edit pages
+#
+"summary"       => "Sumário",
+"subject"       => "Assunto",
+"minoredit"     => "Edição menor",
+"watchthis"     => "Observar este artigo",
+"savearticle"   => "Salvar página",
+"preview"       => "Prever",
+"showpreview"   => "Mostrar Pré-Visualização",
+"blockedtitle"  => "Usuário está bloqueado",
+"blockedtext"   => "Seu nome de usuário ou numero de IP foi bloqueado por $1.
+O motivo é:<br />''$2''<p>Você pode contactar $1 ou outro
+[[{{ns:4}}:administradores|administrador]] para discutir sobre o bloqueio.",
+"whitelistedittitle" => "Login necessário para edição",
+"whitelistedittext" => "Você precisa se [[Especial:Userlogin|logar]] para editar artigos.",
+"whitelistreadtitle" => "Login necessário para leitura",
+"whitelistreadtext" => "Você precisa se [[Especial:Userlogin|logar]] para ler artigos.",
+"whitelistacctitle" => "Você não está habilitado a criar uma conta",
+"whitelistacctext" => "Para ter permissão para se criar uma conta neste Wiki você precisará estar [[Especial:Userlogin|logado]] e ter as permissões apropriadas.",
+"accmailtitle" => "Senha enviada.",
+"accmailtext" => "A senha de '$1' foi enviada para $2.",
+"newarticle"    => "(Novo)",
+"newarticletext" =>
+"Você seguiu um link para um artigo que não existe mais.
+Para criar a página, começe escrevendo na caixa a baixo
+(veja [[{{ns:4}}:Ajuda| a página de ajuda]] para mais informações).
+Se você chegou aqui por engano, apenas clique no botão  '''volta''' do seu navegador.",
+
+"anontalkpagetext" => "---- ''Esta é a página de discussão para um usuário anônimo que não criou uma conta ainda ou que não a usa. Então nós temos que usar o endereço numérico de IP para identificá-lo(la). Um endereço de IP pode ser compartilhado por vários usuários. Se você é um usuário anônimo e acha irrelevante que os comentários sejam direcionados a você, por favor [[Especial:Userlogin|crie uma conta ou autentifique-se]] para evitar futuras confusões com outros usuários anônimos.'' ",
+"noarticletext" => "(Não há atualmente nenhum texto nesta página)",
+"updated"       => "(Atualizado)",
+"note"          => "<strong>Nota:</strong> ",
+"previewnote"   => "Lembre-se que isto é apenas uma previsão, e não foi ainda salvo!",
+"previewconflict" => "Esta previsão reflete o texto que está na área de edição acima e como ele aparecerá se você escolher salvar.",
+"editing"         => "Editando $1",
+"editingsection"  => "Editando $1 (seção)",
+"editingcomment"  => "Editando $1 (comentário)",
+"editconflict"  => "Conflito de edição: $1",
+"explainconflict" => "Alguém mudou a página enquanto você a estava editando.
+A área de texto acima mostra o texto original.
+Suas mudanças são mostradas na área a baixo.
+Você terá que mesclar suas modificações no texto existente.
+<b>SOMENTE</b> o texto na área acima será salvo quando você pressionar \"Salvar página\".<br />",
+"yourtext"      => "Seu texto",
+"storedversion" => "Versão guardada",
+"editingold"    => "<strong>CUIDADO: Você está editando uma revisão desatualizada deste artigo.
+Se você salvá-lo, todas as mudanças feitas a partir desta revisão serão perdidas.</strong>",
+"yourdiff"      => "Diferenças",
+"copyrightwarning" => "Por favor note que todas as contribuições �  {{SITENAME}} são consideradas lançadas sobre a GNU Free Documentation License
+(veja $1 para detalhes).
+Se você não quer que seu texto esteja sobre estes termos, então não os envie.<br />
+Você também promete que está nos enviando um artigo escrito por você mesmo, ou extraindo de uma fonte de domínio público similar.
+<strong>NÃO ENVIE TRABALHO SOB COPYRIGHT SEM PERMISSÃO!</strong>",
+"longpagewarning" => "<strong>CUIDADO: Esta página tem $1 kilobytes ; alguns browsers podem ter problemas ao editar páginas maiores que 32kb.
+Por favor considere quebrar a página em sessões menores.</strong>",
+"readonlywarning" => "<strong>CUIDADO: O banco de dados está sendo bloqueado para manutenção,
+você não está habilitado a salvar suas edições. Você pode copiar e colar o texto em um arquivo de texto e salvá-lo em seu computador para adicioná-lo mais tarde.</strong>",
+"protectedpagewarning" => "<strong>CUIDADO:  Está página foi bloqueada então apenas os usuários com privilégios de sysop podem editá-la. Certifique-se de que você está seguindo o [[Project:Guia_de_páginas_protegidas|guia de páginas protegidas]].</strong>",
+
+# History pages
+#
+"revhistory"    => "Histórico de revisões",
+"nohistory"     => "Não há histórico de revisões para esta página.",
+"revnotfound"   => "Revisão não encontrada",
+"revnotfoundtext" => "A antiga revisão da página que você está procurando não pode ser encontrada.
+Por favor verifique a URL que você usou para acessar esta página.\n",
+"loadhist"      => "Carregando histórico",
+"currentrev"    => "Revisão atual",
+"revisionasof"  => "Revisão de $1",
+"cur"           => "atu",
+"next"          => "prox",
+"last"          => "ult",
+"orig"          => "orig",
+"histlegend"    => "Legenda: (atu) = diferenças da versão atual,
+(ult) = diferença da versão precedente, M = edição minoritária",
+
+# Diffs
+#
+"difference"    => "Diferença entre revisões)",
+"loadingrev"    => "carregando a busca por diferenças",
+"lineno"        => "Linha $1:",
+"editcurrent"   => "Editar a versão atual desta página",
+
+# Resultados da Busca
+#
+"searchresults" => "Buscar resultados",
+"searchresulttext" => "Para mais informações sobre busca na {{SITENAME}}, veja [[Project:Procurando|Busca na {{SITENAME}}]].",
+"searchquery"   => "Para pedido de busca \"$1\"",
+"badquery"      => "Linha de busca incorretamente formada",
+"badquerytext"  => "Nós não pudemos processar seu pedido de busca.
+Isto acoenteceu provavelmente porque você tentou procurar uma palavra de menos que três letras, coisa que o software ainda não consegue realizar. Isto também pode ter ocorrido porque você digitou incorretamente a expressão, por
+exemplo \"peixes <strong>and and</strong> scales\".
+Por favor realize ouro pedido de busca.",
+"matchtotals"   => "A pesquisa \"$1\" resultou $2 títulos de artigos
+e $3 artigos com o texto procurado.",
+"nogomatch" => "Nenhum artigo com um título exatamente igual a este foi encontrado, tentando na pesquisa completa por texto.",
+"titlematches"  => "Resultados nos títulos dos artigos",
+"notitlematches" => "Sem resultados nos títulos dos artigos",
+"textmatches"   => "Resultados nos textos dos artigos",
+"notextmatches" => "Sem resultados nos textos dos artigos",
+"prevn"         => "anterior $1",
+"nextn"         => "próximo $1",
+"viewprevnext"  => "Ver ($1) ($2) ($3).",
+"showingresults" => "Mostrando os próximos <b>$1</b> resultados começando com #<b>$2</b>.",
+"showingresultsnum" => "Mostrando <b>$3</b> resultados começando com #<b>$2</b>.",
+"nonefound"     => "<strong>Nota</strong>: pesquisas mal sucedidas são geralmente causadas devido o uso de palavras muito comuns como \"tem\" e \"de\",
+que não são indexadas, ou pela especificação de mais de um termo (somente as páginas contendo todos os termos aparecerão nos resultados).",
+"powersearch" => "Pesquisa",
+"powersearchtext" => "
+Procurar nos namespaces :<br />
+$1<br />
+$2 Lista redireciona &nbsp; Procura por $3 $9",
+"blanknamespace" => "(Principal)",
+
+# Preferences page
+#
+"preferences"   => "Preferências",
+"prefsnologin" => "Não autenticado",
+"prefsnologintext"  => "Você precisa estar [[Special:Userlogin|autenticado]]
+para definir suas preferências.",
+"prefslogintext" => "Você está autenticado como \"$1\".
+Seu número identificador interno é $2.
+
+veja [[{{ns:4}}:Ajuda_preferências_de_usuários]] para aprender a decifrar as opções.",
+"prefsreset"    => "Preferências foram reconfiguradas.",
+"qbsettings"    => "Configurações da Barra Rápida",
+"changepassword" => "Mudar senha",
+"skin"          => "Aparência(Skin)",
+"math"          => "Rendering math",
+"dateformat"    => "Formato da Data",
+"math_failure"      => "Falhou ao checar gramática(parse)",
+"math_unknown_error"    => "erro desconhecido",
+"math_unknown_function" => "função desconhecida ",
+"math_lexing_error" => "erro léxico",
+"math_syntax_error" => "erro de síntaxe",
+"saveprefs"     => "Salvar preferências",
+"resetprefs"    => "Reconfigurar preferências",
+"oldpassword"   => "Senha antiga",
+"newpassword"   => "Nova senha",
+"retypenew"     => "Redigite a nova senha",
+"textboxsize"   => "Tamanho da Caixa de texto",
+"rows"          => "Linhas",
+"columns"       => "Colunas",
+"searchresultshead" => "Configurar resultados de pesquisas",
+"resultsperpage" => "Resultados por página",
+"contextlines"  => "Linhas por resultados",
+"contextchars"  => "Letras de contexto por linha",
+"stubthreshold" => "Threshold for stub display",
+"recentchangescount" => "Número de títulos em Mudanças Recentes",
+"savedprefs"    => "Suas preferências foram salvas.",
+"timezonetext"  => "Entre com o número de horas que o seu horário local difere do horário do servidor (UTC).",
+"localtime" => "Display de hora local",
+"timezoneoffset" => "Offset",
+"servertime"    => "Horário do servidor é",
+"guesstimezone" => "Colocar no navegador",
+"emailflag"     => "Desabilitar e-mail de outros usuários",
+"defaultns"     => "Procurar nestes namespaces por padrão:",
+
+# Recent changes
+#
+"changes" => "mudanças",
+"recentchanges" => "Mudanças Recentes",
+"recentchangestext" => "Veja as mais novas mudanças na {{SITENAME}} nesta página.
+[[{{ns:4}}:Bem Vindo,_novatos|Bem Vindo, novatos]]!
+Por favor, dê uma olhada nestas páginas: [[{{ns:4}}:FAQ|FAQ da {{SITENAME}}]],
+[[{{ns:4}}:Políticas e Normas| Política da {{SITENAME}}]]
+(especialmente [[{{ns:4}}:Convenções de nomenclatura|convenções de nomenclatura]],
+[[{{ns:4}}:Ponto de vista neutro|Ponto de vista neutro]]),
+e [[{{ns:4}}:Most common {{SITENAME}} faux pas|most common {{SITENAME}} faux pas]].
+
+Se você quer ver a {{SITENAME}} crescer, é muito importante que você não adicione material restrito por outras [[{{ns:4}}:Copyrights|copyrights]].
+Um problema legal poderia realmente prejudicar o projeto de maneira que pedimos, por avor, não faça isso.
+Veja também [http://meta.wikipedia.org/wiki/Special:Recentchanges recent meta discussion].",
+"rcloaderr"     => "Carregando alterações recentes",
+"rcnote"        => "Abaixo estão as últimas <strong>$1</strong> alterações nos últimos <strong>$2</strong> dias.",
+"rcnotefrom"    => "Abaixo estão as mudanças desde <b>$2</b> (até <b>$1</b> mostradas).",
+"rclistfrom"    => "Mostrar as novas alterações a partir de $1",
+# "rclinks"     => "Mostrar as últimas $1 alterações nas últimas $2 hours / últimos $3 dias",
+# "rclinks"     => "Mostrar as últimas $1 mudanças nos últimos $2 dias.",
+"rclinks"       => "Mostrar as últimas $1 mudanças nos últimos $2 dias; $3 edições minoritárias",
+"rchide"        => "em $4 formulários; $1 edições minoritárias; $2 namespaces secundários; $3 múltiplas edições.",
+"rcliu"         => "; $1 edições de usuários autenticados",
+"diff"          => "dif",
+"hist"          => "hist",
+"hide"          => "esconde",
+"show"          => "mostra",
+"tableform"     => "tabela",
+"listform"      => "lista",
+"nchanges"      => "$1 mudanças",
+"minoreditletter" => "M",
+"newpageletter" => "N",
+
+# Upload
+#
+"upload"        => "Carregar arquivo",
+"uploadbtn"     => "Carregar arquivo",
+"uploadlink"    => "Carregar imagens",
+"reupload"      => "Re-carregar",
+"reuploaddesc"  => "Retornar ao formulário de Uploads.",
+"uploadnologin" => "Não autenticado",
+"uploadnologintext" => "Você deve estar [[Special:Userlogin|autenticado]]
+para carregar arquivos.",
+"uploaderror"   => "Erro ao Carregar",
+"uploadtext"    => "'''PARE!''' Antes de você carregar arquivos aqui,
+tenha certeza de ter lido e estar em acordo com a
+[[Project:Política_de_imagens|política de uso de imagens da {{SITENAME}}]].
+
+Para ver ou procurar imagens carregadas,
+vá � [[Special:Imagelist|lista de imagens carregadas]].
+Uploads e deleções são armazenados no
+[[Project:Upload_log|log de uploads]].
+
+Use o formulário a seguir para carregar arquivos de imagens para ilustrar seus artigos. Na maioria dos navegadores, você verá um botão \"Browse...\" , que trárá o diálogo padrão de abertura de arquivo padrão do seu Sistema Operacional.
+Ao escolher um arquivo, o campo de texto próximo ao botão será preenchido.
+Você tembém deve confirmar  que não está carregando nenhum arquivo protegido por Diretos Autorais.
+Pressione o botão \"Carregar\" para finalizar o upload.
+Isto pode demorar um pouco se você tem possui uma conexão lenta.
+
+Os formatos ideais são JPEG para fotos, PNG
+para ilustrações, e OGG para sons.
+Por favor, nomeie seus arquivos de forma descritiva para evitar confusões.
+Para incluir uma imagem em um artigo, use um link na forma
+'''<nowiki>[[image:arquivo.jpg]]</nowiki>''' ou
+'''<nowiki>[[image:arquivo.png|texto descritivo]]</nowiki>''' ou
+'''<nowiki>[[media:audio.ogg]]</nowiki> para sons.
+
+Por favor, note que com as páginas da {{SITENAME}}, outros usuários podem modificar ou deletar seus uploads se eles acharem que isto seja útil �  {{SITENAME}}, e você possa estar bloqueado para uploads devido a abusos do sistema.",
+"uploadlog"     => "log de uploads",
+"uploadlogpage" => "Log_de_Uploads",
+"uploadlogpagetext" => "Segue uma lista dos uploads mais recentes.
+Todas as datas mostradas são do servidor (UTC).
+<ul>
+</ul>
+",
+"filename"      => "Nome do arquivo",
+"filedesc"      => "Sumário",
+"copyrightpage" => "{{ns:4}}:Copyrights",
+"copyrightpagename" => "Direitos Autorais da {{SITENAME}}",
+
+"uploadedfiles" => "Arquivos carregados",
+"ignorewarning" => "Ignorar aviso e salvar de qualquer forma.",
+"minlength"     => "Os nomes das imagens devem ter ao menos três letras.",
+"badfilename"   => "O nome da imagem mudou para \"$1\".",
+"badfiletype"   => "\".$1\" não está em um formato recomendável.",
+"largefile"     => "É recomendado que as imagens não tenham mais que 100k de tamanho.",
+"successfulupload" => "Carregamento efetuado com sucesso",
+"fileuploaded"  => "Arquivo \"$1\" carregado com sucesso.
+Por favor, siga este link : ($2) para ir �  página de descrição e preencha-a com informações sobre o arquivo, como de onde veio , quando e por quem foi criada, e qualquer outra coisa a mais que você saiba.",
+"uploadwarning" => "Aviso de Upload",
+"savefile"      => "Salvar arquivo",
+"uploadedimage" => "\"[[$1]]\" carregado",
+
+# Image list
+#
+"imagelist"     => "Lista de Imagens",
+"imagelisttext" => "A seguir uma lista de $1 imagens organizadas $2.",
+"getimagelist"  => "buscando lista de imagens",
+"ilsubmit"      => "Procura",
+"showlast"      => "Mostrar as  $1 imagens organizadas $2.",
+"byname"        => "por nome",
+"bydate"        => "por data",
+"bysize"        => "por tamanho",
+"imgdelete"     => "del",
+"imgdesc"       => "desc",
+"imglegend"     => "Legenda: (desc) = mostrar/editar descrição de imagem.",
+"imghistory"    => "Histórico das imagens",
+"revertimg"     => "rev",
+"deleteimg"     => "del",
+"deleteimgcompletely"     => "del",
+"imghistlegend" => "Legenda: (cur) = esta é a imagem atual, (del) = deletar
+esta versão antiga, (rev) = reverter para esta versão antiga.
+<br /><i>Clique em data para ver das imagens carregadas nesta data</i>.",
+"imagelinks"    => "Links das imagens",
+"linkstoimage"  => "As páginas seguintes apontam para esta imagem:",
+"nolinkstoimage" => "Nenhuma página aponta para esta imagem.",
+
+# Statistics
+#
+"statistics"    => "Estatísticas",
+"sitestats"     => "Estatísticas do Site",
+"userstats"     => "Estatística dos usuários",
+"sitestatstext" => "Há atualmente um total de <b>$1</b> páginas em nosso banco de dados.
+Isto inclui páginas  \"talk\", páginas sobre a {{SITENAME}}, páginas de rascunho, redirecionamentos, e outras que provavelmente não são qualificadas como artigos.
+Excluindo estas, há <b>$2</b> páginas que provavelmente são artigos legitimos .<p>
+Há um total de <b>$3</b> páginas vistas, e <b>$4</b> edições de página
+desde a última atualização do software (Janeiro de 2004).
+O que nos leva a aproximadamente <b>$5</b> edições por página, e <b>$6</b> vistas por edição.",
+"userstatstext" => "Há atualmente <b>$1</b> usuários registrados.
+Destes, <b>$2</b> são administradores (veja $3).",
+
+# Maintenance Page
+#
+"maintenance"       => "Página de Manutenção",
+"maintnancepagetext"    => "Esta página possui diversas ferramentas úteis para a manutenção diária da {{SITENAME}}. Algumas destas funções costumam estressar o banco de dados, então, por favor, não pressione o botão de Recarregar para cada item que você consertar ;-)",
+"maintenancebacklink"   => "Voltar para a página de Manutenção",
+"disambiguations"   => "Páginas de desambiguamento",
+"disambiguationspage"   => "{{ns:4}}:Links_para_desambiguar_páginas",
+"disambiguationstext"   => "Os artigos a seguir apontam para uma <i>página de desambiguamento</i>. Ao invés disso, eles deveriam apontar para um tópico apropriado.<br /> Uma página é tratada como disambiguamento se ela é por $1.<br />Links de outros namespaces <i>não</i> estão listados aqui.",
+"doubleredirects"   => "Double Redirects",
+"doubleredirectstext"   => "<b>Atenção:</b> Esta lista pode conter positivos falsos. O que usualmente significa que há texto adicional com links depois do primeiro #REDIRECT.<br />\nCada linha contem links para o primeiro e segundo redirecionamento, bem como a primeira linha do segundo texto redirecionado , geralmente dando o artigo alvo \"real\" , para onde o primeiro redirecionamento deveria apontar.",
+"brokenredirects"   => "Redirecionamentos Quebrados",
+"brokenredirectstext"   => "Os seguintes redirecionamentos apontam para um artigo inexistente.",
+"selflinks"     => "Páginas com links próprios",
+"selflinkstext"     => "As páginas a seguir possuem links para si mesmas, o que não deveria acontecer.",
+"mispeelings"           => "Páginas com erros ortográficos",
+"mispeelingstext"               => "As páginas a seguir contém erros comuns que estão listados em $1. A ortografia correta deve ser dada (como isto).",
+"mispeelingspage"       => "Lista de erros comuns",
+"missinglanguagelinks"  => "Missing Language Links",
+"missinglanguagelinksbutton"    => "Find missing language links for",
+"missinglanguagelinkstext"      => "These articles do <i>not</i> link to their counterpart in $1. Redirects and subpages are <i>not</i> shown.",
+
+
+# Miscellaneous special pages
+#
+"orphans"       => "Páginas órfãns",
+"lonelypages"   => "Páginas órfãns",
+"unusedimages"  => "Imagens não utilizadas",
+"popularpages"  => "Páginas populares",
+"nviews"        => "$1 visitas",
+"wantedpages"   => "Páginas procuradas",
+"nlinks"        => "$1 links",
+"allpages"      => "Todas as páginas",
+"randompage"    => "Página randômica",
+"shortpages"    => "Páginas Curtas",
+"longpages"     => "Paginas Longas",
+"listusers"     => "Lista de Usuários",
+"specialpages"  => "Páginas especiais",
+"spheading"     => "Páginas especiais para todos os usuários",
+"protectpage"   => "Páginas Protegidas",
+"recentchangeslinked" => "Páginas relacionadas",
+"rclsub"        => "(para páginas linkadas de \"$1\")",
+"debug"         => "Debug",
+"newpages"      => "Páginas novas",
+"ancientpages"      => "Artigos mais antigos",
+"intl"      => "Links interlínguas",
+"movethispage"  => "Mover esta página",
+"unusedimagestext" => "<p>Por favor note que outros websites como
+as Wikipedias internacionais podem apontar para uma imagem com uma URL direta, e por isto pode estar aparecendo aqui mesmo estando em uso ativo.",
+"booksources"   => "Fontes de livros",
+"booksourcetext" => "Segue uma lista de links para outros sites que vendem livros novos e usados , e podem ter informações adicionais sobre livros que você esteja procurando.
+A {{SITENAME}} não é afiliada a nenhum destes empreendimentos, e a lista não deve ser construída  como apoio.",
+"alphaindexline" => "$1 para $2",
+
+# Email this user
+#
+"mailnologin"   => "No send address",
+"mailnologintext" => "Você deve estar [[Special:Userlogin|autenticado]]
+e ter um e-mail válido em suas [[Special:Preferences|preferências]]
+para poder enviar e-mails para outros usuários.",
+"emailuser"     => "Contactar usuário",
+"emailpage"     => "Enviar e-mail ao usuário",
+"emailpagetext" => "Se este usuário disponibilizou um endereço válido de -mail em suas preferências, o formulário a seguir enviará uma mensagem única.
+O endereço de e-mail que você disponibilizou em suas preferências aparecerá como Remetente da mensagem, então, o usuário poderá responder a você diretamente.",
+"noemailtitle"  => "Sem endereço de e-mail",
+"noemailtext"   => "Este usuário não especificou um endereço de e-mail válido, ou optou por não receber mensagens de outros usuários.",
+"emailfrom"     => "De",
+"emailto"       => "Para",
+"emailsubject"  => "Assunto",
+"emailmessage"  => "Mensagem",
+"emailsend"     => "Enviar",
+"emailsent"     => "E-mail enviado",
+"emailsenttext" => "Sua mensagem foi enviada.",
+
+# Watchlist
+#
+"watchlist"     => "Artigos do meu interesse",
+"watchlistsub"  => "(do usuário \"$1\")",
+"nowatchlist"   => "Você não está monitorando nenhum artigo.",
+"watchnologin"  => "Não está autenticado",
+"watchnologintext"  => "Você deve estar [[Special:Userlogin|autenticado]]
+para modificar sua lista de artigos interessantes.",
+"addedwatch"    => "Adicionados �  lista",
+"addedwatchtext" => "A página \"$1\" foi adicionada a sua <a href=\"{{localurle:Special:Watchlist}}\">lista de artigos de vosso interesse</a>.
+Modificações futuras neste artigo e páginas Talk associadas serão listadas aqui,
+e a página aparecerá <b>negritada</b> na <a href=\"{{localurle:Special:Recentchanges}}\">lista de mudanças recentes</a> para que
+possa pegá-lo com maior facilidade.</p>
+
+<p>Se você quiser remover futuramente o artigo da sua lista monitoramento, clique em  \"Desinteressar-se\" na barra lateral.",
+"removedwatch"  => "Removida da lista de observações",
+"removedwatchtext" => "A página \"$1\" não é mais de seu interesse e portanto foi removida de sua lista de monitoramento.",
+"watchthispage" => "Interessar-se por esta página",
+"unwatchthispage" => "Desinteressar-se",
+"notanarticle"  => "Não é um artigo",
+"watchnochange" => "Nenhum dos itens monitorados foram editados no período exibido.",
+"watchdetails" => "($1 páginas monitoradas excluindo-se as páginas talk;
+$2 páginas editadas desde data limite;
+$3...
+[$4 mostrar e editar a lista completa].)",
+"watchmethod-recent" => "checando edições recentes para os artigos monitorados",
+"watchmethod-list" => "checando páginas monitoradas de edições recentes",
+"removechecked" => "Remover itens selecionados",
+"watchlistcontains" => "Sua lista contém $1 páginas.",
+"watcheditlist" => "Aqui está uma lista alfabética de sua lista de artigos observados. Marque as caixas dos artigos que você deseja remover e clique no botão 'Remover itens selecionados' na parte de baixo da tela.",
+"removingchecked" => "Removendo os itens solicitados de sua lista de monitoramento...",
+"couldntremove" => "Não consegui remover o item '$1'...",
+"iteminvalidname" => "Problema com item '$1', nome inválido...",
+"wlnote" => "Segue as últimas $1 mudanças nas últimas <b>$2</b> horas.",
+
+
+# Delete/protect/revert
+#
+"deletepage"    => "Deletar página",
+"confirm"       => "Confirmar",
+"excontent" => "conteúdo era: '$1'",
+"exbeforeblank" => "conteúdo antes de apagar era: '$1'",
+"exblank" => "página estava vazia",
+"confirmdelete" => "Confirmar deleção",
+"deletesub"     => "(Apagando \"$1\")",
+"historywarning" => "Atenção: A página que você quer deletar tem um histório: ",
+"confirmdeletetext" => "Você está  prestes a deletar permanentemente uma página ou imagem junto com todo seu histórico do banco de dados.
+Por favor, confirme que você realmente pretende fazer isto, que você compreende as consequências, e que você está fazendo isto em acordo com a [[{{ns:4}}:Policy| Política da Wkipedia]].",
+"actioncomplete" => "Ação efetuada com sucesso",
+"deletedtext"   => "\"$1\" foi deletada.
+Veja $2 para um registro de deleções recentes.",
+"deletedarticle" => "apagado \"$1\"",
+"dellogpage"    => "Deletion_log",
+"dellogpagetext" => "Segue uma lista das deleções mais recentes.
+Todos os horários mostrados estão no horário do servidor (UTC).
+<ul>
+</ul>
+",
+"deletionlog"   => "registro de deleções",
+"reverted"      => "Revertido para versão mais nova",
+"deletecomment" => "Motivo da deleção",
+"imagereverted" => "Reversão para versão mais atual efetuada com sucesso.",
+"rollback"      => "Voltar edições",
+"rollbacklink"  => "voltar",
+"rollbackfailed" => "Rollback falhou",
+"cantrollback"  => "Não foi possível reverter a edição; o último contribuidor é o único autor deste artigo.",
+"alreadyrolled" => "Não foi possível reverter as edições de  [[$1]]
+por [[User:$2|$2]] ([[User talk:$2|Talk]]); alguém o editou ou já o reverteu.
+
+A última edição foi de  [[User:$3|$3]] ([[User talk:$3|Conversar com ele]]). ",
+#   only shown if there is an edit comment
+"editcomment" => "O comentário de edição era: \"<i>$1</i>\".",
+"revertpage"    => "Revertido para a última edição por  $1",
+
+# Undelete
+"undelete" => "Restaurar páginas deletadas",
+"undeletepage" => "Ver e restaurar páginas deletadas",
+"undeletepagetext" => "As páginas seguintes foram apagadas mas ainda permanecem no bando de dados e podem ser restauradas. O arquivo pode ser limpo periodicamente.",
+"undeletearticle" => "Restaurar artigo deletado",
+"undeleterevisions" => "$1 revisões arquivadas",
+"undeletehistory" => "Se você restaurar uma página, todas as revisões serão restauradas para o histórico.
+Se uma nova página foi criada com o mesmo nome desde a deleção, as revisões restauradas aparecerão primeiro no histórico e a página existente não será automaticamente recolocada.",
+"undeleterevision" => "Revisões deletadas de  $1",
+"undeletebtn" => "Restaurar!",
+"undeletedarticle" => " \"$1\" restaurado",
+"undeletedtext"   => "O artigo [[$1]] foi restaurado com sucesso.
+Veja [[{{ns:4}}:Deletion_log]] for a record of recent deletions and restorations.",
+
+# Contributions
+#
+"contributions" => "Contribuições de usuários",
+"mycontris" => "Minhas contribuições",
+"contribsub"    => "Para $1",
+"nocontribs"    => "Não foram encontradas mudanças com este critério.",
+"ucnote"        => "Segue as últimas  <b>$1</b> mudanças nos últimos <b>$2</b> dias do usuário.",
+"uclinks"       => "Ver as últimas $1 mudanças; ver os últimos $2 dias.",
+"uctop"     => " (topo)" ,
+
+# What links here
+#
+"whatlinkshere" => "Artigos Relacionado",
+"notargettitle" => "Sem alvo",
+"notargettext"  => "Você não especificou um alvo ou usuário para performar esta função.",
+"linklistsub"   => "(Lista de ligações)",
+"linkshere"     => "Os seguintes artigos contém ligações que apontam para cá:",
+"nolinkshere"   => "Nenhuma página relaciona-se �  esta.",
+"isredirect"    => "página de redirecionamento",
+
+# Block/unblock IP
+#
+"blockip"       => "Bloquear endereço de IP",
+"blockiptext"   => "Utilize o formulário de e-mail �  seguir para bloquear o acesso a escrita de um endereço específico de IP.
+Isto só pode ser feito para previnir vandalismo , e em acordo com a  [[{{ns:4}}:Policy|política da {{SITENAME}}]].
+Preencha com um motivo específico (por exemplo, citando páginas que sofreram vandalismo).",
+"ipaddress"     => "Endereço de IP",
+"ipbreason"     => "Motivo",
+"ipbsubmit"     => "Bloquear este endereço",
+"badipaddress"  => "O endereço de IP está mal-formado.",
+"blockipsuccesssub" => "Bloqueio bem sucedido",
+"blockipsuccesstext" => "O endereço de IP \"$1\" Foi bloqueado.
+<br />Veja [[Special:Ipblocklist|Lista de IP's bloqueados]] para rever os bloqueios.",
+"unblockip"     => "Desbloquear endereço de IP",
+"unblockiptext" => "Utilize o formulário a seguir para restaurar o acesso a escrita para um endereço de IP previamente bloqueado.",
+"ipusubmit"     => "Desbloquear este endereço",
+"ipusuccess"    => "Endereço de IP  \"$1\" foi desbloqueado",
+"ipblocklist"   => "Lista de IP's bloqueados",
+"blocklistline" => "$1, $2 bloqueado $3 ($4)",
+"blocklink"     => "block",
+"unblocklink"   => "unblock",
+"contribslink"  => "contribs",
+
+# Developer tools
+#
+"lockdb"        => "Trancar Banco de Dados",
+"unlockdb"      => "Destrancar Banco de Dados",
+"lockdbtext"    => "Trancar o banco de dados suspenderá a abilidade de todos os usuários de editarem páginas, mudarem suas preferências, lista de monitoração e  outras coisas que requerem mudanças no banco de dados.
+Por favor confirme que você realmente pretende fazer isto, e que você vai desbloquear o banco de dados quando sua manutenção estiver completa.",
+"unlockdbtext"  => "Desbloquear o banco de dados vai restaurar a abilidade de todos os usuários de editar  artigos,  mudar suas preferências, editar suas listas de monitoramento e outras coisas que requerem mudanças no banco de dados. Por favor , confirme que você realmente pretende fazer isto.",
+"lockconfirm"   => "SIM, eu realmente pretendo trancar o banco de dados.",
+"unlockconfirm" => "SIM, eu realmente pretendo destrancar o banco de dados.",
+"lockbtn"       => "Trancar banco",
+"unlockbtn"     => "Destrancar banco",
+"locknoconfirm" => "Você não checou a caixa de confirmação.",
+"lockdbsuccesssub" => "Tranca bem sucedida",
+"unlockdbsuccesssub" => "Destranca bem sucedida",
+"lockdbsuccesstext" => "O banco de dados da {{SITENAME}} foi trancado.
+<br />Lembre-se de remover a tranca após a manutenção.",
+"unlockdbsuccesstext" => "O bando de dados da {{SITENAME}} foi destrancado.",
+
+# Move page
+#
+"movepage"      => "Mover página",
+"movepagetext"  => "Usando o formulário a seguir você poderá renomear uma página , movendo todo o histórico para o novo nome.
+O título antigo será transformado num redirecionamento para o novo título.
+Links para as páginas antigas não serão mudados; certifique-se de checar redirecionamentos  quebrados ou artigos duplos.
+Você é responsável por certificar-se que os links continuam apontando para onde eles deveriam apontar.
+
+Note que a página '''não''' será movida se já existe uma página com o novo título, a não ser que ele esteja vazio ou seja um redirecionamento e não tenha histórico de edições. Isto significa que você pode renomear uma págna de volta para o nome que era antigamente se você cometer algum enganoe você não pode sobrescrever uma página.
+
+<b>!!!CUIDADO!!!</b>
+Isto pode ser uma mudança drástica e inexperada para uma página popular;
+por favor tenha certeza de que compreende as consequencias disto antes de proceder.",
+"movepagetalktext" => "A página associada, se existir, será automaticamente movida,  '''a não ser que:'''
+*Você esteja movendo uma página estre namespaces,
+*Uma página talk (não-vazia) já exista sob o novo nome, ou
+*Você não marque a caixa abaixo.
+
+Nestes casos, você terá que mover ou mesclar a página manualmente se desejar .",
+"movearticle"   => "Mover página",
+"movenologin"   => "Não Autenticado",
+"movenologintext" => "Você deve ser um usuário registrado e [[Special:Userlogin|autenticado]]
+para mover uma página.",
+"newtitle"      => "Pata novo título",
+"movepagebtn"   => "Mover página",
+"pagemovedsub"  => "Moção bem sucedida",
+"pagemovedtext" => "Página \"[[$1]]\" movida para \"[[$2]]\".",
+"articleexists" => "Uma página com este nome já existe, ou o nome que você escolheu é inválido.
+Por favor, escolha outro nome.",
+"talkexists"    => "A página em si foi movida com sucesso, porém a página talk não pode ser movida por que já existe uma com este nome. Por favor, mescle-as manualmente.",
+"movedto"       => "movido para",
+"movetalk"      => "Mover página  \"talk\" também, se aplicável.",
+"talkpagemoved" => "A página talk correspondente foi movida com sucesso.",
+"talkpagenotmoved" => "A página talk correspondente  <strong>não</strong> foi movida.",
+# Math
+'mw_math_png' => "Sempre renderizar PNG",
+'mw_math_simple' => "HTML se for bem simples e PNG",
+'mw_math_html' => "HTML se possível ou então PNG",
+'mw_math_source' => "Deixar como TeX (para navegadores em modo texto)",
+'mw_math_modern' => "Recomendado para navegadores modernos",
+'mw_math_mathml' => 'MathML',
+
+);
+
+require_once( "LanguageUtf8.php" );
+
+class LanguagePt extends LanguageUtf8 {
+
+       function getNamespaces() {
+               global $wgNamespaceNamesPt;
+               return $wgNamespaceNamesPt;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsPt;
+               return $wgQuickbarSettingsPt;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesPt;
+               return $wgSkinNamesPt;
+       }
+
+       function getDateFormats() {
+               global $wgDateFormatsPt;
+               return $wgDateFormatsPt;
+       }
+
+       function timeanddate( $ts, $adj = false ) {
+               return $this->time( $ts, $adj ) . ", " . $this->date( $ts, $adj );
+       }
+
+       function getMessage( $key ) {
+                global $wgAllMessagesPt;
+                if( isset( $wgAllMessagesPt[$key] ) ) {
+                        return $wgAllMessagesPt[$key];
+                } else {
+                        return parent::getMessage( $key );
+               }
+       }
+
+       /**
+        * Portuguese numeric format is 123 456,78
+        */
+       function formatNum( $number, $year = false ) {
+               return $year ? $number : strtr($this->commafy($number), '.,', ', ' );
+       }
+
+}
+
+?>
diff --git a/languages/LanguageRo.php b/languages/LanguageRo.php
new file mode 100644 (file)
index 0000000..d083b47
--- /dev/null
@@ -0,0 +1,1081 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+require_once("LanguageUtf8.php");
+
+/* private */ $wgNamespaceNamesRo = array(
+       NS_MEDIA                        => 'Media',
+       NS_SPECIAL                      => 'Special',
+       NS_MAIN                         => '',
+       NS_TALK                         => 'Discuţie',
+       NS_USER                         => 'Utilizator',
+       NS_USER_TALK            => 'Discuţie_Utilizator',
+       NS_PROJECT                      => $wgMetaNamespace,
+       NS_PROJECT_TALK         => 'Discuţie_'.$wgMetaNamespace,
+       NS_IMAGE                        => 'Imagine',
+       NS_IMAGE_TALK           => 'Discuţie_Imagine',
+       NS_MEDIAWIKI            => 'MediaWiki',
+       NS_MEDIAWIKI_TALK       => 'Discuţie_MediaWiki',
+       NS_TEMPLATE                     => 'Format',
+       NS_TEMPLATE_TALK        => 'Discuţie_Format',
+       NS_HELP                         => 'Ajutor',
+       NS_HELP_TALK            => 'Discuţie_Ajutor',
+       NS_CATEGORY                     => 'Categorie',
+       NS_CATEGORY_TALK        => 'Discuţie_Categorie'
+
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgQuickbarSettingsRo = array(
+       "Fără", "Fixă, în stânga", "Fixă, în dreapta", "Liberă"
+);
+
+/* private */ $wgSkinNamesRo = array(
+       'standard' => "Normală",
+       'nostalgia' => "Nostalgie"
+) + $wgSkinNamesEn;
+
+
+/* private */ $wgDateFormatsRo = array(
+#      "Nici o preferinţă",
+);
+
+/* private */ $wgMagicWordsRo = array(
+#   ID                                 CASE  SYNONYMS
+       MAG_REDIRECT             => array( 0,    "#redirect"                                       ),
+       MAG_NOTOC                => array( 0,    "__NOTOC__", "__FARACUPRINS__"                    ),
+       MAG_NOEDITSECTION        => array( 0,    "__NOEDITSECTION__", "__FARAEDITSECTIUNE__"       ),
+       MAG_START                => array( 0,    "__START__"                                       ),
+       MAG_CURRENTMONTH         => array( 1,    "CURRENTMONTH", "{{NUMARLUNACURENTA}}"            ),
+       MAG_CURRENTMONTHNAME     => array( 1,    "CURRENTMONTHNAME", "{{NUMELUNACURENTA}}"         ),
+       MAG_CURRENTDAY           => array( 1,    "CURRENTDAY", "{{NUMARZIUACURENTA}}"              ),
+       MAG_CURRENTDAYNAME       => array( 1,    "CURRENTDAYNAME", "{{NUMEZIUACURENTA}}"           ),
+       MAG_CURRENTYEAR          => array( 1,    "CURRENTYEAR", "{{ANULCURENT}}"                   ),
+       MAG_CURRENTTIME          => array( 1,    "CURRENTTIME", "{{ORACURENTA}}"                   ),
+       MAG_NUMBEROFARTICLES     => array( 1,    "NUMBEROFARTICLES", "{{NUMARDEARTICOLE}}"         ),
+       MAG_CURRENTMONTHNAMEGEN  => array( 1,    "CURRENTMONTHNAMEGEN", "{{NUMELUNACURENTAGEN}}"   ),
+       MAG_SUBST                => array( 0,    "SUBST:"                                          ),
+       MAG_MSGNW                => array( 0,    "MSGNW:", "MSJNOU:"                               ),
+       MAG_END                  => array( 0,    "__END__", "__FINAL__"                            ),
+       MAG_IMG_THUMBNAIL        => array( 1,    "thumbnail", "thumb"                              ),
+       MAG_IMG_RIGHT            => array( 1,    "right"                                           ),
+       MAG_IMG_LEFT             => array( 1,    "left"                                            ),
+       MAG_IMG_NONE             => array( 1,    "none"                                            ),
+       MAG_IMG_WIDTH            => array( 1,    "$1px"                                            ),
+       MAG_IMG_CENTER           => array( 1,    "center", "centre"                                ),
+       MAG_INT                  => array( 0,    "INT:"                                            )
+
+
+);
+
+/* private */ $wgAllMessagesRo = array(
+'1movedto2' => "$1 a fost mutată la $2",
+#'1movedto2_redir' => "$1 a fost mutată la $2 peste redirijare",
+'Monobook.js' =>
+"/* tooltips and access keys */
+ta = new Object();
+ta['pt-userpage'] = new Array('.','Pagina mea de utilizator');
+ta['pt-anonuserpage'] = new Array('.','Pagina de utilizator pentru adresa IP curentă');
+ta['pt-mytalk'] = new Array('n','Pagina mea de discuţii');
+ta['pt-anontalk'] = new Array('n','Discuţii despre editări pentru adresa IP curentă');
+ta['pt-preferences'] = new Array('','Preferinţele Mele');
+ta['pt-watchlist'] = new Array('l','Lista paginilor pe care le monitorizez.');
+ta['pt-mycontris'] = new Array('y','Listă de contribuţii');
+ta['pt-login'] = new Array('o','Eşti încurajat să te autentifici, deşi acest lucru nu este obligatoriu.');
+ta['pt-anonlogin'] = new Array('o','Eşti încurajat să te autentifici, deşi acest lucru nu este obligatoriu.');
+ta['pt-logout'] = new Array('o','Închide sesiunea');
+ta['ca-talk'] = new Array('t','Discuţie despre articol');
+ta['ca-edit'] = new Array('e','Poţi edita această pagină. Te rugăm să previzualizezi conţinutul înainte de salvare.');
+ta['ca-addsection'] = new Array('+','Adaugă un comentariu acestei discuţii.');
+ta['ca-viewsource'] = new Array('e','Aceasta pagina este protejată. Poţi sa vezi doar codul sursă.');
+ta['ca-history'] = new Array('h','Versiuni vechi ale acestui document.');
+ta['ca-protect'] = new Array('=','Protejează acest document.');
+ta['ca-delete'] = new Array('d','Şterge acest document.');
+ta['ca-undelete'] = new Array('d','Restaureaza editările făcute acestui document, înainte să fi fost şters.');
+ta['ca-move'] = new Array('m','Mută acest document.');
+ta['ca-watch'] = new Array('w','Adaugă acest document în lista ta de monitorizare.');
+ta['ca-unwatch'] = new Array('w','Şterge acest document din lista ta de monitorizare.');
+ta['search'] = new Array('f','Caută în acest Wiki');
+ta['p-logo'] = new Array('','Pagina principală');
+ta['n-mainpage'] = new Array('z','Vizitează pagina principală');
+ta['n-portal'] = new Array('','Despre proiect, ce poţi face tu, unde găseşti soluţii.');
+ta['n-currentevents'] = new Array('','Găseşte informaţii despre evenimente curente');
+ta['n-recentchanges'] = new Array('r','Lista ultimelor schimbări realizate în acest wiki.');
+ta['n-randompage'] = new Array('x','Mergi spre o pagină aleatoare');
+ta['n-help'] = new Array('','Locul în care găseşti ajutor.');
+ta['n-sitesupport'] = new Array('','Sprijină-ne');
+ta['t-whatlinkshere'] = new Array('j','Lista tuturor paginilor wiki care conduc spre această pagină');
+ta['t-recentchangeslinked'] = new Array('k','Schimbări recente în legătură cu această pagină');
+ta['feed-rss'] = new Array('','Alimentează fluxul RSS pentru această pagină');
+ta['feed-atom'] = new Array('','Alimentează fluxul Atom pentru această pagină');
+ta['t-contributions'] = new Array('','Vezi lista de contribuţii ale acestui utilizator');
+ta['t-emailuser'] = new Array('','Trimite un e-mail acestui utilizator');
+ta['t-upload'] = new Array('u','Trimite imagini sau fişiere media');
+ta['t-specialpages'] = new Array('q','Lista tuturor paginilor speciale');
+ta['ca-nstab-main'] = new Array('c','Vezi articolul');
+ta['ca-nstab-user'] = new Array('c','Vezi pagina de utilizator');
+ta['ca-nstab-media'] = new Array('c','Vezi pagina media');
+ta['ca-nstab-special'] = new Array('','Aceasta este o pagină specială, (nu) poţi edita pagina în sine.');
+ta['ca-nstab-wp'] = new Array('a','Vezi pagina proiectului');
+ta['ca-nstab-image'] = new Array('c','Vezi pagina imaginii');
+ta['ca-nstab-mediawiki'] = new Array('c','Vezi mesajul de sistem');
+ta['ca-nstab-template'] = new Array('c','Vezi formatul');
+ta['ca-nstab-help'] = new Array('c','Vezi pagina de ajutor');
+ta['ca-nstab-category'] = new Array('c','Vezi categoria');",
+'about' => "Despre",
+'aboutpage' => "Project:Despre",
+'accesskey-compareselectedversions' => "o",
+'accesskey-minoredit' => "m",
+#'accesskey-preview' => "p",
+#'accesskey-save' => "s",
+'accesskey-search' => "c",
+'accmailtext' => "Parola pentru '$1' a fost trimisă la $2.",
+'accmailtitle' => "Parola a fost trimisă.",
+#'acct_creation_throttle_hit' => "Ne pară rău, ai creat deja $1 conturi. Nu poţi să-ţi mai faci altul.",
+'actioncomplete' => "Acţiune finalizată",
+'addedwatch' => "Adăugată la lista de pagini urmărite",
+'addedwatchtext' => "Pagina \"$1\" a fost adăugată la lista ta de <a href=\"/wiki/Special:Watchlist\">articole urmărite</a>.
+Modificările viitoare ale acestei pagini şi a paginii asociate de discuţii
+vor fi listate aici, şi în plus ele vor apărea cu <b>caractere îngroşate</b> în pagina de <a href=\"/wiki/Special:Recentchanges\">modificări recente</a> pentru evidenţiere.</p>
+
+<p>Dacă doreşti să elimini această pagină din lista ta de pagini urmărite
+în viitor, apasă pe \"Nu mai urmări\" în bara de comenzi în timp ce această pagină este vizibilă.",
+#'addsection' => "+",
+'administrators' => "Project:Administratori",
+'allmessages' => "Toate_mesajele",
+'allmessagestext' => "Aceasta este lista completă a mesajelor disponibile în domeniul \"MediaWiki:\"",
+'allpages' => "Toate paginile",
+'alphaindexline' => "$1 către $2",
+'alreadyloggedin' => "<strong>Eşti deja autentificat ca $1!</strong><br />
+",
+'alreadyrolled' => "Nu se poate reveni peste ultima editare a [[$1]]
+făcută de către [[Utilizator:$2|$2]] ([[Discuţie utilizator:$2|Discuţie]]); altcineva a editat articolul sau a revenit deja.
+
+Ultima editare a fost făcută de către [[Utilizator:$3|$3]] ([[Discuţie utilizator:$3|Discuţie]]).",
+'ancientpages' => "Cele mai vechi articole",
+'and' => "şi",
+'anontalk' => "Discuţia pentru această adresă IP",
+'anontalkpagetext' => "---- ''Aceasta este pagina de discuţii pentru un utilizator care nu şi-a creat un cont încă, sau care nu s-a autentificat. De aceea trebuie să folosim [[adresă IP|adresa IP]] pentru a identifica această persoană. O adresă IP poate fi împărţită între mai mulţi utilizatori. Dacă eşti un astfel de utilizator şi crezi că îţi sunt adresate mesaje irelevante, te rugăm să-ţi [[Special:Userlogin|creezi un cont sau să te autentifici]] pentru a evita confuzii cu alţi utilizatori anonimi în viitor.''",
+'anonymous' => "Utilizator(i) anonimi ai {{SITENAME}}",
+'article' => "Articol",
+'articleexists' => "O pagină cu acelaşi nume există deja,
+sau numele pe care l-ai ales este invalid. Te rugăm să alegi un alt nume.",
+'articlepage' => "Vezi articolul",
+'autoblocker' => "Autoblocat fiindcă foloseşti aceeaşi [[adresă IP]] ca şi \"$1\". Motivul este \"$2\".",
+'badarticleerror' => "Această acţiune nu poate fi efectuată pe această pagină.",
+'badfilename' => "Numele imaginii a fost schimbat; noul nume este \"$1\".",
+'badfiletype' => "\".$1\" nu este un format recomandat pentru imagini.",
+'badipaddress' => "Adresa IP este invalidă.",
+'badquery' => "Căutare invalidă",
+'badquerytext' => "Căutarea ta nu a putut fi procesată.
+Asta se întâmplă probabil din cauză că ai încercat să cauţi un cuvânt cu mai puţin de trei litere.
+E posibil şi să fi scris greşit o expresie sau un nume, cum ar fi \"Mircea cel cel Bătrân\".
+Te rugăm să încerci încă o dată.",
+'badretype' => "Parolele pe care le-ai introdus diferă.",
+'badtitle' => "Titlu invalid",
+'badtitletext' => "Titlul căutat a fost invalid, gol sau o legătură invalidă inter-linguală sau inter-wiki.",
+'blanknamespace' => "(Principală)",
+'blockedtext' => "Utilizatorul sau parola ta au fost blocate de $1.
+Motivul oferit pentru blocare a fost:<br />''$2''<p>Îl poţi contacta pe $1 sau pe unul dintre ceilalţi
+[[Project:administratori|administratori]] pentru a discuta această blocare.",
+'blockedtitle' => "Utilizatorul este blocat",
+'blockip' => "Blocheză adresa IP",
+'blockipsuccesssub' => "Utilizatorul a fost blocat",
+'blockipsuccesstext' => "Adresa IP \"$1\" a fost blocată.
+<br />Vezi [[Special:Ipblocklist|lista de adrese IP blocate]] pentru a revizui adresele blocate.",
+'blockiptext' => "Foloseşte chestionarul de mai jos pentru a bloca
+la scriere o adresă IP. Această funcţie trebuie folosită numai pentru
+a preveni vandalismul conform [[Project:Politica|politicii {{SITENAME}}]].
+Include un motiv specific mai jos (de exemplu citează paginile care
+au fost vandalizate de acest utilizator).",
+'blocklink' => "blochează",
+'blocklistline' => "$1, $2 a blocat $3 ($4)",
+'blocklogentry' => "blocat \"$1\"",
+'blocklogpage' => "Jurnal_blocări",
+'blocklogtext' => "Acesta este un jurnal al acţiunilor de blocare şi deblocare.
+[[Adresă IP|Adresele IP]] blocate automat nu sunt afişate.
+Vezi [[Special:Ipblocklist|Lista de adrese blocate]] pentru o listă explicită a adreselor blocate în acest moment.",
+'bold_sample' => "Text aldin",
+'bold_tip' => "Text aldin",
+'booksources' => "Surse de cărţi",
+'booksourcetext' => "Dedesubt găseşti o listă de surse de cărţi noi şi vechi, şi e posibil să găseşti şi informaţii adiţionale legate de titlurile pe care le cauţi.
+{{SITENAME}} nu este afiliat(ă) nici uneia dintre aceste afaceri,
+iar lista de mai jos nu constituie nici un fel de garanţie sau validare a serviciilor respective din partea {{SITENAME}}.",
+'brokenredirects' => "Redirijări greşite",
+'brokenredirectstext' => "Următoarele redirijări conduc spre articole inexistente.",
+'bugreports' => "Raportare probleme",
+'bugreportspage' => "Project:Rapoarte_probleme",
+'bureaucratlog' => "Raport_birocrat",
+'bureaucratlogentry' => "Drepturile pentru utilizatorul \"$1\" setate \"$2\"",
+'bydate' => "după dată",
+'byname' => "după nume",
+'bysize' => "după mărime",
+'cachederror' => "Aceasta este o versiune din cache a paginii cerute şi este posibil să nu fie ultima variantă a acesteia.",
+'cancel' => "Renunţă",
+'cannotdelete' => "Nu s-a putut şterge pagina sau imaginea (poate a şters-o altcineva deja?)",
+'cantrollback' => "Nu se poate reveni; ultimul contribuitor este autorul acestui articol.",
+'categories' => "Categorii de pagini",
+'category' => "categorie",
+'category_header' => "Articole din categoria \"$1\"",
+#'categoryarticlecount' => "Sunt $1 articole în această categorie.",
+'changepassword' => "Schimbă parola",
+'changes' => "schimbări",
+#'clearyourcache' => "'''Notă:''' După salvare, poţi să-ţi goleşti fişierele din cache pentru a vedea schimbările: '''Mozilla:''' apasă ''ctrl-shift-r'', '''IE:''' ''ctrl-f5'', '''Safari:''' ''cmd-shift-r'', '''Konqueror''' ''f5''.",
+'columns' => "Coloane",
+'commentedit' => " (comentariu)",
+'compareselectedversions' => "Compară versiunile selectate",
+'confirm' => "Confirmă",
+'confirmdelete' => "Confirmă ştergere",
+'confirmdeletetext' => "Eşti pe cale să ştergi permanent o pagină
+sau imagine din baza de date, împreună cu istoria asociată.
+Te rugăm să îţi confirmi intenţia de a face asta, faptul că
+înţelegi consecinţele acestei acţiuni şi faptul că o faci
+în conformitate cu [[Project:Politica]].",
+'confirmprotect' => "Confirmă protejare",
+'confirmprotecttext' => "Eşti sigur(ă) că doreşti să protejezi pagina?",
+'confirmunprotect' => "Confirmă deprotejarea",
+'confirmunprotecttext' => "Eşti sigur(ă) că doreşti să deprotejezi pagina?",
+'contextchars' => "Numărul de caractere per linie",
+'contextlines' => "Numărul de linii per rezultat",
+'contribslink' => "contribuţii",
+'contribsub' => "Pentru $1",
+'contributions' => "Contribuţii ale utilizatorului",
+'copyright' => "Conţinutul este disponibil sub <A href='/wiki/GNU_FDL'>Licenţa GNU pentru documentaţie liberă</a>.",
+'copyrightpage' => "Project:Drepturi_de_autor",
+'copyrightpagename' => "Drepturi de autor în {{SITENAME}}",
+'copyrightwarning' => "Reţine că toate contribuţiile la {{SITENAME}} sunt considerate ca respectând licenţa GNU Free Documentation License
+(vezi $1 pentru detalii).
+Dacă nu doreşti ca ceea ce scrieţi să fie editat fără milă şi redistribuit în voie, atunci nu trimite materialele respective aici.<br />
+De asemenea, trimiţând aceste materiale aici te angajezi că le-ai scris tu sau că sunt copiate dintr-o sursă care permite includerea materialelor sub această licenţă.
+<strong>NU TRIMITE MATERIALE PROTEJATE DE DREPTURI DE AUTOR FĂRĂ PERMISIUNE!</strong>",
+'couldntremove' => "Elementul '$1' nu a putut fi şters...",
+'createaccount' => "Creează cont nou",
+'createaccountmail' => "după e-mail",
+#'creditspage' => "Credits",
+'cur' => "actuală",
+'currentevents' => "Discută la cafenea",
+'currentrev' => "Versiunea curentă",
+'databaseerror' => "Eroare la baza de date",
+'dateformat' => "Formatul datelor",
+'dberrortext' => "A apărut o eroare în execuţia query-ului.
+Aceasta se poate datora unui query ilegal (vezi $5),
+sau poate indica o problemă în program.
+Ultimul query încercat a fost:
+<blockquote><tt>$1</tt></blockquote>
+în cadrul funcţiei \"<tt>$2</tt>\".
+MySQL a returnat eroarea \"<tt>$3: $4</tt>\".",
+'dberrortextcl' => "A apărut o eroare de sintaxă în query.
+Ultimul query încercat a fost:
+\"$1\"
+din funcţia \"$2\".
+MySQL a returnat eroarea \"$3: $4\".
+",
+'deadendpages' => "Pagini fără legături",
+#'debug' => "Debug",
+'defaultns' => "Caută în aceste secţiuni implicit:",
+'defemailsubject' => "E-mail {{SITENAME}}",
+'delete' => "Ştergere",
+'deletecomment' => "Motiv pentru ştergere",
+'deletedarticle' => "\"$1\" a fost şters",
+'deletedtext' => "\"$1\" a fost ştearsă.
+Vezi $2 pentru o listă a elementelor şterse recent.",
+'deleteimg' => "şterg",
+'deleteimgcompletely' => "şterg",
+'deletepage' => "Şterge pagina",
+'deletesub' => "(Şterg \"$1\")",
+'deletethispage' => "Şterge pagina",
+'deletionlog' => "raport de ştergeri",
+'dellogpage' => "Raport_ştergeri",
+'dellogpagetext' => "Găseşti dedesubt o listă a celor mai recente elemente şterse. Toate datele/orele sunt listate în timp universal (UTC).
+<ul>
+</ul>
+",
+'developertext' => "Acţiunea pe care ai încercat-o necesită drepturi de dezvoltator.
+Vezi $1.",
+'developertitle' => "Ai nevoie de acces ca dezvoltator",
+'diff' => "diferenţă",
+'difference' => "(Diferenţa dintre versiuni)",
+'disambiguations' => "Pagini de dezambiguizare",
+'disambiguationspage' => "Project:Legături_către_paginile_de_dezambiguizare",
+'disambiguationstext' => "Următoarele articole conţin legături către cel puţin o <i>pagină de dezambiguizare</i>. Legăturile respective ar trebui făcute către paginile specifice.<br />O pagină este considerată ca fiind de dezambiguizare dacă există o legătură în ea dinspre $1.<br />Legăturile dinspre alte secţiuni {{SITENAME}} <i>nu sunt</i> luate în considerare aici.",
+'disclaimerpage' => "Project:General_disclaimer",
+'disclaimers' => "Disclaimer",
+'doubleredirects' => "Redirijări duble",
+'doubleredirectstext' => "<b>Atenţie:</b> Această listă poate conţine articole care nu sunt în fapt duble redirijări. Asta înseamnă de obicei că există text adiţional sub primul #REDIRECT.<br />
+Fiecare rând care conţine legături către prima sau a doua redirijare, ca şi prima linie din textul celei de-a doua redirijări, de obicei conţinând numele \"real\" al articolului ţintă, către care ar trebui să arate prima redirijare.",
+'edit' => "Editează pagina",
+'editcomment' => "Comentariul de editare a fost: \"<i>$1</i>\".",
+'editconflict' => "Conflict de editare: $1",
+'editcurrent' => "Editarea versiunii curente a acestei pagini",
+'edithelp' => "Ajutor pentru editare",
+'edithelppage' => "Project:Cum_să_editezi_o_pagină",
+'editing' => "Editare $1",
+'editingold' => "<strong>ATENŢIE! Editezi o variantă mai veche a acestei pagini! Orice modificări care s-au făcut de la această versiune şi până la cea curentă se vor pierde!</strong>",
+'editsection' => "editează",
+'editthispage' => "Editează pagina",
+'emailflag' => "Dezactivează serviciul de e-mail de la alţi utilizatori",
+'emailforlost' => "Dacă ţi-ai pierdut parola, poţi cere să ţi se trimită una nouă la adresa de e-mail.",
+'emailfrom' => "De la",
+'emailmessage' => "Mesaj",
+'emailpage' => "E-mail către utilizator",
+'emailpagetext' => "Dacă acest utilizator a introdus o adresă de e-mail validă în pagina de preferinţe atunci formularul de mai jos poate fi folosit pentru a-i trimte un mesaj prin e-mail.
+Adresa pe care ai introdus-o în pagina ta de preferinţe va apărea ca adresa
+de origine a mesajului, astfel încât destinatarul să îţi poată răspunde direct.",
+'emailsend' => "Trimite",
+'emailsent' => "E-mail trimis",
+'emailsenttext' => "E-mailul tău a fost trimis.",
+'emailsubject' => "Subiect",
+'emailto' => "Către",
+'emailuser' => "Trimite e-mail acestui utilizator",
+#'emptyfile' => "Fişierul pe care l-ai trimis pare să fie gol. Acest lucru s-ar putea datora unei greşeli în numele fişierului. Verifică acest lucru dacă mai doreşti să trimiţi fişierul.",
+'enterlockreason' => "Introdu motivul pentru blocare, incluzând o estimare a termenului de deblocare a bazei de date",
+'error' => "Eroare",
+'errorpagetitle' => "Eroare",
+'exbeforeblank' => "conţinutul înainte de golire era: '$1'",
+'exblank' => "pagina era goală",
+'excontent' => "conţinutul era: '$1'",
+'explainconflict' => "Altcineva a modificat această pagină de când ai început să o editezi.
+Caseta de text de sus conţine pagina aşa cum este ea acum (după editarea celeilalte persoane).
+Pagina cu modificările tale (aşa cum ai încercat să o salvezi) se află în caseta de jos.
+Va trebui să editezi manual caseta de sus pentru a reflecta modificările pe care tocmai le-ai făcut în cea de jos.
+<b>Numai</b> textul din caseta de sus va fi salvat atunci când vei apăsa pe  \"Salvează pagina\".<br />",
+'export' => "Exportă pagini",
+'exportcuronly' => "Include numai versiunea curentă, nu şi toată istoria",
+'exporttext' => "Poţi exporta textul şi istoria unei pagini anume sau ale unui grup
+de pagini în XML. Acesta poate fi apoi importat în alt Wiki care rulează software MediaWiki,
+pate fi transformat sau păstrat pur şi simplu fiindcă doreşti tu să-l păstrezi.",
+'extlink_sample' => "http://www.exemplu.ro titlul legăturii",
+'extlink_tip' => "Legătură externă (nu uita prefixul http://)",
+'faq' => "Întrebări frecvente",
+'faqpage' => "Project:Întrebări frecvente",
+#'feedlinks' => "Alimentare flux:",
+'filecopyerror' => "Fişierul \"$1\" nu a putut fi copiat la \"$2\".",
+'filedeleteerror' => "Fişierul \"$1\" nu a putut fi şters.",
+'filedesc' => "Sumar",
+#'fileexists' => "Un fişier cu acest nume există deja, vezi $1 dacă nu eşti sigur că vrei să-l modifici.",
+'filename' => "Nume fişier",
+'filenotfound' => "Fişierul \"$1\" nu a putut fi găsit.",
+'filerenameerror' => "Fişierul \"$1\" nu a putut fi mutat la \"$2\".",
+'filesource' => "Sursa",
+'filestatus' => "Statutul drepturilor de autor",
+'fileuploaded' => "Fişierul \"$1\" a fost trimis.
+Te rugăm să vizitezi această legătură: ($2) pentru a descrie fişierul şi pentru a completa informaţii despre acesta, ca de exemplu de unde provine, când a fost creat şi de către cine, cât şi orice alte informaţii doreşti să le adaugi.",
+'formerror' => "Eroare: datele nu au putut fi trimise",
+'getimagelist' => "încarc lista de imagini",
+'go' => "Du-te",
+'guesstimezone' => "Încearcă determinarea automată a diferenţei",
+'headline_sample' => "Text de titlu",
+'headline_tip' => "Titlu de nivel 2",
+'help' => "Ajutor",
+'helppage' => "Project:Ajutor",
+'hide' => "ascunde",
+'hidetoc' => "ascunde",
+'hist' => "istorie",
+'histlegend' => "Legendă: (actuală) = diferenţe faţă de versiunea curentă,
+(prec) = diferenţe faţă de versiunea precedentă, M = editare minoră",
+'history' => "Versiuni mai vechi",
+#'history_copyright' => "-",
+'history_short' => "Istoric",
+'historywarning' => "Atenţie! Pagina pe care o ştergi are istorie: ",
+'hr_tip' => "Linie orizontală (foloseşte-o cumpătat)",
+'ignorewarning' => "Ignoră atenţionarea şi salvează.",
+#'illegalfilename' => "Numele fişierului \"$1\" conţine caractere care nu sunt permise în titlurile paginilor. Redenumeşte fişierul şi încearcă să-l trimiţi din nou.",
+'ilsubmit' => "Caută",
+'image_sample' => "Exemplu.jpg",
+'image_tip' => "Inserează imagine",
+'imagelinks' => "Legăturile imaginii",
+'imagelist' => "Lista imaginilor",
+'imagelisttext' => "Dedesubt găseşti lista a $1 imagini ordonate $2.",
+'imagepage' => "Vezi pagina imaginii",
+'imagereverted' => "S-a revenit la o versiune veche.",
+'imgdelete' => "şterge",
+#'imgdesc' => "desc",
+'imghistlegend' => "Legendă: (actuală) = versiunea curentă a imaginii, (şterg) = şterge această versiune veche, (rev) = revino la această versiune veche.
+<br /><i>Apasă pe dată pentru a vedea versiunea trimisă la data respectivă</i>.",
+'imghistory' => "Istoria imaginii",
+'imglegend' => "Legendă: (desc) = arată/editează descrierea imaginii.",
+'import' => "Importă pagini",
+'importfailed' => "Import eşuat: $1",
+'importhistoryconflict' => "Există istorii contradictorii (se poate să fi importat această pagină înainte)",
+'importnotext' => "Gol sau fără text",
+'importsuccess' => "Import reuşit!",
+'importtext' => "Te rog exportă fişierul din sursa wiki folosind funcţia Special:Export, salvează-l pe discul tău şi încarcă-l aici.",
+#'info_short' => "Informaţii",
+'infobox' => "Apasă acest buton pentru a vedea un exemplu de text",
+'infobox_alert' => "Introdu textul pe care vrei să-l formatezi.\n Va apărea în infobox pentru copiere şi lipire.\nExemplu:\n$1\nva deveni:\n$2",
+#'infosubtitle' => "Informaţii pentru pagină",
+'internalerror' => "Eroare internă",
+'intl' => "Legături între limbi",
+'ip_range_invalid' => "Serie IP invalidă.",
+'ipaddress' => "Adresa IP",
+'ipb_expiry_invalid' => "Dată de expirare invalidă.",
+'ipbexpiry' => "Expiră",
+'ipblocklist' => "Lista de adrese IP blocate",
+'ipbreason' => "Motiv",
+'ipbsubmit' => "Blochează această adresă",
+'ipusubmit' => "Deblochează adresa",
+'ipusuccess' => "Adresa IP \"$1\" a fost deblocată",
+#'isbn' => "ISBN",
+'isredirect' => "pagină de redirijare",
+'italic_sample' => "Text cursiv",
+'italic_tip' => "Text cursiv",
+'iteminvalidname' => "E o problemă cu elementul '$1', numele este invalid...",
+'largefile' => "Este recomandat ca imaginile să nu depăşească 100 KB ca mărime.",
+'last' => "prec",
+'lastmodified' => "Ultima modificare $1.",
+#'lastmodifiedby' => "Această pagină a fost modificată ultima dată la $1 de către $2.",
+'lineno' => "Linia $1:",
+'link_sample' => "Titlul legăturii",
+'link_tip' => "Legătură internă",
+'linklistsub' => "(Lista de legături)",
+'linkshere' => "Următoarele pagini conţin legături către aceasta:",
+'linkstoimage' => "Următoarele pagini leagă la această imagine:",
+#'linktrail' => "/^([a-z]+)(.*)$/sD",
+'listform' => "listă",
+'listusers' => "Lista de utilizatori",
+'loadhist' => "Încarc istoria versiunilor",
+'loadingrev' => "se încarcă diferenţa dintre versiuni",
+'localtime' => "Ora locală",
+'lockbtn' => "Blochează baza de date",
+'lockconfirm' => "Da, chiar vreau să blochez baza de date.",
+'lockdb' => "Blochează baza de date",
+'lockdbsuccesssub' => "Baza de date a fost blocată",
+'lockdbsuccesstext' => "Baza de date {{SITENAME}} a fost blocată la scriere.
+<br />Nu uita să o deblochezi după ce termini operaţiunile administrative pentru care ai blocat-o.",
+'lockdbtext' => "Blocarea bazei de date va împiedica pe toţi utilizatorii
+să editeze pagini, să-şi schimbe preferinţele, să-şi editeze listele de
+pagini urmărite şi orice alte operaţiuni care ar necesita schimări
+în baza de date.
+Te rugăm să confirmi că intenţionezi acest lucru şi faptul că vei debloca
+baza de date atunci când vei încheia operaţiunile de întreţinere.",
+'locknoconfirm' => "Nu ai confirmat căsuţa de confirmare.",
+'login' => "Autentificare",
+'loginend' => "Pentru a crea un cont de utilizator, introdu [[Project:Nume de utilizator|numele de utilizator]] şi parola, apoi fă clic pe \"Creează cont nou\". Evită folosirea numelui unei personalităţi politice, militare sau religioase, sau a unui eveniment. Evită numele de utilizator care sunt ofensive, dăunătoare sau confuze. Te rugăm să alegi un nume citeţ, nu doar un număr.
+
+Dacă ai nevoie de mai multe informaţii asupra modului de înregistrare, vezi articolul [[Project:Cum mă înregistrez|Cum mă înregistrez]].<br /><br />
+
+După ce te înregistrezi, pentru a te autentifica dăţile viitoare când vizitezi {{SITENAME}}, va trebui să introduci doar numele de utilizator şi parola.<br /><br />
+
+*Introducerea unei adrese de e-mail este opţională, nefiind necesară o confirmare pe e-mail în prealabil. Totuşi, aceasta permite oamenilor să te contacteze prin intermediul acestui sit web, fără să ţi-o afle şi te ajută şi în cazul în care ţi-ai uitat parola.",
+'loginerror' => "Eroare de autentificare",
+'loginpagetitle' => "Autentificare utilizator",
+'loginproblem' => "<b>A fost o problemă cu autentificarea ta</b><br />Încearcă din nou!",
+'loginprompt' => "Trebuie să ai modulele cookie activate pentru a te autentifica la {{SITENAME}}.",
+'loginreqtext' => "Trebuie să te [[special:Userlogin|autentifici]] pentru a vizualiza alte pagini.",
+'loginreqtitle' => "Necesită Autentificare",
+'loginsuccess' => "Ai fost autentificat în {{SITENAME}} ca \"$1\".",
+'loginsuccesstitle' => "Autentificare reuşită",
+'logout' => "Închide sesiunea",
+'logouttext' => "Sesiunea ta în {{SITENAME}} a fost închisă.
+Poţi continua să foloseşti {{SITENAME}} anonim, sau poţi să te reautentifici ca acelaşi sau ca alt utilizator.
+",
+'logouttitle' => "Sesiune închisă",
+'lonelypages' => "Pagini orfane",
+'longpages' => "Pagini lungi",
+'longpagewarning' => "<strong>ATENŢIE! Conţinutul acestei pagini are $1 KB; unele browsere au probleme la editarea paginilor în jur de 32 KB sau mai mari.
+Te rugăm să iei în considerare posibilitatea de a împărţi pagina în mai multe secţiuni.</strong>",
+'mailerror' => "Eroare la trimitere e-mail: $1",
+'mailmypassword' => "Trimite-mi parola pe e-mail!",
+'mailnologin' => "Nu există adresă de trimitere",
+'mailnologintext' => "Trebuie să fii [[Special:Userlogin|autentificat]]
+şi să ai o adresă validă de e-mail în [[Special:Preferences|preferinţe]]
+pentru a trimite e-mail altor utilizatori.",
+'mainpage' => "Pagina principală",
+'mainpagedocfooter' => "Vezi [http://meta.wikipedia.org/wiki/MediaWiki_i18n documentaţia asupra costumizării interfeţei]
+şi [http://meta.wikipedia.org/wiki/MediaWiki_User%27s_Guide Ghidul de utilizator] pentru ajutor de utilizare şi configurare.",
+'mainpagetext' => "Programul Wiki a fost instalat cu succes",
+'maintenance' => "Pagina administrativă",
+'maintenancebacklink' => "Înapoi la pagina administrativă",
+'maintnancepagetext' => "Această pagină conţine diverse unelte create pentru administrare cotidiană. Unele dintre acestea solicită în mod deosebit baza de date, aşa că vă rugăm să evitaţi suprasolicitarea lor.",
+'makesysop' => "Fă dintr-un utilizator un administrator",
+'makesysopfail' => "<b>Utilizatorul \"$1\" nu a putut deveni administrator. (Ai introdus numele corect?)</b>",
+'makesysopname' => "Numele utilizatorului:",
+'makesysopok' => "<b>Utilizatorul \"$1\" este acum administrator</b>",
+'makesysopsubmit' => "Fă din acest utilizator un administrator",
+'makesysoptext' => "Acest formular este utilizat de birocraţi pentru a transforma utilizatori de rând în administratori.
+Tastează numele utilizatorului în cutie şi apasă butonul pentru a face din utilizator un administrator",
+'makesysoptitle' => "Fă dintr-un utilizator un administrator",
+'matchtotals' => "Căutarea \"$1\" a produs $2 rezultate în titluri de articole şi $3 rezultate în texte de articole.",
+'math' => "Aparenţă formule",
+'math_bad_output' => "Nu se poate crea sau nu se poate scrie în directorul de ieşire pentru formule matematice",
+'math_bad_tmpdir' => "Nu se poate crea sau nu se poate scrie în directorul temporar pentru formule matematice",
+'math_failure' => "Nu s-a putut interpreta",
+'math_image_error' => "Conversiune în PNG eşuată",
+'math_lexing_error' => "eroare lexicală",
+'math_notexvc' => "Lipseşte executabilul texvc; vezi math/README pentru configurare.",
+'math_sample' => "Introdu formula aici",
+'math_syntax_error' => "eroare de sintaxă",
+'math_tip' => "Formulă matematică (LaTeX)",
+'math_unknown_error' => "eroare necunoscută",
+'math_unknown_function' => "funcţie necunoscută ",
+'media_sample' => "Exemplu.mp3",
+'media_tip' => "Legătură la fişier media",
+'minlength' => "Numele imaginilor trebuie să aibă cel puţin trei litere.",
+'minoredit' => "Aceasta este o editare minoră",
+#'minoreditletter' => "M",
+'mispeelings' => "Pagini conţinând greşeli comune",
+'mispeelingspage' => "Lista de greşeli frecvente",
+'mispeelingstext' => "Următoarele pagini conţin unele dintre greşelile obişnuite de scriere care apar la $1. Forma corectă poate fi dată (în acest fel).",
+'missingarticle' => "Textul \"$1\" nu a putut fi găsit în baza de date, aşa cum ar fi trebuit. Aceasta nu este o problemă legată de programul care gestionează baza de date, ci probabil o problemă in programul care administrează {{SITENAME}}. Te rugăm să raportezi această problemă unui administrator, incluzând şi adresa acestei pagini.",
+'missingimage' => "<b>Imagine lipsă</b><br /><i>$1</i>",
+'missinglanguagelinks' => "Legături inexistente către alte limbi",
+'missinglanguagelinksbutton' => "Caută limbi inexistente pentru",
+'missinglanguagelinkstext' => "Aceste articole nu se leagă către perechile lor din $1. Redirijările şi sub-paginile <i>nu apar</i> aici.",
+'moredotdotdot' => "Altele...",
+'move' => "Mutare",
+'movearticle' => "Mută pagina",
+'movedto' => "mutată la",
+'movenologin' => "Nu eşti autentificat",
+'movenologintext' => "Trebuie să fi un utilizator înregistrat şi să te [[Special:Userlogin|autentifici]]
+pentru a muta o pagină.",
+'movepage' => "Mută pagina",
+'movepagebtn' => "Mută pagina",
+'movepagetalktext' => "Pagina asociată de discuţii, dacă există, va fi mutată
+automat odată cu aceasta '''afară de cazul că''':
+* Mutaţi pagina în altă secţiune a {{SITENAME}}
+* Există deja o pagină de discuţii cu conţinut (care nu este goală), sau
+* Nu confirmi căsuţa de mai jos.
+
+În oricare din cazurile de mai sus va trebui să muţi sau să unifici
+manual paginile de discuţii, dacă doreşti acest lucru.",
+'movepagetext' => "Poţi folosi formularul de mai jos pentru a redenumi
+o pagină, mutându-i toată istoria sub noul nume.
+Pagina veche va deveni o pagină de redirijare către pagina nouă.
+Legăturile către pagina veche nu vor fi redirijate către cea nouă;
+nu uita să verifici dacă nu există redirijări duble sau invalide.
+
+Te rugăm să reţi că tu eşti responsabil(ă) pentru a face legăturile vechi să rămână valide.
+
+Reţine că pagina '''nu va fi mutată''' dacă există deja o
+pagină cu noul titlu, afară de cazul că este complet goală sau este
+o redirijare şi în plus nu are nici o istorie de editare.
+Cu alte cuvinte, vei putea muta înapoi o pagină pe care ai mutat-o
+greşit, dar nu vei putea suprascrie o pagină validă existentă prin
+mutarea alteia.
+
+<b>ATENŢIE!</b>
+Aceasta poate fi o schimbare drastică şi neaşteptată pentru o pagină populară;
+te rugăm, asigură-te că înţelegi toate consecinţele înainte de a continua.",
+'movetalk' => "Mută şi pagina de \"discuţii\" dacă se poate.",
+'movethispage' => "Mută această pagină",
+'mycontris' => "Contribuţiile mele",
+'mypage' => "Pagina mea",
+'mytalk' => "Discuţiile mele",
+'navigation' => "Navigare",
+'nbytes' => "$1 octeţi",
+'nchanges' => "$1 modificări",
+'newarticle' => "(Nou)",
+'newarticletext' => "Ai ajuns la o pagină care nu există.
+Pentru a o crea, începe să scri în caseta de mai jos
+(vezi [[Project:Ajutor|pagina de ajutor]] pentru mai multe informaţii).
+Dacă ai ajuns aici din greşeală, întoarce-te folosind controalele browser-ului tău",
+'newmessages' => "Ai $1.",
+'newmessageslink' => "mesaje noi",
+'newpage' => "Pagină nouă",
+#'newpageletter' => "N",
+'newpages' => "Pagini noi",
+'newpassword' => "Parola nouă",
+'newtitle' => "Titlul nou",
+'newusersonly' => " (doar pentru utilizatori noi)",
+#'newwindow' => "(se deschide în altă fereastră)",
+'next' => "următoarea",
+'nextn' => "următoarele $1",
+#'nextpage' => "Pagina următoare ($1)",
+'nlinks' => "$1 legături",
+'noarticletext' => "<div style=\"border: 1px solid #ccc; padding: 7px;\">'''{{SITENAME}} nu are încă un articol cu acest nume'''
+* Pentru a începe articolul, fă clic pe '''[{{SERVER}}{{localurl:{{NAMESPACE}}:{{PAGENAME}}|action=edit}} editează pagina]'''.
+* Poate există o intrare cu numele [[Wiktionary:ro:{{PAGENAME}}|{{PAGENAME}}]] în proiectul nostru frate, în [http://ro.wiktionary.org Wikţionar].
+</div>",
+'noconnect' => "Nu s-a putut conecta baza de date pe $1",
+'nocontribs' => "Nu a fost găsită nici o modificare care să satisfacă acest criteriu.",
+'nocookieslogin' => "{{SITENAME}} foloseşte module cookie pentru a autentifica utilizatorii. Browser-ul tău are modulele cookie dezactivate. Te rugăm să le activezi şi să încerci din nou.",
+'nocookiesnew' => "Contul a fost creat, dar tu nu eşti autentificat(ă). {{SITENAME}} foloseşte module cookie pentru a reţine utilizatorii autentificaţi. Browser-ul tău are modulele cookie dezactivate. Te rugăm să le activezi şi să te reautentifici folosind noul nume de utilizator şi noua parolă.",
+'nocreativecommons' => "Metadatele Creative Commons RDF dezactivate pentru acest server.",
+#'nocredits' => "Această pagină nu este atribuită vreunui autor.",
+'nodb' => "Nu s-a putut selecta baza de date $1",
+'nodublincore' => "Metadatele Dublin Core RDF sunt dezactivate pentru acest server.",
+'noemail' => "Nu este nici o adresă de e-mail înregistrată pentru utilizatorul \"$1\".",
+'noemailtext' => "Utilizatorul nu a specificat o adresă validă de e-mail,
+sau a ales să nu primească e-mail de la alţi utilizatori.",
+'noemailtitle' => "Fără adresă de e-mail",
+'nogomatch' => "Nici o pagină cu acest titlu nu a fost găsită, încearcă să căuţi textul şi în pagini. ",
+'nohistory' => "Nu există istorie pentru această pagină.",
+'nolinkshere' => "Nici o pagină nu se leagă aici.",
+'nolinkstoimage' => "Nici o pagină nu se leagă la această imagine.",
+'noname' => "Numele de utilizator pe care l-ai specificat este invalid.",
+'nonefound' => "<strong>Notă</strong>: căutările nereuşite sunt în general datorate căutării unor cuvinte prea comune care nu sunt indexate, sau cautărilor a mai multe cuvinte (numai articolele care conţin ''toate'' cuvintele specificate apar ca rezultate).",
+'nospecialpagetext' => "Ai cerut o pagină specială care nu este recunoscută de {{SITENAME}}.",
+'nosuchaction' => "Această acţiune nu există",
+'nosuchactiontext' => "Acţiunea specificată în adresă nu este recunoscută de {{SITENAME}}.",
+'nosuchspecialpage' => "Această pagină specială nu există",
+'nosuchuser' => "Nu există nici un utilizator cu numele \"$1\".
+Verifică dacă ai scris corect sau foloseşte această pagină pentru a crea un nou utilizator.",
+'notacceptable' => "Serverul wiki nu poate oferi date într-un format pe care clientul tău să-l poată citi.",
+'notanarticle' => "Nu este un articol",
+'notargettext' => "Nu ai specificat nici o pagină sau un utilizator ţintă pentru care să se efectueze această operaţiune.",
+'notargettitle' => "Lipsă ţintă",
+'note' => "<strong>Notă:</strong> ",
+'notextmatches' => "Nici un rezultat în textele articolelor",
+'notitlematches' => "Nici un rezultat în titlurile articolelor",
+'notloggedin' => "Nu eşti autentificat",
+'nowatchlist' => "Nu ai ales să urmăreşti nici un articol.",
+'nowiki_sample' => "Introdu text neformatat aici",
+'nowiki_tip' => "Ignoră formatarea wiki",
+'nstab-category' => "Categorie",
+'nstab-help' => "Ajutor",
+'nstab-image' => "Imagine",
+'nstab-main' => "Articol",
+#'nstab-media' => "Media",
+'nstab-mediawiki' => "Mesaj",
+#'nstab-special' => "Special",
+'nstab-template' => "Format",
+'nstab-user' => "Pagină de utilizator",
+'nstab-wp' => "Despre",
+#'numauthors' => "Număr de autori diferiţi (articol): ",
+#'numedits' => "Numbăr de editări (articol): ",
+#'numtalkauthors' => "Număr de autori diferiţi (pagină de discuţie): ",
+#'numtalkedits' => "Număr de editări (pagină de discuţie): ",
+#'numwatchers' => "Număr de cititori: ",
+'nviews' => "$1 accesări",
+#'ok' => "OK",
+'oldpassword' => "Parola veche",
+#'orig' => "orig",
+'orphans' => "Pagini orfane",
+'othercontribs' => "Bazat pe munca lui $1.",
+'otherlanguages' => "În alte limbi",
+#'others' => "altele",
+'pagemovedsub' => "Pagina a fost mutată",
+'pagemovedtext' => "Pagina \"[[$1]]\" a fost mutată la \"[[$2]]\".",
+'pagetitle' => "$1 - {{SITENAME}}",
+'passwordremindertext' => "Cineva (probabil tu, de la adresa $1)
+a cerut să ţi se trimită o nouă parolă pentru {{SITENAME}}.
+Parola pentru utilizatorul \"$2\" este acum \"$3\".
+Este recomandat să intri pe {{SITENAME}} şi să-ţi schimbi parola cât mai curând.",
+'passwordremindertitle' => "Amintirea parolei în {{SITENAME}}",
+'passwordsent' => "O nouă parolă a fost trimisă la adresa de e-mail a utilizatorului \"$1\".
+Te rugăm să te autentifici în {{SITENAME}} după ce o primeşti.",
+'perfcached' => "Datele următoare au fost păstrate în cache şi s-ar putea să nu fie la zi:",
+'perfdisabled' => "Ne pare rău! Această opţiune a fost dezactivată temporar în timpul orelor de vârf din motive de performanţă. Te rugăm să revi la altă oră şi să încerci din nou.",
+'perfdisabledsub' => "Iată o copie salvată de la $1:",
+#'personaltools' => "Instrumente personale",
+'popularpages' => "Pagini populare",
+'portal' => "Portalul comunităţii",
+'portal-url' => "Portal comunitate",
+'postcomment' => "Adaugă comentariu",
+'poweredby' => "{{SITENAME}} foloseşte [http://www.mediawiki.org/ MediaWiki], un motor wiki open source.",
+'powersearch' => "Caută",
+'powersearchtext' => "
+Caută în secţiunile:<br />
+$1<br />
+$2 Redirijări&nbsp; Căutări după $3 $9",
+'preferences' => "Preferinţe",
+'prefs-help-realname' => "* <strong>Numele tău real</strong> (opţional): Dacă decizi să  introduci numele real aici, acesta va fi folosit pentru a vă atribui munca.<br />",
+'prefs-help-email' => "* <strong>Adresa de e-mail</strong> (opţional): Permite altor utilizatori să te contacteze folosind {{SITENAME}}, fără a fi necesar să le pui la dispoziţie adresa reală de mail. În plus, aici ţi se poate trimite o nouă parolă în caz că o pierzi pe cea existentă.",
+'prefs-misc' => "Diverse reglări",
+'prefs-personal' => "Date de utilizator",
+#'prefs-rc' => "Schimbări recente şi afişare cioturi",
+'prefslogintext' => "Eşti autentificat ca \"$1\".
+Numărul intern de identificare este $2 (nu trebuie să-l reţi decât dacă ai probleme).",
+'prefsnologin' => "Neautentificat",
+'prefsnologintext' => "Trebuie să fii [[Special:Userlogin|autentificat]]
+pentru a-ţi putea salva preferinţele.",
+'prefsreset' => "Preferinţele au fost resetate.",
+'preview' => "Previzualizare",
+'previewconflict' => "Această pre-vizualizare reflectă textul din caseta de sus, respectiv felul în care va arăta articolul dacă alegi să-l salvezi acum.",
+'previewnote' => "Reţine că aceasta este doar o previzualizare - articolul încă nu este salvat! Trebuie să apeşi butonul \"Salvează pagina\" de sub caseta de editare pentru a salva. Nu uita să introduci şi o descriere sumară a modificărilor!",
+'prevn' => "anterioarele $1",
+'printableversion' => "Versiune tipărire",
+'printsubtitle' => "(De la {{SERVER}})",
+'protect' => "Protejare",
+'protectcomment' => "Motiv pentru protejare",
+'protectedarticle' => "protejat [[$1]]",
+'protectedpage' => "Pagină protejată",
+'protectedpagewarning' => "<strong>ATENŢIE! Această pagină a fost blocată şi numai utilizatorii
+cu privilegii de administrator o pot edita. Te rugăm să urmezi sugestiile
+[[Project:Pagină_protejată|despre pagini protejate]] când editezi.</strong>",
+'protectedtext' => "Această pagină a fost protejată la editare;
+există mai multe motive posibile pentru aceasta, vezi
+[[Project:Pagină protejată]].
+
+Poţi vedea şi copia sursa acestei pagini:",
+'protectlogpage' => "Jurnal_protecţii",
+'protectlogtext' => "Dedesubt găseşti lista de blocări/deblocări ale paginilor.
+Vezi [[Project:Pagină protejată]] pentru mai multe informaţii.",
+'protectpage' => "Protejează pagina",
+'protectsub' => "(Protejând \"$1\")",
+'protectthispage' => "Protejează pagina",
+'proxyblocker' => "Blocaj de proxy",
+'proxyblockreason' => "Adresa ta IP a fost blocată pentru că este un proxy deschis. Te rugăm, contactează provider-ul tău de servicii Internet sau tehnicieni IT şi informează-i asupra acestei probleme serioase de securitate.",
+'proxyblocksuccess' => "Realizat.",
+'qbbrowse' => "Răsfoieşte",
+'qbedit' => "Editează",
+'qbfind' => "Găseşte<br />
+<small>Diacritice: ă â î ş ţ</small>",
+'qbmyoptions' => "Opţiunile mele",
+'qbpageinfo' => "Informaţii ale paginii",
+'qbpageoptions' => "Opţiuni ale paginii",
+'qbsettings' => "Setări pentru quickbar",
+#'qbsettingsnote' => "Această funcţie funcţionează doar în straturile 'Standard' şi 'CologneBlue'.",
+'qbspecialpages' => "Pagini speciale",
+'randompage' => "Pagină aleatoare",
+'range_block_disabled' => "Abilitatea dezvoltatorilor de a bloca serii de adrese este dezactivată.",
+'rchide' => "în $4 form; $1 editări minore; $2 namespace-uri secundare; $3 editări multiple.",
+'rclinks' => "Arată ultimele $1 modificări din ultimele $2 zile.",
+'rclistfrom' => "Arată modificările începând de la $1",
+'rcliu' => "; $1 editări operate de utilizatori autentificaţi",
+'rcloaderr' => "Încarc ultimele modificări",
+'rclsub' => "(cu pagini legate de la \"$1\")",
+'rcnote' => "Dedesubt găseşti ultimele <strong>$1</strong> modificări din ultimele <strong>$2</strong> zile.",
+'rcnotefrom' => "Dedesubt sunt modificările de la <b>$2</b> (maxim <b>$1</b> de modificări sunt afişate - schimbă numărul maxim de linii alegând altă valoare mai jos).",
+'readonly' => "Baza de date este blocată la scriere",
+'readonlytext' => "Baza de date {{SITENAME}} este momentan blocată la scriere, probabil pentru o operaţiune de rutină, după care va fi deblocată şi se va reveni la starea normală.
+Administratorul care a blocat-o a oferit această explicaţie:
+<p>$1",
+'readonlywarning' => "<strong>ATENŢIE! Baza de date a fost blocată pentru întreţinere,
+deci nu vei putea să salvezi editările în acest moment. Poţi copia textul
+într-un fişier text local pentru a modifica conţinutul în {{SITENAME}} când va fi posibil.</strong>",
+'recentchanges' => "Schimbări recente",
+'recentchangescount' => "Numărul de articole pentru schimbări recente",
+'recentchangeslinked' => "Modificări corelate",
+'recentchangestext' => "Aceată pagină permite vizualizarea ultimelor modificări ale paginilor {{SITENAME}} în română.
+
+[[Project:bun venit|Bun venit la {{SITENAME}}]]! Nu ezita să vizitezi secţiunile de [[Project:întrebări frecvente|întrebări frecvente]], [[Project:politica|politica {{SITENAME}}]] (în special [[Project:convenţii pentru denumiri|convenţii pentru denumiri]] şi [[Project:punct de vedere neutru|punct de vedere neutru]]), şi cele mai comune [[Project:greşeli frecvente|greşeli în {{SITENAME}}]].
+
+Este foarte important să nu adaugi în {{SITENAME}} materiale protejate de [[drepturi de autor]]. Problemele legale rezultate ar putea prejudicia în mod serios proiectul în întregime, aşa că te rugăm insistent să ai grijă să nu faci acest lucru.",
+'redirectedfrom' => "(Redirijat de la $1)",
+'remembermypassword' => "Reţine-mi parola între sesiuni.",
+'removechecked' => "Elimină elementele bifate din lista de pagini urmărite",
+'removedwatch' => "Ştearsă din lista de pagini urmărite",
+'removedwatchtext' => "Pagina \"$1\" a fost eliminată din lista de pagini urmărite.",
+'removingchecked' => "Se elimină elementele cerute din lista de articole urmărite...",
+'resetprefs' => "Resetează preferinţele",
+'restorelink' => "$1 editări şterse",
+'resultsperpage' => "Numărul de rezultate per pagină",
+'retrievedfrom' => "Adus de la \"$1\"",
+'returnto' => "Înapoi la $1.",
+'retypenew' => "Repetă parola nouă",
+'reupload' => "Re-trimite",
+'reuploaddesc' => "Întoarcere la formularul de trimitere.",
+'reverted' => "Revenit la o versiune mai veche",
+#'revertimg' => "rev",
+'revertpage' => "Revenit la ultima editare de către $1",
+'revhistory' => "Istoria versiunilor",
+'revisionasof' => "Versiunea de la data $1",
+'revnotfound' => "Versiunea nu a fost găsită",
+'revnotfoundtext' => "Versiunea mai veche a paginii pe care ai cerut-o nu a fost găsită. Te rugăm să verifici legătura pe care ai folosit-o pentru a accesa această pagină.
+",
+#'rfcurl' => "http://www.faqs.org/rfcs/rfc$1.html",
+'rights' => "Drepturi:",
+'rollback' => "Editări de revenire",
+'rollback_short' => "Revenire",
+'rollbackfailed' => "Revenirea nu s-a putut face",
+'rollbacklink' => "revenire",
+'rows' => "Rânduri",
+'savearticle' => "Salvează pagina",
+'savedprefs' => "Preferinţele tale au fost salvate.",
+'savefile' => "Salvează fişierul",
+'saveprefs' => "Salvează preferinţele",
+'search' => "Caută",
+'searchdisabled' => "<p>Ne pare rău! Căutarea după text a fost dezactivată temporar, din motive de performanţă. Între timp poţi folosi căutarea prin Google mai jos, însă aceasta poate să dea rezultate învechite.</p>",
+'searchquery' => "Pentru căutarea \"$1\"",
+'searchresults' => "Rezultatele căutării",
+'searchresultshead' => "Setări de căutare",
+'searchresulttext' => "Pentru mai multe detalii despre căutarea în {{SITENAME}}, vezi $1.",
+'selectnewerversionfordiff' => "Selectează o versiunea mai nouă pentru comparare",
+'selectolderversionfordiff' => "Selectează o versiunea mai veche pentru comparaţie",
+'selflinks' => "Pagini cu legături ciclice",
+'selflinkstext' => "Următoarele pagini conţin legături către ele însele, ceea ce n-ar trebui să se întâmple.",
+'servertime' => "Ora serverului (UTC)",
+'set_rights_fail' => "<b>Nu au putut fi acordate drepturi de utilizator lui \"$1\". (Ai introdus numele corect?)</b>",
+'set_user_rights' => "Acordă drepturi de utilizator",
+'setbureaucratflag' => "Acordă şi drepturi de birocrat",
+'shortpages' => "Pagini scurte",
+'show' => "arată",
+'showhideminor' => "$1 editări minore | $2 bots | $3 logged in users | $4 patrolled edits",
+'showingresults' => "Mai jos apar <b>$1</b> rezultate începând cu numărul <b>$2</b>.",
+'showingresultsnum' => "Mai jos apar <b>$3</b> rezultate începând cu numărul <b>$2</b>.",
+'showlast' => "Arată ultimele $1 imagini ordonate $2.",
+'showpreview' => "Arată previzualizare",
+'showtoc' => "arată",
+'sig_tip' => "Semnătura ta datată",
+'sitenotice' => "", #empty
+'sitestats' => "Statisticile sitului",
+'sitestatstext' => "Există un număr total de <b>$1</b> pagini în baza de date.
+Acest număr include paginile de \"discuţii\", paginile despre {{SITENAME}}, pagini minimale (\"cioturi\"), pagini de redirijare şi altele care probabil că nu intră de fapt în categoria articolelor reale.
+În afară de acestea, există <b>$2</b> pagini care sunt probabil articole (numărate automat, în funcţie strict de mărime).<p>
+În total au fost <b>$3</b> vizite (accesări) şi <b>$4</b> editări
+de la ultima actualizare a programului (July 20, 2002).
+În medie rezultă <b>$5</b> editări per pagină sau <b>$6</b> vizualizări la fiecare editare.",
+'sitesubtitle' => "Enciclopedia liberă",
+'sitesupport' => "Donaţii",
+'sitetitle' => "{{SITENAME}}",
+'siteuser' => "Utilizator {{SITENAME}} $1",
+'siteusers' => "Utilizator(i) {{SITENAME}} $1",
+'skin' => "Aparenţă",
+'spamprotectiontext' => "Pagina, pe care doreşti să o salvezi, a fost blocată de filtrul Spam. Aceasta se datorează probabil unei legături spre un sit extern. Ai putea verifica următoarea expresie regulată:",
+'spamprotectiontitle' => "Filtru de protecţie spam",
+'specialpage' => "Pagină Specială",
+'specialpages' => "Pagini speciale",
+'spheading' => "Pagini speciale",
+'statistics' => "Statistici",
+'storedversion' => "Versiunea curentă",
+'stubthreshold' => "Limita de caractere pentru un ciot",
+'subcategories' => "Subcategorii",
+#'subcategorycount' => "Această categorie are $1 subcategorii.",
+'subject' => "Subiect/titlu",
+'subjectpage' => "Vezi subiectul",
+'successfulupload' => "Fişierul a fost trimis",
+'summary' => "<!-- <p style=\"color:red; font-weight:bold;\">NU FACEŢI TESTE AICI!</p> -->
+<div id=\"my-buttons\">
+<a href=\"javascript:insertTags('ă', '', '')\" title=\"Introdu 'ă'\">&nbsp;ă&nbsp;</a>
+<a href=\"javascript:insertTags('â', '', '')\" title=\"Introdu 'â'\">&nbsp;â&nbsp;</a>
+<a href=\"javascript:insertTags('î', '', '')\" title=\"Introdu 'î'\">&nbsp;î&nbsp;</a>
+<a href=\"javascript:insertTags('ş', '', '')\" title=\"Introdu 'ş'\">&nbsp;ş&nbsp;</a>
+<a href=\"javascript:insertTags('ţ', '', '')\" title=\"Introdu 'ţ'\">&nbsp;ţ&nbsp;</a>
+<a href=\"javascript:insertTags('Ă', '', '')\" title=\"Introdu 'Ă'\">&nbsp;Ă&nbsp;</a>
+<a href=\"javascript:insertTags('Â', '', '')\" title=\"Introdu 'Â'\">&nbsp;Â&nbsp;</a>
+<a href=\"javascript:insertTags('Î', '', '')\" title=\"Introdu 'Î'\">&nbsp;Î&nbsp;</a>
+<a href=\"javascript:insertTags('Ş', '', '')\" title=\"Introdu 'Ş'\">&nbsp;Ş&nbsp;</a>
+<a href=\"javascript:insertTags('Ţ', '', '')\" title=\"Introdu 'Ţ'\">&nbsp;Ţ&nbsp;</a>
+<a href=\"javascript:insertTags('†', '', '')\" title=\"Introdu '†'\">&nbsp;†&nbsp;</a>
+<a href=\"javascript:insertTags('<sub'+'>', '</sub>', 'indice')\" title=\"Transformă textul selectat în indice\">X<sub>2</sub></a>
+<a href=\"javascript:insertTags('<sup'+'>', '</sup>', 'exponent')\" title=\"Transformă textul selectat în exponent\">X<sup>2</sup></a>
+<a href=\"javascript:insertTags('„', '“', 'text')\" title=\"Pune în ghilimele textul selectat\">„ ...“</a>
+<a href=\"javascript:insertTags('{' + '{', '}}', '')\" title=\"Pune între acolade duble textul selectat\">{{}}</a>
+<a href=\"javascript:insertTags('<', '>', 'text')\" title=\"Pune între semne de comparaţie textul selectat\"><></a>
+<a href=\"javascript:insertTags('[' + '[', ']]', '')\" title=\"Pune între paranteze drepte duble textul selectat\">[[]]</a>
+<a href=\"javascript:insertTags('€', '', '')\" title=\"Introdu simbolul monedei Euro\">&nbsp;€&nbsp;</a>
+<a href=\"javascript:insertTags('<', '', '')\" title=\"Introdu semnul 'mai mic'\">&nbsp;<&nbsp;</a>
+<a href=\"javascript:insertTags('>', '', '')\" title=\"Introdu semnul 'mai mare'\">&nbsp;>&nbsp;</a>
+</div>
+
+Sumar",
+'sysoptext' => "Acţiunea pe care ai încercat-o necesită drepturi de operator.
+Vezi $1.",
+'sysoptitle' => "Ai nevoie de acces ca operator",
+'tableform' => "tabel",
+'talk' => "Discuţie",
+'talkexists' => "Pagina în sine a fost mutată, dar pagina de discuţii
+nu a putut fi mutată deoarece deja există o alta cu acelaşi nume. Te rugăm
+să unifici manual cele două pagini de discuţii.",
+'talkpage' => "Discută pagina",
+'talkpagemoved' => "Şi pagina de discuţii asociată a fost mutată.",
+'talkpagenotmoved' => "Pagina asociată de discuţii <strong>nu</strong> a fost mutată.",
+#'talkpagetext' => "<!-- MediaWiki:talkpagetext -->",
+'textboxsize' => "Dimensiunile casetei de text",
+'textmatches' => "Rezultate în textele articolelor",
+'thisisdeleted' => "Vezi sau recuperează $1?",
+'thumbnail-more' => "Extinde",
+#'timezonelegend' => "Fus orar",
+'timezoneoffset' => "Diferenţa",
+'timezonetext' => "Introdu numărul de ore diferenţă între ora locală şi ora serverului (UTC, timp universal - pentru România, cifra este 3).",
+'titlematches' => "Rezultate în titluri de articole",
+'toc' => "Cuprins",
+'toolbox' => "Trusa de scule",
+'tooltip-compareselectedversions' => "Vezi diferenţele între cele două versiuni selectate de pe această pagină. [alt-v]",
+'tooltip-minoredit' => "Marchează această editare ca fiind minoră [alt-i]",
+'tooltip-preview' => "Previzualizarea modificărilor tale, foloseşte te rugăm înainte de a salva! [alt-p]",
+'tooltip-save' => "Salvează modificările tale [alt-s]",
+'tooltip-search' => "Căutare în această wiki [alt-f]",
+'uclinks' => "Vezi ultimele $1 modificări; vezi ultimele $2 zile.",
+'ucnote' => "Găseşti dedesubt ultimele <b>$1</b> modificări ale utilizatorului din ultimele <b>$2</b> zile.",
+'uctop' => " (sus)",
+'unblockip' => "Deblochează adresă IP",
+'unblockiptext' => "Foloseşte chestionarul de mai jos pentru a restaura
+drepturile de scriere pentru o adresă IP blocată anterior..",
+'unblocklink' => "deblochează",
+'unblocklogentry' => "deblocat \"$1\"",
+#'uncategorizedpages' => "Pagini necategorizate",
+'undelete' => "Recuperează pagina ştearsă",
+'undelete_short' => "Recuperare",
+'undelete_short1' => "Recuperare",
+'undeletearticle' => "Recuperează articol şters",
+'undeletebtn' => "Recuperează!",
+'undeletedarticle' => "\"$1\" a fost recuperat",
+'undeletedtext' => "Articolul [[$1]] a fost recuperat.
+Vezi [[Project:Raport_ştergeri]] pentru o listă a ştergerilor şi recuperărilor recente.",
+'undeletehistory' => "Dacă recuperezi pagina, toate versiunile asociate
+vor fi adăugate retroactiv în istorie. Dacă o pagină nouă cu acelaşi nume
+a fost creată de la momentul ştergerii acesteia, versiunile recuperate
+vor apărea în istoria paginii, iar versiunea curentă a paginii nu va
+fi înlocuită automat de către versiunea recuperată.",
+'undeletepage' => "Vizualizează şi recuperează pagini şterse",
+'undeletepagetext' => "Următoarele pagini au fost şterse dar încă se află în
+arhivă şi pot fi recuperate. Reţine că arhiva se poate şterge din timp în timp.",
+'undeleterevision' => "Versiunea ştearsă la $1",
+'undeleterevisions' => "$1 versiuni arhivate",
+'unexpected' => "Valoare neaşteptată: \"$1\"=\"$2\".",
+'unlockbtn' => "Deblochează baza de date",
+'unlockconfirm' => "Da, chiar vreau să deblochez baza de date.",
+'unlockdb' => "Deblochează baza de date",
+'unlockdbsuccesssub' => "Baza de date a fost deblocată",
+'unlockdbsuccesstext' => "Baza de date {{SITENAME}} a fost deblocată.",
+'unlockdbtext' => "Deblocarea bazei de date va permite tuturor utilizatorilor
+să editeze pagini, să-şi schimbe preferinţele, să-şi editeze listele de
+pagini urmărite şi orice alte operaţiuni care ar necesita schimări
+în baza de date.
+Te rugăm să-ţi confirmi intenţia de a face acest lucru.",
+'unprotect' => "Deprotejare",
+'unprotectcomment' => "Motiv pentru deprotejare",
+'unprotectedarticle' => "deprotejat [[$1]]",
+'unprotectsub' => "(Deprotejând \"$1\")",
+'unprotectthispage' => "Deprotejează pagina",
+'unusedimages' => "Pagini neutilizate",
+'unusedimagestext' => "<p>Te rugăm ţine cont de faptul că alte situri, inclusiv alte versiuni de limbă {{SITENAME}} pot să aibă legături aici fără ca aceste pagini să fie listate aici - această listă se referă strict la {{SITENAME}} în română.",
+'unwatch' => "Nu mai urmări",
+'unwatchthispage' => "Nu mai urmări",
+'updated' => "(Actualizat)",
+'upload' => "Trimite fişier",
+'uploadbtn' => "Trimite fişier",
+'uploaddisabled' => "Ne pare rău, trimiterea de imagini este dezactivată.",
+'uploadedfiles' => "Fişiere trimise",
+'uploadedimage' => "trimis \"[[$1]]\"",
+'uploaderror' => "Eroare la trimitere fişier",
+'uploadlink' => "Trimite imagine",
+'uploadlog' => "raport de trimitere fişiere",
+'uploadlogpage' => "Raport de trimitere fişiere",
+'uploadlogpagetext' => "Găseşti mai jos lista ultimelor fişiere trimise.
+Toate datele/orele sunt afişate ca timp universal (UTC).
+<ul>
+</ul>
+",
+'uploadnologin' => "Nu eşti autentificat",
+'uploadnologintext' => "Trebuie să fi [[Special:Userlogin|autentificat]]
+ca să trimiţi fişiere.",
+'uploadtext' => "<strong>STOP!</strong> Înainte de a trimite un fişier aici,
+te rugăm să citeşti şi să respecţi <a href=\"/wiki/Project:Politica_de_utilizare_a_imaginilor\">politica de utilizare a imaginilor</a>.
+<p>Pentru a vizualiza sau căuta imagini deja trimise, mergi la <a href=\"/wiki/Special:Imagelist\">lista de imagini</a>.
+Fişierele noi şi cele şterse sunt contorizate pe paginile de <a href=\"/wiki/Project:Upload_log\">raport de trimiteri</a>.
+<p>Foloseşte formularul de mai jos pentru a trimite imagini noi
+pe care le vei putea folosi pentru a ilustra articolele.
+În majoritatea browserelor vei vedea un buton \"Răsfoire...\" (sau \"Browse...\")
+care va deschide fereastra standard dialog a sistemului tău de operare
+pentru alegerea de fişiere.
+Când alegei un fişier în acest fel, caseta de dialog se va completa cu calea locală către acesta.
+Este de asemenea necesar să bifezi căsuţa asociată textului
+în care confirmi că nu violezi nici un drept de autor trimiţând această imagine.
+În final, apasă pe butonul \"Trimite\" petru a trimite efectiv fişierul.
+Această operaţiune poate dura, mai ales dacă ai o legătură lentă la Internet.
+<p>Formatele preferate sunt JPEG pentru imagini fotografice,
+PNG pentru desene şi alte imagini cu contururi clare şi OGG pentru fişiere de sunet.
+
+Te rugăm să foloseşti nume explicite pentru fişiere ca să eviţi confuziile.
+Pentru a include o imagine într-un articol, foloseşti o legătură de forma <b>[[imagine:fişier.jpg]]</b> sau <b>[[imagine:fişier.png|text alternativ]]</b>
+sau <b>[[media:fişier.ogg]]</b> pentru fişiere de sunet.
+<p>Te rugăm reţine că, la fel ca şi în cazul celorlalte secţiuni din {{SITENAME}}, alte persoane pot edita sau şterge fişierele pe care le trimiţi dacă e în interesul enciclopediei, şi ţi se poate chiar bloca accesul la trimiterea de fişiere dacă abuzezi de sistem.",
+'uploadwarning' => "Avertizare la trimiterea fişierului",
+/* 'usenewcategorypage' => "1
+
+Set first character to \"0\" to disable the new category page layout.", */
+'user_rights_set' => "<b>Drepturi de utilizator pentru \"$1\" actualizate</b>",
+'usercssjsyoucanpreview' => "<strong>Sfat:</strong> Foloseşte butonul 'Arată previzualizare' pentru a testa noul tău css/js înainte de a salva.",
+'usercsspreview' => "'''Reţine că urmăreşti doar o previzualizare a css-ului tău de utilizator, acesta nu este încă salvat!'''",
+'userexists' => "Numele de utilizator pe care l-aţi introdus există deja. Încercaţi cu un alt nume.",
+'userjspreview' => "'''Reţine că urmăreşti doar un test/o previzualizare a javascript-ului tău de utilizator, acesta nu este încă salvat!'''",
+'userlogin' => "Autentificare",
+'userlogout' => "Închide sesiunea",
+'usermailererror' => "Obiectul de mail a dat eroare:",
+'userpage' => "Vezi pagina utilizatorului",
+'userstats' => "Statistici legate de utilizatori",
+'userstatstext' => "Există un număr de <b>$1</b> utilizatori înregistraţi.
+Dintre aceştia <b>$2</b> sunt administratori (vezi $3).",
+'version' => "Versiune",
+'viewcount' => "Această pagină a fost vizitată de $1 ori.",
+'viewprevnext' => "Vezi ($1) ($2) ($3).",
+'viewsource' => "Vezi sursa",
+'viewtalkpage' => "Vezi discuţia",
+'wantedpages' => "Pagini dorite",
+'watch' => "Urmărire",
+'watchdetails' => "($1 pagini urmărite în afară de paginile de discuţie;
+$2 pagini editate în total;
+$3...
+[$4 lista completă].)",
+'watcheditlist' => "Aceasta este lista alfabetică a tuturor paginilor pe care le urmăreşti.
+Bifează căsuţele corespunzătoare paginilor pe care doreşti să le elimini din lista de
+pagini urmărite şi apasă pe butonul corespunzător din partea de jos a paginii.",
+'watchlist' => "Articole urmărite",
+'watchlistcontains' => "Lista de articole urmărite conţine $1 pagini",
+'watchlistsub' => "(pentru utilizatorul \"$1\")",
+'watchmethod-list' => "căutarea paginilor urmărite pentru schimbări recente",
+'watchmethod-recent' => "căutarea schimbărilor recente pentru paginile urmărite",
+'watchnochange' => "Nici unul dintre articolele pe care le urmăreşti nu a fost modificat în perioada de timp afişată.",
+'watchnologin' => "Nu eşti autentificat",
+'watchnologintext' => "Trebuie să fii [[Special:Userlogin|autentificat]]
+pentru a-ţi modifica lista de articole urmărite.",
+'watchthis' => "Urmăreşte această pagină",
+'watchthispage' => "Urmăreşte pagina",
+'welcomecreation' => "<h2>Bun venit, $1!</h2><p>A fost creat un cont pentru tine
+Nu uita să-ţi personalizezi preferinţele în {{SITENAME}}.",
+'whatlinkshere' => "Ce se leagă aici",
+'whitelistacctext' => "Trebuie să te [[Special:Userlogin|autentifici]] şi să ai permisiunile corecte pentru a crea conturi.",
+'whitelistacctitle' => "Nu ai dreptul de a crea conturi",
+'whitelistedittext' => "Trebuie să te [[Special:Userlogin|autentifici]] pentru a edita articole.",
+'whitelistedittitle' => "Este necesară autentificarea pentru a edita",
+'whitelistreadtext' => "Trebuie să te [[Special:Userlogin|autentifici]] pentru a citi articole.",
+'whitelistreadtitle' => "Este necesară autentificarea pentru a citi",
+'wikipediapage' => "Vezi pagina meta",
+'wlnote' => "Dedesubt găseşti ultimele $1 schimbări din ultimele <b>$2</b> ore.",
+'wlsaved' => "Aceasta este o versiune salvată a listei tale de pagini urmărite.",
+'wlshowlast' => "Arată ultimele $1 ore $2 zile $3",
+'wrong_wfQuery_params' => "Număr incorect de parametri pentru wfQuery()<br />
+Funcţia: $1<br />
+Query: $2
+",
+'wrongpassword' => "Parola pe care ai introdus-o este greşită. Te rugăm să încerci din nou.",
+'yourdiff' => "Diferenţe",
+'youremail' => "Adresa de e-mail (opţional)*",
+'yourname' => "Numele de utilizator",
+'yournick' => "Versiune scurtă a numelui, pentru semnături",
+'yourpassword' => "Parola",
+'yourpasswordagain' => "Repetă parola",
+'yourrealname' => "Numele tău real*",
+'yourtext' => "Textul tău",
+);
+
+class LanguageRo extends LanguageUtf8 {
+
+       function getNamespaces() {
+               global $wgNamespaceNamesRo;
+               return $wgNamespaceNamesRo;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsRo;
+               return $wgQuickbarSettingsRo;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesRo;
+               return $wgSkinNamesRo;
+       }
+
+       function getDateFormats() {
+               global $wgDateFormatsRo;
+               return $wgDateFormatsRo;
+       }
+
+       function timeanddate( $ts, $adj = false ) {
+               return $this->date( $ts, $adj ) . " " . $this->time( $ts, $adj );
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesRo;
+               if( isset( $wgAllMessagesRo[$key] ) )
+                       return $wgAllMessagesRo[$key];
+               else
+                       return parent::getMessage( $key );
+       }
+
+       function fallback8bitEncoding() {
+               return "iso8859-2";
+       }
+
+       function getMagicWords() {
+               global $wgMagicWordsRo;
+               return $wgMagicWordsRo;
+       }
+}
+
+?>
diff --git a/languages/LanguageRu.php b/languages/LanguageRu.php
new file mode 100644 (file)
index 0000000..5864c0e
--- /dev/null
@@ -0,0 +1,1996 @@
+<?php
+/** Russian (русский язык)
+  *
+  * Based on Language.php 1.633.2.8
+  *
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+require_once( 'LanguageUtf8.php' );
+
+if($wgMetaNamespace === FALSE)
+       $wgMetaNamespace = str_replace( ' ', '_', $wgSitename );
+
+
+/* private */ $wgNamespaceNamesRu = array(
+       NS_MEDIA            => 'Медиа',
+       NS_SPECIAL          => 'Служебная',
+       NS_MAIN             => '',
+       NS_TALK             => 'Обсуждение',
+       NS_USER             => 'Участник',
+       NS_USER_TALK        => 'Обсуждение_участника',
+       NS_PROJECT          => $wgMetaNamespace,
+       NS_PROJECT_TALK     => FALSE,  #Set in constructor
+       NS_IMAGE            => 'Изображение',
+       NS_IMAGE_TALK       => 'Обсуждение_изображения',
+       NS_MEDIAWIKI        => 'MediaWiki',
+       NS_MEDIAWIKI_TALK   => 'Обсуждение_MediaWiki',
+       NS_TEMPLATE         => 'Шаблон',
+       NS_TEMPLATE_TALK    => 'Обсуждение_шаблона',
+       NS_HELP             => 'Справка',
+       NS_HELP_TALK        => 'Обсуждение_справки',
+       NS_CATEGORY         => 'Категория',
+       NS_CATEGORY_TALK    => 'Обсуждение_категории',
+) + $wgNamespaceNamesEn;
+
+
+/* private */ $wgQuickbarSettingsRu = array(
+       'Не показывать', 'Неподвижная слева', 'Неподвижная справа', 'Плавающая слева', 'Плавающая справа'
+);
+
+/* private */ $wgSkinNamesRu = array(
+       'standard' => 'Стандартный',
+       'nostalgia' => 'Ностальгия',
+       'cologneblue' => 'Кёльнская тоска',
+       'davinci' => 'Да Винчи',
+       'mono' => 'Моно',
+       'monobook' => 'Моно-книга',
+       'myskin' => 'Своё',
+       'chick' => 'Цыпа'
+);
+
+
+/* private */ $wgBookstoreListRu = array(
+       'ОЗОН' => 'http://www.ozon.ru/?context=advsearch_book&isbn=$1',
+       'Books.Ru' => 'http://www.books.ru/shop/search/advanced?as%5Btype%5D=books&as%5Bname%5D=&as%5Bisbn%5D=$1&as%5Bauthor%5D=&as%5Bmaker%5D=&as%5Bcontents%5D=&as%5Binfo%5D=&as%5Bdate_after%5D=&as%5Bdate_before%5D=&as%5Bprice_less%5D=&as%5Bprice_more%5D=&as%5Bstrict%5D=%E4%E0&as%5Bsub%5D=%E8%F1%EA%E0%F2%FC&x=22&y=8',
+       'Яндекс.Маркет' => 'http://market.yandex.ru/search.xml?text=$1',
+       'Amazon.com' => 'http://www.amazon.com/exec/obidos/ISBN=$1'
+);
+
+
+# Note to translators:
+#   Please include the English words as synonyms.  This allows people
+#   from other wikis to contribute more easily.
+#
+/* private */ $wgMagicWordsRu = array(
+#   ID                                 CASE  SYNONYMS
+       MAG_REDIRECT             => array( 0,    '#redirect', '#перенаправление', '#перенапр'),
+       MAG_NOTOC                => array( 0,    '__NOTOC__', '__БЕЗСОДЕРЖАНИЯ__'),
+       MAG_FORCETOC             => array( 0,    '__FORCETOC__'),
+       MAG_TOC                  => array( 0,    '__TOC__', '__СОДЕРЖАНИЕ__'),
+       MAG_NOEDITSECTION        => array( 0,    '__NOEDITSECTION__', '__БЕЗРЕДАКТИРОВАНИЯРАЗДЕЛА__'),
+       MAG_START                => array( 0,    '__START__', '__НАЧАЛО__'),
+       MAG_CURRENTMONTH         => array( 1,    'CURRENTMONTH', 'ТЕКУЩИЙМЕСЯЦ'),
+       MAG_CURRENTMONTHNAME     => array( 1,    'CURRENTMONTHNAME','НАЗВАНИЕТЕКУЩЕГОМЕСЯЦА'),
+       MAG_CURRENTMONTHNAMEGEN  => array( 1,    'CURRENTMONTHNAMEGEN','НАЗВАНИЕТЕКУЩЕГОМЕСЯЦАРОД'),
+       MAG_CURRENTMONTHABBREV   => array( 1,    'CURRENTMONTHABBREV', 'НАЗВАНИЕТЕКУЩЕГОМЕСЯЦААБР'),
+       MAG_CURRENTDAY           => array( 1,    'CURRENTDAY','ТЕКУЩИЙДЕНЬ'),
+       MAG_CURRENTDAYNAME       => array( 1,    'CURRENTDAYNAME','НАЗВАНИЕТЕКУЩЕГОДНЯ'),
+       MAG_CURRENTYEAR          => array( 1,    'CURRENTYEAR','ТЕКУЩИЙГОД'),
+       MAG_CURRENTTIME          => array( 1,    'CURRENTTIME','ТЕКУЩЕЕВРЕМЯ'),
+       MAG_NUMBEROFARTICLES     => array( 1,    'NUMBEROFARTICLES','КОЛИЧЕСТВОСТАТЕЙ'),
+       MAG_NUMBEROFFILES        => array( 1,    'NUMBEROFFILES', 'КОЛИЧЕСТВОФАЛОВ'),
+       MAG_PAGENAME             => array( 1,    'PAGENAME','НАЗВАНИЕСТРАНИЦЫ'),
+       MAG_PAGENAMEE            => array( 1,    'PAGENAMEE','НАЗВАНИЕСТРАНИЦЫ2'),
+       MAG_NAMESPACE            => array( 1,    'NAMESPACE','ПРОСТРАНСТВОИМЁН'),
+       MAG_MSG                  => array( 0,    'MSG:'),
+       MAG_SUBST                => array( 0,    'SUBST:','ПОДСТ:'),
+       MAG_MSGNW                => array( 0,    'MSGNW:'),
+       MAG_END                  => array( 0,    '__END__','__КОНЕЦ__'),
+       MAG_IMG_THUMBNAIL        => array( 1,    'thumbnail', 'thumb', 'мини'),
+       MAG_IMG_RIGHT            => array( 1,    'right','справа'),
+       MAG_IMG_LEFT             => array( 1,    'left','слева'),
+       MAG_IMG_NONE             => array( 1,    'none'),
+       MAG_IMG_WIDTH            => array( 1,    '$1px','$1пкс'),
+       MAG_IMG_CENTER           => array( 1,    'center', 'centre','центр'),
+       MAG_IMG_FRAMED           => array( 1,    'framed', 'enframed', 'frame','обрамить'),
+       MAG_INT                  => array( 0,    'INT:'),
+       MAG_SITENAME             => array( 1,    'SITENAME','НАЗВАНИЕСАЙТА'),
+       MAG_NS                   => array( 0,    'NS:','ПИ:'),
+       MAG_LOCALURL             => array( 0,    'LOCALURL:'),
+       MAG_LOCALURLE            => array( 0,    'LOCALURLE:'),
+       MAG_SERVER               => array( 0,    'SERVER','СЕРВЕР'),
+       MAG_SERVERNAME           => array( 0,    'SERVERNAME', 'НАЗВАНИЕСЕРВЕРА'),
+       MAG_SCRIPTPATH           => array( 0,    'SCRIPTPATH', 'ПУТЬКСКРИПТУ'),
+       MAG_GRAMMAR              => array( 0,    'GRAMMAR:'),
+       MAG_NOTITLECONVERT       => array( 0,    '__NOTITLECONVERT__', '__NOTC__', '__БЕЗПРЕОБРАЗОВАНИЯЗАГОЛОВКА__'),
+       MAG_NOCONTENTCONVERT     => array( 0,    '__NOCONTENTCONVERT__', '__NOCC__', '__БЕЗПРЕОБРАЗОВАНИЯТЕКСТА__'),
+       MAG_CURRENTWEEK          => array( 1,    'CURRENTWEEK','ТЕКУЩАЯНЕДЕЛЯ'),
+       MAG_CURRENTDOW           => array( 1,    'CURRENTDOW','ТЕКУЩИЙДЕНЬНЕДЕЛИ'),
+       MAG_REVISIONID           => array( 1,    'REVISIONID', 'ИДВЕРСИИ'),
+);
+
+/* private */ $wgAllMessagesRu = array(
+
+# User preference toggles
+'tog-underline' => 'Подчёркивать ссылки',
+'tog-highlightbroken' => 'Показывать несуществующие ссылки <a href="" class="new">вот так</a> (иначе вот так<a href="" class="internal">?</a>).',
+'tog-justify'   => 'Выравнивать текст по ширине страницы',
+'tog-hideminor' => 'Скрывать малозначимые правки в списке свежих изменений',
+'tog-usenewrc' => 'Улучшенный список свежих изменений (JavaScript)',
+'tog-numberheadings' => 'Автоматически нумеровать заголовки',
+'tog-showtoolbar'               => 'Показывать панель инструментов при редактировании (JavaScript)',
+'tog-editondblclick' => 'Править статьи по двойному щелчку (JavaScript)',
+'tog-editsection'               => 'Показывать ссылку «править» для каждой секции',
+'tog-editsectiononrightclick'   => 'Править секции при правом щелчке мышью на заголовке (JavaScript)',
+'tog-showtoc'                   => 'Показывать оглавление (для страниц более чем с 3 заголовками)',
+'tog-rememberpassword' => 'Запоминать пароль между сеансами',
+'tog-editwidth' => 'Поле редактирования во всю ширину окна обозревателя',
+'tog-watchdefault' => 'По умолчанию добавлять новые и изменённые статьи в список наблюдения',
+'tog-minordefault' => 'По умолчанию помечать изменения как малозначимые',
+'tog-previewontop' => 'Показывать предпросмотр статьи до окна редактирования',
+'tog-previewonfirst' => 'Предварительный просмотр по первому изменению',
+'tog-nocache' => 'Запретить кеширование страниц',
+'tog-enotifwatchlistpages'      => 'Уведомлять по эл. почте об изменениях страниц',
+'tog-enotifusertalkpages'       => 'Уведомлять по эл. почте об изменении персональной страницы обсуждения',
+'tog-enotifminoredits'          => 'Уведомлять по эл. почте даже при малозначительных изменениях',
+'tog-enotifrevealaddr'          => 'Показывать мой почтовый адрес в сообщениях оповещения',
+'tog-shownumberswatching'       => 'Показывать число участников, включивших страницу в свой список наблюдения',
+'tog-fancysig' => 'Простая подпись (без автоматической ссылки)',
+'tog-externaleditor' => 'Использовать по умолчанию внешний редактор',
+'tog-externaldiff' => 'Использовать по умолчанию внешную программу сравнения версий',
+
+'underline-always' => 'Всегда',
+'underline-never' => 'Никогда',
+'underline-default' => 'Использовать настройки браузера',
+
+'skinpreview' => '(Предпросмотр)',
+
+# dates
+'sunday' => 'Воскресенье',
+'monday' => 'Понедельник',
+'tuesday' => 'Вторник',
+'wednesday' => 'Среда',
+'thursday' => 'Четверг',
+'friday' => 'Пятница',
+'saturday' => 'Суббота',
+'january' => 'января',
+'february' => 'февраля',
+'march' => 'марта',
+'april' => 'апреля',
+'may_long' => 'мая',
+'june' => 'июня',
+'july' => 'июля',
+'august' => 'августа',
+'september' => 'сентября',
+'october' => 'октября',
+'november' => 'ноября',
+'december' => 'декабря',
+'jan' => 'янв',
+'feb' => 'фев',
+'mar' => 'мар',
+'apr' => 'апр',
+'may' => 'май',
+'jun' => 'июн',
+'jul' => 'июл',
+'aug' => 'авг',
+'sep' => 'сен',
+'oct' => 'окт',
+'nov' => 'ноя',
+'dec' => 'дек',
+# Bits of text used by many pages:
+#
+'categories' => 'Категории',
+'category' => 'категория',
+'category_header' => 'Статьи в категории «$1»',
+'subcategories' => 'Подкатегории',
+
+
+'linktrail'             => '/^((?:[a-z]|а|б|в|г|д|е|ё|ж|з|и|й|к|л|м|н|о|п|р|с|т|у|ф|х|ц|ч|ш|щ|ъ|ы|ь|э|ю|я)+)(.*)$/sD',
+'linkprefix'            => '/^(.*?)([a-zA-Z\x80-\xff\x4000-\x4f0f]+)$/sD',
+'mainpage'              => 'Заглавная страница',
+'mainpagetext'  => 'Програмное обеспечение вики-проекта успешно установлено.',
+"mainpagedocfooter" => "См. [http://meta.wikipedia.org/wiki/MediaWiki_i18n documentation on customizing the interface]
+и [http://meta.wikipedia.org/wiki/MediaWiki_User%27s_Guide User's Guide] по использованию и настройке справочной системы.",
+
+'portal'                => 'Сообщество',
+'portal-url'            => "{{ns:project}}:Портал сообщества",
+'about'                 => 'Описание',
+'aboutsite'      => 'Описание {{grammar:genitive|{{SITENAME}}}}',
+'aboutpage'           => '{{ns:project}}:Описание',
+'article' => 'Статья',
+'help'                  => 'Справка',
+'helppage'            => '{{ns:project}}:Справка',
+'wikititlesuffix' => '{{SITENAME}}',
+'bugreports'  => 'Отчёт об ошибке',
+'bugreportspage' => '{{ns:project}}:Отчёт об ошибке',
+'sitesupport'   => 'Пожертвования', # To enable, something like 'Donations', '-' to disable
+'sitesupport-url' => "{{ns:project}}:Пожертвования",
+'faq'                   => 'ЧаВО',
+'faqpage'             => '{{ns:project}}:ЧаВО',
+'edithelp'            => 'Справка по редактированию',
+'newwindow'           => '(в новом окне)',
+'edithelppage'        => '{{ns:project}}:Справка по редактированию',
+'cancel'                => 'Отменить',
+'qbfind'                => 'Поиск',
+'qbbrowse'              => 'Просмотреть',
+'qbedit'                => 'Править',
+'qbpageoptions' => 'Настройки страницы',
+'qbpageinfo'    => 'Сведения о статье',
+'qbmyoptions'   => 'Ваши настройки',
+'qbspecialpages'        => 'Специальные страницы',
+'moredotdotdot' => 'Далее…',
+'mypage'                => 'Ваша личная страница',
+'mytalk'                => 'Ваше личное обсуждение',
+'anontalk'              => 'Обсуждение для этого IP-адреса',
+'navigation' => 'Навигация',
+
+# Metadata in edit box
+'metadata' => '<strong>Метаданные</strong> (подробности смотри <a href="$1">здесь</a>)',
+'metadata_page' => "{{ns:project}}:Метаданные",
+
+'currentevents' => 'Текущие события',
+'currentevents-url' => 'Текущие события',
+
+'disclaimers' => 'Отказ от ответственности',
+'disclaimerpage' => "{{ns:project}}:Отказ от ответственности",
+'errorpagetitle' => "Ошибка",
+'returnto'            => "Возврат к странице $1.",
+'tagline'             => "Материал из {{grammar:genitive|{{SITENAME}}}}.",
+'whatlinkshere' => 'Ссылки сюда',
+'help'                  => 'Справка',
+'search'                => 'Поиск',
+'go'            => 'Перейти',
+"history"             => 'История',
+'history_short' => 'История',
+'updatedmarker' => 'Обновлено с моего последнего посещения',
+'info_short'    => 'Информация',
+'printableversion' => 'Версия для печати',
+'print' => 'Печать',
+'edit' => 'Править',
+'editthispage'  => 'Править эту статью',
+'delete' => 'Удалить',
+'deletethispage' => 'Стереть её',
+'undelete_short' => 'Восстановить $1 правок',
+'undelete_short1' => 'Восстановить одну правку',
+'protect' => 'Защитить',
+'protectthispage' => 'Защитить',
+'unprotect' => 'Снять защиту',
+'unprotectthispage' => 'Снять защиту',
+'newpage' => 'Новая статья',
+'talkpage'              => 'Обсуждение',
+'specialpage' => 'Служебная страница',
+'personaltools' => 'Личные инструменты',
+'postcomment'   => 'Комментировать',
+'addsection'   => '+',
+'articlepage'   => 'Просмотреть статью',
+'subjectpage'   => 'Просмотреть тему', # For compatibility
+'talk' => 'Обсуждение',
+'views' => 'Просмотры',
+'toolbox' => 'Инструменты',
+'userpage' => 'Cтраница участника',
+'wikipediapage' => 'Просмотреть мета-страницу',
+'imagepage' =>       'Просмотреть страницу изображения',
+'viewtalkpage' => 'Просмотреть обсуждение',
+'otherlanguages' => 'На других языках',
+'redirectedfrom' => '(Перенаправлено с $1)',
+'lastmodified'  => 'Последнее изменение этой страницы: $1.',
+'viewcount'             => 'К этой странице обращались $1 раз(а).',
+'copyright'     => 'Содержимое доступно в соответствии с $1.',
+'poweredby'     => "{{SITENAME}} работает на [http://www.mediawiki.org/ MediaWiki], открытом вики-движке.",
+'printsubtitle' => "(Материал с {{SERVER}})",
+'protectedpage' => 'Защищённая статья',
+
+'administrators' => "{{ns:project}}:Администраторы",
+'sysoptitle'    => 'Необходим уровень доступа «Администратор»',
+'sysoptext'     => "Затребованное вами действие может быть совершено только пользователями с правами «Администратора».
+См. $1.",
+'developertitle' => 'Необходим уровень доступа «Разработчик»',
+'developertext'  => "Затребованное вами действие может быть совершено только пользователями с правами «Разработчика».
+См. $1.",
+
+'badaccess' => 'Ошибка доступа',
+'badaccesstext' => 'Запрошенное вами действие может быть выполнено
+только участниками с правами доступа «$2». См. $1.',
+
+'versionrequired' => 'Требуется MediaWiki версии $1',
+'versionrequiredtext' => 'Для работы с этой страницей требуется MediaWiki версии $1. См. [[Special:Version]].',
+
+'nbytes'                => '$1 байт(ов)',
+'ok'                    => 'OK',
+'sitetitle'             => "{{SITENAME}}",
+'pagetitle'             => "$1 — {{SITENAME}}",
+'sitesubtitle'  => 'Свободная энциклопедия',
+'retrievedfrom' => "Получено с $1",
+'newmessages' => "Вы получили $1.",
+'newmessageslink' => 'новые сообщения',
+'editsection'=>'править',
+'toc' => 'Содержание',
+'showtoc' => 'показать',
+'hidetoc' => 'убрать',
+'thisisdeleted' => "Просмотреть или восстановить $1?",
+'viewdeleted' => 'Просмотреть $1?',
+'restorelink1' => 'одно удаление',
+'restorelink' => "$1 удаление(й)",
+'feedlinks' => 'В виде:',
+'sitenotice'    => '-', # the equivalent to wgSiteNotice
+
+# Short words for each namespace, by default used in the 'article' tab in monobook
+'nstab-main' => 'Статья',
+'nstab-user' => 'Участник',
+'nstab-media' => 'Мультимедиа',
+'nstab-special' => 'Служебная страница',
+'nstab-wp' => 'О проекте',
+'nstab-image' => 'Файл',
+'nstab-mediawiki' => 'Сообщение MediaWiki',
+'nstab-template' => 'Шаблон',
+'nstab-help' => 'Справка',
+'nstab-category' => 'Категория',
+
+# Main script and global functions
+#
+'nosuchaction'  => 'Неопознанное действие',
+'nosuchactiontext' => 'Действие, указанное в URL, не распознаётся программным обеспечением вики',
+'nosuchspecialpage' => 'Такой специальной страницы нет',
+'nospecialpagetext' => 'Запрошенной вами служебной страницы не существует. См. [[{{ns:special}}:Specialpages|список служебных страниц]].',
+
+# General errors
+#
+'error'                 => 'Ошибка',
+'databaseerror' => 'Ошибка базы данных',
+'dberrortext'   => "Обнаружена ошибка синтаксиса запроса к базе данных.
+Последний запрос к базе данных:
+<blockquote><tt>$1</tt></blockquote>
+произошёл из функции <tt>«$2»</tt>.
+MySQL возвратил ошибку <tt>«$3: $4»</tt>.",
+'dberrortextcl' => "Обнаружена ошибка синтаксиса запроса к базе данных.
+Последний запрос к базе данных:
+«$1»
+произошёл из функции «$2».
+MySQL возвратил ошибку «$3: $4».",
+'noconnect'             => 'Извините, сейчас невозможно связаться с сервером базы данных из-за технических проблем.<br />
+$1',
+'nodb'                  => "Невозможно выбрать базу данных $1",
+'cachederror'           => 'Ниже представлена кешированная копия запрошенной страницы; возможно, она устарела.',
+'laggedslavemode'   => 'Внимание: страница может не содержать последних обновлений.',
+'readonly'              => 'Запись в базу данных заблокирована',
+'enterlockreason' => 'Укажите причину и намеченный срок блокировки.',
+'readonlytext'  => "Добавление новых статей и другие изменения базы данных сейчас заблокированы: вероятно, в связи с плановым обслуживанием.
+Заблокировавший оператор оставил следующее разъяснение:
+$1",
+'missingarticle' => "База данных не нашла текста статьи,
+хотя должна была найти, по имени «$1».
+
+Обычно это вызвано использованием устаревшей ссылки на журнал изменений или различий для статьи, которая была удалена.
+
+Если дело не в этом, то скорее всего, вы обнаружили ошибку в программном обеспечении вики.
+Пожалуйста, сообщите об этом администратору, указав URL.",
+'readonly_lag' => "База данных автоматически заблокирована от изменений на время пока вторичный сервер БД не синхронизируется с первичным.",
+'internalerror' => 'Внутренняя ошибка',
+'filecopyerror' => "Невозможно скопировать файл «$1» в «$2».",
+'filerenameerror' => "Невозможно переименовать файл «$1» в «$2».",
+'filedeleteerror' => "Невозможно удалить файл «$1».",
+'filenotfound'  => "Невозможно найти файл «$1».",
+'unexpected'    => "Неподходящее значение: «$1»=«$2».",
+'formerror'             => 'Ошибка: невозможно передать данные формы',
+'badarticleerror' => 'Это действие не может быть выполнено на данной странице.',
+'cannotdelete'  => 'Невозможно удалить указанную страницу или файл. (Возможно, его уже удалил кто-то другой.)',
+'badtitle'              => 'Недопустимое название',
+'badtitletext' => "Запрашиваемое название статьи неправильно, пусто, либо неправильно указано междуязыковое или между-вики название.",
+'perfdisabled' => 'К сожалению, эта возможность временно недоступна в связи с загруженностью серера.',
+'perfdisabledsub' => "Это — сохранённая копия от $1:", # obsolete?
+'perfcached' => 'Следующие данные взяты из кэша и могут не содержать последних изменений:',
+'wrong_wfQuery_params' => "Недопустимые параметры для функции wfQuery()<br />
+Функция: $1<br />
+Запрос: $2",
+'viewsource' => 'Просмотр',
+'protectedtext' => "Эта страница заблокирована для предотвращения её изменений.
+Существуют несколько причин по которым это могло быть сделано,
+смотрите [[{{ns:project}}:Журнал защиты]] для того чтобы узнать причину, связанную с этой страницей.
+
+Вы можете просмотреть и скопировать исходный код этой страницы:",
+'sqlhidden' => '(SQL запрос скрыт)',
+
+# Login and logout pages
+#
+'logouttitle' => 'Стать инкогнито',
+'logouttext'          => "Вы работаете в том же режиме, который был до вашего представления системе. Вы идентифицируетесь не по имени, а по IP-адресу.
+Вы можете продолжить участие в проекте анонимно или начать новый сеанс как тот же самый или другой пользователь.\n",
+
+'welcomecreation' => "== Добро пожаловать, $1! ==
+
+Вы были зарегистрированы.
+Не забудьте провести [[{{ns:special}}:Preferences|персональную настройку сайта]].",
+'loginpagetitle' => 'Представиться системе',
+'yourname'              => 'Ваше имя участника',
+'yourpassword'  => 'Ваш пароль',
+'yourpasswordagain' => 'Повторный набор пароля',
+'newusersonly'  => ' (только для новых участников)',
+'remembermypassword' => 'Запоминать пароль',
+'yourdomainname'       => 'Ваш домен',
+'externaldberror'      => 'Произошла ошибка при аутентификации с помощью внешней базы данных, или у вас недостаточно прав для внесения изменений в свою внешнюю учётную запись.',
+'loginproblem'  => '<span style="color:red">Участник неопознан.</span>',
+'alreadyloggedin' => "<strong>Участник $1, вы уже представились системе!</strong><br />",
+
+'login'                 => 'Представиться системе',
+'loginprompt'           => "Вы должны разрешить «cookies», чтобы представиться системе.",
+'userlogin'             => 'Представиться системе',
+'logout'                => 'Завершение сеанса',
+'userlogout'    => 'Завершение сеанса',
+'notloggedin'   => 'Вы не представились системе',
+'createaccount' => 'Зарегистрировать нового участника',
+'createaccountmail'     => 'по эл. почте',
+'badretype'             => 'Введённые вами пароли не совпадают.',
+'userexists'    => 'Введённое вами имя участника уже существует. Пожалуйста, выберите другое имя.',
+'youremail'             => 'Ваш адрес электронной почты *',
+'yourrealname'          => 'Ваше настоящее имя (*)',
+'yourlanguage'  => 'Язык интерфейса',
+'yourvariant'  => 'Вариант языка',
+'yournick'              => 'Ваш псевдоним (для подписей)',
+'email'                 => 'Эл. почта',
+'emailforlost'          => "Поля отмеченные звёздочкой необязательны для заполнения.
+Вводить ваш адрес электронной почты необязательно. Однако это позволит людям связываться с вами через веб-сайт, не зная вашего адреса электронной почты. Также это поможет в случае, если вы забудете свой пароль.<br /><br />
+Ваше настоящее имя будет использовано для подписи ваших работ.",
+'prefs-help-email-enotif' => 'Этот адрес также используется для отправки по электронной почте оповещений об изменении страниц если вы активировали соответствующую опцию.',
+'prefs-help-realname'   => '* Настоящее имя (необязательное поле): если вы укажите его, то оно будет использовано для того чтобы показать кем был внесена правка страницы.',
+'loginerror'    => 'Ошибка опознавания участника',
+'prefs-help-email'      => '* Электронная почта (необязательное поле): позволяет другим участникам связаться с вами без раскрытия адреса вашей электронной почты, а также может быть использован для напоминания пароля, если вы его забудете.',
+'nocookiesnew'  => "Участник зарегистрирован, но не представлен. {{SITENAME}} использует «cookies» для представления участников. У вас «cookies» запрещены. Пожалуйста, разрешите их, а затем преставьтесь с вашим новым именем участника и паролем.",
+'nocookieslogin'      => "{{SITENAME}} использует «cookies» для представления участников. Вы их отключили. Пожалуйста, включите их и попробуйте снова.",
+'noname'                => 'Вы не указали допустимого имени участника.',
+'loginsuccesstitle' => 'Опознавание прошло успешно',
+'loginsuccess'  => "Теперь вы работаете под именем $1.",
+'nosuchuser'    => "Участника с именем $1 не существует.
+Проверьте правильность написания, или воспользуйтесь формой ниже, чтобы зарегистрировать нового участника.",
+'nosuchusershort'       => "Не существует участника с именем $1. Проверьте написание имени.",
+'wrongpassword'         => 'Введённый вами пароль неверен. Попробуйте ещё раз.',
+'mailmypassword'        => 'Выслать новый пароль',
+'passwordremindertitle' => "Напоминание пароля участника {{grammar:genitive|{{SITENAME}}}}",
+'passwordremindertext' => "Кто-то (возможно вы) с IP-адресом $1 запросил,
+чтобы мы выслали вам новый пароль участника {{grammar:genitive|{{SITENAME}}}}.
+Пароль для участника $2 теперь: <code>$3</code>.
+Мы рекомендуем вам представиться системе и поменять пароль.",
+'noemail'               => "Для участника с именем $1 электронный адрес указан не был.",
+'passwordsent'          => "Новый пароль был выслан на адрес электронной почты, указанный для участника $1.
+
+Пожалуйста, представьтесь системе заново после получения пароля.",
+'eauthentsent'          =>  "Временный пароль был отправлен на адрес электронной почты нового участника $1. В письме также описаны действия, которые нужно выполнить, чтобы подтвердить, что этот адрес электронной почты действительно принадлежит вам.",
+'loginend'              => ' ',
+'mailerror' => "Ошибка при посылке почты: $1",
+'acct_creation_throttle_hit' => 'К сожалению, вы уже создали $1 учётных записей. Вы не можете создать больше ни одной.',
+'emailauthenticated'    => 'Ваш почтовый адрес был сопоставлен с $1.',
+'emailnotauthenticated' => 'Ваш адрес электронной почты <strong>ещё не был подтверждён</strong>, функции вики-движка по работе с эл. почтой отключены.',
+'noemailprefs'          => '<strong>Адрес электронной почты не был указан</strong>, функции вики-движка по работе с эл. почтой отключены.',
+'emailconfirmlink' => 'Подтвердить ваш адрес электронной почты',
+'invalidemailaddress'   => 'Введённый адрес не может быть принят, т. к. он не соответствует формату адресов электронной почты. Пожалуйста введите корректный адрес или оставьте поле пустым.',
+
+# Edit page toolbar
+'bold_sample'=>'Жирный шрифт',
+'bold_tip'=>'Жирный шрифт',
+'italic_sample'=>'Курсивный текст',
+'italic_tip'=>'Курсивный текст',
+'link_sample'=>'Заголовок ссылки',
+'link_tip'=>'Внутренняя ссылка',
+'extlink_sample'=>'http://www.example.com заголовок ссылки',
+'extlink_tip'=>'Внешняя ссылка (помните о префиксе http:// )',
+'headline_sample'=>'Текст заголовка',
+'headline_tip'=>'Заголовок 2-го уровня',
+'math_sample'=>'Вставляйте сюда формулу',
+'math_tip'=>'Математическая формула (формат LaTeX)',
+'nowiki_sample'=>'Вставляйте сюда неотформатированный текст.',
+'nowiki_tip'=>'Не обрабатывать как размеченный текст',
+'image_sample'=>'Example.jpg',
+'image_tip'=>'Встроенное изображение',
+'media_sample'=>'Example.ogg',
+'media_tip'=>'Ссылка на медиа-файл',
+'sig_tip'=>'Ваша подпись и момент времени',
+'hr_tip'=>'Горизонтальная линия (не используйте часто)',
+'infobox'=>'Щёлкните по кнопке, чтобы получить текст примера',
+# alert box shown in browsers where text selection does not work, test e.g. with mozilla or konqueror
+'infobox_alert'=>"Пожалуйста, ввведите текст, который вы хотите отформатировать.\n Он будет показан в инфобоксе для копирования и вставки.\nНапример:\n$1\nстанет:\n$2",
+
+# Edit pages
+#
+'summary'               => 'Краткое описание изменений',
+'subject'               => 'Тема/заголовок',
+'minoredit'             => 'Незначительное изменение',
+'watchthis'             => 'Включить эту страницу в список наблюдения',
+'savearticle'   => 'Записать страницу',
+'preview'               => 'Предпросмотр',
+'showpreview'   => 'Предварительный просмотр',
+'showdiff'      => 'Внесённые изменения',
+'blockedtitle'  => 'Участник заблокирован',
+'blockedtext'   => "Ваше имя участника или IP-адрес был заблокирован $1.
+Утверждается, что причина такова:<br />''$2''<p>Вы можете связаться с $1 или одним из других
+[[{{ns:project}}:Администраторы|администраторов]] чтобы обсудить блокировку.",
+'whitelistedittitle' => 'Для изменения требуется авторизаци',
+'whitelistedittext' => 'Вы должны [[{{ns:special}}:Userlogin|зарегистрироваться]] для изменения этих страниц.',
+'whitelistreadtitle' => 'Для чтения требуется авторизация',
+'whitelistreadtext' => 'Вы должны [[Special:Userlogin|зарегистрироваться]] для чтения этих страниц.',
+'whitelistacctitle' => 'У вас нет прав чтобы создать учётную запись',
+'whitelistacctext' => 'Для того чтобы иметь возможность создавать учётные записи в этой вики вы должны [[Special:Userlogin|зарегистрироваться]] и иметь соответствующие права.',
+'loginreqtitle' => 'Требуется авторизация',
+'loginreqlink' => 'представиться системе',
+'loginreqpagetext'  => 'Вы должны $1 для того чтобы просматривать остальные страницы.',
+'accmailtitle' => 'Пароль выслан.',
+'accmailtext' => "Пароль для '$1' выслан на $2.",
+'newarticle'    => '(Новая)',
+'newarticletext' =>
+"Вы перешли по ссылке на статью, которая пока не существует.
+Чтобы создать новую страницу, наберите текст в окне, расположенном ниже
+(см. [[{{ns:project}}:Справка|справочную страницу]] чтобы получить больше информации).
+Если вы оказались здесь по ошибке, просто нажмите кнопку '''назад''' вашего браузера.",
+'talkpagetext' => '<!-- MediaWiki:talkpagetext -->',
+'anontalkpagetext' => "---- ''Эта страница обсуждения принадлежит анонимному участнику, который ещё не зарегистрировался или который не представился регистрированным именем. Для его идентификации используется цифоровой [[IP-адрес]]. Если Вы — анонимный участник и полагаете, что получили сообщения, адресованные не Вам (один IP-адрес может использоваться несколькими участниками), [[Служебная:Userlogin|представьтесь системе]], чтобы впредь избежать возможной путаницы с другими анонимными участниками.''",
+'noarticletext' => '(Сейчас на этой странице нет текста)',
+'clearyourcache' => "'''Замечание:''' Чтобы после сохранения увидеть сделанные изменения, очистите кэш своего браузера: '''Mozilla / Firefox''': ''Ctrl+Shift+R'', '''IE:''' ''Ctrl+F5'', '''Safari''': ''Cmd+Shift+R'', '''Konqueror''': ''F5'', '''Opera''': очистить кеш через меню ''Tools→Preferences''.",
+'usercssjsyoucanpreview' => "<strong>Подсказка:</strong> Используйте кнопку предварительного просмотра чтобы протестировать ваш новый css-файл или js-файл перед сохранением.",
+'usercsspreview' => "'''Помните что это только предварительный просмотр вашего css-файла, он ещё не сохранён!'''",
+'userjspreview' => "'''Помните что это только предварительный просмотр вашего javascrpt-файла, он ещё не сохранён!'''",
+'updated'               => '(Обновлена)',
+'note'                  => '<strong>Примечание:</strong> ',
+'previewnote'   => 'обратите внимание, что это только предварительный просмотр, и текст ещё не записан!',
+'previewconflict' => 'Этот предварительный просмотр отражает текст из окна редактирования, как он будет выглядеть, если вы решите записать его.',
+'editing'               => "Редактирование $1",
+'editingsection'                => "Редактирование $1 (секция)",
+'editingcomment'                => "Редактирование $1 (комментарий)",
+'editconflict'  => 'Конфликт редактирования: $1',
+'explainconflict' => "Пока вы редактировали эту статью, кто-то внёс в неё изменения. В верхнем окне для редактирования вы видите тот текст статьи, который будет сохранён при нажатии на кнопку «Записать страницу». В нижнем окне для редактирования находится ваш вариант. Чтобы сохранить ваши изменения, перенесите их из нижнего окна для редактирования в верхнее.<br />",
+'yourtext'              => 'Ваш текст',
+'storedversion' => 'Сохранённая версия',
+'nonunicodebrowser' => "<strong>ПРЕДУПРЕЖДЕНИЕ: Ваш [[браузер]] не поддерживает кодировку [[Юникод]]. При редактировании статей все не-ASCII символы будут заменены на свои шестнадцатеричные коды.</strong>",
+'editingold'    => "<strong>ПРЕДУПРЕЖДЕНИЕ: Вы редактируете устаревшую версию данной страницы. После сохранения страницы будут потеряны изменения сделанные в последующих версиях.</strong>",
+'yourdiff'              => 'Различия',
+'copyrightwarning' => "Пожалуйста, обратите внимание, что все добавления и изменения
+рассматриваются, как выпущенные на условиях лицензии $2 (см. $1).
+Внося какие-либо дополнения, вы соглашаетесь с тем, что они могут быть изменены кем угодно.
+Если вы не хотите, чтобы ваши тексты свободно распространялись и редактировались,
+не помещайте их сюда.<br />
+Вы также подтверждаете, что являетесь автором вносимых дополнений, или скопировали их из
+источника, допускающего свободное распространение и изменение своего содержимого.<br />
+<strong>НЕ РАЗМЕЩАЙТЕ БЕЗ РАЗРЕШЕНИЯ ОХРАНЯЕМЫЕ АВТОРСКИМ ПРАВОМ МАТЕРИАЛЫ!</strong>",
+'copyrightwarning2' => "Пожалуйста, обратите внимание, что все ваши добавления
+могут быть отредактированы или удалены другими участниками.
+Если вы не хотите, чтобы кто-либо изменял ваши тексты, не помещайте их сюда.<br />
+Вы также подтверждаете, что являетесь автором вносимых дополнений, или скопировали их из
+источника допускающего свободное распространение и изменение своего содержимого (см. $1).<br />
+<strong>НЕ РАЗМЕЩАЙТЕ БЕЗ РАЗРЕШЕНИЯ ОХРАНЯЕМЫЕ АВТОРСКИМ ПРАВОМ МАТЕРИАЛЫ!</strong>",
+'longpagewarning' => "<strong>ПРЕДУПРЕЖДЕНИЕ: размер этой страницы $1 килобайт; страницы, размер которых превышает 32 килобайта, могут быть неверно отображены в окне редактирование некоторых браузеров.
+Пожалуйста, рассмотрите вариант разбиения страницы на меньшие части.</strong>",
+'readonlywarning' => '<strong>ПРЕДУПРЕЖДЕНИЕ: база данных заблокирована в связи с процедурами обслуживания,
+поэтому вы не можете записать ваши изменения прямо сейчас.
+Возможно, вам следует сохранить текст в файл на своём диске и поместить его в данный проект позже.</strong>',
+'protectedpagewarning' => "<strong>ПРЕДУПРЕЖДЕНИЕ: эта страница заблокирована и только [[Project:Администраторы|администраторы проекта]] могут изменять её. См. [[Project:Правила защиты страниц|правила защиты страниц]].</strong>",
+'templatesused' => 'Шаблоны, использованные на этой странице:',
+
+# History pages
+#
+'revhistory'    => 'Журнал изменений',
+'nohistory'             => 'Для этой страницы журнал изменений отстуствует.',
+'revnotfound'   => 'Версия не найдена',
+'revnotfoundtext' => "Старая версия страницы не найдена.
+Пожалуйста, проверьте правильность ссылки, которую вы использовали для доступа к этой странице.",
+'loadhist'              => 'Загрузка журнала изменений страницы',
+'currentrev'    => 'Текущая версия',
+'revisionasof'          => 'Версия $1',
+'revisionasofwithlink'  => 'Версия как $1; $2<br />$3 | $4',
+'previousrevision'      => '← Старая версия',
+'nextrevision'          => 'Новые версии →',
+'currentrevisionlink'   => 'перейти к текущей версии',
+'cur'                   => 'текущ.',
+'next'                  => 'след.',
+'last'                  => 'пред.',
+'orig'                  => 'перв.',
+'histlegend'    => 'Пояснения: (текущ.) — отличие от текущей версией,
+(пред.) — отличие от предшествующей версии, M — малозначимое изменение',
+'history_copyright'    => '—',
+'deletedrev' => '[удалена]',
+'histfirst' => 'Первый',
+'histlast' => 'Последний',
+
+# Diffs
+#
+'difference'    => '(Различия между версиями)',
+'loadingrev'    => 'загрузка версии для различения',
+'lineno'                => "Строка $1:",
+'editcurrent'   => 'Редактировать текущую версию данной страницы',
+'selectnewerversionfordiff' => 'Выберите новую версию для сравнения',
+'selectolderversionfordiff' => 'Выберите старую версию для сравнения',
+'compareselectedversions' => 'Сравнить выбранные версии',
+
+# Search results
+#
+'searchresults' => 'Результаты поиска',
+'searchresulttext' => "Для получения более подробной информации о поиске на страницах проекта, см. [[{{ns:project}}:Поиск]].",
+'searchquery'   => "По запросу «$1»",
+'badquery'              => 'Неправильно сформированный запрос',
+'badquerytext'  => 'Невозможно обработать ваш запрос.
+Возможно, причина этого в том, что вы попытались найти слово, которое короче трёх букв, что пока не поддерживается.
+Возможно также, что вы допустили опечатку в слове.
+Попробуйте другой запрос.',
+'matchtotals'   => "Запросу «$1» соответсвует(ют) $2 название(я) статьи(ей) и тексты $3 статьи(ей).",
+'nogomatch' => "Страницы с таким названием не существует.
+
+<span style=\"display: block; margin: 1.5em 2em\">'''[[$1|Создать страницу.]]'''</span>",
+'titlematches'  => 'Совпадения в названиях статей',
+'notitlematches' => 'Нет совпадений в названиях статей',
+'textmatches'   => 'Совпадения в текстах статей',
+'notextmatches' => 'Нет совпадения в текстах статей',
+'prevn'                 => "предыдущие $1",
+'nextn'                 => "следующие $1",
+'viewprevnext'  => "Просмотреть ($1) ($2) ($3).",
+'showingresults' => "Ниже показаны <strong>$1</strong> результатов, начиная с <strong>#$2</strong>.",
+'showingresultsnum' => "Ниже показаны <strong>$3</strong> результатов, начиная с №<strong>$2</strong>.",
+'nonefound'             => "Неудачный поиск может быть вызван попыткой найти общие слова, которые не подлежат индексированию, например — «тоже» и «чтобы» или употреблением более чем одного ключевого слова поиска (показываются только страницы, содержащие все указанные слова для поиска).",
+'powersearchtext' => "
+Искать в пространствах имён:<br />
+$1<br />
+$2 — Показывать перенаправления &nbsp; Искать $3 $9",
+"searchdisabled" => 'Извините, но встроенный полнотекстовый поиск выключен. Вы можете воспользоваться поиском по сайту через поисковые системы общего назначения, однако имейте в виду, что копия сайта в их кэше может быть несколько устаревшей.',
+
+'googlesearch' => '
+<form method="get" action="http://www.google.com/search" id="googlesearch">
+    <input type="hidden" name="domains" value="{{SERVER}}" />
+    <input type="hidden" name="num" value="50" />
+    <input type="hidden" name="ie" value="$2" />
+    <input type="hidden" name="oe" value="$2" />
+
+    <input type="text" name="q" size="31" maxlength="255" value="$1" />
+    <input type="submit" name="btnG" value="Поиск по сайту с помощью Google" />
+    <input type="hidden" name="sitesearch" value="{{SERVER}}" />
+</form>
+<br />
+<br />
+<form name="web" method="get" action="http://www.yandex.ru/yandsearch">
+  <input type="hidden" name="serverurl" value="{{SERVER}}" />
+  <input type="hidden" name="server_name" value="{{SITENAME}} (русская версия)" />
+  <input type="hidden" name="rpt" value="rad" />
+  <input type="hidden" name="referrer1" value="{{SERVER}}" />
+  <input type="hidden" name="referrer2" value="{{SITENAME}} (русская версия)" />
+
+  <input type="text" name="text" size="31" maxlength="255" value="$1" />
+  <input type="submit" value="Поиск по сайту с помощью Яндекса" />
+</form>',
+'blanknamespace' => 'Статьи',
+
+# Preferences page
+#
+'preferences'   => 'Настройки',
+'prefsnologin' => 'Вы не представились системе',
+'prefsnologintext'      => "Вы должны [[Special:Userlogin|представиться системе]]
+чтобы изменять настройки участника.",
+'prefslogintext' => "Вы представились системе под именем $1.
+Ваш внутренний идентификационый номер — $2.
+
+Cм. [[{{ns:project}}:Справка по настройкам]], чтобы разобраться с настройками.",
+'prefsreset'    => 'Настройки были переустановлены в стандартное состояние.',
+'qbsettings'    => 'Панель навигации',
+'changepassword' => 'Сменить пароль',
+'skin'                  => 'Оформление',
+'math'                  => 'Отображение формул',
+'dateformat'    => 'Формат даты',
+'math_failure'          => 'Невозможно разобрать выражение',
+'math_unknown_error'    => 'неизвестная ошибка',
+'math_unknown_function' => 'неизвестная функция ',
+'math_lexing_error'     => 'лексическая ошибка',
+'math_syntax_error'     => 'синтаксическая ошибка',
+'math_image_error'      => 'Преобразование в PNG прошло с ошибкой; проверьте правильность установки latex, dvips, gs и convert',
+'math_bad_tmpdir'       => 'Не удаётся создать или записать во временный каталог математики',
+'math_bad_output'       => 'Не удаётся создать или записать в выходной каталог математики',
+'math_notexvc'  => 'Выполняемый файл texvc не найден; См. math/README — справку по настройке.',
+'prefs-personal' => 'Личное',
+'prefs-rc' => 'Страница свежих правок',
+'prefs-misc' => 'Другие настройки',
+'saveprefs'             => 'Записать',
+'resetprefs'    => 'Сбросить',
+'oldpassword'   => 'Старый пароль',
+'newpassword'   => 'Новый пароль',
+'retypenew'             => 'Повторите ввод нового пароля',
+'textboxsize'   => 'Размеры поля ввода',
+'rows'                  => 'Строк',
+'columns'               => 'Столбцов',
+'searchresultshead' => 'Результаты поиска',
+'resultsperpage' => 'Количество найденных записей на страницу',
+'contextlines'  => 'Количество показываемых строк для каждой найденной',
+'contextchars'  => 'Количество символов контекста на строку',
+'stubthreshold' => 'Порог определения болванки',
+'recentchangescount' => 'Заголовки статей на странице свежих правок',
+'savedprefs'    => 'Ваши настройки сохранены.',
+'timezonelegend' => 'Часовой пояс',
+'timezonetext'  => 'Введите смещение (в часах) вашего местного времени
+от времени сервера (UTC — гринвичского).',
+'localtime'     => 'Местное время',
+'timezoneoffset' => 'Смещение',
+'servertime'    => 'Текущее время сервера',
+'guesstimezone' => 'Заполнить из браузера',
+'emailflag'             => 'Не принимать электронные письма от других участников',
+'defaultns'             => 'По умолчанию, искать в следующих пространствах имён:',
+'default'               => 'по умолчанию',
+'files'                 => 'Файлы',
+
+# User levels special page
+#
+
+# switching pan
+'groups-lookup-group' => 'Управление правами группы',
+'groups-group-edit' => 'Существующие группы: ',
+'editgroup' => 'Изменить группу',
+'addgroup' => 'Добавить группу',
+
+'userrights-lookup-user' => 'Управление группами пользователя',
+'userrights-user-editname' => 'Введите имя участника: ',
+'editusergroup' => 'Изменить группы пользователей',
+
+# group editing
+'groups-editgroup' => 'Изменить группу',
+'groups-addgroup' => 'Добавить группу',
+'groups-editgroup-preamble' => 'Если название или описание начинаются с двоеточия,
+то их текст будет заменён на соответствующее сообщение из пространства имён MediaWiki',
+'groups-editgroup-name' => 'Название группы: ',
+'groups-editgroup-description' => 'Описание группы (максимум 255 символов):<br />',
+'savegroup' => 'Сохранить группу',
+'groups-tableheader'        => 'ID || Название || Описание || Права',
+'groups-existing'           => 'Существующие группы',
+'groups-noname'             => 'Пожалуйста, укажите формально правильное название группы.',
+'groups-already-exists'     => 'Группа с таким названием уже существует',
+'addgrouplogentry'          => 'Добавлена группа $2',
+'changegrouplogentry'       => 'Изменена группа $2',
+'renamegrouplogentry'       => 'Группа $2 переименована в группу $3',
+
+# user groups editing
+'userrights-editusergroup' => 'Изменить группы участника',
+'saveusergroups' => 'Сохранить группы участника',
+'userrights-groupsmember' => 'Член групп:',
+'userrights-groupsavailable' => 'Доступные группы:',
+'userrights-groupshelp' => 'Выберите группы, в которые вы хотите включить или из которых хотите исключить участника.
+Невыбранные группы не изменятся. Группы можно убрать из выборки используя CTRL + левая клавиша мыши',
+'userrights-logcomment' => 'Членство группы изменено с $1 на $2',
+
+# Default group names and descriptions
+#
+'group-anon-name'       => 'Аноним',
+'group-anon-desc'       => 'Анонимные участники',
+'group-loggedin-name'   => 'Участник',
+'group-loggedin-desc'   => 'Зарегистрированные участники',
+'group-admin-name'      => 'Администратор',
+'group-admin-desc'      => 'Администраторы, могут блокировать других участников и удалять статьи',
+'group-bureaucrat-name' => 'Бюрократ',
+'group-bureaucrat-desc' => 'Бюрократы, могут назначать администраторов',
+'group-steward-name'    => 'Стюард',
+'group-steward-desc'    => 'Стюарды, полный доступ',
+
+# Recent changes
+#
+'changes' => 'изменения',
+'recentchanges' => 'Свежие правки',
+'recentchanges-url' => '{{ns:special}}:Recentchanges',
+'recentchangestext' => 'Ниже в хронологическом порядке перечислены последние изменения на страницах {{grammar:genitive|{{SITENAME}}}}.',
+'rcloaderr'             => 'Загрузка свежих правок',
+'rcnote'                => "Последние <strong>$1</strong> изменеий(я) за <strong>$2</strong> дней(я).",
+'rcnotefrom'    => "Ниже перечислены изменения с <strong>$2</strong> (по <strong>$1</strong>).",
+'rclistfrom'    => "Показать изменения с $1.",
+'showhideminor' => "$1 мелкие правки | $2 ботов | $3 представившихся участников | $4 проверенные правки",
+'rclinks'               => "Показать последние $1 изменений за $2 дней;<br />$3.",
+'rchide'                => "в форме $4; $1 малозначимых изменений; $2 вторичное(ые) пространство(а) имён; $3 множественных изменений.",
+'rcliu'                 => "; $1 изменений, сделанных представившимися участниками",
+'diff'                  => 'разн.',
+'hist'                  => 'журнал',
+'hide'                  => 'скрыть',
+'show'                  => 'показать',
+'tableform'             => 'таблица',
+'listform'              => 'список',
+'nchanges'              => "$1 изменение(я,ий)",
+'minoreditletter' => 'М',
+'newpageletter' => 'Н',
+'sectionlink' => '→',
+'number_of_watching_users_RCview'       => '[$1]',
+'number_of_watching_users_pageview'     => '[$1 наблюдающих пользователя]',
+
+# Upload
+#
+'upload'                => 'Загрузить файл',
+'uploadbtn'             => 'Загрузить файл',
+'uploadlink'    => 'Загрузить изображение',
+'reupload'              => 'Закачать повторно',
+'reuploaddesc'  => 'Вернуться к форме загрузки.',
+'uploadnologin' => 'Вы не представились системе',
+'uploadnologintext'     => "Вы должны [[Special:Userlogin|представиться системе]],
+чтобы загружать файлы на сервер.",
+'upload_directory_read_only' => 'Вебсервер не имеет прав записи в папку ($1), в которой предполагается хранить загружаемые файлы.',
+'uploaderror'   => 'Ошибка загрузки файла',
+'uploadtext'    => "Используя эту форму вы можете загрузить на сервер файлы.
+
+Чтобы просмотреть ранее загруженные файлы,
+перейдите сюда: [[Special:Imagelist|список загруженных изображений]].<br />
+Загрузка и удаление файлов отражаются в [[Special:Log|журнале загрузки файлов]].
+
+Вы также должны поставить галочку, подтверждающую, что вы не нарушаете чьих-либо авторских прав загрузкой этого файла.
+
+Нажмите кнопку «Загрузить», чтобы передать файл на сервер.
+
+Для включения изображения в статью вы можете использовать строки вида:
+*'''<nowiki>[[{{ns:6}}:file.jpg]]</nowiki>'''
+*'''<nowiki>[[{{ns:6}}:file.png|thumb|комментарий]]</nowiki>'''
+
+Для ссылки на медиа-файл вы можете использовать строку вида:
+*'''<nowiki>[[{{ns:-2}}:file.ogg]]</nowiki>'''
+",
+'uploadlog'             => 'журнал загрузок',
+'uploadlogpage' => 'Журнал_загрузок',
+'uploadlogpagetext' => 'Ниже представлен список последних загрузок файлов.
+Везде используется время сервера (по Гринвичу, UTC).
+<ul>
+</ul>',
+'filename'              => 'Имя файла',
+'filedesc'              => 'Краткое описание',
+'filestatus' => 'Условия распространения',
+'filesource' => 'Источник',
+'copyrightpage' => "{{ns:project}}:Авторское право",
+'copyrightpagename' => "Авторские права проекта {{SITENAME}}",
+'uploadedfiles' => 'Загруженые файлы',
+'ignorewarning' => 'Игнорировать предупреждение и всё равно записать файл.',
+'minlength'             => 'Название файла должно содержать хотя бы три символа.',
+'illegalfilename'       => 'Имя файла «$1» содержит символы, которые не разрешается использовать в заголовках. Пожалуйста, переименуйте файл и попытайтесь загрузить его снова.',
+'badfilename'   => "Название файла было изменено на $1.",
+'badfiletype'   => "«.$1» не является рекомендованным форматом для файлов с изображениями.",
+'largefile'             => 'Рекомедуется использовать изображения, размер которых не превышает $1 байт (размер загруженного файла составляет $2 байт).',
+'emptyfile'             => 'Загруженный вами файл вероятно пустой. Возможно, это произошло из-за ошибки при наборе имени файла. Пожалуйста, проверьте, действительно ли вы хотите загрузить этот файл.',
+'fileexists'            => 'Файл с этим именем уже существует, пожалуйста проверьте $1 если вы не уверены что вы хотите заменить его.',
+'successfulupload' => 'Загрузка успешно завершена',
+'fileuploaded'  => "Файл \"$1\" успешно загружен.
+
+Пожалуйста, проследуйте по следующей ссылке: ($2) к странице с описанием и заполните информацию о файле, такую как: источник файла, когда и кем был создан файл, а также любую другую информацию известную вам об этом файле.",
+'uploadwarning' => 'Предупреждение',
+'savefile'              => 'Записать файл',
+'uploadedimage' => "загружен «[[$1]]»",
+'uploaddisabled' => 'Извините, загрузка запрещена.',
+'uploadscripted' => 'Файл содержит HTML-код или скрипт, который может быть ошибочно обработан браузером.',
+'uploadcorrupt' => 'Файл либо повреждён, либо имеет неверное расширение. Пожалуйста, проверьте файл и попробуйте загрузить его ещё раз.',
+'uploadvirus' => 'Файл содержит вирус! См. $1',
+'sourcefilename' => 'Исходное имя файла',
+'destfilename' => 'Целевое имя файла',
+
+# Image list
+#
+'imagelist'             => 'Список файлов',
+'imagelisttext' => "Ниже представлен список из $1 файлов, отсортированных $2.",
+'getimagelist'  => 'получение списка файлов',
+'ilsubmit'              => 'Искать',
+'showlast'              => "Показать последние $1 файлов, отсортированных $2.",
+'byname'                => 'по имени',
+'bydate'                => 'по дате',
+'bysize'                => 'по размеру',
+'imgdelete'             => 'удал.',
+'imgdesc'               => 'описание',
+'imglegend'             => 'Пояснения: (описание) — показать/изменить описание файла.',
+'imghistory'    => 'Журнал',
+'revertimg'             => 'откат.',
+'deleteimg'             => 'удал.',
+'deleteimgcompletely'           => 'Удалить все версии',
+'imghistlegend' => 'Пояснения: (тек.) — текущий файл, (удал.) — удалить эту старую версию, (откат.) — откатиться на эту старую версию.
+<br /><em>Выберите дату, чтобы посмотреть список сайлов, загруженных на эту дату</em>.',
+'imagelinks'    => 'Ссылки',
+'linkstoimage'  => 'Следующие страницы ссылаются на данный файл:',
+'nolinkstoimage' => 'Нет страниц, ссылающихся на данный файл.',
+'sharedupload' => "Этот файл взят из [[Commons:Заглавная_страница|Викихранилища]] (WikiCommons), репозитория изображений и других свободно распространяемых медиа-файлов, общего для всех проектов [[Фонд Викимедиа|Фонда Викимедиа]]. См. '''[[Commons:Image:{{PAGENAME}}|страницу описания]]''', где находится описание изображения, в том числе и лицензия на него.",
+'shareduploadwiki' => 'Дополнительную информацию можно найти на $1.',
+'shareduploadwiki-linktext' => 'странице описания файла',
+'shareddescriptionfollows' => '-',
+'noimage'       => "Файла с таким именем не существует. вы можете $1.",
+'noimage-linktext'       => 'загрузить его',
+'uploadnewversion' => "[$1 Загрузить новую версию этого изображения]",
+
+# Statistics
+#
+'statistics'    => 'Статистика',
+'sitestats'             => 'Статистика сайта',
+'userstats'             => 'Статистика участников',
+'sitestatstext' => "Суммарно в базе данных содержится <strong>$1</strong> страниц.
+Это число включает в себя страницы о проекте, страницы обсуждений, незаконченные статьи, перенаправления и другие страницы, которые, не учитываются при учёте количества статей.
+За исключением них, есть <strong>$2</strong> страниц, которые считаются полноценными статьями. Для того, чтобы страница считалась полноценной статьёй, она должна находиться в основном пространстве имён и содержать хотя бы одну внутреннюю ссылку.
+
+Всего с момента установки программного обеспечения было сделано <strong>$4</strong> изменений страниц.
+Таким образом, в среднем приходится <strong>$5</strong> изменений на одну страницу.",
+'userstatstext' => "Зарегистрировались '''$1''' участников, из которых '''$2''' ($4%) являются администраторами (см. $3).",
+
+# Maintenance Page
+#
+'maintenance'           => 'Страница обслуживания',
+'maintnancepagetext'    => 'На этой странице есть несколько удобных инструментов для ежедневного обслуживания. Некоторые из этих функций дают сильную нагрузку на базу данных, поэтому, не перезагружайте страницу после каждого сделанного вами изменения ;-',
+'maintenancebacklink'   => 'Назад, на страницу обслуживания',
+'disambiguations'       => 'Многозначные страницы',
+'disambiguationspage'   => "{{ns:template}}:disambig",
+'disambiguationstext'   => "Следующие статьи ссылаются на <em>многозначные страницы</em>. Вместо этого они, вероятно, должны указывать на соответствующую конкретную статью.<br />Страница считается многозначной, если на ней размещён $1.<br />Ссылки из других пространств имён здесь <em>не</em> приведены.",
+'doubleredirects'       => 'Двойные перенаправления',
+'doubleredirectstext'   => "Каждая строка содержит ссылки на первое и второе перенаправления, а также первую строчку страницы второго перенаправления, в которой обычно указывается название страницы куда должно осуществляться перенаправление. Нужно чтобы и первое перенаправление ссылалось на эту страницу.",
+'brokenredirects'       => 'Разорванные перенаправления',
+'brokenredirectstext'   => 'Следующие перенаправления указывают на несуществующие статьи.',
+'selflinks'             => 'Страницы, ссылающиеся сами на себя',
+'selflinkstext'             => 'Следующие страницы содержат ссылки на себя же, чего не должно быть.',
+'mispeelings'           => 'Страницы с орфографическими ошибками',
+'mispeelingstext'               => "Следующие страницы содержат часто встречающиеся орфографические ошибки, перечисленные на странице $1. Должно быть указано правильное написание (наподобие следующего).",
+'mispeelingspage'       => 'Список часто встречающихся орфографических ошибок',
+'missinglanguagelinks'  => 'Отсутствующие языковые ссылки',
+'missinglanguagelinksbutton'    => 'Найти отсутствующие языковые ссылки для следующего языка',
+'missinglanguagelinkstext'      => "Эти статьи <em>не</em> имеют ссылок на аналог на языке $1. Перенаправления и сложенные страницы <em>не</em> показаны.",
+
+
+# Miscellaneous special pages
+#
+'orphans'               => 'Страницы-сироты',
+'geo'           => 'Географические координаты',
+'validate'              => 'Проверить страницу',
+'lonelypages'   => 'Страницы-сироты',
+'uncategorizedpages'    => 'Некатегоризованные страницы',
+'uncategorizedcategories'       => 'Некатегоризованные категории',
+'unusedcategories' => 'Неиспользуемые категории',
+'unusedimages'  => 'Неиспользуемые файлы',
+'popularpages'  => 'Популярные страницы',
+'nviews'                => '$1 просмотров',
+'wantedpages'   => 'Требуемые страницы',
+'nlinks'                => '$1 ссылок(ки)',
+'allpages'              => 'Все страницы',
+'randompage'    => 'Случайная статья',
+'randompage-url'=> 'Special:Random',
+'shortpages'    => 'Короткие статьи',
+'longpages'             => 'Длинные страницы',
+'deadendpages'  => 'Тупиковые статьи',
+'listusers'             => 'Список участников',
+'specialpages'  => 'Спецстраницы',
+'spheading'             => 'Служебные страницы',
+'restrictedpheading'    => 'Служебные страницы с ограниченным доступом',
+'protectpage'   => 'Защищённая страница',
+'recentchangeslinked' => 'Связанные правки',
+'rclsub'                => "(на статьи, ссылки на которые есть на $1)",
+'debug'                 => 'Отладка',
+'newpages'              => 'Новые статьи',
+'ancientpages'          => 'Самые старые статьи',
+'intl'          => 'Межъязыковые ссылки',
+'move' => 'Переименовать',
+'movethispage'  => 'Переименовать эту страницу',
+'unusedimagestext' => 'Пожалуйста, учтите, что другие веб-сайты могут использовать прямую ссылку (URL) на это изображение, и поэтому изображение может активно использоваться несмотря на его вхождение в этот список.',
+'unusedcategoriestext' => 'Существуют следующие страницы категорий, не содержащие статей или других категорий.',
+'booksources'   => 'Источники книг',
+'categoriespagetext' => 'В вики имеются следующие категории.',
+'data'  => 'Данные',
+'userrights' => 'Управление правами участников',
+'groups' => 'Группы участников',
+
+# FIXME: Other sites, of course, may have affiliate relations with the booksellers list
+'booksourcetext' => "Ниже приведён список ссылок на другие веб-сайты, на которых продаются новые и бывшие в употреблении книги, а также на них может быть информация о книгах, которые вы ищете.",
+'isbn'  => 'ISBN',
+'rfcurl' =>  'http://www.ietf.org/rfc/rfc$1.txt',
+'pubmedurl' =>  'http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?cmd=Retrieve&db=pubmed&dopt=Abstract&list_uids=$1',
+'alphaindexline' => "от $1 до $2",
+'version'               => 'Версия MediaWiki',
+'log'           => 'Журналы',
+'alllogstext'   => 'Комбинированный показ журналов загрузки, удаления, защиты, блокировки и администрирования.
+Вы можете отфильтровать результаты по типу журнала, имени пользователя или затронутой странице.',
+
+# Special:Allpages
+'nextpage'          => 'Следующая страница ($1)',
+'allpagesfrom'          => 'Вывести страницы, начинающиеся на:',
+'allarticles'       => 'Все статьи',
+'allnonarticles'        => 'Все не-статьи',
+'allinnamespace'        => 'Все страницы (пространства имён «$1»)',
+'allnotinnamespace'     => 'Все страницы (кроме пространства имён «$1»)',
+'allpagesprev'      => 'Предыдущие',
+'allpagesnext'      => 'Следующие',
+'allinnamespace' => 'Все страницы ($1 пространство имён)',
+'allpagessubmit'    => 'Выполнить',
+
+# Email this user
+#
+'mailnologin'   => 'Адрес для отправки отсутствует',
+'mailnologintext' => "Вы должны [[Special:Userlogin|представиться системе]]
+и иметь действительный адрес электронной почты в ваших [[Special:Preferences|настройках]],
+чтобы иметь возможность отправлять электронную почту другим участникам.",
+'emailuser'             => 'Письмо участнику',
+'emailpage'             => 'Отправить электронное письмо участнику',
+'emailpagetext' => 'Если этот участник указал действительный адрес электронной почты в своих настройках, то заполнив форму ниже, можно отправить ему сообщение.
+Электронный адрес, который вы указали в своих настройках, будет указан в поле «От кого» письма, поэтому получатель будет иметь возможность ответить.',
+'usermailererror' => 'При посылке e-mail произошла ошибка: ',
+'defemailsubject'  => "{{SITENAME}} e-mail",
+'noemailtitle'  => 'Адрес электронной почты отсутствует',
+'noemailtext'   => 'Этот участник не указал действительный адрес электронной почты, или указал, что не желает получать письма от других участников.',
+'emailfrom'             => 'От кого',
+'emailto'               => 'Кому',
+'emailsubject'  => 'Тема письма',
+'emailmessage'  => 'Сообщение',
+'emailsend'             => 'Отправить',
+'emailsent'             => 'Письмо отправлено',
+'emailsenttext' => 'Ваше электронное сообщение отослано.',
+
+# Watchlist
+#
+'watchlist'                     => 'Ваш список наблюдения',
+'watchlistsub'          => "(для участника $1)",
+'nowatchlist'           => 'Ваш список наблюдения пуст.',
+'watchnologin'          => 'Нужно представиться системе',
+'watchnologintext'      => "Вы должны [[Special:Userlogin|представиться системе]], чтобы иметь возможность изменять свой список наблюдения",
+'addedwatch'            => 'Добавлена в список слежения',
+'addedwatchtext'        => "Статья '''$1''' была добавлена в ваш [[{{ns:special}}:Watchlist|список наблюдения]]. Последующие изменения этой статьи и связанной с ней страницы обсуждения будут отражаться в нём, а также будут отображаться '''жирным шрифтом''' на странице со [[{{ns:special}}:Recentchanges|списком свежих изменений]], чтобы их было легче заметить.
+
+Если позже вы захотите удалить страницу из списка наблюдения, нажмите кнопку «Не следить» в верхней правой части страницы.",
+'removedwatch'          => 'Удалена из списка наблюдения',
+'removedwatchtext'      => "Страница «$1» была удалена из вашего списка наблюдения.",
+'watch' => 'Следить',
+'watchthispage'         => 'Наблюдать за этой страницей',
+'unwatch' => 'Не следить',
+'unwatchthispage'       => 'Прекратить наблюдение',
+'notanarticle'          => 'Не статья',
+'watchnochange'         => 'Ничто из списка наблюдения не изменялось в рассматриваемый период.',
+'watchdetails'          => "В вашем списке наблюдения находится $1 страниц (не считая страниц обсуждения)
+* [[Special:Watchlist/edit|Показать и отредактировать полный список]]
+",
+'wlheader-enotif'       => "* Уведомление по эл. почте включено.",
+'wlheader-showupdated'  => "* Страницы, изменившиеся с вашего последнего их посещения, выделены '''жирным''' шрифтом.",
+'watchmethod-recent'=> 'просмотр последних изменений для наблюдаемых страниц',
+'watchmethod-list'      => 'просмотр наблюдаемых страниц для последних изменений',
+'removechecked'         => 'Удалить выбранные элементы из списка наблюдения',
+'watchlistcontains' => "Ваш список наблюдения содержит $1 страниц.",
+'watcheditlist'         => 'Ниже представлен алфавитный список наблюдаемых
+вами страниц. Отметьте страниц, которые вы хотите удалить из вашего
+списка наблюдения и щёлкните на кнопку «удалить выбранные»
+внизу экрана.',
+'removingchecked'       => 'Удаление выбранных элементов из списка наблюдения…',
+'couldntremove'         => "Невозможно удалить элемент «$1»…",
+'iteminvalidname'       => "Проблема с элементом «$1»', недопустимое название…",
+'wlnote'                        => "Ниже следуют последние $1 изменений за последние <strong>$2</strong> часов.",
+'wlshowlast'            => "Показать за последние $1 часов $2 дней $3",
+'wlsaved'               => 'Это сохранённая версия вашего списка наблюдения',
+'wlhideshowown'         => '$1 ваши правки.',
+'wlshow'                => 'Показать',
+'wlhide'                => 'Скрыть',
+
+'enotif_mailer'             => '{{SITENAME}} Служба извещений по почте',
+'enotif_reset'              => 'Отметить все страницы как просмотренные',
+'enotif_newpagetext'        => 'Это новая страница.',
+'changed'                       => 'изменена',
+'created'                       => 'создана',
+'enotif_subject'    => 'Страница проекта «{{SITENAME}}» $PAGETITLE была $CHANGEDORCREATED участником $PAGEEDITOR',
+'enotif_lastvisited' => 'См. $1 для просмотра всех изменений произошедших с вашего последнего посещения.',
+'enotif_body' => '$WATCHINGUSERNAME,
+
+$PAGEEDITDATE страница проекта «{{SITENAME}}» $PAGETITLE была $CHANGEDORCREATED пользователем $PAGEEDITOR, см. $PAGETITLE_URL для просмотра текущей версии.
+
+$NEWPAGE
+
+Краткое описание изменения: $PAGESUMMARY $PAGEMINOREDIT
+
+Обратиться к изменившему:
+эл. почта $PAGEEDITOR_EMAIL
+вики $PAGEEDITOR_WIKI
+
+Не будет никаких других уведомлений в случае дальнейших изменений, если Вы не посещаете эту страницу. Вы могли также повторно установить флаги уведомления для всех ваших наблюдаемых страниц в вашем списке наблюдения.
+
+             Система оповещения {{grammar:genitive|{{SITENAME}}}}
+
+--
+Чтобы изменить настройки вашего списка наблюдения обратитель к
+{{SERVER}}{{localurl:Special:Watchlist/edit}}
+
+Обратная связь и помощь:
+{{SERVER}}{{localurl:Help:Contents}}',
+
+# Delete/protect/revert
+#
+'deletepage'    => 'Удалить страницу',
+'confirm'               => 'Подтверждение',
+'excontent' => "содержимое: '$1'",
+'excontentauthor' => "содержимое: «$1» (единственным автором был «$2»)",
+'exbeforeblank' => "содержимое до очистки: '$1'",
+'exblank' => 'страница была пуста',
+'confirmdelete' => 'Подтвердить удаление',
+'deletesub'             => "(«$1» удаляется)",
+'historywarning' => 'Предупреждение: У страницы, которую вы собираетесь удалить, есть журнал изменений: ',
+'confirmdeletetext' => "'''ВНИМАНИЕ!''' Сейчас вы '''навсегда''' удалите страницу (изображение) из базы данных. Также будет удалена и вся история изменений этой страницы.
+
+Пожалуйста, подтвердите:
+#Что вы ''действительно'' желаете это сделать;
+#Что вы ''полностью'' понимаете последствия своих действий;
+#Что вы делаете это ''в соответствии'' с правилами, изложенными в разделе [[{{ns:project}}:Правила]].",
+'actioncomplete' => 'Действие выполнено',
+'deletedtext'   => "«$1» была удалена.
+См. $2 для просмотра списка последних удалений.",
+'deletedarticle' => "удалена «[[$1]]»",
+'dellogpage'    => 'Список_удалений',
+'dellogpagetext' => 'Ниже приведён список самых свежих удалений.
+Везде используется время сервера (по Гринвичу, UTC).
+<ul>
+</ul>',
+'deletionlog'   => 'список удалений',
+'reverted'              => 'Откачено к ранней версии',
+'deletecomment' => 'Причина удаления',
+'imagereverted' => 'Откат к ранней версии осуществлён.',
+'rollback'              => 'Откатить изменения',
+'rollback_short' => 'Откат',
+'rollbacklink'  => 'откатить',
+'rollbackfailed' => 'Ошибка при совершении отката',
+'cantrollback'  => 'Невозможно откатить изменения; последний, кто вносил изменения, является единственным автором этой статьи.',
+'alreadyrolled' => "Невозможно откатить последние изменения [[$1]],
+сделанные [[{{ns:user}}:$2|$2]] ([[{{ns:user_talk}}:$2|Обсуждение]]); кто-то другой уже отредактировал или откатил эту страницу.
+
+Последние изменения внёс [[{{ns:user}}:$3|$3]] ([[{{ns:user_talk}}:$3|Обсуждение]]). ",
+#   only shown if there is an edit comment
+'editcomment' => "Изменение было пояснено так: <em>«$1»</em>.",
+'revertpage'    => "Откачено к последнему изменению, сделанному $1",
+'sessionfailure' => 'Похоже, возникли проблемы с текущим сеансом работы;
+это действие было отменено в целях предотвращения «захвата сеанса».
+Пожалуйста, нажмите кнопку «Назад» и перезагрузите страницу с которой вы пришли.',
+'protectlogpage' => 'Журнал_защиты',
+'protectlogtext' => "Ниже — список установок и снятий защиты со статей.
+См. дополнительную информацию на [[{{ns:project}}:Protected page]].",
+'protectedarticle' => "защищена страница «[[$1]]»",
+'unprotectedarticle' => "снята защита со страницы «[[$1]]»",
+'protectsub' =>"(Установка защиты для «$1»)",
+'confirmprotecttext' => 'Вы действительно хотите установить защиту этой страницы?',
+'confirmprotect' => 'Подтвердите установку защиты страницы',
+'protectmoveonly' => 'Защитить только от переименования',
+'protectcomment' => 'Причина установки защиты',
+'unprotectsub' =>"(Снятие защиты «$1»)",
+'confirmunprotecttext' => 'Вы действительно хотите снять защиту этой страницы?',
+'confirmunprotect' => 'Подтвердите снятие защиты страницы',
+'unprotectcomment' => 'Причина снятия защиты',
+
+# Undelete
+'undelete' => 'Просмотреть стёртые страницы',
+'undeletepage' => 'Просмотреть и восстановить стёртые страницы',
+'viewdeletedpage' => 'Просмотреть стёртые страницы',
+'undeletepagetext' => 'Следующие страницы были стёрты, но всё ещё находятся в архиве и поэтому могут быть восстановлены. Архив периодически очищается.',
+'undeletearticle' => 'Восстановить стёртую статью',
+'undeleterevisions' => "В архиве $1 версий",
+'undeletehistory' => 'Если вы восстановите страницу, все версии будут также восстановлены, вместе с журналом изменений.
+Если с момента удаления была создана новая страница с таким же названием, восстановленные версии будут указаны в журнале изменений перед новыми записями, и текущая версия существующей страницы автоматически заменена не будет.',
+'undeleterevision' => "Стёртая версия от $1",
+'undeletebtn' => 'Восстановить!',
+'undeletedarticle' => "«[[$1]]» восстановлена",
+'undeletedrevisions' => "$1 изменений восстановлено",
+'undeletedtext'   => "Статья [[$1]] была восстановлена.
+См. [[{{ns:project}}:Список_удалений]] для просмотра списка свежих удалений и восстановлений.",
+
+# Namespace form on various pages
+'namespace' => 'Пространство имён:',
+'invert' => 'Обратить выделенное',
+
+# Contributions
+#
+'contributions' => 'Вклад участника',
+'mycontris'     => 'Ваш вклад',
+'contribsub'    => "Для $1",
+'nocontribs'    => 'Изменений, соответствующих заданным условиям, задано не было.',
+'ucnote'        => "Ниже приводятся последние <strong>$1</strong> изменений, сделанных этим участником за последние <strong>$2</strong> дня(ей).",
+'uclinks'       => "Просмотреть $1 последних изменений; просмотреть за последние $2 дня(ей).",
+'uctop'         => ' (наверху)' ,
+'newbies'       => 'новички',
+'contribs-showhideminor' => '$1 малознач. правок',
+
+# What links here
+#
+'whatlinkshere' => 'Ссылки сюда',
+'notargettitle' => 'Не указана цель',
+'notargettext'  => 'Вы не указали целевую страницу или участника для этого действия.',
+'linklistsub'   => '(Список ссылок)',
+'linkshere'             => 'Следующие страницы ссылаются сюда:',
+'nolinkshere'   => 'Ни одна страница сюда не ссылается.',
+'isredirect'    => 'страница-перенаправление',
+
+# Block/unblock IP
+#
+'blockip'               => 'Заблокировать IP-адрес',
+'blockiptext'   => "Используйте форму ниже, чтобы заблокировать возможность записи с определённого IP-адреса.
+Это может быть сделано только для предотвращения вандализма и только в соответствии с
+правилами изложенными в разделе [[{{ns:project}}:Правила]].
+Ниже укажите конкретную причину (к примеру, процитируйте некоторые страницы с признаками вандализма).",
+'ipaddress'             => 'IP-адрес',
+'ipadressorusername' => 'IP-адрес или имя участника',
+'ipbexpiry'             => 'Закончится через',
+'ipbreason'             => 'Причина',
+'ipbsubmit'             => 'Заблокировать этот адрес/участника',
+'ipbother'              => 'Другое время',
+'ipboptions'            => '2 hours:2 hours,1 day:1 day,3 days:3 days,1 week:1 week,2 weeks:2 weeks,1 month:1 month,3 months:3 months,6 months:6 months,1 year:1 year,infinite:infinite',
+'ipbotheroption'        => 'иное',
+'badipaddress'  => 'IP-адрес записан в неправильном формате или участника с таким именем не существует.',
+'blockipsuccesssub' => 'Блокировка произведена',
+'blockipsuccesstext' => "[[{{ns:Special}}:Contributions/$1|«$1»]] заблокирован.
+<br />См. [[{{ns:special}}:Ipblocklist|cписок заблокированных IP-адресов]].",
+'unblockip'             => 'Разблокировать IP-адрес',
+'unblockiptext' => 'Используйте форму ниже, чтобы восстановить возможность записи с ранее заблокированного
+IP-адреса.',
+'ipusubmit'             => 'Разблокировать этот адрес',
+'ipusuccess'    => "IP-адрес «[[$1]]» разблокирован",
+'ipblocklist'   => 'Список заблокированных IP-адресов и пользователей',
+'blocklistline' => "$1, $2 заблокировал $3 ($4)",
+'infiniteblock' => 'бессрочная блокировка',
+'expiringblock' => 'блокировка завершится $1',
+'ipblocklistempty'      => 'Список блокировок пуст.',
+'blocklink'     => 'заблокировать',
+'unblocklink'   => 'разблокировать',
+'contribslink'  => 'вклад',
+'autoblocker'   => "Вы автоматически заблокированны, потому что у вас такой же IP-адрес, как у [[user:$1|«$1»]]. Причина блокировки участника «$1»: $2.",
+'blocklogpage'  => 'Журнал_блокировок',
+'blocklogentry' => '«[[$1]]» заблокирован на период $2',
+'blocklogtext'  => 'Это — журнал действий по блокированию и разблокированию участников. Автоматически блокируемые IP-адреса здесь не указываются. См. [[{{ns:special}}:Ipblocklist|Cписок активных запретов и блокировок]].',
+'unblocklogentry'       => '«$1» разблокирован',
+'range_block_disabled'  => 'Способность администратора создавать диапазон блокирования запрещена.',
+'ipb_expiry_invalid'    => 'Недопустимый период действия.',
+'ip_range_invalid'      => "Недопустимый диапазон IP-адресов.\n",
+'proxyblocker'  => 'Блокировка прокси',
+'proxyblockreason'      => 'Ваш IP-адрес заблокирован потому что это открытый прокси. Пожалуйста, свяжитесь с вашим интернет-провайдером  или службой поддержки и сообщите им об этой серьёзной проблеме безопасности.',
+'proxyblocksuccess'     => "Выполнено.\n",
+'sorbs'         => 'SORBS DNSBL',
+'sorbsreason'   => 'Ваш IP-адрес числится как открытый прокси в [http://www.sorbs.net SORBS] DNSBL.',
+'sorbs_create_account_reason' => 'Ваш IP-адрес числится как открытый прокси в [http://www.sorbs.net SORBS] DNSBL. Вы не можете создать учётную запись.',
+
+# Developer tools
+#
+'lockdb'      => 'Сделать базу данных доступной только для чтения',
+'unlockdb'    => 'Восстановить возможность записи в базу данных',
+'lockdbtext'  => 'Блокировка базы данных приостановит для всех участников возможность
+редактировать страницы, изменять настройки, изменять списки наблюдения и производить другие действия, требующие доступа к базе данных.
+
+Пожалуйста, подтвердите, что вы намерены это сделать, и что вы снимете блокировку как только закончите процедуру обслуживания базы данных.',
+'unlockdbtext'        => 'Разблокирование базы данных восстановит для всех участников
+возможность редактировать страницы, изменять настройки, изменять списки наблюдения и производить
+другие действия, требующие доступа к базе данных.
+Пожалуйста, подтвердите, что вы намерены это сделать.',
+'lockconfirm' => 'Да, я действительно хочу заблокировать базу данных на запись.',
+'unlockconfirm'       => 'Да, я действительно хочу снять блокировку базы данных.',
+'lockbtn'     => 'Сделать базу данных доступной только для чтения',
+'unlockbtn'   => 'Восстановить возможность записи в базу данных',
+'locknoconfirm'       => 'Вы не поставили галочку в поле подтверждения.',
+'lockdbsuccesssub'    => 'База данных заблокирована',
+'unlockdbsuccesssub'  => 'База данных разблокирована',
+'lockdbsuccesstext'   => 'База данных проекта была заблокированна.
+<br />Не забудьте убрать блокировку после завершения процедуры обслуживания.',
+'unlockdbsuccesstext' => 'База данных проекта была разблокирована.',
+
+# Make sysop
+'makesysoptitle'        => 'Сделать пользователя администратором',
+'makesysoptext'         => 'Этот формуляр используется бюрократами, чтобы делать обычных участников администраторами.
+Наберите имя участника и нажмите кнопку, чтобы сделать участника администратором',
+'makesysopname'         => 'Имя участника:',
+'makesysopsubmit'       => 'Сделать этого участника администратором',
+'makesysopok'           => "<strong>Участник $1 — теперь администратор</strong>",
+'makesysopfail'         => "<strong>Участника $1 невозможно сделать администратором. (Вы уверены, что правильно ввели его имя?)</strong>",
+'setbureaucratflag' => 'Установить флаг «Бюрократ»',
+'setstewardflag'    => 'Установить флаг «Стюард»',
+'bureaucratlog'         => 'Журнал_бюрократа',
+'rightslogtext'         => 'Это журнал изменений прав пользователя.',
+'bureaucratlogentry'    => "Для участника $1 изменены права доступа:",
+'rights'                        => 'Права:',
+'set_user_rights'       => 'Установить права пользователя',
+'user_rights_set'       => "<strong>Права пользователя $1 обновлены</strong></strong>",
+'set_rights_fail'       => "<strong>Невозможно установить права для пользователя $1. (Проверьте, правильно ли введено его имя)</strong>",
+'makesysop'         => 'Присвоить участнику статус администратора',
+'already_sysop'     => 'Этот участник уже является администратором',
+'already_bureaucrat' => 'Этот участник уже является бюрократом',
+'already_steward' => 'Этот участник уже является стюардом',
+
+# Validation
+'val_yes' => 'Да',
+'val_no' => 'Нет',
+'val_of' => '$1 из $2',
+'val_revision' => 'Версия',
+'val_time' => 'Время',
+'val_user_stats_title' => 'Краткий обзор оценок участника $1',
+'val_my_stats_title' => 'Краткий обзор моих оценок',
+'val_list_header' => '<th>#</th><th>Тема</th><th>Диапазон</th><th>Действие</th>',
+'val_add' => 'Добавить',
+'val_del' => 'Удалить',
+'val_show_my_ratings' => 'Показать мои оценки',
+'val_revision_number' => 'Версия №$1',
+'val_warning' => '<strong>Никогда не изменяйте что-либо здесь без <em>явного</em> согласия сообщества!</strong>',
+'val_rev_for' => 'Версии для $1',
+'val_details_th_user' => 'Участник $1',
+'val_validation_of' => 'Проверка «$1»',
+'val_revision_of' => 'Версия $1',
+'val_revision_changes_ok' => 'Ваши оценки сохранены!',
+'val_rev_stats' => 'См. статистику проверок для «$1» <a href="$2">здесь</a>',
+'val_revision_stats_link' => 'подробнее',
+'val_iamsure' => 'Подтвердите, что вы действительно хотите сделать это!',
+'val_clear_old' => 'Очистить мои другие проверки данных',
+'val_details_th' => '<sub>Участник</sub> \\ <sup>Тема</sup>',
+'val_merge_old' => 'Использовать мою предыдущую оценку там где выбрано «Нет мнения»',
+'val_form_note' => "'''Посказка:''' Слияние ваших данных означает что для версии
+статьи, которую вы выбрали, все опции где вы выбрали пункт ''нет мнения''
+будут заполнены значениями и комментариями самой последней версии для которой вы
+выразили мнение. Например, если вы хотите изменить мнение по какой-то опции
+для новой версии, но при этом сохранить ваши другие установки для этой статьи в этой версии,
+просто выберите какую опцию вы хотели бы ''изменить'', и
+слияние заполнит другие опции вашими предыдущими установками.",
+'val_noop' => 'Нет мнения',
+'val_topic_desc_page' => '{{ns:project}}:Оценки',
+'val_votepage_intro' => 'Измените этот текст <a href="{{SERVER}}{{localurl:MediaWiki:Val_votepage_intro|edit=yes}}">здесь</a>!',
+'val_percent' => '<strong>$1%</strong><br />($2 из $3 баллов<br />$4 участников)',
+'val_percent_single' => '<strong>$1%</strong><br />($2 из $3 баллов<br />для одного участника)',
+'val_total' => 'Всего',
+'val_version' => 'Версия',
+'val_tab' => 'Проверить',
+'val_this_is_current_version' => 'это последняя версия',
+'val_version_of' => "Версия $1" ,
+'val_table_header' => "<tr><th>Класс</th>$1<th colspan=4>Мнение</th>$1<th>Комментарий</th></tr>\n",
+'val_stat_link_text' => 'Статистика проверок для этой статьи',
+'val_view_version' => 'Посмотреть эту версию',
+'val_validate_version' => 'Проверить эту версию',
+'val_user_validations' => 'Этот участник проверил $1 страниц.',
+'val_no_anon_validation' => 'Нужно представиться системе для проверки статей.',
+'val_validate_article_namespace_only' => 'Можно проверять только статьи. Эта страница <em>не</em> относится к статьям.',
+'val_validated' => 'Проверка окончена.',
+'val_article_lists' => 'Список проверенных статей',
+'val_page_validation_statistics' => 'Статистика проверки страниц для $1',
+
+# Move page
+#
+'movepage'              => 'Переименовать страницу',
+'movepagetext'  => 'Воспользовавшись формой ниже, вы переименуете страницу, одновременно переместив на новое место её журнал изменений.
+Старое название станет перенаправлением на новое название.
+Ссылки на старое название не будут изменены (пожалуйста проверьте наличие [[Special:DoubleRedirects|двойных]] и [[Special:BrokenRedirects|разорванных]] перенаправлений).
+Вы обязаны убедиться в том, что ссылки и далее указывают туда, куда предполагалось.
+
+Обратите внимание, что страница \'\'\'не будет\'\'\' переименована, если страница с новым названием уже существует (кроме случаев, если она является перенаправлением или пуста и и не имеет истории правок). Это означает, что вы можете переименовать страницу обратно в то название, которое у него только что было, если вы переименовали по ошибке, но вы не можете случайно затереть существующую страницу.
+
+\'\'\'ПРЕДУПРЕЖДЕНИЕ!\'\'\'
+Переименование может привести к масштабным и неожиданным изменениям для \'\'популярных\'\' страниц. Пожалуйста, прежде, чем вы продолжите, убедитесь, что вы понимаете все возможные последствия.',
+'movepagetalktext' => 'Присоединённая страница обсуждения, если таковая есть,
+будет также автоматически переименована, \'\'\'кроме случаев, когда:\'\'\'
+*Вы перемещаете страницу из одного пространства имён в другое,
+*Не пустая страница обсуждения уже существует под таким же именем или
+*Вы не поставили галочку в поле ниже.
+
+В этих случаях, вы будете вынуждены переместить или объединить страницы вручную,
+если это нужно.',
+'movearticle'   => 'Переименовать страницу',
+'movenologin'   => 'Вы не представились системе',
+'movenologintext' => "Вы должны [[Special:Userlogin|представиться системе]],
+чтобы иметь возможность переименовать страницы.",
+'newtitle'              => 'Новое название',
+'movepagebtn'   => 'Переименовать страницу',
+'pagemovedsub'  => 'Страница переименована',
+'pagemovedtext' => "Страница [[$1|«$1»]] переименована в [[$2|«$2»]].",
+'articleexists' => 'Страница с таким именем уже существует, или указанное вами название недопустимо.
+Пожалуйста, выберите другое название.',
+'talkexists'    => "'''Страница была переименована, но страница обсуждения
+не может быть переименована, потому что страница с таким названием уже
+существует. Пожалуйста, объедините их вручную.'''",
+'movedto'               => 'переименована в',
+'movetalk'              => 'Переименовать также и страницу «обсуждения», если это возможно.',
+'talkpagemoved' => 'Соответствующая страница обсуждения также переименована.',
+'talkpagenotmoved' => 'Соответствующая страница обсуждения <strong>не</strong> была переименована.',
+'1movedto2'             => "«$1» переименована в «$2»",
+'1movedto2_redir' => '«$1» переименована в «$2», установлено перенаправление',
+'movelogpage' => 'Журнал переименований',
+'movelogpagetext' => 'Ниже представлен список переименованных страниц.',
+'movereason'    => 'Причина',
+'revertmove'    => 'откат',
+'delete_and_move' => 'Удалить и переименовать',
+'delete_and_move_text'  =>
+'==Требуется удаление==
+
+Страница с именем [[$1|«$1»]] уже существует. Хотите ли вы удалить её, чтобы сделать возможным переименование?',
+'delete_and_move_reason' => 'Удалено для возможности переименования',
+'selfmove' => "Невозможно переименовать страницу: исходное и новое имя страницы совпадают.",
+'immobile_namespace' => "Невозможно переименовать страницу: новое имя содержит зарезервированное служебное слово.",
+
+# Export
+
+'export'                => 'Экспортирование статей',
+'exporttext'    => 'Вы можете экспортировать текст и журнал изменений конкретной страницы или набора страниц в XML, который потом может быть импортирован в другую Вики, работающую на программном  обеспечении MediaWiki (к сожалению, функция импортирования не реализована в текущей версии ПО)
+
+Чтобы экспортировать статьи, ввведите их наименования в поле редактирования, одно название на строку, и выберите хотите ли вы экспортировать всю историю изменений статей или только последние версии статей.
+
+Вы также можете использовать специальный адрес для экспорта только последней версии статьи. Например для статьи [[Паровоз]] это будет адрес [[{{ns:special}}:Export/Паровоз]].
+',
+'exportcuronly' => 'Включать только текущую версию, без полной предыстории',
+
+# Namespace 8 related
+
+'allmessages'   => 'Системные сообщения',
+'allmessagesname' => 'Сообщение',
+'allmessagesdefault' => 'Текст по умолчанию',
+'allmessagescurrent' => 'Текущий текст',
+'allmessagestext'       => 'Ниже представлен список системных сообщений, доступных в пространстве имён «MediaWiki».',
+'allmessagesnotsupportedUI' => 'Текущий установленный язык <strong>$1</strong> не поддерживается Special:AllMessages на этом сайте.',
+'allmessagesnotsupportedDB' => 'Special:AllMessages не поддерживается так как wgUseDatabaseMessages отключён.',
+
+# Thumbnails
+
+'thumbnail-more'        => 'Увеличить',
+'missingimage'          => "<strong>Изображение не найдено</strong><br /><em>$1</em>\n",
+'filemissing'           => 'Файл не найден',
+
+# Special:Import
+'import'        => 'Импорт страниц',
+ 'importinterwiki' => 'Межвики импорт',
+'importtext'    => 'Пожалуйста, экспортируйте файл из искодной Вики используя страницу Special:Export, сохраните её на диск, а затем загрузите её оттуда.',
+'importfailed'  => "Не удалось импортировать: $1",
+'importnotext'  => 'Текст отсутствует',
+'importsuccess' => 'Импортировано выполнено!',
+'importhistoryconflict' => 'Конфликт существующих версий (возможно, эта страница уже была импортирована)',
+'importnosources' => 'Не был выбран источник межвики импорта, прямая загрузка истории изменений отключена.',
+
+# Keyboard access keys for power users
+'accesskey-search' => 'f',
+'accesskey-minoredit' => 'i',
+'accesskey-save' => 's',
+'accesskey-preview' => 'p',
+'accesskey-diff' => 'v',
+'accesskey-compareselectedversions' => 'v',
+
+# tooltip help for some actions, most are in Monobook.js
+'tooltip-search' => 'Искать [alt-f]',
+'tooltip-minoredit' => 'Отметить это изменение как незначительное [alt-i]',
+'tooltip-save' => 'Сохранить ваши изменения [alt-s]',
+'tooltip-preview' => 'Предварительный просмотр страницы, пожалуйста, используйте перед сохранением! [alt-p]',
+'tooltip-diff' => 'Показать изменения, сделанные по отношению к исходному тексту. [alt-d]',
+'tooltip-compareselectedversions' => 'Посмотреть разницу между двумя выбранными версиями этой страницы. [alt-v]',
+'tooltip-watch' => 'Добавить текущую страницу в список наблюдения [alt-w]',
+
+# stylesheets
+#'Monobook.css' => '/* edit this file to customize the monobook skin for the entire site */',
+#'Monobook.js' => '/* edit this file to change js things in the monobook skin */',
+
+# Metadata
+'nodublincore' => 'Метаданные Dublin Core RDF запрещены для этого сервера.',
+'nocreativecommons' => 'Метаданные Creative Commons RDF запрещены для этого сервера.',
+'notacceptable' => 'Вики-сервер не может предоставить данные в формате который мог бы прочитать ваш браузер.<br />
+The wiki server can\'t provide data in a format your client can read.',
+
+# Attribution
+
+'anonymous' => "Анонимные пользователи {{grammar:genitive|{{SITENAME}}}}",
+'siteuser' => "Участник {{grammar:genitive|{{SITENAME}}}} $1",
+'lastmodifiedby' => "Эта страница последний раз была изменена $1 участником $2.",
+'and' => 'и',
+'othercontribs' => "Основано на работе $1.",
+'others' => 'другие',
+'siteusers' => "Участник(и) {{grammar:genitive|{{SITENAME}}}} $1",
+'creditspage' => 'Благодарности',
+'nocredits' => 'Нет списка участников для этой статьи',
+
+# Spam protection
+
+'spamprotectiontitle' => 'Спам-фильтр',
+'spamprotectiontext' => 'Страница, которую вы пытаетесь сохранить заблокирована спам-фильтром. Вероятнее всего она содержит ссылку на внешний сайт.',
+'spamprotectionmatch' => 'Следующее сообщение было получено от спам-фильтра: $1',
+'subcategorycount' => "Имеется $1 подкатегорий в этой категории.",
+'subcategorycount1' => "Всего $1 подкатегория в этой категории.",
+'categoryarticlecount' => "Имеется $1 статьей в этой категории.",
+'categoryarticlecount1' => "Всего $1 статья в этой категории.",
+'usenewcategorypage' => "1\n\nУстановите первый символ в «0» чтобы заблокировать новое размещение страницы категории.",
+'listingcontinuesabbrev' => " <em><small>(продолжение)</small></em>",
+
+# Info page
+'infosubtitle' => 'Информация о странице',
+'numedits' => 'Число правок (статья): $1',
+'numtalkedits' => 'Число правок (страница обсуждения): $1',
+'numwatchers' => 'Число наблюдателей: $1',
+'numauthors' => 'Число различных авторов (статья): $1',
+'numtalkauthors' => 'Число различных авторов (страница обсуждения): $1',
+
+# Math options
+'mw_math_png' => 'Всегда генерировать PNG',
+'mw_math_simple' => 'HTML в простых случаях, иначе PNG',
+'mw_math_html' => 'HTML если возможно, иначе PNG',
+'mw_math_source' => 'Оставить в разметке ТеХ (для текстовых браузеров)',
+'mw_math_modern' => 'Как рекомендуется для современных браузеров',
+'mw_math_mathml' => 'MathML если возможно (экспериментальная опция)',
+
+# Patrolling
+'markaspatrolleddiff'   => "Пометить как проверенную",
+'markaspatrolledlink'   => "[$1]",
+'markaspatrolledtext'   => "Пометить эту статью как проверенную",
+'markedaspatrolled'     => "Помечена как проверенная",
+'markedaspatrolledtext' => "Выбранная версия помечена как проверенная.",
+'rcpatroldisabled'      => "Патрулирование последних изменений запрещено",
+'rcpatroldisabledtext'  => "Возможность патрулирования последних изменений в настоящее время отключена.",
+
+# Monobook.js: tooltips and access keys for monobook
+'Monobook.js' => '/* tooltips and access keys */
+ta = new Object();
+ta[\'pt-userpage\'] = new Array(\'.\',\'Моя страница пользователя\');
+ta[\'pt-anonuserpage\'] = new Array(\'.\',\'Страница пользователя для моего IP\');
+ta[\'pt-mytalk\'] = new Array(\'n\',\'Моя страница обсуждений\');
+ta[\'pt-anontalk\'] = new Array(\'n\',\'Страница обсуждений для моего IP\');
+ta[\'pt-preferences\'] = new Array(\'\',\'Мои настройки\');
+ta[\'pt-watchlist\'] = new Array(\'l\',\'Список страниц моего наблюдения\');
+ta[\'pt-mycontris\'] = new Array(\'y\',\'Список страниц, которые я редактировал\');
+ta[\'pt-login\'] = new Array(\'o\',\'Здесь можно зарегистрироваться в системе, но это необязательно\');
+ta[\'pt-anonlogin\'] = new Array(\'o\',\'Здесь можно зарегистрироваться в системе, но это необязательно\');
+ta[\'pt-logout\'] = new Array(\'o\',\'Отказаться от регистрации\');
+ta[\'ca-talk\'] = new Array(\'t\',\'Обсуждение статьи\');
+ta[\'ca-edit\'] = new Array(\'e\',\'Эту статью можно изменять. Перед сохранением изменений, пожалуйста, нажмите кнопку предварительного просмотра для визуальной проверки результата\');
+ta[\'ca-addsection\'] = new Array(\'+\',\'Добавить комментарий к обсуждению\');
+ta[\'ca-viewsource\'] = new Array(\'e\',\'Эта страница защищена от изменений, но вы можете посмотреть и скопировать её исходный текст\');
+ta[\'ca-history\'] = new Array(\'h\',\'Журнал изменений страницы\');
+ta[\'ca-protect\'] = new Array(\'=\',\'Защитить страницу от изменений\');
+ta[\'ca-delete\'] = new Array(\'d\',\'Удалить эту страницу\');
+ta[\'ca-undelete\'] = new Array(\'d\',\'Восстановить исправления страницы, сделанные до того, как она была удалена\');
+ta[\'ca-move\'] = new Array(\'m\',\'Переименовать страницу\');
+ta[\'ca-watch\'] = new Array(\'w\',\'Добавить эту страницу в ваш список наблюдения\');
+ta[\'ca-unwatch\'] = new Array(\'w\',\'Удалить эту страницу из вашего списка наблюдения\');
+ta[\'search\'] = new Array(\'f\',\'Искать это слово\');
+ta[\'p-logo\'] = new Array(\'\',\'Заглавная страница\');
+ta[\'n-mainpage\'] = new Array(\'z\',\'Перейти на заглавную страницу\');
+ta[\'n-portal\'] = new Array(\'\',\'О проекте, о том, что вы можете сделать, где что находится\');
+ta[\'n-currentevents\'] = new Array(\'\',\'Список текущих событий\');
+ta[\'n-recentchanges\'] = new Array(\'r\',\'Список последних изменений\');
+ta[\'n-randompage\'] = new Array(\'x\',\'Посмотреть случайную страницу\');
+ta[\'n-help\'] = new Array(\'\',\'Справочник по проекту «{{SITENAME}}»\');
+ta[\'n-sitesupport\'] = new Array(\'\',\'Поддержите проект\');
+ta[\'t-whatlinkshere\'] = new Array(\'j\',\'Список всех страниц, которые ссылаются на эту страницу\');
+ta[\'t-recentchangeslinked\'] = new Array(\'k\',\'Последние изменения в страницах, которые ссылаются на эту страницу\');
+ta[\'feed-rss\'] = new Array(\'\',\'Трансляция в формате RSS для этой страницы\');
+ta[\'feed-atom\'] = new Array(\'\',\'Трансляция в формате Atom для этой страницы\');
+ta[\'t-contributions\'] = new Array(\'\',\'Список страниц, которые изменял этот участник\');
+ta[\'t-emailuser\'] = new Array(\'\',\'Отправить письмо этому участнику\');
+ta[\'t-upload\'] = new Array(\'u\',\'Загрузить изображения или мультимедиа-файлы\');
+ta[\'t-specialpages\'] = new Array(\'q\',\'Список служебных страниц\');
+ta[\'ca-nstab-main\'] = new Array(\'c\',\'Содержание статьи\');
+ta[\'ca-nstab-user\'] = new Array(\'c\',\'Персональная страница участника\');
+ta[\'ca-nstab-media\'] = new Array(\'c\',\'Мультимедиа-файл\');
+ta[\'ca-nstab-special\'] = new Array(\'\',\'Это служебная страница, она недоступна для редактирования\');
+ta[\'ca-nstab-wp\'] = new Array(\'a\',\'Страница проекта\');
+ta[\'ca-nstab-image\'] = new Array(\'c\',\'Страница изображения\');
+ta[\'ca-nstab-mediawiki\'] = new Array(\'c\',\'Страница сообщения MediaWiki\');
+ta[\'ca-nstab-template\'] = new Array(\'c\',\'Страница шаблона\');
+ta[\'ca-nstab-help\'] = new Array(\'c\',\'Страница справки\');
+ta[\'ca-nstab-category\'] = new Array(\'c\',\'Страница категории\');
+',
+
+# image deletion
+'deletedrevision' => 'Удалена старая версия $1.',
+
+# browsing diffs
+'previousdiff' => '← К предыдущему изменению',
+'nextdiff' => 'К след. изменению →',
+
+'imagemaxsize' => 'Ограничивать изображения на странице изображений до: ',
+'thumbsize'    => 'Размер уменьшенной версии изображения: ',
+'showbigimage' => 'Загрузить с высоким разрешением ($1x$2, $3 Кбайт)',
+
+'newimages' => 'Галерея новых файлов',
+'noimages'  => 'Изображения отсутствуют.',
+
+# labels for User: and Title: on Special:Log pages
+'specialloguserlabel' => 'Участник: ',
+'speciallogtitlelabel' => 'Заголовок: ',
+
+'passwordtooshort' => 'Введённый пароль слишком короткий. Пароль должен состоять не менее чем из $1 символов.',
+
+# Media Warning
+'mediawarning' => '\'\'\'Внимание\'\'\': файл может содержать злонамеренный программный код, способный повредить вашей системе. <hr>',
+'fileinfo' => '$1 Кб, MIME-тип: <code>$2</code>',
+
+# Exif data
+'metadata' => 'Метаданные',
+
+# Exif tags
+'exif-imagewidth' =>'Ширина',
+'exif-imagelength' =>'Высота',
+'exif-bitspersample' =>'Глубина цвета',
+'exif-compression' =>'Метод сжатия',
+'exif-photometricinterpretation' =>'Цветовая модель',
+'exif-orientation' =>'Ориентация кадра',
+'exif-samplesperpixel' =>'Количество цветовых компонентов',
+'exif-planarconfiguration' =>'Принцип организации данных',
+'exif-ycbcrsubsampling' =>'Отношение размеров компонент Y и C',
+'exif-ycbcrpositioning' =>'Порядок размещения компонент Y и C',
+'exif-xresolution' =>'Горизонтальное разрешение',
+'exif-yresolution' =>'Вертикальное разрешение',
+'exif-resolutionunit' =>'Единица измерения разрешения',
+'exif-stripoffsets' =>'Положение блока данных',
+'exif-rowsperstrip' =>'Количество строк в 1 блоке',
+'exif-stripbytecounts' =>'Размер сжатого блока',
+'exif-jpeginterchangeformat' =>'Положение начала блока preview',
+'exif-jpeginterchangeformatlength' =>'Размер данных блока preview',
+'exif-transferfunction' =>'Функция преобразования цветового пространства',
+'exif-whitepoint' =>'Цветность белой точки',
+'exif-primarychromaticities' =>'Цветность основных цветов',
+'exif-ycbcrcoefficients' =>'Коэффициенты преобразования цветовой модели',
+'exif-referenceblackwhite' =>'Положение белой и чёрной точек',
+'exif-datetime' =>'Дата и время изменения файла',
+'exif-imagedescription' =>'Название изображения',
+'exif-make' =>'Производитель камеры',
+'exif-model' =>'Модель камеры',
+'exif-software' =>'Программное обеспечение',
+'exif-artist' =>'Автор',
+'exif-copyright' =>'Владелец авторского права',
+'exif-exifversion' =>'Версия Exif',
+'exif-flashpixversion' =>'Поддерживаемая версия FlashPix',
+'exif-colorspace' =>'Цветовое пространство',
+'exif-componentsconfiguration' =>'Конфигурация цветовых компонентов',
+'exif-compressedbitsperpixel' =>'Глубина цвета после сжатия',
+'exif-pixelydimension' =>'Полная высота изображения',
+'exif-pixelxdimension' =>'Полная ширина изображения',
+'exif-makernote' =>'Дополнительные данные производителя',
+'exif-usercomment' =>'Дополнительный комментарий',
+'exif-relatedsoundfile' =>'Файл звукового комментария',
+'exif-datetimeoriginal' =>'Оригинальные дата и время',
+'exif-datetimedigitized' =>'Дата и время оцифровки',
+'exif-subsectime' =>'Доли секунд времени изменения файла',
+'exif-subsectimeoriginal' =>'Доли секунд оригинального времени',
+'exif-subsectimedigitized' =>'Доли секунд времени оцифровки',
+'exif-exposuretime' =>'Время экспозиции',
+'exif-fnumber' =>'Число диафрагмы',
+'exif-exposureprogram' =>'Программа экспозиции',
+'exif-spectralsensitivity' =>'Спектральная чувствительность',
+'exif-isospeedratings' =>'Светочувствительность ISO',
+'exif-oecf' =>'OECF (коэффициент оптоэлектрического преобразования)',
+'exif-shutterspeedvalue' =>'Выдержка',
+'exif-aperturevalue' =>'Диафрагма',
+'exif-brightnessvalue' =>'Яркость',
+'exif-exposurebiasvalue' =>'Компенсация экспозиции',
+'exif-maxaperturevalue' =>'Минимальное число диафрагмы',
+'exif-subjectdistance' =>'Расстояние до объекта',
+'exif-meteringmode' =>'Режим замера экспозиции',
+'exif-lightsource' =>'Источник света',
+'exif-flash' =>'Статус вспышки',
+'exif-focallength' =>'Фокусное расстояние',
+'exif-subjectarea' =>'Положение и площадь объекта съёмки',
+'exif-flashenergy' =>'Энергия вспышки',
+'exif-spatialfrequencyresponse' =>'Пространственная частотная характеристика',
+'exif-focalplanexresolution' =>'Разрешение по X в фокальной плоскости',
+'exif-focalplaneyresolution' =>'Разрешение по Y в фокальной плоскости',
+'exif-focalplaneresolutionunit' =>'Единица измерения разрешения в фокальной плоскости',
+'exif-subjectlocation' =>'Положение объекта относительно левого верхнего угла',
+'exif-exposureindex' =>'Индекс экспозиции',
+'exif-sensingmethod' =>'Тип сенсора',
+'exif-filesource' =>'Источник файла',
+'exif-scenetype' =>'Тип сцены',
+'exif-cfapattern' =>'Тип цветового фильтра',
+'exif-customrendered' =>'Дополнительная обработка',
+'exif-exposuremode' =>'Режим выбора экспозиции',
+'exif-whitebalance' =>'Баланс белого',
+'exif-digitalzoomratio' =>'Коэффициент цифрового увеличения (цифровой зум)',
+'exif-focallengthin35mmfilm' =>'Эквивалентное фокусное расстояние (для 35 мм плёнки)',
+'exif-scenecapturetype' =>'Тип сцены при съёмке',
+'exif-gaincontrol' =>'Повышение яркости',
+'exif-contrast' =>'Контрастность',
+'exif-saturation' =>'Насыщенность',
+'exif-sharpness' =>'Резкость',
+'exif-devicesettingdescription' =>'Описание предустановок камеры',
+'exif-subjectdistancerange' =>'Расстояние до объекта съёмки',
+'exif-imageuniqueid' =>'Номер изображения (ID)',
+
+'exif-gpsversionid' =>'Версия блока GPS-информации',
+'exif-gpslatituderef' =>'Индекс широты',
+'exif-gpslatitude' =>'Широта',
+'exif-gpslongituderef' =>'Индекс долготы',
+'exif-gpslongitude' =>'Долгота',
+'exif-gpsaltituderef' =>'Индекс высоты',
+'exif-gpsaltitude' =>'Высота',
+'exif-gpstimestamp' =>'Точное время по UTC',
+'exif-gpssatellites' =>'Описание использованных спутников',
+'exif-gpsstatus' =>'Статус приёмника в момент съёмки',
+'exif-gpsmeasuremode' =>'Метод измерения положения',
+'exif-gpsdop' =>'Точность измерения',
+'exif-gpsspeedref' =>'Единицы измерения скорости',
+'exif-gpsspeed' =>'Скорость движения',
+'exif-gpstrackref' =>'Тип азимута приёмника GPS (истинный, магнитный)',
+'exif-gpstrack' =>'Азимут приёмника GPS',
+'exif-gpsimgdirectionref' =>'Тип азимута изображения (истинный, магнитный)',
+'exif-gpsimgdirection' =>'Азимут изображения',
+'exif-gpsmapdatum' =>'Использованная геодезическая система координат',
+'exif-gpsdestlatituderef' =>'Индекс долготы объекта',
+'exif-gpsdestlatitude' =>'Долгота объекта',
+'exif-gpsdestlongituderef' =>'Индекс широты объекта',
+'exif-gpsdestlongitude' =>'Широта объекта',
+'exif-gpsdestbearingref' =>'Тип пеленга объекта (истинный, магнитный)',
+'exif-gpsdestbearing' =>'Пеленг объекта',
+'exif-gpsdestdistanceref' =>'Единицы измерения расстояния',
+'exif-gpsdestdistance' =>'Расстояние',
+'exif-gpsprocessingmethod' =>'Метод вычисления положения',
+'exif-gpsareainformation' =>'Название области GPS',
+'exif-gpsdatestamp' =>'Дата',
+'exif-gpsdifferential' =>'Дифференциальная поправка',
+
+# Exif attributes
+
+'exif-compression-1' => 'Несжатый',
+'exif-compression-6' => 'JPEG',
+
+'exif-photometricinterpretation-1' => 'RGB',
+'exif-photometricinterpretation-6' => 'YCbCr',
+
+'exif-orientation-1' => 'Нормальная', // 0th row: top; 0th column: left
+'exif-orientation-2' => 'Отражено по горизонтали', // 0th row: top; 0th column: right
+'exif-orientation-3' => 'Повёрнуто на 180°', // 0th row: bottom; 0th column: right
+'exif-orientation-4' => 'Отражено по вертикали', // 0th row: bottom; 0th column: left
+'exif-orientation-5' => 'Повёрнуто на 90° против часовой стрелки и отражено по вертикали', // 0th row: left; 0th column: top
+'exif-orientation-6' => 'Повёрнуто на 90° по часовой стрелке', // 0th row: right; 0th column: top
+'exif-orientation-7' => 'Повёрнуто на 90° по часовой стрелке и отражено по вертикали', // 0th row: right; 0th column: bottom
+'exif-orientation-8' => 'Повёрнуто на 90° против часовой стрелки', // 0th row: left; 0th column: bottom
+
+'exif-planarconfiguration-1' => 'chunky format',
+'exif-planarconfiguration-2' => 'planar format',
+
+'exif-colorspace-1' => 'sRGB',
+'exif-colorspace-ffff.h' => 'FFFF.H',
+
+'exif-componentsconfiguration-0' => 'не существует',
+'exif-componentsconfiguration-1' => 'Y',
+'exif-componentsconfiguration-2' => 'Cb',
+'exif-componentsconfiguration-3' => 'Cr',
+'exif-componentsconfiguration-4' => 'R',
+'exif-componentsconfiguration-5' => 'G',
+'exif-componentsconfiguration-6' => 'B',
+
+'exif-exposureprogram-0' => 'Неизвестно',
+'exif-exposureprogram-1' => 'Ручной режим',
+'exif-exposureprogram-2' => 'Программный режим (нормальный)',
+'exif-exposureprogram-3' => 'Приоритет диафрагмы',
+'exif-exposureprogram-4' => 'Приоритет выдержки',
+'exif-exposureprogram-5' => 'Художественная программа (на основе нужной глубины резкости)',
+'exif-exposureprogram-6' => 'Спортивный режим (с минимальной выдержкой)',
+'exif-exposureprogram-7' => 'Портретный режим (для снимков на близком расстоянии, с фоном не в фокусе)',
+'exif-exposureprogram-8' => 'Пейзажный режим (для пейзажных снимков, с фоном в фокусе)',
+
+'exif-subjectdistance-value' => '$1 метров',
+
+'exif-meteringmode-0' => 'Неизвестно',
+'exif-meteringmode-1' => 'Средний',
+'exif-meteringmode-2' => 'Центровзвешенный',
+'exif-meteringmode-3' => 'Точечный',
+'exif-meteringmode-4' => 'Мультиточечный',
+'exif-meteringmode-5' => 'Матричный',
+'exif-meteringmode-6' => 'Частичный',
+'exif-meteringmode-255' => 'Другой',
+
+'exif-lightsource-0' => 'Неизвестно',
+'exif-lightsource-1' => 'Дневной свет',
+'exif-lightsource-2' => 'Лампа дневного света',
+'exif-lightsource-3' => 'Лампа накаливания',
+'exif-lightsource-4' => 'Вспышка',
+'exif-lightsource-9' => 'Хорошая погода',
+'exif-lightsource-10' => 'Облачно',
+'exif-lightsource-11' => 'Тень',
+'exif-lightsource-12' => 'Лампа дневного света тип D (5700 − 7100K)',
+'exif-lightsource-13' => 'Лампа дневного света тип N (4600 − 5400K)',
+'exif-lightsource-14' => 'Лампа дневного света тип W (3900 − 4500K)',
+'exif-lightsource-15' => 'Лампа дневного света тип WW (3200 − 3700K)',
+'exif-lightsource-17' => 'Стандартный источник света типа A',
+'exif-lightsource-18' => 'Стандартный источник света типа B',
+'exif-lightsource-19' => 'Стандартный источник света типа C',
+'exif-lightsource-20' => 'D55',
+'exif-lightsource-21' => 'D65',
+'exif-lightsource-22' => 'D75',
+'exif-lightsource-23' => 'D50',
+'exif-lightsource-24' => 'Студийная лампа стандарта ISO',
+'exif-lightsource-255' => 'Другой источник света',
+
+'exif-focalplaneresolutionunit-2' => 'дюймов',
+
+'exif-sensingmethod-1' => 'Неопределённый',
+'exif-sensingmethod-2' => 'Однокристальный матричный цветной сенсор',
+'exif-sensingmethod-3' => 'Цветной сенсор с двумя матрицами',
+'exif-sensingmethod-4' => 'Цветной сенсор с тремя матрицами',
+'exif-sensingmethod-5' => 'Матричный сенсор с последовательным измерением цвета',
+'exif-sensingmethod-7' => 'Трёхцветный линейный сенсор',
+'exif-sensingmethod-8' => 'Линейный сенсор с последовательным измерением цвета',
+
+'exif-filesource-3' => 'Цифровой фотоаппарат',
+
+'exif-scenetype-1' => 'Изображение сфотографировано напрямую',
+
+'exif-customrendered-0' => 'Не производилась',
+'exif-customrendered-1' => 'Нестандартная обработка',
+
+'exif-exposuremode-0' => 'Автоматическая экспозиция',
+'exif-exposuremode-1' => 'Ручная установка экспозиции',
+'exif-exposuremode-2' => 'Брэкетинг',
+
+'exif-whitebalance-0' => 'Автоматический баланс белого',
+'exif-whitebalance-1' => 'Ручная установка баланса белого',
+
+'exif-scenecapturetype-0' => 'Стандартный',
+'exif-scenecapturetype-1' => 'Ландшафт',
+'exif-scenecapturetype-2' => 'Портрет',
+'exif-scenecapturetype-3' => 'Ночная съёмка',
+
+'exif-gaincontrol-0' => 'Нет',
+'exif-gaincontrol-1' => 'Небольшое увеличение',
+'exif-gaincontrol-2' => 'Большое увеличение',
+'exif-gaincontrol-3' => 'Небольшое уменьшение',
+'exif-gaincontrol-4' => 'Сильное уменьшение',
+
+'exif-contrast-0' => 'Нормальная',
+'exif-contrast-1' => 'Мягкое повышение',
+'exif-contrast-2' => 'Сильное повышение',
+
+'exif-saturation-0' => 'Нормальная',
+'exif-saturation-1' => 'Небольшая насыщенность',
+'exif-saturation-2' => 'Большая насыщенность',
+
+'exif-sharpness-0' => 'Нормальная',
+'exif-sharpness-1' => 'Мягкое повышение',
+'exif-sharpness-2' => 'Сильное повышение',
+
+'exif-subjectdistancerange-0' => 'Неизвестно',
+'exif-subjectdistancerange-1' => 'Макросъёмка',
+'exif-subjectdistancerange-2' => 'Съёмка с близкого расстояния',
+'exif-subjectdistancerange-3' => 'Съёмка издалека',
+
+// Pseudotags used for GPSLatitudeRef and GPSDestLatitudeRef
+'exif-gpslatitude-n' => 'северной широты',
+'exif-gpslatitude-s' => 'южной широты',
+
+// Pseudotags used for GPSLongitudeRef and GPSDestLongitudeRef
+'exif-gpslongitude-e' => 'восточной долготы',
+'exif-gpslongitude-w' => 'западной долготы',
+
+'exif-gpsstatus-a' => 'Измерение не закончено',
+'exif-gpsstatus-v' => 'Готов к передаче данных',
+
+'exif-gpsmeasuremode-2' => 'Измерение 2-х координат',
+'exif-gpsmeasuremode-3' => 'Измерение 3-х координат',
+
+// Pseudotags used for GPSSpeedRef and GPSDestDistanceRef
+'exif-gpsspeed-k' => 'км/час',
+'exif-gpsspeed-m' => 'миль/час',
+'exif-gpsspeed-n' => 'узлов',
+
+// Pseudotags used for GPSTrackRef, GPSImgDirectionRef and GPSDestBearingRef
+'exif-gpsdirection-t' => 'истинный',
+'exif-gpsdirection-m' => 'магнитный',
+
+# external editor support
+'edit-externally' => 'Редактировать этот файл используя внешнюю программу',
+'edit-externally-help' => 'Подробности см. на странице [http://meta.wikimedia.org/wiki/Help:External_editors Meta:Help:External_editors].',
+
+# 'all' in various places, this might be different for inflicted languages
+'recentchangesall' => 'все',
+'imagelistall' => 'все',
+'watchlistall1' => 'все',
+'watchlistall2' => 'все',
+'namespacesall' => 'все',
+
+# E-mail address confirmation
+'confirmemail' => 'Подтверждение адреса электронной почты',
+'confirmemail_text' => "Вики-движок требует подтверждения адреса электронной почты перед тем, как начать с ним работать.
+Нажмите на кнопку, чтобы на указанный адрес было отправлено письмо, сореджащее ссылку на специальную страницу, после открытия которой в браузере адрес электронной почты будет считается подтверждённым.",
+
+'confirmemail_send' => 'Отправить письмо с запросом на подтверждение',
+'confirmemail_sent' => 'Письмо с запросом на подтверждение отправлено.',
+'confirmemail_sendfailed' => 'Невозможно отправить письмо с запросом на подтверждение. Проверье правильность адреса электронной почты.',
+'confirmemail_invalid' => 'Нeправильный код подтверждения или срок действия кода истёк.',
+'confirmemail_success' => 'Ваш адрес электронной почты подтверждён.',
+'confirmemail_loggedin' => 'Ваш адрес электронной почты подтверждён.',
+'confirmemail_error' => 'Во время процедуры подтверждения адреса электронной почты произошла ошибка.',
+
+'confirmemail_subject' => '{{SITENAME}}:Запрос на подтверждения адреса эл. почты',
+'confirmemail_body' => "Кто-то с IP-адресом $1, зарегистрировал на сервере проекта {{SITENAME}} учётную запись
+«$2» указав ваш адрес электронной почты.
+
+Чтобы подтвердить, что вы разрешаете использовать ваш адрес электронной почты  в этом проекте откройте в браузере приведённую ниже ссылку (это нужно сделать до $4):
+
+$3
+
+Если вы не отправляли подобного запроса - просто проигнорируйте данное письмо.",
+
+# Inputbox extension, may be useful in other contexts as well
+'tryexact' => 'Строгий поиск',
+'searchfulltext' => 'Полнотекстовый поиск',
+'createarticle' => 'Создать статью',
+
+# Scary transclusion
+'scarytranscludedisabled' => '[«Interwiki transcluding» отключён]',
+'scarytranscludefailed' => '[К сожалению, не удалось обращение к шаблону $1]',
+'scarytranscludetoolong' => '[К сожалению, URL слишком длинный]',
+
+# Trackbacks
+'trackbackbox' => "<div id='mw_trackbacks'>
+Trackback для этой статьи:<br />
+$1
+</div>
+",
+'trackback' => "; $4$5 : [$2 $1]\n",
+'trackbackexcerpt' => "; $4$5 : [$2 $1]: <nowiki>$3</nowiki>\n",
+'trackbackremove' => ' ([$1 удалить])',
+'trackbacklink' => 'Trackback',
+'trackbackdeleteok' => 'Trackback был удалён.',
+
+# delete conflict
+
+'deletedwhileediting' => 'Внимание: пока вы редактировали эту страницу она была удалена!',
+'confirmrecreate' => 'Участник [[User:$1|$1]] ([[User talk:$1|обсуждение]]) удалил эту статью после того, как вы начали её редактировать, причина удаления:
+: \'\'$2\'\'
+Пожалуйста подтвердите, что вы хотите создать статью заново.',
+'recreate' => 'Создать заново',
+'tooltip-recreate' => '',
+
+'unit-pixel' => 'пкс',
+);
+
+/* Please, see Language.php for general function comments */
+class LanguageRu extends LanguageUtf8 {
+       function LanguageRu() {
+               global $wgNamespaceNamesRu, $wgMetaNamespace;
+               LanguageUtf8::LanguageUtf8();
+               $wgNamespaceNamesRu[NS_PROJECT_TALK] = 'Обсуждение_' . $this->convertGrammar( $wgMetaNamespace, 'genitive' );
+       }
+
+       function getNamespaces() {
+               global $wgNamespaceNamesRu;
+               return $wgNamespaceNamesRu;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsRu;
+               return $wgQuickbarSettingsRu;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesRu;
+               return $wgSkinNamesRu;
+       }
+
+       function getDateFormats() {
+               global $wgDateFormatsRu;
+               return $wgDateFormatsRu;
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesRu;
+               return isset($wgAllMessagesRu[$key]) ? $wgAllMessagesRu[$key] : parent::getMessage($key);
+       }
+
+       function fallback8bitEncoding() {
+               return "windows-1251";
+       }
+
+       function getMagicWords()  {
+               global $wgMagicWordsRu;
+               return $wgMagicWordsRu;
+       }
+
+       # Convert from the nominative form of a noun to some other case
+       # Invoked with {{grammar:case|word}}
+       function convertGrammar( $word, $case ) {
+               # These rules are not perfect, but they are currently only used for site names so it doesn't
+               # matter if they are wrong sometimes. Just add a special case for your site name if necessary.
+
+               #join and array_slice instead mb_substr
+
+               preg_match_all( '/./us', $word, $ar );
+               if (!preg_match("/[a-zA-Z_]/us", $word))
+                       switch ( $case ) {
+                               case 'genitive': #родительный падеж
+                                       if ((join('',array_slice($ar[0],-4))=='вики') || (join('',array_slice($ar[0],-4))=='Вики'))
+                                               {}
+                                       elseif (join('',array_slice($ar[0],-1))=='ь')
+                                               $word = join('',array_slice($ar[0],0,-1)).'я';
+                                       elseif (join('',array_slice($ar[0],-2))=='ия')
+                                               $word=join('',array_slice($ar[0],0,-2)).'ии';
+                                       elseif (join('',array_slice($ar[0],-2))=='ти')
+                                               $word=join('',array_slice($ar[0],0,-2)).'тей';
+                                       elseif (join('',array_slice($ar[0],-2))=='ды')
+                                               $word=join('',array_slice($ar[0],0,-2)).'дов';
+                                       elseif (join('',array_slice($ar[0],-3))=='ник')
+                                               $word=join('',array_slice($ar[0],0,-3)).'ника';
+                                       break;
+                               case 'dative':  #дательный падеж
+                                       #stub
+                                       break;
+                               case 'accusative': #винительный падеж
+                                       #stub
+                                       break;
+                               case 'instrumental':  #творительный падеж
+                                       #stub
+                                       break;
+                               case 'prepositional': #предложный падеж
+                                       #stub
+                                       break;
+                       }
+               return $word;
+       }
+
+       function formatNum( $number ) {
+               global $wgTranslateNumerals;
+               return $wgTranslateNumerals ? strtr($number, '.,', ', ' ) : $number;
+       }
+
+}
+
+?>
diff --git a/languages/LanguageSc.php b/languages/LanguageSc.php
new file mode 100644 (file)
index 0000000..e4722f5
--- /dev/null
@@ -0,0 +1,728 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+require_once( "LanguageUtf8.php" );
+
+/* private */ $wgNamespaceNamesSc = array(
+       NS_SPECIAL         => "Speciale",
+       NS_MAIN            => "",
+       NS_TALK            => "Contièndha",
+       NS_USER            => "Utente",
+       NS_USER_TALK       => "Utente_discussioni",
+       NS_PROJECT         => "Wikipedia",
+       NS_PROJECT_TALK    => "Wikipedia_discussioni",
+       NS_IMAGE           => "Immàgini",
+       NS_IMAGE_TALK      => "Immàgini_contièndha"
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgQuickbarSettingsSc = array(
+       "Nessuno", "Fisso a sinistra", "Fisso a destra", "Fluttuante a sinistra"
+);
+
+
+/* private */ $wgAllMessagesSc = array(
+# User Toggles
+
+"tog-underline" => "Sottolinea links",
+"tog-highlightbroken" => "Evidenzia i links che puntano ad articoli ancora da scrivere",
+"tog-justify"  => "Paragrafo: giustificato",
+"tog-hideminor" => "Nascondi le modifiche minori nella pagina \"Modifiche recenti\"",
+"tog-numberheadings" => "Auto-numerazione dei titoli di paragrafo",
+"tog-rememberpassword" => "Ricorda la password (non limitare a una sessione - richiede uso di cookies)",
+"tog-editwidth" => "Casella di edizione ampliata alla massima larghezza",
+"tog-editondblclick" => "Doppio click per modificare l'articolo (richiede JavaScript)",
+"tog-watchdefault" => "Notifica articoli nuovi e modificati",
+"tog-minordefault" => "Indica ogni modifica come minore (solo come predefinito)",
+
+# Dates
+#
+
+'sunday' => "Domiga",
+'monday' => "Lúnis",
+'tuesday' => "Màrtis",
+'wednesday' => "Mércuris",
+'thursday' => "Zóbia",
+'friday' => "Canàbara",
+'saturday' => "Sàudu",
+'january' => "Ghenàlliu",
+'february' => "Fiàrzu",
+'march' => "Màrtu",
+'april' => "Abríli",
+'may_long' => "Màzu",
+'june' => "Làmparas",
+'july' => "Luglio",
+'august' => "Agosto",
+'september' => "Settembre",
+'october' => "Ottobre",
+'november' => "Novembre",
+'december' => "Dicembre",
+'jan' => "Gen",
+'feb' => "Feb",
+'mar' => "Mar",
+'apr' => "Apr",
+'may' => "Mag",
+'jun' => "Giu",
+'jul' => "Lug",
+'aug' => "Ago",
+'sep' => "Set",
+'oct' => "Ott",
+'nov' => "Nov",
+'dec' => "Dic",
+
+# Bits of text used by many pages:
+#
+"linktrail"            => "/^([a-z]+)(.*)\$/sD",
+"mainpage"             => "Wikipedia",
+"about"                        => "A proposito di ",
+"aboutsite"      => "A proposito di Wikipedia",
+"aboutpage"            => "Wikipedia:About",
+"help"                 => "Aiuto",
+"helppage"             => "Wikipedia:Aiuto",
+"bugreports"   => "Segnalazioni di malfunzionamento",
+"bugreportspage" => "Wikipedia:Malfunzionamenti",
+"faq"                  => "FAQ",
+"faqpage"              => "Wikipedia:FAQ",
+"edithelp"             => "Guida per la modifica o la scrittura di un articolo",
+"edithelppage" => "Wikipedia:Come_scrivere_un_articolo",
+"cancel"               => "Cancella",
+"qbfind"               => "Trova",
+"qbbrowse"             => "Sfoglia",
+"qbedit"               => "Modifica",
+"qbpageoptions" => "Opzioni pagina",
+"qbpageinfo"   => "Informazioni sulla pagina",
+"qbmyoptions"  => "Le mie preferenze",
+"mypage"               => "La mia pagina",
+"mytalk"               => "Le mie discussioni",
+"currentevents" => "Attualità",
+"errorpagetitle" => "Errore",
+"returnto"             => "Torna a $1.",
+"tagline"              => "Da Wikipedia, l'enciclopedia libera.",
+"whatlinkshere"        => "Pagine che linkano questa",
+"help"                 => "Aiuto",
+"search"               => "Cerca",
+"history"              => "Versioni precedenti",
+"printableversion" => "Versione stampabile",
+"editthispage" => "Modifica questo articolo",
+"deletethispage" => "Cancella questa pagina",
+"protectthispage" => "Proteggi questa pagina",
+"unprotectthispage" => "Togli la protezione a questa pagina",
+"talkpage"             => "Discussione sull'articolo ",
+"articlepage"  => "Leggi articolo",
+"subjectpage"  => "Vedi articolo ", # For compatibility
+"userpage" => "Vedi pagina Utente",
+"wikipediapage" => "Vedi pagina meta ",
+"imagepage" =>         "Vedi pagina immagine",
+"otherlanguages" => "Altre lingue",
+"redirectedfrom" => "(Reindirizzamento da $1)",
+"lastmodified" => "Ultima modifica il $1.",
+"viewcount"            => "Questo articolo è stato letto $1 volte.",
+"printsubtitle" => "(Articolo di {{SERVER}})",
+"protectedpage" => "Pagina protetta",
+"administrators" => "Wikipedia:Amministratori",
+"sysoptitle"   => "Riservato Sysop",
+"sysoptext"            => "Questa operazione può essere eseguita solo da Utenti con grado di \"sysop\".
+Vedi $1.",
+"developertitle" => "Riservato agli sviluppatori",
+"developertext"        => " Questa operazione può essere eseguita solo da Utenti con grado di \"developer\".
+Vedi $1.",
+"nbytes"               => "$1 bytes",
+"go"                   => "Vai",
+"ok"                   => "OK",
+"sitetitle"            => "Wikipedia",
+"sitesubtitle" => "Sa Entzicropedia Iscóita",
+"retrievedfrom" => "Ricavato da  \"$1\"",
+
+# Main script and global functions
+#
+"nosuchaction" => "Operazione non riconosciuta",
+"nosuchactiontext" => "L'operazione richiesta con la URL immessa non è stata riconosciuta dal software di Wikipedia",
+"nosuchspecialpage" => "Nessuna simile pagina speciale è disponibile",
+"nospecialpagetext" => "Hai richiesto una pagina speciale che non è stata riconosciuta dal software di Wikipedia, o che non è disponibile.",
+
+# General errors
+#
+"error"                        => "Errore",
+"databaseerror" => "Errore del database ",
+"dberrortext"  => "Errore di sintassi nella richiesta inoltrata al database.
+L'ultima richiesta inoltrata al database è stata:
+<blockquote><tt>$1</tt></blockquote>
+dalla funzione \"<tt>$2</tt>\".
+MySQL ha restituito un errore \"<tt>$3: $4</tt>\".",
+"noconnect"            => "Connessione al database fallita su $1",
+"nodb"                 => "Selezione del database $1 fallita",
+"readonly"             => "Accesso al database temporaneamente disabilitato",
+"enterlockreason" => "Fornisci una spiegazione sui motivi del blocco, includendo le probabili data ed ora di riattivazione o di rimozione del blocco.",
+"readonlytext" => "Il database di Wikipedia è al momento bloccato, e non consente nuove immissioni né modifiche, molto probabilmente per manutenzione server, nel qual caso il database sarà presto di nuovo completamente accessibile.
+L/'amministratore di sistema che ha imposto il blocco, ha lasciato questa nota:
+<p>$1",
+"missingarticle" => "Il database non ha trovato il testo di una pagina, che invece avrebbe dovuto trovare, intitolata \"$1\".
+Questo non è un errore del database, ma più probabilmente un problema del software.
+Per favore, segnalate l'accaduto ad un administrator, segnalando la URL e l'ora dell'incidente.",
+"internalerror" => "Errore interno",
+"filecopyerror" => "Non è stato possibile copiare il file \"$1\" come \"$2\".",
+"filerenameerror" => "Non è stato possibile rinominare il file \"$1\" in \"$2\".",
+"filedeleteerror" => "Non è stato possibile cancellare il file \"$1\".",
+"filenotfound" => " Non è stato possibile trovare il file \"$1\".",
+"unexpected"   => "Valore imprevisto: \"$1\"=\"$2\".",
+"formerror"            => "Errore: il modulo non è stato inviato correttamente",
+"badarticleerror" => "Questa operazione non è consentita su questa pagina.",
+"cannotdelete" => "Impossibile cancellare la pagina o l'immagine richiesta.",
+"badtitle"             => "Titolo non corretto",
+"badtitletext" => "La pagina richiesta non è disponibile, potrebbe essere non valida, vuota, o potrebbe trattarsi di un errore in un link interlinguistico o fra diverse versioni di Wikipedia.",
+"perfdisabled" => "Siamo davvero rammaricati, ma questa funzionalità è temporaneamente disabilitata durante le ore di maggiore accesso al database per ragioni di accessibilità al resto del sito! Torna fra le 02:00 e le 14:00 UTC e riprova. Grazie.",
+
+# Login and logout pages
+#
+"logouttitle"  => "Logout Utente",
+"logouttext"   => "Logout effettuato.
+Ora puoi continuare ad usare Wikipedia come utente anonimo (ma il tuo indirizzo IP resterà riconoscibile), oppure puoi nuovamente richiedere il login con il precedente username, oppure come uno diverso.\n",
+
+"welcomecreation" => "<h2>Benvenuto, $1!</h2><p>Il tuo account è stato creato con successo.<br />Grazie per aver scelto di far crescere Wikipedia con il tuo aiuto.<br />Per rendere Wikipedia più tua, e per usarla più scorrevolmente, non dimenticare di personalizzare le tue preferenze.",
+
+"loginpagetitle" => "Login",
+"yourname"             => "Il tuo  user name",
+"yourpassword" => "La tua  password",
+"yourpasswordagain" => "Ripeti la password",
+"newusersonly" => " (solo per nuovi Utenti)",
+"remembermypassword" => "Ricorda la mia password per più sessioni (richiede uso dei cookies).",
+"loginproblem" => "<b>Si è verificato un errore durante il tuo tentativo di login.</b><br />Riprova, sarai più fortunato!",
+"alreadyloggedin" => "<strong>Ehi, Utente $1, hai già fatto il login, sei già connesso al nostro server!</strong><br />\n",
+
+"login"                        => "Log in",
+"userlogin"            => "Log in",
+"logout"               => "Log out",
+"userlogout"   => "Log out",
+"createaccount"        => "Crea nuovo account",
+"badretype"            => "Le password che hai immesso non coincidono, sono diverse fra loro.",
+"userexists"   => "Siamo spiacenti. Lo user name che hai scelto è già usato da un altro Utente. Ti preghiamo perciò di voler scegliere uno user name diverso.",
+"youremail"            => "La tua e-mail",
+"yournick"             => "Il tuo diminutivo o soprannome (per le firme)",
+"emailforlost" => "Se per caso ti dimenticassi della tua password, ne potresti ricevere una nuova di zecca presso la casella e-mail che ci hai indicato.",
+"loginerror"   => "Errore di Login",
+"noname"               => "Lo user name indicato non è valido, non è possibile creare un account a questo nome.",
+"loginsuccesstitle" => "Login effettuato con successo!",
+"loginsuccess" => "Sei stato ammesso alla connessione al server di Wikipedia con il nome utente di \"$1\".",
+"nosuchuser"   => "Attenzione<br /><br />a seguito di verifica, non ci risulta alcun Utente con il nome di  \"$1\".<br /><br />
+Controlla per favore il nome digitato, oppure usa il modulo qui sotto per creare un nuovo user account.",
+"wrongpassword"        => "La password immessa non è corretta.<br /><br />Riprova, per favore.",
+"mailmypassword" => "Spediscimi una nuova password in posta elettronica",
+"passwordremindertitle" => "Servizio Password Reminder di Wikipedia",
+"passwordremindertext" => "Qualcuno (probabilmente tu, con indirizzo IP $1)
+ha richiesto l'invio di una nuova password per il login a Wikipedia.
+La password per l'Utente \"$2\" è ora \"$3\".
+Per evidenti ragioni di sicurezza, dovresti fare un log in il prima possibile, e cambiare la password immediatamente.",
+"noemail"              => "Nessuna casella e-mail risulta registrata per l'Utente \"$1\".",
+"passwordsent" => "Una nuova password è stata inviata alla casella e-mail registrata per l'Utente \"$1\".
+Per favore, fai subito un log in non appena la ricevi.",
+
+# Edit pages
+#
+"summary"              => "Oggetto",
+"minoredit"            => "Questa è una modifica minore",
+"watchthis"            => "Tieni d'occhio questo articolo",
+"savearticle"  => "Salva la pagina",
+"preview"              => "Anteprima",
+"showpreview"  => "Visualizza Anteprima",
+"blockedtitle" => "Questo User name corrisponde purtroppo ad un Utente che è stato disabilitato alla modifica degli articoli.",
+"blockedtext"  => "Il tuo User name o il tuo indirizzo IP sono stati bloccati da $1.<br />
+La motivazione del blocco è la seguente:<br />:''$2''<p>Se lo desideri, puoi contattare $1, o uno degli altri
+[[Wikipedia:administrators|administrators]] per discutere del blocco.",
+"newarticle"   => "(Nuovo)",
+"newarticletext" => "Scrivi qui il tuo testo.",
+"noarticletext" => "(L'articolo è vuoto, potresti gentilmente iniziare l'articolo oppure richiedere la cancellazione di questa pagina)",
+"updated"              => "(Aggiornato)",
+"note"                 => "<strong>Nota:</strong> ",
+"previewnote"  => "Tieni presente che questa è solo una ANTEPRIMA, e che la tua versione non è ancora stata salvata!",
+"previewconflict" => "Questa anteprima rappresenta il testo nella casella di edizione di sopra, l'articolo apparirà n questa forma se sceglierai di salvare la pagina.",
+"editing"              => "Modifica di $1",
+"editconflict" => "Conflitto di edizione: $1",
+"explainconflict" => "Qualcun altro ha salvato una sua versione dell'articolo nel tempo in cui tu stavi preparando la tua versione.<br />
+La casella di modifica di sopra contiene il testo dell'articolo nella sua forma attuale (cioè il testo attualmente online). Le tue modifiche sono invece contenute nella casella di modifica inferiore.
+Dovrai inserire, se lo desideri, le tue modifiche nel testo esistente, e perciò scriverle nella casella di sopra.
+<b>Soltanto</b> il testo nella casella di sopra sarà sakvato se premerai il bottone \"Salva\".<br />",
+"yourtext"             => "Il tuo testo",
+"storedversion" => "Versione in archivio",
+"editingold"   => "<strong>ATTENZIONE: Stai modificando una versione dell'articolo non aggiornata.
+Se la salvi così, tutti i cambiamenti apportati dopo questa revisione verranno persi per sempre.</strong>",
+"yourdiff"             => "Differenze",
+"copyrightwarning" => "Nota, per favore, che tutti i contributi a Wikipedia si considerano rilasciati sotto licenza di tipo GNU Free Documentation License
+(vedi $1 per maggiori dettagli).
+Se non vuoi che il tuo testo possa essere modificato e ridistribuito da chiunque senza pietà e senza altri limiti, allora non inviarlo a Wikipedia, ma realizza piuttosto un tuo sito web personale.<br />
+Con l'invio di questo testo stai garantendo, a tua responsabilità, che il testo è stato scritto da te personalmente ed originalmente, oppure che è stato copiato da una fonte di publico dominio, o una simile fonte, oppure che hai ottenuto espressa autorizzazione ad usare questo testo e che puoi dimostrarlo.
+<strong>NON USARE MATERIALE COPERTO DA DIRITTO DI AUTORE (COPYRIGHT - (c)) IN MANCANZA DI ESPRESSA AUTORIZZAZIONE!!!</strong>",
+
+
+# History pages
+#
+"revhistory"   => "Cronologia delle versioni di questa pagina.",
+"nohistory"            => "Cronologia delle versioni di questa pagina non reperibile.",
+"revnotfound"  => "Versione non trovata ",
+"revnotfoundtext" => "La versione precedente di questo articolo che hai richiesto, non è stata trovata.
+Controlla per favore la URL che hai usato per accedere a questa pagina.\n",
+"loadhist"             => "Caricamento cronologia di questa pagina",
+"currentrev"   => "Versione attuale",
+"revisionasof" => "Revisione $1",
+"cur"                  => "corr",
+"next"                 => "succ",
+"last"                 => "prec",
+"orig"                 => "orig",
+"histlegend"   => "Legend: (corr) = differenze con la versione corrente,
+(prec) = differenze con la versione precedente, M = modifica minore",
+
+# Diffs
+#
+"difference"   => "(Differenze fra le revisioni)",
+"loadingrev"   => "caricamento revisione per differenze",
+"lineno"               => "Riga $1:",
+"editcurrent"  => "Modifica la versione corrente di questa pagina",
+
+# Search results
+#
+"searchresults" => "Risultato della ricerca",
+"searchresulttext" => "Per maggiori informazioni sulla ricerca interna di {{SITENAME}}, vedi [[Project:Ricerca|Ricerca in {{SITENAME}}]].",
+"searchquery"  => "Richiesta \"$1\"",
+"badquery"             => "Richiesta mal inoltrata ",
+"badquerytext" => "La tua richiesta non ha potuto essere processata.
+Questo potrebbe dipendere dall'aver ricercato una parola di meno di tre caratteri.
+Oppure potresti aver scritto male la richiesta, per esempio \"pesce and and azzurro\".
+Per favore, riprova.",
+"matchtotals"  => "La ricerca per la voce \"$1\" ha trovato<br />$2 riscontri nei titoli degli articoli e<br />$3 riscontri nei testi degli articoli.",
+"titlematches" => "Nei titoli degli articoli",
+"notitlematches" => "Voce richiesta non trovata in titoli di articolo",
+"textmatches"  => "Nel testo degli articoli ",
+"notextmatches"        => "Voce richiesta non trovata in testi di articolo",
+"prevn"                        => "precedenti $1",
+"nextn"                        => "successivi $1",
+"viewprevnext" => "Vedi ($1) ($2) ($3).",
+"showingresults" => "Qui di seguito <b>$1</b> risultati, partendo dal numero #<b>$2</b>.",
+"nonefound"            => "<strong>Nota</strong>: la ricerca di parole troppo comuni, come \"avere\" o \"essere\", che non sono indicizzate, può causare un esito negativo, così come indicare più di un termine da ricercare (solo le pagine che contengano tutti i termini ricercati verrebbero infatti visualizzate fra i risultati).",
+"powersearch" => "Ricerca",
+"powersearchtext" => "
+Cerca fra i campi :<br />
+$1<br />
+$2 Elenca i redirects &nbsp; cerca per $3 $9",
+
+
+# Preferences page
+#
+"preferences"  => "Preferenze",
+"prefsnologin" => "Non hai eseguito il login",
+"prefsnologintext"     => "Devi avere eseguito il [[Special:Userlogin|login]]
+per poter personalizzare le tue preferenze.",
+"prefslogintext" => "Sei connesso a Wikipedia come \"$1\".
+Il tuo numero identificativo (ID) interno è $2.",
+"prefsreset"   => "Le tue Preferenze sono state ripescate dalla memoria di sistema del potente server di Wikipedia.",
+"qbsettings"   => "Settaggio della barra menu",
+"changepassword" => "Cambia password",
+"skin"                 => "Aspetto",
+"saveprefs"            => "Salva preferenze",
+"resetprefs"   => "Resetta preferenze",
+"oldpassword"  => "Vecchia password",
+"newpassword"  => "Nuova password",
+"retypenew"            => "Riscrivi qui la nuova password",
+"textboxsize"  => "Dimensione della casella di edizione ",
+"rows"                 => "Righe",
+"columns"              => "Colonne",
+"searchresultshead" => "Settaggio delle preferenze per la ricerca ",
+"resultsperpage" => "Risultati da visualizzare per pagina",
+"contextlines" => "Righe di testo da mostrare per ciascun risultato",
+"contextchars" => "Caratteri per linea",
+"stubthreshold" => "Threshold for stub display",
+"recentchangescount" => "Numero di titoli nelle \"modifiche recenti\" ",
+"savedprefs"   => "Le tue preferenze sono state salvate.",
+"timezonetext" => "Immetti il numero di ore di differenza fra la tua ora locale e la ora del server (UTC).",
+"localtime"    => "Ora Locale",
+"timezoneoffset" => "Offset",
+"emailflag"            => "Nascondi la mia e-mail agli altri utenti",
+
+# Recent changes
+#
+"recentchanges" => "Ultime Modifiche",
+"recentchangestext" => "Segui in questa pagina le ultime modifiche apportate agli articoli di Wikipedia.
+[[Wikipedia:Welcome,_newcomers|Benvenuto]]!
+Leggi anche queste pagine: [[wikipedia:FAQ|Wikipedia FAQ]],
+[[Wikipedia:Policies and guidelines|la policy di Wikipedia]]
+(specialmente [[wikipedia:Convenzioni di nomenclatura| Convenzioni di nomenclatura]],
+[[wikipedia:Neutral point of view|oggettività e neutralità]]),
+e [[wikipedia:Most common Wikipedia faux pas|facili errori nell'uso di Wikipedia]].
+
+Se tieni al successo di questo progetto, è molto importante che eviti di immettere materiale coperto da diritti di autore ([[wikipedia:Copyrights|copyrights]]).
+Gli aspetti legali connessi potrebbero dare fastidio a noi ed a te personalmente, perciò controlla bene che quanto scrivi sia di [[pubblico dominio]], o prova ad ottenere le relative autorizzazioni, che in genere vengono concesse molto facilmente. Vedi anche [http://meta.wikipedia.org/wiki/Special:Recentchanges recent meta discussion].",
+"rcloaderr"            => "Caricamento modifiche recenti ",
+"rcnote"               => "Qui di seguito sono elencate le ultime <strong>$1</strong> pagine modificate negli ultimi <strong>$2</strong> giorni.",
+"rcnotefrom"   => " Qui di seguito sono elencate le modifiche da <b>$2</b> (fino a <b>$1</b>).",
+"rclistfrom"   => "Mostra modifiche a partire da $1",
+# "rclinks"            => "Mostra le ultime $1 modifiche nelle ultime $2 ore / negli ultimi $3 giorni",
+"rclinks"              => " Mostra le ultime $1 modifiche negli ultimi $2 giorni.",
+"rchide"               => "in $4 form; $1 modifiche minori; $2 secondary namespaces; $3 modifiche multiple.",
+"diff"                 => "diff",
+"hist"                 => "cron",
+"hide"                 => "nascondi",
+"show"                 => "mostra",
+"tableform"            => "tabella",
+"listform"             => "elenco",
+"nchanges"             => "$1 modifiche",
+"minoreditletter" => "M",
+"newpageletter" => "N",
+
+# Upload
+#
+"upload"               => "Upload file",
+"uploadbtn"            => "Upload file",
+"uploadlink"   => "Upload immagini",
+"reupload"             => "Ri-upload",
+"reuploaddesc" => "Torna al modulo per lo upload.",
+"uploadnologin" => "Devi fare il login per eseguire questa operazione.",
+"uploadnologintext"    => "Devi eseguire [[Special:Userlogin|il login]]
+per fare lo upload di files.",
+"uploaderror"  => "Errore di Upload",
+"uploadtext"   => "'''FERMA!''' Prima di effettuare un upload su Wikipedia, accertati di avere ben letto e soprattutto compreso
+[[Project:Image_use_policy|le regole di Wikipedia sull'uso delle immagini]].
+
+Per visualizzare o cercare immagini precedentemente caricate su Wikipedia, vai alla [[Special:Imagelist|lista delle immagini già caricate]].
+Uploads e cancellazioni delle immagini sono registrati nello
+[[Project:Upload_log|upload log]].
+
+Usa il modulo sottostante per caricare nuovi files immagine da utilizzare per arricchire ed illustrare i tuoi articoli.
+Sulla maggior parte dei browsers, dovresti vedere un bottone con la scritta \"Browse...\" (oppure \"Sfoglia...\", che aprirà una comune finestra di dialogo.
+Scegliendo uno dei files sul tuo PC, il nome di questo file verrà scritto in automatico nella casella di testo a fianco al bottone.
+Devi anche selezionare la casellina nella quale affermi che con questo upload non stai violando nessun copyright.
+Premi poi il bottone \"Upload\" per completare il caricamento.
+Il caricamento può richiedere qualche minuto se hai una connessione ad Internet lenta, o se l'immagine è eccessivamente pesante (sconsigliato).
+
+I formati immagine preferibili sono il JPEG per immagini fotografiche, il PNG
+per disegni ed altre immagini iconiche o simboliche, il OGG per i suoni.
+Per cortesia, rinomina i tuoi files, prima di caricarli, usando un nome il più possibile descrittivo del contenuto, così da evitare confusioni.
+Per inserire la nuova immagine in un articolo, usa semplicemente un link nella forma
+'''<nowiki>[[image:file.jpg]]</nowiki>''' o
+'''<nowiki>[[image:file.png|alt text, testo alternativo]]</nowiki>''' o
+'''<nowiki>[[media:file.ogg]]</nowiki>''' per i suoni.
+
+Tieni presente che, come per tutte le pagine di Wikipedia, chiunque può modificare o sostituire o cancellare i tuoi files ove ritenga che ciò sia negli interessi della nostra enciclopedia. Tieni anche presente che, in caso di abuso, o di sovraccarico sul sistema, potresti essere bloccato (oltre ad essere perseguito per le connesse responsabilità).",
+"uploadlog"            => "upload log",
+"uploadlogpage" => "Upload_log",
+"uploadlogpagetext" => "Qui di seguito la lista degli ultimi files caricati sul server di Wikipedia.
+Tutti i tempi indicati sono calcolati sul fuso orario del server (UTC).
+<ul>
+</ul>
+",
+"filename"             => "Nome del file",
+"filedesc"             => "Oggetto",
+"copyrightpage" => "Wikipedia:Copyrights",
+"copyrightpagename" => "Wikipedia copyright",
+"uploadedfiles"        => "Files Caricati in Wikipedia",
+"ignorewarning"        => "Ignora le avvertenze e salva comunque il file.",
+"minlength"            => "I nomi dei file immagine debbono essere lunghi almeno tre caratteri, ma è preferibile usare nomi lumghi, purché descrittivi.",
+"badfilename"  => "Il nome del file immagine è stato convertito in \"$1\".",
+"badfiletype"  => "\".$1\" non è un tipo di file raccomandato per le immagini, almeno ai nostri fini.",
+"largefile"            => "Il peso raccomandato per le immagini deve essere inferiore a 100kb.",
+"successfulupload" => "Caricamento completato",
+"fileuploaded" => "File \"$1\" correttamente caricato sul server.
+Segui questo link: ($2) per modificare la pagina di descrizione del file che hai appena caricato, e immetti le informazioni che ritieni opportune (cosa rappresenta, dove lo hai trovato, chi lo ha creato e quando, etc) oltre ad una nota circa la situazione di copyright sul file. Non omettere la nota sul copytright, o il file verrebbe cancellato molto presto. ",
+"uploadwarning" => "Avviso di Upload",
+"savefile"             => "Salva file",
+"uploadedimage" => "caricato \"[[$1]]\"",
+
+# Image list
+#
+"imagelist"            => "Lista delle immagini",
+"imagelisttext"        => "Qui di seguito una lista di $1 immagini, ordinate per $2.",
+"getimagelist" => "ricerca nella lista delle immagini ",
+"ilsubmit"             => "Cerca",
+"showlast"             => "Mostra le ultime $1 immagini ordinate per $2.",
+"byname"               => "nome",
+"bydate"               => "data",
+"bysize"               => "peso",
+"imgdelete"            => "canc",
+"imgdesc"              => "desc",
+"imglegend"            => "Legenda: (desc) = mostra/modifica descrizione immagine.",
+"imghistory"   => "Storia di questa immagine",
+"revertimg"            => "ripr",
+"deleteimg"            => "canc",
+"deleteimgcompletely"          => "canc",
+"imghistlegend" => "Legenda: (cur) = immagine corrente, (canc) = cancella questa vecchia versione, (ripr) = ripristina questa vecchia versione come versione attuale.
+<br /><i>Clicca su una data per vedere tutte le immagini che sono state caricate in quella data </i>.",
+"imagelinks"   => "Link alle immagini",
+"linkstoimage" => "Le pagine seguenti linkano questa immagine:",
+"nolinkstoimage" => "Nessuna pagina linka questa immagine.",
+
+# Statistics
+#
+"statistics"   => "Statistiche",
+"sitestats"            => "Statistiche del sito",
+"userstats"            => "Statistiche del nostro Wikipediano",
+"sitestatstext" => "Ci sono ben <b>$1</b> pagine nel database.
+Questa cifra comprende le pagine \"talk\" (discussione), pagine su Wikipedia, articoli esigui (\"stub\"), redirects, e altre pagine che probabilmente non andrebbero conteggiate fra gli articoli.
+Escludendo queste, ci sono ben  <b>$2</b> pagine che sono con buona probabilità propriamente degli articoli.<p>
+Ci sono state un totale di <b>$3</b> pagine viste, e <b>$4</b> modifiche agli articoli da quando il software è stato potenziato (Dicembre, 2002).
+Questa media rivela che ci sono state una media di  <b>$5</b> modifiche per ciascun articolo, e che l'articolo è stato letto <b>$6</b> volte per ciascuna modifica.",
+"userstatstext" => "Ci sono <b>$1</b> Utenti registrati ([[Wikipediani]]).
+<b>$2</b> di questi hanno il grado di amministratori (vedi $3).",
+
+# Maintenance Page
+#
+"maintenance"          => "Pagina manutenzioni",
+"maintnancepagetext"   => "In questa pagina sono elencati alcuni utili strumenti per una comoda manutenzione quotidiana della nostra enciclopedia. Alcune delle funzioni tendono a stressare il database, assorbendo molte risorse, perciò non fatene un uso continuo: non aggiornate le pagine (reload, refresh) subito dopo ogni singolo intervento. ;-)",
+"maintenancebacklink"  => "Torna alla pagina manutenzione",
+"disambiguations"      => "Disambiguation pages",
+"disambiguationspage"  => "Wikipedia:Links_to_disambiguating_pages",
+"disambiguationstext"  => "The following articles link to a <i>disambiguation page</i>. They should link to the appropriate topic instead.<br />A page is treated as dismbiguation if it is linked from $1.<br />Links from other namespaces are <i>not</i> listed here.",
+"doubleredirects"      => "Doppi Redirects",
+"doubleredirectstext"  => "<b>Attenzione:</b> Questa lista può talvolta contenere dei risultati non corretti. Ciò potrebbe magari accadere perchè vi sono del testo aggiuntivo o dei link dopo il tag #REDIRECT.<br />\nOgni riga contiene i link al primo ed al secondo redirect, oltre alla prima riga di testo del secondo redirect che di solito contiene il \"reale\" articolo di destinazione, quello al quale anche il primo redirect dovrebbe puntare.",
+"brokenredirects"      => "Redirects errati",
+"brokenredirectstext"  => "I seguenti redirects puntano ad articoli non ancora creati.",
+"selflinks"            => "Pagine con Auto-Links",
+"selflinkstext"                => "Le pagine seguenti contengono link che puntano a sé stesse, e in questo caso occorre eliminare questi auto-links.",
+"mispeelings"           => "Pagine con errori di ortografia ",
+"mispeelingstext"               => "Le pagine che seguono contengono errori comuni di ortografia, che sono elencati alla pagina $1. ",
+"mispeelingspage"       => "Lista di comuni errori di ortografia",
+"missinglanguagelinks"  => "Link interlinguistici mancanti",
+"missinglanguagelinksbutton"    => "Trova i Link interlinguistici da aggiungere per ",
+"missinglanguagelinkstext"      => "Questi articoli <i>non</i> hanno link verso i corrispondenti articoli in $1. Redirects e sub-pagine <i>non</i> sono elencati.",
+
+
+# Miscellaneous special pages
+#
+"orphans"              => "Pagine orfane",
+"lonelypages"  => "Pagine solitarie",
+"unusedimages" => "Immagini non utilizzate",
+"popularpages" => "Pagine più viste",
+"nviews"               => "$1 visite",
+"wantedpages"  => "Articoli più richiesti",
+"nlinks"               => "$1 links",
+"allpages"             => "Tutte le pagine",
+"randompage"   => "Una pagina a caso",
+"shortpages"   => "Pagine corte",
+"longpages"            => "Pagine lunghe",
+"listusers"            => "Elenco degli Utenti",
+"specialpages" => "Pagine speciali",
+"spheading"            => "Pagine speciali",
+"protectpage"  => "Proteggi questa pagina ",
+"recentchangeslinked" => "Modifiche correlate",
+"rclsub"               => "(alle pagine linkate da \"$1\")",
+"debug"                        => "Debug",
+"newpages"             => "Pagine nuove",
+"movethispage" => "Sposta questa pagina",
+"unusedimagestext" => "<p>Nota che altri siti web, come la Wikipedia internazionale, potrebbero aver messo un link ad una immagine per mezzo di una URL diretta, perciò le immagini potrebbero essere listate qui anche essendo magari in uso.",
+"booksources"  => "Book sources",
+"booksourcetext" => "Below is a list of links to other sites that
+sell new and used books, and may also have further information
+about books you are looking for.
+Wikipedia is not affiliated with any of these businesses, and
+this list should not be construed as an endorsement.",
+
+# Email this user
+#
+"mailnologin"  => "No send address",
+"mailnologintext" => "Devi fare il [[Special:Userlogin|login]]
+ed aver registrato una valida casella e-mail nelle tue [[Special:Preferences|preferenze]] per mandare posta elettronica ad altri Utenti.",
+"emailuser"            => "Manda una E-mail a questo Utente",
+"emailpage"            => "E-mail user",
+"emailpagetext"        => "Se questo Utente ha registrato una valida casella e-mail, il modulo qui sotto ti consentirà di scrivergli un solo messaggio.
+La e-mail che hai indicato nelle tue preferenze apparirà nel campo \"From\" della mail, così che il destinatario possa, solo se lo desidera però, risponderti.",
+"noemailtitle" => "Nessun indirizzo e-mail",
+"noemailtext"  => "Questo Utente non ha registrato alcuna casella e-mail,
+oppure ha scelto di non ricevere  posta elettronica dagli altri Utenti.",
+"emailfrom"            => "From",
+"emailto"              => "To",
+"emailsubject" => "Subject",
+"emailmessage" => "Message",
+"emailsend"            => "Send",
+"emailsent"            => "E-mail inviata",
+"emailsenttext" => "La tua e-mail è stata inviata.",
+
+# Watchlist
+#
+"watchlist"            => "Osservati Speciali",
+"watchlistsub" => "(per l'Utente \"$1\")",
+"nowatchlist"  => "Non hai indicato articoli da tenere d'occhio.",
+"watchnologin" => "Manca il login",
+"watchnologintext"     => "Devi prima fare il [[Special:Userlogin|login]]
+per modificare la tua lista di osservati speciali.",
+"addedwatch"   => "Aggiunto agli Osservati Speciali",
+"addedwatchtext" => " La pagina  \"$1\" è stata aggiunta alla tua <a href=\"" .
+  "{{localurle:Special:Watchlist}}\"> lista di osservati speciali </a>.
+Le future modifiche a questa pagina ed alla relativa pagina di discussione saranno elencate qui, e la pagina apparirà in <b>grassetto</b> nella pagina delle <a href=\"" .
+  "{{localurle:Special:Recentchanges}}\">modifiche recenti</a> per essere più facile da tener d'occhio.</p>
+
+<p>Se in seguito vorrai togliere questo articolo dalla tua lista di osservati speciali, clicca \" Smetti di seguire \" nella barra dei menu.",
+"removedwatch" => "Rimosso dalla lista degli Osservati Speciali",
+"removedwatchtext" => "La pagina  \"$1\" è stata rimossa dalla lista degli Osservati Speciali.",
+"watchthispage"        => "Segui questo articolo",
+"unwatchthispage" => "Smetti di seguire",
+"notanarticle" => "Non è un articolo",
+
+
+# Delete/protect/revert
+#
+"deletepage"   => "Cancella pagina",
+"confirm"              => "Conferma",
+"confirmdelete" => "Conferma cancellazione",
+"deletesub"            => "(Cancellazione di \"$1\")",
+"confirmdeletetext" => "Stai per cancellare permanentemente dal database una pagina o una immagine, insieme a tutta la sua cronologia.
+Per cortesia, conferma che è tua intenzione procedere a tale cancellazione, conferma che hai piena consapevolezza delle conseguenze della tua azione, e conferma che la tua azione è pienamente ottemperante alle regole stabilite nella
+[[Wikipedia:Policy]].",
+"actioncomplete" => "Azione completata",
+"deletedtext"  => "La pagina \"$1\" è stata cancellata.
+Vedi $2 per un elenco delle pagine cancellate di recente.",
+"deletedarticle" => "Cancellata \"$1\"",
+"dellogpage"   => "Deletion_log",
+"dellogpagetext" => "Qui di seguito, un elenco delle pagine cancellate di recente.
+Tutti i tempi sono in ora del server (UTC).
+<ul>
+</ul>
+",
+"deletionlog"  => "deletion log",
+"reverted"             => "Ripristinata versione precedente",
+"deletecomment"        => "Motivazione della cancellazione ",
+"imagereverted" => "Versione precedente correttamente ripristinata.",
+"rollback"             => "Usa una revisione precdente",
+"cantrollback" => "Impossibile tornare ad una versione precedente: l'ultima modifica è stata apportata dall'unico utente che abbia lavorato a questo articolo.",
+"revertpage"   => "Riportata alla revisione precedente da $1",
+
+# Undelete
+"undelete" => "Recupera una pagina cancellata",
+"undeletepage" => "Vedi e recupera pagine cancellate ",
+"undeletepagetext" => "Le pagine qui di seguito indicate sono state cancellate, ma sono ancora in archivio e pertanto possono essere recuperate. L'archivio viene svuotato periodicamente.",
+"undeletearticle" => "Recupera un articolo cancellato",
+"undeleterevisions" => "$1 revisioni in archivio",
+"undeletehistory" => "Se recuperi questo articolo, tutte le sue revisioni verranno recuperate nella relativa cronologia.
+Se una nuova pagina è stata creata con questo stesso nome dopo la cancellazione, le revisioni recuperate saranno inserite nella cronologia e la versione attualmente online della pagina non verrà modificata.",
+"undeleterevision" => "Cancellata revisione $1",
+"undeletebtn" => "RIPRISTINA!",
+"undeletedarticle" => "Recuperata \"$1\"",
+"undeletedtext"   => "La pagina [[$1]] è stata recuperata.
+Vedi [[Wikipedia:Deletion_log]] per un elenco delle pagine cancellate e recuperate di recente.",
+
+# Contributions
+#
+"contributions"        => "Contributi di questo Utente",
+"contribsub"   => "Per $1",
+"nocontribs"   => "Nessuna modifica trovata conformemente a questi criteri.",
+"ucnote"               => "Qui sotto troverai le ultime <b>$1</b> modifiche effettuate da questo Utente negli ultimi <b>$2</b> giorni.",
+"uclinks"              => "Vedi le ultime $1 modifiche; vedi gli ultimi $2 giorni.",
+"uctop"                => " (ultima per la pagina)" ,
+
+# What links here
+#
+"whatlinkshere"        => "Pagine che linkano questa",
+"notargettitle" => "Dati mancanti",
+"notargettext" => "Non hai specificato una pagina o un Utente in relazione al quale eseguire l'operazione richiesta.",
+"linklistsub"  => "(Lista di links)",
+"linkshere"            => "Le seguenti pagine contengono link che puntano qui:",
+"nolinkshere"  => "Nessuna pagina contiene links che puntano a questa.",
+"isredirect"   => "redirect ",
+
+# Block/unblock IP
+#
+"blockip"              => "Blocca indirizzo IP",
+"blockiptext"  => "Usa il modulo sottostante per bloccare l'accesso con diritto di scrittura da uno specifico indirizzo IP.
+Questo blocco deve essere operato SOLO per prevenire atti di vandalismo, ed in stretta osservanza dei principi tutti della [[Wikipedia:Policy|policy di Wikipedia]]. Il blocco non può in nessun caso essere applicato per motivi ideologici.
+Scrivi un motivo specifico per il quale questo indirizzo IP dovrebbe a tuo avviso essere bloccato (per esempio, cita i titoli di pagine eventualmente già oggetto di vandalismo editoriale).",
+"ipaddress"            => "Indirizzo IP (IP Address)",
+"ipbreason"            => "Motivazione",
+"ipbsubmit"            => "Blocca questo indirizzo IP",
+"badipaddress" => "L'indirizzo IP indicato non è corretto.",
+"blockipsuccesssub" => "Blocco eseguito",
+"blockipsuccesstext" => " L'indirizzo IP \"$1\" è stato bloccato.
+<br />Vedi [[Special:Ipblocklist|lista IP bloccati]].",
+"unblockip"            => " Sblocca indirizzo IP",
+"unblockiptext"        => "Usa il modulo sottostante per restituire il diritto di scrittura ad un indirizzo IP precedentemente bloccato.",
+"ipusubmit"            => "Sblocca questo indirizzo IP",
+"ipusuccess"   => "Indirizzo IP \"$1\" sbloccato",
+"ipblocklist"  => "Lista degli indirizzi IP bloccati",
+"blocklistline"        => "$1, $2 ha bloccato $3 ($4)",
+"blocklink"            => "blocca",
+"unblocklink"  => "sblocca",
+"contribslink" => "contributi",
+
+# Developer tools
+#
+"lockdb"               => "Blocca il database",
+"unlockdb"             => "Sblocca il database",
+"lockdbtext"   => "Bloccare il database sospenderà la possibilità per tutti gli Utenti di modificare le pagine o di crearne di nuove, di cambiare le loro preferenze, di modificare le loro liste di Osservati Speciali, ed in genere non consentirà a nessuno di eseguire operazioni che richiedano modifiche del database.<br /><br />
+Per cortesia, conferma che questo è effettivamente quanto tu intendi ora effettuare e, soprattutto, che il prima possibile sbloccherai nuovamente il database, ripristinandone la corretta funzionalità, non appena avrai terminato le tue manutenzioni.",
+"unlockdbtext" => "Sbloccare il database ripristinerà la possibilità per tutti gli Utenti di modificare le pagine o di crearne di nuove, di cambiare le loro preferenze, di modificare le loro liste di Osservati Speciali, ed in genere di eseguire operazioni che richiedano modifiche del database.
+Per cortesia, conferma che questo è effettivamente quanto tu intendi ora effettuare.",
+"lockconfirm"  => "Sì, effettivamente intendo, sotto la mia responsabilità, bloccare il database.",
+"unlockconfirm"        => " Sì, effettivamente intendo, sotto la mia responsabilità, sbloccare il database.",
+"lockbtn"              => "Blocca il database",
+"unlockbtn"            => "Sblocca il database",
+"locknoconfirm" => "Non hai spuntato la casellina di conferma.",
+"lockdbsuccesssub" => "Blocco del database eseguito",
+"unlockdbsuccesssub" => "Sblocco del database eseguito, rimosso blocco",
+"lockdbsuccesstext" => "Il database di Wikipedia è stato bloccato.
+<br />Ricordati di rimuovere il blocco non appena avrai terminatoi le tue manutenzioni.",
+"unlockdbsuccesstext" => " Il database di Wikipedia è stato sbloccato.",
+
+# Move page
+#
+"movepage"             => "Spostamento di pagina",
+"movepagetext" => "Con il modulo sottostante puoi rinominare una pagina, spostando anche tutta la sua cronologia al nuovo nome.
+Il vecchior titolo diverrà automaticamente un redirect che punta al nuovo titolo.
+I link alla vecchia pagina non saranno aggiornati (e punteranno quindi al redirect); accertati di [[Special:Manutenzioni|controllare con cura]] che non si creino doppi redirects o redirects interrotti.
+Resta nella tua responsabilità di accertarti che i link continuino a puntare verso dove devono dirigersi.
+
+Nota bene: la pagina '''non''' sarà spostata se vi fosse già un articolo con il nuovo nome, a meno che non sia una pagina vuota o un redirect e che non abbia cronologia. Questo significa che, se commetti un errore, puoi nuovamente rinominare una pagina col vecchio titolo, ma non puoi sovrascrivere una pagina già esistente.
+
+<b>ATTENZIONE!</b>
+Questo cambiamento drastico potrebbe creare inattesi contrattempi, specialmente se si tratta di una pagina molto visitata. Accertati di aver ben valutato le conseguenze dello spostamento, prima di procedere. Nel dubbio, contatta un Amministratore.",
+"movepagetalktext" => "La corrispondente pagina di discussione, se esiste, sarà spostata automaticamente insieme all'articolo, '''tranne che nei seguenti casi:'''
+*Spostamento della pagina fra i namespaces,
+*Una pagina di discussione (non vuota) già esiste per il nuovo nome, oppure
+*Hai deselezionato la casellina qui sotto.
+
+In questi casi, se lo ritieni opportuno, dovrai spostare o aggiungere manualmente la pagina di discussione.",
+"movearticle"  => "Rinomina articolo",
+"movenologin"  => "Non hai effettuato il login",
+"movenologintext" => "Devi essere un Utente registrato ed aver effettuato il [[Special:Userlogin|login]]
+per poter spostare una pagina.",
+"newtitle"             => "Al nuovo titolo di ",
+"movepagebtn"  => "Sposta questa pagina",
+"pagemovedsub" => "Spostamento effettuato con successo",
+"pagemovedtext" => "Pagina \"[[$1]]\" rinominata in \"[[$2]]\".",
+"articleexists" => "Una pagina con questo nome esiste già, oppure il nome che hai scelto non è valido.<br />
+Scegli, per cortesia, un titolo diverso per l'articolo.",
+"talkexists"   => "La pagina è stata spostata correttamente, ma la pagina di dicussione non poteva essere spostata perché ne esiste già un'altra con il nuovo titolo. Per favore, modifica manualmente i contenuti delle due pagine discussione, così da mantenerle entrambe per non perdere potenzialmente interessanti riflessioni.",
+"movedto"              => "spostata a ",
+"movetalk"             => "Sposta anche la corrispondente pagina \"discussione\", se possibile.",
+"talkpagemoved" => "Anche la corrispondente pagina di discussione è stata spostata.",
+"talkpagenotmoved" => "La corrispondente pagina di discussione <strong>non è stata spostata</strong>."
+
+);
+
+class LanguageSc extends LanguageUtf8 {
+
+       function getNamespaces() {
+               global $wgNamespaceNamesSc;
+               return $wgNamespaceNamesSc;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsSc;
+               return $wgQuickbarSettingsSc;
+       }
+
+       function date( $ts, $adj = false ) {
+               if ( $adj ) { $ts = $this->userAdjust( $ts ); }
+
+               $d = $this->getMonthAbbreviation( substr( $ts, 4, 2 ) ) .
+                 " " . (0 + substr( $ts, 6, 2 )) . ", " .
+                 substr( $ts, 0, 4 );
+               return $d;
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesSc;
+               if(array_key_exists($key, $wgAllMessagesSc))
+                       return $wgAllMessagesSc[$key];
+               else
+                       return parent::getMessage($key);
+       }
+
+}
+
+?>
diff --git a/languages/LanguageSd.php b/languages/LanguageSd.php
new file mode 100644 (file)
index 0000000..1526815
--- /dev/null
@@ -0,0 +1,18 @@
+<?php
+/** Sindhi language file ( सिनधि )
+  *
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+require_once( 'LanguageUtf8.php' );
+
+class LanguageSd extends LanguageUtf8 {
+       #FIXME: inherit almost everything for now
+
+       function isRTL() {
+               return true;
+       }
+}
+
+?>
diff --git a/languages/LanguageSk.php b/languages/LanguageSk.php
new file mode 100644 (file)
index 0000000..3a5a253
--- /dev/null
@@ -0,0 +1,1766 @@
+<?php
+/**
+ * Slovak (Slovenčina)
+ *
+ * @package MediaWiki
+ * @subpackage Language
+ */
+
+require_once( 'LanguageUtf8.php' );
+
+/* private */ $wgNamespaceNamesSk = array(
+       NS_MEDIA                => 'Médiá',
+       NS_SPECIAL              => 'Špeciálne',
+       NS_MAIN                 => '',
+       NS_TALK                 => 'Diskusia',
+       NS_USER                 => 'Redaktor',
+       NS_USER_TALK            => 'Diskusia_s_redaktorom',
+       NS_PROJECT              => $wgMetaNamespace,
+       NS_PROJECT_TALK         => FALSE, # Nadefinované vo funkcii dole 'Diskusia_k_' . $wgMetaNamespace,
+       NS_IMAGE                => 'Obrázok',
+       NS_IMAGE_TALK           => 'Diskusia_k_obrázku',
+       NS_MEDIAWIKI            => 'MediaWiki',
+       NS_MEDIAWIKI_TALK       => 'Diskusia_k_MediaWiki',
+       NS_TEMPLATE             => 'Šablóna',
+       NS_TEMPLATE_TALK        => 'Diskusia_k_šablóne',
+       NS_HELP                 => 'Pomoc',
+       NS_HELP_TALK            => 'Diskusia_k_pomoci',
+       NS_CATEGORY             => 'Kategória',
+       NS_CATEGORY_TALK        => 'Diskusia_ku_kategórii'
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgQuickbarSettingsSk = array(
+       'Žiadne', 'Ukotvené vľavo', 'Ukotvené vpravo', 'Plávajúce vľavo'
+);
+
+/* private */ $wgDateFormatsSk = array(
+       'Default',
+       '15. január 2001 16:12',
+       '15. jan. 2001 16:12',
+       '16:12, 15. január 2001',
+       '16:12, 15. jan. 2001',
+       'ISO 8601' => '2001-01-15 16:12:34'
+);
+
+/* private */ $wgBookstoreListSk = array(
+       'Bibsys' => 'http://ask.bibsys.no/ask/action/result?cmd=&kilde=biblio&fid=isbn&term=$1',
+       'BokBerit' => 'http://www.bokberit.no/annet_sted/bocker/$1.html',
+       'Bokkilden' => 'http://www.bokkilden.no/ProductDetails.aspx?ProductId=$1',
+       'Haugenbok' => 'http://www.haugenbok.no/searchresults.cfm?searchtype=simple&isbn=$1',
+       'Akademika' => 'http://www.akademika.no/sok.php?isbn=$1',
+       'Gnist' => 'http://www.gnist.no/sok.php?isbn=$1',
+       'Amazon.co.uk' => 'http://www.amazon.co.uk/exec/obidos/ISBN=$1',
+       'Amazon.de' => 'http://www.amazon.de/exec/obidos/ISBN=$1',
+       'Amazon.com' => 'http://www.amazon.com/exec/obidos/ISBN=$1'
+);
+
+# Note to translators:
+# Please include the English words as synonyms. This allows people
+# from other wikis to contribute more easily.
+#
+/* private */ $wgMagicWordsSk = array(
+# ID CASE SYNONYMS
+       MAG_REDIRECT => array( 0, '#redirect', '#presmeruj' ),
+       MAG_NOTOC => array( 0, '__NOTOC__', '__BEZOBSAHU__' ),
+       MAG_FORCETOC => array( 0, '__FORCETOC__', '__VYNÚŤOBSAH__' ),
+       MAG_TOC => array( 0, '__TOC__', '__OBSAH__' ),
+       MAG_NOEDITSECTION => array( 0, '__NOEDITSECTION__', '__NEUPRAVUJSEKCIE__' ),
+       MAG_START => array( 0, '__START__', '__ŠTART__' ),
+       MAG_CURRENTMONTH => array( 1, 'CURRENTMONTH', 'MESIAC' ),
+       MAG_CURRENTMONTHNAME => array( 1, 'CURRENTMONTHNAME', 'MENOMESIACA' ),
+       MAG_CURRENTMONTHNAMEGEN => array( 1, 'CURRENTMONTHNAMEGEN', 'MENOAKTUÁLNEHOMESIACAGEN' ),
+       MAG_CURRENTMONTHABBREV   => array( 1, 'CURRENTMONTHABBREV', 'MENOAKTUÁLNEHOMESIACASKRATKA' ),
+       MAG_CURRENTDAY => array( 1, 'CURRENTDAY', 'AKTUÁLNYDEŇ' ),
+       MAG_CURRENTDAYNAME => array( 1, 'CURRENTDAYNAME', 'MENOAKTUÁLNEHODŇA' ),
+       MAG_CURRENTYEAR => array( 1, 'CURRENTYEAR', 'AKTUÁLNYROK' ),
+       MAG_CURRENTTIME => array( 1, 'CURRENTTIME', 'AKTUÁLNYČAS' ),
+       MAG_NUMBEROFARTICLES => array( 1, 'NUMBEROFARTICLES', 'POČETČLÁNKOV' ),
+       MAG_PAGENAME => array( 1, 'PAGENAME', 'MENOSTRÁNKY' ),
+       MAG_PAGENAMEE => array( 1, 'PAGENAMEE' ),
+       MAG_NAMESPACE => array( 1, 'NAMESPACE', 'MENNÝPRIESTOR' ),
+       MAG_MSG => array( 0, 'MSG:', 'SPRÁVA:' ),
+       MAG_SUBST => array( 0, 'SUBST:' ),
+       MAG_MSGNW => array( 0, 'MSGNW:' ),
+       MAG_END => array( 0, '__END__', '__KONIEC__' ),
+       MAG_IMG_THUMBNAIL => array( 1, 'thumbnail', 'thumb', 'náhľad', 'náhľadobrázka' ),
+       MAG_IMG_RIGHT => array( 1, 'right', 'vpravo' ),
+       MAG_IMG_LEFT => array( 1, 'left', 'vľavo' ),
+       MAG_IMG_NONE => array( 1, 'none', 'žiadny' ),
+       MAG_IMG_WIDTH => array( 1, '$1px', '$1bod' ),
+       MAG_IMG_CENTER => array( 1, 'center', 'centre', 'stred' ),
+       MAG_IMG_FRAMED => array( 1, 'framed', 'enframed', 'frame', 'rám' ),
+       MAG_INT => array( 0, 'INT:' ),
+       MAG_SITENAME => array( 1, 'SITENAME', 'MENOLOKALITY' ),
+       MAG_NS => array( 0, 'NS:', 'MP:' ),
+       MAG_LOCALURL => array( 0, 'LOCALURL:' ),
+       MAG_LOCALURLE => array( 0, 'LOCALURLE:' ),
+       MAG_SERVER => array( 0, 'SERVER' ),
+       MAG_GRAMMAR => array( 0, 'GRAMMAR:', 'GRAMATIKA:' ),
+       MAG_NOTITLECONVERT => array( 0, '__NOTITLECONVERT__', '__NOTC__' ),
+       MAG_NOCONTENTCONVERT => array( 0, '__NOCONTENTCONVERT__', '__NOCC__' ),
+       MAG_CURRENTWEEK => array( 1, 'CURRENTWEEK', 'AKTUÁLNYTÝŽDEŇ' ),
+       MAG_CURRENTDOW => array( 1, 'CURRENTDOW' ),
+       MAG_REVISIONID => array( 1, 'REVISIONID' ),
+);
+
+#-------------------------------------------------------------------
+# Default messages
+#-------------------------------------------------------------------
+
+/* private */ $wgAllMessagesSk = array(
+
+# User Toggles
+
+'tog-editondblclick' => "Upravuj stránky po dvojitom kliknutí (JavaScript)",
+'tog-editsection' => "Umožni upravovať sekcie cez [uprav] odkazy",
+'tog-editsectiononrightclick' => "Umožni upravovať sekcie po kliknutí pravým tlačidlom na nadpisy sekcií (JavaScript)",
+'tog-editwidth' => "Maximálna šírka okna na úpravy",
+'tog-fancysig' => "Nespracovávať podpisy (bez automatických odkazov)",
+'tog-hideminor' => "V posledných úpravách neukazuj drobné úpravy",
+'tog-highlightbroken' => "Neexistujúce odkazy zobrazuj červenou",
+'tog-justify' => "Zarovnávaj odstavce",
+'tog-minordefault' => "Označ všetky zmeny ako drobné",
+'tog-nocache' => "Vypni ukladanie stránok do vyrovnávacej pamäte",
+'tog-numberheadings' => "Automaticky čísluj odstavce",
+'tog-previewonfirst' => "Zobraz náhľad pri prvom upravovaní",
+'tog-previewontop' => "Zobrazuj ukážku pred oknom na úpravy, a nie až za ním",
+'tog-rememberpassword' => "Pamätaj si heslo aj nabudúce",
+'tog-showtoc' => "Zobraz obsah (pre stránky s viac ako 3 nadpismi)",
+'tog-showtoolbar' => "Zobrazuj upravovací panel nástrojov",
+'tog-underline' => "Podčiarkuj odkazy",
+'tog-usenewrc' => "Špeciálne zobrazenie posledných úprav (vyžaduje JavaScript)",
+'tog-watchdefault' => "Upozorňuj na nové a novo upravené stránky",
+#'tog-externaleditor' => 'Use external editor by default',
+#'tog-externaldiff' => 'Use external diff by default',
+
+# Dates
+#
+
+'sunday' => 'nedeľa',
+'monday' => 'pondelok',
+'tuesday' => 'utorok',
+'wednesday' => 'streda',
+'thursday' => 'štvrtok',
+'friday' => 'piatok',
+'saturday' => 'sobota',
+'january' => 'január',
+'february' => 'február',
+'march' => 'marec',
+'april' => 'apríl',
+'may_long' => 'máj',
+'june' => 'jún',
+'july' => 'júl',
+'august' => 'august',
+'september' => 'september',
+'october' => 'október',
+'november' => 'november',
+'december' => 'december',
+'jan' => 'jan',
+'feb' => 'feb',
+'mar' => 'mar',
+'apr' => 'apr',
+'may' => 'máj',
+'jun' => 'jún',
+'jul' => 'júl',
+'aug' => 'aug',
+'sep' => 'sep',
+'oct' => 'okt',
+'nov' => 'nov',
+'dec' => 'dec',
+
+# Bits of text used by many pages:
+#
+'categories' => 'Kategórie',
+'category' => 'kategória',
+'category_header' => 'články v kategórii "$1"',
+'subcategories' => 'podkategórie',
+
+"linktrail" => "/^((?:[a-z]|á|ä|č|ď|é|í|ľ|ĺ|ň|ó|ô|ŕ|š|ť|ú|ý|ž)+)(.*)$/sD",
+"mainpage" => "Hlavná stránka",
+'mainpagetext' => 'Wiki sofvér úspešne nainštalovaný.',
+"mainpagedocfooter" => "Prosím prečítajte si [http://meta.wikipedia.org/wiki/MediaWiki_i18n dokumentáciu ako upraviť rozhranie]
+a [http://meta.wikipedia.org/wiki/MediaWiki_User%27s_Guide Používateľskú príručku], ktorá Vám pomôže pri nastavení a používaní.",
+
+'portal' => 'Portál komunity',
+'portal-url' => 'Project:Portál_komunity',
+'about' => 'Projekt',
+'aboutsite' => 'O {{GRAMMAR:lokál|{{SITENAME}}}}',
+'aboutpage' => 'Project:Úvod',
+'article' => 'Stránka s obsahom',
+'help' => 'Pomoc',
+'helppage' => 'Pomoc:Obsah',
+'bugreports' => 'Oznámenia o chybách',
+'bugreportspage' => 'Project:Oznámenia_o_chybách',
+'sitesupport' => 'Dotácie', # To enable, something like 'Donations',
+'sitesupport-url' => 'Project:Dotácie',
+'faq' => 'FAQ',
+'faqpage' => 'Project:FAQ',
+'edithelp' => 'Ako upravovať stránku',
+'newwindow' => '(otvorí nové okno)',
+'edithelppage' => 'Project:Ako_upravovať_stránku',
+'cancel' => 'Zrušiť',
+'qbfind' => 'Nájdi',
+'qbbrowse' => 'Listuj',
+'qbedit' => 'Upravuj',
+'qbpageoptions' => 'Možnosti stránky',
+'qbpageinfo' => 'Informácie o stránke',
+'qbmyoptions' => 'Moje nastavenia',
+'qbspecialpages' => 'Špeciálne stránky',
+'moredotdotdot' => 'Viac...',
+'mypage' => 'Moja stránka',
+'mytalk' => 'Moja diskusia',
+'anontalk' => 'Diskusia k tejto IP adrese',
+'navigation' => 'Navigácia',
+
+# Metadata in edit box
+'metadata' => "'''Metadáta''' (for an explanation see <a href=\"$1\">here</a>)",
+'metadata_page' => 'Project:Metadáta',
+
+# NOTE: To turn off "Current Events" in the sidebar,
+# set "currentevents" => "-"
+
+'currentevents' => 'Aktuality',
+'currentevents-url' => 'Aktuality',
+
+# NOTE: To turn off "Disclaimers" in the title links,
+# set "disclaimers" => "-"
+
+'disclaimers' => 'Vylúčenie zodpovednosti',
+'disclaimerpage' => "Project:Vylúčenie zodpovednosti",
+'errorpagetitle' => "Chyba",
+'returnto' => "Späť na $1.",
+'tagline' => "Z {{GRAMMAR:genitív|{{SITENAME}}}}",
+'whatlinkshere' => 'Odkazy na tento článok',
+'help' => 'Pomoc',
+'search' => 'Hľadaj',
+'go' => 'Choď',
+"history" => 'História článku',
+'history_short' => 'História',
+'info_short' => 'Informácie',
+'printableversion' => 'Verzia na tlač',
+'edit' => 'Uprav',
+'editthispage' => 'Upravuj túto stránku',
+'delete' => 'Vymaž',
+'deletethispage' => 'Vymaž tento článok',
+'undelete_short1' => 'Obnov jednu úpravu',
+'undelete_short' => 'Obnov $1 úprav',
+'protect' => 'Zamkni',
+'protectthispage' => 'Zamkni tento článok',
+'unprotect' => 'Odomkni',
+'unprotectthispage' => 'Odomkni tento článok',
+'newpage' => 'Nový článok',
+'talkpage' => 'Diskusia k článku',
+'specialpage' => 'Špeciálna stránka',
+'personaltools' => 'Osobné nástroje',
+'postcomment' => 'Pridaj komentár',
+'addsection' => '+',
+'articlepage' => 'Zobraz článok',
+'subjectpage' => 'Zobraz tému', # For compatibility
+'talk' => 'Diskusia',
+'views' => 'Zobrazení',
+'toolbox' => 'Nástroje',
+'userpage' => 'Zobraz stránku redaktora',
+'wikipediapage' => 'Zobraz stránku projektu',
+'imagepage' => 'Zobraz stránku s obrázkom',
+'viewtalkpage' => 'Zobraz diskusiu k článku',
+'otherlanguages' => 'Iné jazyky',
+'redirectedfrom' => '(Presmerované z $1)',
+'lastmodified' => 'K posledným úpravám tejto stránky došlo $1.',
+'viewcount' => 'Táto stránka bola navštívená $1-krát.',
+'copyright' => 'Obsah je dostupný $1.',
+'poweredby' => "{{SITENAME}} používa [http://www.mediawiki.org/ MediaWiki], open source wiki nástroj.",
+'printsubtitle' => "(Zdroj: {{SERVER}})",
+'protectedpage' => 'Zamknutá stránka',
+'administrators' => "Project:Administrátori",
+'sysoptitle' => 'Je potrebné oprávnenie typu administrátor',
+'sysoptext' => "Požadovanú akciu môžu vykonať iba redaktori s oprávnením administrátor. Pozri $1.",
+'developertitle' => 'Je potrebné oprávnenie typu vývojár',
+'developertext' => "Požadovanú akciu môžu vykonať iba redaktori s oprávnením \"vývojár\".
+Pozri $1.",
+'nbytes' => '$1 bajtov',
+'ok' => 'OK',
+'sitetitle' => "{{SITENAME}}",
+'pagetitle' => "$1 - {{SITENAME}}",
+'sitesubtitle' => 'Slobodná encyklopédia', # FIXME
+'retrievedfrom' => "Zdroj: \"$1\"",
+'newmessages' => "Máte $1.",
+'newmessageslink' => 'nové správy',
+'editsection' => 'upraviť',
+'toc' => 'Obsah',
+'showtoc' => 'zobraz',
+'hidetoc' => 'schovaj',
+'thisisdeleted' => "Zobraziť alebo obnoviť $1?",
+'restorelink' => "$1 zmazaných úprav",
+'feedlinks' => 'Kanál:',
+'sitenotice' => '-', # the equivalent to wgSiteNotice
+
+# Short words for each namespace, by default used in the 'article' tab in monobook
+'nstab-main' => 'Článok',
+'nstab-user' => 'Stránka redaktora',
+'nstab-media' => 'Médiá',
+'nstab-special' => 'Špeciálne',
+'nstab-wp' => 'Projekt',
+'nstab-image' => 'Súbor',
+'nstab-mediawiki' => 'Správa',
+'nstab-template' => 'Šablóna',
+'nstab-help' => 'Pomoc',
+'nstab-category' => 'Kategória',
+
+# Main script and global functions
+#
+'nosuchaction' => 'Takáto akcia neexistuje',
+'nosuchactiontext' => 'Softvér MediaWiki nepozná akciu,
+ktorú vyžadujete pomocou URL.',
+'nosuchspecialpage' => 'Takáto špeciálna stránka neexistuje',
+'nospecialpagetext' => 'Softvér MediaWiki nepozná takúto špeciálnu stránku,
+zoznam špeciálnych stránok nájdete na [[{{ns:special}}:Specialpages]].',
+
+# General errors
+#
+'error' => 'Chyba',
+'databaseerror' => 'Chyba v databáze',
+'dberrortext' => "Nastala syntaktická chyba v príkaze na prehľadávanie databázy.
+Posledný pokus o prehľadávanie bol:
+<blockquote><tt>$1</tt></blockquote>
+z funkcie \"<tt>$2</tt>\".
+MySQL vrátil chybu \"<tt>$3: $4</tt>\".",
+'dberrortextcl' => "Nastala syntaktická chyba v príkaze na prehľadávanie databázy.
+Posledný pokus o prehľadávanie bol:
+\"$1\"
+z funkcie \"$2\".
+MySQL vrátil chybu \"$3: $4\".\n",
+'noconnect' => 'Prepáčte! Wiki má technické problémy a nemôže kontaktovať databázový server. <br />
+$1',
+'nodb' => "Neviem vybrať databázu $1",
+'cachederror' => 'Nasledujúca stránka je odložená kópia vyžiadanej stránky a nemusí byť aktuálna.',
+'laggedslavemode' => 'Varovanie: Je možné, že stránka neobsahuje posledné aktualizácie.',
+'readonly' => 'Databáza je zamknutá',
+'enterlockreason' => 'Zadajte dôvod požadovaného zamknutia vrátane odhadu,
+kedy očakávate odomknutie',
+'readonlytext' => "Databáza je momentálne zamknutá,
+nové články a úpravy sú zablokované, pravdepodobne z dôvodu údržby databázy.
+Po skončení tejto údržby bude {{SITENAME}} opäť fungovať normálne.
+Administrátor, ktorý nariadil uzamknutie, uvádza tento dôvod: $1",
+'missingarticle' => "Databáza nenašla text článku, ktorý by mala nájsť,
+konkrétne \"$1\".
+
+Toto je obyčajne zapríčinené odkazovaním na staršie verzie alebo odkazom na článok, ktorý bol zmazaný.
+
+Ak toto neplatí, pravdepodobne ste našli chybu s softvéri.
+Prosím ohláste túto chybu administrátorovi, uveďte aj meno článku - odkaz (URL).",
+#'readonly_lag' => "The database has been automatically locked while the slave database servers catch up to the master",
+'internalerror' => 'Vnútorná chyba',
+'filecopyerror' => "Neviem skopírovať súbor \"$1\" na \"$2\".",
+'filerenameerror' => "Neviem premenovať súbor \"$1\" na \"$2\".",
+'filedeleteerror' => "Neviem vymazať súbor \"$1\".",
+'filenotfound' => "Neviem nájsť súbor \"$1\".",
+'unexpected' => "Nečakaná hodnota: \"$1\"=\"$2\".",
+'formerror' => 'Chyba: neviem spracovať formulár',
+'badarticleerror' => 'Na tejto stránke túto akciu nemožno vykonať.',
+'cannotdelete' => 'Neviem zmazať danú stránku alebo súbor. (Možno už bol zmazaný niekým iným.)',
+'badtitle' => 'Neplatný nadpis',
+'badtitletext' => "Požadovaný nadpis bol neplatný, nezadaný,
+alebo nesprávne odkazovaný z inej jazykovej verzie {{GRAMMAR:genitív|{{SITENAME}}}}.",
+'perfdisabled' => 'Prepáčte! Táto funkcia bola dočasne vypnutá,
+pretože tak spomaľuje databázu, že nikto nemôže používať
+wiki.',
+'perfdisabledsub' => "Tu je uložená kópia z $1:", # obsolete?
+'perfcached' => '<strong>Nasledujúce dáta sú z dočasnej pamäte a nemusia byť úplne aktuálne:</strong>',
+'wrong_wfQuery_params' => "Nesprávny parameter v wfQuery()<br />
+Funkcia: $1<br />
+Dotaz: $2",
+'viewsource' => 'Zobraz zdroj',
+'protectedtext' => "Táto stránka bola zamknutá na zabránenie úprav; pravdepodobne existuje
+veľa dôvodov prečo je to tak, prosíme pozrite
+[[Project:Zamknutá stránka]].
+
+Môžete si pozrieť a skopírovať zdroj tejto stránky:",
+'sqlhidden' => '(SQL príkaz na prehľadávanie je skrytý)',
+
+# Login and logout pages
+#
+'logouttitle' => 'Odhlásiť redaktora',
+'logouttext' => "Práve ste sa odhlásili.
+Odteraz môžete používať {{GRAMMAR:akuzatív|{{SITENAME}}}} ako anonymný redaktor alebo sa môžete
+opäť prihlásiť pod rovnakým alebo odlišným redaktorským menom. Uvedomte si, že niektoré stránky sa môžu
+naďalej zobrazovať ako keby ste boli prihlásený, až kým nevymažete
+vyrovnávaciu pamäť vášho prehliadača.\n",
+
+'welcomecreation' => "== Vitajte, $1! ==
+Vaše konto je vytvorené. Nezabudnite si nastaviť vaše redaktorské nastavenia.",
+
+'loginpagetitle' => 'Prihlásenie redaktora',
+'yourname' => 'Vaše redaktorské meno',
+'yourpassword' => 'Vaše heslo',
+'yourpasswordagain' => 'Zopakujte heslo',
+'newusersonly' => ' (iba noví redaktori)',
+'remembermypassword' => 'Pamätať si heslo aj po vypnutí počítača.',
+'loginproblem' => "'''Nastal problém pri vašom prihlasovaní.'''<br />Skúste to znova!",
+'alreadyloggedin' => "'''Užívateľ $1, vy už ste prihlásený!'''<br />\n",
+
+'login' => 'Prihlásenie',
+'loginprompt' => "Na prihlásenie do {{GRAMMAR:genitív|{{SITENAME}}}} musíte mať zapnuté koláčiky (cookies).",
+'userlogin' => 'Vytvorte si konto alebo sa prihláste',
+'logout' => 'Odhlásenie',
+'userlogout' => 'Odhlásenie',
+'notloggedin' => 'Neprihlásený/á',
+'createaccount' => 'Zriadiť nové konto',
+'createaccountmail' => 'e-mailom',
+'badretype' => 'Zadané heslá nie sú rovnaké.',
+'userexists' => 'Zadané redaktorské meno už používa niekto iný. Zadajte iné meno.',
+'youremail' => 'Váš e-mail²',
+'yourrealname' => 'Vaše skutočné meno¹',
+'yourlanguage' => 'Jazyk',
+'yourvariant' => 'Variant',
+'yournick' => 'Vaša prezývka',
+'email' => 'e-mail',
+'emailforlost' => "Polia označené horným indexom sú nepovinné. Uvedenie e-mailovej adresy umožňuje
+ľuďom vás kontaktovať cez rozhranie prehliadača bez toho, aby ste týmto ľuďom museli prezradiť vašu
+e-mailovú adresu. Navyše možno e-mailovú adresu použiť na zaslanie nového hesla, ak ho náhodou zabudnete.
+<br /><br />
+Vaše skutočné meno, ak sa rozhodnete ho uverejniť, bude priradené k vašej práci.",
+'prefs-help-email-enotif' => 'Táto adresa sa používa aj na posielanie e-mailových upozornení, ak ste túto možnosť povolili.',
+'prefs-help-realname' => '¹ Skutočné meno (nepovinné): ak sa rozhodnete ho poskytnúť, bude použité na označenie Vašej práce.',
+'loginerror' => 'Chyba pri prihlasovaní',
+'prefs-help-email' => '² E-mail (nepovinné): Uloženie e-mailovej adresy umožní iným ľuďom kontaktovať Vás priamo pomocou web stránky, bez uverejňovania Vašej e-mailovej adresy a môže byť použité na poslanie nového hesla, ak zabudnete pôvodné.',
+'nocookiesnew' => "Redaktorské konto bolo vytvorené, ale nie ste prihlásený. {{SITENAME}} používa koláčiky (cookies) na prihlásenie. Vy máte koláčiky (cookies) vypnuté. Zapnite ich a potom sa prihláste s vaším novým redaktorským menom a heslom.",
+'nocookieslogin' => "{{SITENAME}} používa koláčiky (cookies) na prihlásenie. Vy máte koláčiky (cookies) vypnuté. Zapnite ich a skúste znovu.",
+'noname' => 'Nezadali ste platné redaktorské meno.',
+'loginsuccesstitle' => 'Prihlásenie úspešné',
+'loginsuccess' => "Teraz ste prihlásený do {{GRAMMAR:genitív|{{SITENAME}}}} ako \"$1\".",
+'nosuchuser' => "Redaktorské meno \"$1\" neexistuje. Skontrolujte preklepy alebo sa prihláste ako nový redaktor pomocou dolu uvedeného formulára.",
+'nosuchusershort' => "V súčasnosti neexistuje redaktor s menom \"$1\". Skontrolujte preklepy.",
+'wrongpassword' => 'Zadané heslo je nesprávne. Skúste to znovu.',
+'mailmypassword' => 'Pošlite mi e-mailom dočasné heslo',
+'noemail' => "Redaktor \"$1\" nezadal e-mailovú adresu.",
+'passwordsent' => "Nové heslo bolo zaslané na e-mailovú adresu
+redaktora \"$1\".
+Prihláste sa znovu po jeho obdržaní.",
+#'eauthentsent' => "A confirmation email has been sent to the nominated email address.
+#Before any other mail is sent to the account, you will have to follow the instructions in the email,
+#to confirm that the account is actually yours.",
+'loginend' => '&nbsp;',
+'mailerror' => "Chyba pri posielaní e-mailu: $1",
+'acct_creation_throttle_hit' => 'Prepáčte, už máte vytvorených $1 kont. Nemôžete ich vytvoriť viac.',
+'emailauthenticated' => 'Vaša e-mailová adresa bola overená na $1.',
+'emailnotauthenticated' => 'Vaša e-mailová adresa <strong>ešte nebola overená</strong> a pokročilé funkcie e-mailu sú "deaktivované až do overenia"<strong>(d.a.d.o)</strong>.',
+'noemailprefs' => '<strong>Nezadali ste žiadnu e-mailovú adresu</strong>, nasledujúce
+nástroje nebudú prístupné.',
+'emailconfirmlink' => 'Potvrďte vašu e-mailovú adresu',
+'invalidemailaddress' => 'E-mailovú adresu nemožno akceptovať, pretože sa zdá, že má neplatný formát. Zadajte dobre naformátovanú adresu alebo nechajte príslušné políčko prázdne.',
+
+# Edit page toolbar
+'bold_sample' => 'Tučný text',
+'bold_tip' => 'Tučný text',
+'italic_sample' => 'Kurzíva',
+'italic_tip' => 'Kurzíva',
+'link_sample' => 'Názov odkazu',
+'link_tip' => 'Interný odkaz',
+'extlink_sample' => 'http://www.príklad.sk názov odkazu',
+'extlink_tip' => 'Externý odkaz (nezabudnite prefix http://)',
+'headline_sample' => 'Nadpis',
+'headline_tip' => 'Nadpis 2. úrovne',
+'math_sample' => 'Sem vložte vzorec',
+'math_tip' => 'Matematický vzorec (LaTeX)',
+'nowiki_sample' => 'Sem vložte neformátovaný text',
+'nowiki_tip' => 'Ignoruj wiki formátovanie',
+'image_sample' => 'Príklad.jpg',
+'image_tip' => 'Vložený obrázok',
+'media_sample' => 'Príklad.ogg',
+'media_tip' => 'Odkaz na media súbor',
+'sig_tip' => 'Váš podpis s dátumom a časom',
+'hr_tip' => 'Horizontálna čiara (používajte zriedka)',
+'infobox' => 'Na získanie textu príkladu kliknite na tlačidlo',
+'infobox_alert' => "Prosím zadajte text, ktorý chcete, aby bol naformátovaný.\n Zobrazí sa ako text príkladu na kopírovanie a vkladanie.\nPríklad:\n$1\nsa stane:\n$2",
+
+# Edit pages
+#
+'summary' => 'Zhrnutie úprav',
+'subject' => 'Téma/nadpis',
+'minoredit' => 'Toto je drobná úprava.',
+'watchthis' => 'Sleduj úpravy tohto článku',
+'savearticle' => 'Ulož článok',
+'preview' => 'Náhľad',
+'showpreview' => 'Zobraz náhľad',
+'showdiff' => 'Zobraz rozdiely',
+'blockedtitle' => 'Redaktor je zablokovaný',
+'blockedtext' => "Vaše redaktorské meno alebo IP adresu zablokoval $1.
+Udáva tento dôvod:<br />''$2''
+
+Môžete sa skontaktovať s $1 alebo s iným [[Project:Administrátori|administrátorom]] a prediskutovať blokovanie.\",
+
+Uvedomte si, že nemôžete použiť funkciu \"Pošli e-mail redaktorovi\", ak nemáte zaregistrovanú platnú e-mailovú adresu vo vašich [[Špeciálne:Nastavenia|nastaveniach]].
+
+Vaša IP adresa je $3. Prosíme zahrňte túto adresu do každého vášho príkazu na prehľadávanie.
+",
+'whitelistedittitle' => 'Na úpravu je nutné prihlásenie',
+'whitelistedittext' => 'Na úpravu článkov musíte byť [[Special:Userlogin|prihlásený/á]].',
+'whitelistreadtitle' => 'Na čítanie článkov je nutné prihlásenie',
+'whitelistreadtext' => 'Na čítanie článkov musíte byť [[Special:Userlogin|prihlásený/á]]',
+'whitelistacctitle' => 'Nemáte dovolené vytvorenie konta',
+'whitelistacctext' => 'Na umožnenie vytvorenia účtu na tejto Wiki musíte byť [[Special:Userlogin|prihlásený/á]] a mať primerané práva.',
+'loginreqtitle' => 'Nutné prihlásenie',
+'loginreqtext' => 'Na prezeranie ďalších článkov sa musíte [[Special:Userlogin|prihlásiť]].',
+'accmailtitle' => 'Heslo odoslané.',
+'accmailtext' => "Heslo pre '$1' bolo poslané $2.",
+'newarticle' => '(Nový)',
+'newarticletext' =>
+"<div style=\"border: 1px solid #ccc; padding: 7px;\">'''{{SITENAME}} ešte neobsahuje článok s názvom {{PAGENAME}}.'''
+* Na vytvorenie nového článku začnite písať do dolného okna a potom kliknite \"Ulož článok\". Vaše zmeny budú ihneď viditeľné.
+* Prosíme Vás, aby ste nevytvárali článok na prezentáciu samého seba, web stránky, produktu alebo podniku (pozri [[Project:Zásady a pravidlá]]).
+* Ak ste vo {{GRAMMAR:lokál|{{SITENAME}}}} nový/á, prečítajte si pred tvorbou [[Project:Váš prvý článok|vášho prvého článku]] [[Project:Príručka|Príručku]] alebo použite na experimenty [[Project:Pieskovisko|pieskovisko]].
+</div>",
+'talkpagetext' => '<!-- MediaWiki:talkpagetext -->',
+'anontalkpagetext' => "---- ''Toto je diskusná stránka anonymného redaktora, ktorý nemá vytvorené svoje konto alebo ho nepoužíva. Preto musíme na jeho identifikáciu použiť numerickú [[IP adresa|IP adresu]]. Je možné, že takúto IP adresu používajú viacerí redaktori. Ak ste anonymný redaktor a máte pocit, že vám boli adresované irelevantné diskusné príspevky, zriaďte si vlastný účet alebo sa prihláste ([[Special:Userlogin|Zriadenie konta alebo prihlásenie]]), aby sa zamedzilo budúcim zámenám s inými anonymnými redaktormi''",
+'noarticletext' => '(Tento článok momentálne neobsahuje žiaden text)',
+'clearyourcache' => "'''Poznámka:''' Aby sa zmeny prejavili, po uložení musíte vymazať vyrovnávaciu pamäť vášho prehliadača: '''Mozilla:''' ''Ctrl-Shift-R'', '''IE:''' ''Ctrl-F5'', '''Safari:''' ''Cmd-Shift-R'', '''Konqueror:''' ''F5''.",
+'usercssjsyoucanpreview' => "<strong>Tip:</strong> Použite tlačidlo 'Zobraz náhľad', aby sa otestovalo Vaše nové CSS/JS pred uložením.",
+'usercsspreview' => "'''Nezabudnite, že toto je iba náhľad Vášho užívateľského CSS, ešte nebolo uložené!'''",
+'userjspreview' => "'''Nezabudnite, že iba testujete/náhľad vášho užívateľského JavaScriptu, ešte nebol uložený!'''",
+'updated' => '(Aktualizované)',
+'note' => '<strong>Poznámka: </strong> ',
+'previewnote' => 'Nezabudnite, toto je len náhľad vami upravovaného článku. Článok ešte nie je uložený!',
+'previewconflict' => 'Tento náhľad upraveného článku zobrazuje
+text z horného okna na úpravy tak, ako sa zobrazí potom, keď ho uložíte.',
+'editing' => "Úprava stránky $1",
+'editingsection' => "Úprava stránky $1 (sekcia)",
+'editingcomment' => "Úprava stránky $1 (diskusia)",
+'editconflict' => 'Konflikt pri úprave: $1',
+'explainconflict' => "Niekto iný zmenil túto stránku, medzi tým čo ste ju upravovali vy.
+Horné okno na úpravy obsahuje text stránky tak, ako je momentálne platný.
+Vaše úpravy sú uvedené v dolnom okne na úpravy.
+Budete musieť zlúčiť vaše zmeny s existujúcim textom.
+'''Iba''' obsah horného okna sa uloží, keď stlačíte \"Ulož článok\".",
+'yourtext' => 'Váš text',
+'storedversion' => 'Uložená verzia',
+'nonunicodebrowser' => "<strong>UPOZORNENIE: Váš prehliadač nepodporuje unicode, prosím pred úpravou článku použite iný.</strong>",
+'editingold' => "<strong>POZOR: Upravujete starú
+verziu tejto stránky.
+Ak vašu úpravu uložíte, prepíšete tým všetky úpravy, ktoré nasledovali po tejto starej verzii.</strong>",
+'yourdiff' => 'Rozdiely',
+'copyrightwarning' => "<div id=\"specChar\" style=\"margin-top:5px;border-width:1px;border-style:solid;border-color:#aaaaaa;padding:3px;text-align:center;\">
+<small>[[metawikipedia:Help:Special_characters|Zvláštne znaky]]
+</small></div>
+
+Nezabudnite, že všetky príspevky do {{GRAMMAR:genitív|{{SITENAME}}}}
+sa považujú za príspevky uskutočnené podľa GNU Free Documentation License
+(podrobnosti pozri pod $1).
+Ak nechcete, aby bolo to, čo ste napísali, neúprosne upravované a ďalej
+ľubovoľne rozširované, tak sem váš text neumiestňujte.<br />
+Týmto nám tiež sľubujete, že ste tento text buď napísali sám, alebo že je skopírovaný
+zo spoločného vlastníctva (public domain) alebo podobného voľne prístupného zdroja.
+<strong>NEUMIESTŇUJTE TU BEZ POVOLENIA DIELA CHRÁNENÉ AUTORSKÝM PRÁVOM!</strong>",
+'copyrightwarning2' => "Prosím uvedomte si, že všetky príspevky do {{GRAMMAR:genitív|{{SITENAME}}}}
+môžu byť upravované, skracované alebo odstránené inými príspevkami.
+Ak nechcete, aby Vaše texty boli menené, tak ich tu neuverejňujte.<br />
+Týmto nám tiež sľubujete, že ste tento text buď napísali sám, alebo že je skopírovaný
+zo spoločného vlastníctva (public domain) alebo podobného voľne prístupného zdroja.
+<strong>NEUMIESTŇUJTE TU BEZ POVOLENIA DIELA CHRÁNENÉ AUTORSKÝM PRÁVOM!</strong>",
+'longpagewarning' => "<strong>POZOR: Táto stránka má $1 kilobajtov; niektoré
+prehliadače by mohli mať problémy s úpravou stránok, ktorých veľkosť sa blíži k alebo presahuje 32kb.
+Zvážte, či by nebolo možné rozdeliť stránku na menšie sekcie.</strong>",
+'readonlywarning' => '<strong>POZOR: Databáza bola počas upravovania stránky zamknutá z dôvodu údržby,
+takže stránku momentálne nemôžete uložiť. Môžete skopírovať a vložiť
+text do textového súboru a uložiť si ho na neskôr.</strong>',
+'protectedpagewarning' => "<strong>POZOR: Táto stránka bola zamknutá, takže ju môžu upravovať iba redaktori s oprávnením administrátor. Uistite sa, že rozumiete [[Project:Pravidlá zamykania stránok|pravidlám zamykania stránok]].</strong>",
+'templatesused' => 'Šablóny použité v tomto článku:',
+
+# History pages
+#
+'revhistory' => 'Predchádzajúce verzie',
+'nohistory' => 'Pre tento článok neexistuje história.',
+'revnotfound' => 'Predchádzajúca verzia nebola nájdená',
+'revnotfoundtext' => "Požadovaná staršia verzia článku nebola nájdená.
+Prosím skontrolujte URL adresu, ktorú ste použili na prístup k tejto stránke.\n",
+'loadhist' => 'Otváram históriu stránky',
+'currentrev' => 'Aktuálna verzia',
+'revisionasof' => 'Verzia zo dňa a času $1',
+'revisionasofwithlink' => 'Verzia zo dňa $1; $2<br />$3 | $4',
+'previousrevision' => '← Staršia verzia',
+'nextrevision' => 'Novšia verzia →',
+'currentrevisionlink' => 'Zobrazenie aktuálnej úpravy',
+'cur' => 'aktuálna',
+'next' => 'ďalšia',
+'last' => 'posledná',
+'orig' => 'pôvodná',
+'histlegend' => 'Legenda: (aktuálna) = rozdiel oproti aktuálnej verzii,
+(posledná) = rozdiel oproti predchádzajúcej verzii, D = drobná úprava',
+'history_copyright' => '-',
+'deletedrev' => '[zmazané]',
+
+# Diffs
+#
+'difference' => '(Rozdiel medzi verziami)',
+'loadingrev' => 'Sťahujem verzie na zobrazenie rozdielov',
+'lineno' => "Riadok $1:",
+'editcurrent' => 'Upraviť aktuálnu verziu tejto stránky',
+'selectnewerversionfordiff' => 'Vybrať na porovnanie novšiu verziu',
+'selectolderversionfordiff' => 'Vybrať na porovnanie staršiu verziu',
+'compareselectedversions' => 'Porovnaj označené verzie',
+
+# Search results
+#
+'searchresults' => 'Výsledky vyhľadávania',
+'searchresulttext' => "Viac informácií o vyhľadávaní vo {{GRAMMAR:lokál|{{SITENAME}}}} je uvedených na $1.",
+'searchquery' => "Na vyhľadávací dotaz \"$1\"",
+'badquery' => 'Nesprávne formulovaný text na prehľadávanie',
+'badquerytext' => 'Váš text na prehľadávanie sme nemohli spracovať.
+Dôvodom je pravdepodobne to, že ste hľadali slovo
+kratšie ako tri písmená, čo zatiaľ {{SITENAME}} neumožňuje.
+Alebo ste možno výraz zle napísali, napríklad "dom a a záhrada". Skúste iný text na prehľadávanie.',
+'matchtotals' => 'Výsledkom textu na prehľadávanie "$1" je $2 nadpisov článkov a text $3 článkov.',
+'nogomatch' => "Neexistuje článok s presne takýmto nadpisom; skúšam nájsť podobné nadpisy.
+
+<br /><br />Chcete '''<a href=\"$1\" class=\"new\">vytvoriť nový článok s týmto nadpisom</a>'''? Alebo [[Project:Žiadané články|dať žiadosť na jeho tvorbu]]?.",
+'titlematches' => 'Vyhovujúce nadpisy článkov',
+'notitlematches' => 'Niet vyhovujúcich nadpisov článkov',
+'textmatches' => 'Vyhovujúce texty článkov',
+'notextmatches' => 'Niet vyhovujúcich textov článkov',
+'prevn' => "predchádzajúca $1",
+'nextn' => "ďalšia $1",
+'viewprevnext' => "Zobraz ($1) ($2) ($3).",
+'showingresults' => "Nižšie je zobrazených '''$1''' výsledkov, počnúc od #'''$2'''.",
+'showingresultsnum' => "Nižšie je zobrazených '''$3''' výsledkov, počnúc od #'''$2'''.",
+'nonefound' => "<strong>Poznámka</strong>: bezvýsledné vyhľadávania sú
+často spôsobené buď snahou hľadať príliš bežné, obyčajné slová (napríklad mať),
+pretože tieto sa neregistrujú, alebo uvedením viac ako jedného vyhľadávaného výrazu,
+pretože výsledky uvádzajú len stránky obsahujúce všetky vyhľadávané výrazy.",
+'powersearch' => 'Vyhľadávanie',
+'powersearchtext' => "Vyhľadávania v menných priestoroch :<br />
+$1<br />
+$2 Zoznam presmerovaní &nbsp; Hľadanie pre $3 $9",
+'searchdisabled' => 'Prepáčte! Fulltextové vyhľadávanie bolo dočasne vypnuté z dôvodu preťaženia. Zatiaľ môžete použiť hľadanie pomocou Google, ktoré však nemusí byť aktuálne.',
+'blanknamespace' => '(Hlavný)',
+
+# Preferences page
+#
+'preferences' => 'Nastavenia',
+'prefsnologin' => 'Nie ste prihlásený/á',
+'prefsnologintext' => "Musíte byť [[Special:Userlogin|prihlásený/á]],
+aby ste mohli zmeniť vaše nastavenia.",
+'prefslogintext' => "Ste prihlásený ako \"[[Redaktor:$1|$1]]\" ([[Komentár k redaktorovi:$1|Diskusia]], [[Špeciálne:Contributions/$1|príspevky]]). Vaše interné číslo ID je $2.
+
+Pozri [[m:Help:Preferences|Nastavenia]] na vysvetlenie volieb.",
+'prefsreset' => 'Boli obnovené pôvodné nastavenia.',
+'qbsettings' => 'Nastavenia pre bočné menu',
+'changepassword' => 'Zmeniť heslo',
+'skin' => 'Vzhľad',
+'math' => 'Matematika',
+'dateformat' => 'Formát dátumu',
+'math_failure' => 'Syntaktická analýza (parsing) neúspešná',
+'math_unknown_error' => 'neznáma chyba',
+'math_unknown_function' => 'neznáma funkcia ',
+'math_lexing_error' => 'lexingová chyba',
+'math_syntax_error' => 'syntaktická chyba',
+'math_image_error' => 'PNG konverzia neúspešná; skontrolujte správnosť inštalácie programov: latex, dvips, gs a convert',
+'math_bad_tmpdir' => 'Nemôžem zapisovať alebo vytvoriť dočasný matematický adresár',
+'math_bad_output' => 'Nemôžem zapisovať alebo vytvoriť výstupný matematický adresár',
+'math_notexvc' => 'Chýbajúci texvc program; prosím pozrite math/README na konfiguráciu.',
+'prefs-personal' => 'Redaktorské nastavenia',
+'prefs-rc' => 'Zobrazenie posledných úprav a nedokončených článkov',
+'prefs-misc' => 'Rôzne nastavenia',
+'saveprefs' => 'Ulož nastavenia',
+'resetprefs' => 'Obnoviť pôvodné nastavenia',
+'oldpassword' => 'Staré heslo',
+'newpassword' => 'Nové heslo',
+'retypenew' => 'Nové heslo (ešte raz)',
+'textboxsize' => 'Veľkosť okna na úpravy',
+'rows' => 'Riadky',
+'columns' => 'Stĺpce',
+'searchresultshead' => 'Nastavenia výsledkov vyhľadávania',
+'resultsperpage' => 'Počet vyhovujúcich výsledkov zobrazených na strane',
+'contextlines' => 'Počet zobrazených riadkov z kažnej nájdenej stránky',
+'contextchars' => 'Počet kontextových znakov v riadku',
+'stubthreshold' => 'Hranica pre zobrazenie nedokončených článkov',
+'recentchangescount' => 'Počet nadpisov uvedených v posledných úpravách',
+'savedprefs' => 'Vaše nastavenia boli uložené.',
+'timezonelegend' => 'Časové pásmo',
+'timezonetext' => 'Zadajte počet hodín, o ktorý sa váš miestny čas odlišuje
+od času na serveri (UTC).',
+'localtime' => 'Miestny čas',
+'timezoneoffset' => 'Rozdiel¹',
+'servertime' => 'Aktuálny čas na serveri',
+'guesstimezone' => 'Prevziať z prehliadača',
+'emailflag' => 'Zakázať prijímanie e-mailov od druhých redaktorov',
+'defaultns' => 'Štandardne vyhľadávaj v týchto menných priestoroch:',
+'default' => 'štandardne',
+'files' => 'Súbory',
+
+# User levels special page
+#
+
+# switching pan
+'groups-lookup-group' => 'Spravuj práva skupiny',
+'groups-group-edit' => 'Existujúce skupiny: ',
+'editgroup' => 'Uprav skupinu',
+'addgroup' => 'Pridaj skupinu',
+
+'userrights-lookup-user' => 'Spravuj skupiny redaktorov',
+'userrights-user-editname' => 'Napíš meno redaktora: ',
+'editusergroup' => 'Uprav redaktorské skupiny',
+
+# group editing
+'groups-editgroup' => 'Uprav skupinu',
+'groups-addgroup' => 'Pridaj skupinu',
+'groups-editgroup-preamble' => 'Ak opis začína čiarkou, zvyšok sa bude považovať za
+názov systémovej správy a text bude lokalizovateľný pomocou menného priestoru MediaWiki',
+'groups-editgroup-name' => 'Meno skupiny: ',
+'groups-editgroup-description' => 'Opis skupiny (max. 255 znakov):<br />',
+'savegroup' => 'Ulož skupinu',
+'groups-tableheader' => 'ID || Meno || Opis || Práva',
+'groups-existing' => 'Existujúce skupiny',
+'groups-noname' => 'Zvoľte platné meno skupiny',
+'groups-already-exists' => 'Skupina s týmto názvom už existuje',
+'addgrouplogentry' => 'Skupina $2 pridaná',
+'changegrouplogentry' => 'Skupina $2 zmenená',
+'renamegrouplogentry' => 'Skupina $2 premenovaná na $3',
+
+# user groups editing
+#
+'userrights-editusergroup' => 'Uprav skupinu',
+'saveusergroups' => 'Ulož skupinu',
+'userrights-groupsmember' => 'Člen skupiny:',
+'userrights-groupsavailable' => 'Dostupné skupiny:',
+'userrights-groupshelp' => 'Označte skupiny, do ktorých chcete pridať alebo z ktorých chcete
+odobrať redaktora. Neoznačené skupiny nebudú zmenené. Odobrať skupinu možete pomocou CTRL + kliknutie ľavým tlačidlom',
+'userrights-logcomment' => 'Zmenená príslušnosť zo skupiny $1 na skupinu $2',
+
+# Default group names and descriptions
+#
+'group-anon-name' => 'Anonym',
+'group-anon-desc' => 'Anonymný redaktor',
+'group-loggedin-name' => 'Redaktor',
+'group-loggedin-desc' => 'Bežní prihlásení redaktori',
+'group-admin-name' => 'Administrátor',
+'group-admin-desc' => 'Dôveryhodní redaktori, ktorí môžu blokovať redaktorov a mazať články',
+'group-bureaucrat-name' => 'Byrokrat',
+'group-bureaucrat-desc' => 'Skupina byrokratov vytvára sysopov',
+'group-steward-name' => 'Steward',
+'group-steward-desc' => 'Plný prístup',
+
+# Recent changes
+#
+'changes' => 'úpravy',
+'recentchanges' => 'Posledné úpravy',
+'recentchanges-url' => 'Special:Recentchanges',
+'recentchangestext' => 'Pomocou tejto stránky sledujete posledné úpravy vykonané vo {{GRAMMAR:lokál|{{SITENAME}}}}.
+[[Project:Vitajte vo {{GRAMMAR:lokál|{{SITENAME}}}}|]]!
+Pozrite si nasledujúce články: [[Project:FAQ|{{SITENAME}} FAQ]],
+[[Project:Zásady a pravidlá|Zásady a pravidlá]]
+(špeciálne [[Project:Konvencie pre názvoslovie|konvencie pre názvoslovie]],
+[[Project:Neutrálny uhol pohľadu|neutrálny uhol pohľadu]]),
+a [[Project:Bežné chyby|bežné chyby]].
+
+Ak chcete, aby {{SITENAME}} uspela, je veľmi dôležité, aby ste nepridávali
+materiál obmedzený inými [[Project:Autorské právo|autorskými právami]].
+Právne záväzky môžu projekt vážne poškodiť, takže Vás prosíme, aby ste to nerobili.
+Pozrite aj [http://meta.wikipedia.org/wiki/Special:Recentchanges recent meta discussion].',
+'rcloaderr' => 'Nahrávam posledné úpravy',
+'rcnote' => "Tu je posledných <strong>$1</strong> úprav počas posledných <strong>$2</strong> dní.",
+'rcnotefrom' => "Tu sú posledné zmeny od '''$2''' (zobrazených '''$1''' záznamov).",
+'rclistfrom' => "Zobraz nové úpravy počnúc od $1",
+'showhideminor' => "$1 drobné úpravy | $2 robotov | $3 prihlásených redaktorov ",
+'rclinks' => "Zobraz posledných $1 úprav v posledných $2 dňoch<br />$3",
+'rchide' => "vo forme $4; $1 drobné úpravy; $2 druhotné menné priestory; $3 viacnásobné úpravy.",
+'rcliu' => "; $1 úprav od prihlásených redaktorov",
+'diff' => 'rozdiel',
+'hist' => 'história',
+'hide' => 'skryť',
+'show' => 'zobraz',
+'tableform' => 'tabuľka',
+'listform' => 'zoznam',
+'nchanges' => "$1 úprav",
+'minoreditletter' => 'D',
+'newpageletter' => 'N',
+'sectionlink' => '→',
+'number_of_watching_users_RCview' => '[$1]',
+'number_of_watching_users_pageview' => '[sledujúcich redaktorov: $1]',
+
+# Upload
+#
+'upload' => 'Nahranie súboru',
+'uploadbtn' => 'Nahrať súbor',
+'uploadlink' => 'Nahranie súborov',
+'reupload' => 'Zopakovať nahranie',
+'reuploaddesc' => 'Späť k formuláru na nahranie.',
+'uploadnologin' => 'Nie ste prihlásený',
+'uploadnologintext' => "Musíte byť [[Special:Userlogin|prihlásený]],
+aby ste mohli nahrávať súbory.",
+'upload_directory_read_only' => 'Nie je možné zapisovať webovým servrom do adresára pre nahrávanie ($1).',
+'uploaderror' => 'Chyba pri nahrávaní',
+'uploadtext' =>
+"<strong>STOP!</strong> Skôr ako sem začnete nahrávať,
+ubezpečte sa, že ste si prečítali, a že dodržujete [[Project:Zásady používania obrázkov|Zásady používania obrázkov]].
+
+Na zobrazenie alebo vyhľadávanie už nahraných obrázkov,
+choďte na [[Special:Imagelist|zoznam nahraných obrázkov]].
+Nahrania a zmazania sú zaznamenané na [[Project:Záznam nahrávaní|zázname nahrávaní]].
+
+Použite dole uvedený formulár na nahranie nových obrázkov,
+ktoré budú slúžiť ako ilustrácie do vášho článku.
+Na väčšine prehliadačov uvidíte tlačidlo \"Prehľadať...\", ktoré
+spôsobí zobrazenie štandardného dialógu vášho operačného systému
+Otvoriť súbor. Výberom súboru sa automaticky
+vyplní meno súboru v textovom rámčeku vedľa tlačidla.
+
+Musíte tiež zaškrtnutím potvrdiť, že nahraním súboru
+neporušujete žiadne autorské práva.
+Stlačením tlačidla \"Nahrať\" potom ukončíte nahranie.
+Ak máte pomalé internetové pripojenie, môže to trvať istý čas.
+
+Uprednostňované formáty sú JPEG pre fotografické obrázky , PNG
+pre kresby a iné symboly a OGG pre zvuky.
+Prosíme Vás, aby ste svojim súborom dali opisný názov, aby sa zamedzilo zámenám.
+Na začlenenie obrázku v článku použite odkaz v tvare '''<nowiki>[[{{ns:image}}:súbor.jpg]]</nowiki>'''
+alebo '''<nowiki>[[{{ns:image}}:súbor.png|alt text]]</nowiki>'''
+alebo ''<nowiki>'[[{{ns:media}}:súbor.ogg]]</nowiki>''' pre zvuky.
+
+Nezabudnite, že tak ako pri stránkach {{GRAMMAR:genitív|{{SITENAME}}}}, môžu iní upravovať alebo zmazať vaše nahrané súbory, ak si myslia, že to je prospešné encyklopédii, a
+nahrávanie vám môže byť znemožnené (zablokované), ak budete zneužívať systém.",
+
+'uploadlog' => 'Záznam nahrávaní',
+'uploadlogpage' => 'Záznam nahrávaní',
+'uploadlogpagetext' => 'Nižšie je zoznam nedávno nahraných súborov.
+Všetky uvedené časy sú časy na servri (UTC).
+<ul>
+</ul>',
+'filename' => 'Názov súboru',
+'filedesc' => 'Opis súboru',
+'filestatus' => 'Stav autorských práv',
+'filesource' => 'Zdroj',
+'copyrightpage' => "Project:Autorské práva",
+'copyrightpagename' => "{{SITENAME}} copyright",
+'uploadedfiles' => 'Nahrané súbory',
+'ignorewarning' => 'Ignorovať varovanie a súbor napriek tomu uložiť.',
+'minlength' => 'Názvy obrázkov musia obsahovať najmenej tri písmená.',
+'illegalfilename' => 'Názov súboru "$1" obsahuje znaky, ktoré nie sú povolené v názvoch článkov. Prosím premenujte súbor a skúste ho nahrať znovu.',
+'badfilename' => 'Meno obrázka bolo zmenené na "$1".',
+'badfiletype' => "\".$1\" nie je odporúčaný formát obrázkového súboru.",
+'largefile' => 'Odporúčame, aby obrázky neprekročili veľkosť $1 bajtov, veľkosť tohto súboru je $2 bajtov',
+'emptyfile' => 'Súbor, ktorý ste nahrali sa zdá byť prázdny. Toto mohlo vzniknúť preklepom v názve súboru. Skontrolujte, či skutočne chcete nahrať tento súbor.',
+'fileexists' => 'Súbor s týmto názvom už existuje. Skontrolujte $1, ak si nie ste istý, či ho chcete zmeniť.',
+'successfulupload' => 'Nahranie bolo úspešné',
+'fileuploaded' => "Súbor \"$1\" bol úspešne nahraný.
+Nasledujte tento odkaz ($2) na stránku, na ktorej zadáte
+informácie na opis súboru, napríklad odkiaľ pochádza, kedy a kým bol
+vytvorený a všetko ostatné, čo o ňom prípadne viete.
+Ak je nahraný súbor obrázok, možno ho takto vložiť do článku: <tt><nowiki>[[Obrázok:$1|thumb|Opis]]</nowiki></tt>",
+'uploadwarning' => 'Varovanie pre nahrávanie',
+'savefile' => 'Ulož súbor',
+'uploadedimage' => "nahraný \"$1\"",
+'uploaddisabled' => 'Prepáčte, nahrávanie je vypnuté.',
+'uploadscripted' => 'Tento súbor obsahuje kód HTML alebo skript, ktorý može byť chybne interpretovaný prehliadačom.',
+'uploadcorrupt' => 'Tento súbor je závadný alebo má nesprávnu príponu. Skontrolujte súbor a nahrajte ho znova.',
+'uploadvirus' => 'Súbor obsahuje virus! Detaily: $1',
+'sourcefilename' => 'Názov zdrojového súboru',
+'destfilename' => 'Názov cieľového súboru',
+
+# Image list
+#
+'imagelist' => 'Zoznam nahraných obrázkov',
+'imagelisttext' => "Tu je zoznam $1 obrázkov zoradený $2.",
+'getimagelist' => 'Sťahujem zoznam nahraných obrázkov',
+'ilsubmit' => 'Vyhľadávanie',
+'showlast' => "Zobraz posledných $1 obrázkov zoradených $2.",
+'byname' => 'podľa mena',
+'bydate' => 'podľa dátumu',
+'bysize' => 'podľa veľkosti',
+'imgdelete' => 'zmazať',
+'imgdesc' => 'popis',
+'imglegend' => 'Vysvetlivky: (popis) = zobraz/uprav popis obrázku.',
+'imghistory' => 'História súboru',
+'revertimg' => 'obnov',
+'deleteimg' => 'zmazať',
+'deleteimgcompletely' => 'Vymaž všetky verzie',
+'imghistlegend' => "Vysvetlivky: (aktuálna) = toto je aktuálny obrázok, (zmazať) = zmaž
+túto starú verziu, (pôvodná) = vráť sa k tejto starej verzii.
+<br />''Kliknite na dátum, aby sa zobrazil obrázok nahraný v ten deň''.",
+'imagelinks' => 'Odkazy na obrázok',
+'linkstoimage' => 'Na tento obrázok odkazujú nasledujúce články:',
+'nolinkstoimage' => 'Žiadne články neobsahujú odkazy na tento obrázok.',
+'sharedupload' => "Tento súbor je [[:commons:Main_Page|zdieľaný zdroj]] a môže byť použitý v iných wiki.
+
+<br clear=both>
+{| align=center border=0 cellpadding=3 cellspacing=3 style=\"border: solid #aaa 1px; background: #f9f9f9; font-size: 100%;\"
+|-
+| [[Image:Commons without text.png|20px|Wikimedia Commons Logo]]
+|Toto je súbor z [[Commons:Main Page|Wikimedia Commons]]. Prosíme pozrite si jeho '''[[Commons:Image:{{PAGENAME}}|popisnú stránku ]]''' <!--on the Commons-->.
+|}",
+'shareduploadwiki' => "Ďalšie informácie pozrite na [stránka opisu súboru $1].",
+'noimage' => 'Súbor s takým menom neexistuje, môžete ho [$1 nahrať]',
+'uploadnewversion' => '[$1 Nahrajte novú verziu tohto súboru.]',
+
+# Statistics
+#
+'statistics' => 'Štatistiky',
+'sitestats' => 'Štatistika webu',
+'userstats' => 'Štatistika k redaktorom',
+'sitestatstext' => "V databáze je celkovo '''$1''' článkov.
+Vrátane \"diskusných\" stránok, článkov o {{GRAMMAR:lokál|{{SITENAME}}}}, extrémne krátkych článkov,
+presmerovaní a iných, ktoré asi nemožno považovať za články.
+Okrem uvedených, existuje '''$2''' článkov, ktoré možno považovať za právoplatné články.
+
+Celkovo boli stránky navštívené '''$3'''-krát a upravené '''$4'''-krát,
+od posledného vylepšenia (upgrade) softvéru (20. júla 2002).
+To znamená, že pripadá priemerne '''$5''' úprav na každý článok a '''$6''' návštev na každú úpravu.",
+'userstatstext' => "Celkovo je '''$1''' zaregistrovaných redaktorov,
+z čoho '''$2''' (alebo '''$4%''') sú administrátormi (pozri $3).",
+
+# Maintenance Page
+#
+'maintenance' => 'Stránka údržby',
+'maintnancepagetext' => 'Táto stránka obsahuje niekoľko praktických funkcií na každodennú údržbu {{GRAMMAR:genitív|{{SITENAME}}}}. Niektoré z týchto funkcií môžu predstavovať veľkú záťaž pre databázu, preto podľa možnosti nerobte reload po každej zmene ;-)',
+'maintenancebacklink' => 'Späť na Stránku údržby',
+'disambiguations' => 'Stránky na rozlíšenie viacerých významov',
+'disambiguationspage' => "Project:Odkazy na stránky na rozlíšenie viacerých významov",
+'disambiguationstext' => "Tieto články obsahujú odkazy na ''rozlišovaciu stránku''. Namiesto toho by mali obsahovať odkazy na stránku s príslušnou témou. <br />Stránka sa považuje za rozlišovaciu stránku, ak $1 na ňu obsahuje odkaz.<br />Odkazy z iných menných priestorov tu ''nie'' sú uvedené.",
+'doubleredirects' => 'Dvojité presmerovanie',
+'doubleredirectstext' => "Každý riadok obsahuje odkaz na prvé a druhé presmerovanie, ako aj prvý riadok z textu, na ktorý odkazuje druhé presmerovanie, ktoré zvyčajne odkazuje na \"skutočný\" cieľ, na ktorý má odkazovať prvé presmerovanie.",
+'brokenredirects' => 'Pokazené presmerovania',
+'brokenredirectstext' => 'Tieto presmerovania odkazujú na neexistujúci článok.',
+'selflinks' => 'Články s odkazmi na seba',
+'selflinkstext' => 'Tieto články obsahujú odkazy na seba, čo by nemali.',
+'mispeelings' => 'Stránky s nesprávnym pravopisom',
+'mispeelingstext' => "Tieto stránky obsahujú bežné pravopisné chyby, ktoré sú uvedené na $1. Slová uvedené v zátvorkách ukazujú správny pravopis.",
+'mispeelingspage' => 'Zoznam bežných pravopisných chýb',
+'missinglanguagelinks' => 'Chýbajúce jazykové odkazy',
+'missinglanguagelinksbutton' => 'Nájdi chýbajúce jazykové odkazy pre',
+'missinglanguagelinkstext' => "Tieto články ''neobsahujú'' odkazy k ich náprotivku v $1. Presmerovania a podstránky ''nie'' sú zobrazené.",
+
+
+# Miscellaneous special pages
+#
+'orphans' => 'Opustené články',
+'geo' => 'GEO súradnice',
+'validate' => 'Schváliť článok',
+'lonelypages' => 'Opustené články',
+'uncategorizedpages' => 'Nekategorizované články',
+'uncategorizedcategories' => 'Nekategorizované kategórie',
+'unusedimages' => 'Nevyužité súbory',
+'popularpages' => 'Populárne články',
+'nviews' => '$1 návštev',
+'wantedpages' => 'Žiadané články',
+'nlinks' => 'počet odkazov: $1',
+'allpages' => 'Všetky stránky',
+'randompage' => 'Náhodný článok',
+'randompage-url'=> 'Special:Randompage',
+'shortpages' => 'Krátke články',
+'longpages' => 'Dlhé články',
+'deadendpages' => 'Slepé stránky',
+'listusers' => 'Zoznam redaktorov',
+'specialpages' => 'Špeciálne stránky',
+'spheading' => 'Špeciálne stránky pre všetkých redaktorov',
+'restrictedpheading' => 'Obmedzené špeciálne stránky',
+'protectpage' => 'Zamknúť stránku',
+'recentchangeslinked' => 'Súvisiace úpravy',
+'rclsub' => "(na články, na ktoré odkazuje \"$1\")",
+'debug' => 'Ladenie',
+'newpages' => 'Nové články',
+'ancientpages' => 'Najdávnejšie upravované články',
+'intl' => 'Medzijazykové odkazy',
+'move' => 'Presuň',
+'movethispage' => 'Presuň túto stránku',
+'unusedimagestext' => 'Uvedomte si, že niektoré web stránky, môžu odkazovať na tento obrázok
+priamo cez URL adresu, preto tu môže byť stále uvedený, napriek tomu, že
+ho aktívne používajú.',
+'booksources' => 'Knižné zdroje',
+'categoriespagetext' => 'Nasledujúce kategórie existujú vo wiki.',
+'data' => 'Dáta',
+'userrights' => 'Spravovanie redaktorských práv',
+'groups' => 'Skupiny redaktorov',
+
+# FIXME: Other sites, of course, may have affiliate relations with the booksellers list
+'booksourcetext' => "Nižšie je uvedený zoznam odkazov k iným web stránkam, ktoré
+predávajú nové alebo použité knihy a prípadne majú ďalšie informácie
+o knihách, ktoré hľadáte.
+{{SITENAME}} nie je so žiadnym z týchto predajcov v obchodnom spojení a
+tento zoznam nemožno chápať ako ich podporu.",
+'isbn' => 'ISBN',
+'rfcurl' => 'http://www.faqs.org/rfcs/rfc$1.html',
+'pubmedurl' => 'http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?cmd=Retrieve&db=pubmed&dopt=Abstract&list_uids=$1',
+'alphaindexline' => "$1 do $2",
+'version' => 'Zobraz verziu MediaWiki',
+'log' => 'Záznamy',
+'alllogstext' => 'Kombinované zobrazenie nahrávaní, mazaní, zamknutí, blokovaní a akcií sysopa.
+Môžete zmenšiť rozsah, ak zvolíte typ záznamu, meno redaktora alebo dotyčnú stránku.',
+
+# Special:Allpages
+'nextpage' => 'Ďalšia stránka ($1)',
+'allpagesfrom' => 'Zobraz články od článku:',
+'allarticles' => 'Všetky články',
+'allnonarticles' => 'Všetky ne-články',
+'allinnamespace' => 'Všetky stránky (menný priestor $1)',
+'allnotinnamespace' => 'Všetky stránky (nie z menného priestoru $1)',
+'allpagesprev' => 'Predchádzajúci',
+'allpagesnext' => 'Ďalší',
+'allpagessubmit' => 'Choď',
+
+# E this user
+#
+'mailnologin' => 'Žiadna adresa na zaslanie',
+'mailnologintext' => "Musíte byť [[Special:Userlogin|prihlásený]]
+a mať platnú e-mailovú adresu vo vašich [[Special:Preferences|nastaveniach]],
+aby ste mohli iným redaktorom posielať e-maily.",
+'emailuser' => 'Pošli e-mail tomuto redaktorovi',
+'emailpage' => 'E-mail redaktorovi',
+'emailpagetext' => 'Ak tento redaktor zadal platnú e-mailovú adresu vo svojich nastaveniach,
+môžete mu pomocou dole uvedeného formulára poslať e-mail.
+E-mailová adresa, ktorú ste zadali vo vašich nastaveniach sa zobrazí
+ako adresa odosielateľa e-mailu, aby bol príjemca schopný vám
+odpovedať.',
+'usermailererror' => 'Mail objekt vrátil chybu: ',
+'defemailsubject' => "{{SITENAME}} e-mail",
+'noemailtitle' => 'Chýba e-mailová adresa',
+'noemailtext' => 'Tento redaktor nezadal platnú e-mailovú adresu,
+alebo sa rozhodol, že nebude prijímať e-maily od druhých redaktorov.',
+'emailfrom' => 'Odosielateľ',
+'emailto' => 'Príjemca',
+'emailsubject' => 'Vec',
+'emailmessage' => 'Správa',
+'emailsend' => 'Odoslať',
+'emailsent' => 'E-mail bol odoslaný',
+'emailsenttext' => 'Vaša e-mailová správa bola odoslaná.',
+
+# Watchlist
+#
+'watchlist' => 'Sledované články',
+'watchlistsub' => "(pre redaktora \"$1\")",
+'nowatchlist' => 'V sledovaných článkoch nemáte žiadne položky.',
+'watchnologin' => 'Nie ste prihlásený/á',
+'watchnologintext' => "Musíte byť [[Special:Userlogin|prihlásený/á]],
+aby ste mohli modifikovať vaše sledované články.",
+'addedwatch' => 'Pridaný do sledovaných článkov',
+'addedwatchtext' => "Stránka [[$1]] bola pridaná do [[Špeciálne:Watchlist|sledovaných článkov]].
+Budú tam uvedené ďalšie úpravy tejto stránky a jej diskusie
+a stránka bude zobrazená '''tučne''' v [[Špeciálne:Recentchanges|zozname posledných úprav]], aby ste ju ľahšie našli.
+
+Ak budete chcieť neskôr stránku odstrániť zo sledovaných stránok, kliknite na \"nesleduj\" v horných záložkách.",
+'removedwatch' => 'Odstránený zo sledovaných článkov',
+'removedwatchtext' => "Článok \"$1\" bol odstránený z vašich sledovaných článkov.",
+'watch' => 'Sleduj',
+'watchthispage' => 'Sleduj tento článok',
+'unwatch' => 'Nesleduj',
+'unwatchthispage' => 'Nesleduj tento článok',
+'notanarticle' => 'Toto nie je článok',
+'watchnochange' => 'V rámci zobrazeného času nebola upravená žiadna z vašich sledovaných stránok.',
+'watchdetails' => "* $1 sledovaných stránok, nepočítajúc stránky diskusie, $2 úprav stránok spolu za sledované obdobie;
+* Typ dotazu: $3
+* [[Special:Watchlist/edit|zobraz a upravuj úplný zoznam.",
+'wlheader-enotif' => "* Upozorňovanie e-mailom je zapnuté.",
+'wlheader-showupdated' => "* Články, ktoré boli zmené od vašej poslednej návštevy sú zobrazené '''tučne'''.",
+'watchmethod-recent'=> 'kontrolujem posledné úpravy sledovaných článkov',
+'watchmethod-list' => 'kontrolujem sledované články na posledné úpravy',
+'removechecked' => 'Odstráň vybrané položky zo sledovaných článkov',
+'watchlistcontains' => "Vaše sledované články obsahujú $1 článkov.",
+'watcheditlist' => "Tu je abecedný zoznam vašich
+sledovaných článkov. Označte články, ktoré chcete odstrániť
+a kliknite na tlačidlo 'Odstráň vybrané'
+na spodnej časti obrazovky.",
+'removingchecked' => 'Odstraňujem požadované položky zo sledovaných článkov ...',
+'couldntremove' => "Nemôžem odstrániť položku '$1'...",
+'iteminvalidname' => "Problém s položkou '$1', neplatné meno...",
+'wlnote' => "Nižšie je posledných $1 zmien za posledných '''$2''' hodín.",
+'wlshowlast' => 'Zobraz posledných $1 hodín $2 dní $3',
+'wlsaved' => 'Toto je uložená verzia vašich sledovaných článkov.',
+'wlhideshowown' => '$1 moje úpravy.',
+'wlshow' => 'Zobraz',
+'wlhide' => 'Skry',
+
+'enotif_mailer' => 'Upozorňovač {{GRAMMAR:genitív|{{SITENAME}}}}',
+'enotif_reset' => 'Vynulovať upozornenia (nastav ich status na "navštívené")',
+'enotif_newpagetext'=> 'Toto je nový článok.',
+'changed' => 'zmene',
+'created' => 'vytvorení',
+'enotif_subject' => '{{SITENAME}} - stránka $PAGETITLE bola $CHANGEDORCREATED $PAGEEDITOR',
+'enotif_lastvisited' => 'Pozrite $1 pre všetky zmeny od vašej poslednej návštevy.',
+'enotif_body' => 'Drahý $WATCHINGUSERNAME,
+
+na {{GRAMMAR:lokál|{{SITENAME}}}} došlo $PAGEEDITDATE k $CHANGEDORCREATED stránky $PAGETITLE redaktorom $PAGEEDITOR, pozrite si aktuálnu verziu $PAGETITLE_URL .
+
+$NEWPAGE
+
+Zhrnutie: $PAGESUMMARY $PAGEMINOREDIT
+Kontaktujte redaktora:
+mail $PAGEEDITOR_EMAIL
+wiki $PAGEEDITOR_WIKI
+
+Nedostanete ďalšie upozornenia, aj ak bude článok znovu upravovaný, kým nenavštivíte tento článok. Možete tiež vynulovať upozornenia pre všetky vaše sledované stránky.
+
+ Váš upozorňovací systém {{GRAMMAR:genitív|{{SITENAME}}}}
+
+--
+Pre zmenu nastavenia vašich sledovaných článkov navštívte
+{{SERVER}}{{localurl:Special:Watchlist/edit}}
+
+Návrhy a ďalšia pomoc:
+{{SERVER}}{{localurl:Pomoc:Obsah}}',
+
+# Delete/protect/revert
+#
+'deletepage' => 'Zmazať stránku',
+'confirm' => 'Potvrdiť',
+'excontent' => "obsah bol: '$1'",
+'excontentauthor' => "obsah bol: '$1' (a jediný autor bol '$2')",
+'exbeforeblank' => "obsah pred vyčistením stránky bol: '$1'",
+'exblank' => 'stránka bola prázdna',
+'confirmdelete' => 'Potvrdiť zmazanie',
+'deletesub' => "(Mažem \"$1\")",
+'historywarning' => 'POZOR: Stránka, ktorú chcete zmazať má históriu: ',
+'confirmdeletetext' => "Idete trvalo zmazať z databázy stránku alebo obrázok
+spolu so všetkými jeho/jej predchádzajúcimi verziami.
+Potvrďte, že máte v úmysle tak urobiť, že ste si vedomý
+následkov, a že to robíte
+v súlade so [[Project:Zásady a pravidlá]].",
+'actioncomplete' => 'Akcia ukončená',
+'deletedtext' => "\"$1\" bol zmazaný.
+Na $2 nájdete zoznam posledných zmazaní.",
+'deletedarticle' => "\"[[$1]]\" zmazaný",
+'dellogpage' => 'Záznam zmazaní',
+'dellogpagetext' => 'Tu je zoznam posledných zmazaní.',
+'deletionlog' => 'záznam zmazaní',
+'reverted' => 'Vrátené na skoršiu verziu',
+'deletecomment' => 'Dôvod na zmazanie',
+'imagereverted' => 'Vrátenie skoršej verzie bolo úspešné.',
+'rollback' => 'Rollback úprav',
+'rollback_short' => 'Rollback',
+'rollbacklink' => 'rollback',
+'rollbackfailed' => 'Rollback neúspešný',
+'cantrollback' => 'Nemôžem úpravu vrátiť späť, posledný autor je jediný autor tohto článku.',
+'alreadyrolled' => "Nemôžem vrátiť späť poslednú úpravu [[$1]]
+od [[Redaktor:$2|$2]] ([[Diskusia_s_redaktorom:$2|Diskusia]]); niekto iný buď upravoval stránku, alebo už vrátil späť.
+
+Autorom poslednej úpravy je [[Redaktor:$3|$3]] ([[Diskusia_s_redaktorom:$3|Diskusia]]).",
+'editcomment' => "Komentár k úprave bol: \"''$1''\".",
+'revertpage' => "Bola obnovená posledná úprava $2 od $1.",
+'sessionfailure' => 'Zdá sa, že je problém s vašou prihlasovacou reláciou;
+táto akcia bola zrušená ako prevencia proti zneužitiu relácie (session).
+Prosím, stlačte "naspäť", obnovte stránku, z ktorej ste sa sem dostali, a skúste to znova.',
+'protectlogpage' => 'Záznam_zamknutí',
+'protectlogtext' => "Nižšie je zoznam zamknutí/odomknutí stránok.
+Pre dodatočné informácie pozrite [[Project:Zamknutá stránka]].",
+'protectedarticle' => "zamyká \"[[$1]]\"",
+'unprotectedarticle' => "odomyká \"[[$1]]\"",
+'protectsub' =>"(Zamykám \"$1\")",
+'confirmprotecttext' => 'Skutočne chcete zamknúť túto stránku?',
+'confirmprotect' => 'Potvrďte zamknutie',
+'protectmoveonly' => 'Zamkni iba presuny stránky',
+'protectcomment' => 'Dôvod zamknutia',
+'unprotectsub' =>"(Odomykám \"$1\")",
+'confirmunprotecttext' => 'Skutočne chcete odomknúť túto stránku?',
+'confirmunprotect' => 'Potvrďte odomknutie',
+'unprotectcomment' => 'Dôvod odomknutia',
+
+# Undelete
+'undelete' => 'Obnov zmazaný článok',
+'undeletepage' => 'Zobraz a obnov zmazané články',
+'undeletepagetext' => 'Tieto články boli zmazané, ale sú stále v archíve a
+môžu byť obnovené. Archív môže byť pravidelne vyprázdnený.',
+'undeletearticle' => 'Obnov zmazaný článok',
+'undeleterevisions' => "$1 verzií je archivovaných",
+'undeletehistory' => 'Ak obnovíte tento článok, obnovia sa aj všetky predchádzajúce verzie do zoznamu predchádzajúcich verzií.
+Ak bol od zmazania vytvorený nový článok s tým istým menom, zobrazia sa
+obnovené verzie ako posledné úpravy nového článku a aktuálna verzia nového článku
+nebude automaticky nahradená.',
+'undeleterevision' => "Zmazaná verzia zo dňa a času $1",
+'undeletebtn' => 'Obnov!',
+'undeletedarticle' => "obnovený \"[[$1]]\"",
+'undeletedrevisions' => "$1 verzií obnovených",
+'undeletedtext' => "Článok [[$1]] bol úspešne obnovený.
+Pozri [[Special:Log/delete]] - zoznam posledných zmazaní a obnovení.",
+
+# Namespace form on various pages
+'namespace' => 'Menný priestor:',
+'invert' => 'Invertovať výber',
+
+# Contributions
+#
+'contributions' => 'Príspevky redaktora',
+'mycontris' => 'Moje príspevky',
+'contribsub' => "Pre $1",
+'nocontribs' => 'Neboli nájdené úpravy, ktoré by zodpovedali týmto kritériám.',
+'ucnote' => "Nižšie je posledných '''$1''' úprav od tohto redaktora uskutočnených počas posledných '''$2''' dní.",
+'uclinks' => "Zobraz posledných $1 úprav; zobraz posledných $2 dní.",
+'uctop' => ' (posledná úprava)' ,
+'newbies' => 'začiatočníci',
+
+# What links here
+#
+'whatlinkshere' => 'Odkazy na tento článok',
+'notargettitle' => 'Nebol zadaný cieľ',
+'notargettext' => 'Nezadali ste cieľový článok alebo redaktora,
+na ktorý/-ého chcete aplikovať túto funkciu.',
+'linklistsub' => '(Zoznam odkazov)',
+'linkshere' => 'Sem odkazujú nasledujúce články::',
+'nolinkshere' => 'Sem neodkazujú žiadne články.',
+'isredirect' => 'presmerovacia stránka',
+
+# Block/unblock IP
+#
+'blockip' => 'Zablokovať redaktora',
+'blockiptext' => "Použite dolu uvedený formulár na zablokovanie možnosti zápisov uskutočnených
+z IP adresy alebo od redaktora.
+Mali by ste to urobiť len na zabránenie vandalizmu a
+v súlade s [[Project:Zásady a pravidlá]].
+Nižšie uveďte konkrétny dôvod (napríklad uveďte konkrétne stránky,
+ktoré sa stali obeťou vandalizmu).",
+'ipaddress' => 'IP adresa',
+'ipadressorusername' => 'IP adresa/meno redaktora',
+'ipbexpiry' => 'Ukončenie',
+'ipbreason' => 'Dôvod',
+'ipbsubmit' => 'Zablokovať tohto redaktora',
+'badipaddress' => 'IP adresa má nesprávny formát',
+'blockipsuccesssub' => 'Zablokovanie bolo úspešné',
+'blockipsuccesstext' => "\"$1\" bol/a zablokovaný/á.
+<br /> [[Špeciálne:Ipblocklist|IP block list]] obsahuje zoznam blokovaní.",
+'unblockip' => 'Odblokovať redaktora',
+'unblockiptext' => 'Použite nižšie uvedený formulár na obnovenie možnosti zápisov
+z doteraz zablokovanej IP adresy alebo od redaktora.',
+'ipusubmit' => 'Odblokovať túto adresu',
+'ipusuccess' => "\"[[$1]]\" odblokovaný/á",
+'ipblocklist' => 'Zablokovaní/é redaktori/IP adresy',
+'blocklistline' => "$1, $2 zablokoval $3 ($4)",
+'infiniteblock' => 'ukončenie infinite', //fixme
+'expiringblock' => 'ukončenie $1',
+'blocklink' => 'zablokovať',
+'unblocklink' => 'odblokuj',
+'contribslink' => 'príspevky',
+'autoblocker' => "Ste zablokovaný, pretože zdieľate IP adresu s \"$1\". Dôvod \"$2\".",
+'blocklogpage' => 'Záznam_blokovaní',
+'blocklogentry' => 'zablokovaný "[[$1]]" s časom ukončenia $2',
+'blocklogtext' => 'Toto je zoznam blokovaní a odblokovaní redaktorov. Automaticky
+blokované IP adresy nie sú zahrnuté. Pozri zoznam
+[[Špeciálne:Ipblocklist|IP block]] aktuálnych zákazov a blokovaní.',
+'unblocklogentry' => 'odblokovaný/á "$1"',
+'range_block_disabled' => 'Schopnosť sysopa vytvárať bloky rozpätí je deaktivovaná.',
+'ipb_expiry_invalid' => 'Neplatný čas ukončenia.',
+'ip_range_invalid' => "Neplatné rozpätie IP.\n",
+'proxyblocker' => 'Blokovač proxy',
+'proxyblockreason' => 'Vaša IP adresa bola zablokovaná, pretože je otvorená proxy. Prosím kontaktujte vášho internetového poskytovateľa alebo technickú podporu a informujte ich o tomto vážnom bezpečnostnom probléme.',
+'proxyblocksuccess' => "Hotovo.\n",
+'sorbs' => 'SORBS DNSBL',
+'sorbsreason' => 'Vaša IP adresa je vedená ako nezabezpečený proxy server v [http://www.sorbs.net SORBS] DNSBL.',
+
+# Developer tools
+#
+'lockdb' => 'Zamknúť databázu',
+'unlockdb' => 'Odomknúť databázu',
+'lockdbtext' => 'Zamknutím databázy sa preruší možnosť všetkých
+redaktorov upravovať stránky, meniť svoje nastavenia, upravovať sledované stránky a
+iné veci vyžadujúce zmeny v databáze.
+Potvrďte, že to naozaj chcete urobiť, a že
+odomknete databázu po ukončení údržby.',
+'unlockdbtext' => 'Odomknutie databázy obnoví možnosť všetkých
+redaktorov upravovať články, meniť svoje nastavenia, upravovať svoje sledovaných články a
+iné veci vyžadujúce zmeny v databáze.
+Potvrďte, že to naozaj chcete urobiť.',
+'lockconfirm' => 'Áno, naozaj chcem zamknúť databázu.',
+'unlockconfirm' => 'Áno, naozaj chcem odomknúť databázu.',
+'lockbtn' => 'Zamknúť databázu',
+'unlockbtn' => 'Odomknúť databázu',
+'locknoconfirm' => 'Neoznačili ste potvrdzovacie pole.',
+'lockdbsuccesssub' => 'Zamknutie databázy úspešné',
+'unlockdbsuccesssub' => 'Databáza bola úspešne odomknutá',
+'lockdbsuccesstext' => 'Databáza bola zamknutá.
+<br />Nezabudnite po dokončení údržby odstrániť zámok.',
+'unlockdbsuccesstext' => 'Databáza bola odomknutá.',
+
+# Make sysop
+'makesysoptitle' => 'Urob z redaktora administrátora',
+'makesysoptext' => 'Tento formulár používajú byrokrati na zmenu redaktorov na administrátorov.
+Do poľa napíšte meno redaktora a potvrďte zmenu redaktora na administrátora',
+'makesysopname' => 'Meno redaktora:',
+'makesysopsubmit' => 'Urob z tohto redaktora administrátora',
+'makesysopok' => "'''Redaktor \"$1\" je teraz administrátorom (sysop)'''",
+'makesysopfail' => "'''Redaktor \"$1\" nemôže byť administrátorom. (Zadali ste meno správne?)'''",
+'setbureaucratflag' => 'Nastav byrokratický príznak',
+'setstewardflag' => 'Nastav príznak stewarda',
+'bureaucratlog' => 'Záznam byrokratov',
+'rightslogtext' => 'Toto je záznam zmien redaktorových práv.',
+'bureaucratlogentry' => "Zmené členstvo v skupine pre $1 z $2 na $3",
+'rights' => 'Práva:',
+'set_user_rights' => 'Nastav redaktorove práva',
+'user_rights_set' => "'''Práva pre redaktora \"$1\" zmenené'''",
+'set_rights_fail' => "'''Redaktorove práva pre \"$1\" nemohli byť nastavené. (zadali ste meno správne?)'''",
+'makesysop' => 'Urob z redaktora administrátora (sysop)',
+'already_sysop' => 'Tento redaktor už je administrátor',
+'already_bureaucrat' => 'Tento redaktor už je byrokrat',
+'already_steward' => 'Tento redaktor už je steward',
+
+# Validation
+#
+'val_yes' => 'áno',
+'val_no' => 'nie',
+'val_of' => '$1 of $2',
+'val_revision' => 'verzie',
+'val_time' => 'čas',
+'val_user_stats_title' => 'Prehľad overení redaktora $1',
+'val_my_stats_title' => 'Môj prehľad overení',
+'val_list_header' => '<th>#</th><th>Téma</th><th>Rozsah</th><th>Akcia</th>',
+'val_add' => 'Pridaj',
+'val_del' => 'Vymaž',
+'val_show_my_ratings' => 'Ukáž moje overenia',
+'val_revision_number' => 'Verzie #$1',
+'val_warning' => "'''Už ''nikdy'' tu nič nemeň bez ''explicitného'' konsenzu komunity!'''",
+'val_rev_for' => 'verzie pre ',
+'val_details_th_user' => 'Redaktor $1',
+'val_validation_of' => 'Overenie "$1"',
+'val_revision_of' => 'Verzie $1',
+'val_revision_changes_ok' => 'Vaše hodnotenie bolo zaznamenané!',
+'val_revision_stats_link' => '(<a href="$1">detaily</a>)',
+'val_iamsure' => 'Zaškrtnite políčko, ak to myslíte vážne!',
+'val_clear_old' => 'Vymaž moje staršie záznamy overení',
+'val_merge_old' => 'Použi moje predchádzajúce hodnotenia tam, kde je zvolené \'Nemám názor\'',
+'val_form_note' => "'''Tip:''' Zlúčiť vaše údaje znamená, že pre verziu
+článku, ktorý zvolíte, všetky možnosti, kde ste označili ''nemám názor'',
+budú nastavené na hodnotu a komentár najčerstvejšej verzie, pre ktorú
+ste vyjadrili názor. Napríklad, ak chcete zmeniť jedinú nezávislú možnosť
+pre novšiu verziu, ale tiež ponechať vaše ostatné nastavenia pre tento článok
+v tejto verzii, zvoľte iba, ktorú možnosť máte v úmysle ''zmeniť'',
+a zlúčením sa doplnia ostatné možnosti z vašich predchádzajúcich nastavení",
+'val_noop' => 'Nemám názor',
+'val_percent' => "'''$1%'''<br />($2 z $3 bodov<br />od $4 redaktorov)",
+'val_percent_single' => "'''$1%'''<br />($2 z $3 bodov<br />od jedného redaktora)",
+'val_total' => 'Celkovo',
+'val_version' => 'Verzie',
+'val_tab' => 'Overenie',
+'val_this_is_current_version' => 'toto je aktuálna verzia',
+'val_version_of' => "Verzie $1" ,
+'val_table_header' => "<tr><th>Trieda</th>$1<th colspan=4>Názor</th>$1<th>Poznámka</th></tr>\n",
+'val_stat_link_text' => 'Štatistiky overení pre tento článok',
+'val_view_version' => 'Zobraz túto verziu',
+'val_validate_version' => 'Over túto verziu',
+'val_user_validations' => 'Tento redaktor overil $1 článkov.',
+'val_no_anon_validation' => 'Musíte byť prihlásený, ak chcete overovať články.',
+'val_validate_article_namespace_only' => "Overovať možno iba články. Táto stránka ''nie je'' v mennom priestore pre články.",
+'val_validated' => 'Overené.',
+'val_article_lists' => 'Zoznam overených článkov',
+'val_page_validation_statistics' => 'Štatistika overení pre stránku $1',
+
+# Move page
+#
+'movepage' => 'Presunúť článok',
+'movepagetext' => "Pomocou tohto formulára premenujete článok a premiestnite všetky
+jeho predchádzajúce verzie pod zadané nové meno.
+Starý názov sa stane presmerovacím článkom na nový názov.
+Odkazy na starý článok sa však nezmenia, ubezpečte sa, že ste skontrolovali
+výskyt dvojitých alebo pokazených presmerovaní.
+Vy ste zodpovedný za to, aby odkazy naďalej ukazovali
+tam, kam majú.
+
+Uvedomte si, že článok sa nepremiestni, ak pod novým názvom
+už článok existuje. Toto neplatí iba ak je článok prázdny alebo presmerovací a nemá
+žiadne predchádzajúce verzie. To znamená, že môžete premenovať článok späť na meno,
+ktoré mal pred premenovaním, ak ste sa pomýlili, a že nemôžete prepísať
+existujúcí článok.
+
+'''POZOR!'''
+Toto môže byť drastická a nečakaná zmena pre populárny článok;
+ubezpečte sa preto, skôr ako budete pokračovať, že chápete
+dôsledky svojho činu.',
+'movepagetalktext' => 'Príslušná Diskusná stránka (ak vôbec existuje) bude premiestnená spolu so samotným článkom; '''nestane sa tak, iba ak:'''
+*premiestňujete článok do iného menného priestoru,
+*už existuje Diskusná stránka pod týmto novým menom, alebo
+*nezaškrtnete nižšie sa nachádzajúci textový rámček.
+
+V takých prípadoch budete musieť, ak si to želáte, premiestniť alebo zlúčiť článok ručne.",
+'movearticle' => 'Presuň článok',
+'movenologin' => 'Neprihlásený/á',
+'movenologintext' => "Musíte byť registrovaný redaktor a [[Special:Userlogin|prihlásený]] aby ste mohli presunúť článok.",
+'newtitle' => 'Na nový názov',
+'movepagebtn' => 'Presunúť článok',
+'pagemovedsub' => 'Presun bol úspešný',
+'pagemovedtext' => "Článok \"[[$1]]\" bol presunutý na \"[[$2]]\".",
+'articleexists' => 'Stránka s týmto názvom už existuje alebo
+vami zadaný názov je neplatný.
+Prosím vyberte si iný názov.',
+'talkexists' => 'Samotný článok bol úspešne premiestnený,
+ale Diskusná stránka sa nedala premiestniť,
+pretože už jedna existuje pod zadaným novým názvom. Zlúčte ich manuálne.',
+'movedto' => 'presunutý na',
+'movetalk' => 'Premiestniť aj "diskusnú" stránku, ak je to možné.',
+'talkpagemoved' => 'Príslušná diskusná stránka bola tiež premiestnená.',
+'talkpagenotmoved' => 'Príslušná diskusná stránka <strong>nebola</strong> premiestnená.',
+'1movedto2' => "[[$1]] premiestnená na [[$2]]",
+'1movedto2_redir' => '[[$1]] premiestnená na [[$2]] výmenou presmerovania',
+'movelogpage' => 'Záznam presunov',
+'movelogpagetext' => 'Tu je zoznam posledných presunutí.',
+'movereason' => 'Dôvod',
+'revertmove' => 'obnova',
+'delete_and_move' => 'Vymaž a presuň',
+'delete_and_move_text' =>
+'==Potreba zmazať článok==
+
+Cieľový článok "[[$1]]" už existuje. Chcete ho vymazať a vytvoriť tak priestor pre presun?',
+'delete_and_move_reason' => 'Vymaž, aby sa umožnil presun',
+'selfmove' => "Zdrojový a cieľový názov sú rovnaké; nemôžem presunúť článok na seba samého.",
+'immobile_namespace' => "Cieľový názov je špeciálneho typu; nemôžem presunúť článok do tohto menného priestoru.",
+
+# Export
+
+'export' => 'Export stránok',
+'exporttext' => 'Môžete exportovať text a históriu úprav konkrétnej
+stránky alebo množiny stránok do XML; tieto môžu byť potom importované do iného
+wiki používajúceho MediaWiki softvér, zmenené alebo iba ponechané pre
+vaše potešenie. (Súčasná verzia MediaWiki nepodporuje import).
+
+Zadajte názvy článkov, každý názov na nový riadok a zvoľte, či chcete všetky alebo iba poslednú verziu.
+
+Ak chcete iba posledné úpravy, ako napr. [[Special:Export/Tank]] pre článok [[Tank]].
+',
+'exportcuronly' => 'Zahrň iba aktuálnu verziu, nie kompletnú históriu',
+
+# Namespace 8 related
+
+'allmessages' => 'Všetky systémové správy',
+'allmessagesname' => 'Názov',
+'allmessagesdefault' => 'štandardný text',
+'allmessagescurrent' => 'aktuálny text',
+'allmessagestext' => 'Toto je zoznam všetkých správ dostupných v mennom priestore MediaWiki.',
+'allmessagesnotsupportedUI' => "Special:AllMessages na tejto lokalite (site) nepodporuje jazyk pre vaše rozhranie ('''$1'''). ",
+'allmessagesnotsupportedDB' => 'Special:AllMessages nie je podporované, pretože je vypnuté wgUseDatabaseMessages.',
+
+# Thumbnails
+
+'thumbnail-more' => 'Zväčšiť',
+'missingimage' => "'''Chýbajúci obrázok'''<br />''$1''\n",
+'filemissing' => 'Chýbajúci súbor',
+
+# Special:Import
+'import' => 'Import stránok',
+'importtext' => 'Prosím exportujte súbor zo zdrojovej wiki pomocou nástroja Špeciálne:Export, uložte na váš disk a nahrajte tu.',
+'importfailed' => "Chyba pri importe: $1",
+'importnotext' => 'Prázdny alebo žiadny text',
+'importsuccess' => 'Import úspešný!',
+'importhistoryconflict' => 'Existujú konfliktné histórie verzií (možno ste už tento článok importovali)',
+
+# Keyboard access keys for power users
+'accesskey-search' => 'f',
+'accesskey-minoredit' => 'i',
+'accesskey-save' => 's',
+'accesskey-preview' => 'p',
+'accesskey-diff' => 'd',
+'accesskey-compareselectedversions' => 'v',
+
+# tooltip help for some actions, most are in Monobook.js
+'tooltip-search' => 'Hľadaj v tejto wiki. [alt-f]',
+'tooltip-minoredit' => 'Označ toto ako drobnú úpravu. [alt-i]',
+'tooltip-save' => 'Ulož úpravy. [alt-s]',
+'tooltip-preview' => 'Náhľad úprav, prosím použite pred uložením! [alt-p]',
+'tooltip-diff' => 'Ukáž, aké zmeny ste urobili v texte. [alt-d]',
+'tooltip-compareselectedversions' => 'Zobraz rozdiely medzi dvoma vybranými verziami tohto článku. [alt-v]',
+'tooltip-watch' => 'Pridaj túto stránku k sledovaným. [alt-w]',
+
+# stylesheets
+#'Monobook.css' => '/* edit this file to customize the monobook skin for the entire site */',
+#'Monobook.js' => '/* edit this file to change js things in the monobook skin */',
+
+# Metadata
+'nodublincore' => 'Dublin Core RDF metadata sú pre tento server vypnuté.',
+'nocreativecommons' => 'Creative Commons RDF metadata sú pre tento server vypnuté.',
+'notacceptable' => 'Wiki server nedokáže poskytovať dáta vo formáte, v akom ich váš klient vie čítať.',
+
+# Attribution
+
+'anonymous' => "Anonymný redaktor/i {{GRAMMAR:genitív{{SITENAME}}}}",
+'siteuser' => "Redaktor {{GRAMMAR:genitív{{SITENAME}}}} $1",
+'lastmodifiedby' => "Táto stránka bola naposledy upravovaná $1 redaktorom $2.",
+'and' => 'a',
+'othercontribs' => "Založené na práci redaktora $1.",
+'others' => 'iné',
+'siteusers' => "Redaktori {{GRAMMAR:genitív{{SITENAME}}}} $1",
+'creditspage' => 'Ocenenia za stránku', #LEPSI PREKLAD?
+'nocredits' => 'Pre tento článok neexistujú žiadne dostupné ocenenia.', #LEPSI PREKLAD?
+
+# Spam protection
+
+'spamprotectiontitle' => 'Filter na ochranu pred spamom',
+'spamprotectiontext' => 'Článok, ktorý ste chceli uložiť, bol blokovaný filtrom na spam. Pravdepodobne to spôsobil link na externú internetovú lokalitu (site).',
+'spamprotectionmatch' => 'Nasledujúci text aktivoval náš spam filter: $1',
+'subcategorycount' => "V tejto kategórii je $1 podkategórii.",
+'subcategorycount1' => "V tejto kategórii je $1 podkategória.",
+'categoryarticlecount' => "V tejto kategórii je $1 článkov.",
+'categoryarticlecount1' => "V tejto kategórii je $1 článok.",
+'usenewcategorypage' => "1\n\nNastavte prvý znak na \"0\" , aby ste vypli nový layout stránky kategórie.",
+'listingcontinuesabbrev' => " pokrač.",
+
+# Info page
+'infosubtitle' => 'Informácie o stránke',
+'numedits' => 'Počet úprav (článok): $1',
+'numtalkedits' => 'Počet úprav (diskusia k článku): $1',
+'numwatchers' => 'Počet zobrazení: $1',
+'numauthors' => 'Počet odlišných autorov (článok): $1',
+'numtalkauthors' => 'Počet odlišných autorov (diskusia k článku): $1',
+
+# Math options
+'mw_math_png' => 'Vždy vytvor PNG',
+'mw_math_simple' => 'Na jednoduché použi HTML, inak PNG',
+'mw_math_html' => 'Ak sa dá, použi HTML, inak PNG',
+'mw_math_source' => 'Ponechaj TeX (pre textové prehliadače)',
+'mw_math_modern' => 'Odporúčame pre moderné prehliadače',
+'mw_math_mathml' => 'MathML (experimentálne)',
+
+# Patrolling
+'markaspatrolleddiff' => "Označ ako strážené",
+'markaspatrolledlink' => "[$1]",
+'markaspatrolledtext' => "Označ tento článok ako strážený",
+'markedaspatrolled' => "Označené ako strážené",
+'markedaspatrolledtext' => "Vybrané verzie boli označené ako strážené.",
+'rcpatroldisabled' => "Stráženie posledných zmien bolo vypnut",
+'rcpatroldisabledtext' => "Funkcia stráženia posledných zmien je momentálne vypnutá.",
+
+# Monobook.js: tooltips and access keys for monobook
+'Monobook.js' => '/* tooltips and access keys */
+ta = new Object();
+ta[\'pt-userpage\'] = new Array(\'.\',\'Moja redaktorská stránka\');
+ta[\'pt-anonuserpage\'] = new Array(\'.\',\'Stránka redaktora pre ip adresu, ktorú upravujete ako\');
+ta[\'pt-mytalk\'] = new Array(\'n\',\'Moja diskusná stránka\');
+ta[\'pt-anontalk\'] = new Array(\'n\',\'Diskusia o úpravách z tejto ip adresy\');
+ta[\'pt-preferences\'] = new Array(\'\',\'Moje nastavenia\');
+ta[\'pt-watchlist\'] = new Array(\'l\',\'Zoznam článkov, na ktorých sledujete zmeny.\');
+ta[\'pt-mycontris\'] = new Array(\'y\',\'Zoznam mojich príspevkov\');
+ta[\'pt-login\'] = new Array(\'o\',\'Odporúčame Vám prihlásiť sa, nie je to však povinné.\');
+ta[\'pt-anonlogin\'] = new Array(\'o\',\'Odporúčame Vám prihlásiť sa, nie je to však povinné.\');
+ta[\'pt-logout\'] = new Array(\'o\',\'Odhlásenie\');
+ta[\'ca-talk\'] = new Array(\'t\',\'Diskusia o obsahu článku\');
+ta[\'ca-edit\'] = new Array(\'e\',\'Môžete upravovať tento článok. Prosíme, použite tlačidlo náhľad pre uložením.\');
+ta[\'ca-addsection\'] = new Array(\'+\',\'Pridaj komentár k tejto diskusii.\');
+ta[\'ca-viewsource\'] = new Array(\'e\',\'Tento článok je zamknutý. Môžete však vidieť jeho zdrojový text.\');
+ta[\'ca-history\'] = new Array(\'h\',\'Minulé verzie tohto článku.\');
+ta[\'ca-protect\'] = new Array(\'=\',\'Zamkni tento článok\');
+ta[\'ca-delete\'] = new Array(\'d\',\'Vymaž tento článok\');
+ta[\'ca-undelete\'] = new Array(\'d\',\'Obnov úpravy tohto článku až po dobu jeho vymazania\');
+ta[\'ca-move\'] = new Array(\'m\',\'Presuň tento článok\');
+ta[\'ca-watch\'] = new Array(\'w\',\'Pridať tento článok do sledovaných článkov\');
+ta[\'ca-unwatch\'] = new Array(\'w\',\'Odstrániť tento článok zo sledovaných článkov\');
+ta[\'search\'] = new Array(\'f\',\'Prehľadávanie tejto wiki\');
+ta[\'p-logo\'] = new Array(\'\',\'Hlavná stránka\');
+ta[\'n-mainpage\'] = new Array(\'z\',\'Navštíviť Hlavnú stránku\');
+ta[\'n-portal\'] = new Array(\'\',\'O projekte, ako môžete prispieť, kde čo nájsť\');
+ta[\'n-currentevents\'] = new Array(\'\',\'Aktuálne udalosti a ich pozadie\');
+ta[\'n-recentchanges\'] = new Array(\'r\',\'Zoznam posledných úprav vo wiki.\');
+ta[\'n-randompage\'] = new Array(\'x\',\'Zobrazenie náhodného článku\');
+ta[\'n-help\'] = new Array(\'\',\'Pozrieť si pomoc.\');
+ta[\'n-sitesupport\'] = new Array(\'\',\'Podporte nás\');
+ta[\'t-whatlinkshere\'] = new Array(\'j\',\'Zoznam všetkých wiki článkov, ktoré sem odkazujú\');
+ta[\'t-recentchangeslinked\'] = new Array(\'k\',\'Posledné úpravy v článkoch, ktoré odkazujú na túto stránku\');
+ta[\'feed-rss\'] = new Array(\'\',\'RSS feed pre túto stránku\');
+ta[\'feed-atom\'] = new Array(\'\',\'Atom feed pre túto stránku\');
+ta[\'t-contributions\'] = new Array(\'\',\'Pozrieť si zoznam príspevkov od tohto redaktora\');
+ta[\'t-emailuser\'] = new Array(\'\',\'Poslať e-mail tomuto redaktorovi\');
+ta[\'t-upload\'] = new Array(\'u\',\'Nahranie obrázkových alebo mediálnych súborov\');
+ta[\'t-specialpages\'] = new Array(\'q\',\'Zoznam všetkých špeciálnych stránok\');
+ta[\'ca-nstab-main\'] = new Array(\'c\',\'Pozrieť si obsah článku\');
+ta[\'ca-nstab-user\'] = new Array(\'c\',\'Pozrieť si stránku redaktora\');
+ta[\'ca-nstab-media\'] = new Array(\'c\',\'Pozrieť si stránku médii\');
+ta[\'ca-nstab-special\'] = new Array(\'\',\'Toto je špeciálna stránka, nemôžete ju upravovať.\');
+ta[\'ca-nstab-wp\'] = new Array(\'c\',\'Pozrieť si stránku projektu\');
+ta[\'ca-nstab-image\'] = new Array(\'c\',\'Pozrieť si stránku obrázku\');
+ta[\'ca-nstab-mediawiki\'] = new Array(\'c\',\'Pozrieť si systémovú stránku\');
+ta[\'ca-nstab-template\'] = new Array(\'c\',\'Pozrieť si šablónu\');
+ta[\'ca-nstab-help\'] = new Array(\'c\',\'Pozrieť si stránku s Pomocou\');
+ta[\'ca-nstab-category\'] = new Array(\'c\',\'Pozrieť si stránku s kategóriami\');
+',
+
+# image deletion
+'deletedrevision' => 'Zmazať staré verzie $1.',
+
+# browsing diffs
+'previousdiff' => '← Choď na predchádzajúcu verziu',
+'nextdiff' => 'Choď na ďalšiu verziu →',
+
+'imagemaxsize' => 'Obmedzte obrázky na stránke opisu s obrázkami na: ',
+'thumbsize' => 'Veľkosť náhľadu: ',
+'showbigimage' => 'Stiahnuť tento obrázok vo väčšom rozlíšení ($1x$2, $3 KB)',
+
+'newimages' => 'Galéria nových obrázkov',
+'noimages' => 'Nič na zobrazenie.',
+
+# labels for User: and Title: on Special:Log pages
+'specialloguserlabel' => 'Redaktor: ',
+'speciallogtitlelabel' => 'Názov: ',
+
+'passwordtooshort' => 'Vaše heslo je príliš krátke. Musí mať dĺžku aspoň $1 znakov.',
+
+# Media Warning
+'mediawarning' => '\'\'\'Upozornenie\'\'\': Tento súbor môže obsahovať nebezpečný programový kód, po spustení ktorého by bol váš systém kompromitovaný.
+<hr>',
+'fileinfo' => '$1KB, MIME : <code>$2</code>',
+
+# Metadata
+'metadata' => 'Metadáta',
+
+# external editor support
+'edit-externally' => 'Uprav tento súbor pomocou externého programu',
+'edit-externally-help' => 'Viac informácii je na [http://meta.wikimedia.org/wiki/Help:External_editors setup instructions].',
+
+# 'all' in various places, this might be different for inflicted languages
+'recentchangesall' => 'všetky',
+'imagelistall' => 'všetky',
+'watchlistall1' => 'všetky',
+'watchlistall2' => 'všetky',
+'namespacesall' => 'všetky',
+
+# E-mail address confirmation
+'confirmemail' => 'Potvrdiť e-mailovú adresu',
+'confirmemail_text' => "Táto wiki vyžaduje, aby ste potvrdili platnosť Vašej e-mailovej adresy
+pred používaním e-mailových funkcií. Kliknite na tlačidlo dole, aby sa na Vašu adresu odoslal potvrdzovací
+e-mail. V e-maili bude aj odkaz obsahujúci kód; načítajte odkaz
+do Vášho prehliadača pre potvrdenie, že Vaša e-mailová adresa je platná.",
+'confirmemail_send' => 'Odoslať potvrdzovací kód',
+'confirmemail_sent' => 'Potvrdzovací e-mail odoslaný.',
+'confirmemail_sendfailed' => 'Nebolo možné odoslať potvrdzovací e-mail. Skontrolujte neplatné znaky v adrese.',
+'confirmemail_invalid' => 'Neplatný potvrdzovací kód. Kód možno vypršal.',
+'confirmemail_success' => 'Vaša e-mailová adresa bola potvrdená. Môžete sa prihlásiť a využívať wiki.',
+'confirmemail_loggedin' => 'Vaša e-mailová adresa bola potvrdená.',
+'confirmemail_error' => 'Niečo sa pokazilo pri ukladaní vášho potvrdenia.',
+
+'confirmemail_subject' => '{{SITENAME}} - potvrdenie e-mailovej adresy',
+'confirmemail_body' => "Niekto, pravdepodobne vy z IP adresy $1, zaregistroval účet
+\"$2\" s touto e-mailovou adresou na {{GRAMMAR:lokál|{{SITENAME}}}}.
+
+Pre potvrdenie, že tento účet skutočne patrí Vám a pre aktivovanie
+e-mailových funkcií na {{GRAMMAR:lokál|{{SITENAME}}}}, otvorte tento odkaz vo vašom prehliadači:
+
+$3
+
+Ak ste to *neboli* Vy, neotvárajte odkaz. Tento potvrdzovací kód
+vyprší o $4.
+",
+
+
+);
+
+class LanguageSk extends LanguageUtf8 {
+
+       function LanguageSk() {
+               global $wgNamespaceNamesSk, $wgMetaNamespace;
+               LanguageUtf8::LanguageUtf8();
+               $wgNamespaceNamesSk[NS_PROJECT_TALK] = 'Diskusia_k_' . $this->convertGrammar( $wgMetaNamespace, 'datív' );
+       }
+
+       function getNamespaces() {
+               global $wgNamespaceNamesSk;
+               return $wgNamespaceNamesSk;
+       }
+
+
+       function getNsIndex( $text ) {
+               global $wgNamespaceNamesSk;
+
+               foreach ( $wgNamespaceNamesSk as $i => $n ) {
+                       if ( 0 == strcasecmp( $n, $text ) ) { return $i; }
+               }
+               # Compatbility with old names:
+               if( 0 == strcasecmp( "Komentár", $text ) ) { return NS_TALK; } # 1
+               if( 0 == strcasecmp( "Komentár_k_redaktorovi", $text ) ) { return NS_USER_TALK; } # 3
+               if( 0 == strcasecmp( "Komentár_k_Wikipédii", $text ) ) { return NS_PROJECT_TALK; }
+               if( 0 == strcasecmp( "Komentár_k_obrázku", $text ) ) { return NS_IMAGE_TALK; } # 7
+               if( 0 == strcasecmp( "Komentár_k_MediaWiki", $text ) ) { return NS_MEDIAWIKI_TALK; } # 9
+               return false;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsSk;
+               return $wgQuickbarSettingsSk;
+       }
+
+       function getDateFormats() {
+               global $wgDateFormatsSk;
+               return $wgDateFormatsSk;
+       }
+
+       /**
+        * Exports $wgBookstoreListSk
+        * @return array
+        */
+       function getBookstoreList() {
+               global $wgBookstoreListSk ;
+               return $wgBookstoreListSk ;
+       }
+
+       function &getMagicWords() {
+               global $wgMagicWordsSk;
+               return $wgMagicWordsSk;
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesSk;
+               if($wgAllMessagesSk[$key])
+                       return $wgAllMessagesSk[$key];
+               return parent::getMessage( $key );
+       }
+
+       var $digitTransTable = array(
+               ',' => "\xc2\xa0",
+               '.' => ','
+       );
+
+       function formatNum( $number ) {
+               return strtr($number, $this->digitTransTable );
+       }
+
+       # Convert from the nominative form of a noun to some other case
+       # Invoked with {{GRAMMAR:case|word}}
+       function convertGrammar( $word, $case ) {
+               switch ( $case ) {
+                       case 'genitív':
+                               if ( $word == 'Wikipédia' ) {
+                                       $word = 'Wikipédie';
+                               } elseif ( $word == 'Wikislovník' ) {
+                                       $word = 'Wikislovníku';
+                               } elseif ( $word == 'Wikicitáty' ) {
+                                       $word = 'Wikicitátov';
+                               } elseif ( $word == 'Wikiknihy' ) {
+                                       $word = 'Wikikníh';
+                               }
+                       break;
+                       case 'datív':
+                               if ( $word == 'Wikipédia' ) {
+                                       $word = 'Wikipédii';
+                               } elseif ( $word == 'Wikislovník' ) {
+                                       $word = 'Wikislovníku';
+                               } elseif ( $word == 'Wikicitáty' ) {
+                                       $word = 'Wikicitátom';
+                               } elseif ( $word == 'Wikiknihy' ) {
+                                       $word = 'Wikiknihám';
+                               }
+                       break;
+                       case 'akuzatív':
+                               if ( $word == 'Wikipédia' ) {
+                                       $word = 'Wikipédiu';
+                               } elseif ( $word == 'Wikislovník' ) {
+                                       $word = 'Wikislovník';
+                               } elseif ( $word == 'Wikicitáty' ) {
+                                       $word = 'Wikicitáty';
+                               } elseif ( $word == 'Wikiknihy' ) {
+                                       $word = 'Wikiknihy';
+                               }
+                       break;
+                       case 'lokál':
+                               if ( $word == 'Wikipédia' ) {
+                                       $word = 'Wikipédii';
+                               } elseif ( $word == 'Wikislovník' ) {
+                                       $word = 'Wikislovníku';
+                               } elseif ( $word == 'Wikicitáty' ) {
+                                       $word = 'Wikicitátoch';
+                               } elseif ( $word == 'Wikiknihy' ) {
+                                       $word = 'Wikiknihách';
+                               }
+                       break;
+                       case 'inštrumentál':
+                               if ( $word == 'Wikipédia' ) {
+                                       $word = 'Wikipédiou';
+                               } elseif ( $word == 'Wikislovník' ) {
+                                       $word = 'Wikislovníkom';
+                               } elseif ( $word == 'Wikicitáty' ) {
+                                       $word = 'Wikicitátmi';
+                               } elseif ( $word == 'Wikiknihy' ) {
+                                       $word = 'Wikiknihami';
+                               }
+                       break;
+               }
+       return $word;
+       }
+
+}
+?>
diff --git a/languages/LanguageSl.php b/languages/LanguageSl.php
new file mode 100644 (file)
index 0000000..ea990a6
--- /dev/null
@@ -0,0 +1,831 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+#
+# Revision/
+# Inačica 1.00.00 XJamRastafire 2003-07-08 |NOT COMPLETE
+#         1.00.10 XJamRastafire 2003-11-03 |NOT COMPLETE
+# ______________________________________________________
+#         1.00.20 XJamRastafire 2003-11-05 |    COMPLETE
+#         1.00.30 romanm        2003-11-07 |    minor changes
+#         1.00.31 romanm        2003-11-11 |    merged incorrectly broken lines
+#         1.00.32 romanm        2003-11-19 |    merged incorrectly broken lines
+#         1.00.40 romanm        2003-11-21 |    fixed Google search
+
+#         1.00.50 Nikerabbit    2005-08-15 |    removed old stuff, some cleanup, NOT COMPLETE!
+
+
+require_once( "LanguageUtf8.php" );
+
+/** TODO: fixme, remove wikipedia
+/* private */ $wgNamespaceNamesSl = array(
+       NS_MEDIA          => "Media",
+       NS_SPECIAL        => "Posebno",
+       NS_MAIN           => "",
+       NS_TALK           => "Pogovor",
+       NS_USER           => "Uporabnik",
+       NS_USER_TALK      => "Uporabniški_pogovor",
+       NS_PROJECT        => "Wikipedija",
+       NS_PROJECT_TALK   => "Pogovor_k_Wikipediji",
+       NS_IMAGE          => "Slika",
+       NS_IMAGE_TALK     => "Pogovor_k_sliki",
+       NS_MEDIAWIKI      => "MediaWiki",
+       NS_MEDIAWIKI_TALK => "MediaWiki_talk",
+       NS_TEMPLATE       => "Template",
+       NS_TEMPLATE_TALK  => "Template_talk"
+
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgQuickbarSettingsSl = array(
+       "Brez", "Levo nepomično", "Desno nepomično", "Levo leteče"
+);
+
+/* private */ $wgDateFormatsSl = array(
+#        'No preference',
+);
+
+
+/* private */ $wgAllMessagesSl = array(
+# User Toggles
+
+"tog-underline"        => "Podčrtane povezave",
+"tog-highlightbroken"  => "Oblikuj prekinjene povezave <a href=\"\" class=\"new\">kot</a> (druga možnost: kot<a href=\"\" class=\"internal\">?</a>).",
+"tog-justify"     => "Poravnaj odstavke",
+"tog-hideminor"        => "Skrij manjše popravke v trenutnih spremembah",
+"tog-usenewrc"         => "Izbolšane trenutne spremembe (ni za vse brskljalnike)",
+"tog-numberheadings"   => "Samodejno oštevilči poglavja",
+"tog-showtoolbar" => "Show edit toolbar",
+"tog-rememberpassword" => "Zapomni si geslo v vseh urejevanjih",
+"tog-editwidth"        => "Urejevalna škatla ima celo širino",
+"tog-editondblclick"   => "Urejuj strani z dvojnih klikom (JavaScript)",
+"tog-watchdefault"     => "Opazuj nove in spremenjene članke",
+"tog-minordefault"     => "Po privzetem označi vsa urejanja kot manjša",
+"tog-previewontop"     => "Prikaži predogled pred urejevalno škatlo in ne za njo",
+
+# Dates
+'sunday' => 'nedelja',
+'monday' => 'ponedeljek',
+'tuesday' => 'torek',
+'wednesday' => 'sreda',
+'thursday' => 'četrtek',
+'friday' => 'petek',
+'saturday' => 'sobota',
+'january' => 'januar',
+'february' => 'februar',
+'march' => 'marec',
+'april' => 'april',
+'may_long' => 'maj',
+'june' => 'junij',
+'july' => 'julij',
+'august' => 'avgust',
+'september' => 'september',
+'october' => 'oktober',
+'november' => 'november',
+'december' => 'december',
+'jan' => 'jan',
+'feb' => 'feb',
+'mar' => 'mar',
+'apr' => 'apr',
+'may' => 'maj',
+'jun' => 'jun',
+'jul' => 'jul',
+'aug' => 'avg',
+'sep' => 'sep',
+'oct' => 'okt',
+'nov' => 'nov',
+'dec' => 'dec',
+
+# Bits of text used by many pages:
+#
+"linktrail"            => "/^([a-z]+)(.*)\$/sD",
+"mainpage"             => "Glavna stran",
+"about"                        => "O",
+"aboutsite"             => "O Wikipediji",
+"aboutpage"            => "Wikipedija:O_Wikipediji",
+"help"                 => "Pomoč",
+"helppage"             => "Wikipedija:Pomoč",
+"bugreports"           => "Poročila o hroščih",
+"bugreportspage"        => "Wikipedija:Poročila_o_hroščih",
+"faq"                  => "Najpogostejša vprašanja",
+"faqpage"              => "Wikipedija:Najpogostejša_vprašanja",
+"edithelp"             => "Pomoč pri urejanju",
+"edithelppage"         => "Wikipedija:Urejevanje_slovenskih_strani",
+"cancel"               => "Prekini",
+"qbfind"               => "Najdi",
+"qbbrowse"             => "Pobrskaj",
+"qbedit"               => "Uredi",
+"qbpageoptions"         => "Možnosti strani",
+"qbpageinfo"           => "Podatki strani",
+"qbmyoptions"          => "Moje možnosti",
+"mypage"               => "Moja stran",
+"mytalk"               => "Moj pogovor",
+"currentevents"         => "Trenutni dogodki",
+"errorpagetitle"        => "Napaka",
+"returnto"             => "Vrni se k $1.",
+"tagline"                      => "Iz Wikipedije, proste enciklopedije.",
+"whatlinkshere"                => "Strani, ki so vezane sem",
+"help"                 => "Pomoč",
+"search"               => "Išči",
+"go"                   => "Pojdi",
+"history"              => "Stare inačice",
+"printableversion"      => "Inačica za tiskanje",
+"editthispage"         => "Uredi to stran",
+"deletethispage"        => "Zbriši to stran",
+"protectthispage"       => "Zavaruj to stran",
+"unprotectthispage"     => "Ta stran naj bo nezavarovana",
+"newpage"               => "Nova stran",
+"talkpage"             => "Pogovori se o tej strani",
+"articlepage"          => "Poglej članek",
+"subjectpage"          => "Poglej temo", # For compatibility
+"userpage"              => "Poglej uporabnikovo stran",
+"wikipediapage"         => "Poglej meta stran",
+"imagepage"             => "Poglej stran slike",
+"viewtalkpage"          => "Poglej pogovor",
+"otherlanguages"        => "Drugi jeziki",
+"redirectedfrom"        => "(Preusmerjeno iz $1)",
+"lastmodified"         => "Zadnja sprememba $1.",
+"viewcount"            => "To stran so pogledali $1 krat.",
+"printsubtitle"         => "(Iz {{SERVER}})",
+"protectedpage"         => "Zaščitena stran",
+"administrators"        => "Wikipedija:Administratorji",
+"sysoptitle"           => "Zahtevan dostop sistemskega operaterja",
+"sysoptext"            => "To dejanje, ki ste ga zahtevali, lahko izvedejo le uporabniki s statusom \"sysop\". Glej še $1.",
+"developertitle" => "Zahtevan dostop razvijalca",
+"developertext"        => "To dejanje, ki ste ga zahtevali, lahko izvedejo le uporabniki s statusom \"razvijalec\". Glej še $1.",
+"nbytes"               => "$1 bitov",
+"go"                   => "Pojdi",
+"ok"                   => "V redu",
+"sitetitle"            => "Wikipedija",
+"sitesubtitle"         => "Prosta enciklopedija",
+"retrievedfrom"         => "Vzpostavljeno iz \"$1\"",
+"newmessages"           => "Imaš $1.",
+"newmessageslink"       => "novih sporočil",
+"editsection"=>"spremeni",
+"toc" => "Vsebina",
+"showtoc" => "prikaži",
+"hidetoc" => "skrij",
+"thisisdeleted" => "Poglej ali vrni $1?",
+"restorelink" => "$1 pobrisanih popravkov",
+
+# Main script and global functions
+#
+"nosuchaction"         => "Ni takšnega dejanja",
+"nosuchactiontext"      => "Dejanje, ki ga je označil URL programje Wikipedije ne prepozna",
+"nosuchspecialpage"     => "Ne obstaja takšna posebna stran",
+"nospecialpagetext"     => "Zahtevali ste posebno stran, ki jo programje Wikipedije ne prepozna.",
+
+# General errors
+#
+"error"                        => "Napaka",
+"databaseerror"         => "Napaka podatkovne baze",
+"dberrortext"          => "Nastopila je skladenjska povpraševanja podatkovne baze.
+Zadnje poskušano povpraševanje podatkovne baze je bilo:
+<blockquote><tt>$1</tt></blockquote>
+iz telesa funkcije \"<tt>$2</tt>\".
+MySQL je vrnil napako \"<tt>$3: $4</tt>\".",
+"noconnect"            => "Ne morem se povezati s PB na $1",
+"nodb"                 => "ne morem izbrati podatkovne baze $1",
+"readonly"             => "Podatkovna baza je zaklenjena",
+"enterlockreason" => "Vnesi razlog za zastoj, skupaj z oceno, kdaj bo zastoj odpravljen",
+"readonlytext" => "Podatkovna baza Wikipedije je trenutno zaklenjena za nove vnose in nove spremembe, verjetno zaradi njenega tekočega vzdrževanja. Kmalu po tem bo spet v običajnem stanju.
+Administrator, ki jo je zaklenil je ponudil naslednjo razlago:
+<p>$1",
+"missingarticle" => "Podatkovna baza ni našla besedila strani \"$1\", ki bi ga morala. To ni napaka podatkovne baze, ampak najverjetneje hrošč v programju. Prosim sporočite to administratorju in navedite zapisek URL-ja.",
+"internalerror"         => "Notranja napaka",
+"filecopyerror"         => "Ne morem prepisati datoteke \"$1\" v \"$2\".",
+"filerenameerror"       => "Ne morem preimenovati datoteke \"$1\" v \"$2\".",
+"filedeleteerror"       => "Ne morem zbrisati datoteke \"$1\".",
+"filenotfound"         => "Ne najdem datoteke \"$1\".",
+"unexpected"           => "Nepričakovana vrednost: \"$1\"=\"$2\".",
+"formerror"            => "Napaka: ne morem predložiti oblike",
+"badarticleerror"       => "Tega dejanja ne morem izvesti na tej strani.",
+"cannotdelete"         => "Ne morem zbrisati navedene strani ali slike. (Lahko da jo je zbrisal že nekdo drug.)",
+"badtitle"             => "Slab naslov",
+"badtitletext"         => "Naveden naslov strani je neveljaven, prazen ali nepravilno povezan naslov med drugimi jeziki ali med drugimi wikijevimi projekti.",
+"perfdisabled"          => "To je posneta kopija $1:",
+
+# Login and logout pages
+#
+"logouttitle"          => "Izpis uporabnika",
+"logouttext"           => "Sedaj niste vpisani.
+Lahko nadaljujete z uporabo Wikipedije nepodpisani, ali pa se lahko ponovno vpišete kot isti ali drug uporabnik.\n",
+
+"welcomecreation"       => "<h2>Pozdravljeni, $1!</h2><p>Ustvarili smo vaš račun. Ne pozabite si ponastaviti vaših nastavitev Wikipedije.",
+
+"loginpagetitle"        => "Vpis uporabnika",
+"yourname"             => "Vaše uporabniško ime",
+"yourpassword"         => "Vaše geslo",
+"yourpasswordagain"     => "Ponovno vpišite geslo",
+"newusersonly"         => " (Samo novi uporabniki)",
+"remembermypassword"    => "Zapomni si moje geslo vseskozi.",
+"loginproblem"         => "<b>Nastala je tažava z vašim vpisom.</b><br />Poskusite znova!",
+"alreadyloggedin"       => "<strong>Uporabnik $1, ste že vpisani!</strong><br />\n",
+
+"login"                        => "Vpis",
+"userlogin"            => "Vpis",
+"logout"               => "Izpis",
+"userlogout"           => "Izpis",
+"createaccount"                => "Izdelajte nov račun",
+"badretype"            => "Gesli, ki ste ju vnesli, se ne ujemata.",
+"userexists"           => "Uporabniško ime, ki ste ga vnesli, je že v uporabi. Prosimo izberite drugačno ime.",
+"youremail"            => "Vaša elektronska pošta",
+"yournick"             => "Vaš vzdevek (za podpise)",
+"emailforlost"         => "Če ste pozabili geslo, imate lahko novo, poslano na naslov vaše elektronske pošte.",
+"loginerror"           => "Napaka vpisa",
+"noname"               => "Niste navedli veljavnega uporabniškega imena.",
+"loginsuccesstitle"     => "Vpis uspešen",
+"loginsuccess"         => "Sedaj ste vpisani v Wikipediji kot \"$1\".",
+"nosuchuser"           => "Uporabnik z imenom \"$1\" ne obstaja. Preverite vaše črkovanje, ali uporabite spodnji obrazec za izdelavo novega uporabniškega računa.",
+"wrongpassword"                => "Geslo, ki ste ga vnesli je nepravilno. Prosimo poskusite znova.",
+"mailmypassword"        => "Pošljite mi novo geslo",
+"passwordremindertitle" => "Opomnik gesla iz Wikipedije",
+"passwordremindertext"  => "Nekdo (verjetno vi, z IP naslova $1)
+je zahteval, da vam pošljemo novo vpisno geslo Wikipedije.
+Geslo uporabnika \"$2\" je sedaj \"$3\".
+Sedaj se lahko vpišete in spremenite vaše geslo.",
+"noemail"              => "Elektronska pošta za uporabnika \"$1\" ni zapisana.",
+"passwordsent"         => "Novo geslo smo poslali na naslov elektronske pošte, vpisano za \"$1\". Prosimo vpišite se ponovno, ko ga boste prejeli.",
+
+# Edit pages
+#
+"summary"              => "Povzetek",
+"minoredit"            => "To je manjše urejevanje",
+"watchthis"            => "Opazuj ta članek",
+"savearticle"          => "Shrani stran",
+"preview"              => "Predpregled",
+"showpreview"          => "Pokaži predpregled",
+"blockedtitle"         => "Uporabnik je zaprt",
+"blockedtext"          => "Vaše uporabniško ime ali IP naslov je zaprl $1.
+Vzrok za to je naslednji:<br />''$2''<p>Lahko pokličete $1 ali katerega drugega
+[[Wikipedija:Administratorji|administratorja]] za pogovor o zaprtju.",
+"newarticle"           => "(Nov)",
+"newarticletext" =>
+"Sledili ste povezavi, ki še ne obstaja.
+Za izdelavo strani, začnite vnašati besedilo v spodnjo škatlo
+(poglejte [[Wikipedija:Pomoč|stran o pomoči]] za več sporočil).
+Če ste tukaj po pomoti, samo kliknite gumb za '''nazaj''' vašega brskljalnika.",
+"anontalkpagetext"      => "---- ''To je pogovorna stran za nepodpisanega uporabnika, ki še ni ustvaril računa ali, ki ga ne uporablja. Zaradi tega moramo uporabiti števčen [[IP address]] za njegovo/njeno ugotavljanje istovetnosti. Takšen IP naslov si lahko deli več uporabnikov. Če ste nepodpisan uporabnik in če menite, da so nepomembne pripombe namenjene vam, prosimo [[Special:Userlogin|ustvarite račun ali pa se vpišite]], da preprečite naslednje zmede z drugimi nepodpisanimi uporabniki.'' ",
+"noarticletext" => "(Trenutno ni besedila na tej strani)",
+"updated"              => "(Posodobljeno)",
+"note"                 => "<strong>Opomba:</strong> ",
+"previewnote"          => "Zapomnite si, da je to le predpregled in stran še ni bila shranjena!",
+"previewconflict"       => "Ta predpregled kaže besedilo v zgornjem predelu urejevanja besedila kakor se bo pojavilo, če se ga odločite shraniti.",
+"editing"              => "Urejevanje $1",
+"editconflict"         => "Navzkrižje urejevanja: $1",
+"explainconflict"       => "Nekdo je spremenil to stran od takrat, ko ste jo vi začeli urejevati.
+Zgodnji predel besedila vsebuje besedilo strani, ki trenutno obstaja.
+Vaše spremembe so prikazane v spodnjem predelu besedila.
+Morali boste spojiti vaše spremembe v obstoječe besedilo.
+<b>Samo</b> besedilo z zgornjem predelu besedila bo shranjeno, ko boste pritisnili \"Shrani stran\".<br />",
+"yourtext"             => "Vaše besedilo",
+"storedversion"         => "Shranjena inačica",
+"editingold"           => "<strong>OPOZORILO: Urejujete zastarelo inačico te strani.
+Če jo boste shranili, bodo vse spremembe, narejene od tedaj, izgubljene.</strong>",
+"yourdiff"             => "Razlike",
+"copyrightwarning"      => "Prosimo upoštevajte, da se vsi doprinosi k Wikipediji smatrajo kot objave pod GNU licenco proste dokumentacije (glej $1 za podrobnosti).
+Če ne želite, da se vaša pisanja neusmiljeno urejujejo ali ponovno razdeljujejo prostovoljno, potem jih ne predlagajte tukaj.<br />
+Poleg tega nam obljubljate, da ste to napisali samo ali pa prepisali iz javno dostopnega ali podobnega prostega vira.
+<strong>NE PREDLAGAJTE AVTORSKO ZAŠČITENEGA DELA BREZ DOVOLJENJA!</strong>",
+"longpagewarning" => "<strong>OPOZORILO: Ta stran je dolga $1 kilobitov; nekateri brskalniki s težavo urejujejo strani, ki so daljše kot 32 kB. Prosimo, da upoštevate delitev strani na manjše dele.</strong>",
+"readonlywarning" => "<strong>OPOZORILO: Baza je trenutno zaprta zaradi vzdrževanja
+in trenutno ne morete shranjevati sprememb. Skopirajte besedilo v urejevalnik in ga posnemite kasneje.</strong>",
+"protectedpagewarning" => "<strong>OPOZORILO: Ta stran je zaključena in jo lahko spreminjajo samo uporabniki, ki imajo vzdrževalne pravice. Prosimo poglejte [[Project:Smernice_zaščitenih_strani|smernice zaščitenih strani]].</strong>",
+
+# History pages
+#
+"revhistory"           => "Zgodovina različic",
+"nohistory"            => "Ni urejevalne zgodovine za to stran.",
+"revnotfound"          => "Ne najdem različice",
+"revnotfoundtext"       => "Ne morem najti stare različice strani, po kateri ste povpraševali.
+Prosimo preverite URL, ki ste ga uporabili za dostop do te strani.\n",
+"loadhist"             => "Nalagam zgodovino strani",
+"currentrev"           => "Trenutna različica",
+"revisionasof"         => "Različica od $1",
+"cur"                  => "tren",
+"next"                 => "nasl",
+"last"                 => "zadn",
+"orig"                 => "izvi",
+"histlegend"           => "Napotek: (tren) = razlika od trenutne različice,
+(zadn) = razlika od prejšnje različice, M = manjše urejevanje",
+
+# Diffs
+#
+"difference"           => "(Razlika med različicami)",
+"loadingrev"           => "nalagam različico za razliko",
+"lineno"               => "Vrstica $1:",
+"editcurrent"          => "Uredi trenutno različico te strani",
+
+# Search results
+#
+"searchresults"         => "Izidi iskanja",
+"searchresulttext"      => "Za več sporočil o iskanju v Wikipediji glej [[Wikipedija:Iskanje|Iščem v Wikipediji]].",
+"searchquery"          => "Za povpraševanje \"$1\"",
+"badquery"             => "Slabo oblikovano iskalno povpraševanje",
+"badquerytext"         => "Ne moremo obdelati vašega povpraševanja.
+To je verjetno zaradi tega, ker ste hoteli iskati besedo, dolgo manj kot tri črke, kar še ni podprto.
+Lahko ste tudi narobe vnesli izraz, na primer \"Ribi in in Tehntnica\".
+Prosimo poskusite z drugim povpraševanjem.",
+"matchtotals"          => "Povpraševanje \"$1\" se ujema z $2 naslovi člankov in z besedilom $3 člankov.",
+"nogomatch"             => "Ne obstaja stran z natančno tem naslovom, poskušam z iskanjem celotnega besedila. ",
+"titlematches"         => "Ujemanje z naslovom članka",
+"notitlematches"        => "Noben naslov članka se ne ujema",
+"textmatches"          => "Ujemanje z besedilom članka",
+"notextmatches"                => "Nobeno besedilo članka se ne ujema",
+"prevn"                        => "prejšnji $1",
+"nextn"                        => "naslednji $1",
+"viewprevnext"         => "Pogled ($1) ($2) ($3).",
+"showingresults"        => "Spodaj prikažem <b>$1</b> izidov, začenši z #<b>$2</b>.",
+"nonefound"            => "<strong>Opomba</strong>: neuspešna iskanja velikokrat povzročijo iskanja vsakdanjih besed kot sta \"imeti\" in \"iz\", katera niso vnešena v seznam, ali navajanja več iskalnih izrazov (v izidu se bodo pojavile samo strani, ki vsebujejo iskalne izraze).",
+"powersearch"           => "Iskanje",
+"powersearchtext" => "
+Iskanje v imenskem prostoru :<br />
+$1<br />
+$2 Seznam se preusmerja   Iskanje za $3 $9",
+"searchdisabled" => "<p>Oprostite! Iskanje po celotni bazi je zaradi hitrejšega delovanja Wikipedije trenutno onomogočena. Lahko pa se poslužite z Googlovim iskalnikom.</p>
+
+",
+"blanknamespace" => "(Osnovno)",
+
+# Preferences page
+#
+"preferences"          => "Nastavitve",
+"prefsnologin"          => "Niste vpisani",
+"prefsnologintext"     => "Morate biti <a href=\"" .
+  "{{localurle:Special:Userlogin}}\">vpisani</a>
+za ponastavljanje uporabniških nastavitev.",
+"prefslogintext"        => "Vpisani ste kot \"$1\".
+Notranja ID števka je $2.",
+"prefsreset"           => "Nastavitve so bile ponastavljene iz shrambe.",
+"qbsettings"           => "Postavitve hitre vrstice",
+"changepassword"        => "Sprememba gesla",
+"skin"                 => "Koža",
+"math"                 => "Prikazujem matematično besedilo",
+"math_failure"         => "Nisem uspel razčleniti",
+"math_unknown_error"   => "neznana napaka",
+"math_unknown_function"        => "neznana funkcija ",
+"math_lexing_error"    => "slovarska napaka",
+"math_syntax_error"    => "skladenjska napaka",
+"saveprefs"            => "Shrani nastavitve",
+"resetprefs"           => "Ponastavi nastavitve",
+"oldpassword"          => "Staro geslo",
+"newpassword"          => "Novo geslo",
+"retypenew"            => "Ponovno vnesite geslo",
+"textboxsize"          => "Razsežnosti urejevalne škatle",
+"rows"                 => "Vrstice",
+"columns"              => "Stolpci",
+"searchresultshead"     => "Postavitve izida iskanja",
+"resultsperpage"        => "Zadetkov za prikaz na stran",
+"contextlines"         => "Vrstic za prikaz na zadetek",
+"contextchars"         => "Znakov vsebine na vrstico",
+"stubthreshold"         => "Prag za škrbinski prikaz",
+"recentchangescount"    => "Število naslovov v trenutnih spremembah",
+"savedprefs"           => "Vaše nastavitve so bile shranjene.",
+"timezonetext"         => "Vnesite za koliko ur se vaš krajevni čas razlikuje od strežnikovega časa (UTC).",
+"localtime"            => "Krajevni čas",
+"timezoneoffset"        => "Izravnava",
+"emailflag"            => "Ne prikažem elektronske pošte drugim uporabnikom",
+"defaultns"  => "Ponavadi išči na naslednjih imenskih področjih:",
+
+# Recent changes
+#
+"changes"               => "spremembe",
+"recentchanges"         => "Trenutne spremembe",
+"recentchangestext"     => "Sledi najpoznejšim spremembam v Wikipediji na tej strani.
+[[Wikipedija:Dobrodošli,_novinci|Dobrodošli, novinci]]!
+Prosimo poglejte na naslednje strani: [[Wikipedija:Najpogostejša vprašanja|Najpogostejša vprašanja]],
+[[Wikipedija:Primernosti in smernice|Smernice]]
+(še posebej [[Wikipedija:Dogovori o poimenovanjih|Dogovori o poimenovanjih]],
+[[Wikipedija:Nepristransko stališče videnja|Nepristransko stališče videnja (NSV)]]),
+in [[Wikipedija:Najpogostejše stranpoti Wikipedije|Najpogostejše stranpoti Wikipedije]].
+Če bi radi, da Wikipedija uspe, je zelo pomembno, da ne dodajate
+snovi, ki je pridržana z drugimi [[wikipedia:Avtorske pravice|avtorskimi pravicami]].
+Zakonita obveza lahko v resnici škodi opravilu, zatorej ne počnite tega.
+Poglejte tudi [http://meta.wikipedia.org/wiki/Special:Recentchanges recent meta discussion].",
+"rcloaderr"            => "Nalagam trenutne spremembe",
+"rcnote"               => "Spodaj so zadnje <strong>$1</strong> spremembe v zadnjih <strong>$2</strong> dnevih.",
+"rcnotefrom"   => "Spodaj so spremembe od <b>$2</b> (prikazane do <b>$1</b>).",
+"rclistfrom"   => "Prikaži nove spremembe od $1",
+# "rclinks"            => "Prikaži zadnjih $1 sprememb v zadnjih $2 urah / zadnjih $3 dnevih",
+"rclinks"              => "Prikaži zadnjih $1 sprememb v zadnjih $2 dnevih.",
+"rchide"               => "v $4 obliki; $1 manjša urejanja; $2 druga poimenovanja; $3 večkratna urejevanja.",
+"diff"                 => "razl",
+"hist"                 => "zgod",
+"hide"                 => "skrij",
+"show"                 => "prikaži",
+"tableform"            => "tabela",
+"listform"             => "seznam",
+"nchanges"             => "$1 sprememb",
+"minoreditletter"       => "M",
+"newpageletter"         => "N",
+
+# Upload
+#
+"upload"               => "Naložite datoteko",
+"uploadbtn"            => "Naložite datoteko",
+"uploadlink"           => "Naložite slike",
+"reupload"             => "Ponovno naložite",
+"reuploaddesc"         => "Vrnite se v obrazec za nalaganje.",
+"uploadnologin"         => "Niste vpisani",
+"uploadnologintext"    => "Za nalaganje datotek morate biti [[Special:Userlogin|vpisani]]
+.",
+"uploaderror"          => "Naložite napako",
+"uploadtext"   => "'''USTAVITE SE!''' Preden tukaj naložite,
+se prepričajte, da ste prebrali in sledili Wikipedijini
+[[Project:Primernost_uporabe_slik|primernosti uporabe slik]].
+
+Da pregledate ali poiščete prejšnje naložene slike,
+pojdite na [[Special:Imagelist|seznam naloženih slik]].
+Nalaganje in brisanje je vpisano v
+[[Project:Dnevnik_nalaganja|dnevniku nalaganja]].
+
+Uporabite spodnji obrazec za nalaganje novih slik za
+ponazarjanje vaših člankov.
+Na večini brskljalnikov boste videli \"Preišči...\" gumb, ki vas
+bo spravil na standardno pogovorno okno odprtja datoteke vašega operacijskega sistema.
+Z izbiro datoteke se bo vpisalo ime v besedilno
+polje poleg gumba.
+Morate tudi potrditi škatlico s čimer izjavljate,
+da z nalaganjem datoteke ne kršite nobenih avtorskih pravic.
+Pritisnite gumb \"Naloži\" za dokončanje nalaganja.
+To bo malo malce potrajalo, če imate slabšo mrežno povezavo.
+
+Prednostni formati so JPEG za fotografske slike, PNG
+za risbe in druge ikonske slike in OGG za zvoke.
+Imenujete vaše datoteke opisno, da se izognete zmešnjavi.
+Da v članek vključite sliko, uporabite povezavo oblike
+'''<nowiki>[[image:datoteka.jpg]]</nowiki>''' ali
+'''<nowiki>[[image:datoteka.png|alt besedilo]]</nowiki>''' ali
+'''<nowiki>[[media:datoteka.ogg]]</nowiki>''' za zvoke.
+
+Vedite, da lahko znotraj Wikipedijinih strani drugi urejajo ali
+pobrišejo vaše naložene slike, če menijo, da to služi enciklopediji
+in lahko vam zaprejo dostop, če izrabljate sistem.",
+"uploadlog"            => "dnevnik nalaganja",
+"uploadlogpage"         => "Dnevnik_nalaganja",
+"uploadlogpagetext" => "Spodaj je seznam najpoznejših naloženih datotek.
+Vsi prikazani časi so strežnikov čas (UTC).
+<ul>
+</ul>
+",
+"filename"             => "Imedatoteke",
+"filedesc"             => "Povzetek",
+
+"copyrightpage"         => "Wikipedija:Avtorske pravice",
+"copyrightpagename"     => "Avtorske pravice Wikipedije",
+"uploadedfiles"                => "Naložene datoteke",
+"ignorewarning"                => "Zanemari opozorilo in vseeno shrani.",
+"minlength"            => "Imena slik morajo vsebovati vsaj tri črke.",
+"badfilename"          => "Slika se je spremenila v \"$1\".",
+"badfiletype"          => "\".$1\" ni priporočen format datotek slik.",
+"largefile"            => "Priporočeno je, da slike po elikosti ne presegajo 100 k.",
+"successfulupload"      => "Nalaganje uspešno",
+"fileuploaded"         => "Datoteka \"$1\" je bila uspešno naložena.
+Prosimo sledite tej povezavi: ($2) za stran opisa in izpolnite
+podatke o datoteki, na primer od kod prihaja, kdaj je bila
+izdelana in kdo jo je izdelal ali karkoli bi še vedeli o njej.",
+"uploadwarning"         => "Opozorilo nalaganja",
+"savefile"             => "Shrani datoteko",
+"uploadedimage"         => "naloženo \"[[$1]]\"",
+
+# Image list
+#
+"imagelist"            => "Seznam slik",
+"imagelisttext"                => "Spodaj je seznam $1 slik zložen $2.",
+"getimagelist"         => "prinašam seznam slik",
+"ilsubmit"             => "Išči",
+"showlast"             => "Prikaži zadnjih $1 slik zloženih $2.",
+"byname"               => "po imenu",
+"bydate"               => "po datumu",
+"bysize"               => "po velikosti",
+"imgdelete"            => "briš",
+"imgdesc"              => "opis",
+"imglegend"            => "Napotek: (opis) = prikaži/uredi opis slike.",
+"imghistory"           => "Zgodovina slike",
+"revertimg"            => "vrn",
+"deleteimg"            => "bri",
+"deleteimgcompletely"          => "bri",
+"imghistlegend"         => "Napotek: (tre) = trenutna slika, (bri) = briši
+zadnjo inačico, (vrn) = vrni sliko na to zadnjo inačico.
+<br /><i>Klikni na datum, da vidiš katera slika je bila tedaj naložena</i>.",
+"imagelinks"   => "Povezave slike",
+"linkstoimage" => "Naslednje strani so vezane s to sliko:",
+"nolinkstoimage" => "Nobena stran ni vezana s to sliko.",
+
+# Statistics
+#
+"statistics"   => "Statistika",
+"sitestats"            => "Statistika sedeža Wikipedije",
+"userstats"            => "Statistika uporabnika",
+"sitestatstext" => "V podatkovni bazi je skupno <b>$1</b> strani.
+Vključujejo tudi \"pogovorne\" strani, strani o Wikipediji, najmanjše \"škrbinske\" strani, preusmeritve in še druge, ki niso članki.
+Če izključimo te zadnje, obstaja <b>$2</b> strani; ki so po vsej
+verjetnosti pravi članki.<p>
+Do sedaj je bilo <b>$3</b> pregledov strani in <b>$4</b> urejanj strani od
+nadgraditve programske opreme (20. julij 2002).
+To da skupaj povprečno <b>$5</b> urejevanj na stran in <b>$6</b> pogledov
+na eno urejevanje.",
+"userstatstext" => "<b>$1</b> je vpisanih uporabnikov. Od tega jih je <b>$2</b> administratorjev (glej $3).",
+
+# Vzdrževalna stran
+#
+"maintenance"          => "Vzdrževalna stran",
+"maintnancepagetext"   => "Ta stran vsebuje več pripravnih pripomočkov za vsakdanje vzdrževanje. Nekatere teh funkcij obremenjujejo podatkovno bazo, zato prosim ne poženite novega nalaganja pri vsakem popravljanju ;-)",
+"maintenancebacklink"  => "Nazaj na vzdrževalno stran",
+"disambiguations"      => "Razjasnjevalne strani",
+"disambiguationspage"  => "Wikipedija:Povezave_na_razjasnjevalne_strani",
+"disambiguationstext"  => "Naslednji članki so povezani na <i>razjasnjevalno stran</i>. Morajo biti povezani na pripadajočo vsebino.<br />Stran je razjasnjevalna, če je povezana iz $1.<br />Povezave iz drugih imenskih področij tukaj <i>niso</i> prikazane.",
+"doubleredirects"      => "Dvojne preusmeritve",
+"doubleredirectstext"  => "<b>Pozor:</b> ta seznam lahko vsebuje nepravilne člene. To ponavadi pomeni, da obstaja dodatno besedilo s povezavami pod prvim ukazom #REDIRECT.<br />\nVsaka vrsta vsebuje povezave k prvi in drugi preusmeritvi, kot tudi prvo vrstico drugega preusmerjenega besedila, kar ponavadi da \"resnični\" ciljni članek, na katerega mora kazati prva preusmeritev.",
+"brokenredirects"      => "Polomljene preusmeritve",
+"brokenredirectstext"  => "Naslednje preusmeritve kažejo na neobstoječe članke.",
+"selflinks"            => "strani z lastnimi povezavami",
+"selflinkstext"                => "Naslednje strani vsebujejo povezave nase, kar ne bi smele.",
+"mispeelings"           => "Strani z napačnimi črkovanji",
+"mispeelingstext"       => "Naslednje strani vsebujejo običajna napačna črkovanja, ki so prikazana na $1. Pravilno črkovanje bo mogoče zgledalo (kot).",
+"mispeelingspage"       => "Seznam običajni napačnih črkovanja",
+"missinglanguagelinks"  => "Manjkajoče jezikovne povezave",
+"missinglanguagelinksbutton"    => "Najti manjkajoče jezikovne povezave za",
+"missinglanguagelinkstext"      => "Ti članki <i>niso</i> povezani z njihovimi nasprotnimi članki v $1. Preusmeritve in podstrani <i>niso</i> prikazane.",
+
+
+# Miscellaneous special pages
+#
+"orphans"      => "Siromačne strani",
+"lonelypages"  => "Siromačne strani",
+"unusedimages" => "Neuporabljene strani",
+"popularpages" => "Priljubljene strani",
+"nviews"       => "$1 krat pregledano",
+"wantedpages"  => "Želene strani",
+"nlinks"       => "$1 povezav",
+"allpages"     => "Vse strani",
+"randompage"   => "Naključna stran",
+"shortpages"   => "Kratke strani",
+"longpages"    => "Dolge strani",
+"listusers"    => "Seznam uporabnikov",
+"specialpages" => "Posebne strani",
+"spheading"    => "Posebne strani za vse uporabnike",
+"protectpage"  => "Zaščiti stran",
+"recentchangeslinked" => "Povezane strani",
+"rclsub"       => "(na strani povezano od \"$1\")",
+"debug"                => "Razhroščuj",
+"newpages"     => "Nove strani",
+"movethispage" => "Premakni to stran",
+"unusedimagestext" => "<p>Prosimo upoštevajte, da so lahko druge spletne strani, kot so mednarodne Wikipedije povezane s sliko z neposrednim URL-jem in so tukaj navedene, navkljub aktivni uporabi.",
+"booksources"  => "Knjižni viri",
+"booksourcetext" => "Spodaj je seznam k drugim stranem, ki prodajajo nove ali rabljene knjige in kjer so lahko dodatne informacije o knjigah, ki jih iščete.
+Wikipedija ne služi z nobenim od teh poslov in ta spisek ni pokazatelj njihovih uspehov.",
+
+# Email this user
+#
+"mailnologin"  => "Ni naslova odpošiljatelja",
+"mailnologintext" => "Morate biti [[Special:Userlogin|prijavljeni]]
+in imeti veljaven naslov e-pošte v vaših [[Special:Preferences|nastavitvah]],
+da lahko pošljete pošto drugim uporabnikom.",
+"emailuser"    => "Pošlji e-pošto temu uporabniku",
+"emailpage"    => "Pošlji e-pošto uporabniku",
+"emailpagetext"        => "Če je ta uporabnik vnesel veljaven naslov e-pošte v svojih ali njenih nastavitvah, bo spodnji vprašalnik poslal sporočilo.
+Naslov e-pošte, ki ste jo vnesli v vaših uporabniških nastavitvah, bo v
+ \"From\" naslovu pošte in bo lahko prejemnik odgovoril nanjo.",
+"noemailtitle" => "Ni naslova e-pošte",
+"noemailtext"  => "Ta uporabnik ni navedel veljavnega naslova e-pošte, ali pa se je odločil, da ne bo prejemal pošte drugih.",
+"emailfrom"    => "Od",
+"emailto"      => "Za",
+"emailsubject" => "Tema",
+"emailmessage" => "Sporočilo",
+"emailsend"    => "Pošlji",
+"emailsent"    => "E-pošta poslana",
+"emailsenttext" => "Vaše sporočilo je poslano z e-pošto.",
+
+# Watchlist
+#
+"watchlist"    => "Moj spisek nadzorov",
+"watchlistsub" => "(za uporabnika \"$1\")",
+"nowatchlist"  => "Na vašem spisku nadzorov ni nobenega članka.",
+"watchnologin" => "Niste prijavljeni",
+"watchnologintext" => "Morate biti [[Special:Userlogin|prijavljeni]]
+za spremembo seznama nadzorov.",
+"addedwatch"   => "Dodano k seznamu nadzorov",
+"addedwatchtext" => "Stran \"$1\" je dodana na vaš <a href=\"" .
+  "{{localurle:Special:Watchlist}}\">seznam nadzorov</a>.
+Morebitne spremembe te strani in njena pripadajoča pogovorna stran bosta navedeni tam in stran bo prikazana <b>krepko</b> v <a href=\"" .
+  "{{localurle:Special:Recentchanges}}\">seznamu trenutnih sprememb</a>, da jo boste tudi lažje izbrali.</p>
+<p>Če želite kasneje odstraniti stran iz seznama nadzorov, pritisnite \"Prekini nadzor\" v stranski vrstici.",
+"removedwatch" => "Odstranjena iz seznama nadzorov",
+"removedwatchtext" => "Stran \"$1\" je odstranjena iz vašega seznama nadzorov.",
+"watchthispage"        => "Nadzoruj to stran",
+"unwatchthispage" => "Prekini nadzor",
+"notanarticle" => "Ni članek",
+
+# Delete/protect/revert
+#
+"deletepage"   => "Zbriši stran",
+"confirm"      => "Potrdi",
+"excontent"     => "vsebina je bila: '$1'",
+"exbeforeblank" => "vsebina pred brisanjem je bila: '$1'",
+"exblank"       => "stran je bila prazna",
+"confirmdelete" => "Potrdi brisanje",
+"deletesub"    => "(Brišem \"$1\")",
+"historywarning" => "OPOZORILO: stran, ki jo želite brisati ima zgodovino: ",
+"confirmdeletetext" => "Za stalno boste zbrisali stran ali sliko skupaj z zgodovino iz podatkovne baze.
+Prosimo potrdite vaš namen, da razumete posledice in da to počnete v skladu s [[Wikipedija:Pravila|pravili]].",
+"actioncomplete" => "Poseg zaključen",
+"deletedtext"   => "\"$1\" je zbrisana.
+Glej $2 za zabeležbe nadavnih brisanj.",
+"deletedarticle" => "zbrisan \"$1\"",
+"dellogpage"    => "Dnevnik_brisanja",
+"dellogpagetext" => "Spodaj je seznam nedavnih brisanj.
+Vsi časi so časi strežnika (UTC).
+<ul>
+</ul>
+",
+"deletionlog"  => "dnevnik brisanja",
+"reverted"     => "Sprememba v prejšnjo različico",
+"deletecomment"        => "Razlog za brisanje",
+"imagereverted" => "Sprememba v prejšnjo različico je bila uspešna.",
+"rollback"     => "Vrni spremembe",
+"rollbacklink" => "vrni",
+"cantrollback" => "Ne morem vrniti ureditve; zadnji avtor je hkrati edini.",
+"alreadyrolled" => "Ne morem vrniti zadnje spremembe [[$1]]
+od uporabnika [[Uporabnik:$2|$2]] ([[Pogovor z uporabnikom:$2|Pogovor]]); nekdo drug je že spremenil ali vrnil članek.
+
+Zadnja sprememba od uporabnika [[Uporabnik:$3|$3]] ([[Pogovor z uporabnikom:$3|Pogovor]]). ",
+#   only shown if there is an edit comment
+"editcomment"  => "Tolmač spremembe je: \"<i>$1</i>\".",
+"revertpage"   => "Vrnjeno na zadnje urejevanje od $1",
+
+# Undelete
+"undelete" => "Obnovi zbrisano stran",
+"undeletepage" => "Poglej in obnovi zbrisane strani",
+"undeletepagetext" => "Naslednje strani so bile zbrisane, vendar so še vedno v arhivu in jih lahko obnovite. Arhiv se mora občasno počistiti.",
+"undeletearticle" => "Obnovi zbrisan članek",
+"undeleterevisions" => "$1 različic arhiviranih",
+"undeletehistory" => "Če obnovite stran, se bodo obnovile vse različice v zgodovini.
+Če je kdo od brisanja naredil novo stran z istim imenom, se bodo obnovljene različice pojavile v prejšnji zgodovini in trenutna različica žive strani se ne bo samodejno zamenjala.",
+"undeleterevision" => "Zbrisana različica od $1",
+"undeletebtn" => "Obnovi!",
+"undeletedarticle" => "obnovljen \"$1\"",
+"undeletedtext"   => "Članek [[$1]] se je uspešno obnovil.
+Glej [[Wikipedija:Dnevnik_brisanja]] za zabeležbe nedavnih brisanj in obnovitev.",
+
+# Contributions
+#
+"contributions"        => "Prispevki uporabnika",
+"mycontris"     => "Moji prispevki",
+"contribsub"   => "Za $1",
+"nocontribs"   => "Ne najdem nobene spremembe, ki ustreza tem sodilom.",
+"ucnote"       => "Spodaj je zadnjih <b>$1</b> sprememb tega uporabnika v zadnjih <b>$2</b> dnevih.",
+"uclinks"      => "Poglej zadnjih $1 sprememb; poglej zadnje $2 dni.",
+"uctop"                => " (vrh)" ,
+
+# What links here
+#
+"whatlinkshere"        => "Kaj je povezano sem",
+"notargettitle" => "Ni tarče",
+"notargettext" => "Niste navedli ciljne strani ali uporabnika za izvršitev te funkcije.",
+"linklistsub"  => "(Seznam povezav)",
+"linkshere"    => "Naslednje strani so povezane sem:",
+"nolinkshere"  => "Nobena stran ni povezana sem.",
+"isredirect"   => "preusmeritvena stran",
+
+# Block/unblock IP
+#
+"blockip"      => "Prekini IP naslov",
+"blockiptext"  => "Uporabi spodnjo obliko za prekinitev dostopa zapisa iz določenega IP naslova.
+To naredimo samo zaradi zaščite pred nepotrebnim uničevanjem in v skladu s
+[[Wikipedija:Pravila|pravili Wikipedije]].
+Vnesi razloge spodaj (na primer z navedbo določenih strani, ki so jih po nepotrebnem uničili).",
+"ipaddress"    => "IP naslov",
+"ipbreason"    => "Razlog",
+"ipbsubmit"    => "Prekini ta naslov",
+"badipaddress" => "IP naslov je slabo oblikovan.",
+"blockipsuccesssub" => "Prekinitev je uspela",
+"blockipsuccesstext" => "IP naslov \"$1\" je prekinjen.
+<br />Glej [[Posebno:Ipseznamprekinitev|seznam prekinitev IP]] za pregled prekinitev.",
+"unblockip"    => "Poveži IP naslov",
+"unblockiptext"        => "Uporabi spodnjo obliko za obnovitev dostopa zapisa prejšnjega prekinjenega IP naslova.",
+"ipusubmit"    => "Poveži ta naslov",
+"ipusuccess"   => "IP naslov \"$1\" je povezan",
+"ipblocklist"  => "Seznam prekinjenih IP naslovov",
+"blocklistline"        => "$1, $2 je prekinil $3 ($4)",
+"blocklink"    => "prekini",
+"unblocklink"  => "poveži",
+"contribslink" => "prispevki",
+"autoblocker" => "Samodejno se prekinili, ker si delite IP naslov z \"$1\". Razlog \"$2\".",
+
+
+# Developer tools
+#
+"lockdb"       => "Zakleni podatkovno bazo",
+"unlockdb"     => "Odkleni podatkovno bazo",
+"lockdbtext"   => "Zaklenitev podatkovne baze bo odložila možnost urejevanja vsem uporabnikom, spremembe njihovih nastavitev, urejevanja njihovih seznamov nadzorov in drugih stvari, ki zahtevajo spremembe v podatkovni bazi.
+Prosimo potrdite vaš resnični namen in da boste odklenili podatkovno bazo, ko boste zaključili z vzdrževanjem podatkovne baze.",
+"unlockdbtext" => "Odklenitev podatkovne baze bo obnovila zmožnost urejevanja vsem uporabnikom, spremembe njihovih nastavitev, urejevanja njihovih seznamov nadzorov in drugih stvari, ki zahtevajo spremembe v podatkovni bazi.
+Prosimo potrdite vaš resnični namen.",
+"lockconfirm"  => "Da, resnično želim zakleniti podatkovno bazo.",
+"unlockconfirm"        => "Da, resnično želim odkleniti podatkovno bazo.",
+"lockbtn"      => "Zakleni podatkovno bazo",
+"unlockbtn"    => "Odkleni podatkovno bazo",
+"locknoconfirm" => "Niste potrdili svoje namere.",
+"lockdbsuccesssub" => "Zaklenitev podatkovne baze je uspela",
+"unlockdbsuccesssub" => "Podatkovna baza je odklenjena",
+"lockdbsuccesstext" => "Podatkovna baza Wikipedije je bila zaklenjena.
+<br />Ne pozabite odkleniti, ko boste končali z vzdrževanjem.",
+"unlockdbsuccesstext" => "Podatkovna baza Wikipedije je bila odklenjena.",
+
+# Move page
+#
+"movepage"     => "Prestavi stran",
+"movepagetext" => "Uporaba spodnje oblike bo preimenovala stran, prestavila vso njeno zgodovino na novo ime.
+Stara stran bo preusmeritvena stran na nov naslov.
+Povezave na stari naslov strani se ne bodo spremenile; zagotovo [[Posebno:Vzdrževanje|preverite]] dvojne ali pretrgane preusmeritve.
+Odgovorni ste, da povezave še naprej kažejo na pravilna mesta.
+
+Upoštevajte, da stran '''ne''' bo prestavljena, če stran z istim imenom že obstaja, razen če je prazna ali preusmeritvena in je brez zgodovine urejevanj. To pomeni, da lahko preimenujete stran nazaj na prejšnjo, če ste se zmotili in ne morete prepisati obstoječe strani.
+
+<b>OPOZORILO!</b>
+To je lahko velika in nepričakovana sprememba za priljubljeno stran;
+prosimo bodite prepričani, da razumete posledice tega, preden nadaljujete.",
+"movepagetalktext" => "Pripadajoča pogovorna stran bo tudi samodejno prestavljena '''razen:'''
+*Če prestavljate stran preko imenskih področij,
+*Če že obstaja neprazna pogovorna stran pod istim imenom, ali
+*Odkljukajte spodnji okvirček.
+
+V teh primerih boste morali prestaviti ali povezati stran ročno, če to želite.",
+"movearticle"  => "Prestavite stran",
+"movenologin"  => "Niste vpisani",
+"movenologintext" => "Za prestavitev strani morate biti zabeležen uporabnik in [[Special:Userlogin|prijavljeni]].",
+"newtitle"     => "Na nov naslov",
+"movepagebtn"  => "Prestavite stran",
+"pagemovedsub" => "Prstavitev uspela",
+"pagemovedtext" => "Stran \"[[$1]]\" prestavljena na \"[[$2]]\".",
+"articleexists" => "Stran s tem imenom že obstaja ali pa izbrano ime ni pravilno. Prosimo izberite drugo ime.",
+"talkexists"   => "Stran sama je prestavljena uspešno, pogovorna stran pa ne, ker že obstaja na novem naslovu. Prosimo povežite ju ročno.",
+"movedto"      => "prestavljeno na",
+"movetalk"     => "Prestavite tudi \"pogovorno\" stran, če je mogoče.",
+"talkpagemoved" => "Pripadajoča pogovorna stran je tudi prestavljena.",
+"talkpagenotmoved" => "Pripadajoča pogovorna stran <strong>ni</strong> prestavljena.",
+# Math
+'mw_math_png' => "Vedno prikaži PNG",
+'mw_math_simple' => "Če je dovolj preprosto, uporabi HTML, drugače pa PNG",
+'mw_math_html' => "Uporabi HTML, če je možno, drugače pa PNG",
+'mw_math_source' => "Pusti v TeX-ovi obliki (za tekstovne brskljalnike)",
+'mw_math_modern' => "Priporočeno za sodobne brskljalnike",
+'mw_math_mathml' => 'MathML',
+
+);
+
+#--------------------------------------------------------------------------
+# Internationalisation code
+#--------------------------------------------------------------------------
+
+class LanguageSl extends LanguageUtf8 {
+
+       function getNamespaces() {
+               global $wgNamespaceNamesSl;
+               return $wgNamespaceNamesSl;
+       }
+
+
+       function getNsIndex( $text ) {
+               global $wgNamespaceNamesSl;
+
+               foreach ( $wgNamespaceNamesSl as $i => $n ) {
+                       if ( 0 == strcasecmp( $n, $text ) ) { return $i; }
+               }
+               if( 0 == strcasecmp( "Special", $text ) ) { return -1; }
+               if( 0 == strcasecmp( "User", $text ) ) { return 2; }
+               if( 0 == strcasecmp( "Wikipedia", $text ) ) { return 4; }
+               return false;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsSl;
+               return $wgQuickbarSettingsSl;
+       }
+
+       function getDateFormats() {
+               global $wgDateFormatsSl;
+               return $wgDateFormatsSl;
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesSl;
+               if(array_key_exists($key, $wgAllMessagesSl))
+                       return $wgAllMessagesSl[$key];
+               else
+                       return parent::getMessage($key);
+       }
+
+       function fallback8bitEncoding() {
+               return "iso-8859-2";
+       }
+
+       function formatNum( $number, $year = false ) {
+               return $year ? $number : strtr($this->commafy($number), '.,', ',.' );
+       }
+}
+
+?>
diff --git a/languages/LanguageSq.php b/languages/LanguageSq.php
new file mode 100644 (file)
index 0000000..838b9a5
--- /dev/null
@@ -0,0 +1,989 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+require_once("LanguageUtf8.php");
+
+/* private */ $wgNamespaceNamesSq = array(
+       NS_MEDIA          => "Media",
+       NS_SPECIAL        => "Speciale",
+       NS_MAIN           => "",
+       NS_TALK           => "Diskutim",
+       NS_USER           => "Përdoruesi",
+       NS_USER_TALK      => "Përdoruesi_diskutim",
+       NS_PROJECT        => $wgMetaNamespace,
+       NS_PROJECT_TALK   => $wgMetaNamespace . "_diskutim",
+       NS_IMAGE          => "Figura",
+       NS_IMAGE_TALK     => "Figura_diskutim",
+       NS_MEDIAWIKI      => "MediaWiki",
+       NS_MEDIAWIKI_TALK => "MediaWiki_diskutim",
+       NS_TEMPLATE       => "Stampa",
+       NS_TEMPLATE_TALK  => "Stampa_diskutim",
+       NS_HELP           => 'Ndihmë',
+       NS_HELP_TALK      => 'Ndihmë_diskutim'
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgQuickbarSettingsSq = array(
+       "Asgjë", "Lidhur majtas", "Lidhur djathtas", "Fluturo majtas"
+);
+
+/* private */ $wgSkinNamesSq = array(
+       'standard' => "Standarte",
+       'nostalgia' => "Nostalgjike",
+       'cologneblue' => "Kolonjë Blu"
+) + $wgSkinNamesEn;
+
+
+/* private */ $wgDateFormatsSq = array(
+#      "Pa preferencë",
+);
+
+/* private */ $wgAllMessagesSq = array(
+
+# User Toggles
+
+"tog-underline" => "Nënvizo lidhjet",
+"tog-highlightbroken" => "Trego lidhjet e faqeve bosh <a href=\"\" class=\"new\">kështu </a> (ndryshe: kështu<a href=\"\" class=\"internal\">?</a>).",
+"tog-justify"  => "Rregullim i kryeradhës",
+"tog-hideminor" => "Fshih redaktimet e vogla në ndryshimet e fundit",
+"tog-usenewrc" => "Ndryshimet e fundit me formatin e ri (jo për të gjithë shfletuesit)",
+"tog-numberheadings" => "Numëro automatikish mbishkrimet",
+"tog-showtoolbar" => "Show edit toolbar",
+"tog-editondblclick" => "Redakto faqet me dopjo-shtypje (JavaScript)",
+"tog-editsection"=>"Lejo redaktimin e seksioneve me [redakto] lidhje",
+"tog-editsectiononrightclick"=>"Lejo redaktimin e seksioneve me djathtas-shtypje<br /> mbi emrin e seksionit (JavaScript)",
+"tog-showtoc"=>"Trego tabelën e përmbajtjeve<br />(për faqet me më shume se 3 tituj)",
+"tog-rememberpassword" => "Mbaj mënd fjalëkalimin për vizitën e ardhshme",
+"tog-editwidth" => "Kutija e redaktimit ka gjerësi te plotë",
+"tog-watchdefault" => "Shto faqet që redakton tek lista mbikqyrëse",
+"tog-minordefault" => "Shëno të gjitha redaktimet si të vogla automatikisht",
+"tog-previewontop" => "Trego parashikimin përpara kutisë redaktuese, jo mbas saj",
+"tog-nocache" => "Mos ruaj kopje te faqeve",
+
+# Dates
+#
+
+'sunday' => 'E Djelë',
+'monday' => 'E Hënë',
+'tuesday' => 'E Martë',
+'wednesday' => 'E Mërkurë',
+'thursday' => 'E Enjte',
+'friday' => 'E Premte',
+'saturday' => 'E Shtunë',
+'january' => 'Janar',
+'february' => 'Shkurt',
+'march' => 'Mars',
+'april' => 'Prill',
+'may_long' => 'Maj',
+'june' => 'Qershor',
+'july' => 'Korrik',
+'august' => 'Gusht',
+'september' => 'Shtator',
+'october' => 'Tetor',
+'november' => 'Nëntor',
+'december' => 'Dhjetor',
+'jan' => 'Jan',
+'feb' => 'Shk',
+'mar' => 'Mar',
+'apr' => 'Pri',
+'may' => 'Maj',
+'jun' => 'Qer',
+'jul' => 'Kor',
+'aug' => 'Gus',
+'sep' => 'Sht',
+'oct' => 'Tet',
+'nov' => 'Nën',
+'dec' => 'Dhj',
+
+# Bits of text used by many pages:
+#
+"linktrail"            => "/^([a-z]+)(.*)\$/sD",
+"mainpage"             => "Faqja Kryesore",
+"mainpagetext" => "Wiki software u instalua me sukses.",
+"about"                        => "Rreth",
+"aboutsite"      => "Rreth {{SITENAME}}",
+"aboutpage"            => "{{ns:project}}:Rreth",
+"help"                 => "Ndihmë",
+"helppage"             => "{{ns:project}}:Ndihmë",
+"bugreports"   => "Raporto yçkla",
+"bugreportspage" => "{{ns:project}}:Raporto_yçkla",
+"sitesupport"   => "Dhurime",
+"faq"                  => "Pyetje e Përgjigje",
+"faqpage"              => "{{ns:project}}:Pyetje_e_Përgjigje",
+"edithelp"             => "Ndihmë për redaktim",
+"edithelppage" => "{{ns:project}}:Si_redaktohet_një_faqe",
+"cancel"               => "Harroje",
+"qbfind"               => "Kërko",
+"qbbrowse"             => "Shfleto",
+"qbedit"               => "Redakto",
+"qbpageoptions" => "Opsionet e faqes",
+"qbpageinfo"   => "Informacion mbi faqen",
+"qbmyoptions"  => "Opsionet e mia",
+"mypage"               => "Faqja ime",
+"mytalk"               => "Diskutimet e mia",
+"currentevents" => "Evenimente",
+"errorpagetitle" => "Gabim",
+"returnto"             => "Kthehu tek $1.",
+"tagline"              => "Nga {{SITENAME}}, Enciklopedia e Lirë.", # FIXME
+"whatlinkshere"        => "Lidhjet këtu ",
+"help"                 => "Ndihmë",
+"search"               => "Kërko",
+"go"           => "Shko",
+"history"              => "Histori e faqes",
+"printableversion" => "Version i shtypshëm",
+"editthispage" => "Redakto faqen",
+"deletethispage" => "Grise faqen",
+"protectthispage" => "Mbroje faqen",
+"unprotectthispage" => "Liroje faqen",
+"newpage" => "Faqe e re",
+"talkpage"             => "Diskuto faqen",
+"postcomment"   => "Bëj koment",
+"articlepage"  => "Shiko artikullin",
+"subjectpage"  => "Shiko subjektin", # For compatibility
+"userpage" => "Shiko faqen",
+"wikipediapage" => "Shiko faqen meta",
+"imagepage" =>         "Shiko faqen e figurës",
+"viewtalkpage" => "Shiko diskutimin",
+"otherlanguages" => "Gjuhë të tjera",
+"redirectedfrom" => "(Ridrejtuar nga $1)",
+"lastmodified" => "Kjo faqe është ndryshuar për herë te fundit më $1.",
+"viewcount"            => "Kjo faqe është parë $1 herë.",
+"printsubtitle" => "(Nga {{SERVER}})",
+"protectedpage" => "Faqe e mbrojtur",
+"administrators" => "{{ns:project}}:Administruesit",
+"sysoptitle"   => "Nevojitet titulli sysop",
+"sysoptext"            => "Veprimi që kerkove mund të bëhet vetëm nga një përdorues me titullin \"sysop\". Shiko $1.",
+"developertitle" => "Nevojitet titulli zhvillues",
+"developertext"        => "Veprimi që kërkove mund bëhet vetëm nga një përdorues me titullin \"zhvillues\". Shiko $1.",
+"nbytes"               => "$1 bytes",
+"go"                   => "Shko",
+"ok"                   => "Shko",
+"sitetitle"            => '{{SITENAME}}',
+"sitesubtitle" => "Enciklopedia e Lirë",
+"retrievedfrom" => "Marrë nga \"$1\"",
+"newmessages" => "Ti ke $1.",
+"newmessageslink" => "mesazhe të reja",
+"editsection"=>"redakto",
+"toc" => "Tabela e përmbajtjeve",
+"showtoc" => "trego",
+"hidetoc" => "fshih",
+"thisisdeleted" => "Shiko ose restauro $1?",
+"restorelink" => "$1 redaktimet e prishura",
+
+# Main script and global functions
+#
+"nosuchaction" => "Nuk ekziston ky veprim",
+"nosuchactiontext" => "Veprimi i caktuar nga URL nuk
+njihet nga wiki software",
+"nosuchspecialpage" => "Nuk ekziston kjo faqe",
+"nospecialpagetext" => "Ti ke kërkuar një faqe speciale që nuk
+njihet nga wiki software.",
+
+# General errors
+#
+"error"                        => "Gabim",
+"databaseerror" => "Gabim rregjistri",
+"dberrortext"  => "Ka ndodhur një gabim me pyetjen e rregjistrit.
+Pyetja e fundit qe ti i bëre rregjistrit ishte:
+<blockquote><tt>$1</tt></blockquote>
+nga funksioni \"<tt>$2</tt>\".
+MySQL kthehu gabimin \"<tt>$3: $4</tt>\".",
+"dberrortextcl" => "Ka ndodhur një gabim me formatin e pyetjes së rregjistrit.
+Pyetja e fundit qe ti i bëre rregjistrit ishte:
+\"$1\"
+nga funksioni \"$2\".
+MySQL kthehu gabimin \"$3: $4\".\n",
+"noconnect"            => "Ju kërkojmë ndjesë! Difekt teknik, rifillojmë së shpejti.",
+"nodb"                 => "Nuk mund të zgjidhte rregjistrin $1",
+"cachederror"  => "Kjo është një kopje e faqes së kërkuar dhe mund të jetë e vjetër.",
+"readonly"             => "Rregjistri i bllokuar",
+"enterlockreason" => "Fut një arsye për bllokimin, gjithashtu fut edhe kohën se kur
+pritet të ç'bllokohet",
+"readonlytext" => "Rregjistri {{SITENAME}} është i bllokuar dhe nuk lejohen redaktime dhe
+artikuj të ri, ka mundësi të jetë bllokuar për mirëmbajtje,
+dhe do të kthehe në gjëndje normale mbas mirëmbajtjes.
+Administruesi i cili e bllokoi dha këtë arsye:
+<p>$1",
+"missingarticle" => "Rregjistri nuk e gjeti tekstin e faqes
+që duhet të kishte gjetur, të quajtur \"$1\".
+
+<p>Kjo ndodh zakonisht kur ndjek një ndryshe ose histori lidhje tek një
+faqe që është grisur.
+
+<p>Në qoftë se ky nuk është rasti, atëherë ti mund të kesh gjetur një yçkël në softuerin.
+Tregoja këtë përmbledhje një administruesi, duke shënuar edhe URL-in.",
+"internalerror" => "Gabim i brëndshëm",
+"filecopyerror" => "Nuk mundi të kopjojë skedarin \"$1\" tek \"$2\".",
+"filerenameerror" => "Nuk mundi të ndërrojë emrin e skedarit \"$1\" në \"$2\".",
+"filedeleteerror" => "Nuk mundi të grisi skedarin \"$1\".",
+"filenotfound" => "Nuk mundi të gjejë skedarin \"$1\".",
+"unexpected"   => "Vlerë e papritur: \"$1\"=\"$2\".",
+"formerror"            => "Gabim: nuk mundi të dërgojë formularin",
+"badarticleerror" => "Ky veprim nuk mund të bëhet në këtë faqe.",
+"cannotdelete" => "Nuk mundi të grisi këtë faqe ose figurë të dhënë. (Ka mundësi të jetë grisur nga dikush tjeter.)",
+"badtitle"             => "Titull i keq",
+"badtitletext" => "Titulli i faqes që kërkove nuk është ishte saktë, ishte bosh, ose
+ishte një lidhje gabim me një titull wiki internacional.",
+"perfdisabled" => "Ju kërkojmë ndjesë! Ky veprim është bllokuar përkohsisht
+sepse e ngadalëson rregjistrin aq shumë sa nuk e përdor dot njeri tjetër.",
+"perfdisabledsub" => "Kjo është nje kopje e ruajtur nga $1:",
+"viewsource" => "Shiko tekstin",
+"protectedtext" => "Kjo faqe është e mbrojtur që të mos redaktohet; mund të ketë
+disa arsye përse kjo është bërë, të lutem shiko
+[[{{ns:project}}:Faqe e mbrojtur]].
+
+Mund të shikosh dhe kopjosh tekstin e kësaj faqeje:",
+
+# Login and logout pages
+#
+"logouttitle"  => "Përdoruesi doli",
+"logouttext"   => "Tani ti ke dalë jashtë.
+Mund të vazhdosh të përdorësh {{SITENAME}} anonimisht, ose mund të hysh brënda
+përsëri me emrin që kishe ose me një emër tjetër.\n",
+
+"welcomecreation" => "<h2>Mirë se erdhe, $1!</h2><p>Llogaria jote ështe hapur.
+Mos harro të vendosësh preferimet e tua të uikipedias.",
+
+"loginpagetitle" => "Hyrje përdoruesi",
+"yourname"             => "Fut emrin tënd",
+"yourpassword" => "Fut fjalëkalimin tënd",
+"yourpasswordagain" => "Fut fjalëkalimin përsëri",
+"newusersonly" => " (përdoruesit e rinj vetëm)",
+"remembermypassword" => "Mbaj mënd fjalëkalimin tim për tërë vizitat e ardhshme.",
+"loginproblem" => "<b>Kishte një problem me hyrjen tënde.</b><br />Provoje përsëri!",
+"alreadyloggedin" => "<strong>Përdorues $1, ti ke hyrë brënda më parë!</strong><br />\n",
+
+"login"                        => "Hyrje",
+"userlogin"            => "Hyrje",
+"logout"               => "Dalje",
+"userlogout"   => "Dalje",
+"notloggedin"  => "Nuk ke hyrë brënda",
+"createaccount"        => "Hap një llogari",
+"badretype"            => "Fjalëkalimet nuk janë njësoj.",
+"userexists"   => "Emri që përdore është në përdorim. Zgjidh një emër tjetër.",
+"youremail"            => "Adresa e email-it*",
+"yournick"             => "Nofka jote (për firmosje)",
+"emailforlost" => "* Futja e email-it nuk është e detyrueshme. Por lejon përdorues të tjerë
+të të kontaktojnë nëpërmjet faqes pa u treguar adresën, gjithashtu kjo adresë
+është e dobishme n.q.s. harron fjalëkalimin",
+"loginerror"   => "Gabim hyrje",
+"noname"               => "Nuk ke dhënë një emër të saktë.",
+"loginsuccesstitle" => "Hyrje me sukses",
+"loginsuccess" => "Tani ke hyrë brënda në {{SITENAME}} si \"$1\".",
+"nosuchuser"   => "Nuk ka ndonjë përdorues me emrin \"$1\".
+Kontrollo gërmat, ose përdor formularin e mëposhtëm për të hapur një llogari të re.",
+"wrongpassword"        => "Fjalëkalimi që fute nuk është i saktë. Provoje përsëri!",
+"mailmypassword" => "Më dërgo një fjalëkalim të ri tek adresa ime",
+"passwordremindertitle" => "Kujtim për fjalëkalimin nga {{SITENAME}}",
+"passwordremindertext" => "Dikush (ndoshta ti, nga IP adresa $1)
+kërkojë që të dërgojmë një fjalëkalim hyrje të ri për {{SITENAME}}.
+Fjalëkalimi për përdoruesin \"$2\" tani është \"$3\".
+Duhet të hysh përsëri dhe të ndërrosh fjalëkalimin tënd menjëherë.",
+"noemail"              => "Rregjistri nuk ka adresë për përdoruesin \"$1\".",
+"passwordsent" => "Një fjalëkalim i ri është dërguar tek adresa e rregjistruar për \"$1\".
+Hyni përsëri mbasi ta kesh marrë.",
+
+# Edit pages
+#
+"summary"              => "Përmbledhje",
+"subject"              => "Subjekt/Titull",
+"minoredit"            => "Ky është një redaktim i vogël",
+"watchthis"            => "Mbikqyr këtë faqe",
+"savearticle"  => "Kryej ndryshimin",
+"preview"              => "Parashiko",
+"showpreview"  => "Trego parashikimin",
+"blockedtitle" => "Përdoruesi është bllokuar",
+"blockedtext"  => "Emri yt ose adresa e IP-së është bllokuar nga $1.
+Arsyeja e dhënë është kjo:<br />''$2''<p>Mund të kontaktosh $1 ose një nga
+[[{{ns:project}}:Administruesit|administruesit]] e tjerë për të diskutuar bllokimin.
+
+Vë re, nuk mund të përdorësh \"dërgoji email këtij përdoruesi\" n.q.s. nuk ke një adresë të saktë
+të rregjistruar në [[Speciale:Preferences|preferimet e përdoruesit]].
+
+Adresa e IP-së që ke është $3. Na e jep këtë adresë në çdo ankesë.
+
+==Shënim për përdoruesit e AOL-it==
+Për shkak të vandalizmeve të një përdoruesit të AOL-it, Uikipedia shpesh bllokon AOL ndërmjetse. Për fat të keq, një ndërmjetse shërbyese mund të jetë duke u përdorur nga një numër i madh njerëzish, prandaj shpesh disa përdorues të pafajshëm të AOL-its bllokohen. Ju kërkojmë ndjesë për çdo problem që ka ndodhur.
+
+Në qoftë se kjo të ndodh ty, të lutem njoftoni një administrues duke përdorur një adresë AOL-i. Gjithashtu dërgoni edhe adresën e IP-së dhënë mësipër.",
+"newarticle"   => "(I Ri)",
+"newarticletext" =>
+"Ke ndjekur një lidhje tek një faqe që nuk ekziston akoma.
+Për ta krijuar këtë faqe, fillo të shtypësh në kutinë poshtë
+(shiko [[{{ns:project}}:Ndihmë|faqen ndihmuese]] për më shumë informacion).
+Në qoftë se je këtu gabimisht, thjesht shtyp butonin '''Back''' të shfletuesit tuaj.",
+"anontalkpagetext" => "---- ''Kjo është një faqe diskutimi për një përdorues anonim i cili nuk ka hapur akoma një llogari ose nuk e përdor atë. Prandaj, neve na duhet të përdorim numrin e adresës [[IP adresë|IP]] për ta identifikuar. Kjo adresë mund të përdoret nga disa njerëz. Në qoftë se ti je një përdorues anonim dhe mendon se komente kot janë drejtuar ndaj teje, të lutem [[Speciale:Userlogin|krijo një llogari ose hyni brënda]] për të mos
+u ngatarruar me përdorues të tjerë anonim.'' ",
+"noarticletext" => "(Tani për tani, nuk ka tekst në këtë faqe)",
+"updated"              => "(E ndryshuar)",
+"note"                 => "<strong>Shënim:</strong> ",
+"previewnote"  => "Kini kujdes se ky është vetëm një parashikim, nuk është ruajtur akoma!",
+"previewconflict" => "Ky parashikim reflekton tekstin sipër
+kutisë së redaktimit siç do të duket kur ta ruani.",
+"editing"              => "Duke redaktuar $1",
+"editingsection"       => "Duke redaktuar $1 (seksion)",
+"editingcomment"       => "Duke redaktuar $1 (koment)",
+"editconflict" => "Konflikt redaktimi: $1",
+"explainconflict" => "Dikush tjetër ka ndryshuar këtë faqe kur ti po e
+redaktoje.
+Kutija e redaktimit mësipër tregon tekstin e faqes siç ekziston tani.
+Nryshimet e tua janë treguar poshtë kutisë së redaktimit.
+Të duhet të përputhësh ndryshimet e tua me tekstin ekzistues.
+<b>Vetëm</b> teksti në kutinë e sipërme të redaktimit do të ruhet kur ti
+të shtypësh \"Ruaje faqen\".\n<p>",
+"yourtext"             => "Teksti yt",
+"storedversion" => "Versioni i ruajtur",
+"editingold"   => "<strong>KUJDES: Po redakton një version të vjetër të kësaj faqeje.
+Në qoftë se e ruan, çdo ndryshim i bërë deri tani do të humbet.</strong>",
+"yourdiff"             => "Ndryshimet",
+# REPLACE THE COPYRIGHT WARNING IF YOUR SITE ISN'T GFDL!
+"copyrightwarning" => "Të lutem vë re që të gjitha kontributet tek {{SITENAME}} janë
+të konsideruara të dhëna nën liçensën GNU Free Documentation License
+(shiko $1 për detaje).
+Në qoftë se nuk dëshiron që kontributet e tua të redaktohen pa mëshirë dhe të jepen
+kudo, atëherë mos i jep këtu.<br />
+Gjithashtu, ti po na premton që i ke shkruajtur vetë këto, ose i ke kopjuar nga një
+vënd public (public domain) ose diçka e ngjashme e lirë.
+<strong>MOS JEPNI PUNIME QE JANE NEN COPYRIGHT PA PASUR LEJE!</strong>",
+"longpagewarning" => "<strong>KUJDES: Kjo faqe është $1 kilobytes e gjatë; disa
+shfletues mund të kenë probleme për të redaktuar faqe që afrohen ose janë akoma më shumë se 32kb.
+Konsidero ta ndash faqen në disa seksione më të vogla.</strong>",
+"readonlywarning" => "<strong>KUJDES: Rregjistri është bllokuar për mirëmbajtje,
+kështuqë nuk do kesh mundësi të ruash redaktimet e tua tani. Mund të kopjosh dhe ruash tekstin
+në një skedar për më vonë.</strong>",
+"protectedpagewarning" => "<strong>KUJDES:  Kjo faqe është bllokuar kështuqë vetëm përdorues me titullin
+
+sysop mund ta redaktojnë. Ndiq rregullat e dhëna tek
+[[Project:Rregullat_për_faqe_të_bllokuara|faqet e bllokuara]].</strong>",
+
+# History pages
+#
+"revhistory"   => "Historia e redaktimeve",
+"nohistory"            => "Nuk ka histori redaktimesh për këtë faqe.",
+"revnotfound"  => "Versioni nuk u gjet",
+"revnotfoundtext" => "Versioni i vjetër i faqes së kërkuar nuk mund të gjehej.
+Të lutem kontrollo URL-in që përdore për të ardhur tek kjo faqe.\n",
+"loadhist"             => "Duke karikuar historinë e faqes",
+"currentrev"   => "Versioni i tanishëm",
+"revisionasof" => "Versioni i $1",
+"cur"                  => "tani",
+"next"                 => "mbas",
+"last"                 => "fund",
+"orig"                 => "parë",
+"histlegend"   => "Legjenda: (tani) = ndryshimet me versionin e tanishëm,
+(fund) = ndryshimet me versionin e parardhshëm, V = redaktim i vogël",
+
+# Diffs
+#
+"difference"   => "(Ndryshime midis versioneve)",
+"loadingrev"   => "duke karikuar versionin për ndryshimin",
+"lineno"               => "Rreshti $1:",
+"editcurrent"  => "Redakto versionin e tanishëm të kësaj faqeje",
+
+# Search results
+
+#
+"searchresults" => "Rezultatet e kërkimit",
+"searchresulttext" => "Për më shumë informacion për kërkimin e {{SITENAME}}, shiko [[Project:Kërkim|Duke kërkuar {{SITENAME}}]].",
+"searchquery"  => "Për pyetjen \"$1\"",
+"badquery"             => "Pyetje kërkese e formuluar gabim",
+"badquerytext" => "Nuk mundi t'i pergjigjet pyetjes tende.
+Kjo ka mundësi të ketë ndodhur ngaqë provove të kërkosh për një
+fjalë me më pak se tre gërma, gjë që s'mund të behet akoma.
+Ka mundësi që edhe të kesh shtypur keq pyetjen, për
+shëmbull \"peshku dhe dhe halat\".
+Provo një pyetje tjetër.",
+"matchtotals"  => "Pyetja \"$1\" u përpuq $2 tituj faqesh
+dhe teksti i $3 artikujve te pasardhshëm.",
+"nogomatch" => "Nuk ka asnjë faqe me atë emër ekzakt, duke provuar për kërkim me tekst të plotë.",
+"titlematches" => "Tituj faqesh që përputhen",
+"notitlematches" => "Nuk ka asnjë titull faqeje që përputhet",
+"textmatches"  => "Tekst faqesh që përputhet",
+"notextmatches"        => "Nuk ka asnjë tekst faqeje që përputhet",
+"prevn"                        => "$1 më para",
+"nextn"                        => "$1 më pas",
+"viewprevnext" => "Shiko ($1) ($2) ($3).",
+"showingresults" => "Duke treguar më poshtë <b>$1</b> rezultate dhe duke filluar me #<b>$2</b>.",
+"showingresultsnum" => "Duke treguar më poshtë <b>$3</b> rezultate dhe duke filluar me #<b>$2</b>.",
+"nonefound"            => "<strong>Shënim</strong>: kërkimet pa rezultat shpesh ndodhin
+kur kërkon për fjalë që rastisen shpesh si \"ke\" and \"nga\",
+të cilat nuk janë të futura në rregjistër, ose duke dhënë më shumë se një fjalë (vetëm faqet
+që i kanë të gjitha ato fjalë do të tregohen si rezultate).",
+"powersearch" => "Kërko",
+"powersearchtext" => "
+Kërko në hapësirën:<br />
+$1<br />
+$2 Lidhje ridrejtuese &nbsp; Kërko për $3 $9",
+"searchdisabled" => "<p>Kërkim me tekst të plotë është bllokuar tani për tani ngaqë
+shërbyesi është shumë i ngarkuar; shpresojmë ta nxjerrim prapë në gjëndje normale mbas disa punimeve.
+Gjer atëherë, mund të përdorësh google për kërkime:</p>
+
+",
+"blanknamespace" => "(Main)",
+
+# Preferences page
+#
+"preferences"  => "Preferimet",
+"prefsnologin" => "Nuk ke hyrë brënda",
+"prefsnologintext"     => "Duhet të kesh [[Speciale:Userlogin|hyrë brënda]]
+për të vedosur preferimet e përdoruesit.",
+"prefslogintext" => "Ke hyrë si \"$1\".
+Numri yt i brëndshëm i identifikimit është $2.
+
+Shiko [[{{ns:project}}:Ndihmë për preferimet e përdoruesit]] për ndihmë për të kuptuar opsionet.",
+"prefsreset"   => "Preferimet janë rikthyer siç ishin.",
+"qbsettings"   => "Vendimet e shpejta",
+"changepassword" => "Ndërro fjalëkalimin",
+"skin"                 => "Pamja",
+"math"                 => "Tregimi i matematikës",
+"dateformat"   => "Pamja e datës",
+"math_failure"         => "Nuk e kuptoj",
+"math_unknown_error"   => "gabim i panjohur",
+"math_unknown_function"        => "funksion i panjohur ",
+"math_lexing_error"    => "gabim leximi",
+"math_syntax_error"    => "gabim sintakse",
+"saveprefs"            => "Ruaj preferimet",
+"resetprefs"   => "Rikthe preferimet",
+"oldpassword"  => "Fjalëkalimi i vjetër",
+"newpassword"  => "Fjalëkalimi i ri",
+"retypenew"            => "Rishtyp fjalëkalimin e ri",
+"textboxsize"  => "Dimensionet e kutisë së redaktimit",
+"rows"                 => "Rreshta",
+"columns"              => "Kolona",
+"searchresultshead" => "Preferimet e rezultateve të kërkimit",
+"resultsperpage" => "Sa përputhje të tregohen për faqe",
+"contextlines" => "Sa rreshta të tregohen për përputhje",
+"contextchars" => "Sa gërma të tregohen për çdo rresht",
+"stubthreshold" => "Kufiri për tregimin e cungjeve",
+"recentchangescount" => "Numri i titujve në ndryshimet e fundit",
+"savedprefs"   => "Preferimet e tuaja janë ruajtur.",
+"timezonetext" => "Fut numrin e orëve prej të cilave ndryshon ora lokale
+nga ajo e shërbyesit (UTC).",
+"localtime"    => "Tregimi i orës lokale",
+"timezoneoffset" => "Ndryshimi",
+"servertime"   => "Ora e shërbyesit tani është",
+"guesstimezone" => "Gjeje nga shfletuesi",
+"emailflag"            => "Blloko e-mail nga përdorues të tjerë",
+"defaultns"            => "Kërko automatikisht vetëm në këto hapësira:",
+
+# Recent changes
+#
+"changes" => "ndryshime",
+"recentchanges" => "Ndryshimet e fundit",
+# This is the default text, and can be overriden by editing [[{{ns:project}}:Recentchanges]]
+"recentchangestext" => "Ndiq ndryshimet e fundit të {{SITENAME}} në këtë faqe.",
+"rcloaderr"            => "Duke karikuar ndryshimet e fundit",
+"rcnote"               => "Më poshtë janë <strong>$1</strong> ndryshimet e fundit gjatë <strong>$2</strong> ditëve.",
+"rcnotefrom"   => "Më poshtë janë ndryshimet e fundit nga <b>$2</b> (treguar deri në <b>$1</b>).",
+"rclistfrom"   => "Trego ndryshimet e reja duke filluar nga $1",
+# "rclinks"            => "Trego $1 ndryshimet e fundit gjatë $2 orëve të kaluara / $3 ditëve të kaluara",
+# "rclinks"            => "Trego $1 ndryshime gjatë $2 ditëve të fundit.",
+"rclinks"              => "Trego $1 ndryshime gjatë $2 ditëve; $3 redaktime të vogla",
+"rchide"               => "në $4 formë; $1 redaktime të vogla; $2 hapësira të dyta; $3 redaktime të shumta.",
+"rcliu"                        => "; $1 redaktime nga përdorues të rregjistruar",
+"diff"                 => "ndrysh",
+"hist"                 => "hist",
+"hide"                 => "fshih",
+"show"                 => "trego",
+"tableform"            => "tabelë",
+"listform"             => "listë",
+"nchanges"             => "$1 ndryshime",
+"minoreditletter" => "V",
+"newpageletter" => "R",
+
+# Upload
+#
+"upload"               => "Jep skedar",
+"uploadbtn"            => "Jep skedar",
+"uploadlink"   => "Jep skedar",
+"reupload"             => "Ri-jep",
+"reuploaddesc" => "Kthehu tek formulari i dhënies.",
+"uploadnologin" => "Nuk ke hyrë brënda",
+"uploadnologintext"    => "Duhet të kesh [[Speciale:Userlogin|hyrë brënda]]
+për të dhënë skedarë.",
+"uploaderror"  => "Gabim dhënie",
+"uploadtext"   => "'''NDALO!''' Përpara se të japësh këtu,
+lexo dhe ndiq {{SITENAME}}'s
+[[Project:Rregullat_përdorim_figurash|Rregullat e përdorimit të figurave]].
+
+Për të parë ose për të kërkuar figurat e dhëna më parë,
+shko tek [[Speciale:Imagelist|lista e figurave të dhëna]].
+Dhëniet dhe grisjet janë të rregjistruara në
+[[Project:Jep_rregj|rregjistrin e dhënies]].
+
+Përdorni formularin e më poshtëm për të dhënë skedarë të figurave të reja për tu përdorur
+në illustrimet e artikujve.
+Për shumicën e shfletuesve, do të shihni një \"Browse...\" buton, i cili do të
+hapi dialogun standart të skedarëve të operating system që përdorni.
+Zgjedhja e një skedari do të mbushi emrin në rreshtin e tekstit, afer butonit.
+Duhet të konfirmosh që nuk je duke thyer rregullat e të drejtave të kopimit duke vënë shenjën.
+Shtyp butonin \"Jep\" për të mbaruar dhënien.
+Kjo mund të zgjasi për pak kohë n.q.s. keni lidhje të ngadaltë të internet-it.
+
+Formatet e preferuara janë JPEG për fotografi, PNG
+për vizatime dhe ikona të tjera, dhe OGG për zë dhe muzikë.
+Të lutem fut një emër përshkrues për të mos patur konfuzion më vonë.
+Për të futur një figurë në një artikull, përdor lidhjen sipas formës
+'''<nowiki>[[figura:skedar.jpg]]</nowiki>''' ose '''<nowiki>[[figura:skedar.png|tekst përshkrues]]</nowiki>'''
+ose '''<nowiki>[[media:skedar.ogg]]</nowiki>''' për zë.
+
+Vini re se si me të gjitha faqet e tjera wiki, të tjerë mund të redaktojnë ose
+grisin dhëniet tuaja n.q.s. mendojnë se nuk janë enciklopedike, dhe
+ti mund të bllokohesh nga dhënja n.q.s. e abuzon sistemin.",
+"uploadlog"            => "rregjistër dhënie",
+"uploadlogpage" => "Jep_rregj",
+"uploadlogpagetext" => "Më poshtë është një listë e skedarëve më të rinj që janë dhënë.
+Të gjitha orët janë me orën e shërbyesit (UTC).
+<ul>
+</ul>
+",
+"filename"             => "Skedaremër",
+"filedesc"             => "Përmbledhje",
+"copyrightpage" => "{{ns:project}}:Të drejta kopimi",
+"copyrightpagename" => "{{SITENAME}} Të drejta kopimi",
+"uploadedfiles"        => "Jep skedarë",
+"ignorewarning"        => "Injoroje shënimin e kujdesisë dhe ruaje skedarin.",
+"minlength"            => "Emrat e skedarëve duhet të kenë të paktën tre gërma.",
+"badfilename"  => "Emri i skedarit është ndërruar në \"$1\".",
+"badfiletype"  => "\".$1\" nuk rekomandohet si tip skedari.",
+"largefile"            => "Rekomandohet që skedarët të most kalojnë 100k në madhësi.",
+"successfulupload" => "Dhënie e sukseshme",
+"fileuploaded" => "Skedari \"$1\" u mor me sukses.
+Te lutem ndiq këtë lidhje : ($2) për të shkuar tek faqja e përshkrimit dhe për të futur
+informacion për skedarin, si p.sh. ku e gjete, kur u bë, kush e bëri, dhe çdo gjë
+tjetër që na duhet të dimë për të.",
+"uploadwarning" => "Kujdes dhënie",
+"savefile"             => "Ruani skedarin",
+"uploadedimage" => "dha \"[[$1]]\"",
+"uploaddisabled" => "Ndjesë, dhëniet janë bllokuar në këtë shërbyes dhe nuk është gabimi yt.",
+
+# Image list
+#
+"imagelist"            => "Lista e figurave",
+"imagelisttext"        => "Më poshtë është një listë e $1 figurave të renditura sipas $2.",
+"getimagelist" => "duke karikuar të gjithë listën e figurave",
+"ilsubmit"             => "Kërko",
+"showlast"             => "Trego $1 figurat e fundit të renditura sipas $2.",
+"byname"               => "emrit",
+"bydate"               => "datës",
+"bysize"               => "madhësisë",
+"imgdelete"            => "gris",
+"imgdesc"              => "për",
+"imglegend"            => "Legjendë: (për) = trego/redakto përshkrimin e skedarit.",
+"imghistory"   => "Historia e skedarit",
+"revertimg"            => "ktheje",
+"deleteimg"            => "gris",
+"deleteimgcompletely"          => "gris",
+"imghistlegend" => "Legjendë: (tani) = ky është skedari i tanishëm, (gris) = grise
+këtë version të vjetër, (ktheje) = ktheje në këtë version të vjetër.
+<br /><i>Shtyp datën për të parë skedarin e dhënë në atë ditë</i>.",
+"imagelinks"   => "Lidhje skedarësh",
+"linkstoimage" => "Këto faqe lidhen tek ky skedar:",
+"nolinkstoimage" => "Nuk ka asnjë faqe që të lidhet tek ky skedar.",
+
+# Statistics
+#
+"statistics"   => "Statistika",
+"sitestats"            => "Statistikat e faqeve",
+"userstats"            => "Statistikat e përdoruesit",
+"sitestatstext" => "Gjënden <b>$1</b> faqe në totalin e rregjistrit.
+Këto përfshijnë faqet e  \"diskutimit\", faqe rreth {{SITENAME}}, faqe \"cungje\" të vogla,
+ridrejtime, dhe të tjera që ndoshta nuk kualifikohen si artikuj.
+Duke mos i përfshirë këto, gjënden <b>$2</b> faqe që janë artikuj të ligjshëm.<p>
+Gjënden <b>$3</b> shikime faqesh, dhe <b>$4</b> redaktime faqesh që nga dita kur
+softueri u ndërrua (July 20, 2002).
+Kjo do të thotë se janë bërë <b>$5</b> redaktime për faqe afërsisht, dhe <b>$6</b> shikime për redaktim.",
+"userstatstext" => "Gjënden <b>$1</b> përdorues të rregjistruar.
+<b>$2</b> prej tyre janë me titull administrues (shiko $3).",
+
+# Maintenance Page
+#
+"maintenance"          => "Faqja mirëmbajtëse",
+"maintnancepagetext"   => "Kjo faqe ka disa vegla to dobishme për mirëmbajtjen e përditshme. Disa nga këto funksiones e përdorin shumë
+
+rregjistrin, kështuqë mos e fresko faqen mbas çdo ndryshimi ;-)",
+"maintenancebacklink"  => "Mbrapsh tek faqja mirëmbajtëse",
+"disambiguations"      => "Faqe qartësuese",
+"disambiguationspage"  => "{{ns:project}}:Lidhje_tek_faqe_qartësuese",
+"disambiguationstext"  => "Artikujt që vijojnë lidhen tek një <i>faqe qartësuese</i>. Ato duhet të lidhen tek tema e përshtatshme
+
+<br />Një faqe trajtohet si qartësuese lidhet nga $1.<br />Lidhje nga hapësira të tjera <i>nuk</i> jepen këtu.",
+"doubleredirects"      => "Dopjo ridrejtime",
+"doubleredirectstext"  => "<b>Kujdes:</b> Kjo listë mund të ketë lidhje gabim. D.m.th. ka tekst dhe lidhje mbas #REDIRECT-it të parë.
+
+<br />\nÇdo rresht ka lidhje tek ridrejtimi i parë dhe i dytë, gjithashtu ka edhe rreshtin e parë të tekstit të ridrejtimit të dytë,
+
+duke dhënë dhe  artikullin e \"vërtetë\", me të cilin ridrejtimi i parë duhet të lidhet.",
+"brokenredirects"      => "Ridrejtime të prishura",
+"brokenredirectstext"  => "Ridrejtimet që vijojnë lidhen tek një artikull që s'ekziston.",
+"selflinks"            => "Faqe që lidhen tek vetëvetja",
+"selflinkstext"                => "Faqet që vijojnë kanë një lidhje tek vetëvetja, gjë që s'duhet të ndodhi.",
+"mispeelings"           => "Faqe me gabime gramatikore",
+"mispeelingstext"               => "Faqet që vijojnë kanë një gabim shkrimi që ndodh shpesh, të cilat jepen në $1. Shkrimi i vërtetë mund të jetë dhënë (si kështu).",
+"mispeelingspage"       => "Lista e gabimeve më të shpeshta të shkrimit",
+"missinglanguagelinks"  => "Mungojnë gjuhë-lidhjet",
+"missinglanguagelinksbutton"    => "Gjej gjuhë-lidhjet që mungojnë për",
+"missinglanguagelinkstext"      => "Këto artikuj <i>nuk</i> lidhen tek faqja korresponduese në $1. Ridrejtime dhe nën-faqet <i>nuk</i> janë treguar.",
+
+
+# Miscellaneous special pages
+#
+"orphans"              => "Faqe të palidhura",
+"lonelypages"  => "Faqe të palidhura",
+"unusedimages" => "Figura të papërdorura",
+"popularpages" => "Artikuj te frekuentuar shpesh",
+"nviews"               => "$1 shikime",
+"wantedpages"  => "Artikuj më të dëshiruar",
+"nlinks"               => "$1 lidhje",
+"allpages"             => "Të gjitha faqet",
+"randompage"   => "Artikull kuturu",
+"shortpages"   => "Artikuj të shkurtër",
+"longpages"            => "Artikuj të gjatë",
+"listusers"            => "Lista e përdoruesve",
+"specialpages" => "Faqe speciale",
+"spheading"            => "Faqe speciale për të gjithë përdoruesit",
+"protectpage"  => "Mbroje faqen",
+"recentchangeslinked" => "Ndryshime të përafërta",
+"rclsub"               => "(për faqet e lidhura nga \"$1\")",
+"debug"                        => "Raporto yçkla",
+"newpages"             => "Artikuj të rinj",
+"ancientpages"         => "Artikuj më të vjetër",
+"movethispage" => "Zhvendose faqen",
+"unusedimagestext" => "<p>Të lutem, vë re se hapësira të tjera
+si p.sh ato të që kanë të bejnë me gjuhë të ndryshme mund të lidhin
+nje figurë me një URL në mënyrë direkte, kështuqë mund të keto figura mund të jepen
+këtu edhe pse janë në përdorim.",
+"booksources"  => "Burime librash",
+"booksourcetext" => "Më poshtë është një listë me lidhje tek hapësira të tjera që shesin
+libra të rinj dhe të përdorur, dhe mund të kenë më shumë informacion
+për librat që po kerkon.
+{{SITENAME}} nuk ka mardhënie me asnjë nga këto biznese, dhe
+kjo listë nuk duhet të shikohet si një rreklamë.",
+"alphaindexline" => "$1 deri në $2",
+
+# Email this user
+#
+"mailnologin"  => "S'ka adresë dërgimi",
+"mailnologintext" => "Duhet të kesh [[Speciale:Userlogin|hyrë brënda]]
+dhe të kesh një adresë të saktë në [[Speciale:Preferences|preferimet]]
+për të dërguar një e-mail përdoruesve të tjerë.",
+"emailuser"            => "Dërgoji e-mail këtij përdoruesi",
+"emailpage"            => "Dërgo e-mail përdoruesve",
+"emailpagetext"        => "N.q.s. ky përdorues ka dhënë një adresë të saktë në
+preferimet e tij, formulari më poshtë do t'i dërgojë një mesazh.
+Adresa e email-it që ke dhënë në preferimet e tua do të duket
+si pjesa \"From\" e adresës së mesazhit, kështuqë marrësi do të ketë
+mundësi të të përgjigjet.",
+"noemailtitle" => "S'ka adresë email-i",
+"noemailtext"  => "Ky përdorues s'ka dhënë një adresë të saktë,
+ose ka vendosur të mos pranojë mesazhe email-i nga përdorues të tjerë.",
+"emailfrom"            => "Nga",
+"emailto"              => "Për",
+"emailsubject" => "Subjekt",
+"emailmessage" => "Mesazh",
+"emailsend"            => "Dërgo",
+"emailsent"            => "Email-i u nis",
+"emailsenttext" => "Mesazhi e-mail është nisur.",
+
+# Watchlist
+#
+"watchlist"            => "Lista mbikqyrëse",
+"watchlistsub" => "(për përdoruesin \"$1\")",
+"nowatchlist"  => "Ti nuk ke ndonjë faqe në listën mbikqyrëse.",
+"watchnologin" => "Nuk ke hyrë brënda",
+"watchnologintext"     => "Duhet të kesh [[Speciale:Userlogin|hyrë brënda]]
+për të ndryshuar listën mbikqyrëse tënde.",
+"addedwatch"   => "Shtuar tek lista mbikqyrëse",
+"addedwatchtext" => "Faqja \"$1\" është shtuar <a href=\"" .
+  "{{localurle:Speciale:Watchlist}}\">listës mbikqyrëse</a> tënde.
+Ndryshimet e ardhshme të kësaj faqeje dhe faqes së diskutimit të saj do të jepen më poshtë,
+dhe emri i faqes do të duket i <b>trashë</b> në <a href=\"" .
+  "{{localurle:Speciale:Recentchanges}}\">listën e ndryshimeve të fundit</a> për ta
+dalluar më kollaj.</p>
+
+<p>N.q.s. do të heqësh një faqe nga lista mbikqyrëse më vonë, shtyp \"Mos e mbikqyr\" në tabelën anësore.",
+"removedwatch" => "U hoq nga lista mibkqyrëse",
+"removedwatchtext" => "Faqja \"$1\" është hequr nga lista mbikqyrëse e jote.",
+"watchthispage"        => "Mbikqyr këtë faqe",
+"unwatchthispage" => "Mos e mbikqyr",
+"notanarticle" => "S'është një artikull",
+"watchnochange" => "Asnjë nga artikujt nën mbikqyrje është redaktuar gjatë kohës së dhënë.",
+"watchdetails" => "($1 faqe nën mbikqyrje duke mos numëruar faqet e diskutimit;
+$2 faqe(t) brënda kufirit janë redaktuar;
+$3...
+[$4 trego dhe redakto tërë listën].)",
+"watchmethod-recent" => "duke parë ndryshimet e fundit për faqe nën mbikqyrje",
+"watchmethod-list" => "duke parë faqet nën mbikqyrje për ndryshime të fundit",
+"removechecked" => "Hiq të zgjedhurat",
+"watchlistcontains" => "Lista mbikqyrëse e jote ka $1 faqe.",
+"watcheditlist" => "Këtu jepet një listë e alfabetizuar e faqeve
+nën mbikqyrje. Zgjidh kutinë e sejcilës faqe që dëshiron të heqësh nga lista
+dhe shtyp butonin 'Hiq të zgjedhurat' në fund të ekranit.",
+"removingchecked" => "Duke hequr artikujt e zgjedhur nga lista mbikqyrëse...",
+"couldntremove" => "S'mundi të heq arikullin '$1'...",
+"iteminvalidname" => "Problem me artikullin '$1', titull jo i saktë...",
+"wlnote" => "Më poshtë janë $1 ndryshimet e <b>$2</b> orëve të fundit.",
+
+
+# Delete/protect/revert
+#
+"deletepage"   => "Gris faqen",
+"confirm"              => "Konfirmo",
+"excontent" => "përmbajtja ishte: '$1'",
+"exbeforeblank" => "përmbajtja përpara boshatisjes ishte: '$1'",
+"exblank" => "faqja është bosh",
+"confirmdelete" => "Konfirmo grisjen",
+"deletesub"            => "(Duke grisur \"$1\")",
+"historywarning" => "Kujdes: Faqja që je bërë gati pët të grisur ka një histori: ",
+"confirmdeletetext" => "Je duke grisur '''përfundimisht''' një faqe
+ose një skedar me tërë historinë e tij nga rregjistri.
+Të lutem konfirmo që ke ndër mënd ta bësh këtë gjë, që e kupton se cilat janë
+pasojat, dhe që po vepron ne përputhje me [[{{ns:project}}:Rregullat]].",
+"actioncomplete" => "Veprim i mbaruar",
+"deletedtext"  => "\"$1\" është grisur nga rregjistri.
+Shiko $2 për një rekord të grisjeve të fundit.",
+"deletedarticle" => "grisi \"$1\"",
+"dellogpage"   => "Gris_rregj",
+"dellogpagetext" => "Më poshtë është një listë e grisjeve më të fundit.
+Të gjitha kohët janë sipas orës së shërbyesit (UTC).
+<ul>
+</ul>
+",
+"deletionlog"  => "grisje rekordesh",
+"reverted"             => "Kthehu tek një version i vjetër",
+"deletecomment"        => "Arsyeja për grisjen",
+"imagereverted" => "Kthimi tek një version i sukseshëm.",
+"rollback"             => "Rrotulloji mbrapsh redaktimet",
+"rollbacklink" => "rrotullo",
+"rollbackfailed" => "Rrotullimi dështoi",
+"cantrollback" => "Nuk mund të kthejë redaktimin; redaktori i fundit është i vetmi autor i këtij artikulli.",
+"alreadyrolled"        => "Nuk mund të rrotullojë redaktimin e fundit e [[$1]]
+nga [[Përdoruesi:$2|$2]] ([[Përdoruesi diskutim:$2|Diskutim]]); dikush tjetër ka redaktuar ose rrotulluar këtë faqe.
+
+Redaktimi i fundit është bërë nga [[Përdoruesi:$3|$3]] ([[Përdoruesi diskutim:$3|Diskutim]]). ",
+#   only shown if there is an edit comment
+"editcomment" => "Komenti i redaktimit ishte: \"<i>$1</i>\".",
+"revertpage"   => "Kthyer tek redaktimi i fundit nga $1",
+"protectlogpage" => "Mbroj_rregj",
+"protectlogtext" => "Më poshtë është një listë e \"mbrojtjeve/lirimeve\" të faqeve.
+Shiko [[{{ns:project}}:Faqe e mbrojtur]] për më shumë informacion.",
+"protectedarticle" => "mbrojti [[$1]]",
+"unprotectedarticle" => "liroji [[$1]]",
+
+# Undelete
+"undelete" => "Restauro faqet e grisura",
+"undeletepage" => "Shiko ose restauro faqet e grisura",
+"undeletepagetext" => "Më poshtë janë faqet që janë grisur por që gjënden akoma në arshiv dhe
+mund të restaurohen. Arshivi boshatiset periodikisht.",
+"undeletearticle" => "Restauro artikullin e grisur",
+"undeleterevisions" => "$1 versione u futën në arshiv",
+
+"undeletehistory" => "N.q.s. restauron një faqe, të gjitha versionet do të restaurohen në histori.
+N.q.s. një faqe e re me të njëjtin titull është krijuar që nga grisja, versionet e
+restauruara do të duken më përpara në histori, dhe versioni i faqes së fundit nuk do të
+shkëmbehet automatikisht.",
+"undeleterevision" => "U gris versioni i $1",
+"undeletebtn" => "Restauro!",
+"undeletedarticle" => "u restaurua \"$1\"",
+"undeletedtext"   => "Faqja [[$1]] është restauruar me sukses.
+Shiko [[{{ns:project}}:Gris_rregj]] për një listë të grisjeve dhe restaurimeve të fundit.",
+
+# Contributions
+#
+"contributions"        => "Redaktimet e përdoruesit",
+"mycontris" => "Redaktimet e mia",
+"contribsub"   => "Për $1",
+"nocontribs"   => "S'ka asnjë ndryshim që të përputhet me këto kritere.",
+"ucnote"               => "Më poshtë janë redaktimet më të fundit të <b>$1</b> gjatë <b>$2</b> ditëve.",
+"uclinks"              => "Shiko $1 redaktimet e fundit; shiko $2 ditët e fundit.",
+"uctop"                => " (sipër)" ,
+
+# What links here
+#
+"whatlinkshere"        => "Lidhjet këtu",
+"notargettitle" => "Asnjë artikull",
+"notargettext" => "Nuk ke dhënë asnjë artikull ose përdorues mbi të cilin
+të përdorim këtë funksion.",
+"linklistsub"  => "(Listë lidhjesh)",
+"linkshere"            => "Faqet e mëposhtëme lidhen këtu:",
+"nolinkshere"  => "Asnjë faqe nuk lidhet këtu.",
+"isredirect"   => "faqe ridrejtuese",
+
+# Block/unblock IP
+#
+"blockip"              => "Blloko përdoruesin",
+"blockiptext"  => "Përdor formularin e mëposhtëm për të hequr lejen e shkrimit
+për një përdorues ose IP-ë specifike.
+Kjo duhet bërë vetëm në raste vandalizmi, dhe në përputhje me [[{{ns:project}}:Rregullat|{{SITENAME}} regullat]].
+Plotëso arsyen specifike më poshtë (p.sh., trego faqet specifike që u
+vandalizuan).",
+"ipaddress"            => "IP Adresë/përdorues",
+"ipbreason"            => "Arsye",
+"ipbsubmit"            => "Blloko këtë përdorues",
+"badipaddress" => "Nuk ka asnjë përdorues me atë emër",
+"blockipsuccesssub" => "Bllokimi u bë me sukses",
+"blockipsuccesstext" => "\"$1\" është bllokuar.
+<br />Shiko [[Speciale:Ipblocklist|IP blloko listë]] për të parë bllokimet.",
+"unblockip"            => "Ç'blloko përdoruesin",
+"unblockiptext"        => "Përdor formularin e më poshtëm për t'i ridhënë leje shkrimi
+një përdoruesi ose IP adreseje të bllokuar.",
+"ipusubmit"            => "Ç'blloko këtë adresë",
+"ipusuccess"   => "\"$1\" u ç'bllokua",
+"ipblocklist"  => "Lista e përdoruesve dhe e IP adresave të bllokuara",
+"blocklistline"        => "$1, $2 bllokoi $3 ($4)",
+"blocklink"            => "blloko",
+"unblocklink"  => "ç'blloko",
+"contribslink" => "kontribute",
+"autoblocker"  => "I bllokuar automatikisht sepse përdor të njëjtën IP adresë si \"$1\". Arsye \"$2\".",
+
+# Developer tools
+#
+"lockdb"               => "Blloko rregjistrin",
+"unlockdb"             => "Ç'blloko rregjistrin",
+"lockdbtext"   => "Bllokimi i rregjistrit do të ndërpresi mundësinë e përdoruesve
+për të redaktuar faqet, për të ndryshuar preferimet, për të ndryshuar listat mbikqyrëse të tyre, dhe
+për gjëra të tjera për të cilat nevojiten shkrime në rregjistër.
+Të lutem konfirmo që me vërte do të kryesh këtë veprim, dhe se do të ç'bllokosh rregjistrin
+kur të mbarosh së kryeri mirëmbajtje.",
+"unlockdbtext" => "Ç'bllokimi i rregjistrit do të lejojë mundësinë e të gjithë
+përdoruesve për të redaktuar faqe, për të ndryshuar preferimet e tyre, për të ndryshuar listat mbikqyrëse të tyre, dhe
+gjëra të tjera për të cilat nevojiten shkrime në rregjistër.
+Të lutem konfirmo që me vërte do të kryesh këtë veprim.",
+"lockconfirm"  => "Po, dëshiroj me të vërtetë të bllokoj rregjistrin.",
+"unlockconfirm"        => "Po, dëshiroj me të vërtetë të ç'bllokoj rregjistrin",
+"lockbtn"              => "Blloko rregjistrin",
+"unlockbtn"            => "Ç'blloko rregjistrin",
+"locknoconfirm" => "Nuk vendose kryqin tek kutia konfirmuese.",
+"lockdbsuccesssub" => "Rregjistri u bllokua me sukses",
+"unlockdbsuccesssub" => "Rregjistri u ç'bllokua me sukses",
+"lockdbsuccesstext" => "Rregjistri i {{SITENAME}} është bllokuar.
+<br />Kujtohu ta ç'bllokosh mbasi të kesh mbaruar mirëmbajtjen.",
+"unlockdbsuccesstext" => "Rregjistri i {{SITENAME}} është ç'bllokuar.",
+
+# Move page
+#
+"movepage"             => "Zhvendose faqen",
+"movepagetext" => "Duke përdor formularin e mëposhtëm do të ndërrosh titullin e një faqeje,
+duke zhvendosur gjithë historinë përkatëse tek titulli i ri.
+Titulli i vjetër do të bëhet një faqe ridrejtuese tek titulli i ri.
+Lidhjet tek faqja e vjetër nuk do të ndryshohen; duhet të kontrollosh
+mirëmbajtjen për ridrejtime të dyfishta ose të prishura.
+Ti ke përgjegjësinë për tu siguruar që lidhjet të vazhdojnë të jenë të sakta.
+
+Vë re se kjo faqe '''nuk''' do të zhvendoset n.q.s. ekziston një faqe
+me titullin e ri, përveçse kur ajo të jetë bosh ose një ridrejtim dhe të mos ketë
+një histori të vjetër. Kjo do të thotë se ti mund ta zhvendososh një faqe prapë tek emri
+i vjetër n.q.s. ke bërë një gabim, dhe s'mund të prisësh një faqe që ekziston.
+
+<b>KUJDES!</b>
+Ky mund të jetë një ndryshim i madh dhe gjëra të papritura mund të ndoshin për një faqe
+të shumë-frekuentuar; të lutem, ki kujdes dhe mendohu mirë para se të përdorësh këtë funksion.",
+"movepagetalktext" => "Faqja a bashkangjitur e diskutimit, n.q.s. ekziston, do të zhvendoset automatikisht '''përveçse''' kur:
+*Zhvendos një faqe midis hapësirave të ndryshme,
+*Një faqe diskutimi jo-boshe ekziston nën titullin e ri, ose
+*Nuk zgjedh kutinë më poshtë.
+
+Në ato raste, duhet ta zhvendosësh ose perpuqësh faqen vetë n.q.s. dëshiron.",
+"movearticle"  => "Zhvendose faqen",
+"movenologin"  => "Nuk ke hyrë brënda",
+"movenologintext" => "Duhet të kesh hapur një llogari dhe të kesh [[Speciale:Userlogin|hyrë brënda]]
+për të zhvendosur një faqe.",
+"newtitle"             => "Tek titulli i ri",
+"movepagebtn"  => "Zhvendose faqen",
+"pagemovedsub" => "Zhvendosja doli me sukses",
+"pagemovedtext" => "Faqja \"[[$1]]\" u zhvendos tek \"[[$2]]\".",
+"articleexists" => "Një faqe me atë titull ekziston, ose titulli që
+zgjodhe nuk është i saktë.
+Të lutem zgjidh një tjetër.",
+"talkexists"   => "Faqja për vete u zhvendos, ndërsa
+faqja e diskutimit nuk u zhvendos sepse një e tillë ekziston tek titulli i ri.
+Të lutem, përpuqi vetë.",
+"movedto"              => "zhvendosur tek",
+"movetalk"             => "Zhvendos edhe faqen e \"diskutimit\", n.q.s. është e mundur.",
+"talkpagemoved" => "Faqja e diskutimit korrespondente u zhvendos gjithashtu.",
+"talkpagenotmoved" => "Faqja e diskutimit korrespondente <strong>nuk</strong> u zhvendos.",
+
+# Math
+
+'mw_math_png' => "Gjithmonë PNG",
+'mw_math_simple' => "HTML në qoftë se është e thjeshtë ose ndryshe PNG",
+'mw_math_html' => "HTML në qoftë se është e mundur ose ndryshe PNG",
+'mw_math_source' => "Lëre si TeX (për shfletuesit tekst)",
+'mw_math_modern' => "E rekomanduar për shfletuesit modern",
+'mw_math_mathml' => 'MathML',
+
+);
+
+class LanguageSq extends LanguageUtf8 {
+
+       function getNamespaces() {
+               global $wgNamespaceNamesSq;
+               return $wgNamespaceNamesSq;
+       }
+
+       function getNsIndex( $text ) {
+               global $wgNamespaceNamesSq;
+               foreach ( $wgNamespaceNamesSq as $i => $n ) {
+                       if ( 0 == strcasecmp( $n, $text ) ) { return $i; }
+               }
+               # Compatbility with alt names:
+               if( 0 == strcasecmp( "Special", $text ) ) { return -1; } # So both Speciale: and Special: work
+               if( 0 == strcasecmp( "Perdoruesi", $text ) ) return 2;
+               if( 0 == strcasecmp( "Perdoruesi_diskutim", $text ) ) return 3;
+               return false;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsSq;
+               return $wgQuickbarSettingsSq;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesSq;
+               return $wgSkinNamesSq;
+       }
+
+       function getDateFormats() {
+               global $wgDateFormatsSq;
+               return $wgDateFormatsSq;
+       }
+
+       # localised date and time
+       function date( $ts, $adj = false ) {
+               if ( $adj ) { $ts = $this->userAdjust( $ts ); }
+
+               $d = substr( $ts, 0, 4 ) . " " .
+                       $this->getMonthName( substr( $ts, 4, 2 ) ) . " ".
+                       (0 + substr( $ts, 6, 2 ));
+               return $d;
+       }
+
+       function time( $ts, $adj = false ) {
+               if ( $adj ) { $ts = $this->userAdjust( $ts ); }
+
+               $t = substr( $ts, 8, 2 ) . ":" . substr( $ts, 10, 2 );
+               return $t;
+       }
+
+       function timeanddate( $ts, $adj = false ) {
+               return $this->date( $ts, $adj ) . " " . $this->time( $ts, $adj );
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesSq;
+               if(array_key_exists($key, $wgAllMessagesSq))
+                       return $wgAllMessagesSq[$key];
+               else
+                       return parent::getMessage($key);
+       }
+
+       function formatNum( $number ) {
+               global $wgTranslateNumerals;
+               return $wgTranslateNumerals ? strtr($number, '.,', ',.' ) : $number;
+       }
+
+}
+
+?>
diff --git a/languages/LanguageSr.php b/languages/LanguageSr.php
new file mode 100644 (file)
index 0000000..20a11de
--- /dev/null
@@ -0,0 +1,1129 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+require_once( "LanguageUtf8.php" );
+
+# NOTE: To turn off "Current Events" in the sidebar,
+# set "currentevents" => "-"
+
+# The names of the namespaces can be set here, but the numbers
+# are magical, so don't change or move them!  The Namespace class
+# encapsulates some of the magic-ness.
+#
+/* private */ $wgNamespaceNamesSr = array(
+       NS_MEDIA            => "Media",
+       NS_SPECIAL          => "Посебно",
+       NS_MAIN             => "",
+       NS_TALK             => "Разговор",
+       NS_USER             => "Корисник",
+       NS_USER_TALK        => "Разговор_са_корисником",
+       NS_PROJECT          => $wgMetaNamespace,
+       NS_PROJECT_TALK     => ($wgMetaNamespaceTalk ? $wgMetaNamespaceTalk : "Разговор_о_".$wgMetaNamespace ),
+       NS_IMAGE            => "Слика",
+       NS_IMAGE_TALK       => "Разговор_о_слици",
+       NS_MEDIAWIKI        => "МедијаВики",
+       NS_MEDIAWIKI_TALK   => "Разговор_о_МедијаВикију",
+       NS_TEMPLATE         => 'Шаблон',
+       NS_TEMPLATE_TALK    => 'Разговор_о_шаблону',
+       NS_HELP             => 'Помоћ',
+       NS_HELP_TALK        => 'Разговор_о_помоћи',
+       NS_CATEGORY         => 'Категорија',
+       NS_CATEGORY_TALK    => 'Разговор_о_категорији',
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgQuickbarSettingsSr = array(
+ "Никаква", "Причвршћена лево", "Причвршћена десно", "Плутајућа лево"
+);
+
+/* private */ $wgSkinNamesSr = array(
+ "Обична", "Носталгија", "Келнско плаво", "Педингтон", "Монпарнас"
+) + $wgSkinNamesEn;
+
+/* private */ $wgDateFormatsSr = array(
+       'Није битно',
+       '06:12, 5. јануар 2001.',
+       '06:12, 5 јануар 2001',
+       '06:12, 05.01.2001.',
+       '06:12, 5.1.2001.',
+       '06:12, 5. јан 2001.',
+       '06:12, 5 јан 2001',
+       '6:12, 5. јануар 2001.',
+       '6:12, 5 јануар 2001',
+       '6:12, 05.01.2001.',
+       '6:12, 5.1.2001.',
+       '6:12, 5. јан 2001.',
+       '6:12, 5 јан 2001',
+);
+
+
+
+/* NOT USED IN STABLE VERSION */
+/* private */ $wgMagicWordsSr = array(
+#   ID                                 CASE  SYNONYMS
+       MAG_REDIRECT             => array( 0,    "#преусмери"              ),
+       MAG_NOTOC                => array( 0,    "__БЕЗСАДРЖАЈА__"              ),
+       MAG_START                => array( 0,    "__ПОЧЕТАК__"              ),
+       MAG_CURRENTMONTH         => array( 1,    "{{ТРЕНУТНИМЕСЕЦ}}"       ),
+       MAG_CURRENTMONTHNAME     => array( 1,    "{{ИМЕТРЕНУТНОГМЕСЕЦА}}"   ),
+       MAG_CURRENTDAY           => array( 1,    "{{ТРЕНУТНИДАН}}"         ),
+       MAG_CURRENTDAYNAME       => array( 1,    "{{ИМЕТРЕНУТНОГДАНА}}"     ),
+       MAG_CURRENTYEAR          => array( 1,    "{{ТРЕНУТНАГОДИНА}}"        ),
+       MAG_CURRENTTIME          => array( 1,    "{{ТРЕНУТНОВРЕМЕ}}"        ),
+       MAG_NUMBEROFARTICLES     => array( 1,    "{{БРОЈЧЛАНАКА}}"   ),
+       MAG_CURRENTMONTHNAMEGEN  => array( 1,    "{{ГЕНЕРИСАНОИМЕТРЕНУТНОГМЕСЕЦА}}"),
+       MAG_SUBST                => array( 1,    "{{ПОДСТ:$1}}"           ),
+       MAG_MSGNW                => array( 1,    "{{НВПОР:$1}}"           )
+);
+
+/* private */ $wgAllMessagesSr = array(
+
+# User Toggles
+#
+"tog-underline" => "Подвуци везе",
+"tog-highlightbroken" => "Форматирај покварене везе <a href=\"\" class=\"new\">овако</a> (алтернатива: овако<a href=\"\" class=\"internal\">?</a>).",
+"tog-justify" => "Поравнај пасусе",
+"tog-hideminor" => "Сакриј мале измене у списку скорашњих променама",
+"tog-usenewrc" => "Побољшана списку скорашњих промена (не за све бровсере)",
+"tog-numberheadings" => "Аутоматски нумериши поднаслове",
+"tog-showtoolbar" => "Show edit toolbar",
+"tog-editondblclick" => "Мењај странице двоструким кликом (захтева JavaScript)",
+"tog-editsection"=>"Омогући измену делова [мењај] везама",
+"tog-editsectiononrightclick"=>"Омогући измену делова десним кликом<br /> на њихове наслове (захтева JavaScript)",
+"tog-showtoc"=>"Прикажи садржај<br />(у свим чланцима са више од три поднаслова)",
+"tog-rememberpassword" => "Памти шифру кроз више сеанси",
+"tog-editwidth" => "Поље за измене има пуну ширину",
+"tog-watchdefault" => "Додај странице које мењам у мој списак гледања",
+"tog-minordefault" => "Означи све измене малим испрва",
+"tog-previewontop" => "Покажи предпреглед пре поља за измену а не после њега",
+"tog-nocache" => "Онемогући кеширање страница",
+
+# Dates
+#
+
+'sunday' => "Недеља",
+'monday' => "Понедељак",
+'tuesday' => "Уторак",
+'wednesday' => "Среда",
+'thursday' => "Четвртак",
+'friday' => "Петак",
+'saturday' => "Субота",
+'january' => "јануар",
+'february' => "фебруар",
+'march' => "март",
+'april' => "април",
+'may_long' => "мај",
+'june' => "јун",
+'july' => "јул",
+'august' => "август",
+'september' => "септембар",
+'october' => "октобар",
+'november' => "новембар",
+'december' => "децембар",
+'jan' => "јан",
+'feb' => "феб",
+'mar' => "мар",
+'apr' => "апр",
+'may' => "мај",
+'jun' => "јун",
+'jul' => "јул",
+'aug' => "авг",
+'sep' => "сеп",
+'oct' => "окт",
+'nov' => "нов",
+'dec' => "дец",
+
+# Bits of text used by many pages:
+#
+"categories" => "Категорије страница",
+"category" => "категорија",
+"category_header" => "Чланака у категорији: \"$1\"",
+"subcategories" => "Подкатегорије",
+
+"linktrail" => "/^([абвгдђежзијклљмнњопрстћуфхцчџш]+)(.*)$/usD",
+"mainpage"  => "Главна страна",
+"mainpagetext" => "Вики софтвер је успешно инсталиран.",
+"about"   => "О...",
+"aboutsite"      => "О Википедији",
+"aboutpage"  => "{{ns:4}}:О",
+"help"   => "Помоћ",
+"helppage"  => "{{ns:4}}:Помоћ",
+"bugreports" => "Пријаве грешака",
+"bugreportspage" => "{{ns:4}}:Пријаве_грешака",
+"faq"   => "FAQ",
+"faqpage"  => "{{ns:4}}:FAQ",
+"edithelp"  => "Помоћ! Како се мења страна?",
+"edithelppage" => "{{ns:4}}:Како_се_мења_страна",
+"cancel"  => "Поништи",
+"qbfind"  => "Пронађи",
+"qbbrowse"  => "Прелиставај",
+"qbedit"  => "Измени",
+"qbpageoptions" => "Опције странице",
+"qbpageinfo" => "Информације о страници",
+"qbmyoptions" => "Моје опције",
+"mypage"  => "Моја страница",
+"mytalk"  => "Мој разговор",
+"currentevents" => "Тренутни догађаји",
+"errorpagetitle" => "Грешка",
+"returnto"  => "Повратак на $1.",
+"tagline"       => "Из Википедије, слободне енциклопедије.",
+"whatlinkshere" => "Странице које су повезане овде",
+"help"   => "Помоћ",
+"search"  => "Тражи",
+"go"  => "Иди",
+"history"  => "Историја странице",
+"printableversion" => "Верзија за штампу",
+"editthispage" => "Измени ову страницу",
+"deletethispage" => "Обриши ову страницу",
+"protectthispage" => "Заштити ову страницу",
+"unprotectthispage" => "Уклони заштиту са ове странице",
+"newpage" => "Нова страница",
+"talkpage"  => "Разговор о овој страници",
+"postcomment"   => "Пошаљи коментар",
+"articlepage" => "Погледај чланак",
+"subjectpage" => "Погледај тему", # For compatibility
+"userpage" => "Погледај корисничку страну",
+"wikipediapage" => "Погледај страну о овој страни",
+"imagepage" =>  "Погледај страну слике",
+"viewtalkpage" => "Погледај расправу",
+"otherlanguages" => "Остали језици",
+"redirectedfrom" => "(Преусмерено са $1)",
+"lastmodified" => "Ова страница је последњи пут измењена $1.",
+"viewcount"  => "Овој страници је приступљено $1 пута.",
+"printsubtitle" => "(Са {{SERVER}})",
+"protectedpage" => "Заштићена страница",
+"administrators" => "{{ns:4}}:Администратори",
+"sysoptitle" => "Неопходан је сисопски приступ",
+"sysoptext"  => "Акцију коју сте затражили могу
+извести само корисници са \"сисоп\" статусом.
+Погледајте $1.",
+"developertitle" => "Неоходан је девелоперски приступ",
+"developertext" => "Акцију коју сте затражили могу
+извести само корисници са \"девелопер\" статусом.
+Погледајте $1.",
+"nbytes"  => "$1 бајтова",
+"go"   => "Иди",
+"ok"   => "Да",
+"sitetitle"  => "{{SITENAME}}",
+"sitesubtitle" => "Слободна енциклопедија",
+"retrievedfrom" => "Добављено из \"$1\"",
+"newmessages" => "Имате $1.",
+"newmessageslink" => "нових порука",
+"editsection"=>"измени",
+"toc" => "Садржај",
+"showtoc" => "прикажи",
+"hidetoc" => "сакриј",
+"thisisdeleted" => "Погледај или врати $1?",
+"restorelink" => "$1 обрисаних измена",
+/*
+</pre>
+
+==Део 2==
+<pre>
+*/
+# Main script and global functions
+#
+"nosuchaction" => "Нема такве акције",
+"nosuchactiontext" => "Акција наведена у УРЛ-у није
+препозната од стране Википедијиног софтвера.",
+"nosuchspecialpage" => "Нема такве посебне странице",
+"nospecialpagetext" => "Хтели сте посебну страницу која није
+препозната од стране Википедијиног софтвера.",
+
+# General errors
+#
+"error"   => "Грешка",
+"databaseerror" => "Грешка у бази",
+"dberrortext" => "Десила се синтаксна грешка упита базе.
+Ово је могуће због илегалног упита,
+или могуће грешке у софтверу.
+Последњи покушани упит је био:
+<blockquote><tt>$1</tt></blockquote>
+из функције \"<tt>$2</tt>\".
+MySQL је вратио грешку \"<tt>$3: $4</tt>\".",
+"dberrortextcl" => "Десила се синтаксна грешка упита базе.
+Последњи покушани упит је био:
+\"$1\"
+из функције \"$2\".
+MySQL је вратио грешку \"$3: $4\".\n",
+"noconnect"  => "Жалимо! Вики има неке техничке потешкоће, и не може да се повеже се сервером базе.",
+"nodb"   => "Не могу да изаберем базу $1",
+"cachederror"  => "Ово је кеширана копија захтеване странице, и можда није најновија.",
+"readonly"  => "База је закључана",
+"enterlockreason" => "Унесите разлог за закључавање, укључујући процену
+времена откључвања",
+"readonlytext" => "Википедијина база је тренутно закључана за нове
+уносе и остале измене, вероватно због рутинског одржавања,
+после чега ће бити враћена у уобичајено стање.
+Администратор који ју је закључао понудио је ово објашњење:
+<p>$1",
+"missingarticle" => "База није нашла текст странице
+који је требала, назван \"$1\".
+
+<p>Ово је обично изазвано праћењем застарелог \"разл\" или везе ка историји
+странице која је обрисана.
+
+<p>Ако ово није случај, можда сте пронашли грешку у софтверу.
+Молимо вас пријавите ово једном од администратора, заједно са УРЛ-ом.",
+"internalerror" => "Интерна грешка",
+"filecopyerror" => "Не могу да ископирам фајл \"$1\" на \"$2\".",
+"filerenameerror" => "Не могу да променим име фајла \"$1\" у \"$2\".",
+"filedeleteerror" => "Не могу да обришем фајл \"$1\".",
+"filenotfound" => "Не могу да нађем фајл \"$1\".",
+"unexpected" => "Неочекивана вредност: \"$1\"=\"$2\".",
+"formerror"  => "Грешка: не могу да пошаљем упитник",
+"badarticleerror" => "Ова акција не може бити извршена на овој страници.",
+"cannotdelete" => "Не могу да обришем наведену страницу или слику. (Могуће је да ју је неко други већ обрисао.)",
+"badtitle"  => "Лош наслов",
+"badtitletext" => "Захтевани наслов странице је био неисправан, празан или
+неисправно повезан међујезички или међувики наслов.",
+"perfdisabled" => "Жалимо! Ова могућност је привремено онемогућена јер успорава базу до те мере да више нико не може да користи вики.",
+"perfdisabledsub" => "Овде је снимљена копија $1:",
+
+# Login and logout pages
+#
+"logouttitle" => "Одјави се",
+"logouttext" => "Сада сте одјављени. Можете да наставите да користите Википедију анонимно, или се поново пријавити као други корисник. Обратите пажњу да неке странице могу наставити да се приказују као да сте још увек пријављени, док не очистите кеш свог бровсера.\n",
+
+"welcomecreation" => "<h2>Добродошли, $1!</h2><p>Ваш налог је креиран.
+Не заборавите да прилагодите себи своја Википедијина подешавања.",
+
+"loginpagetitle" => "Пријављивање",
+"yourname"  => "Ваше корисничко име",
+"yourpassword" => "Ваша шифра",
+"yourpasswordagain" => "Поново укуцајте шифру",
+"newusersonly" => " (само за нове кориснике)",
+"remembermypassword" => "Запамти моју шифру током више сеанси.",
+"loginproblem" => "<b>Било је проблема са вашим пријављивањем.</b><br />Пробајте поново!",
+"alreadyloggedin" => "<strong>Корисниче $1, већ сте пријављени!</strong><br />\n",
+
+"login"   => "Пријави се",
+"userlogin"  => "Пријави се",
+"logout"  => "Одјави се",
+"userlogout" => "Одјави се",
+"notloggedin" => "Нисте пријављени",
+"createaccount" => "Направи нови налог",
+"createaccountmail" => "e-поштом",
+"badretype"  => "Шифре које сте унели се не поклапају.",
+"userexists" => "Корисничко име које сте унели већ јеу употреби. Молим вас изаберите друго име.",
+"youremail"  => "Ваша е-адреса*",
+"yournick"  => "Ваш надимак (за потписе)",
+"emailforlost" => "* Уношење адресе е-поште није обавезно.  Али оно ће омогућити људима да
+вас контатирају кроз сајт а да не морате да им откријете
+своју адресу, а такође ће вам помоћи ако заборавите вашу
+шифру.",
+"loginerror" => "Грешка при пријављивању",
+"noname"  => "Нисте изабрали исправно корисничко име.",
+"loginsuccesstitle" => "Пријављивање успешно",
+"loginsuccess" => "Сада сте пријављени на Википедију као \"$1\".",
+"nosuchuser" => "Не постоји корисник са именом \"$1\".
+Проверите ваше куцање, или употребите доњи упитник да направите нови кориснички налог.",
+"wrongpassword" => "Шифра коју сте унели је неисправна. Молимо покушајте поново.",
+"mailmypassword" => "Пошаљи ми нову шифру",
+"passwordremindertitle" => "Vikipedijin podsetnik za sifru",
+"passwordremindertext" => "Neko (verovatno vi, sa IP adrese $1)
+je zahtevao da vam posaljemo novu sifru za prijavljivanje na Vikipediju.
+Sifra za korisnika \"$2\" je sada \"$3\".
+Sada biste trebali da se ulogujete i promenite svoju sifru.",
+"noemail"  => "Не постоји е-адреса за корисника \"$1\".",
+"passwordsent" => "Нова шифра је послата на е-адресу
+корисника \"$1\".
+Молимо вас улогујте се пошто је примите.",
+
+# Edit pages
+#
+"summary"  => "Уопштено",
+"subject"  => "Тема/наслов",
+"minoredit"  => "Ово је мала измена",
+"watchthis"  => "Надгледај овај чланак",
+"savearticle" => "Сними страницу",
+"preview"  => "Предпреглед",
+"showpreview" => "Прикажи предпреглед",
+"blockedtitle" => "Корисник је блокиран",
+"blockedtext" => "Ваше корисничко име или ИП адреса је блокирана од стране $1.
+Дати разлог је следећи:<br />''$2''<p>Можете се обратити $1 или неком другом
+[[{{ns:4}}:администратори|администратору]] да бисте разговарали о блокади.",
+"whitelistedittitle" => "Обавезно је пријављивање за мењање",
+"whitelistedittext" => "Морате да се [[Посебно:Пријављивање|пријавите]] да бисте мењали чланке.",
+"whitelistreadtitle" => "Обавезно је пријављивање за читање",
+"whitelistreadtext" => "Морате да се [[Посебно:Пријављивање|пријавите]] да бисте читали чланке.",
+"whitelistacctitle" => "Није вам дозвољено да направите налог",
+"whitelistacctext" => "Да би вам било дозвољено да направите налоге на овом Викију морате да се [[Посебно:Пријављивање|пријавите]] и имате одговарајућа овчашћења.",
+"accmailtitle" => "Шифра послата.",
+"accmailtext" => "Шифра за '$1' је послата на $2.",
+"newarticle" => "(Нови)",
+"newarticletext" =>
+"Пратили сте везу ка страници која још на постоји.
+Да бисте створили страницу, почните да куцате у поље испод
+(погледајте [[{{ns:4}}:Помоћ|помоћ]] за више информација).
+Ако сте овде дошли грешком, само стисните '''back''' дугме вашег бровсера.",
+"anontalkpagetext" => "---- ''Ово је страница за разговор за анонимног корисника који још није направио налог или га не користи. Због тога морамо да користимо бројчану [[ИП адреса|ИП адресу]] да бисмо идентификовали њега или њу. Такву адресу може делити више корисника. Ако сте анонимни корисник и мислите да су вам упућене небитне примедбе, молимо вас да [[Посебно:Пријављивање|направите налог или се пријавите]] да бисте избегли будућу забуну са осталим анонимним корисницима.'' ",
+"noarticletext" => "(Тренутно нема текста на овој страници)",
+"updated"  => "(Освежено)",
+"note"   => "<strong>Пажња:</strong> ",
+"previewnote" => "Запамтите да је ово само предпреглед, и да још није снимљен!",
+"previewconflict" => "Овај предпреглед осликава како ће текст у
+текстуалном пољу изгледати ако се одлучите да га снимите.",
+"editing"  => "Мењам $1",
+"editingsection"  => "Мењам $1 (део)",
+"editingcomment"  => "Мењам $1 (коментар)",
+"editconflict" => "Сукобљене измене: $1",
+"explainconflict" => "Неко други је променио ову страницу откад сте ви почели да је мењате.
+Горње текстуално поље садржи текст странице какв тренутно постоји.
+Ваше измене су приказане у доњем тексту.
+Мораћете да унесете своје промене у постојећи текст.
+<b>Само</b> текст у горњем текстуалном пољу ће бити снимљен када
+притиснете \"Сними страницу\".<br />",
+"yourtext"  => "Ваш текст",
+"storedversion" => "Ускладиштена верзија",
+"editingold" => "<strong>ПАЖЊА: Ви мењате старију
+ревизију ове странице.
+Ако је снимите, све промене учињене од ове ревизије биће изгубљене.</strong>",
+"yourdiff"  => "Разлике",
+"copyrightwarning" => "Молимо вас да обратите пажњу да се за сваки допринос Википедији
+сматра да је објављен под ГНУ лиценцом за слободну документацију
+(погледајте $1 за детаље).
+Ако не желите да се ваше писање мења и редистрибуира
+без ограничења, онда га немојте слати овде.<br />
+Такође нам обећавате да сте га сами написали, или ископирали из
+извора који је у јавном власништву или сличног слободног извора.
+<strong>НЕ ШАЉИТЕ РАД ЗАШТИЋЕН АУТОРСКИМ ПРАВИМА БЕЗ ДОЗВОЛЕ!</strong>",
+"longpagewarning" => "<strong>ПАЖЊА: Ова страница има $1 килобајта; неки
+бровсери могу имати проблема са мењањем страница дугачких скоро 32кб или више.
+Молимо вас да размотрите разбијање странице на мање делове.</strong>",
+"readonlywarning" => "<strong>ПАЖЊА: База је ушраво закључана због одржавања,
+тако да нећете моћи да снимите своје измене управо сада. Можда желите да ископирате и налепите
+текст у текст едитор и снимите га за касније.</strong>",
+"protectedpagewarning" => "<strong>ПАЖЊА:  Ова страница је закључана тако да само
+корисници са сисопским привилегијама могу да је мењају. Уверите се да пратите
+[[Project:Смернице_о_заштићеним_страницама|смернице о заштићеним страницама]].</strong>",
+
+# History pages
+#
+"revhistory" => "Историја измена",
+"nohistory"  => "Не постоји историја измена за ову страницу.",
+"revnotfound" => "Ревизија није пронађена",
+"revnotfoundtext" => "Старија ревизија ове странице коју сте затражили није нађена.
+Молимо вас да проверите УРЛ који сте употребили да бисте приступили овој страници.\n",
+"loadhist"  => "Учитавам историју странице",
+"currentrev" => "Тренутна ревизија",
+"revisionasof" => "Ревизија од $1",
+"cur"   => "трен",
+"next"   => "след",
+"last"   => "посл",
+"orig"   => "ориг",
+"histlegend" => "Објашњење: (трен) = разлика са тренутном верзијом,
+(посл) = разлика са претходном верзијом, М = мала измена",
+
+# Diffs
+#
+"difference" => "(Разлика између ревизија)",
+"loadingrev" => "учитавам ревизију за разлику",
+"lineno"  => "Линија $1:",
+"editcurrent" => "Измени тренутну верзију ове странице",
+
+# Search results
+#
+"searchresults" => "Резултати претраге",
+"searchresulttext" => "За више информација о претраживању Википедије, погледајте [[{{ns:4}}:Тражење|Претраживање Википедије]].",
+"searchquery" => "За упит \"$1\"",
+"badquery"  => "Лоше обликован упит за претрагу",
+"badquerytext" => "Нисмо могли да обрадимо ваш упит.
+Ово је вероватно због тога што сте покушалида тражите
+реч краћу од три слова, што тренутно није подржано.
+Такође је могуће да сте погрешно укуцали израз, на
+пример \"риба ии крљушти\".
+Молимо вас покушајте неким  другим упитом.",
+"matchtotals" => "Упит \"$1\" је нађен у $2 наслова чланака
+и текст $3 чланака.",
+"nogomatch" => "Ниједна страница са оваквим насловом не постоји, покушавам претрагу свог текста.",
+"titlematches" => "Наслов чланка одговара",
+"notitlematches" => "Ниједан наслов чланка не одговара",
+"textmatches" => "Текст чланка одговара",
+"notextmatches" => "НИједан текст чланка не одговара",
+"prevn"   => "претходних $1",
+"nextn"   => "следећих $1",
+"viewprevnext" => "Погледај ($1) ($2) ($3).",
+"showingresults" => "Приказујем <b>$1</b> резултата почев од <b>$2</b>.",
+"showingresultsnum" => "Приказујем <b>$3</b> резултате почев од <b>$2</b>.",
+"nonefound"  => "<strong>Пажња</strong>: неуспешне претраге су
+често изазване тражењем честих речи као \"је\" или \"од\",
+које нису индексиране, или навођењем више од једног израза за тражење (само странице
+које садрже све изразе који се траже ће се појавити у резултату).",
+"powersearch" => "Тражи",
+"powersearchtext" => "
+Претрага и уменским просторима:<br />
+$1<br />
+$2 Излистај преусмерења &nbsp; Тражи $3 $9",
+"searchdisabled" => "<p>Жалимо! Пуна претрага текста је привремено онемогућена, због бржег рада Википедије. Умеђувремену, можете користити Гугле претрагу испод, која може бити застарела.</p>
+
+",
+"blanknamespace" => "(Главно)",
+
+# Preferences page
+#
+"preferences" => "Подешавања",
+"prefsnologin" => "Нисте пријављени",
+"prefsnologintext" => "Морате бити [[Special:Userlogin|пријављени]]
+да бисте подешавали корисничка подешавања.",
+"prefslogintext" => "Пријављени сте као \"$1\".
+Ваш интерни ИД број је $2.
+
+Погледајте [[{{ns:4}}:Помоћ око корисничких подешавања]] за помоћ око дешифровања могућности.",
+"prefsreset" => "Враћена су ускладиштена подешавања.",
+"qbsettings" => "Подешавања брзе палете",
+"changepassword" => "Промени шифру",
+"skin"   => "Кожа",
+"math"   => "Приказивање математике",
+"dateformat" => "Формат датума",
+"math_failure"  => "Неуспех при парсирању",
+"math_unknown_error" => "непозната грешка",
+"math_unknown_function" => "непозната функција ",
+"math_lexing_error" => "речничка грешка",
+"math_syntax_error" => "синтаксна грешка",
+"saveprefs"  => "Сними подешавања",
+"resetprefs" => "Врати подешавања",
+"oldpassword" => "Стара шифра",
+"newpassword" => "Нова шифра",
+"retypenew"  => "Поново откуцајте нову шифру",
+"textboxsize" => "Величине текстуалног поља",
+"rows"   => "Редова",
+"columns"  => "Колона",
+"searchresultshead" => "Подешавања резултата претраге",
+"resultsperpage" => "Погодака по страници",
+"contextlines" => "Линија по поготку",
+"contextchars" => "Карактера контекста по линији",
+"stubthreshold" => "Граница за приказивање окрњака",
+"recentchangescount" => "Број наслова у скорашњим проенама",
+"savedprefs" => "Ваша подешавања су снимљена.",
+"timezonetext" => "Унесите број сати за који се ваше локално време
+разликује од серверског времена (UTC).",
+"localtime" => "Приказ локалног времена",
+"timezoneoffset" => "Одступање",
+"servertime" => "Време на серверу је сада",
+"guesstimezone" => "Попуни из бровсера",
+"emailflag"  => "Онемогући примање е-поште од осталих корисника",
+"defaultns"  => "Уобичајено тражи у овим именским просторима:",
+/*
+</pre>
+==Део 3==
+<pre>
+*/
+# Recent changes
+#
+"changes" => "измене",
+"recentchanges" => "Скорашње измене",
+"recentchangestext" =>
+"Пратите најскорије измене на Википедији овде.
+[[Wikipedia:Добродошли|Добродошли]]!
+Погледајте такође и: [[{{ns:4}}:FAQ|{{SITENAME}} FAQ]],
+[[{{ns:4}}:Смернице|Википедијине смернице]]
+(посебно [[{{ns:4}}:Правила именовања|правила именовања]],
+[[{{ns:4}}:Неутрална тачка гледишта|неутрална тачка гледишта]]),
+и [[{{ns:4}}:Најчешће грешке на Википедији|најчешће грешке на Википедији]].
+
+Ако желите да {{SITENAME}} успе, веома је важно да не додајете
+материјал ограничен туђим [[{{ns:4}}:Ауторска права|ауторским правима]].
+Правна одговорност би могла да повреди пројекат, па вас молимо да то не радите.
+Погледајте такође [http://meta.wikipedia.org/wiki/Special:Recentchanges скорашњу мета дискусију].",
+"rcloaderr"  => "Учитавам скорашње измене",
+"rcnote"  => "Испод је последњих <strong>$1</strong> промена у последњих <strong>$2</strong> дана.",
+"rcnotefrom" => "Испод су промене од <b>$2</b> (до <b>$1</b> приказано).",
+"rclistfrom" => "Покажи нове промене почев од $1",
+# "rclinks"  => "Show last $1 changes in last $2 hours / last $3 days",
+# "rclinks"  => "Show last $1 changes in last $2 days.",
+"rclinks"  => "Покажи последљих $1 промена у последњих $2 дана; $3 мале измене",
+"rchide"  => "у $4 облику; $1 мале измене; $2 секундарни именски простори; $3 вишеструке измене.",
+"rcliu"   => "; $1 измена од пријављених корисника",
+"diff"   => "разл",
+"hist"   => "ист",
+"hide"   => "скриј",
+"show"   => "покажи",
+"tableform"  => "табела",
+"listform"  => "списак",
+"nchanges"  => "$1 промена",
+"minoreditletter" => "М",
+"newpageletter" => "Н",
+
+# Upload
+#
+"upload"  => "Пошаљи фајл",
+"uploadbtn"  => "Пошаљи фајл",
+"uploadlink" => "Пошаљи слике",
+"reupload"  => "Поново пошаљи",
+"reuploaddesc" => "Врати се на упитник за слање.",
+"uploadnologin" => "Нисте пријављени",
+"uploadnologintext" => "Морате бити [[Special:Userlogin|пријављени]]
+да бисте слали фајлове.",
+"uploaderror" => "Грешка при слању",
+"uploadtext" => "'''СТОП!''' Пре него што шаљете овде,
+обавезно прочитајте и пратите Википедијина
+[[Project:Image_use_policy|правила коришћења слика]].
+
+Да бисте прегледали или претраживали раније послате слике,
+идите на [[Special:Imagelist|списак послатих слика]].
+Слања и брисања су логована на
+[[Project:Upload_log|логу слања]].
+
+Употребите доњи упитник да бисте послали нове слике за
+илустровање својих чланака.
+На већини бровсера, видећете \"Browse...\" дугме, које ће вам
+отворити стандардни прозор вашег оперативног система за бирање фајла.
+Избор фајла ће убацити његово име у текст
+поље поред дугмета.
+Такође морате обележити кућицу чиме потврђујете да не
+повређујете никаква ауторска права слањем фајла.
+Притисните дугме \"Пошаљи\" да бисте завршили слање.
+Оно може потрајати ако имате спору Интернет везу.
+
+Пожељни формати су JPEG за фотографије, PNG
+за цртеже и остале једноставне слике, и OGG за звуке.
+Молимо вас да имена ваших фајлова имају неко значење да бисте избегли забуну.
+Да бисте укључили слику у текст, употребите везу у облику
+'''<nowiki>[[image:file.jpg]]</nowiki>''' или '''<nowiki>[[image:file.png|алтернативни текст]]</nowiki>'''
+or '''<nowiki>[[media:file.ogg]]</nowiki>''' за звукове.
+
+Обратите пажњу да, као и код Википедијиних страница, други могу мењати или
+избрисати ваша слања ако мисле да то користи енциклопедији, а
+може вам се и забранити да шаљете ако злоупотребите систем.",
+"uploadlog"  => "лог слања",
+"uploadlogpage" => "Лог_слања",
+"uploadlogpagetext" => "Испод је списак најскоријих слања.
+Сва времена су серверска времена (UTC).
+<ul>
+</ul>
+",
+"filename"  => "Име фајла",
+"filedesc"  => "Опис",
+"filestatus" => "Статус ауторских права",
+"filesource" => "Извор",
+"copyrightpage" => "{{ns:4}}:Ауторска_права",
+"copyrightpagename" => "{{SITENAME}} ауторска права",
+"uploadedfiles" => "Послати фајлови",
+"ignorewarning" => "Игнориши упозорење и свеједно сними фајл.",
+"minlength"  => "Имена слика морају имате бар три слова.",
+"badfilename" => "Име слике је промељено у \"$1\".",
+"badfiletype" => "\".$1\" није препоручени формат слике.",
+"largefile"  => "Препоручује се да слике не пређу величину од 100К.",
+"successfulupload" => "Успешно слање",
+"fileuploaded" => "Фајл \"$1\" је успешно послат.
+Молим пратите ову везу: ($2) до странице за описивање и унесите
+информације о фајлу, као одакле је, када и
+ко га је направио, ибило шта друго што знате о њему.",
+"uploadwarning" => "Упозорење при слању",
+"savefile"  => "Сними фајл",
+"uploadedimage" => "послато \"[[$1]]\"",
+
+# Image list
+#
+"imagelist"  => "Листа слика",
+"imagelisttext" => "Испод је списак $1 слика поређаних $2.",
+"getimagelist" => "прибављам списак слика",
+"ilsubmit"  => "Тражи",
+"showlast"  => "Прикажи последњих $1 слика поређаних по $2.",
+"byname"  => "по имену",
+"bydate"  => "по датуму",
+"bysize"  => "по величини",
+"imgdelete"  => "обр",
+"imgdesc"  => "опис",
+"imglegend"  => "Објашњење: (опис) = прикажи/измени опис слике.",
+"imghistory" => "Историја слике",
+"revertimg"  => "врт",
+"deleteimg"  => "обр",
+"deleteimgcompletely"  => "обр",
+"imghistlegend" => "Објашњење: (трен) = ово је тренутна слика, (обр) = обриши
+ову стару верзију, (врт) = врати на ову стару верзију.
+<br /><i>Кликните на датум давидите слику послату тог датума</i>.",
+"imagelinks" => "Употреба слике",
+"linkstoimage" => "Следеће странице користе на ову слику:",
+"nolinkstoimage" => "Нема страница које користе ову слику.",
+
+# Statistics
+#
+"statistics" => "Статистике",
+"sitestats"  => "Статистике сајта",
+"userstats"  => "Статистике корисника",
+"sitestatstext" => "Постоји укупно <b>$1</b> страница у бази.
+Ово укључује \"разговор\" странице, странице о Википедији, минималне \"окрњке\",
+преусмерења, и остале које се вероватно не могу сматрати чланцима.
+Не рачунајући њих постоји <b>$2</b> страница које су вероватно легитимни
+чланци.<p>
+Странице су погледане <b>$3</b> пута, и мењане <b>$4</b> пута
+откада је софтвер побољшан (20. јул 2002).
+То значи да је у просеку било <b>$5</b> измена по страници, и <b>$6</b> прегледа по измени.",
+"userstatstext" => "Постоји <b>$1</b> пријављених корисника.
+<b>$2</b> њих су администратори (погледајте $3).",
+
+# Maintenance Page
+#
+"maintenance"  => "Страница за одржавање",
+"maintnancepagetext" => "Ова страница садржи неколико згодних алатки за свакодневно одржавање. Неке од њих могу заморити базу, па вас молимо да не учитавате поново после сваке ставке коју сте средили ;-)",
+"maintenancebacklink" => "Назад на страницу за одржавање",
+"disambiguations" => "Странице за обездвосмишљење",
+"disambiguationspage" => "{{ns:4}}:Линкови_на_странице_за_обезвосмишљење",
+"disambiguationstext" => "Следећи чланци се повезују са <i>страницом за обездвосмишљење</i>. Уместо тога, они би требали да се повезују са одговарајућом темом.<br />Страница се третира као обездвосмишљенска ако је повезана са $1.<br />Линкови из осталих именских простора <i>нису</i> наведени овде.",
+"doubleredirects" => "Двострука преусмерења",
+"doubleredirectstext" => "<b>Пажња:</b> Овај списак може да садржи лажне резултате. То обично значи да постоји додатни текст са везама испод првог #REDIRECT.<br />\nСваки ред садржи везе на прво и друго преусмерење, као и на прву линију текста другог преусмерења, што обично даје \"прави\" циљни чланак, на који би прво преусмерење и требало да показује.",
+"brokenredirects" => "Покварена преусмерења",
+"brokenredirectstext" => "Следећа преусмерења су повезана на непостојећи чланак.",
+"selflinks"  => "Странице са самовезама",
+"selflinkstext"  => "Следеће странице садрже везе на саме себе, што не би требало.",
+"mispeelings"           => "Странице са грешкама у куцању",
+"mispeelingstext"               => "Следеће странице садрже честе грешке у куцању, које су наведене на $1. Исправне речи могу бити дате (овако).",
+"mispeelingspage"       => "Листа честих грешака у куцању",
+"missinglanguagelinks"  => "Недостајући језичке везе",
+"missinglanguagelinksbutton"    => "Нађи недостајуће језичке везе за",
+"missinglanguagelinkstext"      => "Ови чланци <i>нису</i> повезани са њима одговарајућим у $1. Преусмерења и подстранице <i>нису</i> приказани.",
+
+
+# Miscellaneous special pages
+#
+"orphans"  => "Сирочићи",
+"lonelypages" => "Сирочићи",
+"unusedimages" => "Неупотребљене слике",
+"popularpages" => "Популарне странице",
+"nviews"  => "$1 пута погледано",
+"wantedpages" => "Тражене страице",
+"nlinks"  => "$1 веза",
+"allpages"  => "Све странице",
+"randompage" => "Случајна страница",
+"shortpages" => "Кратке странице",
+"longpages"  => "Дугачке странице",
+"listusers"  => "Листа корисника",
+"specialpages" => "Посебне странице",
+"spheading"  => "Посебне странице за све кориснике",
+"protectpage" => "Заштити страницу",
+"recentchangeslinked" => "Сродне промене",
+"rclsub"  => "(на странице повезане од \"$1\")",
+"debug"   => "Исправи грешке",
+"newpages"  => "Нове странице",
+"ancientpages"  => "Најстарији чланци",
+"intl"  => "Међујезичке везе",
+"movethispage" => "премести ову страницу",
+"unusedimagestext" => "<p>Обратите пажњу да се други веб сајтови
+као што су међународне Википедије могу повезивати на слику
+директним УРЛ-ом, и тако могујош увек бити приказани овде упркос
+активној употреби.",
+"booksources" => "Штампани извори",
+"booksourcetext" => "Испод је списак веза на друге сајтове који
+продају нове и коришћене књиге, и такође могу имати даљње информације
+о књигама које тражите.
+{{SITENAME}} не сарађује ни се једним од ових предузећа, и
+овај списак не треба да се схвати као потврда њиховог квалитета.",
+"alphaindexline" => "$1 у $2",
+
+# Email this user
+#
+"mailnologin" => "Нема адресе за слање",
+"mailnologintext" => "Морате бити [[Special:Userlogin|пријављени]]
+и имати исправну е-адресу in your [[Special:Preferences|подешавањима]]
+да бисте слали електронску пошту другим корисницима.",
+"emailuser"  => "Пошаљи е-писмо овом кориснику",
+"emailpage"  => "Пошаљи е-писмо кориснику",
+"emailpagetext" => "Ако је овај корисник унео исправну е-адресу у
+своја корисничка подешавања, упитник испод ће послати једну поруку.
+Е-адреса коју сте ви унели у своја корисничка подешавања ће се појавити
+као \"From\" адреса поруке, тако да ће прималац моћи
+да одговори.",
+"noemailtitle" => "Нема е-адресе",
+"noemailtext" => "Овај корисник није навео исправну е-адресу,
+или је изабрао да не прима е-пошту од других корисника.",
+"emailfrom"  => "Од",
+"emailto"  => "За",
+"emailsubject" => "Тема",
+"emailmessage" => "Порука",
+"emailsend"  => "Пошаљи",
+"emailsent"  => "Порука послата",
+"emailsenttext" => "Ваша порука је послата електронском поштом.",
+
+# Watchlist
+#
+"watchlist"  => "Мој списак надгледања",
+"watchlistsub" => "(за корисника \"$1\")",
+"nowatchlist" => "Немате ништа на свом списку надгледања.",
+"watchnologin" => "Нисте пријављени",
+"watchnologintext" => "Морате бити [[Special:Userlogin|пријављени]]
+да бисте мењали списак надгледања.",
+"addedwatch" => "Додати списку надгледања",
+"addedwatchtext" => "Страница \"$1\" је додата вашој <a href=\"" .
+  "{{localurle:Special:Watchlist}}\">списку надгледања</a>.
+Будуће промене ове странице и њој придружене странице за разговор ће бити наведене овде,
+и страница ће бити <b>подебљана</b> у <a href=\"" .
+  "{{localurle:Special:Recentchanges}}\">списку скорашњих измена</a> да
+би се лакше уочила.</p>
+
+<p>Ако касније желите да уклоните страницу са вашег списка надгледања, кликните на \"Прекини надгледање\" на бочној палети.",
+"removedwatch" => "Уклоњено из списка надгледања",
+"removedwatchtext" => "Страница \"$1\" је уклоњена из вашег списка надгледања.",
+"watchthispage" => "Надгледај ову страницу",
+"unwatchthispage" => "Прекини надгледање",
+"notanarticle" => "Није чланак",
+"watchnochange" => "Ништа што надгледате није промењено у приказаном времену.",
+"watchdetails" => "($1 страница надгледано не рачунајући странице за разговор;
+$2 укупно страница измењено од одсецања;
+$3...
+[$4 прикажи и мењај потпуни списак].)",
+"watchmethod-recent" => "проверавам има ли надгледаних страница у скорашњим изменама",
+"watchmethod-list" => "проверавам има ли скорашњих измена у надгледаним страницама",
+"removechecked" => "Уклони обележене уносе из списка надгледања",
+"watchlistcontains" => "Ваш списак надгледања садржи $1 страница.",
+"watcheditlist" => "Овде је азбучни списак страница
+које надгледате. Обележите кућице страница које желите да уклоните
+са свог списка надгледања и кликните на дугме 'уклони изабране'
+на дну екрана.",
+"removingchecked" => "Уклањам обележене ствари са списка надгледања...",
+"couldntremove" => "Не могу да уклоним '$1'...",
+"iteminvalidname" => "Проблем са '$1', неисправно име...",
+"wlnote" => "Испод је последњих $1 измена у последњих <b>$2</b> сати.",
+"wlshowlast" => "Прикажи последњих $1 сати $2 дана $3",
+
+
+# Delete/protect/revert
+#
+"deletepage" => "Обриши страницу",
+"confirm"  => "Потврди",
+"excontent" => "садржај је био: '$1'",
+"exbeforeblank" => "садржај пре брисања је био: '$1'",
+"exblank" => "страница је била празна",
+"confirmdelete" => "Потврди брисање",
+"deletesub"  => "(Бришем \"$1\")",
+"historywarning" => "Пажња: страница коју желите да обришете има историју: ",
+"confirmdeletetext" => "На путу сте да трајно обришете страницу
+или слику заједно са свом њеномисторијом из базе.
+Молим вас потврдите да намеравате да урадите ово, да разумете
+последице, и да ово радите у складу са
+[[{{ns:4}}:Правила]].",
+"actioncomplete" => "Акција завршена",
+"deletedtext" => "\"$1\" је обрисана.
+Погледајте $2 за запис о скорашњим брисањима.",
+"deletedarticle" => "обрисан \"$1\"",
+"dellogpage" => "Лог_брисања",
+"dellogpagetext" => "Испод је списак најскоријих брисања.
+Сва приказана времене су серверска (UTC).
+<ul>
+</ul>
+",
+"deletionlog" => "Лог брисања",
+"reverted"  => "Враћено на ранију ревизију",
+"deletecomment" => "Разлог за брисање",
+"imagereverted" => "Враћање на ранију верзију је успешно.",
+"rollback"  => "Врати измене",
+"rollbacklink" => "врати",
+"rollbackfailed" => "Враћање није успело",
+"cantrollback" => "Не могу да вратим измену; последњи аутор је уједно и једини.",
+"alreadyrolled" => "Не могу да вратим последњу измену [[$1]]
+од корисника [[Корисник:$2|$2]] ([[Разговор са корисником:$2|Разговор]]); неко други је већ изменио или врати чланак.
+
+Последња измена од корисника [[Корисник:$3|$3]] ([[Разговор са корисником:$3|Разговор]]). ",
+#   only shown if there is an edit comment
+"editcomment" => "Коментар измене је: \"<i>$1</i>\".",
+"revertpage" => "Враћено на последњу измену од корисника $1",
+
+# Undelete
+"undelete" => "Врати обрисану страницу",
+"undeletepage" => "Погледај и врати обрисане странице",
+"undeletepagetext" => "Следеће странице су обрисане али су још увек у архиви и
+могу бити враћене. Архива може бити периодично чишћена.",
+"undeletearticle" => "Врати обрисани чланак",
+"undeleterevisions" => "$1 ревизија архивирано",
+"undeletehistory" => "Ако вратите страницу, све ревизије ће бити враћене њеној историји.
+Ако јенова страница истог имена направљена од брисања, враћене
+ревизије ће се појавити у ранијој историји, а тренутна ревизија садашње странице
+неће бити аутоматски замењена.",
+"undeleterevision" => "Обрисана ревизија од $1",
+"undeletebtn" => "Врати!",
+"undeletedarticle" => "враћено \"$1\"",
+"undeletedtext"   => "Чланак [[$1]] је успешно враћен.
+Погледајте [[{{ns:4}}:Лог_брисања]] за запис о скорашњим брисањима и враћањима.",
+
+# Contributions
+#
+"contributions" => "Прилози корисника",
+"mycontris" => "Моји прилози",
+"contribsub" => "За $1",
+"nocontribs" => "Нису нађене промене које задовољавају ове услове.",
+"ucnote"  => "Испод је последњих <b>$1</b> промена у последњих <b>$2</b> дана.",
+"uclinks"  => "Гледај последњих $1 промена; гледај последњих $2 дана.",
+"uctop"  => " (врх)" ,
+
+# What links here
+#
+"whatlinkshere" => "Шта је повезано овде",
+"notargettitle" => "Нема циља",
+"notargettext" => "Нисте навели циљну страницу или корисника
+на коме би се извела ова функција.",
+"linklistsub" => "(Листа веза)",
+"linkshere"  => "Следеће странице су повезане овде:",
+"nolinkshere" => "Ни једна страница није повезана овде.",
+"isredirect" => "Преусмеривач",
+
+# Block/unblock IP
+#
+"blockip"  => "Обуздај корисника",
+"blockiptext" => "Употребите доњи упитник да бисте уклонили право писања
+са одређене ИП адресе или корисничког имена.
+Ово би требало да буде урађено само да би се спречио вандализам, и у складу
+са [[{{ns:4}}:Смернице|Википедијиним смерницама]].
+Унесите конкретан разлог испод (на пример, наводећи које
+странице су вандализоване).",
+"ipaddress"  => "ИП адреса/корисничко име",
+"ipbreason"  => "Разлог",
+"ipbsubmit"  => "Обуздај овог корисника",
+"badipaddress" => "Не постоји ниједан корисник који се тако зове",
+"blockipsuccesssub" => "Обуздавање је успело",
+"blockipsuccesstext" => "\"$1\" је обуздан.
+<br />Погледајте [[Посебно:ИПсписакаобузданих|ИП списак обузданих]] за преглед обуздавања.",
+"unblockip"  => "Отпусти корисника",
+"unblockiptext" => "Употребите доњи упитник да бист вратили право писања
+раније обузданој ИП адреси или корисничком имену.",
+"ipusubmit"  => "Отпусти ову адресу",
+"ipusuccess" => "\"$1\" отпуштен",
+"ipblocklist" => "Списак обузданих ИП адреса и корисника",
+"blocklistline" => "$1, $2 је обуздао $3 ($4)",
+"blocklink"  => "блокирај",
+"unblocklink" => "деблокирај",
+"contribslink" => "прилози",
+"autoblocker" => "Аутоматски сте обуздани јер делите ИП адресу са \"$1\". Разлог \"$2\".",
+# Developer tools
+#
+"lockdb"  => "Закључај базу",
+"unlockdb"  => "Откључај базу",
+"lockdbtext" => "Закључавање базе ће свим корисницима укинути могућност измене страница,
+промене корисничких подешавања, измене списка надгледања, и свега осталог
+што захтева промене у бази.
+Молим потврдите да је ово заиста оно што намеравате да урадите, и да ћете
+откључати базу када завршите посао око њеног одржавања.",
+"unlockdbtext" => "Откључавање базе ће свим корисницима вратити могућност измене страница,
+промене корисничких подешавања, измене списка надгледања, и свега осталог
+што захтева промене у бази.
+Молим потврдите да је ово заиста оно што намеравате да урадите.",
+"lockconfirm" => "Да, заиста желим да закључам базу.",
+"unlockconfirm" => "Да, заиста желим да откључам базу.",
+"lockbtn"  => "Закључај базу",
+"unlockbtn"  => "Откључај базу",
+"locknoconfirm" => "Нисте потврдили своју намеру.",
+"lockdbsuccesssub" => "База је закључана",
+"unlockdbsuccesssub" => "База је откључана",
+"lockdbsuccesstext" => "Википедијина база података је закључана.
+<br />Сетите се да је откључате када завршите са одржавањем.",
+"unlockdbsuccesstext" => "Википедијина база података је откључана.",
+
+# Move page
+#
+"movepage"  => "Премештање странице",
+"movepagetext" => "Доњи упитник ће преименовати страницу, премештајући сву
+њену историју на ново име.
+Стари наслов ће постати преусмерење на нови наслов.
+Линкови према старом наслову неће бити промењени; обавезно
+[[Посебно:Одржавање|потражите]] двострука или покварена преусмерења.
+На вама је одговорност да везе и даље иду
+тамо где би и требало да иду.
+
+Обратите пажњу да страница '''неће''' бити померена ако већ постоји
+страница са новим насловом, осим ако је она празна или преусмерење и нема
+историју промена. Ово значи да не можете преименовати страницу на оно име
+са кога сте је преименовали ако погрешите, и не можете преписати
+постојећу страницу.
+
+<b>ПАЖЊА!</b>
+Ово може бити драстична и неочекивана промена за популарну страницу;
+молимо да будете сигурни да разумете последице овога пре него што
+наставите.",
+"movepagetalktext" => "Одговарајућа страница за разговор, ако постоји, ће бити аутоматски премештена истовремено '''осим:'''
+*Ако премештате страницу preko именских простора,
+*Непразна страница за разговор већ постоји под новим именом, или
+*Одбележите доњу кућицу.
+
+У тим случајевима, мораћете ручно да преместите страницу уколико то желите.",
+"movearticle" => "Премести страницу",
+"movenologin" => "Нисте улоговани",
+"movenologintext" => "Морате бити регистровани корисник и [[Special:Userlogin||пријављени]]
+да бисте преместили страницу.",
+"newtitle"  => "Нови наслов",
+"movepagebtn" => "премести страницу",
+"pagemovedsub" => "Премештање успело",
+"pagemovedtext" => "Страница \"[[$1]]\" премештена је на \"[[$2]]\".",
+"articleexists" => "Страница под тим именом већ постоји, или
+име које сте изабрали није исправно.
+Молим изаберите друго име.",
+"talkexists" => "Сама страница је успешно премештена, али
+страница за разговор није могла бити премештена јер таква већ постоји на новом наслову. Молим да их спојите ручно.",
+"movedto"  => "премештена на",
+"movetalk"  => "Премести \"страницу за разговор\" такође, ако је могуће.",
+"talkpagemoved" => "Одговарајућа страницаза разговор је такође премештена.",
+"talkpagenotmoved" => "Одговарајућа страница за разговор <strong>није</strong> премештена.",
+
+"export"  => "Извези странице",
+"exporttext" => "Можете извести текст и историју промена одређене
+странице или групе страница умотану у неки XML; ово онда може бити увезено у други
+вики који користи МедијаВики софтвер, трансформисано, или коришћено за ваше личне
+потребе.",
+"exportcuronly" => "Укључи само тренутну ревизију, не целу историју",
+
+# Namespace 8 related
+
+"allmessages" => "Све_поруке",
+"allmessagestext" => "Ово је списак свих порука које су у МедијаВики: именском простору",
+
+# Math
+
+'mw_math_png' => "Увек прикажи PNG",
+'mw_math_simple' => "HTML ако је врло једноставно, иначе PNG",
+'mw_math_html' => "HTML ако је могуће, иначе PNG",
+'mw_math_source' => "Остави као ТеХ (за текстуалне бровсере)",
+'mw_math_modern' => "Препоручено за савремене бровсере",
+
+);
+
+#--------------------------------------------------------------------------
+# Internationalisation code
+#--------------------------------------------------------------------------
+
+class LanguageSr extends LanguageUtf8 {
+
+       function getNamespaces() {
+       global $wgNamespaceNamesSr;
+       return $wgNamespaceNamesSr;
+       }
+
+       function getNsIndex( $text ) {
+       global $wgNamespaceNamesSr;
+
+       foreach ( $wgNamespaceNamesSr as $i => $n ) {
+               if ( 0 == strcasecmp( $n, $text ) ) { return $i; }
+       }
+       if( 0 == strcasecmp( "Special", $text ) ) { return -1; }
+       if( 0 == strcasecmp( "User", $text ) ) { return 2; }
+       if( 0 == strcasecmp( "Wikipedia", $text ) ) { return 4; }
+       return false;
+       }
+
+       function getQuickbarSettings() {
+       global $wgQuickbarSettingsSr;
+       return $wgQuickbarSettingsSr;
+       }
+
+       function getSkinNames() {
+       global $wgSkinNamesSr;
+       return $wgSkinNamesSr;
+       }
+
+       function getDateFormats() {
+       global $wgDateFormatsSr;
+       return $wgDateFormatsSr;
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesSr;
+               if(array_key_exists($key, $wgAllMessagesSr))
+                       return $wgAllMessagesSr[$key];
+               else
+                       return parent::getMessage($key);
+       }
+
+       function formatNum( $number, $year = false ) {
+               return $year ? $number : strtr($this->commafy($number), '.,', ',.' );
+       }
+
+       /**
+        * @access public
+        * @param mixed  $ts the time format which needs to be turned into a
+        *               date('YmdHis') format with wfTimestamp(TS_MW,$ts)
+        * @param bool   $adj whether to adjust the time output according to the
+        *               user configured offset ($timecorrection)
+        * @param mixed  $format what format to return, if it's false output the
+        *               default one.
+        * @param string $timecorrection the time offset as returned by
+        *               validateTimeZone() in Special:Preferences
+        * @return string
+        */
+       function date( $ts, $adj = false, $format = true, $timecorrection = false ) {
+
+               if ( $adj ) { $ts = $this->userAdjust( $ts, $timecorrection ); }
+
+               $mm = substr( $ts, 4, 2 );
+               $m = 0 + $mm;
+               $mmmm = $this->getMonthName( $mm );
+               $mmm = $this->getMonthAbbreviation( $mm );
+               $dd = substr( $ts, 6, 2 );
+               $d = 0 + $dd;
+               $yyyy =  substr( $ts, 0, 4 );
+               $yy =  substr( $ts, 2, 2 );
+
+               switch( $format ) {
+                       case '2':
+                       case '8':
+                               return "$d $mmmm $yyyy";
+                       case '3':
+                       case '9':
+                               return "$dd.$mm.$yyyy.";
+                       case '4':
+                       case '10':
+                               return "$d.$m.$yyyy.";
+                       case '5':
+                       case '11':
+                               return "$d. $mmm $yyyy.";
+                       case '6':
+                       case '12':
+                               return "$d $mmm $yyyy";
+                       default:
+                               return "$d. $mmmm $yyyy.";
+               }
+
+       }
+
+       /**
+       * @access public
+       * @param mixed  $ts the time format which needs to be turned into a
+       *               date('YmdHis') format with wfTimestamp(TS_MW,$ts)
+       * @param bool   $adj whether to adjust the time output according to the
+       *               user configured offset ($timecorrection)
+       * @param mixed  $format what format to return, if it's false output the
+       *               default one (default true)
+       * @param string $timecorrection the time offset as returned by
+       *               validateTimeZone() in Special:Preferences
+       * @return string
+       */
+       function time( $ts, $adj = false, $format = true, $timecorrection = false ) {
+
+               if ( $adj ) { $ts = $this->userAdjust( $ts, $timecorrection ); }
+               $hh = substr( $ts, 8, 2 );
+               $h = 0 + $hh;
+               $mm = substr( $ts, 10, 2 );
+               switch( $format ) {
+                       case '7':
+                       case '8':
+                       case '9':
+                       case '10':
+                       case '11':
+                       case '12':
+                               return "$h:$mm";
+                       default:
+                               return "$hh:$mm";
+               }
+       }
+
+       /**
+       * @access public
+       * @param mixed  $ts the time format which needs to be turned into a
+       *               date('YmdHis') format with wfTimestamp(TS_MW,$ts)
+       * @param bool   $adj whether to adjust the time output according to the
+       *               user configured offset ($timecorrection)
+       * @param mixed  $format what format to return, if it's false output the
+       *               default one (default true)
+       * @param string $timecorrection the time offset as returned by
+       *               validateTimeZone() in Special:Preferences
+       * @return string
+       */
+       function timeanddate( $ts, $adj = false, $format = true, $timecorrection = false) {
+               $datePreference = $this->dateFormat($format);
+               return $this->time( $ts, $adj, $datePreference, $timecorrection ) . ', ' . $this->date( $ts, $adj, $datePreference, $timecorrection );
+
+       }
+
+
+}
+
+?>
diff --git a/languages/LanguageSv.php b/languages/LanguageSv.php
new file mode 100644 (file)
index 0000000..7cec227
--- /dev/null
@@ -0,0 +1,954 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+#
+# Swedish localisation for MediaWiki
+#
+# This file is encoded in UTF-8, no byte order mark.
+# For compatibility with Latin-1 installations, please
+# don't add literal characters above U+00ff.
+#
+
+require_once( "LanguageUtf8.php" );
+
+/* private */ $wgNamespaceNamesSv = array(
+       NS_MEDIA            => "Media",
+       NS_SPECIAL          => "Special",
+       NS_MAIN             => "",
+       NS_TALK             => "Diskussion",
+       NS_USER             => "Användare",
+       NS_USER_TALK        => "Användardiskussion",
+       NS_PROJECT              => $wgMetaNamespace,
+       NS_PROJECT_TALK     => $wgMetaNamespace . "diskussion",
+       NS_IMAGE            => "Bild",
+       NS_IMAGE_TALK       => "Bilddiskussion",
+       NS_MEDIAWIKI        => "MediaWiki",
+       NS_MEDIAWIKI_TALK   => "MediaWiki_diskussion",
+       NS_TEMPLATE         => "Mall",
+       NS_TEMPLATE_TALK    => "Malldiskussion",
+       NS_HELP             => "Hjälp",
+       NS_HELP_TALK        => "Hjälp_diskussion",
+       NS_CATEGORY         => "Kategori",
+       NS_CATEGORY_TALK    => "Kategoridiskussion"
+) + $wgNamespaceNamesEn;
+
+/* inherit standard defaults */
+
+/* private */ $wgQuickbarSettingsSv = array(
+       "Ingen",
+       "Fast vänster",
+       "Fast höger",
+       "Flytande vänster"
+);
+
+/* private */ $wgSkinNamesSv = array(
+       'standard' => "Standard",
+       'nostalgia' => "Nostalgi",
+       'cologneblue' => "Cologne Blå",
+) + $wgSkinNamesEn;
+
+
+/* private */ $wgAllMessagesSv = array(
+// User Toggles
+
+"tog-underline"        => "Understryk länkar",
+"tog-highlightbroken"  => "Formatera trasiga länkar <a href=\"\" class=\"new\">så här</a> (alternativt: så här<a href=\"\" class=\"internal\">?</a>).",
+"tog-justify"          => "Justera indrag",
+"tog-hideminor"        => "Göm mindre redigeringar vid senaste ändring",
+"tog-usenewrc"         => "Avancerad 'Senaste ändringar'",
+"tog-numberheadings"   => "Automatisk numrering av överskrifter",
+"tog-showtoolbar"      => "Visa redigeringverktygsrad",
+"tog-rememberpassword" => "Kom ihåg lösenord till nästa besök",
+"tog-editwidth"        => "Redigeringsboxen har full bredd",
+"tog-editondblclick"   => "Redigera sidor med dubbelklick (JavaScript)",
+"tog-editsection"      => "Visa [edit]-länkar för att redigera sektioner",
+"tog-editsectiononrightclick" => "Högerklick på rubriker redigerar sektioner",
+"tog-showtoc"          => "Visa automatisk innehållsförteckning (på sidor med mer än 3 sektioner)",
+"tog-watchdefault"     => "Övervaka nya och ändrade artiklar",
+"tog-minordefault"     => "Markera som standard alla ändringer som mindre",
+"tog-previewontop"     => "Visa förhandsgranskning före textfältet istället för efter",
+"tog-nocache"          => "Slå av cachning av sidor",
+
+// Dates
+
+'sunday' => "söndag",
+'monday' => "måndag",
+'tuesday' => "tisdag",
+'wednesday' => "onsdag",
+'thursday' => "torsdag",
+'friday' => "fredag",
+'saturday' => "lördag",
+'january' => "januari",
+'february' => "februari",
+'march' => "mars",
+'april' => "april",
+'may_long' => "maj",
+'june' => "juni",
+'july' => "juli",
+'august' => "augusti",
+'september' => "september",
+'october' => "oktober",
+'november' => "november",
+'december' => "december",
+'jan' => "jan",
+'feb' => "feb",
+'mar' => "mar",
+'apr' => "apr",
+'may' => "maj",
+'jun' => "jun",
+'jul' => "jul",
+'aug' => "aug",
+'sep' => "sep",
+'oct' => "okt",
+'nov' => "nov",
+'dec' => "dec",
+
+
+// Bits of text used by many pages:
+//
+"linktrail"             => "/^((?:[a-z]|ä|ö|å)+)(.*)\$/sD",
+"mainpage"              => "Huvudsida",
+'portal'               => 'Kollektivportal',
+'portal-url'           => '{{ns:4}}:Kollektivportal',
+"about"                 => "Om",
+"aboutsite"             => "Om {{SITENAME}}",
+"aboutpage"            => "{{ns:4}}:Om",
+'article'               => 'Artikel',
+"help"                  => "Hjälp",
+"helppage"              => "{{ns:4}}:Hjälp",
+"bugreports"            => "Felrapporter",
+"bugreportspage"        => "{{ns:4}}:Felrapporter",
+"sitesupport"           => "Donationer",
+"faq"                   => "FAQ",
+"faqpage"               => "{{ns:4}}:FAQ",
+"edithelp"              => "Redigeringshjälp",
+"edithelppage"          => "{{ns:4}}:Hur_redigerar_jag_en_sida",
+"cancel"                => "Avbryt",
+"qbfind"                => "SnabbSök",
+"qbbrowse"              => "Genomsök",
+"qbedit"                => "Redigera",
+"qbpageoptions"         => "Sidinställningar",
+"qbpageinfo"            => "Sidinformation",
+"qbmyoptions"           => "Mina inställningar",
+"mypage"                => "Min sida",
+"mytalk"                => "Min diskussion",
+"currentevents"         => "-",
+"errorpagetitle"        => "Fel",
+"returnto"              => "Tillbaka till $1.",
+"tagline"               => "Från {{SITENAME}}",
+"whatlinkshere"         => "Vilka sidor länkar hit?",
+"help"                  => "Hjälp",
+"search"                => "Sök",
+"history"               => "Versionshistorik",
+"history_short"         => "Historik",
+"printableversion"      => "Skrivarvänlig version",
+"edit"                  => "Redigera",
+"editthispage"          => "Redigera den här sidan",
+"delete"                => "Ta bort",
+"deletethispage"        => "Ta bort den här sidan",
+"protect"               => "Skydda",
+"protectthispage"       => "Skydda den här sidan",
+"unprotect"             => "Ta bort skydd",
+"unprotectthispage"     => "Ta bort skydd från den här sidan",
+"newpage"               => "Ny sida",
+"talkpage"              => "Diskussionssida",
+"personaltools"         => "Personliga verktyg",
+"postcomment"           => "Skicka en kommentar",
+"addsection"            => "+",
+"articlepage"           => "Visa artikel",
+"subjectpage"           => "Ämnessida",
+"talk"                  => "Diskussion",
+"toolbox"               => "Verktygslåda",
+"userpage"              => "Visa användarsida",
+"wikipediapage"         => "Visa metasida",
+"imagepage"             => "Visa bildsida",
+"viewtalkpage"          => "Visa diskussion",
+"otherlanguages"        => "Andra språk",
+"redirectedfrom"        => "(Omdirigerad från $1)",
+"lastmodified"          => "Den här sidan blev senast ändrad $1.",
+"viewcount"             => "Den här sidan har visats $1 gånger.",
+"copyright"            => "Innehåll tillgängligt under $1.",
+"poweredby"            => "{{SITENAME}} körs med hjälp av [http://www.mediawiki.org/ MediaWiki], en öppen källkods-wikimotor.",
+"printsubtitle"         => "(Från {{SERVER}})",
+"protectedpage"         => "Skyddad sida",
+"administrators"        => "{{ns:4}}:Administratörer",
+"sysoptitle"            => "Sysop-behörighet krävs",
+"sysoptext"             => "Den här funktionen kan bara utföras av användare med \"sysop\" status.
+Se $1.",
+"developertitle"        => "Utvecklarbehörighet krävs",
+"developertext"         => "Den här funktionen kan bara utföras av användare med \"developer\" status.
+Se $1.",
+"nbytes"               => "$1 bytes",
+"go"                    => "Utför",
+"ok"                    => "OK",
+"sitetitle"             => "{{SITENAME}}",
+"pagetitle"            => "$1 - {{SITENAME}}",
+"sitesubtitle"          => "Den fria encyklopedin",
+"retrievedfrom"         => "Hämtad från \"$1\"",
+"newmessages"           => "Du har $1.",
+"newmessageslink"       => "nya meddelanden",
+"editsection"           => "edit",
+"toc"                   => "Innehåll",
+"showtoc"               => "visa",
+"hidetoc"               => "göm",
+"thisisdeleted"         => "Visa eller återställ $1?",
+"restorelink"           => "$1 raderade versioner",
+"feedlinks"             => "Matning:",
+
+// Short words for each namespace, by default used in the 'article' tab in monobook
+"nstab-main"           => "Artikel",
+"nstab-user"           => "Användarsida",
+"nstab-media"          => "Media",
+"nstab-special"        => "Speciell",
+"nstab-wp"             => "Om",
+"nstab-image"          => "Bild",
+"nstab-mediawiki"      => "Meddelande",
+"nstab-template"       => "Mall",
+"nstab-help"           => "Hjälp",
+"nstab-category"       => "Kategori",
+
+
+// Main script and global functions
+//
+"nosuchaction"          => "Funktionen finns inte",
+"nosuchactiontext"      => "Den funktion som specificerats i URL:en kan inte
+hittas av {{SITENAME}}programvaran",
+"nosuchspecialpage"     => "Sådan specialsida finns inte",
+"nospecialpagetext"     => "Du har önskat en specialsida som inte
+hittas av {{SITENAME}}programvaran.",
+
+// General errors
+//
+"error"                 => "Fel",
+"databaseerror"         => "Databasfel",
+"dberrortext"           => "Ett syntaxfel i databasfrågan har uppstått.
+Den senste utförda databasfrågan var:
+<blockquote><tt>$1</tt></blockquote>
+från funktionen \"<tt>$2</tt>\".
+MySQL returnerade felen \"$3<tt>: $4</tt>\".",
+"noconnect"             => "Kunde inte ansluta till databasen på $1",
+"nodb"                  => "Kunde inte välja databasen $1",
+"readonly"              => "Databasen är skrivskyddad",
+"enterlockreason"       => "Skriv en grund för skrivskyddet, inklusive
+en uppskattning på när skrivskyddet skall upphävas",
+"readonlytext"          => "{{SITENAME}}databasen är för ögonblicket skrivskyddad för
+nya sidor och andra modifikationer, beroende på rutinmässigt
+underhåll av databasen, varefter den återgår till normalstatus.
+Den administratör som skrivskyddade den har gett följande förklaring:
+<p>$1",
+"missingarticle"        => "Databasen fann inte texten på en sida
+som den skulle hitta, med namnet \"$1\".
+Dette är inte ett databas fel, utan beror på ett fel i mjukvaran.
+Skicka vänligen en rapport om detta till en administratör, där du också nämner
+URL:en.",
+"internalerror"         => "Internt fel",
+"filecopyerror"         => "Kunde inte kopiera filen \"$1\" til \"$2\".",
+"filerenameerror"       => "Kunde inte byta namn på filen \"$1\" til \"$2\".",
+"filedeleteerror"       => "Kunde inte radera filen \"$1\".",
+"filenotfound"          => "Kunde inte hitta filen \"$1\".",
+"unexpected"            => "Oväntat värde: \"$1\"=\"$2\".",
+"formerror"             => "Fel: Kunde inte sända formulär",
+"badarticleerror"       => "Den här funktionen kan inte utföras på den här sidan.",
+"cannotdelete"          => "Kunde inte radera sidan, eller filen som specificerades.",
+"badtitle"              => "Felaktig titel",
+"badtitletext"          => "Den önskade sidans titel var inte tillåten, tom eller sidan
+är felaktigt länkad från en {{SITENAME}} på ett annat språk.",
+
+
+// Login and logout pages
+//
+"logouttitle"           => "Logga ut Användare",
+"logouttext"            => "Du är nu utloggad.
+Du kan fortsätta som anonym {{SITENAME}}användare, eller så kan du logga in
+igen som samma eller annan användare.\n",
+
+"welcomecreation"       => "<h2>Välkommen, $1!</h2><p>Ditt konto har skapats. Glöm inte att anpassa dina {{SITENAME}}inställningar.",
+
+"loginpagetitle"        => "Logga in Användare",
+"yourname"              => "Ditt användarnamn",
+"yourpassword"          => "Ditt lösenord",
+"yourpasswordagain"     => "Upprepa lösenord",
+"newusersonly"          => " (bara för nya användare)",
+"remembermypassword"    => "Kom ihåg mitt lösenord till nästa gång.",
+"loginproblem"          => "<b>Det var svårt att logga in dig .</b><br />Pröva igen!",
+"alreadyloggedin"       => "<strong>Användare $1, du är redan inloggad !</strong><br />\n",
+
+"login"                 => "Logga in",
+"userlogin"             => "Logga in",
+"logout"                => "Logga ut",
+"userlogout"            => "Logga ut",
+"notloggedin"          => "Ej inloggad",
+"createaccount"         => "Skapa ett konto",
+"badretype"             => "De lösenord du uppgett överenstämmer inte med varandra.",
+"userexists"            => "Detta användarnamn används redan. Ange ett annat användarnamn.",
+"youremail"             => "Din e-postadress",
+"yournick"              => "Ditt smeknamn (till signaturer)",
+"emailforlost"          => "Har du glömt ditt lösenord, så kan du få ett nytt lösenord skickat till din e-post",
+"loginerror"            => "Inloggningsproblem",
+"noname"                => "Det användarnamn som du angett finns inte",
+"loginsuccesstitle"     => "Inloggningen lyckades",
+"loginsuccess"          => "Du är nu inloggad på wikipedia med användarnamnet \"$1\".",
+"nosuchuser"            => "Det finns ingen användare med namnet \"$1\".
+Kontrollera stavningen, eller använd formuläret nedan för att skapa ett nytt konto.",
+"wrongpassword"         => "Lösenordet du skrev är felaktigt. Pröva igen",
+"mailmypassword"        => "Sänd mig ett nytt lösenord",
+"passwordremindertitle" => "Nytt lösenord från {{SITENAME}}",
+"passwordremindertext"  => "Någon (förmodligen du, med IP-numret $1)
+har bett oss sända dig ett nytt lösenord för din {{SITENAME}}-inloggning
+Lösenordet för användare \"$2\" är nu \"$3\".
+Du ska logga in på din användare och byta lösenord.",
+"noemail"               => "Det finns ingen e-postadress registrerad för användare \"$1\".",
+"passwordsent"          => "Ett nytt lösenord har skickats till e-posten registrerad av användaren\"$1\".
+Var snäll och logga in igen när du fått meddelandet.",
+
+
+// Edit pages
+//
+"summary"               => "Sammanfattning",
+"minoredit"             => "Detta är en mindre ändring",
+"watchthis"             => "Bevaka den här artikeln",
+"savearticle"           => "Spara",
+"preview"               => "Förhandsgranska",
+"showpreview"           => "Visa förhandgranskning",
+"blockedtitle"          => "Användaren är spärrad",
+"blockedtext"           => "Ditt användarnamn har blivit spärrat av $1.
+Anledning är att:<br />''$2''<p>Ta kontakt med $1 eller en av de andra
+[[{{ns:4}}:Administratörer|administratörerna]] för att diskutera varför du blivit spärrad", // "
+"newarticle"            => "(Ny)",
+"newarticletext"        => "Du har klickat på en röd länk, en sida som inte finns ännu. Du kan hjälpa till genom att själv skriva vad du vet om ämnet i fältet nedan. Om du inte vill skriva något kan du bara trycka på \"tillbaka\" i din webbläsare.",
+"anontalkpagetext"      => "---- ''Detta är en diskussionssida för en anonym användare, en användare som inte har skapat sig ett konto, eller som inte har loggat in på det. Vi måste därför använda personens numeriska [[IP-adress]] för identifiera honom eller henne. En sådan IP-adress kan ibland användas av flera olika personer. Om du är en anonym användare och ser meddelanden på den här sidan som inte tycks vara riktade till dig, var vänlig [[Special:Userlogin|logga in]] så du undviker förväxling med andra anonyma användare i framtiden.'' ",
+"noarticletext"         => "(Det finns för tillfället ingen text på den här sidan.)",
+"updated"               => "(Uppdaterad)",
+"note"                  => "<strong>Notera:</strong> ",
+"previewnote"           => "Observera att detta är en förhandsvisning, och att sidan ännu inte sparats!",
+"previewconflict"       => "Den här förhandsvisningen är resultatet av den
+redigerbara texten ovanför,
+så som det kommer att se ut om du väljer att spara.",
+"editing"               => "Redigerar $1",
+"editconflict"          => "Redigeringskonflikt: $1",
+"explainconflict"       => "Någon har ändrat den här sidan efter att du började att redigera den.
+Det översta text blocket innehåller den nuvarande texten.
+Dina ändringer syns i det nedersta blocket.
+Du måste infoga dina ändringar i den existerande texten.
+<b>Bara</b> texten i den översta textboxen sparas om du trycker \"Spara sida\".<br />",
+"yourtext"              => "Din text",
+"storedversion"         => "Din sparade version",
+"editingold"            => "<strong>VARNING: Du redigerar en gammal version
+av den här sidan. Om du sparar den, kommer alla ändringar på denns sida föregående revison att bli överskrivna.</strong>",
+"yourdiff"              => "Skillnader",
+"copyrightwarning"      => "Observera att alla bidrag till {{SITENAME}} är
+att betrakta som utgivna under GNU Free Documentation License
+(se $1 för detaljer).
+Om du inte vill ha din text redigerad och kopierad efter andras gottfinnade så skall du inte skriva någon text här.<br />
+Du lovar oss också att du skrev texten själv, eller kopierade från public domain eller liknande fri resurs.<br />
+<strong>LÄGG ALDRIG UT UPPHOVSRÄTTSSKYDDAT MATERIAL HÄR UTAN FÖRFATTARENS TILLÅTELSE!</strong>",
+
+"longpagewarning"       => "<strong>VARNING: Den här artikeln är $1 kilobytes lång; vissa äldre webbläsare
+kan ha problem med att redigera sidor som är omkring 32 kb eller större.
+Du kanske vill överväga att dela upp artikeln i mindre delar.</strong>",
+"readonlywarning"       => "<strong>VARNING: Databasen är tillfälligt låst för underhåll. Du kommer inte att kunna spara
+dina ändringar just nu. För säkerhets skull kanske du vill överväga att kopiera över texten till din egen dator tills
+databasen är upplåst igen.</strong>",
+"protectedpagewarning"  => "<strong>VARNING:  Den här sidan har låsts så att bara administratörer kan redigera den.
+Försäkra dig om att du följer rekommendationerna för [[Project:Skyddade sidor|skyddade sidor]]</strong>",
+
+// History pages
+//
+"revhistory"            => "Versionshistoria",
+"nohistory"             => "Det finns ingen versionshistoria för den här sidan.",
+"revnotfound"           => "Versionen hittades inte",
+"revnotfoundtext"       => "Den gamla versionen av den sida du frågade efter kan inte hittas. Kontrollera den URL du använde för att nå den här sidan.\n",
+"loadhist"              => "Läser sidans versioner",
+"currentrev"            => "Nuvarande version",
+"revisionasof"          => "Versionen från $1",
+"cur"                   => "nuvarande",
+"next"                  => "nästa",
+"last"                  => "föregående",
+"orig"                  => "original",
+"histlegend"            => "Förklaring: (nuvarande) = skillnad mot den nuvarande versionen,
+ (föregående) = skillnad mot den föregående versionen, M = mindre ändring",
+
+
+// Diffs
+//
+"difference"            => "(Skillnad mellan versioner)",
+"loadingrev"            => "läser version för att se skillnad",
+"lineno"                => "Rad $1:",
+"editcurrent"           => "Redigera den nuvarande versionen av den här sidan",
+
+// Search results
+//
+"searchresults"         => "Sökresultat",
+"searchresulttext"      => "För mer information om sökning på {{SITENAME}}, se [[Project:Sökning|Sökning på {{SITENAME}}]].",
+"searchquery"           => "For query \"$1\"",
+"badquery"              => "Felaktigt utformat sökbegrepp",
+"badquerytext"          => "Vi kunde inte utföra din sökning.
+Detta beror sannolikt på att du försökt söka efter ett ord med färre än tre bokstäver, något som f.n. inte stöds. Det kan också vara så att du har anget en felaktig sökning, till exempel \"fisk och och skaldjur\". Prova att formulera om sökningen.",
+"matchtotals"           => "Sökordet förekommer i \"$1\" överensstämde med $2 artiklar titlar
+och texter i $3 artiklar.",
+"titlematches"          => "Artikel titlar som överensstämmer med sökordet",
+"notitlematches"        => "Ingen artikel titlar överensstämmer med sökordet",
+"textmatches"           => "Artikel texter som överensstämmer med sökordet",
+"notextmatches"         => "Ingen artikel texter överensstämmer med sökordet",
+"prevn"                 => "förra $1",
+"nextn"                 => "nästa $1",
+
+"viewprevnext"          => "Om ($1) ($2) ($3).",
+"showingresults"        => "Nedan visas <b>$1</b> resultat som startar med nummer <b>$2</b>.",
+"nonefound"             => "<strong>Note</strong>: Misslyckade sökningar förorsakas ofta av
+ att man söker efter vanliga ord som \"har\" och \"från\",
+vilka inte indexeras, eller att specificera flera sökord (bara
+sidor som innehåller alla sökorden hittas).",
+"powersearch"           => "Sök",
+"powersearchtext"       => "
+Sök i namnutrymme :<br />
+$1<br />
+$2 List redirects &nbsp; Sök efter $3 $9",
+
+
+// Preferences page
+//
+"preferences"           => "Inställningar",
+"prefsnologin"          => "Du är inte inloggad",
+"prefsnologintext"      => "Du måste vara [[Special:Userlogin|inloggad]]
+för att kunna ändra i inställningar.",
+"prefslogintext"        => "Du är inloggad som \"$1\".
+Ditt IP-nummer är $2.",
+"prefsreset"            => "Inställningar har blivit återställda från minne.",
+"qbsettings"            => "Inställningar för snabbmeny",
+"changepassword"        => "Byt lösenord",
+"skin"                  => "Utseende",
+"saveprefs"             => "Spara inställningar",
+"resetprefs"            => "Återställ inställningar",
+"oldpassword"           => "Gammalt lösenord",
+"newpassword"           => "Nytt lösenord",
+"retypenew"             => "Skriv om nytt lösenord",
+"textboxsize"           => "Textbox dimensioner",
+"rows"                  => "Rader",
+"columns"               => "Kolumner",
+"searchresultshead"     => "Inställningar för sökresultat",
+"resultsperpage"        => "Resultat att visa per sida",
+"contextlines"          => "Linjer att visa per sida",
+"contextchars"          => "Antalet bokstäver per linje i resultatet",
+"stubthreshold"         => "Gränser för visning av stubs",
+"recentchangescount"    => "Antalet artiklar i \"senaste ändringarna\" ",
+"savedprefs"            => "Dina inställningar har blivit sparade",
+"timezonetext"          => "Skriv in antalet timmar som din lokal tid skiljer sig från
+serverns klocka (UTC).
+Den blir automatiskt inställd efter svensk tid eller skulle man till exempel för svensk vintertid, endast ha \"1\" (och \"2\" när vi har sommartid).",
+"localtime"             => "Lokal tid",
+"timezoneoffset"        => "Utjämna",
+"emailflag"             => "Hindra andra användare från att skicka e-post till dig",
+
+// Recent changes
+//
+"recentchanges"         => "Senaste ändringarna",
+"recentchangestext"     => "Se de senaste redigerade sidorna i {{SITENAME}} på den här sidan.",
+"rcloaderr"             => "Läser senaste redigerade sidor",
+"rcnote"                => "Nedanför är de senaste <strong>$1</strong> ändringarna under de sista <strong>$2</strong> dagarna.",
+"rcnotefrom"            => "Nedanför är ändringarna från <b>$2</b> till <b>$1</b> visade.",
+"rclistfrom"            => "Visa nya ändringar från och med $1",
+"rclinks"               => "Visa de senaste $1 ändringarna under de senaste $2 dagarna",
+// "rclinks"             => "Visa de senaste $1 ändringarna under de senaste $2 dagarna",
+"rchide"                => "i $4 form; $1 mindre ändringar; $2 andra namnrum; $3 mer än en redigering.",
+"diff"                  => "skillnad",
+"hist"                  => "historia",
+"hide"                  => "göm",
+"show"                  => "visa",
+
+"tableform"             => "tabell",
+"listform"              => "lista",
+"nchanges"              => "$1 ändringar",
+"minoreditletter"       => "M",
+"newpageletter"         => "N",
+
+// Upload
+//
+"upload"                => "Ladda upp",
+"uploadbtn"             => "Ladda upp fil",
+"uploadlink"            => "Ladda upp bild",
+"reupload"              => "återuppladdning",
+"reuploaddesc"          => "Tillbaka till uppladdningsformulär.",
+"uploadnologin"         => "Inte inloggad",
+"uploadnologintext"     => "Du måste vara [[Special:Userlogin|inloggad]]
+för att kunna ladda upp filer.",
+"uploaderror"           => "Uppladdnings fel",
+"uploadtext"            => "'''STOPP!''' Innan du laddar upp här,
+så måste du ha läst och följa {{SITENAME}}s
+[[Project:Policy om bruk av bilder|policy om hur bilder får användas]].
+
+För att visa eller söka tidigare uppladdade bilder gå till
+[[Special:Imagelist|lista över uppladdade bilder]].
+Uppladdningar och borttagningar loggas i
+[[Project:Upload_log|uppladdnings logg]].
+
+Använd formuläret nedan för att ladda upp nya filer, som
+du kan illustrera dina artiklar med.
+På de flesta webbläsare kommer du att se en \"Browse...\" knapp eller en
+\"Öppna...\" knapp, som startar ditt operativsystems dialogruta för att öppna filer. När du valt en fil kommer namnet på den filen att visas i textfältet brevid knappen. Du måste även kryssa för rutan, för att du inte gör något som strider mot upphovsrätten av filen som laddas upp.
+Tryck på \"Upload\" knappen för att ladda upp filen.
+Detta kan dröja ett tag om du har en långsam internetförbindelse.
+
+Formaten på filerna ska helst vara JPEG för bilder, PNG för ritningar
+och andra ikonliknande bilder och OGG för ljud.
+Var vänlig namnge filen med ett så beskrivande namn som möjligt, för att undvika förvirring.
+För att använda en fil i en artikel, skriv följande om det är en bild: '''<nowiki>[[bild:filnamn.jpg]]</nowiki>''' eller '''<nowiki>[[bild:filnamn.png|alternativ text]]</nowiki>'''
+eller '''<nowiki>[[media:filnamn.ogg]]</nowiki>''' om det är en ljudfil.
+
+Kom ihåg att det här är en wiki, vilket gör att andra kan redigera eller ta bort dina uppladdningar om de tycker de inte passar i en artikel. Om du missbrukar systemet med uppladdningar kommer filen avlägsnas och du bli spärrad från att ladda upp filer i framtiden.",
+"uploadlog"             => "upload log",
+"uploadlogpage"         => "Upload_log",
+"uploadlogpagetext"     => "Nedan följer en lista med de senaste uppladdade filerna.
+Alla tider visas efter serverns tid (UTC).
+<ul>
+</ul>
+",
+"filename"              => "Filnamn",
+"filedesc"              => "Beskrivning",
+"copyrightpage"         => "{{ns:4}}:copyright",
+"copyrightpagename"     => "{{SITENAME}} copyright",
+"uploadedfiles"         => "Uppladdade filer",
+"ignorewarning"         => "Ignorera varning och spara fil.",
+"minlength"             => "Namnet på bildfilen ska vara minst tre bokstäver",
+"badfilename"           => "Bildnamn har blivit ändrat till \"$1\".",
+"badfiletype"           => "\".$1\" är inte ett rekomenderat bildformat.",
+"largefile"             => "Bilder ska helst inte vara större än 100k.",
+"successfulupload"      => "Uppladdningen lyckades",
+"fileuploaded"          => "Filen \"$1\" laddades upp korrekt.
+Följ den här länken: ($2) till beskrivningssidan och fyll i
+information om filen, som till exempel var den kommer ifrån,
+när den skapades och vem som gjort den och allt annat du vet om den.",
+"uploadwarning"         => "Uppladdnings varning",
+"savefile"              => "Spara fil",
+"uploadedimage"         => "uppladdad \"[[$1]]\"",
+
+// Image list
+//
+"imagelist"             => "Bildlista",
+"imagelisttext"         => "Nedan är en lista med $1 bilder sorterad $2",
+"getimagelist"          => "hämta bildlista",
+"ilsubmit"              => "Sök",
+"showlast"              => "Visa de senaste $1 bilderna sorterad $2.",
+"byname"                => "efter namn",
+"bydate"                => "efter datum",
+"bysize"                => "efter storlek",
+"imgdelete"             => "ta bort",
+"imgdesc"               => "beskrivning",
+"imglegend"             => "Legend: (beskrivning) = visa/redigera bildbeskrivning.",
+"imghistory"            => "Bildhistoria",
+"revertimg"             => "återgå",
+"deleteimg"             => "radera",
+"deleteimgcompletely"             => "radera",
+"imghistlegend"         => "Legend: (nuvarande) = detta är den nuvarande bilden,
+(ta bort) = ta bort den gamla version, (återgå) = återgå till en gammal version.
+<br /><i>Klicka på ett datum för att se bilden som laddades upp den dagen</i>.", //"
+"imagelinks"            => "Bildlänk",
+"linkstoimage"          => "De följande sidorna länkar till den här bilden:",
+"nolinkstoimage"        => "Det finns ingen sida som länkar till den här bilden.",
+
+// Statistics
+//
+"statistics"            => "Statistik",
+"sitestats"             => "Statistiksida",
+"userstats"             => "Användarstatistik",
+"sitestatstext"         => "Det är <b>$1</b> sidor i databasen.
+Detta inkluderer diskussionssidorna, sidor om {{SITENAME}}, mycket korta\"stub\"
+sidor, omdirigeringssidor, och andra sidor som kvalificerar sig som artiklar.
+Om man tar bort ovanstående så är det <b>$2</b> sidor som anses som riktiga artiklar.<p>
+Det har varit totalt <b>$3</b> sidvisningar och det har varit <b>$4</b> sidor som har ändrats
+sedan uppdateringen av mjukvaran (1 december 2002).
+Det vill säga <b>$5</b> ändringar per sida genomsnittligt,
+och <b>$6</b> sidvisningar per ändring.",
+"userstatstext"         => "Det är <b>$1</b> registrerade användare.
+<b>$2</b> av dem är administratörer (se $3).",
+
+// Maintenance Page
+//
+"maintenance"           => "Underhållssida",
+"maintnancepagetext"    => "Den här sidan innehåller flera verktyg för att sköta sidan. Vissa av dessa funktioner tenderar att stressa databasen (allt tar lång tid), så var snäll och  tryck inte på reloadknappen varje gång du gjort en liten ändring.",
+"maintenancebacklink"   => "Tillbaka till underhållssidorna",
+"disambiguations"       => "Sidor med tvetydiga länkar",
+"disambiguationspage"   => "{{ns:4}}:Länkar till sidor med tvetydiga titlar",
+"disambiguationstext"   => "Följande artiklar länkar till en <i>sidor med tvetydliga titlar</i>. De ska länka till en sidor med en korrekt titel.<br />En sida behandlar som tvetydig om den länkar från $1. <br />Länkar från andra namngrupper är <i>inte</i> listade här.",
+"doubleredirects"       => "Dubbla omdirigeringar",
+"doubleredirectstext"   => "<b>OBS:</b> Den här listan kan innehålla falska resultat. Detta betyder normalt att det finns ytterligare text under den första #REDIRECT.<br />\n Varje rad innehåller en länk till den första och andra omdirigering och den första raden av den andra omdirigeringen ger oftast den \"riktiga\" artikeln, vilket egentligen den första omdirigeringen ska peka på.",
+"brokenredirects"       => "Dåliga omdirigeringar",
+"brokenredirectstext"   => "Följande länkar omdirigerar till en artikel som inte existerar.",
+"selflinks"             => "Sidor med länkar till sig själva",
+"selflinkstext"         => "Följande sidor innehåller länkar till sig själv, vilket de inte ska göra.",
+"mispeelings"           => "Sidor med felstavningar",
+"mispeelingstext"       => "Följande sidor innerhåller vanliga felstavningar, som visas i $1. Den korrekta stavningen kanske ska se ut såhär.",
+"mispeelingspage"       => "Lista med vanliga stavfel",
+"missinglanguagelinks"  => "Saknade språklänkar",
+"missinglanguagelinksbutton"    => "Sök efter saknade språklänkar för",
+"missinglanguagelinkstext"      => "De här artiklarna är <i>inte</i> länkade
+till deras i $1. Redirects och undersidor visas <i>inte</i>.",
+
+// Miscellaneous special pages
+//
+"orphans"               => "Föräldralösa sidor",
+"lonelypages"           => "Föräldralösa sidor",
+"unusedimages"          => "Oanvända bilder",
+"popularpages"          => "Populära sidor",
+"nviews"                => "$1 visningar",
+"wantedpages"           => "Önskelista",
+"nlinks"                => "$1 länkar",
+"allpages"              => "Alla sidor",
+"randompage"            => "Slumpartikel",
+"shortpages"            => "Korta sidor",
+"longpages"             => "Långa sidor",
+"listusers"             => "Användarlista",
+"specialpages"          => "Speciella sidor",
+"spheading"             => "Speciella sidor",
+"protectpage"           => "Skydda sida",
+"recentchangeslinked"   => "Relaterade ändringar",
+"rclsub"                => "(till sidor som är länkade från \"$1\")",
+"debug"                 => "Debug",
+"newpages"              => "Nya sidor",
+"movethispage"          => "Flytta den här sidan",
+"unusedimagestext"      => "<p>Lägg märket till att andra hemsidor
+som till exempel de internationella wikipedias kan länka till bilder
+med en direkt URL, och kan därför bli listade här trots att de används kontinuerligt.",
+"booksources"           => "Bokkällor",
+"booksourcetext"        => "Nedan följer en lista över länkar till hemsidor som säljer
+nya och begagnade böcker, och mycket annan information om de böcker du söker.
+{{SITENAME}} har <b>inget</b> affärssamarbete med ovanstående företag och ska inte heller tolkas som en uppmuntran.",
+
+// Email this user
+//
+"mailnologin"           => "Ingen adress att skicka till",
+"mailnologintext"       => "Du ska vara [[Special:Userlogin|inloggad]]
+och ha angivit en korrekt epost-adress i dina [[Special:Preferences|användarinställningar]]
+för att kunna skicka e-post till andra användare.",
+"emailuser"             => "Skicka e-post till den här användaren",
+"emailpage"             => "Skicka e-post till annan användare",
+"emailpagetext"         => "Om den här användaren har skrivit in en korrekt e-postadress, i sina
+användarinställningar, kommer formuläret nedan skicka ett meddelande.
+Den epost-adress du anget i dina användarinställningar kommer att skrivas
+i \"Från\"fältet i detta e-post, så mottagaren har möjlighet att svara.",
+"noemailtitle"          => "Ingen e-postadress",
+"noemailtext"           => "Den här användaren har inte angivet en korrekt e-postadress eller
+valt att inte ta emot något mail från andra användare.",
+"emailfrom"             => "Från",
+"emailto"               => "Till",
+"emailsubject"          => "Ämne",
+"emailmessage"          => "Meddelande",
+"emailsend"             => "Skickat",
+"emailsent"             => "E-post är nu skickat",
+"emailsenttext"         => "Din e-post har skickats.",
+
+// Watchlist
+//
+"watchlist"             => "Min övervakningslista",
+"watchlistsub"          => "(för användare \"$1\")",
+"nowatchlist"           => "Du har inga sidor upptagna på din övervakningslista.",
+"watchnologin"          => "Du är inte inloggad",
+"watchnologintext"      => "Du ska vara [[Special:Userlogin|inloggad]]
+för att kunna göra ändringar på din övervakningslista.",
+"addedwatch"            => "Tillagd på övervakningslistan",
+"addedwatchtext"        => "Sidan \"$1\" har satts upp på din <a href=\"" .
+  "{{localurle:Special:Watchlist}}\">övervakningslista</a>.
+Framtida ändringar av den här sidan och dess diskussionssida vill listas där,
+
+och sidan kommer att markeras med <b>fet stil</b> i <a href=\"" .
+  "{{localurle:Special:Recentchanges}}\">listan över de senaste ändringarna
+</a> för att lättare kunna hittas</p>
+
+<p>Om du vill ta bort den här sidan från din övervakningslista, så klicka
+\"Ta bort övervakning\" ute i sidan.",
+"removedwatch"          => "Borttagen från övervakningslista",
+"removedwatchtext"      => "Sidan \"$1\" har blivit borttagen från din övervakningslista",
+"watchthispage"         => "Övervaka sida",
+"unwatchthispage"       => "Stoppa övervakning",
+"notanarticle"          => "Inte en artikel",
+'watch'                 => 'Bevaka',
+'unwatch'               => 'Obevaka',
+
+// Delete/protect/revert
+//
+"deletepage"            => "Ta bort sida",
+"confirm"               => "Bekräfta",
+"excontent"             => "före radering: '$1'",
+"exbeforeblank"         => "före tömning: '$1'",
+"exblank"               => "sidan var tom",
+"confirmdelete"         => "Bekräfta borttagning",
+"deletesub"             => "(Tar bort \"$1\")",
+"confirmdeletetext"     => "Du håller på och permanent ta bort en sida
+eller bild med all dess historia från databasen.
+Bekräfta att du förstår vad du håller på med och vilka konsekvenser
+detta leder till, och att det följer
+[[{{ns:4}}:Policy]].",
+"actioncomplete"        => "Genomfört",
+"deletedtext"           => "\"$1\" har blivit borttagen.
+Se $2 för lista över senaste borttagningar",
+"deletedarticle"        => "borttagen \"\$1\"",
+"dellogpage"            => "Borttagningslogg",
+"dellogpagetext"        => "Nedan är en lista över de senaste borttagningarna.
+De tidsangivelser som anges följer serverns klocka (UTC).
+<ul>
+</ul>
+",
+"deletionlog"           => "borttagningslogg",
+"reverted"              => "Återgått till yngre version",
+"deletecomment"         => "Anledningen till borttagning",
+"imagereverted"         => "Återställandet av nyare artikelversion lyckades",
+
+// Undelete
+//
+"undelete"              => "Återställ borttagna sidor",
+"undeletepage"          => "Visa och återställ borttagna sidor",
+"undeletepagetext"      => "Följande sidor har blivit borttagna, men är fortfarande i arkivet och kan användas vid återställning.
+Arkivet kan ibland rensas på gamla versioner.",
+"undeletearticle"       => "Återställ borttagen artikel",
+"undeleterevisions"     => "$1 versioner arkiverade",
+"undeletehistory"       => "Om du återställer sidan kommer allt tidigare versioner att sparas i versionshanteraren.
+Om en ny sida med samma namn har blivit skapad sedan borttagningen så kommer den återställda versionen att
+hamna i den äldre versionshanteraren och den senaste versionen av sidan kommer inte blir automatiskt ersatt.",
+"undeleterevision"      => "Tog bort version $1",
+"undeletebtn"           => "Återställd!",
+"undeletedarticle"      => "återställd \"$1\"",
+"undeletedtext"         => "Artikeln [[$1]] har blivit återställd
+Se [[{{ns:4}}:Borttagningslogg]] för en lista över nyligen gjorda borttagningar och återställningar",
+
+// Contributions
+//
+"contributions"         => "Användarbidrag",
+"mycontris"             => "Mina bidrag",
+"contribsub"            => "För $1",
+"nocontribs"            => "Inga ändringar var funna som motsvarar dessa kriterier",
+"ucnote"                => "Nedan visas dennes användares senaste <b>$1</b> ändringar, under de senaste <b>$2</b> dagarna.",
+"uclinks"               => "Visa de senaste $1 ändringarna. Visa de senaste $2 dagarna.",
+"uctop"                 => " (top)",
+
+// What links here
+//
+"whatlinkshere"         => "Vilka sidor länkar hit",
+"notargettitle"         => "Inget mål",
+"notargettext"          => "Du har inte specificerat en sida eller användare
+för att genomföra den här funktionen.",
+"linklistsub"           => "(Länklista)",
+"linkshere"             => "Följande sidor länkas hit:",
+"nolinkshere"           => "Inga sidor länkar hit.",
+"isredirect"            => "Länka vidare sida",
+
+// Block/unblock IP
+//
+"blockip"               => "Blockera IP-adress",
+"blockiptext"           => "Använd formuläret nedan för att blockera skrivåtkomst
+från en viss IP-adress
+Detta ska bara genomföras för att stoppa klotter och
+överstämma med [[{{ns:4}}:Politik|{{SITENAME}} politik]].
+Fyll i anledningen till blockering nedan (till exempel vilka artiklar som klottrats ner).",
+"ipaddress"             => "IP-adress",
+"ipbreason"             => "Anledning",
+"ipbsubmit"             => "Blockera den här IP-adressen",
+"badipaddress"          => "Du har inte skrivit IP-adressen korrekt.",
+"blockipsuccesssub"     => "Blockeringen lyckades",
+"blockipsuccesstext"    => "IP-adressen \"$1\" har blockerats.
+<br />Se [[Speciel:Ipblocklist|IP blockeringslistan]] för alla blockeringar.",
+"unblockip"             => "Ta bort blockering av IP-adress",
+"unblockiptext"         => "Använd nedanstående formulär för att återställa skrivrättigheten för en tidigare blockerad IP-adress.",
+"ipusubmit"             => "Ta bort blockering för den här adressen",
+"ipusuccess"            => "Blockeringen för IP-adressen \"$1\" har tagits bort",
+
+"ipblocklist"           => "Lista över blockerade IP-adresser",
+"blocklistline"         => "$1, $2 blockerade $3 ($4)",
+"blocklink"             => "blockera",
+"unblocklink"           => "ta bort blockering",
+"contribslink"          => "bidrag",
+
+// Developer tools
+//
+"lockdb"                => "Lås databas",
+"unlockdb"              => "Lås upp databas",
+"lockdbtext"            => "En låsning av databasen hindrar alla användare från att redigera sidor, ändra inställningar och andra saker som kräver ändringar i databasen.
+Bekräfta att du verkligen vill göra detta och att du kommer att låsa upp databasen när underhållet är utfört.",
+"unlockdbtext"          => "Genom att låsa upp databasen kommer alla användare att kunna redigera sidor, ändra inställningar etc. igen.
+Bekräfta att du vill göra detta.",
+"lockconfirm"           => "Ja, jag vill verkligen låsa databasen.",
+"unlockconfirm"         => "Ja, jag vill verkligen låsa upp databasen.",
+"lockbtn"               => "Lås databasen",
+"unlockbtn"             => "Lås upp databasen",
+"locknoconfirm"         => "Du har inte bekräftat låsningen.",
+"lockdbsuccesssub"      => "Databasen har låsts",
+"unlockdbsuccesssub"    => "Databasen har låsts upp",
+"lockdbsuccesstext"     => "{{SITENAME}}databasen är låst.
+<br />Kom ihåg att ta bort låsningen när du är färdig med ditt underhåll.",
+"unlockdbsuccesstext"   => "{{SITENAME}}databasen är upplåst.",
+
+// Move page
+//
+"movepage"              => "Flytta sida",
+"movepagetext"          => "Formuläret nedan byter namn på sidan och flyttar hela dess
+ historia till det nya namnet. Den gamla sidan blir en omdirigeringssida till den nya.
+Länkar till den gamla sidan kommer inte att ändras. Om det finns en diskussionssida
+kommer den inte att flyttas.
+
+<b>OBS!</b> Detta kan innebära en drastisk ändring på en populär sida;
+var säker på att du inser konsekvenserna i förväg.",
+
+"movearticle"           => "Flytta sida",
+"movenologin"           => "Ej inloggad",
+"movenologintext"       => "Du måste vara registrerad användare och ha [[Speciel:Userlogin|loggat in]]
+för att kunna flytta en sida.",
+"newtitle"              => "Till ny titel",
+"movepagebtn"           => "Flytta sida",
+"pagemovedsub"          => "Sidan har flyttats",
+"pagemovedtext"         => "Sidan \"[[$1]]\" har flyttats till \"[[$2]]\".",
+"articleexists"         => "Det finns redan en sida med detta namn eller så är namnet du angett ogiltigt. Välj ett annat namn.",
+"talkexists"            => "Sidan  flyttades korrekt, men den tilhörande diskussionssidan kunde inte flyttas, eftersom det redan existerar en sida med den här nya titeln. Du måste sammanfoga dem manuellt.",
+"movedto"               => "flyttat till",
+"movetalk"              => "Flytta även diskussionssidan, om den finns.",
+"talkpagemoved"         => "Sidans diskussionssida flyttades också.",
+"talkpagenotmoved"      => "Sidans diskussionssida flyttades <strong>inte</strong>.",
+
+# Move page
+#
+"movepage"             => "Move page",
+"movepagetext" => "Using the form below will rename a page, moving all
+of its history to the new name.
+The old title will become a redirect page to the new title.
+Links to the old page title will not be changed; be sure to
+check for double or broken redirects.
+You are responsible for making sure that links continue to
+point where they are supposed to go.
+
+Note that the page will '''not''' be moved if there is already
+a page at the new title, unless it is empty or a redirect and has no
+past edit history. This means that you can rename a page back to where
+it was just renamed from if you make a mistake, and you cannot overwrite
+an existing page.
+
+<b>WARNING!</b>
+This can be a drastic and unexpected change for a popular page;
+please be sure you understand the consequences of this before
+proceeding.",
+"movepagetalktext" => "The associated talk page, if any, will be automatically moved along with it '''unless:'''
+*You are moving the page across namespaces,
+*A non-empty talk page already exists under the new name, or
+*You uncheck the box below.
+
+In those cases, you will have to move or merge the page manually if desired.",
+"movearticle"  => "Move page",
+"movenologin"  => "Not logged in",
+"movenologintext" => "You must be a registered user and [[Special:Userlogin|logged in]]
+to move a page.",
+"newtitle"             => "To new title",
+"movepagebtn"  => "Move page",
+"pagemovedsub" => "Move succeeded",
+"pagemovedtext" => "Page \"[[$1]]\" moved to \"[[$2]]\".",
+"articleexists" => "A page of that name already exists, or the
+name you have chosen is not valid.
+Please choose another name.",
+"talkexists"   => "The page itself was moved successfully, but the
+talk page could not be moved because one already exists at the new
+title. Please merge them manually.",
+"movedto"              => "moved to",
+"movetalk"             => "Move \"talk\" page as well, if applicable.",
+"talkpagemoved" => "The corresponding talk page was also moved.",
+"talkpagenotmoved" => "The corresponding talk page was <strong>not</strong> moved.",
+"1movedto2"            => "$1 moved to $2",
+
+// Export
+
+"export"               => "Exportera sidor",
+"exporttext"   => "Du kan exportera texten och redigeringshistoriken av en specifik
+sida eller ställa in sidor wrappade i lite XML; detta kan sedan importeras till en annan
+wiki som kör MediaWiki-programvara, konverterad, eller bara sparad som syns skull.",
+"exportcuronly"        => "Inkludera endast nuvarande revisionen, inte hela historiken",
+
+# Namespace 8 related
+
+"allmessages"  => "Alla systemmeddelanden",
+"allmessagestext"      => "Detta är en lista över alla systemmeddelanden tillgängliga i Metawiki-namespacet.",
+
+# Thumbnails
+
+"thumbnail-more"       => "Förstora",
+"missingimage"         => "<b>Bild saknas</b><br /><i>$1</i>\n",
+
+# tooltip help for the main actions
+'tooltip-watch' => 'Lägg till den här sidan till din bevakningslista [alt-w]',
+'tooltip-search' => 'Sök den här wikin [alt-f]',
+'tooltip-minoredit' => 'Markera som en mindre ändring [alt-i]',
+'tooltip-save' => 'Spara dina ändringar changes [alt-s]',
+'tooltip-preview' => 'Förhandsgranska dina ändringar, gör detta innan du sparar! [alt-p]',
+'tooltip-compareselectedversions' => 'Visa skillnaden mellan de två markerade versionerna av den här sidan. [alt-v]',
+
+# Metadata
+"nodublincore" => "Dublin Core RDF metadata avstängt för på den här servern.",
+"nocreativecommons" => "Creative Commons RDF metadata avstängt på den här servern.",
+"notacceptable" => "Den här wiki-servern kan inte erbjuda data i ett format som din klient kan läsa.",
+
+# Attribution
+
+"anonymous" => "Anonym användare av {{SITENAME}}",
+"siteuser" => "{{SITENAME}} användare $1",
+"lastmodifiedby" => "Den här sidan var senaste ändrad $1 av $2.",
+"and" => "och",
+"othercontribs" => "Baserad på arbete utfört av $1.",
+"siteusers" => "{{SITENAME}} användare $1"
+
+);
+
+class LanguageSv extends LanguageUtf8 {
+
+       function getNamespaces() {
+               global $wgNamespaceNamesSv;
+               return $wgNamespaceNamesSv;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsSv;
+               return $wgQuickbarSettingsSv;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesSv;
+               return $wgSkinNamesSv;
+       }
+
+       function date( $ts, $adj = false ) {
+               if ( $adj ) { $ts = $this->userAdjust( $ts ); }
+
+               $d = (0 + substr( $ts, 6, 2 )) . " " .
+               $this->getMonthName( substr( $ts, 4, 2 ) ) . " " .
+               substr( $ts, 0, 4 );
+               return $d;
+       }
+
+       // "." is used as the character to separate the
+       // hours from the minutes in the date output
+       function time( $ts, $adj = false ) {
+               if ( $adj ) { $ts = $this->userAdjust( $ts ); }
+
+               $t = substr( $ts, 8, 2 ) . "." . substr( $ts, 10, 2 );
+               return $t;
+       }
+
+       function timeanddate( $ts, $adj = false ) {
+               return $this->date( $ts, $adj ) . " kl." . $this->time( $ts, $adj );
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesSv;
+               if( isset( $wgAllMessagesSv[$key] ) ) {
+                       return $wgAllMessagesSv[$key];
+               } else {
+                       return parent::getMessage( $key );
+               }
+       }
+
+       var $digitTransTable = array(
+               ',' => "\xc2\xa0", // @bug 2749
+               '.' => ','
+       );
+
+       function formatNum( $number, $year = false ) {
+               return $year ? $number : strtr($this->commafy($number), $this->digitTransTable);
+       }
+}
+
+?>
diff --git a/languages/LanguageTa.php b/languages/LanguageTa.php
new file mode 100644 (file)
index 0000000..5a0b560
--- /dev/null
@@ -0,0 +1,814 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+require_once( "LanguageUtf8.php" );
+
+#--------------------------------------------------------------------------
+# Language-specific text
+#--------------------------------------------------------------------------
+
+/* private */ $wgNamespaceNamesTa = array(
+       NS_MEDIA          => 'ஊடகம்',
+       NS_SPECIAL        => 'சிறப்பு',
+       NS_MAIN           => '',
+       NS_TALK           => 'பேச்சு',
+       NS_USER           => 'பயனர்',
+       NS_USER_TALK      => 'பயனர்_பேச்சு',
+       NS_PROJECT        => $wgMetaNamespace,
+       NS_PROJECT_TALK   => $wgMetaNamespace . '_பேச்சு',
+       NS_IMAGE          => 'படிமம்',
+       NS_IMAGE_TALK     => 'உருவப்_பேச்சு',
+       NS_MEDIAWIKI      => 'மீடியாவிக்கி',
+       NS_MEDIAWIKI_TALK => 'மீடியாவிக்கி_பேச்சு',
+       NS_TEMPLATE       => 'வார்ப்புரு',
+       NS_TEMPLATE_TALK  => 'வார்ப்புரு_பேச்சு',
+       NS_HELP           => 'உதவி',
+       NS_HELP_TALK      => 'உதவி_பேச்சு',
+       NS_CATEGORY       => 'பகுப்பு',
+       NS_CATEGORY_TALK  => 'பகுப்பு_பேச்சு',
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgQuickbarSettingsTa = array(
+       "எதுவுமில்லை", "இடம் நிலைத்த", "வலம் நிலைத்த", "இடம் மிதப்பு"
+);
+
+/* private */ $wgSkinNamesTa = array(
+       'standard' => "இயல்பான",
+       'nostalgia' => "பசுமை நினைவு (Nostalgia)",
+       'cologneblue' => "கொலோன் (Cologne) நீலம் Blue",
+       'smarty' => "பாடிங்டன் (Paddington)",
+       'montparnasse' => "மொண்ட்பார்னாசே (Montparnasse)",
+) + $wgSkinNamesEn;
+
+/* private */ $wgDateFormatsTa = array(
+#      "முன்னுரிமை இல்லை",
+);
+
+
+/* private */ $wgAllMessagesTa = array(
+
+# User Toggles
+#
+
+"tog-underline" => "இணைப்புகளுக்கு அடிக்கோடிடு",
+"tog-highlightbroken" => "முறிந்த இணைப்புகளை வடிவமை <a href=\"\" class=\"புதிது\">இதைப் போல </a> (alternative: like this<a href=\"\" class=\"internal\">?</a>).",
+"tog-justify"  => "பந்திகளை ஓரச் சீர்மைப் (Justify) படுத்து",
+"tog-hideminor" => "அண்மைய மாற்றங்களில் சிறிய தொகுப்புகளை மறை",
+"tog-usenewrc" => "மேம்படுத்தப்பட்ட அண்மைய மாற்றங்கள் (எல்லா உலாவிகளுக்குமல்ல)",
+"tog-numberheadings" => "தலைப்புகளுக்கு தானியங்கி இலக்கமிடு",
+"tog-editondblclick" => "இரட்டைச் சொடுக்கில் பக்கங்களைத் தொகு (ஜாவாஸ்கிரிப்ட்)",
+"tog-editsection"=>"இணைப்புவழி (தொகுப்பு) பிரிவுத் தொகுப்பை செயல்படுத்து",
+"tog-editsectiononrightclick"=>"வலச் சொடுக்குவழி பிரிவுத் தலைப்பு தொகுப்பதை செயல் படுத்து (ஜாவாஸ்கிரிப்ட்)",
+"tog-showtoc"=>"உள்ளடக்க அட்டவணையைக் காண்பி<br />(மூன்றுக்கு மேற்பட்ட தலைப்புகளையுடைய கட்டுரைகளுக்கு)",
+"tog-rememberpassword" => "அமர்வுகளுக்கு இடையே கடவுச்சொல்லை ஞாபகத்தில் வைத்துக்கொள்",
+"tog-editwidth" => "தொகுப்புக் கட்டம் முழு அகலத்தைக் கொண்டது",
+"tog-watchdefault" => "நீங்கள் தொகுத்த பக்கங்களை, உங்கள் கவனிப்புப் பட்டியலில்(watchlist) சேருங்கள்",
+"tog-minordefault" => "முன்னிருப்பாக (By default) அனைத்து தொகுப்புகளையும் சிறியது என குறித்துக்கொள்.",
+"tog-previewontop" => "தொகுப்புப் பெட்டிக்கு முன்பே முன்தோற்றத்தைக் காட்டுக. பின்னர் அல்ல.",
+"tog-nocache" => "பக்க இடைமாற்றை (cache) முடக்கு",
+
+
+# Dates
+#
+
+'sunday' => "ஞாயிறு",
+'monday' => "திங்கள்",
+'tuesday' => "செவ்வாய்",
+'wednesday' => "புதன்",
+'thursday' => "வியாழன்",
+'friday' => "வெள்ளி",
+'saturday' => "சனி",
+'january' => "ஜனவரி",
+'february' => "பெப்ரவரி",
+'march' => "மார்ச்",
+'april' => "ஏப்ரில்",
+'may_long' => "மே",
+'june' => "ஜூன்",
+'july' => "ஜூலை",
+'august' => "ஆகஸ்ட்",
+'september' => "செப்டெம்பர்",
+'october' => "அக்டோபர்",
+'november' => "நவம்பர்",
+'december' => "டிசம்பர்",
+'jan' => "ஜன",
+'feb' => "பெப்",
+'mar' => "மார்",
+'apr' => "ஏப்",
+'may' => "மே",
+'jun' => "ஜூன்",
+'jul' => "ஜூலை",
+'aug' => "ஆக",
+'sep' => "செப்",
+'oct' => "அக்",
+'nov' => "நவ",
+'dec' => "டிச",
+
+# Bits of text used by many pages:
+#
+"categories" => "பக்க வகைகள்",
+"category" => "வகை",
+"category_header" => "பகுப்புகளிலுள்ள கட்டுரைகள் \"$1\"",
+"subcategories" => "துணை வகைகள்",
+
+"linktrail"            => "/^([a-z]+)(.*)\$/sD",
+"mainpage"             => "முதற் பக்கம்",
+"mainpagetext" => "விக்கி மென்பொருள் வெற்றிகரமாக உள்ளிடப்பட்டது.",
+"about"                        => "விபரம்",
+"aboutsite"      => "விக்கிபீடியா பற்றி",
+"aboutpage"            => "விக்கிபீடியா:விபரம்",
+"help"                 => "உதவி",
+"helppage"             => "விக்கிபீடியா:உதவி",
+"bugreports"   => "வழு அறிக்கை",
+"bugreportspage" => "விக்கிபீடியா:வழு அறிக்கைகள்",
+"faq"                  => "அடிக்கடி கேட்கப்படும் கேள்விகள்",
+"faqpage"              => "விக்கிபீடியா:அடிக்கடி கேட்கப்படும் கேள்விகள்",
+"edithelp"             => "தொகுத்தலுக்கான உதவி",
+"edithelppage" => "விக்கிபீடியா : ஒருவர் பக்கமொன்றைத் தொகுப்பது எப்படி?",
+"cancel"               => "விடு",
+"qbfind"               => "தேடு",
+"qbbrowse"             => "உலவு",
+"qbedit"               => "தொகு",
+"qbpageoptions" => "பக்க விருப்பத் தேர்வுகள்",
+"qbpageinfo"   => "பக்கத் தகவல்கள்",
+"qbmyoptions"  => "எனது விருப்பத் தேர்வுகள்",
+"mypage"               => "எனது பக்கம்",
+"mytalk"               => "எனது பேச்சு",
+"currentevents" => "தற்போதைய நிகழ்வுகள்",
+"errorpagetitle" => "தவறு",
+"returnto"             => "$1 க்குத் திரும்பு.",
+"tagline"              => "விக்கிபீடியாவிடமிருந்து விடுதலை மனப்பாங்கொடு உருவான கலைக்களஞ்சியம்.",
+"whatlinkshere"        => "இங்கு இணைக்கப்பட்டுள்ள பக்கங்கள்",
+"help"                 => "உதவி",
+"search"               => "தேடு",
+"go"           => "செல்",
+"history"              => "பக்க வரலாறு",
+"printableversion" => "அச்சுக்குகந்த பதிப்பு",
+"editthispage" => "இப்பக்கத்தை தொகு",
+"deletethispage" => "இப்பக்கத்தை நீக்கு",
+"protectthispage" => "இப் பக்கத்தை காப்புச் செய்",
+"unprotectthispage" => "இப் பக்கத்தை காப்பு நீக்கு",
+"newpage" => "புதிய பக்கம்",
+"talkpage"             => "இப் பக்கம்பற்றிக் கலந்துரையாடு",
+"postcomment"   => "கருத்துக்களை அனுப்பு",
+"articlepage"  => "கட்டுரையைப் பார்",
+"subjectpage"  => "உட்பொருளைப் பார்", # பொருத்தப்பாட்டுக்காக
+"userpage" => "பயனர்பக்கம் பார்",
+"wikipediapage" => "மீ (meta) பக்கம் பார்",
+"imagepage" =>         "படிமப் பக்கம் பார்",
+"viewtalkpage" => "கலந்துரையாடல்களைப் பார்",
+"otherlanguages" => "ஏனைய மொழிகள்",
+"redirectedfrom" => "($1 இலிருந்து மீள் வழிப்படுத்தப்பட்டது)",
+"lastmodified" => "இப்பக்கம் கடைசியாகத் திருத்த்ப்பட்டது $1.",
+"viewcount"            => "இப்பக்கம் $1 முறை அணுகப்பட்டது .",
+"printsubtitle" => "({{SERVER}} இலிருந்து)",
+"protectedpage" => "பாதுகாக்கப்பட்ட பக்கம்",
+"administrators" => "விக்கிபீடியா:நிர்வாகிகள்",
+"sysoptitle"   => "முறைமைச் செயற்படுத்துனர்(Sysop) அணுக்கம் வேண்டும்",
+"sysoptext"            => "நீங்கள் கோரிய செயற்பாடுகள்
+ \"sysop\" நிலையிலுள்ள பயனர்களாலேயே செயற்படுத்த்ப்பட முடியும்.
+ $1 பார்க்கவும்.",
+"developertitle" => "உருவாக்குனர் அணுக்கம் தேவை",
+"developertext"        => "நீங்கள் கோரிய செயற்பாடுகள் \"developer\" நிலையிலுள்ள பயனர்களாலேயே செயற்படுத்தப்பட முடியும்.
+$1 பார்க்க.",
+"nbytes"               => "$1 பைட்டுகள் (bytes)",
+"go"                   => "செல்",
+"ok"                   => "சரி",
+"sitetitle"            => "விக்கிபீடியா",
+"sitesubtitle" => " கலைக்களஞ்சியம்",
+"retrievedfrom" => "\"$1\" இலிருந்து மீள்விக்கப்பட்டது",
+"newmessages" => "$1 உங்களிடம் உண்டு.",
+"newmessageslink" => "புதிய செய்திகள்",
+"editsection"=>"தொகு",
+"toc" => "பொருளடக்கம்",
+"showtoc" => "காட்டு",
+"hidetoc" => "மறை",
+"thisisdeleted" => "$1 பார்க்கவா மீள்விக்கவா?",
+"restorelink" => "$1 நீக்கப்பட்ட தொகுப்புகள்",
+
+# Main script and global functions
+#
+"nosuchaction" => "அவ்வித செயற்பாடுகள் எதுவுமில்லை",
+"nosuchactiontext" => "யூஆர்எல்(URL) இனால் குறிப்பிடப்பட்ட செயற்பாடு விக்கிபீடியா மென்பொருளினால் அடையாளம் காணப்படவில்லை ",
+"nosuchspecialpage" => "அவ்வாறான சிறப்புப் பக்கங்கள் எதுவுமில்லை",
+"nospecialpagetext" => "நீங்கள் கோரிய விசேட பக்கம் விக்கிபீடியா மென்பொருளினால் அடையாளம் காணப்படவில்லை",
+# General errors
+#
+"error"                        => "தவறு",
+"databaseerror" => "தரவுத்தள தவறு",
+"dberrortext"  => "ஒரு தரவுத்தள வினவல் தொடரமைப்புத் தவறு ஏற்பட்டுள்ளது.
+கடைசியாக முயற்சிக்கப்பட்ட தரவுத்தள வினவல்:
+<blockquote><tt>$1</tt></blockquote>
+செயலுக்குள்(function) இருந்து \"<tt>$2</tt>\".
+MySQL returned error \"<tt>$3: $4</tt>\".",
+"dberrortextcl" => "ஒரு தரவுத்தள வினவல் தொடரமைப்புத் தவறு ஏற்பட்டுள்ளது.
+கடைசியாக முயற்சிக்கப்பட்ட தரவுத்தள வினவல்:
+\"$1\"
+செயலுக்குள்(function) இருந்து \"$2\".
+MySQL returned error \"$3: $4\".\n",
+"noconnect"            => "மன்னிக்கவும்! இந்த விக்கி தளத்தில் தொழில் நுட்பப் பிரச்சனை ஏற்பட்டுள்ளது, தரவுத்தள வழங்கனுடன் தொடர்பு கொள்ளமுடியவில்லை.",
+"nodb"                 => "தரவுத்தள $1 தெரிவுசெய்ய முடியவில்லை",
+"cachederror"          => "கீழே இருப்பது கோரப்பட்ட பக்கத்தினுடைய ஒரு இடைமாற்று (cached) நகலாகும், இது நிகழ்நிலைக்குச் சரியாக (up to date) இல்லாதிருக்கக் கூடும்.",
+"readonly"             => "தரவுத்தளம் பூட்டப்பட்டது",
+"enterlockreason" => "பூட்டுக்கான காரணத்தைத் தருக. பூட்டு எப்பொழுது திறக்கப்படும் என்பதையும் குறிப்பிடுக.",
+"readonlytext" => "விக்கிபீடியா தரவுத்தளம் தற்போது பூட்டப்பட்டுள்ளது. வழமையான பராமரிப்புக்காகவாக இருக்கலாம். புதிய பதிவுகளோ திருத்த்ங்களோ செய்ய முடியாது.  இதன் பின்னர் இயல்பு நிலைக்குக் கொண்டுவரப்படும்.
+இந்த விளக்கத்தை இதனைப் பூட்டிய நிர்வாகி வழங்கியுள்ளார்:
+<p>$1",
+"missingarticle" => "கண்டுபிடித்திருக்கவேண்டிய பக்கத்தின் எழுத்துக்களை தரவுத்தளம் கண்டுபிடிக்கவில்லை. பக்கத்தின் பெயர் \"$1\".
+
+<p>நீக்கப்பட்ட பக்கமொன்றுக்கு வழக்கிழந்த வேறுபாடு (diff) அல்லது வரலாறு (History) இணைப்பைப் பின்பற்றுவதன் மூலம் இது வழக்கமாக ஏற்படுகிறது.
+<p>அப்படியில்லாவிட்டால் இது ஒரு மென்பொருள் வழுவாக இருக்கக்கூடும். யூஆரெல் (URL) ஐக் குறித்துக் கொண்டு அதைத் தயவுசெய்து ஒரு நிர்வாகிக்கு அறிவிக்கவும்.",
+"internalerror" => "உள்ளகத் தவறு",
+"filecopyerror" => "கோப்பை நகல் செய்ய முடியவில்லை\"$1\" to \"$2\".",
+"filerenameerror" => "கோப்பை பெயர்மாற்ற முடியவில்லை\"$1\" to \"$2\".",
+"filedeleteerror" => "கோப்பை நீக்க முடியவில்லை\"$1\".",
+"filenotfound" => "கோப்பைக் கண்டுபிடிக்க முடியவில்லை\"$1\".",
+"unexpected"   => "எதிர்பாராத பெறுமானம்: \"$1\"=\"$2\".",
+"formerror"            => "தவறு: படிவத்தை சமர்ப்பிக்க முடியவில்லை",
+"badarticleerror" => "இச் செயற்பாட்டை இப்பக்கத்தில் செயற்படுத்த முடியாது.",
+"cannotdelete" => "குறிக்கப்பட்ட பக்கத்தையோ படிமத்தையோ நீக்க முடியாது. (வேறு யாராலோ ஏற்கெனவே நீக்கப்பட்டிருக்கலாம்.)",
+"badtitle"             => "பழுதுள்ள தலைப்பு",
+"badtitletext" => "கோரப்பட்ட பக்கத்தின் தலைப்பு செல்லாது, வெறுமை, அல்லது பிழையாக இணைக்கப்பட்ட மொழிகளிடை அல்லது விக்கியிடைத் தலைப்பாகும்.",
+"perfdisabled" => "மன்னிக்கவும்! இந்த வசதி தற்காலிகமாக செயலற்றதாக்கப்பட்டுள்ளது. ஏனெனில் இது விக்கியை ஒருவரும் பயன்படுத்த முடியாத அளவுக்கு வேகத்தைக் குறைத்துள்ளது.",
+"perfdisabledsub" => "இதோ $1: இலிருந்து ஒரு சேமிக்கப்பட்ட ஒரு நகல்",
+"wrong_wfQuery_params" => "பிழையான அளபுருக்கள்(parameters) wfQuery()<br />
+செயல் (Function): $1<br />
+வினவல் (Query): $2
+",
+"viewsource" => "மூலத்தைப் பார்",
+"protectedtext" => "தொகுப்பதைத் தடுப்பதற்காக இப் பக்கம் பூட்டப்பட்டுள்ளது. இதற்குப் பல காரணங்கள் உண்டு. தயவுசெய்து
+[[$wgMetaNamespace:Protected page]] ஐப் பார்க்கவும்.
+
+நீங்கள் இப் பக்கத்தைப் பார்க்கவும், நகல் எடுக்கவும் முடியும்:",
+
+# Login and logout pages
+#
+"logouttitle"  => "பயனர் விடுபதிகை",
+"logouttext" => "நீங்கள் இப்பொழுது விடுபதிகையில் உள்ளீர்கள்.
+நீங்கள் தொடர்ந்தும் விக்கிபீடியாவை அடையாளமின்றி உபயோகிக்கலாம், அல்லது அதே பயனராகவோ வேறு பயனராகவோ மீண்டும் புகுபதிகை செய்யலாம். உங்கள் உலவியின் இடைமாற்று (browser cache) அழிக்கப்படும்வரை சில பக்கங்கள் தொடர்ந்தும் புகுபதிகையில் உள்ளது போன்றே காட்சி தரும் என்பதைக் கவனிக்கவும்\n",
+
+"welcomecreation" => "<h2>வருக, $1!</h2><p>உங்கள் கணக்கு உருவாக்கப்பட்டுள்ளது.
+உங்கள் விக்கிபீடியா விருப்புகளை சொந்தமயப் (personalize) படுத்த மறவாதீர்கள்.",
+"loginpagetitle" => "பயனர் புகுபதிகை",
+"yourname" => "உங்கள் பயனர்பெயர்",
+"yourpassword" => "உங்கள் கடவுச்சொல்",
+"yourpasswordagain" => "கடவுச்சொல்லைத் திரும்ப எழுதவும்",
+"newusersonly" => " (புதிய பயனர் மட்டும்)",
+"remembermypassword" => "எனது கடவுச்சொல்லை அமர்வுகளிடையே (across sessions) ஞாபகத்தில் வைத்திருக்கவும்.",
+"loginproblem" => "உங்கள் புகுபதிகை தொடர்பில் பிரச்சினை உண்டு.
+திரும்ப முயலவும்!",
+"alreadyloggedin" => "பயனர் $1, நீங்கள் ஏற்கெனவே புகு பதிகையில் உள்ளீர்கள்!
+\n",
+"login" => "புகுபதிகை",
+"userlogin" => "புகுபதிகை",
+"logout" => "விடுபதிகை",
+"userlogout" => "விடுபதிகை",
+"notloggedin" => "புகுபதிகையில் இல்லை",
+"createaccount" => "புதிய கணக்கு உருவாக்கு",
+"createaccountmail" => "மின்னஞ்சல் மூலம்",
+"badretype" => "நீங்கள் பதிந்த கடவுச்சொல் பொருத்தமாக இல்லை.",
+"userexists" => "நீங்கள் பதிந்த கடவுச் சொல் ஏற்கெனவே உபயோகத்தில் உள்ளது. தயவுசெய்து வேறு பெயர் தெரியவும்.",
+"youremail" => "உங்கள் மின்னஞ்சல்*",
+"yournick" => "உங்கள் அழைக்கும் பெயர் (கையொப்பத்துக்காக)",
+"emailforlost" => "* விரும்பினால் மட்டும் மின்னஞ்சல் முகவரியைக் கொடுக்கவும். ஆனால் இது நீங்கள் உங்கள் மின்னஞ்சல் முகவரியை வெளிப்படுத்தாமலே மற்றவர்கள் இணையத்தளம் மூலம் உங்களைத் தொடர்புகொள்ள வழி வகுக்கும். அத்துடன் உங்கள் கடவுச்சொல்லை நீங்கள் மற்ந்துபோகும் சந்தர்ப்பங்களிலும் இது உதவும்.",
+"loginerror" => "புகுபதிகைத் தவறு", "noname" => "நீங்கள் கொடுத்த பயனர் பெயர் செல்லுபடி இல்லை.",
+"loginsuccesstitle" => "புகுபதிகை வெற்றி",
+"loginsuccess" => "நீங்கள் இப்பொழுது \"$1\" ஆக விக்கிபீடியாவில் புகுபதிகை செய்துள்ளீர்கள்.",
+"nosuchuser" => "\"$1\" பெயரில் பயனர் எவருமில்லை. எழுத்துப் பிழைகளைச் சரி பார்க்கவும், அல்லது பின்வரும் படிவத்தை உபயோகித்து புதிய பயனர் கணக்கொன்றை உருவாக்கவும்.",
+"wrongpassword" => "நீங்கள் கொடுத்த கடவுச் சொல் சரியல்ல. மீண்டும் முயற்சிக்கவும்.",
+"mailmypassword" => "புதிய கடவுச் சொல்லொன்றை அஞ்சல் செய்யவும்",
+"passwordremindertitle" => "விக்கிபீடியாவிலிருந்து கடவுச் சொல் நினைவூட்டல்",
+"passwordremindertext" => "யாரோ ஒருவர் (நீங்களாக இருக்கலாம், IP முகவரி $1 இலிருந்து) புதிய விக்கிபீடியா புகுபதிகை கடவுச்சொல் ஒன்று அனுப்பும்படி கோரியுள்ளார். பயனர் \"$2\" க்கான கடவுச்சொல் இப்பொழுது \"$3\". நீங்கள் புகுபதிகை செய்து கடவுச்சொல்லை மாற்றிக்கொள்ளவும்.", "noemail" => "பயனை \"$1\" க்கு மின்னஞ்சல் முகவரி எதுவும் பதியப்பட்டிருக்கவில்லை.",
+"passwordsent" => "\"$1\" பெயரில் பதியப்பட்டுள்ள மின்னஞ்சல் முகவரிக்கு ஒரு புதிய கடவுச்சொல் அனுப்பப்பட்டுள்ளது. பெற்றுக்கொண்டதும் தயவுசெய்து மீண்டும் புகுபதிகை செய்யவும்.",
+# Edit pages
+"summary" => "சுருக்கம்",
+"subject" => "உட்பொருள்/தலைப்புகள்",
+"minoredit" => "இது ஒரு சிறு (minor) தொகுப்பு",
+"watchthis" => "இக் கட்டுரையைக் கவனிக்கவும் (watch)",
+"savearticle" => "பக்கத்தை சேமிக்கவும்",
+"preview" => "முன்தோற்றம்",
+"showpreview" => "முன்தோற்றம் காட்டு",
+"blockedtitle" => "பயனர் தடுக்கப்பட்டுள்ளார்",
+"blockedtext" => "உங்கள் பயனர் பெயர் அல்லது IP முகவரி $1 ஆல் தடுக்கப்பட்டுள்ளது. கொடுக்கப்பட்ட காரணம்: $2
+இது பற்றிப் பேசுவதற்கு $1 ஐயோ அல்லது [[$wgMetaNamespace:Administrators|நிர்வாகிகளில்]] ஒருவரையோ நீங்கள் தொடர்புகொள்ளலாம்.
+பயனர் விருப்பத் தேர்வுகளில்</wiki/Special:Preferences> உங்களுடைய செல்லுபடியாகக்கூடிய மின்னஞ்சல் முகவரி பதியப்பட்டிராவிட்டால் \"email this user\" வசதியை நீங்கள் உபயோகிக்க முடியாது என்பதைக் கவனிக்கவும்.
+உங்கள் IP முகவரி $3. தயவுசெய்து இந்த ஐபி முகவரியை விசாரிப்புகளைச் செய்யும்போது குறிப்பிடவும்.
+
+Note to AOL users
+
+குறிப்பிட்ட ஏஓஎல் (AOL) பயனர் ஒருவருடைய தொடர்ந்த விஷமச் செயல்கள் காரணமாக விக்கிபீடியா அடிக்கடி ஏஓஎல் (AOL) proxy யை தடுக்கிறது. துரதிர்ஷ்டவசமாக ஒரு proxy வழங்கனை பெருமளவு ஏஓஎல் (AOL) பயனர்கள் பயன்படுத்தக் கூடும், அதனால் அப்பாவி AOL பயனர்களும் அடிக்கடி தடுக்கப்படுகிறார்கள். இதனாலேற்படும் வசதியீனங்களுக்கு மன்னிப்புக் கோருகிறோம். இது உங்களுக்கு நிகழ்ந்திருந்தால், தயவுசெய்து ஒரு ஏஓஎல் (AOL) மின்னஞ்சல் முகவரியை உபயோகித்து, நிர்வாகியொருவருக்கு அஞ்சல் செயுங்கள். மேலே கொடுக்கப்பட்டுள்ள ஐபி முகவரியைக் குறிப்பிட மறவாதீர்கள்.",
+"whitelistedittitle" => "தொகுப்பதற்கு புகுபதிகை (login) செய்யப்படவேண்டும்.",
+"whitelistedittext" => " கட்டுரைகளைத் தொகுப்பதற்கு (edit) நீங்கள் புகுபதிகை (login) </wiki/Special:Userlogin>வேண்டும்.",
+"whitelistreadtitle" => "வாசிப்பதற்கு புகுபதிகை (login) செய்ய வேண்டும்",
+"whitelistreadtext" => " கட்டுரைகளை வாசிப்பதற்கு நீங்கள் புகுபதிகை (login) </wiki/Special:Userlogin> செய்யவேண்டும்.",
+"whitelistacctitle" => "கணக்கொன்று உருவாக்குவதற்கு நீங்கள் அனுமதிக்கப்படவில்லை.",
+"whitelistacctext" => "இந்த விக்கியில் கணக்கு ஏற்படுத்துவதற்கு, நீங்கள் log </wiki/Special:Userlogin> செய்வதுடன் உரிய அனுமதியும் பெற்றிருக்க வேண்டும்.",
+"accmailtitle" => "கடவுச்சொல் அனுப்பப்பட்டுள்ளது.",
+"accmailtext" => "'$1' உடைய கடவுச்சொல் $2 க்கு அனுப்பப்பட்டுள்ளது.",
+"newarticle" => "(புதிது)",
+"newarticletext" => "ஒரு இணைப்பினூடாக நீங்கள் வந்துள்ள இப் பக்கம் இன்னும் உருவாக்கப்படவில்லை. பக்கத்தை உருவாக்குவதற்குக் கீழேயுள்ள கட்டத்துள் தட்டச்சிடத் தொடங்குங்கள். (மேலதிக விபரங்களுக்கு உதவிப் பக்கங்களைப்</wiki/Wikipedia:Help> பார்க்கவும்). நீங்கள் தவறுதலாக இங்கே வந்திருந்தால், உங்கள் உலாவி (browser) யின் பின்னே (back) பொத்தானைச் சொடுக்கவும்.",
+"anontalkpagetext" => "---- இது இன்னும் கணக்கொன்று ஏற்படுத்தாத அல்லது இதனை வழமையாகப் பயன்படுத்தாத பயனர்களுக்குரிய கலந்துரையாடல் பக்கமாகும். அதனால் நாங்கள் இவரை அடையாளம் காண்பதற்கு எண்சார்ந்த ஐபி (IP) முகவரி</wiki/IP_address>யை உபயோகிக்கிறோம். இவ்வாறான ஐபி (IP) முகவரிகள் பல பயனர்(user) களினால் பகிர்ந்துகொள்ளப்படலாம். நீங்கள் ஒரு முகவரியற்ற பயனராயிருந்து, தொடர்பற்ற கருத்துக்கள் உங்களைக் குறித்துச் சொல்லப்பட்டிருப்பதாக நீங்கள் உணர்ந்தால், முகவரியற்ற ஏனைய பயனர்களுடனான குழப்பங்களை எதிர்காலத்தில் தவிர்ப்பதற்கு, தயவுசெய்து கணக்கொன்றை ஏற்படுத்துங்கள் அல்லது புகுபதிகை (login) செய்யுங்கள் </wiki/Special:Userlogin>. ",
+"noarticletext" => "(இப் பக்கத்தில் தற்பொழுது எழுத்துக்கள் எதுவுமில்லை)",
+"updated" => "(இற்றைப்படுத்தப்பட்டது Updated)",
+"note" => "Note: ", "previewnote" => "இது ஒரு முன்தோற்றம் (preview) மட்டுமே என்பதையும், இன்னும் சேமிக்கப்படவில்லை என்பதையும் ஞாபகத்தில் வைத்திருக்கவும்!",
+"previewconflict" => "இந்த முன்தோற்றம் உரை தொகுப்புப் பகுதியின் மேற்பகுதியிலுள்ள உரையைப் பிரதிபலிக்கின்றது. நீங்கள் இப்பொழுது சேமித்தால் மேற்படி தோற்றமே கிடைக்கும்.",
+"editing" => "தொகுத்தல் (Editting) $1",
+"editingsection" => "தொகுத்தல் (Editting) $1 (பிரிவு)",
+"editingcomment" => "தொகுத்தல் (Editting) $1 (கருத்து)",
+"editconflict" => "முரண்பாடுகளைத் தொகுக்கவும் (edit): $1",
+"explainconflict" => "நீங்கள் தொகுக்கத் தொடங்கியதின் பின்னர் யாரோஒருவர் இப் பக்கங்களில் மாற்றங்கள் செய்துள்ளார். உரைப் பகுதியின் (text area ) மேற்பக்கம் தற்போதுள்ள உரைகளைக் கொண்டிருக்கும், நீங்கள் செய்த மாற்றங்கள் உரையின் கீழ்ப்பக்கம் காணப்படும். நீங்கள் உங்களுடைய மாற்றங்களை ஏற்கெனவேயிருக்கும் உரையுடன் ஒருங்கிணைக்க வேண்டியிருக்கும்.
+ \"Save page\" ஐ அழுத்தும்போது உரைப்பகுதியின் மேற்பக்கத்திலுள்ள உரை மட்டுமே சேமிக்கப்படும்.<br />",
+
+"yourtext" => "உங்கள் உரை",
+"storedversion" => "சேமிக்கப்பட்ட பதிப்பு",
+"editingold" => "எச்சரிக்கை: நீங்கள் தொகுத்துக்கொண்டிருப்பது இப் பக்கத்தின் பழைய திருத்தமொன்றை(revision)யாகும். இதை நீங்கள் சேமித்தால், மேற்படி திருத்தத்தின் பின்பு நீங்கள் செய்த மாற்றங்கள் அனைத்தும் இழக்கப்படும்.",
+"yourdiff" => "வித்தியாசங்கள்",
+"copyrightwarning" => "விக்கிபீடியாவுக்கான ஆக்கங்கள் அனைத்தும் ஜிஎன்யூ விடுதலை மனப்பாங்கொடு உருவான ஆவண அனுமதி (GNU Free Documentation License) முறையின் கீழ் வழங்கப்பட்டதாகவே கருதப்படும் என்பதைத் தயவு செய்து கவனிக்கவும். (விபரங்களுக்கு $1 ஐப் பார்க்க).
+
+உங்களுடைய எழுத்துக்கள் கடுமையாகத் தொகுக்கப்படுவதையோ, விரும்பியபடி விநியோகிக்கப்படுவதையோ நீங்கள் விரும்பாவிடில் இங்கே சமர்ப்பிக்காதீர்.<br />
+அத்துடன் நீங்களே இதை எழுதியதாகவோ, அல்லது வேறு பொதுக் களம் (domain) அல்லது அது போன்ற விடுதலையளிக்கும் மூலங்களிலிருந்து பிரதி பண்ணியிருப்பதாகவோ உறுதி கூறுகிறீர்கள்.
+<strong>பதிப்புரிமையுள்ள ஆக்கங்களை அனுமதியின்றி சமர்ப்பிக்க வேண்டாம்!</strong>",
+"longpagewarning" => "<strong>எச்சரிக்கை: இந்தப் பக்கம் $1 கிலோபைட்ஸ் நீளமானது; 32kb யை அண்மிக்கும் அல்லது அதிலும் கூடிய அளவுள்ள பக்கங்களைத் தொகுப்பதில் சில உலாவிகளுக்கு (browsers) பிரச்சினை உண்டு.
+தயவுசெய்து பக்கங்களைச் சிறிய பகுதிகளாகப் பிரிப்பது பற்றிக் கவனத்தில் எடுக்கவும்.</strong>",
+"readonlywarning" => "<strong>எச்சரிக்கை: பராமரிப்புக்காகத் தரவுத்தளம் பூட்டப்பட்டுள்ளது, எனவே உங்கள் தொகுப்புக்களை இப்பொழுது சேமிக்க முடியாது. உங்கள் உரையை (text) இன்னொரு உரைக் கோப்பில் (text file) வெட்டி ஒட்டி சேமித்துவைத்துப் பின்பு உபயோகிக்கலாம்.</strong>",
+"protectedpagewarning" => "<strong>எச்சரிக்கை: முறைமை செயற்படுத்துனர் (sysop) முன்னுரிமையுள்ள பயனர்கள் மட்டுமே தொகுக்கும் விதத்தில் இந்த பக்கம் பூட்டப்பட்டுள்ளது.  நீங்கள்
+[[Project:Protected_page_guidelines|காக்கப்பட்ட பக்கங்களுக்கான வழிகாட்டல்களைப் பின்பற்றுவதை உறுதி செய்துகொள்ளவும்]].</strong>",
+
+# History pages
+#
+"revhistory"   => "திருத்த (revision) வரலாறு",
+"nohistory"            => "இப் பக்கத்துக்குத் தொகுப்பு வரலாறு இல்லை.",
+"revnotfound"  => "திருத்தம்(revision) காணப்படவில்லை",
+"revnotfoundtext" => "இப் பக்கத்துக்குரிய, நீங்கள் கோரிய பழைய திருத்தம் (revision) காணப்படவில்லை.
+இந்தப் பக்கத்தை அணுகுவதற்கு நீங்கள் பயன்படுத்திய URL ஐத் தயவுசெய்து சரி பார்க்கவும்.\n",
+"loadhist"             => "பக்க வரலாறு ஏற்றப்படுகிறது",
+"currentrev"   => "நடைமுறையிலுள்ள திருத்தம்",
+"revisionasof" => "$1 இல் நிலவும் திருத்தம் (Revision) ",
+"cur"                  => "நடப்பு",
+"next"                 => "அடுத்த",
+"last"                 => "கடைசி",
+"orig"                 => "மூலம்",
+"histlegend"   => "குறியீட்டு விளக்கம்: (நடப்பு) = நடைமுறையிலுள்ள பதிப்புடனான (version) வேறுபாடு,
+(கடைசி) = முந்திய பதிப்புடனான வேறுபாடு, M = சிறு தொகுப்பு",
+
+# Diffs
+#
+"difference"   => "(திருத்தங்கள்(revisions) இடையிலான வேறுபாடு)",
+"loadingrev"   => "diff க்காகத் திருத்தம் ஏற்றம் செய்யப்படுகிறது",
+"lineno"               => "வரிசை $1:",
+"editcurrent"  => "இப் பக்கத்தின் தற்போதைய பதிப்பைத் தொகுக்கவும்(edit)",
+
+# Search results
+#
+"searchresults" => "தேடல் முடிவுகள்",
+"searchresulttext" => "விக்கிபீடியாவில் தேடுவதற்கான மேலதிக விபரங்களுக்கு, [[விக்கிபீடியா:தேடல்|விக்கிபீடியாவில் தேடல்]] ஐப் பார்க்க.",
+"searchquery"  => "வினவலுக்காக\"$1\"",
+"badquery"             => "பழுதுடன் செய்யப்பட்ட தேடல் வினவல் (search query)",
+"badquerytext" => "உங்களுடைய வினவலை எங்களால் செயலாக்க முடியவில்லை.
+இது ஏனென்றால், சிலவேளை மூன்று எழுத்துக்கள் நீளத்திலும் சிறிதான சொல்லைத் தேட முயன்றிருக்கலாம், இது இன்னும் ஆதரிக்கப்படவில்லை.
+தொடரை நீங்கள் பிழையாகத் தட்டச்சிட்டதனாலும் இது நேர்ந்திருக்கக்கூடும், உதாரணமாக \"fish and and scales\".
+தயவுசெய்து இன்னொரு வினவலை (query) முயலுங்கள்.",
+"matchtotals"  => "வினவல் (query) \"$1\"  $2 கட்டுரைத்,தலைப்புக்களுடனும், $3 கட்டுரை உரைகளுடனும் பொருந்தியுள்ளது.",
+"nogomatch" => "சரியாக இத் தலைப்பையுடைய பக்கமெதுவும் இல்லை, முழு உரைத் தேடல் நடைபெறுகிறது.",
+"titlematches" => "கட்டுரைத் தலைப்பு பொருந்துகிறது",
+"notitlematches" => "ஒரு கட்டுரைத் தலைப்பும் பொருந்தவில்லை",
+"textmatches"  => "கட்டுரை உரை (text) பொருந்துகிறது",
+"notextmatches"        => "கட்டுரை உரை (text) எதுவும் பொருந்தவில்லை",
+"prevn"                        => "முன் $1",
+"nextn"                        => "அடுத்த $1",
+"viewprevnext" => "பார் ($1) ($2) ($3).",
+"showingresults" => "#<b>$2</b> உடன் தொடங்கும் <b>$1</b> முடிவுகள் கீழே காட்டப்பட்டுள்ளன.",
+"showingresultsnum" => "#<b>$2</b> உடன் தொடங்கும் <b>$3</b> முடிவுகள் கீழே காட்டப்பட்டுள்ளன.",
+
+"nonefound"            => "<strong>குறிப்பு</strong>: \"have\", \"from\" போன்ற பொதுவான, அட்டவணைப்படுத்தப்படாத, சொற்களைத் தேடும்போதோ அல்லது ஒன்றுக்கு மேற்பட்ட தேடலுக்கான சொற்களைக் குறிப்பிடும் போதோதான் (எல்லாத் தேடுதலுக்கான சொற்களையும் கொண்ட பக்கங்கள் மட்டுமே தேடல் முடிவில் காணப்படும்) தேடல் அடிக்கடி தோல்வியில் முடிகின்றது.",
+"powersearch" => "தேடு",
+"powersearchtext" => "பெயர்வெளிகளில் (namespaces) இல் தேடுக:<br />
+$1<br />
+$2 பட்டியல் &nbsp; $3 $9 க்கான தேடலை மீள்வழிப்படுத்துகிறது",
+"searchdisabled" => "<p>மன்னிக்கவும்! செயற்திறன் காரணங்களுக்காக முழு அளவு உரை தேடல் தற்காலிகமாக முடக்கப்பட்டுள்ளது. அதுவரை நீங்கள் கீழேயுள்ள கூகிள் (Google) தேடலைப் பயன்படுத்தலாம். இது சில சமயம் இற்றைப்படுத்தப்படாததாய் இருக்கக்கூடும்.</p>
+
+",
+"blanknamespace" => "(முதன்மை)",
+
+# Preferences page
+#
+"preferences"  => "முன்னுரிமைகள்",
+"prefsnologin" => "புகுபதிகை செய்யப்படவில்லை",
+"prefsnologintext"     => "பயனர் விருப்பத் தேர்வுகளை அமைப்பதற்கு நீங்கள் [[Special:Userlogin|புகுபதிகை செய்ய வேண்டும்]].",
+"prefslogintext" => "நீங்கள் \"$1\" ஆக புகுபதிகை செய்துள்ளீர்கள்.
+உங்கள் உள்ளக அடையாள (ID) எண் $2.
+
+உங்கள் விருப்பத் தேர்வுகளை விளங்கிக் கொள்ள [[Wikipedia:User preferences help]] ஐப் பார்க்க.",
+"prefsreset"   => "உங்கள் விருப்புகள் சேமிப்பிலிருந்து மீட்டமைக்கப்பட்டுள்ளன (reset).",
+"qbsettings"   => "விரைவுச் சட்ட அமைவுகள்",
+"changepassword" => "கடவுச்சொல்லை மாற்று",
+"skin"                 => "தோல் (Skin)",
+"math"                 => "பதிப்புவரை கணிதம் (Rendering math)",
+"dateformat"   => "திகதி வடிவம்",
+"math_failure"         => "பாகுபடுத்தல் (parse) தோல்வி",
+"math_unknown_error"   => "அறியப்படாத தவறு",
+"math_unknown_function"        => "அறியப்படாத பணி",
+"math_lexing_error"    => "தொகுத்தல் (lexing) தவறு",
+"math_syntax_error"    => "தொடரமைப்புத் தவறு (syntax error)",
+"saveprefs"            => "விருப்பத் தேர்வுகளைச் சேமி",
+"resetprefs"   => "விருப்பத் தேர்வுகளை மீட்டமை (Reset)",
+"oldpassword"  => "பழைய கடவுச்சொல்",
+"newpassword"  => "புதிய கடவுச்சொல்",
+"retypenew"            => "புதிய கடவுச்சொல்லை மீண்டும் அச்சிடு",
+"textboxsize"  => "உரைக் கட்ட (Textbox) அளவுகள்",
+"rows"                 => "வரிசைகள்",
+"columns"              => "நிரல்கள் (Columns)",
+"searchresultshead" => "தேடல் முடிவு அமைவுகள் (settings)",
+"resultsperpage" => "ஒரு பக்கத்துக்குக் காட்டப்படவேண்டிய அடிகள் (Hits)",
+"contextlines" => "அடித்தலொன்றுக்குக் காட்டப்பட வேண்டிய வரிகள்",
+"contextchars" => "ஒரு வரிக்கான இடம்சார் (context) எழுத்துக்கள்",
+"stubthreshold" => "அடிப்படைக் காட்சிப்படுத்தலுக்கான மாறுநிலை (Threshold)",
+"recentchangescount" => "அண்மைய மாற்றங்களில் தலைப்புகள் எண்ணிக்கை",
+"savedprefs"   => "உங்கள் விருப்புகள் சேமிக்கப்பட்டுள்ளன.",
+"timezonetext" => " வழங்கன் (server) நேரத்துக்கும் (UTC) உங்கள் உள்ளூர் நேரத்துக்குமுள்ள வேறுபாட்டை மணிகளில் பதிக.",
+"localtime"    => "உள்ளூர் நேரக் காட்சிப்பாடு (display)",
+"timezoneoffset" => "நேர இடைவெளி",
+"servertime"   => "தற்போது வழங்கன் (Server) நேரம்",
+"guesstimezone" => "உலவி (browser) யிலிருந்து நிரப்புக.",
+"emailflag"            => "வேறு பயனர்களிடமிருந்தான மின்னஞ்சல்களை முடக்கு",
+"defaultns"            => "முன்னிருப்பாக இந்த பெயர்வெளிகளில் (namespaces) தேடவும்:",
+
+# Recent changes
+#
+"changes" => "மாற்றங்கள்",
+"recentchanges" => "அண்மைய மாற்றங்கள்",
+"recentchangestext" =>
+"விக்கிபீடியாவுக்கு, மிக அண்மையில் செய்யப்பட்ட மாற்றங்களை, இந்தப் பக்கத்தில் கண்டுபிடிக்கவும்.<br />[[Wikipedia:Welcome,_newcomers|வருக, புது வருனர்களே]]!
+தயவுசெய்து பின்வரும் பக்கங்களை ஒருமுறை பாருங்கள்: [[wikipedia:FAQ|விக்கிபீடியா அடிக்கடி கேட்கப்படும் கேள்விகள்( FAQ)]],
+[[Wikipedia:Policies and guidelines|விக்கிபீடியா கொள்கை]]
+(விசேடமாக [[wikipedia:Naming conventions|பெயரிடல் மரபு]],
+[[wikipedia:Neutral point of view|நடுநிலை நோக்கு]]),
+அத்துடன் [[wikipedia:Most common Wikipedia faux pas|மிகப் பொதுவான விக்கிபீடியா ஒழுங்குமுறைப் பிறழ்வுகள்]].
+
+விக்கிபீடியா வெற்றிபெறுவதை நீங்கள் பார்க்க வேண்டுமானால், மற்றவர்களுடைய பதிப்புரிமையினால் </wiki/Wikipedia:Copyrights> கட்டுப்படுத்தப்பட்டுள்ள ஆக்கங்களை இதிலே சேர்க்காதிருப்பது முக்கியமாகும்.
+சட்டம் சார்ந்த பொறுப்பு (liability) இத் திட்டத்தைப் பெரிதும் பாதிக்கும், எனவே தயவுசெய்து இவ்வாறு செய்யாதீர். அண்மைய மீ (meta) கலந்துரையாடலைப் <http://meta.wikipedia.org/wiki/Special:Recentchanges> பார்க்கவும்.",
+"rcloaderr" => "அண்மைய மாற்றங்களை ஏற்றுதல்(Loading).",
+"rcnote" => "கீழே காணப்படுவது கடைசி $2 நாட்களில் செய்யப்பட்ட $1 மாற்றங்களாகும்.",
+"rcnotefrom" => "கீழே காணப்படுவது $2 இலிருந்து செய்யப்பட்ட மாற்றங்கள் ($1வரை காட்டப்பட்டுள்ளது).",
+"rclistfrom" => "$1 தொடக்கம் செய்யப்பட்ட புதிய மாற்றங்களைக் காட்டவும்",
+"rclinks" => "கடைசி $2 மணித்தியாலங்கள் / கடைசி $3 நாட்களில் செய்யப்பட்ட கடைசி $1 மாற்றங்களைக் காட்டு",
+"rclinks" => "கடைசி $2 நாட்களில் கடைசி $1 மாற்றங்களைக் காட்டு .",
+"rclinks" => "கடைசி $2 நாட்களில் செய்யப்பட்ட கடைசி $1 மற்றங்களைக் காட்டு; $3 சிறிய தொகுப்புகள்", "rchide" => "$4 படிவங்களில்; $1 சிறிய தொகுப்புக்கள்; $2 இரண்டாம்தர பெயர்வெளிகள்(namespaces); $3 பல்லினத் தொகுப்புகள்.",
+"rcliu" => "; $1 புகுபதிகை செய்த பயனர்களிடமிருந்தான தொகுப்புகள்",
+"diff" => "வேறுபாடு",
+"hist" => "வரலாறு",
+"hide" => "மறை",
+"show" => "காட்டு",
+"tableform" => "அட்டவணை",
+"listform" => "பட்டியல்",
+"nchanges" => "$1 மாற்றங்கள்",
+"minoreditletter" => "M",
+"newpageletter" => "N",
+# Upload
+"upload" => "கோப்பைப் பதிவேற்று (Upload file)",
+"uploadbtn" => "கோப்பைப் பதிவேற்று (Upload file)",
+"uploadlink" => "படிமங்களைப் பதிவேற்று (Upload images)",
+"reupload" => "மீளப் பதிவேற்று (Re-upload)",
+"reuploaddesc" => "பதிவேற்றும் படிவத்துக்கு மீளச் செல்.",
+"uploadnologin" => "புகுபதிகை (login) செய்யப்படவில்லை ",
+"uploadnologintext" => "கோப்புகளைப் பதிவேற்றம் செய்வதற்கு நீங்கள்[[Special:Userlogin|புகுபதிகை செய்திருக்க வேண்டும்]].",
+"uploaderror" => "ஏற்றுத் தவறு",
+"uploadtext" => "நிறுத்தவும்! இங்கே பதிவேற்றம் செய்யுமுன், விக்கிபீடியாவின் [[Project:Image_use_policy|படிமம் பயன்படுத்தற் கொள்கை]] யை வாசித்துப் பின்பற்றுவதை உறுதிப்படுத்திக் கொள்ளவும்.
+நீங்கள் குறித்த பெயருடைய கோப்பு எற்கெனவே விக்கிபீடியாவில் இருக்குமாயின், அது எச்சரிக்கை கொடாமல் பிரதியீடு செய்யப்படும். எனவே கோப்பொன்றை இற்றைப்படுத்துவது (update) உங்கள் நோக்கமாக இல்லாவிடில், அதே பெயரில் வேறு கோப்பு உள்ளதா என முதலில் அறிந்து கொள்ளவும்.
+முன்னர் பதிவேற்றம் செய்யப்பட்ட படிமங்களைப் பார்ப்பதற்கு அல்லது தேடுவதற்கு, [[Special:Imagelist|பதிவேற்றம் செய்யப்பட்ட படிமங்களின் பட்டிய]] லுக்குச் செல்லவும். பதிவேற்றங்களும் நீக்கல்களும் [[Project:Upload_log|பதிவேற்றப் பதிகையில் (upload log)]] பதியப்பட்டுள்ளன.
+உங்கள் கட்டுரைகளில் பயன்படவுள்ள புதிய படிமங்களைப் பதிவேற்றுவதற்கு கீழேயுள்ள படிவத்தைப் பயன்படுத்தவும். பெரும்பாலான உலவிகளில், கோப்புத் திறக்கும் உரையாடல் பெட்டியைக் காட்டும் உங்கள் இயக்க முறைமையின் (operating system) இயல்பான ஒரு \"Browse...\" பொத்தானைக் காணலாம்.ஒரு கோப்பைத் தெரிவுசெய்யும்பொது, அதன் பெயர், பொத்தானுக்கு அருகிலுள்ள உரைப்புலத்தில் (text field) நிரப்பப்படும். கோப்பைப் பதிவேற்றம் செய்வதன் மூலம்எந்தப் பதிப்புரிமையையும் மீற்வில்லை என்பதை உறுதிப்படுத்த அதற்குரிய கட்டத்திலும் நீங்கள் குறியிடவேண்டும். பதிவேற்றத்தை நிறைவுசெய்வதற்கு \"Upload\" பொத்தானை அழுத்தவும். உங்கள் வலையக இணைப்பு வேகம் குறைந்ததாக இருப்பின், இதற்குச் சிறிது நேரன் எடுக்கக்கூடும்.
+புகைப்படப் படிமங்களுக்கு JPEG யும், வரைபடங்களுக்கும் ஏனைய குறியீட்டுப் (iconic) படிமங்களுக்கும் PNG யும், ஒலிக் கோப்புகளுக்கு OGG யும் விரும்பத்தக்க வடிவங்களாகும்.
+
+
+குழ்ப்பத்தைத் தவிர்ப்பதற்குத் தயவுசெய்து உங்கள் கோப்புகளுக்கு விபரமாகப் பெயரிடவும்.உங்கள் கட்டுரைகளில் படிமங்களைச் சேர்ப்பதற்கு,
+'''<nowiki>[[image:file.jpg]]</nowiki>''' அல்லது '''<nowiki>[[image:file.png|alt text]]</nowiki>''' இணைப்பு வடிவத்தையும், ஒலிகளுக்கு '''<nowiki>[[media:file.ogg]]</nowiki>''' இணைப்புவடிவத்தையும் பயன்படுத்தவும்.
+
+விக்கிபீடியா பக்கங்களைப் பொறுத்தவரை, கலைக் கழஞ்சியத்துக்கு உதவும் என்று மற்றவர்கள் கருதினால், உங்கள் பதிவேற்றத்தைத் தொகுக்கவோ அல்லது நீக்கவோ முடியும். அத்துடன் நீங்கள் இந்த முறைமையைத் துஷ்பிரயோகம் செய்தால், பதிவேற்றம் செய்வதிலிருந்து தடுக்கப்படவும் கூடும் என்பதையும் கவனிக்கவும்.",
+
+"uploadlog"            => "பதிவேற்றப் பதிகை (Upload_log)",
+"uploadlogpage" => "பதிவேற்றப் பதிகை (Upload_log)",
+"uploadlogpagetext" => "கீழேயுள்ளது மிக அண்மையில் பதிவேற்றம் செய்யப்பட்ட கோப்புகளின் பட்டியலாகும்.
+காட்டப்பட்டுள்ள எல்லா நேரங்களும் வழங்கன் நேரமாகும்(UTC).
+<ul>
+</ul>
+",
+"filename"             => "கோப்புப் பெயர்",
+"filedesc"             => "சுருக்கம்",
+"filestatus" => "பதிப்புரிமை நிலை",
+"filesource" => "மூலம்",
+"copyrightpage" => "விக்கிபீடியா:பதிப்புரிமை",
+"copyrightpagename" => "விக்கிபீடியா பதிப்புரிமை",
+"uploadedfiles"        => "ஏற்றப்பட்ட (Uploaded) கோப்புகள்",
+"ignorewarning"        => "எப்படியானாலும் எச்சரிக்கையைக் கவனியாது கோப்பைச் சேமி.",
+"minlength"            => "படிமத்தின் (Image) பெயர் குறைந்தது மூன்று எழுத்துக்களாவது இருக்க வேண்டும்.",
+"badfilename"  => "படிமப் (Image) பெயர் \"$1\" ஆக மாற்றப்பட்டுள்ளது.",
+"badfiletype"  => "\".$1\" இது ஒரு சிபாரிசு செய்யப்பட்ட படிமக் கோப்பு வடிவம் (format) அல்ல.",
+"largefile"            => "படிமங்களிமன் அளவு 100k க்கு மேற்படாதிருக்க சிபாரிசு செய்யப்படுகிறது.",
+"successfulupload" => "வெற்றிகரமான பதிவேற்றுதல் (upload)",
+"fileuploaded" => "File \"$1\" வெற்றிகரமாக பதிவேற்றப்பட்டது (uploaded).
+தயவுசெய்து விபரிப்புப் பக்கத்துக்குப் பின்வரும் இணைப்பைப் பின்பற்றவும்: ($2) அத்துடன் கோப்புப் பற்றிய, எங்கிருந்து கிடைத்தது, எப்பொழுது, யாரால் உருவாக்கப்பட்டது மற்றும் உங்களுக்குத் தெரிந்த இன்னோரன்ன தகவல்களையும் நிரப்பவும்.",
+"uploadwarning" => "பதிவேற்றுதல் எச்சரிக்கை",
+"savefile"             => "கோப்பைச் சேமி",
+"uploadedimage" => "பதிவேற்றப்பட்டது \"[[$1]]\"",
+
+# Image list
+#
+"imagelist"            => "படிமங்களின் பட்டியல்",
+"imagelisttext"        => "கீழ் வருவது $2 பாகுபடுத்தப்பட்ட $1 படிமங்களின் பட்டியலாகும்.",
+"getimagelist" => "படிமப் பட்டியல் பெற்றுக் கொள்ளப்படுகிறது (fetching)",
+"ilsubmit"             => "தேடல்",
+"showlast"             => "$2 பாகுபடுத்தப்பட்ட கடைசி $1 படிமங்களைக் காட்டுக.",
+"byname"               => "பெயர் வழி",
+"bydate"               => "திகதி வழி",
+"bysize"               => "அளவு வழி",
+"imgdelete"            => "நீக்கு",
+"imgdesc"              => "விபரம்",
+"imglegend"            => "குறியீட்டு அட்டவணை: (விபரம்) = படிம விபரங்களைக் காட்டு/தொகு.",
+"imghistory"   => "படிம வரலாறு",
+"revertimg"            => "மீள்",
+"deleteimg"            => "நீக்கு",
+"deleteimgcompletely"          => "நீக்கு",
+"imghistlegend" => "குறியீட்டு அட்டவணை: (நடப்பு) = இது நடப்பிலுள்ள (current) படிமம், (நீக்கு) = இந்த பழைய பதிப்பை நீக்கு, (திரும்பு) = இப் பழைய பதிப்புக்குத் திரும்பு.
+<br /><i>அந்தத் திகதியில் பதிவேற்றம் செய்யப்பட்ட படிமங்களைப் பார்ப்பதற்கு, திகதி மீது சொடுக்கவும்</i>.",
+"imagelinks"   => "படிம இணைப்புகள்",
+"linkstoimage" => "பின்வரும் பக்கங்கள் இப் படிமத்துக்கு இணைக்கப்பட்டுள்ளன:",
+"nolinkstoimage" => "இப் படிமத்துக்கு இணைக்கப்பட்டுள்ள பக்கங்கள் எதுவும் இல்லை.",
+
+# Statistics
+#
+"statistics"   => "புள்ளி விபரங்கள்",
+"sitestats"            => "தள புள்ளி விபரங்கள்",
+"userstats"            => "பயனர் புள்ளி விபரங்கள்",
+"sitestatstext" => "<b>$1</b> மொத்தப் பக்கங்கள் தரவுத் தளத்தில் உள்ளன.
+இது \"talk\" பக்கங்கள், விக்கிபீடியா பற்றிய பக்கங்கள், குறைந்த அளவு \"stub\"
+பக்கங்கள், வழிமாற்றிகள் (redirects), மற்றும் கட்டுரைத் தரத்தில் இல்லாதிருக்கக்கூடிய ஏனையவற்றையும் உள்ளடக்கும். இவை தவிர்த்து, <b>$2</b> பக்கங்கள் முறையான (legitimate) ஆன கட்டுரைகளாக இருக்கக்கூடும்.<p>
+இங்கே மொத்தமாக <b>$3</b> பக்கங்கள் பார்க்கப்பட்டதுடன், மென்பொருள் தரமுயர்த்த்ப்பட்டதிலிருந்து (நவம்பர் 20, 2003) <b>$4</b> பக்கங்கள் தொகுக்கப்பட்டுள்ளன. இது ஒரு பக்கத்துக்கு <b>$5</b> சராசரித் தொகுப்புக்களும், ஒரு தொகுப்புக்கு <b>$6</b> பார்வைகளும் ஆகின்றது.",
+"userstatstext" => "<b>$1</b> பதிவு செய்யப்பட்ட பயனர்கள் உள்ளனர்.
+இவர்களில் <b>$2</b> பேர் நிர்வாகிகள்($3 பார்க்கவும்).",
+
+# Maintenance Page
+#
+"maintenance"          => "பராமரிப்புப் பக்கம்",
+"maintnancepagetext"   => "இந்தப் பக்கம் நாளாந்த பராமரிப்புக்கான பல்வேறு கருவிகளை உள்ளடக்கியுள்ளது. இச் செயற்பாடுகளிற் சில, தரவுத் தளத்தைத் தகைப்பு (stress)க்குள்ளாக்கக் கூடுமென்பதால், ஒவ்வொரு விடயத்தையும் திருத்திய பின்னர் தயவுசெய்து மீள்வேற்றல் செய்ய வேண்டாம்;-)",
+"maintenancebacklink"  => "மீளவும் பராமரிப்புப் பக்கத்துக்கு",
+"disambiguations"      => "கவர்படுநிலைதீர் (Disambiguation) பக்கங்கள்",
+"disambiguationspage"  => "விக்கிபீடியா:கவர்படுநிலைதீர்_பக்க_இணைப்புகள்",
+"disambiguationstext"  => "இக் கட்டுரைகள் ஒரு <i>கவர்படுநிலைதீர் (disambiguation) பக்கத்து</i>க்கு இணைக்கப்பட்டுள்ளன. பதிலாக இவை பொருத்தமான தலைப்புக்களுக்கு இணைக்கப்பட வேண்டும்.<br />ஒரு பக்கம் $1 இலிருந்து இணைப்புக் கொடுபட்டிருந்தால் கவர்படுநிலைத் தீர்வாகக் (disambiguation) கருதப்படும்.<br /> ஏனைய பெயர்வெளிகளிலிருந்தான இணைப்புக்கள் இங்கே பட்டியலிடப்<i>படவில்லை</i>.",
+"doubleredirects"      => "இரட்டை வழிமாற்றுகள் (Redirects)",
+"doubleredirectstext"  => "<b>கவனிக்கவும்:</b> இந்தப் பட்டியல் போலியான நேர்மதிப்பு (positives) களைக் கொண்டிருக்கக்கூடும். இது வழக்கமாக, இணைப்புடன் கூடிய மேலதிக உரை முதலாவது #வழிமாற்றுக்குக் கீழ் இருப்பதைக் குறிக்கும்.<br />\nஒவ்வொரு வரியும், முதலாம் இரண்டாம் வழிமாற்றுகளுக்கு இணைப்புகளைக் கொண்டிருப்பதுடன், இரண்டாவது வழிமாற்று உரையின் முதல் வரிக்கும் இணைப்பைக் கொண்டிருக்கும், இது வழக்கமாக முதலாவது வழிமாற்று குறித்துக் காட்ட வேண்டிய \"real\" இலக்குக் கட்டுரையைக் (taget article) கொடுக்கும்.",
+"brokenredirects"      => "முறிந்த வழிமாற்றுகள்(Redirects)",
+"brokenredirectstext"  => "பின்வரும் வழிமாற்றுகள் ஒரு இல்லாத கட்டுரைகு இணைப்புக் கொடுபட்டுள்ளது.",
+"selflinks"            => "தன்னிணைப்புகளோடு (Self Links) கூடிய பக்கங்கள்",
+"selflinkstext"                => "பின்வரும் பக்கங்கள் தம்முள்ளேயே இணைப்பைக் கொண்டுள்ளன. அவ்வாரு இருக்கக் கூடாது.",
+"mispeelings"           => "எழுத்துப் பிழைகளோடு கூடிய பக்கங்கள்",
+"mispeelingstext"               => "பின்வரும் பக்கங்கள், $1 இல் பட்டியலிடப்பட்டிருக்கும் பொதுவான எழுத்துப் பிழைகளைக் கொண்டுள்ளன. சரியான எழுத்துக் கூட்டல்(இப்படி)க் கொடுக்கப்படலாம்.",
+"mispeelingspage"       => "பொதுவான எழுத்துப் பிழைகளின் அட்டவணை.",
+"missinglanguagelinks"  => "தொலைந்த மொழி இணைப்புகள்",
+"missinglanguagelinksbutton"    => "இவற்றுக்கான தொலைந்த மொழியிணைப்புக்களைக் கண்டுபிடி",
+"missinglanguagelinkstext"      => "இக் கட்டுரைகளுக்கு $1 இலுள்ள அவற்றின் ஒத்த பகுதி(counterpart)களோடு இணைப்பு <i>இல்லை</i>.  வழிமாற்று(Redirects)களும் துணைப் பக்கங்களும் <i>காட்டப்படவில்லை</i>.",
+
+
+# Miscellaneous special pages
+#
+"orphans"              => "உறவிலிப்(Orphaned) பக்கங்கள்",
+"lonelypages"  => "உறவிலிப்(Orphaned) பக்கங்கள்",
+"unusedimages" => "உபயோகப்படுத்தப்படாத படிமங்கள்",
+"popularpages" => "பிரபலமான பக்கங்கள்",
+"nviews"               => "$1 காட்சிகள்",
+"wantedpages"  => "வேண்டிய பக்கங்கள்",
+"nlinks"               => "$1 இணைப்புகள்",
+"allpages"             => "எல்ல பக்கங்கள்",
+"randompage"   => "குறிப்பில்வழிப் (Random) பக்கம்",
+"shortpages"   => "குறும் பக்கங்கள்",
+"longpages"            => "நீளமான பக்கங்கள்",
+"listusers"            => "பயனர் அட்டவணை",
+"specialpages" => "விசேட பக்கங்கள்",
+"spheading"            => "எல்லாப் பயனர்களுக்குமான விசேட பக்கங்கள்",
+"protectpage"  => "பக்கத்தைக் காப்புச் செய்",
+"recentchangeslinked" => "தொடர்பான மாற்றங்கள்",
+"rclsub"               => "(\"$1\" இலிருந்து இணைக்கப்பட்ட பக்கங்களுக்கு)",
+"debug"                        => "வழு நீக்கு",
+"newpages"             => "புதிய பக்கங்கள்",
+"ancientpages"         => "மிகப்பழைய கட்டுரைகள்",
+"intl"         => "மொழியிடை இணைப்புகள்",
+"movethispage" => "இப்பக்கத்தை அசை",
+"unusedimagestext" => "<p>இண்டர்நஷனல் விக்கிபீடியா போன்ற மற்ற வலைத் தளங்களில், நேரடி URL மூலம் ஒரு படிமம் இனைக்கப்பட்டிருக்கக் கூடுமென்பதுடன், செயல்படு (active) பயன்பாட்டில் இருந்தும் கூட இங்கே பட்டியலிடப்பட்டிருக்கக்கூடும் என்பதையும் கவனிக்கவும்.",
+"booksources"  => "நூல் மூலங்கள்",
+"booksourcetext" => "புதிய, பயன்படுத்திய புத்தகங்களை விற்பதுடன், நீங்கள் தேடும் நூல்கள்பற்றிய மேலதிக தகவல்களையும் தரக்கூடிய  வேறு தளங்களுடனான இணைப்புகளின் பட்டியல் கீழே தரப்பட்டுள்ளது. விக்கிபீடியா இந்த வியாபார நிறுவனங்கள் எதனுடனும் கூட்டு வைத்திருக்கவில்லை. அத்துடன் இந்தப் பக்கத்தை ஒரு உத்தரவாதமாக (endorsement) அர்த்தப்படுத்திக்கொள்ளக் கூடாது.",
+
+"alphaindexline" => "$1 to $2",
+
+# Email this user
+#
+"mailnologin"  => "அனுப்பும் முகவரி இல்லை",
+"mailnologintext" => "நீங்கள்[[Special:Userlogin|புகுபதிகை செய்திருப்பதுடன்]]
+ஏனைய பயனர்களுக்கு மின்னஞ்சல் அனுப்பக்கூடியத்தாக செல்லுபடியாகக்கூடிய மின்னஞ்சல் முகவரியொன்றும் உங்களுடைய  [[Special:Preferences|விருப்பத் தெரிவுகளில்]] கொடுபட்டிருக்கவேண்டும்.",
+"emailuser"            => "இப் பயனருக்கு மின்னஞ்சல் செய்",
+"emailpage"            => "மின்னஞ்சல் பயனர்",
+"emailpagetext"        => "இப் பயனர் ஒரு செல்லுபடியாகக்கூடிய மின்னஞ்சல் முகவரியை அவரது பயனர் விருப்பத்தேர்வுகளில் கொடுத்திருந்தால், கீழ் வரும் படிவம் ஒரு தனித்த செய்தியை அனுப்பும்.
+பயனர் விருப்பத்தேர்வுகளில் நீங்கள் கொடுத்துள்ள மின்னஞ்சல் முகவரி, பெறுனர் பதில் எழுத முடியும் வகையில், அஞ்சலின் \"From\" முகவரியாகக் காட்சி தரும்.",
+"noemailtitle" => "மின்னஞ்சல் முகவரி இல்லை",
+"noemailtext" => "இப் பயனர் ஒரு செல்லுபடியாகக்கூடிய மின்னஞ்சல் முகவரியைக் குறிப்பிடவில்லை அல்லது பிற பயனர்களிடமிருந்து மின்னஞ்சல் பெறும் விருப்பத் தேர்வைத் தெரிவு செய்யவில்லை.",
+"emailfrom" => "அனுப்புனர்",
+"emailto" => "பெறுனர்",
+"emailsubject" => "உட்பொருள்",
+"emailmessage" => "செய்தி",
+"emailsend" => "அனுப்பு",
+"emailsent" => "மின்னஞ்சல் அனுப்பப்பட்டது",
+"emailsenttext" => "உங்கள் மின்னஞ்சல் செய்தி அனுப்பப்பட்டது.",
+# Watchlist
+"watchlist" => "என்னுடைய கவனிப்புப் பட்டியல்(watchlist)",
+"watchlistsub" => "(பயனர்\"$1\"க்காக)",
+"nowatchlist" => "உங்களுடைய கவனிப்புப் பட்டியலில் ஒரு விடயமும் இல்லை.",
+"watchnologin" => "புகுபதிகை செயப்படவில்லை",
+"watchnologintext" => "உங்கள் கவனிப்புப் பட்டியலில் திருத்தம் செய்வதற்கு, நீங்கள்[[Special:Userlogin|புகுபதிகை செய்திருக்கவேண்டும்]].",
+"addedwatch" => "கவனிப்புப் பட்டியலில் சேர்க்கப்பட்டது",
+"addedwatchtext" => "பக்கம்\"$1\" உங்கள்<a href=\"" .
+  "{{localurle:Special:Watchlist}}\">கவனிப்புப் பக்கத்தில்</a> சேர்க்கப்பட்டுள்ளது.
+இந்தப் பக்கத்துக்கு எதிகாலத்தில் செய்யப்படவுள்ள மாற்றங்களும், அதனோடிணைந்த பேச்சுப் பக்கமும், அங்கே பட்டியலிடப்படும். அத்துடன் தெரிந்தெடுக்க வசதியாக <a href=\"" .
+  "{{localurle:Special:Recentchanges}}\">அண்மைய மாற்றங்களின் பட்டியலில்</a> இது தடித்த எழுத்துக்களில் காட்டப்படும்.
+பின்னர், இப் பக்கத்தை உங்கள் கவனிப்புப் பட்டியலிலிருந்து நீக்க விரும்பினால், பக்கச் சட்டத் (sidebar) திலுள்ள \"Stop watching\" ஐச் சொடுக்கவும்.",
+"removedwatch" => "கவனிப்புப் பட்டியலிலிருந்து நீக்கப்பட்டது",
+"removedwatchtext" => "இந்தப் பக்கம் \"$1\" உங்கள் கவனிப்புப் பட்டியலிலிருந்து நீக்கப்பட்டது.",
+"watchthispage" => "இந்தப் பக்கத்தைக் கவனிக்கவும்",
+"unwatchthispage" => "கவனிப்பதை நிறுத்தவும்",
+"notanarticle" => "ஒரு கட்டுரை அல்ல",
+"watchnochange" => "காட்சிப்படுத்தப்பட்ட கால இடைவெளியில், கவனிப்பிலுள்ள, உங்கள் விடயமெதுவும் தொகுக்கப்பட்டிருக்கவில்லை.",
+"watchdetails" => "(பேச்சுப் பக்கங்களைக் கணக்கிடாமல், $1 பக்கங்கள் கவனிக்கப்பட்டன; வெட்டுநிலை (cutoff) யிலிருந்து, மொத்தம் $2 பக்கங்கள் தொகுக்கப்பட்டன; $3... [$4 முழுப் பட்டியலையும் காண்பித்துத் தொகுக்கவும்].)",
+"watchmethod-recent" => "கவனிக்கப்படுகின்ற பக்கங்களுக்காக, அண்மைய தொகுப்புகள் தேடிப் பார்க்கப்படுகிறன",
+"watchmethod-list" => "அண்மைய தொகுப்புகளுக்காக, கவனிக்கப்படுகின்ற பக்கங்கள் தேடிப் பார்க்கப்படுகிறன",
+"removechecked" => "குறியிடப்பட்ட விடயங்களைக் கவனிப்புப் பட்டியலிலிருந்து நீக்குக.",
+"watchlistcontains" => "உங்கள் கவனிப்புப் பட்டியல் $1 பக்கங்களைக் கொண்டுள்ளது.",
+"watcheditlist" => "இதோ உங்கள் கவனிப்புப் பக்கங்களுக்கான ஒரு அகரவரிசைப் பட்டியல். உங்கள் கவனிப்புப் பட்டியலிலிருந்து நீக்க விரும்பும் பக்கங்களுக்கான கட்டங்களில் குறியிட்டு, திரையின் கீழ்ப் பாகத்திலுள்ள 'குறியிடப்பட்டதை நீக்குக' பொத்தானைச் சொடுக்கவும்.",
+"removingchecked" => "கோரப்பட்ட விடயங்கள் கவனிப்புப் பட்டியலிலிருந்து நீக்கப்படுகின்றன ...",
+"couldntremove" => "விடயம்'$1' ஐ நீக்க முடியவில்லை...",
+"iteminvalidname" => "விடயம் '$1' தொடர்பில் பிரச்சினை உள்ளது, செல்லுபடியாகாத பெயர்...",
+"wlnote" => "பின்வருவன, கடைசி $2 மணிகளில் செய்யப்பட்ட, கடைசி $1 மாற்றங்களாகும்.",
+"wlshowlast" => "கடைசியைக் காட்டு",
+
+# Delete/protect/revert
+"deletepage" => "பக்கத்தை நீக்கு",
+"confirm" => "உறுதிசெய்",
+"excontent" => "இருந்த உள்ளடக்கம்: '$1'",
+"exbeforeblank" => "வெறுமைப்படுத்த (blanking) முன்னிருந்த உள்ளடக்கம்: '$1'",
+"exblank" => "பக்கம் வெறுமையாய் இருந்தது",
+"confirmdelete" => "நீக்குதலை உறுதிப்படுத்து",
+"deletesub" => "(\"$1\" நீக்கப்படுகிறது)",
+"historywarning" => "எச்சரிக்கை: நீங்கள் நீக்கவுள்ள பக்கத்துக்கு ஒரு வரலாறு உண்டு: ",
+"confirmdeletetext" => "தரவுத் தளத்திலுள்ள பக்கமொன்றை அல்லது படிமமொன்றை, அதன் வரலாற்றுடன் சேர்த்து, நிரந்தரமாக நீக்கும் தறுவாயிலுள்ளீர்கள். இதையே நீங்கள் விரும்புகிறீர்கள் என்பதையும், இதன் விளைவுகளை நீங்கள் விளங்கிக்கொண்டிருக்கிறீர்கள் என்பதையும், இதை நீங்கள் விக்கிபீடியா:கொள்கைகளுக்கு </w/wiki.phtml?title=Wikipedia:Policy&action=edit> உட்பட்டே செய்கிறீர்கள் என்பதையும், தயவுசெய்து உறுதிப்படுத்தவும்.",
+"actioncomplete" => "செயற்பாடு நிறைவுற்றது",
+"deletedtext" => "\"$1\" நீக்கப்பட்டு விட்டது. அண்மைய நீக்குதல்களின் பதிவுக்கு $2 ஐப் பார்க்க.",
+"deletedarticle" => "\"$1\" நீக்கப்பட்டது",
+"dellogpage" => "நீக்கல்_பதிவு",
+"dellogpagetext" => "கீழே காணப்படுவது மிக அண்மைய நீக்கல்களின் அட்டவணையாகும். எல்லா நேரங்களும் வழங்கன்(server) நேரங்களாகும்(UTC).",
+"deletionlog" => "நீக்கல்_பதிவு",
+"reverted" => "முன் திருத்தத்துக்கு மீள்விக்கப்பட்டுள்ளது",
+"deletecomment" => "நீக்கலுக்கான காரணம்",
+"imagereverted" => "வெற்றிகரமாக முன்னைய திருத்தத்துக்கு மீழ்விக்கப்பட்டது.",
+"rollback" => "முன்நிலையாக்கத் (Roll back ) தொகுப்புகள்",
+"rollbacklink" => "முன்நிலையாக்கு",
+"rollbackfailed" => "முன்நிலையாக்கம் (Rollback) தோல்வி",
+"cantrollback" => "தொகுப்பை மீழ்விக்க முடியாது; கடைசிப் பங்களிப்பாளரே (contributor) இக் கட்டுரையின் ஆசிரியராகும்.",
+"alreadyrolled" => " ( [[User:$3|$3]] ([[User talk:$3|Talk]]) ஆல் செய்யப்பட்ட [[$1]] திகதிய கடைசித் தொகுப்பை முன்நிலையாக்க முடியாது; வேறு யாரோ இக் கட்டுரையை ஏற்கெனவே தொகுத்தோ அல்லது முன்நிலையாக்கியோ உள்ளார்.
+கடைசியாகத் தொகுத்தவர்[[User:$3|$3]] ([[User talk:$3|Talk]]). ",
+# only shown if there is an edit comment
+"editcomment" => "தொகுப்புக்குரிய கருத்துரை (comment): \"$1\".",
+"revertpage" => "$1 ஆல் கடைசித் தொகுப்புக்கு முன்நிலையாக்கப்பட்டது",
+# Undelete
+"undelete" => "நீக்கப்பட்ட பக்கங்களை மீட்டெடு",
+"undeletepage" => "பார்ப்பதுடன், நீக்கப்பட்ட பக்கங்களை மீட்டெடு",
+"undeletepagetext" => "பின்வரும் பக்கங்கள் நீக்கப்பட்டுவிட்டன எனினும் காப்பகத்திலுள்ளதுடன் அவற்றை மீட்டெடுக்கவும் முடியும்.  காப்பகம் காலத்துக்குக் காலம் சுத்தப்படுத்தப்படலாம்.",
+"undeletearticle" => "நீக்கப்பட்ட கட்டுரையை மீட்டெடு",
+"undeleterevisions" => "$1 திருத்தங்கள் காப்பகப்படுத்த்ப்பட்டன",
+"undeletehistory" => "இந்தப் பக்கத்தை நீங்கள் மீள்வித்தால், எல்லாத் திருத்தங்களும் வரலாற்றுக்கு மீள்விக்கப்படும். நீக்குதலின் பின்னர், அதே பெயருடைய வேறொரு புதிய பக்கம் உருவாக்கப்பட்டிருந்தால், மீள்விக்கப்பட்ட திருத்தங்கள் முன்னைய வரலாற்றிலேயே காணப்படும், அத்துடன் உயிர்ப்பு நிலையிலுள்ள () நடப்புத் திருத்தம் தன்னியக்கமாகப் பிரதியீடு செய்யப்பட மாட்டாது.",
+"undeleterevision" => "$1 திருத்தத்தை நீக்கு",
+"undeletebtn" => "மீட்டெடு!",
+"undeletedarticle" => "\"$1\" மீட்டெடுக்கப்பட்டது",
+"undeletedtext"   => "கட்டுரை [[$1]] வெற்றிகரமாக மீட்டெடுக்கப்பட்டது.
+அண்மைய மீட்டல்கள், மீட்டெடுத்தல்களின் பதிவுகளுக்கு[[Wikipedia:Deletion_log]] ஐப் பார்க்கவும்.",
+
+# Contributions
+#
+"contributions"        => "பயனர் பங்களிப்புக்கள்",
+"mycontris" => "என் பங்களிப்புக்கள்",
+"contribsub"   => "$1 க்காக",
+"nocontribs"   => "இந்த நிபந்தனையுடன் ஒத்துப்போகும் வகையில் மாற்றங்களெதுவும் காணப்படவில்லை.",
+"ucnote"               => "பின்வருவது கடந்த <b>$2</b> நாட்களில் இப் பயனரினால் செய்யப்பட்ட கடைசி <b>$1</b> மாற்றங்களாகும்.",
+"uclinks"              => "கடைசி $1 மாற்றங்களைக் காண்க; கடைசி $2 நாட்களைப் பார்.",
+"uctop"                => " (மேல்)" ,
+
+# What links here
+#
+"whatlinkshere"        => "இப் பக்கத்தை இணைத்தவை",
+"notargettitle" => "இலக்கு இல்லை",
+"notargettext" => "நீங்கள் இந்தச் செயலை எந்தப் பயனர் அல்லது பக்கம் தொடர்பில் செய்வது என்பதைக் குறிப்பிடவில்லை.",
+"linklistsub"  => "(இணைப்புகளின் பட்டியல்)",
+"linkshere"            => "பின்வரும் பக்கங்களில் இப்பக்கம் இணைக்கப்பட்டுள்ளது:",
+"nolinkshere"  => "எந்தப் பக்கத்திலும் இந்தப் பக்கம் இணைக்கப்படவில்லை.",
+"isredirect"   => "வழிமாற்றுப் பக்கம்",
+
+# Block/unblock IP
+#
+"blockip"              => "பயனரைத் தடு",
+"blockiptext"  => "ஒரு குறிப்பிட்ட ஐபி முகவரி அல்லது பயனரிடமிருந்து எழுத்து அணுக்கத்தைத் தடுப்பதற்குக் கீழேயுள்ள படிவத்தை உபயோகிக்கவும். இது விஷமத்தனத்தைத் தடுப்பதற்கும் [[Wikipedia:Policy|விக்கிபீடியா கொள்கை]]க்கு எற்புடைய வகையிலும் மட்டுமே பயன்படுத்தப்பட வேண்டும்.
+குறிப்பிட்ட காரணமொன்றைக் கீழே நிரப்புக (உதாரணமாக், விஷமத்தனம் செய்யப்பட்ட (vandalized) பக்கங்களை எடுத்துக் காட்டவும்).",
+"ipaddress"            => "ஐபி (IP) முகவரி/பயனர்பெயர்",
+"ipbreason"            => "காரணம்",
+"ipbsubmit"            => "இப் பயனரைத் தடு",
+"badipaddress" => "அந்தப் பெயரில் பயனர் எவரும் இல்லை",
+"blockipsuccesssub" => "தடுப்பு வெற்றி",
+"blockipsuccesstext" => "\"$1\" தடுக்கப்பட்டுள்ளார்.
+<br />தடுப்பை மீளாய்வு செய்ய [[Special:Ipblocklist|IP block list]] ஐப் பார்க்கவும்.",
+"unblockip"            => "பயனர் தடை நீக்கு",
+"unblockiptext"        => "முன்னர் தடுக்கப்பட்ட ஐபி முகவரி அல்லது பயனர்பெயரின் எழுத்து அணுக்கத்தை மீழ்விப்பதற்கு கீழேயுள்ள படிவத்தை உபயோகிக்கவும்.",
+"ipusubmit"            => "இம் முகவரியைத் தடை நீக்கு",
+"ipusuccess"   => "\"$1\" தடை நீக்கப்பட்டது",
+"ipblocklist"  => "தடுக்கப்பட்ட ஐபி முகவரிகளினதும், பயனர் பெயர்களினதும் பட்டியல்",
+"blocklistline"        => "$1, $2 blocked $3 ($4)",
+"blocklink"            => "தடு",
+"unblocklink"  => "தடை நீக்கு",
+"contribslink" => "contribs",
+"autoblocker"  => "நீங்கள் \"$1\" உடன் ஒரே ஐபி முகவரியைப் பகிர்ந்துகொள்வதால் தானியங்கித் தடை விதிக்கப்பட்டுள்ளது. காரணம் \"$2\".",
+"blocklogpage" => "தடைப்_பதிவு (Block_log)",
+"blocklogentry"        => 'தடுக்கப்பட்டது "$1"',
+"blocklogtext" => "இது ஒரு பயனரின் தடுப்பு தடை நீக்கல் செயற்பாடுகளுக்கான பதிவாகும். தானியங்கி முறையில் தடுக்கப்படும் ஐபி முகவரிகள் இப்பட்டியலில் இடம்பெறா.  தற்போது செயற்பாட்டிலுள்ள தடைகளையும்் முடக்கங்களையும் [[Special:Ipblocklist|ஐபி தடுப்பு பட்டியலில்]] பார்க்க.",
+"unblocklogentry"      => 'தடுப்பு நீக்கப்பட்டது "$1"',
+
+# Developer tools
+#
+"lockdb"               => "தரவுத்தளத்தைப் பூட்டு",
+"unlockdb"             => "தரவுத்தளத்தைத் திற",
+"lockdbtext"   => "தரவுத்தளத்தைப் பூட்டுதல், பயனர்கள் பக்கங்களைத் தொகுக்கவும், விருப்பத் தேர்வுகளை மாற்றவும், கவனிப்புப் பட்டியல்களைத் தொகுக்கவும், மற்றும் தரவுத்தளத்தில் மாற்றங்கள் தேவைப்படும் பிற விடயங்களைச் செய்யவும் முடியாமல் இடை நிறுத்தும். இதுதான் உங்களுக்கு வேண்டியது என்பதையும், பராமரிப்பு முடிந்ததும் தரவுத்தளத்தைத் திறந்துவிடுவீர்கள் என்பதையும் தயவுசெய்து உறுதிப்படுத்தவும்.",
+"unlockdbtext" => "தரவுத்தளத்தைத் திறத்தல், பக்கங்களைத் தொகுக்கவும், விருப்பத் தேர்வுகளை மாற்றவும், கவனிப்புப் பட்டியல்களைத் தொகுக்கவும், மற்றும் தரவுத்தளத்தில் மாற்றங்கள் தேவைப்படும் பிற விடயங்களைச் செய்யவும் கூடிய திறனைப் பயனர்களுக்கு மீள்விக்கும். இதுதான் நீங்கள் செய்ய விரும்புகிறீர்கள் என்பதைத் தயவுசெய்து உறுதிப்படுத்துங்கள்.",
+"lockconfirm"  => "ஆம், நான் உண்மையில் தரவுத்தளத்தைப் பூட்ட விரும்புகிறேன்.",
+"unlockconfirm"        => "ஆம், நான் உண்மையில் தரவுத்தளத்தைத் திறக்க விரும்புகிறேன்.",
+"lockbtn"              => "தரவுத்தளத்தைப் பூட்டுக",
+"unlockbtn"            => "தரவுத்தளத்தைத் திறக்கவும்",
+"locknoconfirm" => "நீங்கள் உறுதிப்படுத்தல் கட்டத்துள் குறியிடவில்லை.",
+"lockdbsuccesssub" => "தரவுத்தளப் பூட்டல் வெற்றி",
+"unlockdbsuccesssub" => "தரவுத்தளப் பூட்டு நீக்கப்பட்டது",
+"lockdbsuccesstext" => "விக்கிபீடியா தரவுத்தளம் பூட்டப் பட்டது.
+<br />பராமரிப்பு முடிவடைந்ததும் பூட்டை நீக்க மறவாதீர்.",
+"unlockdbsuccesstext" => "விக்கிபீடியா தரவுத்தளம் திறக்கப்பட்டது.",
+
+# Move page
+#
+"movepage"             => "பக்கத்தை நகர்த்து",
+"movepagetext" => "பின்வரும் படிவத்தைப் பயன்படுத்துவது, பக்கமொன்றின் பெயரை மாற்றி, இதனுடைய முழு வரலாற்றையும் புதிய பெயருக்கு நகர்த்தும். பழைய தலைப்பு, புதிய பக்கத்துக்கான ஒர் வழிகாட்டும் பக்கமாக ஆகும். பழைய பக்கத் தலைப்புக்கு உள்ள இணைப்புக்கள் மாறமாட்டா; இரட்டை அல்லது முறிந்த வழிமாற்றுகள் உள்ளனவா என்பதைச் சரி பார்த்து உறுதிசெய்யவும். இணைப்புகள் எவ்விடத்துக்குச் சென்றடைய வேண்டுமோ அவ்விடத்தைத் தொடர்ந்தும் குறிப்பதை உறுதி செய்து கொள்வது உங்கள் பொறுப்பாகும்.<br />
+ஏற்கெனவே புதிய தலைப்பில் ஒரு பக்கம் இருந்தால், இந்தப் பக்கம் வெறுமையாகவோ அல்லது ஒரு வழிமாற்றுப் பக்கமாகவோ இருப்பதுடன் பழைய தொகுப்பு வரலாறும் இல்லாதிருந்தால்தான்,  இப் பக்கம் நகர்த்தப்படும் என்பதைக் கவனிக்கவும். தற்செயலாக, நீங்கள் தவறு செய்துவிட்டால், எந்தப் பெயரிலிருந்து பெயர் மாற்றம் செய்தீர்களோ அதே பெயருக்கு மீண்டும் மாற்றமுடியும் என்பதுடன் ஏற்கெனவே இருக்கும் பக்கமொன்றை மேலெழுத (overwrite) முடியாது என்பதையும் இது குறிக்கின்றது.
+<b>எச்சரிக்கை!</b>
+இது பிரபலமான ஒரு பக்கத்துக்குச் செய்யும் கடுமையானதும், எதிர்பாராததுமான மாற்றமாக இருக்கக்கூடும்; தொடர்வதற்கு முன் இதன் விளைவுகளை விளங்கிக்கொண்டிருக்கிறீர்கள் என்பதை உறுதிப்படுத்திக் கொள்ளவும்.",
+"movepagetalktext" => "*நீங்கள் பக்கத்தைப் பெயர்வெளிகள் (namespaces) இடையே நகர்த்துகிறீர்கள் என்றோ,
+*ஒரு வெறுமையில்லாத பேச்சுப் பக்கம் புதிய பெயரில் ஏற்கெனவேயிருந்தோ, அல்லது
+*நீங்கள் கீழேயுள்ள கட்டத்தில் குறியிடாமல் விடுகிறீர்கள் என்றோ.
+ '''இல்லாவிடில்''' சேர்ந்திருக்கும் பேச்சுப் பக்கம், ஏதாவது இருந்தால், தன்னியக்கமாக அதனுடன் நகர்த்தப்படும்.
+இப்படியான சந்தர்ப்பங்களில், விரும்பினால், நகர்த்தலையோ அல்லது ஒன்றிணைத்தலையோ நீங்கள் கைவினையாகச் செய்யவேண்டியிருக்கும்.",
+"movearticle"  => "பக்கத்தை இடம்பெயர்",
+"movenologin"  => "புகுபதிகை செய்யப்படவில்லை",
+"movenologintext" => "இப் பக்கத்தை இடம்பெயர்ப்பதற்கு, நீங்கள் ஒரு பதிவு செய்யப்பட்ட பயனராயும்
+[[Special:Userlogin|புகுபதிகை செய்தும்]]
+இருக்க வேண்டும்.",
+"newtitle"             => "புதிய தலைப்புக்கு",
+"movepagebtn"  => "பக்கத்தை நகர்த்து",
+"pagemovedsub" => "நகர்த்தல் வெற்றி",
+"pagemovedtext" => "பக்கம் \"[[$1]]\" \"[[$2]]\" க்கு நகர்த்தப்பட்டுள்ளது.",
+"articleexists" => "அந்தப் பெயரையுடைய பக்கம் ஏற்கெனவே உள்ளது அல்லது நீங்கள் தெரிவு செய்த பெயர் செல்லுபடியாகாது. தயவுசெய்து வேறு பெயரைத் தெரியவும்.",
+"talkexists"   => "பக்கம் வெற்றிகரமாக நகர்த்தப்பட்டது, ஆனால் பேச்சுப் பக்கத்தை நகர்த்த முடியவில்லை ஏனெனில் புதிய தலைப்பில் இன்னொன்று உள்ளது. தயவுசெய்து கையால் (manually) ஒன்றுகலக்கவும்.",
+"movedto"              => "நகர்த்தப்பட்ட இடம்",
+"movetalk"             => "தக்கதாயின் \"talk\" பக்கத்தையும் நகர்த்தவும்.",
+"talkpagemoved" => "ஒத்த பேச்சுப் பக்கமும் நகர்த்தப்பட்டுள்ளது.",
+"talkpagenotmoved" => "ஒத்த பெச்சுப் பக்கம் <strong>நகர்த்தப்படவில்லை</strong>.",
+
+"export"               => "ஏற்றுமதிப் பக்கங்கள்",
+"exporttext"   => "ஒரு பக்கத்தினதோ அல்லது ஒரு தொகுதி பக்கங்களினதோ உரையையும், தொகுப்பு வரலாற்றையும், ஏதாவது XML இல் சுற்றி (wrapped in) ஏற்றுமதி செய்ய முடியும்; இதைப் மீடியாவிக்கி மென்பொருளிலியங்கும் இன்னொரு விக்கிக்கு இறக்குமதி செய்து, அதில் மாற்றம் செய்யலாம் அல்லது உங்கள் தனிப்பட்ட தேவைக்கு வைத்துக்கொள்ளலாம்.",
+"exportcuronly"        => "நடப்புத் திருத்தத்தை மட்டும் சேர்க்கவும்",
+);
+
+class LanguageTa extends LanguageUtf8 {
+       function getNamespaces() {
+               global $wgNamespaceNamesTa;
+               return $wgNamespaceNamesTa;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsTa;
+               return $wgQuickbarSettingsTa;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesTa;
+               return $wgSkinNamesTa;
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesTa;
+               if( array_key_exists( $key, $wgAllMessagesTa ) )
+                       return $wgAllMessagesTa[$key];
+               else
+                       return parent::getMessage($key);
+       }
+}
+
+?>
diff --git a/languages/LanguageTe.php b/languages/LanguageTe.php
new file mode 100644 (file)
index 0000000..b5de0d4
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+/** Telugu (Telugu)
+  *
+  * @package MediaWiki
+  * @subpackage Language
+  *
+  * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
+  */
+
+require_once( 'LanguageUtf8.php' );
+
+class LanguageTe extends LanguageUtf8 {
+       var $digitTransTable = array(
+               '0' => '౦',
+               '1' => '౧',
+               '2' => '౨',
+               '3' => '౩',
+               '4' => '౪',
+               '5' => '౫',
+               '6' => '౬',
+               '7' => '౭',
+               '8' => '౮',
+               '9' => '౯'
+       );
+
+       function formatNum( $number ) {
+               global $wgTranslateNumerals;
+               if( $wgTranslateNumerals ) {
+                       return strtr( $number, $this->digitTransTable );
+               } else {
+                       return $number;
+               }
+       }
+}
+
+?>
diff --git a/languages/LanguageTh.php b/languages/LanguageTh.php
new file mode 100644 (file)
index 0000000..92fe23e
--- /dev/null
@@ -0,0 +1,252 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+#--------------------------------------------------------------------------
+# Translated from English by Varakorn Ungvichian
+# แปลงจากภาษาอังกฤษโดย นาย วรากร อึ้งวิเชียร
+#--------------------------------------------------------------------------
+
+/* private */ $wgNamespaceNamesTh = array(
+       NS_MEDIA                => "Media",
+       NS_SPECIAL              => "พิเศษ",
+       NS_MAIN                 => "",
+       NS_TALK                 => "พูดคุย",
+       NS_USER                 => "ผู้ใช้",
+       NS_USER_TALK            => "คุยเกี่ยวกับผู้ใช้",
+       NS_PROJECT              => $wgMetaNamespace,
+       NS_PROJECT_TALK         => $wgMetaNamespace . "_talk",
+       NS_IMAGE                => "ภาพ",
+       NS_IMAGE_TALK           => "คุยเกี่ยวกับภาพ",
+       NS_MEDIAWIKI            => "MediaWiki",
+       NS_MEDIAWIKI_TALK       => "คุยเกี่ยวกับ_MediaWiki",
+
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgQuickbarSettingsTh = array(
+       "ไม่มี", "อยู่ทางซ้าย", "อยู่ทางขวา", "ลอยทางซ้าย"
+);
+
+/* private */ $wgAllMessagesTh = array(
+
+# User Toggles
+#
+
+"tog-underline" => "ขีดเส้นใต้ลิงก์",
+"tog-highlightbroken" => "จัดลิงก์ที่ไม่มี <a href=\"\" class=\"new\">เป็น ดังนี้</a> (หรือ เป็นดังนี้<a href=\"\" class=\"internal\">?</a>).",
+"tog-justify"  => "จัดย่อหน้าให้เรียบร้อย",
+"tog-hideminor" => "ไม่แสดงการแก้ไขย่อยใน recent changes",
+"tog-usenewrc" => "Enhanced recent changes (ไม่สามารถใช้ได้กับทุกเว็บบราวเซอร์)",
+"tog-numberheadings" => "ใส่ตัวเลขหน้าหัวข้อโดยอัตโนมัติ",
+"tog-showtoolbar" => "Show edit toolbar",
+"tog-editondblclick" => "แก้ไขหน้าโดยใช้ double click (ผ่าน JavaScript)",
+"tog-editsection"=>"สามารถแก้ไขเฉพาะส่วนโดยใช้ลิงก์ [แก้ไข]",
+"tog-editsectiononrightclick"=>"สามารถแก้ไขเฉพาะส่วนโดยใช้ right click<br /> บนชื่อส่วนย่อย (ผ่าน JavaScript)",
+"tog-showtoc"=>"แสดงสารบัญ<br />(สำหรับบทความที่มีมากกว่า 3 หัวข้อ)",
+"tog-rememberpassword" => "จำ password ระหว่าง session",
+"tog-editwidth" => "กล่องสำหรับการแก้ไขกว้างเต็มหน้าจอ",
+"tog-watchdefault" => "นำหน้าที่แก้ไขไปใส่ watchlist",
+"tog-minordefault" => "กำหนด default ให้การแก้ไขทุกครั้งเป็นการแก้ไขย่อย",
+"tog-previewontop" => "แสดง preview ก่อนกล่องสำหรับการแก้ไข",
+"tog-nocache" => "ไม่นำหน้าต่าง ๆ มาใส่ใน cache",
+
+
+# Dates
+#
+
+'sunday' => "วันอาทิตย์",
+'monday' => "วันจันทร์",
+'tuesday' => "วันอังคาร",
+'wednesday' => "วันพุธ",
+'thursday' => "วันพฤหัสบดี",
+'friday' => "วันศุกร์",
+'saturday' => "วันเสาร์",
+'january' => "มกราคม",
+'february' => "กุมภาพันธ์",
+'march' => "มีนาคม",
+'april' => "เมษายน",
+'may_long' => "พฤษภาคม",
+'june' => "มิถุนายน",
+'july' => "กรกฎาคม",
+'august' => "สิงหาคม",
+'september' => "กันยายน",
+'october' => "ตุลาคม",
+'november' => "พฤศจิกายน",
+'december' => "ธันวาคม",
+'jan' => "ม.ค.",
+'feb' => "ก.พ.",
+'mar' => "มี.ค.",
+'apr' => "เม.ย.",
+'may' => "พ.ค.",
+'jun' => "มิ.ย.",
+'jul' => "ก.ค.",
+'aug' => "ส.ค.",
+'sep' => "ก.ย.",
+'oct' => "ต.ค.",
+'nov' => "พ.ย.",
+'dec' => "ธ.ค.",
+
+# Bits of text used by many pages:
+#
+"categories" => "ประเภทของหน้า",
+"category" => "ประเภท",
+"category_header" => "บทความในประเภท \"$1\"",
+"subcategories" => "ประเภทย่อย",
+
+"linktrail"            => "/^([a-z]+)(.*)\$/sD",
+"mainpage"             => "หน้าหลัก",
+"mainpagetext" => "Wiki software  ถูกติดตั้งเรียบร้อยแล้ว",
+"about"                        => "เกี่ยวกับ",
+"aboutsite"      => "เกี่ยวกับ {{SITENAME}}",
+"aboutpage"            => "{{ns:project}}:เกี่ยวกับ",
+"help"                 => "ความช่วยเหลือ",
+"helppage"             => "{{ns:project}}:ความช่วยเหลือ",
+"bugreports"   => "รายงาน bug",
+"bugreportspage" => "{{ns:project}}:รายงาน bug",
+"sitesupport"   => "การบริจาค",
+"faq"                  => "FAQ",
+"faqpage"              => "{{ns:project}}:FAQ",
+"edithelp"             => "ความช่วยเหลือในการแก้ไขหน้า",
+"edithelppage" => "{{ns:project}}:การแก้ไขหน้า",
+"cancel"               => "ยกเลิก",
+"qbfind"               => "ค้นหา",
+"qbbrowse"             => "ค้น",
+"qbedit"               => "แก้ไข",
+"qbpageoptions" => "หน้านี้",
+"qbpageinfo"   => "บริบท",
+"qbmyoptions"  => "หน้าของฉัน",
+"qbspecialpages"       => "หน้าพิเศษ",
+"moredotdotdot"        => "อื่น ๆ ...",
+"mypage"               => "หน้าของฉัน",
+"mytalk"               => "หน้าพูดคุยของฉัน",
+"currentevents" => "เหตุการณ์ปัจจุบัน",
+"errorpagetitle" => "ความผิดพลาด",
+"returnto"             => "กลับไปยัง $1.",
+"tagline"              => "จาก {{SITENAME}}, สารานุกรมฟรี",
+"whatlinkshere"        => "หน้าที่ลิงก์มายังที่นี่",
+"help"                 => "ความช่วยเหลือ",
+"search"               => "ค้นหา",
+"go"           => "ไป",
+"history"              => "ประวัติของหน้านี้",
+"printableversion" => "Printable version",
+"editthispage" => "แก้ไขหน้านี้",
+"deletethispage" => "ลบหน้านี้",
+"protectthispage" => "ป้องกันหน้านี้",
+"unprotectthispage" => "ยกเลิกการป้องกันหน้านี้",
+"newpage" => "หน้าใหม่",
+"talkpage"             => "พูดคุยเกี่ยวกับหน้านี้",
+"postcomment"   => "Post a comment",
+"articlepage"  => "View article",
+"subjectpage"  => "View subject", # For compatibility
+"userpage" => "View user page",
+"wikipediapage" => "View meta page",
+"imagepage" =>         "View image page",
+"viewtalkpage" => "View discussion",
+"otherlanguages" => "Other languages",
+"redirectedfrom" => "(Redirected from $1)",
+"lastmodified" => "This page was last modified $1.",
+"viewcount"            => "This page has been accessed $1 times.",
+"printsubtitle" => "(From {{SERVER}})",
+"protectedpage" => "Protected page",
+"administrators" => "{{ns:project}}:Administrators",
+"sysoptitle"   => "Sysop access required",
+"sysoptext"            => "The action you have requested can only be
+performed by users with \"sysop\" status.
+See $1.",
+"developertitle" => "Developer access required",
+"developertext"        => "The action you have requested can only be
+performed by users with \"developer\" status.
+See $1.",
+
+"nbytes"               => "$1 ไบต์",
+"go"                   => "ไป",
+"ok"                   => "OK",
+"sitetitle"            => "{{SITENAME}}",
+"sitesubtitle" => "สารานุกรมฟรี",
+"retrievedfrom" => "Retrieved from \"$1\"",
+"newmessages" => "คุณมีข้อความใหม่ $1.",
+"newmessageslink" => "ข้อความ",
+"editsection"=>"แก้ไข",
+"toc" => "สารบัญ",
+"showtoc" => "แสดงสารบัญ",
+"hidetoc" => "ซ่อนสารบัญ",
+"thisisdeleted" => "แสดงหรือคืน $1?",
+"restorelink" => "$1 การแก้ไขที่ลบแล้ว",
+
+# Main script and global functions
+#
+"nosuchaction" => "ไม่มีการกระทำดังกล่าว",
+"nosuchactiontext" => "การกระทำที่บอกไว้ใน URL ไม่
+เป็นที่ยอมรับของ wiki",
+"nosuchspecialpage" => "ไม่มีหน้าพิเศษดังกล่าว",
+"nospecialpagetext" => "คุณได้ขอหน้าพิเศษที่ไม่
+เป็นที่ยอมรับของ wiki",
+
+# Login and logout pages
+#
+"loginpagetitle" => "ล็อกอินผู้ใช้",
+"yourname"             => "ชื่อผู้ใช้",
+"yourpassword" => "รหัสผ่าน",
+"yourpasswordagain" => "พิมพ์รหัสผ่านอีกครั้ง",
+"newusersonly" => " (เฉพาะผู้ใช้ใหม่)",
+
+"login"                        => "ล็อกอิน",
+"loginprompt"           => "ต้อง enable cookie เพื่อล็อกอินสู่ {{SITENAME}} ได้",
+"userlogin"            => "ล็อกอิน",
+"logout"               => "ล็อกเอาท์",
+"userlogout"   => "ล็อกเอาท์",
+"notloggedin"  => "ไม่ได้ล็อกอินไว้",
+"createaccount"        => "สร้าง account ใหม่",
+"createaccountmail"    => "ผ่านอีเมล์",
+"badretype"            => "รหัสผ่านที่พิมพ์ไว้ไม่เหมือนกัน",
+"userexists"   => "ชื่อผู้ใช้ที่พิมพ์ไว้ถูกใช้แล้ว โปรดเลือกชื่ออื่น",
+"youremail"            => "อีเมล์ของคุณ*",
+
+# Edit pages
+#
+"newarticletext" =>
+"คุณได้ตามลิงก์ที่นำไปยังหน้าที่ยังไม่ปรากฏอยู่
+เพื่อเริ่มสร้างหน้าใหม่ พิมพ์ลงในกล่องข้างล่างนี้
+(ดู[[{{ns:project}}:ความช่วยเหลือ|หน้าความช่วยเหลือ]]สำหรับข้อมูลเพิ่มเติม)
+If you are here by mistake, just click your browser's '''back''' button.",
+"noarticletext" => "(ไม่มีข้อความในหน้านี้)",
+"updated"              => "(ได้รับการแก้ไขแล้ว)",
+
+);
+
+#--------------------------------------------------------------------------
+# Internationalisation code
+#--------------------------------------------------------------------------
+
+require_once( "LanguageUtf8.php" );
+
+class LanguageTh extends LanguageUtf8 {
+
+       function getNamespaces() {
+               global $wgNamespaceNamesTh;
+               return $wgNamespaceNamesTh;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsTh;
+               return $wgQuickbarSettingsTh;
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesTh;
+               if( isset( $wgAllMessagesTh[$key] ) ) {
+                       return $wgAllMessagesTh[$key];
+               } else {
+                       return parent::getMessage( $key );
+               }
+       }
+
+       function getAllMessages() {
+               global $wgAllMessagesTh;
+               return $wgAllMessagesTh;
+       }
+
+}
+
+?>
diff --git a/languages/LanguageTlh.php b/languages/LanguageTlh.php
new file mode 100644 (file)
index 0000000..a338dc9
--- /dev/null
@@ -0,0 +1,42 @@
+<?php
+/** Klingon (tlhIngan-Hol)
+  *
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+require_once( "LanguageUtf8.php" );
+
+if ( $wgMetaNamespace == "Wikipedia" ) {
+       $wgMetaNamespace = "wIqIpe'DIya";
+}
+
+/* private */ $wgNamespaceNamesTlh = array(
+       NS_MEDIA            => "Doch",
+       NS_SPECIAL          => "le'",
+       NS_MAIN             => "",
+       NS_TALK             => "ja'chuq",
+       NS_USER             => "lo'wI'",
+       NS_USER_TALK        => "lo'wI'_ja'chuq",
+       NS_PROJECT          => $wgMetaNamespace,
+       NS_PROJECT_TALK     => $wgMetaNamespace . "_ja'chuq",
+       NS_IMAGE            => "nagh_beQ",
+       NS_IMAGE_TALK       => "nagh_beQ_ja'chuq",
+       NS_MEDIAWIKI        => "MediaWiki",
+       NS_MEDIAWIKI_TALK   => "MediaWiki_ja'chuq",
+       NS_TEMPLATE         => "chen'ay'",
+       NS_TEMPLATE_TALK    => "chen'ay'_ja'chuq",
+       NS_HELP             => "QaH",
+       NS_HELP_TALK        => "QaH_ja'chuq",
+       NS_CATEGORY         => "Segh",
+       NS_CATEGORY_TALK    => "Segh_ja'chuq"
+) + $wgNamespaceNamesEn;
+
+class LanguageTlh extends LanguageUtf8 {
+       function getNamespaces() {
+               global $wgNamespaceNamesTlh;
+               return $wgNamespaceNamesTlh;
+       }
+}
+
+?>
diff --git a/languages/LanguageTr.php b/languages/LanguageTr.php
new file mode 100644 (file)
index 0000000..a68deba
--- /dev/null
@@ -0,0 +1,43 @@
+<?php
+require_once( "LanguageUtf8.php" );
+
+/* private */ $wgNamespaceNamesTr = array(
+       NS_MEDIA            => 'Media',
+       NS_SPECIAL          => 'Özel',
+       NS_MAIN             => '',
+       NS_TALK             => 'Tartışma',
+       NS_USER             => 'Kullanıcı',
+       NS_USER_TALK        => 'Kullanıcı_mesaj',
+       NS_PROJECT          => $wgMetaNamespace,
+       NS_PROJECT_TALK     => $wgMetaNamespace . '_tartışma',
+       NS_IMAGE            => 'Resim',
+       NS_IMAGE_TALK       => 'Resim_tartışma',
+       NS_MEDIAWIKI        => 'MedyaViki',
+       NS_MEDIAWIKI_TALK   => 'MedyaViki_tartışma',
+       NS_TEMPLATE         => 'Şablon',
+       NS_TEMPLATE_TALK    => 'Şablon_tartışma',
+       NS_HELP             => 'Yardım',
+       NS_HELP_TALK        => 'Yardım_tartışma',
+       NS_CATEGORY         => 'Kategori',
+       NS_CATEGORY_TALK    => 'Kategori_tartışma',
+) + $wgNamespaceNamesEn;
+
+class LanguageTr extends LanguageUtf8 {
+       function getNamespaces() {
+               global $wgNamespaceNamesTr;
+               return $wgNamespaceNamesTr;
+       }
+
+       function formatNum( $number, $year = false ) {
+               return $year ? $number : strtr($this->commafy($number), '.,', ',.' );
+       }
+
+       function ucfirst ( $string ) {
+               if ( $string[0] == 'i' ) {
+                       return 'İ' . substr( $string, 1 );
+               } else {
+                       return parent::ucfirst( $string );
+               }
+       }
+}
+?>
diff --git a/languages/LanguageTt.php b/languages/LanguageTt.php
new file mode 100644 (file)
index 0000000..55bd392
--- /dev/null
@@ -0,0 +1,168 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+#
+# Tatarish localisation for MediaWiki
+#
+# This file is encoded in UTF-8, no byte order mark.
+# For compatibility with Latin-1 installations, please
+# don't add literal characters above U+00ff.
+#
+
+require_once( "LanguageUtf8.php" );
+
+/* private */ $wgNamespaceNamesTt = array(
+       NS_MEDIA            => 'Media',
+       NS_SPECIAL          => 'Maxsus',
+       NS_MAIN             => '',
+       NS_TALK             => 'Bäxäs',
+       NS_USER             => 'Äğzä',
+       NS_USER_TALK        => "Äğzä_bäxäse",
+       NS_PROJECT          => "Wikipedia",
+       NS_PROJECT_TALK     => "Wikipedia_bäxäse",
+       NS_IMAGE            => "Räsem",
+       NS_IMAGE_TALK       => "Räsem_bäxäse",
+       NS_MEDIAWIKI        => "MediaWiki",
+       NS_MEDIAWIKI_TALK   => "MediaWiki_bäxäse",
+       NS_TEMPLATE         => "Ürnäk",
+       NS_TEMPLATE_TALK    => "Ürnäk_bäxäse",
+       NS_HELP             => "Yärdäm",
+       NS_HELP_TALK        => "Yärdäm_bäxäse",
+       NS_CATEGORY         => "Törkem",
+       NS_CATEGORY_TALK    => "Törkem_bäxäse"
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgDateFormatsTt = array(
+#        "köyläwsez",
+);
+
+# Note to translators:
+#   Please include the English words as synonyms.  This allows people
+#   from other wikis to contribute more easily.
+#
+/* private */ $wgMagicWordsTt = array(
+#       ID                                 CASE  SYNONYMS
+       MAG_REDIRECT             => array( 0,    '#yünältü'               ),
+       MAG_NOTOC                => array( 0,    '__ETYUQ__'              ),
+       MAG_FORCETOC             => array( 0,    '__ETTIQ__'              ),
+       MAG_TOC                  => array( 0,    '__ET__'                 ),
+       MAG_NOEDITSECTION        => array( 0,    '__BÜLEMTÖZÄTÜYUQ__'     ),
+       MAG_START                => array( 0,    '__BAŞLAW__'             ),
+       MAG_CURRENTMONTH         => array( 1,    'AĞIMDAĞI_AY'            ),
+       MAG_CURRENTMONTHNAME     => array( 1,    'AĞIMDAĞI_AY_İSEME'      ),
+       MAG_CURRENTDAY           => array( 1,    'AĞIMDAĞI_KÖN'           ),
+       MAG_CURRENTDAYNAME       => array( 1,    'AĞIMDAĞI_KÖN_İSEME'     ),
+       MAG_CURRENTYEAR          => array( 1,    'AĞIMDAĞI_YIL'           ),
+       MAG_CURRENTTIME          => array( 1,    'AĞIMDAĞI_WAQIT'         ),
+       MAG_NUMBEROFARTICLES     => array( 1,    'MÄQÄLÄ_SANI'            ),
+       MAG_CURRENTMONTHNAMEGEN  => array( 1,    'AĞIMDAĞI_AY_İSEME_GEN'  ),
+       MAG_PAGENAME             => array( 1,    'BİTİSEME'               ),
+       MAG_NAMESPACE            => array( 1,    'İSEMARA'                ),
+       MAG_SUBST                => array( 0,    'TÖPÇEK:'                ),
+       MAG_MSGNW                => array( 0,    'MSGNW:'                 ),
+       MAG_END                  => array( 0,    '__AZAQ__'               ),
+       MAG_IMG_THUMBNAIL        => array( 1,    'thumbnail', 'thumb'     ),
+       MAG_IMG_RIGHT            => array( 1,    'uñda'                   ),
+       MAG_IMG_LEFT             => array( 1,    'sulda'                  ),
+       MAG_IMG_NONE             => array( 1,    'yuq'                    ),
+       MAG_IMG_WIDTH            => array( 1,    '$1px'                   ),
+       MAG_IMG_CENTER           => array( 1,    'center', 'centre'       ),
+       MAG_IMG_FRAMED           => array( 1,    'framed', 'enframed', 'frame' ),
+       MAG_INT                  => array( 0,    'EÇKE:'                   ),
+       MAG_SITENAME             => array( 1,    'SÄXİFÄİSEME'            ),
+       MAG_NS                   => array( 0,    'İA:'                    ),
+       MAG_LOCALURL             => array( 0,    'URINLIURL:'              ),
+       MAG_LOCALURLE            => array( 0,    'URINLIURLE:'             ),
+       MAG_SERVER               => array( 0,    'SERVER'                 )
+) + $wgMagicWordsEn;
+
+/* private */ $wgAllMessagesTt = array(
+
+# week days, months
+'sunday' => "Yäkşämbe",
+'monday' => "Düşämbe",
+'tuesday' => "Sişämbe",
+'wednesday' => "Çärşämbe",
+'thursday' => "Pänceşämbe",
+'friday' => "Comğa",
+'saturday' => "Şimbä",
+'january' => "Ğínwar",
+'february' => "Febräl",
+'march' => "Mart",
+'april' => "Äpril",
+'may_long' => "May",
+'june' => "Yün",
+'july' => "Yül",
+'august' => "August",
+'september' => "Sentäber",
+'october' => "Öktäber",
+'november' => "Nöyäber",
+'december' => "Dekäber",
+'jan' => "Ğín",
+'feb' => "Feb",
+'mar' => "Mar",
+'apr' => "Äpr",
+'may' => "May",
+'jun' => "Yün",
+'jul' => "Yül",
+'aug' => "Aug",
+'sep' => "Sen",
+'oct' => "Ökt",
+'nov' => "Nöy",
+'dec' => "Dek",
+
+);
+
+class LanguageTt extends LanguageUtf8 {
+
+       function getNamespaces() {
+               global $wgNamespaceNamesTt;
+               return $wgNamespaceNamesTt;
+       }
+
+       function getDateFormats() {
+               global $wgDateFormatsTt;
+               return $wgDateFormatsTt;
+       }
+
+
+       function date( $ts, $adj = false ) {
+               if ( $adj ) { $ts = $this->userAdjust( $ts ); }
+
+               $d = (0 + substr( $ts, 6, 2 )) . ". " .
+                 $this->getMonthAbbreviation( substr( $ts, 4, 2 ) ) . " " .
+                 substr( $ts, 0, 4 );
+               return $d;
+       }
+
+       function time( $ts, $adj = false ) {
+               if ( $adj ) { $ts = $this->userAdjust( $ts ); }
+
+               $t = substr( $ts, 8, 2 ) . ":" . substr( $ts, 10, 2 );
+               return $t;
+       }
+
+       function timeanddate( $ts, $adj = false ) {
+               return $this->date( $ts, $adj ) . ", " . $this->time( $ts, $adj );
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesTt;
+               if( isset( $wgAllMessagesTt[$key] ) ) {
+                       return $wgAllMessagesTt[$key];
+               } else {
+                       return parent::getMessage( $key );
+               }
+       }
+
+       function fallback8bitEncoding() {
+               # Windows codepage 1252 is a superset of iso 8859-1
+               # override this to use difference source encoding to
+               # translate incoming 8-bit URLs.
+               return "windows-1254";
+       }
+}
+
+?>
diff --git a/languages/LanguageUg.php b/languages/LanguageUg.php
new file mode 100644 (file)
index 0000000..07c87c8
--- /dev/null
@@ -0,0 +1,18 @@
+<?php
+/** Uyghur language file ( Oyghurque )
+  *
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+require_once( 'LanguageUtf8.php' );
+
+class LanguageUg extends LanguageUtf8 {
+       #FIXME: inherit almost everything for now
+
+       function isRTL() {
+               return true;
+       }
+}
+
+?>
diff --git a/languages/LanguageUk.php b/languages/LanguageUk.php
new file mode 100644 (file)
index 0000000..5a9e070
--- /dev/null
@@ -0,0 +1,918 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+require_once( 'LanguageUtf8.php' );
+
+/* private */ $wgNamespaceNamesUk = array(
+       NS_MEDIA            => 'Медіа',
+       NS_SPECIAL          => 'Спеціальні',
+       NS_MAIN             => '',
+       NS_TALK             => 'Обговорення',
+       NS_USER             => 'Користувач',
+       NS_USER_TALK        => 'Обговорення_користувача',
+       NS_PROJECT          => $wgMetaNamespace,
+       NS_PROJECT_TALK     => 'Обговорення_' . $wgMetaNamespace,
+       NS_IMAGE            => 'Зображення',
+       NS_IMAGE_TALK       => 'Обговорення_зображення',
+       NS_MEDIAWIKI        => 'MediaWiki',
+       NS_MEDIAWIKI_TALK   => 'Обговорення_MediaWiki',
+       NS_TEMPLATE         => 'Шаблон',
+       NS_TEMPLATE_TALK    => 'Обговорення_шаблону',
+       NS_HELP             => 'Довідка',
+       NS_HELP_TALK        => 'Обговорення_довідки',
+       NS_CATEGORY         => 'Категорія',
+       NS_CATEGORY_TALK    => 'Обговорення_категорії'
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgQuickbarSettingsUk = array(
+       "Не показувати панель", "Фіксована зліва", "Фіксована справа", "Плаваюча зліва"
+);
+
+/* private */ $wgSkinNamesUk = array(
+       'standard' => "Стандартне",
+       'nostalgia' => "Ностальгія",
+       'cologneblue' => "Кельнське Синє"
+) + $wgSkinNamesEn;
+
+
+/* private */ $wgDateFormatsUk = array(
+#      "Немає значення",
+);
+
+
+/* private */ $wgAllMessagesUk = array(
+# User Toggles
+
+"tog-underline" => "Підкреслювати зв'язки",
+"tog-highlightbroken" => "Форматувати неіснуючі зв'язки <a href=\"\" class=\"new\">ось так</a> (Альтернатива: ось так<a href=\"\" class=\"internal\">?</a>).",
+"tog-justify"  => "Вирівнювати параграфи",
+"tog-hideminor" => "Ховати незначні зміни в списку недавніх змін",
+"tog-usenewrc" => "Покращений список недавніх змін (підтримується не всіма браузерами)",
+"tog-numberheadings" => "Автоматично нумерувати заголовки",
+"tog-editondblclick" => "Редагувати статті при подвійному натисканні кнопки миші (JavaScript)",
+"tog-editsection"=>"Редагувати секції по зв'язку [прав.]",
+"tog-editsectiononrightclick"=>"Редагувати секції по правій кнопці миші на назві секції (JavaScript)",
+"tog-showtoc"=>"Показувати зміст (для статей з більше ніж 3-ма заголовками)",
+"tog-rememberpassword" => "Запам'ятовувати пароль між сеансами",
+"tog-editwidth" => "Розширяти вікно для редагування до меж вікна браузера ",
+"tog-watchdefault" => "Слідкувати за новими та зміненими статтями",
+"tog-minordefault" => "Спочатку вважати всі зміни незначними",
+"tog-previewontop" => "Показувати попередній текст до вікна редагування, а не післе",
+"tog-nocache" => "Заборонити кешування статей",
+# Dates
+'sunday' => "неділя",
+'monday' => "понеділок",
+'tuesday' => "вівторок",
+'wednesday' => "середа",
+'thursday' => "четвер",
+'friday' => "п'ятниця",
+'saturday' => "субота",
+'january' => "січень",
+'february' => "лютий",
+'march' => "березень",
+'april' => "квітень",
+'may_long' => "травень",
+'june' => "червень",
+'july' => "липень",
+'august' => "серпень",
+'september' => "вересень",
+'october' => "жовтень",
+'november' => "листопад",
+'december' => "грудень",
+'january-gen' => 'січня',
+'february-gen' => 'лютого',
+'march-gen' => 'березня',
+'april-gen' => 'квітня',
+'may-gen' => 'травня',
+'june-gen' => 'червня',
+'july-gen' => 'липня',
+'august-gen' => 'серпня',
+'september-gen' => 'вересня',
+'october-gen' => 'жовтня',
+'november-gen' => 'листопада',
+'december-gen' => 'грудня',
+'jan' => "січ",
+'feb' => "лют",
+'mar' => "бер",
+'apr' => "квіт",
+'may' => "трав",
+'jun' => "черв",
+'jul' => "лип",
+'aug' => "серп",
+'sep' => "вер",
+'oct' => "жов",
+'nov' => "лист",
+'dec' => "груд",
+
+# Bits of text used by many pages:
+#
+"linktrail"            => "/^([a-z]+)(.*)\$/sD",
+"mainpage"             => "Головна стаття",
+"mainpagetext" => "Програмне забезпечення вікі встановлено.",
+"about"                        => "Про",
+"aboutsite"      => "Про {{SITENAME}}",
+"aboutpage"            => "{{ns:project}}:Про",
+"help"                 => "Довідка",
+"helppage"             => "{{ns:project}}:Довідка",
+"bugreports"   => "Звіт про помилку",
+"bugreportspage" => "{{ns:project}}:Звіт_про_помилку",
+"sitesupport"   => "Sitesupport",
+"faq"                  => "Часті питання",
+"faqpage"              => "{{ns:project}}:Часті питання",
+"edithelp"             => "Довідка про редагування",
+"edithelppage" => "{{ns:project}}:Як_редагувати_статті",
+"cancel"               => "Відмінити",
+"qbfind"               => "Знайти",
+"qbbrowse"             => "Переглянути",
+"qbedit"               => "Редагувати",
+"qbpageoptions" => "Настройки статті",
+"qbpageinfo"   => "Інформація про статтю",
+"qbmyoptions"  => "Ваші настройки",
+"mypage"               => "Ваша особиста сторінка",
+"mytalk"               => "Ваше особисте обговорення",
+"currentevents" => "Поточні події",
+"errorpagetitle" => "Помилка",
+"returnto"             => "Повернутися до $1.",
+"tagline"              => "Матеріал з {{SITENAME}}",
+"whatlinkshere"        => "Статті, що вказують на дану",
+"help"                 => "Довідка",
+"search"               => "Пошук",
+"go"           => "Перейти",
+"history"              => "Старі версії",
+"printableversion" => "Версія для друку",
+"editthispage" => "Редагувати дану статтю",
+"deletethispage" => "Вилучити дану статтю",
+"protectthispage" => "Встановити захист",
+"unprotectthispage" => "Зняти захист",
+"newpage" => "Нова стаття",
+"talkpage"             => "Обговорити статтю",
+"postcomment"   => "Прокоментувати",
+"articlepage"  => "Переглянути статтю",
+"subjectpage"  => "Переглянути тему", # For compatibility
+"userpage" => "Переглянути сторінку користувача",
+"wikipediapage" => "Переглянути мета-сторінку",
+"imagepage" =>         "Переглянути сторінку зображення",
+"viewtalkpage" => "Переглянути обговорення",
+"otherlanguages" => "Іншими мовами",
+"redirectedfrom" => "(Перенаправлено з $1)",
+"lastmodified" => "Остання зміна $1.",
+"viewcount"            => "Цю статтю переглядали $1 разів.",
+"printsubtitle" => "(Матеріал з {{SERVER}})",
+"protectedpage" => "Захищена стаття",
+"administrators" => "{{ns:project}}:Адміністратори",
+"sysoptitle"   => "Необхідний рівень доступу Оператор",
+"sysoptext"            => "Дана дія може бути виконана тільки користувачами з правами \"Оператор\". Див. $1.",
+"developertitle" => "Необхіден рівень доступу Розробник",
+"developertext"        => "Дана дія може бути виконана тільки користувачами з правами \"Розробник\". Див $1.",
+"nbytes"               => "$1 байт(ів)",
+"go"                   => "Перейти",
+"ok"                   => "OK",
+"sitetitle"            => '{{SITENAME}}',
+"sitesubtitle" => "Вільна енциклопедія",
+"retrievedfrom" => "Отримано від \"$1\"",
+"newmessages" => "Ви отримали $1.",
+"newmessageslink" => "нові повідомлення",
+"editsection"=>"ред.",
+"toc" => "Зміст",
+"showtoc" => "показати",
+"hidetoc" => "сховати",
+"thisisdeleted" => "Переглянути або відновити $1?",
+"restorelink" => "$1 змін вилучено",
+
+# Main script and global functions
+#
+"nosuchaction" => "Такої дії не існує",
+"nosuchactiontext" => "Дія, вказана в URL, не розпізнається програмним забезпеченням {{SITENAME}}",
+"nosuchspecialpage" => "Такої спеціальної сторінки не існує",
+"nospecialpagetext" => "Спеціальна сторінка не розпізнається програмним забезпеченням {{SITENAME}}.",
+
+# General errors
+#
+"error"                        => "Помилка",
+"databaseerror" => "Помилка бази даних",
+"dberrortext"  => "Знайдено помилку синтаксису запиту до бази даних.
+Останній запит до бази даних:
+<blockquote><tt>$1</tt></blockquote>
+відбувся з функції \"<tt>$2</tt>\".
+MySQL повернув помилку \"<tt>$3: $4</tt>\".",
+"dberrortextcl" => "Знайдено помилку синтаксису запиту до бази даних.
+Останній запит до бази даних:
+\"$1\"
+відбувся з функції \"$2\".
+MySQL повернув помилку \"$3: $4\".\n",
+"noconnect"            => "Тяжко вибачаємось! В зв'язку з технічними неполадками зараз неможливо зв'язатися з сервером баз даних.",
+"nodb"                 => "Неможливо вибрати базу даних $1",
+"cachederror"  => "Нижче відображена кеш-копія запитаної статті, можливо вона застаріла.",
+"readonly"             => "Запис в базу даних заблоковано",
+"enterlockreason" => "Введіть обґрунтування блокування та інформацію про те, коли блокування буде знято",
+"readonlytext" => "Внесення нових статей та інші зміни бази даних {{SITENAME}} в даний момент заблоковано, ймовірно, через планове сервісне обслуговування бази даних,
+по закінченню якого нормальний стан буде відновлено.
+Заблокувавший адміністратор дав наступні пояснення:
+<p>$1",
+"missingarticle" => "База даних не знайшла текст статті,
+хоча повинна була знайти під іменем \"$1\".
+<p>Це може бути викликано використанням застарілого посилання на журнал змін або відмінностей для статті, що була вилучена.
+<p>Якщо справа не в цьому, то, швидше за все, ви знайшли помилку в програмному забезпеченні {{SITENAME}}.
+Будь-ласка, повідомте про це адміністратору, вказавши URL.",
+"internalerror" => "Внутрішня помилка",
+"filecopyerror" => "Неможливо скопіювати файл \"$1\" в \"$2\".",
+"filerenameerror" => "Неможливо перейменувати файл \"$1\" в \"$2\".",
+"filedeleteerror" => "Неможливо вилучити файл \"$1\".",
+"filenotfound" => "Неможливо знайти файл \"$1\".",
+"unexpected"   => "Неочікуване значення: \"$1\"=\"$2\".",
+"formerror"            => "Помилка: неможливо прийняти форму",
+"badarticleerror" => "Ця дія не може бути виконана над даною статтею.",
+"cannotdelete" => "Неможливо вилучити вказану статтю чи файл. (Можливо, його вже вилучив хтось інший.)",
+"badtitle"             => "Недопустима назва",
+"badtitletext" => "Невірна назва статті, пуста, або невірно вказано міжмовна або між-вікі назва.",
+"perfdisabled" => "Вибачаємося! Ця можливість тимчасово недоступна через обмеженість ресурсів.",
+"perfdisabledsub" => "Це - збережена копія від $1:",
+"viewsource" => "Переглянути початковий текст",
+"protectedtext" => "Ця сторінка була заблокована, щоб не допустити
+зміни; для цього можуть бути різні причини, подивіться будь-ласка
+[[{{ns:project}}:Захищена стаття]].
+
+You can view and copy the source of this page:",
+
+# Login and logout pages
+#
+"logouttitle"  => "Вийти з системи",
+"logouttext"   => "Ви працюєте в тому ж режимі, який був до вашої реєстрації в системі. Ви ідентифікуєтесь не з іменем, а з IP-адресом.
+Ви можете продовжувати використовувати {{SITENAME}} анонімно, або почати новий сеанс як той же самий чи інший користувач.\n",
+
+"welcomecreation" => "<h2>Вітаємо Вас, $1!</h2><p>Ви зареєстровані.
+Не забудьте налаштувати {{SITENAME}} так, як Вам зручно.",
+
+"loginpagetitle" => "Вхід в систему",
+"yourname"             => "Ваше ім'я",
+"yourpassword" => "Ваш пароль",
+"yourpasswordagain" => "Повторний набір пароля",
+"newusersonly" => " (тільки для нових користувачів)",
+"remembermypassword" => "Запам'ятовувати ваш пароль між сеансами.",
+"loginproblem" => "<b>Проблема при вході в систему.</b><br />попробуйте ще раз!",
+"alreadyloggedin" => "<strong>Користувач $1, ви вже ввійшли в систему!</strong><br />\n",
+"login"                        => "Вхід в систему",
+"userlogin"            => "Вхід в систему",
+"logout"               => "Вийти з системи",
+"userlogout"   => "Вийти з системи",
+"notloggedin"  => "Ви не ввійшли в систему",
+"createaccount"        => "Зареєструвати нового користувача",
+"badretype"            => "Введені вами паролі не співпадають.",
+"userexists"   => "Введене вами ім'я користувача вже існує. Виберіть будь-ласка інше ім'я.",
+"youremail"            => "Адреса вашої електронної пошти*",
+"yournick"             => "Ваш псевдонім (для підписів)",
+"emailforlost" => "* Вказувати адресу вашої електронної пошти необов'язково.
+Але це дозволить людям зв’язатися з вами через веб-сайт без інформування їх про адресу вашої електронної пошти,
+а також допоможе вам якщо ви забудете свій пароль.",
+"loginerror"   => "Помилка при вході в систему",
+"noname"               => "Користувача з таким іменем не існує.",
+"loginsuccesstitle" => "Успішний вхід в систему",
+"loginsuccess" => "Тепер ви працюєте в {{SITENAME}} під іменем \"$1\".",
+"nosuchuser"   => "Користувача з таким іменем \"$1\" не існує.
+Перевірте вірність написання, або скористайтеся формою, що нижче, щоб зареєструвати нового користувача.",
+"wrongpassword"        => "Введений вами пароль невірний. Попробуйте ще раз.",
+"mailmypassword" => "Відправити вам новий пароль",
+"passwordremindertitle" => "Пам'ятка пароля {{SITENAME}}",
+"passwordremindertext" => "Хтось (можливо, ви - з IP-адреси $1)
+зробив запит на відправлення вам нового пароля користувача проекту {{SITENAME}}.
+Пароль користувача \"$2\" тепер такий: \"$3\".
+Тепер вам необхідно ввійти в систему й змінити пароль.",
+"noemail"              => "Для користувача \"$1\" не вказано адресу електронної пошти.",
+"passwordsent" => "Новий пароль відправлено на адресу електронної пошти, вказану для \"$1\".
+Будь-ласка, ввійдіть в систему після отримання пароля.",
+
+# Edit pages
+#
+"summary"              => "Короткий опис",
+"subject"              => "Тема/заголовок",
+"minoredit"            => "Це незначна зміна",
+"watchthis"            => "Спостерігати за цією статтею",
+"savearticle"  => "Зберегти статтю",
+"preview"              => "Попередній перегляд",
+"showpreview"  => "Показати попередній варіант",
+"blockedtitle" => "Користувача заблоковано",
+"blockedtext"  => "Ваш користувач чи IP-адреса заблоковані $1.
+Причина блокування:<br />''$2''<p>Ви можете зв'язатися з $1 чи іншим
+[[{{ns:project}}:Администратори|администратором]] що обговорити блокування.
+Зверніть увагу, що ви не можете використовувати функцію \"Надіслати електронного листа користувачу\", якщо ви не вказали адресу вашої електронної пошти в Ваших [[Спеціальні:Настройки|настройках]]
+Ваша IP-адреса - $3. Будь-ласка, вказуйте, якщо будете запитувати про блокування.
+==Зауваження для користувачів America On-Line==
+Через багаторазові акти вандалізму одного з користувачів AOL, {{SITENAME}} часто блокує проксі-сервери AOL. Один й той же сервер може використовуватися різними користувачами, тому, нажаль, невинні користувачі AOL часто бувають _неспеціальне_ заблоковані. Ми вибачаємося за незручності.
+Якщо це відбулося з Вами, відправте, будь-ласка, електронною поштою листа адміністратору. Не забудьте вказати вашу IP-адресу, вказану вище.",
+"newarticle"   => "(Нова)",
+"newarticletext" => "Ви перейшли на статтю, яка поки що не існує.
+Щоб створити нову статтю, наберіть текст в вікні нижче
+(див. [[{{ns:project}}:Довідка|довідкову статтю]] щоб отримати більше інформації).
+Якщо ви опинились тут помилково, просто натисніть кнопку браузера '''назад'''.",
+"anontalkpagetext" => "---- ''Це сторінка обговорення, що належить анонімному користувачу, який ще не зареєструвався або не скористався зареєстрованим ім'ям. Тому ми вимушені використовувати [[IP-адресу]] для його ідентифікації. Одна IP-адреса може використовуватися декількома користувачами. Якщо ви - анонімний користувач і вважаєте, що отримали коментарі, адресовані не вам, будь ласка [[Спеціальні:Вхід_в_систему|зареєструйтесь або ввійдіть в систему як зареєстрований користувач]], щоб в майбутньому уникнути можливої плутанини з іншими анонімними користувачами.'' ",
+"noarticletext" => "(На даний момент текст в цієї статті відсутній)",
+"updated"              => "(Оновлена)",
+"note"                 => "<strong>Зауваження:</strong> ",
+"previewnote"  => "Зверніть увагу, - це тільки попередній перегляд, і текст ще не збережено!",
+"previewconflict" => "Цей попередній перегляд відображає текст з вікна редагування так, як він буде виглядіти, якщо ви вирішите записати його.",
+"editing"              => "Редагування $1",
+"editingsection"       => "Редагування $1 (секція)",
+"editingcomment"       => "Редагування $1 (коментар)",
+"editconflict" => "Конфлікт редакцій: $1",
+"explainconflict" => "Ще хтось змінив цю статтю з того часу, як ви розпочали її змінювати.
+В верхній частині тексту показано, як стаття виглядить зараз. Ваші зміни показані в нижній частині тексту.
+Вам необхідно буде скомпонувати ваші зміни в існуючий текст.
+Якщо ви натиснете \"Зберегти статтю\", то буде збережено <b>тільки</b> текст в верхньому вікні редагування.<br />",
+"yourtext"             => "Ваш текст",
+"storedversion" => "Збережена версія",
+"editingold"   => "<strong>ПОПЕРЕДЖЕННЯ: Ви редагуєте застарівшу версію даної статті.
+Якщо ви збережете її, будь-які редагування, зроблені між версіями, будуть втрачені.</strong>",
+"yourdiff"             => "Відмінності",
+"copyrightwarning" => "Будь ласка, зверніть увагу, що будь-які добавлення
+й зміни в {{SITENAME}} розглядаються як випущені на умовах
+GNU Free Documentation License без незмінюваних секцій
+(див. $1, щоб взнати подробиці).
+Якщо ви не бажаєте, щоб написане вами безжалісно редагувалось
+і розповсюджувалося за бажанням будь-кого, - не пишіть тут.<br />
+
+Ви також зобов'язуєтесь, що написане вами тут належить вам чи взято з джерела,
+що є суспільною власністю чи подібним вільним джерелом.
+<strong>НЕ ПУБЛІКУЙТЕ ТУТ БЕЗ ДОЗВОЛУ ТВОРИ, ЩО Є ОБ'ЄКТОМ АВТОРСКОГО ПРАВА,
+Й ЛІЦЕНЗІЯ ЯКИХ НЕ ДОЗВОЛЯЄ ПОДІБНОЇ ПУБЛІКАЦІЇ!</strong>",
+"longpagewarning" => "<strong>ПОПЕРЕДЖЕННЯ: Довжина цієї статті $1 кілобайт; статті, розмір яких перевищує 32кб. можуть створювати проблеми для деяких браузерів.
+Розгляньте, будь-ласка, варіанти розбиття статті на менші частини.</strong>",
+"readonlywarning" => "<strong>ПОПЕРЕДЖЕННЯ: База даних заблокована в зв’язку з процедурами обслуговування,
+тому ви не можете записати ваші зміни в даний момент.
+Можливо, вам варто зберегти текст в локальний файл (на свому диску) й записати його в {{SITENAME}} пізніше.</strong>",
+"protectedpagewarning" => "<strong>ПОПЕРЕДЖЕННЯ: Ця стаття заблокована, так що тільки користувачі с правом
+Сисоп можуть змінювати її. Будь-ласка, перегляньте
+[[Project:Правила захисту статей'>правила захисту статей]].</strong>",
+
+# History pages
+#
+"revhistory"   => "Журнал редагувань",
+"nohistory"            => "Для цієї статті відсутній журнал редагувань.",
+"revnotfound"  => "Версію не знайдено",
+"revnotfoundtext" => "Неможливо знайти необхідну вам версію статті.
+Будь-ласка, перевірте правильність URL, який ви використовували для доступу до цієї статті.\n",
+"loadhist"             => "Завантаження журналу редагувань статті",
+"currentrev"   => "Поточна версія",
+"revisionasof" => "Версія $1",
+"cur"                  => "поточн.",
+"next"                 => "наст.",
+"last"                 => "ост.",
+"orig"                 => "ориг.",
+"histlegend"   => "Пояснення: (поточн.) = відмінності від поточної версії,
+(ост.) = відмінності від попередньої версії, M = незначне редагування",
+
+# Diffs
+#
+"difference"   => "(відмінності між версіями)",
+"loadingrev"   => "завантаження версії для розрізнення",
+"lineno"               => "Рядок $1:",
+"editcurrent"  => "Редагувати поточну версію поточної статті",
+
+# Search results
+#
+"searchresults" => "Результати пошуку",
+"searchresulttext" => "Для отримання детальнішої інформації про пошук в {{SITENAME}}, див. [[Project:Пошук|Пошук в {{SITENAME}}]].",
+"searchquery"  => "На запит \"$1\"",
+"badquery"             => "Невірно зфомульований запит",
+"badquerytext" => "Неможливо обробити ваш запит.
+Можливо, причина в тому, що ви намагались знайти слово, яке коротше трьох букв, що поки-що не підтримується.
+Можливо також, що ви допустили опечатку в запиті.
+Попробуйте інший запит.",
+"matchtotals"  => "Запиту \"$1\" відповідає(ють) $2 назва(и) статті(ей) й тексти $3 статті(ей).",
+"nogomatch" => "Статті з такою назвою не існує, проводиться пошук по всьому тексту. ",
+"titlematches" => "Збіг в назвах статей",
+"notitlematches" => "Немає збігу в назвах статей",
+"textmatches"  => "Збіг в текстах статей",
+"notextmatches"        => "Немає збігу в текстах статей",
+"prevn"                        => "попередня $1",
+"nextn"                        => "наступна $1",
+"viewprevnext" => "Переглянути ($1) ($2) ($3).",
+"showingresults" => "Нижче показано <b>$1</b> результатів, починаючи з #<b>$2</b>.",
+"showingresultsnum" => " Нижче показано <b>$3</b> результатів, починаючи з #<b>$2</b>.",
+"nonefound"            => "<strong>Зауваження:</strong>: До невдалого пошуку часто може приводити спроба знайти загальні слова, які не підлягають індексації, наприклад - \"також\" and \"що\", або використання більш ніж одного ключового для пошуку слова (показуються тільки статті, що містять всі вказані для пошуку слова).",
+"powersearch" => "Пошук",
+"powersearchtext" => "
+Пошук в просторі імен :<br />
+$1<br />
+$2 Показувати перенаправлення   Пошук на $3 $9",
+"searchdisabled" => "<p>Повнотекстовий пошук тимчасово недоступний через перевантаження сервера; передбачається, що ця функція буде знову включена після установки нового обладнання. Поки що ми пропонуємо вам скористатися пошуковою машиною google:</p>",
+"blanknamespace" => "(Основне)",
+
+# Preferences page
+#
+"preferences"  => "Настройки",
+"prefsnologin" => "Ви не ввійшли в систему",
+"prefsnologintext"     => "Ви повинні [[Спеціальні:Вхід_в_систему|ввійти в систему]]
+щоб змінити настройки користувача.",
+"prefslogintext" => "Ви ввійшли в систему як \"$1\".
+Ваш внутрішній ідентифікаційний номер - $2.
+
+Див. [[{{ns:project}}:Допомога по настройкам]] що розібратися з настройками.",
+"prefsreset"   => "Настройки були повернуті в стандартний стан.",
+"qbsettings"   => "Настройки панелі навігації",
+"changepassword" => "Змінити пароль",
+"skin"                 => "Оформлення",
+"math"                 => "Відображення математики",
+"dateformat"   => "Формат дати",
+"math_failure"         => "Неможливо розібрати вираз",
+"math_unknown_error"   => "невідома помилка",
+"math_unknown_function"        => "невідома функція ",
+"math_lexing_error"    => "лексична помилка",
+"math_syntax_error"    => "синтаксична помилка",
+"saveprefs"    => "Зберегти настройки",
+"resetprefs"   => "Встановити стандартні настройки",
+"oldpassword"  => "Старий пароль",
+"newpassword"  => "Новий пароль",
+"retypenew"            => "Повторіть ввід нового пароля",
+"textboxsize"  => "Розміри поля вводу",
+"rows"                 => "Рядків",
+"columns"              => "Стовпчиків",
+"searchresultshead" => "Настройки для результатів пошуку",
+"resultsperpage" => "Кількість результатів на сторінку",
+"contextlines" => "Кількість рядків на результат",
+"contextchars" => "Кількість символів контексту на рядок",
+"stubthreshold" => "Поріг визначення заглушки",
+"recentchangescount" => "Кількість заголовків статей на сторінці нових редагувань",
+"savedprefs"   => "Ваші настройки збережено.",
+"timezonetext" => "Введіть зміщення (в годинах) вашого місцевого часу
+від часу сервера (UTC - по Гринвічу).",
+"localtime"    => "Місцевий час",
+"timezoneoffset" => "Зміщення",
+"servertime"   => "Час сервера",
+"guesstimezone" => "Заповнити з браузера",
+"emailflag"            => "Не приймати електронні листи від інших користувачів",
+"defaultns"            => "По замовчанню, шукати в таких просторах імен:",
+
+# Recent changes
+#
+"changes" => "редагування",
+"recentchanges" => "Нові редагування",
+# This is the default text, and can be overriden by editing [[{{ns:project}}::Recentchanges]]
+"recentchangestext" => "На цій сторінці представлені останні редагування в {{SITENAME}}.",
+"rcloaderr"            => "Завантаження нових редагувань",
+"rcnote"               => "Нижче відображені останні <strong>$1</strong> редагувань за останні(й) <strong>$2</strong> день(і,ів).",
+"rcnotefrom"   => "Нижче відображені редагування з <b>$2</b> (до <b>$1</b>).",
+"rclistfrom"   => "Показати редагування починаючи з $1",
+# "rclinks"            => "Show last $1 changes in last $2 hours / last $3 days",
+# "rclinks"            => "Show last $1 changes in last $2 days.",
+"rclinks"              => "Показати останні $1 редагування за останні(й) $2 день(і,ів); $3 незначних редагувань.",
+"rchide"               => "в формі $4; $1 незначних редагувань; $2 вторинних(і) просторів імен; $3 множинних редагувань.",
+"rcliu"                        => "; $1 редагувань, зроблених користувачами зареєстрованими в системі",
+"diff"                 => "різн.",
+"hist"                 => "журнал",
+"hide"                 => "сховати",
+"show"                 => "показати",
+"tableform"            => "таблиця",
+"listform"             => "список",
+"nchanges"             => "$1 редагування(ь)",
+"minoreditletter" => "М",
+"newpageletter" => "Н",
+
+# Upload
+#
+"upload"               => "Завантажити файл",
+"uploadbtn"            => "Завантажити файл",
+"uploadlink"   => "Завантажити зображення",
+"reupload"             => "Завантажити повторно",
+"reuploaddesc" => "Повернутися до форми завантаження.",
+"uploadnologin" => "Ви не ввійшли в систему",
+"uploadnologintext"    => "Ви повинні [[Спеціальні:Вхід_в_систему|ввійти в систему,]]
+щоб завантажувати файли.",
+"uploaderror"  => "Помилка завантаження файлу",
+"uploadtext"   => "'''СТІЙ!''' До того як почати завантажувати файли, переконайтесь, що ви прочитали й дієте відповідно
+[[Project:Правила_використання_зображеннь|правилам використання зображень {{SITENAME}}]].
+
+Якщо файл з вказаним вами іменем вже існує
+в {{SITENAME}}, то він буде замінений без попередження.
+Тому, якщо ви не збираєтесь обновляти файл,
+було б непогано перевірити, чи існує вже
+такий файл.
+
+Щоб переглянути раніше завантажені файли,
+зайдіть на: [[Спеціальні:Список зображень|список завантажених зображень]].
+Завантаження й вилучення відображаються в
+[[Project:Журнал завантажень|журналі завантажень]].
+
+Використовуйте відображену нижче форму завантаження нових файлів зображень, що ілюструють ваші статті.
+В більшості браузерів появиться кнопка \"Переглянути...\", натиснувши яку ви можете викликати стандартний діалог
+відкриття файлів операційної системи.
+Вибір фалу призводить до заповнення текстового поля після кнопки.
+Ви також повинні встановити галочку, що підтверджеє, що ви не порушуєте авторських прав завантажуючи цей файл.
+Нтисніть кнопку \"Завантажити\", щоб провести завантаження.
+Завагтаження може тривати деякий час, якщо у вас повільне інтернет-з'єднання.
+
+Перевагу бажано надавати наступним форматам; JPEG - для фотографій, PNG -
+для малюнків и невеликих зображень, OGG - для звуків та музики.
+Будь-ласка, щоб попередити виникнення путанини, називайте ваші файли відповідно до їх змісту.
+Для включення зображення в статтю, використовуйте ссилки такого вигляду:
+'''<nowiki>[[зображення:file.jpg]]</nowiki>''' або '''<nowiki>[[зображення:file.png|альтернативний текст]]</nowiki>'''
+або '''<nowiki>[[звук:file.ogg]]</nowiki>''' для звуків.
+
+Будь-ласка, зверніть увагу, що аналогічно текстам статей {{SITENAME}}, інші можуть редагувати чи вилучати завантажені вами файли, якщо вони вважають, що це покращить енциклопедію, а ви можете бути заблоковані, якщо ваші дії шкодять системі.",
+"uploadlog"            => "журнал завантажень",
+"uploadlogpage" => "Журнал_завантажень",
+"uploadlogpagetext" => "Нижче представлено список найновіших завантажень файлів.
+Скрізь використовується час сервера (по Гринвічу, UTC).
+<ul>
+</ul>
+",
+"filename"             => "Назва файлу",
+"filedesc"             => "Опис файлу",
+"copyrightpage" => "{{ns:project}}:Авторське право",
+"copyright"    => "Зміст надається згідно з $1.",
+"copyrightpagename" => "Авторські права в {{SITENAME}}",
+"uploadedfiles"        => "Завантажені файли",
+"ignorewarning"        => "Ігнорувати попередження й все одно записати файл.",
+"minlength"            => "Назва зображення повинна містити хоча б три символи.",
+"badfilename"  => "Назву зображення було змінено на \"$1\".",
+"badfiletype"  => "\".$1\" не є рекомендованим форматом для файлів зображень.",
+"largefile"            => "Рекомендується використовувати файли зображень, розмір яких меньший 100 кілобайт.",
+"successfulupload" => "Завантаження успішно завершено",
+"fileuploaded" => "Файл \"$1\" успішно завантажено.
+Будь-ласка, перейдіть за наступним посиланням: ($2) до сторінки з описом і внесіть наступну інформацію про файл: джерело файлу, коли й ким він був створений, та іншу інформацію про цей файл.",
+"uploadwarning" => "Попередження",
+"savefile"             => "Зберегти файл",
+"uploadedimage" => "завантажено \"[[$1]]\"",
+"uploaddisabled" => "Вибачте, можливість завантаження на даний сервер відключена.",
+
+# Image list
+#
+"imagelist"            => "Список зображень",
+"imagelisttext"        => "Нижче відображено список з $1 зображень, відсортованих $2.",
+"getimagelist" => "отримання списку зображень",
+"ilsubmit"             => "Шукати",
+"showlast"             => "Показати останні $1 зображень, відсортованих $2.",
+"byname"               => "за назвою",
+"bydate"               => "за датою",
+"bysize"               => "за розміром",
+"imgdelete"            => "вилуч.",
+"imgdesc"              => "опис",
+"imglegend"            => "Пояснення: (опис) = показати/змінити опис зображення.",
+"imghistory"   => "Журнал зображення",
+"revertimg"            => "відкот.",
+"deleteimg"            => "вилуч.",
+"deleteimgcompletely"          => "вилуч.",
+"imghistlegend" => "Пояснення: (поточ.) = це - поточне зображення, (вилуч.) = вилучити цю стару версію, (відкот.) = відкотитися до цієї старої версії.
+<br /><i>Виберіть дату, щоб переглянути список зображень, звантажених на цю дату</i>.",
+"imagelinks"   => "Посилання зображення",
+"linkstoimage" => "Наступні статті посилаються на дане зображення:",
+"nolinkstoimage" => "Статті, що посилаються на дане зображення, відсутні.",
+
+# Statistics
+#
+"statistics"   => "Статистика",
+"sitestats"            => "Статистика сайту",
+"userstats"            => "Статистика користувачів",
+"sitestatstext" => "Загалом в базі даних <b>$1</b> статей.
+Сюди входять сторінки \"обговорень\", статті про {{SITENAME}}, мінімальні статті-\"заглушки\", перенаправлення, та інші сторінки, які, можливо, не повинні розглядатися як статті.
+За виключенням них, є <b>$2</b> сторінок, які, швидше за все, повноцінні статті.<p>
+Всього зроблено <b>$3</b> переглядів та <b>$4</b> редагувань статей
+з моменту обновлення програмного забезпечення (20 липня 2002).
+Таким чином, в середньому на одну статтю припадає <b>$5</b> редагувань та <b>$6</b> переглядів на одне редагування.",
+"userstatstext" => "Зареєструвалося <b>$1</b> користувачів, з яких
+<b>$2</b> - адміністратори (див. $3).",
+
+# Maintenance Page
+#
+"maintenance"          => "Сторінка обслуговування",
+"maintnancepagetext"   => "На цій сторінці є декілька зручних інструментів для щоденного обслуговування. Деякі з цих функцій сильно перевантажують базу даних, тому, не перезагружайте сторінку після кожного редагування ;-)",
+"maintenancebacklink"  => "Повернутися на сторінку обслуговування",
+"disambiguations"      => "Багатозначні статті",
+"disambiguationspage"  => "{{ns:project}}:Посилання_на_багатозначні_статті",
+"disambiguationstext"  => "Наступна статті посилаються на <i>багатозначні статті</i>. Замість цього вони повинні вказувати на відповідну конкретну статтю.<br />Стаття вважається багатозначною, якщо на неї вказує $1.<br />Посилання з інших просторів імен тут <i>не</i> вказані.",
+"doubleredirects"      => "Подвійні перенаправлення",
+"doubleredirectstext"  => "<b>Увага:</b> Цей список може містити невірні елементи. Це значить, що після першої директиви #REDIRECT йде додатковий текст з посиланнями.<br />\nКожен рядок містить посилання на перше та друге перенаправлення, а також перший рядок тексту другого перенаправлення, що, звичайно, містить \"реальне\" перенаправленне на необхідну статтю, куди повинно вказувати й перше перенаправленне.",
+"brokenredirects"      => "Розірвані перенаправлення",
+"brokenredirectstext"  => "Наступні перенаправлення вказують на неіснуючі статті.",
+"selflinks"            => "Статті, що вказують самі на себе",
+"selflinkstext"                => "Наступні статті містять посилання на себе, чого не повинно бути.",
+"mispeelings"           => "Статті з орфографічними помилками",
+"mispeelingstext"               => "Наступні статті містять орфографічні помилки, що часто зустрічаються. Вони перераховані в статті $1. Повинно бути вказано вірне написання (наприклад так).",
+"mispeelingspage"       => "Список орфографічних помилок, що часто зустрічаються",
+"missinglanguagelinks"  => "Відсутні мовні посилання",
+"missinglanguagelinksbutton"    => "Знайти відсутні мовні посилання для такої мови",
+"missinglanguagelinkstext"      => "Ці статті <i>не</i> мають посилань на аналогічні мовою $1. Перенаправлення та вкладені статті<i>не</i> показано.",
+
+
+# Miscellaneous special pages
+#
+"orphans"              => "Статті-сироти",
+"lonelypages"  => "Статті-сироти",
+"unusedimages" => "Зображення, що не використовуються",
+"popularpages" => "Популярні статті",
+"nviews"               => "$1 переглядів",
+"wantedpages"  => "Необхідні статті",
+"nlinks"               => "$1 посилань",
+"allpages"             => "Всі статті",
+"randompage"   => "Випадкова стаття",
+"shortpages"   => "Короткі статті",
+"longpages"            => "Довгі статті",
+"listusers"            => "Список користувачів",
+"specialpages" => "Спеціальні сторінки",
+"spheading"            => "Спеціальні сторінки",
+"protectpage"  => "Захищена стаття",
+"recentchangeslinked" => "Пов'язані редагування",
+"rclsub"               => "(на статті, посилання на які є на \"$1\")",
+"debug"                        => "Відладка",
+"newpages"             => "Нові статті",
+"ancientpages"         => "Самі старі статті",
+"movethispage" => "Перемістити її",
+"unusedimagestext" => "<p>Будь-ласка, врахуйте, що інші веб-сайти (подібно інших мовних розділів {{SITENAME}}) можуть використовувати пряме посилання (URL) на це зображення, і тому зображення може активно використовуватися не дивлячись на його присутність в цьому списку.",
+"booksources"  => "Джерела книг",
+"booksourcetext" => "Нижче наведено список посилань на інші веб-сайти, де продаються нові та такі, що були використуванні книги, а також там  може бути інформація про книги, які ви шукаєте.
+{{SITENAME}} ніяк не зв’язані з будь-якими з них, і цей список не може розглядатися як їх підтримка.",
+"alphaindexline" => "від $1 до $2",
+
+# Email this user
+#
+"mailnologin"  => "Відсутня адреса для відправки",
+"mailnologintext" => "Ви повинні [[Спеціальні:Вхід_в_систему|ввійти в систему]]
+й мати адресу електронної пошти в ваших [[Спеціальні:Настройки|настройках]],
+щоб мати можливість відправляти електронну пошту іншим користувачам.",
+"emailuser"            => "Відправити електронного листа цьому користувачу",
+"emailpage"            => "Відправити електронного листа користувачу",
+"emailpagetext"        => "Якщо цей користувач вказав справжню адресу електронної пошти в своїх настройках, то заповнивши наведену нижче форму, можна відправити йому повідомлення.
+Електронна адреса, яку ви вказали в своїх настройках, буде вказана в полі \"Від кого\" листа, тому отримувач буде мати можливість відповісти.",
+
+"noemailtitle" => "Відсутня адреса електронної пошти",
+"noemailtext"  => "Цей користувач не вказав справжньої адреси електронної пошти, або вказав, що не бажає отримувати листи від інших користувачів.",
+"emailfrom"            => "Від кого",
+"emailto"              => "Кому",
+"emailsubject" => "Тема листа",
+"emailmessage" => "Повідомлення",
+"emailsend"            => "Відіслати",
+"emailsent"            => "Електронне повідомлення відіслано",
+"emailsenttext" => "Ваше електронне повідомлення відіслано.",
+
+# Watchlist
+#
+"watchlist"            => "Ваш список спостереження",
+"watchlistsub" => "(для користувача \"$1\")",
+"nowatchlist"  => "Ваш список спостереження пустий.",
+"watchnologin" => "Ви не ввійшли в систему",
+"watchnologintext"     => "Ви повинні [[Спеціальні:Реєстрація|ввійти в систему]],
+щоб змінювати список спостереження.",
+"addedwatch"   => "Добавлена в список спостереження",
+"addedwatchtext" => "Стаття \"$1\" добавлена в ваш <a href=\"" .
+  "{{localurle:Спеціальні:Список_спостереження}}\">список спостереження</a>.
+Наступні редагування цієї статті й пов'язані з нею дискусії будуть відображатися тут,
+а також будуть відображатися <b>жирним шрифтом</b> на сторінці з <a href=\"" .
+  "{{localurle:Спеціальні:Останні_редагування}}\">списком останніх редагувань</a>, щоб їх було
+легше помітити.</p>
+
+<p>Якщо пізніше ви захочете вилучити статтю з свого списку спостереження, виберіть \"Відмінити спостереження\" в списку інструментів.",
+"removedwatch" => "Вилучена з списку спостереження",
+"removedwatchtext" => "Стаття \"$1\" була вилучена з вашого списку спостереження.",
+"watchthispage"        => "Спостерігати за нею",
+"unwatchthispage" => "Відмінити спостереження",
+"notanarticle" => "Не стаття",
+"watchnochange" => "За вказаний період в статтях з списку спостереження нічого не змінено.",
+"watchdetails" => "($1 статей, за якими ведеться спостереження, не враховуючи сторінок обговорення;
+$2 всього змінено статей після відсічки;
+$3...
+[$4 показати й відредагувати повний список].)",
+"watchmethod-recent" => "перегляд останніх редагувань статей за якими ведеться спостереження",
+"watchmethod-list" => "перегляд статей за якими ведеться спостереження",
+"removechecked" => "Вилучити вибрані елементи зі списку спостереження",
+"watchlistcontains" => "Ваш список спостереження містить $1 статей.",
+"watcheditlist" => "Нижче відображено алфавітний список статей за якими ви спостерігаєте.
+Відмітьте статті, які ви хочете вилучити з вашого
+списку спостереження й натисніть кнопку 'вилучити вибрані'
+внизу екрану.",
+"removingchecked" => "Вилучення вибраних елементів зі списку спостереження...",
+"couldntremove" => "Неможливо вилучити елемент '$1'...",
+"iteminvalidname" => "Проблема з елементом '$1', недопустиме назва...",
+"wlnote" => "Нище наведено останні $1 редагувань за останні <b>$2</b> годин.",
+
+
+# Delete/protect/revert
+#
+"deletepage"   => "Вилучити статтю",
+"confirm"              => "Підтвердження",
+"excontent" => "зміст: '$1'",
+"exbeforeblank" => "зміст до очистки: '$1'",
+"exblank" => "стаття була пуста",
+"confirmdelete" => "Підтвердити вилучення",
+"deletesub"            => "(\"$1\" вилучається)",
+"historywarning" => "Попередження: Стаття, яку ви збираєтеся вилучити, має журнал редагувань: ",
+"confirmdeletetext" => "Ви ось-ось назавжди вилучите статтю чи файл і всі її журнали редагувань з бази даних.
+Будь-ласка, підтвердіть, що ви бажаєте зробити це, що ви повністю розумієте наслідки й що ви робите це в відповідності з
+[[{{ns:project}}:Правила|правилами {{SITENAME}}]].",
+"actioncomplete" => "Дію виконано",
+"deletedtext"  => "\"$1\" було вилучено.
+Див. $2 для перегляду списку останніх вилучень.",
+"deletedarticle" => "вилучено \"$1\"",
+"dellogpage"   => "Список_вилучень",
+"dellogpagetext" => "Нижче наведено список самих свіжих вилучень.
+Всюди використовується час сервера (по Гринвічу, UTC).
+<ul>
+</ul>
+",
+"deletionlog"  => "список вилучень",
+"reverted"             => "Відновлено з старої версії",
+"deletecomment"        => "Причина вилучення",
+"imagereverted" => "Повернення до молодшої версії проведено.",
+"rollback"             => "Відкинути редагування",
+"rollbacklink" => "відкинути",
+"cantrollback" => "Неможливо відкинути редагування; останній хто редагував є єдиним автором цієї статті.",
+"rollbackfailed" => "Відкинути зміни не вдалося",
+"alreadyrolled"        => "Неможливо відкинути останні редагування [[$1]],
+зроблені [[User:$2|$2]] ([[User talk:$2|Talk]]); хтось інший вже змінив чи відкинув редагування цієї статті.
+Остані редагування зробив [[User:$3|$3]] ([[User talk:$3|Talk]]). ",
+#   only shown if there is an edit comment
+"editcomment" => "Редагування прокоментовано так: \"<i>$1</i>\".",
+"revertpage"   => "Відкинуть всі редагування до зробленого $1",
+"protectlogpage" => "Журнал_захисту",
+"protectlogtext" => "Нижче наведено список установок й зняття захисту з сторінки.
+Додаткова інформація: [[{{ns:project}}:Захищена стаття]].",
+"protectedarticle" => "захист на [[$1]] встановлено",
+"unprotectedarticle" => "захист з [[$1]] знято",
+
+# Undelete
+"undelete" => "Відновити вилучену статтю",
+"undeletepage" => "Переглянути й відновити вилучені статті",
+"undeletepagetext" => "Наступні статті було вилучено, але вони ще в архіві і тому можуть бути відновлені. Архів періодично очищається.",
+"undeletearticle" => "Відновити вилучену статтю",
+"undeleterevisions" => "В архіві $1 версій",
+"undeletehistory" => "Якщо ви відновите статтю, всі версії будуть також відновлені, разом з журналом редагувань.
+Якщо з моменту вилучення було створено статтю з такою ж назвою, відновлені версії будуть вказані в журналі редагувань перед новими записами, але поточна версія існуючої статті не буде замінена автоматично.",
+"undeleterevision" => "Вилучена версія від $1",
+"undeletebtn" => "Відновити!",
+"undeletedarticle" => "\"$1\" відновлена",
+"undeletedtext"   => "Статтю [[$1]] було відновлено.
+Див. [[{{ns:project}}:Список_вилучень]] щоб переглянути список останніх вилучень та відновлень.",
+
+# Contributions
+#
+"contributions"        => "Вклад користувача",
+"mycontris" => "Ваш вклад",
+"contribsub"   => "Для $1",
+"nocontribs"   => "Редагувань, що задовольняють заданим умовам не знайдено.",
+"ucnote"               => "Нижче наводяться останні <b>$1</b> редагувань, зроблених цим користувачем за останні <b>$2</b> дні.",
+"uclinks"              => "Переглянути $1 останніх редагувань; за останні $2 дні.",
+"uctop"                => " (наверху)" ,
+
+# What links here
+#
+"whatlinkshere"        => "Посилання на неї",
+"notargettitle" => "Не вказана ціль",
+"notargettext" => "Ви не вказали цільову статтю чи користувача, для яких необхідно виконати цю функцію.",
+"linklistsub"  => "(Список посилань)",
+"linkshere"            => "Ці статті вказують сюди:",
+"nolinkshere"  => "Сюди не вказує жодна стаття.",
+"isredirect"   => "сторінка-перенаправлення",
+
+# Block/unblock IP
+#
+"blockip"              => "Заблокувати IP-адресу",
+"blockiptext"  => "Використовуйте форму що нижче, щоб заблокувати можливість збереження з вказаної IP-адреси.
+Це може бути зроблене виключно для попередження вандалізму і тільки в відповідності до
+[[{{ns:project}}:Правила|правил {{SITENAME}}]].
+Нище вкажіть конкретную причину (наприклад, процитуйте деякі статті з ознаками вандалізму).",
+"ipaddress"            => "IP-адреса/Імя користувача",
+"ipbreason"            => "Причина",
+"ipbsubmit"            => "Заблокувати доступ цьому користувачу ",
+"badipaddress" => "Користувача з таким іменем не існує.",
+"blockipsuccesssub" => "Блокування проведено",
+"blockipsuccesstext" => "\"$1\" заблоковано.
+<br />См. [[Спеціальні:Список_заблокованих_IP|список заблокованих IP]] щоб взнати, які IP-адреси заблоковані.",
+"unblockip"            => "Розблокувати IP-адресу",
+"unblockiptext"        => "Використовуйте форму що нижче, щоб відновити можливість збереження раніше заблокованої
+IP-адреси.",
+"ipusubmit"            => "Розблокувати цю адресу",
+"ipusuccess"   => "\"$1\" розблоковано",
+"ipblocklist"  => "Список заблокованих IP-адрес й користувачів",
+"blocklistline"        => "$1, $2 заблоковано $3 ($4)",
+"blocklink"            => "заблокувати",
+"unblocklink"  => "розблокувати",
+"contribslink" => "вклад",
+"autoblocker"  => "Доступ заблоковано автоматично, тому що ви використовуєте ту ж адресу, що і \"$1\". Причина: \"$2\".",
+
+# Developer tools
+#
+"lockdb"               => "Заблокувати базу даних (режим \"тільки для читання\")",
+"unlockdb"             => "Розблокувати базу даних",
+"lockdbtext"   => "Блокування бази даних унеможливить редагування статей, настройок, списків спостереження та
+виконувати інші дії, що вимагають доступу до бази даних.
+Будь-ласка, підтвердіть, що це - саме те, що ви хочете зробити, і що ви відміните блокування коли закінчите обслуговування бази даних.",
+"unlockdbtext" => "Разблокування бази даних надасть можливість знову
+редагувати статті, настройки, списки спостереження та виконувати інші дії, що вимагають доступу до бази даних.
+Будь-ласка, підтвердіть, що це - саме те, що ви хочете зробити.",
+"lockconfirm"  => "Так, я дійсно хочу заблокувати базу даних (перейти в режим ''тільки для читання'').",
+"unlockconfirm"        => "Так, я дійсно хочу розблокувати базу даних.",
+"lockbtn"              => "Заблокувати базу даних (режим ''тільки для читання'')",
+"unlockbtn"            => "Розблокувати базу даних",
+"locknoconfirm" => "Ви не поставили галочку в поле підтвердження.",
+"lockdbsuccesssub" => "Базу даних заблоковано",
+"unlockdbsuccesssub" => "Базу даних розблоковано",
+"lockdbsuccesstext" => "Базу даних {{SITENAME}} заблоковано.
+<br />Не забудьте її розблокувати після завершення обслуговування.",
+"unlockdbsuccesstext" => "Базу даних {{SITENAME}} розблоковано.",
+
+# Move page
+#
+"movepage"             => "Перемістити статтю",
+"movepagetext" => "За допомогою форми що нижче, ви можете перейменувати статтю, одночасно перемістивши на нове місце і журнал її редагувань.
+Стаття з старою назвою стане перенаправленням на нову статтю.
+Посилання на стару назву не будуть змінені; обов'язково
+[[Спеціальні:Обслуговування|перевірте]], що не з'явилося подвійних чи розірваних перенаправлень.
+Ви відповідаєте за те, щоб переконатися, що посилання далі вказують туди,
+куди припускалося.
+
+Зверніть увагу, що стаття '''не''' буде переміщена, якщо стаття
+з новою назвою вже існує, якщо тільки вона не пуста і не є
+перенаправленням, а журнал її редагувань порожній. Це означає, що ви
+можете повернути статті стару назву, якщо ви перейменували її
+помилково, але ви не можете затерти існуючу статтю.
+
+<b>ПОПЕРЕДЖЕННЯ!</b>
+
+Дана дія може стати причиною серйозних та неочікуваних змін популярних статей;
+будь-ласка, перед продовженням переконайтесь, що ви впевнені й розумієте можливі наслідки.",
+"movepagetalktext" => "Приєднана сторінка обговорення, якщо така існує,
+також буде автоматично переміщена, '''крім наступних випадків:'''
+*Ви переміщаєте статтю з одного простору імен в інший,
+*Непуста сторінка обговорення з таким іменем вже існує, або
+*Ви не поставили галочку в полі, що нижче.
+
+В цих випадках, ви будете вимушені перемістити чи об'єднати статті вручну,
+якщо це потрібно.",
+"movearticle"  => "Перемістити статтю",
+"movenologin"  => "Ви не ввійшли в систему",
+"movenologintext" => "Ви повинні ввійти в систему [[Спеціальні:Вхід_в_систему]]
+щоб перемістити статтю.",
+"newtitle"             => "Нова назва",
+"movepagebtn"  => "Перемістити статтю",
+"pagemovedsub" => "Переміщення виконано",
+"pagemovedtext" => "Назва статті \"[[$1]]\" змінено на \"[[$2]]\".",
+"articleexists" => "Сторінка з такою назвою вже існує, або
+вибрана вами назва недопустима.
+Будь-ласка, виберіть іншу назву.",
+"talkexists"   => "Стаття була перейменована, але сторінка обговорення
+не може бути переміщена, бо сторінка з такаю назвою вже
+існує. Будь-ласка, об'єднайте їх вручну.",
+"movedto"              => "тепер називається",
+"movetalk"             => "Перемістити також і сторінку обговорення , якщо це можливо.",
+"talkpagemoved" => "Відповідна сторінка обговорення також переміщена.",
+"talkpagenotmoved" => "Відповідна сторінка обговорення <strong>не</strong> переміщена.",
+
+# Math
+
+'mw_math_png' => "Завжди генерувати PNG",
+'mw_math_simple' => "HTML в простих випадках, інакше PNG",
+'mw_math_html' => "HTML якщо можливо, інакше PNG",
+'mw_math_source' => "Залишити в вигляді ТеХ (для текстових браузерів)",
+'mw_math_modern' => "Рекомендовано для сучасних браузерів",
+
+);
+
+class LanguageUk extends LanguageUtf8 {
+
+       function getNamespaces() {
+               global $wgNamespaceNamesUk;
+               return $wgNamespaceNamesUk;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsUk;
+               return $wgQuickbarSettingsUk;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesUk;
+               return $wgSkinNamesUk;
+       }
+
+       function getDateFormats() {
+               global $wgDateFormatsUk;
+               return $wgDateFormatsUk;
+       }
+
+       function getMonthNameGen( $key ) {
+               global $wgMonthNamesGenEn;
+               return wfMsg( $wgMonthNamesGenEn[$key-1] );
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesUk;
+               if( isset( $wgAllMessagesUk[$key] ) ) {
+                       return $wgAllMessagesUk[$key];
+               } else {
+                       return parent::getMessage( $key );
+               }
+       }
+
+       function fallback8bitEncoding() {
+               return "windows-1251";
+       }
+
+       function formatNum( $number ) {
+               global $wgTranslateNumerals;
+               return $wgTranslateNumerals ? strtr($number, '.,', ',.' ) : $number;
+       }
+
+}
+
+?>
diff --git a/languages/LanguageUr.php b/languages/LanguageUr.php
new file mode 100644 (file)
index 0000000..5d9d60e
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+# Stub for Urdu
+
+require_once( "LanguageUtf8.php" );
+
+class LanguageUr extends LanguageUtf8 {
+
+       function getDefaultUserOptions() {
+               $opt = parent::getDefaultUserOptions();
+               $opt["quickbar"] = 2; # Right-to-left
+               $opt["underline"] = 0; # Underline is hard to read in Arabic script
+               return $opt;
+       }
+
+       # For right-to-left language support
+       function isRTL() {
+               return true;
+       }
+}
+
+?>
diff --git a/languages/LanguageUtf8.php b/languages/LanguageUtf8.php
new file mode 100644 (file)
index 0000000..67433b8
--- /dev/null
@@ -0,0 +1,176 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+if( defined( "MEDIAWIKI" ) ) {
+
+# This file and LanguageLatin1.php may be included from within functions, so
+# we need to have global statements
+
+global $wgInputEncoding, $wgOutputEncoding, $wikiUpperChars, $wikiLowerChars;
+global $wgDBname, $wgMemc;
+
+$wgInputEncoding    = "UTF-8";
+$wgOutputEncoding      = "UTF-8";
+
+if( function_exists( 'mb_strtoupper' ) ) {
+       mb_internal_encoding('UTF-8');
+} else {
+       # Hack our own case conversion routines
+
+       # Loading serialized arrays is faster than parsing code :P
+       $wikiUpperChars = $wgMemc->get( $key1 = "$wgDBname:utf8:upper" );
+       $wikiLowerChars = $wgMemc->get( $key2 = "$wgDBname:utf8:lower" );
+
+       if(empty( $wikiUpperChars) || empty($wikiLowerChars )) {
+               require_once( "includes/Utf8Case.php" );
+               $wgMemc->set( $key1, $wikiUpperChars );
+               $wgMemc->set( $key2, $wikiLowerChars );
+       }
+}
+
+/**
+ * Base stuff useful to all UTF-8 based language files
+ * @package MediaWiki
+ */
+class LanguageUtf8 extends Language {
+
+       # These two functions use mbstring library, if it is loaded
+       # or compiled and character mapping arrays otherwise.
+       # In case of language-specific character mismatch
+       # it should be dealt with in Language classes.
+
+       function ucfirst( $string ) {
+               /**
+                * On pages with many links we can get called a lot.
+                * The multibyte uppercase functions are relatively
+                * slow, so check first if we can use a faster ASCII
+                * version instead; it saves a few milliseconds.
+                */
+               if( preg_match( '/^[\x80-\xff]/', $string ) ) {
+                       if (function_exists('mb_strtoupper')) {
+                               return mb_strtoupper(mb_substr($string,0,1)).mb_substr($string,1);
+                       } else {
+                               global $wikiUpperChars;
+                               return preg_replace (
+                                       "/^([a-z]|[\\xc0-\\xff][\\x80-\\xbf]*)/e",
+                                       "strtr ( \"\$1\" , \$wikiUpperChars )",
+                                       $string );
+                       }
+               }
+               return ucfirst( $string );
+       }
+
+       function lcfirst( $string ) {
+               if (function_exists('mb_strtolower')) {
+                       return mb_strtolower(mb_substr($string,0,1)).mb_substr($string,1);
+               } else {
+                   global $wikiLowerChars;
+                   return preg_replace (
+                   "/^([A-Z]|[\\xc0-\\xff][\\x80-\\xbf]*)/e",
+                   "strtr ( \"\$1\" , \$wikiLowerChars )",
+                   $string );
+               }
+       }
+
+       function stripForSearch( $string ) {
+               # MySQL fulltext index doesn't grok utf-8, so we
+               # need to fold cases and convert to hex
+
+               # In Language:: it just returns lowercase, maybe
+               # all strtolower on stripped output or argument
+               # should be removed and all stripForSearch
+               # methods adjusted to that.
+
+               wfProfileIn( "LanguageUtf8::stripForSearch" );
+               if( function_exists( 'mb_strtolower' ) ) {
+                       $out = preg_replace(
+                               "/([\\xc0-\\xff][\\x80-\\xbf]*)/e",
+                               "'U8' . bin2hex( \"$1\" )",
+                               mb_strtolower( $string ) );
+               } else {
+                       global $wikiLowerChars;
+                       $out = preg_replace(
+                               "/([\\xc0-\\xff][\\x80-\\xbf]*)/e",
+                               "'U8' . bin2hex( strtr( \"\$1\", \$wikiLowerChars ) )",
+                               $string );
+               }
+               wfProfileOut( "LanguageUtf8::stripForSearch" );
+               return $out;
+       }
+
+       function fallback8bitEncoding() {
+               # Windows codepage 1252 is a superset of iso 8859-1
+               # override this to use difference source encoding to
+               # translate incoming 8-bit URLs.
+               return "windows-1252";
+       }
+
+       function checkTitleEncoding( $s ) {
+               global $wgInputEncoding;
+
+               if( is_array( $s ) ) {
+                       wfDebugDieBacktrace( 'Given array to checkTitleEncoding.' );
+               }
+               # Check for non-UTF-8 URLs
+               $ishigh = preg_match( '/[\x80-\xff]/', $s);
+               if(!$ishigh) return $s;
+
+               $isutf8 = preg_match( '/^([\x00-\x7f]|[\xc0-\xdf][\x80-\xbf]|' .
+                '[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xf7][\x80-\xbf]{3})+$/', $s );
+               if( $isutf8 ) return $s;
+
+               return $this->iconv( $this->fallback8bitEncoding(), "utf-8", $s );
+       }
+
+       function firstChar( $s ) {
+               preg_match( '/^([\x00-\x7f]|[\xc0-\xdf][\x80-\xbf]|' .
+               '[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xf7][\x80-\xbf]{3})/', $s, $matches);
+
+               return isset( $matches[1] ) ? $matches[1] : "";
+       }
+
+       # Crop a string from the beginning or end to a certain number of bytes.
+       # (Bytes are used because our storage has limited byte lengths for some
+       # columns in the database.) Multibyte charsets will need to make sure that
+       # only whole characters are included!
+       #
+       # $length does not include the optional ellipsis.
+       # If $length is negative, snip from the beginning
+       function truncate( $string, $length, $ellipsis = "" ) {
+               if( $length == 0 ) {
+                       return $ellipsis;
+               }
+               if ( strlen( $string ) <= abs( $length ) ) {
+                       return $string;
+               }
+               if( $length > 0 ) {
+                       $string = substr( $string, 0, $length );
+                       $char = ord( $string[strlen( $string ) - 1] );
+                       if ($char >= 0xc0) {
+                               # We got the first byte only of a multibyte char; remove it.
+                               $string = substr( $string, 0, -1 );
+                       } elseif( $char >= 0x80 &&
+                                 preg_match( '/^(.*)(?:[\xe0-\xef][\x80-\xbf]|' .
+                                             '[\xf0-\xf7][\x80-\xbf]{1,2})$/', $string, $m ) ) {
+                           # We chopped in the middle of a character; remove it
+                               $string = $m[1];
+                       }
+                       return $string . $ellipsis;
+               } else {
+                       $string = substr( $string, $length );
+                       $char = ord( $string[0] );
+                       if( $char >= 0x80 && $char < 0xc0 ) {
+                               # We chopped in the middle of a character; remove the whole thing
+                               $string = preg_replace( '/^[\x80-\xbf]+/', '', $string );
+                       }
+                       return $ellipsis . $string;
+               }
+       }
+}
+
+} # ifdef MEDIAWIKI
+
+?>
diff --git a/languages/LanguageVi.php b/languages/LanguageVi.php
new file mode 100644 (file)
index 0000000..2b9a980
--- /dev/null
@@ -0,0 +1,15 @@
+<?php
+/**
+ * Vietnamese (Tiếng Việt)
+ * @package MediaWiki
+ * @subpackage Language
+ */
+
+require_once( 'LanguageUtf8.php' );
+
+class LanguageVi extends LanguageUtf8 {
+       function formatNum( $number, $year = false ) {
+               return $year ? $number : strtr($this->commafy($number), '.,', ',.' );
+       }
+}
+?>
diff --git a/languages/LanguageWa.php b/languages/LanguageWa.php
new file mode 100644 (file)
index 0000000..fe96a57
--- /dev/null
@@ -0,0 +1,1101 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+require_once( "LanguageUtf8.php" );
+
+# NOTE: cweri après "NOTE:" po des racsegnes so des ratournaedjes
+# k' i gn a.
+
+/* private */ $wgNamespaceNamesWa = array(
+       NS_MEDIA          => "Media", /* Media */
+       NS_SPECIAL        => "Sipeciås", /* Special */
+       NS_MAIN           => "",
+       NS_TALK           => "Copene", /* Talk */
+       NS_USER           => "Uzeu", /* User */
+       NS_USER_TALK      => "Uzeu_copene", /* User_talk */
+       NS_PROJECT        => "Wikipedia", /* Wikipedia */
+       NS_PROJECT_TALK => "Wikipedia_copene", /* Wikipedia_talk */
+       NS_IMAGE          => "Imådje", /* Image */
+       NS_IMAGE_TALK     => "Imådje_copene", /* Image_talk */
+       NS_MEDIAWIKI      => "MediaWiki", /* MediaWiki */
+       NS_MEDIAWIKI_TALK => "MediaWiki_copene", /* MediaWiki_talk */
+       NS_TEMPLATE       => "Modele",
+       NS_TEMPLATE_TALK  => "Modele_copene",
+       NS_HELP           => "Aidance",
+       NS_HELP_TALK      => "Aidance_copene",
+       NS_CATEGORY       => "Categoreye",
+       NS_CATEGORY_TALK  => "Categoreye_copene",
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgQuickbarSettingsWa = array(
+       "Nole bår", "Aclawêye a hintche", "Aclawêye a droete", "Flotante a hintche"
+);
+
+/* private */ $wgDateFormatsWa = array( /* cwè fé chal ??? */
+#      "Nole preferince",
+);
+
+
+/* private */ $wgAllMessagesWa = array(
+# User Toggles
+
+"tog-underline" => "Sorlignî les loyéns",
+"tog-highlightbroken" => "Håyner les vudes loyéns <a href=\"\" class=\"new\">come çouchal</a><br /> &nbsp;&nbsp;&nbsp; (oudonbén: come çouchal<a href=\"\" class=\"internal\">?</a>).",
+"tog-justify"  => "Djustifyî les hagnons",
+"tog-hideminor" => "Èn nén moster les <i>dierins candjmints</i> mineurs",
+"tog-usenewrc" => "Ramidrés <i>dierins candjmints</i> (nén tos les betchteus)",
+"tog-numberheadings" => "Limerotaedje otomatike des tites",
+"tog-editondblclick" => "Candjî les pådjes avou on dobe-clitch (JavaScript)",
+"tog-editsection" => "Eployî les loyéns «[candjî]» po candjî rén k'&nbsp;ene seccion",
+"tog-editsectiononrightclick" => "Candjî les seccions avou on dobe-clitch sol tite (JavaScript)",
+"tog-showtoc" => "Mostrer l'&nbsp;tåvlea d'&nbsp;ådvins<br />(po ls årtikes avou pus di 3 seccions)",
+"tog-rememberpassword" => "Rimimbrer li scret inte les sessions",
+"tog-editwidth" => "Li boesse d'&nbsp;aspougnaedje prind tote li lårdjeu",
+"tog-watchdefault" => "Shuve les årtikes ki dj'&nbsp;fwai ou ki dj'&nbsp;candje",
+"tog-minordefault" => "Prémete mes candjmints come mineurs",
+"tog-previewontop" => "Prévey l'&nbsp;årtike å dzeu del boesse d'&nbsp;aspougnaedje",
+"tog-nocache" => "Èn nén eployî d'&nbsp;muchete pol håynaedje des pådjes",
+# Dates
+'sunday' => "dimegne",
+'monday' => "londi",
+'tuesday' => "mårdi",
+'wednesday' => "mierkidi",
+'thursday' => "djudi",
+'friday' => "vénrdi",
+'saturday' => "semdi",
+'january' => "djanvî",
+'february' => "fevrî",
+'march' => "måss",
+'april' => "avri",
+'may_long' => "may",
+'june' => "djun",
+'july' => "djulete",
+'august' => "awousse",
+'september' => "setimbe",
+'october' => "octôbe",
+'november' => "nôvimbe",
+'december' => "decimbe",
+'jan' => "dja",
+'feb' => "fev",
+'mar' => "mås",
+'apr' => "avr",
+'may' => "may",
+'jun' => "djn",
+'jul' => "djl",
+'aug' => "awo",
+'sep' => "set",
+'oct' => "oct",
+'nov' => "nôv",
+'dec' => "dec",
+
+
+# Bits of text used by many pages:
+#
+# the [] is only for *bytes*, real chars should be one by one :-(
+#"linktrail"     => "/^(?:å|â|ê|î|ô|û|ç|é|è|[a-z]+)(.*)\$/sD",
+"linktrail"     => "/^(å|â|ê|î|ô|û|ç|é|è|[a-z]+)(.*)\$/sD",
+"categories"   => "Categoreyes des pådjes",
+"category"     => "categoreye",
+"category_header" => "Årtikes el categoreye «%s»",
+"subcategories"        => "Dizo-categoreyes",
+"mainpage"             => "Mwaisse pådje",
+"mainpagetext" => "Li programe Wiki a stî astalé a l'&nbsp;idêye.",
+"about"                        => "Å dfait",
+"aboutsite"      => "Å dfait di Wikipedia",
+"aboutpage"            => "Wikipedia:Å dfait",
+"help"                 => "Aidance",
+"helppage"             => "Wikipedia:Aidance",
+"bugreports"   => "Rapoirts di bugs",
+"bugreportspage" => "Wikipedia:Rapoirts di bugs",
+"sitesupport"  => "Ecwårlaedje",
+"faq"                  => "FAQ", # co a fé
+"faqpage"              => "Wikipedia:FAQ", # co a fé
+"edithelp"             => "Aidance",
+"edithelppage" => "Wikipedia:Kimint_candjî_ene_pådje",
+"cancel"               => "Rinoncî",
+"qbfind"               => "Trover",
+"qbbrowse"             => "Foyter",
+"qbedit"               => "Candjî",
+"qbpageoptions"                => "Cisse pådje ci",
+"qbpageinfo"           => "Contecse",
+"qbmyoptions"          => "Mes pådjes",
+"qbspecialpages"       => "Pådjes sipeciåles",
+"moredotdotdot"                => "Co dpus...",
+"mypage"               => "Mi pådje",
+"mytalk"               => "Mi copinaedje",
+#"currentevents" => "-", /* pol dismete */
+"currentevents" => "Actouwålités",
+"errorpagetitle" => "Aroke",
+"returnto"             => "Rivni al pådje «$1».",
+"tagline"              => "Èn årtike di Wikipedia, li libe eciclopedeye.",
+"help"                 => "Aidance",
+"search"               => "Cweri",
+"history"              => "Istwere del pådje",
+"printableversion" => "Modêye sicrirece-amishtåve",
+"editthispage" => "Candjî&nbsp;l'&nbsp;pådje",
+"deletethispage" => "Disfacer l'&nbsp;pådje",
+"protectthispage" => "Protedjî l'&nbsp;pådje",
+"unprotectthispage" => "Disprotedjî l'&nbsp;pådje",
+"newpage" => "Novele pådje",
+"talkpage"     => "Copene sol pådje",
+"postcomment"  => "Sicrire on comintaire",
+"articlepage"  => "Vey l'&nbsp;årtike",
+"subjectpage"  => "Vey li sudjet", # For compatibility
+"userpage" => "Vey li pådje di l'&nbsp;uzeu",
+"wikipediapage" => "Vey li meta-pådje",
+"imagepage" =>         "Vey li pådje di l'&nbsp;imådje",
+"viewtalkpage" => "Vey li pådje di copene",
+"otherlanguages" => "Ôtes lingaedjes",
+"redirectedfrom" => "(Redjiblé di $1)",
+"lastmodified" => "Cisse pådje a stî candjeye pol dierin côp li $1.",
+"viewcount"            => "Cisse pådje la a stî léjhowe $1 côps.",
+"gnunote" => "Tos les tecses chal sont dizo l'&nbsp;libe licince <a class=internal href='/wiki/GFDL'>GFDL (licince di documintåcion libe di GNU)</a>.",
+"printsubtitle" => "(di {{SERVER}})",
+"protectedpage" => "Pådje protedjeye",
+"administrators" => "Wikipedia:Manaedjeus",
+"sysoptitle"   => "I vs fåt esse manaedjeu",
+"sysoptext"            => "The action you have requested can only be
+performed by users with \"sysop\" status.
+See $1.", # co a fé
+"developertitle" => "I vs fåt esse diswalpeu",
+"developertext"        => "The action you have requested can only be
+performed by users with \"developer\" status.
+See $1.", # co a fé
+"nbytes"               => "$1 octets",
+"go"                   => "Potchî",
+"ok"                   => "'l est bon",
+"sitetitle"            => "Wikipedia",
+"sitesubtitle" => "Li libe eciclopedeye",
+"retrievedfrom" => "Prin del pådje «$1»",
+"newmessages" => "Vos avoz des $1.",
+"newmessageslink" => "noveas messaedjes",
+"editsection" => "candjî",
+"toc" => "Ådvins",
+"showtoc" => "mostrer",
+"hidetoc" => "catchî",
+"thisisdeleted" => "Vey ou rapexhî $1?",
+"restorelink" => "$1 candjmints disfacés",
+
+# Main script and global functions
+#
+"nosuchaction" => "Nole sifwaite accion",
+"nosuchactiontext" => "L'&nbsp;accion specifieye pal hårdêye n'&nbsp;est
+nén ricnoxhowe på wiki.",
+"nosuchspecialpage" => "Nole sifwaite pådje",
+"nospecialpagetext" => "Vos avoz dmandé ene pådje sipeciåle ki n'&nbsp;est
+nén ricnoxhowe på wiki.",
+
+# General errors
+#
+"error"                        => "Aroke",
+"databaseerror" => "Åk n'&nbsp;a nén stî avou l'&nbsp;båze di dnêyes",
+"dberrortextcl" => "A database query syntax error has occurred.
+The last attempted database query was:
+\"$1\"
+from within function \"$2\".
+MySQL returned error \"$3: $4\".\n", # co a fé
+"noconnect"            => "Mande escuzes! Li wiki a des rujhes tecnikes pol moumint, eyet c'&nbsp;est nén possibe di s'&nbsp;raloyî al båze di dnêyes.",
+"nodb"                 => "Dji n'&nbsp;sai tchoezi l'&nbsp;båze di dnêyes $1",
+"cachederror"          => "The following is a cached copy of the requested page, and may not be up to date.", # co a fé
+"readonly"             => "Database locked", # co a fé
+"enterlockreason" => "Enter a reason for the lock, including an estimate
+of when the lock will be released", # co a fé
+"readonlytext" => "The database is currently locked to new
+entries and other modifications, probably for routine database maintenance,
+after which it will be back to normal.
+The administrator who locked it offered this explanation:
+<p>$1", # co a fé
+"missingarticle" => "The database did not find the text of a page
+that it should have found, named \"$1\".
+
+<p>This is usually caused by following an outdated diff or history link to a
+page that has been deleted.
+
+<p>If this is not the case, you may have found a bug in the software.
+Please report this to an administrator, making note of the URL.", # co a fé
+"internalerror" => "Divintrinne aroke",
+"filecopyerror" => "Dji n'&nbsp;a savou copyî l'&nbsp;fitchî «$1» viè «$2».",
+"filerenameerror" => "Dji n'&nbsp;a savou rlomer l'&nbsp;fitchî «$1» e «$2».",
+"filedeleteerror" => "Dji n'&nbsp;a savou disfacer l'&nbsp;fitchî «$1».",
+"filenotfound" => "Dji n'&nbsp;a savou trover l'&nbsp;fitchî «$1».",
+"unexpected"   => "Valixhance nén ratindowe: «$1»=«$2».",
+"formerror"            => "Error: could not submit form", # co a fé
+"badarticleerror" => "This action cannot be performed on this page.", # co a fé
+"cannotdelete" => "Could not delete the page or image specified. (It may have already been deleted by someone else.)", # co a fé
+"badtitle"             => "Måva tite",
+"badtitletext" => "The requested page title was invalid, empty, or
+an incorrectly linked inter-language or inter-wiki title.", # co a fé
+"perfdisabled" => "Mande escuzes! mins cisse fonccionålité ci a stî essoctêye
+pol moumint pask'&nbsp;ele est trop pezante pol båze di dnêyes, ki dvént
+si télmint londjinne k'&nbsp;on s'&nbsp;endè pout pus siervi a môde di djin.",
+"perfdisabledsub" => "Vochal ene copeye k'&nbsp;a stî schapêye di $1:",
+"wrong_wfQuery_params" => "Parametes incoreks po wfQuery()<br />
+Fonccion: $1<br />
+Cweraedje: $2
+",
+"viewsource" => "Vey côde sourdant",
+"protectedtext" => "Cisse pådje chal a stî protedjeye siconte des candjmints;
+i gn a sacwantès råjhons po çoula, loukîz
+[[{{ns:4}}:Pådje protedjeye]] s'&nbsp;i vs plait.
+
+Mins nerén vos ploz vey eyet copyî li côde sourdant del pådje:",
+
+
+# Login and logout pages
+#
+"logouttitle"  => "Dislodjaedje",
+"logouttext"   => "Vos vs avoz dislodjî.
+Vos ploz continouwer a naivyî so {{SITENAME}} anonimmint, oudonbén
+vos relodjî dizo l'&nbsp;minme uzeu ou dizo èn uzeu diferin.",
+
+"welcomecreation" => "<h2>Bénvnowe, $1!</h2>
+<p>
+Vosse conte a stî ahivé.
+Èn rovyîz nén di candjî les preferinces di {{SITENAME}} a vosse môde.",
+
+"loginpagetitle" => "Elodjaedje",
+"yourname"             => "Vosse no d'&nbsp;elodjaedje",
+"yourpassword" => "Vosse sicret",
+"yourpasswordagain" => "Ritapez vosse sicret",
+"newusersonly" => " (seulmint po les noveas uzeus)",
+"remembermypassword" => "Rimimbrer m'&nbsp;sicret inte les sessions.",
+"loginproblem" => "<b>Åk n'&nbsp;a nén stî tot vs elodjant.</b><br />Rissayîz!",
+"alreadyloggedin" => "<strong>Uzeu $1, vos estoz ddja elodjî!</strong><br />",
+"login"                        => "S'&nbsp;elodjî",
+"loginprompt"          => "Vos dvoz permete les coûkes po vs elodjî so Wikipedia.",
+"userlogin"            => "S' elodjî", # pont d' "nbsp" chal
+"logout"               => "Si dislodjî",
+"userlogout"   => "Si dislodjî",
+"notloggedin"  => "Nén elodjî",
+"createaccount"        => "Ahiver on novea conte",
+"createaccountmail" => "pa emile",
+"badretype"            => "Vos avoz dné deus screts diferins.",
+"userexists"   => "Li no d'&nbsp;uzeu ki vs avoz tchoezi est ddja eployî. Tchoezixhoz è èn ôte s'&nbsp;i vs plait.",
+"youremail"            => "Vost emile*",
+"yournick"             => "Vosse no metou (po les sinateures)",
+"emailforlost" => "Les tchamps avou ene sitoele (*)
+èn sont nén obligatweres.<br />
+L'&nbsp;adresse emile, si vos ndè dnez ene, vos permetrè di rçure et
+d'&nbsp;evoyî des emiles å dtruviè di cisse waibe chal, sins vos dveur
+diner voste adresse emile, çoula vos srè eto foirt ahessåve si vos rovyîz
+måy vosse sicret (on novea scret vos pôrè-st esse evoyî pa emile).<br />
+Vosse vraiy no, si vos l'&nbsp;dinez, pôrè esse eployî po mete a costé
+di vos ovraedjes.",
+"loginerror"   => "Aroke d'&nbsp;elodjaedje",
+"nocookiesnew" => "Li conte a stî ahivé, mins vos n'&nbsp;estoz nén elodjî. {{SITENAME}} eploye des coûkes po l'&nbsp;elodjaedje des uzeus. Vos avoz dismetou l'&nbsp;sopoirt des coûkes dins vosse betchteu waibe; rimetoz l'&nbsp;en alaedje et relodjîz vs avou vosse novea no d'&nbsp;elodjaedje eyet scret, s'&nbsp;i vs plait.",
+"nocookieslogin" => "{{SITENAME}} eploye des coûkes po l'&nbsp;elodjaedje des uzeus. Vos avoz dismetou l'&nbsp;sopoirt des coûkes dins vosse betchteu waibe; rimetoz l'&nbsp;en alaedje et relodjîz vs s'&nbsp;i vs plait.",
+"noname"       => "Vos n'&nbsp;avoz nén dné di no d'&nbsp;uzeu valide.",
+"loginsuccesstitle" => "Vos estoz elodjî",
+"loginsuccess" => "L'&nbsp;elodjaedje a stî comifåt, asteure vos estoz elodjî dins {{SITENAME}} dizo l'&nbsp;no d'&nbsp;uzeu «$1».",
+"nosuchuser"   => "I gn a nou uzeu dizo l'&nbsp;no «$1».
+Verifyîz çou k'&nbsp;vos avoz tapé, oudonbén rimplixhoz les ôtes tchamps
+et clitchîz sol boton po-z ahiver on novea conte.",
+"wrongpassword"        => "Li scret ki vs avoz dné est måva. Rissayîz s'&nbsp;i vs plait.",
+"mailmypassword" => "M'&nbsp;emiler on novea scret",
+"passwordremindertitle" => "Rimimbraedje do scret po Wikipedia",
+"passwordremindertext" => "Ene sakî (probåblumint vos minme, avou l' adresse IP $1)
+a dmandé k' on vs emile on novea scret po vs elodjî so Wikipedia.
+Li scret po l' uzeu «$2» est asteure «$3».
+Po pus di såvrité, vos dvrîz vos elodjî eyet rcandjî vosse sicret å pus abeye.", # pont d' "&nbsp;" chal, ca c' est po-z esse emilé.
+"noemail"              => "I gn a pont d'&nbsp;adresse emile di cnoxhowe po l'&nbsp;uzeu «$1».",
+"passwordsent" => "On novea scret a stî emilé a l'&nbsp;adresse emile
+racsegneye po l'&nbsp;uzeu «$1».
+Relodjîz vs avou ç'&nbsp;noû scret on côp ki vos l'&nbsp;åroz rçuvou s'&nbsp;i vs plait.",
+
+# Edit pages
+#
+"summary"              => "Rascourti",
+"subject"              => "Sudjet/tiestire",
+"minoredit"            => "C'&nbsp;est on candjmint mineur",
+"watchthis"            => "Shure cist årtike",
+"savearticle"  => "Schaper l'&nbsp;pådje",
+"preview"              => "Vey divant",
+"showpreview"  => "Vey divant",
+"blockedtitle" => "L'&nbsp;uzeu est bloké",
+"blockedtext"  => "Your user name or IP address has been blocked by $1.
+The reason given is this:<br />''$2''<p>You may contact $1 or one of the other
+[[Wikipedia:Manaedjeus|administrators]] to discuss the block.
+
+Note that you may not use the \"email this user\" feature unless you have a valid email address registered in your [[Sipeciås:Preferences|user preferences]].
+
+Your IP address is $3. Please include this address in any queries you make.
+
+==Note to AOL users==
+Due to continuing acts of vandalism by one particular AOL user, Wikipedia often blocks AOL proxies. Unfortunately, a single proxy server may be used by a large number of AOL users, and hence innocent AOL users are often inadvertently blocked. We apologise for any inconvenience caused.
+
+If this happens to you, please email an administrator, using an AOL email address. Be sure to include the IP address given above.
+", # co a fé
+"whitelistedittitle" => "S'&nbsp;elodjî po candjî",
+"whitelistedittext" => "I vs fåt [[Sipeciås:Userlogin|elodjî]] po pleur candjî les årtikes.",
+"whitelistreadtitle" => "S'&nbsp;elodjî po lére",
+"whitelistreadtext" => "I vs fåt [[Sipeciås:Userlogin|elodjî]] po pleur lére les årtikes.",
+"whitelistacctitle" => "Vos n'&nbsp;avoz nén l'&nbsp;permission d'&nbsp;ahiver on conte chal",
+"whitelistacctext" => "Po pleur ahiver on conte so ç'&nbsp;Wiki chal, vos dvoz esse [[Sipeciås:Userlogin|elodjî]] ey aveur les bounès permissions.",
+"accmailtitle" => "Li scret a stî evoyî.",
+"accmailtext" => "Li scret po «$1» a stî evoyî a $2.",
+"newarticle"   => "(Novea)",
+"newarticletext" =>
+"Vos avoz clitchî so on loyén viè ene pådje ki n'&nbsp;egzistêye nén co.
+Mins '''vos''' l'&nbsp;poloz askepyî! Po çoula, vos n'&nbsp;avoz k'&nbsp;a
+cmincî a taper vosse tecse dins l'&nbsp;boesse di tecse chal pa dzo
+(alez vey li [[Wikipedia:Aidance|pådje d'&nbsp;aidance]] po pus
+d'&nbsp;informåcion).
+Si vos n'&nbsp;voloz nén scrire cisse pådje chal, clitchîz simplumint
+sol boton '''En erî''' di vosse betchteu waibe po rivni al pådje di dvant.",
+"anontalkpagetext" => "---- ''Çouchal c'&nbsp;est li pådje di copene po
+èn uzeu anonime ki n'&nbsp;a nén (co) fwait on conte por lu s'&nbsp;elodjî,
+ou ki nel eploye nén. Do côp, on doet eployî si [[adresse IP]] limerike po
+l'&nbsp;idintifyî. Come ene sifwaite adresse IP pout esse eployeye pa pus
+d'&nbsp;èn uzeu, i s'&nbsp;pout ki vos voeyoz chal des rimåkes et des
+messaedjes ki n'&nbsp;sont nén por vos, loukîz s'&nbsp;i vs plait po
+[[Sipeciås:Userlogin|fé on novea conte ou s'&nbsp;elodjî]] po n'&nbsp;pus
+aveur di confuzion avou des ôtes uzeus anonimes.'' ",
+"noarticletext" => "(I gn a pol moumint nou tecse e cisse pådje chal)",
+"updated"              => "(Ramidré)",
+"note"                 => "<strong>Note:</strong> ",
+"previewnote"  => "Èn rovyîz nén ki c'&nbsp;est djusse on
+prévoeyaedje, li pådje n'&nbsp;est nén co schapêye!",
+"previewconflict" => "Ci prévoeyaedje ci mostere kimint kel tecse del
+boesse di tecse do dzeu sereut håyné si vos decidez di clitchî so «schaper».",
+"editing"              => "Candjant $1",
+"editingsection"       => "Candjant $1 (seccion)",
+"editingcomment"       => "Candjant $1 (comintaire)",
+"editconflict" => "Conflit inte deus candjmints: $1",
+"explainconflict" => "Ene sakî a candjî l'&nbsp;pådje do tins ki vos
+estîz a scrire.
+Li boesse di tecse do dzeur mostere li tecse del pådje come il est
+pol moumint sol sierveu.
+Li tecse da vosse est sol boesse di tecse do dzo.
+Les diferinces sont håynêyes å mitan.
+Vos dvoz mete vos candjmints dins l'&nbsp;tecse d'&nbsp;asteure (å dzeur)
+si vos lez vloz co evoyî.
+<b>Seulmint</b> li tecse do dzeur serè candjî cwand vos clitchroz sol
+boton «Schaper l'nbsp;pådje».<br />",
+"yourtext"             => "Li tecse da vosse",
+"storedversion" => "Modêye sol sierveu",
+"editingold"   => "<strong>ASTEME: Vos estoz ki candje ene viye modêye
+del pådje. Si vos l'&nbsp;schapez, tos les candjmints k'&nbsp;ont stî
+fwaits dispoy adon si vont piede.</strong>",
+"yourdiff"             => "Diferinces",
+"copyrightwarning" => "Notez ki totes les contribucions fwaites po {{SITENAME}}
+dvèt esse dizo li licince di documintåcion libe di GNU
+(GFDL, loukîz $1 po pus di racsegnes).
+Si&nbsp;vos n'&nbsp;voloz nén ki vosse tecse poye esse candjî eyet spårdou
+pa tot l'&nbsp;minme kî, adon nel evoyîz nén chal.
+<br />
+Vos nos acertinez eto ki vos avoz scrît l'&nbsp;tecse vos minme, oudonbén
+l'&nbsp;avoz copyî d'&nbsp;on sourdant libe (dominne publik ou on sourdant
+pareymint libe).
+<br />
+<strong>N'&nbsp;EVOYÎZ NÉN DES TECSES DIZO ABONDROETS SINS PERMISSION&nbsp;!</strong>",
+"longpagewarning" => "<strong>ASTEME: Cisse pådje fwait $1 kilo-octets; des
+betchteus waibes k'&nbsp;i gn a polèt aveut des rujhes po-z aspougnî
+des pådjes k'&nbsp;aprepièt ou di pus di 32&nbsp;Ko.
+Vos dvrîz tuzer a pårti l'&nbsp;pådje e pus ptits bokets.</strong>",
+"readonlywarning" => "<strong>ASTEME:  On-z overe sol båze di dnêyes pol moumint, ey elle a stî metowe e mode seulmint-lére.
+Do côp, vos n'&nbsp;såroz schaper vos candjmints asteure; motoit vos dvrîz copyî et aclaper l'&nbsp;tecse dins on fitchî da vosse pol poleur rimete sol {{SITENAME}} pus tård.</strong>",
+"protectedpagewarning" => "<strong>ASTEME: Cisse pådje chal a stî protedjeye siconte
+des candjmints, seulmint les uzeus avou èn accès di manaedjeu el polèt candjî.
+Acertinez vs ki vos shuvoz les
+[[Project:Rîles_po_les_pådjes_protedjeyes|rîles po les pådjes
+protedjeyes]].</strong>",
+
+# History pages
+#
+"revhistory"   => "Istwere des modêyes",
+"nohistory"    => "I gn a pont d'&nbsp;istwere des modêyes po cisse pådje chal.",
+"revnotfound"  => "Modêye nén trovêye",
+"revnotfoundtext" => "Li viye modêye del pådje ki vos avoz dmandé n'&nbsp;a nén stî trovêye.
+Verifyîz l'&nbsp;hårdêye ki vs avoz eployî po-z ariver sol pådje s'&nbsp;i vs plait.\n",
+"loadhist"             => "Tcherdjaedje del pådje di l'&nbsp;istwere",
+"currentrev"   => "Modêye d'&nbsp;asteure",
+"revisionasof" => "Modêye do $1",
+"cur"                  => "ast.",
+"next"                 => "shuv.",
+"last"                 => "dif.",
+"orig"                 => "oridj.",
+"histlegend"   => "Ledjinde: (ast.) = diferince avou l'&nbsp;modêye d'&nbsp;asteure,
+(dif.) = diferince avou l'&nbsp;modêye di dvant, M = candjmint mineur",
+
+# Diffs
+#
+"difference"   => "(Diferinces inte les modêyes)",
+"loadingrev"   => "tcherdjaedje del modêye po les diferinces",
+"lineno"               => "Roye $1:",
+"editcurrent"  => "Candjî li modêye do moumint di cisse pådje chal",
+
+# Search results
+#
+"searchresults" => "Rizultats do cweraedje",
+"searchresulttext" => "Po pus di racsegnes sol manire di fé des cweraedjes so {{SITENAME}}, loukîz [[Project:Cweraedje|Cweraedje so {{SITENAME}}]].",
+"searchquery"  => "Pol cweraedje «$1»",
+"badquery"             => "Badly formed search query", # co a fé
+"badquerytext" => "We could not process your query.
+This is probably because you have attempted to search for a
+word fewer than three letters long, which is not yet supported.
+It could also be that you have mistyped the expression, for
+example \"fish and and scales\".
+Please try another query.", # co a fé
+"matchtotals"  => "Li cweraedje «$1» a trové $2 årtikes avou l'&nbsp;tite
+ki corespond eyet $3 årtikes avou l'&nbsp;tecse ki corespond.",
+"nogomatch" => "I n'&nbsp;a nole pådje avou ç'&nbsp;tite la, dji saye on cweraedje dins l'&nbsp;tecse des årtikes.",
+"titlematches" => "Årtikes avou on tites ki corespond",
+"notitlematches" => "Nol årtike avou on tite ki corespond",
+"textmatches"  => "Årtikes avou do tecse ki corespond",
+"notextmatches"        => "Nol årtike avou do tecse ki corespond",
+"prevn"                        => "$1 di dvant",
+"nextn"                        => "$1 shuvants",
+"viewprevnext" => "Vey ($1) ($2) ($3).",
+"showingresults" => "Chal pa dzo <b>$1</b> rizultats a pårti do limero <b>$2</b>.",
+"showingresultsnum" => "Chal pa dzo <b>$3</b> rizultats a pårti do limero <b>$2</b>.",
+"nonefound"            => "<strong>Note</strong>: des cweraedjes ki n'&nbsp;dinèt nou rzultat c'&nbsp;est sovint li cweraedje di ptits mots trop corants (come «les», «des») ki n'&nbsp;sont nén indecsés, oudonbén des cweraedjes di pus d'&nbsp;on mot (seulmint les pådjes avou tos les mots dmandés sront håynêyes dins l'&nbsp;rizultat do cweraedje).",
+"powersearch" => "Cweri",
+"powersearchtext" => "
+Cweraedje ezès espåces di nos&nbsp;:<br />
+$1<br />
+$2 Håyner les redjiblaedjes &nbsp; Cweri après $3 $9",
+"searchdisabled" => "<p>Mande escuzes! Li cweraedje å dvins des årtikes a stî dismetou
+pol moumint, cåze ki l'&nbsp;sierveu est fortcherdjî.
+Tot ratindant, vos ploz eployî Google po fé les rcweraedjes,
+mins çoula pout esse ene miete vî.</p>",
+"blanknamespace" => "(Mwaisse)",
+
+# Preferences page
+#
+"preferences"  => "Preferinces",
+"prefsnologin" => "Vos n'&nbsp;estoz nén elodjî",
+"prefsnologintext"     => "I vs fåt esse [[Sipeciås:Userlogin|elodjî]]
+po pleur candjî vos preferinces.",
+"prefslogintext" => "Vos estoz elodjî dizo l'&nbsp;uzeu «$1».
+Vosse divintrin idintifiant est l'&nbsp;limero $2.
+
+Loukîz a [[Wikipedia:Aidance so les preferinces]] po saveur çou k'&nbsp;c'&nbsp;est tchaeke des tchuzes des preferinces des uzeus.",
+"prefsreset"   => "Les preferinces ont stî rmetowes come d'&nbsp;avance a
+pårti des wårdêyès valixhances.",
+"qbsettings"   => "Apontiaedjes pol bår di menu",
+"changepassword" => "Candjî l'&nbsp;sicret",
+"skin"                 => "Pea",
+"math"                 => "Håynaedje des formules matematikes",
+"dateformat"           => "Cogne del date",
+"math_failure"         => "Failed to parse", # co a fé
+"math_unknown_error"   => "aroke nén cnoxhowe",
+"math_unknown_function"        => "fonccion nén cnoxhowe ",
+"math_lexing_error"    => "lexing error", # co a fé
+"math_syntax_error"    => "aroke di sintacse",
+"saveprefs"            => "Schaper les preferinces",
+"resetprefs"   => "Rimete les prémetowès valixhances",
+"oldpassword"  => "Vî scret",
+"newpassword"  => "Noû scret",
+"retypenew"            => "Ritapez l'&nbsp;noû scret",
+"textboxsize"  => "Grandeu del boesse di tecse",
+"rows"                 => "Royes",
+"columns"              => "Colones",
+"searchresultshead" => "Håynaedje des rzultats di cweraedje",
+"resultsperpage" => "Nombe di responses a håyner so en pådje",
+"contextlines" => "Nombe di royes a håyner po ene response",
+"contextchars" => "Nombe di caracteres di contecse pa roye",
+"stubthreshold" => "Grandeu minimom po håyner les courts årtikes",
+"recentchangescount" => "Nombe di tites dins les <i>dierins candjmints</i>",
+"savedprefs"   => "Vos preferinces ont stî schapêyes.",
+"timezonetext" => "Tapez li nombe d'&nbsp;eures di diferince avou
+l'&nbsp;tins univiersel (UTC).",
+"localtime"    => "Håyner l'&nbsp;eure locåle",
+"timezoneoffset" => "Diferince d'&nbsp;eures",
+"servertime"   => "Server time is now", # co a fé
+"guesstimezone" => "Fill in from browser", # co a fé
+"emailflag"            => "Èn nén riçure des emiles des ôtes uzeus",
+"defaultns"    => "Prémetous spåces di nos pol cweraedje:",
+
+# Recent changes
+#
+"changes" => "candjmints",
+"recentchanges" => "Dierins candjmints",
+"recentchangestext" => "Shuvoz chal les dierins candjmints k'&nbsp;i gn a yeu
+dzo Wikipedia.",
+"rcloaderr"            => "Tcherdjant les dierins candjmints",
+"rcnote"               => "Chal pa dzo les <strong>$1</strong> dierins candjmints des dierins <strong>$2</strong> djoûs.",
+"rcnotefrom"   => "Chal pa dzo les candjmints dispoy li <b>$2</b> (disk'&nbsp;a <b>$1</b> di mostrés).",
+"rclistfrom"   => "Mostrer les candjmints k'&nbsp;i gn a yeu a pårti do $1",
+# "rclinks"            => "Mostrer les $1 dierins candjmints des dierins $2 djoûs.",
+"showhideminor"                => "$1 candmints mineurs | $2 bots | $3 logged in users | $4 patrolled edits",
+"rclinks"              => "Mostrer les $1 dierins candjmints des dierins $2 djoûs; $3",
+"rchide"               => "e $4; $1 candjmints mineurs; $2 nos d'&nbsp;espåces segondaires; $3 candjmints multipes.",
+"rcliu"                        => "; $1 candjmints pa des uzeus eredjîstrés",
+"diff"                 => "dif.",
+"hist"                 => "ist.",
+"hide"                 => "cat.",
+"show"                 => "håy.",
+"tableform"            => "tåvlea",
+"listform"             => "djivêye",
+"nchanges"             => "$1 candjmints",
+"minoreditletter" => "M",
+"newpageletter" => "N",
+
+# Upload
+#
+"upload"               => "Eberweter on fitchî",
+"uploadbtn"            => "Eberweter",
+"uploadlink"   => "Eberweter des imådjes",
+"reupload"             => "Reberweter",
+"reuploaddesc" => "Rivni al pådje d'&nbsp;eberwetaedje.",
+"uploadnologin" => "Nén elodjî",
+"uploadnologintext"    => "I vs fåt esse [[Sipeciås:Userlogin|elodjî]] por
+vos pleur eberweter des fitchîs.",
+"uploaderror"  => "Aroke d'&nbsp;eberwetaedje",
+"uploadtext"   => "'''ASTEME!''' Divant d'&nbsp;eberweter on
+fitchî chal, léjhoz et s'&nbsp;vos asseurer di bén shure
+les [[Project:Rîles_po_l'_eployaedje_des_imådjes|rîles po l'&nbsp;eployaedje des imådjes]]
+di Wikipedia.
+
+Si on fitchî avou l'&nbsp;minme no egzistêye dedja, i srè replaecî
+sins adviertixhmint pa l'&nbsp;ci ki vos årîz eberweté.
+Dj'&nbsp;ô bén ki, a moens ki vos vôrîz mete a djoû on fitchî tot
+l'&nbsp;replaeçant pa on pus noû, vos dvrîz tofer vos acertiner
+k'&nbsp;i n'&nbsp;a nén ddja on fitchî do minme no.
+
+Po håyner ou cweri des imådjes k'&nbsp;ont ddja stî rçuvowes,
+alez sol [[Sipeciås:Imagelist|djivêye des imådjes dedja eberwetêyes]].
+Les eberwetaedjes et disfaçaedjes sont metous èn on
+[[Project:Djournå_des_eberwetaedjes|djournå des eberwetaedjes]].
+
+Eployîz les boesses d'&nbsp;intrêye chal pa dzo po-z eberweter
+des noveas fitchîs d'&nbsp;imådjes po vos årtikes.
+Sol plupårt des betchteus, vos voeroz on boton «Foyter...» (ou «Browse...»)
+ki vs permetrè di foyter dins les ridants del deure plake da vosse
+po tchoezi l'&nbsp;fitchî, çou ki rimplirè otomaticmint li tchamp
+do no do fitchî k'&nbsp;est a costé.
+Vos dvoz eto clitchî sol boesse por vos acertiner ki vos n'&nbsp;violez
+nou abondroet et ki l'&nbsp;fitchî ki vos evoyîz si pout bén eployî
+dins l'&nbsp;Wikipedia.
+Clitchîz sol boton «Eberweter» po-z evoyî l'&nbsp;fitchî sol sierveu.
+çoula pout prinde do tins si l'&nbsp;raloyaedje al daegntoele est
+londjin.
+
+Les cognes di fitchîs k'&nbsp;on-z a ptchî c'&nbsp;est li JPEG po
+les imådjes foto, eyet li PNG po les dessins, mapes, drapeas, imådjetes...
+et li OGG po les sons.
+S'&nbsp;i vs plait, dinez a vosse fitchî on no ki dit bén çou
+k'&nbsp;c'&nbsp;est, c'&nbsp;est pus åjhey insi.
+Po håyner l'&nbsp;imådje dins èn årtike, eployîz on loyén del
+foûme '''<nowiki>[[imådje:fitchî.jpg]]</nowiki>''' ou
+'''<nowiki>[[imådje:fitchî.png|tecse po les betchteus nén grafikes]]</nowiki>'''
+ou co '''<nowiki>[[media:fitchî.ogg]]</nowiki>''' po les sons.
+
+Notez bén ki, tot come po les pådjes del Wikipedia, les ôtès djins polèt
+candjî ou disfacer vos eberwetaedjes s'&nbsp;i pinsèt ki c'&nbsp;est mî
+po l'&nbsp;eciclopedeye; eyet vos ploz esse espaitchî d'&nbsp;eberweter
+des fitchîs si vos n'&nbsp;rispectez nén l'&nbsp;sistinme.",
+"uploadlog"            => "djournå des eberwetaedjes",
+"uploadlogpage" => "Djournå_des_eberwetaedjes",
+"uploadlogpagetext" => "Chal pa dzo li djivêye des dierins eberwetaedjes.
+Totes les eures sont metowes e tins univiersel (UTC).
+<ul>
+</ul>
+",
+"filename"             => "No do fitchî",
+"filedesc"             => "Discrijhaedje",
+"filestatus"           => "Abondroets ey eployaedje",
+"filesource"           => "Sourdant",
+"copyrightpage" => "Wikipedia:Abondroets",
+"copyrightpagename" => "Abondroets Wikipedia",
+"uploadedfiles"        => "Fitchîs eberwetés",
+"ignorewarning"        => "Passer houte des adviertixhmints eyet schaper tot l'&nbsp;minme li fitchî.",
+"minlength"            => "Les imådjes divèt aveur des nos di pol moens troes letes.",
+"badfilename"  => "Li no d'&nbsp;l'&nbsp;imådje a stî candjî a «$1».",
+"badfiletype"  => "«.$1» n'&nbsp;est nén ene sôre d'&nbsp;imådje ricmandêye.",
+"largefile"            => "C'&nbsp;est mî ki les imådjes åyexhe ene grandeu di moens di 100&nbsp;Ko.",
+"successfulupload" => "L'&nbsp;eberwetaedje a stî comifåt",
+"fileuploaded" => "L'&nbsp;eberwetaedje do fitchî «$1» a stî å paire des pôces.
+Shuvoz ci loyén chal: ($2) pol pådje di discrijhaedje eyet rimplixhoz les
+informåcions sol fitchî, come di wice k'&nbsp;i vént, cwand il a stî
+fwait, et pa kî, et tot l'&nbsp;minme kéne informåcion interessante ki vos ploz
+saveur å dfait do fitchî.",
+"uploadwarning" => "Adviertixhmint so l'&nbsp;eberwetaedje",
+"savefile"             => "Schaper l'&nbsp;fitchî",
+"uploadedimage" => "eberwetaedje di «[[$1]]»",
+
+# Image list
+#
+"imagelist"            => "Djivêye des imådjes",
+"imagelisttext"        => "Chal pa dzo c'&nbsp;est ene djivêye di $1 imådjes relîtes $2.",
+"getimagelist" => "fetching image list", # co a fé
+"ilsubmit"             => "Cweri",
+"showlast"             => "Mostrer les $1 dierinnès imådjes relîtes $2.",
+"byname"               => "påzès nos",
+"bydate"               => "pazès dates",
+"bysize"               => "pa grandeu",
+"imgdelete"            => "oist.",
+"imgdesc"              => "disc.",
+"imglegend"            => "Ledjinde: (disc.) = håyner/candjî l'&nbsp;discrijhaedje di l'&nbsp;imådje.",
+"imghistory"   => "Istwere di l'&nbsp;imådje",
+"revertimg"            => "mod.",
+"deleteimg"            => "oist.",
+"deleteimgcompletely"          => "oist.",
+"imghistlegend" => "Ledjinde: (ast.) = c'&nbsp;est l'&nbsp;imådje k'&nbsp;i gn a asteure, (oist.) = oister (disfacer)
+cisse viye modêye la, (mod.) = rivni a cisse viye modêye la.
+<br /><i>Clitchîz sol date po vey l'&nbsp;imådje evoyeye a cisse date la.</i>",
+"imagelinks"   => "Loyéns viè ciste imådje chal",
+"linkstoimage" => "Les pådjes shuvantes eployèt ciste imådje chal:",
+"nolinkstoimage" => "I n'&nbsp;a nole pådje k'&nbsp;eploye ciste imådje chal.",
+
+# Statistics
+#
+"statistics"   => "Sitatistikes",
+"sitestats"            => "Sitatistikes del waibe",
+"userstats"            => "Sitatistikes des uzeus",
+"sitestatstext" => "I gn a <b>$1</b> pådjes å totå el båze di dnêyes.
+Çoula tot contant les pådjes di «Copenes», les pådjes å dfait di Wikipedia,
+les pådjes «stub» (pådjes sins waire di contnou), les redjiblaedjes,
+eyet co ds ôtes ki n'&nbsp;sont nén vormint des årtikes.
+Si on n'&nbsp;conte nén ces la, i gn a <b>$2</b> pådjes ki sont
+probåblumint des vraiys årtikes.<p>
+I gn a-st avou å totå <b>$3</b> riwaitaedjes di pådjes, eyet <b>$4</b>
+candjmints do contnou des pådjes dispoy li 20 di djulete 2003.
+Dj'&nbsp;ô bén k'&nbsp;i gn a ene moyene di <b>$5</b> candjmints par pådje,
+eyet <b>$6</b> riwaitaedjes po on candjmint.",
+"userstatstext" => "I gn a <b>$1</b> uzeus d'&nbsp;eredjîstrés.
+<b>$2</b> di zels sont eto des manaedjeus (riloukîz a $3).
+
+<p><h2>Des ôtes pus spepieusès statistikes</h2><p>
+Des pus spepieusès statistikes åd dilong des moes sont
+<a href='/stats/WA/Sitemap.htm' class='internal'>chal</a>.
+", # NOTE: loyén viè les statistikes
+
+# Maintenance Page
+#
+"maintenance"          => "Pådje di manaedjmint",
+"maintnancepagetext"   => "Cisse pådje chal a sacwantès ahessåvès usteyes
+po manaedjî les årtikes. Sacwantes di ces fonccions chal polèt esse
+sitréndåves pol båze di dnêyes, do côp on vs dimandrè di n'&nbsp;nén
+clitchî sol boton «rafrister» di vosse betchteu a tchaeke côp
+ki vos fjhoz on ptit candjmint ;-)",
+"maintenancebacklink"  => "Rivni al pådje di manaedjmint",
+"disambiguations"      => "Pådjes d'&nbsp;omonimeye",
+"disambiguationspage"  => "Wikipedia:Loyéns_viè_les_pådjes_d'_omonimeye",
+"disambiguationstext"  => "Les årtikes shuvants ont des loyéns viè en <i>pådje d'&nbsp;omonimeye</i>. I dvrént purade loyî viè l'&nbsp;bon årtike.<br />
+Ene pådje est considerêye come pådje d'&nbsp;omonimeye si elle aparexhe e $1.<br />
+Les loyéns a pårti d'&nbsp;ôtes espåces di lomaedje èn sont <i>nén</i> håynés chal.",
+"doubleredirects"      => "Dobes redjiblaedjes",
+"doubleredirectstext"  => "<b>Asteme:</b> Cisse djivêye chal pout aveur des fås pôzitifs. Dj'&nbsp;ô bén k'&nbsp;i pout aveur do tecse di pus, avou des loyéns, après li prumî «#REDIRECT».<br />\n
+Tchaeke roye a-st on loyén viè l'&nbsp;prumî eyet l'&nbsp;deujhinme redjiblaedje, avou on mostraedje del prumire roye do tecse do deujhinme redjiblaedje, çou ki å pus sovint dene li «vraiy» årtike såme, ki l'&nbsp;prumî redjiblaedje dvreut evoyî viè lu.",
+"brokenredirects"      => "Pierdous redjiblaedjes",
+"brokenredirectstext"  => "Les redjiblaedjes shuvants evoyèt so ene pådje ki n'&nbsp;egzistêye nén.",
+"selflinks"            => "Pådjes avou des loyéns viè zeles minmes",
+"selflinkstext"                => "Les pådjes shuvantes ont on loyén viè zeles minmes, çou ki n'&nbsp;si dvreut nén fé.",
+"mispeelings"           => "Pådjes avou des flotches",
+"mispeelingstext"               => "Les pådjes shuvantes ont ene ou sacwante
+flotche, di cenes metowes so $1. Li scrijhaedje corek pout esse mostré inte
+åtchetes a costé do mot må scrît.",
+"mispeelingspage"       => "Djivêye des flotches les pus corantes",
+"missinglanguagelinks"  => "Loyéns di lingaedjes ki mankèt",
+"missinglanguagelinksbutton"    => "Trover les loyéns di lingaedjes ki mankèt po",
+"missinglanguagelinkstext"      => "Ces årtikes chal èn loynut <i>nén</i> viè leu-z omologues so «$1». Les redjiblaedjes eyet les dzo-pådjes èn sont <i>nén</i> mostrêyes.",
+
+
+# Miscellaneous special pages
+#
+"orphans"              => "Pådjes ôrfulinnes",
+"lonelypages"  => "Pådjes ôrfulinnes",
+"unusedimages" => "Imådjes nén eployeyes",
+"popularpages" => "Pådjes les pus léjhowes",
+"nviews"               => "léjhowe $1 côps",
+"wantedpages"  => "Pådjes les pus rcwerowes",
+"nlinks"               => "$1 loyéns",
+"allpages"             => "Totes les pådjes",
+"randompage"   => "Årtike a l'&nbsp;astcheyance", # TODO: trop longou?
+"shortpages"   => "Coûtès pådjes",
+"longpages"            => "Longowès pådjes",
+"listusers"            => "Djivêye des uzeus",
+"specialpages" => "Pådjes sipeciåles",
+"spheading"            => "Pådjes sipeciåles po tos ls uzeus",
+"protectpage"  => "Protedjî l'&nbsp;pådje",
+"recentchangeslinked" => "Candjmints aloyîs",
+"rclsub"               => "(ezès pådjes ki «$1» a-st on loyén dzeu)",
+"debug"                        => "Disbugaedje",
+"newpages"             => "Novelès pådjes",
+"ancientpages"         => "Viyådjes",
+"intl"         => "Loyéns eterlingaedjes",
+"movethispage" => "Displaecî cisse pådje",
+"unusedimagestext" => "<p>Notez tot l'&nbsp;minme ki d'&nbsp;ôtès waibes,
+come li cenes des ôtes Wikipedias, polèt aveur des loyéns viè ces imådjes la
+gråcès a ene direke hårdêye. Do côp, ces imådjes aparexhèt chal, mågré
+k'&nbsp;ele soeyexhe eployeyes.",
+"booksources"  => "Sourdants po les lives",
+"booksourcetext" => "Chal pa dzo c'&nbsp;est ene djivêye di hårdêyes viè
+des waibes ki vindèt des lives, noûs ou di deujhinme mwin, et ki polèt
+aveur pus d'&nbsp;informåcions å dfait des lives ki vos cweroz après.
+{{SITENAME}} n'&nbsp;a rén a vey avou ces eterprijhes la, eyet cisse djivêye
+chal èn doet nén esse veyowe come èn aspoya ou nerén ene reclame.",
+"alphaindexline" => "di $1 a $2",
+
+# Email this user
+#
+"mailnologin"  => "Nole adresse d'&nbsp;evoyeu",
+"mailnologintext" => "Po-z evoyî èn emile a èn ôte uzeu i vs fåt esse [[Sipeciås:Userlogin|elodjî]]
+eyet aveur ene adresse emile d'&nbsp;evoyeu ki soeye valide
+dins vos [[Sipeciås:Preferences|preferinces]].",
+"emailuser"            => "Emiler a l'&nbsp;uzeu",
+"emailpage"            => "Emilaedje a èn uzeu",
+"emailpagetext"        => "Si cist uzeu chal a dné ene adresse emile valide dins
+ses preferins, vos lyi ploz evoyî èn emile a pårti di cisse pådje chal.
+L'&nbsp;adresse emile k'&nbsp;i gn a dins vos preferinces serè-st eployeye
+come adresse di l'&nbsp;evoyeu (adresse «From:» di l'&nbsp;emile),
+po ki l'&nbsp;riçuveu poye risponde.",
+"noemailtitle" => "Pont d'&nbsp;adresse emile",
+"noemailtext"  => "Cist uzeu chal n'&nbsp;a nén dné d'&nbsp;adresse emile
+valide, ou n'&nbsp;vout nén rçure des emiles des ôtes uzeus.
+Do côp, c'&nbsp;est nén possibe di lyi evoyî èn emile.",
+"emailfrom"            => "Di",
+"emailto"              => "Po",
+"emailsubject" => "Sudjet",
+"emailmessage" => "Messaedje",
+"emailsend"            => "Evoyî",
+"emailsent"            => "Emile evoyî",
+"emailsenttext" => "Vost emilaedje a stî evoyî comifåt.",
+
+# Watchlist
+#
+"watchlist"            => "Mes pådjes shuvowes",
+"watchlistsub" => "(po l'&nbsp;uzeu «$1»)",
+"nowatchlist"  => "Vosse djivêye des pådjes a shuve est vude.",
+"watchnologin" => "Vos n'&nbsp;estoz nén elodjî",
+"watchnologintext"     => "I vs fåt esse [[Sipeciås:Userlogin|elodjî]]
+po pleur candjî vosse djivêye des pådjes a shuve.",
+"addedwatch"   => "Radjouté ås shuvous",
+"addedwatchtext" => "Li pådje «$1» a stî radjoutêye a vosse <a href=\"" .
+  "{{localurle:Sipeciås:Watchlist}}\">djivêye des pådjes a shuve</a>.
+Tos les candjmints k'&nbsp;i gn årè di cisse pådje chal, eyet di si pådje
+di copene, seront håynés chal, eyet li pådje serè metowe e <b>cråssès letes</b>
+el <a href=\"" .
+  "{{localurle:Sipeciås:Recentchanges}}\">djivêye des dierins candjmints</a> po k'&nbsp;ça soeye pus åjhey por vos del rimårker.</p>
+<p>
+Si vos vloz bodjî l'&nbsp;pådje foû di vosse djivêye des shuvous,
+clitchîz so «Èn pus shuve li pådje» dins l'&nbsp;bår di menu sol costé.",
+"removedwatchtext" => "Li pådje «$1» a stî bodjeye foû di vosse djivêye des pådjes a shuve.",
+"watchthispage"        => "Shuve cisse pådje",
+"unwatchthispage" => "Èn pus shuve li pådje",
+"notanarticle" => "Nén èn årtike",
+"watchnochange" => "Nole des pådjes di vosse djivêye di pådjes a shuve n'&nbsp;a stî candjeye dins l'&nbsp;termene di tins dmandêye.",
+"watchdetails" => "($1 pådjes shuvowes, sins conter les pådjes di copene;
+$2 total pages edited since cutoff;
+$3...
+[$4 mostrer eyet candjî l'&bsp;djivêye etire].)", # co a fé
+"watchmethod-recent" => "checking recent edits for watched pages", # co a fé
+"watchmethod-list" => "checking watched pages for recent edits", # co a fé
+"removechecked" => "Bodjî les cayets tchoezis foû del djivêye des pådjes a shuve",
+"watchlistcontains" => "I gn a $1 pådjes e vossse djivêye des pådjes a shuve.",
+"watcheditlist" => "Here's an alphabetical list of your
+watched pages. Check the boxes of pages you want to remove
+from your watchlist and click the 'remove checked' button
+at the bottom of the screen.", # co a fé
+"removingchecked" => "Removing requested items from watchlist...", # co a fé
+"couldntremove" => "Couldn't remove item '$1'...", # co a fé
+"iteminvalidname" => "Åk n'&nbsp;a nén stî avou «$1», no nén valide...",
+"wlnote" => "Chal pa dzo les $1 dierins candjmints des <b>$2</b> dierinnès eures.",
+"wlshowlast" => "Mostrer les dierin(nè)s $1 eures, $2 djoûs $3",
+
+
+# Delete/protect/revert
+#
+"deletepage"   => "Disfacer l'&nbsp;pådje",
+"confirm"              => "Acertiner",
+"excontent" => "li contnou esteut: '$1'",
+"exbeforeblank" => "li contnou dvant l'&nbsp;disfaçaedje esteut: '$1'",
+"exblank" => "li pådje esteut vude",
+"confirmdelete" => "Acertinaedje do disfaçaedje",
+"deletesub"            => "(Djisfaçaedje di «$1»)",
+"historywarning" => "Adviertixhmint: Li pådje ki vos alez disfacer a-st ene istwere: ",
+"confirmdeletetext" => "Vos alez disfacer po tofer del båze di dnêyes ene
+pådje ou ene imådje, avou tote si istwere.
+Acertinez s'&nbsp;i vs plait ki c'&nbsp;est bén çoula ki vos vloz fé,
+ki vos comprindoz les consecwinces, et ki vos fjhoz çoula
+tot [[Wikipedia:Rîles a shure|shuvant les rîles]].",
+"actioncomplete" => "Fwait",
+"deletedtext"  => "Li pådje «$1» a stî disfacêye. Loukîz li $2 po ene
+djivêye des dierins disfaçaedjes.",
+"deletedarticle" => "pådje «$1» disfacêye",
+"dellogpage"   => "Djournå_des_disfaçaedjes",
+"dellogpagetext" => "Chal pa dzo c'&nbsp;est l'&nbsp;djivêye des dierins
+disfaçaedjes. Totes les dates et eures sont-st e tins univiersel (UTC).
+<ul>
+</ul>
+",
+"deletionlog"  => "djournå des disfaçaedjes",
+"reverted"             => "Rimetou ene modêye di dvant",
+"deletecomment"        => "Råjhon do disfaçaedje",
+"imagereverted" => "Li rmetaedje del modêye di dvant a stî comifåt.",
+"rollback"             => "Roll back edits", # co a fé
+"rollbacklink" => "rollback", # co a fé
+"rollbackfailed" => "Rollback failed", # co a fé
+"cantrollback" => "Cannot revert edit; last contributor is only author of this article.", # co a fé
+"alreadyrolled"        => "Cannot rollback last edit of [[$1]]
+by [[Uzeu:$2|$2]] ([[Uzeu copene:$2|Copene]]); someone else has edited or rolled back the article already.
+
+Li dierin candjmint a stî fwait pa [[Uzeu:$3|$3]] ([[Uzeu copene:$3|Copene]]). ",
+#   only shown if there is an edit comment
+"editcomment" => "The edit comment was: \"<i>$1</i>\".", # co a fé
+"revertpage"   => "Rivnou å dierin candjmint da $1",
+"protectlogpage" => "Protection_log", # co a fé
+"protectlogtext" => "Chal pa dzo c'&nbsp;est ene djivêye des protedjaedjes
+et disprotedjaedjes des pådjes.
+Loukîz [[{{ns:4}}:Pådje protedjeye]] po pus di racsegnes.",
+"protectedarticle" => "[[$1]] protedjî",
+"unprotectedarticle" => "[[$1]] disprotedjî",
+
+# Undelete
+"undelete" => "Rapexhî des disfacêyès pådjes",
+"undeletepage" => "Vey et rapexhî des disfacêyès pådjes",
+"undeletepagetext" => "Les pådjes shuvantes ont stî disfacêyes mins ele sont
+co ezès årtchives, do côp ele polèt esse rapexheyes.
+Les årtchives sont netieyes di tins en tins.",
+"undeletearticle" => "Rapexhî on disfacé årtike",
+"undeleterevisions" => "$1 modêyes ezès årtchives",
+"undeletehistory" => "Si vos rapexhîz l'&nbsp;pådje, l'&nbsp;istwere del pådje
+serè rapexheye eto, avou totes les modêyes co ezès årtchives.
+Si ene novele pådje avou l'&nbsp;minme a stî askepieye dispoy li disfaçaedje
+di cisse chal, les rapexheyès modêyes seront metowes e l'&nbsp;istwere mins
+c'&nbsp;est l'&nbsp;modêye do moumint, et nén l'&nbsp;cisse rapexheye, ki
+srè håynêye.",
+"undeleterevision" => "Modêye disfacêye li $1",
+"undeletebtn" => "Rapexhî!",
+"undeletedarticle" => "a rapexhî l'&nbsp;pådje «$1»",
+"undeletedtext"   => "L'&nbsp;årtike [[$1]] a stî rapexhî comifåt.
+Loukîz [[Wikipedia:Djournå_des_disfaçaedjes]] po ene djivêye des dierins
+disfaçaedjes eyet rapexhaedjes.",
+
+# Contributions
+#
+"contributions"        => "Ovraedjes di l'&nbsp;uzeu", /* TODO: problinme di longeu */
+"mycontris" => "Mes contribucions",
+"contribsub"   => "Po l'&nbsp;uzeu $1",
+"nocontribs"   => "Nou candjmint di trové ki corespondreut a ç'&nbsp;critere la.",
+"ucnote"               => "Chal pa dzo les <b>$1</b> dierins candjmints di l'&nbsp;uzeu so les <b>$2</b> dierins djoûs.",
+"uclinks"              => "Vey les $1 dierins candjmints; vey les $2 dierins djoûs.",
+"uctop"                => " (top)" ,
+
+# What links here
+#
+"whatlinkshere"        => "Pådjes ki loynut chal",
+"notargettitle" => "No target", # co a fé
+"notargettext" => "You have not specified a target page or user
+to perform this function on.", # co a fé
+"linklistsub"  => "(Djivêye des loyéns)",
+"linkshere"            => "Les pådjes ki shuvèt ont des loyéns viè cisse ci:",
+"nolinkshere"  => "Nole pådje avou des loyéns viè cisse ci.",
+"isredirect"   => "pådje di redjiblaedje",
+
+# Block/unblock IP
+#
+"blockip"              => "Bloker èn uzeu",
+"blockiptext"  => "Use the form below to block write access
+from a specific IP address or username.
+This should be done only only to prevent vandalism, and in
+accordance with [[Wikipedia:Rîles a shure|{{SITENAME}} policy]].
+Fill in a specific reason below (for example, citing particular
+pages that were vandalized).", # co a fé
+"ipaddress"            => "Adresse IP/no d'&nbsp;uzeu",
+"ipbreason"            => "Råjhon",
+"ipbsubmit"            => "Bloker cist uzeu",
+"badipaddress" => "Nol uzeu avou ç'&nbsp;no la.",
+"blockipsuccesssub" => "Li blocaedje a stî comifåt",
+"blockipsuccesstext" => "«$1» a stî bloké.
+<br />Loukîz li [[Sipeciås:Ipblocklist|Djivêye des blocaedjes]] po candjî on blocaedje.",
+"unblockip"            => "Disbloker èn uzeu",
+"unblockiptext"        => "Use the form below to restore write access
+to a previously blocked IP address.", # co a fé
+"ipusubmit"            => "Unblock this address", # co a fé
+"ipusuccess"   => "«%s» a stî disbloké",
+"ipblocklist"  => "Djivêye d'&nbsp;adresses IP et di nos d'&nbsp;uzeus ki sont blokés",
+"blocklistline"        => "$1, $2 a bloké $3 ($4)",
+"blocklink"            => "bloker",
+"unblocklink"  => "disbloker",
+"contribslink" => "contribs", # co a fé
+"autoblocker"  => "Bloké otomaticmint paski vos eployîz li minme adresse IP ki «%s». Råjhon do blocaedje «%s».",
+"blocklogpage" => "Block_log", # co a fé
+"blocklogentry"        => '«$1» a stî bloké',
+"blocklogtext" => "This is a log of user blocking and unblocking actions. Automatically
+blocked IP addresses are not be listed. See the [[Special:Ipblocklist|IP block list]] for
+the list of currently operational bans and blocks.", # co a fé
+"unblocklogentry"      => '«$1» a stî disbloké',
+
+# Developer tools
+#
+"lockdb"               => "Lock database", # co a fé
+"unlockdb"             => "Unlock database", # co a fé
+"lockdbtext"   => "Locking the database will suspend the ability of all
+users to edit pages, change their preferences, edit their watchlists, and
+other things requiring changes in the database.
+Please confirm that this is what you intend to do, and that you will
+unlock the database when your maintenance is done.", # co a fé
+"unlockdbtext" => "Unlocking the database will restore the ability of all
+users to edit pages, change their preferences, edit their watchlists, and
+other things requiring changes in the database.
+Please confirm that this is what you intend to do.", # co a fé
+"lockconfirm"  => "Yes, I really want to lock the database.", # co a fé
+"unlockconfirm"        => "Yes, I really want to unlock the database.", # co a fé
+"lockbtn"              => "Lock database", # co a fé
+"unlockbtn"            => "Unlock database", # co a fé
+"locknoconfirm" => "You did not check the confirmation box.", # co a fé
+"lockdbsuccesssub" => "Database lock succeeded", # co a fé
+"unlockdbsuccesssub" => "Database lock removed", # co a fé
+"lockdbsuccesstext" => "The database has been locked.
+<br />Remember to remove the lock after your maintenance is complete.", # co a fé
+"unlockdbsuccesstext" => "The database has been unlocked.", # co a fé
+
+# Move page
+#
+"movepage"             => "Displaecî l'&nbsp;pådje",
+"movepagetext" => "Chal vos ploz candjî l'&nbsp;no d'&nbsp;ene pådje,
+dj'&nbsp;ô bén displaecî l'&nbsp;pådje, eyet si istwere, viè l'&nbsp;novea no.
+Li vî tite divénrè-st ene pådje di redjiblaedje viè l'&nbsp;novele/
+Les loyéns viè l'&nbsp;viye pådje èn seront nén candjîs; acertinez vs di
+verifyî s'&nbsp;i n'&nbsp;a nén des dobes
+ou crons redjiblaedjes.
+Vos estoz responsåve di fé çou k'&nbsp;i fåt po k'&nbsp;les loyéns
+continouwexhe di moenner la k'&nbsp;i fåt.
+
+Notez k'anbsp;el pådje èn serè '''nén''' displaeceye s'anbsp;i gn a ddja ene
+pådje avou l'&nbsp;novea tite, a moens k'&nbsp;ele soeye vude, ou ene pådje
+di redjiblaedje, et k'&nbsp;ele n'&nbsp;åye nole istwere.
+Çoula vout dire ki vos ploz ri-displaecî ene pådje viè l'&nbsp;no k'&nbsp;ele
+aveut djusse divant, et insi disfé vosse prumî displaeçaedje, å cas ou vos vs
+rindrîz conte ki vos avoz fwait ene flotche; ey eto ki vos n'&nbsp;poloz nén
+spotchî par accidint ene pådje k'&nbsp;egzistêye dedja.
+
+<b>ASTEME!</b>
+On displaeçaedje pout esse on consecant et nén atindou candjmint po ene
+pådje foirt léjhowe; s'&nbsp;i vs plait tuzez bén åzès consecwinces divant
+d'&nbsp;continouwer.",
+"movepagetalktext" => "Li pådje di copene associeye, s'&nbsp;end a ene, serè
+displaeceye otomaticmint avou, '''a moens ki:'''
+*Vos displaecîz l'&nbsp;pådje d'&nbsp;èn espåce di lomaedje a èn ôte,
+*Ene pådje di copene nén vude egzistêye dedja dizo l'&nbsp;novea no,
+*Vos disclitchrîz l'&nbsp;boesse a clitchî chal pa dzo.
+
+Dins ces cas la, vos dvroz displaecî l'&nbsp;pådje di copene al mwin, ou rcopyî
+si contnou, si vos l'&nbsp;vloz mete adlé l'&nbsp;novea no
+d'&nbsp;l'&nbsp;årtike.",
+"movearticle"  => "Displaecî di",
+"movenologin"  => "Nén elodjî",
+"movenologintext" => "I vs fåt esse èn uzeu eredjîstré eyet esse [[Sipeciås:Userlogin|elodjî]] por vos
+pleur displaecî ene pådje.",
+"newtitle"             => "Viè l'&nbsp;novea tite",
+"movepagebtn"  => "Displaecî",
+"pagemovedsub" => "Li displaeçaedje a stî comifåt",
+"pagemovedtext" => "Li pådje «[[$1]]» a stî displaeceye viè «[[$2]]».",
+"articleexists" => "Ene pådje egzistêye dedja avou ç'&nbsp;no la, oudonbén
+li no k'&nbsp;vos avoz tchoezi n'&nbsp;est nén valide.
+Tchoezixhoz è èn ôte s'&nbsp;i vs plait.",
+"talkexists"   => "The page itself was moved successfully, but the
+talk page could not be moved because one already exists at the new
+title. Please merge them manually.", # co a fé
+"movedto"              => "displaecî viè",
+"movetalk"             => "Displaecî li pådje di copene avou, si ça astchait.",
+"talkpagemoved" => "Li pådje di copene corespondante a stî displaeceye avou.",
+"talkpagenotmoved" => "Li pådje di copene corespondante n'&nbsp;a <strong>nén</strong> stî displaeceye.",
+
+"export"               => "Export pages", # co a fé
+"exporttext"   => "You can export the text and editing history of a particular
+page or set of pages wrapped in some XML; this can then be imported into another
+wiki running MediaWiki software, transformed, or just kept for your private
+amusement.", # co a fé
+"exportcuronly"        => "Inclure fok li modêye do moumint, nén tote l'&nbsp;istwere",
+
+# Namespace 8 related
+
+"allmessages"  => "Tos les messaedjes",
+"allmessagestext"      => "Çouchal est ene djivêye di tos les messaedjes k'&nbsp;i gn a dins l'&nbsp;espåce di lomaedje ''MediaWiki:''",
+
+# Math
+
+'mw_math_png' => "Håyner tofer come ene imådje PNG",
+'mw_math_simple' => "Håyner en HTML si c'&nbsp;est foirt simpe, ôtmint e PNG",
+'mw_math_html' => "Håyner en HTML si c'&nbsp;est possibe, ôtmint e PNG",
+'mw_math_source' => "El leyî e TeX (po les betchteus e môde tecse)",
+'mw_math_modern' => "Ricmandé po les betchteus modienes",
+);
+
+#--------------------------------------------------------------------------
+# Internationalisation code
+#--------------------------------------------------------------------------
+
+class LanguageWa extends LanguageUtf8 {
+
+       function getNamespaces() {
+               global $wgNamespaceNamesWa;
+               return $wgNamespaceNamesWa;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsWa;
+               return $wgQuickbarSettingsWa;
+       }
+
+       function getDateFormats() {
+               global $wgDateFormatsWa;
+               return $wgDateFormatsWa;
+       }
+
+
+       ###
+       ### Dates in Walloon are "1î d' <monthname>" for 1st of the month,
+       ### "<day> di <monthname>" for months starting by a consoun, and
+       ### "<day> d' <monthname>" for months starting with a vowel
+       ###
+       function date( $ts, $adj = false ) {
+               global $wgAmericanDates, $wgUser, $wgUseDynamicDates;
+
+               if ( $adj ) { $ts = $this->userAdjust( $ts ); }
+
+               $m = substr( $ts, 4, 2 );
+               $n = substr( $ts, 6, 2 );
+
+               if ($n == 1) {
+                   $d = "1î d'&nbsp;" . $this->getMonthName( $m ) .
+                       " " .  substr( $ts, 0, 4 );
+               } else if ($n == 2 || $n == 3 || $n == 20 || $n == 22 || $n == 23) {
+                   $d = (0 + $n) . " d'&nbsp;" . $this->getMonthName( $m ) .
+                       " " .  substr( $ts, 0, 4 );
+               } else if ($m == 4 || $m == 8 || $m == 10) {
+                   $d = (0 + $n) . " d'&nbsp;" . $this->getMonthName( $m ) .
+                       " " .  substr( $ts, 0, 4 );
+               } else {
+                   $d = (0 + $n) . " di " . $this->getMonthName( $m ) .
+                       " " .  substr( $ts, 0, 4 );
+               }
+
+               return $d;
+       }
+
+       function time( $ts, $adj = false ) {
+               if ( $adj ) { $ts = $this->userAdjust( $ts ); }
+
+               $t = substr( $ts, 8, 2 ) . ":" . substr( $ts, 10, 2 );
+               return $t;
+       }
+
+       function timeanddate( $ts, $adj = false ) {
+               #return $this->time( $ts, $adj ) . " " . $this->date( $ts, $adj );
+               return $this->date( $ts, $adj ) . " a " . $this->time( $ts, $adj );
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesWa;
+
+               if(array_key_exists($key, $wgAllMessagesWa))
+                       return $wgAllMessagesWa[$key];
+               else
+                       return parent::getMessage($key);
+       }
+
+       function getAllMessages() {
+               global $wgAllMessagesWa;
+               return $wgAllMessagesWa;
+       }
+
+}
+
+?>
diff --git a/languages/LanguageYi.php b/languages/LanguageYi.php
new file mode 100644 (file)
index 0000000..5912320
--- /dev/null
@@ -0,0 +1,24 @@
+<?php
+/** Yiddish (ייִדיש)
+  *
+  * @package MediaWiki
+  * @subpackage Language
+  */
+
+require_once( 'LanguageUtf8.php' );
+
+class LanguageYi extends LanguageUtf8 {
+
+       function getDefaultUserOptions() {
+               $opt = parent::getDefaultUserOptions();
+               $opt['quickbar'] = 2; # Right-to-left
+               return $opt;
+       }
+
+       # For right-to-left language support
+       function isRTL() {
+               return true;
+       }
+}
+
+?>
diff --git a/languages/LanguageZh.php b/languages/LanguageZh.php
new file mode 100644 (file)
index 0000000..f2052ee
--- /dev/null
@@ -0,0 +1,103 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+require_once( "LanguageConverter.php" );
+require_once( "LanguageZh_cn.php");
+require_once( "LanguageZh_tw.php");
+require_once( "LanguageZh_sg.php");
+require_once( "LanguageZh_hk.php");
+
+class ZhConverter extends LanguageConverter {
+       function loadDefaultTables() {
+               require( "includes/ZhConversion.php" );
+               $this->mTables = array();
+               $this->mTables['zh-cn'] = $zh2CN;
+               $this->mTables['zh-tw'] = $zh2TW;
+               $this->mTables['zh-sg'] = array_merge($zh2CN, $zh2SG);
+               $this->mTables['zh-hk'] = array_merge($zh2TW, $zh2HK);
+               $this->mTables['zh'] = array();
+       }
+
+       function postLoadTables() {
+               $this->mTables['zh-sg'] = array_merge($this->mTables['zh-cn'], $this->mTables['zh-sg']);
+               $this->mTables['zh-hk'] = array_merge($this->mTables['zh-tw'], $this->mTables['zh-hk']);
+    }
+
+       /* there shouldn't be any latin text in Chinese conversion, so no need
+          to mark anything
+    */
+       function markNoConversion($text) {
+               return $text;
+       }
+
+       function convertCategoryKey( $key ) {
+               return $this->autoConvert( $key, 'zh-cn' );
+       }
+}
+
+
+/* class that handles both Traditional and Simplified Chinese
+   right now it only distinguish zh_cn, zh_tw, zh_sg and zh_hk.
+*/
+class LanguageZh extends LanguageZh_cn {
+
+       function LanguageZh() {
+               global $wgHooks;
+               $this->mConverter = new ZhConverter($this, 'zh',
+                                            array('zh', 'zh-cn', 'zh-tw', 'zh-sg', 'zh-hk'),
+                                                                                       array('zh'=>'zh-cn',
+                                                                                                 'zh-cn'=>'zh-sg',
+                                                                                                 'zh-sg'=>'zh-cn',
+                                                                                                 'zh-tw'=>'zh-hk',
+                                                                                                 'zh-hk'=>'zh-tw'));
+               $wgHooks['ArticleSaveComplete'][] = $this->mConverter;
+       }
+
+
+       # this should give much better diff info
+       function segmentForDiff( $text ) {
+               return preg_replace(
+                       "/([\\xc0-\\xff][\\x80-\\xbf]*)/e",
+                       "' ' .\"$1\"", $text);
+       }
+
+       function unsegmentForDiff( $text ) {
+               return preg_replace(
+                       "/ ([\\xc0-\\xff][\\x80-\\xbf]*)/e",
+                       "\"$1\"", $text);
+       }
+
+       // word segmentation
+       function stripForSearch( $string ) {
+               $fname="LanguageZh::stripForSearch";
+               wfProfileIn( $fname );
+
+               // eventually this should be a word segmentation
+               // for now just treat each character as a word
+               $t = preg_replace(
+                               "/([\\xc0-\\xff][\\x80-\\xbf]*)/e",
+                               "' ' .\"$1\"", $string);
+
+        //always convert to zh-cn before indexing. it should be
+               //better to use zh-cn for search, since conversion from
+               //Traditional to Simplified is less ambiguous than the
+               //other way around
+
+               $t = $this->mConverter->autoConvert($t, 'zh-cn');
+               $t = LanguageUtf8::stripForSearch( $t );
+               wfProfileOut( $fname );
+               return $t;
+
+       }
+
+       function convertForSearchResult( $termsArray ) {
+               $terms = implode( '|', $termsArray );
+               $terms = implode( '|', $this->mConverter->autoConvertToAllVariants( $terms ) );
+               $ret = array_unique( explode('|', $terms) );
+               return $ret;
+       }
+
+}
+?>
diff --git a/languages/LanguageZh_cn.php b/languages/LanguageZh_cn.php
new file mode 100644 (file)
index 0000000..4892c5a
--- /dev/null
@@ -0,0 +1,972 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+require_once( "LanguageUtf8.php" );
+
+/* private */ $wgNamespaceNamesZh_cn = array(
+       NS_MEDIA            => "Media",
+       NS_SPECIAL          => "Special",
+       NS_MAIN             => "",
+       NS_TALK             => "Talk",
+       NS_USER             => "User",
+       NS_USER_TALK        => "User_talk",
+       NS_PROJECT          => $wgMetaNamespace,
+       NS_PROJECT_TALK     => $wgMetaNamespace . "_talk",
+       NS_IMAGE            => "Image",
+       NS_IMAGE_TALK       => "Image_talk",
+       NS_MEDIAWIKI        => "MediaWiki",
+       NS_MEDIAWIKI_TALK   => "MediaWiki_talk",
+       NS_TEMPLATE         => "Template",
+       NS_TEMPLATE_TALK    => "Template_talk",
+       NS_HELP             => "Help",
+       NS_HELP_TALK        => "Help_talk",
+       NS_CATEGORY         => "Category",
+       NS_CATEGORY_TALK    => "Category_talk"
+
+) + $wgNamespaceNamesEn;
+
+/* private */ $wgQuickbarSettingsZh_cn = array(
+       "无", /* "None" */
+       "左侧固定", /* "Fixed left" */
+       "右侧固定", /* "Fixed right" */
+       "左侧漂移" /* "Floating left" */
+);
+
+/* private */ $wgSkinNamesZh_cn = array(
+       'standard' => "标准",
+       'nostalgia' => "怀旧",
+       'cologneblue' => "科隆香水蓝"
+) + $wgSkinNamesEn;
+
+/* private */ $wgUserTogglesZh_cn = array(
+       'nolangconversion',
+) + $wgUserTogglesEn;
+
+
+/* private */ $wgAllMessagesZh_cn = array(
+# User Toggles
+
+"tog-underline" => "下划链接", /* "Underline links", */
+/* "Format broken links <a href=\"\" class=\"new\">like this</a> (alternative: like this<a href=\"\" class=\"internal\">?</a>).", */
+"tog-highlightbroken" => "毁坏链接格式<a href=\"\" class=\"new\">像这样</a> (或者像这个<a href=\"\" class=\"internal\">?</a>)",
+"tog-justify"  => "段落对齐", /* "Justify paragraphs", */
+"tog-hideminor" => "最近更改中隐藏细微修改", /* "Hide minor edits in recent changes", */
+"tog-usenewrc" => "最近更改增强(只适用部分浏览器)", /* "Enhanced recent changes (not for all browsers)", */
+"tog-numberheadings" => "标题自动编号",
+"tog-showtoolbar" => "Show edit toolbar", /* "Auto-number headings", */
+"tog-editondblclick" => "双击页面编辑(JavaScript)",
+"tog-editsection"=>"允许通过点击[编辑]链接编辑段落",
+"tog-editsectiononrightclick"=>"允许右击标题编辑段落(JavaScript)",
+"tog-showtoc"=>"显示目录<br />(针对一页超过3个标题的文章)",
+"tog-rememberpassword" => "下次登陆记住密码", /* "Remember password across sessions", */
+"tog-editwidth" => "编辑栏位宽度", /* "Edit box has full width", */
+"tog-editondblclick" => "双击编辑页面(Javascript)", /* "Edit pages on double click (JavaScript)", */
+"tog-watchdefault" => "监视新的以及更改过的文章", /* "Watch new and modified articles", */
+"tog-minordefault" => "细微编辑为默认设置", /* "Mark all edits minor by default", */
+"tog-previewontop" => "在编辑框上方显示预览", /* "Show preview before edit box and not after it" */
+# Dates
+
+'sunday' => "星期日",
+'monday' => "星期一",
+'tuesday' => "星期二",
+'wednesday' => "星期三",
+'thursday' => "星期四",
+'friday' => "星期五",
+'saturday' => "星期六",
+'january' => "1月",
+'february' => "2月",
+'march' => "3月",
+'april' => "4月",
+'may_long' => "5月",
+'june' => "6月",
+'july' => "7月",
+'august' => "8月",
+'september' => "9月",
+'october' => "10月",
+'november' => "11月",
+'december' => "12月",
+'jan' => "1月",
+'feb' => "2月",
+'mar' => "3月",
+'apr' => "4月",
+'may' => "5月",
+'jun' => "6月",
+'jul' => "7月",
+'aug' => "8月",
+'sep' => "9月",
+'oct' => "10月",
+'nov' => "11月",
+'dec' => "12月",
+
+# Bits of text used by many pages:
+#
+"categories" => "页面分类",
+        "category" => "分类",
+        "category_header" => "类别”$1“中的条目",
+        "subcategories" => "附分类",
+"linktrail"            => "/^([a-z]+)(.*)\$/sD",
+"mainpage"             => "首页",
+"about"                        => "关于",
+"aboutsite"      => "关于Wikipedia",
+"aboutpage"            => "Wikipedia:关于",
+"help"                 => "帮助",
+"helppage"             => "Wikipedia:帮助",
+"bugreports"   => "错误报告",
+"bugreportspage" => "Wikipedia:错误报告",
+"faq"                  => "常见问题解答",
+"faqpage"              => "Wikipedia:常见问题解答",
+"edithelp"             => "编辑帮助",
+"edithelppage" => "Wikipedia:如何编辑页面",
+"cancel"               => "取消",
+"qbfind"               => "寻找",
+"qbbrowse"             => "浏览",
+"qbedit"               => "编辑",
+"qbpageoptions" => "页面选项",
+"qbpageinfo"   => "页面信息",
+"qbmyoptions"  => "我的选项",
+"mypage"               => "我的页面",
+"mytalk"               => "我的对话页",
+"currentevents" => "新闻动态",
+"errorpagetitle" => "错误",
+"returnto"             => "返回到$1.",
+"tagline"              => "Wikipedia,自由的百科全书",
+"whatlinkshere"        => "链入页面",
+"help"                 => "帮助",
+"search"               => "搜索",
+"go"           => "进入",
+"history"              => "较早版本",
+"printableversion" => "可打印版",
+"editthispage" => "编辑本页",
+"deletethispage" => "删除本页",
+"protectthispage" => "保护本页",
+"unprotectthispage" => "解除保护",
+"newpage" => "新页面",
+"talkpage"             => "讨论本页",
+        "postcomment"   => "发表评论",
+"articlepage"  => "查看文章",
+"subjectpage"  => "查看主题", # For compatibility
+"userpage" => "查看用户页",
+"wikipediapage" => "查看meta页",
+"imagepage" =>         "查看图像页面",
+"viewtalkpage" => "查看讨论",
+"otherlanguages" => "其它语言",
+"redirectedfrom" => "(重定向自$1)",
+"lastmodified" => "最后更改$1.",
+"viewcount"            => "本页面已经被浏览$1次。",
+"printsubtitle" => "(来自 {{SERVER}})",
+"protectedpage" => "被保护页",
+"administrators" => "Wikipedia:管理员",
+"sysoptitle"   => "需要管理员权限",
+"sysoptext"            => "您刚才的请求只有拥有管理员权限的用户才可使用。
+参见$1。",
+"developertitle" => "需要发展者权限",
+"developertext"        => "您刚才的请求只有拥有发展者权限的用户才可使用。
+参见$1。",
+"nbytes"               => "$1字节",
+"go"                   => "进入",
+"ok"                   => "OK",
+"sitetitle"            => "Wikipedia",
+"sitesubtitle" => "自由的百科全书",
+"retrievedfrom" => "取自\"$1\"",
+"newmessages" => "您有$1。",
+"newmessageslink" => "新信息",
+ "editsection"=>"编辑",
+ "toc" => "目录",
+"showtoc" => "显示",
+        "hidetoc" => "隐藏",
+
+# Main script and global functions
+#
+"nosuchaction" => "没有这个命令",
+"nosuchactiontext" => "URL请求的命令无法被 Wikipedia 软件识别。",
+"nosuchspecialpage" => "没有这个特殊页。",
+
+"nospecialpagetext" => "您请求的页面无法被 Wikipedia 软件识别。",
+
+# General errors
+#
+"error"                        => "错误",
+"databaseerror" => "数据库错误",
+"dberrortext"  => "数据库指令语法错误。
+这可能是由于非法搜索指令所引起的(见 $5),
+也可能是由于软件自身的错误所引起。
+最后一次数据库指令是:
+<blockquote><tt>$1</tt></blockquote>
+来自于函数 \"<tt>$2</tt>\"。
+MySQL返回错误 \"<tt>$3: $4</tt>\"。",
+"noconnect"            => "无法在 $1上连接数据库",
+"nodb"                 => "无法选择数据库 $1",
+"readonly"             => "数据库禁止访问",
+"enterlockreason" => "请输入禁止访问原因, 包括估计重新开放的时间",
+"readonlytext" => "Wikipedia数据库目前禁止输入新内容及更改,
+这很可能是由于数据库正在维修,之后即可恢复。
+管理员有如下解释:
+<p>$1",
+"missingarticle" => "数据库找不到文字\"$1\"。
+
+<p>通常这是由于修订历史页上过时的链接到已经被删除的页面所导致的。
+
+<p>如果情况不是这样,您可能找到了软件内的一个臭虫。
+请记录下URL地址,并向管理员报告。",
+"internalerror" => "内部错误",
+"filecopyerror" => "无法复制文件\"$1\"到\"$2\"。",
+"filerenameerror" => "无法重命名文件\"$1\" 到\"$2\"。",
+"filedeleteerror" => "无法删除文件 \"$1\"。",
+"filenotfound" => "找不到文件 \"$1\"。",
+"unexpected"   => "不正常值: \"$1\"=\"$2\"。",
+"formerror"            => "错误:无法提交表单",
+"badarticleerror" => "无法在本页上进行此项操作。",
+"cannotdelete" => "无法删除选定的页面或图像(它可能已经被其他人删除了)。",
+"badtitle"             => "错误的标题",
+"badtitletext" => "所请求页面的标题是无效的、不存在,跨语言或跨wiki链接的标题错误。",
+"perfdisabled" => "抱歉!由于此项操作有可能造成数据库瘫痪,目前暂时无法使用。",
+"perfdisabledsub" => "这里是自$1的复制版本:",
+
+# 登录与登出
+#
+"logouttitle"  => "用户退出",
+"logouttext"   => "您现在已经退出。
+您可以继续以匿名方式使用Wikipeida,或再次以相同或不同用户身份登录。\n",
+
+"welcomecreation" => "<h2>欢迎,$1!</h2><p>您的帐号已经建立,不要忘记设置Wikipedia个人参数。",
+
+"loginpagetitle" => "用户登录",
+"yourname"             => "您的用户名",
+"yourpassword" => "您的密码",
+"yourpasswordagain" => "再次输入密码",
+"newusersonly" => "(仅限新用户)",
+"remembermypassword" => "下次登录记住密码。",
+"loginproblem" => "<b>登录有问题。</b><br />再试一次!",
+"alreadyloggedin" => "<strong>用户$1,您已经登录了!</strong><br />\n",
+
+"login"                        => "登录",
+"userlogin"            => "用户登录",
+"logout"               => "退出",
+"userlogout"   => "用户退出",
+"createaccount"        => "创建新帐号",
+ "createaccountmail"     => "通过eMail",
+"badretype"            => "你所输入的密码并不相同。",
+"userexists"   => "您所输入的用户名已有人使用。请另选一个。",
+"youremail"            => "您的电子邮件*",
+"yournick"             => "绰号(签名时用)",
+"emailforlost" => "* 输入一个电邮地址并不是必须的。但是这将允许他人在您未告知的情况下通过电子邮件与您联系,如果您忘了密码的话电邮地址也会有帮助。",
+"loginerror"   => "登录错误",
+"noname"               => "你没有输入一个有效的用户名。",
+"loginsuccesstitle" => "登录成功",
+"loginsuccess" => "你现在以 \"$1\"的身份登录Wikipedia。",
+"nosuchuser"   => "找不到用户 \"$1\"。
+检查您的拼写,或者用下面的表格建立一个新帐号。",
+"wrongpassword"        => "您输入的密码错误,请再试一次。",
+"mailmypassword" => "将新密码寄给我",
+"passwordremindertitle" => "Wikipedia密码提醒",
+"passwordremindertext" => "有人(可能是您,来自IP地址$1)要求我们将新的Wikipedia登录密码寄给你。
+用户 \"$2\" 的密码现在是 \"$3\"。
+请立即登录并更改密码。",
+"noemail"              => "用户\"$1\"没有登记电子邮件地址。",
+"passwordsent" => "用户\"$1\"的新密码已经寄往所登记的电子邮件地址。
+请在收到后再登录。",
+
+# 编辑
+#
+"summary"              => "简述",
+"subject"               => "主题",
+"minoredit"            => "这是一个小修改",
+"watchthis"            => "监视本页",
+"savearticle"  => "保存本页",
+"preview"              => "预览",
+"showpreview"  => "显示预览",
+"blockedtitle" => "用户被封",
+"blockedtext"  => "您的用户名或IP地址已被$1封。
+理由是:<br />'''$2'''<p>您可以与$1向其他任何[[Wikipedia:管理员|管理员]]询问。",
+ "whitelistedittitle" => "登录后才可编辑",
+        "whitelistedittext" => "您必须先[[Special:Userlogin|登录]]才可编辑页面。",
+        "whitelistreadtitle" => "登录后才可阅读",
+        "whitelistreadtext" => "您必须先[[Special:Userlogin|登录]]才可阅读页面。",
+        "whitelistacctitle" => "您被禁止建立帐号",
+        "whitelistacctext" => "在本Wiki中建立帐号您必须先[[Special:Userlogin|登录]]并拥有相关权限。",
+        "accmailtitle" => "密码寄出",
+        "accmailtext" => "'$1'的密码已经寄到$2。",
+"newarticle"   => "(新)",
+"newarticletext" =>
+"您从一个链接进入了一个并不存在的页面。
+要创建该页面,请在下面的编辑框中输入内容(详情参见Wikipedia:帮助|帮助页面]])。
+如果您不小心来到本页面,直接点击您浏览器中的“返回”按钮。",
+
+"anontalkpagetext" => "---- ''这是一个还未建立帐号的匿名用户的对话页。我们因此只能用[[IP地址]]来与他/她联络。该IP地址可能由几名用户共享。如果您是一名匿名用户并认为本页上的评语与您无关,请[[Special:Userlogin|创建新帐号或登录]]以避免在未来于其他匿名用户混淆。''",
+"noarticletext" => "(本页目前没有内容)",
+"updated"              => "(已更新)",
+"note"                 => "<strong>注意:</strong> ",
+"previewnote"  => "请记住这只是预览,内容还未保存!",
+"previewconflict" => "这个预览显示了上面文字编辑区中的内容。它将在你选择保存后出现。",
+"editing"              => "正在编辑$1",
+"editingsection"       => "正在编辑$1 (段落)",
+"editingcomment"       => "正在编辑$1 (评论)",
+"editconflict" => "编辑冲突:$1",
+"explainconflict" => "有人在你开始编辑后更改了页面。
+上面的文字框内显示的是目前本页的内容。
+你所做的修改显示在下面的文字框中。
+你应当将你所做的修改加入现有的内容中。
+<b>只有</b>在上面文字框中的内容会在你点击\"保存页面\"后被保存。<br />",
+"yourtext"             => "您的文字",
+"storedversion" => "已保存版本",
+"editingold"   => "<strong>警告:你正在编辑的是本页的旧版本。
+如果你保存它的话,在本版本之后的任何修改都会丢失。</strong>",
+"yourdiff"             => "差别",
+"copyrightwarning" => "请注意对Wikipedia的任何贡献都将被认为是在GNU自由文档协议证书下发布。
+(细节请见$1).
+如果您不希望您的文字被任意修改和再散布,请不要提交。<br />
+您同时也向我们保证你所提交的内容是你自己所作,或得自一个不受版权保护或相似自由的来源。
+<strong>不要在未获授权的情况下发表!</strong>",
+
+"longpagewarning" => "<strong>警告:本页长度达$1KB;一些浏览器将无法编辑长过32KB的文章。请考虑将本文切割成几个小段落。</strong>",
+
+"readonlywarning" => "<strong>警告:数据库被锁以进行维护,所以您目前将无法保存您的修改。您或许希望先将本断文字复制并保存到文本文件,然后等一会儿再修改。</strong>",
+"protectedpagewarning" => "<strong>警告:本页已经被保护,只有拥有管理员权限的用户才可修改。请确认您遵守
+[[Project:Protected_page_guidelines|保护页面守则]].</strong>",
+
+# History pages
+#
+"revhistory"   => "修订历史",
+"nohistory"            => "没有本页的修订记录。",
+"revnotfound"  => "没有找到修订记录",
+"revnotfoundtext" => "您请求的更早版本的修订记录没有找到。
+请检查您请求本页面用的 URL 是否正确。\n",
+"loadhist"             => "载入页面修订历史",
+"currentrev"   => "当前修订版本",
+"revisionasof" => "$1的修订版本",
+"cur"                  => "当前",
+"next"                 => "后继",
+"last"                 => "先前",
+"orig"                 => "初始",
+"histlegend"   => "说明:(当前)指与当前修订版本比较;(先前)指与前一个修订版本比较,小 指细微修改。",
+
+# Diffs
+#
+"difference"   => "(修订版本间差异)",
+"loadingrev"   => "载入修订版本比较",
+"lineno"               => "第 $1 行:",
+"editcurrent"  => "编辑本页的当前修订版本",
+
+# Search results
+#
+"searchresults" => "搜索结果",
+"searchresulttext" => "有关搜索{{SITENAME}}的更多详情,参见[[Project:搜索|搜索{{SITENAME}}]]。",
+"searchquery"  => "查询\"$1\"",
+"badquery"             => "搜索查询不正确",
+"badquerytext" => "我们无法处理您的查询。
+这可能是由于您试图搜索一个短于3个字母的外文单词,
+或者您错误地输入了搜索项,例如\"汽车和和火车\"。
+请再尝试一个新的搜索项。",
+"matchtotals"  => "搜索项\"$1\"与$2条文章的题目相符,和$3条文章相符。",
+
+"nogomatch" => "没有文章与搜索项完全匹配,请尝试完整文字搜索。",
+"titlematches" => "文章题目相符",
+"notitlematches" => "没有找到匹配文章题目",
+"textmatches"  => "文章内容相符",
+"notextmatches"        => "没有文章内容匹配",
+
+"prevn"                        => "先前$1",
+"nextn"                        => "之后$1",
+"viewprevnext" => "查看 ($1) ($2) ($3).",
+"showingresults" => "下面显示<b>$1</b>条结果,从第<b>$2</b>条开始",
+"nonefound"            => "<strong>注意:</strong>失败的搜索往往是由于试图搜索诸如“的”或“和”之类的常见字所引起。",
+"powersearch" => "搜索",
+"powersearchtext" => "
+搜索名字空间:<br />$1<br />$2列出重定向页面;搜索$3 $9",
+
+"searchdisabled" => "<p>Wikipedia内部搜索功能由于高峰时段服务器超载而停止使用。
+您可以暂时通过
+<a href=\"http://google.com/\">google</a>搜索Wikipedia。
+谢谢您的耐心。",
+
+# Preferences page
+#
+"preferences"  => "参数设置",
+"prefsnologin" => "还未登录",
+"prefsnologintext"     => "您必须先[[Special:Userlogin|登录]]才能设置个人参数。",
+"prefslogintext" => "你已经以\"$1\"的身份登录。
+你的内部ID是$2。",
+"prefsreset"   => "参数重新设置。",
+"qbsettings"   => "快速导航条设置",
+"changepassword" => "更改密码",
+"skin"                 => "Skin",
+"math"                 => "数学显示",
+"math_failure"         => "无法解析",
+"math_unknown_error"   => "未知错误",
+"math_unknown_function"        => "未知函数",
+"math_lexing_error"    => "句法错误",
+"math_syntax_error"    => "语法错误",
+"saveprefs"            => "保存参数设置",
+"resetprefs"   => "重设参数",
+"oldpassword"  => "旧密码",
+"newpassword"  => "新密码",
+"retypenew"            => "重复新密码",
+"textboxsize"  => "文字框尺寸",
+"rows"                 => "行",
+"columns"              => "列",
+"searchresultshead" => "搜索结果设定",
+"resultsperpage" => "每页显示链接数",
+"contextlines" => "每链接行数",
+"contextchars" => "每行字数",
+"stubthreshold" => "stub显示基本限制",
+"recentchangescount" => "最近更改页行数",
+"savedprefs"   => "您的个人参数设置已经保存。",
+"timezonetext" => "输入当地时间与服务器时间(UTC)的时差。",
+"localtime"    => "当地时间",
+"timezoneoffset" => "差",
+"emailflag"            => "禁止其他用户发e-mail给我",
+
+# Recent changes
+#
+"changes" => "更改",
+"recentchanges" => "最近更改",
+"recentchangestext" => "本页跟踪Wikipedia内最新的更改。
+[[Wikipedia:欢迎,新来者|欢迎,新来者]]!
+请参见这些页面:[[wikipedia:常见问题解答|Wikipedia常见问题解答]]、
+[[Wikipedia:守则与指导|Wikipedia守则]]
+(特别是[[wikipedia:命名常规|命名常规]]、
+[[wikipedia:中性的观点|中立观点]])
+和[[wikipedia:最常见失礼行为|最常见失礼行为]]。
+
+如果您希望 Wikipedia 成功,那么请您不要增加受其它[[wikipedia:版权信息|版权]]
+限制的材料,这一点将非常重要。相关的法律责任会伤害本项工程,所以请不要这样做。
+此外请参见
+[http://meta.wikipedia.org/wiki/Special:Recentchanges 最近的 meta 讨论]。",
+
+"rcloaderr"            => "载入最近更改",
+"rcnote"               => "下面是最近<strong>$2</strong>天内最新的<strong>$1</strong>次改动。",
+"rcnotefrom"   => "下面是自<b>$2</b>(最多显示<b>$1</b>)。",
+"rclistfrom"   => "显示自$1以来的新更改",
+"rclinks"              => "显示最近 $2 天内最新的 $1 次改动。<br />$3",
+"rchide"               => "以$4形式;$1个小修改;$2个二级名字空间;$3个多重修改",
+"diff"                 => "差异",
+"hist"                 => "历史",
+"hide"                 => "隐藏",
+"show"                 => "显示",
+"tableform"            => "表格",
+"listform"             => "列表",
+"nchanges"             => "$1个更改",
+"minoreditletter" => "小",
+"newpageletter" => "新",
+
+# Upload
+#
+"upload"               => "上载文件",
+"uploadbtn"            => "上载文件",
+"uploadlink"   => "上载图像",
+"reupload"             => "重新上载",
+"reuploaddesc" => "返回上载表单。",
+"uploadnologin" => "未登录",
+"uploadnologintext"    => "您必须先[[Special:Userlogin|登录]]
+才能上载文件。",
+"uploaderror"  => "上载错误",
+"uploadtext"   => "'''停止!'''在您上载之前,请先阅读并遵守Wikipedia
+[[Project:Image use policy|图像使用守则]]。
+
+如果您要查看或搜索之前上载的图像,
+请到[[Special:Imagelist|已上载图像列表]].
+所有上载与删除行为都被记录在
+[[Project:上载纪录|上载纪录]]内。
+
+使用下面的表单来上载用在条目内新的图像文件。
+在绝大多数浏览器内,你会看到一个\"浏览...\"按钮,点击它后就会跳出一个打开文件对话框。
+选择一个文件后文件名将出现在按钮旁边的文字框中。
+您也必须点击旁边的复选框确认您所上载的文件并没有违反相关版权法律。
+点击\"上载\" 按钮完成上载程序。
+如果您使用的是较慢的网络连接的话那么这个上载过程会需要一些时间。
+
+我们建议照相图片使用JPEG格式,绘图及其他图标图像使用PNG格式,音像则使用OGG格式。
+请使用具有描述性的语言来命名您的文件以避免混乱。
+要在文章中加入图像,使用以下形式的连接:
+'''<nowiki>[[图像:file.jpg]]</nowiki>'''或者
+'''<nowiki>[[图像:file.png|解释文字]]</nowiki>'''
+或'''<nowiki>[[media:file.ogg]]</nowiki>'''来连接音像文件。
+
+请注意在Wikipedia页面中,其他人可能会为了百科全书的利益而编辑或删除您的上载文件,
+而如果您滥用上载系统,您则有可能被禁止使用上载功能。",
+"uploadlog"            => "上载纪录",
+"uploadlogpage" => "上载纪录",
+"uploadlogpagetext" => "以下是最近上载的文件的一览表。
+所有显示的时间都是服务器时间(UTC)。
+<ul>
+</ul>
+",
+"filename"             => "文件名",
+"filedesc"             => "简述",
+"copyrightpage" => "Wikipedia:版权信息",
+"copyrightpagename" => "Wikipedia版权",
+"uploadedfiles"        => "已上载文件",
+"ignorewarning"        => "忽略警告并保存文件。",
+"minlength"            => "图像名字必须至少有三个字母。",
+"badfilename"  => "图像名已被改为\"$1\"。",
+"badfiletype"  => "\".$1\"不是所推荐的图像文件格式。",
+"largefile"            => "我们建议图像大小不超过100kb。",
+"successfulupload" => "上载成功",
+"fileuploaded" => "文件\"$1\"上载成功。
+请根据连接($2)到图像描述页添加有关文件信息,例如它的来源,在何时由谁创造,
+以及其他任何您知道的关于改图像的信息。",
+"uploadwarning" => "上载警告",
+"savefile"             => "保存文件",
+"uploadedimage" => "已上载\"[[$1]]\"",
+
+# Image list
+#
+"imagelist"            => "图像列表",
+"imagelisttext"        => "以下是按$2排列的$1幅图像列表。",
+"getimagelist" => "正在获取图像列表",
+"ilsubmit"             => "搜索",
+"showlast"             => "显示按$2排列的最后$1幅图像。",
+"byname"               => "名字",
+"bydate"               => "日期",
+"bysize"               => "大小",
+"imgdelete"            => "删",
+"imgdesc"              => "述",
+"imglegend"            => "说明:(述) = 显示/编辑图像描述页。",
+"imghistory"   => "图像历史",
+"revertimg"            => "复",
+"deleteimg"            => "删",
+"deleteimgcompletely"          => "删",
+"imghistlegend" => "egend: (现) = 目前的图像,(删) = 删除旧版本,
+(复) = 恢复到旧版本。
+<br /><i>点击日期查看当天上载的图像</i>.",
+"imagelinks"   => "图像链接",
+
+"linkstoimage" => "以下页面连接到本图像:",
+"nolinkstoimage" => "没有页面连接到本图像。",
+
+# Statistics
+#
+"statistics"   => "统计",
+"sitestats"            => "站点统计",
+"userstats"            => "用户统计",
+"sitestatstext" => "数据库中共有 <b>$1</b> 页页面;
+其中包括对话页、关于 Wikipedia 的页面、最少量的\"stub\"页、重定向的页面,
+以及未达到条目质量的页面;除此之外还有 <b>$2</b> 页可能是合乎标准的条目。
+<p>从系统软件升级以来,全站点共有页面浏览 <b>$3</b> 次,
+页面编辑 <b>$4</b> 次,每页平均编辑 <b>$5</b> 次,
+各次编辑后页面的每个版本平均浏览 <b>$6</b> 次。",
+
+# Maintenance Page
+#
+"maintenance"          => "维护页",
+"maintnancepagetext"   => "这页面提供了几个帮助Wikipedia日常维护的工具。
+但其中几个会对我们的数据库造成压力,
+所以请您不要在每修理好几个项目后就按重新载入 ;-)",
+"maintenancebacklink"  => "返回维护页",
+"disambiguations"      => "消含糊页",
+"disambiguationspage"  => "Wikipedia:Links_to_disambiguating_pages",
+"disambiguationstext"  => "以下的条目都有到消含糊页的链接,但它们应该是链到适当的题目。<br />一个页面会被视为消含糊页如果它是链自$1.<br />由其它他名字空间来的链接<i>不会</i>在这儿被列出来。",
+"doubleredirects"      => "双重重定向",
+"doubleredirectstext"  => "<b>请注意:</b> 这列表可能包括不正确的反应。
+这通常表示在那页面第一个#REDIRECT之下还有文字。<br />\n
+每一行都包含到第一跟第二个重定向页的链接,以及第二个重定向页的第一行文字,
+通常显示的都会是\“真正\” 的目标页面,也就是第一个重定向页应该指向的条目。",
+"brokenredirects"      => "损坏的重定向页",
+"brokenredirectstext"  => "以下的重定向页指向的是不存在的条目。",
+"selflinks"            => "有自我链接的页面",
+"selflinkstext"                => "以下的页面都错误地包含了连到自己的链接。",
+"mispeelings"           => "拼写错误的页面",
+"mispeelingstext"               => "以下页面包含了一些常见的拼写错误(见$1)。正确的拼法已经给出。",
+"mispeelingspage"       => "常见拼写错误列表",
+"missinglanguagelinks"  => "无语言链接",
+"missinglanguagelinksbutton"    => "寻找没有该语言的页面",
+"missinglanguagelinkstext"      => "这些条目<i>没有</i>链接到$1。
+重定向页与副页<b>并没有</b>包括在内。",
+
+
+# Miscellaneous special pages
+#
+"orphans"              => "孤立条目",
+"lonelypages"  => "孤立页面",
+"unusedimages" => "未使用图像",
+"popularpages" => "热点条目",
+"nviews"               => "$1次浏览",
+"wantedpages"  => "待撰页面",
+"nlinks"               => "$1个链接",
+"allpages"             => "所有页面",
+"randompage"   => "随机页面",
+"shortpages"   => "短条目",
+"longpages"            => "长条目",
+"listusers"            => "用户列表",
+"specialpages" => "特殊页面",
+"spheading"            => "特殊页面",
+"protectpage"  => "保护页面",
+"recentchangeslinked" => "链出更改",
+"rclsub"               => "(从 \"$1\"链出的页面)",
+"debug"                        => "除错",
+"newpages"             => "新页面",
+"intl"         => "跨语言链接",
+"movethispage" => "移动本页",
+"unusedimagestext" => "<p>请注意其他网站(例如其他语言版本的Wikipedia)
+有可能直接链接本图像,所以这里列出的图像有可能依然被使用。",
+"booksources"  => "战外书源",
+"booksourcetext" => "以下是链接到销售书籍的网站列表,
+因此有可能拥有您所寻找的图书的进一步资料。
+Wikipedia与这些公司并没有任何商业关系,因此本表不应该
+被看作是一种背书。",
+"alphaindexline" => "$1 到 $2",
+
+# Email this user
+#
+"mailnologin"  => "无电邮地址",
+"mailnologintext" => "您必须先[[Special:Userlogin|登录]]
+并在[[Special:Preferences|参数设置]]
+中有一个有效的e-mail地址才可以电邮其他用户。",
+"emailuser"            => "E-mail该用户",
+"emailpage"            => "E-mail用户",
+"emailpagetext"        => "如果该用户已经在他或她的参数设置页中输入了有效的e-mail地址,以下的表格将寄一个信息给该用户。您在您参数设置中所输入的e-mail地址将出现在邮件“发件人”一栏中,这样该用户就可以回复您。",
+"noemailtitle" => "无e-mail地址",
+"noemailtext"  => "该用户还没有指定一个有效的e-mail地址,
+或者选择不接受来自其他用户的e-mail。",
+
+"emailfrom"            => "发件人",
+"emailto"              => "收件人",
+"emailsubject" => "主题",
+"emailmessage" => "信息",
+"emailsend"            => "发送",
+"emailsent"            => "E-mail已发送",
+"emailsenttext" => "您的e-mail已经发出。",
+
+# Watchlist
+#
+"watchlist"            => "监视列表",
+"watchlistsub" => "(用户\"$1\")",
+"nowatchlist"  => "您的监视列表为空。",
+"watchnologin" => "未登录",
+"watchnologintext"     => "您必须先[[Special:Userlogin|登录]]
+才能更改您的监视列表",
+"addedwatch"   => "加入到监视列表",
+"addedwatchtext" => "本页(“$1”)已经被加入到您的<a href=\"" .
+  "{{localurle:Special:Watchlist}}\">监视列表</a>中。
+未来有关它或它的对话页的任何修改将会在本页中列出,
+而且还会在<a href=\"" .
+  "{{localurle:Special:Recentchanges}}\">最近更改列表</a>中
+以<b>粗体</b>形式列出。</p>
+
+<p>如果您之后想将该页面从监视列表中删除,点击导航条中的“停止监视”链接。",
+"removedwatch" => "停止监视",
+"removedwatchtext" => "页面“$1”已经从您的监视页面中移除。",
+"watchthispage"        => "监视本页",
+"unwatchthispage" => "停止监视",
+"notanarticle" => "不是条目",
+        "watchnochange" => "在显示的时间段内您所监视的页面没有更改。",
+        "watchdetails" => "($1个页面(不含对话页)被监视;
+        总共$2个页面被编辑;
+        $3...
+        [$4 显示并编辑完整列表].)",
+        "watchmethod-recent" => "检查被监视页面的最近编辑",
+        "watchmethod-list" => "checking watched pages for recent edits",
+        "removechecked" => "将被选页面从监视列表中移除",
+        "watchlistcontains" => "您的监视列表包含$1个页面。",
+        "watcheditlist" => "这里是您所监视的页面的列表。要移除某一页面,只要选择该页面然后点击”移除页面“按钮。",
+        "removingchecked" => "移除页面...",
+        "couldntremove" => "无法移除'$1'...",
+        "iteminvalidname" => "页面'$1'错误,无效命名...",
+        "wlnote" => "以下是最近<b>$2</b>小时内的最后$1次修改。",
+
+# Delete/protect/revert
+#
+"deletepage"   => "删除页面",
+"confirm"              => "确认",
+"confirmdelete" => "确认删除",
+"deletesub"            => "(正在删除“$1”)",
+"confirmdeletetext" => "您即将从数据库中永远删除一个页面或图像以及其历史。
+请确定您要进行此项操作,并且了解其后果,同时您的行为符合[[Wikipedia:守则与指导]]。
+",
+"actioncomplete" => "操作完成",
+"deletedtext"  => "“$1”已经被删除。
+最近删除的纪录请参见$2。",
+"deletedarticle" => "已删除“$1”",
+
+"dellogpage"   => "删除纪录",
+"dellogpagetext" => "以下是最近删除的纪录列表。
+所有的时间都是使用服务器时间(UTC)。
+<ul>
+</ul>
+",
+"deletionlog"  => "删除纪录",
+"reverted"             => "恢复到早期版本",
+"deletecomment"        => "删除理由",
+"imagereverted" => "恢复到早期版本操作完成。",
+"rollback"             => "Roll back",
+"rollbacklink" => "rollback",
+"cantrollback" => "无法恢复编辑;最后的巩县者是本文的唯一作者。",
+"revertpage"   => "恢复到$1的最后一次编辑",
+
+# Undelete
+"undelete" => "恢复被删页面",
+"undeletepage" => "浏览及恢复被删页面",
+"undeletepagetext" => "以下页面已经被删除,但依然在档案中并可以被恢复。
+档案库可能被定时清理。",
+"undeletearticle" => "恢复被删文章",
+"undeleterevisions" => "$1版本存档",
+"undeletehistory" => "如果您恢复了该页面,所有版本都会被恢复到修订历史中。
+如果本页删除后有一个同名的新页面建立,
+被恢复的版本将会称为较新的历史,而新页面的当前版本将无法被自动复原。",
+"undeleterevision" => "删除$1时的版本",
+"undeletebtn" => "恢复!",
+"undeletedarticle" => "已经恢复“$1”",
+"undeletedtext"   => "[[$1]]已经被成功复原。
+有关Wikipedia最近的删除与复原,参见[[Wikipedia:删除纪录]]",
+
+# Contributions
+#
+"contributions"        => "用户贡献",
+"mycontris" => "我的贡献",
+"contribsub"   => "为$1",
+"nocontribs"   => "没有找到符合特征的更改。",
+"ucnote"               => "以下是该用户最近<b><$2/b>天内的最后<b>$1</b>次修改。",
+"uclinks"              => "参看最后$1次修改;参看最后$2天。",
+"uctop"                => " (顶)" ,
+
+# What links here
+#
+"whatlinkshere"        => "链入页面",
+"notargettitle" => "无目标",
+"notargettext" => "您还没有指定一个目标页面或用户以进行此项操作。",
+"linklistsub"  => "(链接列表)",
+"linkshere"            => "以下页面链接到这里:",
+"nolinkshere"  => "没有页面链接到这里。",
+"isredirect"   => "重定向页",
+
+# Block/unblock IP
+#
+"blockip"              => "查封IP地址",
+"blockiptext"  => "用下面的表单来禁止来自某一特定IP地址的修改权限。
+只有在为防止破坏,及符合[[Wikipedia:守则与指导]]的情况下才可采取此行动。
+请在下面输入一个具体的理由(例如引述一个被破坏的页面)。",
+"ipaddress"            => "IP地址",
+"ipbreason"            => "原因",
+"ipbsubmit"            => "查封该地址",
+"badipaddress" => "IP地址不正确。",
+"blockipsuccesssub" => "查封成功",
+"blockipsuccesstext" => "IP地址“$1”已经被查封。
+<br />参看[[Special:被封IP地址列表|被封IP地址列表]]以复审查封。",
+"unblockip"            => "解除禁封IP地址",
+"unblockiptext"        => "用下面的表单来恢复先前被禁封的IP地址的书写权。",
+"ipusubmit"            => "解除禁封",
+"ipusuccess"   => "IP地址“$1”已经被解除禁封",
+"ipblocklist"  => "被封IP地址列表",
+"blocklistline"        => "$1,$2禁封$3 ($4)",
+"blocklink"            => "禁封",
+"unblocklink"  => "解除禁封",
+"contribslink" => "贡献",
+
+# Developer tools
+#
+"lockdb"               => "禁止更改数据库",
+"unlockdb"             => "开放更改数据库",
+"lockdbtext"   => "锁住数据库将禁止所有用户进行编辑页面、更改参数、编辑监视列表以及其他需要更改数据库的操作。
+请确认您的决定,并且保证您在维护工作结束后会重新开放数据库。",
+"unlockdbtext" => "开放数据库将会恢复所有用户进行编辑页面、修改参数、编辑监视列表以及其他需要更改数据库的操作。
+请确认您的决定。",
+"lockconfirm"  => "是的,我确实想要封锁数据库。",
+"unlockconfirm"        => "是的,我确实想要开放数据库。",
+"lockbtn"              => "数据库上锁",
+"unlockbtn"            => "开放数据库",
+"locknoconfirm" => "您并没有勾选确认按钮。",
+"lockdbsuccesssub" => "数据库成功上锁",
+
+"unlockdbsuccesssub" => "数据库开放",
+"lockdbsuccesstext" => "Wikipedia数据库已经上锁。
+<br />请记住在维护完成后重新开放数据库。",
+"unlockdbsuccesstext" => "Wikipedia数据库重新开放。",
+
+# Move page
+#
+"movepage"             => "移动页面",
+"movepagetext" => "用下面的表单来重命名一个页面,并将其修订历史同时移动到新页面。
+老的页面将成为新页面的重定向页。
+链接到老页面的链接并不会自动更改;
+请检查双重或损坏重定向链接。
+您应当负责确定所有链接依然会链到指定的页面。
+
+注意如果新页面已经有内容的话,页面将'''不会'''被移动,
+除非新页面无内容或是重定向页,而且没有修订历史。
+这意味着您再必要时可以在移动到新页面后再移回老的页面,
+同时您也无法覆盖现有页面。
+
+<b>警告!</b>
+对一个经常被访问的页面而言这可能是一个重大与唐突的更改;
+请在行动前先了结其所可能带来的后果。",
+"movepagetalktext" => "有关的对话页(如果有的话)将被自动与该页面一起移动,'''除非''':
+*您将页面移动到不同的名字空间(namespaces);
+*新页面已经有一个包含内容的对话页,或者
+*您不勾选下面的复选框。
+
+在这些情况下,您在必要时必须手工移动或合并页面。",
+"movearticle"  => "移动页面",
+"movenologin"  => "未登录",
+"movenologintext" => "您必须是一名登记用户并且[[Special:Userlogin|登录]]
+后才可移动一个页面。",
+"newtitle"             => "新标题",
+"movepagebtn"  => "移动页面",
+"pagemovedsub" => "移动成功",
+"pagemovedtext" => "页面“[[$1]]”已经移动到“[[$2]]”。",
+"articleexists" => "该名字的页面已经存在,或者您选择的名字无效。请再选一个名字。",
+"talkexists"   => "页面本身移动成功,
+但是由于新标题下已经有对话页存在,所以对话页无法移动。请手工合并两个页面。",
+"movedto"              => "移动到",
+"movetalk"             => "如果可能的话,请同时移动对话页。",
+"talkpagemoved" => "相应的对话页也已经移动。",
+"talkpagenotmoved" => "相应的对话页<strong>没有</strong>被移动。",
+
+# Math
+
+'mw_math_png' => "永远使用PNG图像",    /* "Always render PNG" */
+'mw_math_simple' => "如果是简单的公式使用HTML,否则使用PNG图像",   /* "HTML if very simple or else PNG" */
+'mw_math_html' => "如果可以用HTML,否则用PNG图像",   /* "HTML if possible or else PNG" */
+'mw_math_source' => "显示为TeX代码(使用文字浏览器时)",  /* "Leave it as TeX (for text browsers)" */
+'mw_math_modern' => "推荐为新版浏览器使用",  /* "Recommended for modern browsers" */
+
+# some untranslated messages as of 1.4 beta1
+'1movedto2' => "$1移动到$2", //"$1 moved to $2",
+'1movedto2_redir' => "$1重定向到$2", //"$1 moved to $2 over redirect",
+'acct_creation_throttle_hit' => "对不起,您已经注册了$1账号。你不能再注册了。", //"Sorry, you have already created $1 accounts. You can't make any more.",
+'addgroup' => "增加新的组", //"Add Group",
+'allarticles' => "所有条目", //"All articles",
+'allmessages' => "系统界面", //"All system messages",
+'allmessagesnotsupportedDB' => "系统界面功能处于关闭状态 (wgUseDatabaseMessages)。", //"Special:AllMessages not supported because wgUseDatabaseMessages is off.",
+'allmessagestext' => "这里列出所有可定制的系统界面。", //"This is a list of all system messages available in the MediaWiki: namespace.",
+'allinnamespace' => "所有 $1 名字空间的条目", //"All pages ($1 namespace)",
+'allpagesnext' => "下一页", //"Next",
+'allpagesprev' => "上一页", //"Previous",
+'allpagessubmit' => "提交", //"Go",
+'ancientpages' => "老条目", //"Oldest pages",
+'and' => "和", //"and",
+'anontalk' => "该IP的对话页", //"Talk for this IP",
+'anonymous' => "匿名用户", //"Anonymous user(s) of 1.4",
+'article' => "条目", //"Content page",
+'autoblocker' => "你的IP和被封了的 \"$1\" 是一样的。封锁原因: \"$2\".",//"Autoblocked because you share an IP address with \"$1\". Reason \"$2\".",
+'blocklogentry' => "封锁 $1, $2",//"blocked \"$1\" with an expiry time of $2",
+'blocklogpage' => "封锁记录", //"Block_log",
+'categoriespagetext' => "以下列出所有的页面分类。", //"The following categories exists in the wiki.",
+'categoryarticlecount' => "该类页面共有 $1 条目", //There are $1 articles in this category.",
+'clearyourcache' => "'''注意:''' 保存设置后,要清掉浏览器的缓存才能生效:'''Mozilla:''' ''Ctrl-Shift-R'', '''Internet Explorer:''' ''Ctrl-F5'', '''Safari:''' ''Cmd-Shift-R'', '''Konqueror:''' ''F5''。",
+'edit' => "编辑", //"Edit",
+'navigation' => "导航", //"Navigation",
+'nstab-category' => "分类", //"Category",
+'nstab-help' => "帮助",//"Help",
+'nstab-image' => "图像",//"Image",
+'nstab-main' => "条目", //"Article",
+'nstab-mediawiki' => "界面",//"Message",
+'nstab-special' => "特殊",//"Special",
+'nstab-template' => "模板", //"Template",
+'nstab-user' => "用户页面", //"User page",
+'nstab-wp' => "关于", //"About",
+'portal' => "社区",//"Community portal",
+'prefs-help-realname' => "*<strong>真实姓名</strong>(可选):用以对您的贡献署名。<br />",
+'prefs-help-email' => "*<strong>点子邮件</strong>(可选):让他人通过网站在不知道您的电子邮件地址的情况下通过电子邮件与您联络,以及通过电子邮件取得遗忘的密码。", /*"* <strong>Real name</strong> (optional): if you choose to provide it this will be used for giving you attribution for your work.<br />
+* <strong>Email</strong> (optional): Enables people to contact you through the website without you having to reveal your
+email address to them, and it can be used to send you a new password if you forget it.", */
+'prefs-misc' => "杂项", //"Misc settings",
+'prefs-personal' => "用户数据",//"User data",
+'prefs-rc' => "最近更新", //"Recent changes and stub display",
+'showhideminor' => "$1 小修改 | $2 bots | $3 登录用户 | $4 检查过的", //"$1 minor edits | $2 bots | $3 logged in users | $4 patrolled edits ",
+'skin' => "皮肤", //"Skin",
+'talk' => "讨论",//"Discussion",
+'timezonelegend' => "时区", //"Time zone",
+'toolbox' => "工具",//"Toolbox",
+'watch' => "监视",//"Watch",
+'yourlanguage' => "界面语言", //"Your language"
+'yourrealname' => "真实姓名*", //"Your real name"
+'yourvariant' => "中文字体", //"language variant"
+
+# short names for language variants used for language conversion links.
+# to disable showing a particular link, set it to 'disable', e.g.
+# 'variantname-zh-sg' => 'disable',
+'variantname-zh-cn' => '大陆简体',
+'variantname-zh-tw' => '台湾繁体',
+'variantname-zh-hk' => '香港繁体',
+'variantname-zh-sg' => '新加坡简体',
+'variantname-zh' => '不转换',
+
+);
+
+class LanguageZh_cn extends LanguageUtf8 {
+
+       function getUserToggles() {
+               global $wgUserTogglesZh_cn;
+               return $wgUserTogglesZh_cn;
+       }
+
+       function getNamespaces() {
+               global $wgNamespaceNamesZh_cn;
+               return $wgNamespaceNamesZh_cn;
+       }
+
+
+       function getNsIndex( $text ) {
+               global $wgNamespaceNamesZh_cn;
+
+               foreach ( $wgNamespaceNamesZh_cn as $i => $n ) {
+                       if ( 0 == strcasecmp( $n, $text ) ) { return $i; }
+               }
+               # Aliases
+               if ( 0 == strcasecmp( "特殊", $text ) ) { return -1; }
+               if ( 0 == strcasecmp( "", $text ) ) { return ; }
+               if ( 0 == strcasecmp( "对话", $text ) ) { return 1; }
+               if ( 0 == strcasecmp( "用户", $text ) ) { return 2; }
+               if ( 0 == strcasecmp( "用户对话", $text ) ) { return 3; }
+               if ( 0 == strcasecmp( "Wikipedia_对话", $text ) ) { return 5; }
+               if ( 0 == strcasecmp( "图像", $text ) ) { return 6; }
+               if ( 0 == strcasecmp( "图像对话", $text ) ) { return 7; }
+               return false;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsZh_cn;
+               return $wgQuickbarSettingsZh_cn;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesZh_cn;
+               return $wgSkinNamesZh_cn;
+       }
+
+       function date( $ts, $adj = false ) {
+               if ( $adj ) { $ts = $this->userAdjust( $ts ); }
+
+               $d = substr( $ts, 0, 4 ) . "年" .
+                 $this->getMonthAbbreviation( substr( $ts, 4, 2 ) ) .
+                 (0 + substr( $ts, 6, 2 )) . "日";
+               return $d;
+       }
+
+       function timeanddate( $ts, $adj = false ) {
+               return $this->time( $ts, $adj ) . " " . $this->date( $ts, $adj );
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesZh_cn;
+               if( isset( $wgAllMessagesZh_cn[$key] ) )
+                       return $wgAllMessagesZh_cn[$key];
+               else
+                       return parent::getMessage( $key );
+       }
+
+       # inherit default iconv(), ucfirst(), checkTitleEncoding()
+
+       function stripForSearch( $string ) {
+               # MySQL fulltext index doesn't grok utf-8, so we
+               # need to fold cases and convert to hex
+               # we also separate characters as "words"
+               if( function_exists( 'mb_strtolower' ) ) {
+                       return preg_replace(
+                               "/([\\xc0-\\xff][\\x80-\\xbf]*)/e",
+                               "' U8' . bin2hex( \"$1\" )",
+                               mb_strtolower( $string ) );
+               } else {
+                       global $wikiLowerChars;
+                       return preg_replace(
+                               "/([\\xc0-\\xff][\\x80-\\xbf]*)/e",
+                               "' U8' . bin2hex( strtr( \"\$1\", \$wikiLowerChars ) )",
+                               $string );
+               }
+       }
+}
+
+
+?>
diff --git a/languages/LanguageZh_hk.php b/languages/LanguageZh_hk.php
new file mode 100644 (file)
index 0000000..7e55a77
--- /dev/null
@@ -0,0 +1,11 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+require_once( "LanguageZh_tw.php");
+
+class LanguageZh_hk extends LanguageZh_tw {
+# Inherit everything for now
+}
+?>
diff --git a/languages/LanguageZh_sg.php b/languages/LanguageZh_sg.php
new file mode 100644 (file)
index 0000000..6e43c3c
--- /dev/null
@@ -0,0 +1,11 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+require_once( "LanguageZh_cn.php");
+
+class LanguageZh_sg extends LanguageZh_cn {
+# Inherit everything for now
+}
+?>
diff --git a/languages/LanguageZh_tw.php b/languages/LanguageZh_tw.php
new file mode 100644 (file)
index 0000000..3770b23
--- /dev/null
@@ -0,0 +1,940 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+require_once( "LanguageUtf8.php" );
+require_once( "LanguageZh_cn.php" );
+
+/* private */ $wgNamespaceNamesZh_tw = array(
+       NS_MEDIA            => "媒體",
+       NS_SPECIAL          => "特殊",
+       NS_MAIN             => "",
+       NS_TALK             => "討論",
+       NS_USER             => "用戶",
+       NS_USER_TALK        => "用戶討論",
+       NS_PROJECT          => $wgMetaNamespace,
+       NS_PROJECT_TALK     => $wgMetaNamespace . "討論",
+       NS_IMAGE            => "圖像",
+       NS_IMAGE_TALK       => "圖像討論",
+       NS_MEDIAWIKI        => "媒體維基",
+       NS_MEDIAWIKI_TALK   => "媒體維基討論",
+       NS_TEMPLATE         => "樣板",
+       NS_TEMPLATE_TALK    => "樣板討論",
+       NS_HELP             => "幫助",
+       NS_HELP_TALK        => "幫助討論",
+       NS_CATEGORY         => "分類",
+       NS_CATEGORY_TALK    => "分類討論"
+);
+
+/* private */ $wgQuickbarSettingsZh_tw = array(
+        "無", /* "None" */
+       "左側固定", /* "Fixed left" */
+       "右側固定", /* "Fixed right" */
+       "左側漂移" /* "Floating left" */
+);
+
+/* private */ $wgSkinNamesZh_tw = array(
+        "標準",/* "Standard" */
+       "懷舊",/* "Nostalgia" */
+       "科隆香水藍" /* "Cologne Blue" */
+) + $wgSkinNamesEn;
+
+/* private */ $wgBookstoreListZh_tw = array(
+       "博客來書店" => "http://www.books.com.tw/exep/openfind_book_keyword.php?cat1=4&key1=$1",
+       "三民書店" => "http://www.sanmin.com.tw/page-qsearch.asp?ct=search_isbn&qu=$1",
+       "天下書店" => "http://www.cwbook.com.tw/cw/TS.jsp?schType=product.isbn&schStr=$1",
+       "新絲書店" => "http://www.silkbook.com/function/Search_List_Book.asp?item=5&text=$1"
+);
+
+/* private */ $wgAllMessagesZh_tw = array(
+
+/* User toggles */
+       "tog-underline" => "下劃鏈結", /* "Underline links", */
+       "tog-highlightbroken" => "毀壞的鏈結格式<a href=\"\" class=\"new\">像這樣</a> (或者像這個<a href=\"\" class=\"internal\">?</a>)", /* "Format broken links <a href=\"\" class=\"new\">like this</a> (alternative: like this<a href=\"\" class=\"internal\">?</a>).", */
+       "tog-justify"   => "段落對齊", /* "Justify paragraphs", */
+       "tog-hideminor" => "最近更改中隱藏細微修改", /* "Hide minor edits in recent changes", */
+       "tog-usenewrc" => "最近更改增強(只適用部分流覽器)", /* "Enhanced recent changes (not for all browsers)", */
+       "tog-numberheadings" => "標題自動編號",
+       "tog-showtoolbar" => "顯示編輯工具欄",/* "Auto-number headings", */
+   "tog-editondblclick" => "雙擊頁面編輯(JavaScript)",
+       "tog-editsection"=>"允許通過點擊[編輯]鏈結編輯段落",
+       "tog-editsectiononrightclick"=>"允許右擊標題編輯段落(JavaScript)",
+       "tog-showtoc"=>"顯示目錄<br />(針對一頁超過3個標題的文章)",
+       "tog-rememberpassword" => "下次登陸記住密碼",/* "Remember password across sessions", */
+       "tog-editwidth" => "編輯欄位寬度",/* "Edit box has full width", */
+       "tog-editondblclick" => "雙擊編輯頁面(Javascript)",/* "Edit pages on double click (JavaScript)", */
+       "tog-watchdefault" => "監視新的以及更改過的文章",/* "Watch new and modified articles", */
+       "tog-minordefault" => "細微編輯為默認設置",/* "Mark all edits minor by default", */
+       "tog-previewontop" => "在編輯框上方顯示預覽", /* "Show preview before edit box and not after it" */
+
+
+
+# Bits of text used by many pages:
+#
+"categories" => "頁面分類",
+        "category" => "分類",
+        "category_header" => "類別”$1“中的條目",
+        "subcategories" => "子分類",
+"linktrail"            => "/^([a-z]+)(.*)\$/sD",
+"mainpage"             => "首頁",
+"about"                        => "關於",
+"aboutpage"            => "維基百科:關於",
+"help"                 => "幫助",
+"helppage"             => "維基百科:幫助",
+"bugreports"   => "錯誤報告",
+"bugreportspage" => "維基百科:錯誤報告",
+"faq"                  => "常見問題解答",
+"faqpage"              => "維基百科:常見問題解答",
+"edithelp"             => "編輯幫助",
+"edithelppage" => "維基百科:如何編輯頁面",
+"cancel"               => "取消",
+"qbfind"               => "尋找",
+"qbbrowse"             => "瀏覽",
+"qbedit"               => "編輯",
+"qbpageoptions" => "頁面選項",
+"qbpageinfo"   => "頁面信息",
+"qbmyoptions"  => "我的選項",
+"mypage"               => "我的頁面",
+"mytalk"               => "我的對話頁",
+"currentevents" => "新聞動態",
+"errorpagetitle" => "錯誤",
+"returnto"             => "返回到$1.",
+"whatlinkshere"        => "鏈入頁面",
+"help"                 => "幫助",
+"search"               => "搜索",
+"go"           => "進入",
+"history"              => "較早版本",
+"printableversion" => "可列印版",
+"editthispage" => "編輯本頁",
+"deletethispage" => "刪除本頁",
+"protectthispage" => "保護本頁",
+"unprotectthispage" => "解除保護",
+"newpage" => "新頁面",
+"talkpage"             => "討論本頁",
+        "postcomment"   => "發表評論",
+"articlepage"  => "查看文章",
+"subjectpage"  => "查看主題", # For compatibility
+"userpage" => "查看用戶頁",
+"wikipediapage" => "查看元維基頁",
+"imagepage" =>         "查看圖像頁面",
+"viewtalkpage" => "查看討論",
+"otherlanguages" => "其它語言",
+"redirectedfrom" => "(重定向自$1)",
+"lastmodified" => "最後更改$1.",
+"viewcount"            => "本頁面已經被瀏覽$1次。",
+"printsubtitle" => "(來自 {{SERVER}})",
+"protectedpage" => "被保護頁",
+"administrators" => "維基百科:管理員",
+"sysoptitle"   => "需要管理員權限",
+"sysoptext"            => "您剛才的請求只有擁有管理員權限的用戶才可使用。
+參見$1。",
+"developertitle" => "需要發展者權限",
+"developertext"        => "您剛才的請求只有擁有發展者權限的用戶才可使用。
+參見$1。",
+"nbytes"               => "$1字節",
+"go"                   => "進入",
+"ok"                   => "好",
+"sitetitle"            => "維基百科",
+"sitesubtitle" => "自由的百科全書",
+"retrievedfrom" => "取自\"$1\"",
+"newmessages" => "您有$1。",
+"newmessageslink" => "新信息",
+ "editsection"=>"編輯",
+ "toc" => "目錄",
+"showtoc" => "顯示",
+        "hidetoc" => "隱藏",
+
+# weekdays, month names
+'sunday'    => "星期日",
+'monday'    => "星期一",
+'tuesday'   => "星期二",
+'wednesday' => "星期三",
+'thursday'  => "星期四",
+'friday'    => "星期五",
+'saturday'  => "星期六",
+
+'january'   => "一月",
+'february'  => "二月",
+'march'     => "三月",
+'april'     => "四月",
+'may_long'  => "五月",
+'june'      => "六月",
+'july'      => "七月",
+'august'    => "八月",
+'september' => "九月",
+'october'   => "十月",
+'november'  => "十一月",
+'december'  => "十二月",
+
+'jan'       => "一月",
+'feb'       => "二月",
+'mar'       => "三月",
+'apr'       => "四月",
+'may'       => "五月",
+'jun'       => "六月",
+'jul'       => "七月",
+'aug'       => "八月",
+'sep'       => "九月",
+'oct'       => "十月",
+'nov'       => "十一月",
+'dec'       => "十二月",
+
+# Main script and global functions
+#
+"nosuchaction" => "沒有這個命令",
+"nosuchactiontext" => "URL請求的命令無法被維基百科軟件識別。",
+"nosuchspecialpage" => "沒有這個特殊頁。",
+
+"nospecialpagetext" => "您請求的頁面無法被維基百科軟件識別。",
+
+# General errors
+#
+"error"                        => "錯誤",
+"databaseerror" => "數據庫錯誤",
+"dberrortext"  => "數據庫指令語法錯誤。
+這可能是由於非法搜索指令所引起的(見$5),
+也可能是由於軟件自身的錯誤所引起。
+最後一次數據庫指令是:
+<blockquote><tt>$1</tt></blockquote>
+來自於函數 \"<tt>$2</tt>\"。
+MySQL返回錯誤 \"<tt>$3: $4</tt>\"。",
+"noconnect"            => "無法在$1上連接數據庫",
+"nodb"                 => "無法選擇數據庫 $1",
+"readonly"             => "數據庫禁止訪問",
+"enterlockreason" => "請輸入禁止訪問原因, 包括估計重新開放的時間",
+"readonlytext" => "維基百科數據庫目前禁止輸入新內容及更改,
+這很可能是由於數據庫正在維修,之後即可恢復。
+管理員有如下解釋:
+<p>$1",
+"missingarticle" => "數據庫找不到文字\"$1\"。
+
+<p>通常這是由於修訂歷史頁上過時的鏈接到已經被刪除的頁面所導致的。
+
+<p>如果情況不是這樣,您可能找到了軟件內的一個臭蟲。
+請記錄下URL地址,並向管理員報告。",
+"internalerror" => "內部錯誤",
+"filecopyerror" => "無法複製文件\"$1\"到\"$2\"。",
+"filerenameerror" => "無法重命名文件\"$1\"到\"$2\"。",
+"filedeleteerror" => "無法刪除文件\"$1\"。",
+"filenotfound" => "找不到文件\"$1\"。",
+"unexpected"   => "不正常值:\"$1\"=\"$2\"。",
+"formerror"            => "錯誤:無法提交表單",
+"badarticleerror" => "無法在本頁上進行此項操作。",
+"cannotdelete" => "無法刪除選定的頁面或圖像(它可能已經被其他人刪除了)。",
+"badtitle"             => "錯誤的標題",
+"badtitletext" => "所請求頁面的標題是無效的、不存在,跨語言或跨維基鏈接的標題錯誤。",
+"perfdisabled" => "抱歉!由於此項操作有可能造成數據庫癱瘓,目前暫時無法使用。",
+"perfdisabledsub" => "這裏是自$1的複製版本:",
+
+# 登錄與登出
+#
+"logouttitle"  => "用戶退出",
+"logouttext"   => "您現在已經退出。
+您可以繼續以匿名方式使用維基百科,或再次以相同或不同用戶身份登錄。\n",
+
+"welcomecreation" => "<h2>歡迎,$1!</h2><p>您的帳號已經建立,不要忘記設置維基百科個人參數。",
+
+"loginpagetitle" => "用戶登錄",
+"yourname"             => "您的用戶名",
+"yourpassword" => "您的密碼",
+"yourpasswordagain" => "再次輸入密碼",
+"newusersonly" => "(僅限新用戶)",
+"remembermypassword" => "下次登錄記住密碼。",
+"loginproblem" => "<b>登錄有問題。</b><br />再試一次!",
+"alreadyloggedin" => "<strong>用戶$1,您已經登錄了!</strong><br />\n",
+
+"login"                        => "登錄",
+"userlogin"            => "用戶登錄",
+"logout"               => "退出",
+"userlogout"   => "用戶退出",
+"createaccount"        => "創建新帳號",
+ "createaccountmail"     => "通過eMail",
+"badretype"            => "你所輸入的密碼並不相同。",
+"userexists"   => "您所輸入的用戶名已有人使用。請另選一個。",
+"youremail"            => "您的電子郵件*",
+"yournick"             => "綽號(簽名時用)",
+"emailforlost" => "* 輸入一個電郵地址並不是必須的。但是這將允許他人在您未告知的情況下通過電子郵件與您聯繫,如果您忘了密碼的話電郵地址也會有幫助。",
+"loginerror"   => "登錄錯誤",
+"noname"               => "你沒有輸入一個有效的用戶名。",
+"loginsuccesstitle" => "登錄成功",
+"loginsuccess" => "你現在以 \"$1\"的身份登錄維基百科。",
+"nosuchuser"   => "找不到用戶 \"$1\"。
+檢查您的拼寫,或者用下面的表格建立一個新帳號。",
+"wrongpassword"        => "您輸入的密碼錯誤,請再試一次。",
+"mailmypassword" => "將新密碼寄給我",
+"passwordremindertitle" => "維基百科密碼提醒",
+"passwordremindertext" => "有人(可能是您,來自網址$1)要求我們將新的維基百科登錄密碼寄給你。
+用戶 \"$2\" 的密碼現在是 \"$3\"。
+請立即登錄並更改密碼。",
+"noemail"              => "用戶\"$1\"沒有登記電子郵件地址。",
+"passwordsent" => "用戶\"$1\"的新密碼已經寄往所登記的電子郵件地址。
+請在收到後再登錄。",
+
+# 編輯
+#
+"summary"              => "簡述",
+"subject"               => "主題",
+"minoredit"            => "這是一個小修改",
+"watchthis"            => "監視本頁",
+"savearticle"  => "保存本頁",
+"preview"              => "預覽",
+"showpreview"  => "顯示預覽",
+"blockedtitle" => "用戶被封",
+"blockedtext"  => "您的用戶名或網址已被$1封。
+理由是:<br />'''$2'''<p>您可以與$1向其他任何[[維基百科:管理員|管理員]]詢問。",
+ "whitelistedittitle" => "登錄後才可編輯",
+        "whitelistedittext" => "您必須先[[特殊:登錄]]才可編輯頁面。",
+        "whitelistreadtitle" => "登錄後才可閱讀",
+        "whitelistreadtext" => "您必須先[[特殊:登錄]]才可閱讀頁面。",
+        "whitelistacctitle" => "您被禁止建立帳號",
+        "whitelistacctext" => "在本維基中建立帳號您必須先[[特殊:登錄]]並擁有相關權限。",
+        "accmailtitle" => "密碼寄出",
+        "accmailtext" => "'$1'的密碼已經寄到$2。",
+"newarticle"   => "(新)",
+"newarticletext" =>
+"您從一個鏈接進入了一個並不存在的頁面。
+要創建該頁面,請在下面的編輯框中輸入內容(詳情參見[[維基百科:幫助|幫助頁面]])。
+如果您不小心來到本頁面,直接點擊您瀏覽器中的“返回”按鈕。",
+
+"anontalkpagetext" => "---- ''這是一個還未建立帳號的匿名用戶的對話頁。我們因此只能用[[網址]]來與他/她聯絡。該網址可能由幾名用戶共享。如果您是一名匿名用戶並認為本頁上的評語與您無關,請[[特殊:登錄|創建新帳號或登錄]]以避免在未來於其他匿名用戶混淆。''",
+"noarticletext" => "(本頁目前沒有內容)",
+"updated"              => "(已更新)",
+"note"                 => "<strong>注意:</strong> ",
+"previewnote"  => "請記住這只是預覽,內容還未保存!",
+"previewconflict" => "這個預覽顯示了上面文字編輯區中的內容。它將在你選擇保存後出現。",
+"editing"              => "正在編輯$1",
+"editingsection"       => "正在編輯$1 (段落)",
+"editingcomment"       => "正在編輯$1 (評論)",
+"editconflict" => "編輯衝突:$1",
+"explainconflict" => "有人在你開始編輯後更改了頁面。
+上面的文字框內顯示的是目前本頁的內容。
+你所做的修改顯示在下面的文字框中。
+你應當將你所做的修改加入現有的內容中。
+<b>只有</b>在上面文字框中的內容會在你點擊\"保存頁面\"後被保存。<br />",
+"yourtext"             => "您的文字",
+"storedversion" => "已保存版本",
+"editingold"   => "<strong>警告:你正在編輯的是本頁的舊版本。
+如果你保存它的話,在本版本之後的任何修改都會丟失。</strong>",
+"yourdiff"             => "差別",
+"copyrightwarning" => "請注意對W維基百科的任何貢獻都將被認為是在GNU自由文檔協議證書下發佈。
+(細節請見$1).
+如果您不希望您的文字被任意修改和再散佈,請不要提交。<br />
+您同時也向我們保證你所提交的內容是你自己所作,或得自一個不受版權保護或相似自由的來源。
+<strong>不要在未獲授權的情況下發表!</strong>",
+
+"longpagewarning" => "<strong>警告:本頁長度達$1千位;一些瀏覽器將無法編輯長過三十二千位的文章。請考慮將本文切割成幾個小段落。</strong>",
+
+"readonlywarning" => "<strong>警告:數據庫被鎖以進行維護,所以您目前將無法保存您的修改。您或許希望先將本斷文字複製並保存到文本文件,然後等一會兒再修改。</strong>",
+"protectedpagewarning" => "<strong>警告:本頁已經被保護,只有擁有管理員權限的用戶才可修改。請確認您遵守
+[[Project:Protected_page_guidelines|保護頁面守則]].</strong>",
+
+# History pages
+#
+"revhistory"   => "修訂歷史",
+"nohistory"            => "沒有本頁的修訂記錄。",
+"revnotfound"  => "沒有找到修訂記錄",
+"revnotfoundtext" => "您請求的更早版本的修訂記錄沒有找到。
+請檢查您請求本頁面用的URL是否正確。\n",
+"loadhist"             => "載入頁面修訂歷史",
+"currentrev"   => "當前修訂版本",
+"revisionasof" => "$1的修訂版本",
+"cur"                  => "當前",
+"next"                 => "後繼",
+"last"                 => "先前",
+"orig"                 => "初始",
+"histlegend"   => "說明:(當前)指與當前修訂版本比較;(先前)指與前一個修訂版本比較,小 指細微修改。",
+
+# Diffs
+#
+"difference"   => "(修訂版本間差異)",
+"loadingrev"   => "載入修訂版本比較",
+"lineno"               => "第$1行:",
+"editcurrent"  => "編輯本頁的當前修訂版本",
+
+# Search results
+#
+"searchresults" => "搜索結果",
+"searchresulttext" => "有關搜索維基百科的更多詳情,參見$1。",
+"searchquery"  => "查詢\"$1\"",
+"badquery"             => "搜索查詢不正確",
+"badquerytext" => "我們無法處理您的查詢。
+這可能是由於您試圖搜索一個短於3個字母的外文單詞,
+或者您錯誤地輸入了搜索項,例如\"汽車和和火車\"。
+請再嘗試一個新的搜索項。",
+"matchtotals"  => "搜索項\"$1\"與$2條文章的題目相符,和$3條文章相符。",
+
+"nogomatch" => "沒有文章與搜索項完全匹配,請嘗試完整文字搜索。",
+"titlematches" => "文章題目相符",
+"notitlematches" => "沒有找到匹配文章題目",
+"textmatches"  => "文章內容相符",
+"notextmatches"        => "沒有文章內容匹配",
+
+"prevn"                        => "先前$1",
+"nextn"                        => "之後$1",
+"viewprevnext" => "查看 ($1) ($2) ($3).",
+"showingresults" => "下面顯示<b>$1</b>條結果,從第<b>$2</b>條開始",
+"nonefound"            => "<strong>注意:</strong>失敗的搜索往往是由於試圖搜索諸如“的”或“和”之類的常見字所引起。",
+"powersearch" => "搜索",
+"powersearchtext" => "
+搜索名字空間:<br />$1<br />$2列出重定向頁面;搜索$3 $9",
+
+"searchdisabled" => "<p>維基百科內部搜索功能由於高峰時段服務器超載而停止使用。
+您可以暫時通過
+<a href=\"http://google.com.tw/\">google</a>搜索維基百科。
+謝謝您的耐心。",
+
+# Preferences page
+#
+"preferences"  => "參數設置",
+"prefsnologin" => "還未登錄",
+"prefsnologintext"     => "您必須先[[Special:Userlogin|登錄]]才能設置個人參數。",
+"prefslogintext" => "你已經以\"$1\"的身份登錄。
+你的內部ID是$2。",
+"prefsreset"   => "參數重新設置。",
+"qbsettings"   => "快速導航條設置",
+"changepassword" => "更改密碼",
+"skin"                 => "皮膚",
+"math"                 => "數學顯示",
+"math_failure"         => "無法解析",
+"math_unknown_error"   => "未知錯誤",
+"math_unknown_function"        => "未知函數",
+"math_lexing_error"    => "句法錯誤",
+"math_syntax_error"    => "語法錯誤",
+"saveprefs"            => "保存參數設置",
+"resetprefs"   => "重設參數",
+"oldpassword"  => "舊密碼",
+"newpassword"  => "新密碼",
+"retypenew"            => "重複新密碼",
+"textboxsize"  => "文字框尺寸",
+"rows"                 => "行",
+"columns"              => "列",
+"searchresultshead" => "搜索結果設定",
+"resultsperpage" => "每頁顯示鏈接數",
+"contextlines" => "每鏈接行數",
+"contextchars" => "每行字數",
+"stubthreshold" => "短條目顯示基本限制",
+"recentchangescount" => "最近更改頁行數",
+"savedprefs"   => "您的個人參數設置已經保存。",
+"timezonetext" => "輸入當地時間與服務器時間的時差。",
+"localtime"    => "當地時間",
+"timezoneoffset" => "時差",
+"emailflag"            => "禁止其他用戶發電子郵件給我",
+
+# Recent changes
+#
+"changes" => "更改",
+"recentchanges" => "最近更改",
+"recentchangestext" => "本頁跟蹤維基百科內最新的更改。
+[[維基百科:歡迎,新來者|歡迎,新來者]]!
+請參見這些頁面:[[維基百科:常見問題解答|維基百科常見問題解答]]、
+[[維基百科:守則與指導|維基百科守則]]
+(特別是[[維基百科:命名常規|命名常規]]、
+[[維基百科:中性的觀點|中立觀點]])
+和[[維基百科:最常見失禮行為|最常見失禮行為]]。
+
+如果您希望維基百科成功,那麼請您不要增加受其它[[維基百科:版權信息|版權]]
+限制的材料,這一點將非常重要。相關的法律責任會傷害本項工程,所以請不要這樣做。
+此外請參見
+[http://meta.wikipedia.org/wiki/Special:Recentchanges 最近的元維基討論]。",
+
+"rcloaderr"            => "載入最近更改",
+"rcnote"               => "下面是最近<strong>$2</strong>天內最新的<strong>$1</strong>次改動。",
+"rcnotefrom"   => "下面是自<b>$2</b>(最多顯示<b>$1</b>)。",
+"rclistfrom"   => "顯示自$1以來的新更改",
+"rclinks"              => "顯示最近 $2 天內最新的 $1 次改動。<br />$3",
+"rchide"               => "以$4形式;$1個小修改;$2個二級名字空間;$3個多重修改",
+"diff"                 => "差異",
+"hist"                 => "歷史",
+"hide"                 => "隱藏",
+"show"                 => "顯示",
+"tableform"            => "表格",
+"listform"             => "列表",
+"nchanges"             => "$1個更改",
+"minoreditletter" => "小",
+"newpageletter" => "新",
+
+# Upload
+#
+"upload"               => "上載文件",
+"uploadbtn"            => "上載文件",
+"uploadlink"   => "上載圖像",
+"reupload"             => "重新上載",
+"reuploaddesc" => "返回上載表單。",
+"uploadnologin" => "未登錄",
+"uploadnologintext"    => "您必須先[[Special:Userlogin|登錄]]
+才能上載文件。",
+"uploaderror"  => "上載錯誤",
+"uploadtext"   => "<strong>停止!</strong>在您上載之前,請先閱讀並遵守維基百科<a href=\"" .
+"{{localurle:Wikipedia:Image use policy}}\">圖像使用守則</a>。
+<p>如果您要查看或搜索之前上載的圖像,
+請到<a href=\"" . "{{localurle:Special:Imagelist}}" .
+"\">已上載圖像列表</a>.
+所有上載與刪除行為都被記錄在<a href=\"" .
+"{{localurle:Wikipedia:Upload image}}\">上載紀錄</a>內。
+<p>使用下面的表單來上載用在條目內新的圖像文件。
+在絕大多數瀏覽器內,你會看到一個\"瀏覽...\"按鈕,點擊它後就會跳出一個打開文件對話框。
+選擇一個文件後文件名將出現在按鈕旁邊的文字框中。
+您也必須點擊旁邊的複選框確認您所上載的文件並沒有違反相關版權法律。
+點擊\"上載\" 按鈕完成上載程序。
+如果您使用的是較慢的網絡連接的話那麼這個上載過程會需要一些時間。
+<p>我們建議照相圖片使用JPEG格式,繪圖及其他圖標圖像使用PNG格式,音像則使用OGG格式。
+請使用具有描述性的語言來命名您的文件以避免混亂。
+要在文章中加入圖像,使用以下形式的連接:
+<b>[[圖像:檔案.jpg]]</b>或者<b>[[圖像:檔案.png|解釋文字]]</b>
+或<b>[[媒體:檔案.ogg]]</b>來連接音像文件。
+<p>請注意在維基百科頁面中,其他人可能會為了百科全書的利益而編輯或刪除您的上載文件,
+而如果您濫用上載系統,您則有可能被禁止使用上載功能。",
+"uploadlog"            => "上載紀錄",
+"uploadlogpage" => "上載紀錄",
+"uploadlogpagetext" => "以下是最近上載的文件的一覽表。
+所有顯示的時間都是服務器時間。
+<ul>
+</ul>
+",
+"filename"             => "文件名",
+"filedesc"             => "簡述",
+"copyrightpage" => "維基百科:版權信息",
+"copyrightpagename" => "維基百科版權",
+"uploadedfiles"        => "已上載文件",
+"ignorewarning"        => "忽略警告並保存文件。",
+"minlength"            => "圖像名字必須至少有三個字母。",
+"badfilename"  => "圖像名已被改為\"$1\"。",
+"badfiletype"  => "\".$1\"不是所推薦的圖像文件格式。",
+"largefile"            => "我們建議圖像大小不超過百千位。",
+"successfulupload" => "上載成功",
+"fileuploaded" => "文件\"$1\"上載成功。
+請根據連接($2)到圖像描述頁添加有關文件信息,例如它的來源,在何時由誰創造,
+以及其他任何您知道的關於改圖像的信息。",
+"uploadwarning" => "上載警告",
+"savefile"             => "保存文件",
+"uploadedimage" => "已上載\"[[$1]]\"",
+
+# Image list
+#
+"imagelist"            => "圖像列表",
+"imagelisttext"        => "以下是按$2排列的$1幅圖像列表。",
+"getimagelist" => "正在獲取圖像列表",
+"ilsubmit"             => "搜索",
+"showlast"             => "顯示按$2排列的最後$1幅圖像。",
+"byname"               => "名字",
+"bydate"               => "日期",
+"bysize"               => "大小",
+"imgdelete"            => "刪",
+"imgdesc"              => "述",
+"imglegend"            => "說明:(述) = 顯示/編輯圖像描述頁。",
+"imghistory"   => "圖像歷史",
+"revertimg"            => "回",
+"deleteimg"            => "刪",
+"imghistlegend" => "題跋: (現) = 目前的圖像,(刪) = 刪除舊版本,
+(複) = 恢復到舊版本。
+<br /><i>點擊日期查看當天上載的圖像</i>.",
+"imagelinks"   => "圖像鏈接",
+
+"linkstoimage" => "以下頁面連接到本圖像:",
+"nolinkstoimage" => "沒有頁面連接到本圖像。",
+
+# Statistics
+#
+"statistics"   => "統計",
+"sitestats"            => "站點統計",
+"userstats"            => "用戶統計",
+"sitestatstext" => "數據庫中共有 <b>$1</b> 頁頁面;
+其中包括對話頁、關於維基百科的頁面、最少量的\"stub\"頁、重定向的頁面,
+以及未達到條目質量的頁面;除此之外還有 <b>$2</b> 頁可能是合乎標準的條目。
+<p>從系統軟件升級以來,全站點共有頁面瀏覽 <b>$3</b> 次,
+頁面編輯 <b>$4</b> 次,每頁平均編輯 <b>$5</b> 次,
+各次編輯後頁面的每個版本平均瀏覽 <b>$6</b> 次。",
+
+# Maintenance Page
+#
+"maintenance"          => "維護頁",
+"maintnancepagetext"   => "這頁面提供了幾個幫助維基百科日常維護的工具。
+但其中幾個會對我們的數據庫造成壓力,
+所以請您不要在每修理好幾個項目後就按重新載入 ;-)",
+"maintenancebacklink"  => "返回維護頁",
+"disambiguations"      => "消含糊頁",
+"disambiguationspage"  => "維基百科:鏈接到消歧義的頁面",
+"disambiguationstext"  => "以下的條目都有到消含糊頁的鏈接,但它們應該是鏈到適當的題目。<br />一個頁面會被視為消含糊頁如果它是鏈自$1.<br />由其它他名字空間來的鏈接<i>不會</i>在這兒被列出來。",
+"doubleredirects"      => "雙重重定向",
+"doubleredirectstext"  => "<b>請注意:</b> 這列表可能包括不正確的反應。
+這通常表示在那頁面第一個#REDIRECT之下還有文字。<br />\n
+每一行都包含到第一跟第二個重定向頁的鏈接,以及第二個重定向頁的第一行文字,
+通常顯示的都會是\“真正\” 的目標頁面,也就是第一個重定向頁應該指向的條目。",
+"brokenredirects"      => "損壞的重定向頁",
+"brokenredirectstext"  => "以下的重定向頁指向的是不存在的條目。",
+"selflinks"            => "有自我鏈接的頁面",
+"selflinkstext"                => "以下的頁面都錯誤地包含了連到自己的鏈接。",
+"mispeelings"           => "拼寫錯誤的頁面",
+"mispeelingstext"               => "以下頁面包含了一些常見的拼寫錯誤(見$1)。正確的拼法已經給出。",
+"mispeelingspage"       => "常見拼寫錯誤列表",
+"missinglanguagelinks"  => "無語言鏈接",
+"missinglanguagelinksbutton"    => "尋找沒有該語言的頁面",
+"missinglanguagelinkstext"      => "這些條目<i>沒有</i>鏈接到$1。
+重定向頁與副頁<b>並沒有</b>包括在內。",
+
+# Miscellaneous special pages
+#
+"orphans"              => "孤立條目",
+"lonelypages"  => "孤立頁面",
+"unusedimages" => "未使用圖像",
+"popularpages" => "熱點條目",
+"nviews"               => "$1次瀏覽",
+"wantedpages"  => "待撰頁面",
+"nlinks"               => "$1個鏈接",
+"allpages"             => "所有頁面",
+"randompage"   => "隨機頁面",
+"shortpages"   => "短條目",
+"longpages"            => "長條目",
+"listusers"            => "用戶列表",
+"specialpages" => "特殊頁面",
+"spheading"            => "特殊頁面",
+"protectpage"  => "保護頁面",
+"recentchangeslinked" => "鏈出更改",
+"rclsub"               => "(從 \"$1\"鏈出的頁面)",
+"debug"                        => "除錯",
+"newpages"             => "新頁面",
+"intl"         => "跨語言鏈接",
+"movethispage" => "移動本頁",
+"unusedimagestext" => "<p>請注意其他網站(例如其他語言版本的維基百科)
+有可能直接鏈接本圖像,所以這裏列出的圖像有可能依然被使用。",
+"booksources"  => "戰外書源",
+"booksourcetext" => "以下是鏈接到銷售書籍的網站列表,
+因此有可能擁有您所尋找的圖書的進一步資料。
+維基百科與這些公司並沒有任何商業關係,因此本表不應該
+被看作是一種背書。",
+"alphaindexline" => "$1 到 $2",
+
+# Email this user
+#
+"mailnologin"  => "無電郵地址",
+"mailnologintext" => "您必須先[[Special:Userlogin|登錄]]
+並在[[Special:Preferences|參數設置]]
+中有一個有效的電子郵件地址才可以電郵其他用戶。",
+"emailuser"            => "電子郵件該用戶",
+"emailpage"            => "電子郵件用戶",
+"emailpagetext"        => "如果該用戶已經在他或她的參數設置頁中輸入了有效的電子郵件地址,以下的表格將寄一個信息給該用戶。您在您參數設置中所輸入的電子郵件地址將出現在郵件“發件人”一欄中,這樣該用戶就可以回復您。",
+"noemailtitle" => "無電子郵件地址",
+"noemailtext"  => "該用戶還沒有指定一個有效的電子郵件地址,
+或者選擇不接受來自其他用戶的電子郵件。",
+
+"emailfrom"            => "發件人",
+"emailto"              => "收件人",
+"emailsubject" => "主題",
+"emailmessage" => "信息",
+"emailsend"            => "發送",
+"emailsent"            => "電子郵件已發送",
+"emailsenttext" => "您的電子郵件已經發出。",
+
+# Watchlist
+#
+"watchlist"            => "監視列表",
+"watchlistsub" => "(用戶\"$1\")",
+"nowatchlist"  => "您的監視列表為空。",
+"watchnologin" => "未登錄",
+"watchnologintext"     => "您必須先[[Special:Userlogin|登錄]]
+才能更改您的監視列表",
+"addedwatch"   => "加入到監視列表",
+"addedwatchtext" => "本頁(“$1”)已經被加入到您的<a href=\"" .
+  "{{localurle:Special:Watchlist}}\">監視列表</a>中。
+未來有關它或它的對話頁的任何修改將會在本頁中列出,
+而且還會在<a href=\"" .
+  "{{localurle:Special:Recentchanges}}\">最近更改列表</a>中
+以<b>粗體</b>形式列出。</p>
+
+<p>如果您之後想將該頁面從監視列表中刪除,點擊導航條中的“停止監視”鏈接。",
+"removedwatch" => "停止監視",
+"removedwatchtext" => "頁面“$1”已經從您的監視頁面中移除。",
+"watchthispage"        => "監視本頁",
+"unwatchthispage" => "停止監視",
+"notanarticle" => "不是條目",
+        "watchnochange" => "在顯示的時間段內您所監視的頁面沒有更改。",
+        "watchdetails" => "($1個頁面(不含對話頁)被監視;
+        總共$2個頁面被編輯;
+        $3...
+        [$4 顯示並編輯完整列表].)",
+        "watchmethod-recent" => "檢查被監視頁面的最近編輯",
+        "watchmethod-list" => "checking watched pages for recent edits",
+        "removechecked" => "將被選頁面從監視列表中移除",
+        "watchlistcontains" => "您的監視列表包含$1個頁面。",
+        "watcheditlist" => "這裏是您所監視的頁面的列表。要移除某一頁面,只要選擇該頁面然後點擊”移除頁面“按鈕。",
+        "removingchecked" => "移除頁面...",
+        "couldntremove" => "無法移除'$1'...",
+        "iteminvalidname" => "頁面'$1'錯誤,無效命名...",
+        "wlnote" => "以下是最近<b>$2</b>小時內的最後$1次修改。",
+
+# Delete/protect/revert
+#
+"deletepage"   => "刪除頁面",
+"confirm"              => "確認",
+"confirmdelete" => "確認刪除",
+"deletesub"            => "(正在刪除“$1”)",
+"confirmdeletetext" => "您即將從數據庫中永遠刪除一個頁面或圖像以及其歷史。
+請確定您要進行此項操作,並且瞭解其後果,同時您的行為符合[[維基百科:守則與指導]]。
+",
+"actioncomplete" => "操作完成",
+"deletedtext"  => "“$1”已經被刪除。
+最近刪除的紀錄請參見$2。",
+"deletedarticle" => "已刪除“$1”",
+
+"dellogpage"   => "刪除紀錄",
+"dellogpagetext" => "以下是最近刪除的紀錄列表。
+所有的時間都是使用服務器時間。
+<ul>
+</ul>
+",
+"deletionlog"  => "刪除紀錄",
+"reverted"             => "回降到早期版本",
+"deletecomment"        => "刪除理由",
+"imagereverted" => "回降到早期版本操作完成。",
+"rollback"             => "恢復",
+"rollbacklink" => "恢復",
+"cantrollback" => "無法恢復編輯;最後的鞏縣者是本文的唯一作者。",
+"revertpage"   => "回降到$1的最後一次編輯",
+
+# Undelete
+"undelete" => "恢復被刪頁面",
+"undeletepage" => "瀏覽及恢復被刪頁面",
+"undeletepagetext" => "以下頁面已經被刪除,但依然在檔案中並可以被恢復。
+檔案庫可能被定時清理。",
+"undeletearticle" => "恢復被刪文章",
+"undeleterevisions" => "$1版本存檔",
+"undeletehistory" => "如果您恢復了該頁面,所有版本都會被恢復到修訂歷史中。
+如果本頁刪除後有一個同名的新頁面建立,
+被恢復的版本將會稱為較新的歷史,而新頁面的當前版本將無法被自動復原。",
+"undeleterevision" => "刪除$1時的版本",
+"undeletebtn" => "恢復!",
+"undeletedarticle" => "已經恢復“$1”",
+"undeletedtext"   => "[[$1]]已經被成功復原。
+有關維基百科最近的刪除與復原,參見[[維基百科:刪除紀錄]]",
+
+# Contributions
+#
+"contributions"        => "用戶貢獻",
+"mycontris" => "我的貢獻",
+"contribsub"   => "為$1",
+"nocontribs"   => "沒有找到符合特徵的更改。",
+"ucnote"               => "以下是該用戶最近<b><$2/b>天內的最後<b>$1</b>次修改。",
+"uclinks"              => "參看最後$1次修改;參看最後$2天。",
+"uctop"                => " (頂)" ,
+
+# What links here
+#
+"whatlinkshere"        => "鏈入頁面",
+"notargettitle" => "無目標",
+"notargettext" => "您還沒有指定一個目標頁面或用戶以進行此項操作。",
+"linklistsub"  => "(鏈接列表)",
+"linkshere"            => "以下頁面鏈接到這裏:",
+"nolinkshere"  => "沒有頁面鏈接到這裏。",
+"isredirect"   => "重定向頁",
+
+# Block/unblock IP
+#
+"blockip"              => "查封網址",
+"blockiptext"  => "用下面的表單來禁止來自某一特定網址的修改權限。
+只有在為防止破壞,及符合[[維基百科:守則與指導]]的情況下才可採取此行動。
+請在下面輸入一個具體的理由(例如引述一個被破壞的頁面)。",
+"ipaddress"            => "網址",
+"ipbreason"            => "原因",
+"ipbsubmit"            => "查封該地址",
+"badipaddress" => "網址不正確。",
+"blockipsuccesssub" => "查封成功",
+"blockipsuccesstext" => "網址“$1”已經被查封。
+<br />參看[[特殊:被封網址列表|被封網址列表]]以復審查封。",
+"unblockip"            => "解除禁封網址",
+"unblockiptext"        => "用下面的表單來恢復先前被禁封的網址的書寫權。",
+"ipusubmit"            => "解除禁封",
+"ipusuccess"   => "網址”$1”已經被解除禁封",
+"ipblocklist"  => "被封網址列表",
+"blocklistline"        => "$1,$2禁封$3 ($4)",
+"blocklink"            => "禁封",
+"unblocklink"  => "解除禁封",
+"contribslink" => "貢獻",
+
+# Developer tools
+#
+"lockdb"               => "禁止更改數據庫",
+"unlockdb"             => "開放更改數據庫",
+"lockdbtext"   => "鎖住數據庫將禁止所有用戶進行編輯頁面、更改參數、編輯監視列表以及其他需要更改數據庫的操作。
+請確認您的決定,並且保證您在維護工作結束後會重新開放數據庫。",
+"unlockdbtext" => "開放數據庫將會恢復所有用戶進行編輯頁面、修改參數、編輯監視列表以及其他需要更改數據庫的操作。
+請確認您的決定。",
+"lockconfirm"  => "是的,我確實想要封鎖數據庫。",
+"unlockconfirm"        => "是的,我確實想要開放數據庫。",
+"lockbtn"              => "數據庫上鎖",
+"unlockbtn"            => "開放數據庫",
+"locknoconfirm" => "您並沒有勾選確認按鈕。",
+"lockdbsuccesssub" => "數據庫成功上鎖",
+
+"unlockdbsuccesssub" => "數據庫開放",
+"lockdbsuccesstext" => "維基百科數據庫已經上鎖。
+<br />請記住在維護完成後重新開放數據庫。",
+"unlockdbsuccesstext" => "維基百科數據庫重新開放。",
+
+# Move page
+#
+"movepage"             => "移動頁面",
+"movepagetext" => "用下面的表單來重命名一個頁面,並將其修訂歷史同時移動到新頁面。
+老的頁面將成為新頁面的重定向頁。
+鏈接到老頁面的鏈接並不會自動更改;
+請[[特殊:檢查|檢查]]雙重或損壞重定向鏈接。
+您應當負責確定所有鏈接依然會鏈到指定的頁面。
+
+注意如果新頁面已經有內容的話,頁面將'''不會'''被移動,
+除非新頁面無內容或是重定向頁,而且沒有修訂歷史。
+這意味著您再必要時可以在移動到新頁面後再移回老的頁面,
+同時您也無法覆蓋現有頁面。
+
+<b>警告!</b>
+對一個經常被訪問的頁面而言這可能是一個重大與唐突的更改;
+請在行動前先了結其所可能帶來的後果。",
+"movepagetalktext" => "有關的對話頁(如果有的話)將被自動與該頁面一起移動,'''除非''':
+*您將頁面移動到不同的名字空間;
+*新頁面已經有一個包含內容的對話頁,或者
+*您不勾選下麵的複選框。
+
+在這些情況下,您在必要時必須手工移動或合併頁面。",
+"movearticle"  => "移動頁面",
+"movenologin"  => "未登錄",
+"movenologintext" => "您必須是一名登記用戶並且[[Special:Userlogin|登錄]]
+後才可移動一個頁面。",
+"newtitle"             => "新標題",
+"movepagebtn"  => "移動頁面",
+"pagemovedsub" => "移動成功",
+"pagemovedtext" => "頁面“[[$1]]”已經移動到“[[$2]]”。",
+"articleexists" => "該名字的頁面已經存在,或者您選擇的名字無效。請再選一個名字。",
+"talkexists"   => "頁面本身移動成功,
+但是由於新標題下已經有對話頁存在,所以對話頁無法移動。請手工合併兩個頁面。",
+"movedto"              => "移動到",
+"movetalk"             => "如果可能的話,請同時移動對話頁。",
+"talkpagemoved" => "相應的對話頁也已經移動。",
+"talkpagenotmoved" => "相應的對話頁<strong>沒有</strong>被移動。",
+
+
+# some untranslated messages as of 1.4 beta1
+'1movedto2' => "$1移動到$2", //"$1 moved to $2",
+'1movedto2_redir' => "$1重定向到$2", //"$1 moved to $2 over redirect",
+'acct_creation_throttle_hit' => "對不起,您已經註冊了$1賬號。你不能再註冊了。", //"Sorry, you have already created $1 accounts. You can't make any more.",
+'addgroup' => "增加新的組", //"Add Group",
+'allarticles' => "所有條目", //"All articles",
+'allmessages' => "系統界面", //"All system messages",
+'allmessagesnotsupportedDB' => "系統界面功能處於關閉狀態 (wgUseDatabaseMessages)。", //"Special:AllMessages not supported because wgUseDatabaseMessages is off.",
+'allmessagestext' => "這裡列出所有可定製的系統界面。", //"This is a list of all system messages available in the MediaWiki: namespace.",
+'allinnamespace' => "所有 $1 名字空間的條目", //"All pages ($1 namespace)",
+'allpagesnext' => "下一頁", //"Next",
+'allpagesprev' => "上一頁", //"Previous",
+'allpagessubmit' => "提交", //"Go",
+'ancientpages' => "老條目", //"Oldest pages",
+'and' => "和", //"and",
+'anontalk' => "該IP的對話頁", //"Talk for this IP",
+'anonymous' => "匿名用戶", //"Anonymous user(s) of 1.4",
+'article' => "條目", //"Content page",
+'autoblocker' => "你的IP和被封了的 \"$1\" 是一樣的。封鎖原因: \"$2\".",//"Autoblocked because you share an IP address with \"$1\". Reason \"$2\".",
+'blocklogentry' => "封鎖 $1, $2",//"blocked \"$1\" with an expiry time of $2",
+'blocklogpage' => "封鎖記錄", //"Block_log",
+'categoriespagetext' => "以下列出所有的頁面分類。", //"The following categories exists in the wiki.",
+'categoryarticlecount' => "該類頁面共有 $1 條目", //There are $1 articles in this category.",
+'clearyourcache' => "'''注意:''' 保存設置後,要清掉瀏覽器的緩存才能生效:'''Mozilla / Firefox:''' ''Ctrl-Shift-R'', '''Internet Explorer:''' ''Ctrl-F5'', '''Safari:''' ''Cmd-Shift-R'', '''Konqueror:''' ''F5''。",
+'edit' => "編輯", //"Edit",
+'navigation' => "導航", //"Navigation",
+'nstab-category' => "分類", //"Category",
+'nstab-help' => "幫助",//"Help",
+'nstab-image' => "圖像",//"Image",
+'nstab-main' => "條目", //"Article",
+'nstab-mediawiki' => "界面",//"Message",
+'nstab-special' => "特殊",//"Special",
+'nstab-template' => "模板", //"Template",
+'nstab-user' => "用戶頁面", //"User page",
+'nstab-wp' => "關於", //"About",
+'portal' => "社區",//"Community portal",
+'prefs-help-realname' => "*<strong>真實姓名</strong>(可選):用以對您的貢獻署名。<br />",
+'prefs-help-email' => "*<strong>點子郵件</strong>(可選):讓他人通過網站在不知道您的電子郵件地址的情況下通過電子郵件與您聯絡,以及通過電子郵件取得遺忘的密碼。", /*"* <strong>Real name</strong> (optional): if you choose to provide it this will be used for giving you attribution for your work.<br />
+* <strong>Email</strong> (optional): Enables people to contact you through the website without you having to reveal your
+email address to them, and it can be used to send you a new password if you forget it.", */
+'prefs-misc' => "雜項", //"Misc settings",
+'prefs-personal' => "用戶數據",//"User data",
+'prefs-rc' => "最近更新", //"Recent changes and stub display",
+'showhideminor' => "$1 小修改 | $2 bots | $3 登錄用戶 | $4 檢查過的", //"$1 minor edits | $2 bots | $3 logged in users | $4 patrolled edits ",
+'skin' => "面板", //"Skin",
+'talk' => "討論",//"Discussion",
+'timezonelegend' => "時區", //"Time zone",
+'toolbox' => "工具",//"Toolbox",
+'watch' => "監視",//"Watch",
+'yourlanguage' => "界面語言", //"Your language"
+'yourrealname' => "真實姓名*", //"Your real name"
+'yourvariant' => "中文字體", //"language variant"
+
+'personaltools' => "個人工具", //"personaltools""
+'history_short' => "沿革",
+"protect" => "封鎖",
+"delete" => "刪除",
+"move" => "移動",
+"tog-nocache" => "停用頁面快取",
+"specialpage" => "特殊頁面",
+"defaultns" => "預設的搜尋範圍",
+"default" => "預設",
+"aboutsite" => "關於 {{SITENAME}}",
+"disclaimers" => "免責聲明",
+"tog-fancysig" => "使用原始簽名 (不產生自動連結)",
+"tog-previewonfirst" => "第一次編輯時顯示原文內容的預覽",
+"copyright" => "本站所有內容允許以下方式利用: $1",
+"loginprompt" => "您必須允許瀏覽器紀錄Cookie才能成功登入 Wikipedia 並順利進行操作",
+);
+
+class LanguageZh_tw extends LanguageZh_cn {
+       function getBookstoreList () {
+               global $wgBookstoreListZh_tw ;
+               return $wgBookstoreListZh_tw ;
+       }
+
+       function getNamespaces() {
+               global $wgNamespaceNamesZh_tw;
+               return $wgNamespaceNamesZh_tw;
+       }
+
+
+       function getNsIndex( $text ) {
+               global $wgNamespaceNamesZh_tw;
+
+               foreach ( $wgNamespaceNamesZh_tw as $i => $n ) {
+                       if ( 0 == strcasecmp( $n, $text ) ) { return $i; }
+               }
+               # Aliases
+               if ( 0 == strcasecmp( "特殊", $text ) ) { return -1; }
+               if ( 0 == strcasecmp( "", $text ) ) { return ; }
+               if ( 0 == strcasecmp( "對話", $text ) ) { return 1; }
+               if ( 0 == strcasecmp( "用戶", $text ) ) { return 2; }
+               if ( 0 == strcasecmp( "用戶對話", $text ) ) { return 3; }
+               if ( 0 == strcasecmp( "維基百科對話", $text ) ) { return 5; }
+               if ( 0 == strcasecmp( "圖像", $text ) ) { return 6; }
+               if ( 0 == strcasecmp( "圖像對話", $text ) ) { return 7; }
+               return false;
+       }
+
+       function getQuickbarSettings() {
+               global $wgQuickbarSettingsZh_tw;
+               return $wgQuickbarSettingsZh_tw;
+       }
+
+       function getSkinNames() {
+               global $wgSkinNamesZh_tw;
+               return $wgSkinNamesZh_tw;
+       }
+
+       function getMathNames() {
+               global $wgMathNamesZh_tw;
+               return $wgMathNamesZh_tw;
+       }
+
+       function getMessage( $key ) {
+               global $wgAllMessagesZh_tw;
+               if(array_key_exists($key, $wgAllMessagesZh_tw))
+                       return $wgAllMessagesZh_tw[$key];
+               else
+                       return parent::getMessage( $key );
+       }
+
+}
+
+
+?>
diff --git a/languages/Names.php b/languages/Names.php
new file mode 100644 (file)
index 0000000..23ff0ec
--- /dev/null
@@ -0,0 +1,224 @@
+<?php
+/**
+  * @package MediaWiki
+  * @subpackage Language
+  */
+/* private */ $wgLanguageNames = array(
+       'aa' => 'Afar',                 # Afar
+       'ab' => 'Аҧсуа',   # Abkhaz, should possibly add ' бысжѡа'
+       'af' => 'Afrikaans',    # Afrikaans
+       'ak' => 'Akana',                # Akan
+       'als' => 'Alemannisch', # Alemannic
+       'am' => 'አማርኛ', # Amharic
+       'an' => 'Aragonés',    # Aragonese
+       'ang' => 'Anglo Saxon', # Old English
+       'ar' => 'العربية',       # Arabic
+       'arc' => 'ܕܥܒܪܸܝܛ',      # Aramaic
+       'as' => 'অসমীয়া',   # Assamese
+       'ast' => 'Asturianu',   # Asturian
+       'av' => 'Авар',     # Avar
+       'ay' => 'Aymar',                # Aymara, should possibly be Aymará
+       'az' => 'Azərbaycan',  # Azerbaijani
+       'ba' => 'Башҡорт',       # Bashkir
+       'be' => 'Беларуская', # Belarusian ''or'' Byelarussian
+       'bg' => 'Български',   # Bulgarian
+       'bh' => 'भोजपुरी',        # Bihara
+       'bi' => 'Bislama',              # Bislama
+       'bm' => 'Bamanankan',   # Bambara
+       'bn' => 'বাংলা',      # Bengali
+       'bo' => 'བོད་ཡིག',        # Tibetan
+       'br' => 'Brezhoneg',    # Breton
+       'bs' => 'Bosanski',             # Bosnian
+       'ca' => 'Català',      # Catalan
+       'ce' => 'Нохчийн',       # Chechen
+       'ceb' => 'Cebuano',     # Cebuano
+       'ch' => 'Chamoru',              # Chamorro
+       'cho' => 'Choctaw',             # Choctaw
+       'chr' => 'ᏣᎳᎩ', # Cherokee
+       'chy' => 'Tsetsêhestâhese',   # Cheyenne
+       'co' => 'Corsu',                # Corsican
+       'cr' => 'Nehiyaw',              # Cree
+       'cs' => 'Česky',       # Czech
+       'csb' => 'Kaszëbsczi', # Cassubian
+       'cv' => 'Чӑваш',   # Chuvash
+       'cy' => 'Cymraeg',              # Welsh
+       'da' => 'Dansk',                # Danish
+       'de' => 'Deutsch',              # German
+       'dk' => 'Dansk',                # Unused code currently redirecting to Danish, 'da' is correct for the language
+       'dv' => 'ހިބަސް',         # Dhivehi
+       'dz' => 'ཇོང་ཁ',              # Bhutani
+       'ee' => 'Ɛʋɛ',       # Ewe
+       'el' => 'Ελληνικά',     # Greek
+       'en' => 'English',              # English
+       'eo' => 'Esperanto',    # Esperanto
+       'es' => 'Español',     # Spanish
+       'et' => 'Eesti',                # Estonian
+       'eu' => 'Euskara',              # Basque
+       'fa' => 'فارسی',   # Persian
+       'ff' => 'Fulfulde',             # Fulah
+       'fi' => 'Suomi',                # Finnish
+       'fiu-vro' => 'Võro',    # Võro
+       'fj' => 'Na Vosa Vakaviti',     # Fijian
+       'fo' => 'Føroyskt',    # Faroese
+       'fr' => 'Français',    # French
+       'fur' => 'Furlan',              # Friulian
+       'fy' => 'Frysk',                # Frisian
+       'ga' => 'Gaeilge',              # Irish
+       'gd' => 'Gàidhlig',    # Scots Gaelic
+       'gl' => 'Galego',               # Gallegan
+       'gn' => 'Avañe\'ẽ',  # Guarani
+       'got' => '𐌲𐌿𐍄𐌹𐍃𐌺',    # Gothic
+       'gu' => 'ગુજરાતી',        # Gujarati
+       'gv' => 'Gaelg',                # Manx
+       'ha' => 'هَوُسَ', # Hausa
+       'haw' => 'Hawai`i',             # Hawaiian
+       'he' => 'עברית',   # Hebrew
+       'hi' => 'हिन्दी',   # Hindi
+       'ho' => 'Hiri Motu',    # Hiri Motu
+       'hr' => 'Hrvatski',             # Croatian
+       'ht' => 'Krèyol ayisyen',              # Haitian, common/popular form is Kreyòl
+       'hu' => 'Magyar',               # Hungarian
+       'hy' => 'Հայերեն',       # Armenian
+       'hz' => 'Otsiherero',   # Herero
+       'ia' => 'Interlingua',  # Interlingua (IALA)
+       'id' => 'Bahasa Indonesia',     # Indonesian
+       'ie' => 'Interlingue',  # Interlingue (Occidental)
+       'ig' => 'Igbo',                 # Igbo
+       'ii' => 'ꆇꉙ',       # Sichuan Yi
+       'ik' => 'Iñupiak',     # Inupiak
+       'io' => 'Ido',                  # Ido
+       'is' => 'Íslenska',    # Icelandic
+       'it' => 'Italiano',             # Italian
+       'iu' => 'ᐃᓄᒃᑎᑐᑦ',   # Inuktitut
+       'ja' => '日本語',    # Japanese
+       'jbo' => 'Lojban',              # Lojban
+       'jv' => 'Basa Jawa',    # Javanese
+       'ka' => 'ქართული',        # Georgian
+       'kg' => 'Kongo',                # Kongo, (FIXME!) should probaly be KiKongo or KiKoongo
+       'ki' => 'Gĩkũyũ',    # Kikuyu, correctness not guaranteed
+       'kj' => 'Kuanyama',             # Kuanyama (FIXME!)
+       'kk' => 'қазақша',       # Kazakh
+       'kl' => 'Kalaallisut',  # Greenlandic
+       'km' => 'ភាសាខ្មែរ',  # Cambodian
+       'kn' => 'ಕನ್ನಡ',      # Kannada
+       'ko' => '한국어',    # Korean
+       'kr' => 'Kanuri',               # Kanuri (FIXME!)
+       'ks' => 'कश्मीरी - (كشميري)',       # Kashmiri
+       'ku' => 'Kurdî',       # Kurdish
+       'kv' => 'Коми',     # Komi, cyrillic is common script but also written in latin script
+       'kw' => 'Kernewek',             # Cornish
+       'ky' => 'Kırgızca',   # Kirghiz
+       'la' => 'Latina',               # Latin
+       'lb' => 'Lëtzebuergesch',      # Luxemburguish
+       'lg' => 'Luganda',              # Ganda
+       'li' => 'Limburgs',     # Limburgian
+       'ln' => 'Lingala',              # Lingala
+       'lo' => 'ລາວ',# Laotian
+       'lt' => 'Lietuvių',    # Lithuanian
+       'lv' => 'Latviešu',    # Latvian
+       'mg' => 'Malagasy',             # Malagasy
+       'mh' => 'Ebon',                 # Marshallese
+       'mi' => 'Māori',       # Maori
+       'minnan' => 'Bân-lâm-gú', # Min-nan (also zh-min-nan)
+       'mk' => 'Македонски', # Macedonian
+       'ml' => 'മലയാളം',   # Malayalam
+       'mn' => 'Монгол', # Mongoloian
+       'mo' => 'Молдовеняскэ',     # Moldovan
+       'mr' => 'मराठी',      # Marathi
+       'ms' => 'Bahasa Melayu',        # Malay
+       'mt' => 'bil-Malti',    # Maltese
+       'mus' => 'Muscogee',    # Creek, should possibly be Muskogee
+       'my' => 'Myanmasa',             # Burmese
+       'na' => 'Ekakairũ Naoero',             # Nauruan
+       'nah' => 'Nahuatl',             # Nahuatl, en:Wikipedia writes Nahuatlahtolli, while another form is Náhuatl
+       'nb' => 'Norsk (bokmål)',              # Norwegian (Bokmal)
+       'nds' => 'Plattdüütsch',      # Low German ''or'' Low Saxon
+       'ne' => 'नेपाली',   # Nepali
+       'ng' => 'Oshiwambo',            # Ndonga
+       'nl' => 'Nederlands',   # Dutch
+       'nn' => 'Norsk (nynorsk)'       ,       # Norwegian (Nynorsk)
+       'no' => 'Norsk (bokmål)',              # Norwegian
+       'non' => 'Norrǿna',            # Old Norse
+       'nv' => 'Diné bizaad', # Navajo
+       'ny' => 'Chi-Chewa',    # Chichewa
+       'oc' => 'Occitan',              # Occitan
+       'om' => 'Oromoo',               # Oromo
+       'or' => 'ଓଡ଼ିଆ',         # Oriya
+       'os' => 'Иронау', # Ossetic
+       'pa' => 'ਪੰਜਾਬੀ', # Punjabi
+       'pam' => 'Pampangan',   # Pampanga
+       'pi' => 'पािऴ', # Pali
+       'pl' => 'Polski',               # Polish
+       'ps' => 'پښتو',     # Pashto
+       'pt' => 'Português',   # Portuguese
+       'qu' => 'Runa Simi',    # Quechua
+       'rm' => 'Rumantsch',    # Raeto-Romance
+       'rn' => 'Kirundi',              # Kirundi
+       'ro' => 'Română',     # Romanian
+       'roa-rup' => 'Armâneashti', # Aromanian
+       'ru' => 'Русский',       # Russian
+       'rw' => 'Kinyarwanda',  # Kinyarwanda, should possibly be Kinyarwandi
+       'sa' => 'संस्कृत',        # Sanskrit
+       'sc' => 'Sardu',                # Sardinian
+       'scn' => 'Sicilianu',   # Sicilian
+       'sco' => 'Scots',       # Scots 
+       'sd' => 'सिनधि',      # Sindhi
+       'se' => 'Sámegiella',  # Northern Sami
+       'sg' => 'Sängö',              # Sango, possible alternative is Sangho
+       'sh' => 'Srpskohrvatski/Српскохрватски', # Serbocroatian
+       'si' => 'සිංහල',      # Sinhalese
+       'simple' => 'Simple English',   # Simple English
+       'sk' => 'Slovenčina',  # Slovak
+       'sl' => 'Slovenščina',        # Slovenian
+       'sm' => 'Gagana Samoa', # Samoan
+       'sn' => 'chiShona',             # Shona
+       'so' => 'Soomaaliga',   # Somali
+       'sq' => 'Shqip',                # Albanian
+       'sr' => 'Српски / Srpski',        # Serbian
+       'ss' => 'SiSwati',              # Swati
+       'st' => 'seSotho',              # Southern Sotho
+       'su' => 'Basa Sunda',   # Sundanese
+       'sv' => 'Svenska',              # Swedish
+       'sw' => 'Kiswahili',    # Swahili
+       'ta' => 'தமிழ்',      # Tamil
+       'te' => 'తెలుగు',   # Telugu
+       'tg' => 'Тоҷикӣ', # Tajik
+       'th' => 'ไทย',    # Thai
+       'ti' => 'ትግርኛ',         # Tigrinya
+       'tk' => 'تركمن / Туркмен',  # Turkmen
+       'tl' => 'Tagalog',              # Tagalog (Filipino)
+       #'tlh' => 'tlhIngan-Hol',       # Klingon - no interlanguage links allowed
+       'tn' => 'Setswana',             # Setswana
+       'to' => 'faka-Tonga',           # Tonga (Tonga Islands)
+       'tokipona' => 'Toki Pona',      # Toki Pona
+       'tp' => 'Toki Pona',    # Toki Pona - non-standard language code
+       'tpi' => 'Tok Pisin',   # Tok Pisin
+       'tr' => 'Türkçe',     # Turkish
+       'ts' => 'Xitsonga',             # Tsonga
+       'tt' => 'Tatarça',     # Tatar
+       'tum' => 'chiTumbuka',  # Tumbuka
+       'tw' => 'Twi',                  # Twi, (FIXME!)
+       'ty' => 'Reo Mā`ohi',  # Tahitian
+       'ug' => 'Oyghurque',    # Uyghur
+       'uk' => 'Українська', # Ukrainian
+       'ur' => 'اردو',     # Urdu
+       'uz' => 'Ўзбек',   # Uzbek
+       've' => 'Tshivenda',            # Venda
+       'vi' => 'Tiếng Việt',       # Vietnamese
+       'vo' => 'Volapük',     # Volapük
+       'wa' => 'Walon',                # Walloon
+       'wo' => 'Wollof',               # Wolof
+       'xh' => 'isiXhosa',             # Xhosan
+       'yi' => 'ייִדיש', # Yiddish
+       'yo' => 'Yorùbá',     # Yoruba
+       'za' => '(Cuengh)',             # Zhuang
+       'zh' => '中文',       # (Zhōng Wén) - Chinese
+       'zh-cfr' => '閩南語', # Min-nan alias (site is at minnan)
+       'zh-cn' => '中文(简体)',    # Simplified
+       'zh-hk' => '中文(繁體)',    # Traditional (Hong Kong)
+       'zh-min-nan' => 'Bân-lâm-gú', # Min-nan
+       'zh-sg' => '中文(简体)', # Simplified (Singapore)
+       'zh-tw' => '中文(繁體)',    # Traditional
+       'zu' => 'isiZulu'               # Zulu
+);
+?>
diff --git a/maintenance/.htaccess b/maintenance/.htaccess
new file mode 100644 (file)
index 0000000..3a42882
--- /dev/null
@@ -0,0 +1 @@
+Deny from all
diff --git a/maintenance/FiveUpgrade.inc b/maintenance/FiveUpgrade.inc
new file mode 100644 (file)
index 0000000..4c8fcbc
--- /dev/null
@@ -0,0 +1,1213 @@
+<?php
+
+require_once( 'cleanupDupes.inc' );
+require_once( 'userDupes.inc' );
+require_once( 'updaters.inc' );
+
+define( 'MW_UPGRADE_COPY',     false );
+define( 'MW_UPGRADE_ENCODE',   true  );
+define( 'MW_UPGRADE_NULL',     null  );
+define( 'MW_UPGRADE_CALLBACK', null  ); // for self-documentation only
+
+class FiveUpgrade {
+       function FiveUpgrade() {
+               global $wgDatabase;
+               $this->conversionTables = $this->prepareWindows1252();
+               
+               $this->dbw =& $this->newConnection();
+               $this->dbr =& $this->streamConnection();
+               
+               $this->cleanupSwaps = array();
+               $this->emailAuth = false; # don't preauthenticate emails
+               $this->maxLag    = 10; # if slaves are lagged more than 10 secs, wait
+       }
+       
+       function doing( $step ) {
+               return is_null( $this->step ) || $step == $this->step;
+       }
+       
+       function upgrade( $step ) {
+               $this->step = $step;
+               
+               $tables = array(
+                       'page',
+                       'links',
+                       'user',
+                       'image',
+                       'oldimage',
+                       'watchlist',
+                       'logging',
+                       'archive',
+                       'imagelinks',
+                       'categorylinks',
+                       'ipblocks',
+                       'recentchanges',
+                       'querycache' );
+               foreach( $tables as $table ) {
+                       if( $this->doing( $table ) ) {
+                               $method = 'upgrade' . ucfirst( $table );
+                               $this->$method();
+                       }
+               }
+               
+               if( $this->doing( 'cleanup' ) ) {
+                       $this->upgradeCleanup();
+               }
+       }
+       
+       
+       /**
+        * Open a connection to the master server with the admin rights.
+        * @return Database
+        * @access private
+        */
+       function &newConnection() {
+               global $wgDBadminuser, $wgDBadminpassword;
+               global $wgDBserver, $wgDBname;
+               $db =& new Database( $wgDBserver, $wgDBadminuser, $wgDBadminpassword, $wgDBname );
+               return $db;
+       }
+       
+       /**
+        * Open a second connection to the master server, with buffering off.
+        * This will let us stream large datasets in and write in chunks on the
+        * other end.
+        * @return Database
+        * @access private
+        */
+       function &streamConnection() {
+               $timeout = 3600 * 24;
+               $db =& $this->newConnection();
+               $db->bufferResults( false );
+               $db->query( "SET net_read_timeout=$timeout" );
+               $db->query( "SET net_write_timeout=$timeout" );
+               return $db;
+       }
+       
+       /**
+        * Prepare a conversion array for converting Windows Code Page 1252 to
+        * UTF-8. This should provide proper conversion of text that was miscoded
+        * as Windows-1252 by naughty user-agents, and doesn't rely on an outside
+        * iconv library.
+        *
+        * @return array
+        * @access private
+        */
+       function prepareWindows1252() {
+               # Mappings from:
+               # http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1252.TXT
+               static $cp1252 = array(
+                       0x80 => 0x20AC, #EURO SIGN
+                       0x81 => UNICODE_REPLACEMENT,
+                       0x82 => 0x201A, #SINGLE LOW-9 QUOTATION MARK
+                       0x83 => 0x0192, #LATIN SMALL LETTER F WITH HOOK
+                       0x84 => 0x201E, #DOUBLE LOW-9 QUOTATION MARK
+                       0x85 => 0x2026, #HORIZONTAL ELLIPSIS
+                       0x86 => 0x2020, #DAGGER
+                       0x87 => 0x2021, #DOUBLE DAGGER
+                       0x88 => 0x02C6, #MODIFIER LETTER CIRCUMFLEX ACCENT
+                       0x89 => 0x2030, #PER MILLE SIGN
+                       0x8A => 0x0160, #LATIN CAPITAL LETTER S WITH CARON
+                       0x8B => 0x2039, #SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+                       0x8C => 0x0152, #LATIN CAPITAL LIGATURE OE
+                       0x8D => UNICODE_REPLACEMENT,
+                       0x8E => 0x017D, #LATIN CAPITAL LETTER Z WITH CARON
+                       0x8F => UNICODE_REPLACEMENT,
+                       0x90 => UNICODE_REPLACEMENT,
+                       0x91 => 0x2018, #LEFT SINGLE QUOTATION MARK
+                       0x92 => 0x2019, #RIGHT SINGLE QUOTATION MARK
+                       0x93 => 0x201C, #LEFT DOUBLE QUOTATION MARK
+                       0x94 => 0x201D, #RIGHT DOUBLE QUOTATION MARK
+                       0x95 => 0x2022, #BULLET
+                       0x96 => 0x2013, #EN DASH
+                       0x97 => 0x2014, #EM DASH
+                       0x98 => 0x02DC, #SMALL TILDE
+                       0x99 => 0x2122, #TRADE MARK SIGN
+                       0x9A => 0x0161, #LATIN SMALL LETTER S WITH CARON
+                       0x9B => 0x203A, #SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+                       0x9C => 0x0153, #LATIN SMALL LIGATURE OE
+                       0x9D => UNICODE_REPLACEMENT,
+                       0x9E => 0x017E, #LATIN SMALL LETTER Z WITH CARON
+                       0x9F => 0x0178, #LATIN CAPITAL LETTER Y WITH DIAERESIS
+                       );
+               $pairs = array();
+               for( $i = 0; $i < 0x100; $i++ ) {
+                       $unicode = isset( $cp1252[$i] ) ? $cp1252[$i] : $i;
+                       $pairs[chr( $i )] = codepointToUtf8( $unicode );
+               }
+               return $pairs;
+       }
+       
+       /**
+        * Convert from 8-bit Windows-1252 to UTF-8 if necessary.
+        * @param string $text
+        * @return string
+        * @access private
+        */
+       function conv( $text ) {
+               global $wgUseLatin1;
+               return is_null( $text )
+                       ? null
+                       : ( $wgUseLatin1
+                               ? strtr( $text, $this->conversionTables )
+                               : $text );
+       }
+       
+       /**
+        * Dump timestamp and message to output
+        * @param string $message
+        * @access private
+        */
+       function log( $message ) {
+               echo wfTimestamp( TS_DB ) . ': ' . $message . "\n";
+               flush();
+       }
+       
+       /**
+        * Initialize the chunked-insert system.
+        * Rows will be inserted in chunks of the given number, rather
+        * than in a giant INSERT...SELECT query, to keep the serialized
+        * MySQL database replication from getting hung up. This way other
+        * things can be going on during conversion without waiting for
+        * slaves to catch up as badly.
+        *
+        * @param int $chunksize Number of rows to insert at once
+        * @param int $final Total expected number of rows / id of last row,
+        *                   used for progress reports.
+        * @param string $table to insert on
+        * @param string $fname function name to report in SQL
+        * @access private
+        */
+       function setChunkScale( $chunksize, $final, $table, $fname ) {
+               $this->chunkSize  = $chunksize;
+               $this->chunkFinal = $final;
+               $this->chunkCount = 0;
+               $this->chunkStartTime = wfTime();
+               $this->chunkOptions = array( 'IGNORE' );
+               $this->chunkTable = $table;
+               $this->chunkFunction = $fname;
+       }
+       
+       /**
+        * Chunked inserts: perform an insert if we've reached the chunk limit.
+        * Prints a progress report with estimated completion time.
+        * @param array &$chunk -- This will be emptied if an insert is done.
+        * @param int $key A key identifier to use in progress estimation in
+        *                 place of the number of rows inserted. Use this if
+        *                 you provided a max key number instead of a count
+        *                 as the final chunk number in setChunkScale()
+        * @access private
+        */
+       function addChunk( &$chunk, $key = null ) {
+               if( count( $chunk ) >= $this->chunkSize ) {
+                       $this->insertChunk( $chunk );
+               
+                       $this->chunkCount += count( $chunk );
+                       $now = wfTime();
+                       $delta = $now - $this->chunkStartTime;
+                       $rate = $this->chunkCount / $delta;
+                       
+                       if( is_null( $key ) ) {
+                               $completed = $this->chunkCount;
+                       } else {
+                               $completed = $key;
+                       }
+                       $portion = $completed / $this->chunkFinal;
+                       
+                       $estimatedTotalTime = $delta / $portion;
+                       $eta = $this->chunkStartTime + $estimatedTotalTime;
+                       
+                       printf( "%s: %6.2f%% done on %s; ETA %s [%d/%d] %.2f/sec\n",
+                               wfTimestamp( TS_DB, intval( $now ) ),
+                               $portion * 100.0,
+                               $this->chunkTable,
+                               wfTimestamp( TS_DB, intval( $eta ) ),
+                               $completed,
+                               $this->chunkFinal,
+                               $rate );
+                       flush();
+                       
+                       $chunk = array();
+               }
+       }
+       
+       /**
+        * Chunked inserts: perform an insert unconditionally, at the end, and log.
+        * @param array &$chunk -- This will be emptied if an insert is done.
+        * @access private
+        */
+       function lastChunk( &$chunk ) {
+               $n = count( $chunk );
+               if( $n > 0 ) {
+                       $this->insertChunk( $chunk );
+               }
+               $this->log( "100.00% done on $this->chunkTable (last chunk $n rows)." );
+       }
+       
+       /**
+        * Chunked inserts: perform an insert.
+        * @param array &$chunk -- This will be emptied if an insert is done.
+        * @access private
+        */
+       function insertChunk( &$chunk ) {
+               // Give slaves a chance to catch up
+               wfWaitForSlaves( $this->maxLag );
+               $this->dbw->insert( $this->chunkTable, $chunk, $this->chunkFunction, $this->chunkOptions );
+       }
+       
+       
+       /**
+        * Copy and transcode a table to table_temp.
+        * @param string $name Base name of the source table
+        * @param string $tabledef CREATE TABLE definition, w/ $1 for the name
+        * @param array $fields set of destination fields to these constants:
+        *              MW_UPGRADE_COPY   - straight copy
+        *              MW_UPGRADE_ENCODE - for old Latin1 wikis, conv to UTF-8
+        *              MW_UPGRADE_NULL   - just put NULL
+        * @param callable $callback An optional callback to modify the data
+        *                           or perform other processing. Func should be
+        *                           ( object $row, array $copy ) and return $copy
+        * @access private
+        */
+       function copyTable( $name, $tabledef, $fields, $callback = null ) {
+               $fname = 'FiveUpgrade::copyTable';
+               
+               $name_temp = $name . '_temp';
+               $this->log( "Migrating $name table to $name_temp..." );
+
+               $table      = $this->dbw->tableName( $name );
+               $table_temp = $this->dbw->tableName( $name_temp );
+               
+               // Create temporary table; we're going to copy everything in there,
+               // then at the end rename the final tables into place.
+               $def = str_replace( '$1', $table_temp, $tabledef );
+               $this->dbw->query( $def, $fname );
+               
+               $numRecords = $this->dbw->selectField( $name, 'COUNT(*)', '', $fname );
+               $this->setChunkScale( 100, $numRecords, $name_temp, $fname );
+               
+               // Pull all records from the second, streaming database connection.
+               $sourceFields = array_keys( array_filter( $fields,
+                       create_function( '$x', 'return $x !== MW_UPGRADE_NULL;' ) ) );
+               $result = $this->dbr->select( $name,
+                       $sourceFields,
+                       '',
+                       $fname );
+               
+               $add = array();
+               while( $row = $this->dbr->fetchObject( $result ) ) {
+                       $copy = array();
+                       foreach( $fields as $field => $source ) {
+                               if( $source === MW_UPGRADE_COPY ) {
+                                       $copy[$field] = $row->$field;
+                               } elseif( $source === MW_UPGRADE_ENCODE ) {
+                                       $copy[$field] = $this->conv( $row->$field );
+                               } elseif( $source === MW_UPGRADE_NULL ) {
+                                       $copy[$field] = null;
+                               } else {
+                                       $this->log( "Unknown field copy type: $field => $source" );
+                               }
+                       }
+                       if( is_callable( $callback ) ) {
+                               $copy = call_user_func( $callback, $row, $copy );
+                       }
+                       $add[] = $copy;
+                       $this->addChunk( $add );
+               }
+               $this->lastChunk( $add );
+               $this->dbr->freeResult( $result );
+               
+               $this->log( "Done converting $name." );
+               $this->cleanupSwaps[] = $name;
+       }
+       
+       function upgradePage() {
+               $fname = "FiveUpgrade::upgradePage";
+               $chunksize = 100;
+               
+               if( $this->dbw->tableExists( 'page' ) ) {
+                       $this->log( 'Page table already exists; aborting.' );
+                       die( -1 );
+               }
+               
+               $this->log( "Checking cur table for unique title index and applying if necessary" );
+               checkDupes( true );
+
+               $this->log( "...converting from cur/old to page/revision/text DB structure." );
+               
+               extract( $this->dbw->tableNames( 'cur', 'old', 'page', 'revision', 'text' ) );
+
+               $this->log( "Creating page and revision tables..." );
+               $this->dbw->query("CREATE TABLE $page (
+                       page_id int(8) unsigned NOT NULL auto_increment,
+                       page_namespace int NOT NULL,
+                       page_title varchar(255) binary NOT NULL,
+                       page_restrictions tinyblob NOT NULL default '',
+                       page_counter bigint(20) unsigned NOT NULL default '0',
+                       page_is_redirect tinyint(1) unsigned NOT NULL default '0',
+                       page_is_new tinyint(1) unsigned NOT NULL default '0',
+                       page_random real unsigned NOT NULL,
+                       page_touched char(14) binary NOT NULL default '',
+                       page_latest int(8) unsigned NOT NULL,
+                       page_len int(8) unsigned NOT NULL,
+
+                       PRIMARY KEY page_id (page_id),
+                       UNIQUE INDEX name_title (page_namespace,page_title),
+                       INDEX (page_random),
+                       INDEX (page_len)
+                       ) TYPE=InnoDB", $fname );
+               $this->dbw->query("CREATE TABLE $revision (
+                       rev_id int(8) unsigned NOT NULL auto_increment,
+                       rev_page int(8) unsigned NOT NULL,
+                       rev_text_id int(8) unsigned NOT NULL,
+                       rev_comment tinyblob NOT NULL default '',
+                       rev_user int(5) unsigned NOT NULL default '0',
+                       rev_user_text varchar(255) binary NOT NULL default '',
+                       rev_timestamp char(14) binary NOT NULL default '',
+                       rev_minor_edit tinyint(1) unsigned NOT NULL default '0',
+                       rev_deleted tinyint(1) unsigned NOT NULL default '0',
+  
+                       PRIMARY KEY rev_page_id (rev_page, rev_id),
+                       UNIQUE INDEX rev_id (rev_id),
+                       INDEX rev_timestamp (rev_timestamp),
+                       INDEX page_timestamp (rev_page,rev_timestamp),
+                       INDEX user_timestamp (rev_user,rev_timestamp),
+                       INDEX usertext_timestamp (rev_user_text,rev_timestamp)
+                       ) TYPE=InnoDB", $fname );
+
+               $maxold = IntVal( $this->dbw->selectField( 'old', 'max(old_id)', '', $fname ) );
+               $this->log( "Last old record is {$maxold}" );
+
+               global $wgLegacySchemaConversion;
+               if( $wgLegacySchemaConversion ) {
+                       // Create HistoryBlobCurStub entries.
+                       // Text will be pulled from the leftover 'cur' table at runtime.
+                       echo "......Moving metadata from cur; using blob references to text in cur table.\n";
+                       $cur_text = "concat('O:18:\"historyblobcurstub\":1:{s:6:\"mCurId\";i:',cur_id,';}')";
+                       $cur_flags = "'object'";
+               } else {
+                       // Copy all cur text in immediately: this may take longer but avoids
+                       // having to keep an extra table around.
+                       echo "......Moving text from cur.\n";
+                       $cur_text = 'cur_text';
+                       $cur_flags = "''";
+               }
+
+               $maxcur = $this->dbw->selectField( 'cur', 'max(cur_id)', '', $fname );
+               $this->log( "Last cur entry is $maxcur" );
+               
+               /**
+                * Copy placeholder records for each page's current version into old
+                * Don't do any conversion here; text records are converted at runtime
+                * based on the flags (and may be originally binary!) while the meta
+                * fields will be converted in the old -> rev and cur -> page steps.
+                */
+               $this->setChunkScale( $chunksize, $maxcur, 'old', $fname );
+               $result = $this->dbr->query(
+                       "SELECT cur_id, cur_namespace, cur_title, $cur_text AS text, cur_comment,
+                       cur_user, cur_user_text, cur_timestamp, cur_minor_edit, $cur_flags AS flags
+                       FROM $cur
+                       ORDER BY cur_id", $fname );
+               $add = array();
+               while( $row = $this->dbr->fetchObject( $result ) ) {
+                       $add[] = array(
+                               'old_namespace'  => $row->cur_namespace,
+                               'old_title'      => $row->cur_title,
+                               'old_text'       => $row->text,
+                               'old_comment'    => $row->cur_comment,
+                               'old_user'       => $row->cur_user,
+                               'old_user_text'  => $row->cur_user_text,
+                               'old_timestamp'  => $row->cur_timestamp,
+                               'old_minor_edit' => $row->cur_minor_edit,
+                               'old_flags'      => $row->flags );
+                       $this->addChunk( $add, $row->cur_id );
+               }
+               $this->lastChunk( $add );
+               $this->dbr->freeResult( $result );
+               
+               /**
+                * Copy revision metadata from old into revision.
+                * We'll also do UTF-8 conversion of usernames and comments.
+                */
+               #$newmaxold = $this->dbw->selectField( 'old', 'max(old_id)', '', $fname );
+               #$this->setChunkScale( $chunksize, $newmaxold, 'revision', $fname );
+               #$countold = $this->dbw->selectField( 'old', 'count(old_id)', '', $fname );
+               $countold = $this->dbw->selectField( 'old', 'max(old_id)', '', $fname );
+               $this->setChunkScale( $chunksize, $countold, 'revision', $fname );
+               
+               $this->log( "......Setting up revision table." );
+               $result = $this->dbr->query(
+                       "SELECT old_id, cur_id, old_comment, old_user, old_user_text,
+                       old_timestamp, old_minor_edit
+                       FROM $old,$cur WHERE old_namespace=cur_namespace AND old_title=cur_title",
+                       $fname );
+
+               $add = array();
+               while( $row = $this->dbr->fetchObject( $result ) ) {
+                       $add[] = array(
+                               'rev_id'         =>              $row->old_id,
+                               'rev_page'       =>              $row->cur_id,
+                               'rev_text_id'    =>              $row->old_id,
+                               'rev_comment'    => $this->conv( $row->old_comment ),
+                               'rev_user'       =>              $row->old_user,
+                               'rev_user_text'  => $this->conv( $row->old_user_text ),
+                               'rev_timestamp'  =>              $row->old_timestamp,
+                               'rev_minor_edit' =>              $row->old_minor_edit );
+                       $this->addChunk( $add );
+               }
+               $this->lastChunk( $add );
+               $this->dbr->freeResult( $result );
+               
+
+               /**
+                * Copy page metadata from cur into page.
+                * We'll also do UTF-8 conversion of titles.
+                */
+               $this->log( "......Setting up page table." );
+               $this->setChunkScale( $chunksize, $maxcur, 'page', $fname );
+               $result = $this->dbr->query( "
+                       SELECT cur_id, cur_namespace, cur_title, cur_restrictions, cur_counter, cur_is_redirect, cur_is_new,
+                               cur_random, cur_touched, rev_id, LENGTH(cur_text) AS len
+                       FROM $cur,$revision
+                       WHERE cur_id=rev_page AND rev_timestamp=cur_timestamp AND rev_id > {$maxold}
+                       ORDER BY cur_id", $fname );
+               $add = array();
+               while( $row = $this->dbr->fetchObject( $result ) ) {
+                       $add[] = array(
+                               'page_id'           =>              $row->cur_id,
+                               'page_namespace'    =>              $row->cur_namespace,
+                               'page_title'        => $this->conv( $row->cur_title ),
+                               'page_restrictions' =>              $row->cur_restrictions,
+                               'page_counter'      =>              $row->cur_counter,
+                               'page_is_redirect'  =>              $row->cur_is_redirect,
+                               'page_is_new'       =>              $row->cur_is_new,
+                               'page_random'       =>              $row->cur_random,
+                               'page_touched'      =>              $this->dbw->timestamp(),
+                               'page_latest'       =>              $row->rev_id,
+                               'page_len'          =>              $row->len );
+                       #$this->addChunk( $add, $row->cur_id );
+                       $this->addChunk( $add );
+               }
+               $this->lastChunk( $add );
+               $this->dbr->freeResult( $result );
+               
+               $this->log( "...done with cur/old -> page/revision." );
+       }
+       
+       function upgradeLinks() {
+               $fname = 'FiveUpgrade::upgradeLinks';
+               $chunksize = 200;
+               extract( $this->dbw->tableNames( 'links', 'brokenlinks', 'pagelinks', 'cur' ) );
+               
+               $this->log( 'Checking for interwiki table change in case of bogus items...' );
+               if( $this->dbw->fieldExists( 'interwiki', 'iw_trans' ) ) {
+                       $this->log( 'interwiki has iw_trans.' );
+               } else {
+                       $this->log( 'adding iw_trans...' );
+                       dbsource( 'maintenance/archives/patch-interwiki-trans.sql', $this->dbw );
+                       $this->log( 'added iw_trans.' );
+               }
+               
+               $this->log( 'Creating pagelinks table...' );
+               $this->dbw->query( "
+CREATE TABLE $pagelinks (
+  -- Key to the page_id of the page containing the link.
+  pl_from int(8) unsigned NOT NULL default '0',
+  
+  -- Key to page_namespace/page_title of the target page.
+  -- The target page may or may not exist, and due to renames
+  -- and deletions may refer to different page records as time
+  -- goes by.
+  pl_namespace int NOT NULL default '0',
+  pl_title varchar(255) binary NOT NULL default '',
+  
+  UNIQUE KEY pl_from(pl_from,pl_namespace,pl_title),
+  KEY (pl_namespace,pl_title)
+
+) TYPE=InnoDB" );
+
+               $this->log( 'Importing live links -> pagelinks' );
+               $nlinks = $this->dbw->selectField( 'links', 'count(*)', '', $fname );
+               if( $nlinks ) {
+                       $this->setChunkScale( $chunksize, $nlinks, 'pagelinks', $fname );
+                       $result = $this->dbr->query( "
+                         SELECT l_from,cur_namespace,cur_title
+                               FROM $links, $cur
+                               WHERE l_to=cur_id", $fname );
+                       $add = array();
+                       while( $row = $this->dbr->fetchObject( $result ) ) {
+                               $add[] = array(
+                                       'pl_from'      =>              $row->l_from,
+                                       'pl_namespace' =>              $row->cur_namespace,
+                                       'pl_title'     => $this->conv( $row->cur_title ) );
+                               $this->addChunk( $add );
+                       }
+                       $this->lastChunk( $add );
+               } else {
+                       $this->log( 'no links!' );
+               }
+               
+               $this->log( 'Importing brokenlinks -> pagelinks' );
+               $nbrokenlinks = $this->dbw->selectField( 'brokenlinks', 'count(*)', '', $fname );
+               if( $nbrokenlinks ) {
+                       $this->setChunkScale( $chunksize, $nbrokenlinks, 'pagelinks', $fname );
+                       $result = $this->dbr->query(
+                               "SELECT bl_from, bl_to FROM $brokenlinks",
+                               $fname );
+                       $add = array();
+                       while( $row = $this->dbr->fetchObject( $result ) ) {
+                               $pagename = $this->conv( $row->bl_to );
+                               $title = Title::newFromText( $pagename );
+                               if( is_null( $title ) ) {
+                                       $this->log( "** invalid brokenlink: $row->bl_from -> '$pagename' (converted from '$row->bl_to')" );
+                               } else {
+                                       $add[] = array(
+                                               'pl_from'      => $row->bl_from,
+                                               'pl_namespace' => $title->getNamespace(),
+                                               'pl_title'     => $title->getDBkey() );
+                                       $this->addChunk( $add );
+                               }
+                       }
+                       $this->lastChunk( $add );
+               } else {
+                       $this->log( 'no brokenlinks!' );
+               }
+               
+               $this->log( 'Done with links.' );
+       }
+       
+       function upgradeUser() {
+               // Apply unique index, if necessary:
+               $duper = new UserDupes( $this->dbw );
+               if( $duper->hasUniqueIndex() ) {
+                       $this->log( "Already have unique user_name index." );
+               } else {
+                       $this->log( "Clearing user duplicates..." );
+                       if( !$duper->clearDupes() ) {
+                               $this->log( "WARNING: Duplicate user accounts, may explode!" );
+                       }
+               }
+               
+               $tabledef = <<<END
+CREATE TABLE $1 (
+  user_id int(5) unsigned NOT NULL auto_increment,
+  user_name varchar(255) binary NOT NULL default '',
+  user_real_name varchar(255) binary NOT NULL default '',
+  user_password tinyblob NOT NULL default '',
+  user_newpassword tinyblob NOT NULL default '',
+  user_email tinytext NOT NULL default '',
+  user_options blob NOT NULL default '',
+  user_touched char(14) binary NOT NULL default '',
+  user_token char(32) binary NOT NULL default '',
+  user_email_authenticated CHAR(14) BINARY,
+  user_email_token CHAR(32) BINARY,
+  user_email_token_expires CHAR(14) BINARY,
+
+  PRIMARY KEY user_id (user_id),
+  UNIQUE INDEX user_name (user_name),
+  INDEX (user_email_token)
+
+) TYPE=InnoDB
+END;
+               $fields = array(
+                       'user_id'                  => MW_UPGRADE_COPY,
+                       'user_name'                => MW_UPGRADE_ENCODE,
+                       'user_real_name'           => MW_UPGRADE_ENCODE,
+                       'user_password'            => MW_UPGRADE_COPY,
+                       'user_newpassword'         => MW_UPGRADE_COPY,
+                       'user_email'               => MW_UPGRADE_ENCODE,
+                       'user_options'             => MW_UPGRADE_ENCODE,
+                       'user_touched'             => MW_UPGRADE_CALLBACK,
+                       'user_token'               => MW_UPGRADE_COPY,
+                       'user_email_authenticated' => MW_UPGRADE_CALLBACK,
+                       'user_email_token'         => MW_UPGRADE_NULL,
+                       'user_email_token_expires' => MW_UPGRADE_NULL );
+               $this->copyTable( 'user', $tabledef, $fields,
+                       array( &$this, 'userCallback' ) );
+       }
+       
+       function userCallback( $row, $copy ) {
+               $now = $this->dbw->timestamp();
+               $copy['user_touched'] = $now;
+               $copy['user_email_authenticated'] = $this->emailAuth ? $now : null;
+               return $copy;
+       }
+       
+       function upgradeImage() {
+               $tabledef = <<<END
+CREATE TABLE $1 (
+  img_name varchar(255) binary NOT NULL default '',
+  img_size int(8) unsigned NOT NULL default '0',
+  img_width int(5)  NOT NULL default '0',
+  img_height int(5)  NOT NULL default '0',
+  img_metadata mediumblob NOT NULL,
+  img_bits int(3)  NOT NULL default '0',
+  img_media_type ENUM("UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE") default NULL,
+  img_major_mime ENUM("unknown", "application", "audio", "image", "text", "video", "message", "model", "multipart") NOT NULL default "unknown",
+  img_minor_mime varchar(32) NOT NULL default "unknown",
+  img_description tinyblob NOT NULL default '',
+  img_user int(5) unsigned NOT NULL default '0',
+  img_user_text varchar(255) binary NOT NULL default '',
+  img_timestamp char(14) binary NOT NULL default '',
+  
+  PRIMARY KEY img_name (img_name),
+  INDEX img_size (img_size),
+  INDEX img_timestamp (img_timestamp)
+) TYPE=InnoDB
+END;
+               $fields = array(
+                       'img_name'        => MW_UPGRADE_ENCODE,
+                       'img_size'        => MW_UPGRADE_COPY,
+                       'img_width'       => MW_UPGRADE_CALLBACK,
+                       'img_height'      => MW_UPGRADE_CALLBACK,
+                       'img_metadata'    => MW_UPGRADE_CALLBACK,
+                       'img_bits'        => MW_UPGRADE_CALLBACK,
+                       'img_media_type'  => MW_UPGRADE_CALLBACK,
+                       'img_major_mime'  => MW_UPGRADE_CALLBACK,
+                       'img_minor_mime'  => MW_UPGRADE_CALLBACK,
+                       'img_description' => MW_UPGRADE_ENCODE,
+                       'img_user'        => MW_UPGRADE_COPY,
+                       'img_user_text'   => MW_UPGRADE_ENCODE,
+                       'img_timestamp'   => MW_UPGRADE_COPY );
+               $this->copyTable( 'image', $tabledef, $fields,
+                       array( &$this, 'imageCallback' ) );
+       }
+       
+       function imageCallback( $row, $copy ) {
+               global $options;
+               if( !isset( $options['noimage'] ) ) {
+                       // Fill in the new image info fields
+                       $info = $this->imageInfo( $row->img_name );
+                       
+                       $copy['img_width'     ] = $info['width'];
+                       $copy['img_height'    ] = $info['height'];
+                       $copy['img_metadata'  ] = ""; // loaded on-demand
+                       $copy['img_bits'      ] = $info['bits'];
+                       $copy['img_media_type'] = $info['media'];
+                       $copy['img_major_mime'] = $info['major'];
+                       $copy['img_minor_mime'] = $info['minor'];
+               }
+               
+               // If doing UTF8 conversion the file must be renamed
+               $this->renameFile( $row->img_name, 'wfImageDir' );
+               
+               return $copy;
+       }
+       
+       function imageInfo( $name, $subdirCallback='wfImageDir', $basename = null ) {
+               if( is_null( $basename ) ) $basename = $name;
+               $dir = call_user_func( $subdirCallback, $basename );
+               $filename = $dir . '/' . $name;
+               $info = array(
+                       'width'  => 0,
+                       'height' => 0,
+                       'bits'   => 0,
+                       'media'  => '',
+                       'major'  => '',
+                       'minor'  => '' );
+               
+               $magic =& wfGetMimeMagic();
+               $mime = $magic->guessMimeType( $filename, true );
+               list( $info['major'], $info['minor'] ) = explode( '/', $mime );
+               
+               $info['media'] = $magic->getMediaType( $filename, $mime );
+               
+               # Height and width
+               $gis = false;
+               if( $mime == 'image/svg' ) {
+                       $gis = wfGetSVGsize( $this->imagePath );
+               } elseif( $magic->isPHPImageType( $mime ) ) {
+                       $gis = getimagesize( $filename );
+               } else {
+                       $this->log( "Surprising mime type: $mime" );
+               }
+               if( $gis ) {
+                       $info['width' ] = $gis[0];
+                       $info['height'] = $gis[1];
+               }
+               if( isset( $gis['bits'] ) ) {
+                       $info['bits'] = $gis['bits'];
+               }
+               
+               return $info;
+       }
+       
+
+       /**
+        * Truncate a table.
+        * @param string $table The table name to be truncated
+        */
+       function clearTable( $table ) {
+               print "Clearing $table...\n";
+               $tableName = $this->db->tableName( $table );
+               $this->db->query( 'TRUNCATE $tableName' );
+       }
+       
+       /**
+        * Rename a given image or archived image file to the converted filename,
+        * leaving a symlink for URL compatibility.
+        *
+        * @param string $oldname pre-conversion filename
+        * @param string $basename pre-conversion base filename for dir hashing, if an archive
+        * @access private
+        */
+       function renameFile( $oldname, $subdirCallback='wfImageDir', $basename=null ) {
+               $newname = $this->conv( $oldname );
+               if( $newname == $oldname ) {
+                       // No need to rename; another field triggered this row.
+                       return false;
+               }
+               
+               if( is_null( $basename ) ) $basename = $oldname;
+               $ubasename = $this->conv( $basename );
+               $oldpath = call_user_func( $subdirCallback, $basename ) . '/' . $oldname;
+               $newpath = call_user_func( $subdirCallback, $ubasename ) . '/' . $newname;
+               
+               $this->log( "$oldpath -> $newpath" );
+               if( rename( $oldpath, $newpath ) ) {
+                       $relpath = $this->relativize( $newpath, dirname( $oldpath ) );
+                       if( !symlink( $relpath, $oldpath ) ) {
+                               $this->log( "... symlink failed!" );
+                       }
+                       return $newname;
+               } else {
+                       $this->log( "... rename failed!" );
+                       return false;
+               }
+       }
+       
+       /**
+        * Generate a relative path name to the given file.
+        * Assumes Unix-style paths, separators, and semantics.
+        *
+        * @param string $path Absolute destination path including target filename
+        * @param string $from Absolute source path, directory only
+        * @return string
+        * @access private
+        * @static
+        */
+       function relativize( $path, $from ) {
+               $pieces  = explode( '/', dirname( $path ) );
+               $against = explode( '/', $from );
+               
+               // Trim off common prefix
+               while( count( $pieces ) && count( $against )
+                       && $pieces[0] == $against[0] ) {
+                       array_shift( $pieces );
+                       array_shift( $against );
+               }
+               
+               // relative dots to bump us to the parent
+               while( count( $against ) ) {
+                       array_unshift( $pieces, '..' );
+                       array_shift( $against );
+               }
+               
+               array_push( $pieces, basename( $path ) );
+               
+               return implode( '/', $pieces );
+       }
+       
+       function upgradeOldImage() {
+               $tabledef = <<<END
+CREATE TABLE $1 (
+  -- Base filename: key to image.img_name
+  oi_name varchar(255) binary NOT NULL default '',
+  
+  -- Filename of the archived file.
+  -- This is generally a timestamp and '!' prepended to the base name.
+  oi_archive_name varchar(255) binary NOT NULL default '',
+  
+  -- Other fields as in image...
+  oi_size int(8) unsigned NOT NULL default 0,
+  oi_width int(5) NOT NULL default 0,
+  oi_height int(5) NOT NULL default 0,
+  oi_bits int(3) NOT NULL default 0,
+  oi_description tinyblob NOT NULL default '',
+  oi_user int(5) unsigned NOT NULL default '0',
+  oi_user_text varchar(255) binary NOT NULL default '',
+  oi_timestamp char(14) binary NOT NULL default '',
+
+  INDEX oi_name (oi_name(10))
+
+) TYPE=InnoDB;
+END;
+               $fields = array(
+                       'oi_name'         => MW_UPGRADE_ENCODE,
+                       'oi_archive_name' => MW_UPGRADE_ENCODE,
+                       'oi_size'         => MW_UPGRADE_COPY,
+                       'oi_width'        => MW_UPGRADE_CALLBACK,
+                       'oi_height'       => MW_UPGRADE_CALLBACK,
+                       'oi_bits'         => MW_UPGRADE_CALLBACK,
+                       'oi_description'  => MW_UPGRADE_ENCODE,
+                       'oi_user'         => MW_UPGRADE_COPY,
+                       'oi_user_text'    => MW_UPGRADE_ENCODE,
+                       'oi_timestamp'    => MW_UPGRADE_COPY );
+               $this->copyTable( 'oldimage', $tabledef, $fields,
+                       array( &$this, 'oldimageCallback' ) );
+       }
+       
+       function oldimageCallback( $row, $copy ) {
+               global $options;
+               if( !isset( $options['noimage'] ) ) {
+                       // Fill in the new image info fields
+                       $info = $this->imageInfo( $row->oi_archive_name, 'wfImageArchiveDir', $row->oi_name );
+                       $copy['oi_width' ] = $info['width' ];
+                       $copy['oi_height'] = $info['height'];
+                       $copy['oi_bits'  ] = $info['bits'  ];
+               }
+               
+               // If doing UTF8 conversion the file must be renamed
+               $this->renameFile( $row->oi_archive_name, 'wfImageArchiveDir', $row->oi_name );
+               
+               return $copy;
+       }
+       
+
+       function upgradeWatchlist() {
+               $fname = 'FiveUpgrade::upgradeWatchlist';
+               $chunksize = 100;
+               
+               extract( $this->dbw->tableNames( 'watchlist', 'watchlist_temp' ) );
+               
+               $this->log( 'Migrating watchlist table to watchlist_temp...' );
+               $this->dbw->query(
+"CREATE TABLE $watchlist_temp (
+  -- Key to user_id
+  wl_user int(5) unsigned NOT NULL,
+  
+  -- Key to page_namespace/page_title
+  -- Note that users may watch patches which do not exist yet,
+  -- or existed in the past but have been deleted.
+  wl_namespace int NOT NULL default '0',
+  wl_title varchar(255) binary NOT NULL default '',
+  
+  -- Timestamp when user was last sent a notification e-mail;
+  -- cleared when the user visits the page.
+  -- FIXME: add proper null support etc
+  wl_notificationtimestamp varchar(14) binary NOT NULL default '0',
+  
+  UNIQUE KEY (wl_user, wl_namespace, wl_title),
+  KEY namespace_title (wl_namespace,wl_title)
+
+) TYPE=InnoDB;", $fname );
+
+               // Fix encoding for Latin-1 upgrades, add some fields,
+               // and double article to article+talk pairs
+               $numwatched = $this->dbw->selectField( 'watchlist', 'count(*)', '', $fname );
+               
+               $this->setChunkScale( $chunksize, $numwatched * 2, 'watchlist_temp', $fname );
+               $result = $this->dbr->select( 'watchlist',
+                       array(
+                               'wl_user',
+                               'wl_namespace',
+                               'wl_title' ),
+                       '',
+                       $fname );
+               
+               $add = array();
+               while( $row = $this->dbr->fetchObject( $result ) ) {
+                       $now = $this->dbw->timestamp();
+                       $add[] = array(
+                               'wl_user'      =>                        $row->wl_user,
+                               'wl_namespace' => Namespace::getSubject( $row->wl_namespace ),
+                               'wl_title'     =>           $this->conv( $row->wl_title ),
+                               'wl_notificationtimestamp' =>            '0' );
+                       $this->addChunk( $add );
+                       
+                       $add[] = array(
+                               'wl_user'      =>                        $row->wl_user,
+                               'wl_namespace' =>    Namespace::getTalk( $row->wl_namespace ),
+                               'wl_title'     =>           $this->conv( $row->wl_title ),
+                               'wl_notificationtimestamp' =>            '0' );
+                       $this->addChunk( $add );
+               }
+               $this->lastChunk( $add );
+               $this->dbr->freeResult( $result );
+               
+               $this->log( 'Done converting watchlist.' );
+               $this->cleanupSwaps[] = 'watchlist';
+       }
+
+       function upgradeLogging() {
+               $tabledef = <<<END
+CREATE TABLE $1 (
+  -- Symbolic keys for the general log type and the action type
+  -- within the log. The output format will be controlled by the
+  -- action field, but only the type controls categorization.
+  log_type char(10) NOT NULL default '',
+  log_action char(10) NOT NULL default '',
+  
+  -- Timestamp. Duh.
+  log_timestamp char(14) NOT NULL default '19700101000000',
+  
+  -- The user who performed this action; key to user_id
+  log_user int unsigned NOT NULL default 0,
+  
+  -- Key to the page affected. Where a user is the target,
+  -- this will point to the user page.
+  log_namespace int NOT NULL default 0,
+  log_title varchar(255) binary NOT NULL default '',
+  
+  -- Freeform text. Interpreted as edit history comments.
+  log_comment varchar(255) NOT NULL default '',
+  
+  -- LF separated list of miscellaneous parameters
+  log_params blob NOT NULL default '',
+
+  KEY type_time (log_type, log_timestamp),
+  KEY user_time (log_user, log_timestamp),
+  KEY page_time (log_namespace, log_title, log_timestamp)
+
+) TYPE=InnoDB
+END;
+               $fields = array(
+                       'log_type'      => MW_UPGRADE_COPY,
+                       'log_action'    => MW_UPGRADE_COPY,
+                       'log_timestamp' => MW_UPGRADE_COPY,
+                       'log_user'      => MW_UPGRADE_COPY,
+                       'log_namespace' => MW_UPGRADE_COPY,
+                       'log_title'     => MW_UPGRADE_ENCODE,
+                       'log_comment'   => MW_UPGRADE_ENCODE,
+                       'log_params'    => MW_UPGRADE_ENCODE );
+               $this->copyTable( 'logging', $tabledef, $fields );
+       }
+
+       function upgradeArchive() {
+               $tabledef = <<<END
+CREATE TABLE $1 (
+  ar_namespace int NOT NULL default '0',
+  ar_title varchar(255) binary NOT NULL default '',
+  ar_text mediumblob NOT NULL default '',
+  
+  ar_comment tinyblob NOT NULL default '',
+  ar_user int(5) unsigned NOT NULL default '0',
+  ar_user_text varchar(255) binary NOT NULL,
+  ar_timestamp char(14) binary NOT NULL default '',
+  ar_minor_edit tinyint(1) NOT NULL default '0',
+  
+  ar_flags tinyblob NOT NULL default '',
+
+  ar_rev_id int(8) unsigned,
+  ar_text_id int(8) unsigned,
+  
+  KEY name_title_timestamp (ar_namespace,ar_title,ar_timestamp)
+
+) TYPE=InnoDB
+END;
+               $fields = array(
+                       'ar_namespace'  => MW_UPGRADE_COPY,
+                       'ar_title'      => MW_UPGRADE_ENCODE,
+                       'ar_text'       => MW_UPGRADE_COPY,
+                       'ar_comment'    => MW_UPGRADE_ENCODE,
+                       'ar_user'       => MW_UPGRADE_COPY,
+                       'ar_user_text'  => MW_UPGRADE_ENCODE,
+                       'ar_timestamp'  => MW_UPGRADE_COPY,
+                       'ar_minor_edit' => MW_UPGRADE_COPY,
+                       'ar_flags'      => MW_UPGRADE_COPY,
+                       'ar_rev_id'     => MW_UPGRADE_NULL,
+                       'ar_text_id'    => MW_UPGRADE_NULL );
+               $this->copyTable( 'archive', $tabledef, $fields );
+       }
+       
+       function upgradeImagelinks() {
+               global $wgUseLatin1;
+               if( $wgUseLatin1 ) {
+                       $tabledef = <<<END
+CREATE TABLE $1 (
+  -- Key to page_id of the page containing the image / media link.
+  il_from int(8) unsigned NOT NULL default '0',
+  
+  -- Filename of target image.
+  -- This is also the page_title of the file's description page;
+  -- all such pages are in namespace 6 (NS_IMAGE).
+  il_to varchar(255) binary NOT NULL default '',
+  
+  UNIQUE KEY il_from(il_from,il_to),
+  KEY (il_to)
+
+) TYPE=InnoDB
+END;
+                       $fields = array(
+                               'il_from' => MW_UPGRADE_COPY,
+                               'il_to'   => MW_UPGRADE_ENCODE );
+                       $this->copyTable( 'imagelinks', $tabledef, $fields );
+               }
+       }
+
+       function upgradeCategorylinks() {
+               global $wgUseLatin1;
+               if( $wgUseLatin1 ) {
+                       $tabledef = <<<END
+CREATE TABLE $1 (
+  cl_from int(8) unsigned NOT NULL default '0',
+  cl_to varchar(255) binary NOT NULL default '',
+  cl_sortkey varchar(86) binary NOT NULL default '',
+  cl_timestamp timestamp NOT NULL,
+  
+  UNIQUE KEY cl_from(cl_from,cl_to),
+  KEY cl_sortkey(cl_to,cl_sortkey),
+  KEY cl_timestamp(cl_to,cl_timestamp)
+) TYPE=InnoDB
+END;
+                       $fields = array(
+                               'cl_from'      => MW_UPGRADE_COPY,
+                               'cl_to'        => MW_UPGRADE_ENCODE,
+                               'cl_sortkey'   => MW_UPGRADE_ENCODE,
+                               'cl_timestamp' => MW_UPGRADE_COPY );
+                       $this->copyTable( 'categorylinks', $tabledef, $fields );
+               }
+       }
+       
+       function upgradeIpblocks() {
+               global $wgUseLatin1;
+               if( $wgUseLatin1 ) {
+                       $tabledef = <<<END
+CREATE TABLE $1 (
+  ipb_id int(8) NOT NULL auto_increment,
+  ipb_address varchar(40) binary NOT NULL default '',
+  ipb_user int(8) unsigned NOT NULL default '0',
+  ipb_by int(8) unsigned NOT NULL default '0',
+  ipb_reason tinyblob NOT NULL default '',
+  ipb_timestamp char(14) binary NOT NULL default '',
+  ipb_auto tinyint(1) NOT NULL default '0',
+  ipb_expiry char(14) binary NOT NULL default '',
+
+  PRIMARY KEY ipb_id (ipb_id),
+  INDEX ipb_address (ipb_address),
+  INDEX ipb_user (ipb_user)
+
+) TYPE=InnoDB
+END;
+                       $fields = array(
+                               'ipb_id'        => MW_UPGRADE_COPY,
+                               'ipb_address'   => MW_UPGRADE_COPY,
+                               'ipb_user'      => MW_UPGRADE_COPY,
+                               'ipb_by'        => MW_UPGRADE_COPY,
+                               'ipb_reason'    => MW_UPGRADE_ENCODE,
+                               'ipb_timestamp' => MW_UPGRADE_COPY,
+                               'ipb_auto'      => MW_UPGRADE_COPY,
+                               'ipb_expiry'    => MW_UPGRADE_COPY );
+                       $this->copyTable( 'ipblocks', $tabledef, $fields );
+               }
+       }
+       
+       function upgradeRecentchanges() {
+               // There's a format change in the namespace field
+               $tabledef = <<<END
+CREATE TABLE $1 (
+  rc_id int(8) NOT NULL auto_increment,
+  rc_timestamp varchar(14) binary NOT NULL default '',
+  rc_cur_time varchar(14) binary NOT NULL default '',
+  
+  rc_user int(10) unsigned NOT NULL default '0',
+  rc_user_text varchar(255) binary NOT NULL default '',
+  
+  rc_namespace int NOT NULL default '0',
+  rc_title varchar(255) binary NOT NULL default '',
+  
+  rc_comment varchar(255) binary NOT NULL default '',
+  rc_minor tinyint(3) unsigned NOT NULL default '0',
+  
+  rc_bot tinyint(3) unsigned NOT NULL default '0',
+  rc_new tinyint(3) unsigned NOT NULL default '0',
+  
+  rc_cur_id int(10) unsigned NOT NULL default '0',
+  rc_this_oldid int(10) unsigned NOT NULL default '0',
+  rc_last_oldid int(10) unsigned NOT NULL default '0',
+  
+  rc_type tinyint(3) unsigned NOT NULL default '0',
+  rc_moved_to_ns tinyint(3) unsigned NOT NULL default '0',
+  rc_moved_to_title varchar(255) binary NOT NULL default '',
+  
+  rc_patrolled tinyint(3) unsigned NOT NULL default '0',
+  
+  rc_ip char(15) NOT NULL default '',
+  
+  PRIMARY KEY rc_id (rc_id),
+  INDEX rc_timestamp (rc_timestamp),
+  INDEX rc_namespace_title (rc_namespace, rc_title),
+  INDEX rc_cur_id (rc_cur_id),
+  INDEX new_name_timestamp(rc_new,rc_namespace,rc_timestamp),
+  INDEX rc_ip (rc_ip)
+
+) TYPE=InnoDB
+END;
+               $fields = array(
+                       'rc_id'             => MW_UPGRADE_COPY,
+                       'rc_timestamp'      => MW_UPGRADE_COPY,
+                       'rc_cur_time'       => MW_UPGRADE_COPY,
+                       'rc_user'           => MW_UPGRADE_COPY,
+                       'rc_user_text'      => MW_UPGRADE_ENCODE,
+                       'rc_namespace'      => MW_UPGRADE_COPY,
+                       'rc_title'          => MW_UPGRADE_ENCODE,
+                       'rc_comment'        => MW_UPGRADE_ENCODE,
+                       'rc_minor'          => MW_UPGRADE_COPY,
+                       'rc_bot'            => MW_UPGRADE_COPY,
+                       'rc_new'            => MW_UPGRADE_COPY,
+                       'rc_cur_id'         => MW_UPGRADE_COPY,
+                       'rc_this_oldid'     => MW_UPGRADE_COPY,
+                       'rc_last_oldid'     => MW_UPGRADE_COPY,
+                       'rc_type'           => MW_UPGRADE_COPY,
+                       'rc_moved_to_ns'    => MW_UPGRADE_COPY,
+                       'rc_moved_to_title' => MW_UPGRADE_ENCODE,
+                       'rc_patrolled'      => MW_UPGRADE_COPY,
+                       'rc_ip'             => MW_UPGRADE_COPY );
+               $this->copyTable( 'recentchanges', $tabledef, $fields );
+       }
+       
+       function upgradeQuerycache() {
+               // There's a format change in the namespace field
+               $tabledef = <<<END
+CREATE TABLE $1 (
+  -- A key name, generally the base name of of the special page.
+  qc_type char(32) NOT NULL,
+  
+  -- Some sort of stored value. Sizes, counts...
+  qc_value int(5) unsigned NOT NULL default '0',
+  
+  -- Target namespace+title
+  qc_namespace int NOT NULL default '0',
+  qc_title char(255) binary NOT NULL default '',
+  
+  KEY (qc_type,qc_value)
+
+) TYPE=InnoDB
+END;
+               $fields = array(
+                       'qc_type'      => MW_UPGRADE_COPY,
+                       'qc_value'     => MW_UPGRADE_COPY,
+                       'qc_namespace' => MW_UPGRADE_COPY,
+                       'qc_title'     => MW_UPGRADE_ENCODE );
+               $this->copyTable( 'querycache', $tabledef, $fields );
+       }
+       
+       /**
+        * Rename all our temporary tables into final place.
+        * We've left things in place so a read-only wiki can continue running
+        * on the old code during all this.
+        */
+       function upgradeCleanup() {
+               $this->renameTable( 'old', 'text' );
+               
+               foreach( $this->cleanupSwaps as $table ) {
+                       $this->swap( $table );
+               }
+       }
+       
+       function renameTable( $from, $to ) {
+               $this->log( "Renaming $from to $to..." );
+
+               $fromtable = $this->dbw->tableName( $from );
+               $totable   = $this->dbw->tableName( $to );
+               $this->dbw->query( "ALTER TABLE $fromtable RENAME TO $totable" );
+       }
+       
+       function swap( $base ) {
+               $this->renameTable( $base, "{$base}_old" );
+               $this->renameTable( "{$base}_temp", $base );
+       }
+       
+}
+
+?>
\ No newline at end of file
diff --git a/maintenance/InitialiseMessages.inc b/maintenance/InitialiseMessages.inc
new file mode 100644 (file)
index 0000000..811637a
--- /dev/null
@@ -0,0 +1,228 @@
+<?php
+/**
+ * Script to initialise the MediaWiki namespace
+ *
+ * This script is included from update.php and install.php. Do not run it 
+ * by itself.
+ *
+ * @deprecated
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+/** */
+function initialiseMessages( $overwrite = false, $messageArray = false ) {
+       global $wgContLang, $wgContLanguageCode;
+       global $wgContLangClass, $wgAllMessagesEn;
+       global $wgDisableLangConversion;
+       global $wgForceUIMsgAsContentMsg;
+       global $wgLanguageNames;
+       global $IP;
+
+       # overwrite language conversion option so that all variants 
+       # of the messages are initialised
+       $wgDisableLangConversion = false;
+
+       if ( $messageArray ) {
+               $sortedArray = $messageArray;
+       } else {
+               $sortedArray = $wgAllMessagesEn;
+       }
+       
+       ksort( $sortedArray );
+       $messages=array();
+
+       $variants = $wgContLang->getVariants();
+       if(!in_array($wgContLanguageCode, $variants))
+               $variants[]=$wgContLanguageCode;
+
+       foreach ($variants as $v) {
+               $langclass = 'Language'. str_replace( '-', '_', ucfirst( $v ) );
+               if( !class_exists($langclass) ) {
+                       die ("class $langclass not defined. perhaps you need to include the file $langclass.php in $wgContLangClass.php?");
+               }
+               $lang = new $langclass;
+
+               if($v==$wgContLanguageCode)
+                       $suffix='';
+               else
+                       $suffix="/$v";
+               foreach ($sortedArray as $key => $msg) {
+                       $messages[$key.$suffix] = $lang->getMessage($key);
+               }
+       }
+
+       require_once('languages/Names.php');
+
+    /*
+         initialize all messages in $wgForceUIMsgAsContentMsg for all
+         languages in Names.php
+    */
+       if( is_array( $wgForceUIMsgAsContentMsg ) ) {
+               foreach( $wgForceUIMsgAsContentMsg as $uikey ) {
+                       foreach( $wgLanguageNames as $code => $name) {
+                               if( $code == $wgContLanguageCode )
+                                       continue;
+                               $msg = $wgContLang->getMessage( $uikey );
+                               if( $msg )
+                                       $messages[$uikey. '/' . $code] = $msg;
+                       }
+               }
+       }
+       initialiseMessagesReal( $overwrite, $messages );
+}
+
+/** */
+function initialiseMessagesReal( $overwrite = false, $messageArray = false ) {
+       global $wgContLang, $wgScript, $wgServer, $wgAllMessagesEn;
+       global $wgOut, $wgArticle, $wgUser;
+       global $wgMessageCache, $wgMemc, $wgDBname, $wgUseMemCached;
+
+       # Initialise $wgOut and $wgUser for a command line script
+       $wgOut->disable();
+
+       $wgUser = new User;
+       $wgUser->setLoaded( true ); # Don't load from DB
+       $wgUser->setName( 'MediaWiki default' );
+       
+       # Don't try to draw messages from the database we're initialising
+       $wgMessageCache->disable();
+       $wgMessageCache->disableTransform();
+
+       $fname = 'initialiseMessages';
+       $ns = NS_MEDIAWIKI;
+       # cur_user_text responsible for the modifications
+       # Don't change it unless you're prepared to update the DBs accordingly, otherwise the 
+       # default messages won't be overwritte
+       $username = 'MediaWiki default';
+
+       
+       print "Initialising \"MediaWiki\" namespace...\n";
+
+       
+       $dbr =& wfGetDB( DB_SLAVE );
+       $dbw =& wfGetDB( DB_MASTER );
+       $page = $dbr->tableName( 'page' );
+       $revision = $dbr->tableName( 'revision' );
+
+       $timestamp = wfTimestampNow();
+
+       #$sql = "SELECT cur_title,cur_is_new,cur_user_text FROM $cur WHERE cur_namespace=$ns AND cur_title IN(";
+       $sql = "SELECT page_title,page_is_new,rev_user_text FROM $page, $revision WHERE
+               page_namespace=$ns AND rev_page=page_id AND page_title IN(";
+
+       # Get keys from $wgAllMessagesEn, which is more complete than the local language
+       $first = true;
+       if ( $messageArray ) {
+               $sortedArray = $messageArray;
+       } else {
+               $sortedArray = $wgAllMessagesEn;
+       }
+       
+       ksort( $sortedArray );
+
+       # SELECT all existing messages
+       # Can't afford to be locking all rows for update, this script can take quite a long time to complete
+       foreach ( $sortedArray as $key => $enMsg ) {
+               if ( $key == '' ) {
+                       continue; // Skip odd members
+               }
+               if ( $first ) {
+                       $first = false;
+               } else {
+                       $sql .= ',';
+               }
+               $titleObj = Title::newFromText( $wgContLang->ucfirst( $key ) );
+               $enctitle = $dbr->strencode($titleObj->getDBkey());
+               $sql .= "'$enctitle'";
+       }
+       $sql .= ')';
+       $res = $dbr->query( $sql );
+       $row = $dbr->fetchObject( $res );
+
+       # Read the results into an array
+       # Decide whether or not each one needs to be overwritten
+       $existingTitles = array();
+       while ( $row ) {
+               if ( $row->rev_user_text != $username  && $row->rev_user_text != 'Template namespace initialisation script' ) {
+                       $existingTitles[$row->page_title] = 'keep';
+               } else {
+                       $existingTitles[$row->page_title] = 'chuck';
+               }
+
+               $row = $dbr->fetchObject( $res );
+       }
+
+       # Insert queries are done in one multi-row insert
+       # Here's the start of it:
+       $arr = array();
+       $talk = $wgContLang->getNsText( NS_TALK );
+       $mwtalk = $wgContLang->getNsText( NS_MEDIAWIKI_TALK );
+       
+       # Merge these into a single transaction for speed
+       $dbw->begin();
+
+       # Process each message
+       foreach ( $sortedArray as $key => $enMsg ) {
+               if ( $key == '' ) {
+                       continue; // Skip odd members
+               }
+               # Get message text
+               if ( $messageArray ) {
+                       $message = $enMsg;
+               } else {
+                       $message = wfMsgNoDBForContent( $key );
+               }
+               $titleObj = Title::newFromText( $wgContLang->ucfirst( $key ), NS_MEDIAWIKI );
+               $title = $titleObj->getDBkey();
+
+               # Update messages which already exist
+               if ( array_key_exists( $title, $existingTitles ) ) {
+                       if ( $existingTitles[$title] == 'chuck' || $overwrite) {
+                               # Don't bother writing a new revision if we're the same
+                               # as the current text!
+                               $revision = Revision::newFromTitle( $titleObj );
+                               if( is_null( $revision ) || $revision->getText() != $message ) {
+                                       $article = new Article( $titleObj );
+                                       $article->quickEdit( $message );
+                               }
+                       }
+               } else {
+                       $article = new Article( $titleObj );
+                       $newid = $article->insertOn( $dbw, 'sysop' );
+                       # FIXME: set restrictions
+                       $revision = new Revision( array(
+                               'page'      => $newid,
+                               'text'      => $message,
+                               'user'      => 0,
+                               'user_text' => $username,
+                               'comment'   => '',
+                               ) );
+                       $revid = $revision->insertOn( $dbw );
+                       $article->updateRevisionOn( $dbw, $revision );
+               }
+       }
+       $dbw->commit();
+
+       # Clear the relevant memcached key
+       print 'Clearing message cache...';
+       $wgMessageCache->clear();
+       print "Done.\n";
+}
+
+/** */
+function loadLanguageFile( $filename ) {
+       $contents = file_get_contents( $filename );
+       # Remove header line
+       $p = strpos( $contents, "\n" ) + 1;
+       $contents = substr( $contents, $p );
+       # Unserialize
+       return unserialize( $contents );
+}
+
+/** */
+function doUpdates() {
+       global $wgDeferredUpdateList;
+       foreach ( $wgDeferredUpdateList as $up ) { $up->doUpdate(); }
+}
+?>
diff --git a/maintenance/Makefile b/maintenance/Makefile
new file mode 100644 (file)
index 0000000..8cdb03f
--- /dev/null
@@ -0,0 +1,13 @@
+.PHONY: help doc test
+help:
+       # Run 'make test' to run the parser tests.
+       # Run 'make doc' to run the phpdoc generation.
+
+test:
+       php parserTests.php
+
+test-light:
+       php parserTests.php --color=light
+
+doc:
+       php mwdocgen.php --all
diff --git a/maintenance/README b/maintenance/README
new file mode 100644 (file)
index 0000000..363d298
--- /dev/null
@@ -0,0 +1,10 @@
+The .sql scripts in this directory are not meant to be run
+standalone, although they can be in some cases if you know
+what you're doing.  Most of the time you'll want to run the
+.php scripts from the command line.  You must run them from
+this directory, and the LocalSettings.php file in the
+directory above must point to the installation.
+
+The scripts in archives are for updating databases from
+older versions of the software.
+
diff --git a/maintenance/alltrans.php b/maintenance/alltrans.php
new file mode 100644 (file)
index 0000000..2fdc449
--- /dev/null
@@ -0,0 +1,11 @@
+<?php
+/**
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+require_once('commandLine.inc');
+
+foreach(array_keys($wgAllMessagesEn) as $key)
+       echo "$key\n";
+?>
diff --git a/maintenance/apache-ampersand.diff b/maintenance/apache-ampersand.diff
new file mode 100644 (file)
index 0000000..f281ce1
--- /dev/null
@@ -0,0 +1,53 @@
+--- orig/apache_1.3.26/src/modules/standard/mod_rewrite.h      Wed Mar 13 13:05:34 2002
++++ apache_1.3.26/src/modules/standard/mod_rewrite.h   Tue Oct 15 14:07:21 2002
+@@ -447,6 +447,7 @@
+ static char *rewrite_mapfunc_toupper(request_rec *r, char *key);
+ static char *rewrite_mapfunc_tolower(request_rec *r, char *key);
+ static char *rewrite_mapfunc_escape(request_rec *r, char *key);
++static char *rewrite_mapfunc_ampescape(request_rec *r, char *key);
+ static char *rewrite_mapfunc_unescape(request_rec *r, char *key);
+ static char *select_random_value_part(request_rec *r, char *value);
+ static void  rewrite_rand_init(void);
+--- orig/apache_1.3.26/src/modules/standard/mod_rewrite.c      Wed May 29 10:39:23 2002
++++ apache_1.3.26/src/modules/standard/mod_rewrite.c   Tue Oct 15 14:07:49 2002
+@@ -502,6 +502,9 @@
+         else if (strcmp(a2+4, "unescape") == 0) {
+             new->func = rewrite_mapfunc_unescape;
+         }
++        else if (strcmp(a2+4, "ampescape") == 0) {
++            new->func = rewrite_mapfunc_ampescape;
++        }
+         else if (sconf->state == ENGINE_ENABLED) {
+             return ap_pstrcat(cmd->pool, "RewriteMap: internal map not found:",
+                               a2+4, NULL);
+@@ -2982,6 +2985,30 @@
+     value = ap_escape_uri(r->pool, key);
+     return value;
++}
++
++static char *rewrite_mapfunc_ampescape(request_rec *r, char *key)
++{
++    /* We only need to escape the ampersand */
++    char *copy = ap_palloc(r->pool, 3 * strlen(key) + 3);
++    const unsigned char *s = (const unsigned char *)key;
++    unsigned char *d = (unsigned char *)copy;
++    unsigned c;
++
++    while ((c = *s)) {
++      if (c == '&') {
++          *d++ = '%';
++          *d++ = '2';
++          *d++ = '6';
++      }
++      else {
++          *d++ = c;
++      }
++      ++s;
++    }
++    *d = '\0';
++    
++    return copy;
+ }
+ static char *rewrite_mapfunc_unescape(request_rec *r, char *key)
diff --git a/maintenance/archives/.htaccess b/maintenance/archives/.htaccess
new file mode 100644 (file)
index 0000000..3a42882
--- /dev/null
@@ -0,0 +1 @@
+Deny from all
diff --git a/maintenance/archives/patch-archive-rev_id.sql b/maintenance/archives/patch-archive-rev_id.sql
new file mode 100644 (file)
index 0000000..375001b
--- /dev/null
@@ -0,0 +1,6 @@
+-- New field in archive table to preserve revision IDs across undeletion.
+-- Added 2005-03-10
+
+ALTER TABLE /*$wgDBprefix*/archive
+  ADD
+    ar_rev_id int(8) unsigned;
diff --git a/maintenance/archives/patch-archive-text_id.sql b/maintenance/archives/patch-archive-text_id.sql
new file mode 100644 (file)
index 0000000..f59715f
--- /dev/null
@@ -0,0 +1,14 @@
+-- New field in archive table to preserve text source IDs across undeletion.
+--
+-- Older entries containing NULL in this field will contain text in the
+-- ar_text and ar_flags fields, and will cause the (re)creation of a new
+-- text record upon undeletion.
+--
+-- Newer ones will reference a text.old_id with this field, and the existing
+-- entries will be used as-is; only a revision record need be created.
+--
+-- Added 2005-05-01
+
+ALTER TABLE /*$wgDBprefix*/archive
+  ADD
+    ar_text_id int(8) unsigned;
diff --git a/maintenance/archives/patch-bot.sql b/maintenance/archives/patch-bot.sql
new file mode 100644 (file)
index 0000000..ce61884
--- /dev/null
@@ -0,0 +1,11 @@
+-- Add field to recentchanges for easy filtering of bot entries
+-- edits by a user with 'bot' in user.user_rights should be
+-- marked 1 in rc_bot.
+
+-- Change made 2002-12-15 by Brion VIBBER <brion@pobox.com>
+-- this affects code in Article.php, User.php SpecialRecentchanges.php
+-- column also added to buildTables.inc
+
+ALTER TABLE /*$wgDBprefix*/recentchanges
+  ADD COLUMN rc_bot tinyint(3) unsigned NOT NULL default '0'
+  AFTER rc_minor;
diff --git a/maintenance/archives/patch-cache.sql b/maintenance/archives/patch-cache.sql
new file mode 100644 (file)
index 0000000..5651c3c
--- /dev/null
@@ -0,0 +1,41 @@
+-- patch-cache.sql
+-- 2003-03-22  <brion@pobox.com>
+--
+-- Add 'last touched' fields to cur and user tables.
+-- These are useful for maintaining cache consistency.
+-- (Updates to OutputPage.php and elsewhere.)
+--
+-- cur_touched should be set to the current time whenever:
+--  * the page is updated
+--  * a linked page is created
+--  * a linked page is destroyed
+--
+-- The cur_touched time will then be compared against the
+-- timestamps of cached pages to ensure consistency; if
+-- cur_touched is later, the page must be regenerated.
+
+ALTER TABLE /*$wgDBprefix*/cur
+  ADD COLUMN cur_touched char(14) binary NOT NULL default '';
+
+-- Existing pages should be initialized to the current
+-- time so they don't needlessly rerender until they are
+-- changed for the first time:
+
+UPDATE /*$wgDBprefix*/cur
+  SET cur_touched=NOW()+0;
+
+-- user_touched should be set to the current time whenever:
+--  * the user logs in
+--  * the user saves preferences (if no longer default...?)
+--  * the user's newtalk status is altered
+--
+-- The user_touched time should also be checked against the
+-- timestamp reported by a browser requesting revalidation.
+-- If user_touched is later than the reported last modified
+-- time, the page should be rerendered with new options and
+-- sent again.
+
+ALTER TABLE /*$wgDBprefix*/user
+  ADD COLUMN user_touched char(14) binary NOT NULL default '';
+UPDATE /*$wgDBprefix*/user
+  SET user_touched=NOW()+0;
diff --git a/maintenance/archives/patch-categorylinks.sql b/maintenance/archives/patch-categorylinks.sql
new file mode 100644 (file)
index 0000000..53c82fc
--- /dev/null
@@ -0,0 +1,39 @@
+--
+-- Track category inclusions *used inline*
+-- This tracks a single level of category membership
+-- (folksonomic tagging, really).
+--
+CREATE TABLE /*$wgDBprefix*/categorylinks (
+  -- Key to page_id of the page defined as a category member.
+  cl_from int(8) unsigned NOT NULL default '0',
+  
+  -- Name of the category.
+  -- This is also the page_title of the category's description page;
+  -- all such pages are in namespace 14 (NS_CATEGORY).
+  cl_to varchar(255) binary NOT NULL default '',
+
+  -- The title of the linking page, or an optional override
+  -- to determine sort order. Sorting is by binary order, which
+  -- isn't always ideal, but collations seem to be an exciting
+  -- and dangerous new world in MySQL...
+  --
+  -- For MySQL 4.1+ with charset set to utf8, the sort key *index*
+  -- needs cut to be smaller than 1024 bytes (at 3 bytes per char).
+  -- To sort properly on the shorter key, this field needs to be
+  -- the same shortness.
+  cl_sortkey varchar(86) binary NOT NULL default '',
+  
+  -- This isn't really used at present. Provided for an optional
+  -- sorting method by approximate addition time.
+  cl_timestamp timestamp NOT NULL,
+  
+  UNIQUE KEY cl_from(cl_from,cl_to),
+  
+  -- This key is trouble. It's incomplete, AND it's too big
+  -- when collation is set to UTF-8. Bleeeacch!
+  KEY cl_sortkey(cl_to,cl_sortkey),
+  
+  -- Not really used?
+  KEY cl_timestamp(cl_to,cl_timestamp)
+
+) TYPE=InnoDB;
diff --git a/maintenance/archives/patch-drop-user_newtalk.sql b/maintenance/archives/patch-drop-user_newtalk.sql
new file mode 100644 (file)
index 0000000..6ec84fb
--- /dev/null
@@ -0,0 +1,3 @@
+-- Patch for email authentication T.Gries/M.Arndt 27.11.2004
+-- Table user_newtalk is dropped, as the table watchlist is now also used for storing user_talk-page notifications
+DROP TABLE /*$wgDBprefix*/user_newtalk;
diff --git a/maintenance/archives/patch-drop_img_type.sql b/maintenance/archives/patch-drop_img_type.sql
new file mode 100644 (file)
index 0000000..e373761
--- /dev/null
@@ -0,0 +1,3 @@
+-- img_type is no longer used, delete it
+
+ALTER TABLE /*$wgDBprefix*/image DROP COLUMN img_type;
diff --git a/maintenance/archives/patch-email-authentication.sql b/maintenance/archives/patch-email-authentication.sql
new file mode 100644 (file)
index 0000000..b35b10f
--- /dev/null
@@ -0,0 +1,3 @@
+-- Added early in 1.5 alpha development, removed 2005-04-25
+
+ALTER TABLE /*$wgDBprefix*/user DROP COLUMN user_emailauthenticationtimestamp;
diff --git a/maintenance/archives/patch-email-notification.sql b/maintenance/archives/patch-email-notification.sql
new file mode 100644 (file)
index 0000000..02a32a0
--- /dev/null
@@ -0,0 +1,11 @@
+-- Patch for email notification on page changes T.Gries/M.Arndt 11.09.2004
+
+-- A new column 'wl_notificationtimestamp' is added to the table 'watchlist'.
+-- When a page watched by a user X is changed by someone else, an email is sent to the watching user X
+-- if and only if the field 'wl_notificationtimestamp' is '0'. The time/date of sending the mail is then stored in that field.
+-- Further pages changes do not trigger new notification mails as long as user X has not re-visited that page.
+-- The field is reset to '0' when user X re-visits the page or when he or she resets all notification timestamps
+-- ("notification flags") at once by clicking the new button on his/her watchlist page.
+-- T. Gries/M. Arndt  11.09.2004 - December 2004
+
+ALTER TABLE /*$wgDBprefix*/watchlist ADD (wl_notificationtimestamp varchar(14) binary NOT NULL default '0');
diff --git a/maintenance/archives/patch-hitcounter.sql b/maintenance/archives/patch-hitcounter.sql
new file mode 100644 (file)
index 0000000..260f717
--- /dev/null
@@ -0,0 +1,9 @@
+--
+-- hitcounter table is used to buffer page hits before they are periodically 
+-- counted and added to the cur_counter column in the cur table.
+-- December 2003
+--
+
+CREATE TABLE /*$wgDBprefix*/hitcounter (
+  hc_id INTEGER UNSIGNED NOT NULL
+) TYPE=HEAP MAX_ROWS=25000;
diff --git a/maintenance/archives/patch-image_name_primary.sql b/maintenance/archives/patch-image_name_primary.sql
new file mode 100644 (file)
index 0000000..5bd8826
--- /dev/null
@@ -0,0 +1,6 @@
+-- Make the image name index unique
+
+ALTER TABLE /*$wgDBprefix*/image DROP INDEX img_name;
+
+ALTER TABLE /*$wgDBprefix*/image
+  ADD PRIMARY KEY img_name (img_name);
diff --git a/maintenance/archives/patch-image_name_unique.sql b/maintenance/archives/patch-image_name_unique.sql
new file mode 100644 (file)
index 0000000..5cf02d4
--- /dev/null
@@ -0,0 +1,6 @@
+-- Make the image name index unique
+
+ALTER TABLE /*$wgDBprefix*/image DROP INDEX img_name;
+
+ALTER TABLE /*$wgDBprefix*/image
+  ADD UNIQUE INDEX img_name (img_name);
diff --git a/maintenance/archives/patch-img_exif.sql b/maintenance/archives/patch-img_exif.sql
new file mode 100644 (file)
index 0000000..2fd78f7
--- /dev/null
@@ -0,0 +1,3 @@
+-- Extra image exif metadata, added for 1.5 but quickly removed.
+
+ALTER TABLE /*$wgDBprefix*/image DROP img_exif;
diff --git a/maintenance/archives/patch-img_media_type.sql b/maintenance/archives/patch-img_media_type.sql
new file mode 100644 (file)
index 0000000..2356fc6
--- /dev/null
@@ -0,0 +1,17 @@
+-- media type columns, added for 1.5
+-- this alters the scheme for 1.5, img_type is no longer used.
+
+ALTER TABLE /*$wgDBprefix*/image ADD (
+  -- Media type as defined by the MEDIATYPE_xxx constants
+  img_media_type ENUM("UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE") default NULL,
+  
+  -- major part of a MIME media type as defined by IANA
+  -- see http://www.iana.org/assignments/media-types/
+  img_major_mime ENUM("unknown", "application", "audio", "image", "text", "video", "message", "model", "multipart") NOT NULL default "unknown",
+  
+  -- minor part of a MIME media type as defined by IANA
+  -- the minor parts are not required to adher to any standard
+  -- but should be consistent throughout the database
+  -- see http://www.iana.org/assignments/media-types/
+  img_minor_mime varchar(32) NOT NULL default "unknown"
+);
diff --git a/maintenance/archives/patch-img_metadata.sql b/maintenance/archives/patch-img_metadata.sql
new file mode 100644 (file)
index 0000000..407e432
--- /dev/null
@@ -0,0 +1,6 @@
+-- Moving img_exif to img_metadata, so the name won't be so confusing when we
+-- Use it for Ogg metadata or something like that.
+
+ALTER TABLE /*$wgDBprefix*/image ADD (
+  img_metadata mediumblob NOT NULL
+);
diff --git a/maintenance/archives/patch-img_width.sql b/maintenance/archives/patch-img_width.sql
new file mode 100644 (file)
index 0000000..c99bd46
--- /dev/null
@@ -0,0 +1,18 @@
+-- Extra image metadata, added for 1.5
+
+-- NOTE: as by patch-img_media_type.sql, the img_type
+-- column is no longer used and has therefore be removed from this patch
+
+ALTER TABLE /*$wgDBprefix*/image ADD (
+  img_width int(5) NOT NULL default 0,
+  img_height int(5) NOT NULL default 0,
+  img_bits int(5) NOT NULL default 0
+);
+
+ALTER TABLE /*$wgDBprefix*/oldimage ADD (
+  oi_width int(5) NOT NULL default 0,
+  oi_height int(5) NOT NULL default 0,
+  oi_bits int(3) NOT NULL default 0
+);
+
+
diff --git a/maintenance/archives/patch-indexes.sql b/maintenance/archives/patch-indexes.sql
new file mode 100644 (file)
index 0000000..23eec07
--- /dev/null
@@ -0,0 +1,24 @@
+-- 
+-- patch-indexes.sql
+-- 
+-- Fix up table indexes; new to stable release in November 2003
+-- 
+
+ALTER TABLE /*$wgDBprefix*/links
+   DROP INDEX l_from,
+   ADD INDEX l_from (l_from);
+
+ALTER TABLE /*$wgDBprefix*/brokenlinks
+   DROP INDEX bl_to,
+   ADD INDEX bl_to (bL_to);
+
+ALTER TABLE /*$wgDBprefix*/recentchanges
+   ADD INDEX rc_timestamp (rc_timestamp),
+   ADD INDEX rc_namespace_title (rc_namespace, rc_title),
+   ADD INDEX rc_cur_id (rc_cur_id);
+
+ALTER TABLE /*$wgDBprefix*/archive
+   ADD KEY name_title_timestamp (ar_namespace,ar_title,ar_timestamp);
+
+ALTER TABLE /*$wgDBprefix*/watchlist
+   ADD KEY namespace_title (wl_namespace,wl_title);
diff --git a/maintenance/archives/patch-interwiki-trans.sql b/maintenance/archives/patch-interwiki-trans.sql
new file mode 100644 (file)
index 0000000..2384a66
--- /dev/null
@@ -0,0 +1,2 @@
+ALTER TABLE /*$wgDBprefix*/interwiki
+       ADD COLUMN iw_trans TINYINT(1) NOT NULL DEFAULT 0;
diff --git a/maintenance/archives/patch-interwiki.sql b/maintenance/archives/patch-interwiki.sql
new file mode 100644 (file)
index 0000000..90b162e
--- /dev/null
@@ -0,0 +1,20 @@
+-- Creates interwiki prefix<->url mapping table
+-- used from 2003-08-21 dev version.
+-- Import the default mappings from maintenance/interwiki.sql
+
+CREATE TABLE /*$wgDBprefix*/interwiki (
+  -- The interwiki prefix, (e.g. "Meatball", or the language prefix "de")
+  iw_prefix char(32) NOT NULL,
+  
+  -- The URL of the wiki, with "$1" as a placeholder for an article name.
+  -- Any spaces in the name will be transformed to underscores before
+  -- insertion.
+  iw_url char(127) NOT NULL,
+  
+  -- A boolean value indicating whether the wiki is in this project
+  -- (used, for example, to detect redirect loops)
+  iw_local BOOL NOT NULL,
+  
+  UNIQUE KEY iw_prefix (iw_prefix)
+
+) TYPE=InnoDB;
diff --git a/maintenance/archives/patch-inverse_timestamp.sql b/maintenance/archives/patch-inverse_timestamp.sql
new file mode 100644 (file)
index 0000000..0f7d66f
--- /dev/null
@@ -0,0 +1,15 @@
+-- Removes the inverse_timestamp field from early 1.5 alphas.
+-- This field was used in the olden days as a crutch for sorting
+-- limitations in MySQL 3.x, but is being dropped now as an
+-- unnecessary burden. Serious wikis should be running on 4.x.
+--
+-- Updater added 2005-03-13
+
+ALTER TABLE /*$wgDBprefix*/revision
+  DROP COLUMN inverse_timestamp,
+  DROP INDEX page_timestamp,
+  DROP INDEX user_timestamp,
+  DROP INDEX usertext_timestamp,
+  ADD  INDEX page_timestamp (rev_page,rev_timestamp),
+  ADD  INDEX user_timestamp (rev_user,rev_timestamp),
+  ADD  INDEX usertext_timestamp (rev_user_text,rev_timestamp);
diff --git a/maintenance/archives/patch-ipb_expiry.sql b/maintenance/archives/patch-ipb_expiry.sql
new file mode 100644 (file)
index 0000000..0f106d7
--- /dev/null
@@ -0,0 +1,8 @@
+-- Adds the ipb_expiry field to ipblocks
+
+ALTER TABLE /*$wgDBprefix*/ipblocks ADD ipb_expiry char(14) binary NOT NULL default '';
+
+-- All IP blocks have one day expiry
+UPDATE /*$wgDBprefix*/ipblocks SET ipb_expiry = date_format(date_add(ipb_timestamp,INTERVAL 1 DAY),"%Y%m%d%H%i%s") WHERE ipb_user = 0;
+
+-- Null string is fine for user blocks, since this indicates infinity
diff --git a/maintenance/archives/patch-ipblocks.sql b/maintenance/archives/patch-ipblocks.sql
new file mode 100644 (file)
index 0000000..8e47798
--- /dev/null
@@ -0,0 +1,6 @@
+-- For auto-expiring blocks --
+
+ALTER TABLE /*$wgDBprefix*/ipblocks
+       ADD ipb_auto tinyint(1) NOT NULL default '0',
+       ADD ipb_id int(8) NOT NULL auto_increment,
+       ADD PRIMARY KEY (ipb_id);
diff --git a/maintenance/archives/patch-linkscc-1.3.sql b/maintenance/archives/patch-linkscc-1.3.sql
new file mode 100644 (file)
index 0000000..e397fcb
--- /dev/null
@@ -0,0 +1,6 @@
+--
+-- linkscc table used to cache link lists in easier to digest form.
+-- New schema for 1.3 - removes old lcc_title column.
+-- May 2004
+--
+ALTER TABLE /*$wgDBprefix*/linkscc DROP COLUMN lcc_title;
\ No newline at end of file
diff --git a/maintenance/archives/patch-linkscc.sql b/maintenance/archives/patch-linkscc.sql
new file mode 100644 (file)
index 0000000..91d4da5
--- /dev/null
@@ -0,0 +1,12 @@
+--
+-- linkscc table used to cache link lists in easier to digest form
+-- November 2003
+--
+-- Format later updated.
+--
+
+CREATE TABLE /*$wgDBprefix*/linkscc (
+  lcc_pageid INT UNSIGNED NOT NULL UNIQUE KEY,
+  lcc_cacheobj MEDIUMBLOB NOT NULL
+
+) TYPE=InnoDB;
diff --git a/maintenance/archives/patch-linktables.sql b/maintenance/archives/patch-linktables.sql
new file mode 100644 (file)
index 0000000..bb9bd03
--- /dev/null
@@ -0,0 +1,70 @@
+--
+-- Track links that do exist
+-- l_from and l_to key to cur_id
+--
+DROP TABLE IF EXISTS /*$wgDBprefix*/links;
+CREATE TABLE /*$wgDBprefix*/links (
+  -- Key to the page_id of the page containing the link.
+  l_from int(8) unsigned NOT NULL default '0',
+  
+  -- Key to the page_id of the link target.
+  -- An unfortunate consequence of this is that rename
+  -- operations require changing the links entries for
+  -- all links to the moved page.
+  l_to int(8) unsigned NOT NULL default '0',
+  
+  UNIQUE KEY l_from(l_from,l_to),
+  KEY (l_to)
+
+) TYPE=InnoDB;
+
+--
+-- Track links to pages that don't yet exist.
+-- bl_from keys to cur_id
+-- bl_to is a text link (namespace:title)
+--
+DROP TABLE IF EXISTS /*$wgDBprefix*/brokenlinks;
+CREATE TABLE /*$wgDBprefix*/brokenlinks (
+  -- Key to the page_id of the page containing the link.
+  bl_from int(8) unsigned NOT NULL default '0',
+  
+  -- Text of the target page title ("namesapce:title").
+  -- Unfortunately this doesn't split the namespace index
+  -- key and therefore can't easily be joined to anything.
+  bl_to varchar(255) binary NOT NULL default '',
+  UNIQUE KEY bl_from(bl_from,bl_to),
+  KEY (bl_to)
+
+) TYPE=InnoDB;
+
+--
+-- Track links to images *used inline*
+-- il_from keys to cur_id, il_to keys to image_name.
+-- We don't distinguish live from broken links.
+--
+DROP TABLE IF EXISTS /*$wgDBprefix*/imagelinks;
+CREATE TABLE /*$wgDBprefix*/imagelinks (
+  -- Key to page_id of the page containing the image / media link.
+  il_from int(8) unsigned NOT NULL default '0',
+  
+  -- Filename of target image.
+  -- This is also the page_title of the file's description page;
+  -- all such pages are in namespace 6 (NS_IMAGE).
+  il_to varchar(255) binary NOT NULL default '',
+  
+  UNIQUE KEY il_from(il_from,il_to),
+  KEY (il_to)
+
+) TYPE=InnoDB;
+
+--
+-- Stores (possibly gzipped) serialized objects with
+-- cache arrays to reduce database load slurping up
+-- from links and brokenlinks.
+--
+DROP TABLE IF EXISTS /*$wgDBprefix*/linkscc;
+CREATE TABLE /*$wgDBprefix*/linkscc (
+  lcc_pageid INT UNSIGNED NOT NULL UNIQUE KEY,
+  lcc_cacheobj MEDIUMBLOB NOT NULL
+
+) TYPE=InnoDB;
diff --git a/maintenance/archives/patch-list.txt b/maintenance/archives/patch-list.txt
new file mode 100644 (file)
index 0000000..93a63bf
--- /dev/null
@@ -0,0 +1,182 @@
+List of database patches and upgrades as the PediaWiki software evolves...
+
+* 2002-11-23: Search index format changed for UTF-8 wikis
+For wikis using the UTF-8 languages, the search index entries
+need to be rebuild to allow searching to work. (Other wikis
+that have been run through the old phase2->phase3 conversion
+script should also be reindexed to catch apostrophe misplacement.)
+
+Run rebuildIndex.php on your wiki.
+
+
+
+* 2002-11-27: Watchlist format changed
+Converts the user_watchlist entries out to a separate table which
+links user_id<->cur_id and can be more handily queried.
+
+Run upgradeWatchlist.php on your wiki.
+
+
+
+* 2002-12-14: Recentchanges table bot/hidden column
+Adds a column to indicate changes by registered bots (or perhaps
+later other admin actions) that should be hidden from the default
+Recentchanges list because people think they're tedious, but should
+still be available in article histories, contribs lists, and
+power-user RC lists.
+
+Run bot.sql against your database.
+
+
+
+* 2002-12-17: Watchlist format changed again
+Now using namespace, title instead of cur_id. This can track deleted/
+recreated pages better, makes it easier to handle talk pages (now with
+the auto-watch feature there's a lot more watching of talk pages!)
+and whatnot.
+
+Run patch-watchlist.sql against your database. If all is well, drop
+the oldwatchlist table which is no longer needed. (Note that this update
+also drops the vestigial user_watchlist column.)
+
+
+
+* 2002-12-26: TeX math rendering adds 'math' table
+A new 'math' table is used to cache TeX sections.
+
+Run patch-math.sql against your database, and add 'tmp' and 'math'
+subdirectories to your tree alongside the upload directory, and copy
+the 'math' source subdirectory under the wiki's PHP directory and run
+"make" to compile the texvc evaluator. (whew!)
+
+TeX support requires TeX, OCaml, and ImageMagick. If you don't want
+to use TeX support on your wiki, you can globally disable it by
+setting $wgUseTeX=false in LocalSettings.php.
+
+
+
+* 2003-01-25: searchindex table
+A new 'searchindex' table separates the fulltext index fields from
+'cur'. This enables use of InnoDB tables, which don't support fulltext
+search, for the main data, and will keep junk out of the backup dumps.
+
+Run patch-searchindex.sql on the database. If you wish to change table
+tables on the others, use 'alter table' manually. (See MySQL docs.)
+
+
+* 2003-01-24: Talk pages for anonymous users
+A new table user_newtalk contains a list of talk pages that were
+changed, both pages by anonymous and those by non-anonymous users.
+
+Run patch-usernewtalk.sql if your database was created before
+this date.
+
+
+* 2003-02-02: Math table changed
+Rerun patch-math.sql to recreate it.
+
+* 2003-02-03: Index added to USER table for performance reasons. Run
+patch-userindex.sql to create it.
+
+
+* 2003-02-09: Random table & inverse timestamps
+The random page queue table has been removed in favor of a column
+in the cur table. This eliminates the ssllooww queue refill step;
+pre-storing random indices in an indexed column means we can do the
+random sort instantly; each element is re-randomized upon selection.
+
+Also, an inverse_timestamp field has been added to the cur and old
+tables. This will allow fast index-based sorting in history lists,
+user contribs, linked recentchanges, etc with MySQL 3, which doesn't
+allow DESC ordering on an indexed field. This may be removed later
+when MySQL is found to be stable.
+
+
+* 2003-03-22: Last touched fields for caching
+'Last touched' timestamp fields have been added to the cur and user
+tables to aid in maintaining cache consistency. Web clients will
+be forced to reload a page if it has been touched since the client's
+cached copy (this will catch indirect changes like creation of
+linked pages) or if a user changes preferences or logs in anew (so
+visual changes and login status are taken into account).
+
+Run patch-cache.sql on the database to set these fields up. This is
+required for changes to OutputPage.php and elsewhere to continue
+working on an older database.
+
+
+* 2003-05-23: Index for "Oldest articles"
+"Oldest articles" needs an index on namespace, redirect and timestamp
+to be reasonably fast. (patch-oldestindex.sql)
+
+OutputPage.php User.php maintenance/buildTables.inc maintenance/patch-cache.sql maintenance/patch-list.txt
+
+* 2003-09: Ipblocks auto-expiry update
+patch-ipblocks.sql
+
+* Interwiki URL table
+Moves the interwiki prefix<->url mapping table from a static array
+into the database. If you've got a custom table, be sure to make
+your changes!
+Run patch-interwiki.sql to create the interwiki table, then the
+plain interwiki.sql to load up the default set of mappings.
+
+* 2003-05-30: File upload license fields
+Adds fields to 'image' table.
+INCOMPLETE, DO NOT USE
+
+
+* 2003-08-21: Interwiki URL table
+Moves the interwiki prefix<->url mapping table from a static array
+into the database. If you've got a custom table, be sure to make
+your changes!
+
+Run patch-interwiki.sql to create the interwiki table, then the
+plain interwiki.sql to load up the default set of mappings.
+
+* 2003-09: Ipblocks auto-expiry update
+patch-ipblocks.sql
+
+* Interwiki URL table
+Moves the interwiki prefix<->url mapping table from a static array
+into the database. If you've got a custom table, be sure to make
+your changes!
+Run patch-interwiki.sql to create the interwiki table, then the
+plain interwiki.sql to load up the default set of mappings.
+
+* 2003-11: Indexes
+Fixes up indexes on links, brokenlinks, recentchanges, watchlist,
+and archive tables to boost speed.
+
+Run patch-indexes.sql.
+
+* 2003-11: linkscc table creation
+patch-linkscc.sql
+
+
+* 2004-01-25: recentchanges additional index
+Adds an index to recentchanges to optimize Special:Newpages
+patch-rc-newindex.sql
+
+* 2004-02-14: Adds the ipb_expiry field to ipblocks
+patch-ipb_expiry.sql
+
+
+* 2004-03-11: Recreate links tables to avoid duplicating titles
+everywhere. **Rebuild your links after this with refreshLinks.php**
+
+patch-linktables.sql
+
+
+* 2004-04: Add user_real_name field
+patch-user-realname.sql
+
+* 2004-05-08: Add querycache table for caching special pages and generic
+       object cache to cover some slow operations w/o memcached.
+patch-querycache.sql
+patch-objectcache.sql
+
+* 2004-05-14: Add categorylinks table for handling category membership
+patch-categorylinks.sql
diff --git a/maintenance/archives/patch-log_params.sql b/maintenance/archives/patch-log_params.sql
new file mode 100644 (file)
index 0000000..aa00a67
--- /dev/null
@@ -0,0 +1 @@
+ALTER TABLE /*$wgDBprefix*/logging ADD log_params blob NOT NULL default '';
diff --git a/maintenance/archives/patch-logging-title.sql b/maintenance/archives/patch-logging-title.sql
new file mode 100644 (file)
index 0000000..c5da0dc
--- /dev/null
@@ -0,0 +1,6 @@
+-- 1.4 betas were missing the 'binary' marker from logging.log_title,
+-- which causes a collation mismatch error on joins in MySQL 4.1.
+
+ALTER TABLE /*$wgDBprefix*/logging
+  CHANGE COLUMN log_title
+    log_title varchar(255) binary NOT NULL default '';
diff --git a/maintenance/archives/patch-logging.sql b/maintenance/archives/patch-logging.sql
new file mode 100644 (file)
index 0000000..79bb53b
--- /dev/null
@@ -0,0 +1,37 @@
+-- Add the logging table and adjust recentchanges to accomodate special pages
+-- 2004-08-24
+
+CREATE TABLE /*$wgDBprefix*/logging (
+  -- Symbolic keys for the general log type and the action type
+  -- within the log. The output format will be controlled by the
+  -- action field, but only the type controls categorization.
+  log_type char(10) NOT NULL default '',
+  log_action char(10) NOT NULL default '',
+  
+  -- Timestamp. Duh.
+  log_timestamp char(14) NOT NULL default '19700101000000',
+  
+  -- The user who performed this action; key to user_id
+  log_user int unsigned NOT NULL default 0,
+  
+  -- Key to the page affected. Where a user is the target,
+  -- this will point to the user page.
+  log_namespace int NOT NULL default 0,
+  log_title varchar(255) binary NOT NULL default '',
+  
+  -- Freeform text. Interpreted as edit history comments.
+  log_comment varchar(255) NOT NULL default '',
+  
+  -- LF separated list of miscellaneous parameters
+  log_params blob NOT NULL default '',
+
+  KEY type_time (log_type, log_timestamp),
+  KEY user_time (log_user, log_timestamp),
+  KEY page_time (log_namespace, log_title, log_timestamp)
+
+) TYPE=InnoDB;
+
+
+-- Change from unsigned to signed so we can store special pages
+ALTER TABLE recentchanges
+  MODIFY rc_namespace tinyint(3) NOT NULL default '0';
diff --git a/maintenance/archives/patch-math.sql b/maintenance/archives/patch-math.sql
new file mode 100644 (file)
index 0000000..aee24a8
--- /dev/null
@@ -0,0 +1,28 @@
+-- Creates table math used for caching TeX blocks.  Needs to be run
+-- on old installations when adding TeX support (2002-12-26)
+-- Or, TeX can be disabled via $wgUseTeX=false in LocalSettings.php
+
+-- Note: math table has changed, and this script needs to be run again
+-- to create it. (2003-02-02)
+
+DROP TABLE IF EXISTS /*$wgDBprefix*/math;
+CREATE TABLE /*$wgDBprefix*/math (
+  -- Binary MD5 hash of the latex fragment, used as an identifier key.
+  math_inputhash varchar(16) NOT NULL,
+  
+  -- Not sure what this is, exactly...
+  math_outputhash varchar(16) NOT NULL,
+  
+  -- texvc reports how well it thinks the HTML conversion worked;
+  -- if it's a low level the PNG rendering may be preferred.
+  math_html_conservativeness tinyint(1) NOT NULL,
+  
+  -- HTML output from texvc, if any
+  math_html text,
+  
+  -- MathML output from texvc, if any
+  math_mathml text,
+  
+  UNIQUE KEY math_inputhash (math_inputhash)
+
+) TYPE=InnoDB;
diff --git a/maintenance/archives/patch-objectcache.sql b/maintenance/archives/patch-objectcache.sql
new file mode 100644 (file)
index 0000000..18572aa
--- /dev/null
@@ -0,0 +1,9 @@
+-- For a few generic cache operations if not using Memcached
+CREATE TABLE /*$wgDBprefix*/objectcache (
+  keyname char(255) binary not null default '',
+  value mediumblob,
+  exptime datetime,
+  unique key (keyname),
+  key (exptime)
+
+) TYPE=InnoDB;
diff --git a/maintenance/archives/patch-oldestindex.sql b/maintenance/archives/patch-oldestindex.sql
new file mode 100644 (file)
index 0000000..930214f
--- /dev/null
@@ -0,0 +1,5 @@
+-- Add index for "Oldest articles" (Special:Ancientpages)
+-- 2003-05-23 Erik Moeller <moeller@scireview.de>
+
+ALTER TABLE /*$wgDBprefix*/cur
+   ADD INDEX namespace_redirect_timestamp(cur_namespace,cur_is_redirect,cur_timestamp);
diff --git a/maintenance/archives/patch-page_len.sql b/maintenance/archives/patch-page_len.sql
new file mode 100644 (file)
index 0000000..c32dc8d
--- /dev/null
@@ -0,0 +1,16 @@
+-- Page length field (in bytes) for current revision of page.
+-- Since page text is now stored separately, it may be compressed
+-- or otherwise difficult to calculate. Additionally, the field
+-- can be indexed for handy 'long' and 'short' page lists.
+--
+-- Added 2005-03-12
+
+ALTER TABLE /*$wgDBprefix*/page
+  ADD page_len int(8) unsigned NOT NULL,
+  ADD INDEX (page_len);
+
+-- Not accurate if upgrading from intermediate
+-- 1.5 alpha and have revision compression on.
+UPDATE /*$wgDBprefix*/page, /*$wgDBprefix*/text
+  SET page_len=LENGTH(old_text)
+  WHERE page_latest=old_id;
diff --git a/maintenance/archives/patch-pagelinks.sql b/maintenance/archives/patch-pagelinks.sql
new file mode 100644 (file)
index 0000000..7240cff
--- /dev/null
@@ -0,0 +1,56 @@
+--
+-- Create the new pagelinks table to merge links and brokenlinks data,
+-- and populate it.
+-- 
+-- Unlike the old links and brokenlinks, these records will not need to be
+-- altered when target pages are created, deleted, or renamed. This should
+-- reduce the amount of severe database frustration that happens when widely-
+-- linked pages are altered.
+--
+-- Fixups for brokenlinks to pages in namespaces need to be run after this;
+-- this is done by updaters.inc if run through the regular update scripts.
+--
+-- 2005-05-26
+--
+
+--
+-- Track page-to-page hyperlinks within the wiki.
+--
+CREATE TABLE /*$wgDBprefix*/pagelinks (
+  -- Key to the page_id of the page containing the link.
+  pl_from int(8) unsigned NOT NULL default '0',
+  
+  -- Key to page_namespace/page_title of the target page.
+  -- The target page may or may not exist, and due to renames
+  -- and deletions may refer to different page records as time
+  -- goes by.
+  pl_namespace int NOT NULL default '0',
+  pl_title varchar(255) binary NOT NULL default '',
+  
+  UNIQUE KEY pl_from(pl_from,pl_namespace,pl_title),
+  KEY (pl_namespace,pl_title)
+
+) TYPE=InnoDB;
+
+
+-- Import existing-page links
+INSERT
+  INTO /*$wgDBprefix*/pagelinks (pl_from,pl_namespace,pl_title)
+  SELECT l_from,page_namespace,page_title
+    FROM /*$wgDBprefix*/links, /*$wgDBprefix*/page
+    WHERE l_to=page_id;
+
+-- import brokenlinks
+-- NOTE: We'll have to fix up individual entries that aren't in main NS
+INSERT INTO /*$wgDBprefix*/pagelinks (pl_from,pl_namespace,pl_title)
+  SELECT bl_from, 0, bl_to
+  FROM /*$wgDBprefix*/brokenlinks;
+
+-- For each namespace do something like:
+--
+-- UPDATE /*$wgDBprefix*/pagelinks
+--   SET pl_namespace=$ns,
+--       pl_title=TRIM(LEADING '$prefix:' FROM pl_title)
+-- WHERE pl_namespace=0
+--   AND pl_title LIKE '$likeprefix:%'";
+--
diff --git a/maintenance/archives/patch-parsercache.sql b/maintenance/archives/patch-parsercache.sql
new file mode 100644 (file)
index 0000000..854e6c5
--- /dev/null
@@ -0,0 +1,15 @@
+--
+-- parsercache table, for cacheing complete parsed articles 
+-- before they are imbedded in the skin.
+--
+
+CREATE TABLE /*$wgDBprefix*/parsercache (
+  pc_pageid INT(11) NOT NULL,
+  pc_title VARCHAR(255) NOT NULL,
+  pc_prefhash CHAR(32) NOT NULL,
+  pc_expire DATETIME NOT NULL,
+  pc_data MEDIUMBLOB NOT NULL,
+  PRIMARY KEY (pc_pageid, pc_prefhash),
+  KEY(pc_title),
+  KEY(pc_expire)
+) TYPE=InnoDB;
diff --git a/maintenance/archives/patch-profiling.sql b/maintenance/archives/patch-profiling.sql
new file mode 100644 (file)
index 0000000..1b22778
--- /dev/null
@@ -0,0 +1,10 @@
+-- profiling table
+-- This is optional
+
+CREATE TABLE /*$wgDBprefix*/profiling (
+       pf_count integer not null default 0,
+       pf_time float not null default 0,
+       pf_name varchar(255) not null default '',
+       UNIQUE KEY pf_name (pf_name)
+);
+       
diff --git a/maintenance/archives/patch-querycache.sql b/maintenance/archives/patch-querycache.sql
new file mode 100644 (file)
index 0000000..7df9129
--- /dev/null
@@ -0,0 +1,16 @@
+-- Used for caching expensive grouped queries
+
+CREATE TABLE /*$wgDBprefix*/querycache (
+  -- A key name, generally the base name of of the special page.
+  qc_type char(32) NOT NULL,
+  
+  -- Some sort of stored value. Sizes, counts...
+  qc_value int(5) unsigned NOT NULL default '0',
+  
+  -- Target namespace+title
+  qc_namespace int NOT NULL default '0',
+  qc_title char(255) binary NOT NULL default '',
+  
+  KEY (qc_type,qc_value)
+
+) TYPE=InnoDB;
diff --git a/maintenance/archives/patch-random-dateindex.sql b/maintenance/archives/patch-random-dateindex.sql
new file mode 100644 (file)
index 0000000..5d514cc
--- /dev/null
@@ -0,0 +1,54 @@
+-- patch-random-dateindex.sql
+-- 2003-02-09
+--
+-- This patch does two things:
+--  * Adds cur_random column to replace random table
+--    (Requires change to SpecialRandom.php)
+--    random table no longer needs refilling
+--    Note: short-term duplicate results *are* possible, but very unlikely on large wiki
+--
+--  * Adds inverse_timestamp columns to cur and old and indexes
+--    to allow descending timestamp sort in history, contribs, etc
+--    (Requires changes to Article.php, DatabaseFunctions.php,
+--     ... )
+--                       cur_timestamp  inverse_timestamp
+--     99999999999999 - 20030209222556 = 79969790777443
+--     99999999999999 - 20030211083412 = 79969788916587
+--
+--    We won't need this on MySQL 4; there will be a removal patch later.
+
+-- Indexes:
+-- cur needs (cur_random) for random sort
+-- cur and old need (namespace,title,timestamp) index for history,watchlist,rclinked
+-- cur and old need (user,timestamp) index for contribs
+-- cur and old need (user_text,timestamp) index for contribs
+
+ALTER TABLE /*$wgDBprefix*/cur
+  DROP INDEX cur_user,
+  DROP INDEX cur_user_text,
+  ADD COLUMN cur_random real unsigned NOT NULL,
+  ADD COLUMN inverse_timestamp char(14) binary NOT NULL default '',
+  ADD INDEX (cur_random),
+  ADD INDEX name_title_timestamp (cur_namespace,cur_title,inverse_timestamp),
+  ADD INDEX user_timestamp (cur_user,inverse_timestamp),
+  ADD INDEX usertext_timestamp (cur_user_text,inverse_timestamp);
+
+UPDATE /*$wgDBprefix*/cur SET
+  inverse_timestamp=99999999999999-cur_timestamp,
+  cur_random=RAND();
+
+ALTER TABLE /*$wgDBprefix*/old
+  DROP INDEX old_user,
+  DROP INDEX old_user_text,
+  ADD COLUMN inverse_timestamp char(14) binary NOT NULL default '',
+  ADD INDEX name_title_timestamp (old_namespace,old_title,inverse_timestamp),
+  ADD INDEX user_timestamp (old_user,inverse_timestamp),
+  ADD INDEX usertext_timestamp (old_user_text,inverse_timestamp);
+
+UPDATE /*$wgDBprefix*/old SET
+  inverse_timestamp=99999999999999-old_timestamp;
+
+-- If leaving wiki publicly accessible in read-only mode during
+-- the upgrade, comment out the below line; leave 'random' table
+-- in place until the new software is installed.
+DROP TABLE /*$wgDBprefix*/random;
diff --git a/maintenance/archives/patch-rc-newindex.sql b/maintenance/archives/patch-rc-newindex.sql
new file mode 100644 (file)
index 0000000..2315ff3
--- /dev/null
@@ -0,0 +1,9 @@
+--
+-- patch-rc-newindex.sql
+-- Adds an index to recentchanges to optimize Special:Newpages
+-- 2004-01-25
+--
+
+ALTER TABLE /*$wgDBprefix*/recentchanges
+       ADD INDEX new_name_timestamp(rc_new,rc_namespace,rc_timestamp);
+
diff --git a/maintenance/archives/patch-rc-patrol.sql b/maintenance/archives/patch-rc-patrol.sql
new file mode 100644 (file)
index 0000000..1839c1e
--- /dev/null
@@ -0,0 +1,9 @@
+--
+-- patch-rc-patrol.sql
+-- Adds a row to recentchanges for the patrolling feature
+-- 2004-08-09
+--
+
+ALTER TABLE /*$wgDBprefix*/recentchanges
+       ADD COLUMN rc_patrolled tinyint(3) unsigned NOT NULL default '0';
+
diff --git a/maintenance/archives/patch-rc_id.sql b/maintenance/archives/patch-rc_id.sql
new file mode 100644 (file)
index 0000000..6dd9ef4
--- /dev/null
@@ -0,0 +1,7 @@
+-- Primary key in recentchanges
+
+ALTER TABLE /*$wgDBprefix*/recentchanges 
+  ADD rc_id int(8) NOT NULL auto_increment,
+  ADD PRIMARY KEY rc_id (rc_id);
+
+
diff --git a/maintenance/archives/patch-rc_ip.sql b/maintenance/archives/patch-rc_ip.sql
new file mode 100644 (file)
index 0000000..a68a22c
--- /dev/null
@@ -0,0 +1,7 @@
+-- Adding the rc_ip field for logging of IP addresses in recentchanges
+
+ALTER TABLE /*$wgDBprefix*/recentchanges 
+  ADD rc_ip char(15) NOT NULL default '',
+  ADD INDEX rc_ip (rc_ip);
+
+
diff --git a/maintenance/archives/patch-rc_type.sql b/maintenance/archives/patch-rc_type.sql
new file mode 100644 (file)
index 0000000..1097771
--- /dev/null
@@ -0,0 +1,9 @@
+-- recentchanges improvements --
+
+ALTER TABLE /*$wgDBprefix*/recentchanges
+  ADD rc_type tinyint(3) unsigned NOT NULL default '0',
+  ADD rc_moved_to_ns tinyint(3) unsigned NOT NULL default '0',
+  ADD rc_moved_to_title varchar(255) binary NOT NULL default '';
+
+UPDATE /*$wgDBprefix*/recentchanges SET rc_type=1 WHERE rc_new;
+UPDATE /*$wgDBprefix*/recentchanges SET rc_type=3 WHERE rc_namespace=4 AND (rc_title='Deletion_log' OR rc_title='Upload_log');
diff --git a/maintenance/archives/patch-rename-group.sql b/maintenance/archives/patch-rename-group.sql
new file mode 100644 (file)
index 0000000..026b60b
--- /dev/null
@@ -0,0 +1,10 @@
+-- Rename groups table to groups, which is not a keyword
+-- It was called group in a few alpha versions
+
+RENAME TABLE /*$wgDBprefix*/`group` TO /*$wgDBprefix*/groups;
+ALTER TABLE /*$wgDBprefix*/groups 
+       CHANGE group_id gr_id int(5) unsigned NOT NULL auto_increment,
+       CHANGE group_name gr_name varchar(50) NOT NULL default '',
+       CHANGE group_description gr_description varchar(255) NOT NULL default '',
+       CHANGE group_rights gr_rights tinyblob;
+
diff --git a/maintenance/archives/patch-rename-user_groups-and_rights.sql b/maintenance/archives/patch-rename-user_groups-and_rights.sql
new file mode 100644 (file)
index 0000000..abd5931
--- /dev/null
@@ -0,0 +1,9 @@
+
+ALTER TABLE /*$wgDBprefix*/user_groups
+       CHANGE user_id ug_user INT(5) UNSIGNED NOT NULL DEFAULT '0',
+       CHANGE group_id ug_group INT(5) UNSIGNED NOT NULL DEFAULT '0';
+
+ALTER TABLE /*$wgDBprefix*/user_rights
+       CHANGE user_id ur_user INT(5) UNSIGNED NOT NULL,
+       CHANGE user_rights ur_rights TINYBLOB NOT NULL DEFAULT '';
+
diff --git a/maintenance/archives/patch-restructure.sql b/maintenance/archives/patch-restructure.sql
new file mode 100644 (file)
index 0000000..53f1836
--- /dev/null
@@ -0,0 +1,147 @@
+-- The Great Restructuring of October 2004
+-- Creates 'page', 'revision' tables and transforms the classic
+-- cur+old into a separate page+revision+text structure.
+--
+-- The pre-conversion 'old' table is renamed to 'text' and used
+-- without internal restructuring to avoid rebuilding the entire
+-- table. (This can be done separately if desired.)
+--
+-- The pre-conversion 'cur' table is now redundant and can be
+-- discarded when done.
+
+CREATE TABLE /*$wgDBprefix*/page (
+  page_id int(8) unsigned NOT NULL auto_increment,
+  page_namespace tinyint NOT NULL,
+  page_title varchar(255) binary NOT NULL,
+  page_restrictions tinyblob NOT NULL default '',
+  page_counter bigint(20) unsigned NOT NULL default '0',
+  page_is_redirect tinyint(1) unsigned NOT NULL default '0',
+  page_is_new tinyint(1) unsigned NOT NULL default '0',
+  page_random real unsigned NOT NULL,
+  page_touched char(14) binary NOT NULL default '',
+  page_latest int(8) unsigned NOT NULL,
+  page_len int(8) unsigned NOT NULL,
+
+  PRIMARY KEY page_id (page_id),
+  UNIQUE INDEX name_title (page_namespace,page_title),
+  INDEX (page_random),
+  INDEX (page_len)
+);
+
+CREATE TABLE /*$wgDBprefix*/revision (
+  rev_id int(8) unsigned NOT NULL auto_increment,
+  rev_page int(8) unsigned NOT NULL,
+  rev_comment tinyblob NOT NULL default '',
+  rev_user int(5) unsigned NOT NULL default '0',
+  rev_user_text varchar(255) binary NOT NULL default '',
+  rev_timestamp char(14) binary NOT NULL default '',
+  rev_minor_edit tinyint(1) unsigned NOT NULL default '0',
+  rev_deleted tinyint(1) unsigned NOT NULL default '0',
+
+  
+  PRIMARY KEY rev_page_id (rev_page, rev_id),
+  UNIQUE INDEX rev_id (rev_id),
+  INDEX rev_timestamp (rev_timestamp),
+  INDEX page_timestamp (rev_page,rev_timestamp),
+  INDEX user_timestamp (rev_user,rev_timestamp),
+  INDEX usertext_timestamp (rev_user_text,rev_timestamp)
+);
+
+-- If creating new 'text' table it would look like this:
+--
+-- CREATE TABLE /*$wgDBprefix*/text (
+--   old_id int(8) unsigned NOT NULL auto_increment,
+--   old_text mediumtext NOT NULL default '',
+--   old_flags tinyblob NOT NULL default '',
+--   
+--   PRIMARY KEY old_id (old_id)
+-- );
+
+
+-- Lock!
+LOCK TABLES /*$wgDBprefix*/page WRITE, /*$wgDBprefix*/revision WRITE, /*$wgDBprefix*/old WRITE, /*$wgDBprefix*/cur WRITE;
+
+-- Save the last old_id value for later
+SELECT (@maxold:=MAX(old_id)) FROM /*$wgDBprefix*/old;
+
+-- First, copy all current entries into the old table.
+INSERT
+  INTO /*$wgDBprefix*/old
+    (old_namespace,
+    old_title,
+    old_text,
+    old_comment,
+    old_user,
+    old_user_text,
+    old_timestamp,
+    old_minor_edit,
+    old_flags)
+  SELECT
+    cur_namespace,
+    cur_title,
+    cur_text,
+    cur_comment,
+    cur_user,
+    cur_user_text,
+    cur_timestamp,
+    cur_minor_edit,
+    ''
+  FROM /*$wgDBprefix*/cur;
+
+-- Now, copy all old data except the text into revisions
+INSERT
+  INTO /*$wgDBprefix*/revision
+    (rev_id,
+    rev_page,
+    rev_comment,
+    rev_user,
+    rev_user_text,
+    rev_timestamp,
+    rev_minor_edit)
+  SELECT
+    old_id,
+    cur_id,
+    old_comment,
+    old_user,
+    old_user_text,
+    old_timestamp,
+    old_minor_edit
+  FROM /*$wgDBprefix*/old,/*$wgDBprefix*/cur
+  WHERE old_namespace=cur_namespace
+    AND old_title=cur_title;
+
+-- And, copy the cur data into page
+INSERT
+  INTO /*$wgDBprefix*/page
+    (page_id,
+    page_namespace,
+    page_title,
+    page_restrictions,
+    page_counter,
+    page_is_redirect,
+    page_is_new,
+    page_random,
+    page_touched,
+    page_latest)
+  SELECT
+    cur_id,
+    cur_namespace,
+    cur_title,
+    cur_restrictions,
+    cur_counter,
+    cur_is_redirect,
+    cur_is_new,
+    cur_random,
+    cur_touched,
+    rev_id
+  FROM /*$wgDBprefix*/cur,/*$wgDBprefix*/revision
+  WHERE cur_id=rev_page
+    AND rev_timestamp=cur_timestamp
+    AND rev_id > @maxold;
+
+UNLOCK TABLES;
+
+-- Keep the old table around as the text store.
+-- Its extra fields will be ignored, but trimming them is slow
+-- so we won't bother doing it for now.
+ALTER TABLE /*$wgDBprefix*/old RENAME TO /*$wgDBprefix*/text;
diff --git a/maintenance/archives/patch-rev_deleted.sql b/maintenance/archives/patch-rev_deleted.sql
new file mode 100644 (file)
index 0000000..3af0c1d
--- /dev/null
@@ -0,0 +1,11 @@
+--
+-- Add rev_deleted flag to revision table.
+-- Deleted revisions can thus continue to be listed in history
+-- and user contributions, and their text storage doesn't have
+-- to be disturbed.
+--
+-- 2005-03-31
+--
+
+ALTER TABLE /*$wgDBprefix*/revision
+  ADD rev_deleted tinyint(1) unsigned NOT NULL default '0';
diff --git a/maintenance/archives/patch-rev_text_id.sql b/maintenance/archives/patch-rev_text_id.sql
new file mode 100644 (file)
index 0000000..44ef438
--- /dev/null
@@ -0,0 +1,17 @@
+--
+-- Adds rev_text_id field to revision table.
+-- This is a key to text.old_id, so that revisions can be stored
+-- for non-save operations without duplicating text, and so that
+-- a back-end storage system can provide its own numbering system
+-- if necessary.
+--
+-- rev.rev_id and text.old_id are no longer assumed to be the same.
+--
+-- 2005-03-28
+--
+
+ALTER TABLE /*$wgDBprefix*/revision
+  ADD rev_text_id int(8) unsigned NOT NULL;
+
+UPDATE /*$wgDBprefix*/revision
+  SET rev_text_id=rev_id;
diff --git a/maintenance/archives/patch-searchindex.sql b/maintenance/archives/patch-searchindex.sql
new file mode 100644 (file)
index 0000000..fb54dbb
--- /dev/null
@@ -0,0 +1,40 @@
+-- Break fulltext search index out to separate table from cur
+-- This is being done mainly to allow us to use InnoDB tables
+-- for the main db while keeping the MyISAM fulltext index for
+-- search.
+
+-- 2002-12-16, 2003-01-25 Brion VIBBER <brion@pobox.com>
+
+-- Creating searchindex table...
+DROP TABLE IF EXISTS /*$wgDBprefix*/searchindex;
+CREATE TABLE /*$wgDBprefix*/searchindex (
+  -- Key to page_id
+  si_page int(8) unsigned NOT NULL,
+  
+  -- Munged version of title
+  si_title varchar(255) NOT NULL default '',
+  
+  -- Munged version of body text
+  si_text mediumtext NOT NULL default '',
+  
+  UNIQUE KEY (si_page)
+
+) TYPE=MyISAM;
+
+-- Copying data into new table...
+INSERT INTO /*$wgDBprefix*/searchindex
+  (si_page,si_title,si_text)
+  SELECT
+    cur_id,cur_ind_title,cur_ind_text
+    FROM /*$wgDBprefix*/cur;
+
+
+-- Creating fulltext index...
+ALTER TABLE /*$wgDBprefix*/searchindex
+  ADD FULLTEXT si_title (si_title),
+  ADD FULLTEXT si_text (si_text);
+
+-- Dropping index columns from cur table.
+ALTER TABLE /*$wgDBprefix*/cur
+  DROP COLUMN cur_ind_title,
+  DROP COLUMN cur_ind_text;
diff --git a/maintenance/archives/patch-ss_total_articles.sql b/maintenance/archives/patch-ss_total_articles.sql
new file mode 100644 (file)
index 0000000..b4a48cf
--- /dev/null
@@ -0,0 +1,6 @@
+-- Faster statistics, as of 1.4.3
+
+ALTER TABLE /*$wgDBprefix*/site_stats
+  ADD ss_total_pages bigint(20) default -1,
+  ADD ss_users bigint(20) default -1,
+  ADD ss_admins int(10) default -1;
diff --git a/maintenance/archives/patch-trackbacks.sql b/maintenance/archives/patch-trackbacks.sql
new file mode 100644 (file)
index 0000000..4193d05
--- /dev/null
@@ -0,0 +1,10 @@
+CREATE TABLE /*$wgDBprefix*/trackbacks (
+       tb_id           INTEGER AUTO_INCREMENT PRIMARY KEY,
+       tb_page         INTEGER REFERENCES page(page_id) ON DELETE CASCADE,
+       tb_title        VARCHAR(255) NOT NULL,
+       tb_url          VARCHAR(255) NOT NULL,
+       tb_ex           TEXT,
+       tb_name         VARCHAR(255),
+
+       INDEX (tb_page)
+);
diff --git a/maintenance/archives/patch-transcache.sql b/maintenance/archives/patch-transcache.sql
new file mode 100644 (file)
index 0000000..2bdc10c
--- /dev/null
@@ -0,0 +1,7 @@
+CREATE TABLE /*$wgDBprefix*/transcache (
+       tc_url          VARCHAR(255) NOT NULL,
+       tc_contents     TEXT,
+       tc_time         INT NOT NULL,
+       UNIQUE INDEX tc_url_idx(tc_url)
+);
+
diff --git a/maintenance/archives/patch-user-realname.sql b/maintenance/archives/patch-user-realname.sql
new file mode 100644 (file)
index 0000000..96edaa4
--- /dev/null
@@ -0,0 +1,5 @@
+-- Add a 'real name' field where users can specify the name they want
+-- used for author attribution or other places that real names matter.
+
+ALTER TABLE user 
+        ADD (user_real_name varchar(255) binary NOT NULL default '');
diff --git a/maintenance/archives/patch-user_email_token.sql b/maintenance/archives/patch-user_email_token.sql
new file mode 100644 (file)
index 0000000..d4d633b
--- /dev/null
@@ -0,0 +1,12 @@
+--
+-- E-mail confirmation token and expiration timestamp,
+-- for verification of e-mail addresses.
+--
+-- 2005-04-25
+--
+
+ALTER TABLE /*$wgDBprefix*/user
+  ADD COLUMN user_email_authenticated CHAR(14) BINARY,
+  ADD COLUMN user_email_token CHAR(32) BINARY,
+  ADD COLUMN user_email_token_expires CHAR(14) BINARY,
+  ADD INDEX (user_email_token);
diff --git a/maintenance/archives/patch-user_groups.sql b/maintenance/archives/patch-user_groups.sql
new file mode 100644 (file)
index 0000000..50f9999
--- /dev/null
@@ -0,0 +1,25 @@
+--
+-- User permissions have been broken out to a separate table;
+-- this allows sites with a shared user table to have different
+-- permissions assigned to a user in each project.
+--
+-- This table replaces the old user_rights field which used a
+-- comma-separated blob.
+--
+CREATE TABLE /*$wgDBprefix*/user_groups (
+  -- Key to user_id
+  ug_user int(5) unsigned NOT NULL default '0',
+  
+  -- Group names are short symbolic string keys.
+  -- The set of group names is open-ended, though in practice
+  -- only some predefined ones are likely to be used.
+  --
+  -- At runtime $wgGroupPermissions will associate group keys
+  -- with particular permissions. A user will have the combined
+  -- permissions of any group they're explicitly in, plus
+  -- the implicit '*' and 'user' groups.
+  ug_group char(16) NOT NULL default '',
+  
+  PRIMARY KEY (ug_user,ug_group),
+  KEY (ug_group)
+) TYPE=InnoDB;
diff --git a/maintenance/archives/patch-user_nameindex.sql b/maintenance/archives/patch-user_nameindex.sql
new file mode 100644 (file)
index 0000000..9bf0aab
--- /dev/null
@@ -0,0 +1,13 @@
+--
+-- Change the index on user_name to a unique index to prevent
+-- duplicate registrations from creeping in.
+--
+-- Run maintenance/userDupes.php or through the updater first
+-- to clean up any prior duplicate accounts.
+--
+-- Added 2005-06-05
+--
+
+     ALTER TABLE /*$wgDBprefix*/user
+      DROP INDEX user_name,
+ADD UNIQUE INDEX user_name(user_name);
diff --git a/maintenance/archives/patch-user_rights.sql b/maintenance/archives/patch-user_rights.sql
new file mode 100644 (file)
index 0000000..36f0102
--- /dev/null
@@ -0,0 +1,21 @@
+-- Split user table into two parts:
+--   user
+--   user_rights
+-- The later contains only the permissions of the user. This way,
+-- you can store the accounts for several wikis in one central
+-- database but keep user rights local to the wiki.
+
+CREATE TABLE /*$wgDBprefix*/user_rights (
+  -- Key to user_id
+  ur_user int(5) unsigned NOT NULL,
+  
+  -- Comma-separated list of permission keys
+  ur_rights tinyblob NOT NULL default '',
+  
+  UNIQUE KEY ur_user (ur_user)
+
+) TYPE=InnoDB;
+
+INSERT INTO /*$wgDBprefix*/user_rights SELECT user_id,user_rights FROM /*$wgDBprefix*/user;
+
+ALTER TABLE /*$wgDBprefix*/user DROP COLUMN user_rights;
diff --git a/maintenance/archives/patch-user_token.sql b/maintenance/archives/patch-user_token.sql
new file mode 100644 (file)
index 0000000..797dc98
--- /dev/null
@@ -0,0 +1,15 @@
+-- user_token patch
+-- 2004-09-23
+
+ALTER TABLE /*$wgDBprefix*/user ADD user_token char(32) binary NOT NULL default '';
+
+UPDATE /*$wgDBprefix*/user SET user_token = concat(
+       substring(rand(),3,4),
+       substring(rand(),3,4),
+       substring(rand(),3,4),
+       substring(rand(),3,4),
+       substring(rand(),3,4),
+       substring(rand(),3,4),
+       substring(rand(),3,4),
+       substring(rand(),3,4)
+);
diff --git a/maintenance/archives/patch-userindex.sql b/maintenance/archives/patch-userindex.sql
new file mode 100644 (file)
index 0000000..c039b2f
--- /dev/null
@@ -0,0 +1 @@
+ ALTER TABLE /*$wgDBprefix*/user ADD INDEX ( `user_name` );
\ No newline at end of file
diff --git a/maintenance/archives/patch-userlevels-defaultgroups.sql b/maintenance/archives/patch-userlevels-defaultgroups.sql
new file mode 100644 (file)
index 0000000..065653d
--- /dev/null
@@ -0,0 +1,30 @@
+--
+-- Provide default groups
+-- Should probably be inserted when someone create a new database
+--
+
+INSERT INTO /*$wgDBprefix*/groups (gr_id,gr_name,gr_description,gr_rights)
+       VALUES (
+               1,':group-anon-name',':group-anon-desc',
+               'read,edit,createaccount'
+       );
+INSERT INTO /*$wgDBprefix*/groups (gr_id,gr_name,gr_description,gr_rights)
+       VALUES (
+               2,':group-loggedin-name',':group-loggedin-desc',
+               'read,edit,move,upload,validate,createaccount'
+       );
+INSERT INTO /*$wgDBprefix*/groups (gr_id,gr_name,gr_description,gr_rights)
+       VALUES (
+               3,':group-admin-name',':group-admin-desc',
+               'read,edit,move,upload,validate,createaccount,delete,undelete,protect,block,upload,asksql,rollback,patrol,editinterface,import'
+       );
+INSERT INTO /*$wgDBprefix*/groups (gr_id,gr_name,gr_description,gr_rights)
+       VALUES (
+               4,':group-bureaucrat-name',':group-bureaucrat-desc',
+               'read,edit,move,upload,validate,createaccount,delete,undelete,protect,block,upload,asksql,rollback,patrol,editinterface,import,makesysop'
+       );
+INSERT INTO /*$wgDBprefix*/groups (gr_id,gr_name,gr_description,gr_rights)
+       VALUES (
+               5,':group-steward-name',':group-steward-desc',
+               'read,edit,move,upload,validate,createaccount,delete,undelete,protect,block,upload,asksql,rollback,patrol,editinterface,import,makesysop,userrights,grouprights,siteadmin'
+       );
diff --git a/maintenance/archives/patch-userlevels-rights.sql b/maintenance/archives/patch-userlevels-rights.sql
new file mode 100644 (file)
index 0000000..7f1cabf
--- /dev/null
@@ -0,0 +1,5 @@
+-- Oct. 24 2004
+-- Adds the gr_rights field missing from early dev work
+
+-- Hold group name and description
+ALTER TABLE /*$wgDBprefix*/groups ADD gr_rights tinyblob;
diff --git a/maintenance/archives/patch-userlevels.sql b/maintenance/archives/patch-userlevels.sql
new file mode 100644 (file)
index 0000000..ab3a9a7
--- /dev/null
@@ -0,0 +1,22 @@
+-- Oct. 1st 2004 - Ashar Voultoiz
+-- Implement the new sitelevels
+--
+-- This is under development to provide a showcase in HEAD :o)
+
+-- Hold group name and description
+CREATE TABLE /*$wgDBprefix*/groups (
+  gr_id int(5) unsigned NOT NULL auto_increment,
+  gr_name varchar(50) NOT NULL default '',
+  gr_description varchar(255) NOT NULL default '',
+  gr_rights tinyblob,
+  PRIMARY KEY  (gr_id)
+
+) TYPE=InnoDB;
+
+-- Relation table between user and groups
+CREATE TABLE /*$wgDBprefix*/user_groups (
+       ug_user int(5) unsigned NOT NULL default '0',
+       ug_group int(5) unsigned NOT NULL default '0',
+       PRIMARY KEY  (ug_user,ug_group)
+
+) TYPE=InnoDB;
diff --git a/maintenance/archives/patch-usernewtalk.sql b/maintenance/archives/patch-usernewtalk.sql
new file mode 100644 (file)
index 0000000..fb8c865
--- /dev/null
@@ -0,0 +1,20 @@
+--- This table stores all the IDs of users whose talk
+--- page has been changed (the respective row is deleted
+--- when the user looks at the page).
+--- The respective column in the user table is no longer
+--- required and therefore dropped.
+
+CREATE TABLE /*$wgDBprefix*/user_newtalk (
+  user_id int(5) NOT NULL default '0',
+  user_ip varchar(40) NOT NULL default '',
+  KEY user_id (user_id),
+  KEY user_ip (user_ip)
+) TYPE=MyISAM;
+
+INSERT INTO
+  /*$wgDBprefix*/user_newtalk (user_id, user_ip)
+  SELECT user_id, ''
+    FROM user
+    WHERE user_newtalk != 0;
+
+ALTER TABLE /*$wgDBprefix*/user DROP COLUMN user_newtalk;
diff --git a/maintenance/archives/patch-usernewtalk2.sql b/maintenance/archives/patch-usernewtalk2.sql
new file mode 100644 (file)
index 0000000..477109b
--- /dev/null
@@ -0,0 +1,6 @@
+CREATE TABLE /*$wgDBprefix*/user_newtalk (
+ user_id int(5) NOT NULL default '0',
+ user_ip varchar(40) NOT NULL default '',
+ INDEX user_id (user_id),
+ INDEX user_ip (user_ip)
+);
diff --git a/maintenance/archives/patch-val_ip.sql b/maintenance/archives/patch-val_ip.sql
new file mode 100644 (file)
index 0000000..9214218
--- /dev/null
@@ -0,0 +1,4 @@
+-- Column added 2005-05-24
+
+ALTER TABLE /*$wgDBprefix*/validate
+  ADD COLUMN val_ip varchar(20) NOT NULL default '';
diff --git a/maintenance/archives/patch-validate.sql b/maintenance/archives/patch-validate.sql
new file mode 100644 (file)
index 0000000..3fa7e84
--- /dev/null
@@ -0,0 +1,13 @@
+-- For article validation
+
+DROP TABLE IF EXISTS /*$wgDBprefix*/validate;
+CREATE TABLE /*$wgDBprefix*/validate (
+  `val_user` int(11) NOT NULL default '0',
+  `val_page` int(11) unsigned NOT NULL default '0',
+  `val_revision` int(11) unsigned NOT NULL default '0',
+  `val_type` int(11) unsigned NOT NULL default '0',
+  `val_value` int(11) default '0',
+  `val_comment` varchar(255) NOT NULL default '',
+  `val_ip` varchar(20) NOT NULL default '',
+  KEY `val_user` (`val_user`,`val_revision`)
+) TYPE=InnoDB;
diff --git a/maintenance/archives/patch-watchlist.sql b/maintenance/archives/patch-watchlist.sql
new file mode 100644 (file)
index 0000000..adee010
--- /dev/null
@@ -0,0 +1,30 @@
+-- Convert watchlists to new new format ;)
+
+-- Ids just aren't convenient when what we want is to
+-- treat article and talk pages as equivalent.
+-- Better to use namespace (drop the 1 bit!) and title
+
+-- 2002-12-17 by Brion Vibber <brion@pobox.com>
+-- affects, affected by changes to SpecialWatchlist.php, User.php,
+-- Article.php, Title.php, SpecialRecentchanges.php
+
+DROP TABLE IF EXISTS watchlist2;
+CREATE TABLE watchlist2 (
+  wl_user int(5) unsigned NOT NULL,
+  wl_namespace tinyint(2) unsigned NOT NULL default '0',
+  wl_title varchar(255) binary NOT NULL default '',
+  UNIQUE KEY (wl_user, wl_namespace, wl_title)
+) TYPE=MyISAM PACK_KEYS=1;
+
+INSERT INTO watchlist2 (wl_user,wl_namespace,wl_title)
+  SELECT DISTINCT wl_user,(cur_namespace | 1) - 1,cur_title
+  FROM watchlist,cur WHERE wl_page=cur_id;
+
+ALTER TABLE watchlist RENAME TO oldwatchlist;
+ALTER TABLE watchlist2 RENAME TO watchlist;
+
+-- Check that the new one is correct, then:
+-- DROP TABLE oldwatchlist;
+
+-- Also should probably drop the ancient and now unused:
+ALTER TABLE user DROP COLUMN user_watch;
diff --git a/maintenance/archives/rebuildRecentchanges.inc b/maintenance/archives/rebuildRecentchanges.inc
new file mode 100644 (file)
index 0000000..54f6cb3
--- /dev/null
@@ -0,0 +1,122 @@
+<?php
+/**
+ * Rebuild recent changes table
+ *
+ * @deprecated
+ * @package MediaWiki
+ * @subpackage MaintenanceArchive
+ */
+
+/** */
+function rebuildRecentChangesTable()
+{
+       $sql = "DROP TABLE IF EXISTS recentchanges";
+       wfQuery( $sql );
+
+       $sql = "CREATE TABLE recentchanges (
+  rc_timestamp varchar(14) binary NOT NULL default '',
+  rc_cur_time varchar(14) binary NOT NULL default '',
+  rc_user int(10) unsigned NOT NULL default '0',
+  rc_user_text varchar(255) binary NOT NULL default '',
+  rc_namespace tinyint(3) unsigned NOT NULL default '0',
+  rc_title varchar(255) binary NOT NULL default '',
+  rc_comment varchar(255) binary NOT NULL default '',
+  rc_minor tinyint(3) unsigned NOT NULL default '0',
+  rc_new tinyint(3) unsigned NOT NULL default '0',
+  rc_cur_id int(10) unsigned NOT NULL default '0',
+  rc_this_oldid int(10) unsigned NOT NULL default '0',
+  rc_last_oldid int(10) unsigned NOT NULL default '0',
+  INDEX rc_cur_id (rc_cur_id),
+  INDEX rc_cur_time (rc_cur_time),
+  INDEX rc_timestamp (rc_timestamp),
+  INDEX rc_namespace (rc_namespace),
+  INDEX rc_title (rc_title)
+) TYPE=MyISAM PACK_KEYS=1;";
+       wfQuery( $sql );
+
+       print( "Loading from CUR table...\n" );
+
+       $sql = "INSERT INTO recentchanges (rc_timestamp,rc_cur_time,rc_user," .
+         "rc_user_text,rc_namespace,rc_title,rc_comment,rc_minor,rc_new," .
+         "rc_cur_id,rc_this_oldid,rc_last_oldid) SELECT cur_timestamp," .
+         "cur_timestamp,cur_user,cur_user_text,cur_namespace,cur_title," .
+         "cur_comment,cur_minor_edit,cur_is_new,cur_id,0,0 FROM cur " .
+         "ORDER BY cur_timestamp DESC LIMIT 5000";
+       wfQuery( $sql );
+
+       print( "Loading from OLD table...\n" );
+
+       $sql = "INSERT INTO recentchanges (rc_timestamp,rc_cur_time,rc_user," .
+      "rc_user_text,rc_namespace,rc_title,rc_comment,rc_minor,rc_new," .
+      "rc_cur_id,rc_this_oldid,rc_last_oldid) SELECT old_timestamp,''," .
+         "old_user,old_user_text,old_namespace,old_title,old_comment," .
+         "old_minor_edit,0,0,old_id,0 FROM old ORDER BY old_timestamp " .
+         "DESC LIMIT 5000";
+       wfQuery( $sql );
+
+       $sql = "SELECT rc_timestamp FROM recentchanges " .
+         "ORDER BY rc_timestamp DESC LIMIT 5000,1";
+       $res = wfQuery( $sql );
+       $obj = wfFetchObject( $res );
+       $ts = $obj->rc_timestamp;
+
+       $sql = "DELETE FROM recentchanges WHERE rc_timestamp < '{$ts}'";
+       wfQuery( $sql );
+
+       rebuildRecentChangesTablePass2();
+}
+
+function rebuildRecentChangesTablePass2()
+{
+       $ns = $id = $count = 0;
+       $title = $ct =  "";
+
+       print( "Updating links...\n" );
+
+       $sql = "SELECT rc_namespace,rc_title,rc_timestamp FROM recentchanges " .
+         "ORDER BY rc_namespace,rc_title,rc_timestamp DESC";
+       $res = wfQuery( $sql );
+
+       while ( $obj = wfFetchObject( $res ) ) {
+               if ( ! ( $ns == $obj->rc_namespace &&
+                          0 == strcmp( $title, wfStrencode( $obj->rc_title ) ) ) ) {
+
+                       $ns = $obj->rc_namespace;
+                       $title = wfStrencode( $obj->rc_title );
+
+                       $sql = "SELECT cur_id,cur_timestamp FROM cur WHERE " .
+                         "cur_namespace={$ns} AND cur_title='{$title}'";
+                       $res2 = wfQuery( $sql );
+                       $obj2 = wfFetchObject( $res2 );
+
+                       $id = $obj2->cur_id;
+                       $ct = $obj2->cur_timestamp;
+               }
+               $sql = "SELECT old_id FROM old WHERE old_namespace={$ns} " .
+                 "AND old_title='{$title}' AND old_timestamp < '" .
+                 "{$obj->rc_timestamp}' ORDER BY old_timestamp DESC LIMIT 1";
+               $res2 = wfQuery( $sql );
+
+               if ( 0 != wfNumRows( $res2 ) ) {
+                       $obj2 = wfFetchObject( $res2 );
+
+                       $sql = "UPDATE recentchanges SET rc_cur_id={$id},rc_cur_time=" .
+                         "'{$ct}',rc_last_oldid={$obj2->old_id} WHERE " .
+                         "rc_namespace={$ns} AND rc_title='{$title}' AND " .
+                         "rc_timestamp='{$obj->rc_timestamp}'";
+                       wfQuery( $sql );
+               } else {
+                       $sql = "UPDATE recentchanges SET rc_cur_id={$id},rc_cur_time=" .
+                         "'{$ct}' WHERE rc_namespace={$ns} AND rc_title='{$title}' " .
+                         "AND rc_timestamp='{$obj->rc_timestamp}'";
+                       wfQuery( $sql );
+               }
+
+               if ( 0 == ( ++$count % 500 ) ) {
+                       printf( "%d records processed.\n", $count );
+               }
+       }
+}
+
+
+?>
diff --git a/maintenance/archives/upgradeWatchlist.php b/maintenance/archives/upgradeWatchlist.php
new file mode 100644 (file)
index 0000000..b4605a5
--- /dev/null
@@ -0,0 +1,67 @@
+<?php
+/**
+ * @deprecated
+ * @package MediaWiki
+ * @subpackage MaintenanceArchive
+ */
+
+/** */
+print "This script is obsolete!";
+print "It is retained in the source here in case some of its
+code might be useful for ad-hoc conversion tasks, but it is
+not maintained and probably won't even work as is.";
+exit();
+
+# Convert watchlists to new format
+
+global $IP;
+require_once( "../LocalSettings.php" );
+require_once( "$IP/Setup.php" );
+
+$wgTitle = Title::newFromText( "Rebuild links script" );
+set_time_limit(0);
+
+$wgDBuser                      = "wikiadmin";
+$wgDBpassword          = $wgDBadminpassword;
+
+$sql = "DROP TABLE IF EXISTS watchlist";
+wfQuery( $sql, DB_MASTER );
+$sql = "CREATE TABLE watchlist (
+  wl_user int(5) unsigned NOT NULL,
+  wl_page int(8) unsigned NOT NULL,
+  UNIQUE KEY (wl_user, wl_page)
+) TYPE=MyISAM PACK_KEYS=1";
+wfQuery( $sql, DB_MASTER );
+
+$lc = new LinkCache;
+
+# Now, convert!
+$sql = "SELECT user_id,user_watch FROM user";
+$res = wfQuery( $sql, DB_SLAVE );
+$nu = wfNumRows( $res );
+$sql = "INSERT into watchlist (wl_user,wl_page) VALUES ";
+$i = $n = 0;
+while( $row = wfFetchObject( $res ) ) {
+       $list = explode( "\n", $row->user_watch );
+       $bits = array();
+       foreach( $list as $title ) {
+               if( $id = $lc->addLink( $title ) and ! $bits[$id]++) {
+                       $sql .= ($i++ ? "," : "") . "({$row->user_id},{$id})";
+               }
+       }
+       if( ($n++ % 100) == 0 ) echo "$n of $nu users done...\n";
+}
+echo "$n users done.\n";
+if( $i ) {
+       wfQuery( $sql, DB_MASTER );
+}
+
+
+# Add index
+# is this necessary?
+$sql = "ALTER TABLE watchlist
+  ADD INDEX wl_user (wl_user),
+  ADD INDEX wl_page (wl_page)";
+#wfQuery( $sql, DB_MASTER );
+
+?>
diff --git a/maintenance/attribute.php b/maintenance/attribute.php
new file mode 100644 (file)
index 0000000..d8acd0c
--- /dev/null
@@ -0,0 +1,105 @@
+<?php
+/**
+ * Script for re-attributing edits
+ *
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+/** */
+require_once( "commandLine.inc" );
+
+# Parameters
+if ( count( $args ) < 2 ) {
+       print "Not enough parameters\n";
+       if ( $wgWikiFarm ) {
+               print "Usage: php attribute.php <language> <site> <source> <destination>\n";
+       } else {
+               print "Usage: php attribute.php <source> <destination>\n";
+       }
+       exit;
+}
+
+$source = $args[0];
+$dest = $args[1];
+
+$dbr =& wfGetDB( DB_SLAVE );
+extract( $dbr->tableNames( 'page', 'revision','user' ));
+$eSource = $dbr->strencode( $source );
+$eDest = $dbr->strencode( $dest );
+
+# Get user id
+$res = $dbr->query( "SELECT user_id FROM $user WHERE user_name='$eDest'" );
+$row = $dbr->fetchObject( $res );
+if ( !$row ) {
+       print "Warning: the target name \"$dest\" does not exist";
+       $uid = 0;
+} else {
+       $uid = $row->user_id;
+}
+
+# Initialise files
+$logfile = fopen( "attribute.log", "a" );
+$sqlfile = fopen( "attribute.sql", "a" );
+
+fwrite( $logfile, "* $source &rarr; $dest\n" );
+
+fwrite( $sqlfile, 
+"-- Changing attribution SQL file
+-- Generated with attribute.php
+-- $source -> $dest ($uid)
+");
+
+$omitTitle = "Wikipedia:Changing_attribution_for_an_edit";
+
+# Get revisions
+print "\nPage revisions\n\n";
+
+$res = $dbr->query( "SELECT page_namespace, page_title, rev_id, rev_timestamp
+FROM $revision,$page
+WHERE rev_user_text='$eSource' and rev_page=page_id" );
+$row = $dbr->fetchObject( $res );
+
+if ( $row ) {
+/*
+       if ( $row->old_title=='Votes_for_deletion' && $row->old_namespace == 4 ) {
+               # We don't have that long
+               break;
+       }
+*/
+       fwrite( $logfile, "**Revision IDs: " );
+       fwrite( $sqlfile, "UPDATE $revision SET rev_user=$uid, rev_user_text='$eDest' WHERE rev_id IN (\n" );
+       
+       for ( $first=true; $row; $row = $dbr->fetchObject( $res ) ) {
+               $title = Title::makeTitle( $row->page_namespace, $row->page_title );
+               $fullTitle = $title->getPrefixedDbKey();
+               if ( $fullTitle == $omitTitle ) {
+                       continue;
+               }
+
+               print "$fullTitle\n";
+               $url = $title->getFullUrl( "oldid={$row->rev_id}" );
+               
+               # Output
+               fwrite( $sqlfile, "      " );
+               if ( $first ) {
+                       $first = false;
+               } else {
+                       fwrite( $sqlfile, ", " );
+                       fwrite( $logfile, ", " );
+               }
+
+               fwrite( $sqlfile, "{$row->rev_id} -- $url\n" );
+               fwrite( $logfile, "[$url {$row->rev_id}]" );
+
+       }
+       fwrite( $sqlfile, ");\n" );
+       fwrite( $logfile, "\n" );
+}
+
+print "\n";
+
+fclose( $sqlfile );
+fclose( $logfile );
+
+?>
diff --git a/maintenance/benchmarkPurge.php b/maintenance/benchmarkPurge.php
new file mode 100644 (file)
index 0000000..9f45433
--- /dev/null
@@ -0,0 +1,65 @@
+<?php
+/**
+ * Squid purge benchmark script
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+/** */
+require_once( "commandLine.inc" );
+
+/** @todo document */
+function benchSquid( $urls, $trials = 1 ) {
+       $start = wfTime();
+       for( $i = 0; $i < $trials; $i++) {
+               SquidUpdate::purge( $urls );
+       }
+       $delta = wfTime() - $start;
+       $pertrial = $delta / $trials;
+       $pertitle = $pertrial / count( $urls );
+       return sprintf( "%4d titles in %6.2fms (%6.2fms each)",
+               count( $urls ), $pertrial * 1000.0, $pertitle * 1000.0 );
+}
+
+/** @todo document */
+function randomUrlList( $length ) {
+       $list = array();
+       for( $i = 0; $i < $length; $i++ ) {
+               $list[] = randomUrl();
+       }
+       return $list;
+}
+
+/** @todo document */
+function randomUrl() {
+       global $wgServer, $wgArticlePath;
+       return $wgServer . str_replace( '$1', randomTitle(), $wgArticlePath );
+}
+
+/** @todo document */
+function randomTitle() {
+       $str = '';
+       $length = mt_rand( 1, 20 );
+       for( $i = 0; $i < $length; $i++ ) {
+               $str .= chr( mt_rand( ord('a'), ord('z') ) );
+       }
+       return ucfirst( $str );
+}
+
+if( !$wgUseSquid ) {
+       die( "Squid purge benchmark doesn't do much without squid support on.\n" );
+} else {
+       printf( "There are %d defined squid servers:\n", count( $wgSquidServers ) );
+       #echo implode( "\n", $wgSquidServers ) . "\n";
+       if( isset( $options['count'] ) ) {
+               $lengths = array( IntVal( $options['count'] ) );
+       } else {
+               $lengths = array( 1, 10, 100 );
+       }
+       foreach( $lengths as $length ) {
+               $urls = randomUrlList( $length );
+               $trial = benchSquid( $urls );
+               print "$trial\n";
+       }
+}
+?>
\ No newline at end of file
diff --git a/maintenance/build-intl-wiki.sql b/maintenance/build-intl-wiki.sql
new file mode 100644 (file)
index 0000000..f094c8b
--- /dev/null
@@ -0,0 +1,31 @@
+-- Experimental: create shared international database
+-- for new interlinking code.
+--
+
+CREATE DATABASE intl;
+
+GRANT DELETE,INSERT,SELECT,UPDATE ON intl.*
+TO wikiuser@'%' IDENTIFIED BY 'userpass';
+GRANT DELETE,INSERT,SELECT,UPDATE ON intl.*
+TO wikiuser@localhost IDENTIFIED BY 'userpass';
+GRANT DELETE,INSERT,SELECT,UPDATE ON intl.*
+TO wikiuser@localhost.localdomain IDENTIFIED BY 'userpass';
+
+USE intl;
+
+CREATE TABLE ilinks (
+ lang_from varchar(5) default NULL,
+ lang_to varchar(5) default NULL,
+ title_from tinyblob,
+ title_to tinyblob,
+ target_exists tinyint(1) default NULL
+) TYPE=MyISAM;
+
+CREATE TABLE recentchanges (
+ user_name tinyblob,
+ user_lang varchar(5) default NULL,
+ date timestamp(14) NOT NULL,
+ message tinyblob
+) TYPE=MyISAM;
+
+
diff --git a/maintenance/changeuser.sql b/maintenance/changeuser.sql
new file mode 100644 (file)
index 0000000..ad1c6da
--- /dev/null
@@ -0,0 +1,12 @@
+set @oldname = 'At18'; 
+set @newname = 'Alfio';
+
+update low_priority /*$wgDBprefix*/user set user_name=@newname where user_name=@oldname;
+update low_priority /*$wgDBprefix*/user_newtalk set user_ip=@newname where user_ip=@oldname;
+update low_priority /*$wgDBprefix*/cur set cur_user_text=@newname where cur_user_text=@oldname;
+update low_priority /*$wgDBprefix*/old set old_user_text=@newname where old_user_text=@oldname;
+update low_priority /*$wgDBprefix*/archive set ar_user_text=@newname where ar_user_text=@oldname;
+update low_priority /*$wgDBprefix*/ipblocks set ipb_address=@newname where ipb_address=@oldname;
+update low_priority /*$wgDBprefix*/oldimage set oi_user_text=@newname where oi_user_text=@oldname;
+update low_priority /*$wgDBprefix*/recentchanges set rc_user_text=@newname where rc_user_text=@oldname;
+
diff --git a/maintenance/checktrans.php b/maintenance/checktrans.php
new file mode 100644 (file)
index 0000000..ebab4c7
--- /dev/null
@@ -0,0 +1,30 @@
+<?php
+/**
+ * @package MediaWiki
+ * @subpackage Maintenance
+ * Check to see if all messages have been translated into the selected language.
+ * To run this script, you must have a working installation, and it checks the
+ * selected language of that installation.
+ */
+
+/** */
+require_once('commandLine.inc');
+
+if ( 'en' == $wgLanguageCode ) {
+       print "Current selected language is English. Cannot check translations.\n";
+       exit();
+}
+
+$count = $total = 0;
+$msgarray = 'wgAllMessages' . ucfirst( $wgLanguageCode );
+
+foreach ( $wgAllMessagesEn as $code => $msg ) {
+       ++$total;
+       if ( ! array_key_exists( $code, $$msgarray ) ) {
+               print "'{$code}' => \"$msg\",\n";
+               ++$count;
+       }
+}
+
+print "{$count} messages of {$total} not translated.\n";
+?>
diff --git a/maintenance/cleanupCaps.php b/maintenance/cleanupCaps.php
new file mode 100644 (file)
index 0000000..7d59c8b
--- /dev/null
@@ -0,0 +1,156 @@
+<?php
+/*
+ * Script to clean up broken page links when somebody turns on $wgCapitalLinks.
+ *
+ * Usage: php cleanupCaps.php [--dry-run]
+ * Options:
+ *   --dry-run  don't actually try moving them
+ * 
+ * Copyright (C) 2005 Brion Vibber <brion@pobox.com>
+ * http://www.mediawiki.org/
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or 
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @author Brion Vibber <brion at pobox.com>
+ * @package MediaWiki
+ * @subpackage maintenance
+ */
+
+$options = array( 'dry-run' );
+
+require_once( 'commandLine.inc' );
+require_once( 'FiveUpgrade.inc' );
+
+class CapsCleanup extends FiveUpgrade {
+       function CapsCleanup( $dryrun = false ) {
+               parent::FiveUpgrade();
+               
+               $this->maxLag = 10; # if slaves are lagged more than 10 secs, wait
+               $this->dryrun = $dryrun;
+       }
+       
+       function cleanup() {
+               global $wgCapitalLinks;
+               if( $wgCapitalLinks ) {
+                       echo "\$wgCapitalLinks is on -- no need for caps links cleanup.\n";
+                       return false;
+               }
+               
+               $this->runTable( 'page', 'WHERE page_namespace=0',
+                       array( &$this, 'processPage' ) );
+       }
+       
+       function init( $count, $table ) {
+               $this->processed = 0;
+               $this->updated = 0;
+               $this->count = $count;
+               $this->startTime = wfTime();
+               $this->table = $table;
+       }
+       
+       function progress( $updated ) {
+               $this->updated += $updated;
+               $this->processed++;
+               if( $this->processed % 100 != 0 ) {
+                       return;
+               }
+               $portion = $this->processed / $this->count;
+               $updateRate = $this->updated / $this->processed;
+               
+               $now = wfTime();
+               $delta = $now - $this->startTime;
+               $estimatedTotalTime = $delta / $portion;
+               $eta = $this->startTime + $estimatedTotalTime;
+               
+               printf( "%s: %6.2f%% done on %s; ETA %s [%d/%d] %.2f/sec <%.2f%% updated>\n",
+                       wfTimestamp( TS_DB, intval( $now ) ),
+                       $portion * 100.0,
+                       $this->table,
+                       wfTimestamp( TS_DB, intval( $eta ) ),
+                       $this->processed,
+                       $this->count,
+                       $this->processed / $delta,
+                       $updateRate * 100.0 );
+               flush();
+       }
+       
+       function runTable( $table, $where, $callback ) {
+               $fname = 'CapsCleanup::buildTable';
+               
+               $count = $this->dbw->selectField( $table, 'count(*)', '', $fname );
+               $this->init( $count, 'page' );
+               $this->log( "Processing $table..." );
+               
+               $tableName = $this->dbr->tableName( $table );
+               $sql = "SELECT * FROM $tableName $where";
+               $result = $this->dbr->query( $sql, $fname );
+               
+               while( $row = $this->dbr->fetchObject( $result ) ) {
+                       $updated = call_user_func( $callback, $row );
+               }
+               $this->log( "Finished $table... $this->updated of $this->processed rows updated" );
+               $this->dbr->freeResult( $result );
+       }
+       
+       function processPage( $row ) {
+               global $wgContLang;
+               
+               $current = Title::makeTitle( $row->page_namespace, $row->page_title );
+               $display = $current->getPrefixedText();
+               $upper = $row->page_title;
+               $lower = $wgContLang->lcfirst( $row->page_title );
+               if( $upper == $lower ) {
+                       $this->log( "\"$display\" already lowercase." );
+                       return $this->progress( 0 );
+               }
+               
+               $target = Title::makeTitle( $row->page_namespace, $lower );
+               $targetDisplay = $target->getPrefixedText();
+               if( $target->exists() ) {
+                       $this->log( "\"$display\" skipped; \"$targetDisplay\" already exists" );
+                       return $this->progress( 0 );
+               }
+               
+               if( $this->dryrun ) {
+                       $this->log( "\"$display\" -> \"$targetDisplay\": DRY RUN, NOT MOVED" );
+                       $ok = true;
+               } else {
+                       $ok = $current->moveTo( $target, false, 'Converting page titles to lowercase' );
+                       $this->log( "\"$display\" -> \"$targetDisplay\": $ok" );
+               }
+               if( $ok === true ) {
+                       $this->progress( 1 );
+                       
+                       if( $row->page_namespace == NS_MAIN ) {
+                               $talk = Title::makeTitle( NS_TALK, $row->page_title );
+                               $xrow = $row;
+                               $row->page_namespace = NS_TALK;
+                               if( $talk->exists() ) {
+                                       return $this->processPage( $row );
+                               }
+                       }
+               } else {
+                       $this->progress( 0 );
+               }
+       }
+
+}
+
+$wgUser->setName( 'Conversion script' );
+$caps = new CapsCleanup( isset( $options['dry-run'] ) );
+$caps->cleanup();
+
+?>
diff --git a/maintenance/cleanupDupes.inc b/maintenance/cleanupDupes.inc
new file mode 100644 (file)
index 0000000..12c296f
--- /dev/null
@@ -0,0 +1,131 @@
+<?php
+# Copyright (C) 2004 Brion Vibber <brion@pobox.com>
+# http://www.mediawiki.org/
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or 
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# http://www.gnu.org/copyleft/gpl.html
+
+/**
+ * If on the old non-unique indexes, check the cur table for duplicate
+ * entries and remove them...
+ *
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+function fixDupes( $fixthem = false) {
+       $dbw =& wfGetDB( DB_MASTER );
+       $cur = $dbw->tableName( 'cur' );
+       $old = $dbw->tableName( 'old' );
+       $dbw->query( "LOCK TABLES $cur WRITE, $old WRITE" );
+       echo "Checking for duplicate cur table entries... (this may take a while on a large wiki)\n";
+       $res = $dbw->query( <<<END
+SELECT cur_namespace,cur_title,count(*) as c,min(cur_id) as id
+  FROM $cur
+ GROUP BY cur_namespace,cur_title
+HAVING c > 1
+END
+       );
+       $n = $dbw->numRows( $res );
+       echo "Found $n titles with duplicate entries.\n";
+       if( $n > 0 ) {
+               if( $fixthem ) {
+                       echo "Correcting...\n";
+               } else {
+                       echo "Just a demo...\n";
+               }
+               while( $row = $dbw->fetchObject( $res ) ) {
+                       $ns = IntVal( $row->cur_namespace );
+                       $title = $dbw->addQuotes( $row->cur_title );
+                       
+                       # Get the first responding ID; that'll be the one we keep.
+                       $id = $dbw->selectField( 'cur', 'cur_id', array(
+                               'cur_namespace' => $row->cur_namespace,
+                               'cur_title'     => $row->cur_title ) );
+                       
+                       echo "$ns:$row->cur_title (canonical ID $id)\n";
+                       if( $id != $row->id ) {
+                               echo "  ** minimum ID $row->id; ";
+                               $timeMin = $dbw->selectField( 'cur', 'cur_timestamp', array(
+                                       'cur_id' => $row->id ) );
+                               $timeFirst = $dbw->selectField( 'cur', 'cur_timestamp', array(
+                                       'cur_id' => $id ) );
+                               if( $timeMin == $timeFirst ) {
+                                       echo "timestamps match at $timeFirst; ok\n";
+                               } else {
+                                       echo "timestamps don't match! min: $timeMin, first: $timeFirst; ";
+                                       if( $timeMin > $timeFirst ) {
+                                               $id = $row->id;
+                                               echo "keeping minimum: $id\n";
+                                       } else {
+                                               echo "keeping first: $id\n";
+                                       }
+                               }
+                       }
+                       
+                       if( $fixthem ) {
+                               $dbw->query( <<<END
+INSERT
+  INTO $old
+      (old_namespace, old_title,      old_text,
+       old_comment,   old_user,       old_user_text,
+       old_timestamp, old_minor_edit, old_flags,
+       inverse_timestamp)
+SELECT cur_namespace, cur_title,      cur_text,
+       cur_comment,   cur_user,       cur_user_text,
+       cur_timestamp, cur_minor_edit, '',
+       inverse_timestamp
+  FROM $cur
+ WHERE cur_namespace=$ns
+   AND cur_title=$title
+   AND cur_id != $id
+END
+                               );
+                               $dbw->query( <<<END
+DELETE
+  FROM $cur
+ WHERE cur_namespace=$ns
+   AND cur_title=$title
+   AND cur_id != $id
+END
+                               );
+                       }
+               }
+       }
+       $dbw->query( 'UNLOCK TABLES' );
+       if( $fixthem ) {
+               echo "Done.\n";
+       } else {
+               echo "Run again with --fix option to delete the duplicates.\n";
+       }
+}
+
+function checkDupes( $fixthem = false, $indexonly = false ) {
+       global $wgDBname;
+       $dbw =& wfGetDB( DB_MASTER );
+       if( $dbw->indexExists( 'cur', 'name_title' ) &&
+           $dbw->indexUnique( 'cur', 'name_title' ) ) {
+               echo "$wgDBname: cur table has the current unique index; no duplicate entries.\n";
+       } elseif( $dbw->indexExists( 'cur', 'name_title_dup_prevention' ) ) {
+               echo "$wgDBname: cur table has a temporary name_title_dup_prevention unique index; no duplicate entries.\n";
+       } else {
+               echo "$wgDBname: cur table has the old non-unique index and may have duplicate entries.\n";
+               if( !$indexonly ) {
+                       fixDupes( $fixthem );
+               }
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/maintenance/cleanupDupes.php b/maintenance/cleanupDupes.php
new file mode 100644 (file)
index 0000000..85c5d1b
--- /dev/null
@@ -0,0 +1,37 @@
+<?php
+# Copyright (C) 2004 Brion Vibber <brion@pobox.com>
+# http://www.mediawiki.org/
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or 
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# http://www.gnu.org/copyleft/gpl.html
+
+/**
+ * If on the old non-unique indexes, check the cur table for duplicate
+ * entries and remove them...
+ *
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+$options = array( 'fix', 'index' );
+
+/** */
+require_once( 'commandLine.inc' );
+require_once( 'cleanupDupes.inc' );
+$wgTitle = Title::newFromText( 'Dupe cur entry cleanup script' );
+
+checkDupes( isset( $options['fix'] ), isset( $options['index'] ) );
+
+?>
diff --git a/maintenance/clear_interwiki_cache.php b/maintenance/clear_interwiki_cache.php
new file mode 100644 (file)
index 0000000..ca26d73
--- /dev/null
@@ -0,0 +1,19 @@
+<?php
+/**
+ * This script is used to clear the interwiki links for ALL languages in
+ * memcached.
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+/** */
+require_once('commandLine.inc');
+
+foreach ( $wgLocalDatabases as $db ) {
+       print "$db ";
+       foreach ( $wgLanguageNamesEn as $prefix => $name ) {
+               $wgMemc->delete("$db:interwiki:$prefix");
+       }
+}
+print "\n";
+?>
\ No newline at end of file
diff --git a/maintenance/clear_stats.php b/maintenance/clear_stats.php
new file mode 100644 (file)
index 0000000..278c609
--- /dev/null
@@ -0,0 +1,25 @@
+<?php
+require_once('commandLine.inc');
+
+foreach ( $wgLocalDatabases as $db ) {
+       noisyDelete("$db:stats:pcache_hit");
+       noisyDelete("$db:stats:pcache_miss_invalid");
+       noisyDelete("$db:stats:pcache_miss_expired");
+       noisyDelete("$db:stats:pcache_miss_absent");
+       noisyDelete("$db:stats:image_cache_hit");
+       noisyDelete("$db:stats:image_cache_miss");
+       noisyDelete("$db:stats:image_cache_update");
+}
+
+function noisyDelete( $key ) {
+       global $wgMemc;
+       /*
+       print "$key ";
+       if ( $wgMemc->delete($key) ) {
+               print "deleted\n";
+       } else {
+               print "FAILED\n";
+       }*/
+       $wgMemc->delete($key);
+}
+?>
diff --git a/maintenance/commandLine.inc b/maintenance/commandLine.inc
new file mode 100644 (file)
index 0000000..8c737be
--- /dev/null
@@ -0,0 +1,202 @@
+<?php
+/**
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+/** */
+# Abort if called from a web server
+if ( isset( $_SERVER ) && array_key_exists( 'REQUEST_METHOD', $_SERVER ) ) {
+       print "This script must be run from the command line\n";
+       exit();
+}
+
+define("MEDIAWIKI",true);
+
+# Process command line arguments
+# $options becomes an array with keys set to the option names
+# $optionsWithArgs is an array of GNU-style options that take an argument. The arguments are returned
+# in the values of $options.
+# $args becomes a zero-based array containing the non-option arguments
+
+if ( !isset( $optionsWithArgs ) ) {
+       $optionsWithArgs = array();
+}
+$optionsWithArgs[] = 'conf'; # For specifying the location of LocalSettings.php
+
+$self = array_shift( $argv );
+$self = __FILE__;
+$IP = realpath( dirname( $self ) . "/.." );
+chdir( $IP );
+
+$options = array();
+$args = array();
+
+for( $arg = reset( $argv ); $arg !== false; $arg = next( $argv ) ) {
+       if ( substr( $arg, 0, 2 ) == '--' ) {
+               # Long options
+               $option = substr( $arg, 2 );
+               if ( in_array( $option, $optionsWithArgs ) ) {
+                       $param = next( $argv );
+                       if ( $param === false ) {
+                               die( "$arg needs an value after it\n" );
+                       }
+                       $options[$option] = $param;
+               } else {
+                       $bits = explode( '=', $option, 2 );
+                       if( count( $bits ) > 1 ) {
+                               $option = $bits[0];
+                               $param = $bits[1];
+                       } else {
+                               $param = 1;
+                       }
+                       $options[$option] = $param;
+               }
+       } elseif ( $arg{0} == '-' ) {
+               # Short options
+               for ( $p=1; $p<strlen( $arg ); $p++ ) {
+                       $option = $arg{$p};
+                       if ( in_array( $option, $optionsWithArgs ) ) {
+                               $param = next( $argv );
+                               if ( $param === false ) {
+                                       die( "$arg needs an value after it\n" );
+                               }
+                               $options[$option] = $param;
+                       } else {
+                               $options[$option] = 1;
+                       }
+               }
+       } else {
+               $args[] = $arg;
+       }
+}
+
+# General initialisation
+
+$wgCommandLineMode = true;
+# Turn off output buffering if it's on
+@ob_end_flush();
+$sep = strchr( $include_path = ini_get( "include_path" ), ";" ) ? ";" : ":";
+
+if (!isset( $wgUseNormalUser ) ) {
+       $wgUseNormalUser = false;
+}
+
+if ( file_exists( '/home/wikipedia/common/langlist' ) ) {
+       $wgWikiFarm = true;
+       require_once( "$IP/includes/SiteConfiguration.php" );
+
+       # Get $conf
+       require( "$IP/InitialiseSettings.php" );
+
+       if ( empty( $wgNoDBParam ) ) {
+               # Check if we were passed a db name
+               $db = array_shift( $args );
+               list( $site, $lang ) = $wgConf->siteFromDB( $db );
+
+               # If not, work out the language and site the old way
+               if ( is_null( $site ) || is_null( $lang ) ) {
+                       if ( !$db ) {   
+                               $lang = "aa";
+                       } else {
+                               $lang = $db;
+                       }
+                       if ( isset( $args[0] ) ) {
+                               $site = array_shift( $args );
+                       } else {
+                               $site = "wikipedia";
+                       }
+               }
+       } else {
+               $lang = "aa";
+               $site = "wikipedia";
+       }
+
+       # This is for the IRC scripts, which now run as the apache user
+       # The apache user doesn't have access to the wikiadmin_pass command
+       if ( $_ENV['USER'] == "apache" ) {
+               $wgUseNormalUser = true;
+       }
+
+       putenv( "wikilang=$lang");
+
+       $DP = $IP;
+       ini_set( "include_path", ".:$IP:$IP/includes:$IP/languages:$IP/maintenance" );
+
+       require_once( "$IP/includes/Defines.php" );
+       require_once( "$IP/CommonSettings.php" );
+
+       if ( !$wgUseNormalUser ) {
+               $wgDBuser = $wgDBadminuser = "wikiadmin";
+               $wgDBpassword = $wgDBadminpassword = trim(`wikiadmin_pass`);
+       }
+} else {
+       $wgWikiFarm = false;
+       if ( isset( $options['conf'] ) ) {
+               $settingsFile = $options['conf'];
+       } else {
+               $settingsFile = "$IP/LocalSettings.php";
+       }
+
+       if ( ! is_readable( $settingsFile ) ) {
+               print "A copy of your installation's LocalSettings.php\n" .
+                 "must exist in the source directory.\n";
+               exit();
+       }
+       $wgCommandLineMode = true;
+       $DP = $IP;
+       require_once( "$IP/includes/Defines.php" );
+       require_once( $settingsFile );
+       ini_set( "include_path", ".$sep$IP$sep$IP/includes$sep$IP/languages$sep$IP/maintenance" );
+       
+       if ( is_readable( "$IP/AdminSettings.php" ) ) {
+               require_once( "$IP/AdminSettings.php" );
+       }
+}
+
+# Turn off output buffering again, it might have been turned on in the settings files
+@ob_end_flush();
+# Same with these
+$wgCommandLineMode = true;
+
+if ( empty( $wgUseNormalUser ) && isset( $wgDBadminuser ) && $wgDBservers ) {
+       $wgDBuser = $wgDBadminuser;
+       $wgDBpassword = $wgDBadminpassword;
+
+       foreach ( $wgDBservers as $i => $server ) {
+               $wgDBservers[$i]['user'] = $wgDBuser;
+               $wgDBservers[$i]['password'] = $wgDBpassword;
+       }
+}
+
+ini_set( 'memory_limit', -1 );
+
+require_once( "Setup.php" );
+require_once( "install-utils.inc" );
+$wgTitle = Title::newFromText( "Command line script" );
+set_time_limit(0);
+
+// --------------------------------------------------------------------
+// Functions
+// --------------------------------------------------------------------
+
+function wfWaitForSlaves( $maxLag ) {
+       global $wgLoadBalancer;
+       if ( $maxLag ) {
+               list( $host, $lag ) = $wgLoadBalancer->getMaxLag();
+               while ( $lag > $maxLag ) {
+                       $name = @gethostbyaddr( $host );
+                       if ( $name !== false ) {
+                               $host = $name;
+                       }
+                       print "Waiting for $host (lagged $lag seconds)...\n";
+                       sleep($maxLag);
+                       list( $host, $lag ) = $wgLoadBalancer->getMaxLag();
+               }
+       }
+}
+
+
+
+?>
diff --git a/maintenance/convertLinks.inc b/maintenance/convertLinks.inc
new file mode 100644 (file)
index 0000000..fe523da
--- /dev/null
@@ -0,0 +1,219 @@
+<?php
+/**
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+/** */
+function convertLinks() {
+       global $wgDBtype;
+       if( $wgDBtype == 'PostgreSQL' ) {
+               print "Links table already ok on PostgreSQL.\n";
+               return;
+       }
+       
+       print "Converting links table to ID-ID...\n";
+       
+       global $wgLang, $wgDBserver, $wgDBadminuser, $wgDBadminpassword, $wgDBname;
+       global $noKeys, $logPerformance, $fh;
+       
+       $numRows = $tuplesAdded = $numBadLinks = $curRowsRead = 0; #counters etc
+       $totalTuplesInserted = 0; # total tuples INSERTed into links_temp
+
+       $reportCurReadProgress = true; #whether or not to give progress reports while reading IDs from cur table
+       $curReadReportInterval = 1000; #number of rows between progress reports
+
+       $reportLinksConvProgress = true; #whether or not to give progress reports during conversion
+       $linksConvInsertInterval = 1000; #number of rows per INSERT
+
+       $initialRowOffset = 0;
+       #$finalRowOffset = 0; # not used yet; highest row number from links table to process
+
+       # Overwrite the old links table with the new one.  If this is set to false,
+       # the new table will be left at links_temp.
+       $overwriteLinksTable = true;
+
+       # Don't create keys, and so allow duplicates in the new links table.
+       # This gives a huge speed improvement for very large links tables which are MyISAM. (What about InnoDB?)
+       $noKeys = false;
+
+
+       $logPerformance = false; # output performance data to a file
+       $perfLogFilename = "convLinksPerf.txt";
+       #--------------------------------------------------------------------
+       
+       $dbw =& wfGetDB( DB_MASTER );
+       extract( $dbw->tableNames( 'cur', 'links', 'links_temp', 'links_backup' ) );
+
+       $res = $dbw->query( "SELECT l_from FROM $links LIMIT 1" );
+       if ( $dbw->fieldType( $res, 0 ) == "int" ) {
+               print "Schema already converted\n";
+               return;
+       }
+       
+       $res = $dbw->query( "SELECT COUNT(*) AS count FROM $links" );
+       $row = $dbw->fetchObject($res);
+       $numRows = $row->count;
+       $dbw->freeResult( $res );
+
+       if ( $numRows == 0 ) {
+               print "Updating schema (no rows to convert)...\n";
+               createTempTable();
+       } else {
+               if ( $logPerformance ) { $fh = fopen ( $perfLogFilename, "w" ); }
+               $baseTime = $startTime = getMicroTime();
+               # Create a title -> cur_id map
+               print "Loading IDs from $cur table...\n";
+               performanceLog ( "Reading $numRows rows from cur table...\n" );
+               performanceLog ( "rows read vs seconds elapsed:\n" );
+               
+               $dbw->bufferResults( false );
+               $res = $dbw->query( "SELECT cur_namespace,cur_title,cur_id FROM $cur" );
+               $ids = array();
+
+               while ( $row = $dbw->fetchObject( $res ) ) {
+                       $title = $row->cur_title;
+                       if ( $row->cur_namespace ) {
+                               $title = $wgLang->getNsText( $row->cur_namespace ) . ":$title";
+                       }
+                       $ids[$title] = $row->cur_id;
+                       $curRowsRead++;
+                       if ($reportCurReadProgress) {
+                               if (($curRowsRead % $curReadReportInterval) == 0) {
+                                       performanceLog( $curRowsRead . " " . (getMicroTime() - $baseTime) . "\n" );
+                                       print "\t$curRowsRead rows of $cur table read.\n";      
+                               }
+                       }
+               }
+               $dbw->freeResult( $res );
+               $dbw->bufferResults( true );
+               print "Finished loading IDs.\n\n";
+               performanceLog( "Took " . (getMicroTime() - $baseTime) . " seconds to load IDs.\n\n" );
+       #--------------------------------------------------------------------
+
+               # Now, step through the links table (in chunks of $linksConvInsertInterval rows),
+               # convert, and write to the new table.
+               createTempTable();
+               performanceLog( "Resetting timer.\n\n" );
+               $baseTime = getMicroTime();
+               print "Processing $numRows rows from $links table...\n";
+               performanceLog( "Processing $numRows rows from $links table...\n" );
+               performanceLog( "rows inserted vs seconds elapsed:\n" );
+               
+               for ($rowOffset = $initialRowOffset; $rowOffset < $numRows; $rowOffset += $linksConvInsertInterval) {
+                       $sqlRead = "SELECT * FROM $links ".$dbw->limitResult($linksConvInsertInterval,$rowOffset);
+                       $res = $dbw->query($sqlRead);
+                       if ( $noKeys ) {
+                               $sqlWrite = array("INSERT INTO $links_temp (l_from,l_to) VALUES ");
+                       } else {
+                               $sqlWrite = array("INSERT IGNORE INTO $links_temp (l_from,l_to) VALUES ");
+                       }
+                       
+                       $tuplesAdded = 0; # no tuples added to INSERT yet
+                       while ( $row = $dbw->fetchObject($res) ) {
+                               $fromTitle = $row->l_from; 
+                               if ( array_key_exists( $fromTitle, $ids ) ) { # valid title
+                                       $from = $ids[$fromTitle];
+                                       $to = $row->l_to;
+                                       if ( $tuplesAdded != 0 ) {
+                                               $sqlWrite[] = ",";
+                                       }
+                                       $sqlWrite[] = "($from,$to)";
+                                       $tuplesAdded++;                         
+                               } else { # invalid title
+                                       $numBadLinks++;
+                               }
+                       }
+                       $dbw->freeResult($res);
+                       #print "rowOffset: $rowOffset\ttuplesAdded: $tuplesAdded\tnumBadLinks: $numBadLinks\n";
+                       if ( $tuplesAdded != 0  ) {
+                               if ($reportLinksConvProgress) {
+                                       print "Inserting $tuplesAdded tuples into $links_temp...";
+                               }
+                               $dbw->query( implode("",$sqlWrite) );
+                               $totalTuplesInserted += $tuplesAdded;
+                               if ($reportLinksConvProgress)
+                                       print " done. Total $totalTuplesInserted tuples inserted.\n";
+                                       performanceLog( $totalTuplesInserted . " " . (getMicroTime() - $baseTime) . "\n"  );
+                       }
+               }
+               print "$totalTuplesInserted valid titles and $numBadLinks invalid titles were processed.\n\n";
+               performanceLog( "$totalTuplesInserted valid titles and $numBadLinks invalid titles were processed.\n" );
+               performanceLog( "Total execution time: " . (getMicroTime() - $startTime) . " seconds.\n" );
+               if ( $logPerformance ) { fclose ( $fh ); }
+       }
+       #--------------------------------------------------------------------
+
+       if ( $overwriteLinksTable ) {
+               $dbConn = Database::newFromParams( $wgDBserver, $wgDBadminuser, $wgDBadminpassword, $wgDBname );
+               if (!($dbConn->isOpen())) {
+                       print "Opening connection to database failed.\n";
+                       return;
+               }
+               # Check for existing links_backup, and delete it if it exists.
+               print "Dropping backup links table if it exists...";
+               $dbConn->query( "DROP TABLE IF EXISTS $links_backup", DB_MASTER);
+               print " done.\n";
+               
+               # Swap in the new table, and move old links table to links_backup
+               print "Swapping tables '$links' to '$links_backup'; '$links_temp' to '$links'...";
+               $dbConn->query( "RENAME TABLE links TO $links_backup, $links_temp TO $links", DB_MASTER );
+               print " done.\n\n";
+               
+               $dbConn->close();
+               print "Conversion complete. The old table remains at $links_backup;\n";
+               print "delete at your leisure.\n";
+       } else {
+               print "Conversion complete.  The converted table is at $links_temp;\n";
+               print "the original links table is unchanged.\n";
+       }
+}
+
+#--------------------------------------------------------------------
+
+function createTempTable() {
+       global $wgDBserver, $wgDBadminuser, $wgDBadminpassword, $wgDBname;
+       global $noKeys;
+       $dbConn = Database::newFromParams( $wgDBserver, $wgDBadminuser, $wgDBadminpassword, $wgDBname );
+       
+       if (!($dbConn->isOpen())) {
+               print "Opening connection to database failed.\n";
+               return;
+       }
+       $links_temp = $dbConn->tableName( 'links_temp' );
+       
+       print "Dropping temporary links table if it exists...";
+       $dbConn->query( "DROP TABLE IF EXISTS $links_temp");
+       print " done.\n";
+       
+       print "Creating temporary links table...";
+       if ( $noKeys ) {
+               $dbConn->query( "CREATE TABLE $links_temp ( " .
+               "l_from int(8) unsigned NOT NULL default '0', " .
+               "l_to int(8) unsigned NOT NULL default '0')");
+       } else {
+               $dbConn->query( "CREATE TABLE $links_temp ( " .
+               "l_from int(8) unsigned NOT NULL default '0', " .
+               "l_to int(8) unsigned NOT NULL default '0', " .
+               "UNIQUE KEY l_from(l_from,l_to), " .
+               "KEY (l_to))");
+       }
+       print " done.\n\n";
+}
+
+function performanceLog( $text ) {
+       global $logPerformance, $fh;
+       if ( $logPerformance ) {
+               fwrite( $fh, $text );
+       }
+}
+
+function getMicroTime() { # return time in seconds, with microsecond accuracy
+       list($usec, $sec) = explode(" ", microtime());
+       return ((float)$usec + (float)$sec);
+}
+
+
+
+?>
diff --git a/maintenance/convertLinks.php b/maintenance/convertLinks.php
new file mode 100644 (file)
index 0000000..5939b94
--- /dev/null
@@ -0,0 +1,16 @@
+<?php
+/**
+ * Convert from the old links schema (string->ID) to the new schema (ID->ID)
+ * The wiki should be put into read-only mode while this script executes
+ *
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+/** */
+require_once( "commandLine.inc" );
+require_once( "convertLinks.inc" );
+
+convertLinks();
+
+?>
diff --git a/maintenance/convertUtf8.php b/maintenance/convertUtf8.php
new file mode 100644 (file)
index 0000000..023906e
--- /dev/null
@@ -0,0 +1,235 @@
+<?php
+/**
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+die("This file is not complete; it's checked in so I don't forget it.");
+
+/**
+ * UTF-8 conversion of DOOOOOOOM
+ *
+ * 1. Lock the wiki
+ * 2. Make a convertlist of all pages
+ * 3. Enable CONVERTLOCK mode and switch to UTF-8
+ * 4. As quick as possible, convert the cur, images, *links, user, etc tables.
+ * Clear cache tables.
+ * 5. Unlock the wiki. Attempts to access pages on the convertlist will be
+ * trapped to read-only.
+ * 6. Go through the list, fixing up old revisions. Remove pages from the
+ * convertlist.
+ */
+
+/**
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+class UtfUpdater {
+       /** Constructor, set the database */
+       function UtfUpdater() {
+               $this->db =& wfGetDB( DB_MASTER );
+       }
+
+       /**
+        * @param string $string A string to be converted to UTF-8
+        */     
+       function toUtf8( $string ) {
+               if( function_exists( 'iconv' ) ) {
+                       # There are likely to be Windows code page 1252 chars in there.
+                       # Convert them to the proper UTF-8 chars if possible.
+                       return iconv( 'CP1252', 'UTF-8', $string );
+               } else {
+                       # Will work from plain iso 8859-1 and may corrupt these chars
+                       return utf8_encode( $string );
+               }
+       }
+
+       /**
+        * Truncate a table.
+        * @param string $table The table name to be truncated
+        */
+       function clearTable( $table ) {
+               print "Clearing $table...\n";
+               $tableName = $this->db->tableName( $table );
+               $this->db->query( 'TRUNCATE $tableName' );
+       }
+       
+       /**
+        * @param string $table Table to be converted
+        * @param string $key Primary key, to identify fields in the UPDATE. If NULL, all fields will be used to match.
+        * @param array $fields List of all fields to grab and convert. If null, will assume you want the $key, and will ask for DISTINCT.
+        * @param array $timestamp A field which should be updated to the current timestamp on changed records.
+        * @param callable $callback
+        * @access private
+        */
+       function convertTable( $table, $key, $fields = null, $timestamp = null, $callback = null ) {
+               $fname = 'UtfUpdater::convertTable';
+               if( $fields ) {
+                       $distinct = '';
+               } else {
+                       # If working on one key only, there will be multiple rows.
+                       # Use DISTINCT to return only one and save us some trouble.
+                       $fields = array( $key );
+                       $distinct = 'DISTINCT';
+               }
+               $condition = '';
+               foreach( $fields as $field ) {
+                       if( $condition ) $condition .= ' OR ';
+                       $condition .= "$field RLIKE '[\x80-\xff]'";
+               }
+               $res = $this->db->selectArray(
+                       $table,
+                       array_merge( $fields, array( $key ) ),
+                       $condition,
+                       $fname,
+                       $distinct );
+               print "Converting " . $this->db->numResults( $res ) . " rows from $table:\n";
+               $n = 0;
+               while( $s = $this->db->fetchObject( $res ) ) {
+                       $set = array();
+                       foreach( $fields as $field ) {
+                               $set[] = $this->toUtf8( $s->$field );
+                       }
+                       if( $timestamp ) {
+                               $set[$timestamp] = $this->db->timestamp();
+                       }
+                       if( $key ) {
+                               $keyCond = array( $key, $s->$key );
+                       } else {
+                               $keyCond = array();
+                               foreach( $fields as $field ) {
+                                       $keyCond[$field] = $s->$field;
+                               }
+                       }
+                       $this->db->updateArray(
+                               $table,
+                               $set,
+                               $keyCond,
+                               $fname );
+                       if( ++$n % 100 == 0 ) echo "$n\n";
+                       
+                       if( is_callable( $callback ) ) {
+                               call_user_func( $callback, $s );
+                       }
+               }
+               echo "$n done.\n";
+               $this->db->freeResult( $res );
+       }
+       
+       /**
+        * @param object $row
+        * @access private
+        */
+       function imageRenameCallback( $row ) {
+               $this->renameFile( $row->img_name, 'wfImageDir' );
+       }
+       
+       /**
+        * @param object $row
+        * @access private
+        */
+       function oldimageRenameCallback( $row ) {
+               $this->renameFile( $row->oi_archive_name, 'wfImageArchiveDir' );
+       }
+       
+       /**
+        * Rename a given image or archived image file to the converted filename,
+        * leaving a symlink for URL compatibility.
+        *
+        * @param string $oldname pre-conversion filename
+        * @param callable $subdirCallback a function to generate hashed directories
+        * @access private
+        */
+       function renameFile( $oldname, $subdirCallback ) {
+               $newname = $this->toUtf8( $oldname );
+               if( $newname == $oldname ) {
+                       // No need to rename; another field triggered this row.
+                       return;
+               }
+               
+               $oldpath = call_user_func( $subdirCallback, $oldname ) . '/' . $oldname;
+               $newpath = call_user_func( $subdirCallback, $newname ) . '/' . $newname;
+               
+               echo "Renaming $oldpath to $newpath... ";
+               if( rename( $oldpath, $newpath ) ) {
+                       echo "ok\n";
+                       echo "Creating compatibility symlink from $newpath to $oldpath... ";
+                       if( symlink( $newpath, $oldpath ) ) {
+                               echo "ok\n";
+                       } else {
+                               echo " symlink failed!\n";
+                       }
+               } else {
+                       echo " rename failed!\n";
+               }
+       }
+       
+       /**
+        * Lock tables.
+        * @param array $tables An array of table to be locked.
+        */
+       function lockTables( $tables ) {
+               $query = '';
+               foreach( $tables as $table ) {
+                       $tableName = $this->db->tableName( $table );
+                       if( $query ) $query .= ', ';
+                       $query .= '$tableName WRITE';
+               }
+               $this->db->query( 'LOCK TABLES ' . $query );
+       }
+
+       /**
+        * @todo document
+        */     
+       function updateAll() {
+               $this->lockTables( array(
+                       'objectcache', 'searchindex', 'querycache',
+                       'ipblocks', 'user', 'page', 'revision', 'recentchanges',
+                       'brokenlinks', 'categorylinks', 'imagelinks', 'watchlist',
+                       'image', 'oldimage', 'archive' ) );
+               
+               # These are safe to clear out:
+               $this->clearTable( 'objectcache' );
+
+               # These need to be rebuild if used:
+               $this->clearTable( 'searchindex' );
+               $this->clearTable( 'querycache' );
+
+               # And convert the rest...
+               $this->convertTable( 'ipblocks', 'ipb_id', array( 'ipb_reason' ) );
+               $this->convertTable( 'user', 'user_id', 
+                       array( 'user_name', 'user_real_name', 'user_options' ),
+                       'user_touched' );
+               $this->convertTable( 'page', 'page_id',
+                       array( 'page_title' ), 'page_touched' );
+               $this->convertTable( 'revision', 'rev_id',
+                       array( 'rev_user_text', 'rev_comment' ) );
+               
+               $this->convertTable( 'recentchanges', 'rc_id',
+                       array( 'rc_user_text', 'rc_title', 'rc_comment' ) );
+               
+               $this->convertTable( 'pagelinks', 'pl_title' );
+               $this->convertTable( 'categorylinks', 'cl_to' );
+               $this->convertTable( 'imagelinks', 'il_to' );
+               $this->convertTable( 'watchlist', 'wl_title' );
+               
+               # We'll also need to change the files.
+               $this->convertTable( 'image', 'img_name',
+                       array( 'img_name', 'img_description', 'img_user_text' ),
+                       null,
+                       array( &$this, 'imageRenameCallback' ) );
+               $this->convertTable( 'oldimage', 'archive_name',
+                       array( 'oi_name', 'oi_archive_name', 'oi_description', 'oi_user_text' ),
+                       null,
+                       array( &$this, 'oldimageRenameCallback' ) );
+               
+               # Don't change the ar_text entries; use $wgLegacyEncoding to read them at runtime
+               $this->convertTable( 'archive', null,
+                       array( 'ar_title', 'ar_comment', 'ar_user_text' ) );
+               echo "Not converting text table: be sure to set \$wgLegacyEncoding!\n";
+               
+               $this->db->query( 'UNLOCK TABLES' );
+       }
+       
+}
+?>
diff --git a/maintenance/database.sql b/maintenance/database.sql
new file mode 100644 (file)
index 0000000..dea9954
--- /dev/null
@@ -0,0 +1,7 @@
+-- SQL script to create database for wiki.  This is run from
+-- the installation script which replaces the variables with
+-- their values from local settings.
+--
+
+DROP DATABASE IF EXISTS `{$wgDBname}`;
+CREATE DATABASE `{$wgDBname}`;
diff --git a/maintenance/delete-idle-wiki-users.pl b/maintenance/delete-idle-wiki-users.pl
new file mode 100644 (file)
index 0000000..aef68cc
--- /dev/null
@@ -0,0 +1,138 @@
+#!/usr/bin/perl
+#
+# Nuke idle wiki accounts from the wiki's user database.
+#
+# Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
+#
+# This program is free software; you can redistribute  it and/or modify it
+# under  the terms of  the GNU General  Public License as published by the
+# Free Software Foundation;  either version 2 of the  License, or (at your
+# option) any later version.
+#
+# THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+# WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+# NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+# USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+# ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# You should have received a copy of the  GNU General Public License along
+# with this program; if not, write  to the Free Software Foundation, Inc.,
+# 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+my $database = "DBI:mysql:database=wikidb;host=localhost";
+my $dbuser   = "wikiuser";
+my $dbpasswd = "password";
+
+use strict;
+use DBI();
+
+my $verbose = 0;
+my $for_real = 1;
+
+sub do_db_op
+{
+       my ($dbh, $sql) = @_;
+
+       if ($verbose >= 3) {
+               print $sql . ";\n"
+       }
+
+       if ($for_real == 1) {
+               $dbh->do($sql);
+       }
+}
+
+sub undo_user
+{
+       my ($ref, $dbh, $sth, $killed);
+
+       # Connect to the database.
+       $dbh = DBI->connect($database, $dbuser, $dbpasswd, {RaiseError => 1});
+
+       $sth = $dbh->prepare("SELECT * FROM user");
+       $sth->execute();
+
+       $ref = $sth->fetchrow_hashref();
+
+       if ($sth->rows == 0) {
+               print "There is no user in this wiki.\n";
+               return;
+       }
+
+       while ($ref = $sth->fetchrow_hashref()) {
+               my ($user_id, $user_name, $cph, $oph, $edits);
+
+               $user_name = $ref->{user_name};
+               $user_id = $ref->{user_id};
+               if ($verbose >= 2) {
+                       print "Annihilating user " . $user_name .
+                             " has user_id " . $user_id . ".\n";
+               }
+
+               $cph = $dbh->prepare("SELECT * FROM cur where " .
+                               "cur_user = $user_id" .
+                               " AND " .
+                               "cur_user_text = " . $dbh->quote("$user_name"));
+               $cph->execute();
+
+               $oph = $dbh->prepare("SELECT * FROM old where " .
+                               "old_user = $user_id" .
+                               " AND " .
+                               "old_user_text = " . $dbh->quote("$user_name"));
+               $oph->execute();
+
+               $edits = $cph->rows + $oph->rows;
+
+               $cph->finish();
+               $oph->finish();
+
+               if ($edits == 0) {
+                       if ($verbose >= 2) {
+                               print "Keeping user " . $user_name .
+                                     ", user_id " . $user_id . ".\n";
+                       }
+
+                       do_db_op($dbh,
+                        "DELETE FROM user WHERE user_name = " .
+                        $dbh->quote("$user_name") .
+                        " AND " .
+                        "user_id = $user_id");
+
+                       $killed++;
+               }
+       }
+
+       $sth->finish();
+
+       $dbh->disconnect();
+
+       if ($verbose >= 1) {
+               print "Killed " . $killed . " users\n";
+       }
+}
+
+my (@users, $user, $this, $opts);
+
+@users = ();
+$opts = 1;
+
+foreach $this (@ARGV) {
+       if ($opts == 1 && $this eq '-v') {
+               $verbose++;
+       } elsif ($opts == 1 && $this eq '--verbose') {
+               $verbose = 1;
+       } elsif ($opts == 1 && $this eq '--') {
+               $opts = 0;
+       } else {
+               push(@users, $this);
+       }
+}
+
+undo_user();
+
diff --git a/maintenance/deleteOldRevisions.inc b/maintenance/deleteOldRevisions.inc
new file mode 100644 (file)
index 0000000..dd48028
--- /dev/null
@@ -0,0 +1,60 @@
+<?php
+
+/**
+ * Support functions for the deleteOldRevisions script
+ *
+ * @package MediaWiki
+ * @subpackage Maintenance
+ * @author Rob Church <robchur@gmail.com>
+ */
+require_once( 'purgeOldText.inc' );
+
+function DeleteOldRevisions( $delete = false ) {
+
+       # Data should come off the master, wrapped in a transaction
+       $dbw =& wfGetDB( DB_MASTER );
+       $dbw->begin();
+       
+       $tbl_pag = $dbw->tableName( 'page' );
+       $tbl_rev = $dbw->tableName( 'revision' );
+       
+       # Get "active" revisions from the page table
+       echo( "Searching for active revisions..." );
+       $res = $dbw->query( "SELECT page_latest FROM $tbl_pag" );
+       while( $row = $dbw->fetchObject( $res ) ) {
+               $cur[] = $row->page_latest;
+       }
+       echo( "done.\n" );
+       
+       # Get all revisions that aren't in this set
+       echo( "Searching for inactive revisions..." );
+       $set = implode( ', ', $cur );
+       $res = $dbw->query( "SELECT rev_id FROM $tbl_rev WHERE rev_id NOT IN ( $set )" );
+       while( $row = $dbw->fetchObject( $res ) ) {
+               $old[] = $row->rev_id;
+       }
+       echo( "done.\n" );
+       
+       # Inform the user of what we're going to do
+       $count = count( $old );
+       echo( "$count old revisions found.\n" );
+       
+       # Delete as appropriate
+       if( $delete && $count ) {
+               echo( "Deleting..." );
+               $set = implode( ', ', $old );
+               $dbw->query( "DELETE FROM $tbl_rev WHERE rev_id IN ( $set )" );
+               echo( "done.\n" );
+       }
+       
+       # This bit's done
+       # Purge redundant text records
+       $dbw->commit();
+       if( $delete ) {
+               PurgeRedundantText( true );
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/maintenance/deleteOldRevisions.php b/maintenance/deleteOldRevisions.php
new file mode 100644 (file)
index 0000000..9695a8c
--- /dev/null
@@ -0,0 +1,30 @@
+<?php
+
+/**
+ * Delete old (non-current) revisions from the database
+ *
+ * @package MediaWiki
+ * @subpackage Maintenance
+ * @author Rob Church <robchur@gmail.com>
+ */
+
+$options = array( 'delete', 'help' );
+require_once( 'commandLine.inc' );
+require_once( 'deleteOldRevisions.inc' );
+
+echo( "Delete Old Revisions\n\n" );
+
+if( @$options['help'] ) {
+       ShowUsage();
+} else {
+       DeleteOldRevisions( @$options['delete'] );
+}
+
+function ShowUsage() {
+       echo( "Deletes non-current revisions from the database.\n\n" );
+       echo( "Usage: php deleteOldRevisions.php [--delete|--help]\n\n" );
+       echo( "delete : Performs the deletion\n" );
+       echo( "  help : Show this usage information\n" );
+}
+
+?>
\ No newline at end of file
diff --git a/maintenance/diffLanguage.php b/maintenance/diffLanguage.php
new file mode 100644 (file)
index 0000000..e709c41
--- /dev/null
@@ -0,0 +1,159 @@
+<?php
+# MediaWiki web-based config/installation
+# Copyright (C) 2004 Ashar Voultoiz <thoane@altern.org> and others
+# http://www.mediawiki.org/
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# http://www.gnu.org/copyleft/gpl.html
+
+/**
+ * Usage: php DiffLanguage.php [lang [file]]
+ *
+ * lang: Enter the language code following "Language" of the LanguageXX.php you
+ * want to check. If using linux you might need to follow case aka Zh and not
+ * zh.
+ *
+ * file: A php language file you want to include to compare mediawiki
+ * Language{Lang}.php against (for example Special:Allmessages PHP output).
+ *
+ * The goal is to get a list of messages not yet localised in a languageXX.php
+ * file using the language.php file as reference.
+ * 
+ * The script then print a list of wgAllMessagesXX keys that aren't localised, a
+ * percentage of messages correctly localised and the number of messages to be
+ * translated.
+ * 
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+/** This script run from the commandline */
+require_once( 'parserTests.inc' );
+require_once( 'commandLine.inc' );
+
+if( isset($options['help']) ) { usage(); die(); }
+
+$wgLanguageCode = ucfirstlcrest($wgLanguageCode);
+/** Language messages we will use as reference. By default 'en' */
+$referenceMessages = $wgAllMessagesEn;
+$referenceLanguage = 'En';
+$referenceFilename = 'Language'.$referenceLanguage.'.php';
+/** Language messages we will test. */ 
+$testMessages = array();
+$testLanguage = '';
+/** whereas we use an external language file */
+$externalRef = false;
+
+# FUNCTIONS
+/** @todo more informations !! */
+function usage() {
+echo 'php DiffLanguage.php [lang [file]] [--color=(yes|no|light)]'."\n";
+}
+
+/** Return a given string with first letter upper case, the rest lowercase */
+function ucfirstlcrest($string) {
+       return strtoupper(substr($string,0,1)).strtolower(substr($string,1));
+}
+
+/**
+ * Return a $wgAllmessages array shipped in MediaWiki
+ * @param string $languageCode Formated language code
+ * @return array The MediaWiki default $wgAllMessages array requested
+ */
+function getMediawikiMessages($languageCode = 'En') {
+
+       $foo = "wgAllMessages$languageCode";
+       global $$foo;
+
+       // it might already be loaded in LocalSettings.php
+       if(!isset($$foo)) {
+               global $IP;
+               $langFile = $IP.'/languages/Language'.$languageCode.'.php';
+               if (file_exists( $langFile ) ) {
+                       print "Including $langFile\n";
+                       global $wgNamespaceNamesEn;
+                       include($langFile);
+               } else die("ERROR: The file $langFile does not exist !\n");
+       }
+       return $$foo;
+}
+
+/**
+ * Return a $wgAllmessages array in a given file. Language of the array
+ * need to be given cause we can not detect which language it provides
+ * @param string $filename Filename of the file containing a message array
+ * @param string $languageCode Language of the external array
+ * @return array A $wgAllMessages array from an external file.
+ */
+function getExternalMessages($filename, $languageCode) {
+       print "Including external file $filename.\n";
+       include($filename);
+       $foo = "wgAllMessages$languageCode";
+       return $$foo;
+}
+
+# MAIN ENTRY
+if ( isset($args[0]) ) {
+       $lang = ucfirstlcrest($args[0],1);
+
+       // eventually against another language file we will use as reference instead
+       // of the default english language.
+       if( isset($args[1])) {
+               // we assume the external file contain an array of messages for the
+               // lang we are testing
+               $referenceMessages = getExternalMessages( $args[1], $lang );
+               $referenceLanguage = $lang;
+               $referenceFilename = $args[1];
+               $externalRef = true;
+       }
+
+       // Load datas from MediaWiki
+       $testMessages = getMediawikiMessages($lang);
+       $testLanguage = $lang;          
+} else {
+       usage();
+       die();
+}
+
+/** parsertest is used to do differences */
+$myParserTest =& new ParserTest();
+
+# Get all references messages and check if they exist in the tested language
+$i = 0;
+
+$msg = "MW Language{$testLanguage}.php against ";
+if($externalRef) { $msg .= 'external file '; }
+else { $msg .= 'internal file '; }
+$msg .= $referenceFilename.' ('.$referenceLanguage."):\n----\n";
+echo $msg;
+
+// process messages
+foreach($referenceMessages as $index => $ref)
+{
+       // message is not localized
+       if(!(isset($testMessages[$index]))) {
+               $i++;
+               print "'$index' => \"$ref\",\n";
+       // Messages in the same language differs
+       } elseif( ($lang == $referenceLanguage) AND ($testMessages[$index] != $ref)) {
+               print "$index differs:\n";
+               print $myParserTest->quickDiff($testMessages[$index],$ref,'tested','reference');
+       }
+}
+
+echo "\n----\n".$msg;
+echo "$referenceLanguage language is complete at ".number_format((100 - $i/count($wgAllMessagesEn) * 100),2)."%\n";
+echo "$i unlocalised messages of the ".count($wgAllMessagesEn)." messages available.\n";
+?>
diff --git a/maintenance/dumpBackup.php b/maintenance/dumpBackup.php
new file mode 100644 (file)
index 0000000..51d9ee0
--- /dev/null
@@ -0,0 +1,180 @@
+<?php
+/**
+ * Copyright (C) 2005 Brion Vibber <brion@pobox.com>
+ * http://www.mediawiki.org/
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or 
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+$originalDir = getcwd();
+
+$optionsWithArgs = array( 'server', 'pagelist' );
+
+require_once( 'commandLine.inc' );
+require_once( 'SpecialExport.php' );
+
+class BackupDumper {
+       var $reportingInterval = 100;
+       var $reporting = true;
+       var $pageCount = 0;
+       var $revCount  = 0;
+       var $server    = null; // use default
+       var $pages     = null; // all pages
+       
+       function BackupDumper() {
+               $this->stderr = fopen( "php://stderr", "wt" );
+       }
+       
+       function dump( $history ) {
+               # This shouldn't happen if on console... ;)
+               header( 'Content-type: text/html; charset=UTF-8' );
+               
+               # Notice messages will foul up your XML output even if they're
+               # relatively harmless.
+               ini_set( 'display_errors', false );
+               
+               $this->startTime = wfTime();
+               
+               $dbr =& wfGetDB( DB_SLAVE );
+               $this->maxCount = $dbr->selectField( 'page', 'MAX(page_id)', '', 'BackupDumper::dump' );
+               $this->startTime = wfTime();
+               
+               $db =& $this->backupDb();
+               $exporter = new WikiExporter( $db, $history, MW_EXPORT_STREAM );
+               $exporter->setPageCallback( array( &$this, 'reportPage' ) );
+               $exporter->setRevisionCallback( array( &$this, 'revCount' ) );
+               
+               $exporter->openStream();
+
+               if ( is_null( $this->pages ) ) {
+                       $exporter->allPages();
+               } else {
+                       $exporter->pagesByName( $this->pages );
+               }
+
+               $exporter->closeStream();
+               
+               $this->report( true );
+       }
+       
+       function &backupDb() {
+               global $wgDBadminuser, $wgDBadminpassword;
+               global $wgDBname;
+               $db =& new Database( $this->backupServer(), $wgDBadminuser, $wgDBadminpassword, $wgDBname );
+               $timeout = 3600 * 24;
+               $db->query( "SET net_read_timeout=$timeout" );
+               $db->query( "SET net_write_timeout=$timeout" );
+               return $db;
+       }
+       
+       function backupServer() {
+               global $wgDBserver;
+               return $this->server
+                       ? $this->server
+                       : $wgDBserver;
+       }
+
+       function reportPage( $page ) {
+               $this->pageCount++;
+               $this->report();
+       }
+       
+       function revCount( $rev ) {
+               $this->revCount++;
+       }
+       
+       function report( $final = false ) {
+               if( $final xor ( $this->pageCount % $this->reportingInterval == 0 ) ) {
+                       $this->showReport();
+               }
+       }
+       
+       function showReport() {
+               if( $this->reporting ) {
+                       $delta = wfTime() - $this->startTime;
+                       $now = wfTimestamp( TS_DB );
+                       if( $delta ) {
+                               $rate = $this->pageCount / $delta;
+                               $revrate = $this->revCount / $delta;
+                               $portion = $this->pageCount / $this->maxCount;
+                               $eta = $this->startTime + $delta / $portion;
+                               $etats = wfTimestamp( TS_DB, intval( $eta ) );
+                       } else {
+                               $rate = '-';
+                               $revrate = '-';
+                               $etats = '-';
+                       }
+                       global $wgDBname;
+                       $this->progress( "$now: $wgDBname $this->pageCount, ETA $etats ($rate pages/sec $revrate revs/sec)" );
+               }
+       }
+       
+       function progress( $string ) {
+               fwrite( $this->stderr, $string . "\n" );
+       }
+}
+
+$dumper = new BackupDumper();
+if( isset( $options['quiet'] ) ) {
+       $dumper->reporting = false;
+}
+if( isset( $options['report'] ) ) {
+       $dumper->reportingInterval = IntVal( $options['report'] );
+}
+if( isset( $options['server'] ) ) {
+       $dumper->server = $options['server'];
+}
+
+if ( isset( $options['pagelist'] ) ) {
+       $olddir = getcwd();
+       chdir( $originalDir );
+       $pages = file( $options['pagelist'] );
+       chdir( $olddir );
+       if ( $pages === false ) {
+               print "Unable to open file {$options['pagelist']}\n";
+               exit;
+       }
+       $pages = array_map( 'trim', $pages );
+       $dumper->pages = array_filter( $pages, create_function( '$x', 'return $x !== "";' ) );
+}
+
+if( isset( $options['full'] ) ) {
+       $dumper->dump( MW_EXPORT_FULL );
+} elseif( isset( $options['current'] ) ) {
+       $dumper->dump( MW_EXPORT_CURRENT );
+} else {
+       $dumper->progress( <<<END
+This script dumps the wiki page database into an XML interchange wrapper
+format for export or backup.
+
+XML output is sent to stdout; progress reports are sent to stderr.
+
+Usage: php dumpBackup.php <action> [<options>]
+Actions:
+  --full      Dump complete history of every page.
+  --current   Includes only the latest revision of each page.
+Options:
+  --quiet     Don't dump status reports to stderr.
+  --report=n  Report position and speed after every n pages processed.
+              (Default: 100)
+END
+);
+}
+
+?>
diff --git a/maintenance/dumpHTML.inc b/maintenance/dumpHTML.inc
new file mode 100644 (file)
index 0000000..3eb4ffb
--- /dev/null
@@ -0,0 +1,387 @@
+<?php
+/**
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+define( 'REPORTING_INTERVAL', 10 );
+
+require_once( 'includes/ImagePage.php' );
+require_once( 'includes/CategoryPage.php' );
+
+class DumpHTML {
+       # Destination directory
+       var $dest;
+
+       # Show interlanguage links?
+       var $interwiki = true;
+       
+       # Depth of HTML directory tree
+       var $depth = 3;
+
+       # Directory that commons images are copied into
+       var $sharedStaticPath;
+       
+       # Relative path to image directory
+       var $imageRel = 'upload';
+
+       # Copy commons images instead of symlinking
+       var $forceCopy = false;
+
+       # Make links assuming the script path is in the same directory as 
+       # the destination
+       var $alternateScriptPath = false;
+
+       function DumpHTML( $settings ) {
+               foreach ( $settings as $var => $value ) {
+                       $this->$var = $value;
+               }
+       }
+
+       /** 
+        * Write a set of articles specified by start and end page_id 
+        * Skip categories and images, they will be done separately
+        */
+       function doArticles( $start, $end = false ) {
+               $fname = 'DumpHTML::doArticles';
+               
+               $this->setupGlobals();
+               
+               if ( $end === false ) {
+                       $dbr =& wfGetDB( DB_SLAVE );
+                       $end = $dbr->selectField( 'page', 'max(page_id)', false, $fname );
+               }
+
+               
+               for ($id = $start; $id <= $end; $id++) {
+                       if ( !($id % REPORTING_INTERVAL) ) {
+                               print "Processing ID: $id\r";
+                       }
+                       $title = Title::newFromID( $id );
+                       if ( $title ) {
+                               $ns = $title->getNamespace() ;
+                               if ( $ns != NS_CATEGORY ) { 
+                                       $this->doArticle( $title );
+                               }
+                       }
+               }
+               print "\n";
+       }       
+
+       function doSpecials() {
+               $this->doMainPage();
+
+               $this->setupGlobals();
+               print "Special:Categories...";
+               $this->doArticle( Title::makeTitle( NS_SPECIAL, 'Categories' ) );
+               print "\n";
+       }
+
+       /** Write the main page as index.html */
+       function doMainPage() {
+               global $wgMakeDumpLinks;
+
+               print "Making index.html  ";
+
+               // Set up globals with no ../../.. in the link URLs
+               $this->setupGlobals( 0 );
+
+               // But still use that directory style
+               $wgMakeDumpLinks = 3;
+               
+               $title = Title::newMainPage();
+               $text = $this->getArticleHTML( $title );
+               $file = fopen( "{$this->dest}/index.html", "w" );
+               if ( !$file ) {
+                       print "\nCan't open index.html for writing\n";
+                       return false;
+               }
+               fwrite( $file, $text );
+               fclose( $file );
+               print "\n";
+       }
+
+       function doImageDescriptions() {
+               global $wgSharedUploadDirectory;
+               
+               $fname = 'DumpHTML::doImageDescriptions';
+               
+               $this->setupGlobals( 3 );
+
+               /** 
+                * Dump image description pages that don't have an associated article, but do 
+                * have a local image
+                */
+               $dbr =& wfGetDB( DB_SLAVE );
+               extract( $dbr->tableNames( 'image', 'page' ) );
+               $res = $dbr->select( 'image', array( 'img_name' ), false, $fname );
+
+               $i = 0;
+               print "Writing image description pages for local images\n";
+               $num = $dbr->numRows( $res );
+               while ( $row = $dbr->fetchObject( $res ) ) {
+                       if ( !( ++$i % REPORTING_INTERVAL ) ) {
+                               print "Done $i of $num\r";
+                       }
+                       $title = Title::makeTitle( NS_IMAGE, $row->img_name );
+                       if ( $title->getArticleID() ) { 
+                               // Already done by dumpHTML
+                               continue;
+                       }
+                       $this->doArticle( $title );
+               }
+               print "\n";
+
+               /**
+                * Dump images which only have a real description page on commons
+                */
+               print "Writing description pages for commons images\n";
+               $i = 0;
+               for ( $hash = 0; $hash < 256; $hash++ ) {                               
+                       $dir = sprintf( "%01x/%02x", intval( $hash / 16 ), $hash );
+                       $paths = glob( "{$this->sharedStaticPath}/$dir/*" );
+                       $paths += glob( "{$this->sharedStaticPath}/thumb/$dir/*" );
+
+                       foreach ( $paths as $path ) {
+                               $file = basename( $path );
+                               if ( !(++$i % REPORTING_INTERVAL ) ) {
+                                       print "$i\r";
+                               }
+
+                               $title = Title::makeTitle( NS_IMAGE, $file );
+                               $this->doArticle( $title );
+                       }
+               }
+               print "\n";
+       }
+
+       function doCategories() {
+               $fname = 'DumpHTML::doCategories';
+               $this->setupGlobals();
+
+               $dbr =& wfGetDB( DB_SLAVE );
+               print "Selecting categories...";
+               $sql = 'SELECT DISTINCT cl_to FROM ' . $dbr->tableName( 'categorylinks' );
+               $res = $dbr->query( $sql, $fname );
+
+               print "\nWriting " . $dbr->numRows( $res ).  " category pages\n";
+               $i = 0;
+               while ( $row = $dbr->fetchObject( $res ) ) {
+                       if ( !(++$i % REPORTING_INTERVAL ) ) {
+                               print "$i\r";
+                       }
+                       $title = Title::makeTitle( NS_CATEGORY, $row->cl_to );
+                       $this->doArticle( $title );
+               }
+               print "\n";
+       }
+
+
+       /** Write an article specified by title */
+       function doArticle( $title ) {
+               global $wgTitle, $wgSharedUploadPath, $wgSharedUploadDirectory;
+               global $wgUploadDirectory;
+               
+               $text = $this->getArticleHTML( $title );
+               if ( $text === false ) {
+                       return;
+               }
+
+               # Parse the XHTML to find the images
+               $images = $this->findImages( $text );
+               $this->copyImages( $images );
+
+               # Write to file
+               $this->writeArticle( $title, $text );
+       }
+
+       /** Write the given text to the file identified by the given title object */
+       function writeArticle( &$title, $text ) {
+               $filename = $title->getHashedFilename();
+               $fullName = "{$this->dest}/$filename";
+               $fullDir = dirname( $fullName );
+
+               wfMkdirParents( $fullDir, 0755 );
+
+               $file = fopen( $fullName, 'w' );
+               if ( !$file ) {
+                       print("Can't open file $fullName for writing\n");
+                       return;
+               }
+               
+               fwrite( $file, $text );
+               fclose( $file );
+       }
+
+       /** Set up globals required for parsing */
+       function setupGlobals( $depth = NULL ) {
+               global $wgUser, $wgTitle, $wgMakeDumpLinks, $wgStylePath, $wgArticlePath;
+               global $wgUploadPath, $wgLogo, $wgMaxCredits, $wgSharedUploadPath;
+               global $wgHideInterlanguageLinks, $wgUploadDirectory, $wgThumbnailScriptPath;
+               global $wgSharedThumbnailScriptPath, $wgEnableParserCache;
+
+               static $oldLogo = NULL;
+               
+               if ( is_null( $depth ) ) {
+                       $wgMakeDumpLinks = $this->depth;
+               } else {
+                       $wgMakeDumpLinks = $depth;
+               }
+               
+               if ( $this->alternateScriptPath ) {
+                       if ( $wgMakeDumpLinks == 0 ) {
+                               $wgScriptPath = '.';
+                       } else {
+                               $wgScriptPath = '..' . str_repeat( '/..', $wgMakeDumpLinks - 1 );
+                       }
+               } else {
+                       $wgScriptPath = '..' . str_repeat( '/..', $wgMakeDumpLinks );
+               }
+
+               $wgArticlePath = str_repeat( '../', $wgMakeDumpLinks ) . '$1';
+
+               # Logo image
+               # Allow for repeated setup
+               if ( !is_null( $oldLogo ) ) {
+                       $wgLogo = $oldLogo;
+               } else {
+                       $oldLogo = $wgLogo;
+               }
+
+               if ( strpos( $wgLogo, $wgUploadPath ) === 0 ) {
+                       # If it's in the upload directory, rewrite it to the new upload directory
+                       $wgLogo = "$wgScriptPath/{$this->imageRel}/" . substr( $wgLogo, strlen( $wgUploadPath ) + 1 );
+               } elseif ( $wgLogo{0} == '/' ) {
+                       # This is basically heuristic
+                       # Rewrite an absolute logo path to one relative to the the script path
+                       $wgLogo = $wgScriptPath . $wgLogo;
+               }
+
+               $wgStylePath = "$wgScriptPath/skins";
+               $wgUploadPath = "$wgScriptPath/{$this->imageRel}";
+               $wgSharedUploadPath = "$wgUploadPath/shared";
+               $wgMaxCredits = -1;
+               $wgHideInterlangageLinks = !$this->interwiki;
+               $wgThumbnailScriptPath = $wgSharedThumbnailScriptPath = false;
+               $wgEnableParserCache = false;
+
+               $wgUser = new User;
+               $wgUser->setOption( 'skin', 'htmldump' );
+               $wgUser->setOption( 'editsection', 0 );
+
+               $this->sharedStaticPath = "$wgUploadDirectory/shared";
+
+       }
+
+       /** Reads the content of a title object, executes the skin and captures the result */
+       function getArticleHTML( &$title ) {
+               global $wgOut, $wgTitle, $wgArticle, $wgUser, $wgUseCategoryMagic;
+               
+               $wgOut = new OutputPage;
+               $wgOut->setParserOptions( new ParserOptions );
+               
+               $wgTitle = $title;
+               if ( is_null( $wgTitle ) ) {
+                       return false;
+               }
+               
+               $ns = $wgTitle->getNamespace();
+               if ( $ns == NS_SPECIAL ) {
+                       SpecialPage::executePath( $wgTitle );
+               } else {
+                       if ( $ns == NS_IMAGE ) {
+                               $wgArticle = new ImagePage( $wgTitle );
+                       } elseif ( $wgUseCategoryMagic && $ns == NS_CATEGORY ) {
+                               $wgArticle = new CategoryPage( $wgTitle );
+                       } else {
+                               $wgArticle = new Article( $wgTitle );
+                       }
+                       $wgArticle->view();
+               }
+
+               $sk =& $wgUser->getSkin();
+               ob_start();
+               $sk->outputPage( $wgOut );
+               $text = ob_get_contents();
+               ob_end_clean();
+
+               return $text;
+       }
+
+       /** Returns image paths used in an XHTML document */
+       function findImages( $text ) {
+               global $wgOutputEncoding, $wgDumpImages;
+               $parser = xml_parser_create( $wgOutputEncoding );
+               xml_set_element_handler( $parser, 'wfDumpStartTagHandler', 'wfDumpEndTagHandler' );
+               
+               $wgDumpImages = array();
+               xml_parse( $parser, $text );
+               xml_parser_free( $parser );
+
+               return $wgDumpImages;
+       }
+
+       /**
+        * Copy images (or create symlinks) from commons to a static directory.
+        * This is necessary even if you intend to distribute all of commons, because
+        * the directory contents is used to work out which image description pages
+        * are needed.
+        */
+       function copyImages( $images ) {
+               global $wgSharedUploadPath, $wgSharedUploadDirectory;
+               # Find shared uploads and copy them into the static directory
+               $sharedPathLength = strlen( $wgSharedUploadPath ); 
+               foreach ( $images as $image => $dummy ) {
+                       # Is it shared?
+                       if ( substr( $image, 0, $sharedPathLength ) == $wgSharedUploadPath ) {
+                               # Reconstruct full filename
+                               $rel = substr( $image, $sharedPathLength + 1 ); // +1 for slash
+                               $sourceLoc = "$wgSharedUploadDirectory/$rel";
+                               $staticLoc = "{$this->sharedStaticPath}/$rel";
+                               #print "Copying $sourceLoc to $staticLoc\n";
+                               # Copy to static directory
+                               if ( !file_exists( $staticLoc ) ) {
+                                       wfMkdirParents( dirname( $staticLoc ), 0755 );
+                                       if ( function_exists( 'symlink' ) && !$this->forceCopy ) {
+                                               symlink( $sourceLoc, $staticLoc );
+                                       } else {
+                                               copy( $sourceLoc, $staticLoc );
+                                       }
+                               }
+
+                               if ( substr( $rel, 0, 6 ) == 'thumb/' ) {
+                                       # That was a thumbnail
+                                       # We will also copy the real image
+                                       $parts = explode( '/', $rel );
+                                       $rel = "{$parts[1]}/{$parts[2]}/{$parts[3]}";
+                                       $sourceLoc = "$wgSharedUploadDirectory/$rel";
+                                       $staticLoc = "{$this->sharedStaticPath}/$rel";
+                                       #print "Copying $sourceLoc to $staticLoc\n";
+                                       if ( !file_exists( $staticLoc ) ) {
+                                               wfMkdirParents( dirname( $staticLoc ), 0755 );
+                                               if ( function_exists( 'symlink' ) && !$this->forceCopy ) {
+                                                       symlink( $sourceLoc, $staticLoc );
+                                               } else {
+                                                       copy( $sourceLoc, $staticLoc );
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+}
+
+/** XML parser callback */
+function wfDumpStartTagHandler( $parser, $name, $attribs ) {
+       global $wgDumpImages;
+
+       if ( $name == 'IMG' && isset( $attribs['SRC'] ) ) {
+               $wgDumpImages[$attribs['SRC']] = true;
+       }
+}
+
+/** XML parser callback */
+function wfDumpEndTagHandler( $parser, $name ) {}
+
+# vim: syn=php
+?>
diff --git a/maintenance/dumpHTML.php b/maintenance/dumpHTML.php
new file mode 100644 (file)
index 0000000..bfde002
--- /dev/null
@@ -0,0 +1,99 @@
+<?php
+/**
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+/**
+ * Usage:
+ * php dumpHTML.php [options...]
+ *
+ * -d <dest>      destination directory
+ * -s <start>     start ID
+ * -e <end>       end ID
+ * --images       only do image description pages
+ * --categories   only do category pages
+ * --special      only do miscellaneous stuff
+ * --force-copy   copy commons instead of symlink, needed for Wikimedia
+ * --interlang    allow interlanguage links
+ */
+
+
+$optionsWithArgs = array( 's', 'd', 'e' );
+
+require_once( "commandLine.inc" );
+require_once( "dumpHTML.inc" );
+
+error_reporting( E_ALL & (~E_NOTICE) );
+define( 'CHUNK_SIZE', 50 );
+
+if ( !empty( $options['s'] ) ) {
+       $start = $options['s'];
+} else {
+       $start = 1;
+}
+
+if ( !empty( $options['e'] ) ) {
+       $end = $options['e'];
+} else {
+       $dbr =& wfGetDB( DB_SLAVE );
+       $end = $dbr->selectField( 'page', 'max(page_id)', false );      
+}
+
+if ( !empty( $options['d'] ) ) {
+       $dest = $options['d'];
+} else {
+       $dest = 'static';
+}
+
+$d = new DumpHTML( array( 
+       'dest' => $dest, 
+       'forceCopy' => $options['force-copy'],
+       'alternateScriptPath' => $options['interlang'],
+       'interwiki' => $options['interlang'],
+));
+
+
+if ( $options['special'] ) {
+       $d->doSpecials();
+} elseif ( $options['images'] ) {
+       $d->doImageDescriptions();
+} elseif ( $options['categories'] ) {
+       $d->doCategories();
+} else {
+       print("Creating static HTML dump in directory $dest. \n".
+               "Starting from page_id $start of $end.\n");
+       $d->doArticles( $start, $end );
+       $d->doImageDescriptions();
+       $d->doCategories();
+       $d->doSpecials();
+       
+       /*
+       if ( $end - $start > CHUNK_SIZE * 2 ) {
+               // Split the problem into smaller chunks, run them in different PHP instances
+               // This is a memory/resource leak workaround
+               print("Creating static HTML dump in directory $dest. \n".
+                       "Starting from page_id $start of $end.\n");
+
+               chdir( "maintenance" );
+               for ( $chunkStart = $start; $chunkStart < $end; $chunkStart += CHUNK_SIZE ) {
+                       $chunkEnd = $chunkStart + CHUNK_SIZE - 1;
+                       if ( $chunkEnd > $end ) {
+                               $chunkEnd = $end;
+                       }
+                       passthru( "php dumpHTML.php -d " . wfEscapeShellArg( $dest ) . " -s $chunkStart -e $chunkEnd" );
+               }
+               chdir( ".." );
+               $d->doImageDescriptions();
+               $d->doCategories();
+               $d->doMainPage( $dest );
+       } else {
+               $d->doArticles( $start, $end );
+       }
+       */
+}
+
+exit();
+
+?>
diff --git a/maintenance/dumpMessages.php b/maintenance/dumpMessages.php
new file mode 100644 (file)
index 0000000..84ecc4c
--- /dev/null
@@ -0,0 +1,19 @@
+<?php
+/**
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+/** */
+require_once( "commandLine.inc" );
+$wgMessageCache->disableTransform();
+$messages = array();
+foreach ( $wgAllMessagesEn as $key => $englishValue )
+{
+       $messages[$key] = wfMsg( $key );
+}
+print "MediaWiki $wgVersion language file\n";
+print serialize( $messages );
+
+?>
diff --git a/maintenance/dumpReplayLog.php b/maintenance/dumpReplayLog.php
new file mode 100644 (file)
index 0000000..b87770a
--- /dev/null
@@ -0,0 +1,118 @@
+<?php
+/**
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+error_reporting(E_ALL);
+
+/** */
+require_once( "commandLine.inc" );
+require_once( 'includes/SpecialExport.php' );
+
+/** */
+function dumpReplayLog( $start ) {
+       $dbw =& wfGetDB( DB_MASTER );
+       $recentchanges = $dbw->tableName( 'recentchanges' );
+       $result =& $dbw->safeQuery( "SELECT * FROM $recentchanges WHERE rc_timestamp >= "
+               . $dbw->timestamp( $start ) . ' ORDER BY rc_timestamp');
+       
+       global $wgInputEncoding;
+       echo '<' . '?xml version="1.0" encoding="' . $wgInputEncoding . '" ?' . ">\n";
+       echo "<wikilog version='experimental'>\n";
+       echo "<!-- Do not use this script for any purpose. It's scary. -->\n";
+       while( $row = $dbw->fetchObject( $result ) ) {
+               echo dumpReplayEntry( $row );
+       }
+       echo "</wikilog>\n";
+       $dbw->freeResult( $result );
+}
+
+/** */
+function dumpReplayEntry( $row ) {
+       $title = Title::MakeTitle( $row->rc_namespace, $row->rc_title );
+       switch( $row->rc_type ) {
+       case RC_EDIT:
+       case RC_NEW:
+               # Edit
+               $dbr =& wfGetDB( DB_MASTER );
+               
+               $out = "  <edit>\n";
+               $out .= "    <title>" . xmlsafe( $title->getPrefixedText() ) . "</title>\n";
+               
+               # Get previous edit timestamp
+               if( $row->rc_last_oldid ) {
+                       $s = $dbr->selectRow( 'old',
+                               array( 'old_timestamp' ),
+                               array( 'old_id' => $row->rc_last_oldid ) );
+                       $out .= "    <lastedit>" . wfTimestamp2ISO8601( $s->old_timestamp ) . "</lastedit>\n";
+               } else {
+                       $out .= "    <newpage/>\n";
+               }
+               
+               if( $row->rc_this_oldid ) {
+                       $s = $dbr->selectRow( 'old', array( 'old_id as id','old_timestamp as timestamp', 
+                               'old_user as user', 'old_user_text as user_text', 'old_comment as comment', 
+                               'old_text as text', 'old_flags as flags' ),
+                               array( 'old_id' => $row->rc_this_oldid ) );
+                       $out .= revision2xml( $s, true, false );
+               } else {
+                       $s = $dbr->selectRow( 'cur', array( 'cur_id as id','cur_timestamp as timestamp','cur_user as user',
+                               'cur_user_text as user_text', 'cur_restrictions as restrictions','cur_comment as comment',
+                               'cur_text as text' ),
+                               array( 'cur_id' => $row->rc_cur_id ) );
+                       $out .= revision2xml( $s, true, true );
+               }
+               $out .= "  </edit>\n";
+               break;
+       case RC_LOG:
+               $dbr =& wfGetDB( DB_MASTER );
+               $s = $dbr->selectRow( 'logging',
+                       array( 'log_type', 'log_action', 'log_timestamp', 'log_user',
+                               'log_namespace', 'log_title', 'log_comment' ),
+                       array( 'log_timestamp' => $row->rc_timestamp,
+                              'log_user'      => $row->rc_user ) );
+               $ts = wfTimestamp2ISO8601( $row->rc_timestamp );
+               $target = Title::MakeTitle( $s->log_namespace, $s->log_title );
+               $out  = "  <log>\n";
+               $out .= "    <type>" . xmlsafe( $s->log_type ) . "</type>\n";
+               $out .= "    <action>" . xmlsafe( $s->log_action ) . "</action>\n";
+               $out .= "    <timestamp>" . $ts . "</timestamp>\n";
+               $out .= "    <contributor><username>" . xmlsafe( $row->rc_user_text ) . "</username></contributor>\n";
+               $out .= "    <target>" . xmlsafe( $target->getPrefixedText() ) . "</target>\n";
+               $out .= "    <comment>" . xmlsafe( $s->log_comment ) . "</comment>\n";
+               $out .= "  </log>\n";
+               break;
+       case RC_MOVE:
+       case RC_MOVE_OVER_REDIRECT:
+               $target = Title::MakeTitle( $row->rc_moved_to_ns, $row->rc_moved_to_title );
+               $out  = "  <move>\n";
+               $out .= "    <title>" . xmlsafe( $title->getPrefixedText() ) . "</title>\n";
+               $out .= "    <target>" . xmlsafe( $target->getPrefixedText() ) . "</target>\n";
+               if( $row->rc_type == RC_MOVE_OVER_REDIRECT ) {
+                       $out .= "    <override/>\n";
+               }
+               $ts = wfTimestamp2ISO8601( $row->rc_timestamp );
+               $out .= "    <id>$row->rc_cur_id</id>\n";
+               $out .= "    <timestamp>$ts</timestamp>\n";
+               if($row->rc_user_text) {
+                       $u = "<username>" . xmlsafe( $row->rc_user_text ) . "</username>";
+                       $u .= "<id>$row->rc_user</id>";
+               } else {
+                       $u = "<ip>" . xmlsafe( $row->rc_user_text ) . "</ip>";
+               }
+               $out .= "    <contributor>$u</contributor>\n";
+               $out .= "  </move>\n";
+       }
+       return $out;
+}
+
+
+if( isset( $options['start'] ) ) {
+       $start = wfTimestamp( TS_MW, $options['start'] );
+       dumpReplayLog( $start );
+} else {
+       echo "This is an experimental script to encapsulate data from recent edits.\n";
+       echo "Usage:  php dumpReplayLog.php --start=20050118032544\n";
+}
+
+?>
\ No newline at end of file
diff --git a/maintenance/dumpRev.php b/maintenance/dumpRev.php
new file mode 100644 (file)
index 0000000..b665d93
--- /dev/null
@@ -0,0 +1,20 @@
+<?php
+/**
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+/** */
+require_once( 'commandLine.inc' );
+$dbr =& wfGetDB( DB_SLAVE );
+$row = $dbr->selectRow( 'old', array( 'old_flags', 'old_text' ), array( 'old_id' => $args[0] ) );
+$obj = unserialize( $row->old_text );
+
+if ( get_class( $obj ) == 'concatenatedgziphistoryblob' ) {
+       print_r( array_keys( $obj->mItems ) );
+} else {
+       var_dump( $obj );
+}
+
+?>
diff --git a/maintenance/duplicatetrans.php b/maintenance/duplicatetrans.php
new file mode 100644 (file)
index 0000000..89d9cff
--- /dev/null
@@ -0,0 +1,29 @@
+<?php
+/**
+ * Prints out messages that are the same as the message with the corrisponding
+ * key in the Language.php file
+ *
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+require_once('commandLine.inc');
+
+if ( 'en' == $wgLanguageCode ) {
+       print "Current selected language is English. Cannot check translations.\n";
+       exit();
+}
+
+$count = $total = 0;
+$msgarray = 'wgAllMessages' . ucfirst( $wgLanguageCode );
+
+foreach ( $$msgarray as $code => $msg ) {
+       ++$total;
+       if ( @$wgAllMessagesEn[$code] == $msg ) {
+               echo "* $code\n";
+               ++$count;
+       }
+}
+
+echo "{$count} messages of {$total} are duplicates\n";
+?>
diff --git a/maintenance/entities2literals.pl b/maintenance/entities2literals.pl
new file mode 100644 (file)
index 0000000..dd47f6b
--- /dev/null
@@ -0,0 +1,276 @@
+#!/usr/bin/env perl
+# Takes STDIN and converts Converts hexadecimal, decimal and named HTML
+# entities to their respective literals.
+#
+# Usage: perl entities2literals.pl < file_to_convert [> outfile]
+# Reference: http://www.w3.org/TR/REC-html40/sgml/entities.html
+# Copyright 2005 Ævar Arnfjörð Bjarmason <avarab@gmail.com> No rights reserved
+
+use encoding 'utf8';
+use strict;
+
+my $file = join /\n/, <>;
+
+$file =~ s/&#(\d+);/chr $1/eg;
+$file =~ s/&#x([0-9a-fA-F]+);/chr hex $1/eg;
+
+while (<DATA>) {
+       chomp;
+       my ($number, $entity) = split / +/;
+       $file =~ s/&$entity;/chr $number/eg;
+}
+print $file;
+
+__DATA__
+34   quot
+38   amp
+60   lt
+62   gt
+160  nbsp
+161  iexcl
+162  cent
+163  pound
+164  curren
+165  yen
+166  brvbar
+167  sect
+168  uml
+169  copy
+170  ordf
+171  laquo
+172  not
+173  shy
+174  reg
+175  macr
+176  deg
+177  plusmn
+178  sup2
+179  sup3
+180  acute
+181  micro
+182  para
+183  middot
+184  cedil
+185  sup1
+186  ordm
+187  raquo
+188  frac14
+189  frac12
+190  frac34
+191  iquest
+192  Agrave
+193  Aacute
+194  Acirc
+195  Atilde
+196  Auml
+197  Aring
+198  AElig
+199  Ccedil
+200  Egrave
+201  Eacute
+202  Ecirc
+203  Euml
+204  Igrave
+205  Iacute
+206  Icirc
+207  Iuml
+208  ETH
+209  Ntilde
+210  Ograve
+211  Oacute
+212  Ocirc
+213  Otilde
+214  Ouml
+215  times
+216  Oslash
+217  Ugrave
+218  Uacute
+219  Ucirc
+220  Uuml
+221  Yacute
+222  THORN
+223  szlig
+224  agrave
+225  aacute
+226  acirc
+227  atilde
+228  auml
+229  aring
+230  aelig
+231  ccedil
+232  egrave
+233  eacute
+234  ecirc
+235  euml
+236  igrave
+237  iacute
+238  icirc
+239  iuml
+240  eth
+241  ntilde
+242  ograve
+243  oacute
+244  ocirc
+245  otilde
+246  ouml
+247  divide
+248  oslash
+249  ugrave
+250  uacute
+251  ucirc
+252  uuml
+253  yacute
+254  thorn
+255  yuml
+338  OElig
+339  oelig
+352  Scaron
+353  scaron
+376  Yuml
+402  fnof
+710  circ
+732  tilde
+913  Alpha
+914  Beta
+915  Gamma
+916  Delta
+917  Epsilon
+918  Zeta
+919  Eta
+920  Theta
+921  Iota
+922  Kappa
+923  Lambda
+924  Mu
+925  Nu
+926  Xi
+927  Omicron
+928  Pi
+929  Rho
+931  Sigma
+932  Tau
+933  Upsilon
+934  Phi
+935  Chi
+936  Psi
+937  Omega
+945  alpha
+946  beta
+947  gamma
+948  delta
+949  epsilon
+950  zeta
+951  eta
+952  theta
+953  iota
+954  kappa
+955  lambda
+956  mu
+957  nu
+958  xi
+959  omicron
+960  pi
+961  rho
+962  sigmaf
+963  sigma
+964  tau
+965  upsilon
+966  phi
+967  chi
+968  psi
+969  omega
+977  thetasym
+978  upsih
+982  piv
+8194 ensp
+8195 emsp
+8201 thinsp
+8204 zwnj
+8205 zwj
+8206 lrm
+8207 rlm
+8211 ndash
+8212 mdash
+8216 lsquo
+8217 rsquo
+8218 sbquo
+8220 ldquo
+8221 rdquo
+8222 bdquo
+8224 dagger
+8225 Dagger
+8226 bull
+8230 hellip
+8240 permil
+8242 prime
+8243 Prime
+8249 lsaquo
+8250 rsaquo
+8254 oline
+8260 frasl
+8364 euro
+8465 image
+8472 weierp
+8476 real
+8482 trade
+8501 alefsym
+8592 larr
+8593 uarr
+8594 rarr
+8595 darr
+8596 harr
+8629 crarr
+8656 lArr
+8657 uArr
+8658 rArr
+8659 dArr
+8660 hArr
+8704 forall
+8706 part
+8707 exist
+8709 empty
+8711 nabla
+8712 isin
+8713 notin
+8715 ni
+8719 prod
+8721 sum
+8722 minus
+8727 lowast
+8730 radic
+8733 prop
+8734 infin
+8736 ang
+8743 and
+8744 or
+8745 cap
+8746 cup
+8747 int
+8756 there4
+8764 sim
+8773 cong
+8776 asymp
+8800 ne
+8801 equiv
+8804 le
+8805 ge
+8834 sub
+8835 sup
+8836 nsub
+8838 sube
+8839 supe
+8853 oplus
+8855 otimes
+8869 perp
+8901 sdot
+8968 lceil
+8969 rceil
+8970 lfloor
+8971 rfloor
+9001 lang
+9002 rang
+9674 loz
+9824 spades
+9827 clubs
+9829 hearts
+9830 diams
diff --git a/maintenance/eval.php b/maintenance/eval.php
new file mode 100644 (file)
index 0000000..e211830
--- /dev/null
@@ -0,0 +1,44 @@
+<?php
+/**
+ * PHP lacks an interactive mode, but this can be very helpful when debugging.
+ * This script lets a command-line user start up the wiki engine and then poke
+ * about by issuing PHP commands directly.
+ *
+ * Unlike eg Python, you need to use a 'return' statement explicitly for the
+ * interactive shell to print out the value of the expression. Multiple lines
+ * are evaluated separately, so blocks need to be input without a line break.
+ * Fatal errors such as use of undeclared functions can kill the shell.
+ *
+ * To get decent line editing behavior, you should compile PHP with support 
+ * for GNU readline (pass --with-readline to configure).
+ *
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+$wgForceLoadBalancing = (getenv('MW_BALANCE') ? true : false);
+$wgUseNormalUser = (getenv('MW_WIKIUSER') ? true : false);
+
+/** */
+require_once( "commandLine.inc" );
+
+$line = readconsole( "> " );
+
+while ( $line !== false ) {
+       $val = eval( $line . ";" );
+       if( is_null( $val ) ) {
+               echo "\n";
+       } elseif( is_string( $val ) || is_numeric( $val ) ) {
+               echo "$val\n";
+       } else {
+               var_dump( $val );
+       }
+       if ( function_exists( "readline_add_history" ) ) {
+               readline_add_history( $line );
+       }
+       $line = readconsole( "> " );
+}
+
+print "\n";
+
+?>
diff --git a/maintenance/fetchInterwiki.pl b/maintenance/fetchInterwiki.pl
new file mode 100644 (file)
index 0000000..cb56a6d
--- /dev/null
@@ -0,0 +1,102 @@
+#!/usr/bin/env perl
+# Copyright (C) 2005 Ævar Arnfjörð Bjarmason
+use strict;
+use warnings;
+use Socket;
+
+# Conf
+my $map = &get(&url('http://usemod.com/intermap.txt'));
+
+# --- #
+my $cont;
+my @map = split /\n/, $map;
+
+$cont .= '<?php
+# Note: this file is generated by maintenance/fetchInterwiki.pl
+# Edit and rerun that script rather than modifying this directly.
+
+/* private */ $wgValidInterwikis = array(
+';
+
+$cont .= "\t# The usemod interwiki map\n";
+for (my $i=0;$i<=$#map;++$i) {
+       my ($name, $url) = $map[$i] =~ m#^([^ ]+) (.+)#i;
+       $cont .= "\t'$name' => '$url\$1',\n";
+}
+
+my @iso = qw(
+aa ab af als am ar as ay az ba be bg bh bi bn bo bs ca chr co cs csb cy da de dk:da dz el en eo
+es et eu fa fi fj fo fr fy ga gd gl gn gu gv ha he hi hr hu hy ia id ik io is it iu ja jv ka kk
+kl km kn ko ks ku ky la lo lt lv mg mi mk ml mn mo mr ms my na nah nb nds ne nl no oc om or pa
+pl ps pt qu rm rn ro ru rw sa sd sg sh si sk sl sm sn so sq sr ss st su sv sw ta te tg th ti tk
+tl tn to tp tpi tr ts tt tw ug uk ur uz vi vo wa wo xh yi yo za zh zh-cn zh-tw zu);
+
+$cont .= '
+       # Some custom additions:
+       "ReVo"  =>      "http://purl.org/NET/voko/revo/art/$1.html",
+         # eg [[ReVo:cerami]], [[ReVo:astero]] - note X-sensitive!
+       "EcheI" =>      "http://www.ikso.net/cgi-bin/wiki.pl?$1",
+       "E\\xc4\\x89eI" =>      "http://www.ikso.net/cgi-bin/wiki.pl?$1",
+       "UnuMondo"      =>      "http://unumondo.com/cgi-bin/wiki.pl?$1", # X-sensitive!
+       "JEFO"  =>      "http://esperanto.jeunes.free.fr/vikio/index.php?$1",
+       "PMEG"  =>      "http://www.bertilow.com/pmeg/$1.php",
+               # ekz [[PMEG:gramatiko/kunligaj vortetoj/au]]
+       "EnciclopediaLibre" => "http://enciclopedia.us.es/wiki.phtml?title=$1",
+
+       # Wikipedia-specific stuff:
+       # Special cases
+       "w"             => "http://www.wikipedia.org/wiki/$1",
+       "m"             => "http://meta.wikipedia.org/wiki/$1",
+       "meta"          => "http://meta.wikipedia.org/wiki/$1",
+       "sep11"         => "http://sep11.wikipedia.org/wiki/$1",
+       "simple"=> "http://simple.wikipedia.com/wiki.cgi?$1",
+       "wiktionary"    => "http://wiktionary.wikipedia.org/wiki/$1",
+       "PageHistory" => "http://www.wikipedia.org/w/wiki.phtml?title=$1&action=history",
+       "UserContributions" => "http://www.wikipedia.org/w/wiki.phtml?title=Special:Contributions&target=$1",
+       "BackLinks" => "http://www.wikipedia.org/w/wiki.phtml?title=Special:Whatlinkshere&target=$1",
+
+       # ISO 639 2-letter language codes
+';
+
+for(my $i=0; $i<=$#iso;++$i) {
+       my @arr = split /:/, $iso[$i];
+       $cont .= "\t";
+       $cont .= "'$arr[0]' => 'http://";
+       
+       if ($arr[1]) {
+               $cont .= $arr[1];
+       } else {
+               $cont .= $arr[0];
+       }
+       $cont .= ".wikipedia.org/wiki/\$1',\n";
+}
+
+$cont .= '
+);
+?>
+';
+
+open IW, ">Interwiki.php";
+print IW $cont;
+close IW;
+
+sub get {
+       my ($host, $url) = @_;
+       my $cont;
+       my $eat;
+
+       my $proto = getprotobyname('tcp');
+       socket(Socket, AF_INET, SOCK_STREAM, $proto);
+       my $iaddr = inet_aton("$host");
+       my $port = getservbyname('http', 'tcp');
+       my $sin = sockaddr_in($port, $iaddr);
+       connect(Socket, $sin);
+       send Socket, "GET $url HTTP/1.0\r\nHost: $host\r\n\r\n",0;
+       while (<Socket>) {
+               $cont .= $_ if $eat; # mmm, food
+               ++$eat if ($_ =~ /^(\n|\r\n|)$/);
+       }
+       return $cont;
+}
+
+sub url {my ($server, $path) = $_[0] =~ m#.*(?=//)//([^/]*)(.*)#g;}
diff --git a/maintenance/importDump.php b/maintenance/importDump.php
new file mode 100644 (file)
index 0000000..f4e8d3c
--- /dev/null
@@ -0,0 +1,141 @@
+<?php
+/**
+ * Copyright (C) 2005 Brion Vibber <brion@pobox.com>
+ * http://www.mediawiki.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+$optionsWithArgs = array( 'report' );
+
+require_once( 'commandLine.inc' );
+require_once( 'SpecialImport.php' );
+
+class BackupReader {
+       var $reportingInterval = 100;
+       var $reporting = true;
+       var $pageCount = 0;
+       var $revCount  = 0;
+       var $dryRun    = false;
+
+       function BackupReader() {
+               $this->stderr = fopen( "php://stderr", "wt" );
+       }
+
+       function reportPage( $page ) {
+               $this->pageCount++;
+       }
+
+       function handleRevision( $rev ) {
+               $title = $rev->getTitle();
+               if (!$title) {
+                       $this->progress( "Got bogus revision with null title!" );
+                       return;
+               }
+               $display = $title->getPrefixedText();
+               $timestamp = $rev->getTimestamp();
+               #echo "$display $timestamp\n";
+
+               $this->revCount++;
+               $this->report();
+
+               if( !$this->dryRun ) {
+                       call_user_func( $this->importCallback, $rev );
+               }
+       }
+
+       function report( $final = false ) {
+               if( $final xor ( $this->pageCount % $this->reportingInterval == 0 ) ) {
+                       $this->showReport();
+               }
+       }
+
+       function showReport() {
+               if( $this->reporting ) {
+                       $delta = wfTime() - $this->startTime;
+                       if( $delta ) {
+                               $rate = $this->pageCount / $delta;
+                               $revrate = $this->revCount / $delta;
+                       } else {
+                               $rate = '-';
+                               $revrate = '-';
+                       }
+                       $this->progress( "$this->pageCount ($rate pages/sec $revrate revs/sec)" );
+               }
+       }
+
+       function progress( $string ) {
+               fwrite( $this->stderr, $string . "\n" );
+       }
+
+       function importFromFile( $filename ) {
+               if( preg_match( '/\.gz$/', $filename ) ) {
+                       $filename = 'compress.zlib://' . $filename;
+               }
+               $file = fopen( $filename, 'rt' );
+               return $this->importFromHandle( $file );
+       }
+
+       function importFromStdin() {
+               $file = fopen( 'php://stdin', 'rt' );
+               return $this->importFromHandle( $file );
+       }
+
+       function importFromHandle( $handle ) {
+               $this->startTime = wfTime();
+
+               $source = new ImportStreamSource( $handle );
+               $importer = new WikiImporter( $source );
+
+               $importer->setPageCallback( array( &$this, 'reportPage' ) );
+               $this->importCallback =  $importer->setRevisionCallback(
+                       array( &$this, 'handleRevision' ) );
+
+               return $importer->doImport();
+       }
+}
+
+if( wfReadOnly() ) {
+       die( "Wiki is in read-only mode; you'll need to disable it for import to work.\n" );
+}
+
+$reader = new BackupReader();
+if( isset( $options['quiet'] ) ) {
+       $reader->reporting = false;
+}
+if( isset( $options['report'] ) ) {
+       $reader->reportingInterval = intval( $options['report'] );
+}
+if( isset( $options['dry-run'] ) ) {
+       $reader->dryRun = true;
+}
+
+if( isset( $args[0] ) ) {
+       $result = $reader->importFromFile( $args[0] );
+} else {
+       $result = $reader->importFromStdin();
+}
+
+if( WikiError::isError( $result ) ) {
+       echo $result->getMessage() . "\n";
+} else {
+       echo "Done!\n";
+}
+
+?>
diff --git a/maintenance/importLogs.inc b/maintenance/importLogs.inc
new file mode 100644 (file)
index 0000000..c31f1c7
--- /dev/null
@@ -0,0 +1,144 @@
+<?php
+# Copyright (C) 2004 Brion Vibber <brion@pobox.com>
+# http://www.mediawiki.org/
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or 
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# http://www.gnu.org/copyleft/gpl.html
+
+/**
+ * Attempt to import existing log pages into the log tables.
+ *
+ * Not yet complete.
+ *
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+/** */
+require_once( 'GlobalFunctions.php' );
+require_once( 'Database.php' );
+require_once( 'Article.php' );
+require_once( 'LogPage.php' );
+
+/**
+ * Log importer
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+class LogImporter {
+       var $dummy = false;
+       
+       function LogImporter( $type ) {
+               $this->type = $type;
+               $this->db =& wfGetDB( DB_MASTER );
+               $this->actions = $this->setupActions();
+       }
+       
+       function setupActions() {
+               $actions = array();
+               foreach( LogPage::validActions( $this->type ) as $action ) {
+                       $key = "{$this->type}/$action";
+                       $actions[$key] = $this->makeLineRegexp( $this->type, $action );
+               }
+               return $actions;
+       }
+       
+       function makeLineRegexp( $type, $action ) {
+               $linkRegexp = '(?:\[\[)?([^|\]]+?)(?:\|[^\]]+?)?(?:\]\])?';
+               $linkRegexp2 = '\[\[([^|\]]+?)(?:\|[^\]]+?)?\]\]';
+               
+               $text = LogPage::actionText( $type, $action );
+               $text = preg_quote( $text, '/' );
+               $text = str_replace( '\$1', $linkRegexp, $text );
+               $text = '^(.*?) ' . $linkRegexp2 . ' ' . $text;
+               $text .= '(?: <em>\((.*)\)<\/em>)?';
+               $text = "/$text/";
+               return $text;
+       }
+       
+       function importText( $text ) {
+               if( $this->dummy ) {
+                       print $text;
+                       var_dump( $this->actions );
+               }
+               $lines = explode( '<li>', $text );
+               foreach( $lines as $line ) {
+                       if( preg_match( '!^(.*)</li>!', $line, $matches ) ) {
+                               $this->importLine( $matches[1] );
+                       }
+               }
+       }
+       
+       function fixDate( $date ) {
+               # Yuck! Parsing multilingual date formats??!!!!???!!??!
+               # 01:55, 23 Aug 2004 - won't take in strtotimr
+               # "Aug 23 2004 01:55" - seems ok
+               # TODO: multilingual attempt to extract from the data in Language
+               if( preg_match( '/^(\d+:\d+(?::\d+)?), (.*)$/', $date, $matches ) ) {
+                       $date = $matches[2] . ' ' . $matches[1];
+               }
+               $n = strtotime( $date ) + date("Z");
+               # print gmdate( 'D, d M Y H:i:s T', $n ) . "\n";
+               $timestamp = wfTimestamp( TS_MW, $n );
+               return $timestamp;
+       }
+       
+       function importLine( $line ) {
+               foreach( $this->actions as $action => $regexp ) {
+                       if( preg_match( $regexp, $line, $matches ) ) {
+                               if( $this->dummy ) {
+                                       #var_dump( $matches );
+                               }
+                               $date = $this->fixDate( $matches[1] );
+                               $user = Title::newFromText( $matches[2] );
+                               $target = Title::newFromText( $matches[3] );
+                               if( isset( $matches[4] ) ) {
+                                       $comment = $matches[4];
+                               } else {
+                                       $comment = '';
+                               }
+                               
+                               $insert = array(
+                                       'log_type' => $this->type,
+                                       'log_action' => preg_replace( '!^.*/!', '', $action ),
+                                       'log_timestamp' => $date,
+                                       'log_user' => IntVal( User::idFromName( $user->getText() ) ),
+                                       'log_namespace' => $target->getNamespace(),
+                                       'log_title' => $target->getDBkey(),
+                                       'log_comment' => wfUnescapeWikiText( $comment ),
+                               );
+                               if( $this->dummy ) {
+                                       var_dump( $insert );
+                               } else {
+                                       # FIXME: avoid duplicates!
+                                       $this->db->insert( 'logging', $insert );
+                               }
+                               break;
+                       }
+               }
+       }
+}
+
+function wfUnescapeWikiText( $text ) {
+       $text = str_replace( 
+               array( '&#91;', '&#124;', '&#39;', 'ISBN&#32;', '&#58;//' , "\n&#61;", '&#123;&#123;' ),
+               array( '[',             '|',      "'",     'ISBN '        , '://'         , "\n=", '{{' ),
+               $text );
+       return $text;
+}
+
+?>
diff --git a/maintenance/importLogs.php b/maintenance/importLogs.php
new file mode 100644 (file)
index 0000000..00bb662
--- /dev/null
@@ -0,0 +1,27 @@
+<?php
+/**
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+/** */
+require_once( "commandLine.inc" );
+require_once( "importLogs.inc" );
+
+#print $text;
+#exit();
+
+foreach( LogPage::validTypes() as $type ) {
+       if( $type == '' ) continue;
+       
+       $page = LogPage::logName( $type );
+       $log = new Article( Title::makeTitleSafe( NS_PROJECT, $page ) );
+       $text = $log->getContentWithoutUsingSoManyDamnGlobals();
+
+       $importer = new LogImporter( $type );
+       $importer->dummy = true;
+       $importer->importText( $text );
+}
+
+?>
diff --git a/maintenance/importPhase2.php b/maintenance/importPhase2.php
new file mode 100644 (file)
index 0000000..e53097b
--- /dev/null
@@ -0,0 +1,370 @@
+<?php
+# MediaWiki 'phase 2' to current format import script
+# (import format current as of 1.2.0, March 2004)
+# 
+# Copyright (C) 2004 Brion Vibber <brion@pobox.com>
+# Portions by Lee Daniel Crocker, 2002
+# http://www.mediawiki.org/
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or 
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# http://www.gnu.org/copyleft/gpl.html
+
+/**
+ * @todo document
+ * @deprecated
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+/** */
+die( "This import script is not currently maintained.
+If you need it you'll have to modify it as necessary.\n");
+
+if ( ! is_readable( "../LocalSettings.php" ) ) {
+       print "A copy of your installation's LocalSettings.php\n" .
+         "must exist in the source directory.\n";
+       exit();
+}
+
+$wgCommandLineMode = true;
+ini_set("implicit_flush", 1);
+
+$DP = "../includes";
+require_once( "../LocalSettings.php" );
+require_once( "../AdminSettings.php" );
+
+$wgDBuser = $wgDBadminuser;
+$wgDBpassword = $wgDBadminpassword;
+
+$sep = ( DIRECTORY_SEPARATOR == "\\" ) ? ";" : ":";
+ini_set( "include_path", "$IP$sep$include_path" );
+
+require_once( "Setup.php" );
+
+require_once( "../install-utils.inc" );
+require_once( "InitialiseMessages.inc" );
+require_once( "rebuildlinks.inc" );
+require_once( "rebuildrecentchanges.inc" );
+require_once( "rebuildtextindex.inc" );
+
+/**
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+class Phase2Importer {
+       var $olddb, $titleCache;
+       
+       function Phase2Importer( $database ) {
+               $this->olddb = $database;
+               $this->titleCache = new TitleCache;
+       }
+       
+       function importAll() {
+               $this->importCurData();
+               $this->fixCurTitles();
+               
+               $this->importOldData();
+               $this->fixOldTitles();
+               
+               $this->importUserData();
+               $this->fixUserOptions();
+               
+               $this->importWatchlists();
+               
+               $this->importLinkData();
+
+               /*
+               # For some reason this is broken. RecentChanges will just start anew...
+               rebuildRecentChangesTablePass1();
+               rebuildRecentChangesTablePass2();
+               */
+               
+               print "Rebuilding search index:\n";
+               dropTextIndex();
+               rebuildTextIndex();
+               createTextIndex();
+               
+               initialiseMessages();
+       }
+       
+       # Simple import functions; for the most part these are pretty straightforward.
+       # MySQL copies everything over to the new database and tweaks a few things.
+       function importCurData() {
+               print "Clearing pages from default install, if any...\n";
+               wfQuery( "DELETE FROM cur", DB_MASTER );
+               
+               print "Importing current revision data...\n";
+               wfQuery( "INSERT INTO cur (cur_id,cur_namespace,cur_title,cur_text,cur_comment,
+                       cur_user,cur_user_text,cur_timestamp,cur_restrictions,cur_counter,
+                       cur_is_redirect,cur_minor_edit,cur_is_new,cur_random,cur_touched)
+                       SELECT cur_id,0,cur_title,cur_text,cur_comment,
+                               cur_user,cur_user_text,cur_timestamp,REPLACE(cur_restrictions,'is_',''),cur_counter,
+                               cur_text like '#redirect%',cur_minor_edit,0,RAND(),NOW()+0,
+                       FROM {$this->olddb}.cur", DB_MASTER );
+               $n = mysql_affected_rows();
+               print "$n rows imported.\n";
+       }
+
+       function importOldData() {
+               print "Clearing old revision data from default install, if any...\n";
+               wfQuery( "DELETE FROM old", DB_MASTER );
+
+               print "Importing old revision data...\n";
+               wfQuery( "INSERT INTO old (old_id,old_namespace,old_title,old_text,old_comment,
+                       old_user,old_user_text,old_timestamp,old_minor_edit,old_flags)
+                       SELECT old_id,0,old_title,old_text,old_comment,
+                               old_user,old_user_text,old_timestamp,old_minor_edit,''
+                       FROM {$this->olddb}.old", DB_MASTER );
+               $n = mysql_affected_rows();
+               print "$n rows imported.\n";
+       }
+
+       function importUserData() {
+               print "Clearing users from default install, if any...\n";
+               wfQuery( "DELETE FROM user", DB_MASTER );
+
+               print "Importing user data...\n";
+               wfQuery( "INSERT INTO $newdb.user (user_id,user_name,user_rights,
+                       user_password,user_newpassword,user_email,user_options,user_touched)
+                       SELECT user_id,user_name,REPLACE(user_rights,'is_',''),
+                               MD5(CONCAT(user_id,'-',MD5(user_password))),'',user_email,user_options,NOW()+0
+                       FROM {$this->olddb}.user", DB_MASTER );
+               $n = mysql_affected_rows();
+               print "$n rows imported.\n";
+       }
+
+       # A little less clean...
+       function importWatchlists() {
+               print "Clearing watchlists from default install, if any...\n";
+               wfQuery( "DELETE FROM watchlist", DB_MASTER );
+
+               print "Importing watchlists...";
+               $res = wfQuery( "SELECT user_id,user_watch FROM {$this->olddb}.user WHERE user_watch != ''", DB_MASTER );
+               $total = wfNumRows( $res );
+               $n = 0;
+               print " ($total total)\n";
+               
+               while( $row = wfFetchObject( $res ) ) {
+                       $id = IntVal( $row->user_id );
+                       $list = explode( "\n", $row->user_watch );
+                       foreach( $list as $page ) {
+                               $title = $this->titleCache->fetch( $page );
+                               if( is_null( $title ) ) {
+                                       print "Caught bad title '{$row->title}'\n";
+                               } else {
+                                       $ns = $title->getNamespace();
+                                       $t = wfStrencode( $title->getDBkey() );
+                                       wfQuery( "INSERT INTO watchlist(wl_user,wl_namespace,wl_title) VALUES ($id,$ns,'$t')", DB_MASTER );
+                               }
+                       }
+                       if( ++$n % 50 == 0 ) {
+                               print "$n\n";
+                       }
+               }
+               wfFreeResult( $res );
+       }
+       
+       function importLinkData() {
+               # MUST BE CALLED BEFORE! fixCurTitles()
+               print "Clearing links from default install, if any...\n";
+               wfQuery( "DELETE FROM links", DB_MASTER );
+               wfQuery( "DELETE FROM brokenlinks", DB_MASTER );
+
+               print "Importing live links...";
+               wfQuery( "INSERT INTO links (l_from, l_to)
+                                       SELECT DISTINCT linked_from,cur_id
+                                       FROM {$this->olddb}.linked,{$this->olddb}.cur
+                                       WHERE linked_to=cur_title", DB_MASTER );
+               $n = mysql_affected_rows();
+               print "$n rows imported.\n";
+               
+               print "Importing broken links...";
+               wfQuery( "INSERT INTO brokenlinks (bl_from, bl_to)
+                                       SELECT DISTINCT cur_id,unlinked_to
+                                       FROM {$this->olddb}.unlinked,{$this->olddb}.cur
+                                       WHERE unlinked_from=cur_title", DB_MASTER );
+               $n = mysql_affected_rows();
+               print "$n rows imported.\n";
+       }
+
+       # Fixup functions: munge data that's already been brought into tables
+       function fixCurTitles() {
+               $this->fixTitles( "cur" );
+       }
+       
+       function fixOldTitles() {
+               $this->fixTitles( "old" );
+       }
+       
+       function fixTitles( $table ) {
+               print "Fixing titles in $table...";
+               $res = wfQuery( "SELECT DISTINCT {$table}_title AS title FROM $table", DB_MASTER );
+               $total = wfNumRows( $res );
+               $n = 0;
+               print " ($total total)\n";
+               
+               while( $row = wfFetchObject( $res ) ) {
+                       $xt = wfStrencode( $row->title );
+                       $title = $this->titleCache->fetch( $row->title );
+                       if( is_null( $title ) ) {
+                               print "Caught bad title '{$row->title}'\n";
+                       } else {
+                               $ns = $title->getNamespace();
+                               $t = wfStrencode( $title->getDBkey() );
+                               wfQuery( "UPDATE $table SET {$table}_namespace=$ns,{$table}_title='$t'
+                                                               WHERE {$table}_namespace=0 AND {$table}_title='$xt'", DB_MASTER );
+                       }
+                       if( ++$n % 50 == 0 ) {
+                               print "$n\n";
+                       }
+               }
+               wfFreeResult( $res );
+       }
+
+       function rewriteUserOptions( $in )
+       {
+               $s = urldecode( $in );
+               $a = explode( "\n", $s );
+       
+               foreach ( $a as $l ) {
+                       if ( preg_match( "/^([A-Za-z0-9_]+)=(.*)/", $l, $m ) ) {
+                               $ops[$m[1]] = $m[2];
+                       }
+               }
+               $nops = array();
+       
+               $q = strtolower( $ops["quickBar"] );
+               if ( $q == "none" ) { $q = 0; }
+               else { $q = 1; } # Default to left
+               $nops["quickbar"] = $q;
+       
+               if ( $ops["markupNewTopics"] == "inverse" ) {
+                       $nops["highlightbroken"] = 1;
+               }
+               $sk = substr( strtolower( $ops["skin"] ), 0, 4 );
+               if ( "star" == $sk ) { $sk = 0; }
+               else if ( "nost" == $sk ) { $sk = 1; }
+               else if ( "colo" == $sk ) { $sk = 2; }
+               else { $sk = 0; }
+               $nops["skin"] = $sk;
+       
+               $u = strtolower( $ops["underlineLinks"] );
+               if ( "yes" == $u || "on" == $u ) { $nops["underline"] = 1; }
+               else { $nops["underline"] = 0; }
+       
+               $t = ( (int) ($ops["hourDiff"]) );
+               if ( $t < -23 || $t > 23 ) { $t = 0; }
+               if ( 0 != $t ) { $nops["timecorrection"] = $t; }
+       
+               $j = strtolower( $ops["justify"] );
+               if ( "yes" == $j || "on" == $j ) { $nops["justify"] = 1; }
+               $n = strtolower( $ops["numberHeadings"] );
+               if ( "yes" == $n || "on" == $n ) { $nops["numberheadings"] = 1; }
+               $h = strtolower( $ops["hideMinor"] );
+               if ( "yes" == $h || "on" == $h ) { $nops["hideminor"] = 1; }
+               $r = strtolower( $ops["rememberPassword"] );
+               if ( "yes" == $r || "on" == $r ) { $nops["rememberpassword"] = 1; }
+               $s = strtolower( $ops["showHover"] );
+               if ( "yes" == $s || "on" == $s ) { $nops["hover"] = 1; }
+       
+               $c = $ops["cols"];
+               if ( $c < 20 || $c > 200 ) { $nops["cols"] = 80; }
+               else { $nops["cols"] = $c; }
+               $r = $ops["rows"];
+               if ( $r < 5 || $r > 100 ) { $nops["rows"] = 20; }
+               else { $nops["rows"] = $r; }
+               $r = $ops["resultsPerPage"];
+               if ( $r < 3 || $r > 500 ) { $nops["searchlimit"] = 20; }
+               else { $nops["searchlimit"] = $r; }
+               $r = $ops["viewRecentChanges"];
+               if ( $r < 10 || $r > 1000 ) { $nops["rclimit"] = 50; }
+               else { $nops["rclimit"] = $r; }
+               $nops["rcdays"] = 3;
+       
+               $a = array();
+               foreach ( $nops as $oname => $oval ) {
+                       array_push( $a, "$oname=$oval" );
+               }
+               $s = implode( "\n", $a );
+               return $s;
+       }
+
+       function fixUserOptions() {
+               print "Fixing user options...";
+               $res = wfQuery( "SELECT user_id,user_options FROM user", DB_MASTER );
+               $total = wfNumRows( $res );
+               $n = 0;
+               print " ($total total)\n";
+               
+               while( $row = wfFetchObject( $res ) ) {
+                       $id = IntVal( $row->user_id );
+                       $option = wfStrencode( $this->rewriteUserOptions( $row->user_options ) );
+                       wfQuery( "UPDATE user SET user_options='$option' WHERE user_id=$id LIMIT 1", DB_MASTER );
+                       if( ++$n % 50 == 0 ) {
+                               print "$n\n";
+                       }
+               }
+               wfFreeResult( $res );
+       }
+       
+}
+
+/**
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+class TitleCache {
+       var $hash = array();
+       
+       function &fetch( $dbkey ) {
+               if( !isset( $hash[$dbkey] ) ) {
+                       $hash[$dbkey] = Title::newFromDBkey( $dbkey );
+               }
+               return $hash[$dbkey];
+       }
+       
+}
+
+#
+print "You should have already run the installer to create a fresh, blank database.\n";
+print "Data will be inserted into '$wgDBname'. THIS SHOULD BE EMPTY AND ANY DATA IN IN WILL BE ERASED!\n";
+print "\nIf that's not what you want, ABORT NOW!\n\n";
+
+print "Please enter the name of the old 'phase 2'-format database that will be used as a source:\n";
+print "Old database name [enciclopedia]: ";
+$olddb = readconsole();
+if( empty( $olddb ) ) $olddb = "enciclopedia";
+
+if( $olddb == $wgDBname ) {
+       die( "Can't upgrade in-place! You must create a new database and copy data into it.\n" );
+}
+
+print "\nSource database: '$olddb'\n";
+print "  Dest database: '$wgDBname'\n";
+print "Is this correct? Anything in '$wgDBname' WILL BE DESTROYED. [y/N] ";
+$response = readconsole();
+if( strtolower( $response{0} ) != 'y' ) {
+       die( "\nAborted by user.\n" );
+}
+
+print "Starting import....\n";
+
+$wgTitle = Title::newFromText( "Conversion script" );
+$importer = new Phase2Importer( $olddb );
+$importer->importAll();
+
+?>
diff --git a/maintenance/importUseModWiki.php b/maintenance/importUseModWiki.php
new file mode 100644 (file)
index 0000000..46eed2b
--- /dev/null
@@ -0,0 +1,363 @@
+<?php
+
+/**
+ * Import data from a UseModWiki into a MediaWiki wiki
+ * 2003-02-09 Brion VIBBER <brion@pobox.com>
+ * Based loosely on Magnus's code from 2001-2002
+ *
+ * Updated limited version to get something working temporarily
+ * 2003-10-09
+ * Be sure to run the link & index rebuilding scripts!
+ *
+ * Some more munging for charsets etc
+ * 2003-11-28
+ *
+ * Partial fix for pages starting with lowercase letters (??)
+ * and CamelCase and /Subpage link conversion
+ * 2004-11-17
+ *
+ * Rewrite output to create Special:Export format for import
+ * instead of raw SQL. Should be 'future-proof' against future
+ * schema changes.
+ * 2005-03-14
+ *
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+if( php_sapi_name() != 'cli' ) {
+       die( "Please customize the settings and run me from the command line." );
+}
+
+/** Set these correctly! */
+$wgImportEncoding = "CP1252"; /* We convert all to UTF-8 */
+$wgRootDirectory = "/kalman/Projects/wiki2002/wiki/lib-http/db/wiki";
+
+/* On a large wiki, you might run out of memory */
+@ini_set( 'memory_limit', '40M' );
+
+/* globals */
+$wgFieldSeparator = "\xb3"; # Some wikis may use different char
+       $FS = $wgFieldSeparator ;
+       $FS1 = $FS."1" ;
+       $FS2 = $FS."2" ;
+       $FS3 = $FS."3" ;
+
+# Unicode sanitization tools
+require_once( '../includes/normal/UtfNormal.php' );
+
+$usercache = array();
+
+importPages();
+
+# ------------------------------------------------------------------------------
+
+function importPages()
+{
+       global $wgRootDirectory;
+       
+       $gt = '>';
+       echo <<<END
+<?xml version="1.0" encoding="UTF-8" ?$gt
+<mediawiki xmlns="http://www.mediawiki.org/xml/export-0.1/"
+           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+           xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.1/
+                               http://www.mediawiki.org/xml/export-0.1.xsd"
+           version="0.1"
+           xml:lang="en">
+<!-- generated by importUseModWiki.php -->
+
+END;
+       $letters = array(
+               'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
+               'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
+               'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'other' );
+       foreach( $letters as $letter ) {
+               $dir = "$wgRootDirectory/page/$letter";
+               if( is_dir( $dir ) )
+                       importPageDirectory( $dir );
+       }
+       echo <<<END
+</mediawiki>
+
+END;
+}
+
+function importPageDirectory( $dir, $prefix = "" )
+{
+       echo "\n<!-- Checking page directory " . xmlCommentSafe( $dir ) . " -->\n";
+       $mydir = opendir( $dir );
+       while( $entry = readdir( $mydir ) ) {
+               if( preg_match( '/^(.+)\.db$/', $entry, $m ) ) {
+                       echo importPage( $prefix . $m[1] );
+               } else {
+                       if( is_dir( "$dir/$entry" ) ) {
+                               if( $entry != '.' && $entry != '..' ) {
+                                       importPageDirectory( "$dir/$entry", "$entry/" );
+                               }
+                       } else {
+                               echo "<!-- File '" . xmlCommentSafe( $entry ) . "' doesn't seem to contain an article. Skipping. -->\n";
+                       }
+               }
+       }
+}
+
+
+# ------------------------------------------------------------------------------
+
+/* fetch_ functions
+       Grab a given item from the database
+       */
+
+function useModFilename( $title ) {
+       $c = substr( $title, 0, 1 );
+       if(preg_match( '/[A-Z]/i', $c ) ) {
+               return strtoupper( $c ) . "/$title";
+       }
+       return "other/$title";
+}
+
+function fetchPage( $title )
+{
+       global $FS,$FS1,$FS2,$FS3, $wgRootDirectory;
+       
+       $fname = $wgRootDirectory . "/page/" . useModFilename( $title ) . ".db";
+       if( !file_exists( $fname ) ) {
+               die( "Couldn't open file '$fname' for page '$title'.\n" );
+       }
+       
+       $page = splitHash( $FS1, file_get_contents( $fname ) );
+       $section = splitHash( $FS2, $page["text_default"] );
+       $text = splitHash( $FS3, $section["data"] );
+       
+       return array2object( array( "text" => $text["text"] , "summary" => $text["summary"] ,
+               "minor" => $text["minor"] , "ts" => $section["ts"] ,
+               "username" => $section["username"] , "host" => $section["host"] ) );
+}
+
+function fetchKeptPages( $title )
+{
+       global $FS,$FS1,$FS2,$FS3, $wgRootDirectory, $wgTimezoneCorrection;
+       
+       $fname = $wgRootDirectory . "/keep/" . useModFilename( $title ) . ".kp";
+       if( !file_exists( $fname ) ) return array();
+       
+       $keptlist = explode( $FS1, file_get_contents( $fname ) );
+       array_shift( $keptlist ); # Drop the junk at beginning of file
+       
+       $revisions = array();
+       foreach( $keptlist as $rev ) {
+               $section = splitHash( $FS2, $rev );
+               $text = splitHash( $FS3, $section["data"] );
+               if ( $text["text"] && $text["minor"] != "" && ( $section["ts"]*1 > 0 ) ) {
+                       array_push( $revisions, array2object( array ( "text" => $text["text"] , "summary" => $text["summary"] ,
+                               "minor" => $text["minor"] , "ts" => $section["ts"] ,
+                               "username" => $section["username"] , "host" => $section["host"] ) ) );
+               } else {
+                       echo "<!-- skipped a bad old revision -->\n";
+               }
+       }
+       return $revisions;
+}
+
+function splitHash ( $sep , $str ) {
+       $temp = explode ( $sep , $str ) ;
+       $ret = array () ;
+       for ( $i = 0; $i+1 < count ( $temp ) ; $i++ ) {
+               $ret[$temp[$i]] = $temp[++$i] ;
+               }
+       return $ret ;
+       }
+
+
+/* import_ functions
+       Take a fetched item and produce SQL
+       */
+
+function checkUserCache( $name, $host )
+{
+       global $usercache;
+
+       if( $name ) {
+               if( in_array( $name, $usercache ) ) {
+                       $userid = $usercache[$name];
+               } else {
+                       # If we haven't imported user accounts
+                       $userid = 0;
+               }
+               $username = str_replace( '_', ' ', $name );
+       } else {
+               $userid = 0;
+               $username = $host;
+       }
+       return array( $userid, $username );
+}
+
+function importPage( $title )
+{
+       global $usercache;
+       
+       echo "\n<!-- Importing page " . xmlCommentSafe( $title ) . " -->\n";
+       $page = fetchPage( $title );
+
+       $newtitle = xmlsafe( str_replace( '_', ' ', recodeText( $title ) ) );
+       
+       $munged = mungeFormat( $page->text );
+       if( $munged != $page->text ) {
+               /**
+                * Save a *new* revision with the conversion, and put the
+                * previous last version into the history.
+                */
+               $next = array2object( array(
+                       'text'     => $munged,
+                       'minor'    => 1,
+                       'username' => 'Conversion script',
+                       'host'     => '127.0.0.1',
+                       'ts'       => time(),
+                       'summary'  => 'link fix',
+                       ) );
+               $revisions = array( $page, $next );
+       } else {
+               /**
+                * Current revision:
+                */
+               $revisions = array( $page );
+       }
+       $xml = <<<END
+       <page>
+               <title>$newtitle</title>
+
+END;
+
+       # History
+       $revisions = array_merge( $revisions, fetchKeptPages( $title ) );
+       if(count( $revisions ) == 0 ) {
+               return $sql;
+       }
+       
+       foreach( $revisions as $rev ) {
+               $text      = xmlsafe( recodeText( $rev->text ) );
+               $minor     = ($rev->minor ? '<minor/>' : '');
+               list( $userid, $username ) = checkUserCache( $rev->username, $rev->host );
+               $username  = xmlsafe( recodeText( $username ) );
+               $timestamp = xmlsafe( timestamp2ISO8601( $rev->ts ) );
+               $comment   = xmlsafe( recodeText( $rev->summary ) );
+               
+               $xml .= <<<END
+               <revision>
+                       <timestamp>$timestamp</timestamp>
+                       <contributor><username>$username</username></contributor>
+                       $minor
+                       <comment>$comment</comment>
+                       <text>$text</text>
+               </revision>
+
+END;
+       }
+       $xml .= "</page>\n\n";
+       return $xml;
+}
+
+# Whee!
+function recodeText( $string ) {
+       global $wgImportEncoding;
+       # For currently latin-1 wikis
+       $string = str_replace( "\r\n", "\n", $string );
+       $string = @iconv( $wgImportEncoding, "UTF-8", $string );
+       $string = wfMungeToUtf8( $string ); # Any old &#1234; stuff
+       return $string;
+}
+
+function wfUtf8Sequence($codepoint) {
+       if($codepoint <     0x80) return chr($codepoint);
+       if($codepoint <    0x800) return chr($codepoint >>  6 & 0x3f | 0xc0) .
+                                     chr($codepoint       & 0x3f | 0x80);
+    if($codepoint <  0x10000) return chr($codepoint >> 12 & 0x0f | 0xe0) .
+                                     chr($codepoint >>  6 & 0x3f | 0x80) .
+                                     chr($codepoint       & 0x3f | 0x80);
+       if($codepoint < 0x100000) return chr($codepoint >> 18 & 0x07 | 0xf0) . # Double-check this
+                                        chr($codepoint >> 12 & 0x3f | 0x80) .
+                                     chr($codepoint >>  6 & 0x3f | 0x80) .
+                                     chr($codepoint       & 0x3f | 0x80);
+       # Doesn't yet handle outside the BMP
+       return "&#$codepoint;";
+}
+
+function wfMungeToUtf8($string) {
+       $string = preg_replace ( '/&#([0-9]+);/e', 'wfUtf8Sequence($1)', $string );
+       $string = preg_replace ( '/&#x([0-9a-f]+);/ie', 'wfUtf8Sequence(0x$1)', $string );
+       # Should also do named entities here
+       return $string;
+}
+
+function timestamp2ISO8601( $ts ) {
+       #2003-08-05T18:30:02Z
+       return gmdate( 'Y-m-d', $ts ) . 'T' . gmdate( 'H:i:s', $ts ) . 'Z';
+}
+
+function xmlsafe( $string ) {
+       /**
+        * The page may contain old data which has not been properly normalized.
+        * Invalid UTF-8 sequences or forbidden control characters will make our
+        * XML output invalid, so be sure to strip them out.
+        */
+       $string = UtfNormal::cleanUp( $string );
+       
+       $string = htmlspecialchars( $string );
+       return $string;
+}
+
+function xmlCommentSafe( $text ) {
+       return str_replace( '--', '\\-\\-', xmlsafe( recodeText( $text ) ) );
+}
+
+
+function array2object( $arr ) {
+       $o = (object)0;
+       foreach( $arr as $x => $y ) {
+               $o->$x = $y;
+       }
+       return $o;
+}
+
+
+/**
+ * Make CamelCase and /Talk links work
+ */
+function mungeFormat( $text ) {
+       global $nowiki;
+       $nowiki = array();
+       $staged = preg_replace_callback(
+               '/(<nowiki>.*?<\\/nowiki>|(?:http|https|ftp):\\S+|\[\[[^]\\n]+]])/s',
+               'nowikiPlaceholder', $text );
+       
+       # This is probably not  100% correct, I'm just
+       # glancing at the UseModWiki code.
+       $upper   = "[A-Z]";
+       $lower   = "[a-z_0-9]";
+       $any     = "[A-Za-z_0-9]";
+       $camel   = "(?:$upper+$lower+$upper+$any*)";
+       $subpage = "(?:\\/$any+)";
+       $substart = "(?:\\/$upper$any*)";
+       
+       $munged = preg_replace( "/(?!\\[\\[)($camel$subpage*|$substart$subpage*)\\b(?!\\]\\]|>)/",
+               '[[$1]]', $staged );
+       
+       $final = preg_replace( '/' . preg_quote( placeholder() ) . '/es',
+               'array_shift( $nowiki )', $munged );
+       return $final;
+}
+
+
+function placeholder( $x = null ) {
+       return '\xffplaceholder\xff';
+}
+
+function nowikiPlaceholder( $matches ) {
+       global $nowiki;
+       $nowiki[] = $matches[1];
+       return placeholder();
+}
+
+?>
diff --git a/maintenance/initStats.php b/maintenance/initStats.php
new file mode 100644 (file)
index 0000000..7e02f48
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+
+require_once( 'commandLine.inc' );
+
+$dbr =& wfGetDB( DB_SLAVE );
+
+$edits = $dbr->selectField( 'revision', 'COUNT(rev_id)', '' );
+$pages = $dbr->selectField( 'page', 'COUNT(page_id)',
+       array(
+               'page_namespace' => 0,
+               'page_is_redirect' => 0,
+               'page_len > 0',
+       )
+); // HACK APPROXIMATION
+
+echo "$wgDBname: setting edits $edits, pages $pages\n";
+
+$dbw =& wfGetDB( DB_MASTER );
+$dbw->delete( 'site_stats', array( 'ss_row_id' => 1 ) );
+$dbw->insert( 'site_stats',
+       array( 'ss_row_id'=> 1,
+              'ss_total_views'   => 0,
+              'ss_total_edits'   => $edits,
+              'ss_good_articles' => $pages ) );
+
+?>
\ No newline at end of file
diff --git a/maintenance/interwiki.sql b/maintenance/interwiki.sql
new file mode 100644 (file)
index 0000000..ca656e4
--- /dev/null
@@ -0,0 +1,179 @@
+-- Based more or less on the public interwiki map from MeatballWiki
+-- Default interwiki prefixes...
+
+REPLACE INTO /*$wgDBprefix*/interwiki (iw_prefix,iw_url,iw_local) VALUES
+('abbenormal','http://www.ourpla.net/cgi-bin/pikie.cgi?$1',0),
+('acadwiki','http://xarch.tu-graz.ac.at/autocad/wiki/$1',0),
+('acronym','http://www.acronymfinder.com/af-query.asp?String=exact&Acronym=$1',0),
+('advogato','http://www.advogato.org/$1',0),
+('aiwiki','http://www.ifi.unizh.ch/ailab/aiwiki/aiw.cgi?$1',0),
+('alife','http://news.alife.org/wiki/index.php?$1',0),
+('annotation','http://bayle.stanford.edu/crit/nph-med.cgi/$1',0),
+('annotationwiki','http://www.seedwiki.com/page.cfm?wikiid=368&doc=$1',0),
+('arxiv','http://www.arxiv.org/abs/$1',0),
+('aspienetwiki','http://aspie.mela.de/Wiki/index.php?title=$1',0),
+('bemi','http://bemi.free.fr/vikio/index.php?$1',0),
+('benefitswiki','http://www.benefitslink.com/cgi-bin/wiki.cgi?$1',0),
+('brasilwiki','http://rio.ifi.unizh.ch/brasilienwiki/index.php/$1',0),
+('bridgeswiki','http://c2.com/w2/bridges/$1',0),
+('c2find','http://c2.com/cgi/wiki?FindPage&value=$1',0),
+('cache','http://www.google.com/search?q=cache:$1',0),
+('ciscavate','http://ciscavate.org/index.php/$1',0),
+('cliki','http://ww.telent.net/cliki/$1',0),
+('cmwiki','http://www.ourpla.net/cgi-bin/wiki.pl?$1',0),
+('codersbase','http://www.codersbase.com/$1',0),
+('commons','http://commons.wikimedia.org/wiki/$1',0),
+('consciousness','http://teadvus.inspiral.org/',0),
+('corpknowpedia','http://corpknowpedia.org/wiki/index.php/$1',0),
+('creationmatters','http://www.ourpla.net/cgi-bin/wiki.pl?$1',0),
+('dejanews','http://www.deja.com/=dnc/getdoc.xp?AN=$1',0),
+('demokraatia','http://wiki.demokraatia.ee/',0),
+('dictionary','http://www.dict.org/bin/Dict?Database=*&Form=Dict1&Strategy=*&Query=$1',0),
+('disinfopedia','http://www.disinfopedia.org/wiki.phtml?title=$1',0),
+('diveintoosx','http://diveintoosx.org/$1',0),
+('docbook','http://docbook.org/wiki/moin.cgi/$1',0),
+('dolphinwiki','http://www.object-arts.com/wiki/html/Dolphin/$1',0),
+('drumcorpswiki','http://www.drumcorpswiki.com/index.php/$1',0),
+('dwjwiki','http://www.suberic.net/cgi-bin/dwj/wiki.cgi?$1',0),
+('eĉei','http://www.ikso.net/cgi-bin/wiki.pl?$1',0),
+('echei','http://www.ikso.net/cgi-bin/wiki.pl?$1',0),
+('ecxei','http://www.ikso.net/cgi-bin/wiki.pl?$1',0),
+('efnetceewiki','http://purl.net/wiki/c/$1',0),
+('efnetcppwiki','http://purl.net/wiki/cpp/$1',0),
+('efnetpythonwiki','http://purl.net/wiki/python/$1',0),
+('efnetxmlwiki','http://purl.net/wiki/xml/$1',0),
+('eljwiki','http://elj.sourceforge.net/phpwiki/index.php/$1',0),
+('emacswiki','http://www.emacswiki.org/cgi-bin/wiki.pl?$1',0),
+('elibre','http://enciclopedia.us.es/index.php/$1',0),
+('eokulturcentro','http://esperanto.toulouse.free.fr/wakka.php?wiki=$1',0),
+('evowiki','http://www.evowiki.org/index.php/$1',0),
+('finalempire','http://final-empire.sourceforge.net/cgi-bin/wiki.pl?$1',0),
+('firstwiki','http://firstwiki.org/index.php/$1',0),
+('foldoc','http://www.foldoc.org/foldoc/foldoc.cgi?$1',0),
+('foxwiki','http://fox.wikis.com/wc.dll?Wiki~$1',0),
+('fr.be','http://fr.wikinations.be/$1',0),
+('fr.ca','http://fr.ca.wikinations.org/$1',0),
+('fr.fr','http://fr.fr.wikinations.org/$1',0),
+('fr.org','http://fr.wikinations.org/$1',0),
+('freebsdman','http://www.FreeBSD.org/cgi/man.cgi?apropos=1&query=$1',0),
+('gamewiki','http://gamewiki.org/wiki/index.php/$1',0),
+('gej','http://www.esperanto.de/cgi-bin/aktivikio/wiki.pl?$1',0),
+('gentoo-wiki','http://gentoo-wiki.com/$1',0),
+('globalvoices','http://cyber.law.harvard.edu/dyn/globalvoices/wiki/$1',0),
+('gmailwiki','http://www.gmailwiki.com/index.php/$1',0),
+('google','http://www.google.com/search?q=$1',0),
+('googlegroups','http://groups.google.com/groups?q=$1',0),
+('gotamac','http://www.got-a-mac.org/$1',0),
+('greencheese','http://www.greencheese.org/$1',0),
+('hammondwiki','http://www.dairiki.org/HammondWiki/index.php3?$1',0),
+('haribeau','http://wiki.haribeau.de/cgi-bin/wiki.pl?$1',0),
+('hewikisource','http://he.wikisource.org/wiki/$1',1),
+('herzkinderwiki','http://www.herzkinderinfo.de/Mediawiki/index.php/$1',0),
+('hrwiki','http://www.hrwiki.org/index.php/$1',0),
+('iawiki','http://www.IAwiki.net/$1',0),
+('imdb','http://us.imdb.com/Title?$1',0),
+('infosecpedia','http://www.infosecpedia.org/pedia/index.php/$1',0),
+('jargonfile','http://sunir.org/apps/meta.pl?wiki=JargonFile&redirect=$1',0),
+('jefo','http://www.esperanto-jeunes.org/vikio/index.php?$1',0),
+('jiniwiki','http://www.cdegroot.com/cgi-bin/jini?$1',0),
+('jspwiki','http://www.ecyrd.com/JSPWiki/Wiki.jsp?page=$1',0),
+('kerimwiki','http://wiki.oxus.net/$1',0),
+('kmwiki','http://www.voght.com/cgi-bin/pywiki?$1',0),
+('knowhow','http://www2.iro.umontreal.ca/~paquetse/cgi-bin/wiki.cgi?$1',0),
+('lanifexwiki','http://opt.lanifex.com/cgi-bin/wiki.pl?$1',0),
+('lasvegaswiki','http://wiki.gmnow.com/index.php/$1',0),
+('linuxwiki','http://www.linuxwiki.de/$1',0),
+('lojban','http://www.lojban.org/tiki/tiki-index.php?page=$1',0),
+('lqwiki','http://wiki.linuxquestions.org/wiki/$1',0),
+('lugkr','http://lug-kr.sourceforge.net/cgi-bin/lugwiki.pl?$1',0),
+('lutherwiki','http://www.lutheranarchives.com/mw/index.php/$1',0),
+('mathsongswiki','http://SeedWiki.com/page.cfm?wikiid=237&doc=$1',0),
+('mbtest','http://www.usemod.com/cgi-bin/mbtest.pl?$1',0),
+('meatball','http://www.usemod.com/cgi-bin/mb.pl?$1',0),
+('mediazilla','http://bugzilla.wikipedia.org/$1',1),
+('memoryalpha','http://www.memory-alpha.org/en/index.php/$1',0),
+('metaweb','http://www.metaweb.com/wiki/wiki.phtml?title=$1',0),
+('metawiki','http://sunir.org/apps/meta.pl?$1',0),
+('metawikipedia','http://meta.wikimedia.org/wiki/$1',0),
+('moinmoin','http://purl.net/wiki/moin/$1',0),
+('mozillawiki','http://wiki.mozilla.org/index.php/$1',0),
+('muweb','http://www.dunstable.com/scripts/MuWebWeb?$1',0),
+('netvillage','http://www.netbros.com/?$1',0),
+('oeis','http://www.research.att.com/cgi-bin/access.cgi/as/njas/sequences/eisA.cgi?Anum=$1',0),
+('openfacts','http://openfacts.berlios.de/index.phtml?title=$1',0),
+('openwiki','http://openwiki.com/?$1',0),
+('opera7wiki','http://nontroppo.org/wiki/$1',0),
+('orgpatterns','http://www.bell-labs.com/cgi-user/OrgPatterns/OrgPatterns?$1',0),
+('osi reference model','http://wiki.tigma.ee/',0),
+('pangalacticorg','http://www.pangalactic.org/Wiki/$1',0),
+('personaltelco','http://www.personaltelco.net/index.cgi/$1',0),
+('patwiki','http://gauss.ffii.org/$1',0),
+('phpwiki','http://phpwiki.sourceforge.net/phpwiki/index.php?$1',0),
+('pikie','http://pikie.darktech.org/cgi/pikie?$1',0),
+('pmeg','http://www.bertilow.com/pmeg/$1.php',0),
+('ppr','http://c2.com/cgi/wiki?$1',0),
+('purlnet','http://purl.oclc.org/NET/$1',0),
+('pythoninfo','http://www.python.org/cgi-bin/moinmoin/$1',0),
+('pythonwiki','http://www.pythonwiki.de/$1',0),
+('pywiki','http://www.voght.com/cgi-bin/pywiki?$1',0),
+('raec','http://www.raec.clacso.edu.ar:8080/raec/Members/raecpedia/$1',0),
+('revo','http://purl.org/NET/voko/revo/art/$1.html',0),
+('rfc','http://www.rfc-editor.org/rfc/rfc$1.txt',0),
+('s23wiki','http://is-root.de/wiki/index.php/$1',0),
+('scoutpedia','http://www.scoutpedia.info/index.php/$1',0),
+('seapig','http://www.seapig.org/$1',0),
+('seattlewiki','http://seattlewiki.org/wiki/$1',0),
+('seattlewireless','http://seattlewireless.net/?$1',0),
+('seeds','http://www.IslandSeeds.org/wiki/$1',0),
+('senseislibrary','http://senseis.xmp.net/?$1',0),
+('shakti','http://cgi.algonet.se/htbin/cgiwrap/pgd/ShaktiWiki/$1',0),
+('slashdot','http://slashdot.org/article.pl?sid=$1',0),
+('smikipedia','http://www.smikipedia.org/$1',0),
+('sockwiki','http://wiki.socklabs.com/$1',0),
+('sourceforge','http://sourceforge.net/$1',0),
+('squeak','http://minnow.cc.gatech.edu/squeak/$1',0),
+('strikiwiki','http://ch.twi.tudelft.nl/~mostert/striki/teststriki.pl?$1',0),
+('susning','http://www.susning.nu/$1',0),
+('svgwiki','http://www.protocol7.com/svg-wiki/default.asp?$1',0),
+('tavi','http://tavi.sourceforge.net/$1',0),
+('tejo','http://www.tejo.org/vikio/$1',0),
+('terrorwiki','http://www.liberalsagainstterrorism.com/wiki/index.php/$1',0),
+('tmbw','http://www.tmbw.net/wiki/index.php/$1',0),
+('tmnet','http://www.technomanifestos.net/?$1',0),
+('tmwiki','http://www.EasyTopicMaps.com/?page=$1',0),
+('turismo','http://www.tejo.org/turismo/$1',0),
+('theopedia','http://www.theopedia.com/$1',0),
+('twiki','http://twiki.org/cgi-bin/view/$1',0),
+('twistedwiki','http://purl.net/wiki/twisted/$1',0),
+('uea','http://www.tejo.org/uea/$1',0),
+('unreal','http://wiki.beyondunreal.com/wiki/$1',0),
+('ursine','http://ursine.ca/$1',0),
+('usej','http://www.tejo.org/usej/$1',0),
+('usemod','http://www.usemod.com/cgi-bin/wiki.pl?$1',0),
+('visualworks','http://wiki.cs.uiuc.edu/VisualWorks/$1',0),
+('warpedview','http://www.warpedview.com/index.php/$1',0),
+('webdevwikinl','http://www.promo-it.nl/WebDevWiki/index.php?page=$1',0),
+('webisodes','http://www.webisodes.org/$1',0),
+('webseitzwiki','http://webseitz.fluxent.com/wiki/$1',0),
+('why','http://clublet.com/c/c/why?$1',0),
+('wiki','http://c2.com/cgi/wiki?$1',0),
+('wikia','http://www.wikia.com/wiki/index.php/$1',0),
+('wikibooks','http://en.wikibooks.org/wiki/$1',1),
+('wikicities','http://www.wikicities.com/index.php/$1',0),
+('wikif1','http://www.wikif1.org/$1',0),
+('wikinfo','http://www.wikinfo.org/wiki.php?title=$1',0),
+('wikimedia','http://wikimediafoundation.org/wiki/$1',0),
+('wikiquote','http://en.wikiquote.org/wiki/$1',1),
+('wikinews','http://en.wikinews.org/wiki/$1',0),
+('wikisource','http://sources.wikipedia.org/wiki/$1',1),
+('wikispecies','http://species.wikipedia.org/wiki/$1',1),
+('wikitravel','http://wikitravel.org/en/$1',0),
+('wikiworld','http://WikiWorld.com/wiki/index.php/$1',0),
+('wiktionary','http://en.wiktionary.org/wiki/$1',1),
+('wlug','http://www.wlug.org.nz/$1',0),
+('wlwiki','http://winslowslair.supremepixels.net/wiki/index.php/$1',0),
+('ypsieyeball','http://sknkwrks.dyndns.org:1957/writewiki/wiki.pl?$1',0),
+('zwiki','http://www.zwiki.org/$1',0),
+('zzz wiki','http://wiki.zzz.ee/',0),
+('wikt','http://en.wiktionary.org/wiki/$1',1);
+
diff --git a/maintenance/liveCmdLine.inc b/maintenance/liveCmdLine.inc
new file mode 100644 (file)
index 0000000..529bf6f
--- /dev/null
@@ -0,0 +1,57 @@
+<?php
+/**
+ * This is a drop-in replacement for commandLine.inc, for use only on
+ * the Wikimedia wikis.
+ * Call your command-line script with the language name and site name,
+ * e.g. php convertLinks.php aa wikipedia
+ *
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+/** */
+if ( isset( $_SERVER ) && array_key_exists( 'REQUEST_METHOD', $_SERVER ) ) {
+       print "This script must be run from the command line\n";
+       exit();
+}
+
+$wgCommandLineMode = true;
+$self = array_shift( $argv );
+# Turn off output buffering if it's on
+@ob_end_flush();
+
+if ( isset( $argv[0] ) ) {
+       $lang = array_shift( $argv );
+} else {
+       $lang = "aa";
+}
+if ( isset( $argv[0] ) ) {
+       $site = array_shift( $argv );
+} else {
+       $site = "wikipedia";
+}
+
+# This is for the IRC scripts, which now run as the apache user
+if ( $_ENV['USER'] != "apache" ) {
+       $wgDBadminuser = "wikiadmin";
+       $wgDBadminpassword = trim(`wikiadmin_pass`);
+}
+
+$sep = strchr( $include_path = ini_get( "include_path" ), ";" ) ? ";" : ":";
+putenv( "wikilang=$lang");
+$newpath = "/home/wikipedia/common/php-new$sep";
+
+$DP = "../includes";
+#ini_set( "include_path", "$newpath$sep$include_path" );
+ini_set( "include_path", "/home/wikipedia/common/php-new:/home/wikipedia/common/php-new/includes" );
+
+require_once( "/home/wikipedia/common/php-new/CommonSettings.php" );
+
+define("MEDIAWIKI",true);
+require_once( "Setup.php" );
+require_once( "../install-utils.inc" );
+$wgTitle = Title::newFromText( "Command line script" );
+$wgCommandLineMode = true;
+set_time_limit(0);
+?>
diff --git a/maintenance/mcc.php b/maintenance/mcc.php
new file mode 100644 (file)
index 0000000..a32fd6f
--- /dev/null
@@ -0,0 +1,86 @@
+<?php
+/**
+ * memcached diagnostic tool
+ *
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+/** */
+require_once( "commandLine.inc" );
+require_once("memcached-client.php");
+
+$mcc = new memcached( array('persistant' => true, 'debug' => true) );
+$mcc->set_servers( $wgMemCachedServers );
+$mcc->set_debug( true );
+
+do {
+       $bad = false;
+       $quit = false;
+       $line = readconsole( "> " );
+       if ($line === false) exit;
+       $args = explode( " ", $line );
+       $command = array_shift( $args );
+       switch ( $command ) {
+               case "get":
+                       print "Getting {$args[0]}[{$args[1]}]\n";
+                       $res = $mcc->get( $args[0] );
+                       if ( array_key_exists( 1, $args ) ) {
+                               $res = $res[$args[1]];
+                       }
+                       if ( $res === false ) {
+                               #print 'Error: ' . $mcc->error_string() . "\n";
+                               print "MemCached error\n";
+                       } elseif ( is_string( $res ) ) {
+                               print "$res\n";
+                       } else {
+                               var_dump( $res );
+                       }
+                       break;
+               case "getsock":
+                       $res = $mcc->get( $args[0] );
+                       $sock = $mcc->get_sock( $args[0] );
+                       var_dump( $sock );
+                       break;
+               case "set":
+                       $key = array_shift( $args );
+                       if ( $args[0] == "#" && is_numeric( $args[1] ) ) {
+                               $value = str_repeat( "*", $args[1] );
+                       } else {
+                               $value = implode( " ", $args );
+                       }
+                       if ( !$mcc->set( $key, $value, 0 ) ) {
+                               #print 'Error: ' . $mcc->error_string() . "\n";
+                               print "MemCached error\n";
+                       }
+                       break;
+               case "delete":
+                       $key = implode( " ", $args );
+                       if ( !$mcc->delete( $key ) ) {
+                               #print 'Error: ' . $mcc->error_string() . "\n";
+                               print "MemCached error\n";
+                       }
+                       break;                                 
+               case "dumpmcc":
+                       var_dump( $mcc );
+                       break;
+               case "quit":
+               case "exit":
+                       $quit = true;
+                       break;
+               default:
+                       $bad = true;
+       }
+       if ( $bad ) {
+               if ( $command ) {
+                       print "Bad command\n";
+               }
+       } else {
+               if ( function_exists( "readline_add_history" ) ) {
+                       readline_add_history( $line );
+               }
+       }
+} while ( !$quit );
+
+?>
diff --git a/maintenance/mwdocgen.php b/maintenance/mwdocgen.php
new file mode 100644 (file)
index 0000000..d973342
--- /dev/null
@@ -0,0 +1,166 @@
+<?php
+/**
+ * Script to easily generate the mediawiki documentation.
+ *
+ * By default it will generate the whole documentation but you will be able to
+ * generate just some parts.
+ *
+ * Usage:
+ *   php mwdocgen.php
+ *
+ * Then make a selection from the menu
+ *
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Maintenance
+ *
+ * @author Ashar Voultoiz <thoane@altern.org>
+ * @version first release
+ */
+
+#
+# Variables / Configuration
+#
+
+if( php_sapi_name() != 'cli' ) {
+       die( "Run me from the command line." );
+}
+
+/** Phpdoc script with full path */
+#$pdExec       = '/usr/bin/phpdoc';
+$pdExec = 'phpdoc';
+
+/** Figure out the base directory. */
+$here = dirname( dirname( __FILE__ ) ) . DIRECTORY_SEPARATOR;
+
+/** where Phpdoc should output documentation */
+#$pdOutput = '/var/www/mwdoc/';
+$pdOutput = "{$here}docs" . DIRECTORY_SEPARATOR . 'html';
+
+/** Some more Phpdoc settings */
+# This will be used as the default for all files that don't have a package,
+# it's useful to set it to something like 'untagged' to hunt down and fix files
+# that don't have a package name declared.
+$pdOthers = " -dn MediaWiki"; 
+$pdOthers .= ' --title "MediaWiki generated documentation"'; 
+$pdOthers .= ' --output "HTML:Smarty:HandS"'; #,HTML:Smarty:HandS"'; ###### HTML:frames:DOM/earthli
+$pdOthers .= ' --ignore AdminSettings.php,LocalSettings.php,tests/LocalTestSettings.php';
+$pdOthers .= ' --parseprivate on';
+$pdOthers .= ' --sourcecode on';
+
+/** MediaWiki location */
+#$mwPath = '/var/www/mediawiki/';
+$mwPath = "{$here}";
+
+/** MediaWiki subpaths */
+$mwPathI = $mwPath.'includes/';
+$mwPathL = $mwPath.'languages/';
+$mwPathM = $mwPath.'maintenance/';
+$mwPathS = $mwPath.'skins/';
+$mwBaseFiles = $mwPath.'*php ';
+
+
+/** Variable to get user input */
+$input = '';
+/** shell command that will be run */
+$command = '';
+
+#
+# Functions
+#
+
+function readaline( $prompt = '') {
+       print $prompt;
+       $fp = fopen( "php://stdin", "r" );
+       $resp = trim( fgets( $fp, 1024 ) );
+       fclose( $fp );
+       return $resp;
+       }
+
+#
+# Main !
+#
+
+unset( $file );
+
+if( is_array( $argv ) && isset( $argv[1] ) ) {
+       switch( $argv[1] ) {
+       case '--all':         $input = 0; break;
+       case '--includes':    $input = 1; break;
+       case '--languages':   $input = 2; break;
+       case '--maintenance': $input = 3; break;
+       case '--skins':       $input = 4; break;
+       case '--file':
+               $input = 5;
+               if( isset( $argv[2] ) ) {
+                       $file = $argv[2];
+               }
+               break;
+       }
+}
+
+if( $input === '' ) {
+?>Several documentation possibilities:
+ 0 : whole documentation (1 + 2 + 3)
+ 1 : only includes
+ 2 : only languages
+ 3 : only maintenance
+ 4 : only skins
+ 5 : only a given file<?php
+       while ( !is_numeric($input) )
+       {
+               $input = readaline( "\nEnter your choice [0]:" );
+               if($input == '') {
+                       $input = 0;
+               }
+       }
+}
+
+$command = 'phpdoc ';
+switch ($input) {
+case 0:
+       $command .= " -f $mwBaseFiles -d $mwPathI,$mwPathL,$mwPathM,$mwPathS";
+       break;
+case 1:
+       $command .= "-d $mwPathI";
+       break;
+case 2: 
+       $command .= "-d $mwPathL";
+       break;
+case 3:
+       $command .= "-d $mwPathM";
+       break;
+case 4:
+       $command .= "-d $mwPathS";
+       break;
+case 5:
+       if( !isset( $file ) ) {
+               $file = readaline("Enter file name $mwPath");
+       }
+       $command .= ' -f '.$mwPath.$file;
+}
+
+$command .= " -t $pdOutput ".$pdOthers;
+
+?>
+---------------------------------------------------
+Launching the command:
+
+<?php echo $command ?>
+
+---------------------------------------------------
+<?php
+
+passthru($command);
+
+?>
+---------------------------------------------------
+Phpdoc execution finished.
+Check above for possible errors.
+<?php
+
+# phpdoc -d ./mediawiki/includes/ ./mediawiki/maintenance/ -f ./mediawiki/*php -t ./mwdoc/ -dn 'MediaWiki' --title 'MediaWiki generated documentation' -o 'HTML:frames:DOM/earthli'
+
+# phpdoc -f ./mediawiki/includes/GlobalFunctions.php -t ./mwdoc/ -dn 'MediaWiki' --title 'MediaWiki generated documentation' -o 'HTML:frames:DOM/earthli'
+
+?>
diff --git a/maintenance/mysql5/tables.sql b/maintenance/mysql5/tables.sql
new file mode 100644 (file)
index 0000000..3914f23
--- /dev/null
@@ -0,0 +1,862 @@
+-- Experimental table definitions for MySQL 4.1 and 5.0 with
+-- explicit character set support. Not fully tested, may have
+-- surprises!
+--
+-- TODO: Test various fields
+-- TODO: Anything else need to be moved to VARBINARY and BLOB?
+-- TODO: UCS-2 better than UTF-8?
+-- TODO: Find out how to get 4-byte UTF-8 chars into MySQL...
+--       An alternate UCS-2 that does UTF-16 conversion would work.
+-- TODO: Work on collation usage
+
+-- ------------------------------------------------------------
+
+-- SQL to create the initial tables for the MediaWiki database.
+-- This is read and executed by the install script; you should
+-- not have to run it by itself unless doing a manual install.
+
+--
+-- General notes:
+--
+-- If possible, create tables as InnoDB to benefit from the
+-- superior resiliency against crashes and ability to read
+-- during writes (and write during reads!)
+--
+-- Only the 'searchindex' table requires MyISAM due to the
+-- requirement for fulltext index support, which is missing
+-- from InnoDB.
+--
+--
+-- The MySQL table backend for MediaWiki currently uses
+-- 14-character CHAR or VARCHAR fields to store timestamps.
+-- The format is YYYYMMDDHHMMSS, which is derived from the
+-- text format of MySQL's TIMESTAMP fields.
+--
+-- Historically TIMESTAMP fields were used, but abandoned
+-- in early 2002 after a lot of trouble with the fields
+-- auto-updating.
+--
+-- The PostgreSQL backend uses DATETIME fields for timestamps,
+-- and we will migrate the MySQL definitions at some point as
+-- well.
+--
+--
+-- The /*$wgDBprefix*/ comments in this and other files are
+-- replaced with the defined table prefix by the installer
+-- and updater scripts. If you are installing or running
+-- updates manually, you will need to manually insert the
+-- table prefix if any when running these scripts.
+--
+
+
+--
+-- The user table contains basic account information,
+-- authentication keys, etc.
+--
+-- Some multi-wiki sites may share a single central user table
+-- between separate wikis using the $wgSharedDB setting.
+--
+-- Note that when a external authentication plugin is used,
+-- user table entries still need to be created to store
+-- preferences and to key tracking information in the other
+-- tables.
+--
+CREATE TABLE /*$wgDBprefix*/user (
+  user_id int(5) unsigned NOT NULL auto_increment,
+  
+  -- Usernames must be unique, must not be in the form of
+  -- an IP address. _Shouldn't_ allow slashes or case
+  -- conflicts. Spaces are allowed, and are _not_ converted
+  -- to underscores like titles. (Conflicts?)
+  user_name varchar(255) binary NOT NULL default '',
+  
+  -- Optional 'real name' to be displayed in credit listings
+  user_real_name varchar(255) binary NOT NULL default '',
+  
+  -- Password hashes, normally hashed like so:
+  -- MD5(CONCAT(user_id,'-',MD5(plaintext_password)))
+  user_password tinyblob NOT NULL default '',
+  
+  -- When using 'mail me a new password', a random
+  -- password is generated and the hash stored here.
+  -- The previous password is left in place until
+  -- someone actually logs in with the new password,
+  -- at which point the hash is moved to user_password
+  -- and the old password is invalidated.
+  user_newpassword tinyblob NOT NULL default '',
+  
+  -- Note: email should be restricted, not public info.
+  -- Same with passwords.
+  user_email tinytext NOT NULL default '',
+  
+  -- Newline-separated list of name=value pairs.
+  user_options blob NOT NULL default '',
+  
+  -- This is a timestamp which is updated when a user
+  -- logs in, logs out, changes preferences, or performs
+  -- some other action requiring HTML cache invalidation
+  -- to ensure that the UI is updated.
+  user_touched char(14) binary NOT NULL default '',
+  
+  -- A pseudorandomly generated value that is stored in
+  -- a cookie when the "remember password" feature is
+  -- used (previously, a hash of the password was used, but
+  -- this was vulnerable to cookie-stealing attacks)
+  user_token char(32) binary NOT NULL default '',
+  
+  -- Initially NULL; when a user's e-mail address has been
+  -- validated by returning with a mailed token, this is
+  -- set to the current timestamp.
+  user_email_authenticated CHAR(14) BINARY,
+  
+  -- Randomly generated token created when the e-mail address
+  -- is set and a confirmation test mail sent.
+  user_email_token CHAR(32) BINARY,
+  
+  -- Expiration date for the 
+  user_email_token_expires CHAR(14) BINARY,
+
+  PRIMARY KEY user_id (user_id),
+  UNIQUE INDEX user_name (user_name),
+  INDEX (user_email_token)
+
+) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+
+--
+-- User permissions have been broken out to a separate table;
+-- this allows sites with a shared user table to have different
+-- permissions assigned to a user in each project.
+--
+-- This table replaces the old user_rights field which used a
+-- comma-separated blob.
+--
+CREATE TABLE /*$wgDBprefix*/user_groups (
+  -- Key to user_id
+  ug_user int(5) unsigned NOT NULL default '0',
+  
+  -- Group names are short symbolic string keys.
+  -- The set of group names is open-ended, though in practice
+  -- only some predefined ones are likely to be used.
+  --
+  -- At runtime $wgGroupPermissions will associate group keys
+  -- with particular permissions. A user will have the combined
+  -- permissions of any group they're explicitly in, plus
+  -- the implicit '*' and 'user' groups.
+  ug_group char(16) NOT NULL default '',
+  
+  PRIMARY KEY (ug_user,ug_group),
+  KEY (ug_group)
+) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+
+-- Stores notifications of user talk page changes, for the display
+-- of the "you have new messages" box
+CREATE TABLE /*$wgDBprefix*/user_newtalk (
+ user_id int(5) NOT NULL default '0',
+ user_ip varchar(40) NOT NULL default '',
+ INDEX user_id (user_id),
+ INDEX user_ip (user_ip)
+) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+
+
+--
+-- Core of the wiki: each page has an entry here which identifies
+-- it by title and contains some essential metadata.
+--
+CREATE TABLE /*$wgDBprefix*/page (
+  -- Unique identifier number. The page_id will be preserved across
+  -- edits and rename operations, but not deletions and recreations.
+  page_id int(8) unsigned NOT NULL auto_increment,
+  
+  -- A page name is broken into a namespace and a title.
+  -- The namespace keys are UI-language-independent constants,
+  -- defined in Namespace.php.
+  page_namespace int NOT NULL,
+  
+  -- The rest of the title, as text.
+  -- Spaces are transformed into underscores in title storage.
+  page_title varchar(255) binary NOT NULL,
+  
+  -- Comma-separated set of permission keys indicating who
+  -- can move or edit the page.
+  page_restrictions tinyblob NOT NULL default '',
+  
+  -- Number of times this page has been viewed.
+  page_counter bigint(20) unsigned NOT NULL default '0',
+  
+  -- 1 indicates the article is a redirect.
+  page_is_redirect tinyint(1) unsigned NOT NULL default '0',
+  
+  -- 1 indicates this is a new entry, with only one edit.
+  -- Not all pages with one edit are new pages.
+  page_is_new tinyint(1) unsigned NOT NULL default '0',
+  
+  -- Random value between 0 and 1, used for Special:Randompage
+  page_random real unsigned NOT NULL,
+  
+  -- This timestamp is updated whenever the page changes in
+  -- a way requiring it to be re-rendered, invalidating caches.
+  -- Aside from editing this includes permission changes,
+  -- creation or deletion of linked pages, and alteration
+  -- of contained templates.
+  page_touched char(14) binary NOT NULL default '',
+
+  -- Handy key to revision.rev_id of the current revision.
+  -- This may be 0 during page creation, but that shouldn't
+  -- happen outside of a transaction... hopefully.
+  page_latest int(8) unsigned NOT NULL,
+  
+  -- Uncompressed length in bytes of the page's current source text.
+  page_len int(8) unsigned NOT NULL,
+
+  PRIMARY KEY page_id (page_id),
+  UNIQUE INDEX name_title (page_namespace,page_title),
+  
+  -- Special-purpose indexes
+  INDEX (page_random),
+  INDEX (page_len)
+
+) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+
+--
+-- Every edit of a page creates also a revision row.
+-- This stores metadata about the revision, and a reference
+-- to the text storage backend.
+--
+CREATE TABLE /*$wgDBprefix*/revision (
+  rev_id int(8) unsigned NOT NULL auto_increment,
+  
+  -- Key to page_id. This should _never_ be invalid.
+  rev_page int(8) unsigned NOT NULL,
+  
+  -- Key to text.old_id, where the actual bulk text is stored.
+  -- It's possible for multiple revisions to use the same text,
+  -- for instance revisions where only metadata is altered
+  -- or a rollback to a previous version.
+  rev_text_id int(8) unsigned NOT NULL,
+  
+  -- Text comment summarizing the change.
+  -- This text is shown in the history and other changes lists,
+  -- rendered in a subset of wiki markup.
+  rev_comment tinyblob NOT NULL default '',
+  
+  -- Key to user_id of the user who made this edit.
+  -- Stores 0 for anonymous edits and for some mass imports.
+  rev_user int(5) unsigned NOT NULL default '0',
+  
+  -- Text username or IP address of the editor.
+  rev_user_text varchar(255) binary NOT NULL default '',
+  
+  -- Timestamp
+  rev_timestamp char(14) binary NOT NULL default '',
+  
+  -- Records whether the user marked the 'minor edit' checkbox.
+  -- Many automated edits are marked as minor.
+  rev_minor_edit tinyint(1) unsigned NOT NULL default '0',
+  
+  -- Not yet used; reserved for future changes to the deletion system.
+  rev_deleted tinyint(1) unsigned NOT NULL default '0',
+  
+  PRIMARY KEY rev_page_id (rev_page, rev_id),
+  UNIQUE INDEX rev_id (rev_id),
+  INDEX rev_timestamp (rev_timestamp),
+  INDEX page_timestamp (rev_page,rev_timestamp),
+  INDEX user_timestamp (rev_user,rev_timestamp),
+  INDEX usertext_timestamp (rev_user_text,rev_timestamp)
+
+) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+
+
+--
+-- Holds text of individual page revisions.
+--
+-- Field names are a holdover from the 'old' revisions table in
+-- MediaWiki 1.4 and earlier: an upgrade will transform that
+-- table into the 'text' table to minimize unnecessary churning
+-- and downtime. If upgrading, the other fields will be left unused.
+--
+CREATE TABLE /*$wgDBprefix*/text (
+  -- Unique text storage key number.
+  -- Note that the 'oldid' parameter used in URLs does *not*
+  -- refer to this number anymore, but to rev_id.
+  old_id int(8) unsigned NOT NULL auto_increment,
+  
+  -- Depending on the contents of the old_flags field, the text
+  -- may be convenient plain text, or it may be funkily encoded.
+  old_text mediumblob NOT NULL default '',
+  
+  -- Comma-separated list of flags:
+  -- gzip: text is compressed with PHP's gzdeflate() function.
+  -- utf8: text was stored as UTF-8.
+  --       If $wgLegacyEncoding option is on, rows *without* this flag
+  --       will be converted to UTF-8 transparently at load time.
+  -- object: text field contained a serialized PHP object.
+  --         The object either contains multiple versions compressed
+  --         together to achieve a better compression ratio, or it refers
+  --         to another row where the text can be found.
+  old_flags tinyblob NOT NULL default '',
+  
+  PRIMARY KEY old_id (old_id)
+
+) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+
+--
+-- Holding area for deleted articles, which may be viewed
+-- or restored by admins through the Special:Undelete interface.
+-- The fields generally correspond to the page, revision, and text
+-- fields, with several caveats.
+--
+CREATE TABLE /*$wgDBprefix*/archive (
+  ar_namespace int NOT NULL default '0',
+  ar_title varchar(255) binary NOT NULL default '',
+  
+  -- Newly deleted pages will not store text in this table,
+  -- but will reference the separately existing text rows.
+  -- This field is retained for backwards compatibility,
+  -- so old archived pages will remain accessible after
+  -- upgrading from 1.4 to 1.5.
+  -- Text may be gzipped or otherwise funky.
+  ar_text mediumblob NOT NULL default '',
+  
+  -- Basic revision stuff...
+  ar_comment tinyblob NOT NULL default '',
+  ar_user int(5) unsigned NOT NULL default '0',
+  ar_user_text varchar(255) binary NOT NULL,
+  ar_timestamp char(14) binary NOT NULL default '',
+  ar_minor_edit tinyint(1) NOT NULL default '0',
+  
+  -- See ar_text note.
+  ar_flags tinyblob NOT NULL default '',
+  
+  -- When revisions are deleted, their unique rev_id is stored
+  -- here so it can be retained after undeletion. This is necessary
+  -- to retain permalinks to given revisions after accidental delete
+  -- cycles or messy operations like history merges.
+  -- 
+  -- Old entries from 1.4 will be NULL here, and a new rev_id will
+  -- be created on undeletion for those revisions.
+  ar_rev_id int(8) unsigned,
+  
+  -- For newly deleted revisions, this is the text.old_id key to the
+  -- actual stored text. To avoid breaking the block-compression scheme
+  -- and otherwise making storage changes harder, the actual text is
+  -- *not* deleted from the text table, merely hidden by removal of the
+  -- page and revision entries.
+  --
+  -- Old entries deleted under 1.2-1.4 will have NULL here, and their
+  -- ar_text and ar_flags fields will be used to create a new text
+  -- row upon undeletion.
+  ar_text_id int(8) unsigned,
+  
+  KEY name_title_timestamp (ar_namespace,ar_title,ar_timestamp)
+
+) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+
+
+--
+-- Track page-to-page hyperlinks within the wiki.
+--
+CREATE TABLE /*$wgDBprefix*/pagelinks (
+  -- Key to the page_id of the page containing the link.
+  pl_from int(8) unsigned NOT NULL default '0',
+  
+  -- Key to page_namespace/page_title of the target page.
+  -- The target page may or may not exist, and due to renames
+  -- and deletions may refer to different page records as time
+  -- goes by.
+  pl_namespace int NOT NULL default '0',
+  pl_title varchar(255) binary NOT NULL default '',
+  
+  UNIQUE KEY pl_from(pl_from,pl_namespace,pl_title),
+  KEY (pl_namespace,pl_title)
+
+) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+
+
+--
+-- Track links to images *used inline*
+-- We don't distinguish live from broken links here, so
+-- they do not need to be changed on upload/removal.
+--
+CREATE TABLE /*$wgDBprefix*/imagelinks (
+  -- Key to page_id of the page containing the image / media link.
+  il_from int(8) unsigned NOT NULL default '0',
+  
+  -- Filename of target image.
+  -- This is also the page_title of the file's description page;
+  -- all such pages are in namespace 6 (NS_IMAGE).
+  il_to varchar(255) binary NOT NULL default '',
+  
+  UNIQUE KEY il_from(il_from,il_to),
+  KEY (il_to)
+
+) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+
+--
+-- Track category inclusions *used inline*
+-- This tracks a single level of category membership
+-- (folksonomic tagging, really).
+--
+CREATE TABLE /*$wgDBprefix*/categorylinks (
+  -- Key to page_id of the page defined as a category member.
+  cl_from int(8) unsigned NOT NULL default '0',
+  
+  -- Name of the category.
+  -- This is also the page_title of the category's description page;
+  -- all such pages are in namespace 14 (NS_CATEGORY).
+  cl_to varchar(255) binary NOT NULL default '',
+  
+  -- The title of the linking page, or an optional override
+  -- to determine sort order. Sorting is by binary order, which
+  -- isn't always ideal, but collations seem to be an exciting
+  -- and dangerous new world in MySQL...
+  --
+  -- For MySQL 4.1+ with charset set to utf8, the sort key *index*
+  -- needs cut to be smaller than 1024 bytes (at 3 bytes per char).
+  -- To sort properly on the shorter key, this field needs to be
+  -- the same shortness.
+  cl_sortkey varchar(86) binary NOT NULL default '',
+  
+  -- This isn't really used at present. Provided for an optional
+  -- sorting method by approximate addition time.
+  cl_timestamp timestamp NOT NULL,
+  
+  UNIQUE KEY cl_from(cl_from,cl_to),
+  
+  -- We always sort within a given category...
+  KEY cl_sortkey(cl_to,cl_sortkey),
+  
+  -- Not really used?
+  KEY cl_timestamp(cl_to,cl_timestamp)
+
+) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+
+--
+-- Contains a single row with some aggregate info
+-- on the state of the site.
+--
+CREATE TABLE /*$wgDBprefix*/site_stats (
+  -- The single row should contain 1 here.
+  ss_row_id int(8) unsigned NOT NULL,
+  
+  -- Total number of page views, if hit counters are enabled.
+  ss_total_views bigint(20) unsigned default '0',
+  
+  -- Total number of edits performed.
+  ss_total_edits bigint(20) unsigned default '0',
+  
+  -- An approximate count of pages matching the following criteria:
+  -- * in namespace 0
+  -- * not a redirect
+  -- * contains the text '[['
+  -- See isCountable() in includes/Article.php
+  ss_good_articles bigint(20) unsigned default '0',
+  
+  -- Total pages, theoretically equal to SELECT COUNT(*) FROM page; except faster
+  ss_total_pages bigint(20) default -1,
+
+  -- Number of users, theoretically equal to SELECT COUNT(*) FROM user;
+  ss_users bigint(20) default -1,
+
+  -- Deprecated, no longer updated as of 1.5
+  ss_admins int(10) default -1,
+
+  UNIQUE KEY ss_row_id (ss_row_id)
+
+) TYPE=InnoDB;
+
+--
+-- Stores an ID for every time any article is visited;
+-- depending on $wgHitcounterUpdateFreq, it is
+-- periodically cleared and the page_counter column
+-- in the page table updated for the all articles
+-- that have been visited.)
+--
+CREATE TABLE /*$wgDBprefix*/hitcounter (
+  hc_id INTEGER UNSIGNED NOT NULL
+) TYPE=HEAP MAX_ROWS=25000;
+
+
+--
+-- The internet is full of jerks, alas. Sometimes it's handy
+-- to block a vandal or troll account.
+--
+CREATE TABLE /*$wgDBprefix*/ipblocks (
+  -- Primary key, introduced for privacy.
+  ipb_id int(8) NOT NULL auto_increment,
+  
+  -- Blocked IP address in dotted-quad form or user name.
+  ipb_address varchar(40) binary NOT NULL default '',
+  
+  -- Blocked user ID or 0 for IP blocks.
+  ipb_user int(8) unsigned NOT NULL default '0',
+  
+  -- User ID who made the block.
+  ipb_by int(8) unsigned NOT NULL default '0',
+  
+  -- Text comment made by blocker.
+  ipb_reason tinyblob NOT NULL default '',
+  
+  -- Creation (or refresh) date in standard YMDHMS form.
+  -- IP blocks expire automatically.
+  ipb_timestamp char(14) binary NOT NULL default '',
+  
+  -- Indicates that the IP address was banned because a banned
+  -- user accessed a page through it. If this is 1, ipb_address
+  -- will be hidden, and the block identified by block ID number.
+  ipb_auto tinyint(1) NOT NULL default '0',
+  
+  -- Time at which the block will expire.
+  ipb_expiry char(14) binary NOT NULL default '',
+
+  PRIMARY KEY ipb_id (ipb_id),
+  INDEX ipb_address (ipb_address),
+  INDEX ipb_user (ipb_user)
+
+) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+
+
+--
+-- Uploaded images and other files.
+--
+CREATE TABLE /*$wgDBprefix*/image (
+  -- Filename.
+  -- This is also the title of the associated description page,
+  -- which will be in namespace 6 (NS_IMAGE).
+  img_name varchar(255) binary NOT NULL default '',
+  
+  -- File size in bytes.
+  img_size int(8) unsigned NOT NULL default '0',
+  
+  -- For images, size in pixels.
+  img_width int(5)  NOT NULL default '0',
+  img_height int(5)  NOT NULL default '0',
+  
+  -- Extracted EXIF metadata stored as a serialized PHP array.
+  img_metadata mediumblob NOT NULL,
+  
+  -- For images, bits per pixel if known.
+  img_bits int(3)  NOT NULL default '0',
+  
+  -- Media type as defined by the MEDIATYPE_xxx constants
+  img_media_type ENUM("UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE") default NULL,
+  
+  -- major part of a MIME media type as defined by IANA
+  -- see http://www.iana.org/assignments/media-types/
+  img_major_mime ENUM("unknown", "application", "audio", "image", "text", "video", "message", "model", "multipart") NOT NULL default "unknown",
+  
+  -- minor part of a MIME media type as defined by IANA
+  -- the minor parts are not required to adher to any standard
+  -- but should be consistent throughout the database
+  -- see http://www.iana.org/assignments/media-types/
+  img_minor_mime varchar(32) NOT NULL default "unknown",
+  
+  -- Description field as entered by the uploader.
+  -- This is displayed in image upload history and logs.
+  img_description tinyblob NOT NULL default '',
+  
+  -- user_id and user_name of uploader.
+  img_user int(5) unsigned NOT NULL default '0',
+  img_user_text varchar(255) binary NOT NULL default '',
+  
+  -- Time of the upload.
+  img_timestamp char(14) binary NOT NULL default '',
+  
+  PRIMARY KEY img_name (img_name),
+  
+  -- Used by Special:Imagelist for sort-by-size
+  INDEX img_size (img_size),
+  
+  -- Used by Special:Newimages and Special:Imagelist
+  INDEX img_timestamp (img_timestamp)
+
+) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+
+--
+-- Previous revisions of uploaded files.
+-- Awkwardly, image rows have to be moved into
+-- this table at re-upload time.
+--
+CREATE TABLE /*$wgDBprefix*/oldimage (
+  -- Base filename: key to image.img_name
+  oi_name varchar(255) binary NOT NULL default '',
+  
+  -- Filename of the archived file.
+  -- This is generally a timestamp and '!' prepended to the base name.
+  oi_archive_name varchar(255) binary NOT NULL default '',
+  
+  -- Other fields as in image...
+  oi_size int(8) unsigned NOT NULL default 0,
+  oi_width int(5) NOT NULL default 0,
+  oi_height int(5) NOT NULL default 0,
+  oi_bits int(3) NOT NULL default 0,
+  oi_description tinyblob NOT NULL default '',
+  oi_user int(5) unsigned NOT NULL default '0',
+  oi_user_text varchar(255) binary NOT NULL default '',
+  oi_timestamp char(14) binary NOT NULL default '',
+
+  INDEX oi_name (oi_name(10))
+
+) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+
+
+--
+-- Primarily a summary table for Special:Recentchanges,
+-- this table contains some additional info on edits from
+-- the last few days.
+--
+CREATE TABLE /*$wgDBprefix*/recentchanges (
+  rc_id int(8) NOT NULL auto_increment,
+  rc_timestamp varchar(14) binary NOT NULL default '',
+  rc_cur_time varchar(14) binary NOT NULL default '',
+  
+  -- As in revision
+  rc_user int(10) unsigned NOT NULL default '0',
+  rc_user_text varchar(255) binary NOT NULL default '',
+  
+  -- When pages are renamed, their RC entries do _not_ change.
+  rc_namespace int NOT NULL default '0',
+  rc_title varchar(255) binary NOT NULL default '',
+  
+  -- as in revision...
+  rc_comment varchar(255) binary NOT NULL default '',
+  rc_minor tinyint(3) unsigned NOT NULL default '0',
+  
+  -- Edits by user accounts with the 'bot' rights key are
+  -- marked with a 1 here, and will be hidden from the
+  -- default view.
+  rc_bot tinyint(3) unsigned NOT NULL default '0',
+  
+  rc_new tinyint(3) unsigned NOT NULL default '0',
+  
+  -- Key to page_id (was cur_id prior to 1.5).
+  -- This will keep links working after moves while
+  -- retaining the at-the-time name in the changes list.
+  rc_cur_id int(10) unsigned NOT NULL default '0',
+  
+  -- rev_id of the given revision
+  rc_this_oldid int(10) unsigned NOT NULL default '0',
+  
+  -- rev_id of the prior revision, for generating diff links.
+  rc_last_oldid int(10) unsigned NOT NULL default '0',
+  
+  -- These may no longer be used, with the new move log.
+  rc_type tinyint(3) unsigned NOT NULL default '0',
+  rc_moved_to_ns tinyint(3) unsigned NOT NULL default '0',
+  rc_moved_to_title varchar(255) binary NOT NULL default '',
+  
+  -- If the Recent Changes Patrol option is enabled,
+  -- users may mark edits as having been reviewed to
+  -- remove a warning flag on the RC list.
+  -- A value of 1 indicates the page has been reviewed.
+  rc_patrolled tinyint(3) unsigned NOT NULL default '0',
+  
+  -- Recorded IP address the edit was made from, if the
+  -- $wgPutIPinRC option is enabled.
+  rc_ip char(15) NOT NULL default '',
+  
+  PRIMARY KEY rc_id (rc_id),
+  INDEX rc_timestamp (rc_timestamp),
+  INDEX rc_namespace_title (rc_namespace, rc_title),
+  INDEX rc_cur_id (rc_cur_id),
+  INDEX new_name_timestamp(rc_new,rc_namespace,rc_timestamp),
+  INDEX rc_ip (rc_ip)
+
+) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+
+CREATE TABLE /*$wgDBprefix*/watchlist (
+  -- Key to user_id
+  wl_user int(5) unsigned NOT NULL,
+  
+  -- Key to page_namespace/page_title
+  -- Note that users may watch patches which do not exist yet,
+  -- or existed in the past but have been deleted.
+  wl_namespace int NOT NULL default '0',
+  wl_title varchar(255) binary NOT NULL default '',
+  
+  -- Timestamp when user was last sent a notification e-mail;
+  -- cleared when the user visits the page.
+  -- FIXME: add proper null support etc
+  wl_notificationtimestamp varchar(14) binary NOT NULL default '0',
+  
+  UNIQUE KEY (wl_user, wl_namespace, wl_title),
+  KEY namespace_title (wl_namespace,wl_title)
+
+) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+
+
+--
+-- Used by texvc math-rendering extension to keep track
+-- of previously-rendered items.
+--
+CREATE TABLE /*$wgDBprefix*/math (
+  -- Binary MD5 hash of the latex fragment, used as an identifier key.
+  math_inputhash varbinary(16) NOT NULL,
+  
+  -- Not sure what this is, exactly...
+  math_outputhash varbinary(16) NOT NULL,
+  
+  -- texvc reports how well it thinks the HTML conversion worked;
+  -- if it's a low level the PNG rendering may be preferred.
+  math_html_conservativeness tinyint(1) NOT NULL,
+  
+  -- HTML output from texvc, if any
+  math_html text,
+  
+  -- MathML output from texvc, if any
+  math_mathml text,
+  
+  UNIQUE KEY math_inputhash (math_inputhash)
+
+) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+
+--
+-- When using the default MySQL search backend, page titles
+-- and text are munged to strip markup, do Unicode case folding,
+-- and prepare the result for MySQL's fulltext index.
+--
+-- This table must be MyISAM; InnoDB does not support the needed
+-- fulltext index.
+--
+CREATE TABLE /*$wgDBprefix*/searchindex (
+  -- Key to page_id
+  si_page int(8) unsigned NOT NULL,
+  
+  -- Munged version of title
+  si_title varchar(255) NOT NULL default '',
+  
+  -- Munged version of body text
+  si_text mediumtext NOT NULL default '',
+  
+  UNIQUE KEY (si_page),
+  FULLTEXT si_title (si_title),
+  FULLTEXT si_text (si_text)
+
+) TYPE=MyISAM, DEFAULT CHARSET=utf8;
+
+--
+-- Recognized interwiki link prefixes
+--
+CREATE TABLE /*$wgDBprefix*/interwiki (
+  -- The interwiki prefix, (e.g. "Meatball", or the language prefix "de")
+  iw_prefix char(32) NOT NULL,
+  
+  -- The URL of the wiki, with "$1" as a placeholder for an article name.
+  -- Any spaces in the name will be transformed to underscores before
+  -- insertion.
+  iw_url char(127) NOT NULL,
+  
+  -- A boolean value indicating whether the wiki is in this project
+  -- (used, for example, to detect redirect loops)
+  iw_local BOOL NOT NULL,
+  
+  -- Boolean value indicating whether interwiki transclusions are allowed.
+  iw_trans TINYINT(1) NOT NULL DEFAULT 0,
+  
+  UNIQUE KEY iw_prefix (iw_prefix)
+
+) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+
+--
+-- Used for caching expensive grouped queries
+--
+CREATE TABLE /*$wgDBprefix*/querycache (
+  -- A key name, generally the base name of of the special page.
+  qc_type char(32) NOT NULL,
+  
+  -- Some sort of stored value. Sizes, counts...
+  qc_value int(5) unsigned NOT NULL default '0',
+  
+  -- Target namespace+title
+  qc_namespace int NOT NULL default '0',
+  qc_title char(255) binary NOT NULL default '',
+  
+  KEY (qc_type,qc_value)
+
+) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+
+--
+-- For a few generic cache operations if not using Memcached
+--
+CREATE TABLE /*$wgDBprefix*/objectcache (
+  keyname char(255) binary not null default '',
+  value mediumblob,
+  exptime datetime,
+  unique key (keyname),
+  key (exptime)
+
+) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+
+-- For article validation
+CREATE TABLE /*$wgDBprefix*/validate (
+  val_user int(11) NOT NULL default '0',
+  val_page int(11) unsigned NOT NULL default '0',
+  val_revision int(11) unsigned NOT NULL default '0',
+  val_type int(11) unsigned NOT NULL default '0',
+  val_value int(11) default '0',
+  val_comment varchar(255) NOT NULL default '',
+  val_ip varchar(20) NOT NULL default '',
+  KEY val_user (val_user,val_revision)
+) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+
+
+CREATE TABLE /*$wgDBprefix*/logging (
+  -- Symbolic keys for the general log type and the action type
+  -- within the log. The output format will be controlled by the
+  -- action field, but only the type controls categorization.
+  log_type char(10) NOT NULL default '',
+  log_action char(10) NOT NULL default '',
+  
+  -- Timestamp. Duh.
+  log_timestamp char(14) NOT NULL default '19700101000000',
+  
+  -- The user who performed this action; key to user_id
+  log_user int unsigned NOT NULL default 0,
+  
+  -- Key to the page affected. Where a user is the target,
+  -- this will point to the user page.
+  log_namespace int NOT NULL default 0,
+  log_title varchar(255) binary NOT NULL default '',
+  
+  -- Freeform text. Interpreted as edit history comments.
+  log_comment varchar(255) NOT NULL default '',
+  
+  -- LF separated list of miscellaneous parameters
+  log_params blob NOT NULL default '',
+
+  KEY type_time (log_type, log_timestamp),
+  KEY user_time (log_user, log_timestamp),
+  KEY page_time (log_namespace, log_title, log_timestamp)
+
+) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+
+
+
+
+
+-- Hold group name and description
+--CREATE TABLE /*$wgDBprefix*/groups (
+--  gr_id int(5) unsigned NOT NULL auto_increment,
+--  gr_name varchar(50) NOT NULL default '',
+--  gr_description varchar(255) NOT NULL default '',
+--  gr_rights tinyblob,
+--  PRIMARY KEY  (gr_id)
+--
+--) TYPE=InnoDB;
+
+CREATE TABLE /*$wgDBprefix*/trackbacks (
+       tb_id           INTEGER AUTO_INCREMENT PRIMARY KEY,
+       tb_page         INTEGER REFERENCES page(page_id) ON DELETE CASCADE,
+       tb_title        VARCHAR(255) NOT NULL,
+       tb_url          VARCHAR(255) NOT NULL,
+       tb_ex           TEXT,
+       tb_name         VARCHAR(255),
+
+       INDEX (tb_page)
+) TYPE=InnoDB, DEFAULT CHARSET=utf8;
+
+CREATE TABLE /*$wgDBprefix*/transcache (
+       tc_url          VARCHAR(255) NOT NULL,
+       tc_contents     TEXT,
+       tc_time         INT NOT NULL,
+       UNIQUE INDEX tc_url_idx(tc_url)
+);
\ No newline at end of file
diff --git a/maintenance/namespace2sql.php b/maintenance/namespace2sql.php
new file mode 100644 (file)
index 0000000..8084bfe
--- /dev/null
@@ -0,0 +1,14 @@
+<?php
+#
+# Print SQL to insert namespace names into database.
+# This source code is in the public domain.
+
+require_once( "commandLine.inc" );
+
+for ($i = -2; $i < 16; ++$i) {
+       $nsname = wfStrencode( $wgLang->getNsText( $i ) );
+       $dbname = wfStrencode( $wgDBname );
+       print "INSERT INTO ns_name(ns_db, ns_num, ns_name) VALUES('$dbname', $i, '$nsname');\n";
+}
+
+?>
diff --git a/maintenance/namespaceDupes.php b/maintenance/namespaceDupes.php
new file mode 100644 (file)
index 0000000..35d325c
--- /dev/null
@@ -0,0 +1,167 @@
+<?php
+# Copyright (C) 2005 Brion Vibber <brion@pobox.com>
+# http://www.mediawiki.org/
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or 
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# http://www.gnu.org/copyleft/gpl.html
+
+$options = array( 'fix', 'suffix' );
+
+/** */
+require_once( 'commandLine.inc' );
+#require_once( 'maintenance/userDupes.inc' );
+
+class NamespaceConflictChecker {
+       function NamespaceConflictChecker( &$db ) {
+               $this->db =& $db;
+       }
+       
+       function checkAll( $fix, $suffix = '' ) {
+               global $wgContLang;
+               $spaces = $wgContLang->getNamespaces();
+               $ok = true;
+               foreach( $spaces as $ns => $name ) {
+                       $ok = $this->checkNamespace( $ns, $name, $fix, $suffix ) && $ok;
+               }
+               return $ok;
+       }
+       
+       function checkNamespace( $ns, $name, $fix, $suffix = '' ) {
+               echo "Checking namespace $ns: \"$name\"\n";
+               if( $name == '' ) {
+                       echo "... skipping article namespace\n";
+                       return true;
+               }
+               
+               $conflicts = $this->getConflicts( $ns, $name );
+               $count = count( $conflicts );
+               if( $count == 0 ) {
+                       echo "... no conflicts detected!\n";
+                       return true;
+               }
+               
+               echo "... $count conflicts detected:\n";
+               $ok = true;
+               foreach( $conflicts as $row ) {
+                       $resolvable = $this->reportConflict( $row, $suffix );
+                       $ok = $ok && $resolvable;
+                       if( $fix && ( $resolvable || $suffix != '' ) ) {
+                               $ok = $this->resolveConflict( $row, $resolvable, $suffix ) && $ok;
+                       }
+               }
+               return $ok;
+       }
+       
+       function getConflicts( $ns, $name ) {
+               $page  = $this->newSchema() ? 'page' : 'cur';
+               $table = $this->db->tableName( $page );
+               
+               $prefix     = $this->db->strencode( $name );
+               $likeprefix = str_replace( '_', '\\_', $prefix);
+               
+               $sql = "SELECT {$page}_id                                  AS id,
+                              {$page}_title                               AS oldtitle,
+                              $ns                                         AS namespace,
+                              TRIM(LEADING '$prefix:' FROM {$page}_title) AS title
+                         FROM {$table}
+                        WHERE {$page}_namespace=0
+                          AND {$page}_title LIKE '$likeprefix:%'";
+               
+               $result = $this->db->query( $sql, 'NamespaceConflictChecker::getConflicts' );
+               
+               $set = array();
+               while( $row = $this->db->fetchObject( $result ) ) {
+                       $set[] = $row;
+               }
+               $this->db->freeResult( $result );
+               
+               return $set;
+       }
+       
+       function reportConflict( $row, $suffix ) {
+               $newTitle = Title::makeTitle( $row->namespace, $row->title );
+               printf( "... %d (0,\"%s\") -> (%d,\"%s\") [[%s]]\n",
+                       $row->id,
+                       $row->oldtitle,
+                       $row->namespace,
+                       $row->title,
+                       $newTitle->getPrefixedText() );
+               
+               $id = $newTitle->getArticleId();
+               if( $id ) {
+                       echo "...  *** cannot resolve automatically; page exists with ID $id ***\n";
+                       return false;
+               } else {
+                       return true;
+               }
+       }
+       
+       function resolveConflict( $row, $resolvable, $suffix ) {
+               if( !$resolvable ) {
+                       $row->title .= $suffix;
+                       $title = Title::makeTitle( $row->namespace, $row->title );
+                       echo "...  *** using suffixed form [[" . $title->getPrefixedText() . "]] ***\n";
+               }
+               $tables = $this->newSchema() 
+                       ? array( 'page' )
+                       : array( 'cur', 'old' );
+               foreach( $tables as $table ) {
+                       $this->resolveConflictOn( $row, $table );
+               }
+               return true;
+       }
+       
+       function resolveConflictOn( $row, $table ) {
+               $fname = 'NamespaceConflictChecker::resolveConflictOn';
+               echo "... resolving on $table... ";
+               $this->db->update( $table,
+                       array(
+                               "{$table}_namespace" => $row->namespace,
+                               "{$table}_title"     => $row->title,
+                       ),
+                       array(
+                               "{$table}_namespace" => 0,
+                               "{$table}_title"     => $row->oldtitle,
+                       ),
+                       $fname );
+               echo "ok.\n";
+               return true;
+       }
+       
+       function newSchema() {
+               return class_exists( 'Revision' );
+       }
+}
+
+
+
+
+$wgTitle = Title::newFromText( 'Namespace title conflict cleanup script' );
+
+$fix = isset( $options['fix'] );
+$suffix = isset( $options['suffix'] ) ? $options['suffix'] : '';
+$dbw =& wfGetDB( DB_MASTER );
+$duper = new NamespaceConflictChecker( $dbw );
+$retval = $duper->checkAll( $fix, $suffix );
+
+if( $retval ) {
+       echo "\nLooks good!\n";
+       exit( 0 );
+} else {
+       echo "\nOh noeees\n";
+       exit( -1 );
+}
+
+?>
\ No newline at end of file
diff --git a/maintenance/nukePage.inc b/maintenance/nukePage.inc
new file mode 100644 (file)
index 0000000..921faba
--- /dev/null
@@ -0,0 +1,80 @@
+<?php
+
+/**
+ * Support functions for the nukeArticle script
+ *
+ * @package MediaWiki
+ * @subpackage Maintenance
+ * @author Rob Church <robchur@gmail.com>
+ */
+
+require_once( 'purgeOldText.inc' );
+
+function NukePage( $name, $delete = false ) {
+
+       $dbw =& wfGetDB( DB_MASTER );
+       $dbw->begin();
+       
+       $tbl_pag = $dbw->tableName( 'page' );
+       $tbl_rec = $dbw->tableName( 'recentchanges' );
+       $tbl_rev = $dbw->tableName( 'revision' );
+       
+       # Get page ID
+       echo( "Searching for \"$name\"..." );
+       $title = Title::newFromText( $name );
+       if( $title ) {
+               $id   = $title->getArticleID();
+               $real = $title->getPrefixedText();
+               echo( "found \"$real\" with ID $id.\n" );
+               
+               # Get corresponding revisions
+               echo( "Searching for revisions..." );
+               $res = $dbw->query( "SELECT rev_id FROM $tbl_rev WHERE rev_page = $id" );
+               while( $row = $dbw->fetchObject( $res ) ) {
+                       $revs[] = $row->rev_id;
+               }
+               $count = count( $revs );
+               echo( "found $count.\n" );
+               
+               # Delete the page record and associated recent changes entries
+               if( $delete ) {
+                       echo( "Deleting page record..." );
+                       $dbw->query( "DELETE FROM $tbl_pag WHERE page_id = $id" );
+                       echo( "done.\n" );
+                       echo( "Cleaning up recent changes..." );
+                       $dbw->query( "DELETE FROM $tbl_rec WHERE rc_cur_id = $id" );
+                       echo( "done.\n" );
+               }
+
+               $dbw->commit();
+               
+               # Delete revisions as appropriate
+               if( $delete && $count ) {
+                       echo( "Deleting revisions..." );
+                       DeleteRevisions( $revs );
+                       echo( "done.\n" );
+                       PurgeRedundantText( true );
+               }
+               
+       } else {
+               echo( "not found in database.\n" );
+               $dbw->commit();
+       }
+       
+}
+
+function DeleteRevisions( $ids ) {
+
+       $dbw =& wfGetDB( DB_MASTER );
+       $dbw->begin();
+       
+       $tbl_rev = $dbw->tableName( 'revision' );
+       
+       $set = implode( ', ', $ids );
+       $dbw->query( "DELETE FROM $tbl_rev WHERE rev_id IN ( $set )" );
+       
+       $dbw->commit(); 
+       
+}
+
+?>
\ No newline at end of file
diff --git a/maintenance/nukePage.php b/maintenance/nukePage.php
new file mode 100644 (file)
index 0000000..b5c3f28
--- /dev/null
@@ -0,0 +1,30 @@
+<?php
+
+/**
+ * Erase a page record from the database
+ * Irreversible (can't use standard undelete) and does not update link tables
+ *
+ * @package MediaWiki
+ * @subpackage Maintenance
+ * @author Rob Church <robchur@gmail.com>
+ */
+
+require_once( 'commandLine.inc' );
+require_once( 'nukePage.inc' );
+
+echo( "Erase Page Record\n\n" );
+
+if( isset( $args[0] ) ) {
+       NukePage( $args[0], true );
+} else {
+       ShowUsage();
+}
+
+/** Show script usage information */
+function ShowUsage() {
+       echo( "Remove a page record from the database.\n\n" );
+       echo( "Usage: php nukePage.php <title>\n\n" );
+       echo( " <title> : Page title; spaces escaped with underscores\n\n" );
+}
+
+?>
\ No newline at end of file
diff --git a/maintenance/orphans.php b/maintenance/orphans.php
new file mode 100644 (file)
index 0000000..219926c
--- /dev/null
@@ -0,0 +1,207 @@
+<?php
+# Copyright (C) 2005 Brion Vibber <brion@pobox.com>
+# http://www.mediawiki.org/
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or 
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# http://www.gnu.org/copyleft/gpl.html
+
+/**
+ * Look for 'orphan' revisions hooked to pages which don't exist
+ * And 'childless' pages with no revisions.
+ * Then, kill the poor widows and orphans.
+ * Man this is depressing.
+ *
+ * @author <brion@pobox.com>
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+$options = array( 'fix' );
+
+/** */
+require_once( 'commandLine.inc' );
+$wgTitle = Title::newFromText( 'Orphan revision cleanup script' );
+
+checkOrphans( isset( $options['fix'] ) );
+checkSeparation( isset( $options['fix'] ) );
+#checkWidows( isset( $options['fix'] ) );
+
+# ------
+
+function checkOrphans( $fix ) {
+       $dbw =& wfGetDB( DB_MASTER );
+       $page = $dbw->tableName( 'page' );
+       $revision = $dbw->tableName( 'revision' );
+       
+       if( $fix ) {
+               $dbw->query( "LOCK TABLES $page WRITE, $revision WRITE" );
+       }
+       
+       echo "Checking for orphan revision table entries... (this may take a while on a large wiki)\n";
+       $result = $dbw->query( "
+               SELECT *
+               FROM $revision LEFT OUTER JOIN $page ON rev_page=page_id
+               WHERE page_id IS NULL
+       ");
+       $orphans = $dbw->numRows( $result );
+       if( $orphans > 0 ) {
+               global $wgContLang;
+               echo "$orphans orphan revisions...\n";
+               printf( "%10s %10s %14s %20s %s\n", 'rev_id', 'rev_page', 'rev_timestamp', 'rev_user_text', 'rev_comment' );
+               while( $row = $dbw->fetchObject( $result ) ) {
+                       $comment = ( $row->rev_comment == '' )
+                               ? ''
+                               : '(' . $wgContLang->truncate( $row->rev_comment, 40, '...' ) . ')';
+                       printf( "%10d %10d %14s %20s %s\n",
+                               $row->rev_id,
+                               $row->rev_page,
+                               $row->rev_timestamp,
+                               $wgContLang->truncate( $row->rev_user_text, 17, '...' ),
+                               $comment );
+                       if( $fix ) {
+                               $dbw->delete( 'revision', array( 'rev_id' => $row->rev_id ) );
+                       }
+               }
+               if( !$fix ) {
+                       echo "Run again with --fix to remove these entries automatically.\n";
+               }
+       } else {
+               echo "No orphans! Yay!\n";
+       }
+       
+       if( $fix ) {
+               $dbw->query( "UNLOCK TABLES" );
+       }
+}
+
+/**
+ * @todo DON'T USE THIS YET! It will remove entries which have children,
+ *       but which aren't properly attached (eg if page_latest is bogus
+ *       but valid revisions do exist)
+ */
+function checkWidows( $fix ) {
+       $dbw =& wfGetDB( DB_MASTER );
+       $page = $dbw->tableName( 'page' );
+       $revision = $dbw->tableName( 'revision' );
+       
+       if( $fix ) {
+               $dbw->query( "LOCK TABLES $page WRITE, $revision WRITE" );
+       }
+       
+       echo "\nChecking for childless page table entries... (this may take a while on a large wiki)\n";
+       $result = $dbw->query( "
+               SELECT *
+               FROM $page LEFT OUTER JOIN $revision ON page_latest=rev_id
+               WHERE rev_id IS NULL
+       ");
+       $widows = $dbw->numRows( $result );
+       if( $widows > 0 ) {
+               global $wgContLang;
+               echo "$widows childless pages...\n";
+               printf( "%10s %11s %2s %s\n", 'page_id', 'page_latest', 'ns', 'page_title' );
+               while( $row = $dbw->fetchObject( $result ) ) {
+                       printf( "%10d %11d %2d %s\n",
+                               $row->page_id,
+                               $row->page_latest,
+                               $row->page_namespace,
+                               $row->page_title );
+                       if( $fix ) {
+                               $dbw->delete( 'page', array( 'page_id' => $row->page_id ) );
+                       }
+               }
+               if( !$fix ) {
+                       echo "Run again with --fix to remove these entries automatically.\n";
+               }
+       } else {
+               echo "No childless pages! Yay!\n";
+       }
+       
+       if( $fix ) {
+               $dbw->query( "UNLOCK TABLES" );
+       }
+}
+
+
+function checkSeparation( $fix ) {
+       $dbw =& wfGetDB( DB_MASTER );
+       $page     = $dbw->tableName( 'page' );
+       $revision = $dbw->tableName( 'revision' );
+       $text     = $dbw->tableName( 'text' );
+       
+       if( $fix ) {
+               $dbw->query( "LOCK TABLES $page WRITE, $revision WRITE, $text WRITE" );
+       }
+       
+       echo "\nChecking for pages whose page_latest links are incorrect... (this may take a while on a large wiki)\n";
+       $result = $dbw->query( "
+               SELECT *
+               FROM $page LEFT OUTER JOIN $revision ON page_latest=rev_id
+       ");
+       $found = 0;
+       while( $row = $dbw->fetchObject( $result ) ) {
+               $result2 = $dbw->query( "
+                       SELECT MAX(rev_timestamp) as max_timestamp
+                       FROM $revision 
+                       WHERE rev_page=$row->page_id
+               " );
+               $row2 = $dbw->fetchObject( $result2 );
+               $dbw->freeResult( $result2 );
+               if( $row2 ) {
+                       if( $row->rev_timestamp != $row2->max_timestamp ) {
+                               if( $found == 0 ) {
+                                       printf( "%10s %10s %14s %14s\n",
+                                               'page_id', 'rev_id', 'timestamp', 'max timestamp' );
+                               }
+                               ++$found;
+                               printf( "%10d %10d %14s %14s\n",
+                                       $row->page_id,
+                                       $row->page_latest,
+                                       $row->rev_timestamp,
+                                       $row2->max_timestamp );
+                               if( $fix ) {
+                                       # ...
+                                       $maxId = $dbw->selectField(
+                                               'revision',
+                                               'rev_id',
+                                               array(
+                                                       'rev_page'      => $row->page_id,
+                                                       'rev_timestamp' => $row2->max_timestamp ) );
+                                       echo "... updating to revision $maxId\n";
+                                       $maxRev = Revision::newFromId( $maxId );
+                                       $title = Title::makeTitle( $row->page_namespace, $row->page_title );
+                                       $article = new Article( $title );
+                                       $article->updateRevisionOn( $dbw, $maxRev );
+                               }
+                       }
+               } else {
+                       echo "wtf\n";
+               }
+       }
+       
+       if( $found ) {
+               echo "Found $found pages with incorrect latest revision.\n";
+       } else {
+               echo "No pages with incorrect latest revision. Yay!\n";
+       }
+       if( !$fix && $found > 0 ) {
+               echo "Run again with --fix to remove these entries automatically.\n";
+       }
+       
+       if( $fix ) {
+               $dbw->query( "UNLOCK TABLES" );
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/maintenance/ourusers.php b/maintenance/ourusers.php
new file mode 100644 (file)
index 0000000..37b1abb
--- /dev/null
@@ -0,0 +1,89 @@
+<?php
+/**
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+/** */
+$wikiuser_pass = `wikiuser_pass`;
+$wikiadmin_pass = `wikiadmin_pass`;
+$wikisql_pass = `wikisql_pass`;
+
+$hosts = array( 
+       'localhost',
+       '207.142.131.194',
+       '207.142.131.195',
+       '207.142.131.196',
+       '207.142.131.197',
+       '207.142.131.198',
+       '207.142.131.199',
+       '207.142.131.226',
+       '207.142.131.227',
+       '207.142.131.228',
+       '207.142.131.229',
+       '207.142.131.230',
+       '207.142.131.231',
+       '207.142.131.232',
+       '207.142.131.233',
+       '207.142.131.234',
+       '207.142.131.237',
+       '207.142.131.238',
+       '207.142.131.239',
+       '207.142.131.243',
+       '207.142.131.244',
+       '207.142.131.249',
+       '207.142.131.250',
+       '207.142.131.216',
+       '10.0.%',
+);
+
+$databases = array(
+       '%wikibooks',
+       '%wiki',
+       '%wikiquote',
+       '%wiktionary',
+       '%wikisource',
+       '%wikinews',
+       '%wikiversity',
+       '%wikimedia',
+);
+
+foreach( $hosts as $host ) {
+       print "--\n-- $host\n--\n\n-- wikiuser\n\n";
+       print "GRANT REPLICATION CLIENT,PROCESS ON *.* TO 'wikiuser'@'$host' IDENTIFIED BY '$wikiuser_pass';\n";
+       print "GRANT ALL PRIVILEGES ON `boardvote`.* TO 'wikiuser'@'$host' IDENTIFIED BY '$wikiuser_pass';\n";
+       foreach( $databases as $db ) {
+               print "GRANT SELECT, INSERT, UPDATE, DELETE ON `$db`.* TO 'wikiuser'@'$host' IDENTIFIED BY '$wikiuser_pass';\n";
+       }
+       
+/*
+       print "\n-- wikisql\n\n";
+       foreach ( $databases as $db ) {
+print <<<EOS
+GRANT SELECT ON `$db`.`old` TO 'wikisql'@'$host' IDENTIFIED BY '$wikisql_pass';
+GRANT SELECT ON `$db`.`imagelinks` TO 'wikisql'@'$host' IDENTIFIED BY '$wikisql_pass';
+GRANT SELECT ON `$db`.`image` TO 'wikisql'@'$host' IDENTIFIED BY '$wikisql_pass';
+GRANT SELECT ON `$db`.`watchlist` TO 'wikisql'@'$host' IDENTIFIED BY '$wikisql_pass';
+GRANT SELECT ON `$db`.`site_stats` TO 'wikisql'@'$host' IDENTIFIED BY '$wikisql_pass';
+GRANT SELECT ON `$db`.`archive` TO 'wikisql'@'$host' IDENTIFIED BY '$wikisql_pass';
+GRANT SELECT ON `$db`.`links` TO 'wikisql'@'$host' IDENTIFIED BY '$wikisql_pass';
+GRANT SELECT ON `$db`.`ipblocks` TO 'wikisql'@'$host' IDENTIFIED BY '$wikisql_pass';
+GRANT SELECT ON `$db`.`cur` TO 'wikisql'@'$host' IDENTIFIED BY '$wikisql_pass';
+GRANT SELECT (user_rights, user_id, user_name, user_options) ON `$db`.`user` TO 'wikisql'@'$host' IDENTIFIED BY '$wikisql_pass';
+GRANT SELECT ON `$db`.`oldimage` TO 'wikisql'@'$host' IDENTIFIED BY '$wikisql_pass';
+GRANT SELECT ON `$db`.`recentchanges` TO 'wikisql'@'$host' IDENTIFIED BY '$wikisql_pass';
+GRANT SELECT ON `$db`.`math` TO 'wikisql'@'$host' IDENTIFIED BY '$wikisql_pass';
+GRANT SELECT ON `$db`.`brokenlinks` TO 'wikisql'@'$host' IDENTIFIED BY '$wikisql_pass';
+
+EOS;
+       }*/
+       
+       print "\n-- wikiadmin\n\n";
+       print "GRANT PROCESS, REPLICATION CLIENT ON *.* TO 'wikiadmin'@'$host' IDENTIFIED BY '$wikiadmin_pass';\n";
+       print "GRANT ALL PRIVILEGES ON `boardvote`.* TO wikiadmin@'$host' IDENTIFIED BY '$wikiadmin_pass';\n";
+       foreach ( $databases as $db ) {
+               print "GRANT ALL PRIVILEGES ON `$db`.* TO wikiadmin@'$host' IDENTIFIED BY '$wikiadmin_pass';\n";
+       }
+       print "\n";
+}
diff --git a/maintenance/parserTests.inc b/maintenance/parserTests.inc
new file mode 100644 (file)
index 0000000..39596e5
--- /dev/null
@@ -0,0 +1,713 @@
+<?php
+# Copyright (C) 2004 Brion Vibber <brion@pobox.com>
+# http://www.mediawiki.org/
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or 
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# http://www.gnu.org/copyleft/gpl.html
+
+/**
+ * @todo Make this more independent of the configuration (and if possible the database)
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+/** */
+$options = array( 'quick', 'color', 'quiet', 'help' );
+$optionsWithArgs = array( 'regex' );
+
+require_once( 'commandLine.inc' );
+require_once( "$IP/includes/ObjectCache.php" );
+require_once( "$IP/includes/BagOStuff.php" );
+require_once( "$IP/languages/LanguageUtf8.php" );
+
+/**
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+class ParserTest {
+       /**
+        * boolean $color whereas output should be colorized
+        * @access private
+        */
+       var $color;
+
+       /**
+        * boolean $lightcolor whereas output should use light colors
+        * @access private
+        */
+       var $lightcolor;
+
+       /**
+        * Sets terminal colorization and diff/quick modes depending on OS and
+        * command-line options (--color and --quick).
+        *
+        * @access public
+        */
+       function ParserTest() {
+               global $options;
+               
+               # Only colorize output if stdout is a terminal.
+               $this->lightcolor = false;
+               $this->color = !wfIsWindows() && posix_isatty(1);
+               
+               if( isset( $options['color'] ) ) {
+                       switch( $options['color'] ) {
+                       case 'no':
+                               $this->color = false;
+                               break;
+                       case 'light':
+                               $this->lightcolor = true;
+                               # Fall through
+                       case 'yes':
+                       default:
+                               $this->color = true;
+                               break;
+                       }
+               }
+               
+               $this->showDiffs = !isset( $options['quick'] );
+               
+               $this->quiet = isset( $options['quiet'] );
+
+               if (isset($options['regex'])) {
+                       $this->regex = $options['regex'];
+               } else {
+                       # Matches anything
+                       $this->regex = '';
+               }
+       }
+
+       /**
+        * Remove last character if it is a newline
+        * @access private
+        */
+       function chomp($s) {
+               if (substr($s, -1) === "\n") {
+                       return substr($s, 0, -1);
+               }
+               else {
+                       return $s;
+               }
+       }
+       
+       /**
+        * Run a series of tests listed in the given text file.
+        * Each test consists of a brief description, wikitext input,
+        * and the expected HTML output.
+        *
+        * Prints status updates on stdout and counts up the total
+        * number and percentage of passed tests.
+        *
+        * @param string $filename
+        * @return bool True if passed all tests, false if any tests failed.
+        * @access public
+        */
+       function runTestsFromFile( $filename ) {
+               $infile = fopen( $filename, 'rt' );
+               if( !$infile ) {
+                       die( "Couldn't open parserTests.txt\n" );
+               }
+               
+               $data = array();
+               $section = null;
+               $success = 0;
+               $total = 0;
+               $n = 0;
+               while( false !== ($line = fgets( $infile ) ) ) {
+                       $n++;
+                       if( preg_match( '/^!!\s*(\w+)/', $line, $matches ) ) {
+                               $section = strtolower( $matches[1] );
+                               if( $section == 'endarticle') {
+                                       if( !isset( $data['text'] ) ) {
+                                               die( "'endarticle' without 'text' at line $n\n" );
+                                       }
+                                       if( !isset( $data['article'] ) ) {
+                                               die( "'endarticle' without 'article' at line $n\n" );
+                                       }
+                                       $this->addArticle($this->chomp($data['article']), $this->chomp($data['text']), $n);
+                                       $data = array();
+                                       $section = null;
+                                       continue;
+                               }
+                               if( $section == 'end' ) {
+                                       if( !isset( $data['test'] ) ) {
+                                               die( "'end' without 'test' at line $n\n" );
+                                       }
+                                       if( !isset( $data['input'] ) ) {
+                                               die( "'end' without 'input' at line $n\n" );
+                                       }
+                                       if( !isset( $data['result'] ) ) {
+                                               die( "'end' without 'result' at line $n\n" );
+                                       }
+                                       if( !isset( $data['options'] ) ) {
+                                               $data['options'] = '';
+                                       }
+                                       else {
+                                               $data['options'] = $this->chomp( $data['options'] );
+                                       }
+                                       if (preg_match('/\\bdisabled\\b/i', $data['options'])
+                                               || !preg_match("/{$this->regex}/i", $data['test'])) {
+                                               # disabled test
+                                               $data = array();
+                                               $section = null;
+                                               continue;
+                                       }
+                                       if( $this->runTest(
+                                               $this->chomp( $data['test'] ),
+                                               $this->chomp( $data['input'] ),
+                                               $this->chomp( $data['result'] ),
+                                               $this->chomp( $data['options'] ) ) ) {
+                                               $success++;
+                                       }
+                                       $total++;
+                                       $data = array();
+                                       $section = null;
+                                       continue;
+                               }
+                               if ( isset ($data[$section] ) ) {
+                                       die ( "duplicate section '$section' at line $n\n" );
+                               }
+                               $data[$section] = '';
+                               continue;
+                       }
+                       if( $section ) {
+                               $data[$section] .= $line;
+                       }
+               }
+               if( $total > 0 ) {
+                       $ratio = wfPercent( 100 * $success / $total );
+                       print $this->termColor( 1 ) . "\nPassed $success of $total tests ($ratio) ";
+                       if( $success == $total ) {
+                               print $this->termColor( 32 ) . "PASSED!";
+                       } else {
+                               print $this->termColor( 31 ) . "FAILED!";
+                       }
+                       print $this->termReset() . "\n";
+                       return ($success == $total);
+               } else {
+                       die( "No tests found.\n" );
+               }
+       }
+
+       /**
+        * Run a given wikitext input through a freshly-constructed wiki parser,
+        * and compare the output against the expected results.
+        * Prints status and explanatory messages to stdout.
+        *
+        * @param string $input Wikitext to try rendering
+        * @param string $result Result to output
+        * @return bool
+        */
+       function runTest( $desc, $input, $result, $opts ) {
+               if( !$this->quiet ) {
+                       $this->showTesting( $desc );
+               }
+
+               $this->setupGlobals($opts);
+
+               $user =& new User();
+               $options =& ParserOptions::newFromUser( $user );
+
+               if (preg_match('/\\bmath\\b/i', $opts)) {
+                       # XXX this should probably be done by the ParserOptions
+                       require_once('Math.php');
+
+                       $options->setUseTex(true);
+               }
+
+               if (preg_match('/title=\[\[(.*)\]\]/', $opts, $m)) {
+                       $titleText = $m[1];
+               }
+               else {
+                       $titleText = 'Parser test';
+               }
+
+               $parser =& new Parser();
+               $title =& Title::makeTitle( NS_MAIN, $titleText );
+
+               if (preg_match('/\\bpst\\b/i', $opts)) {
+                       $out = $parser->preSaveTransform( $input, $title, $user, $options );
+               } elseif (preg_match('/\\bmsg\\b/i', $opts)) {
+                       $out = $parser->transformMsg( $input, $options );
+               } else {
+                       $output =& $parser->parse( $input, $title, $options );
+                       $out = $output->getText();
+
+                       if (preg_match('/\\bill\\b/i', $opts)) {
+                               $out = $this->tidy( implode( ' ', $output->getLanguageLinks() ) );
+                       } else if (preg_match('/\\bcat\\b/i', $opts)) {
+                               $out = $this->tidy ( implode( ' ', $output->getCategoryLinks() ) );
+                       }
+
+                       $result = $this->tidy($result);
+               }
+               
+               $this->teardownGlobals();
+               
+               if( $result === $out && $this->wellFormed( $out ) ) {
+                       return $this->showSuccess( $desc );
+               } else {
+                       return $this->showFailure( $desc, $result, $out );
+               }
+       }
+       
+       /**
+        * Set up the global variables for a consistent environment for each test.
+        * Ideally this should replace the global configuration entirely.
+        *
+        * @access private
+        */
+       function setupGlobals($opts = '') {
+               # Save the prefixed / quoted table names for later use when we make the temporaries.
+               $db =& wfGetDB( DB_READ );
+               $this->oldTableNames = array();
+               foreach( $this->listTables() as $table ) {
+                       $this->oldTableNames[$table] = $db->tableName( $table );
+               }
+               if( !isset( $this->uploadDir ) ) {
+                       $this->uploadDir = $this->setupUploadDir();
+               }
+               
+               $settings = array(
+                       'wgServer' => 'http://localhost',
+                       'wgScript' => '/index.php',
+                       'wgScriptPath' => '/',
+                       'wgArticlePath' => '/wiki/$1',
+                       'wgUploadPath' => '/images',
+                       'wgUploadDirectory' => $this->uploadDir,
+                       'wgStyleSheetPath' => '/skins',
+                       'wgSitename' => 'MediaWiki',
+                       'wgLanguageCode' => 'en',
+                       'wgContLanguageCode' => 'en',
+                       'wgDBprefix' => 'parsertest',
+                       'wgDefaultUserOptions' => array(),
+                       
+                       'wgLang' => new LanguageUtf8(),
+                       'wgContLang' => new LanguageUtf8(),
+                       'wgNamespacesWithSubpages' => array( 0 => preg_match('/\\bsubpage\\b/i', $opts)),
+                       'wgMaxTocLevel' => 999,
+                       'wgCapitalLinks' => true,
+                       'wgDefaultUserOptions' => array(),
+                       'wgNoFollowLinks' => true,
+                       'wgThumbnailScriptPath' => false,
+                       'wgUseTeX' => false,
+                       );
+               $this->savedGlobals = array();
+               foreach( $settings as $var => $val ) {
+                       $this->savedGlobals[$var] = $GLOBALS[$var];
+                       $GLOBALS[$var] = $val;
+               }
+               $GLOBALS['wgLoadBalancer']->loadMasterPos();
+               $GLOBALS['wgMessageCache']->initialise( new BagOStuff(), false, 0, $GLOBALS['wgDBname'] );
+               $this->setupDatabase();
+               
+               global $wgUser;
+               $wgUser = new User();
+       }
+       
+       # List of temporary tables to create, without prefix
+       # Some of these probably aren't necessary
+       function listTables() {
+               return array('user', 'page', 'revision', 'text',
+                       'pagelinks', 'imagelinks', 'categorylinks',
+                       'site_stats', 'hitcounter',
+                       'ipblocks', 'image', 'oldimage',
+                       'recentchanges',
+                       'watchlist', 'math', 'searchindex',
+                       'interwiki', 'querycache',
+                       'objectcache'
+               );
+       }
+       
+       /**
+        * Set up a temporary set of wiki tables to work with for the tests.
+        * Currently this will only be done once per run, and any changes to
+        * the db will be visible to later tests in the run.
+        *
+        * @access private
+        */
+       function setupDatabase() {
+               static $setupDB = false;
+               global $wgDBprefix;
+
+               # Make sure we don't mess with the live DB
+               if (!$setupDB && $wgDBprefix === 'parsertest') {
+                       # oh teh horror
+                       $GLOBALS['wgLoadBalancer'] = LoadBalancer::newFromParams( $GLOBALS['wgDBservers'] );
+                       $db =& wfGetDB( DB_MASTER );
+
+                       $tables = $this->listTables();
+
+                       if (!(strcmp($db->getServerVersion(), '4.1') < 0 and stristr($db->getSoftwareLink(), 'MySQL'))) {
+                               # Database that supports CREATE TABLE ... LIKE
+                               global $wgDBtype;
+                               if( $wgDBtype == 'PostgreSQL' ) {
+                                       $def = 'INCLUDING DEFAULTS';
+                               } else {
+                                       $def = '';
+                               }
+                               foreach ($tables as $tbl) {
+                                       $newTableName = $db->tableName( $tbl );
+                                       $tableName = $this->oldTableNames[$tbl];
+                                       $db->query("CREATE TEMPORARY TABLE $newTableName (LIKE $tableName $def)");
+                               }
+                       } else {
+                               # Hack for MySQL versions < 4.1, which don't support
+                               # "CREATE TABLE ... LIKE". Note that
+                               # "CREATE TEMPORARY TABLE ... SELECT * FROM ... LIMIT 0"
+                               # would not create the indexes we need....
+                               foreach ($tables as $tbl) {
+                                       $res = $db->query("SHOW CREATE TABLE {$this->oldTableNames[$tbl]}");
+                                       $row = $db->fetchRow($res);
+                                       $create = $row[1];
+                                       $create_tmp = preg_replace('/CREATE TABLE `(.*?)`/', 'CREATE TEMPORARY TABLE `'
+                                               . $wgDBprefix . $tbl .'`', $create);
+                                       if ($create === $create_tmp) {
+                                               # Couldn't do replacement
+                                               die("could not create temporary table $tbl");
+                                       }
+                                       $db->query($create_tmp);
+                               }
+
+                       }
+
+                       # Hack: insert a few Wikipedia in-project interwiki prefixes,
+                       # for testing inter-language links
+                       $db->insert( 'interwiki', array(
+                               array( 'iw_prefix' => 'Wikipedia',
+                                      'iw_url'    => 'http://en.wikipedia.org/wiki/$1',
+                                      'iw_local'  => 0 ),
+                               array( 'iw_prefix' => 'MeatBall',
+                                      'iw_url'    => 'http://www.usemod.com/cgi-bin/mb.pl?$1',
+                                      'iw_local'  => 0 ),
+                               array( 'iw_prefix' => 'zh',
+                                      'iw_url'    => 'http://zh.wikipedia.org/wiki/$1',
+                                      'iw_local'  => 1 ),
+                               array( 'iw_prefix' => 'es',
+                                      'iw_url'    => 'http://es.wikipedia.org/wiki/$1',
+                                      'iw_local'  => 1 ),
+                               array( 'iw_prefix' => 'fr',
+                                      'iw_url'    => 'http://fr.wikipedia.org/wiki/$1',
+                                      'iw_local'  => 1 ),
+                               array( 'iw_prefix' => 'ru',
+                                      'iw_url'    => 'http://ru.wikipedia.org/wiki/$1',
+                                      'iw_local'  => 1 ),
+                               ) );
+
+                       # Hack: Insert an image to work with
+                       $db->insert( 'image', array(
+                               'img_name'        => 'Foobar.jpg',
+                               'img_size'        => 12345,
+                               'img_description' => 'Some lame file',
+                               'img_user'        => 1,
+                               'img_user_text'   => 'WikiSysop',
+                               'img_timestamp'   => $db->timestamp( '20010115123500' ),
+                               'img_width'       => 1941,
+                               'img_height'      => 220,
+                               'img_bits'        => 24,
+                               'img_media_type'  => MEDIATYPE_BITMAP, 
+                               'img_major_mime'  => "image", 
+                               'img_minor_mime'  => "jpeg", 
+                               ) );
+                       
+                       $setupDB = true;
+               }
+       }
+       
+       /**
+        * Create a dummy uploads directory which will contain a couple
+        * of files in order to pass existence tests.
+        * @return string The directory
+        * @access private
+        */
+       function setupUploadDir() {
+               global $IP;
+               
+               $dir = wfTempDir() . "/mwParser-" . mt_rand() . "-images";
+               mkdir( $dir );
+               mkdir( $dir . '/3' );
+               mkdir( $dir . '/3/3a' );
+               
+               $img = "$IP/skins/monobook/headbg.jpg";
+               $h = fopen($img, 'r');
+               $c = fread($h, filesize($img));
+               fclose($h);
+               
+               $f = fopen( $dir . '/3/3a/Foobar.jpg', 'wb' );
+               fwrite( $f, $c );
+               fclose( $f );
+               return $dir;
+       }
+       
+       /**
+        * Restore default values and perform any necessary clean-up
+        * after each test runs.
+        *
+        * @access private
+        */
+       function teardownGlobals() {
+               foreach( $this->savedGlobals as $var => $val ) {
+                       $GLOBALS[$var] = $val;
+               }
+               if( isset( $this->uploadDir ) ) {
+                       $this->teardownUploadDir( $this->uploadDir );
+                       unset( $this->uploadDir );
+               }
+       }
+       
+       /**
+        * Remove the dummy uploads directory
+        * @access private
+        */
+       function teardownUploadDir( $dir ) {
+               unlink( "$dir/3/3a/Foobar.jpg" );
+               rmdir( "$dir/3/3a" );
+               rmdir( "$dir/3" );
+
+               @unlink( "$dir/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" );
+               @rmdir( "$dir/thumb/3/3a/Foobar.jpg" );
+               @rmdir( "$dir/thumb/3/3a" );
+               @rmdir( "$dir/thumb/3/39" ); # wtf?
+               @rmdir( "$dir/thumb/3" );
+               @rmdir( "$dir/thumb" );
+               rmdir( "$dir" );
+       }
+       
+       /**
+        * "Running test $desc..."
+        * @access private
+        */
+       function showTesting( $desc ) {
+               print "Running test $desc... ";
+       }
+       
+       /**
+        * Print a happy success message.
+        *
+        * @param string $desc The test name
+        * @return bool
+        * @access private
+        */
+       function showSuccess( $desc ) {
+               if( !$this->quiet ) {
+                       print $this->termColor( '1;32' ) . 'PASSED' . $this->termReset() . "\n";
+               }
+               return true;
+       }
+       
+       /**
+        * Print a failure message and provide some explanatory output
+        * about what went wrong if so configured.
+        *
+        * @param string $desc The test name
+        * @param string $result Expected HTML output
+        * @param string $html Actual HTML output
+        * @return bool
+        * @access private
+        */
+       function showFailure( $desc, $result, $html ) {
+               if( $this->quiet ) {
+                       # In quiet mode we didn't show the 'Testing' message before the
+                       # test, in case it succeeded. Show it now:
+                       $this->showTesting( $desc );
+               }
+               print $this->termColor( '1;31' ) . 'FAILED!' . $this->termReset() . "\n";
+               if( $this->showDiffs ) {
+                       print $this->quickDiff( $result, $html );
+               }
+               if( !$this->wellFormed( $html ) ) {
+                       print "XML error: $this->mXmlError\n";
+               }
+               return false;
+       }
+       
+       /**
+        * Run given strings through a diff and return the (colorized) output.
+        * Requires writable /tmp directory and a 'diff' command in the PATH.
+        *
+        * @param string $input
+        * @param string $output
+        * @param string $inFileTail Tailing for the input file name
+        * @param string $outFileTail Tailing for the output file name
+        * @return string
+        * @access private
+        */
+       function quickDiff( $input, $output, $inFileTail='expected', $outFileTail='actual' ) {
+               $prefix = wfTempDir() . "/mwParser-" . mt_rand();
+               
+               $infile = "$prefix-$inFileTail";
+               $this->dumpToFile( $input, $infile );
+               
+               $outfile = "$prefix-$outFileTail";
+               $this->dumpToFile( $output, $outfile );
+               
+               $diff = `diff -au $infile $outfile`;
+               unlink( $infile );
+               unlink( $outfile );
+               
+               return $this->colorDiff( $diff );
+       }
+       
+       /**
+        * Write the given string to a file, adding a final newline.
+        *
+        * @param string $data
+        * @param string $filename
+        * @access private
+        */
+       function dumpToFile( $data, $filename ) {
+               $file = fopen( $filename, "wt" );
+               fwrite( $file, $data . "\n" );
+               fclose( $file );
+       }
+       
+       /**
+        * Return ANSI terminal escape code for changing text attribs/color,
+        * or empty string if color output is disabled.
+        *
+        * @param string $color Semicolon-separated list of attribute/color codes
+        * @return string
+        * @access private
+        */
+       function termColor( $color ) {
+               if($this->lightcolor) {
+                       return $this->color ? "\x1b[1;{$color}m" : '';
+               } else {
+                       return $this->color ? "\x1b[{$color}m" : '';
+               }
+       }
+       
+       /**
+        * Return ANSI terminal escape code for restoring default text attributes,
+        * or empty string if color output is disabled.
+        *
+        * @return string
+        * @access private
+        */
+       function termReset() {
+               return $this->color ? "\x1b[0m" : '';
+       }
+       
+       /**
+        * Colorize unified diff output if set for ANSI color output.
+        * Subtractions are colored blue, additions red.
+        *
+        * @param string $text
+        * @return string
+        * @access private
+        */
+       function colorDiff( $text ) {
+               return preg_replace(
+                       array( '/^(-.*)$/m', '/^(\+.*)$/m' ),
+                       array( $this->termColor( 34 ) . '$1' . $this->termReset(),
+                              $this->termColor( 31 ) . '$1' . $this->termReset() ),
+                       $text );
+       }
+
+       /**
+        * Insert a temporary test article
+        * @param string $name the title, including any prefix
+        * @param string $text the article text
+        * @param int $line the input line number, for reporting errors
+        * @static
+        * @access private
+        */
+       function addArticle($name, $text, $line) {
+               $this->setupGlobals();
+               $title = Title::newFromText( $name );
+               if ( is_null($title) ) {
+                       die( "invalid title at line $line\n" );
+               }
+
+               $aid = $title->getArticleID( GAID_FOR_UPDATE );
+               if ($aid != 0) {
+                       die( "duplicate article at line $line\n" );
+               }
+
+               $art = new Article($title);
+               $art->insertNewArticle($text, '', false, false );
+               $this->teardownGlobals();
+       }
+
+       /*
+        * Run the "tidy" command on text if the $wgUseTidy
+        * global is true
+        *
+        * @param string $text the text to tidy
+        * @return string
+        * @static
+        * @access private
+        */
+       function tidy( $text ) {
+               global $wgUseTidy;
+               if ($wgUseTidy) {
+                       $text = Parser::tidy($text);
+               }
+               return $text;
+       }
+       
+       function wellFormed( $text ) {
+               $html = 
+                       '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ' .
+                       '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' .
+                       '<html>' .
+                       $text .
+                       '</html>';
+               
+               $parser = xml_parser_create( "UTF-8" );
+               
+               # case folding violates XML standard, turn it off
+               xml_parser_set_option( $parser, XML_OPTION_CASE_FOLDING, false );
+               
+               if( !xml_parse( $parser, $html, true ) ) {
+                       $err = xml_error_string( xml_get_error_code( $parser ) );
+                       $position = xml_get_current_byte_index( $parser );
+                       $fragment = $this->extractFragment( $html, $position );
+                       $this->mXmlError = "$err at byte $position:\n$fragment";
+                       xml_parser_free( $parser );
+                       return false;
+               }
+               xml_parser_free( $parser );
+               return true;
+       }
+       
+       function extractFragment( $text, $position ) {
+               $start = max( 0, $position - 10 );
+               $before = $position - $start;
+               $fragment = '...' .
+                       $this->termColor( 34 ) .
+                       substr( $text, $start, $before ) .
+                       $this->termColor( 0 ) .
+                       $this->termColor( 31 ) .
+                       $this->termColor( 1 ) .
+                       substr( $text, $position, 1 ) .
+                       $this->termColor( 0 ) .
+                       $this->termColor( 34 ) .
+                       substr( $text, $position + 1, 9 ) .
+                       $this->termColor( 0 ) .
+                       '...';
+               $display = str_replace( "\n", ' ', $fragment );
+               $caret = '   ' .
+                       str_repeat( ' ', $before ) .
+                       $this->termColor( 31 ) .
+                       '^' .
+                       $this->termColor( 0 );
+               return "$display\n$caret";
+       }
+       
+}
+
+?>
diff --git a/maintenance/parserTests.php b/maintenance/parserTests.php
new file mode 100644 (file)
index 0000000..6f08bf6
--- /dev/null
@@ -0,0 +1,57 @@
+<?php
+# Copyright (C) 2004 Brion Vibber <brion@pobox.com>
+# http://www.mediawiki.org/
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# http://www.gnu.org/copyleft/gpl.html
+
+/**
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+/** */
+require('parserTests.inc');
+
+if( isset( $options['help'] ) ) {
+    echo <<<END
+MediaWiki $wgVersion parser test suite
+Usage: php parserTests.php [--quick] [--quiet] [--color[=(yes|no|light)]]
+                           [--regex <expression>] [--help]
+Options:
+  --quick  Suppress diff output of failed tests
+  --quiet  Suppress notification of passed tests (shows only failed tests)
+  --color  Override terminal detection and force color output on or off
+           'light' option is similar to 'yes' but with color for dark backgrounds
+  --regex  Only run tests whose descriptions which match given regex
+  --help   Show this help message
+
+
+END;
+    exit( 0 );
+}
+
+# There is a convention that the parser should never
+# refer to $wgTitle directly, but instead use the title
+# passed to it.
+$wgTitle = Title::newFromText( 'Parser test script do not use' );
+$tester =& new ParserTest();
+
+# Note: the command line setup changes the current working directory
+# to the parent, which is why we have to put the subdir here:
+$ok = $tester->runTestsFromFile( 'maintenance/parserTests.txt' );
+
+exit ($ok ? 0 : -1);
+?>
diff --git a/maintenance/parserTests.txt b/maintenance/parserTests.txt
new file mode 100644 (file)
index 0000000..d69e0ad
--- /dev/null
@@ -0,0 +1,2684 @@
+# MediaWiki Parser test cases
+# Some taken from http://meta.wikimedia.org/wiki/Parser_testing
+# All (C) their respective authors and released under the GPL
+#
+# The syntax should be fairly self-explanatory.
+#
+# Currently supported test options:
+#      One of the following three:
+#
+#      (default)       generate HTML output
+#      pst             apply pre-save transform
+#      msg             apply message transform
+#
+#      Plus any combination of these:
+#
+#      cat             add category links
+#      ill             add inter-language links
+#      subpage         enable subpages (disabled by default)
+#      title=[[XXX]]   run test using article title XXX
+#      disabled        do not run test
+#
+# For testing purposes, temporary articles can created:
+# !!article / NAMESPACE:TITLE / !!text / ARTICLE TEXT / !!endarticle
+# where '/' denotes a newline.
+
+# This is the standard article assumed to exist.
+!! article
+Main Page
+!! text
+blah blah
+!! endarticle
+
+###
+### Basic tests
+###
+!! test
+Blank input
+!! input
+!! result
+!! end
+
+
+!! test
+Simple paragraph
+!! input
+This is a simple paragraph.
+!! result
+<p>This is a simple paragraph.
+</p>
+!! end
+
+!! test
+Simple list
+!! input
+* Item 1
+* Item 2
+!! result
+<ul><li> Item 1
+</li><li> Item 2
+</li></ul>
+
+!! end
+
+!! test
+Italics and bold
+!! input
+* plain
+* plain''italic''plain
+* plain''italic''plain''italic''plain
+* plain'''bold'''plain
+* plain'''bold'''plain'''bold'''plain
+* plain''italic''plain'''bold'''plain
+* plain'''bold'''plain''italic''plain
+* plain''italic'''bold-italic'''italic''plain
+* plain'''bold''bold-italic''bold'''plain
+* plain'''''bold-italic'''italic''plain
+* plain'''''bold-italic''bold'''plain
+* plain''italic'''bold-italic'''''plain
+* plain'''bold''bold-italic'''''plain
+* plain l'''italic''plain
+!! result
+<ul><li> plain
+</li><li> plain<i>italic</i>plain
+</li><li> plain<i>italic</i>plain<i>italic</i>plain
+</li><li> plain<b>bold</b>plain
+</li><li> plain<b>bold</b>plain<b>bold</b>plain
+</li><li> plain<i>italic</i>plain<b>bold</b>plain
+</li><li> plain<b>bold</b>plain<i>italic</i>plain
+</li><li> plain<i>italic<b>bold-italic</b>italic</i>plain
+</li><li> plain<b>bold<i>bold-italic</i>bold</b>plain
+</li><li> plain<i><b>bold-italic</b>italic</i>plain
+</li><li> plain<b><i>bold-italic</i>bold</b>plain
+</li><li> plain<i>italic<b>bold-italic</b></i>plain
+</li><li> plain<b>bold<i>bold-italic</i></b>plain
+</li><li> plain l'<i>italic</i>plain
+</li></ul>
+
+!! end
+
+###
+### <nowiki> test cases
+###
+
+!! test
+<nowiki> unordered list
+!! input
+<nowiki>* This is not an unordered list item.</nowiki>
+!! result
+<p>* This is not an unordered list item.
+</p>
+!! end
+
+!! test
+<nowiki> spacing
+!! input
+<nowiki>Lorem ipsum dolor
+
+sed abit.
+  sed nullum.
+
+:and a colon
+</nowiki>
+!! result
+<p>Lorem ipsum dolor
+
+sed abit.
+  sed nullum.
+
+:and a colon
+
+</p>
+!! end
+
+!! test
+nowiki 3
+!! input
+:There is not nowiki.
+:There is <nowiki>nowiki</nowiki>.
+
+#There is not nowiki.
+#There is <nowiki>nowiki</nowiki>.
+
+*There is not nowiki.
+*There is <nowiki>nowiki</nowiki>.
+!! result
+<dl><dd>There is not nowiki.
+</dd><dd>There is nowiki.
+</dd></dl>
+<ol><li>There is not nowiki.
+</li><li>There is nowiki.
+</li></ol>
+<ul><li>There is not nowiki.
+</li><li>There is nowiki.
+</li></ul>
+
+!! end
+
+###
+### Comments
+###
+!! test
+Comment test 1
+!! input
+<!-- comment 1 --> asdf
+<!-- comment 2 -->
+!! result
+<pre>asdf
+</pre>
+
+!! end
+
+!! test
+Comment test 2
+!! input
+asdf
+<!-- comment 1 -->
+jkl
+!! result
+<p>asdf
+jkl
+</p>
+!! end
+
+!! test
+Comment test 3
+!! input
+asdf
+<!-- comment 1 -->
+<!-- comment 2 -->
+jkl
+!! result
+<p>asdf
+jkl
+</p>
+!! end
+
+!! test
+Comment test 4
+!! input
+asdf<!-- comment 1 -->jkl
+!! result
+<p>asdfjkl
+</p>
+!! end
+
+!! test
+Comment spacing
+!! input
+a
+ <!-- foo --> b <!-- bar -->
+c
+!! result
+<p>a
+</p>
+<pre> b 
+</pre>
+<p>c
+</p>
+!! end
+
+###
+### Preformatted text
+###
+!! test
+Preformatted text
+!! input
+ This is some
+ Preformatted text
+ With ''italic''
+ And '''bold'''
+ And a [[Main Page|link]]
+!! result
+<pre>This is some
+Preformatted text
+With <i>italic</i>
+And <b>bold</b>
+And a <a href="/wiki/Main_Page" title="Main Page">link</a>
+</pre>
+!! end
+
+###
+### Definition lists
+###
+!! test
+Simple definition
+!! input
+; name : Definition
+!! result
+<dl><dt> name&nbsp;</dt><dd> Definition
+</dd></dl>
+
+!! end
+
+!! test
+Simple definition
+!! input
+: Indented text
+!! result
+<dl><dd> Indented text
+</dd></dl>
+
+!! end
+
+!! test
+Definition list with no space
+!! input
+;name:Definition
+!! result
+<dl><dt>name</dt><dd>Definition
+</dd></dl>
+
+!!end
+
+!! test
+Definition list with URL link
+!! input
+; http://example.com/ : definition
+!! result
+<dl><dt> <a href="http://example.com/" class='external free' title="http://example.com/" rel="nofollow">http://example.com/</a>&nbsp;</dt><dd> definition
+</dd></dl>
+
+!! end
+
+!! test
+Definition list with bracketed URL link
+!! input
+;[http://www.google.com/ Google]:Number one search engine
+!! result
+<dl><dt><a href="http://www.google.com/" class='external text' title="http://www.google.com/" rel="nofollow">Google</a></dt><dd>Number one search engine
+</dd></dl>
+
+!! end
+
+!! test
+Definition list with wikilink containing colon
+!! input
+; [[Help:FAQ]]: The least-read page on Wikipedia
+!! result
+<dl><dt> <a href="/index.php?title=Help:FAQ&amp;action=edit" class="new" title="Help:FAQ">Help:FAQ</a></dt><dd> The least-read page on Wikipedia
+</dd></dl>
+
+!! end
+
+# At Brion's and JeLuF's insistence... :)
+!! test
+Definition list with wikilink containing colon
+!! input
+;  news:alt.wikipedia.rox: This isn't even a real newsgroup!
+!! result
+<dl><dt>  <a href="news:alt.wikipedia.rox" class='external free' title="news:alt.wikipedia.rox" rel="nofollow">news:alt.wikipedia.rox</a></dt><dd> This isn't even a real newsgroup!
+</dd></dl>
+
+!! end
+
+!! test
+Malformed definition list with colon
+!! input
+;  news:alt.wikipedia.rox -- don't crash or enter an infinite loop
+!! result
+<dl><dt>  <a href="news:alt.wikipedia.rox" class='external free' title="news:alt.wikipedia.rox" rel="nofollow">news:alt.wikipedia.rox</a> -- don't crash or enter an infinite loop
+</dt></dl>
+
+!! end
+
+!! test
+Definition lists: colon in external link text
+!! input
+; [http://www.wikipedia2.org/ Wikipedia : The Next Generation]: OK, I made that up
+!! result
+<dl><dt> <a href="http://www.wikipedia2.org/" class='external text' title="http://www.wikipedia2.org/" rel="nofollow">Wikipedia&nbsp;: The Next Generation</a></dt><dd> OK, I made that up
+</dd></dl>
+
+!! end
+
+
+###
+### External links
+###
+!! test
+External links: non-bracketed
+!! input
+Non-bracketed: http://example.com
+!! result
+<p>Non-bracketed: <a href="http://example.com" class='external free' title="http://example.com" rel="nofollow">http://example.com</a>
+</p>
+!! end
+
+!! test
+External links: numbered
+!! input
+Numbered: [http://example.com]
+Numbered: [http://example.net]
+Numbered: [http://example.org]
+!! result
+<p>Numbered: <a href="http://example.com" class='external autonumber' title="http://example.com" rel="nofollow">[1]</a>
+Numbered: <a href="http://example.net" class='external autonumber' title="http://example.net" rel="nofollow">[2]</a>
+Numbered: <a href="http://example.org" class='external autonumber' title="http://example.org" rel="nofollow">[3]</a>
+</p>
+!!end
+
+!! test
+External links: specified text
+!! input
+Specified text: [http://example.com link]
+!! result
+<p>Specified text: <a href="http://example.com" class='external text' title="http://example.com" rel="nofollow">link</a>
+</p>
+!!end
+
+!! test
+External links: trail
+!! input
+Linktrails should not work for external links: [http://example.com link]s
+!! result
+<p>Linktrails should not work for external links: <a href="http://example.com" class='external text' title="http://example.com" rel="nofollow">link</a>s
+</p>
+!! end
+
+!! test
+External links: dollar sign in URL
+!! input
+http://example.com/1$2345
+!! result
+<p><a href="http://example.com/1$2345" class='external free' title="http://example.com/1$2345" rel="nofollow">http://example.com/1$2345</a>
+</p>
+!! end
+
+!! test
+External links: dollar sign in URL (named)
+!! input
+[http://example.com/1$2345]
+!! result
+<p><a href="http://example.com/1$2345" class='external autonumber' title="http://example.com/1$2345" rel="nofollow">[1]</a>
+</p>
+!!end
+
+!! test
+External image
+!! input
+External image: http://meta.wikimedia.org/upload/f/f1/Ncwikicol.png
+!! result
+<p>External image: <img src="http://meta.wikimedia.org/upload/f/f1/Ncwikicol.png" alt="Ncwikicol.png" />
+</p>
+!! end
+
+!! test
+External image from https
+!! input
+External image from https: https://meta.wikimedia.org/upload/f/f1/Ncwikicol.png
+!! result
+<p>External image from https: <img src="https://meta.wikimedia.org/upload/f/f1/Ncwikicol.png" alt="Ncwikicol.png" />
+</p>
+!! end
+
+!! test
+Link to non-http image, no img tag
+!! input
+Link to non-http image, no img tag: ftp://example.com/test.jpg
+!! result
+<p>Link to non-http image, no img tag: <a href="ftp://example.com/test.jpg" class='external free' title="ftp://example.com/test.jpg" rel="nofollow">ftp://example.com/test.jpg</a>
+</p>
+!! end
+
+!! test
+External links: terminating separator
+!! input
+Terminating separator: http://example.com/thing,
+!! result
+<p>Terminating separator: <a href="http://example.com/thing" class='external free' title="http://example.com/thing" rel="nofollow">http://example.com/thing</a>,
+</p>
+!! end
+
+!! test
+External links: intervening separator
+!! input
+Intervening separator: http://example.com/1,2,3
+!! result
+<p>Intervening separator: <a href="http://example.com/1,2,3" class='external free' title="http://example.com/1,2,3" rel="nofollow">http://example.com/1,2,3</a>
+</p>
+!! end
+
+!! test
+External links: old bug with URL in query
+!! input
+Old bug with URL in query: [http://example.com/thing?url=http://example.com link]
+!! result
+<p>Old bug with URL in query: <a href="http://example.com/thing?url=http://example.com" class='external text' title="http://example.com/thing?url=http://example.com" rel="nofollow">link</a>
+</p>
+!! end
+
+!! test
+External links: old URL-in-URL bug, mixed protocols
+!! input
+And again with mixed protocols: [ftp://example.com?url=http://example.com link]
+!! result
+<p>And again with mixed protocols: <a href="ftp://example.com?url=http://example.com" class='external text' title="ftp://example.com?url=http://example.com" rel="nofollow">link</a>
+</p>
+!!end
+
+!! test
+External links: URL in text
+!! input
+URL in text: [http://example.com http://example.com]
+!! result
+<p>URL in text: <a href="http://example.com" class='external free' title="http://example.com" rel="nofollow">http://example.com</a>
+</p>
+!! end
+
+!! test
+External links: Clickable images
+!! input
+ja-style clickable images: [http://example.com http://meta.wikimedia.org/upload/f/f1/Ncwikicol.png]
+!! result
+<p>ja-style clickable images: <a href="http://example.com" class='external text' title="http://example.com" rel="nofollow"><img src="http://meta.wikimedia.org/upload/f/f1/Ncwikicol.png" alt="Ncwikicol.png" /></a>
+</p>
+!!end
+
+!! test
+External links: raw ampersand
+!! input
+Old &amp; use: http://x&y
+!! result
+<p>Old &amp; use: <a href="http://x&amp;y" class='external free' title="http://x&amp;y" rel="nofollow">http://x&amp;y</a>
+</p>
+!! end
+
+!! test
+External links: encoded ampersand
+!! input
+Old &amp; use: http://x&amp;y
+!! result
+<p>Old &amp; use: <a href="http://x&amp;y" class='external free' title="http://x&amp;y" rel="nofollow">http://x&amp;y</a>
+</p>
+!! end
+
+!! test
+External links: [raw ampersand]
+!! input
+Old &amp; use: [http://x&y]
+!! result
+<p>Old &amp; use: <a href="http://x&amp;y" class='external autonumber' title="http://x&amp;y" rel="nofollow">[1]</a>
+</p>
+!! end
+
+!! test
+External links: [encoded ampersand]
+!! input
+Old &amp; use: [http://x&amp;y]
+!! result
+<p>Old &amp; use: <a href="http://x&amp;y" class='external autonumber' title="http://x&amp;y" rel="nofollow">[1]</a>
+</p>
+!! end
+
+!! test
+External links: www.jpeg.org (bug 554)
+!! input
+http://www.jpeg.org
+!!result
+<p><a href="http://www.jpeg.org" class='external free' title="http://www.jpeg.org" rel="nofollow">http://www.jpeg.org</a>
+</p>
+!! end
+
+!! test
+External links: URL within URL (original bug 2)
+!! input
+[http://www.unausa.org/newindex.asp?place=http://www.unausa.org/programs/mun.asp]
+!! result
+<p><a href="http://www.unausa.org/newindex.asp?place=http://www.unausa.org/programs/mun.asp" class='external autonumber' title="http://www.unausa.org/newindex.asp?place=http://www.unausa.org/programs/mun.asp" rel="nofollow">[1]</a>
+</p>
+!! end
+
+!! test
+BUG 361: URL inside bracketed URL
+!! input
+[http://www.example.com/foo http://www.example.com/bar]
+!! result
+<p><a href="http://www.example.com/foo" class='external text' title="http://www.example.com/foo" rel="nofollow">http://www.example.com/bar</a>
+</p>
+!! end
+
+!! test
+BUG 361: URL within URL, not bracketed
+!! input
+http://www.example.com/foo?=http://www.example.com/bar
+!! result
+<p><a href="http://www.example.com/foo?=http://www.example.com/bar" class='external free' title="http://www.example.com/foo?=http://www.example.com/bar" rel="nofollow">http://www.example.com/foo?=http://www.example.com/bar</a>
+</p>
+!! end
+
+!! test
+BUG 289: ">"-token in URL-tail
+!! input
+http://www.example.com/<hello>
+!! result
+<p><a href="http://www.example.com/" class='external free' title="http://www.example.com/" rel="nofollow">http://www.example.com/</a>&lt;hello&gt;
+</p>
+!!end
+
+!! test
+BUG 289: literal ">"-token in URL-tail
+!! input
+http://www.example.com/<b>html</b>
+!! result
+<p><a href="http://www.example.com/" class='external free' title="http://www.example.com/" rel="nofollow">http://www.example.com/</a><b>html</b>
+</p>
+!!end
+
+!! test
+BUG 289: ">"-token in bracketed URL
+!! input
+[http://www.example.com/<hello> stuff]
+!! result
+<p><a href="http://www.example.com/" class='external text' title="http://www.example.com/" rel="nofollow">&lt;hello&gt; stuff</a>
+</p>
+!!end
+
+!! test
+BUG 289: literal ">"-token in bracketed URL
+!! input
+[http://www.example.com/<b>html</b> stuff]
+!! result
+<p><a href="http://www.example.com/" class='external text' title="http://www.example.com/" rel="nofollow"><b>html</b> stuff</a>
+</p>
+!!end
+
+!! test
+BUG 289: literal double quote at end of URL
+!! input
+http://www.example.com/"hello"
+!! result
+<p><a href="http://www.example.com/" class='external free' title="http://www.example.com/" rel="nofollow">http://www.example.com/</a>"hello"
+</p>
+!!end
+
+!! test
+BUG 289: literal double quote in bracketed URL
+!! input
+[http://www.example.com/"hello" stuff]
+!! result
+<p><a href="http://www.example.com/" class='external text' title="http://www.example.com/" rel="nofollow">"hello" stuff</a>
+</p>
+!!end
+
+!! test
+External links: invalid character
+!! input
+[http://www.example.com\0 test]
+!! result
+<p>[<a href="http://www.example.com" class='external free' title="http://www.example.com" rel="nofollow">http://www.example.com</a>\0 test]
+</p>
+!! end
+
+!! test
+BUG 787: Links with one slash after the url protocol are invalid
+!! input
+http:/example.com
+
+[http:/example.com title]
+!! result
+<p>http:/example.com
+</p><p>[http:/example.com title]
+</p>
+!! end
+
+!! test
+Bug 2702: Mismatched <i> and <a> tags are invalid
+!! input
+''[http://example.com text'']
+!! result
+<p><i><a href="http://example.com" class='external text' title="http://example.com" rel="nofollow">text</a></i>
+</p>
+!! end
+
+###
+### Quotes
+###
+
+!! test
+Quotes
+!! input
+Normal text. '''Bold text.''' Normal text. ''Italic text.''
+
+Normal text. '''''Bold italic text.''''' Normal text.
+!!result
+<p>Normal text. <b>Bold text.</b> Normal text. <i>Italic text.</i>
+</p><p>Normal text. <i><b>Bold italic text.</b></i> Normal text.
+</p>
+!! end
+
+
+!! test
+Unclosed and unmatched quotes
+!! input
+'''''Bold italic text '''with bold deactivated''' in between.'''''
+
+'''''Bold italic text ''with italic deactivated'' in between.'''''
+
+'''Bold text..
+
+..spanning two paragraphs (should not work).'''
+
+'''Bold tag left open
+
+''Italic tag left open
+
+Normal text.
+
+<!-- Unmatching number of opening, closing tags: -->
+'''This year''''s election ''should'' beat '''last year''''s.
+
+''Tom'''s car is bigger than ''Susan'''s.
+!! result
+<p><i><b>Bold italic text </b>with bold deactivated<b> in between.</b></i>
+</p><p><b><i>Bold italic text </i>with italic deactivated<i> in between.</i></b>
+</p><p><b>Bold text..</b>
+</p><p>..spanning two paragraphs (should not work).<b></b>
+</p><p><b>Bold tag left open</b>
+</p><p><i>Italic tag left open</i>
+</p><p>Normal text.
+</p><p><b>This year'</b>s election <i>should</i> beat <b>last year'</b>s.
+</p><p><i>Tom<b>s car is bigger than </b></i><b>Susan</b>s.
+</p>
+!! end
+
+###
+### Tables
+###
+### some content taken from http://meta.wikimedia.org/wiki/MediaWiki_User%27s_Guide:_Using_tables
+###
+
+# This should not produce <table></table> as <table><tr><td></td></tr></table>
+# is the bare minimun required by the spec, see:
+# http://www.w3.org/TR/xhtml-modularization/dtd_module_defs.html#a_module_Basic_Tables
+!! test
+A table with no data.
+!! input
+{||}
+!! result
+!! end
+
+# A table with nothing but a caption is invalid XHTML, we might want to render
+# this as <p>caption</p>
+!! test
+A table with nothing but a caption
+!! input 
+{|
+|+ caption
+|}
+!! result
+<table>
+<caption> caption
+</caption>
+<tr>
+<td>
+</td></tr></table>
+!! end
+
+!! test
+Simple table
+!! input
+{| 
+| 1 || 2
+|- 
+| 3 || 4
+|}
+!! result
+<table>
+<tr>
+<td> 1 </td><td> 2
+</td></tr>
+<tr>
+<td> 3 </td><td> 4
+</td></tr></table>
+
+!! end
+
+!! test
+Multiplication table
+!! input
+{| border="1" cellpadding="2"
+|+Multiplication table
+|-
+! &times; !! 1 !! 2 !! 3
+|-
+! 1
+| 1 || 2 || 3
+|-
+! 2
+| 2 || 4 || 6
+|-
+! 3
+| 3 || 6 || 9
+|-
+! 4
+| 4 || 8 || 12
+|-
+! 5
+| 5 || 10 || 15
+|}
+!! result
+<table border="1" cellpadding="2">
+<caption>Multiplication table
+</caption>
+<tr>
+<th> &times; </th><th> 1 </th><th> 2 </th><th> 3
+</th></tr>
+<tr>
+<th> 1
+</th><td> 1 </td><td> 2 </td><td> 3
+</td></tr>
+<tr>
+<th> 2
+</th><td> 2 </td><td> 4 </td><td> 6
+</td></tr>
+<tr>
+<th> 3
+</th><td> 3 </td><td> 6 </td><td> 9
+</td></tr>
+<tr>
+<th> 4
+</th><td> 4 </td><td> 8 </td><td> 12
+</td></tr>
+<tr>
+<th> 5
+</th><td> 5 </td><td> 10 </td><td> 15
+</td></tr></table>
+
+!! end
+
+!! test
+Table rowspan
+!! input
+{| align=right border=1
+| Cell 1, row 1 
+|rowspan=2| Cell 2, row 1 (and 2) 
+| Cell 3, row 1 
+|- 
+| Cell 1, row 2 
+| Cell 3, row 2 
+|}
+!! result
+<table align="right" border="1">
+<tr>
+<td> Cell 1, row 1
+</td><td rowspan="2"> Cell 2, row 1 (and 2)
+</td><td> Cell 3, row 1
+</td></tr>
+<tr>
+<td> Cell 1, row 2
+</td><td> Cell 3, row 2
+</td></tr></table>
+
+!! end
+
+!! test
+Nested table
+!! input
+{| border=1
+| &alpha;
+|
+{| bgcolor=#ABCDEF border=2
+|nested
+|-
+|table
+|}
+|the original table again
+|}
+!! result
+<table border="1">
+<tr>
+<td> &alpha;
+</td><td>
+<table bgcolor="#ABCDEF" border="2">
+<tr>
+<td>nested
+</td></tr>
+<tr>
+<td>table
+</td></tr></table>
+</td><td>the original table again
+</td></tr></table>
+
+!! end
+
+!! test
+Invalid attributes in table cell (bug 1830)
+!! input
+{|
+|Cell:|broken
+|}
+!! result
+<table>
+<tr>
+<td>broken
+</td></tr></table>
+
+!! end
+
+
+###
+### Internal links
+###
+!! test
+Plain link, capitalized
+!! input
+[[Main Page]]
+!! result
+<p><a href="/wiki/Main_Page" title="Main Page">Main Page</a>
+</p>
+!! end
+
+!! test
+Plain link, uncapitalized
+!! input
+[[main Page]]
+!! result
+<p><a href="/wiki/Main_Page" title="Main Page">main Page</a>
+</p>
+!! end
+
+!! test
+Piped link
+!! input
+[[Main Page|The Main Page]]
+!! result
+<p><a href="/wiki/Main_Page" title="Main Page">The Main Page</a>
+</p>
+!! end
+
+!! test
+Broken link
+!! input
+[[Zigzagzogzagzig]]
+!! result
+<p><a href="/index.php?title=Zigzagzogzagzig&amp;action=edit" class="new" title="Zigzagzogzagzig">Zigzagzogzagzig</a>
+</p>
+!! end
+
+!! test
+Link with prefix
+!! input
+xxx[[main Page]], xxx[[Main Page]], Xxx[[main Page]] XXX[[main Page]], XXX[[Main Page]]
+!! result
+<p>xxx<a href="/wiki/Main_Page" title="Main Page">main Page</a>, xxx<a href="/wiki/Main_Page" title="Main Page">Main Page</a>, Xxx<a href="/wiki/Main_Page" title="Main Page">main Page</a> XXX<a href="/wiki/Main_Page" title="Main Page">main Page</a>, XXX<a href="/wiki/Main_Page" title="Main Page">Main Page</a>
+</p>
+!! end
+
+!! test
+Link with suffix
+!! input
+[[Main Page]]xxx, [[Main Page]]XXX
+!! result
+<p><a href="/wiki/Main_Page" title="Main Page">Main Pagexxx</a>, <a href="/wiki/Main_Page" title="Main Page">Main Page</a>XXX
+</p>
+!! end
+
+!! test
+Link with 3 brackets
+!! input
+[[[main page]]]
+!! result
+<p>[[[main page]]]
+</p>
+!! end
+
+!! test
+Piped link with 3 brackets
+!! input
+[[[main page|the main page]]]
+!! result
+<p>[[[main page|the main page]]]
+</p>
+!! end
+
+!! test
+Link with multiple pipes
+!! input
+[[Main Page|The|Main|Page]]
+!! result
+<p><a href="/wiki/Main_Page" title="Main Page">The|Main|Page</a>
+</p>
+!! end
+
+!! test
+Link to namespaces
+!! input
+[[Talk:Parser testing]], [[Meta:Disclaimers]]
+!! result
+<p><a href="/index.php?title=Talk:Parser_testing&amp;action=edit" class="new" title="Talk:Parser testing">Talk:Parser testing</a>, <a href="/index.php?title=Meta:Disclaimers&amp;action=edit" class="new" title="Meta:Disclaimers">Meta:Disclaimers</a>
+</p>
+!! end
+
+!! test
+Piped link to namespace
+!! input
+[[Meta:Disclaimers|The disclaimers]]
+!! result
+<p><a href="/index.php?title=Meta:Disclaimers&amp;action=edit" class="new" title="Meta:Disclaimers">The disclaimers</a>
+</p>
+!! end
+
+!! test
+Link containing }
+!! input
+[[Usually caused by a typo (oops}]]
+!! result
+<p>[[Usually caused by a typo (oops}]]
+</p>
+!! end
+
+!! test
+Link containing % (not as a hex sequence)
+!! input
+[[7% Solution]]
+!! result
+<p><a href="/index.php?title=7%25_Solution&amp;action=edit" class="new" title="7% Solution">7% Solution</a>
+</p>
+!! end
+
+!! test
+Link containing % as a single hex sequence interpreted to char
+!! input
+[[7%25 Solution]]
+!! result
+<p><a href="/index.php?title=7%25_Solution&amp;action=edit" class="new" title="7% Solution">7% Solution</a>
+</p>
+!!end
+
+!! test
+Link containing % as a double hex sequence interpreted to hex sequence
+!! input
+[[7%2525 Solution]]
+!! result
+<p>[[7%2525 Solution]]
+</p>
+!!end
+
+!! test
+Plain link to URL
+!! input
+[[http://www.example.org]]
+!! result
+<p>[<a href="http://www.example.org" class='external autonumber' title="http://www.example.org" rel="nofollow">[1]</a>]
+</p>
+!! end
+
+# I'm fairly sure the expected result here is wrong.
+# We want these to be URL links, not pseudo-pages with URLs for titles....
+# However the current output is also pretty screwy.
+#
+# ----
+# I'm changing it to match the current output--it arguably makes more
+# sense in the light of the test above. Old expected result was:
+#<p>Piped link to URL: <a href="/index.php?title=Http://www.example.org&amp;action=edit" class="new" title="Http://www.example.org">an example URL</a>
+#</p>
+# But I think this test is bordering on "garbage in, garbage out" anyway.
+# -- wtm
+!! test
+Piped link to URL
+!! input
+Piped link to URL: [[http://www.example.org|an example URL]]
+!! result
+<p>Piped link to URL: [<a href="http://www.example.org|an" class='external text' title="http://www.example.org|an" rel="nofollow">example URL</a>]
+</p>
+!! end
+
+!! test
+BUG 2: [[page|http://url/]] should link to page, not http://url/
+!! input
+[[Main Page|http://url/]]
+!! result
+<p><a href="/wiki/Main_Page" title="Main Page">http://url/</a>
+</p>
+!! end
+
+!! test
+BUG 337: Escaped self-links should be bold
+!! options
+title=[[Bug462]]
+!! input
+[[Bu&#103;462]] [[Bug462]]
+!! result
+<p><strong>Bu&#103;462</strong> <strong>Bug462</strong>
+</p>
+!! end
+
+!! test
+Self-link to section should not be bold
+!! options
+title=[[Main Page]]
+!! input
+[[Main Page#section]]
+!! result
+<p><a href="/wiki/Main_Page#section" title="Main Page">Main Page#section</a>
+</p>
+!! end
+
+!! test
+<nowiki> inside a link
+!! input
+[[Main<nowiki> Page</nowiki>]] [[Main Page|the main page <nowiki>[it's not very good]</nowiki>]]
+!! result
+<p><a href="/wiki/Main_Page" title="Main Page">Main Page</a> <a href="/wiki/Main_Page" title="Main Page">the main page [it's not very good]</a>
+</p>
+!! end
+
+###
+### Interwiki links (see maintenance/interwiki.sql)
+###
+
+!! test
+Inline interwiki link
+!! input
+[[MeatBall:SoftSecurity]]
+!! result
+<p><a href="http://www.usemod.com/cgi-bin/mb.pl?SoftSecurity" class='extiw' title="MeatBall:SoftSecurity">MeatBall:SoftSecurity</a>
+</p>
+!! end
+
+!! test
+Inline interwiki link with empty title (bug 2372)
+!! input
+[[MeatBall:]]
+!! result
+<p><a href="http://www.usemod.com/cgi-bin/mb.pl?" class='extiw' title="MeatBall:">MeatBall:</a>
+</p>
+!! end
+
+!! test
+Interwiki link encoding conversion (bug 1636)
+!! input
+*[[Wikipedia:ro:Olteni&#0355;a]]
+*[[Wikipedia:ro:Olteni&#355;a]]
+!! result
+<ul><li><a href="http://en.wikipedia.org/wiki/ro:Olteni%C5%A3a" class='extiw' title="Wikipedia:ro:Olteniţa">Wikipedia:ro:Olteni&#355;a</a>
+</li><li><a href="http://en.wikipedia.org/wiki/ro:Olteni%C5%A3a" class='extiw' title="Wikipedia:ro:Olteniţa">Wikipedia:ro:Olteni&#355;a</a>
+</li></ul>
+
+!! end
+
+!! test
+Interwiki link with fragment (bug 2130)
+!! input
+[[MeatBall:SoftSecurity#foo]]
+!! result
+<p><a href="http://www.usemod.com/cgi-bin/mb.pl?SoftSecurity#foo" class='extiw' title="MeatBall:SoftSecurity">MeatBall:SoftSecurity#foo</a>
+</p>
+!! end
+
+##
+## XHTML tidiness
+###
+
+!! test
+<br> to <br />
+!! input
+1<br>2<br />3
+!! result
+<p>1<br />2<br />3
+</p>
+!! end
+
+!! test
+Incorrecly removing closing slashes from correctly formed XHTML
+!! input
+<br style="clear:both;" />
+!! result
+<p><br style="clear:both;" />
+</p>
+!! end
+
+!! test 
+Failing to transform badly formed HTML into correct XHTML
+!! input
+<br clear=left>
+<br clear=right>
+<br clear=all>
+!! result
+<p><br style="clear:left;" />
+<br style="clear:right;" />
+<br style="clear:both;" />
+</p>
+!!end
+
+!! test 
+Horizontal ruler (should it add that extra space?)
+!! input 
+<hr>
+<hr >
+foo <hr
+> bar
+!! result 
+<hr />
+<hr />
+foo <hr /> bar
+!! end
+
+###
+### Block-level elements
+###
+!! test
+Common list
+!! input
+*Common list
+* item 2
+*item 3
+!! result
+<ul><li>Common list
+</li><li> item 2
+</li><li>item 3
+</li></ul>
+
+!! end
+
+!! test
+Numbered list
+!! input
+#Numbered list
+#item 2
+# item 3
+!! result
+<ol><li>Numbered list
+</li><li>item 2
+</li><li> item 3
+</li></ol>
+
+!! end
+
+!! test
+Mixed list
+!! input
+*Mixed list
+*# with numbers
+** and bullets
+*# and numbers
+*bullets again
+**bullet level 2
+***bullet level 3
+***#Number on level 4
+**bullet level 2
+**#Number on level 3
+**#Number on level 3
+*#number level 2
+*Level 1
+!! result
+<ul><li>Mixed list
+<ol><li> with numbers
+</li></ol>
+<ul><li> and bullets
+</li></ul>
+<ol><li> and numbers
+</li></ol>
+</li><li>bullets again
+<ul><li>bullet level 2
+<ul><li>bullet level 3
+<ol><li>Number on level 4
+</li></ol>
+</li></ul>
+</li><li>bullet level 2
+<ol><li>Number on level 3
+</li><li>Number on level 3
+</li></ol>
+</li></ul>
+<ol><li>number level 2
+</li></ol>
+</li><li>Level 1
+</li></ul>
+
+!! end
+
+!! test
+List items are not parsed correctly following a <pre> block (bug 785)
+!! input
+* <pre>foo</pre>
+* <pre>bar</pre>
+* zar
+!! result
+<ul><li> <pre>foo</pre>
+</li><li> <pre>bar</pre>
+</li><li> zar
+</li></ul>
+
+!! end
+
+###
+### Magic variables
+###
+!! test
+Magic variables
+!! input
+{{SITENAME}}
+!! result
+<p>MediaWiki
+</p>
+!! end
+
+###
+### Magic links
+###
+!! test
+Magic links: internal link to RFC (bug 479)
+!! input
+[[RFC 123]]
+!! result
+<p><a href="/index.php?title=RFC_123&amp;action=edit" class="new" title="RFC 123">RFC 123</a>
+</p>
+!! end
+
+!! test
+Magic links: RFC (bug 479)
+!! input
+RFC 822
+!! result
+<p><a href='http://www.ietf.org/rfc/rfc822.txt' class='external' title="http://www.ietf.org/rfc/rfc822.txt">RFC 822</a>
+</p>
+!! end
+
+!! test
+Magic links: ISBN (bug 1937)
+!! input
+ISBN 0-306-40615-2
+!! result
+<p><a href="/index.php?title=Special:Booksources&amp;isbn=0306406152" class="internal">ISBN 0-306-40615-2</a>
+</p>
+!! end
+
+!! test
+Magic links: PMID incorrectly converts space to underscore
+!! input
+PMID 1234
+!! result
+<p><a href='http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?cmd=Retrieve&amp;db=pubmed&amp;dopt=Abstract&amp;list_uids=1234' class='external' title="http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?cmd=Retrieve&amp;db=pubmed&amp;dopt=Abstract&amp;list_uids=1234">PMID 1234</a>
+</p>
+!! end
+
+###
+### Templates
+####
+
+!! test
+Nonexistant template
+!! input
+{{thistemplatedoesnotexist}}
+!! result
+<p><a href="/index.php?title=Template:Thistemplatedoesnotexist&amp;action=edit" class="new" title="Template:Thistemplatedoesnotexist">Template:Thistemplatedoesnotexist</a>
+</p>
+!! end
+
+!! article
+Template:test
+!! text
+This is a test template
+!! endarticle
+
+!! test
+Simple template
+!! input
+{{test}}
+!! result
+<p>This is a test template
+</p>
+!! end
+
+!! test
+Template with explicit namespace
+!! input
+{{Template:test}}
+!! result
+<p>This is a test template
+</p>
+!! end
+
+
+!! article
+Template:paramtest
+!! text
+This is a test template with parameter {{{param}}}
+!! endarticle
+
+!! test
+Template parameter
+!! input
+{{paramtest|param=foo}}
+!! result
+<p>This is a test template with parameter foo
+</p>
+!! end
+
+!! article
+Template:paramtestnum
+!! text
+[[{{{1}}}|{{{2}}}]]
+!! endarticle
+
+!! test
+Template unnamed parameter
+!! input
+{{paramtestnum|Main Page|the main page}}
+!! result
+<p><a href="/wiki/Main_Page" title="Main Page">the main page</a>
+</p>
+!! end
+
+!! test
+BUG 553: link with two variables in a piped link
+!! input
+{| 
+|[[{{{1}}}|{{{2}}}]]
+|}
+!! result
+<table>
+<tr>
+<td>[[{{{1}}}|{{{2}}}]]
+</td></tr></table>
+
+!! end
+
+!! test
+Magic variable as template parameter
+!! input
+{{paramtest|param={{SITENAME}}}}
+!! result
+<p>This is a test template with parameter MediaWiki
+</p>
+!! end
+
+!! article
+Template:linktest
+!! text
+[[{{{param}}}|link]]
+!! endarticle
+
+!! test
+Template parameter as link source
+!! input
+{{linktest|param=Main Page}}
+!! result
+<p><a href="/wiki/Main_Page" title="Main Page">link</a>
+</p>
+!! end
+
+
+!!article
+Template:paramtest2
+!! text
+including another template, {{paramtest|param={{{arg}}}}}
+!! endarticle
+
+!! test
+Template passing argument to another template
+!! input
+{{paramtest2|arg='hmm'}}
+!! result
+<p>including another template, This is a test template with parameter 'hmm'
+</p>
+!! end
+
+!! article
+Template:Linktest2
+!! text
+Main Page
+!! endarticle
+
+!! test
+Template as link source
+!! input
+[[{{linktest2}}]]
+!! result
+<p><a href="/wiki/Main_Page" title="Main Page">Main Page</a>
+</p>
+!! end
+
+
+!! article
+Template:loop1
+!! text
+{{loop2}}
+!! endarticle
+
+!! article
+Template:loop2
+!! text
+{{loop1}}
+!! endarticle
+
+!! test
+Template infinite loop
+!! input
+{{loop1}}
+!! result
+<p>{{loop1}}<!-- WARNING: template loop detected -->
+</p>
+!! end
+
+!! test
+Template from main namespace
+!! input
+{{:Main Page}}
+!! result
+<p>blah blah
+</p>
+!! end
+
+!! article
+Template:table
+!! text
+{| 
+| 1 || 2
+|- 
+| 3 || 4
+|}
+!! endarticle
+
+!! test
+BUG 529: Template with table, not included at beginning of line
+!! input
+foo {{table}}
+!! result
+<p>foo 
+</p>
+<table>
+<tr>
+<td> 1 </td><td> 2
+</td></tr>
+<tr>
+<td> 3 </td><td> 4
+</td></tr></table>
+
+!! end
+
+!! test
+BUG 523: Template shouldn't eat newline (or add an extra one before table)
+!! input
+foo
+{{table}}
+!! result
+<p>foo
+</p>
+<table>
+<tr>
+<td> 1 </td><td> 2
+</td></tr>
+<tr>
+<td> 3 </td><td> 4
+</td></tr></table>
+
+!! end
+
+!! test
+BUG 41: Template parameters shown as broken links
+!! input
+{{{parameter}}}
+!! result
+<p>{{{parameter}}}
+</p>
+!! end
+
+
+!! article
+Template:MSGNW test
+!! text
+''None'' of '''this''' should be 
+* interepreted
+ but rather passed unmodified
+{{test}}
+!! endarticle
+
+# hmm, fix this or just deprecate msgnw and document its behavior?
+!! test
+msgnw keyword
+!! options
+disabled
+!! input
+{{msgnw:MSGNW test}}
+!! result
+<p>''None'' of '''this''' should be 
+* interepreted
+ but rather passed unmodified
+{{test}}
+</p>
+!! end
+
+!! test
+int keyword
+!! input
+{{int:newmessages|lots of money}}
+!! result
+<p>You have lots of money.
+</p>
+!! end
+
+###
+### Pre-save transform tests
+###
+!! test
+pre-save transform: subst:
+!! options
+PST
+!! input
+{{subst:test}}
+!! result
+This is a test template
+!! end
+
+!! test
+pre-save transform: normal template
+!! options
+PST
+!! input
+{{test}}
+!! result
+{{test}}
+!! end
+
+!! test
+pre-save transform: nonexistant template
+!! options
+PST
+!! input
+{{thistemplatedoesnotexist}}
+!! result
+{{thistemplatedoesnotexist}}
+!! end
+
+
+!! test
+pre-save transform: subst magic variables
+!! options
+PST
+!! input
+{{subst:SITENAME}}
+!! result
+MediaWiki
+!! end
+
+# This is bug 89, which I fixed. -- wtm
+!! test
+pre-save transform: subst: templates with parameters
+!! options
+pst
+!! input
+{{subst:paramtest|param="something else"}}
+!! result
+This is a test template with parameter "something else"
+!! end
+
+
+!! article
+Template:nowikitest
+!! text
+<nowiki>'''not wiki'''</nowiki>
+!! endarticle
+
+!! test
+pre-save transform: nowiki in subst (bug 1188)
+!! options
+pst
+!! input
+{{subst:nowikitest}}
+!! result
+<nowiki>'''not wiki'''</nowiki>
+!! end
+
+
+!! article
+Template:commenttest
+!! text
+This template has <!-- a comment --> in it.
+!! endarticle
+
+!! test
+pre-save transform: comment in subst (bug 1936)
+!! options
+pst
+!! input
+{{subst:commenttest}}
+!! result
+This template has <!-- a comment --> in it.
+!! end
+
+
+!! article
+Template:dangerous
+!!text
+<span onmouseover="alert('crap')">Oh no</span>
+!!endarticle
+
+!!test
+(confirming safety of fix for subst bug 1936)
+!! input
+{{Template:dangerous}}
+!! result
+<p><span>Oh no</span>
+</p>
+!! end
+
+
+###
+### Message transform tests
+###
+!! test
+message transform: magic variables
+!! options
+msg
+!! input
+{{SITENAME}}
+!! result
+MediaWiki
+!! end
+
+!! test
+message transform: should not transform wiki markup
+!! options
+msg
+!! input
+''test''
+!! result
+''test''
+!! end
+
+###
+### Images
+###
+!! test
+Simple image
+!! input
+[[Image:foobar.jpg]]
+!! result
+<p><a href="/wiki/Image:Foobar.jpg" class="image" title="Image:foobar.jpg"><img src="/images/3/3a/Foobar.jpg" alt="Image:foobar.jpg" width="1941" height="220" longdesc="/wiki/Image:Foobar.jpg" /></a>
+</p>
+!! end
+
+!! test
+Right-aligned image
+!! input
+[[Image:foobar.jpg|right]]
+!! result
+<div class="floatright"><span><a href="/wiki/Image:Foobar.jpg" class="image" title=""><img src="/images/3/3a/Foobar.jpg" alt="" width="1941" height="220" longdesc="/wiki/Image:Foobar.jpg" /></a></span></div>
+
+!! end
+
+!! test
+Image with caption
+!! input
+[[Image:foobar.jpg|right|Caption text]]
+!! result
+<div class="floatright"><span><a href="/wiki/Image:Foobar.jpg" class="image" title="Caption text"><img src="/images/3/3a/Foobar.jpg" alt="Caption text" width="1941" height="220" longdesc="/wiki/Image:Foobar.jpg" /></a></span></div>
+
+!! end
+
+!! test
+Image with frame and link
+!! input
+[[Image:Foobar.jpg|frame|left|This is a test image [[Main Page]]]]
+!! result
+<div class="thumb tleft"><div style="width:1943px;"><a href="/wiki/Image:Foobar.jpg" class="internal" title="This is a test image Main Page"><img src="/images/3/3a/Foobar.jpg" alt="This is a test image Main Page" width="1941" height="220" longdesc="/wiki/Image:Foobar.jpg" /></a>  <div class="thumbcaption" >This is a test image <a href="/wiki/Main_Page" title="Main Page">Main Page</a></div></div></div>
+
+!! end
+
+!! test
+Link to image page
+!! input
+[[:Image:test]]
+!! result
+<p><a href="/wiki/Image:Test" title="Image:Test">Image:test</a>
+</p>
+!! end
+
+!! test
+Frameless image caption with a free URL
+!! input
+[[Image:foobar.jpg|http://example.com]]
+!! result
+<p><a href="/wiki/Image:Foobar.jpg" class="image" title="http://example.com"><img src="/images/3/3a/Foobar.jpg" alt="http://example.com" width="1941" height="220" longdesc="/wiki/Image:Foobar.jpg" /></a>
+</p>
+!! end
+
+!! test
+Thumbnail image caption with a free URL
+!! input
+[[Image:foobar.jpg|thumb|http://example.com]]
+!! result
+<div class="thumb tright"><div style="width:182px;"><a href="/wiki/Image:Foobar.jpg" class="internal" title="http://example.com"><img src="/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" alt="http://example.com" width="180" height="20" longdesc="/wiki/Image:Foobar.jpg" /></a>  <div class="thumbcaption" ><div class="magnify" style="float:right"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="Enlarge" /></a></div><a href="http://example.com" class='external free' title="http://example.com" rel="nofollow">http://example.com</a></div></div></div>
+
+!! end
+
+!! test
+BUG 1887: A ISBN with a thumbnail
+!! input
+[[Image:foobar.jpg|thumb|ISBN 12354]]
+!! result
+<div class="thumb tright"><div style="width:182px;"><a href="/wiki/Image:Foobar.jpg" class="internal" title="ISBN 12354"><img src="/images/3/3a/Foobar.jpg" alt="ISBN 12354" longdesc="/wiki/Image:Foobar.jpg" height="180" width="180"></a>  <div class="thumbcaption"><div class="magnify" style="float:right;"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="Enlarge"></a></div><a href="index.php?title=Special:Booksources&amp;isbn=12354" class="internal">ISBN 12354</a></div></div></div>
+!! end
+
+!! test
+BUG 1887: A <math> with a thumbnail
+!! input
+[[Image:foobar.jpg|thumb|<math>2+2</math>]]
+!! result
+<div class="thumb tright"><div style="width:182px;"><a href="/wiki/Image:Foobar.jpg" class="internal" title="2+2"><img src="/images/3/3a/Foobar.jpg" alt="2+2" longdesc="/wiki/Image:Foobar.jpg" height="180" width="180"></a>  <div class="thumbcaption"><div class="magnify" style="float:right;"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="Enlarge"></a></div>&lt;math&gt;2+2&lt;math&gt;</div></div></div>
+!! end
+
+# Pending resolution to bug 368
+!! test
+BUG 648: Frameless image caption with a link
+!! input
+[[Image:foobar.jpg|text with a [[link]] in it]]
+!! result
+<p><a href="/wiki/Image:Foobar.jpg" class="image" title="text with a link in it"><img src="/images/3/3a/Foobar.jpg" alt="text with a link in it" width="1941" height="220" longdesc="/wiki/Image:Foobar.jpg" /></a>
+</p>
+!! end
+
+!! test
+BUG 648: Frameless image caption with a link (suffix)
+!! input
+[[Image:foobar.jpg|text with a [[link]]foo in it]]
+!! result
+<p><a href="/wiki/Image:Foobar.jpg" class="image" title="text with a linkfoo in it"><img src="/images/3/3a/Foobar.jpg" alt="text with a linkfoo in it" width="1941" height="220" longdesc="/wiki/Image:Foobar.jpg" /></a>
+</p>
+!! end
+
+!! test
+BUG 648: Frameless image caption with an interwiki link
+!! input
+[[Image:foobar.jpg|text with a [[MeatBall:Link]] in it]]
+!! result
+<p><a href="/wiki/Image:Foobar.jpg" class="image" title="text with a MeatBall:Link in it"><img src="/images/3/3a/Foobar.jpg" alt="text with a MeatBall:Link in it" width="1941" height="220" longdesc="/wiki/Image:Foobar.jpg" /></a>
+</p>
+!! end
+
+!! test
+BUG 648: Frameless image caption with a piped interwiki link
+!! input
+[[Image:foobar.jpg|text with a [[MeatBall:Link|link]] in it]]
+!! result
+<p><a href="/wiki/Image:Foobar.jpg" class="image" title="text with a link in it"><img src="/images/3/3a/Foobar.jpg" alt="text with a link in it" width="1941" height="220" longdesc="/wiki/Image:Foobar.jpg" /></a>
+</p>
+!! end
+
+!! test
+Escape HTML special chars in image alt text
+!! input
+[[Image:foobar.jpg|& < > "]]
+!! result
+<p><a href="/wiki/Image:Foobar.jpg" class="image" title="&amp; &lt; &gt; &quot;"><img src="/images/3/3a/Foobar.jpg" alt="&amp; &lt; &gt; &quot;" width="1941" height="220" longdesc="/wiki/Image:Foobar.jpg" /></a>
+</p>
+!! end
+
+!! test
+BUG 499: Alt text should have &#1234;, not &amp;1234;
+!! input
+[[Image:foobar.jpg|&#9792;]]
+!! result
+<p><a href="/wiki/Image:Foobar.jpg" class="image" title="&#9792;"><img src="/images/3/3a/Foobar.jpg" alt="&#9792;" width="1941" height="220" longdesc="/wiki/Image:Foobar.jpg" /></a>
+</p>
+!! end
+
+!! test
+Broken image caption with link
+!! input
+[[Image:Foobar.jpg|thumb|This is a broken caption. But [[Main Page|this]] is just an ordinary link.
+!! result
+<p>[[Image:Foobar.jpg|thumb|This is a broken caption. But <a href="/wiki/Main_Page" title="Main Page">this</a> is just an ordinary link.
+</p>
+!! end
+
+!! test
+Image caption containing another image
+!! input
+[[Image:Foobar.jpg|thumb|This is a caption with another [[Image:icon.png|image]] inside it!]]
+!! result
+<div class="thumb tright"><div style="width:182px;"><a href="/wiki/Image:Foobar.jpg" class="internal" title="This is a caption with another Image:Icon.png inside it!"><img src="/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" alt="This is a caption with another Image:Icon.png inside it!" width="180" height="20" longdesc="/wiki/Image:Foobar.jpg" /></a>  <div class="thumbcaption" ><div class="magnify" style="float:right"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="Enlarge" /></a></div>This is a caption with another <a href="/index.php?title=Special:Upload&amp;wpDestFile=Icon.png" class="new" title="Image:Icon.png">Image:Icon.png</a> inside it!</div></div></div>
+
+!! end
+
+!! test
+Image caption containing a newline
+!! input
+[[Image:Foobar.jpg|This
+*is some text]]
+!! result
+<p><a href="/wiki/Image:Foobar.jpg" class="image" title="This *is some text"><img src="/images/3/3a/Foobar.jpg" alt="This *is some text" width="1941" height="220" longdesc="/wiki/Image:Foobar.jpg" /></a>
+</p>
+!!end
+
+
+!! test
+Bug 3090: External links other than http: in image captions
+!! input
+[[Image:Foobar.jpg|thumb|200px|This caption has [irc://example.net irc] and [https://example.com Secure] ext links in it.]]
+!! result
+<div class="thumb tright"><div style="width:202px;"><a href="/wiki/Image:Foobar.jpg" class="internal" title="This caption has irc and Secure ext links in it."><img src="/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" alt="This caption has irc and Secure ext links in it." width="200" height="23" longdesc="/wiki/Image:Foobar.jpg" /></a>  <div class="thumbcaption" ><div class="magnify" style="float:right"><a href="/wiki/Image:Foobar.jpg" class="internal" title="Enlarge"><img src="/skins/common/images/magnify-clip.png" width="15" height="11" alt="Enlarge" /></a></div>This caption has <a href="irc://example.net" class='external text' title="irc://example.net" rel="nofollow">irc</a> and <a href="https://example.com" class='external text' title="https://example.com" rel="nofollow">Secure</a> ext links in it.</div></div></div>
+
+!! end
+
+
+###
+### Subpages
+###
+!! article
+Subpage test/subpage
+!! text
+foo
+!! endarticle
+
+!! test
+Subpage link
+!! options
+subpage title=[[Subpage test]]
+!! input
+[[/subpage]]
+!! result
+<p><a href="/wiki/Subpage_test/subpage" title="Subpage test/subpage">/subpage</a>
+</p>
+!! end
+
+!! test
+Subpage noslash link
+!! options
+subpage title=[[Subpage test]]
+!!input
+[[/subpage/]]
+!! result
+<p><a href="/wiki/Subpage_test/subpage" title="Subpage test/subpage">subpage</a>
+</p>
+!! end
+
+!! test
+Disabled subpages
+!! input
+[[/subpage]]
+!! result
+<p><a href="/index.php?title=/subpage&amp;action=edit" class="new" title="/subpage">/subpage</a>
+</p>
+!! end
+
+!! test
+BUG 561: {{/Subpage}}
+!! options
+subpage title=[[Page]]
+!! input
+{{/Subpage}}
+!! result
+<p><a href="/index.php?title=Page/Subpage&amp;action=edit" class="new" title="Page/Subpage">Page/Subpage</a>
+</p>
+!! end
+
+###
+### Categories
+###
+!! article
+Category:MediaWiki User's Guide
+!! text
+blah
+!! endarticle
+
+!! test
+Link to category
+!! input
+[[:Category:MediaWiki User's Guide]]
+!! result
+<p><a href="/wiki/Category:MediaWiki_User%27s_Guide" title="Category:MediaWiki User's Guide">Category:MediaWiki User's Guide</a>
+</p>
+!! end
+
+!! test
+Simple category
+!! options
+cat
+!! input
+[[Category: MediaWiki User's Guide]]
+!! result
+<a href="/wiki/Category:MediaWiki_User%27s_Guide" title="Category:MediaWiki User's Guide">MediaWiki User's Guide</a>
+!! end
+
+###
+### Inter-language links
+###
+!! test
+Inter-language links
+!! options
+ill
+!! input
+[[es:Alimento]]
+[[fr:Nourriture]]
+[[zh:&#39135;&#21697;]]
+!! result
+es:Alimento fr:Nourriture zh:食品
+!! end
+
+###
+### Sections
+###
+!! test
+Basic section headings
+!! options
+title=[[Parser test script]]
+!! input
+== Headline 1 ==
+Some text
+
+==Headline 2==
+More
+===Smaller headline===
+Blah blah
+!! result
+<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test_script&amp;action=edit&amp;section=1" title="Parser test script">edit</a>]</div><a name="Headline_1"></a><h2> Headline 1 </h2>
+<p>Some text
+</p>
+<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test_script&amp;action=edit&amp;section=2" title="Parser test script">edit</a>]</div><a name="Headline_2"></a><h2>Headline 2</h2>
+<p>More
+</p>
+<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test_script&amp;action=edit&amp;section=3" title="Parser test script">edit</a>]</div><a name="Smaller_headline"></a><h3>Smaller headline</h3>
+<p>Blah blah
+</p>
+!! end
+
+!! test
+Section headings with TOC
+!! options
+title=[[Parser test script]]
+!! input
+== Headline 1 ==
+=== Subheadline 1 ===
+===== Skipping a level =====
+====== Skipping a level ======
+
+== Headline 2 ==
+Some text
+===Another headline===
+!! result
+<table id='toc' class='toc'><tr><td><div id='toctitle'><h2>Contents</h2></div>
+<ul>
+<li class='toclevel-1'><a href="#Headline_1"><span class="tocnumber">1</span> <span class="toctext">Headline 1</span></a>
+<ul>
+<li class='toclevel-2'><a href="#Subheadline_1"><span class="tocnumber">1.1</span> <span class="toctext">Subheadline 1</span></a>
+<ul>
+<li class='toclevel-3'><a href="#Skipping_a_level"><span class="tocnumber">1.1.1</span> <span class="toctext">Skipping a level</span></a>
+<ul>
+<li class='toclevel-4'><a href="#Skipping_a_level_2"><span class="tocnumber">1.1.1.1</span> <span class="toctext">Skipping a level</span></a></li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+</li>
+<li class='toclevel-1'><a href="#Headline_2"><span class="tocnumber">2</span> <span class="toctext">Headline 2</span></a>
+<ul>
+<li class='toclevel-2'><a href="#Another_headline"><span class="tocnumber">2.1</span> <span class="toctext">Another headline</span></a></li>
+</ul>
+</li>
+</ul>
+</td></tr></table>
+<script type="text/javascript"> if (window.showTocToggle) { var tocShowText = "show"; var tocHideText = "hide"; showTocToggle(); } </script>
+<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test_script&amp;action=edit&amp;section=1" title="Parser test script">edit</a>]</div><a name="Headline_1"></a><h2> Headline 1 </h2>
+<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test_script&amp;action=edit&amp;section=2" title="Parser test script">edit</a>]</div><a name="Subheadline_1"></a><h3> Subheadline 1 </h3>
+<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test_script&amp;action=edit&amp;section=3" title="Parser test script">edit</a>]</div><a name="Skipping_a_level"></a><h5> Skipping a level </h5>
+<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test_script&amp;action=edit&amp;section=4" title="Parser test script">edit</a>]</div><a name="Skipping_a_level_2"></a><h6> Skipping a level </h6>
+<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test_script&amp;action=edit&amp;section=5" title="Parser test script">edit</a>]</div><a name="Headline_2"></a><h2> Headline 2 </h2>
+<p>Some text
+</p>
+<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test_script&amp;action=edit&amp;section=6" title="Parser test script">edit</a>]</div><a name="Another_headline"></a><h3>Another headline</h3>
+
+!! end
+
+# perl -e 'print "="x$_," Level $_ heading","="x$_,"\n" for 1..10'
+!! test
+Handling of sections up to level 6 and beyond
+!! input 
+= Level 1 Heading=
+== Level 2 Heading==
+=== Level 3 Heading===
+==== Level 4 Heading====
+===== Level 5 Heading=====
+====== Level 6 Heading======
+======= Level 7 Heading=======
+======== Level 8 Heading========
+========= Level 9 Heading=========
+========== Level 10 Heading==========
+!! result
+<table id='toc' class='toc'><tr><td><div id='toctitle'><h2>Contents</h2></div>
+<ul>
+<li class='toclevel-1'><a href="#Level_1_Heading"><span class="tocnumber">1</span> <span class="toctext">Level 1 Heading</span></a>
+<ul>
+<li class='toclevel-2'><a href="#Level_2_Heading"><span class="tocnumber">1.1</span> <span class="toctext">Level 2 Heading</span></a>
+<ul>
+<li class='toclevel-3'><a href="#Level_3_Heading"><span class="tocnumber">1.1.1</span> <span class="toctext">Level 3 Heading</span></a>
+<ul>
+<li class='toclevel-4'><a href="#Level_4_Heading"><span class="tocnumber">1.1.1.1</span> <span class="toctext">Level 4 Heading</span></a>
+<ul>
+<li class='toclevel-5'><a href="#Level_5_Heading"><span class="tocnumber">1.1.1.1.1</span> <span class="toctext">Level 5 Heading</span></a>
+<ul>
+<li class='toclevel-6'><a href="#Level_6_Heading"><span class="tocnumber">1.1.1.1.1.1</span> <span class="toctext">Level 6 Heading</span></a></li>
+<li class='toclevel-6'><a href="#.3D_Level_7_Heading.3D"><span class="tocnumber">1.1.1.1.1.2</span> <span class="toctext">= Level 7 Heading=</span></a></li>
+<li class='toclevel-6'><a href="#.3D.3D_Level_8_Heading.3D.3D"><span class="tocnumber">1.1.1.1.1.3</span> <span class="toctext">== Level 8 Heading==</span></a></li>
+<li class='toclevel-6'><a href="#.3D.3D.3D_Level_9_Heading.3D.3D.3D"><span class="tocnumber">1.1.1.1.1.4</span> <span class="toctext">=== Level 9 Heading===</span></a></li>
+<li class='toclevel-6'><a href="#.3D.3D.3D.3D_Level_10_Heading.3D.3D.3D.3D"><span class="tocnumber">1.1.1.1.1.5</span> <span class="toctext">==== Level 10 Heading====</span></a></li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+</td></tr></table>
+<p><script type="text/javascript"> if (window.showTocToggle) { var tocShowText = "show"; var tocHideText = "hide"; showTocToggle(); } </script>
+</p>
+<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Parser test">edit</a>]</div><a name="Level_1_Heading"></a><h1> Level 1 Heading</h1>
+<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=2" title="Parser test">edit</a>]</div><a name="Level_2_Heading"></a><h2> Level 2 Heading</h2>
+<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=3" title="Parser test">edit</a>]</div><a name="Level_3_Heading"></a><h3> Level 3 Heading</h3>
+<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=4" title="Parser test">edit</a>]</div><a name="Level_4_Heading"></a><h4> Level 4 Heading</h4>
+<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=5" title="Parser test">edit</a>]</div><a name="Level_5_Heading"></a><h5> Level 5 Heading</h5>
+<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=6" title="Parser test">edit</a>]</div><a name="Level_6_Heading"></a><h6> Level 6 Heading</h6>
+<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=7" title="Parser test">edit</a>]</div><a name=".3D_Level_7_Heading.3D"></a><h6>= Level 7 Heading=</h6>
+<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=8" title="Parser test">edit</a>]</div><a name=".3D.3D_Level_8_Heading.3D.3D"></a><h6>== Level 8 Heading==</h6>
+<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=9" title="Parser test">edit</a>]</div><a name=".3D.3D.3D_Level_9_Heading.3D.3D.3D"></a><h6>=== Level 9 Heading===</h6>
+<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test&amp;action=edit&amp;section=10" title="Parser test">edit</a>]</div><a name=".3D.3D.3D.3D_Level_10_Heading.3D.3D.3D.3D"></a><h6>==== Level 10 Heading====</h6>
+
+!! end
+
+!! test
+Resolving duplicate section names
+!! options
+title=[[Parser test script]]
+!! input
+== Foo bar ==
+== Foo bar ==
+!! result
+<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test_script&amp;action=edit&amp;section=1" title="Parser test script">edit</a>]</div><a name="Foo_bar"></a><h2> Foo bar </h2>
+<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test_script&amp;action=edit&amp;section=2" title="Parser test script">edit</a>]</div><a name="Foo_bar_2"></a><h2> Foo bar </h2>
+
+!! end
+
+!! article
+Template:sections
+!! text
+===Section 1===
+==Section 2==
+!! endarticle
+
+!! test
+Template with sections, __NOTOC__
+!! options
+title=[[Parser test script]]
+!! input
+__NOTOC__
+==Section 0==
+{{sections}}
+==Section 4==
+!! result
+<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test_script&amp;action=edit&amp;section=1" title="Parser test script">edit</a>]</div><a name="Section_0"></a><h2>Section 0</h2>
+<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Template:Sections&amp;action=edit&amp;section=1" title="Template:Sections">edit</a>]</div><a name="Section_1"></a><h3>Section 1</h3>
+<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Template:Sections&amp;action=edit&amp;section=2" title="Template:Sections">edit</a>]</div><a name="Section_2"></a><h2>Section 2</h2>
+<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test_script&amp;action=edit&amp;section=2" title="Parser test script">edit</a>]</div><a name="Section_4"></a><h2>Section 4</h2>
+
+!! end
+
+!! test
+__NOEDITSECTION__ keyword
+!! input
+__NOEDITSECTION__
+==Section 1==
+==Section 2==
+!! result
+<a name="Section_1"></a><h2>Section 1</h2>
+<a name="Section_2"></a><h2>Section 2</h2>
+
+!! end
+
+!! test
+Link inside a section heading
+!! options
+title=[[Parser test script]]
+!! input
+==Section with a [[Main Page|link]] in it==
+!! result
+<div class="editsection" style="float:right;margin-left:5px;">[<a href="/index.php?title=Parser_test_script&amp;action=edit&amp;section=1" title="Parser test script">edit</a>]</div><a name="Section_with_a_link_in_it"></a><h2>Section with a <a href="/wiki/Main_Page" title="Main Page">link</a> in it</h2>
+
+!! end
+
+
+!! test
+BUG 1219 URL next to image (good)
+!! input
+http://example.com [[Image:foobar.jpg]]
+!! result
+<p><a href="http://example.com" class='external free' title="http://example.com" rel="nofollow">http://example.com</a> <a href="/wiki/Image:Foobar.jpg" class="image" title="Image:foobar.jpg"><img src="/images/3/3a/Foobar.jpg" alt="Image:foobar.jpg" width="1941" height="220" longdesc="/wiki/Image:Foobar.jpg" /></a>
+</p>
+!!end
+
+!! test
+BUG 1219 URL next to image (broken)
+!! input
+http://example.com[[Image:foobar.jpg]]
+!! result
+<p><a href="http://example.com" class='external free' title="http://example.com" rel="nofollow">http://example.com</a><a href="/wiki/Image:Foobar.jpg" class="image" title="Image:foobar.jpg"><img src="/images/3/3a/Foobar.jpg" alt="Image:foobar.jpg" width="1941" height="220" longdesc="/wiki/Image:Foobar.jpg" /></a>
+</p>
+!!end
+
+!! test
+Bug 1186 news: in the middle of text
+!! input
+http://en.wikinews.org/wiki/Wikinews:Workplace
+!! result
+<p><a href="http://en.wikinews.org/wiki/Wikinews:Workplace" class='external free' title="http://en.wikinews.org/wiki/Wikinews:Workplace" rel="nofollow">http://en.wikinews.org/wiki/Wikinews:Workplace</a>
+</p>
+!!end
+
+
+!! test
+Namespaced link must have a title
+!! input
+[[Project:]]
+!! result
+<p>[[Project:]]
+</p>
+!!end
+
+!! test
+Namespaced link must have a title (bad fragment version)
+!! input
+[[Project:#fragment]]
+!! result
+<p>[[Project:#fragment]]
+</p>
+!!end
+
+
+!! test
+div with no attributes
+!! input
+<div>HTML rocks</div>
+!! result
+<div>HTML rocks</div>
+
+!! end
+
+!! test
+div with double-quoted attribute
+!! input
+<div id="rock">HTML rocks</div>
+!! result
+<div id="rock">HTML rocks</div>
+
+!! end
+
+!! test
+div with single-quoted attribute
+!! input
+<div id='rock'>HTML rocks</div>
+!! result
+<div id="rock">HTML rocks</div>
+
+!! end
+
+!! test
+div with unquoted attribute
+!! input
+<div id=rock>HTML rocks</div>
+!! result
+<div id="rock">HTML rocks</div>
+
+!! end
+
+!! test
+div with illegal double attributes
+!! input
+<div align="center" align="right">HTML rocks</div>
+!! result
+<div align="right">HTML rocks</div>
+
+!!end
+
+!! test
+HTML multiple attributes correction
+!! input
+<p class="error" class="awesome">Awesome!</p>
+!! result
+<p class="awesome">Awesome!</p>
+
+!!end
+
+!! test
+Table multiple attributes correction
+!! input
+{|
+!+ class="error" class="awesome"| status
+|}
+!! result
+<table>
+<tr>
+<th class="awesome">status</th>
+</tr>
+</table>
+
+!!end
+
+!! test
+DIV IN UPPERCASE
+!! input
+<DIV ALIGN="center">HTML ROCKS</DIV>
+!! result
+<div align="center">HTML ROCKS</div>
+
+!!end
+
+
+!! test
+text with amp in the middle of nowhere
+!! input
+Remember AT&T?
+!!result
+<p>Remember AT&amp;T?
+</p>
+!! end
+
+!! test
+text with character entity: eacute
+!! input
+I always thought &eacute; was a cute letter.
+!! result
+<p>I always thought &eacute; was a cute letter.
+</p>
+!! end
+
+!! test
+text with undefined character entity: xacute
+!! input
+I always thought &xacute; was a cute letter.
+!! result
+<p>I always thought &amp;xacute; was a cute letter.
+</p>
+!! end
+
+
+###
+### Media links
+###
+
+!! test
+Media link
+!! input
+[[Media:Foobar.jpg]]
+!! result
+<p><a href="/images/3/3a/Foobar.jpg" class='internal' title="Foobar.jpg">Media:Foobar.jpg</a>
+</p>
+!! end
+
+!! test
+Media link with text
+!! input
+[[Media:Foobar.jpg|A neat file to look at]]
+!! result
+<p><a href="/images/3/3a/Foobar.jpg" class='internal' title="Foobar.jpg">A neat file to look at</a>
+</p>
+!! end
+
+# FIXME: this is still bad HTML tag nesting
+!! test
+Media link with nasty text
+!! input
+[[Media:Foobar.jpg|Safe Link<div style=display:none>" onmouseover="alert(document.cookie)" onfoo="</div>]]
+!! result
+<p><a href="/images/3/3a/Foobar.jpg" class='internal' title="Foobar.jpg">Safe Link<div style="display:none">" onmouseover="alert(document.cookie) onfoo="</div></a>
+</p>
+!! end
+
+!! test
+Media link to nonexistent file (bug 1702)
+!! input
+[[Media:No such.jpg]]
+!! result
+<p><a href="/index.php?title=Special:Upload&amp;wpDestFile=No_such.jpg" class='new' title="No such.jpg">Media:No such.jpg</a>
+</p>
+!! end
+
+
+
+!! test
+Character reference normalization in link text (bug 1938)
+!! input
+[[Main Page|this&that]]
+!! result
+<p><a href="/wiki/Main_Page" title="Main Page">this&amp;that</a>
+</p>
+!!end
+
+!! test
+Empty attribute crash test (bug 2067)
+!! input
+<font color="">foo</font>
+!! result
+<p><font color="">foo</font>
+</p>
+!! end
+
+!! test
+Empty attribute crash test single-quotes (bug 2067)
+!! input
+<font color=''>foo</font>
+!! result
+<p><font color="">foo</font>
+</p>
+!! end
+
+!! test
+Attribute test: equals, then nothing
+!! input
+<font color=>foo</font>
+!! result
+<p><font>foo</font>
+</p>
+!! end
+
+!! test
+Attribute test: unquoted value
+!! input
+<font color=x>foo</font>
+!! result
+<p><font color="x">foo</font>
+</p>
+!! end
+
+!! test
+Attribute test: unquoted but illegal value (hash)
+!! input
+<font color=#x>foo</font>
+!! result
+<p><font color="#x">foo</font>
+</p>
+!! end
+
+!! test
+Attribute test: no value
+!! input
+<font color>foo</font>
+!! result
+<p><font color="color">foo</font>
+</p>
+!! end
+
+!! test
+Bug 2095: link with three closing brackets
+!! input
+[[Main Page]]]
+!! result
+<p><a href="/wiki/Main_Page" title="Main Page">Main Page</a>]
+</p>
+!! end
+
+!! test
+Bug 2095: link with pipe and three closing brackets
+!! input
+[[Main Page|link]]]
+!! result
+<p><a href="/wiki/Main_Page" title="Main Page">link</a>]
+</p>
+!! end
+
+
+###
+### Safety
+###
+
+!! article
+Template:Dangerous attribute
+!! text
+" onmouseover="alert(document.cookie)
+!! endarticle
+
+!! article
+Template:Dangerous style attribute
+!! text
+border-size: expression(alert(document.cookie))
+!! endarticle
+
+!! article
+Template:Div style
+!! text
+<div style="float: right; {{{1}}}">Magic div</div>
+!! endarticle
+
+!! test
+Bug 2304: HTML attribute safety (safe template; regression bug 2309)
+!! input
+<div title="{{test}}"></div>
+!! result
+<div title="This is a test template"></div>
+
+!! end
+
+!! test
+Bug 2304: HTML attribute safety (dangerous template; 2309)
+!! input
+<div title="{{dangerous attribute}}"></div>
+!! result
+<div title=""></div>
+
+!! end
+
+!! test
+Bug 2304: HTML attribute safety (dangerous style template; 2309)
+!! input
+<div style="{{dangerous style attribute}}"></div>
+!! result
+<div></div>
+
+!! end
+
+!! test
+Bug 2304: HTML attribute safety (safe parameter; 2309)
+!! input
+{{div style|width: 200px}}
+!! result
+<div style="float: right; width: 200px">Magic div</div>
+
+!! end
+
+!! test
+Bug 2304: HTML attribute safety (unsafe parameter; 2309)
+!! input
+{{div style|width: expression(alert(document.cookie))}}
+!! result
+<div>Magic div</div>
+
+!! end
+
+!! test
+Bug 2304: HTML attribute safety (unsafe breakout parameter; 2309)
+!! input
+{{div style|"><script>alert(document.cookie)</script>}}
+!! result
+<div>Magic div</div>
+
+!! end
+
+!! test
+Bug 2304: HTML attribute safety (unsafe breakout parameter 2; 2309)
+!! input
+{{div style|" ><script>alert(document.cookie)</script>}}
+!! result
+<div style="float: right; ">Magic div</div>
+
+!! end
+
+!! test
+Bug 2304: HTML attribute safety (link)
+!! input
+<div title="[[Main Page]]"></div>
+!! result
+<div title="&#91;&#91;Main Page]]"></div>
+
+!! end
+
+!! test
+Bug 2304: HTML attribute safety (italics)
+!! input
+<div title="''foobar''"></div>
+!! result
+<div title="&#39;&#39;foobar&#39;&#39;"></div>
+
+!! end
+
+!! test
+Bug 2304: HTML attribute safety (bold)
+!! input
+<div title="'''foobar'''"></div>
+!! result
+<div title="&#39;&#39;'foobar&#39;&#39;'"></div>
+
+!! end
+
+!! test
+Bug 2304: HTML attribute safety (ISBN)
+!! input
+<div title="ISBN 1234567890"></div>
+!! result
+<div title="&#73;SBN 1234567890"></div>
+
+!! end
+
+!! test
+Bug 2304: HTML attribute safety (RFC)
+!! input
+<div title="RFC 1234"></div>
+!! result
+<div title="&#82;FC 1234"></div>
+
+!! end
+
+!! test
+Bug 2304: HTML attribute safety (PMID)
+!! input
+<div title="PMID 1234567890"></div>
+!! result
+<div title="&#80;MID 1234567890"></div>
+
+!! end
+
+!! test
+Bug 2304: HTML attribute safety (web link)
+!! input
+<div title="http://example.com/"></div>
+!! result
+<div title="http&#58;//example.com/"></div>
+
+!! end
+
+!! test
+Bug 2304: HTML attribute safety (named web link)
+!! input
+<div title="[http://example.com/ link]"></div>
+!! result
+<div title="&#91;http&#58;//example.com/ link]"></div>
+
+!! end
+
+!! test
+Bug 3244: HTML attribute safety (extension; safe)
+!! input
+<div style="<nowiki>background:blue</nowiki>"></div>
+!! result
+<div style="background:blue"></div>
+
+!! end
+
+!! test
+Bug 3244: HTML attribute safety (extension; unsafe)
+!! input
+<div style="<nowiki>border-left:expression(alert(document.cookie))</nowiki>"></div>
+!! result
+<div></div>
+
+!! end
+
+
+!! test
+Math section safety when disabled
+!! input
+<math><script>alert(document.cookies);</script></math>
+!! result
+<p>&lt;math&gt;&lt;script&gt;alert(document.cookies);&lt;/script&gt;&lt;/math&gt;
+</p>
+!! end
+
+
+!! test
+Table attribute legitimate extension
+!! input
+{|
+!+ style="<nowiki>color:blue</nowiki>"| status
+|}
+!! result
+<table>
+<tr>
+<th style="color:blue"> status
+</th></tr></table>
+
+!!end
+
+!! test
+Table attribute safety
+!! input
+{|
+!+ style="<nowiki>border-width:expression(0+alert(document.cookie))</nowiki>"| status
+|}
+!! result
+<table>
+<tr>
+<th> status
+</th></tr></table>
+
+!! end
+
+
+# More MSIE fun discovered by Tom Gilder
+
+!! test
+MSIE CSS safety test: spurious slash
+!! input
+<div style="background-image:u\rl(javascript:alert('boo'))">evil</div>
+!! result
+<div>evil</div>
+
+!! end
+
+!! test
+MSIE CSS safety test: hex code
+!! input
+<div style="background-image:u\72l(javascript:alert('boo'))">evil</div>
+!! result
+<div>evil</div>
+
+!! end
+
+!! test
+MSIE CSS safety test: comment in url
+!! input
+<div style="background-image:u/**/rl(javascript:alert('boo'))">evil</div>
+!! result
+<div style="background-image:u rl(javascript:alert('boo'))">evil</div>
+
+!! end
+
+!! test
+MSIE CSS safety test: comment in expression
+!! input
+<div style="background-image:expres/**/sion(alert('boo4'))">evil4</div>
+!! result
+<div style="background-image:expres sion(alert('boo4'))">evil4</div>
+
+!! end
+
+
+TODO:
+more images
+more tables
+math
+character entities
+and much more
diff --git a/maintenance/portal.php b/maintenance/portal.php
new file mode 100644 (file)
index 0000000..c3093c6
--- /dev/null
@@ -0,0 +1,117 @@
+<?php
+/**
+ * @package MediaWiki
+ * @subpackage Maintenance
+ * @todo document
+ */
+$textsourcefile_web = "http://meta.wikipedia.org/w/index.php?title=PortalText&action=raw" ;
+$textsourcefile = "t.txt" ;
+#$articlecountfile_web = "http://magnusmanske.de/wikipedia/num.txt" ;
+$articlecountfile_web = "num.txt" ;
+$articlecountfile = "n.txt" ;
+$perrow = 3 ;
+
+if ( isset ( $HTTP_SERVER_VARS["HTTP_ACCEPT_LANGUAGE"] ) )
+       $userlang = $HTTP_SERVER_VARS["HTTP_ACCEPT_LANGUAGE"] ;
+else $userlang = '' ;
+
+# Update local files
+if ( isset ( $_GET["update"] ) )
+       {
+       copy ( $textsourcefile_web , $textsourcefile ) ;
+       copy ( $articlecountfile_web , $articlecountfile ) ;
+       }
+
+/**
+ * Reads a file into a string
+ */
+function readafile ( $filename )
+       {
+       $handle = fopen($filename, "r");
+       $contents = '';
+       while (!feof($handle))
+               $contents .= fread($handle, 8192);
+       fclose($handle);
+       return $contents ;
+       }
+
+/** Parsing statistics file */
+function get_numbers ( $filename )
+       {
+       $r = array () ;
+       $nt = readafile ( $filename ) ;
+       $nt = explode ( "\n" , $nt ) ;
+       foreach ( $nt AS $x )
+               {
+               $y = explode ( ":" , $x ) ;
+               if ( count ( $y ) == 2 )
+                       $r[strtolower($y[0])] = $y[1] ;
+               }
+       return $r ;
+       }
+       
+/** Make shades for pref. language(s) */
+function getshades ( $l )
+       {
+       $r = array () ;
+       $l = explode ( "," , $l ) ;
+       foreach ( $l AS $x )
+               {
+               $y = explode ( ";" , $x ) ;
+               if ( count ( $y ) == 2 ) $weight = array_pop ( explode ( "=" , $y[1] ) ) ;
+               else $weight = "1.0" ;
+               
+               $lang = array_shift ( $y ) ;
+               $lang = explode ( "-" , $lang ) ;
+               $lang = trim ( strtolower ( array_shift ( $lang ) ) ) ;
+
+               $w = 5 * $weight ;
+               $w = chr ( 70 - $w ) ;
+               $w = $w . $w ;
+               $w = $w.$w.$w ;
+               if ( !isset ( $r[$lang] ) || $r[$lang] < $w )
+                       $r[$lang] = $w ;
+               }
+       return $r ;
+       }
+
+# Parsing text file and generating output
+$n = get_numbers ( $articlecountfile ) ;
+$shade = getshades ( $userlang ) ;
+$l = "<table align=center border=1 width='50%' cellpadding=2>" ;
+$count = 0 ;
+$t = readafile ( $textsourcefile ) ;
+$t = explode ( "\n" , $t ) ;
+foreach ( $t AS $x )
+       {
+       $y = explode ( ':' , $x , 2 ) ;
+       if ( count ( $y ) == 2 )
+               {
+               $language = trim ( strtolower ( $y[0] ) ) ; # language id
+               if ( isset ( $n[$language] ) ) # Only if there's a number to show
+                       {
+                       $ltext = $y[1] ; # Language text
+                       $noa = $n[$language] ; # Number of articles
+                       $ltext = str_replace ( "###" , "<b>{$noa}</b>" , $ltext ) ;
+                       if ( isset ( $shade[$language] ) ) $s = " bgcolor='#" . $shade[$language] . "'" ;
+                       else $s = "" ;
+                       $ltext = "<td{$s}>{$ltext}</td>\n" ;
+                       if ( $count == 0 ) $l .= "<tr>" ;
+                       $l .= $ltext ;
+                       if ( $count == $perrow-1 )
+                               {
+                               $l .= "</tr>" ;
+                               $count = 0 ;
+                               }
+                       else $count++ ;
+                       }
+               }
+       }
+if ( $count != 0 ) $l .= "</tr>" ;
+$l .= "</table>" ;
+       
+print "<html><head></head><body>" ;
+print $l ;
+print "</body></html>" ;
+
+?>
\ No newline at end of file
diff --git a/maintenance/purgeOldText.inc b/maintenance/purgeOldText.inc
new file mode 100644 (file)
index 0000000..0bf6225
--- /dev/null
@@ -0,0 +1,63 @@
+<?php
+
+/**
+ * Support functions for cleaning up redundant text records
+ *
+ * @package MediaWiki
+ * @subpackage Maintenance
+ * @author Rob Church <robchur@gmail.com>
+ */
+
+function PurgeRedundantText( $delete = false ) {
+       
+       # Data should come off the master, wrapped in a transaction
+       $dbw =& wfGetDB( DB_MASTER );
+       $dbw->begin();
+       
+       $tbl_arc = $dbw->tableName( 'archive' );
+       $tbl_rev = $dbw->tableName( 'revision' );
+       $tbl_txt = $dbw->tableName( 'text' );
+       
+       # Get "active" text records from the revisions table
+       echo( "Searching for active text records in revisions table..." );
+       $res = $dbw->query( "SELECT DISTINCTROW rev_text_id FROM $tbl_rev" );
+       while( $row = $dbw->fetchObject( $res ) ) {
+               $cur[] = $row->rev_text_id;
+       }
+       echo( "done.\n" );
+       
+       # Get "active" text records from the archive table
+       echo( "Searching for active text records in archive table..." );
+       $res = $dbw->query( "SELECT DISTINCTROW ar_text_id FROM $tbl_arc" );
+       while( $row = $dbw->fetchObject( $res ) ) {
+               $cur[] = $row->ar_text_id;
+       }
+       echo( "done.\n" );
+       
+       # Get the IDs of all text records not in these sets
+       echo( "Searching for inactive text records..." );
+       $set = implode( ', ', $cur );
+       $res = $dbw->query( "SELECT old_id FROM $tbl_txt WHERE old_id NOT IN ( $set )" );
+       while( $row = $dbw->fetchObject( $res ) ) {
+               $old[] = $row->old_id;
+       }
+       echo( "done.\n" );
+       
+       # Inform the user of what we're going to do
+       $count = count( $old );
+       echo( "$count inactive items found.\n" );
+       
+       # Delete as appropriate
+       if( $delete && $count ) {
+               echo( "Deleting..." );
+               $set = implode( ', ', $old );
+               $dbw->query( "DELETE FROM $tbl_txt WHERE old_id IN ( $set )" );
+               echo( "done.\n" );
+       }
+       
+       # Done
+       $dbw->commit();
+       
+}
+
+?>
\ No newline at end of file
diff --git a/maintenance/purgeOldText.php b/maintenance/purgeOldText.php
new file mode 100644 (file)
index 0000000..e8a738a
--- /dev/null
@@ -0,0 +1,30 @@
+<?php
+
+/**
+ * Purge old text records from the database
+ *
+ * @package MediaWiki
+ * @subpackage Maintenance
+ * @author Rob Church <robchur@gmail.com>
+ */
+
+$options = array( 'purge', 'help' );
+require_once( 'commandLine.inc' );
+require_once( 'purgeOldText.inc' );
+
+echo( "Purge Old Text\n\n" );
+
+if( @$options['help'] ) {
+       ShowUsage();
+} else {
+       PurgeRedundantText( @$options['purge'] );
+}
+
+function ShowUsage() {
+       echo( "Prunes unused text records from the database.\n\n" );
+       echo( "Usage: php purgeOldText.php [--purge]\n\n" );
+       echo( "purge : Performs the deletion\n" );
+       echo( " help : Show this usage information\n" );
+}
+
+?>
\ No newline at end of file
diff --git a/maintenance/rebuildImages.php b/maintenance/rebuildImages.php
new file mode 100644 (file)
index 0000000..d14f77b
--- /dev/null
@@ -0,0 +1,275 @@
+<?php
+/*
+ * Script to update image metadata records
+ *
+ * Usage: php rebuildImages.php [--missing] [--dry-run]
+ * Options:
+ *   --missing  Crawl the uploads dir for images without records, and
+ *              add them only.
+ * 
+ * Copyright (C) 2005 Brion Vibber <brion@pobox.com>
+ * http://www.mediawiki.org/
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or 
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @author Brion Vibber <brion at pobox.com>
+ * @package MediaWiki
+ * @subpackage maintenance
+ */
+
+$options = array( 'missing', 'dry-run' );
+
+require_once( 'commandLine.inc' );
+require_once( 'FiveUpgrade.inc' );
+
+class ImageBuilder extends FiveUpgrade {
+       function ImageBuilder( $dryrun = false ) {
+               parent::FiveUpgrade();
+               
+               $this->maxLag = 10; # if slaves are lagged more than 10 secs, wait
+               $this->dryrun = $dryrun;
+       }
+       
+       function build() {
+               $this->buildImage();
+               $this->buildOldImage();
+       }
+       
+       function init( $count, $table ) {
+               $this->processed = 0;
+               $this->updated = 0;
+               $this->count = $count;
+               $this->startTime = wfTime();
+               $this->table = $table;
+       }
+       
+       function progress( $updated ) {
+               $this->updated += $updated;
+               $this->processed++;
+               if( $this->processed % 100 != 0 ) {
+                       return;
+               }
+               $portion = $this->processed / $this->count;
+               $updateRate = $this->updated / $this->processed;
+               
+               $now = wfTime();
+               $delta = $now - $this->startTime;
+               $estimatedTotalTime = $delta / $portion;
+               $eta = $this->startTime + $estimatedTotalTime;
+               
+               printf( "%s: %6.2f%% done on %s; ETA %s [%d/%d] %.2f/sec <%.2f%% updated>\n",
+                       wfTimestamp( TS_DB, intval( $now ) ),
+                       $portion * 100.0,
+                       $this->table,
+                       wfTimestamp( TS_DB, intval( $eta ) ),
+                       $completed,
+                       $this->count,
+                       $rate,
+                       $updateRate * 100.0 );
+               flush();
+       }
+       
+       function buildTable( $table, $key, $callback ) {
+               $fname = 'ImageBuilder::buildTable';
+               
+               $count = $this->dbw->selectField( $table, 'count(*)', '', $fname );
+               $this->init( $count, $table );
+               $this->log( "Processing $table..." );
+               
+               $tableName = $this->dbr->tableName( $table );
+               $sql = "SELECT * FROM $tableName";
+               $result = $this->dbr->query( $sql, $fname );
+               
+               while( $row = $this->dbr->fetchObject( $result ) ) {
+                       $update = call_user_func( $callback, $row );
+                       if( is_array( $update ) ) {
+                               if( !$this->dryrun ) {
+                                       $this->dbw->update( $table,
+                                               $update,
+                                               array( $key => $row->$key ),
+                                               $fname );
+                               }
+                               $this->progress( 1 );
+                       } else {
+                               $this->progress( 0 );
+                       }
+               }
+               $this->log( "Finished $table... $this->updated of $this->processed rows updated" );
+               $this->dbr->freeResult( $result );
+       }
+       
+       function buildImage() {
+               $callback = array( &$this, 'imageCallback' );
+               $this->buildTable( 'image', 'img_name', $callback );
+       }
+       
+       function imageCallback( $row ) {
+               if( $row->img_width ) {
+                       // Already processed
+                       return null;
+               }
+               
+               // Fill in the new image info fields
+               $info = $this->imageInfo( $row->img_name );
+
+               global $wgMemc, $wgDBname;
+               $key = $wgDBname . ":Image:" . md5( $row->img_name );
+               $wgMemc->delete( $key );
+
+               return array(
+                       'img_width'      => $info['width'],
+                       'img_height'     => $info['height'],
+                       'img_bits'       => $info['bits'],
+                       'img_media_type' => $info['media'],
+                       'img_major_mime' => $info['major'],
+                       'img_minor_mime' => $info['minor'] );
+       }
+       
+       
+       function buildOldImage() {
+               $this->buildTable( 'oldimage', 'oi_archive_name',
+                       array( &$this, 'oldimageCallback' ) );
+       }
+       
+       function oldimageCallback( $row ) {
+               if( $row->oi_width ) {
+                       return null;
+               }
+               
+               // Fill in the new image info fields
+               $info = $this->imageInfo( $row->oi_archive_name, 'wfImageArchiveDir', $row->oi_name );
+               return array(
+                       'oi_width'  => $info['width' ],
+                       'oi_height' => $info['height'],
+                       'oi_bits'   => $info['bits'  ] );
+       }
+       
+       function crawlMissing() {
+               global $wgUploadDirectory, $wgHashedUploadDirectory;
+               if( $wgHashedUploadDirectory ) {
+                       for( $i = 0; $i < 16; $i++ ) {
+                               for( $j = 0; $j < 16; $j++ ) {
+                                       $dir = sprintf( '%s%s%01x%s%02x',
+                                               $wgUploadDirectory,
+                                               DIRECTORY_SEPARATOR,
+                                               $i,
+                                               DIRECTORY_SEPARATOR,
+                                               $i * 16 + $j );
+                                       $this->crawlDirectory( $dir );
+                               }
+                       }
+               } else {
+                       $this->crawlDirectory( $wgUploadDirectory );
+               }
+       }
+       
+       function crawlDirectory( $dir ) {
+               if( !file_exists( $dir ) ) {
+                       return $this->log( "no directory, skipping $dir" );
+               }
+               if( !is_dir( $dir ) ) {
+                       return $this->log( "not a directory?! skipping $dir" );
+               }
+               if( !is_readable( $dir ) ) {
+                       return $this->log( "dir not readable, skipping $dir" );
+               }
+               $source = opendir( $dir );
+               if( $source === false ) {
+                       return $this->log( "couldn't open dir, skipping $dir" );
+               }
+               
+               $this->log( "crawling $dir" );
+               while( false !== ( $filename = readdir( $source ) ) ) {
+                       $fullpath = $dir . DIRECTORY_SEPARATOR . $filename;
+                       if( is_dir( $fullpath ) ) {
+                               continue;
+                       }
+                       if( is_link( $fullpath ) ) {
+                               $this->log( "skipping symlink at $fullpath" );
+                               continue;
+                       }
+                       $this->checkMissingImage( $filename, $fullpath );
+               }
+               closedir( $source );
+       }
+       
+       function checkMissingImage( $filename, $fullpath ) {
+               $fname = 'ImageBuilder::checkMissingImage';
+               $row = $this->dbw->selectRow( 'image',
+                       array( 'img_name' ),
+                       array( 'img_name' => $filename ),
+                       $fname );
+               
+               if( $row ) {
+                       // already known, move on
+                       return;
+               } else {
+                       $this->addMissingImage( $filename, $fullpath );
+               }
+       }
+       
+       function addMissingImage( $filename, $fullpath ) {
+               $fname = 'ImageBuilder::addMissingImage';
+               
+               $size = filesize( $fullpath );
+               $info = $this->imageInfo( $filename );
+               $timestamp = $this->dbw->timestamp( filemtime( $fullpath ) );
+               
+               global $wgContLang;
+               $altname = $wgContLang->checkTitleEncoding( $filename );
+               if( $altname != $filename ) {
+                       if( $this->dryrun ) {
+                               $filename = $altname;
+                               $this->log( "Estimating transcoding... $altname" );
+                       } else {
+                               $filename = $this->renameFile( $filename );
+                       }
+               }
+               
+               if( $filename == '' ) {
+                       $this->log( "Empty filename for $fullpath" );
+                       return;
+               }
+               
+               $fields = array(
+                       'img_name'       => $filename,
+                       'img_size'       => $size,
+                       'img_width'      => $info['width'],
+                       'img_height'     => $info['height'],
+                       'img_metadata'   => '', // filled in on-demand
+                       'img_bits'       => $info['bits'],
+                       'img_media_type' => $info['media'],
+                       'img_major_mime' => $info['major'],
+                       'img_minor_mime' => $info['minor'],
+                       'img_description' => '(recovered file, missing upload log entry)',
+                       'img_user'        => 0,
+                       'img_user_text'   => 'Conversion script',
+                       'img_timestamp'   => $timestamp );
+               if( !$this->dryrun ) {
+                       $this->dbw->insert( 'image', $fields, $fname );
+               }
+               $this->log( $fullpath );
+       }
+}
+
+$builder = new ImageBuilder( isset( $options['dry-run'] ) );
+if( isset( $options['missing'] ) ) {
+       $builder->crawlMissing();
+} else {
+       $builder->build();
+}
+
+?>
diff --git a/maintenance/rebuildInterwiki.inc b/maintenance/rebuildInterwiki.inc
new file mode 100644 (file)
index 0000000..3404627
--- /dev/null
@@ -0,0 +1,234 @@
+<?php
+/**
+ * Rebuild interwiki table using the file on meta and the language list
+ * Wikimedia specific!
+ *
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+/** */
+
+/**
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+class Site {
+       var $suffix, $lateral, $url;
+
+       function Site( $s, $l, $u ) {
+               $this->suffix = $s;
+               $this->lateral = $l;
+               $this->url = $u;
+       }
+
+       function getURL( $lang ) {
+               return "http://$lang.{$this->url}/wiki/\$1";
+       }
+}
+
+function getRebuildInterwikiSQL() {
+       global $langlist, $languageAliases, $wgDBname;
+
+       # Initialise lists of wikis
+       $sites = array( 
+               'wiki' => new Site( 'wiki', 'w', 'wikipedia.org' ),
+               'wiktionary' => new Site( 'wiktionary', 'wikt', 'wiktionary.org' ),
+               'wikiquote' => new Site( 'wikiquote', 'q', 'wikiquote.org' ),
+               'wikibooks' => new Site( 'wikibooks', 'b', 'wikibooks.org' ),
+               'wikinews' => new Site( 'wikinews', 'n', 'wikinews.org' ),
+       );
+       $langlist = array_map( "trim", file( "/home/wikipedia/common/langlist" ) );
+       $dblist = array_map( "trim", file( "/home/wikipedia/common/all.dblist" ) );
+       
+       $specials = array( 
+               'sourceswiki' => 'sources.wikipedia.org',
+               'quotewiki' => 'wikiquote.org',
+               'textbookwiki' => 'wikibooks.org',
+               'sep11wiki' => 'sep11.wikipedia.org',
+               'metawiki' => 'meta.wikimedia.org',
+               'commonswiki' => 'commons.wikimedia.org',
+       );
+
+       $extraLinks = array(
+               array( 'm', 'http://meta.wikimedia.org/wiki/$1', 1 ),
+               array( 'meta', 'http://meta.wikimedia.org/wiki/$1', 1 ),
+               array( 'sep11', 'http://sep11.wikipedia.org/wiki/$1', 1 ),
+       );
+
+       $languageAliases = array(
+               'zh-cn' => 'zh',
+               'zh-tw' => 'zh',
+               'dk' => 'da',
+               'nb' => 'no',
+       );
+
+       # Construct a list of reserved prefixes
+       $reserved = array();
+       foreach ( $langlist as $lang ) {
+               $reserved[$lang] = 1;
+       }
+       foreach ( $languageAliases as $alias => $lang ) {
+               $reserved[$alias] = 1;
+       }
+       foreach( $sites as $site ) {
+               $reserved[$site->lateral] = 1;
+       }
+
+       # Extract the intermap from meta
+       $intermap = wfGetHTTP( 'http://meta.wikimedia.org/w/index.php?title=Interwiki_map&action=raw' );
+       $lines = array_map( 'trim', explode( "\n", trim( $intermap ) ) );
+
+       if ( !$lines ) {
+               die( "m:Interwiki_map not found" );
+       }
+
+       $iwArray = array();
+
+       foreach ( $lines as $line ) {
+               if ( preg_match( '/^\|\s*(.*?)\s*\|\|\s*(.*?)\s*$/', $line, $matches ) ) {
+                       $prefix = strtolower( $matches[1] );
+                       $url = $matches[2];
+                       if ( preg_match( '/(wikipedia|wiktionary|wikisource|wikiquote|wikibooks)\.org/', $url ) ) {
+                               $local = 1;
+                       } else {
+                               $local = 0;
+                       }
+                       
+                       if ( empty( $reserved[$prefix] ) ) {
+                               $iwArray[$prefix] = array( "iw_prefix" => $prefix, "iw_url" => $url, "iw_local" => $local );
+                       }
+               }
+       }
+       
+       $sql = "-- Generated by rebuildInterwiki.php";
+
+
+       foreach ( $dblist as $db ) {
+               if ( isset( $specials[$db] ) ) {
+                       # Special wiki
+                       # Has interwiki links and interlanguage links to wikipedia
+                       
+                       $host = $specials[$db];
+                       $sql .= "\n--$host\n\n";
+                       $sql .= "USE $db;\n" .
+                                       "TRUNCATE TABLE interwiki;\n" . 
+                                       "INSERT INTO interwiki (iw_prefix, iw_url, iw_local) VALUES \n";
+                       $first = true;
+                       
+                       # Intermap links
+                       foreach ( $iwArray as $iwEntry ) {
+                               $sql .= makeLink( $iwEntry, $first );
+                       }
+
+                       # Links to multilanguage sites
+                       foreach ( $sites as $targetSite ) {
+                               $sql .= makeLink( array( $targetSite->lateral, $targetSite->getURL( 'en' ), 1 ), $first );
+                       }
+                       
+                       # Interlanguage links to wikipedia
+                       $sql .= makeLanguageLinks( $sites['wiki'], $first );
+
+                       # Extra links
+                       foreach ( $extraLinks as $link ) {
+                               $sql .= makeLink( $link, $first );
+                       }
+                       
+                       $sql .= ";\n";
+               } else {
+                       # Find out which site this DB belongs to
+                       $site = false;
+                       foreach( $sites as $candidateSite ) {
+                               $suffix = $candidateSite->suffix;
+                               if ( preg_match( "/(.*)$suffix$/", $db, $matches ) ) {
+                                       $site = $candidateSite;
+                                       break;
+                               }
+                       }
+                       if ( !$site ) {
+                               print "Invalid database $db\n";
+                               continue;
+                       }
+                       $lang = $matches[1];
+                       $host = "$lang." . $site->url;
+                       $sql .= "\n--$host\n\n";
+                       
+                       $sql .= "USE $db;\n" .
+                                       "TRUNCATE TABLE interwiki;\n" .
+                                       "INSERT INTO interwiki (iw_prefix,iw_url,iw_local) VALUES\n";
+                       $first = true;
+
+                       # Intermap links
+                       foreach ( $iwArray as $iwEntry ) {
+                               # Suppress links with the same name as the site
+                               if ( ( $suffix == 'wiki' && $iwEntry['iw_prefix'] != 'wikipedia' ) || 
+                                 ( $suffix != 'wiki' && $suffix != $iwEntry['iw_prefix'] ) ) 
+                               {
+                                       $sql .= makeLink( $iwEntry, $first );
+                               }
+                       }
+
+                       # Lateral links
+                       foreach ( $sites as $targetSite ) {
+                               # Suppress link to self
+                               if ( $targetSite->suffix != $site->suffix ) {
+                                       $sql .= makeLink( array( $targetSite->lateral, $targetSite->getURL( $lang ), 1 ), $first );
+                               }
+                       }
+
+                       # Interlanguage links
+                       $sql .= makeLanguageLinks( $site, $first );
+
+                       # w link within wikipedias
+                       # Other sites already have it as a lateral link
+                       if ( $site->suffix == "wiki" ) {
+                               $sql .= makeLink( array("w", "http://en.wikipedia.org/wiki/$1", 1), $first );
+                       }
+                       
+                       # Extra links
+                       foreach ( $extraLinks as $link ){ 
+                                       $sql .= makeLink( $link, $first );
+                       }
+                       $sql .= ";\n\n";
+               }
+       }
+       return $sql;
+}
+
+# ------------------------------------------------------------------------------------------
+
+# Returns part of an INSERT statement, corresponding to all interlanguage links to a particular site
+function makeLanguageLinks( &$site, &$first ) {
+       global $langlist, $languageAliases;
+
+       $sql = "";
+
+       # Actual languages with their own databases
+       foreach ( $langlist as $targetLang ) {
+               $sql .= makeLink( array( $targetLang, $site->getURL( $targetLang ), 1 ), $first );
+       }
+
+       # Language aliases
+       foreach ( $languageAliases as $alias => $lang ) {
+               $sql .= makeLink( array( $alias, $site->getURL( $lang ), 1 ), $first );
+       }
+       return $sql;
+}
+
+# Make SQL for a single link from an array
+function makeLink( $entry, &$first ) {
+       $sql = "";
+       # Add comma
+       if ( $first ) {
+               $first = false;
+       } else {
+               $sql .= ",\n";
+       }
+       $dbr =& wfGetDB( DB_SLAVE );
+       $sql .= "(" . $dbr->makeList( $entry ) . ")";
+       return $sql;
+}
+
+?>
diff --git a/maintenance/rebuildInterwiki.php b/maintenance/rebuildInterwiki.php
new file mode 100644 (file)
index 0000000..3f786d0
--- /dev/null
@@ -0,0 +1,31 @@
+<?php
+/**
+ * Rebuild interwiki table using the file on meta and the language list
+ * Wikimedia specific!
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+/** */
+$oldCwd = getcwd();
+
+$optionsWithArgs = array( "o" );
+include_once( "commandLine.inc" );
+include_once( "rebuildInterwiki.inc" );
+
+$sql = getRebuildInterwikiSQL();
+
+# Output
+if ( isset( $options['o'] ) ) {        
+       # To file specified with -o
+       chdir( $oldCwd );
+       $file = fopen( $options['o'], "w" );
+       fwrite( $file, $sql );
+       fclose( $file );
+} else {
+       # To stdout
+       print $sql;
+}
+
+?>
diff --git a/maintenance/rebuildMessages.php b/maintenance/rebuildMessages.php
new file mode 100644 (file)
index 0000000..40c8f60
--- /dev/null
@@ -0,0 +1,66 @@
+<?php
+/**
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+/** */
+$options = array( 'update' => null, 'rebuild' => null );
+require_once( "commandLine.inc" );
+include_once( "InitialiseMessages.inc" );
+
+$wgTitle = Title::newFromText( "Rebuild messages script" );
+
+if ( isset( $args[0] ) ) {
+       # Retain script compatibility
+       $response = array_shift( $args );
+       if ( $response == "update" ) {
+               $response = 1;
+       } elseif ( $response == "rebuild" ) {
+               $response = 2;
+       }
+} else {
+       $response = 0;
+}
+if ( isset( $args[0] ) ) {
+       $messages = loadLanguageFile( array_shift( $args ) );
+} else {
+       $messages = false;
+}
+if( isset( $options['update'] ) ) $response = 1;
+if( isset( $options['rebuild'] ) ) $response = 2;
+
+if ( $response == 0 ) {
+       $dbr =& wfGetDB( DB_SLAVE );
+       $row = $dbr->selectRow( "page", array("count(*) as c"), array("page_namespace" => NS_MEDIAWIKI) );
+       print "Current namespace size: {$row->c}\n";
+
+       print <<<END
+Usage:   php rebuildMessages.php <action> [filename]
+
+Action must be one of:
+  --update   Update messages to include latest additions to Language.php
+  --rebuild  Delete all messages and reinitialise namespace
+
+If a message dump file is given, messages will be read from it to supplement
+the defaults in MediaWiki's Language*.php. The file should contain a serialized
+PHP associative array, as produced by dumpMessages.php.
+
+
+END;
+       exit(0);
+}
+
+switch ( $response ) {
+       case 1:
+               initialiseMessages( false, $messages );
+               break;
+       case 2:
+               initialiseMessages( true, $messages );
+               break;
+}
+
+exit();
+
+?>
diff --git a/maintenance/rebuildall.php b/maintenance/rebuildall.php
new file mode 100644 (file)
index 0000000..7c44e30
--- /dev/null
@@ -0,0 +1,39 @@
+<?php
+/**
+ * Rebuild link tracking tables from scratch.  This takes several
+ * hours, depending on the database size and server configuration.
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+/** */
+require_once( "commandLine.inc" );
+
+#require_once( "rebuildlinks.inc" );
+require_once( "refreshLinks.inc" );
+require_once( "rebuildtextindex.inc" );
+require_once( "rebuildrecentchanges.inc" );
+
+$database = Database::newFromParams( $wgDBserver, $wgDBadminuser, $wgDBadminpassword, $wgDBname );
+
+print "** Rebuilding fulltext search index (if you abort this will break searching; run this script again to fix):\n";
+dropTextIndex( $database );
+rebuildTextIndex( $database );
+createTextIndex( $database );
+
+print "\n\n** Rebuilding recentchanges table:\n";
+rebuildRecentChangesTablePass1();
+rebuildRecentChangesTablePass2();
+
+# Doesn't work anymore
+# rebuildLinkTables();
+
+# Use the slow incomplete one instead. It's designed to work in the background
+print "\n\n** Rebuilding links tables -- this can take a long time. It should be safe to abort via ctrl+C if you get bored.\n";
+refreshLinks( 1 );
+
+print "Done.\n";
+exit();
+
+?>
diff --git a/maintenance/rebuildrecentchanges.inc b/maintenance/rebuildrecentchanges.inc
new file mode 100644 (file)
index 0000000..cfc7af7
--- /dev/null
@@ -0,0 +1,95 @@
+<?php
+/**
+ * Rebuild recent changes table.
+ *
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+/** */
+function rebuildRecentChangesTablePass1()
+{
+       $fname = 'rebuildRecentChangesTablePass1';
+       $dbw =& wfGetDB( DB_MASTER );
+       extract( $dbw->tableNames( 'recentchanges', 'cur', 'old' ) );
+
+       $dbw->delete( 'recentchanges', '*' );
+
+       print( "Loading from page and revision tables...\n" );
+       
+       global $wgRCMaxAge;
+       $cutoff = time() - $wgRCMaxAge;
+       $dbw->insertSelect( 'recentchanges', array( 'page', 'revision' ),
+               array(
+                       'rc_timestamp'  => 'rev_timestamp',
+                       'rc_cur_time'   => 'rev_timestamp',
+                       'rc_user'       => 'rev_user',
+                       'rc_user_text'  => 'rev_user_text',
+                       'rc_namespace'  => 'page_namespace',
+                       'rc_title'      => 'page_title',
+                       'rc_comment'    => 'rev_comment',
+                       'rc_minor'      => 'rev_minor_edit',
+                       'rc_bot'        => 0,
+                       'rc_new'        => 'page_is_new',
+                       'rc_cur_id'     => 'page_id',
+                       'rc_this_oldid' => 'rev_id',
+                       'rc_last_oldid' => 0, // is this ok?
+                       'rc_type'       => $dbw->conditional( 'page_is_new != 0', RC_NEW, RC_EDIT ),
+               ), array(
+                       'rev_timestamp > ' . $dbw->timestamp( $cutoff ),
+                       'rev_page=page_id'
+               ), $fname, array( 'ORDER BY' => 'rev_timestamp', 'LIMIT' => 5000 )
+       );
+}
+
+function rebuildRecentChangesTablePass2()
+{
+       $dbw =& wfGetDB( DB_MASTER );
+       extract( $dbw->tableNames( 'recentchanges', 'revision' ) );
+
+       $ns = $id = $count = 0;
+       $title = $ct =  "";
+
+       print( "Updating links...\n" );
+
+       # Fill in the rc_last_oldid field, which points to the previous edit
+       #
+       $sql = "SELECT rc_cur_id,rc_this_oldid,rc_timestamp FROM $recentchanges " .
+         "ORDER BY rc_cur_id,rc_timestamp";
+       $res = $dbw->query( $sql, DB_MASTER );
+
+       $lastCurId = 0;
+       $lastOldId = 0;
+       while ( $obj = $dbw->fetchObject( $res ) ) {
+               $new = 0;
+               if( $obj->rc_cur_id != $lastCurId ) {
+                       # Switch! Look up the previous last edit, if any
+                       $lastCurId = IntVal( $obj->rc_cur_id );
+                       $emit = $obj->rc_timestamp;
+                       $sql2 = "SELECT rev_id FROM $revision " .
+                               "WHERE rev_page={$lastCurId} ".
+                               "AND rev_timestamp<'{$emit}' ORDER BY rev_timestamp DESC LIMIT 1";
+                       $res2 = $dbw->query( $sql2 );
+                       if( $row = $dbw->fetchObject( $res2 ) ) {
+                               $lastOldId = intval( $row->rev_id );
+                       } else {
+                               # No previous edit
+                               $lastOldId = 0;
+                               $new = 1;
+                       }
+                       $dbw->freeResult( $res2 );
+               }
+               if( $lastCurId == 0 ) {
+                       print "Uhhh, something wrong? No curid\n";
+               } else {
+                       $sql3 = "UPDATE $recentchanges SET rc_last_oldid=$lastOldId,rc_new=$new,rc_type=$new " .
+                               "WHERE rc_cur_id={$lastCurId} AND rc_this_oldid={$obj->rc_this_oldid}";
+                       $dbw->query( $sql3 );
+                       $lastOldId = IntVal( $obj->rc_this_oldid );
+               }
+       }
+       $dbw->freeResult( $res );
+}
+
+?>
diff --git a/maintenance/rebuildrecentchanges.php b/maintenance/rebuildrecentchanges.php
new file mode 100644 (file)
index 0000000..77816cf
--- /dev/null
@@ -0,0 +1,25 @@
+<?php
+/**
+ * Rebuild link tracking tables from scratch.  This takes several
+ * hours, depending on the database size and server configuration.
+ *
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+/** */
+require_once( "commandLine.inc" );
+require_once( "rebuildrecentchanges.inc" );
+$wgTitle = Title::newFromText( "Rebuild recent changes script" );
+
+$wgDBuser                      = $wgDBadminuser;
+$wgDBpassword          = $wgDBadminpassword;
+
+rebuildRecentChangesTablePass1();
+rebuildRecentChangesTablePass2();
+
+print "Done.\n";
+exit();
+
+?>
diff --git a/maintenance/rebuildtextindex.inc b/maintenance/rebuildtextindex.inc
new file mode 100644 (file)
index 0000000..beac559
--- /dev/null
@@ -0,0 +1,67 @@
+<?php
+/**
+ * Rebuild the fulltext search indexes. This may take a while
+ * depending on the database size and server configuration.
+ *
+ * Rebuilding is faster if you drop the index and recreate it,
+ * but that will prevent searches from working while it runs.
+ *
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+/** */
+define( "RTI_CHUNK_SIZE", 500 );
+
+function dropTextIndex( &$database )
+{
+       $searchindex = $database->tableName( 'searchindex' );
+       if ( $database->indexExists( "searchindex", "si_title" ) ) {
+               echo "Dropping index...\n";
+               $sql = "ALTER TABLE $searchindex DROP INDEX si_title, DROP INDEX si_text";
+               $database->query($sql, "dropTextIndex" );
+       }
+}
+
+function createTextIndex( &$database )
+{
+       $searchindex = $database->tableName( 'searchindex' );
+       echo "Rebuild the index...\n";
+       $sql = "ALTER TABLE $searchindex ADD FULLTEXT si_title (si_title), " .
+         "ADD FULLTEXT si_text (si_text)";
+       $database->query($sql, "createTextIndex" );
+}
+
+function rebuildTextIndex( &$database )
+{
+       extract( $database->tableNames( 'page', 'revision', 'text', 'searchindex' ) );
+
+       $sql = "SELECT MAX(page_id) AS count FROM $page";
+       $res = $database->query($sql, "rebuildTextIndex" );
+       $s = $database->fetchObject($res);
+       $count = $s->count;
+       echo "Rebuilding index fields for {$count} pages...\n";
+       $n = 0;
+
+       while ( $n < $count ) {
+               print "$n\n";
+               $end = $n + RTI_CHUNK_SIZE - 1;
+               $sql = "SELECT page_id, page_namespace, page_title, old_flags, old_text
+                         FROM $page, $revision, $text
+                        WHERE page_id BETWEEN $n AND $end
+                          AND page_latest=rev_id
+                          AND rev_text_id=old_id";
+               $res = $database->query($sql, "rebuildTextIndex" );
+
+               while( $s = $database->fetchObject($res) ) {
+                       $revtext = Revision::getRevisionText( $s );
+                       $u = new SearchUpdate( $s->page_id, $s->page_title, $revtext );
+                       $u->doUpdate();
+               }
+               $database->freeResult( $res );
+               $n += RTI_CHUNK_SIZE;
+       }
+}
+
+?>
diff --git a/maintenance/rebuildtextindex.php b/maintenance/rebuildtextindex.php
new file mode 100644 (file)
index 0000000..e7c1b02
--- /dev/null
@@ -0,0 +1,25 @@
+<?php
+/**
+ * Rebuild search index table from scratch.  This takes several
+ * hours, depending on the database size and server configuration.
+ *
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */ 
+
+/** */
+require_once( "commandLine.inc" );
+require_once( "rebuildtextindex.inc" );
+$wgTitle = Title::newFromText( "Rebuild text index script" );
+
+$database = Database::newFromParams( $wgDBserver, $wgDBadminuser, $wgDBadminpassword, $wgDBname );
+
+dropTextIndex( $database );
+rebuildTextIndex( $database );
+createTextIndex( $database );
+
+print "Done.\n";
+exit();
+
+?>
diff --git a/maintenance/redundanttrans.php b/maintenance/redundanttrans.php
new file mode 100644 (file)
index 0000000..de09686
--- /dev/null
@@ -0,0 +1,28 @@
+<?php
+/**
+ * Prints out messages that are no longer used.
+ *
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+require_once('commandLine.inc');
+
+if ( 'en' == $wgLanguageCode ) {
+       print "Current selected language is English. Cannot check translations.\n";
+       exit();
+}
+
+$count = $total = 0;
+$msgarray = 'wgAllMessages' . ucfirst( $wgLanguageCode );
+
+foreach ( $$msgarray as $code => $msg ) {
+       ++$total;
+       if ( ! array_key_exists( $code, $wgAllMessagesEn ) ) {
+               print "* $code\n";
+               ++$count;
+       }
+}
+
+print "{$count} messages of {$total} are redundant\n";
+?>
diff --git a/maintenance/refreshLinks.inc b/maintenance/refreshLinks.inc
new file mode 100644 (file)
index 0000000..355cf52
--- /dev/null
@@ -0,0 +1,157 @@
+<?php
+/**
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+/** */
+define( "REPORTING_INTERVAL", 100 );
+
+function refreshLinks( $start, $newOnly = false, $maxLag = false ) {
+       global $wgUser, $wgParser, $wgUseImageResize;
+
+       $fname = 'refreshLinks';
+       $dbr =& wfGetDB( DB_SLAVE );
+       $dbw =& wfGetDB( DB_MASTER );
+       $start = intval( $start );
+       
+       # Don't generate TeX PNGs (lack of a sensible current directory causes errors anyway)
+       $wgUser->setOption("math", 3);
+
+       # Don't generate extension images (e.g. Timeline)
+       $wgParser->mTagHooks = array();
+       
+       # Don't generate thumbnail images
+       $wgUseImageResize = false;
+
+       if ( $newOnly ) {
+               print "Refreshing links from ";
+               $res = $dbr->select( 'page', array( 'page_id' ), 
+                 array( 'page_is_new' => 1, "page_id > $start" ), $fname );
+               $num = $dbr->numRows( $res );
+               print "$num new articles...\n";
+               
+               $i = 0;
+               while ( $row = $dbr->fetchObject( $res ) ) {
+                       if ( !( ++$i % REPORTING_INTERVAL ) ) {
+                               print "$i\n";
+                               wfWaitForSlaves( $maxLag );
+                       }
+
+                       fixLinksFromArticle( $row->page_id );
+               }
+       } else {
+               print "Refreshing link table.\n";
+               $end = $dbr->selectField( 'page', 'max(page_id)', false );
+               print("Starting from page_id $start of $end.\n");
+
+               for ($id = $start; $id <= $end; $id++) {
+                       
+                       if ( !($id % REPORTING_INTERVAL) ) {
+                               print "$id\n";
+                               wfWaitForSlaves( $maxLag );
+                       }
+                       fixLinksFromArticle( $id );
+               }
+               
+
+       }
+}
+
+function fixLinksFromArticle( $id ) {
+       global $wgTitle, $wgArticle, $wgLinkCache, $wgOut;
+       
+       $wgTitle = Title::newFromID( $id );
+       $dbw =& wfGetDB( DB_MASTER );
+       
+       if ( is_null( $wgTitle ) ) {
+               return;
+       }
+       $dbw->begin();
+
+       $wgArticle = new Article( $wgTitle );
+       $text = $wgArticle->getContent( true );
+       $wgLinkCache = new LinkCache;
+       $wgLinkCache->forUpdate( true );
+       
+       global $wgLinkHolders;
+       $wgLinkHolders = array(
+               'namespaces' => array(),
+               'dbkeys' => array(),
+               'queries' => array(),
+               'texts' => array(),
+               'titles' => array()
+       );
+
+
+       # Parse the text and replace links with placeholders
+       $wgOut->addWikiText( $text );
+       
+       # Look up the links in the DB and add them to the link cache
+       $wgOut->transformBuffer();
+       $wgOut->clearHTML();
+
+       $linksUpdate = new LinksUpdate( $id, $wgTitle->getPrefixedDBkey() );
+       $linksUpdate->doDumbUpdate();
+       $dbw->immediateCommit();
+}
+
+function deleteLinksFromNonexistent( $maxLag = 0 ) {
+       $fname = 'deleteLinksFromNonexistent';
+       
+       wfWaitForSlaves( $maxLag );
+
+       $dbw =& wfGetDB( DB_WRITE );
+       
+       $linksTables = array( 
+               'pagelinks' => 'pl_from',
+               'imagelinks' => 'il_from',
+               'categorylinks' => 'cl_from',
+       );
+
+       $page = $dbw->tableName( 'page' );
+
+
+       foreach ( $linksTables as $table => $field ) {
+               if ( !$dbw->ping() ) {
+                       print "DB disconnected, reconnecting...";
+                       while ( !$dbw->ping() ) {
+                               print ".";
+                               sleep(10);
+                       }
+                       print "\n";
+               }
+
+               $pTable = $dbw->tableName( $table );
+               global $wgDBmysql4, $wgDBtype;
+               if( $wgDBmysql4 || $wgDBtype != 'mysql' ) {
+                       $sql = "DELETE $pTable FROM $pTable LEFT JOIN $page ON page_id=$field WHERE page_id IS NULL";
+               } else {
+                       # Hack-around for MySQL 3.x, which lacks support
+                       # for multi-table deletes.
+                       
+                       $sql = "SELECT DISTINCT $field AS id FROM $pTable LEFT JOIN $page ON page_id=$field WHERE page_id IS NULL";
+                       echo "Looking in $table from non-existent articles...";
+                       $result = $dbw->query( $sql );
+                       $ids = array();
+                       while( $row = $dbw->fetchObject( $result ) ) {
+                               $ids[] = $row->id;
+                       }
+                       $dbw->freeResult( $result );
+                       
+                       if( empty( $ids ) ) {
+                               echo " none.\n";
+                               continue;
+                       }
+                       echo " found.\n";
+                       $sql = "DELETE FROM $pTable WHERE $field IN (" . implode( ",", $ids ) . ")";
+               }
+               
+               print "Deleting $table from non-existent articles...";
+               $dbw->query( $sql, $fname );
+               print " fixed " .$dbw->affectedRows() . " row(s)\n";
+       }
+}
+
+?>
diff --git a/maintenance/refreshLinks.php b/maintenance/refreshLinks.php
new file mode 100644 (file)
index 0000000..f37c8e8
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+/**
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+/** */
+$optionsWithArgs = array( 'm' );
+require_once( "commandLine.inc" );
+require_once( "refreshLinks.inc" );
+
+error_reporting( E_ALL & (~E_NOTICE) );
+
+if ( !$options['dfn-only'] ) {
+       if ($args[0]) {
+               $start = (int)$args[0];
+       } else {
+               $start = 1;
+       }
+
+       refreshLinks( $start, $options['new-only'], $options['m'] );
+}
+deleteLinksFromNonexistent();
+
+?>
diff --git a/maintenance/removeUnusedAccounts.php b/maintenance/removeUnusedAccounts.php
new file mode 100644 (file)
index 0000000..1c6213c
--- /dev/null
@@ -0,0 +1,60 @@
+<?php
+
+/**
+ * Remove unused user accounts from the database
+ * An unused account is one which has made no edits
+ *
+ * @package MediaWiki
+ * @subpackage Maintenance
+ * @author Rob Church <robchur@gmail.com>
+ */
+
+define( 'ACTION_REPORT', 0 );
+define( 'ACTION_DELETE', 1 );
+$options = array( 'delete','help' );
+require_once( 'commandLine.inc' );
+require_once( 'userFunctions.inc' );
+
+echo( "Remove Unused Accounts\nThis script will delete all users who have made no edits.\n\n" );
+
+# Check parameters
+if( @$options['help'] ) {
+       echo( "USAGE: removeUnusedAccounts.php [--help|--delete]\n\nThe first (default) account is ignored.\n\n" );
+       wfDie();
+} else {
+       $delete = @$options['delete'] ? true : false ;
+}
+
+$count = 0;
+$del = array();
+
+# Right, who needs deleting?
+$users = GetUsers();
+echo( "Found " . count( $users ) . " accounts.\n\n" );
+echo( "Locating inactive users..." );
+foreach( $users as $user ) {
+       if( $user != 1 ) {      # Don't *touch* the first user account, ever
+               if( CountEdits( $user, false ) == 0 ) {
+                       # User has no edits, mark them for deletion
+                       $del[] = $user;
+                       $count++;
+               }
+       }
+}
+echo( "done.\n" );
+
+# Purge the inactive accounts we found
+echo( $count . " inactive accounts found.\n" );
+if( $count > 0 ) {
+       if( $delete ) {
+               echo( "Deleting..." );
+               DeleteUsers( $del );
+               echo( "done.\n" );
+       } else {
+               echo "Run the script with the --delete option to remove them from the database.\n";
+       }
+}
+               
+echo( "\n" );
+
+?>
diff --git a/maintenance/stats.php b/maintenance/stats.php
new file mode 100644 (file)
index 0000000..a194671
--- /dev/null
@@ -0,0 +1,24 @@
+<?php
+require_once('commandLine.inc');
+
+$hits = intval($wgMemc->get("$wgDBname:stats:pcache_hit"));
+$invalid = intval($wgMemc->get("$wgDBname:stats:pcache_miss_invalid"));
+$expired = intval($wgMemc->get("$wgDBname:stats:pcache_miss_expired"));
+$absent = intval($wgMemc->get("$wgDBname:stats:pcache_miss_absent"));
+$total = $hits + $invalid + $expired + $absent;
+printf( "hits:    %-10d %6.2f%%\n", $hits, $hits/$total*100 );
+printf( "invalid: %-10d %6.2f%%\n", $invalid, $invalid/$total*100 );
+printf( "expired: %-10d %6.2f%%\n", $expired, $expired/$total*100 );
+printf( "absent:  %-10d %6.2f%%\n", $absent, $absent/$total*100 );
+printf( "total:   %-10d %6.2f%%\n", $total, 100 );
+
+$hits = intval($wgMemc->get("$wgDBname:stats:image_cache_hit"));
+$misses = intval($wgMemc->get("$wgDBname:stats:image_cache_miss"));
+$updates = intval($wgMemc->get("$wgDBname:stats:image_cache_update"));
+$total = $hits + $misses;
+print("\nImage cache\n");
+printf( "hits:    %-10d %6.2f%%\n", $hits, $hits/$total*100 );
+printf( "misses:  %-10d %6.2f%%\n", $misses, $misses/$total*100 );
+printf( "updates: %-10d\n", $updates );
+
+?>
diff --git a/maintenance/storage/blobs.sql b/maintenance/storage/blobs.sql
new file mode 100644 (file)
index 0000000..3e72f77
--- /dev/null
@@ -0,0 +1,8 @@
+-- Blobs table for external storage
+
+CREATE TABLE /*$wgDBprefix*/blobs (
+       blob_id int(8) NOT NULL default '0' AUTO_INCREMENT,
+       blob_text mediumtext,
+       PRIMARY KEY  (blob_id)
+) TYPE=InnoDB;
+
diff --git a/maintenance/storage/compressOld.inc b/maintenance/storage/compressOld.inc
new file mode 100644 (file)
index 0000000..344a490
--- /dev/null
@@ -0,0 +1,246 @@
+<?php
+/**
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+/** */
+require_once( 'Revision.php' );
+require_once( 'ExternalStoreDB.php' );
+
+/** @todo document */
+function compressOldPages( $start = 0, $extdb = '' ) {
+       $fname = 'compressOldPages';
+
+       $chunksize = 50;
+       print "Starting from old_id $start...\n";
+       $dbw =& wfGetDB( DB_MASTER );
+       do {
+               $end = $start + $chunksize;
+               $res = $dbw->select( 'text', array( 'old_id','old_flags','old_namespace','old_title','old_text' ),
+                       "old_id>=$start", $fname, array( 'ORDER BY' => 'old_id', 'LIMIT' => $chunksize, 'FOR UPDATE' ) );
+               if( $dbw->numRows( $res ) == 0 ) {
+                       break;
+               }
+               $last = $start;
+               while( $row = $dbw->fetchObject( $res ) ) {
+                       # print "  {$row->old_id} - {$row->old_namespace}:{$row->old_title}\n";
+                       compressPage( $row, $extdb );
+                       $last = $row->old_id;
+               }
+               $dbw->freeResult( $res );
+               $start = $last + 1; # Deletion may leave long empty stretches
+               print "$start...\n";
+       } while( true );
+}
+
+/** @todo document */
+function compressPage( $row, $extdb ) {
+       $fname = 'compressPage';
+       if ( false !== strpos( $row->old_flags, 'gzip' ) || false !== strpos( $row->old_flags, 'object' ) ) {
+               #print "Already compressed row {$row->old_id}\n";
+               return false;
+       }
+       $dbw =& wfGetDB( DB_MASTER );
+       $flags = $row->old_flags ? "{$row->old_flags},gzip" : "gzip";
+       $compress = gzdeflate( $row->old_text );
+
+       # Store in external storage if required
+       if ( $extdb !== '' ) {
+               $storeObj = new ExternalStoreDB;
+               $compress = $storeObj->store( $extdb, $compress );
+               if ( $compress === false ) {
+                       print "Unable to store object\n";
+                       return false;
+               }
+       }
+
+       # Update text row
+       $dbw->update( 'text', 
+               array( /* SET */
+                       'old_flags' => $flags,
+                       'old_text' => $compress
+               ), array( /* WHERE */
+                       'old_id' => $row->old_id
+               ), $fname, 'LIMIT 1'
+       );
+       return true;
+}
+
+define( 'LS_INDIVIDUAL', 0 );
+define( 'LS_CHUNKED', 1 );
+
+/** @todo document */
+function compressWithConcat( $startId, $maxChunkSize, $maxChunkFactor, $factorThreshold, $beginDate, $endDate )
+{
+       $fname = 'compressWithConcat';
+       $loadStyle = LS_CHUNKED;
+       
+       $dbr =& wfGetDB( DB_SLAVE );
+       $dbw =& wfGetDB( DB_MASTER );
+
+       # Get all articles by page_id
+       $maxPageId = $dbr->selectField( 'page', 'max(page_id)', '', $fname );
+       $pageConds = array();
+
+       /*
+       if ( $exclude_ns0 ) {
+               print "Excluding main namespace\n";
+               $pageConds[] = 'page_namespace<>0';
+       }
+       if ( $queryExtra ) {
+                $pageConds[] = $queryExtra;
+       }
+        */
+
+       # For each article, get a list of revisions which fit the criteria
+       # No recompression, use a condition on old_flags
+       $conds = array(
+               "old_flags NOT LIKE '%object%' " .
+               " AND (old_flags NOT LIKE '%external%' OR old_text NOT LIKE 'DB://%/%/%')");
+       
+       if ( $beginDate ) {
+               $conds[] = "rev_timestamp>'" . $beginDate . "'";
+       } 
+       if ( $endDate )  {
+               $conds[] = "rev_timestamp<'" . $endDate . "'";
+       }
+       if ( $loadStyle == LS_CHUNKED ) {
+               $tables = array( 'revision', 'text' );
+               $fields = array( 'rev_id', 'rev_text_id', 'old_flags', 'old_text' );
+               $conds[] = 'rev_text_id=old_id';
+               $revLoadOptions = 'FOR UPDATE';
+       } else {
+               $tables = array( 'revision' );
+               $fields = array( 'rev_id', 'rev_text_id' );
+               $revLoadOptions = array();
+       }
+
+       $oldReadsSinceLastSlaveWait = 0;        #check slave lag periodically
+       $totalMatchingRevisions = 0;
+       $masterPos = false;
+       for ( $pageId = $startId; $pageId <= $maxPageId; $pageId++ ) {
+               $pageRes = $dbr->select( 'page', array('page_id', 'page_namespace', 'page_title'), 
+                       $pageConds + array('page_id' => $pageId), $fname );
+               if ( $dbr->numRows( $pageRes ) == 0 ) {
+                       continue;
+               }
+               $pageRow = $dbr->fetchObject( $pageRes );
+
+               # Display progress
+               $titleObj = Title::makeTitle( $pageRow->page_namespace, $pageRow->page_title );
+               print "$pageId\t" . $titleObj->getPrefixedDBkey() . " ";
+
+               # Load revisions
+               $revRes = $dbw->select( $tables, $fields,
+                       array( 'rev_page' => $pageRow->page_id ) + $conds, 
+                       $fname,
+                       $revLoadOptions
+               );
+               $revs = array();
+               while ( $revRow = $dbw->fetchObject( $revRes ) ) {
+                       $revs[] = $revRow;
+               }
+               
+               if ( count( $revs ) < 2) {
+                       # No revisions matching, no further processing
+                       print "\n";
+                       continue;
+               }
+
+               # For each chunk
+               $i = 0;
+               while ( $i < count( $revs ) ) {
+                       if ( $i < count( $revs ) - $maxChunkSize ) {
+                               $thisChunkSize = $maxChunkSize;
+                       } else {
+                               $thisChunkSize = count( $revs ) - $i;
+                       }
+
+                       $chunk = new ConcatenatedGzipHistoryBlob();
+                       $stubs = array();
+                       $dbw->begin();
+                       $usedChunk = false;
+                       $primaryOldid = $revs[$i]->rev_text_id;
+                       
+                       # Get the text of each revision and add it to the object
+                       for ( $j = 0; $j < $thisChunkSize && $chunk->isHappy( $maxChunkFactor, $factorThreshold ); $j++ ) {
+                               $oldid = $revs[$i + $j]->rev_text_id;
+                               
+                               # Get text
+                               if ( $loadStyle == LS_INDIVIDUAL ) {
+                                       $textRow = $dbw->selectRow( 'text', 
+                                               array( 'old_flags', 'old_text' ),
+                                               array( 'old_id' => $oldid ),
+                                               $fname,
+                                               'FOR UPDATE'
+                                       );
+                                       $text = Revision::getRevisionText( $textRow );
+                               } else {
+                                       $text = Revision::getRevisionText( $revs[$i + $j] );
+                               }
+
+                               if ( $text === false ) {
+                                       print "\nError, unable to get text in old_id $oldid\n";
+                                       #$dbw->delete( 'old', array( 'old_id' => $oldid ) );
+                               }
+
+                               if ( $j == 0 ) {
+                                       $chunk->setText( $text );
+                                       print '.';
+                               } else {
+                                       # Don't make a stub if it's going to be longer than the article
+                                       # Stubs are typically about 100 bytes
+                                       if ( strlen( $text ) < 120 ) {
+                                               $stub = false;
+                                               print 'x';
+                                       } else {
+                                               $stub = $chunk->addItem( $text );
+                                               $stub->setLocation( $primaryOldid );
+                                               $hash = $stub->getHash();
+                                               $stub = serialize( $stub );
+                                               print '.';
+                                               $usedChunk = true;
+                                       }
+                                       $stubs[$j] = $stub;
+                               }
+                       }
+                       $thisChunkSize = $j;
+                       
+                       # If we couldn't actually use any stubs because the pages were too small, do nothing
+                       if ( $usedChunk ) {
+                               # Store the main object
+                               $dbw->update( 'text',
+                                       array( /* SET */
+                                               'old_text' => serialize( $chunk ),
+                                               'old_flags' => 'object,utf-8',
+                                       ), array( /* WHERE */
+                                               'old_id' => $primaryOldid
+                                       )
+                               );
+
+                               # Store the stub objects
+                               for ( $j = 1; $j < $thisChunkSize; $j++ ) {
+                                       # Skip if not compressing
+                                       if ( $stubs[$j] !== false ) {
+                                               $dbw->update( 'text',
+                                                       array( /* SET */
+                                                               'old_text' => $stubs[$j],
+                                                               'old_flags' => 'object,utf-8',
+                                                       ), array( /* WHERE */
+                                                               'old_id' => $revs[$i + $j]->rev_text_id
+                                                       )
+                                               );
+                                       }
+                               }
+                       }
+                       # Done, next
+                       print "/";
+                       $dbw->commit();
+                       $i += $thisChunkSize;
+               }
+               print "\n";
+       }
+       return true;
+}
+?>
diff --git a/maintenance/storage/compressOld.php b/maintenance/storage/compressOld.php
new file mode 100644 (file)
index 0000000..35d8c82
--- /dev/null
@@ -0,0 +1,81 @@
+<?php
+/**
+ * Compress the text of a wiki
+ * 
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+/** */
+
+/**
+ * Usage: 
+ *
+ * Non-wikimedia
+ * php compressOld.php [options...]
+ *
+ * Wikimedia
+ * php compressOld.php <database> [options...]
+ *
+ * Options are:
+ *  -t <type>           set compression type to either:
+ *                          gzip: compress revisions independently
+ *                          concat: concatenate revisions and compress in chunks (default)
+ *  -c <chunk-size>     maximum number of revisions in a concat chunk
+ *  -b <begin-date>     earliest date to check for uncompressed revisions
+ *  -e <end-date>       latest revision date to compress
+ *  -s <start-id>       the old_id to start from
+ *  -f <max-factor>     the maximum ratio of compressed chunk bytes to uncompressed avg. revision bytes
+ *  -h <threshold>      is a minimum number of KB, where <max-factor> cuts in
+ *  --extdb <cluster>   store specified revisions in an external cluster (untested)
+ *
+ */
+
+$optionsWithArgs = array( 't', 'c', 's', 'f', 'h', 'extdb' );
+require_once( "../commandLine.inc" );
+require_once( "compressOld.inc" );
+
+if( !function_exists( "gzdeflate" ) ) {
+       print "You must enable zlib support in PHP to compress old revisions!\n";
+       print "Please see http://www.php.net/manual/en/ref.zlib.php\n\n";
+       die();
+}
+
+$defaults = array( 
+       't' => 'concat',
+       'c' => 20,
+       's' => 0,
+       'f' => 3,
+       'h' => 100,
+       'b' => '',
+    'e' => '',
+    'extdb' => '',
+);
+
+$options = $options + $defaults;
+
+if ( $options['t'] != 'concat' && $options['t'] != 'gzip' ) {
+       print "Type \"{$options['t']}\" not supported\n";
+}
+
+print "Depending on the size of your database this may take a while!\n";
+print "If you abort the script while it's running it shouldn't harm anything,\n";
+print "but if you haven't backed up your data, you SHOULD abort now!\n\n";
+print "Press control-c to abort first (will proceed automatically in 5 seconds)\n";
+#sleep(5);
+
+$success = true;
+if ( $options['t'] == 'concat' ) {
+    $success = compressWithConcat( $options['s'], $options['c'], $options['f'], $options['h'], $options['b'], 
+        $options['e'], $options['extdb'] );
+} else {
+       compressOldPages( $options['s'], $options['extdb'] );
+} 
+
+if ( $success ) {
+       print "Done.\n";
+}
+
+exit();
+
+?>
diff --git a/maintenance/storage/dumpRev.php b/maintenance/storage/dumpRev.php
new file mode 100644 (file)
index 0000000..4d0ccb5
--- /dev/null
@@ -0,0 +1,14 @@
+<?php
+
+require_once( 'commandLine.inc' );
+$dbr =& wfGetDB( DB_SLAVE );
+$row = $dbr->selectRow( 'old', array( 'old_flags', 'old_text' ), array( 'old_id' => $args[0] ) );
+$obj = unserialize( $row->old_text );
+
+if ( get_class( $obj ) == 'concatenatedgziphistoryblob' ) {
+       print_r( array_keys( $obj->mItems ) );
+} else {
+       var_dump( $obj );
+}
+
+?>
diff --git a/maintenance/storage/moveToExternal.php b/maintenance/storage/moveToExternal.php
new file mode 100644 (file)
index 0000000..8b441d2
--- /dev/null
@@ -0,0 +1,80 @@
+<?php
+
+define( 'REPORTING_INTERVAL', 100 );
+define( 'STUB_HEADER', 'O:15:"historyblobstub"' );
+
+if ( !defined( 'MEDIAWIKI' ) ) {
+       $optionsWithArgs = array( 'm' );
+
+       require_once( '../commandLine.inc' );
+       require_once( 'ExternalStoreDB.php' );
+       require_once( 'resolveStubs.php' );
+
+       $fname = 'moveToExternal';
+
+       if ( !isset( $args[0] ) ) {
+               print "Usage: php moveToExternal.php [-m <maxid>] <cluster>\n";
+               exit;
+       }
+
+       $cluster = $args[0];
+       $dbw =& wfGetDB( DB_MASTER );
+
+       if ( isset( $options['m'] ) ) {
+               $maxID = $options['m'];
+       } else {
+               $maxID = $dbw->selectField( 'text', 'MAX(old_id)', false, $fname );
+       }
+
+       moveToExternal( $cluster, $maxID );
+}
+
+
+
+function moveToExternal( $cluster, $maxID ) {
+       $fname = 'moveToExternal';
+       $dbw =& wfGetDB( DB_MASTER );
+
+       print "Moving $maxID text rows to external storage\n";
+       $ext = new ExternalStoreDB;
+       for ( $id = 1; $id <= $maxID; $id++ ) {
+               if ( !($id % REPORTING_INTERVAL) ) {
+                       print "$id\n";
+                       wfWaitForSlaves( 5 );
+               }
+               $row = $dbw->selectRow( 'text', array( 'old_flags', 'old_text' ),
+                       array( 
+                               'old_id' => $id,
+                               "old_flags NOT LIKE '%external%'",
+                       ), $fname );
+               if ( !$row ) {
+                       # Non-existent or already done
+                       continue;
+               }
+
+               # Resolve stubs
+               $flags = explode( ',', $row->old_flags );
+               if ( in_array( 'object', $flags ) 
+                       && substr( $row->old_text, 0, strlen( STUB_HEADER ) ) === STUB_HEADER ) 
+               {
+                       resolveStub( $id, $row->old_text, $row->old_flags );
+                       continue;
+               }
+
+               $url = $ext->store( $cluster, $row->old_text );
+               if ( !$url ) {
+                       print "Error writing to external storage\n";
+                       exit;
+               }
+               if ( $row->old_flags === '' ) {
+                       $flags = 'external';
+               } else {
+                       $flags = "{$row->old_flags},external";
+               }
+               $dbw->update( 'text', 
+                       array( 'old_flags' => $flags, 'old_text' => $url ),
+                       array( 'old_id' => $id ), $fname );
+       }
+}
+
+?>
diff --git a/maintenance/storage/resolveStubs.php b/maintenance/storage/resolveStubs.php
new file mode 100644 (file)
index 0000000..d22976c
--- /dev/null
@@ -0,0 +1,108 @@
+<?php
+
+define( 'REPORTING_INTERVAL', 100 );
+
+if ( !defined( 'MEDIAWIKI' ) ) {
+       $optionsWithArgs = array( 'm' );
+
+       require_once( '../commandLine.inc' );
+       require_once( 'includes/ExternalStoreDB.php' );
+
+       resolveStubs();
+}
+
+/**
+ * Convert history stubs that point to an external row to direct
+ * external pointers
+ */
+function resolveStubs() {
+       $fname = 'resolveStubs';
+
+       print "Retrieving stub rows...\n";
+       $dbr =& wfGetDB( DB_SLAVE );
+       $maxID = $dbr->selectField( 'text', 'MAX(old_id)', false, $fname );
+       $stubs = array();
+       $flagsArray = array();
+
+       # Do it in 100 blocks
+       for ( $b = 0; $b < 100; $b++ ) {
+               print "$b%\r";
+               $start = intval($maxID / 100) * $b + 1;
+               $end = intval($maxID / 100) * ($b + 1);
+
+               $res = $dbr->select( 'text', array( 'old_id', 'old_text', 'old_flags' ),
+                       "old_id>=$start AND old_id<=$end AND old_flags like '%object%' ".
+                       "AND old_text LIKE 'O:15:\"historyblobstub\"%'", $fname );
+               while ( $row = $dbr->fetchObject( $res ) ) {
+                       $stubs[$row->old_id] = $row->old_text;
+                       $flagsArray[$row->old_id] = $row->old_flags;
+               }
+               $dbr->freeResult( $res );
+       }
+       print "100%\n";
+
+       print "\nConverting " . count( $stubs ) . " rows ...\n";
+
+       # Get master database, no transactions
+       $dbw =& wfGetDB( DB_MASTER );
+       $dbw->clearFlag( DBO_TRX );
+       $dbw->immediateCommit();
+
+       $i = 0;
+       foreach( $stubs as $id => $stub ) {
+               if ( !(++$i % REPORTING_INTERVAL) ) {
+                       print "$i\n";
+                       wfWaitForSlaves( 5 );
+               }
+
+               resolveStub( $id, $stub, $flagsArray[$id] );
+       }
+}
+
+/**
+ * Resolve a history stub
+ */
+function resolveStub( $id, $stubText, $flags ) {
+       $fname = 'resolveStub';
+
+       $stub = unserialize( $stubText );
+       $flags = explode( ',', $flags );
+
+       $dbr =& wfGetDB( DB_SLAVE );
+       $dbw =& wfGetDB( DB_MASTER );
+       
+       if ( get_class( $stub ) !== 'historyblobstub' ) {
+               print "Error, invalid stub object\n";
+               return;
+       }
+
+       # Get the (maybe) external row
+       $externalRow = $dbr->selectRow( 'text', array( 'old_text' ), 
+               array( 'old_id' => $stub->mOldId, "old_flags LIKE '%external%'" ),
+               $fname 
+       );
+
+       if ( !$externalRow ) {
+               # Object wasn't external
+               continue;
+       }
+
+       # Preserve the legacy encoding flag, but switch from object to external
+       if ( in_array( 'utf-8', $flags ) ) {
+               $newFlags = 'external,utf-8';
+       } else {
+               $newFlags = 'external';
+       }
+
+       # Update the row
+       $dbw->update( 'text',
+               array( /* SET */
+                       'old_flags' => $newFlags, 
+                       'old_text' => $externalRow->old_text . '/' . $stub->mHash
+               ), 
+               array( /* WHERE */ 
+                       'old_id' => $id 
+               ), $fname 
+       );
+}
+?>
diff --git a/maintenance/tables.sql b/maintenance/tables.sql
new file mode 100644 (file)
index 0000000..e53a658
--- /dev/null
@@ -0,0 +1,850 @@
+-- SQL to create the initial tables for the MediaWiki database.
+-- This is read and executed by the install script; you should
+-- not have to run it by itself unless doing a manual install.
+
+--
+-- General notes:
+--
+-- If possible, create tables as InnoDB to benefit from the
+-- superior resiliency against crashes and ability to read
+-- during writes (and write during reads!)
+--
+-- Only the 'searchindex' table requires MyISAM due to the
+-- requirement for fulltext index support, which is missing
+-- from InnoDB.
+--
+--
+-- The MySQL table backend for MediaWiki currently uses
+-- 14-character CHAR or VARCHAR fields to store timestamps.
+-- The format is YYYYMMDDHHMMSS, which is derived from the
+-- text format of MySQL's TIMESTAMP fields.
+--
+-- Historically TIMESTAMP fields were used, but abandoned
+-- in early 2002 after a lot of trouble with the fields
+-- auto-updating.
+--
+-- The PostgreSQL backend uses DATETIME fields for timestamps,
+-- and we will migrate the MySQL definitions at some point as
+-- well.
+--
+--
+-- The /*$wgDBprefix*/ comments in this and other files are
+-- replaced with the defined table prefix by the installer
+-- and updater scripts. If you are installing or running
+-- updates manually, you will need to manually insert the
+-- table prefix if any when running these scripts.
+--
+
+
+--
+-- The user table contains basic account information,
+-- authentication keys, etc.
+--
+-- Some multi-wiki sites may share a single central user table
+-- between separate wikis using the $wgSharedDB setting.
+--
+-- Note that when a external authentication plugin is used,
+-- user table entries still need to be created to store
+-- preferences and to key tracking information in the other
+-- tables.
+--
+CREATE TABLE /*$wgDBprefix*/user (
+  user_id int(5) unsigned NOT NULL auto_increment,
+  
+  -- Usernames must be unique, must not be in the form of
+  -- an IP address. _Shouldn't_ allow slashes or case
+  -- conflicts. Spaces are allowed, and are _not_ converted
+  -- to underscores like titles. (Conflicts?)
+  user_name varchar(255) binary NOT NULL default '',
+  
+  -- Optional 'real name' to be displayed in credit listings
+  user_real_name varchar(255) binary NOT NULL default '',
+  
+  -- Password hashes, normally hashed like so:
+  -- MD5(CONCAT(user_id,'-',MD5(plaintext_password)))
+  user_password tinyblob NOT NULL default '',
+  
+  -- When using 'mail me a new password', a random
+  -- password is generated and the hash stored here.
+  -- The previous password is left in place until
+  -- someone actually logs in with the new password,
+  -- at which point the hash is moved to user_password
+  -- and the old password is invalidated.
+  user_newpassword tinyblob NOT NULL default '',
+  
+  -- Note: email should be restricted, not public info.
+  -- Same with passwords.
+  user_email tinytext NOT NULL default '',
+  
+  -- Newline-separated list of name=value pairs.
+  user_options blob NOT NULL default '',
+  
+  -- This is a timestamp which is updated when a user
+  -- logs in, logs out, changes preferences, or performs
+  -- some other action requiring HTML cache invalidation
+  -- to ensure that the UI is updated.
+  user_touched char(14) binary NOT NULL default '',
+  
+  -- A pseudorandomly generated value that is stored in
+  -- a cookie when the "remember password" feature is
+  -- used (previously, a hash of the password was used, but
+  -- this was vulnerable to cookie-stealing attacks)
+  user_token char(32) binary NOT NULL default '',
+  
+  -- Initially NULL; when a user's e-mail address has been
+  -- validated by returning with a mailed token, this is
+  -- set to the current timestamp.
+  user_email_authenticated CHAR(14) BINARY,
+  
+  -- Randomly generated token created when the e-mail address
+  -- is set and a confirmation test mail sent.
+  user_email_token CHAR(32) BINARY,
+  
+  -- Expiration date for the 
+  user_email_token_expires CHAR(14) BINARY,
+
+  PRIMARY KEY user_id (user_id),
+  UNIQUE INDEX user_name (user_name),
+  INDEX (user_email_token)
+
+) TYPE=InnoDB;
+
+--
+-- User permissions have been broken out to a separate table;
+-- this allows sites with a shared user table to have different
+-- permissions assigned to a user in each project.
+--
+-- This table replaces the old user_rights field which used a
+-- comma-separated blob.
+--
+CREATE TABLE /*$wgDBprefix*/user_groups (
+  -- Key to user_id
+  ug_user int(5) unsigned NOT NULL default '0',
+  
+  -- Group names are short symbolic string keys.
+  -- The set of group names is open-ended, though in practice
+  -- only some predefined ones are likely to be used.
+  --
+  -- At runtime $wgGroupPermissions will associate group keys
+  -- with particular permissions. A user will have the combined
+  -- permissions of any group they're explicitly in, plus
+  -- the implicit '*' and 'user' groups.
+  ug_group char(16) NOT NULL default '',
+  
+  PRIMARY KEY (ug_user,ug_group),
+  KEY (ug_group)
+) TYPE=InnoDB;
+
+-- Stores notifications of user talk page changes, for the display
+-- of the "you have new messages" box
+CREATE TABLE /*$wgDBprefix*/user_newtalk (
+ user_id int(5) NOT NULL default '0',
+ user_ip varchar(40) NOT NULL default '',
+ INDEX user_id (user_id),
+ INDEX user_ip (user_ip)
+);
+
+
+--
+-- Core of the wiki: each page has an entry here which identifies
+-- it by title and contains some essential metadata.
+--
+CREATE TABLE /*$wgDBprefix*/page (
+  -- Unique identifier number. The page_id will be preserved across
+  -- edits and rename operations, but not deletions and recreations.
+  page_id int(8) unsigned NOT NULL auto_increment,
+  
+  -- A page name is broken into a namespace and a title.
+  -- The namespace keys are UI-language-independent constants,
+  -- defined in Namespace.php.
+  page_namespace int NOT NULL,
+  
+  -- The rest of the title, as text.
+  -- Spaces are transformed into underscores in title storage.
+  page_title varchar(255) binary NOT NULL,
+  
+  -- Comma-separated set of permission keys indicating who
+  -- can move or edit the page.
+  page_restrictions tinyblob NOT NULL default '',
+  
+  -- Number of times this page has been viewed.
+  page_counter bigint(20) unsigned NOT NULL default '0',
+  
+  -- 1 indicates the article is a redirect.
+  page_is_redirect tinyint(1) unsigned NOT NULL default '0',
+  
+  -- 1 indicates this is a new entry, with only one edit.
+  -- Not all pages with one edit are new pages.
+  page_is_new tinyint(1) unsigned NOT NULL default '0',
+  
+  -- Random value between 0 and 1, used for Special:Randompage
+  page_random real unsigned NOT NULL,
+  
+  -- This timestamp is updated whenever the page changes in
+  -- a way requiring it to be re-rendered, invalidating caches.
+  -- Aside from editing this includes permission changes,
+  -- creation or deletion of linked pages, and alteration
+  -- of contained templates.
+  page_touched char(14) binary NOT NULL default '',
+
+  -- Handy key to revision.rev_id of the current revision.
+  -- This may be 0 during page creation, but that shouldn't
+  -- happen outside of a transaction... hopefully.
+  page_latest int(8) unsigned NOT NULL,
+  
+  -- Uncompressed length in bytes of the page's current source text.
+  page_len int(8) unsigned NOT NULL,
+
+  PRIMARY KEY page_id (page_id),
+  UNIQUE INDEX name_title (page_namespace,page_title),
+  
+  -- Special-purpose indexes
+  INDEX (page_random),
+  INDEX (page_len)
+
+) TYPE=InnoDB;
+
+--
+-- Every edit of a page creates also a revision row.
+-- This stores metadata about the revision, and a reference
+-- to the text storage backend.
+--
+CREATE TABLE /*$wgDBprefix*/revision (
+  rev_id int(8) unsigned NOT NULL auto_increment,
+  
+  -- Key to page_id. This should _never_ be invalid.
+  rev_page int(8) unsigned NOT NULL,
+  
+  -- Key to text.old_id, where the actual bulk text is stored.
+  -- It's possible for multiple revisions to use the same text,
+  -- for instance revisions where only metadata is altered
+  -- or a rollback to a previous version.
+  rev_text_id int(8) unsigned NOT NULL,
+  
+  -- Text comment summarizing the change.
+  -- This text is shown in the history and other changes lists,
+  -- rendered in a subset of wiki markup.
+  rev_comment tinyblob NOT NULL default '',
+  
+  -- Key to user_id of the user who made this edit.
+  -- Stores 0 for anonymous edits and for some mass imports.
+  rev_user int(5) unsigned NOT NULL default '0',
+  
+  -- Text username or IP address of the editor.
+  rev_user_text varchar(255) binary NOT NULL default '',
+  
+  -- Timestamp
+  rev_timestamp char(14) binary NOT NULL default '',
+  
+  -- Records whether the user marked the 'minor edit' checkbox.
+  -- Many automated edits are marked as minor.
+  rev_minor_edit tinyint(1) unsigned NOT NULL default '0',
+  
+  -- Not yet used; reserved for future changes to the deletion system.
+  rev_deleted tinyint(1) unsigned NOT NULL default '0',
+  
+  PRIMARY KEY rev_page_id (rev_page, rev_id),
+  UNIQUE INDEX rev_id (rev_id),
+  INDEX rev_timestamp (rev_timestamp),
+  INDEX page_timestamp (rev_page,rev_timestamp),
+  INDEX user_timestamp (rev_user,rev_timestamp),
+  INDEX usertext_timestamp (rev_user_text,rev_timestamp)
+
+) TYPE=InnoDB;
+
+
+--
+-- Holds text of individual page revisions.
+--
+-- Field names are a holdover from the 'old' revisions table in
+-- MediaWiki 1.4 and earlier: an upgrade will transform that
+-- table into the 'text' table to minimize unnecessary churning
+-- and downtime. If upgrading, the other fields will be left unused.
+--
+CREATE TABLE /*$wgDBprefix*/text (
+  -- Unique text storage key number.
+  -- Note that the 'oldid' parameter used in URLs does *not*
+  -- refer to this number anymore, but to rev_id.
+  old_id int(8) unsigned NOT NULL auto_increment,
+  
+  -- Depending on the contents of the old_flags field, the text
+  -- may be convenient plain text, or it may be funkily encoded.
+  old_text mediumblob NOT NULL default '',
+  
+  -- Comma-separated list of flags:
+  -- gzip: text is compressed with PHP's gzdeflate() function.
+  -- utf8: text was stored as UTF-8.
+  --       If $wgLegacyEncoding option is on, rows *without* this flag
+  --       will be converted to UTF-8 transparently at load time.
+  -- object: text field contained a serialized PHP object.
+  --         The object either contains multiple versions compressed
+  --         together to achieve a better compression ratio, or it refers
+  --         to another row where the text can be found.
+  old_flags tinyblob NOT NULL default '',
+  
+  PRIMARY KEY old_id (old_id)
+
+) TYPE=InnoDB;
+
+--
+-- Holding area for deleted articles, which may be viewed
+-- or restored by admins through the Special:Undelete interface.
+-- The fields generally correspond to the page, revision, and text
+-- fields, with several caveats.
+--
+CREATE TABLE /*$wgDBprefix*/archive (
+  ar_namespace int NOT NULL default '0',
+  ar_title varchar(255) binary NOT NULL default '',
+  
+  -- Newly deleted pages will not store text in this table,
+  -- but will reference the separately existing text rows.
+  -- This field is retained for backwards compatibility,
+  -- so old archived pages will remain accessible after
+  -- upgrading from 1.4 to 1.5.
+  -- Text may be gzipped or otherwise funky.
+  ar_text mediumblob NOT NULL default '',
+  
+  -- Basic revision stuff...
+  ar_comment tinyblob NOT NULL default '',
+  ar_user int(5) unsigned NOT NULL default '0',
+  ar_user_text varchar(255) binary NOT NULL,
+  ar_timestamp char(14) binary NOT NULL default '',
+  ar_minor_edit tinyint(1) NOT NULL default '0',
+  
+  -- See ar_text note.
+  ar_flags tinyblob NOT NULL default '',
+  
+  -- When revisions are deleted, their unique rev_id is stored
+  -- here so it can be retained after undeletion. This is necessary
+  -- to retain permalinks to given revisions after accidental delete
+  -- cycles or messy operations like history merges.
+  -- 
+  -- Old entries from 1.4 will be NULL here, and a new rev_id will
+  -- be created on undeletion for those revisions.
+  ar_rev_id int(8) unsigned,
+  
+  -- For newly deleted revisions, this is the text.old_id key to the
+  -- actual stored text. To avoid breaking the block-compression scheme
+  -- and otherwise making storage changes harder, the actual text is
+  -- *not* deleted from the text table, merely hidden by removal of the
+  -- page and revision entries.
+  --
+  -- Old entries deleted under 1.2-1.4 will have NULL here, and their
+  -- ar_text and ar_flags fields will be used to create a new text
+  -- row upon undeletion.
+  ar_text_id int(8) unsigned,
+  
+  KEY name_title_timestamp (ar_namespace,ar_title,ar_timestamp)
+
+) TYPE=InnoDB;
+
+
+--
+-- Track page-to-page hyperlinks within the wiki.
+--
+CREATE TABLE /*$wgDBprefix*/pagelinks (
+  -- Key to the page_id of the page containing the link.
+  pl_from int(8) unsigned NOT NULL default '0',
+  
+  -- Key to page_namespace/page_title of the target page.
+  -- The target page may or may not exist, and due to renames
+  -- and deletions may refer to different page records as time
+  -- goes by.
+  pl_namespace int NOT NULL default '0',
+  pl_title varchar(255) binary NOT NULL default '',
+  
+  UNIQUE KEY pl_from(pl_from,pl_namespace,pl_title),
+  KEY (pl_namespace,pl_title)
+
+) TYPE=InnoDB;
+
+
+--
+-- Track links to images *used inline*
+-- We don't distinguish live from broken links here, so
+-- they do not need to be changed on upload/removal.
+--
+CREATE TABLE /*$wgDBprefix*/imagelinks (
+  -- Key to page_id of the page containing the image / media link.
+  il_from int(8) unsigned NOT NULL default '0',
+  
+  -- Filename of target image.
+  -- This is also the page_title of the file's description page;
+  -- all such pages are in namespace 6 (NS_IMAGE).
+  il_to varchar(255) binary NOT NULL default '',
+  
+  UNIQUE KEY il_from(il_from,il_to),
+  KEY (il_to)
+
+) TYPE=InnoDB;
+
+--
+-- Track category inclusions *used inline*
+-- This tracks a single level of category membership
+-- (folksonomic tagging, really).
+--
+CREATE TABLE /*$wgDBprefix*/categorylinks (
+  -- Key to page_id of the page defined as a category member.
+  cl_from int(8) unsigned NOT NULL default '0',
+  
+  -- Name of the category.
+  -- This is also the page_title of the category's description page;
+  -- all such pages are in namespace 14 (NS_CATEGORY).
+  cl_to varchar(255) binary NOT NULL default '',
+  
+  -- The title of the linking page, or an optional override
+  -- to determine sort order. Sorting is by binary order, which
+  -- isn't always ideal, but collations seem to be an exciting
+  -- and dangerous new world in MySQL...
+  --
+  -- For MySQL 4.1+ with charset set to utf8, the sort key *index*
+  -- needs cut to be smaller than 1024 bytes (at 3 bytes per char).
+  -- To sort properly on the shorter key, this field needs to be
+  -- the same shortness.
+  cl_sortkey varchar(86) binary NOT NULL default '',
+  
+  -- This isn't really used at present. Provided for an optional
+  -- sorting method by approximate addition time.
+  cl_timestamp timestamp NOT NULL,
+  
+  UNIQUE KEY cl_from(cl_from,cl_to),
+  
+  -- We always sort within a given category...
+  KEY cl_sortkey(cl_to,cl_sortkey),
+  
+  -- Not really used?
+  KEY cl_timestamp(cl_to,cl_timestamp)
+
+) TYPE=InnoDB;
+
+--
+-- Contains a single row with some aggregate info
+-- on the state of the site.
+--
+CREATE TABLE /*$wgDBprefix*/site_stats (
+  -- The single row should contain 1 here.
+  ss_row_id int(8) unsigned NOT NULL,
+  
+  -- Total number of page views, if hit counters are enabled.
+  ss_total_views bigint(20) unsigned default '0',
+  
+  -- Total number of edits performed.
+  ss_total_edits bigint(20) unsigned default '0',
+  
+  -- An approximate count of pages matching the following criteria:
+  -- * in namespace 0
+  -- * not a redirect
+  -- * contains the text '[['
+  -- See isCountable() in includes/Article.php
+  ss_good_articles bigint(20) unsigned default '0',
+  
+  -- Total pages, theoretically equal to SELECT COUNT(*) FROM page; except faster
+  ss_total_pages bigint(20) default -1,
+
+  -- Number of users, theoretically equal to SELECT COUNT(*) FROM user;
+  ss_users bigint(20) default -1,
+
+  -- Deprecated, no longer updated as of 1.5
+  ss_admins int(10) default -1,
+
+  UNIQUE KEY ss_row_id (ss_row_id)
+
+) TYPE=InnoDB;
+
+--
+-- Stores an ID for every time any article is visited;
+-- depending on $wgHitcounterUpdateFreq, it is
+-- periodically cleared and the page_counter column
+-- in the page table updated for the all articles
+-- that have been visited.)
+--
+CREATE TABLE /*$wgDBprefix*/hitcounter (
+  hc_id INTEGER UNSIGNED NOT NULL
+) TYPE=HEAP MAX_ROWS=25000;
+
+
+--
+-- The internet is full of jerks, alas. Sometimes it's handy
+-- to block a vandal or troll account.
+--
+CREATE TABLE /*$wgDBprefix*/ipblocks (
+  -- Primary key, introduced for privacy.
+  ipb_id int(8) NOT NULL auto_increment,
+  
+  -- Blocked IP address in dotted-quad form or user name.
+  ipb_address varchar(40) binary NOT NULL default '',
+  
+  -- Blocked user ID or 0 for IP blocks.
+  ipb_user int(8) unsigned NOT NULL default '0',
+  
+  -- User ID who made the block.
+  ipb_by int(8) unsigned NOT NULL default '0',
+  
+  -- Text comment made by blocker.
+  ipb_reason tinyblob NOT NULL default '',
+  
+  -- Creation (or refresh) date in standard YMDHMS form.
+  -- IP blocks expire automatically.
+  ipb_timestamp char(14) binary NOT NULL default '',
+  
+  -- Indicates that the IP address was banned because a banned
+  -- user accessed a page through it. If this is 1, ipb_address
+  -- will be hidden, and the block identified by block ID number.
+  ipb_auto tinyint(1) NOT NULL default '0',
+  
+  -- Time at which the block will expire.
+  ipb_expiry char(14) binary NOT NULL default '',
+
+  PRIMARY KEY ipb_id (ipb_id),
+  INDEX ipb_address (ipb_address),
+  INDEX ipb_user (ipb_user)
+
+) TYPE=InnoDB;
+
+
+--
+-- Uploaded images and other files.
+--
+CREATE TABLE /*$wgDBprefix*/image (
+  -- Filename.
+  -- This is also the title of the associated description page,
+  -- which will be in namespace 6 (NS_IMAGE).
+  img_name varchar(255) binary NOT NULL default '',
+  
+  -- File size in bytes.
+  img_size int(8) unsigned NOT NULL default '0',
+  
+  -- For images, size in pixels.
+  img_width int(5)  NOT NULL default '0',
+  img_height int(5)  NOT NULL default '0',
+  
+  -- Extracted EXIF metadata stored as a serialized PHP array.
+  img_metadata mediumblob NOT NULL,
+  
+  -- For images, bits per pixel if known.
+  img_bits int(3)  NOT NULL default '0',
+  
+  -- Media type as defined by the MEDIATYPE_xxx constants
+  img_media_type ENUM("UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE") default NULL,
+  
+  -- major part of a MIME media type as defined by IANA
+  -- see http://www.iana.org/assignments/media-types/
+  img_major_mime ENUM("unknown", "application", "audio", "image", "text", "video", "message", "model", "multipart") NOT NULL default "unknown",
+  
+  -- minor part of a MIME media type as defined by IANA
+  -- the minor parts are not required to adher to any standard
+  -- but should be consistent throughout the database
+  -- see http://www.iana.org/assignments/media-types/
+  img_minor_mime varchar(32) NOT NULL default "unknown",
+  
+  -- Description field as entered by the uploader.
+  -- This is displayed in image upload history and logs.
+  img_description tinyblob NOT NULL default '',
+  
+  -- user_id and user_name of uploader.
+  img_user int(5) unsigned NOT NULL default '0',
+  img_user_text varchar(255) binary NOT NULL default '',
+  
+  -- Time of the upload.
+  img_timestamp char(14) binary NOT NULL default '',
+  
+  PRIMARY KEY img_name (img_name),
+  
+  -- Used by Special:Imagelist for sort-by-size
+  INDEX img_size (img_size),
+  
+  -- Used by Special:Newimages and Special:Imagelist
+  INDEX img_timestamp (img_timestamp)
+
+) TYPE=InnoDB;
+
+--
+-- Previous revisions of uploaded files.
+-- Awkwardly, image rows have to be moved into
+-- this table at re-upload time.
+--
+CREATE TABLE /*$wgDBprefix*/oldimage (
+  -- Base filename: key to image.img_name
+  oi_name varchar(255) binary NOT NULL default '',
+  
+  -- Filename of the archived file.
+  -- This is generally a timestamp and '!' prepended to the base name.
+  oi_archive_name varchar(255) binary NOT NULL default '',
+  
+  -- Other fields as in image...
+  oi_size int(8) unsigned NOT NULL default 0,
+  oi_width int(5) NOT NULL default 0,
+  oi_height int(5) NOT NULL default 0,
+  oi_bits int(3) NOT NULL default 0,
+  oi_description tinyblob NOT NULL default '',
+  oi_user int(5) unsigned NOT NULL default '0',
+  oi_user_text varchar(255) binary NOT NULL default '',
+  oi_timestamp char(14) binary NOT NULL default '',
+
+  INDEX oi_name (oi_name(10))
+
+) TYPE=InnoDB;
+
+
+--
+-- Primarily a summary table for Special:Recentchanges,
+-- this table contains some additional info on edits from
+-- the last few days.
+--
+CREATE TABLE /*$wgDBprefix*/recentchanges (
+  rc_id int(8) NOT NULL auto_increment,
+  rc_timestamp varchar(14) binary NOT NULL default '',
+  rc_cur_time varchar(14) binary NOT NULL default '',
+  
+  -- As in revision
+  rc_user int(10) unsigned NOT NULL default '0',
+  rc_user_text varchar(255) binary NOT NULL default '',
+  
+  -- When pages are renamed, their RC entries do _not_ change.
+  rc_namespace int NOT NULL default '0',
+  rc_title varchar(255) binary NOT NULL default '',
+  
+  -- as in revision...
+  rc_comment varchar(255) binary NOT NULL default '',
+  rc_minor tinyint(3) unsigned NOT NULL default '0',
+  
+  -- Edits by user accounts with the 'bot' rights key are
+  -- marked with a 1 here, and will be hidden from the
+  -- default view.
+  rc_bot tinyint(3) unsigned NOT NULL default '0',
+  
+  rc_new tinyint(3) unsigned NOT NULL default '0',
+  
+  -- Key to page_id (was cur_id prior to 1.5).
+  -- This will keep links working after moves while
+  -- retaining the at-the-time name in the changes list.
+  rc_cur_id int(10) unsigned NOT NULL default '0',
+  
+  -- rev_id of the given revision
+  rc_this_oldid int(10) unsigned NOT NULL default '0',
+  
+  -- rev_id of the prior revision, for generating diff links.
+  rc_last_oldid int(10) unsigned NOT NULL default '0',
+  
+  -- These may no longer be used, with the new move log.
+  rc_type tinyint(3) unsigned NOT NULL default '0',
+  rc_moved_to_ns tinyint(3) unsigned NOT NULL default '0',
+  rc_moved_to_title varchar(255) binary NOT NULL default '',
+  
+  -- If the Recent Changes Patrol option is enabled,
+  -- users may mark edits as having been reviewed to
+  -- remove a warning flag on the RC list.
+  -- A value of 1 indicates the page has been reviewed.
+  rc_patrolled tinyint(3) unsigned NOT NULL default '0',
+  
+  -- Recorded IP address the edit was made from, if the
+  -- $wgPutIPinRC option is enabled.
+  rc_ip char(15) NOT NULL default '',
+  
+  PRIMARY KEY rc_id (rc_id),
+  INDEX rc_timestamp (rc_timestamp),
+  INDEX rc_namespace_title (rc_namespace, rc_title),
+  INDEX rc_cur_id (rc_cur_id),
+  INDEX new_name_timestamp(rc_new,rc_namespace,rc_timestamp),
+  INDEX rc_ip (rc_ip)
+
+) TYPE=InnoDB;
+
+CREATE TABLE /*$wgDBprefix*/watchlist (
+  -- Key to user_id
+  wl_user int(5) unsigned NOT NULL,
+  
+  -- Key to page_namespace/page_title
+  -- Note that users may watch patches which do not exist yet,
+  -- or existed in the past but have been deleted.
+  wl_namespace int NOT NULL default '0',
+  wl_title varchar(255) binary NOT NULL default '',
+  
+  -- Timestamp when user was last sent a notification e-mail;
+  -- cleared when the user visits the page.
+  -- FIXME: add proper null support etc
+  wl_notificationtimestamp varchar(14) binary NOT NULL default '0',
+  
+  UNIQUE KEY (wl_user, wl_namespace, wl_title),
+  KEY namespace_title (wl_namespace,wl_title)
+
+) TYPE=InnoDB;
+
+
+--
+-- Used by texvc math-rendering extension to keep track
+-- of previously-rendered items.
+--
+CREATE TABLE /*$wgDBprefix*/math (
+  -- Binary MD5 hash of the latex fragment, used as an identifier key.
+  math_inputhash varchar(16) NOT NULL,
+  
+  -- Not sure what this is, exactly...
+  math_outputhash varchar(16) NOT NULL,
+  
+  -- texvc reports how well it thinks the HTML conversion worked;
+  -- if it's a low level the PNG rendering may be preferred.
+  math_html_conservativeness tinyint(1) NOT NULL,
+  
+  -- HTML output from texvc, if any
+  math_html text,
+  
+  -- MathML output from texvc, if any
+  math_mathml text,
+  
+  UNIQUE KEY math_inputhash (math_inputhash)
+
+) TYPE=InnoDB;
+
+--
+-- When using the default MySQL search backend, page titles
+-- and text are munged to strip markup, do Unicode case folding,
+-- and prepare the result for MySQL's fulltext index.
+--
+-- This table must be MyISAM; InnoDB does not support the needed
+-- fulltext index.
+--
+CREATE TABLE /*$wgDBprefix*/searchindex (
+  -- Key to page_id
+  si_page int(8) unsigned NOT NULL,
+  
+  -- Munged version of title
+  si_title varchar(255) NOT NULL default '',
+  
+  -- Munged version of body text
+  si_text mediumtext NOT NULL default '',
+  
+  UNIQUE KEY (si_page),
+  FULLTEXT si_title (si_title),
+  FULLTEXT si_text (si_text)
+
+) TYPE=MyISAM;
+
+--
+-- Recognized interwiki link prefixes
+--
+CREATE TABLE /*$wgDBprefix*/interwiki (
+  -- The interwiki prefix, (e.g. "Meatball", or the language prefix "de")
+  iw_prefix char(32) NOT NULL,
+  
+  -- The URL of the wiki, with "$1" as a placeholder for an article name.
+  -- Any spaces in the name will be transformed to underscores before
+  -- insertion.
+  iw_url char(127) NOT NULL,
+  
+  -- A boolean value indicating whether the wiki is in this project
+  -- (used, for example, to detect redirect loops)
+  iw_local BOOL NOT NULL,
+  
+  -- Boolean value indicating whether interwiki transclusions are allowed.
+  iw_trans TINYINT(1) NOT NULL DEFAULT 0,
+  
+  UNIQUE KEY iw_prefix (iw_prefix)
+
+) TYPE=InnoDB;
+
+--
+-- Used for caching expensive grouped queries
+--
+CREATE TABLE /*$wgDBprefix*/querycache (
+  -- A key name, generally the base name of of the special page.
+  qc_type char(32) NOT NULL,
+  
+  -- Some sort of stored value. Sizes, counts...
+  qc_value int(5) unsigned NOT NULL default '0',
+  
+  -- Target namespace+title
+  qc_namespace int NOT NULL default '0',
+  qc_title char(255) binary NOT NULL default '',
+  
+  KEY (qc_type,qc_value)
+
+) TYPE=InnoDB;
+
+--
+-- For a few generic cache operations if not using Memcached
+--
+CREATE TABLE /*$wgDBprefix*/objectcache (
+  keyname char(255) binary not null default '',
+  value mediumblob,
+  exptime datetime,
+  unique key (keyname),
+  key (exptime)
+
+) TYPE=InnoDB;
+
+-- For article validation
+CREATE TABLE /*$wgDBprefix*/validate (
+  val_user int(11) NOT NULL default '0',
+  val_page int(11) unsigned NOT NULL default '0',
+  val_revision int(11) unsigned NOT NULL default '0',
+  val_type int(11) unsigned NOT NULL default '0',
+  val_value int(11) default '0',
+  val_comment varchar(255) NOT NULL default '',
+  val_ip varchar(20) NOT NULL default '',
+  KEY val_user (val_user,val_revision)
+) TYPE=InnoDB;
+
+
+CREATE TABLE /*$wgDBprefix*/logging (
+  -- Symbolic keys for the general log type and the action type
+  -- within the log. The output format will be controlled by the
+  -- action field, but only the type controls categorization.
+  log_type char(10) NOT NULL default '',
+  log_action char(10) NOT NULL default '',
+  
+  -- Timestamp. Duh.
+  log_timestamp char(14) NOT NULL default '19700101000000',
+  
+  -- The user who performed this action; key to user_id
+  log_user int unsigned NOT NULL default 0,
+  
+  -- Key to the page affected. Where a user is the target,
+  -- this will point to the user page.
+  log_namespace int NOT NULL default 0,
+  log_title varchar(255) binary NOT NULL default '',
+  
+  -- Freeform text. Interpreted as edit history comments.
+  log_comment varchar(255) NOT NULL default '',
+  
+  -- LF separated list of miscellaneous parameters
+  log_params blob NOT NULL default '',
+
+  KEY type_time (log_type, log_timestamp),
+  KEY user_time (log_user, log_timestamp),
+  KEY page_time (log_namespace, log_title, log_timestamp)
+
+) TYPE=InnoDB;
+
+
+
+
+
+-- Hold group name and description
+--CREATE TABLE /*$wgDBprefix*/groups (
+--  gr_id int(5) unsigned NOT NULL auto_increment,
+--  gr_name varchar(50) NOT NULL default '',
+--  gr_description varchar(255) NOT NULL default '',
+--  gr_rights tinyblob,
+--  PRIMARY KEY  (gr_id)
+--
+--) TYPE=InnoDB;
+
+CREATE TABLE /*$wgDBprefix*/trackbacks (
+       tb_id           INTEGER AUTO_INCREMENT PRIMARY KEY,
+       tb_page         INTEGER REFERENCES page(page_id) ON DELETE CASCADE,
+       tb_title        VARCHAR(255) NOT NULL,
+       tb_url          VARCHAR(255) NOT NULL,
+       tb_ex           TEXT,
+       tb_name         VARCHAR(255),
+
+       INDEX (tb_page)
+) TYPE=InnoDB;
+
+CREATE TABLE /*$wgDBprefix*/transcache (
+       tc_url          VARCHAR(255) NOT NULL,
+       tc_contents     TEXT,
+       tc_time         INT NOT NULL,
+       UNIQUE INDEX tc_url_idx(tc_url)
+) TYPE=InnoDB;
+
diff --git a/maintenance/transstat.php b/maintenance/transstat.php
new file mode 100644 (file)
index 0000000..f8aac37
--- /dev/null
@@ -0,0 +1,93 @@
+<?php
+/**
+ * @package MediaWiki
+ * @subpackage Maintenance
+ *
+ * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
+ * @bug 2499
+ *
+ * Output is posted from time to time on:
+ * http://meta.wikimedia.org/wiki/Localization_statistics
+ */
+
+/** */
+require_once('commandLine.inc');
+
+$langs = array();
+$dir = opendir("$IP/languages");
+while ($file = readdir($dir)) {
+       if (preg_match("/Language(.*?)\.php$/", $file, $m)) {
+               $langs[] = $m[1];
+       }
+}
+
+sort($langs);
+
+// Cleanup
+foreach($langs as $key => $lang) {
+       if ($lang == 'Utf8' || $lang == '' || $lang == 'Converter')
+               unset($langs[$key]);
+}
+
+
+$msgs = array();
+foreach($langs as $lang) {
+       // Since they aren't loaded by default..
+       require_once( 'languages/Language' . $lang . '.php' );
+       $arr = 'wgAllMessages' . $lang;
+       if (@is_array($$arr)) { // Some of them don't have a message array 
+               $msgs[$wgContLang->lcfirst($lang)] = array(
+                       'total' => count($$arr),
+                       'redundant' => redundant($$arr),
+               );
+       } else {
+               $msgs[$wgContLang->lcfirst($lang)] = array(
+                       'total' => 0,
+                       'redundant' => 0,
+               );
+       }
+}
+
+// wiki syntax header
+$out = "{| border=2 cellpadding=4 cellspacing=0 style=\"background: #f9f9f9; border: 1px #aaa solid; border-collapse: collapse;\" width=100%\n";
+$out .= beginul();
+$out .= li('Language', true);
+$out .= li('Translated', true);
+$out .= li('%', true);
+$out .= li('Untranslated', true);
+$out .= li('%', true);
+$out .= li('Redundant', true);
+$out .= li('%', true);
+$out .= endul();
+
+// generate table rows using wikisyntax
+foreach($msgs as $lang => $stats) {
+       $out .= beginul();
+       $out .= li($wgContLang->getLanguageName(strtr($lang, '_', '-')) . " ($lang)"); // Language
+       $out .= li($stats['total'] . '/' . $msgs['en']['total']); // Translated
+       $out .= li(percent($stats['total'], $msgs['en']['total'])); // % Translated
+       $out .= li($msgs['en']['total'] - $stats['total']); // Untranslated
+       $out .= li(percent($msgs['en']['total'] - $stats['total'], $msgs['en']['total'])); // % Untranslated
+       $out .= li($stats['redundant'] . '/' . $stats['total']); // Redundant
+       $out .= li(percent($stats['redundant'],  $stats['total'])); // % Redundant
+       $out .= endul();
+}
+$out = substr($out, 0, -3) . "|}\n";
+echo $out;
+
+function beginul() { return ''; }
+function endul() { return "|-\n"; }
+function li($in, $heading = false) { return ($heading ? '!' : '|') . " $in\n"; }
+function percent($subset, $total, $accuracy = 2) { return @sprintf( '%.' . $accuracy . 'f%%', 100 * $subset / $total ); }
+
+// FIXME: This takes an obscene amount of time
+function redundant(&$arr) {
+       global $wgAllMessagesEn;
+       
+       $redundant = 0;
+       foreach(array_keys($arr) as $key) {
+               if ( ! array_key_exists( $key, $wgAllMessagesEn) )
+                       ++$redundant;
+       }
+       return $redundant;
+}
diff --git a/maintenance/trivialCmdLine.php b/maintenance/trivialCmdLine.php
new file mode 100644 (file)
index 0000000..2f12815
--- /dev/null
@@ -0,0 +1,21 @@
+<?php
+/**
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+/** */
+require_once( "commandLine.inc" );
+# print "DB name: $wgDBname\n";
+# print "DB user: $wgDBuser\n";
+# print "DB password: $wgDBpassword\n";
+
+print "This is an example command-line maintenance script.\n";
+
+$dbr =& wfGetDB( DB_SLAVE );
+$page = $dbr->tableName( 'page' );
+$res = $dbr->query( "SELECT MAX(page_id) as m FROM $page" );
+$row = $dbr->fetchObject( $res );
+print "Max page_id: {$row->m}\n";
+
+?>
diff --git a/maintenance/update.php b/maintenance/update.php
new file mode 100644 (file)
index 0000000..87dd4b1
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Run all updaters.
+ *
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */ 
+
+/** */
+$wgUseMasterForMaintenance = true;
+$options = array( 'quick' );
+require_once( "commandLine.inc" );
+require_once( "updaters.inc" );
+$wgTitle = Title::newFromText( "MediaWiki database updater" );
+$wgDatabase = Database::newFromParams( $wgDBserver, $wgDBadminuser, $wgDBadminpassword, $wgDBname );
+
+print "Going to run database updates for $wgDBname\n";
+print "Depending on the size of your database this may take a while!\n";
+
+if( !isset( $options['quick'] ) ) {
+       print "Abort with control-c in the next five seconds... ";
+       
+       for ($i = 5; $i >= 0; --$i) {
+               echo $i;
+               sleep(1);
+               echo( ($i == 0) ? "\n" : chr(8) );
+       }
+}
+
+do_all_updates();
+
+print "Done.\n";
+
+?>
diff --git a/maintenance/updateSearchIndex.inc b/maintenance/updateSearchIndex.inc
new file mode 100644 (file)
index 0000000..a91cc2b
--- /dev/null
@@ -0,0 +1,104 @@
+<?php
+/**
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+/** */
+function updateSearchIndex( $start, $end, $maxLockTime, $quiet ) {
+       global $wgQuiet;
+       global $wgDisableSearchUpdate;
+
+       $fname = "updateSearchIndex";
+
+       $wgQuiet = $quiet;
+       $wgDisableSearchUpdate = false;
+
+       $dbw =& wfGetDB( DB_MASTER );
+       $recentchanges = $dbw->tableName( 'recentchanges' );
+       
+       output( "Updating searchindex between $start and $end\n" );
+
+       # Select entries from recentchanges which are on top and between the specified times
+       $start = $dbw->strencode( $start );
+       $end = $dbw->strencode( $end );
+
+       $sql = "SELECT rc_cur_id,rc_type,rc_moved_to_ns,rc_moved_to_title FROM $recentchanges
+         WHERE rc_this_oldid=0 AND rc_timestamp BETWEEN '$start' AND '$end'";
+       $res = $dbw->query( $sql, $fname );
+
+       # Lock searchindex
+       if ( $maxLockTime ) {
+               output( "   --- Waiting for lock ---" );
+               lockSearchindex();
+               $lockTime = time();
+               output( "\n" );
+       }
+
+       # Loop through the results and do a search update
+       while ( $row = $dbw->fetchObject( $res ) ) {
+               # Allow reads to be processed
+               if ( $maxLockTime && time() > $lockTime + $maxLockTime ) {
+                       output( "    --- Relocking ---" );
+                       relockSearchindex();
+                       $lockTime = time();
+                       output( "\n" );
+               }
+               if ( $row->rc_type == RC_LOG ) {
+                       continue;
+               } elseif ( $row->rc_type == RC_MOVE || $row->rc_type == RC_MOVE_OVER_REDIRECT ) {
+                       # Rename searchindex entry
+                       $titleObj = Title::makeTitle( $row->rc_moved_to_ns, $row->rc_moved_to_title );
+                       $title = $titleObj->getPrefixedDBkey();
+                       output( "$title..." );
+                       $u = new SearchUpdate( $row->rc_cur_id, $title, false );
+                       output( "\n" );
+               } else {
+                       # Get cur row
+                       $curRow = $dbw->selectRow( 'cur', array( 'cur_namespace', 'cur_title', 'cur_text' ), 
+                               array( 'cur_id' => $row->rc_cur_id ), $fname, 'FOR UPDATE' );
+                       if ( $curRow ) {
+                               $titleObj = Title::makeTitle( $curRow->cur_namespace, $curRow->cur_title );
+                               $title = $titleObj->getPrefixedDBkey();
+                               output( $title );
+                               # Update searchindex
+                               $u = new SearchUpdate( $row->rc_cur_id, $curRow->cur_title, $curRow->cur_text );
+                               $u->doUpdate();
+                               output( "\n" );
+                       }
+               }
+       }
+       
+       # Unlock searchindex
+       if ( $maxLockTime ) {
+               unlockSearchindex();
+       }
+       output( "Done\n" );
+}
+
+function lockSearchindex( &$db ) {
+       $dbw =& wfGetDB( DB_MASTER );
+       extract( $dbw->tableNames( 'searchindex', 'cur', 'interwiki' ) );
+       $dbw->query( "LOCK TABLES $searchindex LOW_PRIORITY WRITE, $cur READ, $interwiki READ" );
+}
+
+function unlockSearchindex() {
+       $dbw =& wfGetDB( DB_MASTER );
+       $dbw->query( "UNLOCK TABLES" );
+}
+
+# Unlock and lock again
+# Since the lock is low-priority, queued reads will be able to complete
+function relockSearchindex() {
+       unlockSearchindex();
+       lockSearchindex();
+}
+
+function output( $text ) {
+       global $wgQuiet;
+       if ( !$wgQuiet ) {
+               print $text;
+       }
+}
+
+?>
diff --git a/maintenance/updateSearchIndex.php b/maintenance/updateSearchIndex.php
new file mode 100644 (file)
index 0000000..c4bc483
--- /dev/null
@@ -0,0 +1,57 @@
+<?php
+/**
+ * Script for periodic off-peak updating of the search index
+ *
+ * Usage: php updateSearchIndex.php [-s START] [-e END] [-p POSFILE] [-l LOCKTIME] [-q]
+ * Where START is the starting timestamp
+ * END is the ending timestamp
+ * POSFILE is a file to load timestamps from and save them to, searchUpdate.pos by default
+ * LOCKTIME is how long the searchindex and cur tables will be locked for
+ * -q means quiet
+ *
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+
+/** */
+$optionsWithArgs = array( 's', 'e', 'p' );
+
+require_once( 'commandLine.inc' );
+require_once( 'updateSearchIndex.inc' );
+
+if ( isset( $options['p'] ) ) {
+       $posFile = $options['p'];
+} else {
+       $posFile = 'searchUpdate.pos';
+}
+
+if ( isset( $options['e'] ) ) {
+       $end = $options['e'];
+} else {
+       $end = wfTimestampNow();
+}
+
+if ( isset( $options['s'] ) ) {
+       $start = $options['s'];
+} else {
+       $start = @file_get_contents( $posFile );
+       if ( !$start ) {
+               $start = wfTimestamp( TS_MW, time() - 86400 );
+       } 
+}
+
+if ( isset( $options['l'] ) ) {
+       $lockTime = $options['l'];
+} else {
+       $lockTime = 20;
+}
+
+$quiet = (bool)(@$options['q']);
+
+updateSearchIndex( $start, $end, $lockTime, $quiet );
+
+$file = fopen( $posFile, 'w' );
+fwrite( $file, $end );
+fclose( $file );
+
+?>
diff --git a/maintenance/updateSpecialPages.php b/maintenance/updateSpecialPages.php
new file mode 100644 (file)
index 0000000..3605362
--- /dev/null
@@ -0,0 +1,89 @@
+<?php
+
+# Run this script periodically if you have miser mode enabled, to refresh the caches
+$options = array('only','help');
+
+require_once( 'commandLine.inc' );
+
+require_once( 'SpecialPage.php' );
+require_once( 'QueryPage.php' );
+
+if($options['help']) {
+       print "usage:updateSpecialPages.php [--help] [--only=page]\n";
+       print "  --help      : this help message\n";
+       print "  --only=page : only update 'page'. Ex: --only=BrokenRedirects\n";
+       die();
+}
+
+$wgOut->disable();
+$dbw =& wfGetDB( DB_MASTER );
+
+foreach ( $wgQueryPages as $page ) {
+       list( $class, $special ) = $page;
+
+       $specialObj = SpecialPage::getPage( $special );
+       if ( !$specialObj ) {
+               print "No such special page: $special\n";
+               exit;
+       }
+       $file = $specialObj->getFile();
+       if ( $file ) {
+               require_once( $file );
+       }
+       $queryPage = new $class;
+
+       if( !(isset($options['only'])) or ($options['only'] == $queryPage->getName()) ) {
+       printf( '%-30s',  $special );
+
+       if ( $queryPage->isExpensive() ) {
+               $t1 = explode( ' ', microtime() );
+               # Do the query
+               $num = $queryPage->recache();
+               $t2 = explode( ' ', microtime() );
+
+               if ( $num === false ) {
+                       print "FAILED: database error\n";
+               } else {
+                       print "got $num rows in ";
+
+                       $elapsed = ($t2[0] - $t1[0]) + ($t2[1] - $t1[1]);
+                       $hours = intval( $elapsed / 3600 );
+                       $minutes = intval( $elapsed % 3600 / 60 );
+                       $seconds = $elapsed - $hours * 3600 - $minutes * 60;
+                       if ( $hours ) {
+                               print $hours . 'h ';
+                       }
+                       if ( $minutes ) {
+                               print $minutes . 'm ';
+                       }
+                       printf( "%.2fs\n", $seconds );
+               }
+
+               # Reopen any connections that have closed
+               if ( !$wgLoadBalancer->pingAll())  {
+                       print "\n";
+                       do {
+                               print "Connection failed, reconnecting in 10 seconds...\n";
+                               sleep(10);
+                       } while ( !$wgLoadBalancer->pingAll() );
+                       print "Reconnected\n\n";
+               } else {
+                       # Commit the results
+                       $dbw->immediateCommit();
+               }
+
+               # Wait for the slave to catch up
+               $slaveDB =& wfGetDB( DB_SLAVE, array('QueryPage::recache', 'vslow' ) );
+               while( $slaveDB->getLag() > 600 ) {
+                       print "Slave lagged, waiting...\n";
+                       sleep(30);
+
+               }
+
+       } else {
+               print "cheap, skipped\n";
+       }
+       }
+}
+
+?>
diff --git a/maintenance/updaters.inc b/maintenance/updaters.inc
new file mode 100644 (file)
index 0000000..4ebda93
--- /dev/null
@@ -0,0 +1,701 @@
+<?php
+/**
+ * @package MediaWiki
+ * @subpackage Maintenance
+ */
+ /** */
+
+require_once 'convertLinks.inc';
+require_once 'InitialiseMessages.inc';
+require_once 'userDupes.inc';
+
+$wgRenamedTables = array(
+#           from             to                  patch file
+#      array( 'group',         'groups',           'patch-rename-group.sql' ),
+);
+
+$wgNewTables = array(
+#            table          patch file (in maintenance/archives)
+       array( 'hitcounter',    'patch-hitcounter.sql' ),
+       array( 'querycache',    'patch-querycache.sql' ),
+       array( 'objectcache',   'patch-objectcache.sql' ),
+       array( 'categorylinks', 'patch-categorylinks.sql' ),
+       array( 'logging',       'patch-logging.sql' ),
+       array( 'validate',      'patch-validate.sql' ),
+       array( 'user_newtalk',  'patch-usernewtalk2.sql' ),
+       array( 'transcache',    'patch-transcache.sql' ),
+       array( 'trackbacks',    'patch-trackbacks.sql' ),
+);
+
+$wgNewFields = array(
+#           table            field             patch file (in maintenance/archives)
+       array( 'ipblocks',      'ipb_id',           'patch-ipblocks.sql' ),
+       array( 'ipblocks',      'ipb_expiry',       'patch-ipb_expiry.sql' ),
+       array( 'recentchanges', 'rc_type',          'patch-rc_type.sql' ),
+       array( 'recentchanges', 'rc_ip',            'patch-rc_ip.sql' ),
+       array( 'recentchanges', 'rc_id',            'patch-rc_id.sql' ),
+       array( 'recentchanges', 'rc_patrolled',     'patch-rc-patrol.sql' ),
+       array( 'user',          'user_real_name',   'patch-user-realname.sql' ),
+       array( 'user',          'user_token',       'patch-user_token.sql' ),
+       array( 'user',          'user_email_token', 'patch-user_email_token.sql' ),
+       array( 'logging',       'log_params',       'patch-log_params.sql' ),
+       array( 'archive',       'ar_rev_id',        'patch-archive-rev_id.sql' ),
+       array( 'archive',       'ar_text_id',       'patch-archive-text_id.sql' ),
+       array( 'page',          'page_len',         'patch-page_len.sql' ),
+       array( 'revision',      'rev_deleted',      'patch-rev_deleted.sql' ),
+       array( 'image',         'img_width',        'patch-img_width.sql' ),
+       array( 'image',         'img_metadata',     'patch-img_metadata.sql' ),
+       array( 'image',         'img_media_type',   'patch-img_media_type.sql' ),
+       array( 'validate',      'val_ip',           'patch-val_ip.sql' ),
+       array( 'site_stats',    'ss_total_pages',   'patch-ss_total_articles.sql' ),
+       array( 'interwiki',     'iw_trans',         'patch-interwiki-trans.sql' ),
+);
+
+function rename_table( $from, $to, $patch ) {
+       global $wgDatabase;
+       if ( $wgDatabase->tableExists( $from ) ) {
+               if ( $wgDatabase->tableExists( $to ) ) {
+                       echo "...can't move table $from to $to, $to already exists.\n";
+               } else {
+                       echo "Moving table $from to $to...";
+                       dbsource( "maintenance/archives/$patch", $wgDatabase );
+                       echo "ok\n";
+               }
+       } else {
+               // Source table does not exist
+               // Renames are done before creations, so this is typical for a new installation
+               // Ignore silently
+       }
+}
+
+function add_table( $name, $patch ) {
+       global $wgDatabase;
+       if ( $wgDatabase->tableExists( $name ) ) {
+               echo "...$name table already exists.\n";
+       } else {
+               echo "Creating $name table...";
+               dbsource( "maintenance/archives/$patch", $wgDatabase );
+               echo "ok\n";
+       }
+}
+
+function add_field( $table, $field, $patch ) {
+       global $wgDatabase;
+       if ( !$wgDatabase->tableExists( $table ) ) {
+               echo "...$table table does not exist, skipping new field patch\n";
+       } elseif ( $wgDatabase->fieldExists( $table, $field ) ) {
+               echo "...have $field field in $table table.\n";
+       } else {
+               echo "Adding $field field to table $table...";
+               dbsource( "maintenance/archives/$patch" , $wgDatabase );
+               echo "ok\n";
+       }
+}
+
+function do_revision_updates() {
+       global $wgSoftwareRevision;
+       if ( $wgSoftwareRevision < 1001 ) {
+               update_passwords();
+       }
+}
+
+function update_passwords() {
+       wfDebugDieBacktrace( "This function needs to be updated or removed.\n" );
+       
+       global $wgDatabase;
+       $fname = "Update script: update_passwords()";
+       print "\nIt appears that you need to update the user passwords in your\n" .
+         "database. If you have already done this (if you've run this update\n" .
+         "script once before, for example), doing so again will make all your\n" .
+         "user accounts inaccessible, so be sure you only do this once.\n" .
+         "Update user passwords? (yes/no)";
+
+       $resp = readconsole();
+    if ( ! ( "Y" == $resp{0} || "y" == $resp{0} ) ) { return; }
+
+       $sql = "SELECT user_id,user_password FROM user";
+       $source = $wgDatabase->query( $sql, $fname );
+
+       while ( $row = $wgDatabase->fetchObject( $source ) ) {
+               $id = $row->user_id;
+               $oldpass = $row->user_password;
+               $newpass = md5( "{$id}-{$oldpass}" );
+
+               $sql = "UPDATE user SET user_password='{$newpass}' " .
+                 "WHERE user_id={$id}";
+               $wgDatabase->query( $sql, $fname );
+       }
+}
+
+function do_interwiki_update() {
+       # Check that interwiki table exists; if it doesn't source it
+       global $wgDatabase;
+       if( $wgDatabase->tableExists( "interwiki" ) ) {
+               echo "...already have interwiki table\n";
+               return true;
+       }
+       echo "Creating interwiki table: ";
+       dbsource( "maintenance/archives/patch-interwiki.sql" );
+       echo "ok\n";
+       echo "Adding default interwiki definitions: ";
+       dbsource( "maintenance/interwiki.sql" );
+       echo "ok\n";
+}
+
+function do_index_update() {
+       # Check that proper indexes are in place
+       global $wgDatabase;
+       $meta = $wgDatabase->fieldInfo( "recentchanges", "rc_timestamp" );
+       if( $meta->multiple_key == 0 ) {
+               echo "Updating indexes to 20031107: ";
+               dbsource( "maintenance/archives/patch-indexes.sql" );
+               echo "ok\n";
+               return true;
+       }
+       echo "...indexes seem up to 20031107 standards\n";
+       return false;
+}
+
+function do_image_name_unique_update() {
+       global $wgDatabase;
+       if( $wgDatabase->indexExists( 'image', 'PRIMARY' ) ) {
+               echo "...image primary key already set.\n";
+       } else {
+               echo "Making img_name the primary key... ";
+               dbsource( "maintenance/archives/patch-image_name_primary.sql", $wgDatabase );
+               echo "ok\n";
+       }
+}
+
+function do_watchlist_update() {
+       global $wgDatabase;
+       $fname = 'do_watchlist_update';
+       if( $wgDatabase->fieldExists( 'watchlist', 'wl_notificationtimestamp' ) ) {
+               echo "The watchlist table is already set up for email notification.\n";
+       } else {
+               echo "Adding wl_notificationtimestamp field for email notification management.";
+               /* ALTER TABLE watchlist ADD (wl_notificationtimestamp varchar(14) binary NOT NULL default '0'); */
+               dbsource( "maintenance/archives/patch-email-notification.sql", $wgDatabase );
+               echo "ok\n";
+       }
+       # Check if we need to add talk page rows to the watchlist
+       $talk = $wgDatabase->selectField( 'watchlist', 'count(*)', 'wl_namespace & 1', $fname );
+       $nontalk = $wgDatabase->selectField( 'watchlist', 'count(*)', 'NOT (wl_namespace & 1)', $fname );
+       if ( $talk != $nontalk ) {
+               echo "Adding missing watchlist talk page rows... ";
+               flush();
+
+               $wgDatabase->insertSelect( 'watchlist', 'watchlist', 
+                       array(
+                               'wl_user' => 'wl_user',
+                               'wl_namespace' => 'wl_namespace | 1',
+                               'wl_title' => 'wl_title',
+                               'wl_notificationtimestamp' => 'wl_notificationtimestamp'
+                       ), array( 'NOT (wl_namespace & 1)' ), $fname, 'IGNORE' );
+               echo "ok\n";
+       } else {
+               echo "...watchlist talk page rows already present\n";
+       }
+}
+
+function do_copy_newtalk_to_watchlist() {
+       global $wgDatabase;
+       global $wgCommandLineMode;      # this needs to be saved while getID() and getName() are called
+
+       $res = $wgDatabase->safeQuery( 'SELECT user_id, user_ip FROM !',
+               $wgDatabase->tableName( 'user_newtalk' ) );
+       $num_newtalks=$wgDatabase->numRows($res);
+       echo "Now converting ".$num_newtalks." user_newtalk entries to watchlist table entries ... \n";
+
+       $user = new User();
+       for ( $i = 1; $i <= $num_newtalks; $i++ ) {
+               $wluser = $wgDatabase->fetchObject( $res );
+               if ($wluser->user_id == 0) { # anonymous users ... have IP numbers as "names"
+                       if ($user->isIP($wluser->user_ip)) { # do only if it really looks like an IP number (double checked)
+                               $wgDatabase->replace( 'watchlist',
+                                       array(array('wl_user','wl_namespace', 'wl_title', 'wl_notificationtimestamp' )),
+                                         array('wl_user'                       => 0,
+                                               'wl_namespace'                  => NS_USER_TALK,
+                                               'wl_title'                      => $wluser->user_ip,
+                                               'wl_notificationtimestamp'      => '19700101000000'
+                                               ), 'updaters.inc::do_watchlist_update2'
+                                       );
+                       }
+               } else { # normal users ... have user_ids
+                       $user->setID($wluser->user_id);
+                       $wgDatabase->replace( 'watchlist',
+                               array(array('wl_user','wl_namespace', 'wl_title', 'wl_notificationtimestamp' )),
+                                 array('wl_user'                       => $user->getID(),
+                                       'wl_namespace'                  => NS_USER_TALK,
+                                       'wl_title'                      => $user->getName(),
+                                       'wl_notificationtimestamp'      => '19700101000000'
+                                       ), 'updaters.inc::do_watchlist_update3'
+                               );
+               }
+       }
+       echo "Done.\n";
+}
+
+
+function do_user_update() {
+       global $wgDatabase;
+       if( $wgDatabase->fieldExists( 'user', 'user_emailauthenticationtimestamp' ) ) {
+               echo "User table contains old email authentication field. Dropping... ";
+               dbsource( "maintenance/archives/patch-email-authentication.sql", $wgDatabase );
+               echo "ok\n";
+       } else {
+               echo "...user table does not contain old email authentication field.\n";
+       }
+}
+
+/**
+ * 1.4 betas were missing the 'binary' marker from logging.log_title,
+ * which causes a collation mismatch error on joins in MySQL 4.1.
+ */
+function do_logging_encoding() {
+       global $wgDatabase;
+       $logging = $wgDatabase->tableName( 'logging' );
+       $res = $wgDatabase->query( "SELECT log_title FROM $logging LIMIT 0" );
+       $flags = explode( ' ', mysql_field_flags( $res, 0 ) );
+       $wgDatabase->freeResult( $res );
+       
+       if( in_array( 'binary', $flags ) ) {
+               echo "Logging table has correct title encoding.\n";
+       } else {
+               echo "Fixing title encoding on logging table... ";
+               dbsource( 'maintenance/archives/patch-logging-title.sql', $wgDatabase );
+               echo "ok\n";
+       }
+}
+
+function do_schema_restructuring() {
+       global $wgDatabase;
+       $fname="do_schema_restructuring";
+       if ( $wgDatabase->tableExists( 'page' ) ) {
+               echo "...page table already exists.\n";
+       } else {
+               echo "...converting from cur/old to page/revision/text DB structure.\n"; flush();
+               echo wfTimestamp();
+               echo "......checking for duplicate entries.\n"; flush();
+               
+               extract( $wgDatabase->tableNames( 'cur', 'old', 'page', 'revision', 'text' ) );
+
+               $rows = $wgDatabase->query( "SELECT cur_title, cur_namespace, COUNT(cur_namespace) AS c
+                               FROM $cur GROUP BY cur_title, cur_namespace HAVING c>1", $fname );
+
+               if ( $wgDatabase->numRows( $rows ) > 0 ) {
+                       echo wfTimestamp();
+                       echo "......<b>Found duplicate entries</b>\n";
+                       echo ( sprintf( "<b>      %-60s %3s %5s</b>\n", 'Title', 'NS', 'Count' ) );
+                       while ( $row = $wgDatabase->fetchObject( $rows ) ) {
+                               if ( ! isset( $duplicate[$row->cur_namespace] ) ) {
+                                       $duplicate[$row->cur_namespace] = array();
+                               }
+                               $duplicate[$row->cur_namespace][] = $row->cur_title;
+                               echo ( sprintf( "      %-60s %3s %5s\n", $row->cur_title, $row->cur_namespace, $row->c ) );
+                       }
+                       $sql = "SELECT cur_title, cur_namespace, cur_id, cur_timestamp FROM $cur WHERE ";
+                       $firstCond = true; 
+                       foreach ( $duplicate as $ns => $titles ) {
+                               if ( $firstCond ) {
+                                       $firstCond = false;
+                               } else {
+                                       $sql .= ' OR ';
+                               }
+                               $sql .= "( cur_namespace = {$ns} AND cur_title in (";
+                               $first = true;
+                               foreach ( $titles as $t ) {
+                                       if ( $first ) {
+                                               $sql .= $wgDatabase->addQuotes( $t );
+                                               $first = false;
+                                       } else {
+                                               $sql .= ', ' . $wgDatabase->addQuotes( $t );
+                                       }
+                               }
+                               $sql .= ") ) \n";
+                       }
+                       # By sorting descending, the most recent entry will be the first in the list.
+                       # All following entries will be deleted by the next while-loop.
+                       $sql .= 'ORDER BY cur_namespace, cur_title, cur_timestamp DESC';
+
+                       $rows = $wgDatabase->query( $sql, $fname );
+
+                       $prev_title = $prev_namespace = false;
+                       $deleteId = array();
+
+                       while ( $row = $wgDatabase->fetchObject( $rows ) ) {
+                               if ( $prev_title == $row->cur_title && $prev_namespace == $row->cur_namespace ) {
+                                       $deleteId[] = $row->cur_id;
+                               }
+                               $prev_title     = $row->cur_title;
+                               $prev_namespace = $row->cur_namespace;
+                       }
+                       $sql = "DELETE FROM $cur WHERE cur_id IN ( " . join( ',', $deleteId ) . ')';
+                       $rows = $wgDatabase->query( $sql, $fname );
+                       echo wfTimestamp();
+                       echo "......<b>Deleted</b> ".$wgDatabase->affectedRows()." records.\n";
+               }
+               
+
+               echo wfTimestamp();
+               echo "......Creating tables.\n";
+               $wgDatabase->query("CREATE TABLE $page (
+                       page_id int(8) unsigned NOT NULL auto_increment,
+                       page_namespace int NOT NULL,
+                       page_title varchar(255) binary NOT NULL,
+                       page_restrictions tinyblob NOT NULL default '',
+                       page_counter bigint(20) unsigned NOT NULL default '0',
+                       page_is_redirect tinyint(1) unsigned NOT NULL default '0',
+                       page_is_new tinyint(1) unsigned NOT NULL default '0',
+                       page_random real unsigned NOT NULL,
+                       page_touched char(14) binary NOT NULL default '',
+                       page_latest int(8) unsigned NOT NULL,
+                       page_len int(8) unsigned NOT NULL,
+
+                       PRIMARY KEY page_id (page_id),
+                       UNIQUE INDEX name_title (page_namespace,page_title),
+                       INDEX (page_random),
+                       INDEX (page_len)
+                       ) TYPE=InnoDB", $fname );
+               $wgDatabase->query("CREATE TABLE $revision (
+                       rev_id int(8) unsigned NOT NULL auto_increment,
+                       rev_page int(8) unsigned NOT NULL,
+                       rev_comment tinyblob NOT NULL default '',
+                       rev_user int(5) unsigned NOT NULL default '0',
+                       rev_user_text varchar(255) binary NOT NULL default '',
+                       rev_timestamp char(14) binary NOT NULL default '',
+                       rev_minor_edit tinyint(1) unsigned NOT NULL default '0',
+                       rev_deleted tinyint(1) unsigned NOT NULL default '0',
+  
+                       PRIMARY KEY rev_page_id (rev_page, rev_id),
+                       UNIQUE INDEX rev_id (rev_id),
+                       INDEX rev_timestamp (rev_timestamp),
+                       INDEX page_timestamp (rev_page,rev_timestamp),
+                       INDEX user_timestamp (rev_user,rev_timestamp),
+                       INDEX usertext_timestamp (rev_user_text,rev_timestamp)
+                       ) TYPE=InnoDB", $fname );
+
+               echo wfTimestamp();
+               echo "......Locking tables.\n";
+               $wgDatabase->query( "LOCK TABLES $page WRITE, $revision WRITE, $old WRITE, $cur WRITE", $fname );
+
+               $maxold = intval( $wgDatabase->selectField( 'old', 'max(old_id)', '', $fname ) );
+               echo wfTimestamp();
+               echo "......maxold is {$maxold}\n";
+
+               echo wfTimestamp();
+               global $wgLegacySchemaConversion;
+               if( $wgLegacySchemaConversion ) {
+                       // Create HistoryBlobCurStub entries.
+                       // Text will be pulled from the leftover 'cur' table at runtime.
+                       echo "......Moving metadata from cur; using blob references to text in cur table.\n";
+                       $cur_text = "concat('O:18:\"historyblobcurstub\":1:{s:6:\"mCurId\";i:',cur_id,';}')";
+                       $cur_flags = "'object'";
+               } else {
+                       // Copy all cur text in immediately: this may take longer but avoids
+                       // having to keep an extra table around.
+                       echo "......Moving text from cur.\n";
+                       $cur_text = 'cur_text';
+                       $cur_flags = "''";
+               }
+               $wgDatabase->query( "INSERT INTO $old (old_namespace, old_title, old_text, old_comment, old_user, old_user_text,
+                               old_timestamp, old_minor_edit, old_flags)
+                       SELECT cur_namespace, cur_title, $cur_text, cur_comment, cur_user, cur_user_text, cur_timestamp, cur_minor_edit, $cur_flags
+                       FROM $cur", $fname );
+
+               echo wfTimestamp();
+               echo "......Setting up revision table.\n";
+               $wgDatabase->query( "INSERT INTO $revision (rev_id, rev_page, rev_comment, rev_user, rev_user_text, rev_timestamp,
+                               rev_minor_edit)
+                       SELECT old_id, cur_id, old_comment, old_user, old_user_text,
+                               old_timestamp, old_minor_edit
+                       FROM $old,$cur WHERE old_namespace=cur_namespace AND old_title=cur_title", $fname );
+
+               echo wfTimestamp();
+               echo "......Setting up page table.\n";
+               $wgDatabase->query( "INSERT INTO $page (page_id, page_namespace, page_title, page_restrictions, page_counter,
+                               page_is_redirect, page_is_new, page_random, page_touched, page_latest, page_len)
+                       SELECT cur_id, cur_namespace, cur_title, cur_restrictions, cur_counter, cur_is_redirect, cur_is_new,
+                               cur_random, cur_touched, rev_id, LENGTH(cur_text)
+                       FROM $cur,$revision
+                       WHERE cur_id=rev_page AND rev_timestamp=cur_timestamp AND rev_id > {$maxold}", $fname );
+
+               echo wfTimestamp();
+               echo "......Unlocking tables.\n";
+               $wgDatabase->query( "UNLOCK TABLES", $fname );
+
+               echo wfTimestamp();
+               echo "......Renaming old.\n";
+               $wgDatabase->query( "ALTER TABLE $old RENAME TO $text", $fname );
+               
+               echo wfTimestamp();
+               echo "...done.\n";
+       }
+}
+
+function do_inverse_timestamp() {
+       global $wgDatabase;
+       $fname="do_schema_restructuring";
+       if( $wgDatabase->fieldExists( 'revision', 'inverse_timestamp' ) ) {
+               echo "Removing revision.inverse_timestamp and fixing indexes... ";
+               dbsource( 'maintenance/archives/patch-inverse_timestamp.sql', $wgDatabase );
+               echo "ok\n";
+       } else {
+               echo "revision timestamp indexes already up to 2005-03-13\n";
+       }
+}
+
+function do_text_id() {
+       global $wgDatabase;
+       if( $wgDatabase->fieldExists( 'revision', 'rev_text_id' ) ) {
+               echo "...rev_text_id already in place.\n";
+       } else {
+               echo "Adding rev_text_id field... ";
+               dbsource( 'maintenance/archives/patch-rev_text_id.sql', $wgDatabase );
+               echo "ok\n";
+       }
+}
+
+function do_namespace_size() {
+       $tables = array(
+               'page'          => 'page',
+               'archive'       => 'ar',
+               'recentchanges' => 'rc',
+               'watchlist'     => 'wl',
+               'querycache'    => 'qc',
+               'logging'       => 'log',
+       );
+       foreach( $tables as $table => $prefix ) {
+               do_namespace_size_on( $table, $prefix );
+               flush();
+       }
+}
+
+function do_namespace_size_on( $table, $prefix ) {
+       global $wgDatabase;
+       $field = $prefix . '_namespace';
+       
+       $tablename = $wgDatabase->tableName( $table );
+       $result = $wgDatabase->query( "SHOW COLUMNS FROM $tablename LIKE '$field'" );
+       $info = $wgDatabase->fetchObject( $result );
+       $wgDatabase->freeResult( $result );
+       
+       if( substr( $info->Type, 0, 3 ) == 'int' ) {
+               echo "...$field is already a full int ($info->Type).\n";
+       } else {
+               echo "Promoting $field from $info->Type to int... ";
+               
+               $sql = "ALTER TABLE $tablename MODIFY $field int NOT NULL";
+               $wgDatabase->query( $sql );
+               
+               echo "ok\n";
+       }
+}
+
+function do_pagelinks_update() {
+       global $wgDatabase;
+       if( $wgDatabase->tableExists( 'pagelinks' ) ) {
+               echo "...already have pagelinks table.\n";
+       } else {
+               echo "Converting links and brokenlinks tables to pagelinks... ";
+               dbsource( "maintenance/archives/patch-pagelinks.sql", $wgDatabase );
+               echo "ok\n";
+               flush();
+               
+               global $wgCanonicalNamespaceNames;
+               foreach( $wgCanonicalNamespaceNames as $ns => $name ) {
+                       if( $ns != 0 ) {
+                               do_pagelinks_namespace( $ns );
+                       }
+               }
+       }
+}
+
+function do_pagelinks_namespace( $namespace ) {
+       global $wgDatabase, $wgContLang;
+       
+       $ns = IntVal( $namespace );
+       echo "Cleaning up broken links for namespace $ns... ";
+       
+       $pagelinks = $wgDatabase->tableName( 'pagelinks' );
+       $name = $wgContLang->getNsText( $ns );
+       $prefix = $wgDatabase->strencode( $name );
+       $likeprefix = str_replace( '_', '\\_', $prefix);
+       
+       $sql = "UPDATE $pagelinks
+                  SET pl_namespace=$ns,
+                      pl_title=TRIM(LEADING '$prefix:' FROM pl_title)
+                WHERE pl_namespace=0
+                  AND pl_title LIKE '$likeprefix:%'";
+       
+       $wgDatabase->query( $sql, 'do_pagelinks_namespace' );
+       echo "ok\n";
+}
+
+function do_drop_img_type() {
+       global $wgDatabase;
+       
+       if( $wgDatabase->fieldExists( 'image', 'img_type' ) ) {
+               echo "Dropping unused img_type field in image table... ";
+               dbsource( "maintenance/archives/patch-drop_img_type.sql", $wgDatabase );
+               echo "ok\n";
+       } else {
+               echo "No img_type field in image table; Good.\n";
+       }
+}
+
+function do_old_links_update() {
+       global $wgDatabase;
+       if( $wgDatabase->tableExists( 'pagelinks' ) ) {
+               echo "Already have pagelinks; skipping old links table updates.\n";
+       } else {
+               convertLinks(); flush();
+       }
+}
+
+function do_user_unique_update() {
+       global $wgDatabase;
+       $duper = new UserDupes( $wgDatabase );
+       if( $duper->hasUniqueIndex() ) {
+               echo "Already have unique user_name index.\n";
+       } else {
+               if( !$duper->clearDupes() ) {
+                       echo "WARNING: This next step will probably fail due to unfixed duplicates...\n";
+               }
+               echo "Adding unique index on user_name... ";
+               dbsource( 'maintenance/archives/patch-user_nameindex.sql', $wgDatabase );
+               echo "ok\n";
+       }
+}
+
+function do_user_groups_update() {
+       $fname = 'do_user_groups_update';
+       global $wgDatabase;
+       
+       if( $wgDatabase->tableExists( 'user_groups' ) ) {
+               echo "...user_groups table already exists.\n";
+               return do_user_groups_reformat();
+       }
+       
+       echo "Adding user_groups table... ";
+       dbsource( 'maintenance/archives/patch-user_groups.sql', $wgDatabase );
+       echo "ok\n";
+       
+       if( !$wgDatabase->tableExists( 'user_rights' ) ) {
+               if( $wgDatabase->fieldExists( 'user', 'user_rights' ) ) {
+                       echo "Upgrading from a 1.3 or older database? Breaking out user_rights for conversion...";
+                       dbsource( 'maintenance/archives/patch-user_rights.sql', $wgDatabase );
+                       echo "ok\n";
+               } else {
+                       echo "*** WARNING: couldn't locate user_rights table or field for upgrade.\n";
+                       echo "*** You may need to manually configure some sysops by manipulating\n";
+                       echo "*** the user_groups table.\n";
+                       return;
+               }
+       }
+       
+       echo "Converting user_rights table to user_groups... ";
+       $result = $wgDatabase->select( 'user_rights',
+               array( 'ur_user', 'ur_rights' ),
+               array( "ur_rights != ''" ),
+               $fname );
+       
+       while( $row = $wgDatabase->fetchObject( $result ) ) {
+               $groups = array_unique(
+                       array_map( 'trim',
+                               explode( ',', $row->ur_rights ) ) );
+               
+               foreach( $groups as $group ) {
+                       $wgDatabase->insert( 'user_groups',
+                               array(
+                                       'ug_user'  => $row->ur_user,
+                                       'ug_group' => $group ),
+                               $fname );
+               }
+       }
+       $wgDatabase->freeResult( $result );
+       echo "ok\n";
+}
+
+function do_user_groups_reformat() {
+       # Check for bogus formats from previous 1.5 alpha code.
+       global $wgDatabase;
+       $info = $wgDatabase->fieldInfo( 'user_groups', 'ug_group' );
+       
+       if( $info->type == 'int' ) {
+               $oldug = $wgDatabase->tableName( 'user_groups' );
+               $newug = $wgDatabase->tableName( 'user_groups_bogus' );
+               echo "user_groups is in bogus intermediate format. Renaming to $newug... ";
+               $wgDatabase->query( "ALTER TABLE $oldug RENAME TO $newug" );
+               echo "ok\n";
+               
+               echo "Re-adding fresh user_groups table... ";
+               dbsource( 'maintenance/archives/patch-user_groups.sql', $wgDatabase );
+               echo "ok\n";
+               
+               echo "***\n";
+               echo "*** WARNING: You will need to manually fix up user permissions in the user_groups\n";
+               echo "*** table. Old 1.5 alpha versions did some pretty funky stuff...\n";
+               echo "***\n";
+       } else {
+               echo "...user_groups is in current format.\n";
+       }
+       
+}
+
+function do_all_updates() {
+       global $wgNewTables, $wgNewFields, $wgRenamedTables, $wgSharedDB, $wgDBname;
+       
+       $doUser = !$wgSharedDB || $wgSharedDB == $wgDBname;
+
+       # Rename tables
+       foreach ( $wgRenamedTables as $tableRecord ) {
+               rename_table( $tableRecord[0], $tableRecord[1], $tableRecord[2] );
+       }
+
+       # Add missing tables
+       foreach ( $wgNewTables as $tableRecord ) {
+               add_table( $tableRecord[0], $tableRecord[1] );
+               flush();
+       }
+
+       # Add missing fields
+       foreach ( $wgNewFields as $fieldRecord ) {
+               # Don't update shared DB
+               if ( $doUser || $fieldRecord[0] != 'user') {
+                       add_field( $fieldRecord[0], $fieldRecord[1], $fieldRecord[2] );
+               }
+               flush();
+       }
+       
+       # Do schema updates which require special handling
+       do_interwiki_update(); flush();
+       do_index_update(); flush();
+       do_old_links_update(); flush();
+       do_image_name_unique_update(); flush();
+       do_watchlist_update(); flush();
+       if ( $doUser ) {
+               do_user_update(); flush();
+       }
+###### do_copy_newtalk_to_watchlist(); flush();
+       do_logging_encoding(); flush();
+       
+       do_schema_restructuring(); flush();
+       do_inverse_timestamp(); flush();
+       do_text_id(); flush();
+       do_namespace_size(); flush();
+       
+       do_pagelinks_update(); flush();
+       
+       do_drop_img_type(); flush();
+       
+       if ( $doUser ) {
+               do_user_unique_update(); flush();
+       }
+       do_user_groups_update(); flush();
+       
+       initialiseMessages(); flush();
+}
+
+?>
diff --git a/maintenance/upgrade1_5.php b/maintenance/upgrade1_5.php
new file mode 100644 (file)
index 0000000..a269c33
--- /dev/null
@@ -0,0 +1,24 @@
+<?php
+
+// Alternate 1.4 -> 1.5 schema upgrade
+// This does only the main tables + UTF-8
+// and is designed to allow upgrades to interleave
+// with other updates on the replication stream so
+// that large wikis can be upgraded without disrupting
+// other services.
+//
+// Note: this script DOES NOT apply every update, nor
+// will it probably handle much older versions, etc.
+// Run this, FOLLOWED BY update.php, for upgrading
+// from 1.4.5 release to 1.5.
+
+$options = array( 'step', 'noimages' );
+
+require_once( 'commandLine.inc' );
+require_once( 'FiveUpgrade.inc' );
+
+$upgrade = new FiveUpgrade();
+$step = isset( $options['step'] ) ? $options['step'] : null;
+$upgrade->upgrade( $step );
+
+?>
diff --git a/maintenance/userDupes.inc b/maintenance/userDupes.inc
new file mode 100644 (file)
index 0000000..377d1bc
--- /dev/null
@@ -0,0 +1,328 @@
+<?php
+# Copyright (C) 2005 Brion Vibber <brion@pobox.com>
+# http://www.mediawiki.org/
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or 
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# http://www.gnu.org/copyleft/gpl.html
+
+/**
+ * Look for duplicate user table entries and optionally prune them.
+ */
+class UserDupes {
+       var $db;
+       var $reassigned;
+       var $trimmed;
+       var $failed;
+       
+       function UserDupes( &$database ) {
+               $this->db =& $database;
+       }
+       
+       /**
+        * Check if this database's user table has already had a unique
+        * user_name index applied.
+        * @return bool
+        */
+       function hasUniqueIndex() {
+               $fname = 'UserDupes::hasUniqueIndex';
+               $info = $this->db->indexInfo( 'user', 'user_name', $fname );
+               if( !$info ) {
+                       echo "WARNING: doesn't seem to have user_name index at all!\n";
+                       return false;
+               }
+               
+               # Confusingly, 'Non_unique' is 0 for *unique* indexes,
+               # and 1 for *non-unique* indexes. Pass the crack, MySQL,
+               # it's obviously some good stuff!
+               return ( $info->Non_unique == 0 );
+       }
+       
+       /**
+        * Checks the database for duplicate user account records
+        * and remove them in preparation for application of a unique
+        * index on the user_name field. Returns true if the table is
+        * clean or if duplicates have been resolved automatically.
+        *
+        * May return false if there are unresolvable problems.
+        * Status information will be echo'd to stdout.
+        *
+        * @return bool
+        */
+       function clearDupes() {
+               return $this->checkDupes( true );
+       }
+       
+       /**
+        * Checks the database for duplicate user account records
+        * in preparation for application of a unique index on the
+        * user_name field. Returns true if the table is clean or
+        * if duplicates can be resolved automatically.
+        *
+        * Returns false if there are duplicates and resolution was
+        * not requested. (If doing resolution, edits may be reassigned.)
+        * Status information will be echo'd to stdout.
+        *
+        * @param bool $doDelete pass true to actually remove things
+        *                       from the database; false to just check.
+        * @return bool
+        */
+       function checkDupes( $doDelete = false ) {
+               global $wgDBname;
+               
+               if( $this->hasUniqueIndex() ) {
+                       echo "$wgDBname already has a unique index on its user table.\n";
+                       return true;
+               }
+               
+               $this->lock();
+               
+               echo "Checking for duplicate accounts...\n";
+               $dupes = $this->getDupes();
+               $count = count( $dupes );
+               
+               echo "Found $count accounts with duplicate records on $wgDBname.\n";
+               $this->trimmed    = 0;
+               $this->reassigned = 0;
+               $this->failed     = 0;
+               foreach( $dupes as $name ) {
+                       $this->examine( $name, $doDelete );
+               }
+               
+               $this->unlock();
+               
+               echo "\n";
+               
+               if( $this->reassigned > 0 ) {
+                       if( $doDelete ) {
+                               echo "$this->reassigned duplicate accounts had edits reassigned to a canonical record id.\n";
+                       } else {
+                               echo "$this->reassigned duplicate accounts need to have edits reassigned.\n";
+                       }
+               }
+               
+               if( $this->trimmed > 0 ) {
+                       if( $doDelete ) {
+                               echo "$this->trimmed duplicate user records were deleted from $wgDBname.\n";
+                       } else {
+                               echo "$this->trimmed duplicate user accounts were found on $wgDBname which can be removed safely.\n";
+                       }
+               }
+               
+               if( $this->failed > 0 ) {
+                       echo "Something terribly awry; $this->failed duplicate accounts were not removed.\n";
+                       return false;
+               }
+               
+               if( $this->trimmed == 0 || $doDelete ) {
+                       echo "It is now safe to apply the unique index on user_name.\n";
+                       return true;
+               } else {
+                       echo "Run this script again with the --fix option to automatically delete them.\n";
+                       return false;
+               }
+       }
+       
+       /**
+        * We don't want anybody to mess with our stuff...
+        * @access private
+        */
+       function lock() {
+               $fname = 'UserDupes::lock';
+               if( $this->newSchema() ) {
+                       $set = array( 'user', 'revision' );
+               } else {
+                       $set = array( 'user', 'cur', 'old' );
+               }
+               $names = array_map( array( $this, 'lockTable' ), $set );
+               $tables = implode( ',', $names );
+               
+               $result = $this->db->query( "LOCK TABLES $tables", $fname );
+       }
+       
+       function lockTable( $table ) {
+               return $this->db->tableName( $table ) . ' WRITE';
+       }
+       
+       /**
+        * @return bool
+        * @access private
+        */
+       function newSchema() {
+               return class_exists( 'Revision' );
+       }
+       
+       /**
+        * @access private
+        */
+       function unlock() {
+               $fname = 'UserDupes::unlock';
+               $result = $this->db->query( "UNLOCK TABLES", $fname );
+       }
+       
+       /**
+        * Grab usernames for which multiple records are present in the database.
+        * @return array
+        * @access private
+        */
+       function getDupes() {
+               $fname = 'UserDupes::listDupes';
+               $user = $this->db->tableName( 'user' );
+               $result = $this->db->query(
+                        "SELECT user_name,COUNT(*) AS n
+                           FROM $user
+                       GROUP BY user_name
+                         HAVING n > 1", $fname );
+               
+               $list = array();
+               while( $row = $this->db->fetchObject( $result ) ) {
+                       $list[] = $row->user_name;
+               }
+               $this->db->freeResult( $result );
+               
+               return $list;
+       }
+       
+       /**
+        * Examine user records for the given name. Try to see which record
+        * will be the one that actually gets used, then check remaining records
+        * for edits. If the dupes have no edits, we can safely remove them.
+        * @param string $name
+        * @param bool $doDelete
+        * @access private
+        */
+       function examine( $name, $doDelete ) {
+               $fname = 'UserDupes::listDupes';
+               $result = $this->db->select( 'user',
+                       array( 'user_id' ),
+                       array( 'user_name' => $name ),
+                       $fname );
+               
+               $firstRow = $this->db->fetchObject( $result );
+               $firstId  = $firstRow->user_id;
+               echo "Record that will be used for '$name' is user_id=$firstId\n";
+               
+               while( $row = $this->db->fetchObject( $result ) ) {
+                       $dupeId = $row->user_id;
+                       echo "... dupe id $dupeId: ";
+                       $edits = $this->editCount( $dupeId );
+                       if( $edits > 0 ) {
+                               $this->reassigned++;
+                               echo "has $edits edits! ";
+                               if( $doDelete ) {
+                                       $this->reassignEdits( $dupeId, $firstId );
+                                       $newEdits = $this->editCount( $dupeId );
+                                       if( $newEdits == 0 ) {
+                                               echo "confirmed cleaned. ";
+                                       } else {
+                                               $this->failed++;
+                                               echo "WARNING! $newEdits remaining edits for $dupeId; NOT deleting user.\n";
+                                               continue;
+                                       }
+                               } else {
+                                       echo "(will need to reassign edits on fix)";
+                               }
+                       } else {
+                               echo "ok, no edits. ";
+                       }
+                       $this->trimmed++;
+                       if( $doDelete ) {
+                               $this->trimAccount( $dupeId );
+                       }
+                       echo "\n";
+               }
+               $this->db->freeResult( $result );
+       }
+       
+       /**
+        * Count the number of edits attributed to this user.
+        * Does not currently check log table or other things
+        * where it might show up...
+        * @param int $userid
+        * @return int
+        * @access private
+        */
+       function editCount( $userid ) {
+               if( $this->newSchema() ) {
+                       return $this->editCountOn( 'revision', 'rev_user', $userid );
+               } else {
+                       return $this->editCountOn( 'cur', 'cur_user', $userid ) +
+                               $this->editCountOn( 'old', 'old_user', $userid );
+               }
+       }
+       
+       /**
+        * Count the number of hits on a given table for this account.
+        * @param string $table
+        * @param string $field
+        * @param int $userid
+        * @return int
+        * @access private
+        */
+       function editCountOn( $table, $field, $userid ) {
+               $fname = 'UserDupes::editCountOn';
+               return IntVal( $this->db->selectField(
+                       $table,
+                       'COUNT(*)',
+                       array( $field => $userid ),
+                       $fname ) );
+       }
+       
+       /**
+        * @param int $from
+        * @param int $to
+        * @access private
+        */
+       function reassignEdits( $from, $to ) {
+               $set = $this->newSchema()
+                       ? array( 'revision' => 'rev_user' )
+                       : array( 'cur' => 'cur_user', 'old' => 'old_user' );
+               foreach( $set as $table => $field ) {
+                       $this->reassignEditsOn( $table, $field, $from, $to );
+               }
+       }
+       
+       /**
+        * @param string $table
+        * @param string $field
+        * @param int $from
+        * @param int $to
+        * @access private
+        */
+       function reassignEditsOn( $table, $field, $from, $to ) {
+               $fname = 'UserDupes::reassignEditsOn';
+               echo "reassigning on $table... ";
+               $result = $this->db->update( $table,
+                       array( $field => $to ),
+                       array( $field => $from ),
+                       $fname );
+               echo "ok. ";
+       }
+       
+       /**
+        * Remove a user account line.
+        * @param int $userid
+        * @access private
+        */
+       function trimAccount( $userid ) {
+               $fname = 'UserDupes::trimAccount';
+               echo "deleting...";
+               $this->db->delete( 'user', array( 'user_id' => $userid ), $fname );
+               echo " ok";
+       }
+       
+}
+
+
+?>
\ No newline at end of file
diff --git a/maintenance/userDupes.php b/maintenance/userDupes.php
new file mode 100644 (file)
index 0000000..8dca2b5
--- /dev/null
@@ -0,0 +1,41 @@
+<?php
+# Copyright (C) 2005 Brion Vibber <brion@pobox.com>
+# http://www.mediawiki.org/
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or 
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# http://www.gnu.org/copyleft/gpl.html
+
+$options = array( 'fix' );
+
+/** */
+require_once( 'commandLine.inc' );
+require_once( 'maintenance/userDupes.inc' );
+
+$wgTitle = Title::newFromText( 'Dupe user entry cleanup script' );
+
+$fix = isset( $options['fix'] );
+$dbw =& wfGetDB( DB_MASTER );
+$duper = new UserDupes( $dbw );
+$retval = $duper->checkDupes( $fix );
+
+if( $retval ) {
+       echo "\nLooks good!\n";
+       exit( 0 );
+} else {
+       echo "\nOh noeees\n";
+       exit( -1 );
+}
+
+?>
\ No newline at end of file
diff --git a/maintenance/userFunctions.inc b/maintenance/userFunctions.inc
new file mode 100644 (file)
index 0000000..c635de5
--- /dev/null
@@ -0,0 +1,91 @@
+<?php
+
+/**
+ * Support functions for dealing with user accounts at a database level
+ *
+ * @package MediaWiki
+ * @subpackage Maintenance
+ * @author Rob Church <robchur@gmail.com>
+ */
+
+/**
+ * Count the number of edits the specified user has made
+ *
+ * @param integer $user User ID
+ * @param bool $slave Whether or not a slave can be used
+ * @return integer
+ */
+function CountEdits( $user, $slave = true ) {
+       $dbw =& wfGetDB( $slave ? DB_SLAVE: DB_MASTER );
+       $res = $dbw->select( 'revision', 'COUNT(rev_id) AS count', array( 'rev_user' => $user ) );
+       $row = $dbw->fetchObject( $res );
+       return( $row->count );
+}
+
+/**
+ * Retrieve all valid user IDs
+ *
+ * @return array
+ */
+function GetUsers() {
+       $dbr =& wfGetDB( DB_SLAVE );
+       $res = $dbr->select( 'user', 'user_id' );
+       $users = array();
+       while( $row = $dbr->fetchObject( $res ) ) {
+               $users[] = $row->user_id;
+       }
+       return( $users );
+}
+
+/**
+ * Resolve a username to a user ID
+ *
+ * @param string $username Username
+ * @return mixed
+ */
+function GetUserID( $username ) {
+       $dbr =& wfGetDB( DB_SLAVE );
+       $res = $dbr->select( 'user', 'user_id', array( 'user_name' => '"' . $username . '"' ) );
+       if( $res !== false ) {
+               $row = $dbr->fetchObject( $res );
+               return( $row->user_id );
+       } else {
+               return( false );
+       }
+}
+
+/**
+ * Delete one or more users
+ *
+ * @param mixed $users Single integer or array of integers corresponding to user IDs
+ * @return bool
+ */
+function DeleteUsers( $users ) {
+       $dbw =& wfGetDB( DB_MASTER );
+       $dbw->begin();
+       foreach( $users as $user ) {
+               $dbw->delete( 'user', array( 'user_id' => $user ) );
+       }
+       $dbw->commit();
+       return( true );
+}
+
+/**
+ * Add a user to the named group(s)
+ *
+ * @param integer $user User ID
+ * @param mixed $groups Single string or array of strings corresponding to group names
+ * @return bool
+ */
+function SetUserGroups( $user, $groups ) {
+       $dbw =& wfGetDB( DB_MASTER );
+       foreach( $groups as $group ) {
+               $row = array( 'ug_user' => $user, 'ug_group' => $group );
+               if( !$dbw->insert( 'user_groups', $row, 'SetUserGroups' ) ) {
+                       return( false );
+               }
+       }
+       return( true );
+}
+
+?>
\ No newline at end of file
diff --git a/maintenance/users.sql b/maintenance/users.sql
new file mode 100644 (file)
index 0000000..9c2bd4b
--- /dev/null
@@ -0,0 +1,12 @@
+-- SQL script to create required database users with proper
+-- access rights.  This is run from the installation script
+-- which replaces the password variables with their values
+-- from local settings.
+--
+
+GRANT DELETE,INSERT,SELECT,UPDATE ON `{$wgDBname}`.*
+ TO '{$wgDBuser}'@'%' IDENTIFIED BY '{$wgDBpassword}';
+GRANT DELETE,INSERT,SELECT,UPDATE ON `{$wgDBname}`.*
+ TO '{$wgDBuser}'@localhost IDENTIFIED BY '{$wgDBpassword}';
+GRANT DELETE,INSERT,SELECT,UPDATE ON `{$wgDBname}`.*
+ TO '{$wgDBuser}'@localhost.localdomain IDENTIFIED BY '{$wgDBpassword}';
diff --git a/maintenance/wikipedia-interwiki.sql b/maintenance/wikipedia-interwiki.sql
new file mode 100644 (file)
index 0000000..c6e4883
--- /dev/null
@@ -0,0 +1,220 @@
+-- For convenience, here are the *in-project* interwiki prefixes
+-- for Wikipedia.
+
+REPLACE INTO /*$wgDBprefix*/interwiki (iw_prefix,iw_url,iw_local) VALUES
+('q','http://en.wikiquote.org/wiki/$1',1),
+('b','http://en.wikibooks.org/wiki/$1',1),
+('n','http://en.wikinews.org/wiki/$1',1),
+('aa','http://aa.wikipedia.org/wiki/$1',1),
+('ab','http://ab.wikipedia.org/wiki/$1',1),
+('af','http://af.wikipedia.org/wiki/$1',1),
+('ak','http://ak.wikipedia.org/wiki/$1',1),
+('als','http://als.wikipedia.org/wiki/$1',1),
+('am','http://am.wikipedia.org/wiki/$1',1),
+('an','http://an.wikipedia.org/wiki/$1',1),
+('ang','http://ang.wikipedia.org/wiki/$1',1),
+('ar','http://ar.wikipedia.org/wiki/$1',1),
+('arc','http://arc.wikipedia.org/wiki/$1',1),
+('as','http://as.wikipedia.org/wiki/$1',1),
+('ast','http://ast.wikipedia.org/wiki/$1',1),
+('av','http://av.wikipedia.org/wiki/$1',1),
+('ay','http://ay.wikipedia.org/wiki/$1',1),
+('az','http://az.wikipedia.org/wiki/$1',1),
+('ba','http://ba.wikipedia.org/wiki/$1',1),
+('be','http://be.wikipedia.org/wiki/$1',1),
+('bg','http://bg.wikipedia.org/wiki/$1',1),
+('bh','http://bh.wikipedia.org/wiki/$1',1),
+('bi','http://bi.wikipedia.org/wiki/$1',1),
+('bm','http://bm.wikipedia.org/wiki/$1',1),
+('bn','http://bn.wikipedia.org/wiki/$1',1),
+('bo','http://bo.wikipedia.org/wiki/$1',1),
+('br','http://br.wikipedia.org/wiki/$1',1),
+('bs','http://bs.wikipedia.org/wiki/$1',1),
+('ca','http://ca.wikipedia.org/wiki/$1',1),
+('ce','http://ce.wikipedia.org/wiki/$1',1),
+('ch','http://ch.wikipedia.org/wiki/$1',1),
+('cho','http://cho.wikipedia.org/wiki/$1',1),
+('chr','http://chr.wikipedia.org/wiki/$1',1),
+('chy','http://chy.wikipedia.org/wiki/$1',1),
+('co','http://co.wikipedia.org/wiki/$1',1),
+('cr','http://cr.wikipedia.org/wiki/$1',1),
+('cs','http://cs.wikipedia.org/wiki/$1',1),
+('csb','http://csb.wikipedia.org/wiki/$1',1),
+('cv','http://cv.wikipedia.org/wiki/$1',1),
+('cy','http://cy.wikipedia.org/wiki/$1',1),
+('da','http://da.wikipedia.org/wiki/$1',1),
+('de','http://de.wikipedia.org/wiki/$1',1),
+('dv','http://dv.wikipedia.org/wiki/$1',1),
+('dz','http://dz.wikipedia.org/wiki/$1',1),
+('ee','http://ee.wikipedia.org/wiki/$1',1),
+('el','http://el.wikipedia.org/wiki/$1',1),
+('en','http://en.wikipedia.org/wiki/$1',1),
+('eo','http://eo.wikipedia.org/wiki/$1',1),
+('es','http://es.wikipedia.org/wiki/$1',1),
+('et','http://et.wikipedia.org/wiki/$1',1),
+('eu','http://eu.wikipedia.org/wiki/$1',1),
+('fa','http://fa.wikipedia.org/wiki/$1',1),
+('ff','http://ff.wikipedia.org/wiki/$1',1),
+('fi','http://fi.wikipedia.org/wiki/$1',1),
+('fj','http://fj.wikipedia.org/wiki/$1',1),
+('fo','http://fo.wikipedia.org/wiki/$1',1),
+('fr','http://fr.wikipedia.org/wiki/$1',1),
+('fy','http://fy.wikipedia.org/wiki/$1',1),
+('fur','http://fur.wikipedia.org/wiki/$1',1),
+('ga','http://ga.wikipedia.org/wiki/$1',1),
+('gd','http://gd.wikipedia.org/wiki/$1',1),
+('gl','http://gl.wikipedia.org/wiki/$1',1),
+('gn','http://gn.wikipedia.org/wiki/$1',1),
+('got','http://got.wikipedia.org/wiki/$1',1),
+('gu','http://gu.wikipedia.org/wiki/$1',1),
+('gv','http://gv.wikipedia.org/wiki/$1',1),
+('ha','http://ha.wikipedia.org/wiki/$1',1),
+('haw','http://haw.wikipedia.org/wiki/$1',1),
+('he','http://he.wikipedia.org/wiki/$1',1),
+('hi','http://hi.wikipedia.org/wiki/$1',1),
+('ho','http://ho.wikipedia.org/wiki/$1',1),
+('hr','http://hr.wikipedia.org/wiki/$1',1),
+('ht','http://ht.wikipedia.org/wiki/$1',1),
+('hu','http://hu.wikipedia.org/wiki/$1',1),
+('hy','http://hy.wikipedia.org/wiki/$1',1),
+('hz','http://hz.wikipedia.org/wiki/$1',1),
+('ia','http://ia.wikipedia.org/wiki/$1',1),
+('id','http://id.wikipedia.org/wiki/$1',1),
+('ie','http://ie.wikipedia.org/wiki/$1',1),
+('ig','http://ig.wikipedia.org/wiki/$1',1),
+('ii','http://ii.wikipedia.org/wiki/$1',1),
+('ik','http://ik.wikipedia.org/wiki/$1',1),
+('io','http://io.wikipedia.org/wiki/$1',1),
+('is','http://is.wikipedia.org/wiki/$1',1),
+('it','http://it.wikipedia.org/wiki/$1',1),
+('iu','http://iu.wikipedia.org/wiki/$1',1),
+('ja','http://ja.wikipedia.org/wiki/$1',1),
+('jbo','http://jbo.wikipedia.org/wiki/$1',1),
+('jv','http://jv.wikipedia.org/wiki/$1',1),
+('ka','http://ka.wikipedia.org/wiki/$1',1),
+('kg','http://kg.wikipedia.org/wiki/$1',1),
+('ki','http://ki.wikipedia.org/wiki/$1',1),
+('kj','http://kj.wikipedia.org/wiki/$1',1),
+('kk','http://kk.wikipedia.org/wiki/$1',1),
+('kl','http://kl.wikipedia.org/wiki/$1',1),
+('km','http://km.wikipedia.org/wiki/$1',1),
+('kn','http://kn.wikipedia.org/wiki/$1',1),
+('ko','http://ko.wikipedia.org/wiki/$1',1),
+('kr','http://kr.wikipedia.org/wiki/$1',1),
+('ks','http://ks.wikipedia.org/wiki/$1',1),
+('ku','http://ku.wikipedia.org/wiki/$1',1),
+('kv','http://kv.wikipedia.org/wiki/$1',1),
+('kw','http://kw.wikipedia.org/wiki/$1',1),
+('ky','http://ky.wikipedia.org/wiki/$1',1),
+('la','http://la.wikipedia.org/wiki/$1',1),
+('lb','http://lb.wikipedia.org/wiki/$1',1),
+('lg','http://lg.wikipedia.org/wiki/$1',1),
+('li','http://li.wikipedia.org/wiki/$1',1),
+('ln','http://ln.wikipedia.org/wiki/$1',1),
+('lo','http://lo.wikipedia.org/wiki/$1',1),
+('lt','http://lt.wikipedia.org/wiki/$1',1),
+('lv','http://lv.wikipedia.org/wiki/$1',1),
+('mg','http://mg.wikipedia.org/wiki/$1',1),
+('mh','http://mh.wikipedia.org/wiki/$1',1),
+('mi','http://mi.wikipedia.org/wiki/$1',1),
+('mk','http://mk.wikipedia.org/wiki/$1',1),
+('ml','http://ml.wikipedia.org/wiki/$1',1),
+('mn','http://mn.wikipedia.org/wiki/$1',1),
+('mo','http://mo.wikipedia.org/wiki/$1',1),
+('mr','http://mr.wikipedia.org/wiki/$1',1),
+('ms','http://ms.wikipedia.org/wiki/$1',1),
+('mt','http://mt.wikipedia.org/wiki/$1',1),
+('mus','http://mus.wikipedia.org/wiki/$1',1),
+('my','http://my.wikipedia.org/wiki/$1',1),
+('na','http://na.wikipedia.org/wiki/$1',1),
+('nah','http://nah.wikipedia.org/wiki/$1',1),
+('nb','http://nb.wikipedia.org/wiki/$1',1),
+('nds','http://nds.wikipedia.org/wiki/$1',1),
+('ne','http://ne.wikipedia.org/wiki/$1',1),
+('ng','http://ng.wikipedia.org/wiki/$1',1),
+('nl','http://nl.wikipedia.org/wiki/$1',1),
+('nn','http://nn.wikipedia.org/wiki/$1',1),
+('no','http://no.wikipedia.org/wiki/$1',1),
+('nv','http://nv.wikipedia.org/wiki/$1',1),
+('ny','http://ny.wikipedia.org/wiki/$1',1),
+('oc','http://oc.wikipedia.org/wiki/$1',1),
+('om','http://om.wikipedia.org/wiki/$1',1),
+('or','http://or.wikipedia.org/wiki/$1',1),
+('pa','http://pa.wikipedia.org/wiki/$1',1),
+('pi','http://pi.wikipedia.org/wiki/$1',1),
+('pl','http://pl.wikipedia.org/wiki/$1',1),
+('ps','http://ps.wikipedia.org/wiki/$1',1),
+('pt','http://pt.wikipedia.org/wiki/$1',1),
+('qu','http://qu.wikipedia.org/wiki/$1',1),
+('rm','http://rm.wikipedia.org/wiki/$1',1),
+('rn','http://rn.wikipedia.org/wiki/$1',1),
+('ro','http://ro.wikipedia.org/wiki/$1',1),
+('roa-rup','http://roa-rup.wikipedia.org/wiki/$1',1),
+('ru','http://ru.wikipedia.org/wiki/$1',1),
+('rw','http://rw.wikipedia.org/wiki/$1',1),
+('sa','http://sa.wikipedia.org/wiki/$1',1),
+('sc','http://sc.wikipedia.org/wiki/$1',1),
+('scn','http://scn.wikipedia.org/wiki/$1',1),
+('sd','http://sd.wikipedia.org/wiki/$1',1),
+('se','http://se.wikipedia.org/wiki/$1',1),
+('sg','http://sg.wikipedia.org/wiki/$1',1),
+('sh','http://sh.wikipedia.org/wiki/$1',1),
+('si','http://si.wikipedia.org/wiki/$1',1),
+('simple','http://simple.wikipedia.org/wiki/$1',1),
+('sk','http://sk.wikipedia.org/wiki/$1',1),
+('sl','http://sl.wikipedia.org/wiki/$1',1),
+('sm','http://sm.wikipedia.org/wiki/$1',1),
+('sn','http://sn.wikipedia.org/wiki/$1',1),
+('so','http://so.wikipedia.org/wiki/$1',1),
+('sq','http://sq.wikipedia.org/wiki/$1',1),
+('sr','http://sr.wikipedia.org/wiki/$1',1),
+('ss','http://ss.wikipedia.org/wiki/$1',1),
+('st','http://st.wikipedia.org/wiki/$1',1),
+('su','http://su.wikipedia.org/wiki/$1',1),
+('sv','http://sv.wikipedia.org/wiki/$1',1),
+('sw','http://sw.wikipedia.org/wiki/$1',1),
+('ta','http://ta.wikipedia.org/wiki/$1',1),
+('te','http://te.wikipedia.org/wiki/$1',1),
+('tg','http://tg.wikipedia.org/wiki/$1',1),
+('th','http://th.wikipedia.org/wiki/$1',1),
+('ti','http://ti.wikipedia.org/wiki/$1',1),
+('tk','http://tk.wikipedia.org/wiki/$1',1),
+('tl','http://tl.wikipedia.org/wiki/$1',1),
+('tlh','http://tlh.wikipedia.org/wiki/$1',1),
+('tn','http://tn.wikipedia.org/wiki/$1',1),
+('to','http://to.wikipedia.org/wiki/$1',1),
+('tokipona','http://tokipona.wikipedia.org/wiki/$1',1),
+('tpi','http://tpi.wikipedia.org/wiki/$1',1),
+('tr','http://tr.wikipedia.org/wiki/$1',1),
+('ts','http://ts.wikipedia.org/wiki/$1',1),
+('tt','http://tt.wikipedia.org/wiki/$1',1),
+('tum','http://tum.wikipedia.org/wiki/$1',1),
+('tw','http://tw.wikipedia.org/wiki/$1',1),
+('ty','http://ty.wikipedia.org/wiki/$1',1),
+('ug','http://ug.wikipedia.org/wiki/$1',1),
+('uk','http://uk.wikipedia.org/wiki/$1',1),
+('ur','http://ur.wikipedia.org/wiki/$1',1),
+('uz','http://uz.wikipedia.org/wiki/$1',1),
+('ve','http://ve.wikipedia.org/wiki/$1',1),
+('vi','http://vi.wikipedia.org/wiki/$1',1),
+('vo','http://vo.wikipedia.org/wiki/$1',1),
+('wa','http://wa.wikipedia.org/wiki/$1',1),
+('wo','http://wo.wikipedia.org/wiki/$1',1),
+('xh','http://xh.wikipedia.org/wiki/$1',1),
+('yi','http://yi.wikipedia.org/wiki/$1',1),
+('yo','http://yo.wikipedia.org/wiki/$1',1),
+('za','http://za.wikipedia.org/wiki/$1',1),
+('zh','http://zh.wikipedia.org/wiki/$1',1),
+('zh-min-nan','http://zh-min-nan.wikipedia.org/wiki/$1',1),
+('zu','http://zu.wikipedia.org/wiki/$1',1),
+('zh-cn','http://zh.wikipedia.org/wiki/$1',1),
+('zh-tw','http://zh.wikipedia.org/wiki/$1',1),
+('minnan','http://zh-min-nan.wikipedia.org/wiki/$1',1),
+('zh-cfr','http://zh-min-nan.wikipedia.org/wiki/$1',1),
+('dk','http://da.wikipedia.org/wiki/$1',1),
+('w','http://en.wikipedia.org/wiki/$1',1),
+('m','http://meta.wikimedia.org/wiki/$1',1),
+('meta','http://meta.wikimedia.org/wiki/$1',1),
+('sep11','http://sep11.wikipedia.org/wiki/$1',1),
+('os','http://os.wikipedia.org/wiki/$1',1);
+
diff --git a/maintenance/wiktionary-interwiki.sql b/maintenance/wiktionary-interwiki.sql
new file mode 100644 (file)
index 0000000..787962d
--- /dev/null
@@ -0,0 +1,160 @@
+-- For convenience, here are the *in-project* interwiki prefixes
+-- for Wikipedia.
+
+REPLACE INTO /*$wgDBprefix*/interwiki (iw_prefix,iw_url,iw_local) VALUES
+('w','http://www.wikipedia.org/wiki/$1',1),
+('m','http://meta.wikipedia.org/wiki/$1',1),
+('meta','http://meta.wikipedia.org/wiki/$1',1),
+('sep11','http://sep11.wikipedia.org/wiki/$1',1),
+('simple','http://simple.wiktionary.org/wiki/$1',1),
+('aa','http://aa.wiktionary.org/wiki/$1',1),
+('ab','http://ab.wiktionary.org/wiki/$1',1),
+('af','http://af.wiktionary.org/wiki/$1',1),
+('als','http://als.wiktionary.org/wiki/$1',1),
+('am','http://am.wiktionary.org/wiki/$1',1),
+('ar','http://ar.wiktionary.org/wiki/$1',1),
+('as','http://as.wiktionary.org/wiki/$1',1),
+('ay','http://ay.wiktionary.org/wiki/$1',1),
+('az','http://az.wiktionary.org/wiki/$1',1),
+('ba','http://ba.wiktionary.org/wiki/$1',1),
+('be','http://be.wiktionary.org/wiki/$1',1),
+('bg','http://bg.wiktionary.org/wiki/$1',1),
+('bh','http://bh.wiktionary.org/wiki/$1',1),
+('bi','http://bi.wiktionary.org/wiki/$1',1),
+('bn','http://bn.wiktionary.org/wiki/$1',1),
+('bo','http://bo.wiktionary.org/wiki/$1',1),
+('bs','http://bs.wiktionary.org/wiki/$1',1),
+('ca','http://ca.wiktionary.org/wiki/$1',1),
+('chr','http://chr.wiktionary.org/wiki/$1',1),
+('co','http://co.wiktionary.org/wiki/$1',1),
+('cs','http://cs.wiktionary.org/wiki/$1',1),
+('csb','http://csb.wiktionary.org/wiki/$1',1),
+('cy','http://cy.wiktionary.org/wiki/$1',1),
+('da','http://da.wiktionary.org/wiki/$1',1),
+('de','http://de.wiktionary.org/wiki/$1',1),
+('dk','http://da.wiktionary.org/wiki/$1',1),
+('dz','http://dz.wiktionary.org/wiki/$1',1),
+('el','http://el.wiktionary.org/wiki/$1',1),
+('en','http://en.wiktionary.org/wiki/$1',1),
+('eo','http://eo.wiktionary.org/wiki/$1',1),
+('es','http://es.wiktionary.org/wiki/$1',1),
+('et','http://et.wiktionary.org/wiki/$1',1),
+('eu','http://eu.wiktionary.org/wiki/$1',1),
+('fa','http://fa.wiktionary.org/wiki/$1',1),
+('fi','http://fi.wiktionary.org/wiki/$1',1),
+('fj','http://fj.wiktionary.org/wiki/$1',1),
+('fo','http://fo.wiktionary.org/wiki/$1',1),
+('fr','http://fr.wiktionary.org/wiki/$1',1),
+('fy','http://fy.wiktionary.org/wiki/$1',1),
+('ga','http://ga.wiktionary.org/wiki/$1',1),
+('gd','http://gd.wiktionary.org/wiki/$1',1),
+('gl','http://gl.wiktionary.org/wiki/$1',1),
+('gn','http://gn.wiktionary.org/wiki/$1',1),
+('gu','http://gu.wiktionary.org/wiki/$1',1),
+('gv','http://gv.wiktionary.org/wiki/$1',1),
+('ha','http://ha.wiktionary.org/wiki/$1',1),
+('he','http://he.wiktionary.org/wiki/$1',1),
+('hi','http://hi.wiktionary.org/wiki/$1',1),
+('hr','http://hr.wiktionary.org/wiki/$1',1),
+('hu','http://hu.wiktionary.org/wiki/$1',1),
+('hy','http://hy.wiktionary.org/wiki/$1',1),
+('ia','http://ia.wiktionary.org/wiki/$1',1),
+('id','http://id.wiktionary.org/wiki/$1',1),
+('ik','http://ik.wiktionary.org/wiki/$1',1),
+('io','http://io.wiktionary.org/wiki/$1',1),
+('is','http://is.wiktionary.org/wiki/$1',1),
+('it','http://it.wiktionary.org/wiki/$1',1),
+('iu','http://iu.wiktionary.org/wiki/$1',1),
+('ja','http://ja.wiktionary.org/wiki/$1',1),
+('jv','http://jv.wiktionary.org/wiki/$1',1),
+('ka','http://ka.wiktionary.org/wiki/$1',1),
+('kk','http://kk.wiktionary.org/wiki/$1',1),
+('kl','http://kl.wiktionary.org/wiki/$1',1),
+('km','http://km.wiktionary.org/wiki/$1',1),
+('kn','http://kn.wiktionary.org/wiki/$1',1),
+('ko','http://ko.wiktionary.org/wiki/$1',1),
+('ks','http://ks.wiktionary.org/wiki/$1',1),
+('ku','http://ku.wiktionary.org/wiki/$1',1),
+('ky','http://ky.wiktionary.org/wiki/$1',1),
+('la','http://la.wiktionary.org/wiki/$1',1),
+('lo','http://lo.wiktionary.org/wiki/$1',1),
+('lt','http://lt.wiktionary.org/wiki/$1',1),
+('lv','http://lv.wiktionary.org/wiki/$1',1),
+('mg','http://mg.wiktionary.org/wiki/$1',1),
+('mi','http://mi.wiktionary.org/wiki/$1',1),
+('mk','http://mk.wiktionary.org/wiki/$1',1),
+('ml','http://ml.wiktionary.org/wiki/$1',1),
+('mn','http://mn.wiktionary.org/wiki/$1',1),
+('mo','http://mo.wiktionary.org/wiki/$1',1),
+('mr','http://mr.wiktionary.org/wiki/$1',1),
+('ms','http://ms.wiktionary.org/wiki/$1',1),
+('my','http://my.wiktionary.org/wiki/$1',1),
+('na','http://na.wiktionary.org/wiki/$1',1),
+('nah','http://nah.wiktionary.org/wiki/$1',1),
+('nb', 'http://no.wiktionary.org/wiki/$1',1),
+('nds','http://nds.wiktionary.org/wiki/$1',1),
+('ne','http://ne.wiktionary.org/wiki/$1',1),
+('nl','http://nl.wiktionary.org/wiki/$1',1),
+('no','http://no.wiktionary.org/wiki/$1',1),
+('oc','http://oc.wiktionary.org/wiki/$1',1),
+('om','http://om.wiktionary.org/wiki/$1',1),
+('or','http://or.wiktionary.org/wiki/$1',1),
+('pa','http://pa.wiktionary.org/wiki/$1',1),
+('pl','http://pl.wiktionary.org/wiki/$1',1),
+('ps','http://ps.wiktionary.org/wiki/$1',1),
+('pt','http://pt.wiktionary.org/wiki/$1',1),
+('qu','http://qu.wiktionary.org/wiki/$1',1),
+('rm','http://rm.wiktionary.org/wiki/$1',1),
+('rn','http://rn.wiktionary.org/wiki/$1',1),
+('ro','http://ro.wiktionary.org/wiki/$1',1),
+('ru','http://ru.wiktionary.org/wiki/$1',1),
+('rw','http://rw.wiktionary.org/wiki/$1',1),
+('sa','http://sa.wiktionary.org/wiki/$1',1),
+('sd','http://sd.wiktionary.org/wiki/$1',1),
+('sg','http://sg.wiktionary.org/wiki/$1',1),
+('sh','http://sh.wiktionary.org/wiki/$1',1),
+('si','http://si.wiktionary.org/wiki/$1',1),
+('sk','http://sk.wiktionary.org/wiki/$1',1),
+('sl','http://sl.wiktionary.org/wiki/$1',1),
+('sm','http://sm.wiktionary.org/wiki/$1',1),
+('sn','http://sn.wiktionary.org/wiki/$1',1),
+('so','http://so.wiktionary.org/wiki/$1',1),
+('sq','http://sq.wiktionary.org/wiki/$1',1),
+('sr','http://sr.wiktionary.org/wiki/$1',1),
+('ss','http://ss.wiktionary.org/wiki/$1',1),
+('st','http://st.wiktionary.org/wiki/$1',1),
+('su','http://su.wiktionary.org/wiki/$1',1),
+('sv','http://sv.wiktionary.org/wiki/$1',1),
+('sw','http://sw.wiktionary.org/wiki/$1',1),
+('ta','http://ta.wiktionary.org/wiki/$1',1),
+('te','http://te.wiktionary.org/wiki/$1',1),
+('tg','http://tg.wiktionary.org/wiki/$1',1),
+('th','http://th.wiktionary.org/wiki/$1',1),
+('ti','http://ti.wiktionary.org/wiki/$1',1),
+('tk','http://tk.wiktionary.org/wiki/$1',1),
+('tl','http://tl.wiktionary.org/wiki/$1',1),
+('tn','http://tn.wiktionary.org/wiki/$1',1),
+('to','http://to.wiktionary.org/wiki/$1',1),
+('tokipona','http://tokipona.wiktionary.org/wiki/$1',1),
+('tpi','http://tpi.wiktionary.org/wiki/$1',1),
+('tr','http://tr.wiktionary.org/wiki/$1',1),
+('ts','http://ts.wiktionary.org/wiki/$1',1),
+('tt','http://tt.wiktionary.org/wiki/$1',1),
+('tw','http://tw.wiktionary.org/wiki/$1',1),
+('ug','http://ug.wiktionary.org/wiki/$1',1),
+('uk','http://uk.wiktionary.org/wiki/$1',1),
+('ur','http://ur.wiktionary.org/wiki/$1',1),
+('uz','http://uz.wiktionary.org/wiki/$1',1),
+('vi','http://vi.wiktionary.org/wiki/$1',1),
+('vo','http://vo.wiktionary.org/wiki/$1',1),
+('wa','http://wa.wiktionary.org/wiki/$1',1),
+('wo','http://wo.wiktionary.org/wiki/$1',1),
+('xh','http://xh.wiktionary.org/wiki/$1',1),
+('yi','http://yi.wiktionary.org/wiki/$1',1),
+('yo','http://yo.wiktionary.org/wiki/$1',1),
+('za','http://za.wiktionary.org/wiki/$1',1),
+('zh','http://zh.wiktionary.org/wiki/$1',1),
+('zh-cn','http://zh.wiktionary.org/wiki/$1',1),
+('zh-tw','http://zh.wiktionary.org/wiki/$1',1),
+('zu','http://zu.wiktionary.org/wiki/$1',1);
+
diff --git a/math/.cvsignore b/math/.cvsignore
new file mode 100644 (file)
index 0000000..6aa9640
--- /dev/null
@@ -0,0 +1,7 @@
+texvc
+texvc_test
+texvc_tex
+*.cmi
+*.cmx
+*.mli
+*~
diff --git a/math/.htaccess b/math/.htaccess
new file mode 100644 (file)
index 0000000..3a42882
--- /dev/null
@@ -0,0 +1 @@
+Deny from all
diff --git a/math/Makefile b/math/Makefile
new file mode 100644 (file)
index 0000000..47c40f9
--- /dev/null
@@ -0,0 +1,64 @@
+OBJ=render_info.cmo tex.cmo texutil.cmo parser.cmo lexer.cmo texvc.cmo \
+render_info.cmx tex.cmx texutil.cmx parser.cmx lexer.cmx texvc.cmx \
+lexer.cmi parser.cmi render_info.cmi tex.cmi texutil.cmi texvc.cmi \
+lexer.o parser.o render_info.o tex.o texutil.o texvc.o \
+lexer.ml parser.ml parser.mli texvc texvc.bc texvc_test.cmo \
+texvc_test.cmx texvc_test.cmi texvc_test.o texvc_test util.o \
+util.cmo util.cmx util.cmi texvc_cgi.cmi texvc_cgi texvc_cgi.cmo \
+render.o render.cmi render.cmo render.cmx texvc_tex.cmx \
+texvc_tex.o texvc_tex.cmi texvc_tex html.cmi html.cmo html.cmx \
+html.o mathml.cmi mathml.cmo mathml.cmx mathml.o
+CGIPATH=-I /usr/lib/ocaml/cgi -I /usr/lib/ocaml/netstring -I /usr/lib/ocaml/pcre
+
+all: texvc texvc_test texvc_tex
+texvc.bc: util.cmo parser.cmo html.cmo mathml.cmo texutil.cmo render.cmo lexer.cmo texvc.cmo
+       ocamlc -o $@ unix.cma $^
+texvc: util.cmx parser.cmx html.cmx mathml.cmx texutil.cmx render.cmx lexer.cmx texvc.cmx
+       ocamlopt -o $@ unix.cmxa $^
+texvc_test: util.cmx parser.cmx html.cmx mathml.cmx texutil.cmx lexer.cmx texvc_test.cmx
+       ocamlopt -o $@ $^
+texvc_tex: util.cmx parser.cmx html.cmx mathml.cmx texutil.cmx lexer.cmx texvc_tex.cmx
+       ocamlopt -o $@ $^
+%.ml: %.mll
+       ocamllex $<
+%.mli %.ml: %.mly
+       ocamlyacc $<
+%.cmo: %.ml
+       ocamlc -c $<
+%.cmx: %.ml
+       ocamlopt -c $<
+%.cmi: %.mli
+       ocamlc -c $<
+texvc_cgi.cmo: texvc_cgi.ml
+       ocamlc -c $(CGIPATH) $<
+texvc_cgi: util.cmo parser.cmo texutil.cmo render.cmo lexer.cmo texvc_cgi.cmo
+       ocamlc -o $@ unix.cma $(CGIPATH) pcre.cma netstring.cma cgi.cma $^
+       chmod g-w $@
+clean:
+       rm -f $(OBJ)
+
+html.cmo: render_info.cmi tex.cmi util.cmo html.cmi 
+html.cmx: render_info.cmi tex.cmi util.cmx html.cmi 
+html.cmi: tex.cmi 
+lexer.cmo: parser.cmi render_info.cmi tex.cmi texutil.cmi 
+lexer.cmx: parser.cmx render_info.cmi tex.cmi texutil.cmx 
+mathml.cmo: tex.cmi mathml.cmi 
+mathml.cmx: tex.cmi mathml.cmi 
+mathml.cmi: tex.cmi 
+parser.cmo: render_info.cmi tex.cmi parser.cmi 
+parser.cmx: render_info.cmi tex.cmi parser.cmi 
+parser.cmi: render_info.cmi tex.cmi 
+render.cmo: texutil.cmi util.cmo 
+render.cmx: texutil.cmx util.cmx 
+tex.cmi: render_info.cmi 
+texutil.cmo: html.cmi parser.cmi render_info.cmi tex.cmi util.cmo texutil.cmi 
+texutil.cmx: html.cmx parser.cmx render_info.cmi tex.cmi util.cmx texutil.cmi 
+texutil.cmi: parser.cmi tex.cmi 
+texvc.cmo: html.cmi lexer.cmo mathml.cmi parser.cmi render.cmo texutil.cmi util.cmo 
+texvc.cmx: html.cmx lexer.cmx mathml.cmx parser.cmx render.cmx texutil.cmx util.cmx 
+texvc_cgi.cmo: lexer.cmo parser.cmi render.cmo texutil.cmi util.cmo 
+texvc_cgi.cmx: lexer.cmx parser.cmx render.cmx texutil.cmx util.cmx 
+texvc_test.cmo: html.cmi lexer.cmo parser.cmi texutil.cmi util.cmo 
+texvc_test.cmx: html.cmx lexer.cmx parser.cmx texutil.cmx util.cmx 
+texvc_tex.cmo: lexer.cmo parser.cmi texutil.cmi util.cmo 
+texvc_tex.cmx: lexer.cmx parser.cmx texutil.cmx util.cmx 
diff --git a/math/README b/math/README
new file mode 100644 (file)
index 0000000..1349b83
--- /dev/null
@@ -0,0 +1,107 @@
+== About texvc ==
+
+texvc takes LaTeX-compatible equations and produces formatted output in
+HTML, MathML, and (via LaTeX/dvips/ImageMagick) rasterized PNG images.
+Input data is parsed and scrutinized for safety, and the output includes
+an estimate of whether the code is simple enough that HTML rendering will
+look acceptable.
+
+The program was written by Tomasz Wegrzanowski for use with MediaWiki;
+it's included as part of the MediaWiki package (http://wikipedia.sf.net)
+and is under the GPL license.
+
+Please report bugs at: http://bugzilla.wikimedia.org/ (under "MediaWiki")
+
+== Setup ==
+
+=== Requirements ===
+
+OCaml 3.06 or later is required to compile texvc; this can be acquired
+from http://caml.inria.fr/ if your system doesn't have it available.
+
+The makefile requires GNU make.
+
+Rasterization is done via LaTeX, dvips, and ImageMagick. These need
+to be installed and in the PATH: latex, dvips, convert
+
+To work properly with rendering non-ASCII Unicode characters, a
+supplemental TeX package is needed (cjk-latex in Debian)
+
+=== Installation ===
+
+Run 'make' (or 'gmake' if GNU make is not your default make). This should
+produce the texvc executable.
+
+If you're using MediaWiki's install.php and have enabled $wgUseTeX in your
+LocalSettings.php, the installer will try to copy texvc into place, in the
+'math' subdirectory under where wiki.phtml is installed.
+
+
+== Usage ==
+
+Normally texvc is called from MediaWiki's Math.php modules and everything
+Just Works. It can be run manually for testing or for use in another app.
+
+=== Command-line parameters ===
+
+    texvc <temp directory> <output directory> <TeX code> <encoding>
+
+Be sure to properly quote the TeX code!
+
+Example:
+
+    texvc /home/wiki/tmp /home/wiki/math "y=x+2" iso-8859-1
+
+=== Output format ===
+
+Status codes and HTML/MathML transformations are returned on stdout.
+A rasterized PNG file will be written to the output directory, named
+for the MD5 hash code.
+
+texvc output format is like this:
+    +%5                ok, but not html or mathml
+    c%5%h      ok, conservative html, no mathml
+    m%5%h      ok, moderate html, no mathml
+    l%5%h      ok, liberal html, no mathml
+    C%5%h\0%m  ok, conservative html, with mathml
+    M%5%h\0%m  ok, moderate html, with mathml
+    L%5%h\0%m  ok, liberal html, with mathml
+    X%5%m      ok, no html, with mathml
+    S          syntax error
+    E          lexing error
+    F%s                unknown function %s
+    -          other error
+
+ \0 - null character
+ %5 - md5, 32 hex characters
+ %h - html code, without \0 characters
+ %m - mathml code, without \0 characters
+
+
+== Troubleshooting ==
+
+Unforunately, many error conditions with rasterization are not well reported.
+texvc will return as though everything is successful, and the only obvious
+sign of problems for the user is a big X on a wiki page where an equation
+should be.
+
+Try running texvc from the command line to ensure that the software it relies
+upon is all set up.
+
+Ensure that the temporary and math directories exist and can be written to by
+the user account the web server runs under; if you don't control the server,
+you may have to make them world-writable.
+
+== Hacking ==
+
+Before you start hacking on the math package its good to know the workflow,
+which is basically:
+
+1. texvc gets called by includes/Math.php (check out the line begining with "$cmd")
+2. texvc does its magic, which is basically to check for invalid latex code.
+3. texvc takes the user input if valid and creates a latex file containing it, see
+   get_preface in texutil.ml
+4. latex(1) gets called to create a .dvi file, the a .ps file is created from the
+   .dvi file using dvips(1), and finally convert(1) creates a .png file from
+   the .ps file. See render.ml for this process (commenting out the removal of
+   the temporary file is useful for debugging).
diff --git a/math/TODO b/math/TODO
new file mode 100644 (file)
index 0000000..bd8d1f4
--- /dev/null
+++ b/math/TODO
@@ -0,0 +1,3 @@
+* It would be better if PNGs were transparent
+* CJK support
+* Documentation, in particular about instalation of Latex support for Unicode
diff --git a/math/html.ml b/math/html.ml
new file mode 100644 (file)
index 0000000..6a24b11
--- /dev/null
@@ -0,0 +1,119 @@
+open Render_info
+open Tex
+open Util
+
+exception Too_difficult_for_html
+type context = CTX_NORMAL | CTX_IT | CTX_RM 
+type conservativeness_t = CONSERVATIVE | MODERATE | LIBERAL
+
+let conservativeness = ref CONSERVATIVE
+let html_liberal () = conservativeness := LIBERAL
+let html_moderate () = if !conservativeness = CONSERVATIVE then conservativeness := MODERATE else ()
+
+
+let new_ctx = function
+    FONTFORCE_IT -> CTX_IT
+  | FONTFORCE_RM -> CTX_RM
+let font_render lit = function
+    (_,     FONT_UFH) -> lit
+  | (_,     FONT_UF)  -> lit
+  | (CTX_IT,FONT_RTI) -> raise Too_difficult_for_html
+  | (_,     FONT_RTI) -> lit
+  | (CTX_IT,FONT_RM)  -> "<i>"^lit^"</i>"
+  | (_,     FONT_RM)  -> lit
+  | (CTX_RM,FONT_IT)  -> lit
+  | (_,     FONT_IT)  -> "<i>"^lit^"</i>"
+
+let rec html_render_flat ctx = function
+    TEX_LITERAL (HTMLABLE (ft,_,sh))::r -> (html_liberal (); (font_render sh (ctx,ft))^html_render_flat ctx r)
+  | TEX_LITERAL (HTMLABLEC(ft,_,sh))::r -> (font_render sh (ctx,ft))^html_render_flat ctx r
+  | TEX_LITERAL (MHTMLABLEC(ft,_,sh,_,_))::r -> (font_render sh (ctx,ft))^html_render_flat ctx r
+  | TEX_LITERAL (HTMLABLEM(ft,_,sh))::r -> (html_moderate(); (font_render sh (ctx,ft))^html_render_flat ctx r)
+  | TEX_LITERAL (HTMLABLE_BIG (_,sh))::r -> (html_liberal (); sh^html_render_flat ctx r)
+  | TEX_FUN1hl (_,(f1,f2),a)::r -> f1^(html_render_flat ctx [a])^f2^html_render_flat ctx r
+  | TEX_FUN1hf (_,ff,a)::r -> (html_render_flat (new_ctx ff) [a])^html_render_flat ctx r
+  | TEX_DECLh (_,ff,a)::r -> (html_render_flat (new_ctx ff) a)^html_render_flat ctx r
+  | TEX_CURLY ls::r -> html_render_flat ctx (ls @ r)
+  | TEX_DQ (a,b)::r  -> (html_liberal ();
+                        let bs = html_render_flat ctx [b] in match html_render_size ctx a with
+                        true, s -> raise Too_difficult_for_html
+                      | false, s -> s^"<sub>"^bs^"</sub>")^html_render_flat ctx r
+  | TEX_UQ (a,b)::r  -> (html_liberal ();
+                        let bs = html_render_flat ctx [b] in match html_render_size ctx a with
+                        true, s ->  raise Too_difficult_for_html
+                      | false, s -> s^"<sup>"^bs^"</sup>")^html_render_flat ctx r
+  | TEX_FQ (a,b,c)::r -> (html_liberal ();
+                        (let bs = html_render_flat ctx [b] in let cs = html_render_flat ctx [c] in
+                         match html_render_size ctx a with
+                         true, s -> raise Too_difficult_for_html
+                       | false, s -> s^"<sub>"^bs^"</sub><sup>"^cs^"</sup>")^html_render_flat ctx r)
+  | TEX_BOX (_,s)::r -> s^html_render_flat ctx r
+  | TEX_LITERAL (TEX_ONLY _)::_ -> raise Too_difficult_for_html
+  | TEX_FUN1 _::_ -> raise Too_difficult_for_html
+  | TEX_FUN2  _::_ -> raise Too_difficult_for_html
+  | TEX_FUN2h  _::_ -> raise Too_difficult_for_html
+  | TEX_FUN2sq  _::_ -> raise Too_difficult_for_html
+  | TEX_INFIX _::_ -> raise Too_difficult_for_html
+  | TEX_INFIXh _::_ -> raise Too_difficult_for_html
+  | TEX_MATRIX _::_ -> raise Too_difficult_for_html
+  | TEX_LR _::_ -> raise Too_difficult_for_html
+  | TEX_BIG _::_ -> raise Too_difficult_for_html
+  | [] -> ""
+and html_render_size ctx = function
+    TEX_LITERAL (HTMLABLE_BIG (_,sh)) -> true,sh
+  | x -> false,html_render_flat ctx [x]
+
+let rec html_render_deep ctx = function
+    TEX_LITERAL (HTMLABLE (ft,_,sh))::r -> (html_liberal (); ("",(font_render sh (ctx,ft)),"")::html_render_deep ctx r)
+  | TEX_LITERAL (HTMLABLEM(ft,_,sh))::r -> (html_moderate(); ("",(font_render sh (ctx,ft)),"")::html_render_deep ctx r)
+  | TEX_LITERAL (HTMLABLEC(ft,_,sh))::r -> ("",(font_render sh (ctx,ft)),"")::html_render_deep ctx r
+  | TEX_LITERAL (MHTMLABLEC(ft,_,sh,_,_))::r -> ("",(font_render sh (ctx,ft)),"")::html_render_deep ctx r
+  | TEX_LITERAL (HTMLABLE_BIG (_,sh))::r -> (html_liberal (); ("",sh,"")::html_render_deep ctx r)
+  | TEX_FUN2h (_,f,a,b)::r -> (html_liberal (); (f a b)::html_render_deep ctx r)
+  | TEX_INFIXh (_,f,a,b)::r -> (html_liberal (); (f a b)::html_render_deep ctx r)
+  | TEX_CURLY ls::r -> html_render_deep ctx (ls @ r)
+  | TEX_DQ (a,b)::r  -> (let bs = html_render_flat ctx [b] in match html_render_size ctx a with
+                        true, s ->  "","<font size='+2'>"^s^"</font>",bs
+                      | false, s -> "",(s^"<sub>"^bs^"</sub>"),"")::html_render_deep ctx r
+  | TEX_UQ (a,b)::r  -> (let bs = html_render_flat ctx [b] in match html_render_size ctx a with
+                        true, s ->  bs,"<font size='+2'>"^s^"</font>",""
+                      | false, s -> "",(s^"<sup>"^bs^"</sup>"),"")::html_render_deep ctx r
+  | TEX_FQ (a,b,c)::r -> (html_liberal ();
+                        (let bs = html_render_flat ctx [b] in let cs = html_render_flat ctx [c] in
+                         match html_render_size ctx a with
+                         true, s ->  (cs,"<font size='+2'>"^s^"</font>",bs)
+                       | false, s -> ("",(s^"<sub>"^bs^"</sub><sup>"^cs^"</sup>"),""))::html_render_deep ctx r)
+  | TEX_FUN1hl (_,(f1,f2),a)::r -> ("",f1,"")::(html_render_deep ctx [a]) @ ("",f2,"")::html_render_deep ctx r
+  | TEX_FUN1hf (_,ff,a)::r -> (html_render_deep (new_ctx ff) [a]) @ html_render_deep ctx r
+  | TEX_DECLh  (_,ff,a)::r -> (html_render_deep (new_ctx ff) a) @ html_render_deep ctx r
+  | TEX_BOX (_,s)::r -> ("",s,"")::html_render_deep ctx r
+  | TEX_LITERAL (TEX_ONLY _)::_ -> raise Too_difficult_for_html
+  | TEX_FUN1 _::_ -> raise Too_difficult_for_html
+  | TEX_FUN2 _::_ -> raise Too_difficult_for_html
+  | TEX_FUN2sq  _::_ -> raise Too_difficult_for_html
+  | TEX_INFIX _::_ -> raise Too_difficult_for_html
+  | TEX_MATRIX _::_ -> raise Too_difficult_for_html
+  | TEX_LR _::_ -> raise Too_difficult_for_html
+  | TEX_BIG _::_ -> raise Too_difficult_for_html
+  | [] -> []
+
+let rec html_render_table = function
+    sf,u,d,("",a,"")::("",b,"")::r -> html_render_table (sf,u,d,(("",a^b,"")::r))
+  | sf,u,d,(("",a,"") as c)::r     -> html_render_table (c::sf,u,d,r)
+  | sf,u,d,((_,a,"") as c)::r      -> html_render_table (c::sf,true,d,r)
+  | sf,u,d,(("",a,_) as c)::r      -> html_render_table (c::sf,u,true,r)
+  | sf,u,d,((_,a,_) as c)::r       -> html_render_table (c::sf,true,true,r)
+  | sf,false,false,[]              -> mapjoin (function (u,m,d) -> m) (List.rev sf)
+  | sf,true,false,[]               -> let ustr,mstr = List.fold_left (fun (us,ms) (u,m,d) -> (us^"<td>"^u^"</td>",ms^"<td>"^u^"</td>"))
+                                       ("","") (List.rev sf) in
+                                       "<table><tr align='center' valign='bottom'>" ^ ustr ^ "</tr><tr align='center'>" ^ mstr ^ "</tr></table>"
+  | sf,false,true,[]               -> let mstr,dstr = List.fold_left (fun (ms,ds) (u,m,d) -> (ms^"<td>"^m^"</td>",ds^"<td>"^d^"</td>"))
+                                       ("","") (List.rev sf) in
+                                       "<table><tr align='center'>" ^ mstr ^ "</tr><tr align='center' valign='top'>" ^ dstr ^ "</tr></table>"
+  | sf,true,true,[]               -> let ustr,mstr,dstr = List.fold_left (fun (us,ms,ds) (u,m,d) ->
+                                       (us^"<td>"^u^"</td>",ms^"<td>"^m^"</td>",ds^"<td>"^d^"</td>")) ("","","") (List.rev sf) in
+                                       "<table><tr align='center' valign='bottom'>" ^ ustr ^ "</tr><tr align='center'>" ^ mstr ^ "</tr><tr align='center' valign='top'>" ^ dstr ^ "</tr></table>"
+
+let html_render tree = html_render_table ([],false,false,html_render_deep CTX_NORMAL tree)
+
+let render tree = try Some (html_render tree) with _ -> None
diff --git a/math/html.mli b/math/html.mli
new file mode 100644 (file)
index 0000000..00b41cf
--- /dev/null
@@ -0,0 +1,5 @@
+val render : Tex.t list -> string option
+val html_render : Tex.t list -> string
+
+type conservativeness_t = CONSERVATIVE | MODERATE | LIBERAL
+val conservativeness : conservativeness_t ref
diff --git a/math/lexer.mll b/math/lexer.mll
new file mode 100644 (file)
index 0000000..e5bb1dd
--- /dev/null
@@ -0,0 +1,93 @@
+{
+    open Parser
+    open Render_info
+    open Tex
+}
+let space = [' ' '\t' '\n' '\r']
+let alpha = ['a'-'z' 'A'-'Z']
+let literal_id = ['a'-'z' 'A'-'Z']
+let literal_mn = ['0'-'9']
+let literal_uf_lt = [',' ':' ';' '?' '!' '\'']
+let delimiter_uf_lt = ['(' ')' '.']
+let literal_uf_op = ['+' '-' '*' '=']
+let delimiter_uf_op = ['/' '|']
+let boxchars  = ['0'-'9' 'a'-'z' 'A'-'Z' '+' '-' '*' ',' '=' '(' ')' ':' '/' ';' '?' '.' '!' ' ' '\128'-'\255']
+let aboxchars = ['0'-'9' 'a'-'z' 'A'-'Z' '+' '-' '*' ',' '=' '(' ')' ':' '/' ';' '?' '.' '!' ' ']
+
+rule token = parse
+    space +                    { token lexbuf }
+  | "\\mbox" space * '{' aboxchars + '}'
+                               { let str = Lexing.lexeme lexbuf in
+                                 let n = String.index str '{' + 1 in
+                                 BOX ("\\mbox", String.sub str n (String.length str - n - 1)) }
+  | "\\hbox" space * '{' aboxchars + '}'
+                               { let str = Lexing.lexeme lexbuf in
+                                 let n = String.index str '{' + 1 in
+                                 BOX ("\\hbox", String.sub str n (String.length str - n - 1)) }
+  | "\\vbox" space * '{' aboxchars + '}'
+                               { let str = Lexing.lexeme lexbuf in
+                                 let n = String.index str '{' + 1 in
+                                 BOX ("\\vbox", String.sub str n (String.length str - n - 1)) }
+  | "\\mbox" space * '{' boxchars + '}'
+                               { let str = Lexing.lexeme lexbuf in
+                                 let n = String.index str '{' + 1 in
+                                 Texutil.tex_use_nonascii();
+                                 BOX ("\\mbox", String.sub str n (String.length str - n - 1)) }
+  | "\\hbox" space * '{' boxchars + '}'
+                               { let str = Lexing.lexeme lexbuf in
+                                 let n = String.index str '{' + 1 in
+                                 Texutil.tex_use_nonascii();
+                                 BOX ("\\hbox", String.sub str n (String.length str - n - 1)) }
+  | "\\vbox" space * '{' boxchars + '}'
+                               { let str = Lexing.lexeme lexbuf in
+                                 let n = String.index str '{' + 1 in
+                                 Texutil.tex_use_nonascii();
+                                 BOX ("\\vbox", String.sub str n (String.length str - n - 1)) }
+  | literal_id                 { let str = Lexing.lexeme lexbuf in LITERAL (MHTMLABLEC (FONT_IT, str,str,MI,str)) }
+  | literal_mn                 { let str = Lexing.lexeme lexbuf in LITERAL (MHTMLABLEC (FONT_RM, str,str,MN,str)) }
+  | literal_uf_lt              { let str = Lexing.lexeme lexbuf in LITERAL (HTMLABLEC (FONT_UFH, str,str)) }
+  | delimiter_uf_lt            { let str = Lexing.lexeme lexbuf in DELIMITER (HTMLABLEC (FONT_UFH, str,str)) }
+  | "-"                                { let str = Lexing.lexeme lexbuf in LITERAL (MHTMLABLEC (FONT_UFH,"-"," &minus; ",MO,str))}
+  | literal_uf_op              { let str = Lexing.lexeme lexbuf in LITERAL (MHTMLABLEC (FONT_UFH, str," "^str^" ",MO,str)) }
+  | delimiter_uf_op            { let str = Lexing.lexeme lexbuf in DELIMITER (MHTMLABLEC (FONT_UFH, str," "^str^" ",MO,str)) }
+  | "\\" alpha +               { Texutil.find (Lexing.lexeme lexbuf) }
+  | "\\sqrt" space * "["       { FUN_AR1opt "\\sqrt" }
+  | "\\,"                      { LITERAL (HTMLABLE (FONT_UF, "\\,","&nbsp;")) }
+  | "\\ "                      { LITERAL (HTMLABLE (FONT_UF, "\\ ","&nbsp;")) }
+  | "\\;"                      { LITERAL (HTMLABLE (FONT_UF, "\\;","&nbsp;")) }
+  | "\\!"                      { LITERAL (TEX_ONLY "\\!") }
+  | "\\{"                      { DELIMITER (HTMLABLEC(FONT_UFH,"\\{","{")) }
+  | "\\}"                      { DELIMITER (HTMLABLEC(FONT_UFH,"\\}","}")) }
+  | "\\|"                      { DELIMITER (HTMLABLE (FONT_UFH,"\\|","||")) }
+  | "\\_"                      { LITERAL (HTMLABLEC(FONT_UFH,"\\_","_")) }
+  | "\\#"                      { LITERAL (HTMLABLE (FONT_UFH,"\\#","#")) }
+  | "\\%"                      { LITERAL (HTMLABLE (FONT_UFH,"\\%","%")) }
+  | "\\$"                      { LITERAL (HTMLABLE (FONT_UFH,"\\$","$")) }
+  | "&"                                { NEXT_CELL }
+  | "\\\\"                     { NEXT_ROW }
+  | "\\begin{matrix}"          { Texutil.tex_use_ams(); BEGIN__MATRIX }
+  | "\\end{matrix}"            { END__MATRIX }
+  | "\\begin{pmatrix}"         { Texutil.tex_use_ams(); BEGIN_PMATRIX }
+  | "\\end{pmatrix}"           { END_PMATRIX }
+  | "\\begin{bmatrix}"         { Texutil.tex_use_ams(); BEGIN_BMATRIX }
+  | "\\end{bmatrix}"           { END_BMATRIX }
+  | "\\begin{Bmatrix}"         { Texutil.tex_use_ams(); BEGIN_BBMATRIX }
+  | "\\end{Bmatrix}"           { END_BBMATRIX }
+  | "\\begin{vmatrix}"         { Texutil.tex_use_ams(); BEGIN_VMATRIX }
+  | "\\end{vmatrix}"           { END_VMATRIX }
+  | "\\begin{Vmatrix}"         { Texutil.tex_use_ams(); BEGIN_VVMATRIX }
+  | "\\end{Vmatrix}"           { END_VVMATRIX }
+  | "\\begin{cases}"           { Texutil.tex_use_ams(); BEGIN_CASES }
+  | "\\end{cases}"             { END_CASES }
+  | '>'                                { LITERAL (HTMLABLEC(FONT_UFH,">"," &gt; ")) }
+  | '<'                                { LITERAL (HTMLABLEC(FONT_UFH,"<"," &lt; ")) }
+  | '%'                                { LITERAL (HTMLABLEC(FONT_UFH,"\\%","%")) }
+  | '$'                                { LITERAL (HTMLABLEC(FONT_UFH,"\\$","$")) }
+  | '~'                                { LITERAL (HTMLABLE (FONT_UF, "~","&nbsp;")) }
+  | '['                                { DELIMITER (HTMLABLEC(FONT_UFH,"[","[")) }
+  | ']'                                { SQ_CLOSE }
+  | '{'                                { CURLY_OPEN }
+  | '}'                                { CURLY_CLOSE }
+  | '^'                                { SUP }
+  | '_'                                { SUB }
+  | eof                                { EOF }
diff --git a/math/mathml.ml b/math/mathml.ml
new file mode 100644 (file)
index 0000000..b6c76af
--- /dev/null
@@ -0,0 +1,20 @@
+open Tex
+open Render_info
+
+type t = TREE_MN of string | TREE_MO of string | TREE_MI of string
+
+let rec make_mathml_tree = function
+    TREE_MN a::otr,TEX_LITERAL(MHTMLABLEC(_,_,_,MN,b))::itr -> make_mathml_tree(TREE_MN (a^b)::otr,itr)
+  | otr,TEX_LITERAL(MHTMLABLEC(_,_,_,MN,a))::itr -> make_mathml_tree(TREE_MN a::otr,itr)
+  | otr,TEX_LITERAL(MHTMLABLEC(_,_,_,MO,a))::itr -> make_mathml_tree(TREE_MO a::otr,itr)
+  | otr,TEX_LITERAL(MHTMLABLEC(_,_,_,MI,a))::itr -> make_mathml_tree(TREE_MI a::otr,itr)
+  | otr,TEX_CURLY(crl)::itr -> make_mathml_tree(otr,crl@itr)
+  | otr,[] -> List.rev otr
+  | _ -> failwith "failed to render mathml"
+
+let render_mathml_tree = function
+    TREE_MN s -> "<mn>"^s^"</mn>"
+  | TREE_MI s -> "<mi>"^s^"</mi>"
+  | TREE_MO s -> "<mo>"^s^"</mo>"
+
+let render tree = try Some (Util.mapjoin render_mathml_tree (make_mathml_tree ([],tree))) with _ -> None
diff --git a/math/mathml.mli b/math/mathml.mli
new file mode 100644 (file)
index 0000000..fcc2cd4
--- /dev/null
@@ -0,0 +1 @@
+val render : Tex.t list -> string option
diff --git a/math/parser.mly b/math/parser.mly
new file mode 100644 (file)
index 0000000..4787db3
--- /dev/null
@@ -0,0 +1,103 @@
+%{
+    open Tex
+    open Render_info
+    
+    let sq_close_ri = HTMLABLEC(FONT_UFH,"]", "]")
+%}
+%token <Render_info.t> LITERAL DELIMITER
+%token <string> FUN_AR2 FUN_INFIX FUN_AR1 DECL FUN_AR1opt BIG
+%token <string*string> BOX
+%token <string*(string*string)> FUN_AR1hl
+%token <string*Render_info.font_force> FUN_AR1hf DECLh
+%token <string*(Tex.t->Tex.t->string*string*string)> FUN_AR2h
+%token <string*(Tex.t list->Tex.t list->string*string*string)> FUN_INFIXh
+%token EOF CURLY_OPEN CURLY_CLOSE SUB SUP SQ_CLOSE NEXT_CELL NEXT_ROW
+%token BEGIN__MATRIX BEGIN_PMATRIX BEGIN_BMATRIX BEGIN_BBMATRIX BEGIN_VMATRIX BEGIN_VVMATRIX BEGIN_CASES
+%token END__MATRIX END_PMATRIX END_BMATRIX END_BBMATRIX END_VMATRIX END_VVMATRIX END_CASES
+%token LEFT RIGHT
+
+%type <Tex.t list> tex_expr
+%start tex_expr
+
+%%
+tex_expr:
+    expr EOF                   { $1 }
+  | ne_expr FUN_INFIX ne_expr EOF
+                               { [TEX_INFIX($2,$1,$3)] }
+  | ne_expr FUN_INFIXh ne_expr EOF
+                               { let t,h=$2 in [TEX_INFIXh(t,h,$1,$3)] }
+expr:
+    /* */                      { [] }
+  | ne_expr                    { $1 }
+ne_expr:
+    lit_aq expr                        { $1 :: $2 }
+  | litsq_aq expr              { $1 :: $2 }
+  | DECLh expr                 { let t,h = $1 in [TEX_DECLh(t,h,$2)] }
+litsq_aq:
+    litsq_zq                   { $1 }
+  | litsq_dq                   { let base,downi = $1 in TEX_DQ(base,downi) }
+  | litsq_uq                   { let base,upi = $1   in TEX_UQ(base,upi)}
+  | litsq_fq                   { $1 }
+litsq_fq:
+    litsq_dq SUP lit           { let base,downi = $1 in TEX_FQ(base,downi,$3) }
+  | litsq_uq SUB lit           { let base,upi = $1   in TEX_FQ(base,$3,upi) }
+litsq_uq:
+    litsq_zq SUP lit           { $1,$3 }
+litsq_dq:
+    litsq_zq SUB lit           { $1,$3 }
+litsq_zq:
+  | SQ_CLOSE                   { TEX_LITERAL sq_close_ri }
+expr_nosqc:
+    /* */                      { [] }
+  | lit_aq expr_nosqc          { $1 :: $2 }
+lit_aq:
+    lit                                { $1 }
+  | lit_dq                     { let base,downi = $1 in TEX_DQ(base,downi) }
+  | lit_uq                     { let base,upi = $1   in TEX_UQ(base,upi)}
+  | lit_fq                     { $1 }
+lit_fq:
+    lit_dq SUP lit             { let base,downi = $1 in TEX_FQ(base,downi,$3) }
+  | lit_uq SUB lit             { let base,upi = $1   in TEX_FQ(base,$3,upi) }
+lit_uq:
+    lit SUP lit                        { $1,$3 }
+lit_dq:
+    lit SUB lit                        { $1,$3 }
+left:
+    LEFT DELIMITER             { $2 }
+  | LEFT SQ_CLOSE              { sq_close_ri }
+right:
+    RIGHT DELIMITER            { $2 }
+  | RIGHT SQ_CLOSE             { sq_close_ri }
+lit:
+    LITERAL                    { TEX_LITERAL $1 }
+  | DELIMITER                  { TEX_LITERAL $1 }
+  | BIG DELIMITER              { TEX_BIG ($1,$2) }
+  | BIG SQ_CLOSE               { TEX_BIG ($1,sq_close_ri) }
+  | left expr right            { TEX_LR ($1,$3,$2) }
+  | FUN_AR1 lit                        { TEX_FUN1($1,$2) }
+  | FUN_AR1hl lit              { let t,h=$1 in TEX_FUN1hl(t,h,$2) }
+  | FUN_AR1hf lit              { let t,h=$1 in TEX_FUN1hf(t,h,$2) }
+  | FUN_AR1opt expr_nosqc SQ_CLOSE lit { TEX_FUN2sq($1,TEX_CURLY $2,$4) }
+  | FUN_AR2 lit lit            { TEX_FUN2($1,$2,$3) }
+  | FUN_AR2h lit lit           { let t,h=$1 in TEX_FUN2h(t,h,$2,$3) }
+  | BOX                                { let bt,s = $1 in TEX_BOX (bt,s) }
+  | CURLY_OPEN expr CURLY_CLOSE
+                               { TEX_CURLY $2 }
+  | CURLY_OPEN ne_expr FUN_INFIX ne_expr CURLY_CLOSE
+                               { TEX_INFIX($3,$2,$4) }
+  | CURLY_OPEN ne_expr FUN_INFIXh ne_expr CURLY_CLOSE
+                               { let t,h=$3 in TEX_INFIXh(t,h,$2,$4) }
+  | BEGIN__MATRIX  matrix END__MATRIX  { TEX_MATRIX ("matrix", $2) }
+  | BEGIN_PMATRIX  matrix END_PMATRIX  { TEX_MATRIX ("pmatrix", $2) }
+  | BEGIN_BMATRIX  matrix END_BMATRIX  { TEX_MATRIX ("bmatrix", $2) }
+  | BEGIN_BBMATRIX matrix END_BBMATRIX { TEX_MATRIX ("Bmatrix", $2) }
+  | BEGIN_VMATRIX  matrix END_VMATRIX  { TEX_MATRIX ("vmatrix", $2) }
+  | BEGIN_VVMATRIX matrix END_VVMATRIX { TEX_MATRIX ("Vmatrix", $2) }
+  | BEGIN_CASES    matrix END_CASES    { TEX_MATRIX ("cases", $2) }
+matrix:
+    line                       { [$1] }
+  | line NEXT_ROW matrix       { $1::$3 }
+line:
+    expr                       { [$1] }
+  | expr NEXT_CELL line                { $1::$3 }
+;;
diff --git a/math/render.ml b/math/render.ml
new file mode 100644 (file)
index 0000000..f070a91
--- /dev/null
@@ -0,0 +1,33 @@
+let cmd_dvips tmpprefix = "dvips -R -E " ^ tmpprefix ^ ".dvi -f >" ^ tmpprefix ^ ".ps"
+let cmd_latex tmpprefix = "latex " ^ tmpprefix ^ ".tex >/dev/null"
+(* Putting -transparent white in converts arguments will sort-of give you transperancy *)
+let cmd_convert tmpprefix finalpath = "convert -quality 100 -density 120 " ^ tmpprefix ^ ".ps " ^ finalpath ^ " >/dev/null 2>/dev/null"
+
+exception ExternalCommandFailure of string
+
+let render tmppath finalpath outtex md5 =
+    let tmpprefix0 = (string_of_int (Unix.getpid ()))^"_"^md5 in
+    let tmpprefix = (tmppath^"/"^tmpprefix0) in
+    let unlink_all () =
+      begin
+        (* Commenting this block out will aid in debugging *)
+       Sys.remove (tmpprefix ^ ".dvi");
+       Sys.remove (tmpprefix ^ ".aux");
+       Sys.remove (tmpprefix ^ ".log");
+        Sys.remove (tmpprefix ^ ".tex");
+       Sys.remove (tmpprefix ^ ".ps");
+      end in
+    let f = (Util.open_out_unless_exists (tmpprefix ^ ".tex")) in
+      begin
+       output_string f (Texutil.get_preface ());
+       output_string f outtex;
+       output_string f (Texutil.get_footer ());
+       close_out f;
+       if Util.run_in_other_directory tmppath (cmd_latex tmpprefix0) != 0
+       then (unlink_all (); raise (ExternalCommandFailure "latex"))
+       else if (Sys.command (cmd_dvips tmpprefix) != 0)
+       then (unlink_all (); raise (ExternalCommandFailure "dvips"))
+       else if (Sys.command (cmd_convert tmpprefix (finalpath^"/"^md5^".png")) != 0)
+       then (unlink_all (); raise (ExternalCommandFailure "convert"))
+       else unlink_all ()
+      end
diff --git a/math/render_info.mli b/math/render_info.mli
new file mode 100644 (file)
index 0000000..d5e7fde
--- /dev/null
@@ -0,0 +1,20 @@
+type font_force =
+    FONTFORCE_IT
+  | FONTFORCE_RM
+type font_class =
+    FONT_IT  (* IT default, may be forced to be RM *)
+  | FONT_RM  (* RM default, may be forced to be IT *)
+  | FONT_UF  (* not affected by IT/RM setting *)
+  | FONT_RTI (* RM - any, IT - not available in HTML *)
+  | FONT_UFH (* in TeX UF, in HTML RM *)
+type math_class =
+    MN
+  | MI
+  | MO
+type t =
+      HTMLABLEC of font_class * string * string
+    | HTMLABLEM of font_class * string * string
+    | HTMLABLE of font_class * string * string
+    | MHTMLABLEC of font_class * string * string * math_class * string
+    | HTMLABLE_BIG of string * string
+    | TEX_ONLY of string
diff --git a/math/tex.mli b/math/tex.mli
new file mode 100644 (file)
index 0000000..9e6013d
--- /dev/null
@@ -0,0 +1,19 @@
+type t =
+      TEX_LITERAL of Render_info.t
+    | TEX_CURLY of t list
+    | TEX_FQ of t * t * t
+    | TEX_DQ of t * t
+    | TEX_UQ of t * t
+    | TEX_LR of Render_info.t * Render_info.t * t list
+    | TEX_BOX of string * string
+    | TEX_BIG of string * Render_info.t
+    | TEX_FUN1 of string * t
+    | TEX_FUN2 of string * t * t
+    | TEX_INFIX of string * t list * t list
+    | TEX_FUN2sq of string * t * t
+    | TEX_FUN1hl  of string * (string * string) * t
+    | TEX_FUN1hf  of string * Render_info.font_force * t
+    | TEX_FUN2h  of string * (t -> t -> string * string * string) * t * t
+    | TEX_INFIXh of string * (t list -> t list -> string * string * string) * t list * t list
+    | TEX_MATRIX of string * t list list list
+    | TEX_DECLh  of string * Render_info.font_force * t list
diff --git a/math/texutil.ml b/math/texutil.ml
new file mode 100644 (file)
index 0000000..be49e34
--- /dev/null
@@ -0,0 +1,472 @@
+open Parser
+open Render_info
+open Tex
+open Util
+
+let tex_part = function
+    HTMLABLE (_,t,_) -> t
+  | HTMLABLEM (_,t,_) -> t
+  | HTMLABLEC (_,t,_) -> t
+  | MHTMLABLEC (_,t,_,_,_) -> t
+  | HTMLABLE_BIG (t,_) -> t
+  | TEX_ONLY t -> t
+let rec render_tex = function
+    TEX_FQ (a,b,c) -> (render_tex a) ^ "_{" ^ (render_tex  b) ^ "}^{" ^ (render_tex  c) ^ "}"
+  | TEX_DQ (a,b) -> (render_tex a) ^ "_{" ^ (render_tex  b) ^ "}"
+  | TEX_UQ (a,b) -> (render_tex a) ^ "^{" ^ (render_tex  b) ^ "}"
+  | TEX_LITERAL s -> tex_part s
+  | TEX_FUN1 (f,a) -> "{" ^ f ^ " " ^ (render_tex a) ^ "}"
+  | TEX_FUN1hl (f,_,a) -> "{" ^ f ^ " " ^ (render_tex a) ^ "}"
+  | TEX_FUN1hf (f,_,a) -> "{" ^ f ^ " " ^ (render_tex a) ^ "}"
+  | TEX_DECLh (f,_,a) -> "{" ^ f ^ "{" ^ (mapjoin render_tex a) ^ "}}"
+  | TEX_FUN2 (f,a,b) -> "{" ^ f ^ " " ^ (render_tex a) ^ (render_tex b) ^ "}"
+  | TEX_FUN2h (f,_,a,b) -> "{" ^ f ^ " " ^ (render_tex a) ^ (render_tex b) ^ "}"
+  | TEX_FUN2sq (f,a,b) -> "{" ^ f ^ "[ " ^ (render_tex a) ^ "]" ^ (render_tex b) ^ "}"
+  | TEX_CURLY (tl) -> "{" ^ (mapjoin render_tex tl) ^ "}"
+  | TEX_INFIX (s,ll,rl) -> "{" ^ (mapjoin render_tex ll) ^ " " ^ s ^ "" ^ (mapjoin render_tex rl) ^ "}"
+  | TEX_INFIXh (s,_,ll,rl) -> "{" ^ (mapjoin render_tex ll) ^ " " ^ s ^ "" ^ (mapjoin render_tex rl) ^ "}"
+  | TEX_BOX (bt,s) -> "{"^bt^"{" ^ s ^ "}}"
+  | TEX_BIG (bt,d) -> "{"^bt^(tex_part d)^"}"
+  | TEX_MATRIX (t,rows) -> "{\\begin{"^t^"}"^(mapjoine "\\\\" (mapjoine "&" (mapjoin render_tex)) rows)^"\\end{"^t^"}}"
+  | TEX_LR (l,r,tl) -> "\\left "^(tex_part l)^(mapjoin render_tex tl)^"\\right "^(tex_part r)
+
+(* Dynamic loading*)
+type encoding_t = LATIN1 | LATIN2 | UTF8
+
+let modules_ams = ref false
+let modules_nonascii = ref false
+let modules_encoding = ref UTF8
+
+let tex_use_ams ()     = modules_ams := true
+let tex_use_nonascii () = modules_nonascii := true
+let tex_mod_reset ()   = (modules_ams := false; modules_nonascii := false; modules_encoding := UTF8)
+
+let get_encoding = function
+    UTF8 -> "\\usepackage{ucs}\n\\usepackage[utf8]{inputenc}\n"
+  | LATIN1 -> "\\usepackage[latin1]{inputenc}\n"
+  | LATIN2 -> "\\usepackage[latin2]{inputenc}\n"
+
+let get_preface ()  = "\\nonstopmode\n\\documentclass[12pt]{article}\n" ^
+              (if !modules_nonascii then get_encoding !modules_encoding else "") ^
+              (if !modules_ams then "\\usepackage{amsmath}\n\\usepackage{amsfonts}\n\\usepackage{amssymb}\n" else "") ^
+              "\\pagestyle{empty}\n\\begin{document}\n$$\n"
+let get_footer  ()  = "\n$$\n\\end{document}\n"
+
+let set_encoding = function
+    "ISO-8859-1" -> modules_encoding := LATIN1
+  | "iso-8859-1" -> modules_encoding := LATIN1
+  | "ISO-8859-2" -> modules_encoding := LATIN2
+  | _ -> modules_encoding := UTF8
+
+(* Turn that into hash table lookup *)
+exception Illegal_tex_function of string
+
+let find = function
+      "\\alpha"            -> LITERAL (HTMLABLEC (FONT_UF,  "\\alpha ", "&alpha;"))
+    | "\\Alpha"            -> LITERAL (HTMLABLEC (FONT_RTI, "A", "&Alpha;"))
+    | "\\beta"             -> LITERAL (HTMLABLEC (FONT_UF,  "\\beta ",  "&beta;"))
+    | "\\Beta"             -> LITERAL (HTMLABLEC (FONT_RTI, "B",  "&Beta;"))
+    | "\\gamma"            -> LITERAL (HTMLABLEC (FONT_UF,  "\\gamma ", "&gamma;"))
+    | "\\Gamma"            -> LITERAL (HTMLABLEC (FONT_RTI, "\\Gamma ", "&Gamma;"))
+    | "\\delta"            -> LITERAL (HTMLABLEC (FONT_UF,  "\\delta ", "&delta;"))
+    | "\\Delta"            -> LITERAL (HTMLABLEC (FONT_RTI, "\\Delta ", "&Delta;"))
+    | "\\epsilon"          -> LITERAL (HTMLABLEC (FONT_UF,  "\\epsilon ", "&epsilon;"))
+    | "\\Epsilon"          -> LITERAL (HTMLABLEC (FONT_RTI, "E", "&Epsilon;"))
+    | "\\varepsilon"       -> LITERAL (TEX_ONLY "\\varepsilon ")
+    | "\\zeta"             -> LITERAL (HTMLABLEC (FONT_UF,  "\\zeta ", "&zeta;"))
+    | "\\Zeta"             -> LITERAL (HTMLABLEC (FONT_RTI, "Z", "&Zeta;"))
+    | "\\eta"              -> LITERAL (HTMLABLEC (FONT_UF,  "\\eta ", "&eta;"))
+    | "\\Eta"              -> LITERAL (HTMLABLEC (FONT_RTI, "H", "&Eta;"))
+    | "\\theta"            -> LITERAL (HTMLABLEC (FONT_UF,  "\\theta ", "&theta;"))
+    | "\\Theta"            -> LITERAL (HTMLABLEC (FONT_RTI, "\\Theta ", "&Theta;"))
+    | "\\vartheta"         -> LITERAL (HTMLABLE  (FONT_UF,  "\\vartheta ", "&thetasym;"))
+    | "\\thetasym"         -> LITERAL (HTMLABLE  (FONT_UF,  "\\vartheta ", "&thetasym;"))
+    | "\\iota"             -> LITERAL (HTMLABLEC (FONT_UF,  "\\iota ", "&iota;"))
+    | "\\Iota"             -> LITERAL (HTMLABLEC (FONT_RTI, "I", "&Iota;"))
+    | "\\kappa"            -> LITERAL (HTMLABLEC (FONT_UF,  "\\kappa ", "&kappa;"))
+    | "\\Kappa"            -> LITERAL (HTMLABLEC (FONT_RTI, "K", "&Kappa;"))
+    | "\\lambda"           -> LITERAL (HTMLABLEC (FONT_UF,  "\\lambda ", "&lambda;"))
+    | "\\Lambda"           -> LITERAL (HTMLABLEC (FONT_RTI, "\\Lambda ", "&Lambda;"))
+    | "\\mu"               -> LITERAL (HTMLABLEC (FONT_UF,  "\\mu ", "&mu;"))
+    | "\\Mu"               -> LITERAL (HTMLABLEC (FONT_RTI, "M", "&Mu;"))
+    | "\\nu"               -> LITERAL (HTMLABLEC (FONT_UF,  "\\nu ", "&nu;"))
+    | "\\Nu"               -> LITERAL (HTMLABLEC (FONT_RTI, "N", "&Nu;"))
+    | "\\pi"               -> LITERAL (HTMLABLEC (FONT_UF,  "\\pi ", "&pi;"))
+    | "\\Pi"               -> LITERAL (HTMLABLEC (FONT_RTI, "\\Pi ", "&Pi;"))
+    | "\\varpi"            -> LITERAL (TEX_ONLY "\\varpi ")
+    | "\\rho"              -> LITERAL (HTMLABLEC (FONT_UF,  "\\rho ", "&rho;"))
+    | "\\Rho"              -> LITERAL (HTMLABLEC (FONT_RTI, "P", "&Rho;"))
+    | "\\varrho"           -> LITERAL (TEX_ONLY "\\varrho ")
+    | "\\sigma"            -> LITERAL (HTMLABLEC (FONT_UF,  "\\sigma ", "&sigma;"))
+    | "\\Sigma"            -> LITERAL (HTMLABLEC (FONT_RTI, "\\Sigma ", "&Sigma;"))
+    | "\\varsigma"         -> LITERAL (TEX_ONLY "\\varsigma ")
+    | "\\tau"              -> LITERAL (HTMLABLEC (FONT_UF,  "\\tau ", "&tau;"))
+    | "\\Tau"              -> LITERAL (HTMLABLEC (FONT_RTI, "T", "&Tau;"))
+    | "\\upsilon"          -> LITERAL (HTMLABLEC (FONT_UF,  "\\upsilon ", "&upsilon;"))
+    | "\\Upsilon"          -> LITERAL (HTMLABLEC (FONT_RTI, "\\Upsilon ", "&Upsilon;"))
+    | "\\phi"              -> LITERAL (HTMLABLEC (FONT_UF,  "\\phi ", "&phi;"))
+    | "\\Phi"              -> LITERAL (HTMLABLEC (FONT_RTI, "\\Phi ", "&Phi;"))
+    | "\\varphi"           -> LITERAL (TEX_ONLY "\\varphi ")
+    | "\\chi"              -> LITERAL (HTMLABLEC (FONT_UF,  "\\chi ", "&chi;"))
+    | "\\Chi"              -> LITERAL (HTMLABLEC (FONT_RTI, "X", "&Chi;"))
+    | "\\psi"              -> LITERAL (HTMLABLEC (FONT_UF,  "\\psi ", "&psi;"))
+    | "\\Psi"              -> LITERAL (HTMLABLEC (FONT_RTI, "\\Psi ", "&Psi;"))
+    | "\\omega"            -> LITERAL (HTMLABLEC (FONT_UF,  "\\omega ", "&omega;"))
+    | "\\Omega"            -> LITERAL (HTMLABLEC (FONT_RTI, "\\Omega ", "&Omega;"))
+    | "\\xi"               -> LITERAL (HTMLABLEC (FONT_UF,  "\\xi ", "&xi;"))
+    | "\\Xi"               -> LITERAL (HTMLABLEC (FONT_RTI, "\\Xi ", "&Xi;"))
+    | "\\aleph"            -> LITERAL (HTMLABLE  (FONT_UF,  "\\aleph ", "&alefsym;"))
+    | "\\alef"             -> LITERAL (HTMLABLE  (FONT_UF,  "\\aleph ", "&alefsym;"))
+    | "\\alefsym"          -> LITERAL (HTMLABLE  (FONT_UF,  "\\aleph ", "&alefsym;"))
+    | "\\larr"             -> LITERAL (HTMLABLEM (FONT_UF,  "\\leftarrow ", "&larr;"))
+    | "\\leftarrow"        -> LITERAL (HTMLABLEM (FONT_UF,  "\\leftarrow ", "&larr;"))
+    | "\\rarr"             -> LITERAL (HTMLABLEM (FONT_UF,  "\\rightarrow ", "&rarr;"))
+    | "\\to"               -> LITERAL (HTMLABLEM (FONT_UF,  "\\to ", "&rarr;"))
+    | "\\gets"             -> LITERAL (HTMLABLEM (FONT_UF,  "\\gets ", "&larr;"))
+    | "\\rightarrow"       -> LITERAL (HTMLABLEM (FONT_UF,  "\\rightarrow ", "&rarr;"))
+    | "\\longleftarrow"    -> LITERAL (HTMLABLE  (FONT_UF,  "\\longleftarrow ", "&larr;"))
+    | "\\longrightarrow"   -> LITERAL (HTMLABLE  (FONT_UF,  "\\longrightarrow ", "&rarr;"))
+    | "\\Larr"             -> LITERAL (HTMLABLE  (FONT_UF,  "\\Leftarrow ", "&lArr;"))
+    | "\\lArr"             -> LITERAL (HTMLABLE  (FONT_UF,  "\\Leftarrow ", "&lArr;"))
+    | "\\Leftarrow"        -> LITERAL (HTMLABLE  (FONT_UF,  "\\Leftarrow ", "&lArr;"))
+    | "\\Rarr"             -> LITERAL (HTMLABLE  (FONT_UF,  "\\Rightarrow ", "&rArr;"))
+    | "\\rArr"             -> LITERAL (HTMLABLE  (FONT_UF,  "\\Rightarrow ", "&rArr;"))
+    | "\\Rightarrow"       -> LITERAL (HTMLABLEM (FONT_UF,  "\\Rightarrow ", "&rArr;"))
+    | "\\mapsto"           -> LITERAL (HTMLABLE  (FONT_UF,  "\\mapsto ", "&rarr;"))
+    | "\\longmapsto"       -> LITERAL (HTMLABLE  (FONT_UF,  "\\longmapsto ", "&rarr;"))
+    | "\\Longleftarrow"    -> LITERAL (HTMLABLE  (FONT_UF,  "\\Longleftarrow ", "&lArr;"))
+    | "\\Longrightarrow"   -> LITERAL (HTMLABLE  (FONT_UF,  "\\Longrightarrow ", "&rArr;"))
+    | "\\uarr"             -> DELIMITER (HTMLABLEM (FONT_UF,  "\\uparrow ", "&uarr;"))
+    | "\\uparrow"          -> DELIMITER (HTMLABLEM (FONT_UF,  "\\uparrow ", "&uarr;"))
+    | "\\uArr"             -> DELIMITER (HTMLABLE  (FONT_UF,  "\\Uparrow ", "&uArr;"))
+    | "\\Uarr"             -> DELIMITER (HTMLABLE  (FONT_UF,  "\\Uparrow ", "&uArr;"))
+    | "\\Uparrow"          -> DELIMITER (HTMLABLE  (FONT_UF,  "\\Uparrow ", "&uArr;"))
+    | "\\darr"             -> DELIMITER (HTMLABLEM (FONT_UF,  "\\downarrow ", "&darr;"))
+    | "\\downarrow"        -> DELIMITER (HTMLABLEM (FONT_UF,  "\\downarrow ", "&darr;"))
+    | "\\dArr"             -> DELIMITER (HTMLABLE  (FONT_UF,  "\\Downarrow ", "&dArr;"))
+    | "\\Darr"             -> DELIMITER (HTMLABLE  (FONT_UF,  "\\Downarrow ", "&dArr;"))
+    | "\\Downarrow"        -> DELIMITER (HTMLABLE  (FONT_UF,  "\\Downarrow ", "&dArr;"))
+    | "\\updownarrow"      -> DELIMITER (TEX_ONLY "\\updownarrow ")
+    | "\\Updownarrow"      -> DELIMITER (TEX_ONLY "\\Updownarrow ")
+    | "\\leftrightarrow"   -> LITERAL (HTMLABLE  (FONT_UF,  "\\leftrightarrow ", "&harr;"))
+    | "\\lrarr"            -> LITERAL (HTMLABLE  (FONT_UF,  "\\leftrightarrow ", "&harr;"))
+    | "\\harr"             -> LITERAL (HTMLABLE  (FONT_UF,  "\\leftrightarrow ", "&harr;"))
+    | "\\Leftrightarrow"   -> LITERAL (HTMLABLE  (FONT_UF,  "\\Leftrightarrow ", "&hArr;"))
+    | "\\Lrarr"            -> LITERAL (HTMLABLE  (FONT_UF,  "\\Leftrightarrow ", "&hArr;"))
+    | "\\Harr"             -> LITERAL (HTMLABLE  (FONT_UF,  "\\Leftrightarrow ", "&hArr;"))
+    | "\\lrArr"            -> LITERAL (HTMLABLE  (FONT_UF,  "\\Leftrightarrow ", "&hArr;"))
+    | "\\hAar"             -> LITERAL (HTMLABLE  (FONT_UF,  "\\Leftrightarrow ", "&hArr;"))
+    | "\\Longleftrightarrow"->LITERAL (HTMLABLE  (FONT_UF,  "\\Longleftrightarrow ", "&harr;"))
+    | "\\iff"              -> LITERAL (HTMLABLE  (FONT_UF,  "\\iff ", "&harr;"))
+    | "\\ll"              -> LITERAL (TEX_ONLY "\\ll ")
+    | "\\gg"              -> LITERAL (TEX_ONLY "\\gg ")
+    | "\\div"             -> LITERAL (TEX_ONLY "\\div ")
+    | "\\searrow"          -> LITERAL (TEX_ONLY "\\searrow ")
+    | "\\nearrow"          -> LITERAL (TEX_ONLY "\\nearrow ")
+    | "\\swarrow"          -> LITERAL (TEX_ONLY "\\swarrow ")
+    | "\\nwarrow"          -> LITERAL (TEX_ONLY "\\nwarrow ")
+    | "\\sim"              -> LITERAL (TEX_ONLY "\\sim ")
+    | "\\simeq"            -> LITERAL (TEX_ONLY "\\simeq ")
+    | "\\star"             -> LITERAL (TEX_ONLY "\\star ")
+    | "\\ell"              -> LITERAL (TEX_ONLY "\\ell ")
+    | "\\P"                -> LITERAL (TEX_ONLY "\\P ")
+    | "\\smile"            -> LITERAL (TEX_ONLY "\\smile ")
+    | "\\frown"            -> LITERAL (TEX_ONLY "\\frown ")
+    | "\\bigcap"           -> LITERAL (TEX_ONLY "\\bigcap ")
+    | "\\bigodot"          -> LITERAL (TEX_ONLY "\\bigodot ")
+    | "\\bigcup"           -> LITERAL (TEX_ONLY "\\bigcup ")
+    | "\\bigotimes"        -> LITERAL (TEX_ONLY "\\bigotimes ")
+    | "\\coprod"           -> LITERAL (TEX_ONLY "\\coprod ")
+    | "\\bigsqcup"         -> LITERAL (TEX_ONLY "\\bigsqcup ")
+    | "\\bigoplus"         -> LITERAL (TEX_ONLY "\\bigoplus ")
+    | "\\bigvee"           -> LITERAL (TEX_ONLY "\\bigvee ")
+    | "\\biguplus"         -> LITERAL (TEX_ONLY "\\biguplus ")
+    | "\\oint"             -> LITERAL (TEX_ONLY "\\oint ")
+    | "\\bigwedge"         -> LITERAL (TEX_ONLY "\\bigwedge ")
+    | "\\models"           -> LITERAL (TEX_ONLY "\\models ")
+    | "\\vdash"            -> LITERAL (TEX_ONLY "\\vdash ")
+    | "\\triangle"         -> LITERAL (TEX_ONLY "\\triangle ")
+    | "\\wr"               -> LITERAL (TEX_ONLY "\\wr ")
+    | "\\triangleleft"     -> LITERAL (TEX_ONLY "\\triangleleft ")
+    | "\\triangleright"    -> LITERAL (TEX_ONLY "\\triangleright ")
+    | "\\textvisiblespace" -> LITERAL (TEX_ONLY "\\textvisiblespace ")
+    | "\\ker"              -> LITERAL (TEX_ONLY "\\ker ")
+    | "\\lim"              -> LITERAL (TEX_ONLY "\\lim ")
+    | "\\limsup"           -> LITERAL (TEX_ONLY "\\limsup ")
+    | "\\liminf"           -> LITERAL (TEX_ONLY "\\liminf ")
+    | "\\sup"              -> LITERAL (TEX_ONLY "\\sup ")
+    | "\\Pr"               -> LITERAL (TEX_ONLY "\\Pr ")
+    | "\\hom"              -> LITERAL (TEX_ONLY "\\hom ")
+    | "\\arg"              -> LITERAL (TEX_ONLY "\\arg ")
+    | "\\dim"              -> LITERAL (TEX_ONLY "\\dim ")
+    | "\\inf"              -> LITERAL (TEX_ONLY "\\inf ")
+    | "\\circ"             -> LITERAL (TEX_ONLY "\\circ ")
+    | "\\hbar"             -> LITERAL (TEX_ONLY "\\hbar ")
+    | "\\imath"            -> LITERAL (TEX_ONLY "\\imath ")
+    | "\\lnot"             -> LITERAL (TEX_ONLY "\\lnot ")
+    | "\\hookrightarrow"   -> LITERAL (TEX_ONLY "\\hookrightarrow ")
+    | "\\hookleftarrow"    -> LITERAL (TEX_ONLY "\\hookleftarrow ")
+    | "\\mp"               -> LITERAL (TEX_ONLY "\\mp ")
+    | "\\approx"           -> LITERAL (TEX_ONLY "\\approx ")
+    | "\\propto"           -> LITERAL (TEX_ONLY "\\propto ")
+    | "\\flat"             -> LITERAL (TEX_ONLY "\\flat ")
+    | "\\sharp"            -> LITERAL (TEX_ONLY "\\sharp ")
+    | "\\natural"          -> LITERAL (TEX_ONLY "\\natural ")
+    | "\\int"              -> LITERAL (HTMLABLE_BIG ("\\int ", "&int;"))
+    | "\\sum"              -> LITERAL (HTMLABLE_BIG ("\\sum ", "&sum;"))
+    | "\\prod"             -> LITERAL (HTMLABLE_BIG ("\\prod ", "&prod;"))
+    | "\\vdots"            -> LITERAL (TEX_ONLY "\\vdots ")
+    | "\\limits"           -> LITERAL (TEX_ONLY "\\limits ")
+    | "\\nolimits"         -> LITERAL (TEX_ONLY "\\nolimits ")
+    | "\\top"              -> LITERAL (TEX_ONLY "\\top ")
+    | "\\sin"              -> LITERAL (HTMLABLEC(FONT_UFH,"\\sin ","sin"))
+    | "\\cos"              -> LITERAL (HTMLABLEC(FONT_UFH,"\\cos ","cos"))
+    | "\\sinh"             -> LITERAL (HTMLABLEC(FONT_UFH,"\\sinh ","sinh"))
+    | "\\cosh"             -> LITERAL (HTMLABLEC(FONT_UFH,"\\cosh ","cosh"))
+    | "\\tan"              -> LITERAL (HTMLABLEC(FONT_UFH,"\\tan ","tan"))
+    | "\\tanh"             -> LITERAL (HTMLABLEC(FONT_UFH,"\\tanh ","tanh"))
+    | "\\sec"              -> LITERAL (HTMLABLEC(FONT_UFH,"\\sec ","sec"))
+    | "\\csc"              -> LITERAL (HTMLABLEC(FONT_UFH,"\\csc ","csc"))
+    | "\\arcsin"           -> LITERAL (HTMLABLEC(FONT_UFH,"\\arcsin ","arcsin"))
+    | "\\arctan"           -> LITERAL (HTMLABLEC(FONT_UFH,"\\arctan ","arctan"))
+    | "\\arccos"           -> (tex_use_ams (); LITERAL (HTMLABLEC(FONT_UFH,"\\mathop{\\mathrm{arccos}}","arccos")))
+    | "\\arccot"           -> (tex_use_ams (); LITERAL (HTMLABLEC(FONT_UFH,"\\mathop{\\mathrm{arccot}}","arccot")))
+    | "\\arcsec"           -> (tex_use_ams (); LITERAL (HTMLABLEC(FONT_UFH,"\\mathop{\\mathrm{arcsec}}","arcsec")))
+    | "\\arccsc"           -> (tex_use_ams (); LITERAL (HTMLABLEC(FONT_UFH,"\\mathop{\\mathrm{arccsc}}","arccsc")))
+    | "\\sgn"              -> (tex_use_ams (); LITERAL (HTMLABLEC(FONT_UFH,"\\mathop{\\mathrm{sgn}}","sgn")))
+    | "\\cot"              -> LITERAL (HTMLABLEC(FONT_UFH,"\\cot ","cot"))
+    | "\\coth"             -> LITERAL (HTMLABLEC(FONT_UFH,"\\coth ","coth"))
+    | "\\log"              -> LITERAL (HTMLABLEC(FONT_UFH,"\\log ", "log"))
+    | "\\lg"               -> LITERAL (HTMLABLEC(FONT_UFH,"\\lg ", "lg"))
+    | "\\ln"               -> LITERAL (HTMLABLEC(FONT_UFH,"\\ln ", "ln"))
+    | "\\exp"              -> LITERAL (HTMLABLEC(FONT_UFH,"\\exp ", "exp"))
+    | "\\min"              -> LITERAL (HTMLABLEC(FONT_UFH,"\\min ", "min"))
+    | "\\max"              -> LITERAL (HTMLABLEC(FONT_UFH,"\\max ", "max"))
+    | "\\gcd"              -> LITERAL (HTMLABLEC(FONT_UFH,"\\gcd ", "gcd"))
+    | "\\deg"              -> LITERAL (HTMLABLEC(FONT_UFH,"\\deg ", "deg"))
+    | "\\det"              -> LITERAL (HTMLABLEC(FONT_UFH,"\\det ", "det"))
+    | "\\bullet"           -> LITERAL (HTMLABLE (FONT_UFH, "\\bullet ", "&bull;"))
+    | "\\bull"             -> LITERAL (HTMLABLE (FONT_UFH, "\\bullet ", "&bull;"))
+    | "\\angle"            -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UF, "\\angle ", "&ang;")))
+    | "\\dagger"           -> LITERAL (HTMLABLEM(FONT_UFH, "\\dagger ", "&dagger;"))
+    | "\\ddagger"          -> LITERAL (HTMLABLEM(FONT_UFH, "\\ddagger ", "&Dagger;"))
+    | "\\Dagger"           -> LITERAL (HTMLABLEM(FONT_UFH, "\\ddagger ", "&Dagger;"))
+    | "\\colon"            -> LITERAL (HTMLABLEC(FONT_UFH, "\\colon ", ":"))
+    | "\\Vert"             -> DELIMITER (HTMLABLEM(FONT_UFH, "\\Vert ", "||"))
+    | "\\vert"             -> DELIMITER (HTMLABLEM(FONT_UFH, "\\vert ", "|"))
+    | "\\wp"               -> LITERAL (HTMLABLE (FONT_UF,  "\\wp ", "&weierp;"))
+    | "\\weierp"           -> LITERAL (HTMLABLE (FONT_UF,  "\\wp ", "&weierp;"))
+    | "\\wedge"            -> LITERAL (HTMLABLE (FONT_UF,  "\\wedge ", "&and;"))
+    | "\\and"              -> LITERAL (HTMLABLE (FONT_UF,  "\\land ", "&and;"))
+    | "\\land"             -> LITERAL (HTMLABLE (FONT_UF,  "\\land ", "&and;"))
+    | "\\vee"              -> LITERAL (HTMLABLE (FONT_UF,  "\\vee ", "&or;"))
+    | "\\or"               -> LITERAL (HTMLABLE (FONT_UF,  "\\lor ", "&or;"))
+    | "\\lor"              -> LITERAL (HTMLABLE (FONT_UF,  "\\lor ", "&or;"))
+    | "\\sub"              -> LITERAL (HTMLABLE (FONT_UF,  "\\subset ", "&sub;"))
+    | "\\supe"             -> LITERAL (HTMLABLE (FONT_UF,  "\\supseteq ", "&supe;"))
+    | "\\sube"             -> LITERAL (HTMLABLE (FONT_UF,  "\\subseteq ", "&sube;"))
+    | "\\supset"           -> LITERAL (HTMLABLE (FONT_UF,  "\\supset ", "&sup;"))
+    | "\\subset"           -> LITERAL (HTMLABLE (FONT_UF,  "\\subset ", "&sub;"))
+    | "\\supseteq"         -> LITERAL (HTMLABLE (FONT_UF,  "\\supseteq ", "&supe;"))
+    | "\\subseteq"         -> LITERAL (HTMLABLE (FONT_UF,  "\\subseteq ", "&sube;"))
+    | "\\sqsupset"         -> (tex_use_ams (); LITERAL (TEX_ONLY "\\sqsupset "))
+    | "\\sqsubset"         -> (tex_use_ams (); LITERAL (TEX_ONLY "\\sqsubset "))
+    | "\\sqsupseteq"       -> (tex_use_ams (); LITERAL (TEX_ONLY "\\sqsupseteq "))
+    | "\\sqsubseteq"       -> (tex_use_ams (); LITERAL (TEX_ONLY "\\sqsubseteq "))
+    | "\\perp"             -> LITERAL (HTMLABLE (FONT_UF,  "\\perp ", "&perp;"))
+    | "\\bot"              -> LITERAL (HTMLABLE (FONT_UF,  "\\bot ", "&perp;"))
+    | "\\lfloor"           -> DELIMITER (HTMLABLE (FONT_UF,  "\\lfloor ", "&lfloor;"))
+    | "\\rfloor"           -> DELIMITER (HTMLABLE (FONT_UF,  "\\rfloor ", "&rfloor;"))
+    | "\\lceil"            -> DELIMITER (HTMLABLE (FONT_UF,  "\\lceil ", "&lceil;"))
+    | "\\rceil"            -> DELIMITER (HTMLABLE (FONT_UF,  "\\rceil ", "&rceil;"))
+    | "\\lbrace"           -> DELIMITER (HTMLABLEC(FONT_UFH, "\\lbrace ", "{"))
+    | "\\rbrace"           -> DELIMITER (HTMLABLEC(FONT_UFH, "\\rbrace ", "}"))
+    | "\\infty"            -> LITERAL (HTMLABLEM(FONT_UF,  "\\infty ", "&infin;"))
+    | "\\infin"            -> LITERAL (HTMLABLEM(FONT_UF,  "\\infty ", "&infin;"))
+    | "\\isin"             -> LITERAL (HTMLABLE (FONT_UF,  "\\in ", "&isin;"))
+    | "\\in"               -> LITERAL (HTMLABLE (FONT_UF,  "\\in ", "&isin;"))
+    | "\\ni"               -> LITERAL (HTMLABLE (FONT_UF,  "\\ni ", "&ni;"))
+    | "\\notin"            -> LITERAL (HTMLABLE (FONT_UF,  "\\notin ", "&notin;"))
+    | "\\smallsetminus"    -> (tex_use_ams (); LITERAL (TEX_ONLY "\\smallsetminus "))
+    | "\\And"              -> (tex_use_ams (); LITERAL (HTMLABLEM(FONT_UFH, "\\And ", "&nbsp;&amp;&nbsp;")))
+    | "\\forall"           -> LITERAL (HTMLABLE (FONT_UFH, "\\forall ", "&forall;"))
+    | "\\exists"           -> LITERAL (HTMLABLE (FONT_UFH, "\\exists ", "&exist;"))
+    | "\\exist"            -> LITERAL (HTMLABLE (FONT_UFH, "\\exists ", "&exist;"))
+    | "\\equiv"            -> LITERAL (HTMLABLEM(FONT_UFH, "\\equiv ", "&equiv;"))
+    | "\\ne"               -> LITERAL (HTMLABLEM(FONT_UFH, "\\neq ", "&ne;"))
+    | "\\neq"              -> LITERAL (HTMLABLEM(FONT_UFH, "\\neq ", "&ne;"))
+    | "\\Re"               -> LITERAL (HTMLABLE (FONT_UF,  "\\Re ", "&real;"))
+    | "\\real"             -> LITERAL (HTMLABLE (FONT_UF,  "\\Re ", "&real;"))
+    | "\\Im"               -> LITERAL (HTMLABLE (FONT_UF,  "\\Im ", "&image;"))
+    | "\\image"            -> LITERAL (HTMLABLE (FONT_UF,  "\\Im ", "&image;"))
+    | "\\prime"            -> LITERAL (HTMLABLE (FONT_UFH,"\\prime ", "&prime;"))
+    | "\\backslash"        -> DELIMITER (HTMLABLEM(FONT_UFH,"\\backslash ", "\\"))
+    | "\\setminus"         -> LITERAL (HTMLABLEM(FONT_UFH,"\\setminus ", "\\"))
+    | "\\times"            -> LITERAL (HTMLABLEM(FONT_UFH,"\\times ", "&times;"))
+    | "\\pm"               -> LITERAL (HTMLABLEM(FONT_UFH,"\\pm ", "&plusmn;"))
+    | "\\plusmn"           -> LITERAL (HTMLABLEM(FONT_UFH,"\\pm ", "&plusmn;"))
+    | "\\cdot"             -> LITERAL (HTMLABLE (FONT_UFH,"\\cdot ", "&sdot;"))
+    | "\\AA"               -> LITERAL (HTMLABLE (FONT_UFH,"\\AA ", "&Aring;"))
+    | "\\cdots"            -> LITERAL (HTMLABLE (FONT_UFH,"\\cdots ", "&sdot;&sdot;&sdot;"))
+    | "\\sdot"             -> LITERAL (HTMLABLE (FONT_UFH,"\\cdot ", "&sdot;"))
+    | "\\oplus"            -> LITERAL (HTMLABLE (FONT_UF, "\\oplus ", "&oplus;"))
+    | "\\otimes"           -> LITERAL (HTMLABLE (FONT_UF, "\\otimes ", "&otimes;"))
+    | "\\cap"              -> LITERAL (HTMLABLEM(FONT_UF, "\\cap ", "&cap;"))
+    | "\\cup"              -> LITERAL (HTMLABLE (FONT_UF, "\\cup ", "&cup;"))
+    | "\\sqcap"            -> (tex_use_ams (); LITERAL (TEX_ONLY "\\sqcap "))
+    | "\\sqcup"            -> (tex_use_ams (); LITERAL (TEX_ONLY "\\sqcup "))
+    | "\\empty"            -> LITERAL (HTMLABLE (FONT_UF, "\\emptyset ", "&empty;"))
+    | "\\emptyset"         -> LITERAL (HTMLABLE (FONT_UF, "\\emptyset ", "&empty;"))
+    | "\\O"                -> LITERAL (HTMLABLE (FONT_UF, "\\emptyset ", "&empty;"))
+    | "\\S"                -> LITERAL (HTMLABLEM(FONT_UFH,"\\S ", "&sect;"))
+    | "\\sect"             -> LITERAL (HTMLABLEM(FONT_UFH,"\\S ", "&sect;"))
+    | "\\nabla"            -> LITERAL (HTMLABLE (FONT_UF, "\\nabla ", "&nabla;"))
+    | "\\geq"              -> LITERAL (HTMLABLE (FONT_UFH,"\\geq ", "&ge;"))
+    | "\\ge"               -> LITERAL (HTMLABLE (FONT_UFH,"\\geq ", "&ge;"))
+    | "\\leq"              -> LITERAL (HTMLABLE (FONT_UFH,"\\leq ", "&le;"))
+    | "\\le"               -> LITERAL (HTMLABLE (FONT_UFH,"\\leq ", "&le;"))
+    | "\\cong"             -> LITERAL (HTMLABLE (FONT_UF, "\\cong ", "&cong;"))
+    | "\\ang"              -> LITERAL (HTMLABLE (FONT_UF, "\\angle ", "&ang;"))
+    | "\\part"             -> LITERAL (HTMLABLEM(FONT_UF, "\\partial ", "&part;"))
+    | "\\partial"          -> LITERAL (HTMLABLEM(FONT_UF, "\\partial ", "&part;"))
+    | "\\ldots"            -> LITERAL (HTMLABLEM(FONT_UFH,"\\ldots ", "..."))
+    | "\\dots"             -> LITERAL (HTMLABLEM(FONT_UFH,"\\dots ", "..."))
+    | "\\quad"             -> LITERAL (HTMLABLE (FONT_UF, "\\quad ","&nbsp;&nbsp;"))
+    | "\\qquad"            -> LITERAL (HTMLABLE (FONT_UF, "\\qquad ","&nbsp;&nbsp;&nbsp;&nbsp;"))
+    | "\\mid"              -> LITERAL (HTMLABLEM(FONT_UFH,"\\mid ", " | "))
+    | "\\neg"              -> LITERAL (HTMLABLEM(FONT_UFH,"\\neg ", "&not;"))
+    | "\\langle"           -> DELIMITER (HTMLABLE (FONT_UFH,"\\langle ","&lang;"))
+    | "\\rangle"           -> DELIMITER (HTMLABLE (FONT_UFH,"\\rangle ","&rang;"))
+    | "\\lang"             -> DELIMITER (HTMLABLE (FONT_UFH,"\\langle ","&lang;"))
+    | "\\rang"             -> DELIMITER (HTMLABLE (FONT_UFH,"\\rangle ","&rang;"))
+    | "\\lbrack"           -> DELIMITER (HTMLABLEC(FONT_UFH,"[","["))
+    | "\\rbrack"           -> DELIMITER (HTMLABLEC(FONT_UFH,"]","]"))
+    | "\\ddots"            -> LITERAL (TEX_ONLY "\\ddots ")
+    | "\\clubs"            -> LITERAL (TEX_ONLY "\\clubsuit ")
+    | "\\clubsuit"         -> LITERAL (TEX_ONLY "\\clubsuit ")
+    | "\\spades"           -> LITERAL (TEX_ONLY "\\spadesuit ")
+    | "\\spadesuit"        -> LITERAL (TEX_ONLY "\\spadesuit ")
+    | "\\hearts"           -> LITERAL (TEX_ONLY "\\heartsuit ")
+    | "\\heartsuit"        -> LITERAL (TEX_ONLY "\\heartsuit ")
+    | "\\diamonds"         -> LITERAL (TEX_ONLY "\\diamondsuit ")
+    | "\\diamondsuit"      -> LITERAL (TEX_ONLY "\\diamondsuit ")
+    | "\\implies"          -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UF, "\\implies ", "&rArr;")))
+    | "\\mod"              -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UFH,"\\mod ", "mod")))
+    | "\\Diamond"          -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UF, "\\Diamond ", "&loz;")))
+    | "\\dotsb"            -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UF, "\\dotsb ", "&sdot;&sdot;&sdot;")))
+    | "\\reals"            -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UFH,"\\mathbb{R}", "<b>R</b>")))
+    | "\\Reals"            -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UFH,"\\mathbb{R}", "<b>R</b>")))
+    | "\\R"                -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UFH,"\\mathbb{R}", "<b>R</b>")))
+    | "\\cnums"            -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UFH,"\\mathbb{C}", "<b>C</b>")))
+    | "\\Complex"          -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UFH,"\\mathbb{C}", "<b>C</b>")))
+    | "\\Z"                -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UFH,"\\mathbb{Z}", "<b>Z</b>")))
+    | "\\natnums"          -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UFH,"\\mathbb{N}", "<b>N</b>")))
+    | "\\N"                -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UFH,"\\mathbb{N}", "<b>N</b>")))
+    | "\\lVert"            -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UFH,"\\lVert ", "||")))
+    | "\\rVert"            -> (tex_use_ams (); LITERAL (HTMLABLE (FONT_UFH,"\\rVert ", "||")))
+    | "\\nmid"             -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nmid "))
+    | "\\lesssim"          -> (tex_use_ams (); LITERAL (TEX_ONLY "\\lesssim "))
+    | "\\ngeq"             -> (tex_use_ams (); LITERAL (TEX_ONLY "\\ngeq "))
+    | "\\smallsmile"       -> (tex_use_ams (); LITERAL (TEX_ONLY "\\smallsmile "))
+    | "\\smallfrown"       -> (tex_use_ams (); LITERAL (TEX_ONLY "\\smallfrown "))
+    | "\\nleftarrow"       -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nleftarrow "))
+    | "\\nrightarrow"      -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nrightarrow "))
+    | "\\trianglelefteq"   -> (tex_use_ams (); LITERAL (TEX_ONLY "\\trianglelefteq "))
+    | "\\trianglerighteq"  -> (tex_use_ams (); LITERAL (TEX_ONLY "\\trianglerighteq "))
+    | "\\square"           -> (tex_use_ams (); LITERAL (TEX_ONLY "\\square "))
+    | "\\checkmark"        -> (tex_use_ams (); LITERAL (TEX_ONLY "\\checkmark "))
+    | "\\supsetneq"        -> (tex_use_ams (); LITERAL (TEX_ONLY "\\supsetneq "))
+    | "\\subsetneq"        -> (tex_use_ams (); LITERAL (TEX_ONLY "\\subsetneq "))
+    | "\\Box"              -> (tex_use_ams (); LITERAL (TEX_ONLY "\\Box "))
+    | "\\nleq"             -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nleq "))
+    | "\\upharpoonright"   -> (tex_use_ams (); LITERAL (TEX_ONLY "\\upharpoonright "))
+    | "\\upharpoonleft"    -> (tex_use_ams (); LITERAL (TEX_ONLY "\\upharpoonleft "))
+    | "\\downharpoonright" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\downharpoonright "))
+    | "\\downharpoonleft"  -> (tex_use_ams (); LITERAL (TEX_ONLY "\\downharpoonleft "))
+    | "\\rightharpoonup"   -> (tex_use_ams (); LITERAL (TEX_ONLY "\\rightharpoonup "))
+    | "\\rightharpoondown" -> (tex_use_ams (); LITERAL (TEX_ONLY "\\rightharpoondown "))
+    | "\\leftharpoonup"    -> (tex_use_ams (); LITERAL (TEX_ONLY "\\leftharpoonup "))
+    | "\\leftharpoondown"  -> (tex_use_ams (); LITERAL (TEX_ONLY "\\leftharpoondown "))
+    | "\\nless"            -> (tex_use_ams (); LITERAL (TEX_ONLY "\\nless "))
+    | "\\Vdash"            -> (tex_use_ams (); LITERAL (TEX_ONLY "\\Vdash "))
+    | "\\vDash"            -> (tex_use_ams (); LITERAL (TEX_ONLY "\\vDash "))
+    | "\\varkappa"         -> (tex_use_ams (); LITERAL (TEX_ONLY "\\varkappa "))
+    | "\\digamma"          -> (tex_use_ams (); LITERAL (TEX_ONLY "\\digamma "))
+    | "\\beth"             -> (tex_use_ams (); LITERAL (TEX_ONLY "\\beth "))
+    | "\\daleth"           -> (tex_use_ams (); LITERAL (TEX_ONLY "\\daleth "))
+    | "\\gimel"            -> (tex_use_ams (); LITERAL (TEX_ONLY "\\gimel "))
+    | "\\complement"       -> (tex_use_ams (); LITERAL (TEX_ONLY "\\complement "))
+    | "\\eth"              -> (tex_use_ams (); LITERAL (TEX_ONLY "\\eth "))
+    | "\\hslash"           -> (tex_use_ams (); LITERAL (TEX_ONLY "\\hslash "))
+    | "\\mho"              -> (tex_use_ams (); LITERAL (TEX_ONLY "\\mho "))
+    | "\\Finv"             -> (tex_use_ams (); LITERAL (TEX_ONLY "\\Finv "))
+    | "\\Game"             -> (tex_use_ams (); LITERAL (TEX_ONLY "\\Game "))
+    | "\\varlimsup"        -> (tex_use_ams (); LITERAL (TEX_ONLY "\\varlimsup "))
+    | "\\varliminf"        -> (tex_use_ams (); LITERAL (TEX_ONLY "\\varliminf "))
+    | "\\varinjlim"        -> (tex_use_ams (); LITERAL (TEX_ONLY "\\varinjlim "))
+    | "\\varprojlim"       -> (tex_use_ams (); LITERAL (TEX_ONLY "\\varprojlim "))
+    | "\\injlim"           -> (tex_use_ams (); LITERAL (TEX_ONLY "\\injlim "))
+    | "\\projlim"          -> (tex_use_ams (); LITERAL (TEX_ONLY "\\projlim "))
+    | "\\iint"             -> (tex_use_ams (); LITERAL (TEX_ONLY "\\iint "))
+    | "\\iiint"            -> (tex_use_ams (); LITERAL (TEX_ONLY "\\iiint "))
+    | "\\iiiint"           -> (tex_use_ams (); LITERAL (TEX_ONLY "\\iiiint "))
+    | "\\varnothing"       -> (tex_use_ams (); LITERAL (TEX_ONLY "\\varnothing "))
+    | "\\left"             -> LEFT
+    | "\\right"            -> RIGHT
+    | "\\hat"              -> FUN_AR1 "\\hat "
+    | "\\widehat"          -> FUN_AR1 "\\widehat "
+    | "\\overline"         -> FUN_AR1 "\\overline "
+    | "\\overbrace"        -> FUN_AR1 "\\overbrace "
+    | "\\underline"        -> FUN_AR1 "\\underline "
+    | "\\underbrace"       -> FUN_AR1 "\\underbrace "
+    | "\\overleftarrow"    -> FUN_AR1 "\\overleftarrow "
+    | "\\overrightarrow"   -> FUN_AR1 "\\overrightarrow "
+    | "\\overleftrightarrow"->FUN_AR1 "\\overleftrightarrow "
+    | "\\check"            -> FUN_AR1 "\\check "
+    | "\\acute"            -> FUN_AR1 "\\acute "
+    | "\\grave"            -> FUN_AR1 "\\grave "
+    | "\\bar"              -> FUN_AR1 "\\bar "
+    | "\\vec"              -> FUN_AR1 "\\vec "
+    | "\\dot"              -> FUN_AR1 "\\dot "
+    | "\\ddot"             -> FUN_AR1 "\\ddot "
+    | "\\breve"            -> FUN_AR1 "\\breve "
+    | "\\tilde"            -> FUN_AR1 "\\tilde "
+    | "\\not"              -> FUN_AR1 "\\not "
+    | "\\choose"           -> FUN_INFIX "\\choose "
+    | "\\atop"             -> FUN_INFIX "\\atop "
+    | "\\binom"            -> FUN_AR2 "\\binom "
+    | "\\frac"             -> FUN_AR2h ("\\frac ", fun num den -> Html.html_render [num], "<hr style=\"{background: black}\"/>", Html.html_render [den])
+    | "\\cfrac"            -> (tex_use_ams (); FUN_AR2h ("\\cfrac ", fun num den -> Html.html_render [num], "<hr style=\"{background: black}\">", Html.html_render [den]))
+    | "\\over"             -> FUN_INFIXh ("\\over ", fun num den -> Html.html_render num, "<hr style=\"{background: black}\"/>", Html.html_render den)
+    | "\\sqrt"             -> FUN_AR1 "\\sqrt "
+    | "\\pmod"             -> FUN_AR1hl ("\\pmod ", ("(mod ", ")"))
+    | "\\bmod"             -> FUN_AR1hl ("\\bmod ", ("mod ", ""))
+    | "\\emph"             -> FUN_AR1 "\\emph "
+    | "\\texttt"           -> FUN_AR1 "\\texttt "
+    | "\\textbf"           -> FUN_AR1 "\\textbf "
+    | "\\textit"           -> FUN_AR1hf ("\\textit ", FONTFORCE_IT)
+    | "\\textrm"           -> FUN_AR1hf ("\\textrm ", FONTFORCE_RM)
+    | "\\rm"               -> DECLh ("\\rm ", FONTFORCE_RM)
+    | "\\it"               -> DECLh ("\\it ", FONTFORCE_IT)
+    | "\\cal"              -> DECL "\\cal "
+    | "\\bf"               -> DECL "\\bf "
+    | "\\big"              -> BIG "\\big "
+    | "\\Big"              -> BIG "\\Big "
+    | "\\bigg"             -> BIG "\\bigg "
+    | "\\Bigg"             -> BIG "\\Bigg "
+    | "\\mathit"           -> (tex_use_ams (); FUN_AR1hf ("\\mathit ", FONTFORCE_IT))
+    | "\\mathrm"           -> (tex_use_ams (); FUN_AR1hf ("\\mathrm ", FONTFORCE_RM))
+    | "\\mathop"           -> (tex_use_ams (); FUN_AR1 "\\mathop ")
+    | "\\boldsymbol"       -> (tex_use_ams (); FUN_AR1 "\\boldsymbol ")
+    | "\\bold"             -> (tex_use_ams (); FUN_AR1 "\\mathbf ")
+    | "\\Bbb"              -> (tex_use_ams (); FUN_AR1 "\\mathbb ")
+    | "\\mathbf"           -> (tex_use_ams (); FUN_AR1 "\\mathbf ")
+    | "\\mathsf"           -> (tex_use_ams (); FUN_AR1 "\\mathsf ")
+    | "\\mathcal"          -> (tex_use_ams (); FUN_AR1 "\\mathcal ")
+    | "\\mathbb"           -> (tex_use_ams (); FUN_AR1 "\\mathbb ")
+    | "\\mathfrak"         -> (tex_use_ams (); FUN_AR1 "\\mathfrak ")
+    | "\\operatorname"     -> (tex_use_ams (); FUN_AR1 "\\operatorname ")
+    | "\\mbox"             -> raise (Failure "malformatted \\mbox")
+    | "\\vbox"             -> raise (Failure "malformatted \\vbox")
+    | "\\hbox"             -> raise (Failure "malformatted \\hbox")
+    | s                    -> raise (Illegal_tex_function s)
diff --git a/math/texutil.mli b/math/texutil.mli
new file mode 100644 (file)
index 0000000..99d0e4e
--- /dev/null
@@ -0,0 +1,11 @@
+val render_tex : Tex.t -> string
+
+val set_encoding : string -> unit
+val tex_use_nonascii: unit -> unit
+val tex_use_ams: unit -> unit
+
+val get_preface : unit -> string
+val get_footer : unit -> string
+
+exception Illegal_tex_function of string
+val find: string -> Parser.token
diff --git a/math/texvc.ml b/math/texvc.ml
new file mode 100644 (file)
index 0000000..abddd3d
--- /dev/null
@@ -0,0 +1,34 @@
+exception LexerException of string
+let lexer_token_safe lexbuf =
+    try Lexer.token lexbuf
+    with Failure s -> raise (LexerException s)
+
+let render tmppath finalpath tree =
+    let outtex = Util.mapjoin Texutil.render_tex tree in
+    let md5 = Digest.to_hex (Digest.string outtex) in
+    begin
+       let mathml = Mathml.render tree
+       and html = Html.render tree
+       in print_string (match (html,!Html.conservativeness,mathml) with
+           None,_,None -> "+" ^ md5 
+         | Some h,Html.CONSERVATIVE,None -> "c" ^ md5  ^ h
+         | Some h,Html.MODERATE,None -> "m" ^ md5  ^ h
+         | Some h,Html.LIBERAL,None -> "l" ^ md5  ^ h
+         | Some h,Html.CONSERVATIVE,Some m -> "C" ^ md5  ^ h ^ "\000" ^ m
+         | Some h,Html.MODERATE,Some m -> "M" ^ md5  ^ h ^ "\000" ^ m
+         | Some h,Html.LIBERAL,Some m -> "L" ^ md5 ^ h ^ "\000" ^ m
+         | None,_,Some m -> "X" ^ md5   ^ m
+       );
+       Render.render tmppath finalpath outtex md5
+    end
+let _ =
+    Texutil.set_encoding (try Sys.argv.(4) with _ -> "UTF-8");
+    try render Sys.argv.(1) Sys.argv.(2) (Parser.tex_expr lexer_token_safe (Lexing.from_string Sys.argv.(3)))
+    with Parsing.Parse_error -> print_string "S"
+       | LexerException _ -> print_string "E"
+       | Texutil.Illegal_tex_function s -> print_string ("F" ^ s)
+       | Util.FileAlreadyExists -> print_string "-"
+       | Invalid_argument _ -> print_string "-"
+       | Failure _ -> print_string "-"
+       | Render.ExternalCommandFailure s -> ()
+       | _ -> print_string "-"
diff --git a/math/texvc_cgi.ml b/math/texvc_cgi.ml
new file mode 100644 (file)
index 0000000..57b4d97
--- /dev/null
@@ -0,0 +1,62 @@
+open Netcgi;;
+open Netcgi_types;;
+open Netcgi_env;;
+open Netchannels;;
+
+let cgi = new Netcgi.std_activation ()
+let out = cgi # output # output_string
+let math = cgi # argument_value ~default:"" "math"
+let tmppath = "/home/taw/public_html/wiki/tmp/"
+let finalpath = "/home/taw/public_html/wiki/math/"
+let finalurl = "http://wroclaw.taw.pl.eu.org/~taw/wiki/math/"
+;;
+
+let h_header = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\""^
+            " \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"^
+            "<html><head><title>texvc</title></head><body>"^
+            "<form method=post action=\"http://wroclaw.taw.pl.eu.org/~taw/cgi-bin/newcodebase/math/texvc_cgi\">"^
+            "<textarea name='math' rows=10 cols=80>"
+let h_middle = "</textarea><br><input type=submit value=\"Preview\" name='preview'></form>"
+let h_footer = "</body></html>\n"
+
+let render tmppath finalpath tree =
+    let outtex = Texutil.mapjoin Texutil.print tree in
+    let md5 = Digest.to_hex (Digest.string outtex) in
+    begin
+       out "<h3>TeX</h3>";
+        out outtex; (* <, &  and > should be protected *)
+       (try out ("<h3>HTML</h3>" ^ (Texutil.html_render tree))
+         with _ -> out "<h3>HTML could not be rendered</h3>");
+       try  Render.render tmppath finalpath outtex md5;
+           out ("<h3>Image:</h3><img src=\""^finalurl^md5^".png\">")
+       with Util.FileAlreadyExists -> out ("<h3>Image:</h3><img src=\""^finalurl^md5^".png\">")
+           | Failure s -> out ("<h3>Other failure: " ^ s ^ "</h3>")
+          | Render.ExternalCommandFailure "latex" -> out "<h3>latex failed</h3>"
+          | Render.ExternalCommandFailure "dvips" -> out "<h3>dvips failed</h3>"
+           | _ ->  out "<h3>Other failure</h3>"
+    end
+;;
+
+cgi#set_header ();;
+
+out h_header;;
+out math;;
+out h_middle;;
+
+exception LexerException of string
+let lexer_token_safe lexbuf =
+    try Lexer.token lexbuf
+    with Failure s -> raise (LexerException s)
+;;
+if math = ""
+then ()
+else try
+       render tmppath finalpath (Parser.tex_expr lexer_token_safe (Lexing.from_string math))
+    with Parsing.Parse_error -> out "<h3>Parse error</h3>"
+       | LexerException s -> out "<h3>Lexing failure</h3>"
+       | Texutil.Illegal_tex_function s -> out ("<h3>Illegal TeX function: " ^ s ^ "</h3>")
+       | Failure s -> out ("<h3>Other failure: " ^ s ^ "</h3>")
+       | _ -> out "<h3>Other failure</h3>"
+;;
+
+out h_footer
diff --git a/math/texvc_test.ml b/math/texvc_test.ml
new file mode 100644 (file)
index 0000000..3bce529
--- /dev/null
@@ -0,0 +1,25 @@
+exception LexerException of string
+let lexer_token_safe lexbuf =
+    try Lexer.token lexbuf
+    with Failure s -> raise (LexerException s)
+
+let rec foo () =
+    try
+       let line = input_line stdin in
+       (try
+           let tree = Parser.tex_expr lexer_token_safe (Lexing.from_string line) in
+           let out = Util.mapjoin Texutil.render_tex tree in
+           (match Html.render tree with
+               Some _ -> print_string "$^\n"
+             | None -> print_string "$_\n";
+           )
+        with
+           Texutil.Illegal_tex_function s -> print_string ("$T" ^ s ^ " " ^ line ^ "\n")
+         | LexerException s               -> print_string ("$L" ^ line ^ "\n")
+         | _                              -> print_string ("$ " ^ line ^ "\n"));
+       flush stdout;
+       foo ();
+    with
+       End_of_file -> ()
+;;
+foo ();;
diff --git a/math/texvc_tex.ml b/math/texvc_tex.ml
new file mode 100644 (file)
index 0000000..30c0f67
--- /dev/null
@@ -0,0 +1,3 @@
+Texutil.set_encoding (try Sys.argv.(2) with _ -> "UTF-8");
+try print_string (Util.mapjoin Texutil.render_tex (Parser.tex_expr Lexer.token (Lexing.from_string Sys.argv.(1))))
+with _ -> ()
diff --git a/math/util.ml b/math/util.ml
new file mode 100644 (file)
index 0000000..f045856
--- /dev/null
@@ -0,0 +1,17 @@
+let mapjoin f l = (List.fold_left (fun a b -> a ^ (f b)) "" l)
+let mapjoine e f = function
+    [] -> ""
+  | h::t -> (List.fold_left (fun a b -> a ^ e ^ (f b)) (f h) t)
+
+exception FileAlreadyExists
+let open_out_unless_exists path =
+    if Sys.file_exists path
+    then raise FileAlreadyExists
+    else open_out path
+
+let run_in_other_directory tmppath cmd =
+    let prevdir = Sys.getcwd () in(
+       Sys.chdir tmppath;
+       let retval = Sys.command cmd in
+           (Sys.chdir prevdir; retval)
+    )
diff --git a/profileinfo.php b/profileinfo.php
new file mode 100644 (file)
index 0000000..e18c571
--- /dev/null
@@ -0,0 +1,244 @@
+<!--
+     Show profiling data.
+
+     Copyright 2005 Kate Turner.
+
+     Permission is hereby granted, free of charge, to any person obtaining a copy
+     of this software and associated documentation files (the "Software"), to deal
+     in the Software without restriction, including without limitation the rights
+     to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+     copies of the Software, and to permit persons to whom the Software is
+     furnished to do so, subject to the following conditions:
+
+     The above copyright notice and this permission notice shall be included in
+     all copies or substantial portions of the Software.
+
+     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+     IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+     FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+     AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+     LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+     SOFTWARE.
+
+-->
+<html>
+<head>
+<title>Profiling data</title>
+<style type="text/css">
+       th {
+               text-align: left;
+               border-bottom: solid 1px black;
+       }
+
+       th, td {
+               padding-left: 0.5em;
+               padding-right: 0.5em;
+       }
+
+       td.time, td.count {
+               text-align: right;
+       }
+</style>
+</head>
+<body>
+<?php
+
+$wgDBadminuser = $wgDBadminpassword = $wgDBserver = $wgDBname = $wgEnableProfileInfo = false;
+
+define("MEDIAWIKI", 1);
+
+require_once("./includes/Defines.php");
+require_once("./LocalSettings.php");
+require_once("./AdminSettings.php");
+
+if (!$wgEnableProfileInfo)
+       die("disabled");
+
+foreach (array("wgDBadminuser", "wgDBadminpassword", "wgDBserver", "wgDBname") as $var)
+       if ($$var === false)
+               die("AdminSettings.php not correct");
+
+$expand = array();
+if (isset($_REQUEST['expand']))
+       foreach(explode(",", $_REQUEST['expand']) as $f)
+               $expand[$f] = true;
+
+class profile_point {
+       var $name;
+       var $count;
+       var $time;
+       var $children;
+
+       function profile_point($name, $count, $time) {
+               $this->name = $name;
+               $this->count = $count;
+               $this->time = $time;
+               $this->children = array();
+       }
+
+       function add_child($child) {
+               $this->children[] = $child;
+       }
+
+       function display($indent = 0.0) {
+               global $expand;
+               usort($this->children, "compare_point");
+
+               $extet = '';
+               if (isset($expand[$this->name()]))
+                       $ex = true;
+               else    $ex = false;
+               if (!$ex) {
+                       if (count($this->children)) {
+                               $url = makeurl(false, false, $expand + array($this->name() => true));
+                               $extet = " <a href=\"$url\">[+]</a>";
+                       } else $extet = '';
+               } else {
+                       $e = array();
+                       foreach ($expand as $name => $ep)
+                               if ($name != $this->name())
+                                       $e += array($name => $ep);
+
+                       $extet = " <a href=\"" . makeurl(false, false, $e) . "\">[&ndash;]</a>";
+               }
+               ?>
+               <tr>
+               <td class="time"><tt><?php echo $this->fmttime() ?></tt></td>
+               <td class="count"><?php echo $this->count() ?></td>
+               <td class="name" style="padding-left: <?php echo $indent ?>em">
+                       <?php echo htmlspecialchars($this->name()) . $extet ?>
+               </td>
+               </tr>
+               <?php
+               if ($ex)
+                       foreach ($this->children as $child)
+                               $child->display($indent + 2);
+       }
+
+       function name() {
+               return $this->name;
+       }
+
+       function count() {
+               return $this->count;
+       }
+
+       function time() {
+               return $this->time;
+       }
+
+       function fmttime() {
+               return sprintf("%5.02f", $this->time);
+       }
+};
+
+function compare_point($a, $b) {
+       global $sort;
+       switch ($sort) {
+       case "name":
+               return strcmp($a->name(), $b->name());
+       case "time":
+               return $a->time() > $b->time() ? -1 : 1;
+       case "count":
+               return $a->count() > $b->count() ? -1 : 1;
+       }
+}
+
+$sorts = array("time", "count", "name");
+$sort = 'time';
+if (isset($_REQUEST['sort']) && in_array($_REQUEST['sort'], $sorts))
+       $sort = $_REQUEST['sort'];
+
+$dbh = mysql_connect($wgDBserver, $wgDBadminuser, $wgDBadminpassword)
+       or die("mysql server failed: " . mysql_error());
+mysql_select_db($wgDBname, $dbh) or die(mysql_error($dbh));
+$res = mysql_query("
+       SELECT pf_count, pf_time, pf_name
+       FROM profiling
+       ORDER BY pf_name ASC
+", $dbh) or die("query failed: " . mysql_error());
+
+if (isset($_REQUEST['filter']))
+       $filter = $_REQUEST['filter'];
+else   $filter = '';
+
+?>
+<form method="profiling.php">
+<p>
+<input type="text" name="filter" value="<?php echo htmlspecialchars($filter)?>"/>
+<input type="hidden" name="sort" value="<?php echo htmlspecialchars($sort)?>"/>
+<input type="hidden" name="expand" value="<?php echo htmlspecialchars(implode(",", array_keys($expand)))?>"/>
+<input type="submit" value="Filter" />
+</p>
+</form>
+
+<table cellspacing="0">
+<tr id="top">
+<th><a href="<?php echo makeurl(false, "time") ?>">Time</a></th>
+<th><a href="<?php echo makeurl(false, "count") ?>">Count</a></th>
+<th><a href="<?php echo makeurl(false, "name") ?>">Name</a></th>
+</tr>
+<?php
+$totaltime = 0.0;
+
+function makeurl($_filter = false, $_sort = false, $_expand = false) {
+       global $filter, $sort, $expand;
+
+       if ($_expand === false)
+               $_expand = $expand;
+
+       $nfilter = $_filter ? $_filter : $filter;
+       $nsort = $_sort ? $_sort : $sort;
+       $exp = urlencode(implode(',', array_keys($_expand)));
+       return "?filter=$nfilter&amp;sort=$nsort&amp;expand=$exp";
+}
+
+$points = array();
+$queries = array();
+$sqltotal = 0.0;
+
+$last = false;
+while (($o = mysql_fetch_object($res)) !== false) {
+       $next = new profile_point($o->pf_name, $o->pf_count, $o->pf_time);
+       $totaltime += $next->time();
+       if ($last !== false) {
+               if (preg_match("/^".preg_quote($last->name(), "/")."/", $next->name())) {
+                       $last->add_child($next);
+                       continue;
+               }
+       }
+       $last = $next;
+       if (preg_match("/^query: /", $next->name())) {
+               $sqltotal += $next->time();
+               $queries[] = $next;
+       } else {
+               $points[] = $next;
+       }
+}
+
+$s = new profile_point("SQL Queries", 0, $sqltotal);
+foreach ($queries as $q)
+       $s->add_child($q);
+$points[] = $s;
+
+usort($points, "compare_point");
+
+foreach ($points as $point) {
+       if (strlen($filter) && !strstr($point->name(), $filter))
+               continue;
+
+       $point->display();
+}
+?>
+</table>
+
+<p>Total time: <tt><?php printf("%5.02f", $totaltime) ?></p>
+<?php
+
+mysql_free_result($res);
+mysql_close($dbh);
+
+?>
+</body>
+</html>
diff --git a/redirect.php b/redirect.php
new file mode 100644 (file)
index 0000000..92a8890
--- /dev/null
@@ -0,0 +1,19 @@
+<?php
+unset( $DP );
+unset( $IP );
+$wgCommandLineMode = false;
+define( 'MEDIAWIKI', true );
+
+require_once( './includes/Defines.php' );
+require_once( './LocalSettings.php' );
+global $wgArticlePath;
+
+require_once( 'includes/WebRequest.php' );
+$wgRequest = new WebRequest();
+
+$page = $wgRequest->getVal( 'wpDropdown' );
+
+$url = str_replace( "$1", urlencode( $page ), $wgArticlePath );
+
+header( "Location: {$url}" );
+?>
diff --git a/redirect.phtml b/redirect.phtml
new file mode 100644 (file)
index 0000000..79e3cea
--- /dev/null
@@ -0,0 +1,4 @@
+<?php
+// stub file for compatibility with older versions
+include_once('./redirect.php');
+?>
\ No newline at end of file
diff --git a/skins/Chick.php b/skins/Chick.php
new file mode 100644 (file)
index 0000000..e56a17b
--- /dev/null
@@ -0,0 +1,30 @@
+<?php
+/**
+ * See skin.txt
+ *
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Skins
+ */
+
+if( !defined( 'MEDIAWIKI' ) )
+       die();
+
+/** */
+require_once('MonoBook.php');
+
+/**
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Skins
+ */
+class SkinChick extends SkinTemplate {
+       function initPage( &$out ) {
+               SkinTemplate::initPage( $out );
+               $this->skinname  = 'chick';
+               $this->stylename = 'chick';
+               $this->template  = 'MonoBookTemplate';
+       }
+}
+
+?>
diff --git a/skins/CologneBlue.php b/skins/CologneBlue.php
new file mode 100644 (file)
index 0000000..27ad32c
--- /dev/null
@@ -0,0 +1,318 @@
+<?php
+/**
+ * See skin.txt
+ *
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Skins
+ */
+
+if( !defined( 'MEDIAWIKI' ) )
+       die();
+
+/**
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Skins
+ */
+class SkinCologneBlue extends Skin {
+
+       function getStylesheet() {
+               return "common/cologneblue.css";
+       }
+       function getSkinName() {
+               return "cologneblue";
+       }
+
+       function doBeforeContent() {
+               global $wgOut, $wgTitle;
+
+               $s = "";
+               $qb = $this->qbSetting();
+               $mainPageObj = Title::newMainPage();
+               
+               $s .= "\n<div id='content'>\n<div id='topbar'>" .
+                 "<table width='100%' border='0' cellspacing='0' cellpadding='8'><tr>";
+
+               $s .= "<td class='top' align='left' valign='middle' nowrap='nowrap'>";
+               $s .= "<a href=\"" . $mainPageObj->escapeLocalURL() . "\">";
+               $s .= "<span id='sitetitle'>" . wfMsg( "sitetitle" ) . "</span></a>";
+
+               $s .= "</td><td class='top' align='right' valign='bottom' width='100%'>";
+               $s .= $this->sysLinks();
+               $s .= "</td></tr><tr><td valign='top'>";
+
+               $s .= "<font size='-1'><span id='sitesub'>";
+               $s .= htmlspecialchars( wfMsg( "sitesubtitle" ) ) . "</span></font>";
+               $s .= "</td><td align='right'>" ;
+
+               $s .= "<font size='-1'><span id='langlinks'>" ;
+               $s .= str_replace ( "<br />" , "" , $this->otherLanguages() );
+               $cat = $this->getCategoryLinks();
+               if( $cat ) $s .= "<br />$cat\n";
+               $s .= "<br />" . $this->pageTitleLinks();
+               $s .= "</span></font>";
+
+               $s .= "</td></tr></table>\n";
+
+               $s .= "\n</div>\n<div id='article'>";
+
+               $notice = wfGetSiteNotice();
+               if( $notice ) {
+                       $s .= "\n<div id='siteNotice'>$notice</div>\n";
+               }
+               $s .= $this->pageTitle();
+               $s .= $this->pageSubtitle() . "\n";
+               return $s;
+       }
+
+       function doAfterContent()
+       {
+               global $wgOut;
+
+               $s = "\n</div><br clear='all' />\n";
+
+               $s .= "\n<div id='footer'>";
+               $s .= "<table width='98%' border='0' cellspacing='0'><tr>";
+
+               $qb = $this->qbSetting();
+               if ( 1 == $qb || 3 == $qb ) { # Left
+                       $s .= $this->getQuickbarCompensator();
+               }
+               $s .= "<td class='bottom' align='center' valign='top'>";
+
+               $s .= $this->bottomLinks();
+               $s .= "\n<br />" . $this->makeKnownLink( wfMsgForContent( "mainpage" ) ) . " | "
+                 . $this->aboutLink() . " | "
+                 . $this->searchForm( wfMsg( "qbfind" ) );
+
+               $s .= "\n<br />" . $this->pageStats();
+
+               $s .= "</td>";
+               if ( 2 == $qb ) { # Right
+                       $s .= $this->getQuickbarCompensator();
+               }
+               $s .= "</tr></table>\n</div>\n</div>\n";
+
+               if ( 0 != $qb ) { $s .= $this->quickBar(); }
+               return $s;
+       }
+       
+       function doGetUserStyles() {
+               global $wgOut, $wgStyleSheetPath;
+               $s = parent::doGetUserStyles();
+               $qb = $this->qbSetting();
+
+               if ( 2 == $qb ) { # Right
+                       $s .= "#quickbar { position: absolute; right: 4px; }\n" .
+                         "#article { margin-left: 4px; margin-right: 148px; }\n";
+               } else if ( 1 == $qb ) {
+                       $s .= "#quickbar { position: absolute; left: 4px; }\n" .
+                         "#article { margin-left: 148px; margin-right: 4px; }\n";
+               } else if ( 3 == $qb ) { # Floating left
+                       $s .= "#quickbar { position:absolute; left:4px } \n" .
+                         "#topbar { margin-left: 148px }\n" .
+                         "#article { margin-left:148px; margin-right: 4px; } \n" .
+                         "body>#quickbar { position:fixed; left:4px; top:4px; overflow:auto ;bottom:4px;} \n"; # Hides from IE
+               } else if ( 4 == $qb ) { # Floating right
+                       $s .= "#quickbar { position: fixed; right: 4px; } \n" .
+                         "#topbar { margin-right: 148px }\n" .
+                         "#article { margin-right: 148px; margin-left: 4px; } \n" .
+                         "body>#quickbar { position: fixed; right: 4px; top: 4px; overflow: auto ;bottom:4px;} \n"; # Hides from IE
+               }
+               return $s;
+       }
+       
+       function sysLinks() {
+               global $wgUser, $wgContLang, $wgTitle;
+               $li = $wgContLang->specialPage("Userlogin");
+               $lo = $wgContLang->specialPage("Userlogout");
+
+               $rt = $wgTitle->getPrefixedURL();
+               if ( 0 == strcasecmp( urlencode( $lo ), $rt ) ) {
+                       $q = "";
+               } else { 
+                       $q = "returnto={$rt}"; 
+               }
+               
+               $s = "" .
+                 $this->makeKnownLink( wfMsgForContent( "mainpage" ), wfMsg( "mainpage" ) )
+                 . " | " .
+                 $this->makeKnownLink( wfMsgForContent( "aboutpage" ), wfMsg( "about" ) )
+                 . " | " .
+                 $this->makeKnownLink( wfMsgForContent( "helppage" ), wfMsg( "help" ) )
+                 . " | " .
+                 $this->makeKnownLink( wfMsgForContent( "faqpage" ), wfMsg("faq") )
+                 . " | " .
+                 $this->specialLink( "specialpages" ) . " | ";
+
+               if ( $wgUser->isLoggedIn() ) {
+                       $s .=  $this->makeKnownLink( $lo, wfMsg( "logout" ), $q );
+               } else {
+                       $s .=  $this->makeKnownLink( $li, wfMsg( "login" ), $q );
+               }
+
+               /* show links to different language variants */
+               global $wgDisableLangConversion;
+               $variants = $wgContLang->getVariants();
+               if( !$wgDisableLangConversion && sizeof( $variants ) > 1 ) {
+                       $actstr = '';
+                       foreach( $variants as $code ) {
+                               $varname = $wgContLang->getVariantname( $code );
+                               if( $varname == 'disable' )
+                                       continue;
+                               $s .= ' | <a href="' . $wgTitle->getLocalUrl( 'variant=' . $code ) . '">' . $varname . '</a>';
+                       }
+               }
+
+
+
+               return $s;
+       }
+
+       /**
+        * Compute the sidebar
+        * @private
+        */
+       function quickBar()
+       {
+               global $wgOut, $wgTitle, $wgUser, $wgLang, $wgContLang, $wgEnableUploads;
+
+               $tns=$wgTitle->getNamespace();
+
+               $s = "\n<div id='quickbar'>";
+
+               $sep = "<br />";
+               $s .= $this->menuHead( "qbfind" );
+               $s .= $this->searchForm();
+
+               $s .= $this->menuHead( "qbbrowse" );
+
+               # Use the first heading from the Monobook sidebar as the "browse" section
+               $bar = $this->buildSidebar();
+               $browseLinks = reset( $bar );
+
+               foreach ( $browseLinks as $link ) {
+                       if ( $link['text'] != '-' ) {
+                               $s .= "<a href=\"{$link['href']}\">" .
+                                       htmlspecialchars( $link['text'] ) . '</a>' . $sep;
+                       }
+               }
+               
+               if ( $wgOut->isArticle() ) {
+                       $s .= $this->menuHead( "qbedit" );
+                       $s .= "<strong>" . $this->editThisPage() . "</strong>";
+
+                       $s .= $sep . $this->makeKnownLink( wfMsgForContent( "edithelppage" ), wfMsg( "edithelp" ) );
+
+                       if( $wgUser->isLoggedIn() ) {
+                               $s .= $sep . $this->moveThisPage();
+                       }
+                       if ( $wgUser->isAllowed('delete') ) {
+                               $dtp = $this->deleteThisPage();
+                               if ( "" != $dtp ) {
+                                       $s .= $sep . $dtp;
+                               }
+                       }
+                       if ( $wgUser->isAllowed('protect') ) {
+                               $ptp = $this->protectThisPage();
+                               if ( "" != $ptp ) {
+                                       $s .= $sep . $ptp;
+                               }
+                       }
+                       $s .= $sep;
+
+                       $s .= $this->menuHead( "qbpageoptions" );
+                       $s .= $this->talkLink()
+                         . $sep . $this->commentLink() 
+                         . $sep . $this->printableLink();
+                       if ( $wgUser->isLoggedIn() ) {
+                               $s .= $sep . $this->watchThisPage();
+                       }
+
+                       $s .= $sep;
+
+                       $s .= $this->menuHead("qbpageinfo")
+                         . $this->historyLink()
+                         . $sep . $this->whatLinksHere()
+                         . $sep . $this->watchPageLinksLink();
+                         
+                       if( $tns == NS_USER || $tns == NS_USER_TALK ) {
+                               $id=User::idFromName($wgTitle->getText());
+                               if ($id != 0) {
+                                       $s .= $sep . $this->userContribsLink();
+                                       if( $this->showEmailUser( $id ) ) {
+                                               $s .= $sep . $this->emailUserLink();
+                                       }
+                               }
+                       }
+                       $s .= $sep;
+               }
+
+               $s .= $this->menuHead( "qbmyoptions" );
+               if ( $wgUser->isLoggedIn() ) {
+                       $name = $wgUser->getName();
+                       $tl = $this->makeKnownLinkObj( $wgUser->getTalkPage(),
+                               wfMsg( 'mytalk' ) );
+                       if ( $wgUser->getNewtalk() ) {
+                               $tl .= " *";
+                       }
+
+                       $s .= $this->makeKnownLinkObj( $wgUser->getUserPage(),
+                               wfMsg( "mypage" ) )
+                         . $sep . $tl
+                         . $sep . $this->specialLink( "watchlist" )
+                         . $sep . $this->makeKnownLinkObj( Title::makeTitle( NS_SPECIAL, "Contributions" ),
+                               wfMsg( "mycontris" ), "target=" . wfUrlencode($wgUser->getName() ) )            
+                         . $sep . $this->specialLink( "preferences" )
+                         . $sep . $this->specialLink( "userlogout" );
+               } else {
+                       $s .= $this->specialLink( "userlogin" );
+               }
+
+               $s .= $this->menuHead( "qbspecialpages" )
+                 . $this->specialLink( "newpages" ) 
+                 . $sep . $this->specialLink( "imagelist" ) 
+                 . $sep . $this->specialLink( "statistics" ) 
+                 . $sep . $this->bugReportsLink();
+               if ( $wgUser->isLoggedIn() && $wgEnableUploads ) {
+                       $s .= $sep . $this->specialLink( "upload" );
+               }
+               global $wgSiteSupportPage;
+               if( $wgSiteSupportPage) {
+                       $s .= $sep."<a href=\"".htmlspecialchars($wgSiteSupportPage)."\" class =\"internal\">"
+                             .wfMsg( "sitesupport" )."</a>";
+               }
+               
+               $s .= $sep . $this->makeKnownLinkObj(
+                       Title::makeTitle( NS_SPECIAL, 'Specialpages' ),
+                       wfMsg( 'moredotdotdot' ) );
+
+               $s .= $sep . "\n</div>\n";
+               return $s;
+       }
+
+       function menuHead( $key )
+       {
+               $s = "\n<h6>" . wfMsg( $key ) . "</h6>";
+               return $s;
+       }
+
+       function searchForm( $label = "" )
+       {
+               global $wgRequest;
+
+               $search = $wgRequest->getText( 'search' );
+               $action = $this->escapeSearchLink();
+               $s = "<form id=\"search\" method=\"get\" class=\"inline\" action=\"$action\">";
+               if ( "" != $label ) { $s .= "{$label}: "; }
+
+               $s .= "<input type='text' name=\"search\" size='14' value=\""
+                 . htmlspecialchars(substr($search,0,256)) . "\" />"
+                 . "<br /><input type='submit' name=\"go\" value=\"" . htmlspecialchars( wfMsg( "go" ) ) . "\" /> <input type='submit' name=\"fulltext\" value=\"" . htmlspecialchars( wfMsg( "search" ) ) . "\" /></form>";
+
+               return $s;
+       }
+}
+
+?>
diff --git a/skins/MonoBook.php b/skins/MonoBook.php
new file mode 100644 (file)
index 0000000..9df9f9e
--- /dev/null
@@ -0,0 +1,225 @@
+<?php
+/**
+ * MonoBook nouveau
+ *
+ * Translated from gwicke's previous TAL template version to remove
+ * dependency on PHPTAL.
+ *
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Skins
+ */
+
+if( !defined( 'MEDIAWIKI' ) )
+       die();
+
+/** */
+require_once('includes/SkinTemplate.php');
+
+/**
+ * Inherit main code from SkinTemplate, set the CSS and template filter.
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Skins
+ */
+class SkinMonoBook extends SkinTemplate {
+       /** Using monobook. */
+       function initPage( &$out ) {
+               SkinTemplate::initPage( $out );
+               $this->skinname  = 'monobook';
+               $this->stylename = 'monobook';
+               $this->template  = 'MonoBookTemplate';
+       }
+}
+
+/**
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Skins
+ */
+class MonoBookTemplate extends QuickTemplate {
+       /**
+        * Template filter callback for MonoBook skin.
+        * Takes an associative array of data set from a SkinTemplate-based
+        * class, and a wrapper for MediaWiki's localization database, and
+        * outputs a formatted page.
+        *
+        * @access private
+        */
+       function execute() {
+               // Suppress warnings to prevent notices about missing indexes in $this->data
+               wfSuppressWarnings();
+
+?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<?php $this->text('lang') ?>" lang="<?php $this->text('lang') ?>" dir="<?php $this->text('dir') ?>">
+  <head>
+    <meta http-equiv="Content-Type" content="<?php $this->text('mimetype') ?>; charset=<?php $this->text('charset') ?>" />
+    <?php $this->html('headlinks') ?>
+    <title><?php $this->text('pagetitle') ?></title>
+    <style type="text/css" media="screen,projection">/*<![CDATA[*/ @import "<?php $this->text('stylepath') ?>/<?php $this->text('stylename') ?>/main.css"; /*]]>*/</style>
+    <link rel="stylesheet" type="text/css" <?php if(empty($this->data['printable']) ) { ?>media="print"<?php } ?> href="<?php $this->text('stylepath') ?>/common/commonPrint.css" />
+    <!--[if lt IE 5.5000]><style type="text/css">@import "<?php $this->text('stylepath') ?>/<?php $this->text('stylename') ?>/IE50Fixes.css";</style><![endif]-->
+    <!--[if IE 5.5000]><style type="text/css">@import "<?php $this->text('stylepath') ?>/<?php $this->text('stylename') ?>/IE55Fixes.css";</style><![endif]-->
+    <!--[if gte IE 6]><style type="text/css">@import "<?php $this->text('stylepath') ?>/<?php $this->text('stylename') ?>/IE60Fixes.css";</style><![endif]-->
+    <!--[if lt IE 7]><script type="<?php $this->text('jsmimetype') ?>" src="<?php $this->text('stylepath') ?>/common/IEFixes.js"></script>
+    <meta http-equiv="imagetoolbar" content="no" /><![endif]-->
+    <?php if($this->data['jsvarurl'  ]) { ?><script type="<?php $this->text('jsmimetype') ?>" src="<?php $this->text('jsvarurl'  ) ?>"></script><?php } ?>
+    <script type="<?php $this->text('jsmimetype') ?>" src="<?php                                   $this->text('stylepath' ) ?>/common/wikibits.js"></script>
+    <?php if($this->data['usercss'   ]) { ?><style type="text/css"><?php              $this->html('usercss'   ) ?></style><?php    } ?>
+    <?php if($this->data['userjs'    ]) { ?><script type="<?php $this->text('jsmimetype') ?>" src="<?php $this->text('userjs'    ) ?>"></script><?php } ?>
+    <?php if($this->data['userjsprev']) { ?><script type="<?php $this->text('jsmimetype') ?>"><?php      $this->html('userjsprev') ?></script><?php   } ?>
+    <?php if($this->data['trackbackhtml']) print $this->data['trackbackhtml']; ?>
+  </head>
+  <body <?php if($this->data['body_ondblclick']) { ?>ondblclick="<?php $this->text('body_ondblclick') ?>"<?php } ?>
+        <?php if($this->data['body_onload'    ]) { ?>onload="<?php     $this->text('body_onload')     ?>"<?php } ?>
+        <?php if($this->data['nsclass'        ]) { ?>class="<?php      $this->text('nsclass')         ?>"<?php } ?>>
+    <div id="globalWrapper">
+      <div id="column-content">
+       <div id="content">
+         <a name="top" id="top"></a>
+         <?php if($this->data['sitenotice']) { ?><div id="siteNotice"><?php $this->html('sitenotice') ?></div><?php } ?>
+         <h1 class="firstHeading"><?php $this->text('title') ?></h1>
+         <div id="bodyContent">
+           <h3 id="siteSub"><?php $this->msg('tagline') ?></h3>
+           <div id="contentSub"><?php $this->html('subtitle') ?></div>
+           <?php if($this->data['undelete']) { ?><div id="contentSub"><?php     $this->html('undelete') ?></div><?php } ?>
+           <?php if($this->data['newtalk'] ) { ?><div class="usermessage"><?php $this->html('newtalk')  ?></div><?php } ?>
+           <!-- start content -->
+           <?php $this->html('bodytext') ?>
+           <?php if($this->data['catlinks']) { ?><div id="catlinks"><?php       $this->html('catlinks') ?></div><?php } ?>
+           <!-- end content -->
+           <div class="visualClear"></div>
+         </div>
+       </div>
+      </div>
+      <div id="column-one">
+       <div id="p-cactions" class="portlet">
+         <h5><?php $this->msg('views') ?></h5>
+         <ul>
+           <?php foreach($this->data['content_actions'] as $key => $action) {
+              ?><li id="ca-<?php echo htmlspecialchars($key) ?>"
+              <?php if($action['class']) { ?>class="<?php echo htmlspecialchars($action['class']) ?>"<?php } ?>
+              ><a href="<?php echo htmlspecialchars($action['href']) ?>"><?php
+              echo htmlspecialchars($action['text']) ?></a></li><?php
+            } ?>
+         </ul>
+       </div>
+       <div class="portlet" id="p-personal">
+         <h5><?php $this->msg('personaltools') ?></h5>
+         <div class="pBody">
+           <ul>
+           <?php foreach($this->data['personal_urls'] as $key => $item) {
+              ?><li id="pt-<?php echo htmlspecialchars($key) ?>"><a href="<?php
+              echo htmlspecialchars($item['href']) ?>"<?php
+              if(!empty($item['class'])) { ?> class="<?php
+              echo htmlspecialchars($item['class']) ?>"<?php } ?>><?php
+              echo htmlspecialchars($item['text']) ?></a></li><?php
+           } ?>
+           </ul>
+         </div>
+       </div>
+       <div class="portlet" id="p-logo">
+         <a style="background-image: url(<?php $this->text('logopath') ?>);"
+           href="<?php echo htmlspecialchars($this->data['nav_urls']['mainpage']['href'])?>"
+           title="<?php $this->msg('mainpage') ?>"></a>
+       </div>
+       <script type="<?php $this->text('jsmimetype') ?>"> if (window.isMSIE55) fixalpha(); </script>
+       <?php foreach ($this->data['sidebar'] as $bar => $cont) { ?>
+       <div class='portlet' id='p-<?php echo htmlspecialchars($bar) ?>'>
+         <h5><?php $out = wfMsg( $bar ); if (wfNoMsg($bar, $out)) echo $bar; else echo $out; ?></h5>
+         <div class='pBody'>
+           <ul>
+           <?php foreach($cont as $key => $val) { ?>
+             <li id="<?php echo htmlspecialchars($val['id']) ?>"><a href="<?php echo htmlspecialchars($val['href']) ?>"><?php echo htmlspecialchars($val['text'])?></a></li>
+            <?php } ?>
+           </ul>
+         </div>
+       </div>
+       <?php } ?>
+       <div id="p-search" class="portlet">
+         <h5><label for="searchInput"><?php $this->msg('search') ?></label></h5>
+         <div class="pBody">
+           <form name="searchform" action="<?php $this->text('searchaction') ?>" id="searchform">
+             <input id="searchInput" name="search" type="text"
+               <?php if($this->haveMsg('accesskey-search')) {
+                 ?>accesskey="<?php $this->msg('accesskey-search') ?>"<?php }
+               if( isset( $this->data['search'] ) ) {
+                 ?> value="<?php $this->text('search') ?>"<?php } ?> />
+             <input type='submit' name="go" class="searchButton" id="searchGoButton"
+               value="<?php $this->msg('go') ?>"
+               />&nbsp;<input type='submit' name="fulltext"
+               class="searchButton"
+               value="<?php $this->msg('search') ?>" />
+           </form>
+         </div>
+       </div>
+       <div class="portlet" id="p-tb">
+         <h5><?php $this->msg('toolbox') ?></h5>
+         <div class="pBody">
+           <ul>
+                 <?php if($this->data['notspecialpage']) { foreach( array( 'whatlinkshere', 'recentchangeslinked' ) as $special ) { ?>
+                 <li id="t-<?php echo $special?>"><a href="<?php
+                   echo htmlspecialchars($this->data['nav_urls'][$special]['href'])
+                   ?>"><?php echo $this->msg($special) ?></a></li>
+                 <?php } } ?>
+              <?php if(isset($this->data['nav_urls']['trackbacklink'])) { ?>
+                 <li id="t-trackbacklink"><a href="<?php
+                   echo htmlspecialchars($this->data['nav_urls']['trackbacklink']['href'])
+                   ?>"><?php echo $this->msg('trackbacklink') ?></a></li>
+             <?php } ?>
+             <?php if($this->data['feeds']) { ?><li id="feedlinks"><?php foreach($this->data['feeds'] as $key => $feed) {
+               ?><span id="feed-<?php echo htmlspecialchars($key) ?>"><a href="<?php
+               echo htmlspecialchars($feed['href']) ?>"><?php echo htmlspecialchars($feed['text'])?></a>&nbsp;</span>
+               <?php } ?></li><?php } ?>
+             <?php foreach( array('contributions', 'emailuser', 'upload', 'specialpages') as $special ) { ?>
+             <?php if($this->data['nav_urls'][$special]) {?><li id="t-<?php echo $special ?>"><a href="<?php
+               echo htmlspecialchars($this->data['nav_urls'][$special]['href'])
+               ?>"><?php $this->msg($special) ?></a></li><?php } ?>
+             <?php } ?>
+             <?php if(!empty($this->data['nav_urls']['print']['href'])) { ?>
+             <li id="t-print"><a href="<?php
+                   echo htmlspecialchars($this->data['nav_urls']['print']['href'])
+                   ?>"><?php echo $this->msg('printableversion') ?></a></li>
+             <?php } ?>
+           </ul>
+         </div>
+       </div>
+       <?php if( $this->data['language_urls'] ) { ?><div id="p-lang" class="portlet">
+         <h5><?php $this->msg('otherlanguages') ?></h5>
+         <div class="pBody">
+           <ul>
+             <?php foreach($this->data['language_urls'] as $langlink) { ?>
+             <li class="<?php echo htmlspecialchars($langlink['class'])?>">
+             <a href="<?php echo htmlspecialchars($langlink['href'])
+               ?>"><?php echo $langlink['text'] ?></a>
+             </li>
+             <?php } ?>
+           </ul>
+         </div>
+       </div>
+       <?php } ?>
+      </div><!-- end of the left (by default at least) column -->
+      <div class="visualClear"></div>
+      <div id="footer">
+    <?php if($this->data['poweredbyico']) { ?><div id="f-poweredbyico"><?php $this->html('poweredbyico') ?></div><?php } ?>
+       <?php if($this->data['copyrightico']) { ?><div id="f-copyrightico"><?php $this->html('copyrightico') ?></div><?php } ?>
+       <ul id="f-list">
+         <?php if($this->data['lastmod'   ]) { ?><li id="f-lastmod"><?php    $this->html('lastmod')    ?></li><?php } ?>
+         <?php if($this->data['viewcount' ]) { ?><li id="f-viewcount"><?php  $this->html('viewcount')  ?></li><?php } ?>
+         <?php if($this->data['numberofwatchingusers' ]) { ?><li id="f-numberofwatchingusers"><?php  $this->html('numberofwatchingusers') ?></li><?php } ?>
+         <?php if($this->data['credits'   ]) { ?><li id="f-credits"><?php    $this->html('credits')    ?></li><?php } ?>
+         <?php if($this->data['copyright' ]) { ?><li id="f-copyright"><?php  $this->html('copyright')  ?></li><?php } ?>
+         <?php if($this->data['about'     ]) { ?><li id="f-about"><?php      $this->html('about')      ?></li><?php } ?>
+         <?php if($this->data['disclaimer']) { ?><li id="f-disclaimer"><?php $this->html('disclaimer') ?></li><?php } ?>
+         <?php if($this->data['tagline']) { ?><li id="f-tagline"><?php echo $this->data['tagline'] ?></li><?php } ?>
+       </ul>
+      </div>
+    </div>
+    <?php $this->html('reporttime') ?>
+  </body>
+</html>
+<?php
+       wfRestoreWarnings();
+       }
+}
+?>
diff --git a/skins/MySkin.php b/skins/MySkin.php
new file mode 100644 (file)
index 0000000..232a0cf
--- /dev/null
@@ -0,0 +1,30 @@
+<?php
+/**
+ * See skin.txt
+ *
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Skins
+ */
+
+if( !defined( 'MEDIAWIKI' ) )
+       die();
+
+/** */
+require_once('MonoBook.php');
+
+/**
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Skins
+ */
+class SkinMySkin extends SkinTemplate {
+       function initPage( &$out ) {
+               SkinTemplate::initPage( $out );
+               $this->skinname  = 'myskin';
+               $this->stylename = 'myskin';
+               $this->template  = 'MonoBookTemplate';
+       }
+}
+
+?>
diff --git a/skins/Nostalgia.php b/skins/Nostalgia.php
new file mode 100644 (file)
index 0000000..36ee791
--- /dev/null
@@ -0,0 +1,98 @@
+<?php
+/**
+ * See skin.txt
+ *
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Skins
+ */
+
+if( !defined( 'MEDIAWIKI' ) )
+       die();
+
+/**
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Skins
+ */
+class SkinNostalgia extends Skin {
+
+       function initPage() {
+               # ...
+       }
+
+       function getStylesheet() {
+               return 'common/nostalgia.css';
+       }
+       function getSkinName() {
+               return "nostalgia";
+       }
+
+       function doBeforeContent() {
+               global $wgUser, $wgOut, $wgTitle;
+
+               $s = "\n<div id='content'>\n<div id='topbar'>";
+               $s .= $this->logoText( "right" );
+
+               $s .= $this->pageTitle();
+               $s .= $this->pageSubtitle() . "\n";
+
+               $s .= $this->topLinks() . "\n<br />";
+
+               $notice = wfGetSiteNotice();
+               if( $notice ) {
+                       $s .= "\n<div id='siteNotice'>$notice</div>\n";
+               }
+               $s .= $this->pageTitleLinks();
+
+               $ol = $this->otherLanguages();
+               if($ol) $s .= "<br />" . $ol;
+               
+               $cat = $this->getCategoryLinks();
+               if($cat) $s .= "<br />" . $cat;
+
+               $s .= "<br clear='all' /><hr />\n</div>\n";
+               $s .= "\n<div id='article'>";
+
+               return $s;
+       }
+
+       function topLinks() {
+               global $wgOut, $wgUser;
+               $sep = " |\n";
+
+               $s = $this->mainPageLink() . $sep
+                 . $this->specialLink( "recentchanges" );
+
+               if ( $wgOut->isArticle() ) {
+                       $s .=  $sep . $this->editThisPage()
+                         . $sep . $this->historyLink();
+               }
+               if ( $wgUser->isAnon() ) {
+                       $s .= $sep . $this->specialLink( "userlogin" );
+               } else {
+                       $s .= $sep . $this->specialLink( "userlogout" );
+               }
+               $s .= $sep . $this->specialPagesList();
+
+               return $s;
+       }
+
+       function doAfterContent() {
+               $s = "\n</div><br clear='all' />\n";
+
+               $s .= "\n<div id='footer'><hr />";
+
+               $s .= $this->bottomLinks();
+               $s .= "\n<br />" . $this->pageStats();
+               $s .= "\n<br />" . $this->mainPageLink()
+                 . " | " . $this->aboutLink()
+                 . " | " . $this->searchForm();
+
+               $s .= "\n</div>\n</div>\n";
+
+               return $s;
+       }
+}
+
+?>
diff --git a/skins/Simple.php b/skins/Simple.php
new file mode 100644 (file)
index 0000000..53a98e4
--- /dev/null
@@ -0,0 +1,70 @@
+<?php
+/**
+ * See skin.txt
+ *
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Skins
+ */
+
+if( !defined( 'MEDIAWIKI' ) )
+       die();
+
+/** */
+require_once('MonoBook.php');
+
+/**
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Skins
+ */
+class SkinSimple extends SkinTemplate {
+       function initPage( &$out ) {
+               SkinTemplate::initPage( $out );
+               $this->skinname  = 'simple';
+               $this->stylename = 'simple';
+               $this->template  = 'MonoBookTemplate';
+       }
+
+       function reallyDoGetUserStyles() {
+               global $wgUser;
+               $s = '';
+               if (($undopt = $wgUser->getOption("underline")) != 2) {
+                       $underline = $undopt ? 'underline' : 'none';
+                       $s .= "a { text-decoration: $underline; }\n";
+               }
+               if ($wgUser->getOption('highlightbroken')) {
+                       $s .= "a.new, #quickbar a.new { text-decoration: line-through; }\n";
+               } else {
+                       $s .= <<<END
+a.new, #quickbar a.new,
+a.stub, #quickbar a.stub {
+       color: inherit;
+       text-decoration: inherit;
+}
+a.new:after, #quickbar a.new:after {
+       content: "?";
+       color: #CC2200;
+       text-decoration: $underline;
+}
+a.stub:after, #quickbar a.stub:after {
+       content: "!";
+       color: #772233;
+       text-decoration: $underline;
+}
+END;
+               }
+               if ($wgUser->getOption('justify')) {
+                       $s .= "#article, #bodyContent { text-align: justify; }\n";
+               }
+               if (!$wgUser->getOption('showtoc')) {
+                       $s .= "#toc { display: none; }\n";
+               }
+               if (!$wgUser->getOption('editsection')) {
+                       $s .= ".editsection { display: none; }\n";
+               }
+               return $s;
+       }
+}
+
+?>
diff --git a/skins/Skin.sample b/skins/Skin.sample
new file mode 100644 (file)
index 0000000..c011c14
--- /dev/null
@@ -0,0 +1,19 @@
+<?php
+# Your class extension is defined there.
+#
+# Do NOT use PHPTal with this sample, if you want PHPTal support have a look at
+# the other sample : SkinPHPTal.sample.
+#
+# The class name MUST begin with 'Skin' and the rest is the name of the file
+# excluding '.php'
+# This file is named Skin.sample (but it should end with php). So the
+# class name will be 'Skin' . 'Skin'
+
+class SkinSkin extends Skin {
+# Override method below
+#
+
+}
+
+}
+?>
diff --git a/skins/SkinPHPTal.sample b/skins/SkinPHPTal.sample
new file mode 100644 (file)
index 0000000..683c208
--- /dev/null
@@ -0,0 +1,28 @@
+<?php
+require_once('includes/SkinPHPTal.php');
+
+# Test if PHPTal is enabled. If not MediaWiki will load the 'standard' skin
+# which doesnt use PHPTal
+if( class_exists( 'SkinPHPTal' ) ) {
+       
+       # Your class extension is defined there.
+       #
+       # The class name MUST begin with 'Skin' and the rest is the name of the file
+       # excluding '.php'
+       # This file is named SkinPHPTal.sample (but it should end with php). So the
+       # class name will be 'Skin' . 'SkinPHPTal'
+       
+       class SkinSkinPHPTal extends SkinPHPTal {
+               function initPage( &$out ) {
+                       SkinPHPTal::initPage( $out );
+                       $this->skinname = 'name of your skin all lower case';
+                       $this->template = 'phptal template used do not put the .pt';
+               }
+       
+       # Override method below
+       #
+       
+       }
+
+}
+?>
diff --git a/skins/Standard.php b/skins/Standard.php
new file mode 100644 (file)
index 0000000..9e20e1a
--- /dev/null
@@ -0,0 +1,291 @@
+<?php
+/**
+ * See skin.txt
+ *
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Skins
+ */
+
+if( !defined( 'MEDIAWIKI' ) )
+       die();
+
+/**
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Skins
+ */
+class SkinStandard extends Skin {
+
+       /**
+        *
+        */
+       function getHeadScripts() {
+               global $wgStylePath, $wgJsMimeType;
+
+               $s = parent::getHeadScripts();
+               if ( 3 == $this->qbSetting() ) { # Floating left
+                       $s .= "<script language='javascript' type='$wgJsMimeType' " .
+                         "src='{$wgStylePath}/common/sticky.js'></script>\n";
+               }
+               return $s;
+       }
+
+       /**
+        *
+        */
+       function getUserStyles() {
+               global $wgStylePath;
+               $s = '';
+               if ( 3 == $this->qbSetting() ) { # Floating left
+                       $s .= "<style type='text/css'>\n" .
+                         "@import '{$wgStylePath}/common/quickbar.css';\n</style>\n";
+               } else if ( 4 == $this->qbSetting() ) { # Floating right        
+                       $s .= "<style type='text/css'>\n" .
+                         "@import '{$wgStylePath}/common/quickbar-right.css';\n</style>\n";
+               }
+               $s .= parent::getUserStyles();
+               return $s;
+       }
+
+       /**
+        *
+        */
+       function doGetUserStyles() {
+               global $wgUser, $wgOut, $wgStylePath;
+
+               $s = parent::doGetUserStyles();
+               $qb = $this->qbSetting();
+
+               if ( 2 == $qb ) { # Right
+                       $s .= "#quickbar { position: absolute; top: 4px; right: 4px; " .
+                         "border-left: 2px solid #000000; }\n" .
+                         "#article { margin-left: 4px; margin-right: 152px; }\n";
+               } else if ( 1 == $qb || 3 == $qb ) {
+                       $s .= "#quickbar { position: absolute; top: 4px; left: 4px; " .
+                         "border-right: 1px solid gray; }\n" .
+                         "#article { margin-left: 152px; margin-right: 4px; }\n";
+               } else if ( 4 == $qb) {
+                       $s .= "#quickbar { border-right: 1px solid gray; }\n" .
+                         "#article { margin-right: 152px; margin-left: 4px; }\n";
+               }       
+               return $s;
+       }
+
+       /**
+        *
+        */
+       function getBodyOptions() {
+               $a = parent::getBodyOptions();
+
+               if ( 3 == $this->qbSetting() ) { # Floating left
+                       $qb = "setup(\"quickbar\")";
+                       if($a["onload"]) {
+                               $a["onload"] .= ";$qb";
+                       } else {
+                               $a["onload"] = $qb;
+                       }
+               }
+               return $a;
+       }
+
+       function doAfterContent() {
+               global $wgUser, $wgOut, $wgContLang;
+               $fname =  'SkinStandard::doAfterContent';
+               wfProfileIn( $fname );
+               wfProfileIn( $fname.'-1' );
+
+               $s = "\n</div><br style=\"clear:both\" />\n";
+               $s .= "\n<div id='footer'>";
+               $s .= '<table border="0" cellspacing="0"><tr>';
+
+               wfProfileOut( $fname.'-1' );
+               wfProfileIn( $fname.'-2' );
+
+               $qb = $this->qbSetting();
+               $shove = ($qb != 0);
+               $left = ($qb == 1 || $qb == 3);
+               if($wgContLang->isRTL()) $left = !$left;
+
+               if ( $shove && $left ) { # Left
+                               $s .= $this->getQuickbarCompensator();
+               }
+               wfProfileOut( $fname.'-2' );
+               wfProfileIn( $fname.'-3' );
+               $l = $wgContLang->isRTL() ? 'right' : 'left';
+               $s .= "<td class='bottom' align='$l' valign='top'>";
+
+               $s .= $this->bottomLinks();
+               $s .= "\n<br />" . $this->mainPageLink()
+                 . ' | ' . $this->aboutLink()
+                 . ' | ' . $this->specialLink( 'recentchanges' )
+                 . ' | ' . $this->searchForm()
+                 . '<br /><span id="pagestats">' . $this->pageStats() . '</span>';
+
+               $s .= "</td>";
+               if ( $shove && !$left ) { # Right
+                       $s .= $this->getQuickbarCompensator();
+               }
+               $s .= "</tr></table>\n</div>\n</div>\n";
+
+               wfProfileOut( $fname.'-3' );
+               wfProfileIn( $fname.'-4' );
+               if ( 0 != $qb ) { $s .= $this->quickBar(); }
+               wfProfileOut( $fname.'-4' );
+               wfProfileOut( $fname );
+               return $s;
+       }
+
+       function quickBar() {
+               global $wgOut, $wgTitle, $wgUser, $wgRequest, $wgContLang;
+               global $wgEnableUploads, $wgRemoteUploads;
+
+               $fname =  'Skin::quickBar';
+               wfProfileIn( $fname );
+
+               $action = $wgRequest->getText( 'action' );
+               $wpPreview = $wgRequest->getBool( 'wpPreview' );
+               $tns=$wgTitle->getNamespace();
+
+               $s = "\n<div id='quickbar'>";
+               $s .= "\n" . $this->logoText() . "\n<hr class='sep' />";
+
+               $sep = "\n<br />";
+               
+               # Use the first heading from the Monobook sidebar as the "browse" section
+               $bar = $this->buildSidebar();
+               $browseLinks = reset( $bar );
+
+               foreach ( $browseLinks as $link ) {
+                       if ( $link['text'] != '-' ) {
+                               $s .= "<a href=\"{$link['href']}\">" .
+                                       htmlspecialchars( $link['text'] ) . '</a>' . $sep;
+                       }
+               }
+
+               if( $wgUser->isLoggedIn() ) {
+                       $s.= $this->specialLink( 'watchlist' ) ;
+                       $s .= $sep . $this->makeKnownLink( $wgContLang->specialPage( 'Contributions' ),
+                               wfMsg( 'mycontris' ), 'target=' . wfUrlencode($wgUser->getName() ) );
+               }
+               // only show watchlist link if logged in
+               $s .= "\n<hr class='sep' />";
+               $articleExists = $wgTitle->getArticleId();
+               if ( $wgOut->isArticle() || $action =='edit' || $action =='history' || $wpPreview) {
+                       if($wgOut->isArticle()) {
+                               $s .= '<strong>' . $this->editThisPage() . '</strong>';
+                       } else { # backlink to the article in edit or history mode
+                               if($articleExists){ # no backlink if no article
+                                       switch($tns) {
+                                               case 0:
+                                               $text = wfMsg('articlepage');
+                                               break;
+                                               case 1:
+                                               $text = wfMsg('viewtalkpage');
+                                               break;
+                                               case 2:
+                                               $text = wfMsg('userpage');
+                                               break;
+                                               case 3:
+                                               $text = wfMsg('viewtalkpage');
+                                               break;
+                                               case 4:
+                                               $text = wfMsg('wikipediapage');
+                                               break;
+                                               case 5:
+                                               $text = wfMsg('viewtalkpage');
+                                               break;
+                                               case 6:
+                                               $text = wfMsg('imagepage');
+                                               break;
+                                               case 7:
+                                               $text = wfMsg('viewtalkpage');
+                                               break;
+                                               default:
+                                               $text= wfMsg('articlepage');
+                                       }
+
+                                       $link = $wgTitle->getText();
+                                       if ($nstext = $wgContLang->getNsText($tns) ) { # add namespace if necessary
+                                               $link = $nstext . ':' . $link ;
+                                       }
+
+                                       $s .= $this->makeLink( $link, $text );
+                               } elseif( $wgTitle->getNamespace() != NS_SPECIAL ) {
+                                       # we just throw in a "New page" text to tell the user that he's in edit mode,
+                                       # and to avoid messing with the separator that is prepended to the next item
+                                       $s .= '<strong>' . wfMsg('newpage') . '</strong>';
+                               }
+
+                       }
+
+
+                       if( $tns%2 && $action!='edit' && !$wpPreview) {
+                               $s.= '<br />'.$this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg('postcomment'),'action=edit&section=new');
+                       }
+
+                       /*
+                       watching could cause problems in edit mode:
+                       if user edits article, then loads "watch this article" in background and then saves
+                       article with "Watch this article" checkbox disabled, the article is transparently
+                       unwatched. Therefore we do not show the "Watch this page" link in edit mode
+                       */
+                       if ( $wgUser->isLoggedIn() && $articleExists) {
+                               if($action!='edit' && $action != 'submit' )
+                               {
+                                       $s .= $sep . $this->watchThisPage();
+                               }
+                               if ( $wgTitle->userCanEdit() )
+                                       $s .= $sep . $this->moveThisPage();
+                       }
+                       if ( $wgUser->isAllowed('delete') and $articleExists ) {
+                               $s .= $sep . $this->deleteThisPage() .
+                               $sep . $this->protectThisPage();
+                       }
+                       $s .= $sep . $this->talkLink();
+                       if ($articleExists && $action !='history') {
+                               $s .= $sep . $this->historyLink();
+                       }
+                       $s.=$sep . $this->whatLinksHere();
+
+                       if($wgOut->isArticleRelated()) {
+                               $s .= $sep . $this->watchPageLinksLink();
+                       }
+
+                       if ( NS_USER == $wgTitle->getNamespace()
+                               || $wgTitle->getNamespace() == NS_USER_TALK ) {
+
+                               $id=User::idFromName($wgTitle->getText());
+                               $ip=User::isIP($wgTitle->getText());
+
+                               if($id||$ip) {
+                                       $s .= $sep . $this->userContribsLink();
+                               }
+                               if( $this->showEmailUser( $id ) ) {
+                                       $s .= $sep . $this->emailUserLink();
+                               }
+                       }
+                       $s .= "\n<br /><hr class='sep' />";
+               }
+
+               if ( $wgUser->isLoggedIn() && ( $wgEnableUploads || $wgRemoteUploads ) ) {
+                       $s .= $this->specialLink( 'upload' ) . $sep;
+               }
+               $s .= $this->specialLink( 'specialpages' )
+                 . $sep . $this->bugReportsLink();
+
+               global $wgSiteSupportPage;
+               if( $wgSiteSupportPage ) {
+                       $s .= "\n<br /><a href=\"" . htmlspecialchars( $wgSiteSupportPage ) .
+                         '" class="internal">' . wfMsg( 'sitesupport' ) . '</a>';
+               }
+
+               $s .= "\n<br /></div>\n";
+               wfProfileOut( $fname );
+               return $s;
+       }
+
+
+}
+
+?>
diff --git a/skins/chick/IE50Fixes.css b/skins/chick/IE50Fixes.css
new file mode 100644 (file)
index 0000000..dd9eda3
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+** IE5.0 Fix Stylesheet
+*/
+
+#column-content {
+    margin: 0 !important;
+    float: none;
+}
+#column-content #content { 
+    margin-top: 3em; 
+    height: 1%;
+}
+#column-one {
+    position: absolute;
+    overflow: visible;
+    top: 0;
+    left: 0;
+    z-index: 3;
+}
+#footer {
+    margin: 0 0 0 13.6em;
+}
+
+/* IE 5 & 5.5 interpret keyword sizes one off */
+body { font-size: xx-small; }
+/*
+** the edit tabs
+*/
+#p-cactions li {
+    float: left;
+    padding-top: 0;
+    padding-bottom: 0 !important;
+    height: 0.9em;
+}
+#p-cactions li a {
+    display: block;
+    padding-bottom: 0.045em;
+}
+#p-cactions li.selected a {
+    padding-bottom: 0.17em;
+}
+#p-cactions li a:hover {
+    padding-bottom: 0.17em;
+}
+/* 5.0 doesn't like the background icon for external links and user */
+.link-external,
+.external {
+    background: none;
+    padding: 0;
+}
+#p-personal ul { float: right }
+#p-personal li { float: left }
+li#pt-userpage,
+li#pt-anonuserpage,
+li#pt-login,
+li#pt-logout {
+    background: none;
+    padding-left: none;
+}
+.visualClear {
+    width:100%;
+    height: 0px;
+    padding:0;
+    margin:0;
+}
+.firstHeading { margin-bottom: 0.3em; }
+/*div{ border:1px solid Red !important;}*/
diff --git a/skins/chick/IE55Fixes.css b/skins/chick/IE55Fixes.css
new file mode 100644 (file)
index 0000000..2f78561
--- /dev/null
@@ -0,0 +1,81 @@
+/* IE5.5/win- only fixes */
+
+#column-content { 
+    float: none; 
+    margin-left: 0;
+    height: 1%;
+}
+#column-content #content {
+    position: relative;
+    z-index: 5;
+    margin-left: 12.2em;
+    margin-top: 3em;
+    height: 1%;
+}
+#column-one {
+    position: absolute;
+    top: 0;
+    left: 0;
+    z-index: 4;
+    width: 100%;
+}
+#footer {
+    margin-left: 13.6em;
+    border-left: 1px solid #fabd23;
+}
+
+/*#bodyContent div,
+#bodyContent pre { overflow: auto; }*/
+
+#p-personal { padding-bottom: 0.1em; }
+
+body { font-size: xx-small; }
+
+#p-cactions {
+    width: 76% !important;
+    z-index: 3 !important;
+    float: none;
+}
+#p-cactions li {
+    padding-bottom: 0 !important;
+    border: none;
+    background-color: transparent;
+    cursor: default;
+    float: none !important;
+}
+#p-cactions li a {
+    display: inline-block !important;
+    vertical-align: top;
+    padding-bottom: 0;
+    border: solid #aaa;
+    border-width: 1px 1px 0;
+}
+#p-cactions li.selected a {
+    border-color: #fabd23;
+    padding-bottom: 0.17em;
+}
+#p-cactions li a:hover {
+    padding-bottom: 0.17em;
+}
+.portlet {
+    overflow:hidden;
+}
+#bodyContent a.external {
+    background: url(external.png) center right no-repeat;
+    padding-right: 13px;
+}
+/* show the hand */
+#p-logo a,
+#p-logo a:hover {
+    cursor: pointer;
+}
+.visualClear {
+    width:90%;
+    height: 1px;
+    padding:0;
+    margin:0;
+}
+
+#editform {
+    width: 100%;
+}
diff --git a/skins/chick/IE60Fixes.css b/skins/chick/IE60Fixes.css
new file mode 100644 (file)
index 0000000..feec15f
--- /dev/null
@@ -0,0 +1,79 @@
+/* 6.0 - only fixes */
+/* content area */ 
+/* workaround for various ie float bugs */
+#column-content { 
+    float: none; 
+    margin-left: 0;
+    height: 1%;
+}
+#column-content #content {
+    margin-left: 12.2em;
+    margin-top: 3em;
+    height: 1%;
+}
+#column-one {
+    position: absolute;
+    top: 0;
+    left: 0;
+    z-index: 4;
+}
+#footer {
+    margin-left: 13.6em;
+    border-left: 1px solid #fabd23;
+}
+
+/* the tabs */
+
+#p-cactions {
+    z-index: 3;
+}
+
+#p-cactions li {
+    padding-bottom: 0 !important;
+    border: none;
+    background-color: transparent;
+    cursor: default;
+    float: none !important;
+}
+#p-cactions li a {
+    display: inline-block !important;
+    vertical-align: top;
+    padding-bottom: 0;
+    border: solid #aaa;
+    border-width: 1px 1px 0;
+}
+#p-cactions li.selected a {
+    border-color: #fabd23;
+    padding-bottom: 0.17em;
+}
+#p-cactions li a:hover {
+    padding-bottom: 0.17em;
+}
+#portal-personaltools {
+    padding-bottom: 0.1em;
+}
+#bodyContent a.external {
+    background: url(external.png) center right no-repeat;
+    padding-right: 13px;
+}
+
+/* show the hand */
+#p-logo a,
+#p-logo a:hover {
+    cursor: pointer;
+}
+div.visualClear {
+    width:100%;
+    line-height: 0;
+}
+textarea {
+    width: 96%;
+}
+
+div.editsection,
+#catlinks,
+div.tright,
+div.tleft {
+    position: relative;
+}
+/*{ border:1px solid Red !important;}*/
diff --git a/skins/chick/main.css b/skins/chick/main.css
new file mode 100644 (file)
index 0000000..25c3ee2
--- /dev/null
@@ -0,0 +1,478 @@
+/*
+** MediaWiki 'chick' style sheet for PDAs or other small-screen devices.
+** Copyright Timwi
+** License: GPL (http://www.gnu.org/copyleft/gpl.html)
+**
+** Loosely based on Monobook by Gabriel Wicke
+*/
+
+body {
+    font-family: sans-serif;
+    color: Black;
+    margin: 0;
+    padding: 0.3em;
+}
+
+a { color: #002bb8; }
+a:visited { color: #5a3696; }
+a:active { color: #ffa500; }
+a.stub { color: #772233; }
+a.new,
+#p-personal a.new { color:#ba0000; }
+a.new:visited,
+#p-personal a.new:visited { color:#a55858; }
+
+img {
+    border: none;
+    vertical-align: middle;
+}
+p {
+    margin: 0.4em 0em 0.5em 0em;
+    line-height: 1.5em;
+}
+
+p img { margin: 0; }
+
+hr {
+    height: 1px;
+    color: #aaaaaa;
+    background-color: #aaaaaa;
+    border: 0;
+    margin: 0.2em 0 0.2em 0;
+}
+
+h1, h2, h3, h4, h5, h6 {
+    color: Black;
+    background: none;
+    font-weight: normal;
+    margin: 0;
+    padding-top: 0.5em;
+    padding-bottom: 0.17em;
+    border-bottom: 1px solid #aaaaaa;
+}
+h1 { font-size: 188%; }
+h2 { font-size: 150%; }
+h3, h4, h5, h6 {
+    border-bottom: none;
+    font-weight: bold;
+}
+h3 { font-size: 132%; }
+h4 { font-size: 116%; }
+h5 { font-size: 100%; }
+h6 { font-size: 80%;  }
+
+ul {
+    line-height: 1.5em;
+    margin: 0.3em 0 0 1.5em;
+    padding:0;
+}
+ol {
+    line-height: 1.5em;
+    margin: 0.3em 0 0 3.2em;
+    padding:0;
+    list-style-image: none;
+}
+li { margin-bottom: 0.1em; }
+dt {
+    font-weight: bold;
+    margin-bottom: 0.1em;
+}
+dl{
+    margin-top: 0.2em;
+    margin-bottom: 0.5em;
+}
+dd {
+    line-height: 1.5em;
+    margin-left: 2em;
+    margin-bottom: 0.1em;
+}
+
+fieldset {
+    border: 1px solid #2f6fab;
+    margin: 1em 0em 1em 0em;
+    padding: 0em 1em 1em 1em;
+    line-height: 1.5em;
+}
+legend {
+    background: White;
+    padding: 0.5em;
+    font-size: 95%;
+}
+form {
+    border: none;
+    margin: 0;
+}
+
+textarea {
+    border: 1px solid #2f6fab;
+    color: Black;
+    background-color: white;
+    width: 100%;
+    padding: 0.1em;
+    overflow: auto;
+}
+/* hide this from ie/mac and konq2.2 */
+@media All {
+    head:first-child+body input {
+        visibility: visible;
+        border: 1px solid #2f6fab;
+        color: Black;
+        background-color: white;
+        vertical-align: middle;
+        padding: 0.2em;
+    }
+}
+input.historysubmit {
+    padding: 0 0.3em 0.3em 0.3em !important;
+    font-size: 94%;
+    cursor: pointer;
+    height: 1.7em !important;
+    margin-left: 1.6em;
+}
+input[type="radio"],
+input[type="checkbox"] { border:none; }
+select {
+    border: 1px solid #2f6fab;
+    color: Black;
+    vertical-align: top;
+}
+abbr, acronym, .explain {
+    border-bottom: 1px dotted Black;
+    color: Black;
+    background: none;
+    cursor: help;
+}
+q {
+    font-family: Times, "Times New Roman", serif;
+    font-style: italic;
+}
+code { background-color: #f9f9f9; }
+pre {
+    padding: 1em;
+    border: 1px dashed #2f6fab;
+    color: Black;
+    background-color: #f9f9f9;
+    line-height: 1.1em;
+}
+
+/*
+** the main content area
+*/
+
+span.subpages { display: block; }
+
+/* Some space under the headers in the content area */
+#bodyContent h1, #bodyContent h2 { margin-bottom:0.6em; }
+#bodyContent h3,
+#bodyContent h4,
+#bodyContent h5 {
+    margin-bottom: 0.3em;
+}
+.firstHeading { margin-bottom:0.1em; }
+
+/* user notification thing */
+.usermessage {
+    background-color: #ffce7b;
+    border: 1px solid #ffa500;
+    color: Black;
+    font-weight: bold;
+    margin: 0.1em 0 0 0;
+    padding: 2px 5px;
+    vertical-align: middle;
+}
+#siteNotice {
+    text-align: center;
+    font-size: 95%;
+    padding: 0 0.9em 0 0.9em;
+}
+#siteNotice p { margin: 0; padding: 0; }
+.error {
+    color: red;
+    font-size: larger;
+}
+#catlinks {
+    border:1px solid #aaaaaa;
+    background-color:#f9f9f9;
+    padding: 2px 5px;
+    margin: 0.1em 0 0 0;
+    clear: both;
+}
+p.catlinks { margin: 0; padding: 0; }
+
+
+/* currently unused, intended to be used by a metadata box
+in the bottom-right corner of the content area */
+.documentDescription {
+    /* The summary text describing the document */
+    font-weight: bold;
+    display: block;
+    margin: 1em 0em;
+    line-height: 1.5em;
+}
+.documentByLine {
+    text-align: right;
+    font-size: 90%;
+    clear: both;
+    font-weight: normal;
+    color: #76797c;
+}
+
+/* emulate center */
+.center {
+    width: 100%;
+    text-align: center;
+}
+*.center * {
+    margin-left: auto;
+    margin-right: auto;
+}
+/* small for tables and similar */
+.small, .small * { font-size: 94%; }
+table.small { font-size: 100% }
+
+/*
+** content styles
+*/
+
+#toc {
+    /*border:1px solid #2f6fab;*/
+    border:1px solid #aaaaaa;
+    background-color:#f9f9f9;
+    padding:5px;
+    font-size: 95%;
+}
+#toc ul { margin-left: 2em; }
+#toc .toctoggle { font-size: 94%; }
+#toc .editsection {
+    margin-top: 0.7em;
+    font-size: 94%;
+}
+
+/* images */
+div.floatright, table.floatright {
+    clear: right;
+    float: right;
+    margin: 0;
+    position: relative;
+    border: 0.5em solid White;
+    border-width: 0.5em 0 0.8em 1.4em;
+}
+div.floatright p { font-style: italic; }
+div.floatleft, table.floatleft {
+    float: left;
+    margin: 0.3em 0.5em 0.5em 0;
+    position: relative;
+    border: 0.5em solid White;
+    border-width: 0.5em 1.4em 0.8em 0;
+}
+div.floatleft p { font-style: italic; }
+/* thumbnails */
+div.thumb {
+    margin-bottom: 0.5em;
+    border-style: solid; border-color: White;
+    width: auto;
+}
+div.thumb div {
+    border:1px solid #cccccc;
+    padding: 3px !important;
+    background-color:#f9f9f9;
+    font-size: 94%;
+    text-align: center;
+    overflow: hidden;
+}
+div.thumb div a img {
+    border:1px solid #cccccc;
+}
+div.thumb div div.thumbcaption {
+    border: none;
+    text-align: left;
+    line-height: 1.4em;
+    padding: 0.3em 0 0.1em 0;
+}
+div.magnify {
+    float: right;
+    border: none !important;
+    background: none !important;
+}
+div.magnify a, div.magnify img {
+    display: block;
+    border: none !important;
+    background: none !important;
+}
+div.tright {
+    clear: right;
+    float: right;
+    border-width: 0.5em 0 0.8em 1.4em;
+}
+div.tleft {
+    float: left;
+    margin-right:0.5em;
+    border-width: 0.5em 1.4em 0.8em 0;
+}
+
+.hiddenStructure {
+    display: none;
+}
+img.tex { vertical-align: middle; }
+span.texhtml { font-family: serif; }
+
+/*
+** classes for special content elements like town boxes
+** intended to be referenced directly from the wiki src
+*/
+
+/*
+** User styles
+*/
+/* table standards */
+table.rimage {
+    float:right;
+    position:relative;
+    margin-left:1em;
+    margin-bottom:1em;
+    text-align:center;
+}
+.toccolours {
+    border:1px solid #aaaaaa;
+    background-color:#f9f9f9;
+    padding:5px;
+    font-size: 95%;
+}
+div.townBox {
+    position:relative;
+    float:right;
+    background:White;
+    margin-left:1em;
+    border: 1px solid gray;
+    padding:0.3em;
+    width: 200px;
+    overflow: hidden;
+    clear: right;
+}
+div.townBox dl {
+    padding: 0;
+    margin: 0 0 0.3em 0;
+    font-size: 96%;
+}
+div.townBox dl dt {
+    background: none;
+    margin: 0.4em 0 0 0;
+}
+div.townBox dl dd {
+    margin: 0.1em 0 0 1.1em;
+    background-color: #f3f3f3;
+}
+
+/*
+** edit views etc
+*/
+.special li {
+    line-height: 1.4em;
+    margin: 0;
+    padding: 0;
+}
+
+/* Page history styling */
+/* the auto-generated edit comments */
+.autocomment { color: gray; }
+#pagehistory span.user {
+    margin-left: 1.4em;
+    margin-right: 0.4em;
+}
+#pagehistory span.minor { font-weight: bold; }
+#pagehistory li { border: 1px solid White; }
+#pagehistory li.selected {
+    background-color:#f9f9f9;
+    border:1px dashed #aaaaaa;
+}
+/*
+** Diff rendering
+*/
+table.diff { background:white; }
+td.diff-otitle { background:#ffffff; }
+td.diff-ntitle { background:#ffffff; }
+td.diff-addedline {
+    background:#ccffcc;
+    font-size: smaller;
+}
+td.diff-deletedline {
+    background:#ffffaa;
+    font-size: smaller;
+}
+td.diff-context {
+    background:#eeeeee;
+    font-size: smaller;
+}
+span.diffchange { color: red; }
+
+a.external { color: #3366bb; }
+
+div#footer { text-align: center; }
+
+ul#f-list li { list-style: none;  text-align: center; }
+
+div.portlet { margin: 0.5em 0; }
+
+.redirectText {
+       font-size:150%;
+       margin:5px;
+}
+
+ul.special li.not-patrolled, ol.special li.not-patrolled {
+       background-color: #ffa;
+}
+div.patrollink {
+       font-size: 75%;
+       text-align: right;
+}
+span.newpage, span.minor {
+       font-weight: bold;
+}
+
+span.updatedmarker {
+       color:black;
+       background-color:#00FF00;
+}
+span.newpageletter {
+       font-weight:bold;
+       color:black;
+       background-color:yellow;
+}
+span.minoreditletter {
+       color:black;
+       background-color:#C5FFE6;
+}
+
+table.gallery {
+        border:  1px solid #cccccc;
+        margin:  2px;
+        padding: 2px;
+        background-color:#ffffff;
+}
+
+table.gallery tr { 
+        vertical-align:top;
+}
+
+table.gallery td {
+      vertical-align:top;
+      background-color:#f9f9f9;
+      border: solid 2px white;
+}
+
+div.gallerybox {
+        margin: 2px;
+        width:  150px;
+}
+
+div.gallerybox div.thumb {
+        text-align: center;
+        border: 1px solid #cccccc;
+        margin: 2px;
+}       
+
+div.gallerytext {
+        font-size: 94%;
+        padding: 2px 4px;
+}       
+
diff --git a/skins/common/IEFixes.js b/skins/common/IEFixes.js
new file mode 100644 (file)
index 0000000..29c2d65
--- /dev/null
@@ -0,0 +1,126 @@
+// IE fixes javascript
+
+var isMSIE55 = (window.showModalDialog && window.clipboardData && window.createPopup);
+var doneIETransform;
+var doneIEAlphaFix;
+
+if (document.attachEvent)
+  document.attachEvent('onreadystatechange', hookit);
+
+function hookit() {
+    if (!doneIETransform && document.getElementById && document.getElementById('bodyContent')) {
+        doneIETransform = true;
+        relativeforfloats();
+        fixalpha();
+    }
+}
+
+// png alpha transparency fixes
+function fixalpha() {
+    // bg
+    if (isMSIE55 && !doneIEAlphaFix)
+    {
+        doneIEAlphaFix = true;
+        var plogo = document.getElementById('p-logo');
+        if (!plogo) return;
+
+        var logoa = plogo.getElementsByTagName('a')[0];
+        if (!logoa) return;
+
+        var bg = logoa.currentStyle.backgroundImage;
+        var imageUrl = bg.substring(5, bg.length-2);
+
+        if (imageUrl.substr(imageUrl.length-4).toLowerCase() == '.png') {
+            var logospan = logoa.appendChild(document.createElement('span'));
+           
+            logoa.style.backgroundImage = 'none';
+            logospan.style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=' + imageUrl + ')';
+            logospan.style.height = '100%';
+            logospan.style.position = 'absolute';
+            logospan.style.width = logoa.currentStyle.width;
+            logospan.style.cursor = 'hand';
+            // Center image with hack for IE5.5
+            if (document.documentElement.dir == "rtl") 
+            {
+              logospan.style.right = '50%';
+              logospan.style.setExpression('marginRight', '"-" + (this.offsetWidth / 2) + "px"');
+            }
+            else
+            {
+              logospan.style.left = '50%';
+              logospan.style.setExpression('marginLeft', '"-" + (this.offsetWidth / 2) + "px"');
+            }
+            logospan.style.top = '50%';
+            logospan.style.setExpression('marginTop', '"-" + (this.offsetHeight / 2) + "px"');
+            var linkFix = logoa.appendChild(logoa.cloneNode());
+            linkFix.style.position = 'absolute';
+            linkFix.style.height = '100%';
+            linkFix.style.width = '100%';
+        }
+    }
+}
+
+// fix ie6 disappering float bug
+function relativeforfloats() {
+    var bc = document.getElementById('bodyContent');
+    if (bc) {
+        var tables = bc.getElementsByTagName('table');
+        var divs = bc.getElementsByTagName('div');
+    }
+    setrelative(tables);
+    setrelative(divs);
+}
+function setrelative (nodes) {
+    var i = 0;
+    while (i < nodes.length) {
+        if(((nodes[i].style.float && nodes[i].style.float != ('none') ||
+        (nodes[i].align && nodes[i].align != ('none'))) &&
+        (!nodes[i].style.position || nodes[i].style.position != 'relative'))) 
+        {
+            nodes[i].style.position = 'relative';
+        }
+        i++;
+    }
+}
+
+
+// Expand links for printing
+
+String.prototype.hasClass = function(classWanted)
+{
+    var classArr = this.split(/\s/);
+    for (var i=0; i<classArr.length; i++)
+      if (classArr[i].toLowerCase() == classWanted.toLowerCase()) return true;
+    return false;
+}
+
+var expandedURLs;
+
+onbeforeprint = function() { 
+    expandedURLs = [];
+
+    var contentEl = document.getElementById("content");
+
+    if (contentEl)
+    {
+      var allLinks = contentEl.getElementsByTagName("a");
+
+      for (var i=0; i < allLinks.length; i++) {
+          if (allLinks[i].className.hasClass("external") && !allLinks[i].className.hasClass("free")) {
+              var expandedLink = document.createElement("span");
+              var expandedText = document.createTextNode(" (" + allLinks[i].href + ")");
+              expandedLink.appendChild(expandedText);
+              allLinks[i].parentNode.insertBefore(expandedLink, allLinks[i].nextSibling);
+              expandedURLs[i] = expandedLink;
+          }
+      }
+   }
+}
+
+onafterprint = function()
+{
+    for (var i=0; i < expandedURLs.length; i++)
+        if (expandedURLs[i])
+            expandedURLs[i].removeNode(true);
+}
\ No newline at end of file
diff --git a/skins/common/cologneblue.css b/skins/common/cologneblue.css
new file mode 100644 (file)
index 0000000..faf00fe
--- /dev/null
@@ -0,0 +1,97 @@
+@import url("common.css");
+
+body { margin: 0px; padding: 0px; color: black; }
+#specialform { display: inline; }
+#content { top: 0; margin: 0; padding: 0; }
+#topbar { padding: 0px; }
+#powersearch {
+  background: #DDEEFF; border-style: solid; border-width: 1px; padding: 2px;
+}
+#quickbar {
+ width: 140px; top: 18ex; padding: 2px; visibility: visible; z-index: 99;
+}
+#article, #article td, #article th, #article p {
+ font-family: Verdana, Arial, sans-serif;
+ font-size: 10pt; color: black;
+}
+#article p {
+ padding-top: 0; padding-bottom: 0;
+ margin-top: 1ex; margin-bottom: 0;
+}
+p, pre, td, th, li, dd, dt { line-height: 12pt; }
+textarea { overflow: auto; }
+
+#footer { padding: 4px; }
+#footer form { display: inline; }
+#sitetitle {
+ font-family: Times, serif;
+ color: white;
+ font-weight: normal; font-size: 32pt;
+ line-height: 32pt;
+}
+td.top {
+ background-color: #6688AA; color: white;
+ margin-top: 4px; margin-bottom: 4px;
+ padding-top: 0; padding-bottom: 0;
+ text-transform: uppercase;
+ font-family: Verdana, Arial, sans-serif; font-size: 8pt;
+}
+td.top a {
+ font-family: Verdana, Arial, sans-serif;
+ background-color: #6688AA; color: white;
+ text-decoration: none; font-size: 10pt;
+}
+td.bottom {
+ font-family: Verdana, Arial, sans-serif;
+ font-size: 10pt;
+ padding: 0;
+}
+#pagestats {
+ font-family: Verdana, Arial, sans-serif;
+ color: black;
+ font-size: 9pt;
+}
+#sitesub {
+ font-family: Verdana, Arial, sans-serif;
+ font-size: 9pt; font-weight: bold;
+ color: black;
+ padding-top: 0;
+}
+#quickbar {
+ font-family: Verdana, Arial, sans-serif;
+ font-size: 8pt; font-weight: bold; line-height: 9.5pt;
+ text-decoration: none;
+ color: black;
+ padding: 0; margin-top: 0;
+}
+#quickbar a { color: #446688; }
+
+#quickbar h6 {
+ font-family: Verdana, Arial, sans-serif;
+ font-size: 10pt; font-weight: bold; line-height: 12pt;
+ text-decoration: none;
+ color: #666666;
+ padding: 0; margin-bottom: 2px; margin-top: 6px;
+}
+#quickbar form { padding: 0; margin-top: 0; }
+
+h1 {
+ color: #666666;
+ font-family: Verdana, Arial, sans-serif;
+ font-size: 18pt; font-weight: bold; line-height: 21pt;
+}
+h1.pagetitle { padding-bottom: 0; margin-bottom: 0; }
+#article p.subtitle {
+ color: #666666; font-size: 11pt; font-weight: bold;
+ padding-top: 0; margin-top: 0; padding-bottom: 1ex;
+}
+
+a { color: #223366; }
+a.external { color: #336644; }
+a:visited { color: #8D0749; }
+a.printable { text-decoration: underline; }
+a.stub, #quickbar a.stub { color:#772233; text-decoration:none; }
+a.new, #quickbar a.new { color: #CC2200; }
+h2, h3, h4, h5, h6 { margin-bottom: 0; }
+small { font-size: 75%; }
+
diff --git a/skins/common/common.css b/skins/common/common.css
new file mode 100644 (file)
index 0000000..3e9c305
--- /dev/null
@@ -0,0 +1,375 @@
+/*
+ * common.css
+ * This file contains CSS settings common to Wikistandard, Nostalgia and CologneBlue
+ */
+#footer { clear: both }
+/* images */
+div.floatright { float: right; margin: 0 0 1em 1em; }
+div.floatright p { font-style: italic; }
+div.floatleft { float: left; margin: 0.3em 0.5em 0.5em 0; }
+div.floatleft p { font-style: italic; }
+
+
+/* Print-specific things to hide */
+.printfooter {
+        display: none;
+}
+
+/* table standards */
+table.rimage {
+        float:right;
+        margin-left:1em;
+        margin-bottom:1em;
+        text-align:center;
+        font-size:smaller;
+}
+
+/* thumbnails */
+div.thumb {
+    margin: 10px;
+    text-align: center;
+    width: auto;
+}
+div.thumb div {
+    border: 1px solid #8888aa;
+    background-color: #f7f8ff;
+    padding: 2px;
+    font-size: 94%;
+    text-align: center;
+    overflow: hidden;
+}
+div.thumb div * {
+    border: none;
+    background: none;
+}
+div.thumb img {
+    border:1px solid #8888AA;
+    margin-bottom:3px;
+    background:#FFFFFF;
+}
+div.thumbcaption,
+div.thumbcaption * {
+    border: none !important;
+    background: none !important;
+}
+div.thumbcaption {
+    padding: 0.2em 0 0.2em 0 !important;
+    text-align: left !important;
+}
+div.tright {
+    float: right;
+    margin-left:0.5em;
+}
+div.tleft {
+    float: left;
+    margin-right:0.5em;
+}
+
+/* Page history styling */
+/* the auto-generated edit comments */
+.autocomment { color: #4b4b4b; }
+#pagehistory span.user {
+    margin-left: 1.4em;
+    margin-right: 0.4em;
+}
+#pagehistory span.minor { font-weight: bold; }
+#pagehistory li { border: 1px solid White; }
+#pagehistory li.selected {
+    background-color:#f9f9f9;
+    border:1px dashed #aaaaaa;
+}
+
+table.diff { background:white; }
+td.diff-otitle { background:#cccccc; }
+td.diff-ntitle { background:#cccccc; }
+td.diff-addedline {
+    background:#ccffcc;
+    font-size: 94%;
+}
+td.diff-deletedline {
+    background:#ffffaa;
+    font-size: 94%;
+}
+td.diff-context {
+    background:#eeeeee;
+    font-size: 94%;
+}
+span.diffchange { color: red; font-weight: bold; }
+
+img { border: none; }
+img.tex { vertical-align: middle; }
+span.texhtml { font-family: serif; }
+
+
+#toc,
+.toc {
+       border: 1px solid #bba;
+       background-color: #f7f8ff;
+       padding: 5px;
+       font-size: 95%;
+       text-align: center;
+}
+#toc h2,
+.toc h2 {
+       display: inline;
+       border: none;
+       padding: 0;
+       font-size: 100%;
+       font-weight: bold;
+}
+#toc ul,
+.toc ul {
+       list-style-type: none;
+       list-style-image: none;
+       margin-left: 0;
+       padding-left: 0;
+       text-align: left;
+}
+#toc ul ul,
+.toc ul ul {
+       margin: 0 0 0 2em;
+}
+#toc .toctoggle,
+.toc .toctoggle {
+       font-size: 94%;
+}
+
+
+.error {
+       color: red;
+       font-size: larger;
+}
+
+/* preference page with js-genrated toc */
+#preftoc {
+    float: left;
+    margin: 1em 1em 1em 1em;
+    width: 13em;
+}
+#preftoc li { border: 1px solid White; }
+#preftoc li.selected {
+    background-color:#f9f9f9;
+    border:1px dashed #aaaaaa;
+}
+#preftoc a,
+#preftoc a:active {
+    display: block;
+    color: #005189;
+}
+#prefcontrol {
+    clear: left;
+    float: left;
+    margin-top: 1em;
+}
+div.prefsectiontip {
+    font-size: 94%;
+    margin-top: 1em;
+}
+fieldset.prefsection { margin-top: 1em }
+fieldset.operaprefsection { margin-left: 15em }
+
+/* emulate center */
+.center {
+    width: 100%;
+    text-align: center;
+}
+*.center * {
+    margin-left: auto;
+    margin-right: auto;
+}
+/* small for tables and similar */
+.small, .small * { font-size: 94%; }
+table.small { font-size: 100% }
+
+div.townBox {
+    position:relative;
+    float:right;
+    background:White;
+    margin-left:1em;
+    border: 1px solid gray;
+    padding:0.3em;
+    width: 200px;
+    overflow: hidden;
+    clear: right;
+}
+div.townBox dl {
+    padding: 0;
+    margin: 0 0 0.3em 0;
+    font-size: 96%;
+}
+div.townBox dl dt {
+    background: none;
+    margin: 0.4em 0 0 0;
+}
+div.townBox dl dd {
+    margin: 0.1em 0 0 1.1em;
+    background-color: #f3f3f3;
+}
+/* use this instead of #toc for page content */
+.toccolours {
+    border:1px solid #aaaaaa;
+    background-color:#f9f9f9;
+    padding:5px;
+    font-size: 95%;
+}
+#siteNotice {
+    border:1px solid #aaaaaa;
+    padding-left: 0.5em;
+    padding-right: 0.5em;
+}
+.redirectText {
+       font-size:150%;
+       margin:5px;
+}
+.searchmatch {
+       color: red;
+       font-weight: bold;
+}
+.sharedUploadNotice {
+       font-style: italic;
+}
+span.unpatrolled {
+       font-weight:bold;
+       color:red;
+}
+
+span.updatedmarker {
+       color:black;
+       background-color:#00FF00;
+}
+span.newpageletter {
+       font-weight:bold;
+       color:black;
+       background-color:yellow;
+}
+span.minoreditletter {
+       color:black;
+       background-color:#C5FFE6;
+}
+
+table.gallery {
+        border:  1px solid #cccccc;
+        margin:  2px;
+        padding: 2px;
+        background-color:#ffffff;
+}
+
+table.gallery tr {
+        vertical-align:top;
+}
+
+table.gallery td {
+      vertical-align:top;
+      background-color:#f9f9f9;
+      border: solid 2px white;
+}
+
+div.gallerybox {
+        margin: 2px;
+        width:  150px;
+}
+
+div.gallerybox div.thumb {
+        text-align: center;
+        border: 1px solid #cccccc;
+        margin: 2px;
+}
+
+div.gallerytext {
+        font-size: 94%;
+        padding: 2px 4px;
+}
+
+span.comment {
+       font-style: italic;
+}
+
+span.changedby {
+       font-size: 95%;
+}
+
+.previewnote {
+       text-align: center;
+       color: #cc0000;
+}
+.editExternally {
+        border-style:solid;
+        border-width:1px;
+        border-color:gray;
+        background: #ffffff;
+        padding:3px;
+        margin-top:0.5em;
+        float:left;
+        font-size:small;
+        text-align:center;
+}
+.editExternallyHelp {
+        font-style:italic;
+        color:gray;
+}
+
+li span.deleted {
+       text-decoration: line-through;
+       color: #888;
+       font-style: italic;
+}
+
+
+/* Classes for EXIF data display */
+table.exif {
+       margin-left: 0.5em;
+}
+
+table.exif caption { font-weight: bold; }
+table.exif th { font-weight: normal; }
+table.exif td { padding: 0.1em; }
+
+table.exif {
+       border: none;
+       border-collapse: collapse;
+}
+table.exif td, table.exif th {
+       border: 1px solid #aaaaaa;
+       padding-left: 4px;
+       padding-right: 4px;
+}
+table.exif th {
+       background-color: #f9f9f9;
+}
+table.exif td {
+       background-color: #fcfcfc;
+}
+table.exif td.spacer {
+       background: inherit;
+       border-top: none;
+       border-bottom: none;
+}
+
+.visualClear {
+    clear: both;
+}
+
+#mw_trackbacks {
+       border: solid 1px #bbbbff;
+       background-color: #eeeeff;
+       padding: 0.2em;
+}
+
+/* Allmessages table */
+
+#allmessagestable th {
+       background-color: #b2b2ff;
+}
+
+#allmessagestable tr.orig {
+       background-color: #ffe2e2;
+}
+
+#allmessagestable tr.new {
+       background-color: #e2ffe2;
+}
+
+#allmessagestable tr.def {
+       background-color: #f0f0ff;
+}
+
diff --git a/skins/common/commonPrint.css b/skins/common/commonPrint.css
new file mode 100644 (file)
index 0000000..76b054c
--- /dev/null
@@ -0,0 +1,277 @@
+/*
+** MediaWiki Print style sheet for CSS2-capable browsers.
+** Copyright Gabriel Wicke, http://www.aulinx.de/
+**
+** Derived from the plone (http://plone.org/) styles
+** Copyright Alexander Limi
+*/
+
+/* Thanks to A List Apart (http://alistapart.com/) for useful extras */
+a.stub,
+a.new{ color:#ba0000; text-decoration:none; }
+
+#toc { 
+    /*border:1px solid #2f6fab;*/
+    border:1px solid #aaaaaa;
+    background-color:#f9f9f9;
+    padding:5px;
+}
+.tocindent {
+       margin-left: 2em;
+}
+.tocline {
+       margin-bottom: 0px;
+}
+.toctoggle, .editsection {
+       font-size: smaller;
+}
+
+/* images */
+div.floatright { 
+    float: right; 
+    margin: 0;
+    position:relative;
+    border: 0.5em solid White;
+    border-width: 0.5em 0 0.8em 1.4em;
+}
+div.floatright p { font-style: italic;} 
+div.floatleft { 
+    float: left; 
+    margin: 0.3em 0.5em 0.5em 0;
+    position:relative;
+    border: 0.5em solid White;
+    border-width: 0.5em 1.4em 0.8em 0;
+}
+div.floatleft p { font-style: italic; } 
+/* thumbnails */
+div.thumb {
+    margin-bottom: 0.5em;
+    border-style: solid; border-color: White;
+    width: auto;
+    overflow: hidden;
+}
+div.thumb div {
+    border:1px solid #cccccc;
+    padding: 3px !important;
+    background-color:#f9f9f9;
+    font-size: 94%;
+    text-align: center;
+}
+div.thumb div a img {
+    border:1px solid #cccccc;
+}
+div.thumb div div.thumbcaption {
+    border: none;
+    padding: 0.3em 0 0.1em 0;
+}
+div.magnify { display: none; }
+div.tright {
+    float: right;
+    border-width: 0.5em 0 0.8em 1.4em;
+}
+div.tleft {
+    float: left;
+    margin-right:0.5em;
+    border-width: 0.5em 1.4em 0.8em 0;
+}
+
+/* table standards */
+table.rimage {
+    float:right; 
+    width:1pt; 
+    position:relative;
+    margin-left:1em; 
+    margin-bottom:1em;
+    text-align:center;
+}
+
+body {
+    background: White;
+    /*font-size: 11pt !important;*/
+    color: Black;
+    margin: 0;
+    padding: 0;
+}
+
+.noprint,
+div.top,
+div#column-one,
+#colophon,
+.editsection,
+.toctoggle,
+.tochidden,
+div#f-poweredbyico,
+div#f-copyrightico,
+li#f-viewcount,
+li#f-about,
+li#f-disclaimer {
+    /* Hides all the elements irrelevant for printing */
+    display: none;
+}
+
+ul { 
+    list-style-type: square;
+}
+
+#content {
+    background: none;
+    border: none ! important;
+    font-size: 11pt;
+    padding: 0 ! important;
+    margin: 0 ! important;
+}
+#footer {
+    border-top: 1px solid black;
+}
+
+h1, h2, h3, h4, h5, h6
+{
+    font-weight: bold;
+}
+
+p, .documentDescription {
+    margin: 1em 0 ! important;
+    line-height: 1.2em;    
+}
+
+.tocindent p {
+       margin: 0 0 0 0 ! important;
+}
+
+pre {
+    border: 1pt dashed black;
+    white-space: pre;
+    font-size: 8pt;
+    overflow: auto;
+    padding: 1em 0;
+}
+
+table.listing,
+table.listing td {
+    border: 1pt solid black;
+    border-collapse: collapse;
+}
+
+a {
+    color: Black !important;
+    padding: 0 !important
+}
+
+a:link, a:visited {
+    color: #520;
+    background: transparent;
+    text-decoration: underline;
+}
+
+#content a.external.text:after, #content a.external.autonumber:after {
+    /* Expand URLs for printing */
+    content: " (" attr(href) ") ";
+}
+
+#globalWrapper {
+    width: 100% !important;
+    min-width: 0 !important;
+}
+
+#column-content {
+    margin: 0 !important;
+}
+
+#column-content #content {
+    padding: 1em;
+    margin: 0 !important;
+}
+/* MSIE/Win doesn't understand 'inherit' */
+a, a.external, a.new, a.stub {
+       color: black ! important;
+       text-decoration: none ! important;
+}
+
+/* Continue ... */
+a, a.external, a.new, a.stub {
+       color: inherit ! important;
+       text-decoration: inherit ! important;
+}
+
+img { border: none; }
+img.tex { vertical-align: middle; }
+span.texhtml { font-family: serif; }
+
+div.townBox {
+    position:relative;
+    float:right;
+    background:White;
+    margin-left:1em;
+    border: 1px solid gray;
+    padding:0.3em;
+    width: 200px;
+    overflow: hidden;
+    clear: right;
+}
+div.townBox dl {
+    padding: 0;
+    margin: 0 0 0.3em 0; 
+    font-size: 96%;
+}
+div.townBox dl dt {
+    background: none;
+    margin: 0.4em 0 0 0;
+}
+div.townBox dl dd {
+    margin: 0.1em 0 0 1.1em;
+    background-color: #f3f3f3;
+}
+
+#siteNotice { display: none; }
+
+table.gallery {
+        border:  1px solid #cccccc;
+        margin:  2px;
+        padding: 2px;
+        background-color:#ffffff;
+}
+
+table.gallery tr { 
+        vertical-align:top;
+}
+
+div.gallerybox {
+        border: 1px solid #cccccc;
+        margin: 2px;
+        background-color:#f9f9f9;
+        width:  150px;
+}
+
+div.gallerybox div.thumb {
+        text-align: center;
+        border: 1px solid #cccccc;
+        margin: 2px;
+}       
+
+div.gallerytext {
+        font-size: 94%;
+        padding: 2px 4px;
+}       
+
+/*
+** Diff rendering
+*/
+table.diff { background:white; }
+td.diff-otitle { background:#ffffff; }
+td.diff-ntitle { background:#ffffff; }
+td.diff-addedline {
+    background:#ccffcc;
+    font-size: smaller;
+    border: solid 2px black;
+}
+td.diff-deletedline {
+    background:#ffffaa;
+    font-size: smaller;
+    border: dotted 2px black;
+}
+td.diff-context {
+    background:#eeeeee;
+    font-size: smaller;
+}
+span.diffchange { color: silver; font-weight: bold; text-decoration: underline; }
+
diff --git a/skins/common/common_rtl.css b/skins/common/common_rtl.css
new file mode 100644 (file)
index 0000000..8f50b2a
--- /dev/null
@@ -0,0 +1,15 @@
+/* js pref toc */
+#preftoc { float: right; }
+/* workaround for moz bug, displayed bullets on left side */
+#preftoc li { list-style: none; }
+#prefcontrol { float: right; }
+fieldset.prefsection,
+fieldset.operaprefsection { 
+    margin-left: 0;
+    margin-right: 18em;
+}
+/* page history */
+#pagehistory span.user { 
+    margin-right: 1.4em;
+    margin-left: 0.4em;
+}
diff --git a/skins/common/feed.css b/skins/common/feed.css
new file mode 100644 (file)
index 0000000..fa52a45
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+Make RSS and Atom feeds at least semi-legible to folk who accidentally
+load them in a browser...
+
+Compatibility:
+* Mozilla is fine.
+* Safari 1.2: the RSS <link> text isn't shown
+* Opera 7.5 uses the style sheet instead of its native RSS mode.
+* IE/Mac 5.2: none of the :before content works; doesn't get the charset right and displays garbage for non-ASCII.
+* IE/Win 6.0: No background color, borders, font size, font weight, or :before content.
+
+*/
+
+/* RSS: */ rss, channel, title, link, description, language, generator, lastBuildDate, item, pubDate, author, comments, creator,
+/* Atom: */ feed, modified, tagline, entry, issued, created, summary, comment {
+       display: block;
+}
+
+rss, feed {
+       background: white;
+       color: black;
+       margin: 1em;
+       font-family: "Verdana", "Tahoma", "Arial", "Helvetica", sans-serif;
+       line-height: 1.5em;
+}
+
+rss:before {
+       content: "This RSS feed is meant to be read in a syndicated news reader, and isn't ideal for a web browser.";
+}
+
+feed:before {
+       content: "This Atom feed is meant to be read in a syndicated news reader, and isn't ideal for a web browser.";
+}
+rss:before, feed:before {
+       color: red;
+       text-align: center;
+       line-height: 2em;
+}
+
+channel>title,
+item>title,
+feed>title,
+entry>title {
+       font-weight: bold;
+       border-bottom: solid 1px #aaa;
+       margin-left: -0.5em;
+}
+channel>title, feed>title {
+       font-size: larger;
+}
+item>title, entry>title {
+       font-size: large;
+}
+item, entry {
+       margin-top: 1em;
+       margin-left: 2em;
+}
+
+item>description, entry>summary {
+       white-space: pre;
+       overflow: auto;
+       background: #f8f8ff;
+}
+
+pubDate:before { content: "Date: " }
+link:before { content: "Link: " }
+author:before, creator:before { content: "Author: " }
+description:before { content: "Description: " }
+
+generator:before { content: "Generator: " }
+language:before { content: "Language: " }
+lastBuildDate:before { content: "Updated: " }
+comments:before { content: "Comments page: " }
+
+tagline:before { content: "Tagline: " }
+issued:before { content: "Issued: " }
+created:before { content: "Created: " }
+modified:before { content: "Modified: " }
+summary:before { content: "Summary: " }
+comment:before { content: "Comment: " }
+
+pubDate:before, link:before, author:before, description:before,
+language:before, generator:before, lastBuildDate:before, comments:before,
+tagline:before, issued:before, created:before, modified:before,
+summary:before, comment:before, creator:before {
+       color: #224;
+       font-weight: bold;
+}
+
+feed link:after {
+       content: attr(href);
+}
diff --git a/skins/common/images/Arr_.png b/skins/common/images/Arr_.png
new file mode 100644 (file)
index 0000000..83fafc7
Binary files /dev/null and b/skins/common/images/Arr_.png differ
diff --git a/skins/common/images/Arr_d.png b/skins/common/images/Arr_d.png
new file mode 100644 (file)
index 0000000..421dd10
Binary files /dev/null and b/skins/common/images/Arr_d.png differ
diff --git a/skins/common/images/Arr_l.png b/skins/common/images/Arr_l.png
new file mode 100644 (file)
index 0000000..9db6623
Binary files /dev/null and b/skins/common/images/Arr_l.png differ
diff --git a/skins/common/images/Arr_r.png b/skins/common/images/Arr_r.png
new file mode 100644 (file)
index 0000000..d1b161b
Binary files /dev/null and b/skins/common/images/Arr_r.png differ
diff --git a/skins/common/images/Arr_r.xcf b/skins/common/images/Arr_r.xcf
new file mode 100644 (file)
index 0000000..83b7b2a
Binary files /dev/null and b/skins/common/images/Arr_r.xcf differ
diff --git a/skins/common/images/Zoom_sans.gif b/skins/common/images/Zoom_sans.gif
new file mode 100644 (file)
index 0000000..6ba0adc
Binary files /dev/null and b/skins/common/images/Zoom_sans.gif differ
diff --git a/skins/common/images/bullet.gif b/skins/common/images/bullet.gif
new file mode 100644 (file)
index 0000000..b43de48
Binary files /dev/null and b/skins/common/images/bullet.gif differ
diff --git a/skins/common/images/button_bold.png b/skins/common/images/button_bold.png
new file mode 100644 (file)
index 0000000..5e52dee
Binary files /dev/null and b/skins/common/images/button_bold.png differ
diff --git a/skins/common/images/button_extlink.png b/skins/common/images/button_extlink.png
new file mode 100644 (file)
index 0000000..12ec5f2
Binary files /dev/null and b/skins/common/images/button_extlink.png differ
diff --git a/skins/common/images/button_headline.png b/skins/common/images/button_headline.png
new file mode 100644 (file)
index 0000000..aa0ca54
Binary files /dev/null and b/skins/common/images/button_headline.png differ
diff --git a/skins/common/images/button_hr.png b/skins/common/images/button_hr.png
new file mode 100644 (file)
index 0000000..19cfc48
Binary files /dev/null and b/skins/common/images/button_hr.png differ
diff --git a/skins/common/images/button_image.png b/skins/common/images/button_image.png
new file mode 100644 (file)
index 0000000..6c3c330
Binary files /dev/null and b/skins/common/images/button_image.png differ
diff --git a/skins/common/images/button_italic.png b/skins/common/images/button_italic.png
new file mode 100644 (file)
index 0000000..96b1fb9
Binary files /dev/null and b/skins/common/images/button_italic.png differ
diff --git a/skins/common/images/button_link.png b/skins/common/images/button_link.png
new file mode 100644 (file)
index 0000000..e9507b9
Binary files /dev/null and b/skins/common/images/button_link.png differ
diff --git a/skins/common/images/button_math.png b/skins/common/images/button_math.png
new file mode 100644 (file)
index 0000000..e91fb61
Binary files /dev/null and b/skins/common/images/button_math.png differ
diff --git a/skins/common/images/button_media.png b/skins/common/images/button_media.png
new file mode 100644 (file)
index 0000000..0207079
Binary files /dev/null and b/skins/common/images/button_media.png differ
diff --git a/skins/common/images/button_nowiki.png b/skins/common/images/button_nowiki.png
new file mode 100644 (file)
index 0000000..7b2d539
Binary files /dev/null and b/skins/common/images/button_nowiki.png differ
diff --git a/skins/common/images/button_sig.png b/skins/common/images/button_sig.png
new file mode 100644 (file)
index 0000000..ef3a46d
Binary files /dev/null and b/skins/common/images/button_sig.png differ
diff --git a/skins/common/images/button_template.png b/skins/common/images/button_template.png
new file mode 100644 (file)
index 0000000..8e9cc26
Binary files /dev/null and b/skins/common/images/button_template.png differ
diff --git a/skins/common/images/fileicon.xcf b/skins/common/images/fileicon.xcf
new file mode 100644 (file)
index 0000000..85a0a61
Binary files /dev/null and b/skins/common/images/fileicon.xcf differ
diff --git a/skins/common/images/gnu-fdl.png b/skins/common/images/gnu-fdl.png
new file mode 100644 (file)
index 0000000..1371aba
Binary files /dev/null and b/skins/common/images/gnu-fdl.png differ
diff --git a/skins/common/images/gnu-fdl.xcf b/skins/common/images/gnu-fdl.xcf
new file mode 100644 (file)
index 0000000..364440d
Binary files /dev/null and b/skins/common/images/gnu-fdl.xcf differ
diff --git a/skins/common/images/icons/COPYING b/skins/common/images/icons/COPYING
new file mode 100644 (file)
index 0000000..4aa80e1
--- /dev/null
@@ -0,0 +1,43 @@
+The icons used here are derived from the crystalsvg icons in the the
+pics/crystalsvg/ directory of kdelibs-3.4.0 they were modified on 2005-05-15
+by Ævar Arnfjörð Bjarmason for use in MediaWiki.
+
+What follows is the contents of the LICENSE.crystalsvg file found in the pics/
+subdirectory of kdelibs-3.4.0:
+
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+This copyright and license notice covers all CrystalSVG images.
+Note the license notice contains an add-on.
+********************************************************************************
+KDE Crystal theme icons.
+Copyright (C) 2002 and following years KDE Artists
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation,
+version 2.1 of the License.
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+    **** NOTE THIS ADD-ON ****
+The GNU Lesser General Public License or LGPL is written for software libraries
+in the first place. We expressly want the LGPL to be valid for this artwork
+library too.
+KDE Crystal theme icons is a special kind of software library, it is an
+artwork library, it's elements can be used in a Graphical User Interface, or
+GUI.
+Source code, for this library means:
+ - for vectors svg;
+ - for pixels, if applicable, the multi-layered formats xcf or psd, or
+otherwise png.
+The LGPL in some sections obliges you to make the files carry
+notices. With images this is in some cases impossible or hardly useful.
+With this library a notice is placed at a prominent place in the directory
+containing the elements. You may follow this practice.
+The exception in section 6 of the GNU Lesser General Public License covers
+the use of elements of this art library in a GUI.
+kde-artists [at] kde.org
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
diff --git a/skins/common/images/icons/fileicon-c.png b/skins/common/images/icons/fileicon-c.png
new file mode 100644 (file)
index 0000000..6da6916
Binary files /dev/null and b/skins/common/images/icons/fileicon-c.png differ
diff --git a/skins/common/images/icons/fileicon-cpp.png b/skins/common/images/icons/fileicon-cpp.png
new file mode 100644 (file)
index 0000000..ba54e77
Binary files /dev/null and b/skins/common/images/icons/fileicon-cpp.png differ
diff --git a/skins/common/images/icons/fileicon-deb.png b/skins/common/images/icons/fileicon-deb.png
new file mode 100644 (file)
index 0000000..ac1e2cf
Binary files /dev/null and b/skins/common/images/icons/fileicon-deb.png differ
diff --git a/skins/common/images/icons/fileicon-dvi.png b/skins/common/images/icons/fileicon-dvi.png
new file mode 100644 (file)
index 0000000..6c7aa1a
Binary files /dev/null and b/skins/common/images/icons/fileicon-dvi.png differ
diff --git a/skins/common/images/icons/fileicon-exe.png b/skins/common/images/icons/fileicon-exe.png
new file mode 100644 (file)
index 0000000..6ccf182
Binary files /dev/null and b/skins/common/images/icons/fileicon-exe.png differ
diff --git a/skins/common/images/icons/fileicon-h.png b/skins/common/images/icons/fileicon-h.png
new file mode 100644 (file)
index 0000000..d091aff
Binary files /dev/null and b/skins/common/images/icons/fileicon-h.png differ
diff --git a/skins/common/images/icons/fileicon-html.png b/skins/common/images/icons/fileicon-html.png
new file mode 100644 (file)
index 0000000..7c47952
Binary files /dev/null and b/skins/common/images/icons/fileicon-html.png differ
diff --git a/skins/common/images/icons/fileicon-iso.png b/skins/common/images/icons/fileicon-iso.png
new file mode 100644 (file)
index 0000000..b4192e9
Binary files /dev/null and b/skins/common/images/icons/fileicon-iso.png differ
diff --git a/skins/common/images/icons/fileicon-java.png b/skins/common/images/icons/fileicon-java.png
new file mode 100644 (file)
index 0000000..757c6ae
Binary files /dev/null and b/skins/common/images/icons/fileicon-java.png differ
diff --git a/skins/common/images/icons/fileicon-mid.png b/skins/common/images/icons/fileicon-mid.png
new file mode 100644 (file)
index 0000000..aa82607
Binary files /dev/null and b/skins/common/images/icons/fileicon-mid.png differ
diff --git a/skins/common/images/icons/fileicon-mov.png b/skins/common/images/icons/fileicon-mov.png
new file mode 100644 (file)
index 0000000..2c0da0d
Binary files /dev/null and b/skins/common/images/icons/fileicon-mov.png differ
diff --git a/skins/common/images/icons/fileicon-o.png b/skins/common/images/icons/fileicon-o.png
new file mode 100644 (file)
index 0000000..bf051cb
Binary files /dev/null and b/skins/common/images/icons/fileicon-o.png differ
diff --git a/skins/common/images/icons/fileicon-ogg.png b/skins/common/images/icons/fileicon-ogg.png
new file mode 100644 (file)
index 0000000..b8ba771
Binary files /dev/null and b/skins/common/images/icons/fileicon-ogg.png differ
diff --git a/skins/common/images/icons/fileicon-ogg.xcf b/skins/common/images/icons/fileicon-ogg.xcf
new file mode 100644 (file)
index 0000000..a91024b
Binary files /dev/null and b/skins/common/images/icons/fileicon-ogg.xcf differ
diff --git a/skins/common/images/icons/fileicon-pdf.png b/skins/common/images/icons/fileicon-pdf.png
new file mode 100644 (file)
index 0000000..ee39b6c
Binary files /dev/null and b/skins/common/images/icons/fileicon-pdf.png differ
diff --git a/skins/common/images/icons/fileicon-ps.png b/skins/common/images/icons/fileicon-ps.png
new file mode 100644 (file)
index 0000000..f1f504d
Binary files /dev/null and b/skins/common/images/icons/fileicon-ps.png differ
diff --git a/skins/common/images/icons/fileicon-rm.png b/skins/common/images/icons/fileicon-rm.png
new file mode 100644 (file)
index 0000000..5ba04e5
Binary files /dev/null and b/skins/common/images/icons/fileicon-rm.png differ
diff --git a/skins/common/images/icons/fileicon-rpm.png b/skins/common/images/icons/fileicon-rpm.png
new file mode 100644 (file)
index 0000000..0f1c3b8
Binary files /dev/null and b/skins/common/images/icons/fileicon-rpm.png differ
diff --git a/skins/common/images/icons/fileicon-svg.png b/skins/common/images/icons/fileicon-svg.png
new file mode 100644 (file)
index 0000000..8dc6d30
Binary files /dev/null and b/skins/common/images/icons/fileicon-svg.png differ
diff --git a/skins/common/images/icons/fileicon-tar.png b/skins/common/images/icons/fileicon-tar.png
new file mode 100644 (file)
index 0000000..a4b15d7
Binary files /dev/null and b/skins/common/images/icons/fileicon-tar.png differ
diff --git a/skins/common/images/icons/fileicon-tex.png b/skins/common/images/icons/fileicon-tex.png
new file mode 100644 (file)
index 0000000..ee8c022
Binary files /dev/null and b/skins/common/images/icons/fileicon-tex.png differ
diff --git a/skins/common/images/icons/fileicon-ttf.png b/skins/common/images/icons/fileicon-ttf.png
new file mode 100644 (file)
index 0000000..1b53066
Binary files /dev/null and b/skins/common/images/icons/fileicon-ttf.png differ
diff --git a/skins/common/images/icons/fileicon-txt.png b/skins/common/images/icons/fileicon-txt.png
new file mode 100644 (file)
index 0000000..76e9890
Binary files /dev/null and b/skins/common/images/icons/fileicon-txt.png differ
diff --git a/skins/common/images/icons/fileicon.png b/skins/common/images/icons/fileicon.png
new file mode 100644 (file)
index 0000000..5675170
Binary files /dev/null and b/skins/common/images/icons/fileicon.png differ
diff --git a/skins/common/images/link_icon.gif b/skins/common/images/link_icon.gif
new file mode 100644 (file)
index 0000000..815ccb1
Binary files /dev/null and b/skins/common/images/link_icon.gif differ
diff --git a/skins/common/images/magnify-clip.png b/skins/common/images/magnify-clip.png
new file mode 100644 (file)
index 0000000..50abcb6
Binary files /dev/null and b/skins/common/images/magnify-clip.png differ
diff --git a/skins/common/images/magnify-clip.png.old b/skins/common/images/magnify-clip.png.old
new file mode 100644 (file)
index 0000000..4304142
Binary files /dev/null and b/skins/common/images/magnify-clip.png.old differ
diff --git a/skins/common/images/mediawiki-small.xcf b/skins/common/images/mediawiki-small.xcf
new file mode 100644 (file)
index 0000000..7535517
Binary files /dev/null and b/skins/common/images/mediawiki-small.xcf differ
diff --git a/skins/common/images/mediawiki.png b/skins/common/images/mediawiki.png
new file mode 100644 (file)
index 0000000..69fce98
Binary files /dev/null and b/skins/common/images/mediawiki.png differ
diff --git a/skins/common/images/poweredby_mediawiki_88x31.png b/skins/common/images/poweredby_mediawiki_88x31.png
new file mode 100644 (file)
index 0000000..ce1765d
Binary files /dev/null and b/skins/common/images/poweredby_mediawiki_88x31.png differ
diff --git a/skins/common/images/redirect.png b/skins/common/images/redirect.png
new file mode 100644 (file)
index 0000000..7b2b071
Binary files /dev/null and b/skins/common/images/redirect.png differ
diff --git a/skins/common/images/wiki.png b/skins/common/images/wiki.png
new file mode 100644 (file)
index 0000000..49913f6
Binary files /dev/null and b/skins/common/images/wiki.png differ
diff --git a/skins/common/nostalgia.css b/skins/common/nostalgia.css
new file mode 100644 (file)
index 0000000..5944543
--- /dev/null
@@ -0,0 +1,18 @@
+@import url("common.css");
+body {
+       /* Background color is set separately on page type */
+       color: black;
+}
+#specialform { display: inline; }
+#powersearch {
+  background: #DDEEFF; border-style: solid; border-width: 1px; padding: 2px;
+}
+a.interwiki, a.external { color: #3366BB; }
+a.printable { text-decoration: underline; }
+a.stub { color:#772233; text-decoration:none; }
+h1.pagetitle { padding-top: 0; margin-top: 0; padding-bottom: 0; margin-bottom: 0; }
+h2, h3, h4, h5, h6 { margin-bottom: 0; }
+textarea { overflow: auto; }
+p.subtitle { padding-top: 0; margin-top: 0; }
+
+
diff --git a/skins/common/preview.js b/skins/common/preview.js
new file mode 100644 (file)
index 0000000..7695185
--- /dev/null
@@ -0,0 +1,45 @@
+// Live preview
+
+function openXMLHttpRequest() {
+       if( window.XMLHttpRequest ) {
+               return new XMLHttpRequest();
+       } else if( window.ActiveXObject && navigator.platform != 'MacPPC' ) {
+               // IE/Mac has an ActiveXObject but it doesn't work.
+               return new ActiveXObject("Microsoft.XMLHTTP");
+       } else {
+               return null;
+       }
+}
+
+/**
+ * Returns true if could open the request,
+ * false otherwise (eg no browser support).
+ */
+function livePreview(target, text, postUrl) {
+       prevTarget = target;
+       if( !target ) {
+               window.alert('crash and burn');
+       }
+       prevReq = openXMLHttpRequest();
+       if( !prevReq ) return false;
+       
+       prevReq.onreadystatechange = updatePreviewText;
+       prevReq.open("POST", postUrl, true);
+       
+       var postData = 'wpTextbox1=' + encodeURIComponent(text);
+       prevReq.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+       prevReq.send(postData);
+       return true;
+}
+
+function updatePreviewText() {
+       if( prevReq.readyState != 4 ) {
+               return;
+       }
+       if( prevReq.status != 200 ) {
+               window.alert('Failed to connect: ' + prevReq.status +
+                       ' "' + prevReq.statusText + '"');
+               return;
+       }
+       prevTarget.innerHTML = prevReq.responseText;
+}
diff --git a/skins/common/quickbar-right.css b/skins/common/quickbar-right.css
new file mode 100644 (file)
index 0000000..43bd427
--- /dev/null
@@ -0,0 +1 @@
+#quickbar { position: fixed; right: 0px; top: 0px; padding: 4px;}
diff --git a/skins/common/quickbar.css b/skins/common/quickbar.css
new file mode 100644 (file)
index 0000000..d7930c2
--- /dev/null
@@ -0,0 +1 @@
+#quickbar { position: fixed; padding: 4px; }
diff --git a/skins/common/sticky.js b/skins/common/sticky.js
new file mode 100644 (file)
index 0000000..cf248c3
--- /dev/null
@@ -0,0 +1,124 @@
+// Make a layer that stays in the same place on screen when scrolling the browser window.
+// Version 1.2
+// See http://www.mark.ac/help for browser support.
+
+var mySticky;
+var theLayer;
+
+// Setup variables for sliding.
+// lastY and staticYOffset should match your CSS top definition.
+
+lastY=10;YOffset=0;staticYOffset=10;refreshMS=25;
+
+
+// Setup function that runs when the page loads.
+       function setup(eID){
+               bw=new checkBrowser;
+               if(bw.ns4||bw.opera){MM_reloadPage(true);}
+               var noFix=bw.ie4||bw.ns4||(bw.macie50)?true:false;
+               if (window.attachEvent){fix_bind()}
+               else if(noFix){ 
+                       if(bw.ns6){document.getElementById(eID).style.position="absolute";}
+                       if(bw.macie50){document.getElementById(eID).style.position="absolute";document.getElementById(eID).style.backgroundColor="#ccffcc";}
+                       if(bw.ns6&&YOffset==0){YOffset=-15}
+                       mySticky=new makeLayerObj(eID);
+                       layerSlide(eID)}
+               else{
+                       mySticky=new makeLayerObj(eID);
+                       mySticky.css.position="fixed";}
+
+               if(!mySticky){mySticky=new makeLayerObj(eID);}
+               //mySticky.css.visibility="visible";
+       }
+
+
+// -------------------------
+// emulate css 'position: fixed' in IE5+ Win
+// code by aclover@1value.com
+       fix_elements = new Array();
+       
+       function fix_event(){
+               var i;
+               for (i=0; i < fix_elements.length; i++){
+                       fix_elements[i].style.left = parseInt(fix_elements[i].fix_left)+document.getElementsByTagName('html')[0].scrollLeft+document.getElementsByTagName('body')[0].scrollLeft+'px';
+                       fix_elements[i].style.top = parseInt(fix_elements[i].fix_top)+document.getElementsByTagName('html')[0].scrollTop+document.getElementsByTagName('body')[0].scrollTop+'px';
+               }
+       }
+
+       function fix_bind(){
+               var i;
+               for (i=0; i < document.all.length; i++){
+                       if (document.all[i].currentStyle.position=='fixed'){
+                               document.all[i].fix_left = document.all[i].currentStyle.left;
+                               document.all[i].fix_top = document.all[i].currentStyle.top;
+                               document.all[i].style.position = 'absolute';
+                               fix_elements[fix_elements.length] = document.all[i];
+                               window.attachEvent('onscroll', fix_event);
+                               window.attachEvent('onresize', fix_event);
+                       } 
+               }
+       }
+// -------------------------
+
+
+// -------------------------
+// DHTML menu sliding. Requires checkBrowser()
+// Based on source at http://www.simplythebest.net/
+       function layerSlide(layerID) {
+               if(bw.dhtml){
+                       if(!mySticky){mySticky=new makeLayerObj(layerID);}
+                       if (bw.ns) {winY = window.pageYOffset;}
+                       else if (bw.ie) {winY = document.body.scrollTop;}
+                       if (bw.ie||bw.ns) {
+                               if (winY!=lastY&&winY>YOffset-staticYOffset){smooth = .3 * (winY - lastY - YOffset + staticYOffset);}
+                               else if (YOffset-staticYOffset+lastY>YOffset-staticYOffset){smooth = .3 * (winY - lastY - (YOffset-(YOffset-winY)));}
+                               else{smooth=0}
+                               if(smooth > 0) {smooth = Math.ceil(smooth);}
+                               else{smooth = Math.floor(smooth);}
+                               if (bw.ie){mySticky.css.pixelTop+=smooth;}
+                               else if (bw.ns){mySticky.css.top=parseInt(mySticky.css.top)+smooth;}
+                               lastY = lastY+smooth;
+                               top.window.status=new Date()
+                               setTimeout('layerSlide("'+layerID+'")', refreshMS)}}}
+// -------------------------
+
+// Netscape 4.x browser resize fix
+       function MM_reloadPage(init) {
+       if (init==true) with (navigator) {if ((appName=="Netscape")&&(parseInt(appVersion)==4)) {
+       document.MM_pgW=innerWidth; document.MM_pgH=innerHeight; top.onresize=MM_reloadPage; }}
+       else if (innerWidth!=document.MM_pgW || innerHeight!=document.MM_pgH) {location.reload();}}
+
+// Create browser-independent layer and browser objects
+       function makeLayerObj(eID){
+               if(document.getElementById){this.css=document.getElementById(eID).style}
+               else if(document.layers){this.css=document.layers[eID];}
+               else if(document.all){this.css=document.all[eID].style;}
+               return this
+       }
+       
+       function checkBrowser(){
+               this.ver=navigator.appVersion;
+               this.name=navigator.appName;
+               this.mac=(navigator.platform.toLowerCase().indexOf('mac')>-1)?true:false;
+               this.opera=(navigator.userAgent.toLowerCase().indexOf('opera')>-1)?true:false;
+               this.dom=document.getElementById?true:false;
+               this.ns=(this.name=='Netscape');
+               this.ie4=(document.all && !this.dom)?true:false;
+               this.ie=(this.name =='Microsoft Internet Explorer'&&!this.opera)?true:false;
+               this.ie5=(this.ie && (navigator.userAgent.indexOf("MSIE 5")!=-1))?true:false;
+               this.macie50=(this.mac&&this.ie5&&(navigator.userAgent.indexOf("MSIE 5.0")!=-1))?true:false
+               this.ns4=(this.ns && parseInt(this.ver) == 4)?true:false;
+               this.ns6=((this.name=="Netscape")&&(parseInt(this.ver)==5))?true:false
+               this.standards=document.getElementById?true:false;
+               this.dhtml=this.standards||this.ie4||this.ns4;
+       }
+       
+       function showMe(eID){
+               myFloater=new makeLayerObj(eID)
+               myFloater.css.visibility="visible";
+       }
+       
+       function hideMe(eID){
+               myFloater=new makeLayerObj(eID)
+               myFloater.css.visibility="hidden";
+       }
\ No newline at end of file
diff --git a/skins/common/wikibits.js b/skins/common/wikibits.js
new file mode 100644 (file)
index 0000000..76485a2
--- /dev/null
@@ -0,0 +1,497 @@
+// Wikipedia JavaScript support functions
+// if this is true, the toolbar will no longer overwrite the infobox when you move the mouse over individual items
+var noOverwrite=false;
+var alertText;
+var clientPC = navigator.userAgent.toLowerCase(); // Get client info
+var is_gecko = ((clientPC.indexOf('gecko')!=-1) && (clientPC.indexOf('spoofer')==-1)
+                && (clientPC.indexOf('khtml') == -1) && (clientPC.indexOf('netscape/7.0')==-1));
+var is_safari = ((clientPC.indexOf('AppleWebKit')!=-1) && (clientPC.indexOf('spoofer')==-1));
+var is_khtml = (navigator.vendor == 'KDE' || ( document.childNodes && !document.all && !navigator.taintEnabled ));
+if (clientPC.indexOf('opera')!=-1) {
+    var is_opera = true;
+    var is_opera_preseven = (window.opera && !document.childNodes);
+    var is_opera_seven = (window.opera && document.childNodes);
+}
+
+// add any onload functions in this hook (please don't hard-code any events in the xhtml source)
+function onloadhook () {
+    // don't run anything below this for non-dom browsers
+    if(!(document.getElementById && document.getElementsByTagName)) return;
+    histrowinit();
+    unhidetzbutton();
+    tabbedprefs();
+    akeytt();
+}
+if (window.addEventListener) window.addEventListener("load",onloadhook,false);
+else if (window.attachEvent) window.attachEvent("onload",onloadhook);
+
+
+// document.write special stylesheet links
+if(typeof stylepath != 'undefined' && typeof skin != 'undefined') {
+    if (is_opera_preseven) {
+        document.write('<link rel="stylesheet" type="text/css" href="'+stylepath+'/'+skin+'/Opera6Fixes.css">');
+    } else if (is_opera_seven) {
+        document.write('<link rel="stylesheet" type="text/css" href="'+stylepath+'/'+skin+'/Opera7Fixes.css">');
+    } else if (is_khtml) {
+        document.write('<link rel="stylesheet" type="text/css" href="'+stylepath+'/'+skin+'/KHTMLFixes.css">');
+    }
+}
+// Un-trap us from framesets
+if( window.top != window ) window.top.location = window.location;
+
+// for enhanced RecentChanges
+function toggleVisibility( _levelId, _otherId, _linkId) {
+       var thisLevel = document.getElementById( _levelId );
+       var otherLevel = document.getElementById( _otherId );
+       var linkLevel = document.getElementById( _linkId );
+       if ( thisLevel.style.display == 'none' ) {
+               thisLevel.style.display = 'block';
+               otherLevel.style.display = 'none';
+               linkLevel.style.display = 'inline';
+       } else {
+               thisLevel.style.display = 'none';
+               otherLevel.style.display = 'inline';
+               linkLevel.style.display = 'none';
+               }
+}
+
+// page history stuff
+// attach event handlers to the input elements on history page
+function histrowinit () {
+    hf = document.getElementById('pagehistory');
+    if(!hf) return;
+    lis = hf.getElementsByTagName('li');
+    for (i=0;i<lis.length;i++) {
+        inputs=lis[i].getElementsByTagName('input');
+        if(inputs[0] && inputs[1]) {
+                inputs[0].onclick = diffcheck;
+                inputs[1].onclick = diffcheck;
+        }
+    }
+    diffcheck();
+}
+// check selection and tweak visibility/class onclick
+function diffcheck() { 
+    var dli = false; // the li where the diff radio is checked
+    var oli = false; // the li where the oldid radio is checked
+    hf = document.getElementById('pagehistory');
+    if(!hf) return;
+    lis = hf.getElementsByTagName('li');
+    for (i=0;i<lis.length;i++) {
+        inputs=lis[i].getElementsByTagName('input');
+        if(inputs[1] && inputs[0]) {
+            if(inputs[1].checked || inputs[0].checked) { // this row has a checked radio button
+                if(inputs[1].checked && inputs[0].checked && inputs[0].value == inputs[1].value) return false;
+                if(oli) { // it's the second checked radio
+                    if(inputs[1].checked) {
+                    oli.className = "selected";
+                    return false 
+                    }
+                } else if (inputs[0].checked) {
+                    return false;
+                }
+                if(inputs[0].checked) dli = lis[i];
+                if(!oli) inputs[0].style.visibility = 'hidden';
+                if(dli) inputs[1].style.visibility = 'hidden';
+                lis[i].className = "selected";
+                oli = lis[i];
+            }  else { // no radio is checked in this row
+                if(!oli) inputs[0].style.visibility = 'hidden';
+                else inputs[0].style.visibility = 'visible';
+                if(dli) inputs[1].style.visibility = 'hidden';
+                else inputs[1].style.visibility = 'visible';
+                lis[i].className = "";
+            }
+        }
+    }
+}
+
+// generate toc from prefs form, fold sections
+// XXX: needs testing on IE/Mac and safari
+// more comments to follow
+function tabbedprefs() {
+    prefform = document.getElementById('preferences');
+    if(!prefform || !document.createElement) return;
+    if(prefform.nodeName.toLowerCase() == 'a') return; // Occasional IE problem
+    prefform.className = prefform.className + 'jsprefs';
+    var sections = new Array();
+    children = prefform.childNodes;
+    var seci = 0;
+    for(i=0;i<children.length;i++) {
+        if(children[i].nodeName.toLowerCase().indexOf('fieldset') != -1) {
+            children[i].id = 'prefsection-' + seci;
+            children[i].className = 'prefsection';
+            if(is_opera || is_khtml) children[i].className = 'prefsection operaprefsection';
+            legends = children[i].getElementsByTagName('legend');
+            sections[seci] = new Object();
+            if(legends[0] && legends[0].firstChild.nodeValue)
+                sections[seci].text = legends[0].firstChild.nodeValue;
+            else
+                sections[seci].text = '# ' + seci;
+            sections[seci].secid = children[i].id;
+            seci++;
+            if(sections.length != 1) children[i].style.display = 'none';
+            else var selectedid = children[i].id;
+        }
+    }
+    var toc = document.createElement('ul');
+    toc.id = 'preftoc';
+    toc.selectedid = selectedid;
+    for(i=0;i<sections.length;i++) {
+        var li = document.createElement('li');
+        if(i == 0) li.className = 'selected';
+        var a =  document.createElement('a');
+        a.href = '#' + sections[i].secid;
+        a.onclick = uncoversection;
+        a.appendChild(document.createTextNode(sections[i].text));
+        a.secid = sections[i].secid;
+        li.appendChild(a);
+        toc.appendChild(li);
+    }
+    prefform.insertBefore(toc, children[0]);
+    document.getElementById('prefsubmit').id = 'prefcontrol';
+}
+function uncoversection() {
+    oldsecid = this.parentNode.parentNode.selectedid;
+    newsec = document.getElementById(this.secid);
+    if(oldsecid != this.secid) {
+        ul = document.getElementById('preftoc');
+        document.getElementById(oldsecid).style.display = 'none';
+        newsec.style.display = 'block';
+        ul.selectedid = this.secid;
+        lis = ul.getElementsByTagName('li');
+        for(i=0;i< lis.length;i++) {
+            lis[i].className = '';
+        }
+        this.parentNode.className = 'selected';
+    }
+    return false;
+}
+
+// Timezone stuff
+// tz in format [+-]HHMM
+function checkTimezone( tz, msg ) {
+       var localclock = new Date();
+       // returns negative offset from GMT in minutes
+       var tzRaw = localclock.getTimezoneOffset();
+       var tzHour = Math.floor( Math.abs(tzRaw) / 60);
+       var tzMin = Math.abs(tzRaw) % 60;
+       var tzString = ((tzRaw >= 0) ? "-" : "+") + ((tzHour < 10) ? "0" : "") + tzHour + ((tzMin < 10) ? "0" : "") + tzMin;
+       if( tz != tzString ) {
+               var junk = msg.split( '$1' );
+               document.write( junk[0] + "UTC" + tzString + junk[1] );
+       }
+}
+function unhidetzbutton() {
+    tzb = document.getElementById('guesstimezonebutton')
+    if(tzb) tzb.style.display = 'inline';
+}
+
+// in [-]HH:MM format...
+// won't yet work with non-even tzs
+function fetchTimezone() {
+       // FIXME: work around Safari bug
+       var localclock = new Date();
+       // returns negative offset from GMT in minutes
+       var tzRaw = localclock.getTimezoneOffset();
+       var tzHour = Math.floor( Math.abs(tzRaw) / 60);
+       var tzMin = Math.abs(tzRaw) % 60;
+       var tzString = ((tzRaw >= 0) ? "-" : "") + ((tzHour < 10) ? "0" : "") + tzHour +
+               ":" + ((tzMin < 10) ? "0" : "") + tzMin;
+       return tzString;
+}
+
+function guessTimezone(box) {
+       document.preferences.wpHourDiff.value = fetchTimezone();
+}
+
+function showTocToggle() {
+  if (document.createTextNode) {
+    // Uses DOM calls to avoid document.write + XHTML issues
+
+    var linkHolder = document.getElementById('toctitle')
+    if (!linkHolder) return;
+
+    var outerSpan = document.createElement('span');
+    outerSpan.className = 'toctoggle';
+
+    var toggleLink = document.createElement('a');
+    toggleLink.id = 'togglelink';
+    toggleLink.className = 'internal';
+    toggleLink.href = 'javascript:toggleToc()';
+    toggleLink.appendChild(document.createTextNode(tocHideText));
+
+    outerSpan.appendChild(document.createTextNode('['));
+    outerSpan.appendChild(toggleLink);
+    outerSpan.appendChild(document.createTextNode(']'));
+
+    linkHolder.appendChild(document.createTextNode(' '));
+    linkHolder.appendChild(outerSpan);
+
+    var cookiePos = document.cookie.indexOf("hidetoc=");
+    if (cookiePos > -1 && document.cookie.charAt(cookiePos + 8) == 1)
+     toggleToc();
+  }
+}
+
+function changeText(el, newText) {
+  // Safari work around
+  if (el.innerText)
+    el.innerText = newText;
+  else if (el.firstChild && el.firstChild.nodeValue)
+    el.firstChild.nodeValue = newText;
+}
+  
+function toggleToc() {
+       var toc = document.getElementById('toc').getElementsByTagName('ul')[0];
+  var toggleLink = document.getElementById('togglelink')
+  
+       if(toc && toggleLink && toc.style.display == 'none') {
+     changeText(toggleLink, tocHideText);
+               toc.style.display = 'block';
+     document.cookie = "hidetoc=0";
+       } else {
+    changeText(toggleLink, tocShowText);
+               toc.style.display = 'none';
+    document.cookie = "hidetoc=1";
+       }
+}
+
+// this function generates the actual toolbar buttons with localized text
+// we use it to avoid creating the toolbar where javascript is not enabled
+function addButton(imageFile, speedTip, tagOpen, tagClose, sampleText) {
+
+       imageFile=escapeQuotesHTML(imageFile);
+       speedTip=escapeQuotesHTML(speedTip);
+       tagOpen=escapeQuotes(tagOpen);
+       tagClose=escapeQuotes(tagClose);
+       sampleText=escapeQuotes(sampleText);
+       var mouseOver="";
+
+       // we can't change the selection, so we show example texts
+       // when moving the mouse instead, until the first button is clicked
+       if(!document.selection && !is_gecko) {
+               // filter backslashes so it can be shown in the infobox
+               var re=new RegExp("\\\\n","g");
+               tagOpen=tagOpen.replace(re,"");
+               tagClose=tagClose.replace(re,"");
+               mouseOver = "onMouseover=\"if(!noOverwrite){document.infoform.infobox.value='"+tagOpen+sampleText+tagClose+"'};\"";
+       }
+
+       document.write("<a href=\"javascript:insertTags");
+       document.write("('"+tagOpen+"','"+tagClose+"','"+sampleText+"');\">");
+
+       document.write("<img width=\"23\" height=\"22\" src=\""+imageFile+"\" border=\"0\" alt=\""+speedTip+"\" title=\""+speedTip+"\""+mouseOver+">");
+       document.write("</a>");
+       return;
+}
+
+function addInfobox(infoText,text_alert) {
+       alertText=text_alert;
+       var clientPC = navigator.userAgent.toLowerCase(); // Get client info
+
+       var re=new RegExp("\\\\n","g");
+       alertText=alertText.replace(re,"\n");
+
+       // if no support for changing selection, add a small copy & paste field
+       // document.selection is an IE-only property. The full toolbar works in IE and
+       // Gecko-based browsers.
+       if(!document.selection && !is_gecko) {
+               infoText=escapeQuotesHTML(infoText);
+               document.write("<form name='infoform' id='infoform'>"+
+                       "<input size=80 id='infobox' name='infobox' value=\""+
+                       infoText+"\" readonly='readonly'></form>");
+       }
+
+}
+
+function escapeQuotes(text) {
+       var re=new RegExp("'","g");
+       text=text.replace(re,"\\'");
+       re=new RegExp("\\n","g");
+       text=text.replace(re,"\\n");
+       return escapeQuotesHTML(text);
+}
+
+function escapeQuotesHTML(text) {
+       var re=new RegExp('&',"g");
+       text=text.replace(re,"&amp;");
+       var re=new RegExp('"',"g");
+       text=text.replace(re,"&quot;");
+       var re=new RegExp('<',"g");
+       text=text.replace(re,"&lt;");
+       var re=new RegExp('>',"g");
+       text=text.replace(re,"&gt;");
+       return text;
+}
+
+// apply tagOpen/tagClose to selection in textarea,
+// use sampleText instead of selection if there is none
+// copied and adapted from phpBB
+function insertTags(tagOpen, tagClose, sampleText) {
+
+       var txtarea = document.editform.wpTextbox1;
+       // IE
+       if(document.selection  && !is_gecko) {
+               var theSelection = document.selection.createRange().text;
+               if(!theSelection) { theSelection=sampleText;}
+               txtarea.focus();
+               if(theSelection.charAt(theSelection.length - 1) == " "){// exclude ending space char, if any
+                       theSelection = theSelection.substring(0, theSelection.length - 1);
+                       document.selection.createRange().text = tagOpen + theSelection + tagClose + " ";
+               } else {
+                       document.selection.createRange().text = tagOpen + theSelection + tagClose;
+               }
+
+       // Mozilla
+       } else if(txtarea.selectionStart || txtarea.selectionStart == '0') {
+               var startPos = txtarea.selectionStart;
+               var endPos = txtarea.selectionEnd;
+               var scrollTop=txtarea.scrollTop;
+               var myText = (txtarea.value).substring(startPos, endPos);
+               if(!myText) { myText=sampleText;}
+               if(myText.charAt(myText.length - 1) == " "){ // exclude ending space char, if any
+                       subst = tagOpen + myText.substring(0, (myText.length - 1)) + tagClose + " ";
+               } else {
+                       subst = tagOpen + myText + tagClose;
+               }
+               txtarea.value = txtarea.value.substring(0, startPos) + subst +
+                 txtarea.value.substring(endPos, txtarea.value.length);
+               txtarea.focus();
+
+               var cPos=startPos+(tagOpen.length+myText.length+tagClose.length);
+               txtarea.selectionStart=cPos;
+               txtarea.selectionEnd=cPos;
+               txtarea.scrollTop=scrollTop;
+
+       // All others
+       } else {
+               var copy_alertText=alertText;
+               var re1=new RegExp("\\$1","g");
+               var re2=new RegExp("\\$2","g");
+               copy_alertText=copy_alertText.replace(re1,sampleText);
+               copy_alertText=copy_alertText.replace(re2,tagOpen+sampleText+tagClose);
+               var text;
+               if (sampleText) {
+                       text=prompt(copy_alertText);
+               } else {
+                       text="";
+               }
+               if(!text) { text=sampleText;}
+               text=tagOpen+text+tagClose;
+               document.infoform.infobox.value=text;
+               // in Safari this causes scrolling
+               if(!is_safari) {
+                       txtarea.focus();
+               }
+               noOverwrite=true;
+       }
+       // reposition cursor if possible
+       if (txtarea.createTextRange) txtarea.caretPos = document.selection.createRange().duplicate();
+}
+
+function akeytt() {
+    if(typeof ta == "undefined" || !ta) return;
+    pref = 'alt-';
+    if(is_safari || navigator.userAgent.toLowerCase().indexOf( 'mac' ) + 1 ) pref = 'control-';
+    if(is_opera) pref = 'shift-esc-';
+    for(id in ta) {
+        n = document.getElementById(id);
+        if(n){
+            a = n.childNodes[0];
+            if(a){
+                if(ta[id][0].length > 0) {
+                    a.accessKey = ta[id][0];
+                    ak = ' ['+pref+ta[id][0]+']';
+                } else {
+                    ak = '';
+                }
+                a.title = ta[id][1]+ak;
+            } else {
+                if(ta[id][0].length > 0) {
+                    n.accessKey = ta[id][0];
+                    ak = ' ['+pref+ta[id][0]+']';
+                } else {
+                    ak = '';
+                }
+                n.title = ta[id][1]+ak;
+            }
+        }
+    }
+}
+
+function setupRightClickEdit() {
+       if( document.getElementsByTagName ) {
+               var divs = document.getElementsByTagName( 'div' );
+               for( var i = 0; i < divs.length; i++ ) {
+                       var el = divs[i];
+                       if( el.className == 'editsection' ) {
+                               addRightClickEditHandler( el );
+                       }
+               }
+       }
+}
+
+function addRightClickEditHandler( el ) {
+       for( var i = 0; i < el.childNodes.length; i++ ) {
+               var link = el.childNodes[i];
+               if( link.nodeType == 1 && link.nodeName.toLowerCase() == 'a' ) {
+                       var editHref = link.getAttribute( 'href' );
+                       
+                       // find the following a
+                       var next = el.nextSibling;
+                       while( next.nodeType != 1 )
+                               next = next.nextSibling;
+                       
+                       // find the following header
+                       next = next.nextSibling;
+                       while( next.nodeType != 1 )
+                               next = next.nextSibling;
+                       
+                       if( next && next.nodeType == 1 &&
+                               next.nodeName.match( /^[Hh][1-6]$/ ) ) {
+                               next.oncontextmenu = function() {
+                                       document.location = editHref;
+                                       return false;
+                               }
+                       }
+               }
+       }
+}
+
+function fillDestFilename() {
+       if (!document.getElementById) return;
+       var path = document.getElementById('wpUploadFile').value;
+       // Find trailing part
+       var slash = path.lastIndexOf( '/' );
+       var backslash = path.lastIndexOf( '\\' );
+       var fname;
+       if ( slash == -1 && backslash == -1 ) {
+               fname = path;
+       } else if ( slash > backslash ) {
+               fname = path.substring( slash+1, 10000 );
+       } else {
+               fname = path.substring( backslash+1, 10000 );
+       }
+
+       // Capitalise first letter and replace spaces by underscores
+       fname = fname.charAt(0).toUpperCase().concat(fname.substring(1,10000)).replace( / /g, '_' );
+
+       // Output result
+       var destFile = document.getElementById('wpDestFile');
+       if (destFile) destFile.value = fname;
+}
+       
+
+function considerChangingExpiryFocus() {
+       if (!document.getElementById) return;
+       var drop = document.getElementById('wpBlockExpiry');
+       if (!drop) return;
+       var field = document.getElementById('wpBlockOther');
+       if (!field) return;
+       var opt = drop.value;
+       if (opt == 'other')
+               field.style.display = '';
+       else
+               field.style.display = 'none';
+}
diff --git a/skins/common/wikiprintable.css b/skins/common/wikiprintable.css
new file mode 100644 (file)
index 0000000..58e132d
--- /dev/null
@@ -0,0 +1,46 @@
+/* MediaWiki print stylesheet */
+
+body {
+       color: #000000; background: #ffffff;
+}
+
+
+/* MSIE/Win doesn't understand 'inherit' */
+a, a.external, a.new, a.stub {
+       color: black ! important;
+       text-decoration: none ! important;
+}
+#article {
+       margin: 0 ! important;
+}
+
+/* Continue ... */
+a, a.external, a.new, a.stub {
+       color: inherit ! important;
+       text-decoration: inherit ! important;
+}
+
+/* Hide ugly UI stuff */
+#quickbar, #topbar, #footer, #siteNotice,
+.editsection, .toctoggle {
+       display: none;
+}
+
+/* */
+#article {
+       position: relative;
+       margin: inherit ! important;
+}
+
+.printfooter {
+       border-top: solid 1px black;
+       display: block ! important;
+}
+
+/* Old stuff, fixme:
+a.CBlink { color: #0000AA; text-decoration: none; font-size: 12pt; }
+a.interwiki, a.external { color: #3333BB; text-decoration: none; }
+h1.pagetitle { padding-bottom: 0; margin-bottom: 0; }
+i.link, u.link { color: #000066; }
+p.subtitle { padding-top: 0; margin-top: 0; }
+*/
diff --git a/skins/common/wikistandard.css b/skins/common/wikistandard.css
new file mode 100644 (file)
index 0000000..22fbddb
--- /dev/null
@@ -0,0 +1,44 @@
+@import url("common.css");
+
+#article { padding: 4px; }
+#content { margin: 0; padding: 0; }
+#footer { padding: 4px;font-size:95%;clear: both; }
+#pagestats { font-size: 9pt; }
+#powersearch {
+  background: #DDEEFF; border-style: solid; border-width: 1px; padding: 2px;
+}
+#quickbar { width: 140px; padding: 4px; visibility: visible; z-index:99;font-size:95%;}
+#topbar { padding: 4px;font-size:95%; }
+
+
+/* Table of contents */
+.toctoggle, .editsection { font-size: smaller; }
+
+/* ... */
+#toolbar { padding:0px; }
+#infobox { background:#eeeeff;color:black;}
+#editform { margin-top:1px; }
+a.interwiki, a.external { color: #3366BB; }
+a.printable { text-decoration: underline; }
+a.stub { color:#772233; text-decoration:none; }
+a:visited { color: #5A3696; }
+body { margin: 0px; padding: 4px; color: black; }
+form.inline { display: inline; }
+textarea { overflow: auto; }
+
+
+h1.pagetitle { padding-top: 0; margin-top: 0; padding-bottom: 0; margin-bottom: 0;
+font-size:150%; }
+h2 { font-size: 120%; }
+h2, h3, h4, h5, h6 { margin-bottom: 0;}
+h3 { font-size: 106.25%; }
+h4 { font-size: 103.125%; }
+h5 { font-size: 100%; }
+h6 { font-size: 95%; }
+hr.sep { color:gray;height:1px;background-color:gray;}
+p.subpages { font-size:small;}
+p.subtitle { padding-top: 0; margin-top: 0;}
+p.catlinks { font-size:small; margin-top:0; text-align:right;}
+td { empty-cells:show; }
+td.bottom { border-top: 1px solid gray; }
+td.top { border-bottom: 1px solid gray; }
diff --git a/skins/disabled/Amethyst.php b/skins/disabled/Amethyst.php
new file mode 100644 (file)
index 0000000..15767a2
--- /dev/null
@@ -0,0 +1,39 @@
+<?php
+/**
+ * Amethyst skin
+ * Original design by Sorkhiri and Sorwena members of the EverQuest
+ * <Amethyst> guild
+ * Ported to MediaWiki by Ashar Voultoiz
+ *
+ * See skin.txt for documentation
+ *
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Skins
+ */
+
+if( !defined( 'MEDIAWIKI' ) )
+       die();
+
+/** */
+require_once('includes/SkinPHPTal.php');
+if( class_exists( 'SkinPHPTal' ) ) {
+
+/**
+ * See skin.txt
+ *
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Skins
+ */
+class SkinAmethyst extends SkinPHPTal {
+       function initPage( &$out ) {
+               SkinPHPTal::initPage( $out );
+               $this->skinname  = 'amethyst';
+               $this->stylename = 'amethyst';
+               $this->template  = 'Amethyst';
+       }
+}
+
+}
+?>
diff --git a/skins/disabled/Amethyst.pt b/skins/disabled/Amethyst.pt
new file mode 100644 (file)
index 0000000..dc39092
--- /dev/null
@@ -0,0 +1,151 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="${lang}" lang="${lang}" dir="${dir}">
+  <head>
+    <meta http-equiv="Content-Type" content="${mimetype}; charset=${charset}" />
+    ${headlinks}
+    <title tal:content="pagetitle">Exciting xhtml slimfast</title>
+    <style type="text/css" media="screen,projection">/*<![CDATA[*/ @import "${stylepath}/${stylename}/main.css"; /*]]>*/</style>
+    <link rel="stylesheet" type="text/css" media="print" href="${stylepath}/common/commonPrint.css" />
+    <!--[if IE]><style type="text/css" media="all">@import "${stylepath}/${stylename}/IEFixes.css";</style>
+    <script type="${jsmimetype}" src="${stylepath}/common/IEFixes.js"></script>
+    <meta http-equiv="imagetoolbar" content="no" /><![endif]-->
+    <script tal:condition="jsvarurl" type="${jsmimetype}" tal:attributes="src jsvarurl"></script>
+    <script type="${jsmimetype}" src="${stylepath}/common/wikibits.js"></script>
+    <style tal:condition="usercss" type="text/css">/*<![CDATA[*/ ${usercss} /*]]>*/</style>
+    <script tal:condition="userjs" type="${jsmimetype}" tal:attributes="src userjs"></script><script 
+      tal:condition="userjsprev" type="${jsmimetype}">/*<![CDATA[*/${userjsprev}/*]]>*/</script>
+  </head>
+  <body tal:attributes="ondblclick body-ondblclick|default; class nsclass|default">
+    <div id="globalWrapper">
+      <div id="column-content">
+       <div id="content">
+         <a name="top" id="contentTop"></a>
+         <div id="siteNotice" tal:condition="sitenotice" tal:content="structure sitenotice"></div>
+         <h1 class="firstHeading" tal:content="title">Leonardo da Vinci</h1>
+         <div id="bodyContent">
+           <h3 id="siteSub" i18n:translate="string:tagline">From Wikipedia, the free encyclopedia.</h3>
+           <div id="contentSub" tal:content="structure subtitle"></div>
+           <div id="contentSub" tal:condition="undelete" tal:content="structure undelete"></div>
+           <div tal:condition="newtalk" class="usermessage" tal:content="structure newtalk"></div>
+           <!-- start content -->
+           ${bodytext}
+           <div tal:condition="catlinks" id="catlinks" tal:content="structure catlinks"></div>
+           <!-- end content -->
+           <div class="visualClear"></div>
+         </div>
+       </div>
+      </div>
+      <div id="column-one">
+       <div id="p-cactions" class="portlet">
+         <h5>Views</h5>
+         <ul>
+           <li tal:repeat="action content_actions" 
+           tal:attributes="id string:ca-${repeat/action/key}; class action/class|default"><a
+             tal:attributes="href action/href|default"
+             tal:content="action/text">Linktext</a></li>
+         </ul>
+       </div>
+       <div class="portlet" id="p-personal">
+         <h5 i18n:translate="string:personaltools">Personal Tools</h5>
+         <div class="pBody">
+           <ul>
+             <li tal:repeat="item personal_urls" 
+             tal:attributes="id string:pt-${repeat/item/key};"><a href="myuserpage"
+               tal:attributes="href item/href; class item/class|default"
+               tal:content="item/text">Log in</a></li>
+           </ul>
+         </div>
+       </div>
+       <div class="portlet" id="p-logo">
+         <a style="background-image: url(${logopath});" href="${nav_urls/mainpage/href}" i18n:attributes="title string:mainpage"></a>
+       </div>
+       <script type="${jsmimetype}"> if (window.isMSIE55) fixalpha(); </script>
+       <div class="portlet" id="p-navigation">
+         <h5 i18n:translate="string:navigation">Navigation</h5>
+         <div class="pBody">
+           <ul>
+             <li id="n-mainpage"><a href="${nav_urls/mainpage/href}"
+               i18n:translate="string:mainpage">Main Page</a></li>
+             <li id="n-portal" tal:condition="nav_urls/portal/href"><a href="${nav_urls/portal/href}"
+               i18n:translate="string:portal">Community Portal</a></li>
+             <li id="n-currentevents" tal:condition="nav_urls/currentevents/href"><a href="${nav_urls/currentevents/href}"
+               i18n:translate="string:currentevents">Current Events</a></li>
+             <li id="n-recentchanges"><a href="${nav_urls/recentchanges/href}"
+               i18n:translate="string:recentchanges">Recent Changes</a></li>
+             <li id="n-randompage"><a href="${nav_urls/randompage/href}"
+               i18n:translate="string:randompage">Random Page</a></li>
+             <li id="n-help"><a href="${nav_urls/help/href}"
+               i18n:translate="string:help">Help</a></li>
+             <li id="n-sitesupport" tal:condition="nav_urls/sitesupport/href"><a href="${nav_urls/sitesupport/href}"
+               i18n:translate="string:sitesupport">Donations</a></li>
+           </ul>
+         </div>
+       </div>
+       <div id="p-search" class="portlet">
+         <h5 i18n:translate="string:search">Search</h5>
+         <div class="pBody">
+           <form name="searchform" action="${searchaction}" id="searchform">
+             <input id="searchInput" name="search" type="text"
+             i18n:attributes="accesskey string:accesskey-search | default"/>
+             <input type='submit' name="go" value="Go" class="searchButton" 
+             i18n:attributes="value string:go"/>&nbsp;<input type='submit' name="fulltext"
+             value="Search" class="searchButton"
+             i18n:attributes="value string:search"/>
+           </form>
+         </div>
+       </div>
+       <div class="portlet" id="p-tb">
+         <h5 i18n:translate="string:toolbox">Toolbox</h5>
+         <div class="pBody">
+           <ul>
+             <li id="t-whatlinkshere" tal:condition="notspecialpage"><a href="${nav_urls/whatlinkshere/href}"
+               i18n:translate="string:whatlinkshere">What links here</a></li>
+             <li id="t-recentchangeslinked" tal:condition="notspecialpage"><a href="${nav_urls/recentchangeslinked/href}"
+               i18n:translate="string:recentchangeslinked">Related Changes</a></li>
+             <li tal:condition="feeds" id="feedlinks">
+             <span i18n:translate="string:feedlinks">Feeds:</span>
+             <span tal:repeat="feed feeds" 
+               tal:attributes="id string:feed-${repeat/feed/key};"><a 
+                 tal:attributes="href feed/href;"
+                 tal:content="feed/text">rss</a>&nbsp;</span>
+             </li>
+             <li id="t-contributions" tal:condition="nav_urls/contributions/href"><a href="${nav_urls/contributions/href}"
+               i18n:translate="string:contributions">Contributions</a></li>
+             <li id="t-emailuser" tal:condition="nav_urls/emailuser/href"><a href="${nav_urls/emailuser/href}"
+               i18n:translate="string:emailuser">Email this user</a></li>
+             <li id="t-upload" tal:condition="nav_urls/upload/href"><a href="${nav_urls/upload/href}"
+               i18n:translate="string:upload">Upload a file</a></li>
+             <li id="t-specialpages"><a href="${nav_urls/specialpages/href}"
+               i18n:translate="string:specialpages">Special Pages</a></li>
+           </ul>
+         </div>
+       </div>
+       <div id="p-lang" class="portlet" tal:condition="language_urls">
+         <h5 i18n:translate="string:otherlanguages">Language</h5>
+         <div class="pBody">
+           <ul>
+             <li tal:repeat="langlink language_urls">
+             <a tal:attributes="href langlink/href"
+               tal:content="structure langlink/text">English</a>
+             </li>
+           </ul>
+         </div>
+       </div>
+      </div><!-- end of the left (by default at least) column -->
+      <div class="visualClear"></div>
+      <div id="footer">
+       <div id="f-poweredbyico" tal:condition="poweredbyico">${poweredbyico}</div>
+       <div id="f-copyrightico" tal:condition="copyrightico">${copyrightico}</div>
+       <ul id="f-list">
+         <li id="f-lastmod" tal:condition="lastmod">${lastmod}</li>
+         <li id="f-viewcount" tal:condition="viewcount">${viewcount}</li>
+         <li id="f-credits" tal:condition="credits">${credits}</li>
+         <li id="f-copyright" tal:condition="copyright">${copyright}</li>
+         <li id="f-about" tal:condition="about">${about}</li>
+         <li id="f-disclaimer" tal:condition="disclaimer">${disclaimer}</li>
+       </ul>
+      </div>
+    </div>
+    ${reporttime}
+  </body>
+</html>
diff --git a/skins/disabled/Chick.php b/skins/disabled/Chick.php
new file mode 100644 (file)
index 0000000..75f8285
--- /dev/null
@@ -0,0 +1,34 @@
+<?php
+/**
+ * See skin.txt
+ *
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Skins
+ */
+
+if( !defined( 'MEDIAWIKI' ) )
+       die();
+
+/** */
+require_once('includes/SkinPHPTal.php');
+if( class_exists( 'SkinPHPTal' ) ) {
+
+/**
+ * See skin.txt
+ *
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Skins
+ */
+class SkinChick extends SkinPHPTal {
+       function initPage( &$out ) {
+               SkinPHPTal::initPage( $out );
+               $this->skinname = 'chick';
+               $this->template = 'Chick';
+       }
+       function printSource() { return ''; }
+}
+
+}
+?>
diff --git a/skins/disabled/Chick.pt b/skins/disabled/Chick.pt
new file mode 100644 (file)
index 0000000..a1ce335
--- /dev/null
@@ -0,0 +1,100 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="${lang}" lang="${lang}" dir="${dir}">
+  <head>
+    <meta http-equiv="Content-Type" content="${mimetype}; charset=${charset}" />
+    <div tal:replace="structure headlinks"></div>
+    <title tal:content="pagetitle">Exciting xhtml slimfast</title>
+    <style type="text/css" media="screen,projection">/*<![CDATA[*/ @import "${stylepath}/${stylename}/main.css"; /*]]>*/</style>
+    <script tal:condition="jsvarurl" type="${jsmimetype}" tal:attributes="src jsvarurl"></script>
+    <script type="${jsmimetype}" src="${stylepath}/common/wikibits.js"></script>
+    <style tal:condition="usercss" tal:content="structure usercss" type="text/css"></style>
+    <script tal:condition="userjs" type="${jsmimetype}" tal:attributes="src userjs"></script><script 
+      tal:condition="userjsprev" tal:content="structure userjsprev" type="${jsmimetype}"></script>
+  </head>
+  <body>
+    <a name="top"></a>
+    <div class="searchBox">
+      <form name="searchform" action="${searchaction}" id="searchform">
+        <input id="searchInput" name="search" type="text" size="15"
+        i18n:attributes="accesskey string:accesskey-search | default" />
+        <input type='submit' name="go" value="Go" class="searchButton"
+        i18n:attributes="value string:go" />&nbsp;<input type='submit' name="fulltext"
+        value="Search" class="searchButton" i18n:attributes="value string:search" />
+      </form>
+    </div>
+    <div id="siteNotice" tal:condition="sitenotice" tal:content="structure sitenotice"></div>
+    <h1 class="firstHeading" tal:content="title">Leonardo da Vinci</h1>
+    <div id="siteSub" i18n:translate="string:tagline">From Wikipedia, the free encyclopedia.</div>
+    <div id="contentSub" tal:content="structure subtitle"></div>
+    <div id="contentUndel" tal:condition="undelete" tal:content="structure undelete"></div>
+    <div tal:condition="newtalk" class="usermessage" tal:content="structure newtalk"></div>
+    <div tal:condition="catlinks" id="catlinks" tal:content="structure catlinks"></div>
+    <!-- start content -->
+           <div tal:replace="structure bodytext"></div>
+    <!-- end content -->
+    <hr />
+
+    <div id="p-cactions" class="portlet">
+      <strong>Views:</strong>
+      <span tal:repeat="action content_actions"> <a
+         tal:attributes="id string:ca-${repeat/action/key}; class action/class|default;
+            href action/href|default" tal:content="action/text">Linktext</a> </span>
+    </div>
+
+    <div class="portlet" id="p-personal">
+      <strong><span i18n:translate="string:personaltools">Personal Tools</span>:</strong>
+      <span tal:repeat="item personal_urls"> <a
+         tal:attributes="id string:pt-${repeat/item/key}; href item/href;
+            class item/class|default" tal:content="item/text">Log in</a> </span>
+    </div>
+
+    <div class="portlet" id="p-navigation">
+      <strong><span i18n:translate="string:navigation">Navigation</span>:</strong>
+      <a href="${nav_urls/mainpage/href}" i18n:translate="string:mainpage">Main Page</a>
+      <a href="${nav_urls/portal/href}" i18n:translate="string:portal">Community Portal</a>
+      <a href="${nav_urls/currentevents/href}" i18n:translate="string:currentevents">Current Events</a>
+      <a href="${nav_urls/recentchanges/href}" i18n:translate="string:recentchanges">Recent Changes</a>
+      <a href="${nav_urls/randompage/href}" i18n:translate="string:randompage">Random Page</a>
+      <a href="${nav_urls/help/href}" i18n:translate="string:help">Help</a>
+      <a tal:condition="nav_urls/sitesupport/href" href="${nav_urls/sitesupport/href}"
+        i18n:translate="string:sitesupport">Donations</a>
+    </div>
+
+    <div class="portlet" id="p-tb">
+      <strong><span i18n:translate="string:toolbox">Toolbox</span>:</strong>
+      <a href="${nav_urls/whatlinkshere/href}" tal:condition="notspecialpage" i18n:translate="string:whatlinkshere">What links here</a>
+      <a href="${nav_urls/recentchangeslinked/href}" tal:condition="notspecialpage" i18n:translate="string:recentchangeslinked">Related Changes</a>
+      <span tal:condition="feeds" id="feedlinks">
+        <span i18n:translate="string:feedlinks">Feeds:</span>
+        <span tal:repeat="feed feeds"> <a tal:attributes="id string:feed-${repeat/feed/key};
+              href feed/href;" tal:content="feed/text">rss</a> </span>
+      </span>
+      <a tal:condition="nav_urls/contributions/href" href="${nav_urls/contributions/href}" i18n:translate="string:contributions">Contributions</a>
+      <a tal:condition="nav_urls/emailuser/href" href="${nav_urls/emailuser/href}" i18n:translate="string:emailuser">Email this user</a>
+      <a tal:condition="loggedin" href="${nav_urls/upload/href}" i18n:translate="string:upload">Upload a file</a>
+      <a href="${nav_urls/specialpages/href}" i18n:translate="string:specialpages">Special Pages</a>
+    </div>
+
+    <div id="p-lang" class="portlet" tal:condition="language_urls">
+      <strong><span i18n:translate="string:otherlanguages">Other languages</span>:</strong>
+      <span tal:repeat="langlink language_urls"> <a tal:attributes="href langlink/href"
+         tal:content="structure langlink/text">English</a> </span>
+    </div>
+
+    <hr style="clear: both;" />
+
+    <div id="footer">
+      <span tal:condition="poweredbyico" tal:content="structure poweredbyico"></span>
+      <span tal:condition="copyrightico" tal:content="structure copyrightico"></span>
+      <ul id="f-list">
+         <li id="f-lastmod" tal:condition="lastmod" tal:content="structure lastmod"></li>
+         <li id="f-viewcount" tal:condition="viewcount" tal:content="structure viewcount"></li>
+         <li id="f-credits" tal:condition="credits" tal:content="structure credits"></li>
+         <li id="f-copyright" tal:condition="copyright" tal:content="structure copyright"></li>
+         <li id="f-about" tal:condition="about" tal:content="structure about"></li>
+         <li id="f-disclaimer" tal:condition="disclaimer" tal:content="structure disclaimer"></li>
+      </ul>
+    </div>
+    <div tal:replace="structure reporttime"></div>
+  </body>
+</html>
diff --git a/skins/disabled/HTMLDump.php b/skins/disabled/HTMLDump.php
new file mode 100644 (file)
index 0000000..b4c1a47
--- /dev/null
@@ -0,0 +1,211 @@
+<?php
+
+/** 
+ * Default skin for HTML dumps, based on MonoBook.php
+ */
+
+if( !defined( 'MEDIAWIKI' ) )
+       die();
+
+/** */
+require_once( 'includes/SkinTemplate.php' );
+
+/**
+ * Inherit main code from SkinTemplate, set the CSS and template filter.
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Skins
+ */
+class SkinHTMLDump extends SkinTemplate {
+       /** Using monobook. */
+       function initPage( &$out ) {
+               SkinTemplate::initPage( $out );
+               $this->template  = 'HTMLDumpTemplate';
+       }
+
+       function buildSidebar() {
+               $sections = parent::buildSidebar();
+               $badMessages = array( 'recentchanges-url', 'randompage-url' );
+               $badUrls = array();
+               foreach ( $badMessages as $msg ) {
+                       $badUrls[] = $this->makeInternalOrExternalUrl( wfMsgForContent( $msg ) );
+               }
+
+               foreach ( $sections as $heading => $section ) {
+                       foreach ( $section as $index => $link ) {
+                               if ( in_array( $link['href'], $badUrls ) ) {
+                                       unset( $sections[$heading][$index] );
+                               }
+                       }
+               }
+               return $sections;
+       }
+
+       function buildContentActionUrls() {
+               $content_actions = array();
+               $nskey = $this->getNameSpaceKey();
+               $content_actions[$nskey] = $this->tabAction(
+                       $this->mTitle->getSubjectPage(),
+                       $nskey,
+                       !$this->mTitle->isTalkPage() );
+               
+               $content_actions['talk'] = $this->tabAction(
+                       $this->mTitle->getTalkPage(),
+                       'talk',
+                       $this->mTitle->isTalkPage(),
+                       '',
+                       true);
+               return $content_actions;
+       }
+
+       function makeBrokenLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' ) {
+               if ( !isset( $nt ) ) {
+                       return "<!-- ERROR -->{$prefix}{$text}{$trail}";
+               }
+               
+               if ( $nt->getNamespace() == NS_CATEGORY ) {
+                       return $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
+               }
+               
+               if ( $text == '' ) {
+                       $text = $nt->getPrefixedText();
+               }
+               return $prefix . $text . $trail;
+       }
+}
+
+/**
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Skins
+ */
+class HTMLDumpTemplate extends QuickTemplate {
+       /**
+        * Template filter callback for MonoBook skin.
+        * Takes an associative array of data set from a SkinTemplate-based
+        * class, and a wrapper for MediaWiki's localization database, and
+        * outputs a formatted page.
+        *
+        * @access private
+        */
+       function execute() {
+               $this->modifySetup();
+               $this->reallyExecute();
+       }
+
+
+       function modifySetup() {
+               /*
+               foreach ( $this->data['navigation_urls'] as $index => $link ) {
+                       if ( $link['text'] == 'recentchanges' ) {
+                               unset( $this->data['navigation_urls'][$index] );
+                       } elseif ( $link['text'] */
+       }
+       
+       function reallyExecute() {
+               wfSuppressWarnings();
+?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<?php $this->text('lang') ?>" lang="<?php $this->text('lang') ?>" dir="<?php $this->text('dir') ?>">
+  <head>
+    <meta http-equiv="Content-Type" content="<?php $this->text('mimetype') ?>; charset=<?php $this->text('charset') ?>" />
+    <?php $this->html('headlinks') ?>
+    <title><?php $this->text('pagetitle') ?></title>
+    <style type="text/css" media="screen,projection">/*<![CDATA[*/ @import "<?php $this->text('stylepath') ?>/<?php $this->text('stylename') ?>/main.css"; /*]]>*/</style>
+    <link rel="stylesheet" type="text/css" media="print" href="<?php $this->text('stylepath') ?>/common/commonPrint.css" />
+    <!--[if lt IE 5.5000]><style type="text/css">@import "<?php $this->text('stylepath') ?>/<?php $this->text('stylename') ?>/IE50Fixes.css";</style><![endif]-->
+    <!--[if IE 5.5000]><style type="text/css">@import "<?php $this->text('stylepath') ?>/<?php $this->text('stylename') ?>/IE55Fixes.css";</style><![endif]-->
+    <!--[if gte IE 6]><style type="text/css">@import "<?php $this->text('stylepath') ?>/<?php $this->text('stylename') ?>/IE60Fixes.css";</style><![endif]-->
+    <!--[if IE]><script type="<?php $this->text('jsmimetype') ?>" src="<?php $this->text('stylepath') ?>/common/IEFixes.js"></script>
+    <meta http-equiv="imagetoolbar" content="no" /><![endif]-->
+    <?php if($this->data['jsvarurl'  ]) { ?><script type="<?php $this->text('jsmimetype') ?>" src="<?php $this->text('jsvarurl'  ) ?>"></script><?php } ?>
+    <script type="<?php $this->text('jsmimetype') ?>" src="<?php $this->text('stylepath' ) ?>/common/wikibits.js"></script>
+  </head>
+  <body 
+    <?php if($this->data['nsclass'        ]) { ?>class="<?php      $this->text('nsclass')         ?>"<?php } ?>>
+    <div id="globalWrapper">
+      <div id="column-content">
+       <div id="content">
+         <a name="top" id="contentTop"></a>
+         <?php if($this->data['sitenotice']) { ?><div id="siteNotice"><?php $this->html('sitenotice') ?></div><?php } ?>
+         <h1 class="firstHeading"><?php $this->text('title') ?></h1>
+         <div id="bodyContent">
+           <h3 id="siteSub"><?php $this->msg('tagline') ?></h3>
+           <div id="contentSub"><?php $this->html('subtitle') ?></div>
+           <?php if($this->data['undelete']) { ?><div id="contentSub"><?php     $this->html('undelete') ?></div><?php } ?>
+           <?php if($this->data['newtalk'] ) { ?><div class="usermessage"><?php $this->html('newtalk')  ?></div><?php } ?>
+           <!-- start content -->
+           <?php $this->html('bodytext') ?>
+           <?php if($this->data['catlinks']) { ?><div id="catlinks"><?php       $this->html('catlinks') ?></div><?php } ?>
+           <!-- end content -->
+           <div class="visualClear"></div>
+         </div>
+       </div>
+      </div>
+      <div id="column-one">
+       <div id="p-cactions" class="portlet">
+         <h5>Views</h5>
+         <ul>
+           <?php foreach($this->data['content_actions'] as $key => $action) {
+              ?><li id="ca-<?php echo htmlspecialchars($key) ?>"
+              <?php if($action['class']) { ?>class="<?php echo htmlspecialchars($action['class']) ?>"<?php } ?>
+              ><a href="<?php echo htmlspecialchars($action['href']) ?>"><?php
+              echo htmlspecialchars($action['text']) ?></a></li><?php
+            } ?>
+         </ul>
+       </div>
+       <div class="portlet" id="p-logo">
+         <a style="background-image: url(<?php $this->text('logopath') ?>);"
+           href="<?php echo htmlspecialchars($this->data['nav_urls']['mainpage']['href'])?>"
+           title="<?php $this->msg('mainpage') ?>"></a>
+       </div>
+       <script type="<?php $this->text('jsmimetype') ?>"> if (window.isMSIE55) fixalpha(); </script>
+       <?php foreach ($this->data['sidebar'] as $bar => $cont) { ?>
+       <div class='portlet' id='p-<?php echo htmlspecialchars($bar) ?>'>
+         <h5><?php $this->msg( $bar ) ?></h5>
+         <div class='pBody'>
+           <ul>
+           <?php foreach($cont as $key => $val) { ?>
+             <li id="<?php echo htmlspecialchars($val['id']) ?>"><a href="<?php echo htmlspecialchars($val['href']) ?>"><?php echo htmlspecialchars($val['text'])?></a></li>
+            <?php } ?>
+           </ul>
+         </div>
+       </div>
+       <?php } ?>
+       <?php if( $this->data['language_urls'] ) { ?><div id="p-lang" class="portlet">
+         <h5><?php $this->msg('otherlanguages') ?></h5>
+         <div class="pBody">
+           <ul>
+             <?php foreach($this->data['language_urls'] as $langlink) { ?>
+             <li>
+             <a href="<?php echo htmlspecialchars($langlink['href'])
+               ?>"><?php echo $langlink['text'] ?></a>
+             </li>
+             <?php } ?>
+           </ul>
+         </div>
+       </div>
+       <?php } ?>
+      </div><!-- end of the left (by default at least) column -->
+      <div class="visualClear"></div>
+      <div id="footer">
+    <?php if($this->data['poweredbyico']) { ?><div id="f-poweredbyico"><?php $this->html('poweredbyico') ?></div><?php } ?>
+       <?php if($this->data['copyrightico']) { ?><div id="f-copyrightico"><?php $this->html('copyrightico') ?></div><?php } ?>
+       <ul id="f-list">
+         <?php if($this->data['lastmod'   ]) { ?><li id="f-lastmod"><?php    $this->html('lastmod')    ?></li><?php } ?>
+         <?php if($this->data['numberofwatchingusers' ]) { ?><li id="f-numberofwatchingusers"><?php  $this->html('numberofwatchingusers') ?></li><?php } ?>
+         <?php if($this->data['credits'   ]) { ?><li id="f-credits"><?php    $this->html('credits')    ?></li><?php } ?>
+         <?php if($this->data['copyright' ]) { ?><li id="f-copyright"><?php  $this->html('copyright')  ?></li><?php } ?>
+         <?php if($this->data['about'     ]) { ?><li id="f-about"><?php      $this->html('about')      ?></li><?php } ?>
+         <?php if($this->data['disclaimer']) { ?><li id="f-disclaimer"><?php $this->html('disclaimer') ?></li><?php } ?>
+         <?php if($this->data['tagline']) { ?><li id="f-tagline"><?php echo $this->data['tagline'] ?></li><?php } ?>
+       </ul>
+      </div>
+    </div>
+    <?php $this->html('reporttime') ?>
+  </body>
+</html>
+<?php
+               wfRestoreWarnings();
+       }
+}
+?>
diff --git a/skins/disabled/MonoBook.pt b/skins/disabled/MonoBook.pt
new file mode 100644 (file)
index 0000000..8d5fb3f
--- /dev/null
@@ -0,0 +1,142 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="${lang}" lang="${lang}" dir="${dir}">
+  <head>
+    <meta http-equiv="Content-Type" content="${mimetype}; charset=${charset}" />
+    <div tal:replace="structure headlinks"></div>
+    <title tal:content="pagetitle">Exciting xhtml slimfast</title>
+    <style type="text/css" media="screen,projection">/*<![CDATA[*/ @import "${stylepath}/${stylename}/main.css"; /*]]>*/</style>
+    <link rel="stylesheet" type="text/css" media="print" href="${stylepath}/common/commonPrint.css" />
+    <!--[if lt IE 5.5000]><style type="text/css"> @import "${stylepath}/${stylename}/IE50Fixes.css"; </style><![endif]-->
+    <!--[if IE 5.5000]><style type="text/css"> @import "${stylepath}/${stylename}/IE55Fixes.css"; </style><![endif]-->
+    <!--[if gte IE 6]><style type="text/css"> @import "${stylepath}/${stylename}/IE60Fixes.css"; </style><![endif]-->
+    <!--[if IE]><script type="${jsmimetype}" src="${stylepath}/common/IEFixes.js"></script>
+    <meta http-equiv="imagetoolbar" content="no" /><![endif]-->
+    <script tal:condition="jsvarurl" type="${jsmimetype}" tal:attributes="src jsvarurl"></script>
+    <script type="${jsmimetype}" src="${stylepath}/common/wikibits.js"></script>
+    <style tal:condition="usercss" tal:content="structure usercss" type="text/css"></style>
+    <script tal:condition="userjs" type="${jsmimetype}" tal:attributes="src userjs"></script><script 
+      tal:condition="userjsprev" tal:content="structure userjsprev" type="${jsmimetype}"></script>
+  </head>
+  <body tal:attributes="ondblclick body_ondblclick|default; class nsclass|default">
+    <div id="globalWrapper">
+      <div id="column-content">
+       <div id="content">
+         <a name="top" id="contentTop"></a>
+         <div id="siteNotice" tal:condition="sitenotice" tal:content="structure sitenotice"></div>
+         <h1 class="firstHeading" tal:content="title">Leonardo da Vinci</h1>
+         <div id="bodyContent">
+           <h3 id="siteSub" i18n:translate="string:tagline">From Wikipedia, the free encyclopedia.</h3>
+           <div id="contentSub" tal:content="structure subtitle"></div>
+           <div id="contentSub" tal:condition="undelete" tal:content="structure undelete"></div>
+           <div tal:condition="newtalk" class="usermessage" tal:content="structure newtalk"></div>
+           <!-- start content -->
+           <div tal:replace="structure bodytext"></div>
+           <div tal:condition="catlinks" id="catlinks" tal:content="structure catlinks"></div>
+           <!-- end content -->
+           <div class="visualClear"></div>
+         </div>
+       </div>
+      </div>
+      <div id="column-one">
+       <div id="p-cactions" class="portlet">
+         <h5>Views</h5>
+         <ul>
+           <li tal:repeat="action content_actions" 
+           tal:attributes="id string:ca-${repeat/action/key}; class action/class|default"><a
+             tal:attributes="href action/href|default"
+             tal:content="action/text">Linktext</a></li>
+         </ul>
+       </div>
+       <div class="portlet" id="p-personal">
+         <h5 i18n:translate="string:personaltools">Personal Tools</h5>
+         <div class="pBody">
+           <ul>
+             <li tal:repeat="item personal_urls" 
+             tal:attributes="id string:pt-${repeat/item/key};"><a href="myuserpage"
+               tal:attributes="href item/href; class item/class|default"
+               tal:content="item/text">Log in</a></li>
+           </ul>
+         </div>
+       </div>
+       <div class="portlet" id="p-logo">
+         <a style="background-image: url(${logopath});" href="${nav_urls/mainpage/href}" i18n:attributes="title string:mainpage"></a>
+       </div>
+       <script type="${jsmimetype}"> if (window.isMSIE55) fixalpha(); </script>
+       <div class="portlet" id="p-navigation">
+         <h5 i18n:translate="string:navigation">Navigation</h5>
+         <div class="pBody">
+           <ul>
+             <li tal:repeat="navlink navigation_urls" tal:attributes="id navlink/id">
+               <a tal:attributes="href navlink/href" tal:content="structure navlink/text">NavLink</a>
+             </li>
+           </ul>
+         </div>
+       </div>
+       <div id="p-search" class="portlet">
+         <h5 i18n:translate="string:search">Search</h5>
+         <div class="pBody">
+           <form name="searchform" tal:attributes="action searchaction" id="searchform">
+             <input id="searchInput" name="search" type="text"
+             i18n:attributes="accesskey string:accesskey-search | default"/>
+             <input type='submit' name="go" value="Go" class="searchButton" 
+             i18n:attributes="value string:go"/>&nbsp;<input type='submit' name="fulltext"
+             value="Search" class="searchButton"
+             i18n:attributes="value string:search"/>
+           </form>
+         </div>
+       </div>
+       <div class="portlet" id="p-tb">
+         <h5 i18n:translate="string:toolbox">Toolbox</h5>
+         <div class="pBody">
+           <ul>
+             <li id="t-whatlinkshere" tal:condition="notspecialpage"><a tal:attributes="href nav_urls/whatlinkshere/href"
+               i18n:translate="string:whatlinkshere">What links here</a></li>
+             <li id="t-recentchangeslinked" tal:condition="notspecialpage"><a tal:attributes="href nav_urls/recentchangeslinked/href"
+               i18n:translate="string:recentchangeslinked">Related Changes</a></li>
+             <li tal:condition="feeds" id="feedlinks">
+             <span i18n:translate="string:feedlinks">Feeds:</span>
+             <span tal:repeat="feed feeds" 
+               tal:attributes="id string:feed-${repeat/feed/key};"><a 
+                 tal:attributes="href feed/href;"
+                 tal:content="feed/text">rss</a>&nbsp;</span>
+             </li>
+             <li id="t-contributions" tal:condition="nav_urls/contributions"><a tal:attributes="href nav_urls/contributions/href"
+               i18n:translate="string:contributions">Contributions</a></li>
+             <li id="t-emailuser" tal:condition="nav_urls/emailuser"><a tal:attributes="href nav_urls/emailuser/href"
+               i18n:translate="string:emailuser">Email this user</a></li>
+             <li id="t-upload" tal:condition="nav_urls/upload"><a tal:attributes="href nav_urls/upload/href"
+               i18n:translate="string:upload">Upload a file</a></li>
+             <li id="t-specialpages"><a tal:attributes="href nav_urls/specialpages/href"
+               i18n:translate="string:specialpages">Special Pages</a></li>
+           </ul>
+         </div>
+       </div>
+       <div id="p-lang" class="portlet" tal:condition="language_urls">
+         <h5 i18n:translate="string:otherlanguages">Language</h5>
+         <div class="pBody">
+           <ul>
+             <li tal:repeat="langlink language_urls">
+             <a tal:attributes="href langlink/href"
+               tal:content="structure langlink/text">English</a>
+             </li>
+           </ul>
+         </div>
+       </div>
+      </div><!-- end of the left (by default at least) column -->
+      <div class="visualClear"></div>
+      <div id="footer">
+       <div id="f-poweredbyico" tal:condition="poweredbyico" tal:content="structure poweredbyico"></div>
+       <div id="f-copyrightico" tal:condition="copyrightico" tal:content="structure copyrightico"></div>
+       <ul id="f-list">
+         <li id="f-lastmod" tal:condition="lastmod" tal:content="structure lastmod"></li>
+         <li id="f-viewcount" tal:condition="viewcount" tal:content="structure viewcount"></li>
+         <li id="f-credits" tal:condition="credits" tal:content="structure credits"></li>
+         <li id="f-copyright" tal:condition="copyright" tal:content="structure copyright"></li>
+         <li id="f-about" tal:condition="about" tal:content="structure about"></li>
+         <li id="f-disclaimer" tal:condition="disclaimer" tal:content="structure disclaimer"></li>
+       </ul>
+      </div>
+    </div>
+    <div tal:replace="structure reporttime"></div>
+  </body>
+</html>
diff --git a/skins/disabled/MonoBookTal.php b/skins/disabled/MonoBookTal.php
new file mode 100644 (file)
index 0000000..876150c
--- /dev/null
@@ -0,0 +1,44 @@
+<?php
+/**
+ * This is for the old PHPTAL-based version of MonoBook.
+ * The main MonoBook has been converted to straight PHP
+ * to avoid the dependency on PHPTAL and, hopefully,
+ * reduce the frequent problems users have with compiled
+ * PHPTAL templates failing.
+ *
+ * You can still use MonoBook.pt as a sample, or copy it
+ * to the parent directory to test with.
+ *
+ * @todo document
+ * @package MediaWiki
+ * @subpackage Skins
+ */
+
+if( !defined( 'MEDIAWIKI' ) )
+       die();
+
+/** */
+require_once('includes/SkinPHPTal.php');
+
+# Test if PHPTal is enabled. If not MediaWiki will load the 'standard' skin
+# which doesnt use PHPTal
+if( class_exists( 'SkinPHPTal' ) ) {
+       /**
+        * Inherit everything from SkinPHPTal
+        * This is a dummy skin as MonoBook is the default PHPTal skin.
+        * @todo document
+        * @package MediaWiki
+        * @subpackage Skins
+        */
+       class SkinMonoBookTal extends SkinPHPTal {
+               /** Using monobook. */
+               function initPage( &$out ) {
+                       SkinPHPTal::initPage( $out );
+                       $this->skinname  = 'monobooktal';
+                       $this->stylename = 'monobook';
+                       $this->template  = 'MonoBook';
+               }
+       }
+
+}
+?>
diff --git a/skins/disabled/WikimediaWiki.php b/skins/disabled/WikimediaWiki.php
new file mode 100644 (file)
index 0000000..87564df
--- /dev/null
@@ -0,0 +1,94 @@
+<?php
+/**
+ * Tentative to make a skin for wikimedia.org
+ *
+ * @package MediaWiki
+ * @subpackage Skins
+ */
+
+if( !defined( 'MEDIAWIKI' ) )
+       die();
+
+/** */
+
+require_once('includes/SkinPHPTal.php');
+if( class_exists( 'SkinPHPTal' ) ) {
+
+$wgExtraSkins['wikimediawiki'] = 'Wikimediawiki';
+
+require_once('MonoBook.php');
+
+/**
+ *
+ * @package MediaWiki
+ * @subpackage Skins
+ */
+class SkinWikimediawiki extends SkinMonoBook {
+       function initPage( &$out ) {
+               SkinPHPTal::initPage( $out );
+               $this->skinname = 'wikimediawiki';
+               $this->stylename = 'monobook';
+               $this->template = 'WikimediaWiki';
+       }
+
+       # build array of common navigation links
+       function buildNavUrls () {
+               global $wgTitle, $wgUser, $wgRequest;
+               global $wgSiteSupportPage;
+
+               $action = $wgRequest->getText( 'action' );
+               $oldid = $wgRequest->getVal( 'oldid' );
+               $diff = $wgRequest->getVal( 'diff' );
+               // XXX: remove htmlspecialchars when tal:attributes works with i18n:attributes
+               $nav_urls = array();
+               $nav_urls['mainpage'] = array('href' => htmlspecialchars( $this->makeI18nUrl('mainpage')));
+               $nav_urls['randompage'] = (wfMsgForContent('randompage') != '-') ? array('href' => htmlspecialchars( $this->makeSpecialUrl('Randompage'))) : false;
+               $nav_urls['recentchanges'] = (wfMsgForContent('recentchanges') != '-') ? array('href' => htmlspecialchars( $this->makeSpecialUrl('Recentchanges'))) : false;
+               $nav_urls['whatlinkshere'] = array('href' => htmlspecialchars( $this->makeSpecialUrl('Whatlinkshere', 'target='.urlencode( $this->thispage ))));
+               $nav_urls['currentevents'] = (wfMsgForContent('currentevents') != '-') ? array('href' => htmlspecialchars( $this->makeI18nUrl('currentevents'))) : false;
+               $nav_urls['portal'] = (wfMsgForContent('portal') != '-') ? array('href' => htmlspecialchars( $this->makeI18nUrl('portal-url'))) : false;
+               $nav_urls['recentchangeslinked'] = array('href' => htmlspecialchars( $this->makeSpecialUrl('Recentchangeslinked', 'target='.urlencode( $this->thispage ))));
+               $nav_urls['bugreports'] = (wfMsgForContent('bugreports') != '-') ? array('href' => htmlspecialchars( $this->makeI18nUrl('bugreportspage'))) : false;
+               $nav_urls['sitesupport'] = array('href' => htmlspecialchars( $wgSiteSupportPage));
+               $nav_urls['help'] = array('href' => htmlspecialchars( $this->makeI18nUrl('helppage')));
+               $nav_urls['upload'] = array('href' => htmlspecialchars( $this->makeSpecialUrl('Upload')));
+               $nav_urls['specialpages'] = array('href' => htmlspecialchars( $this->makeSpecialUrl('Specialpages')));
+
+
+               # Specific for mediawiki.org menu
+               $nav_urls['aboutmediawiki'] = (wfMsgForContent('aboutmediawiki') != '-') ? array('href' => htmlspecialchars( $this->makeI18nUrl('aboutmediawiki-url'))) : false;
+               $nav_urls['projects'] = (wfMsgForContent('projects') != '-') ? array('href' => htmlspecialchars( $this->makeI18nUrl('projects-url'))) : false;
+               $nav_urls['membership'] = (wfMsgForContent('membership') != '-') ? array('href' => htmlspecialchars( $this->makeI18nUrl('membership-url'))) : false;
+               $nav_urls['pressroom'] = (wfMsgForContent('pressroom') != '-') ? array('href' => htmlspecialchars( $this->makeI18nUrl('pressroom-url'))) : false;
+               $nav_urls['software'] = (wfMsgForContent('software') != '-') ? array('href' => htmlspecialchars( $this->makeI18nUrl('software-url'))) : false;
+               $nav_urls['localchapters'] = (wfMsgForContent('localchapters') != '-') ? array('href' => htmlspecialchars( $this->makeI18nUrl('localchapters-url'))) : false;
+               $nav_urls['contactus'] = (wfMsgForContent('contactus') != '-') ? array('href' => htmlspecialchars( $this->makeI18nUrl('contactus-url'))) : false;
+
+               if( $wgTitle->getNamespace() == NS_USER || $wgTitle->getNamespace() == NS_USER_TALK ) {
+                       $id = User::idFromName($wgTitle->getText());
+                       $ip = User::isIP($wgTitle->getText());
+               } else {
+                       $id = 0;
+                       $ip = false;
+               }
+
+               if ( 0 != $wgUser->getID() ) { # show only to signed in users
+                       if($id) {
+                               # can only email non-anons
+                               $nav_urls['emailuser'] = array(
+                                       'href' => htmlspecialchars( $this->makeSpecialUrl('Emailuser', "target=" . $wgTitle->getPartialURL() ) )
+                               );
+                               # only non-anons have contrib list
+                               $nav_urls['contributions'] = array(
+                                       'href' => htmlspecialchars( $this->makeSpecialUrl('Contributions', "target=" . $wgTitle->getPartialURL() ) )
+                               );
+                       }
+               }
+
+
+               return $nav_urls;
+       }
+}
+
+}
+?>
diff --git a/skins/disabled/WikimediaWiki.pt b/skins/disabled/WikimediaWiki.pt
new file mode 100644 (file)
index 0000000..32fa5ae
--- /dev/null
@@ -0,0 +1,165 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="${lang}" lang="${lang}" dir="${dir}">
+  <head>
+    <meta http-equiv="Content-Type" content="${mimetype}; charset=${charset}" />
+    ${headlinks}
+    <title tal:content="pagetitle">Exciting xhtml slimfast</title>
+    <style type="text/css" media="screen,projection">/*<![CDATA[*/ @import "${stylepath}/${stylename}/main.css"; /*]]>*/</style>
+    <link rel="stylesheet" type="text/css" media="print" href="${stylepath}/common/commonPrint.css" />
+    <!--[if IE]><style type="text/css" media="all">@import "${stylepath}/${stylename}/common/IEFixes.css";</style>
+    <script type="${jsmimetype}" src="${stylepath}/IEFixes.js"></script>
+    <meta http-equiv="imagetoolbar" content="no" /><![endif]-->
+    <script tal:condition="jsvarurl" type="${jsmimetype}" tal:attributes="src jsvarurl"></script>
+    <script type="${jsmimetype}" src="${stylepath}/common/wikibits.js"></script>
+    <style tal:condition="usercss" type="text/css">/*<![CDATA[*/ ${usercss} /*]]>*/</style>
+    <script tal:condition="userjs" type="${jsmimetype}" tal:attributes="src userjs"></script><script 
+      tal:condition="userjsprev" type="${jsmimetype}">/*<![CDATA[*/${userjsprev}/*]]>*/</script>
+  </head>
+  <body tal:attributes="ondblclick body-ondblclick|default; class nsclass|default">
+    <div id="globalWrapper">
+      <div id="column-content">
+       <div id="content">
+         <a name="top" id="contentTop"></a>
+         <div id="siteNotice" tal:condition="sitenotice" tal:content="structure sitenotice"></div>
+         <h1 class="firstHeading" tal:content="title">Leonardo da Vinci</h1>
+         <div id="bodyContent">
+           <h3 id="siteSub" i18n:translate="string:tagline">From Wikipedia, the free encyclopedia.</h3>
+           <div id="contentSub" tal:content="structure subtitle"></div>
+           <div id="contentSub" tal:condition="undelete" tal:content="structure undelete"></div>
+           <div tal:condition="newtalk" class="usermessage" tal:content="structure newtalk"></div>
+           <!-- start content -->
+           ${bodytext}
+           <div tal:condition="catlinks" id="catlinks" tal:content="structure catlinks"></div>
+           <!-- end content -->
+           <div class="visualClear"></div>
+         </div>
+       </div>
+      </div>
+      <div id="column-one">
+       <div id="p-cactions" class="portlet">
+         <h5>Views</h5>
+         <ul>
+           <li tal:repeat="action content_actions" 
+           tal:attributes="id string:ca-${repeat/action/key}; class action/class|default"><a
+             tal:attributes="href action/href|default"
+             tal:content="action/text">Linktext</a></li>
+         </ul>
+       </div>
+       <div class="portlet" id="p-personal">
+         <h5 i18n:translate="string:personaltools">Personal Tools</h5>
+         <div class="pBody">
+           <ul>
+             <li tal:repeat="item personal_urls" 
+             tal:attributes="id string:pt-${repeat/item/key};"><a href="myuserpage"
+               tal:attributes="href item/href; class item/class|default"
+               tal:content="item/text">Log in</a></li>
+           </ul>
+         </div>
+       </div>
+       <div class="portlet" id="p-logo">
+         <a style="background-image: url(${logopath});" href="${nav_urls/mainpage/href}" i18n:attributes="title string:mainpage"></a>
+       </div>
+       <script type="${jsmimetype}"> if (window.isMSIE55) fixalpha(); </script>
+       <div class="portlet" id="p-navigation">
+         <h5 i18n:translate="string:navigation">Navigation</h5>
+         <div class="pBody">
+           <ul>
+             <li id="n-mainpage"><a href="${nav_urls/mainpage/href}"
+               i18n:translate="string:mainpage">Home</a></li>
+             <li id="n-aboutmediawiki"><a href="${nav_urls/aboutmediawiki/href}"
+               i18n:translate="string:aboutmediawiki">About MediaWiki</a></li>
+             <li id="n-portal" tal:condition="nav_urls/portal/href"><a href="${nav_urls/portal/href}"
+               i18n:translate="string:portal">Community Portal</a></li>
+             <li id="n-currentevents" tal:condition="nav_urls/currentevents/href"><a href="${nav_urls/currentevents/href}"
+               i18n:translate="string:currentevents">Last News</a></li>
+             <li id="n-projects" tal:condition="nav_urls/projects/href"><a href="${nav_urls/projects/href}"
+               i18n:translate="string:projects">Our projects</a></li>
+             <li id="n-recentchanges" tal:condition="nav_urls/recentchanges/href"><a href="${nav_urls/recentchanges/href}"
+               i18n:translate="string:recentchanges">Recent Changes</a></li>
+             <li id="n-randompage" tal:condition="nav_urls/randompage/href"><a href="${nav_urls/randompage/href}"
+               i18n:translate="string:randompage">Random Page</a></li>
+             <li id="n-help" tal:condition="nav_urls/help/href"><a href="${nav_urls/help/href}"
+               i18n:translate="string:help">Help</a></li>
+             <li id="n-sitesupport" tal:condition="nav_urls/sitesupport/href"><a href="${nav_urls/sitesupport/href}"
+               i18n:translate="string:sitesupport">Support us</a></li>
+             <li id="n-membership" tal:condition="nav_urls/membership/href"><a href="${nav_urls/membership/href}"
+               i18n:translate="string:membership">Membership</a></li>
+             <li id="n-pressroom" tal:condition="nav_urls/pressroom/href"><a href="${nav_urls/pressroom/href}"
+               i18n:translate="string:pressroom">Press room</a></li>
+             <li id="n-software" tal:condition="nav_urls/software/href"><a href="${nav_urls/software/href}"
+               i18n:translate="string:software">Our software</a></li>
+             <li id="n-localchapters" tal:condition="nav_urls/localchapters/href"><a href="${nav_urls/localchapters/href}"
+               i18n:translate="string:localchapters">Local chapters</a></li>
+             <li id="n-contactus" tal:condition="nav_urls/contactus/href"><a href="${nav_urls/contactus/href}"
+               i18n:translate="string:contactus">Contact us</a></li>
+           </ul>
+         </div>
+       </div>
+       <div id="p-search" class="portlet">
+         <h5 i18n:translate="string:search">Search</h5>
+         <div class="pBody">
+           <form name="searchform" action="${searchaction}" id="searchform">
+             <input id="searchInput" name="search" type="text"
+             i18n:attributes="accesskey string:accesskey-search | default"/>
+             <input type='submit' name="go" value="Go" class="searchButton" 
+             i18n:attributes="value string:go"/>&nbsp;<input type='submit' name="fulltext"
+             value="Search" class="searchButton"
+             i18n:attributes="value string:search"/>
+           </form>
+         </div>
+       </div>
+       <div class="portlet" id="p-tb">
+         <h5 i18n:translate="string:toolbox">Toolbox</h5>
+         <div class="pBody">
+           <ul>
+             <li id="t-whatlinkshere" tal:condition="notspecialpage"><a href="${nav_urls/whatlinkshere/href}"
+               i18n:translate="string:whatlinkshere">What links here</a></li>
+             <li id="t-recentchangeslinked" tal:condition="notspecialpage"><a href="${nav_urls/recentchangeslinked/href}"
+               i18n:translate="string:recentchangeslinked">Related Changes</a></li>
+             <li tal:condition="feeds" id="feedlinks">
+             <span i18n:translate="string:feedlinks">Feeds:</span>
+             <span tal:repeat="feed feeds" 
+               tal:attributes="id string:feed-${repeat/feed/key};"><a 
+                 tal:attributes="href feed/href;"
+                 tal:content="feed/text">rss</a>&nbsp;</span>
+             </li>
+             <li id="t-contributions" tal:condition="nav_urls/contributions/href"><a href="${nav_urls/contributions/href}"
+               i18n:translate="string:contributions">Contributions</a></li>
+             <li id="t-emailuser" tal:condition="nav_urls/emailuser/href"><a href="${nav_urls/emailuser/href}"
+               i18n:translate="string:emailuser">Email this user</a></li>
+             <li id="t-upload" tal:condition="loggedin"><a href="${nav_urls/upload/href}"
+               i18n:translate="string:upload">Upload a file</a></li>
+             <li id="t-specialpages"><a href="${nav_urls/specialpages/href}"
+               i18n:translate="string:specialpages">Special Pages</a></li>
+           </ul>
+         </div>
+       </div>
+       <div id="p-lang" class="portlet" tal:condition="language_urls">
+         <h5 i18n:translate="string:otherlanguages">Language</h5>
+         <div class="pBody">
+           <ul>
+             <li tal:repeat="langlink language_urls">
+             <a tal:attributes="href langlink/href"
+               tal:content="structure langlink/text">English</a>
+             </li>
+           </ul>
+         </div>
+       </div>
+      </div><!-- end of the left (by default at least) column -->
+      <div class="visualClear"></div>
+      <div id="footer">
+       <div id="f-poweredbyico" tal:condition="poweredbyico">${poweredbyico}</div>
+       <div id="f-copyrightico" tal:condition="copyrightico">${copyrightico}</div>
+       <ul id="f-list">
+         <li id="f-lastmod" tal:condition="lastmod">${lastmod}</li>
+         <li id="f-viewcount" tal:condition="viewcount">${viewcount}</li>
+         <li id="f-credits" tal:condition="credits">${credits}</li>
+         <li id="f-copyright" tal:condition="copyright">${copyright}</li>
+         <li id="f-about" tal:condition="about">${about}</li>
+         <li id="f-disclaimer" tal:condition="disclaimer">${disclaimer}</li>
+       </ul>
+      </div>
+    </div>
+    ${reporttime}
+  </body>
+</html>
diff --git a/skins/monobook/IE50Fixes.css b/skins/monobook/IE50Fixes.css
new file mode 100644 (file)
index 0000000..dd9eda3
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+** IE5.0 Fix Stylesheet
+*/
+
+#column-content {
+    margin: 0 !important;
+    float: none;
+}
+#column-content #content { 
+    margin-top: 3em; 
+    height: 1%;
+}
+#column-one {
+    position: absolute;
+    overflow: visible;
+    top: 0;
+    left: 0;
+    z-index: 3;
+}
+#footer {
+    margin: 0 0 0 13.6em;
+}
+
+/* IE 5 & 5.5 interpret keyword sizes one off */
+body { font-size: xx-small; }
+/*
+** the edit tabs
+*/
+#p-cactions li {
+    float: left;
+    padding-top: 0;
+    padding-bottom: 0 !important;
+    height: 0.9em;
+}
+#p-cactions li a {
+    display: block;
+    padding-bottom: 0.045em;
+}
+#p-cactions li.selected a {
+    padding-bottom: 0.17em;
+}
+#p-cactions li a:hover {
+    padding-bottom: 0.17em;
+}
+/* 5.0 doesn't like the background icon for external links and user */
+.link-external,
+.external {
+    background: none;
+    padding: 0;
+}
+#p-personal ul { float: right }
+#p-personal li { float: left }
+li#pt-userpage,
+li#pt-anonuserpage,
+li#pt-login,
+li#pt-logout {
+    background: none;
+    padding-left: none;
+}
+.visualClear {
+    width:100%;
+    height: 0px;
+    padding:0;
+    margin:0;
+}
+.firstHeading { margin-bottom: 0.3em; }
+/*div{ border:1px solid Red !important;}*/
diff --git a/skins/monobook/IE55Fixes.css b/skins/monobook/IE55Fixes.css
new file mode 100644 (file)
index 0000000..2f78561
--- /dev/null
@@ -0,0 +1,81 @@
+/* IE5.5/win- only fixes */
+
+#column-content { 
+    float: none; 
+    margin-left: 0;
+    height: 1%;
+}
+#column-content #content {
+    position: relative;
+    z-index: 5;
+    margin-left: 12.2em;
+    margin-top: 3em;
+    height: 1%;
+}
+#column-one {
+    position: absolute;
+    top: 0;
+    left: 0;
+    z-index: 4;
+    width: 100%;
+}
+#footer {
+    margin-left: 13.6em;
+    border-left: 1px solid #fabd23;
+}
+
+/*#bodyContent div,
+#bodyContent pre { overflow: auto; }*/
+
+#p-personal { padding-bottom: 0.1em; }
+
+body { font-size: xx-small; }
+
+#p-cactions {
+    width: 76% !important;
+    z-index: 3 !important;
+    float: none;
+}
+#p-cactions li {
+    padding-bottom: 0 !important;
+    border: none;
+    background-color: transparent;
+    cursor: default;
+    float: none !important;
+}
+#p-cactions li a {
+    display: inline-block !important;
+    vertical-align: top;
+    padding-bottom: 0;
+    border: solid #aaa;
+    border-width: 1px 1px 0;
+}
+#p-cactions li.selected a {
+    border-color: #fabd23;
+    padding-bottom: 0.17em;
+}
+#p-cactions li a:hover {
+    padding-bottom: 0.17em;
+}
+.portlet {
+    overflow:hidden;
+}
+#bodyContent a.external {
+    background: url(external.png) center right no-repeat;
+    padding-right: 13px;
+}
+/* show the hand */
+#p-logo a,
+#p-logo a:hover {
+    cursor: pointer;
+}
+.visualClear {
+    width:90%;
+    height: 1px;
+    padding:0;
+    margin:0;
+}
+
+#editform {
+    width: 100%;
+}
diff --git a/skins/monobook/IE60Fixes.css b/skins/monobook/IE60Fixes.css
new file mode 100644 (file)
index 0000000..feec15f
--- /dev/null
@@ -0,0 +1,79 @@
+/* 6.0 - only fixes */
+/* content area */ 
+/* workaround for various ie float bugs */
+#column-content { 
+    float: none; 
+    margin-left: 0;
+    height: 1%;
+}
+#column-content #content {
+    margin-left: 12.2em;
+    margin-top: 3em;
+    height: 1%;
+}
+#column-one {
+    position: absolute;
+    top: 0;
+    left: 0;
+    z-index: 4;
+}
+#footer {
+    margin-left: 13.6em;
+    border-left: 1px solid #fabd23;
+}
+
+/* the tabs */
+
+#p-cactions {
+    z-index: 3;
+}
+
+#p-cactions li {
+    padding-bottom: 0 !important;
+    border: none;
+    background-color: transparent;
+    cursor: default;
+    float: none !important;
+}
+#p-cactions li a {
+    display: inline-block !important;
+    vertical-align: top;
+    padding-bottom: 0;
+    border: solid #aaa;
+    border-width: 1px 1px 0;
+}
+#p-cactions li.selected a {
+    border-color: #fabd23;
+    padding-bottom: 0.17em;
+}
+#p-cactions li a:hover {
+    padding-bottom: 0.17em;
+}
+#portal-personaltools {
+    padding-bottom: 0.1em;
+}
+#bodyContent a.external {
+    background: url(external.png) center right no-repeat;
+    padding-right: 13px;
+}
+
+/* show the hand */
+#p-logo a,
+#p-logo a:hover {
+    cursor: pointer;
+}
+div.visualClear {
+    width:100%;
+    line-height: 0;
+}
+textarea {
+    width: 96%;
+}
+
+div.editsection,
+#catlinks,
+div.tright,
+div.tleft {
+    position: relative;
+}
+/*{ border:1px solid Red !important;}*/
diff --git a/skins/monobook/IEMacFixes.css b/skins/monobook/IEMacFixes.css
new file mode 100644 (file)
index 0000000..faa720a
--- /dev/null
@@ -0,0 +1,44 @@
+/* IE/Mac only fix stylesheet, imported from main.css */
+#portal-column-content {
+    margin: 0 0 4.8em 0;
+    float: none;
+}
+#portal-column-content #content {
+    z-index: 0;
+}
+#portal-column-one {
+    position: absolute;
+    top:0;
+    left:0;
+    z-index: 3;
+}
+#portal-footer {
+    margin-left: 12em; 
+}
+/*
+#portlet-contentViews {
+    top: 0.6em !important;
+    left: 14.5em !important;
+}
+*/
+#portlet-contentViews li,
+#portlet-contentViews .selected {
+    border: none !important;
+}
+#portlet-contentViews li a   {
+    border: 1px solid #aaaaaa;
+    border-bottom: none;
+}
+#portlet-contentViews li.selected a {
+    border: 1px solid #fabd23;
+    border-bottom: none;
+}
+/* no background images */
+li#personaltools-userpage,
+li#personaltools-login/* */ {
+    background: none;
+    padding-left: none;
+}
+#mactest {
+color: Green;
+}
diff --git a/skins/monobook/KHTMLFixes.css b/skins/monobook/KHTMLFixes.css
new file mode 100644 (file)
index 0000000..97fba0c
--- /dev/null
@@ -0,0 +1,3 @@
+/* KHTML fix stylesheet */
+/* work around the horizontal scrollbars */
+#column-content { margin-left: 0; }
diff --git a/skins/monobook/Opera6Fixes.css b/skins/monobook/Opera6Fixes.css
new file mode 100644 (file)
index 0000000..01bf27e
--- /dev/null
@@ -0,0 +1,14 @@
+/* opera 6 fixes */
+#column-one {
+    position: relative;
+    max-width: 11.7em;
+}
+#p-personal {
+    width: 45em;
+    margin-left: 8.6em;
+    right: 0;
+}
+#bodyContent a.external {
+    background: url(external.png) center right no-repeat;
+    padding-right: 13px;
+}
diff --git a/skins/monobook/Opera7Fixes.css b/skins/monobook/Opera7Fixes.css
new file mode 100644 (file)
index 0000000..c005768
--- /dev/null
@@ -0,0 +1,11 @@
+/* small tweaks for opera seven */
+#p-cactions {
+    margin-top: 0.1em;
+}
+#p-cactions li a {
+    top: 2px;
+}
+#bodyContent a.external {
+    background: url(external.png) center right no-repeat;
+    padding-right: 13px;
+}
diff --git a/skins/monobook/bullet.gif b/skins/monobook/bullet.gif
new file mode 100644 (file)
index 0000000..b43de48
Binary files /dev/null and b/skins/monobook/bullet.gif differ
diff --git a/skins/monobook/discussionitem_icon.gif b/skins/monobook/discussionitem_icon.gif
new file mode 100644 (file)
index 0000000..baec471
Binary files /dev/null and b/skins/monobook/discussionitem_icon.gif differ
diff --git a/skins/monobook/external.png b/skins/monobook/external.png
new file mode 100644 (file)
index 0000000..419c06f
Binary files /dev/null and b/skins/monobook/external.png differ
diff --git a/skins/monobook/file_icon.gif b/skins/monobook/file_icon.gif
new file mode 100644 (file)
index 0000000..847f648
Binary files /dev/null and b/skins/monobook/file_icon.gif differ
diff --git a/skins/monobook/headbg.jpg b/skins/monobook/headbg.jpg
new file mode 100644 (file)
index 0000000..5491c6e
Binary files /dev/null and b/skins/monobook/headbg.jpg differ
diff --git a/skins/monobook/link_icon.gif b/skins/monobook/link_icon.gif
new file mode 100644 (file)
index 0000000..815ccb1
Binary files /dev/null and b/skins/monobook/link_icon.gif differ
diff --git a/skins/monobook/lock_icon.gif b/skins/monobook/lock_icon.gif
new file mode 100644 (file)
index 0000000..8a87e28
Binary files /dev/null and b/skins/monobook/lock_icon.gif differ
diff --git a/skins/monobook/magnify-clip.png b/skins/monobook/magnify-clip.png
new file mode 100644 (file)
index 0000000..992aa2e
Binary files /dev/null and b/skins/monobook/magnify-clip.png differ
diff --git a/skins/monobook/mail_icon.gif b/skins/monobook/mail_icon.gif
new file mode 100644 (file)
index 0000000..50a87a9
Binary files /dev/null and b/skins/monobook/mail_icon.gif differ
diff --git a/skins/monobook/main.css b/skins/monobook/main.css
new file mode 100644 (file)
index 0000000..58e5778
--- /dev/null
@@ -0,0 +1,1209 @@
+/*
+** MediaWiki 'monobook' style sheet for CSS2-capable browsers.
+** Copyright Gabriel Wicke - http://wikidev.net/
+** License: GPL (http://www.gnu.org/copyleft/gpl.html)
+**
+** Loosely based on http://www.positioniseverything.net/ordered-floats.html by Big John
+** and the Plone 2.0 styles, see http://plone.org/ (Alexander Limi,Joe Geldart & Tom Croucher,
+** Michael Zeltner and Geir Bækholt)
+** All you guys rock :)
+*/
+
+#column-content {
+    width: 100%;
+    float: right;
+    margin: 0 0 .6em -12.2em;
+    padding: 0;
+}
+#content {
+    margin: 2.8em 0 0 12.2em;
+    padding: 0 1em 1.5em 1em;
+    background: white;
+    color: black;
+    border: 1px solid #aaa;
+    border-right: none;
+    line-height: 1.5em;
+    position: relative;
+    z-index: 2;
+}
+#column-one {
+    padding-top: 160px;
+}
+/* the left column width is specified in class .portlet */
+
+/* Font size:
+** We take advantage of keyword scaling- browsers won't go below 9px
+** More at http://www.w3.org/2003/07/30-font-size
+** http://style.cleverchimp.com/font_size_intervals/altintervals.html
+*/
+
+body {
+    font: x-small sans-serif;
+    background: #f9f9f9 url(headbg.jpg) 0 0 no-repeat;
+    color: black;
+    margin: 0;
+    padding: 0;
+}
+
+/* scale back up to a sane default */
+#globalWrapper {
+    font-size: 127%;
+    width: 100%;
+    margin: 0;
+    padding: 0;
+}
+.visualClear {
+    clear: both;
+}
+
+/* general styles */
+
+table {
+    font-size: 100%;
+    background: white;
+    color: black;
+}
+a {
+    text-decoration: none;
+    color: #002bb8;
+    background: none;
+}
+a:visited {
+    color: #5a3696;
+}
+a:active {
+    color: #faa700;
+}
+a:hover {
+    text-decoration: underline;
+}
+a.stub {
+    color: #772233;
+}
+a.new, #p-personal a.new {
+    color: #ba0000;
+}
+a.new:visited, #p-personal a.new:visited {
+    color: #a55858;
+}
+
+img {
+    border: none;
+    vertical-align: middle;
+}
+p {
+    margin: .4em 0 .5em 0;
+    line-height: 1.5em;
+}
+p img {
+    margin: 0;
+}
+
+hr {
+    height: 1px;
+    color: #aaa;
+    background-color: #aaa;
+    border: 0;
+    margin: .2em 0 .2em 0;
+}
+
+h1, h2, h3, h4, h5, h6 {
+    color: black;
+    background: none;
+    font-weight: normal;
+    margin: 0;
+    padding-top: .5em;
+    padding-bottom: .17em;
+    border-bottom: 1px solid #aaa;
+}
+h1 { font-size: 188%; }
+h2 { font-size: 150%; }
+h3, h4, h5, h6 {
+    border-bottom: none;
+    font-weight: bold;
+}
+h3 { font-size: 132%; }
+h4 { font-size: 116%; }
+h5 { font-size: 100%; }
+h6 { font-size: 80%;  }
+
+ul {
+    line-height: 1.5em;
+    list-style-type: square;
+    margin: .3em 0 0 1.5em;
+    padding: 0;
+    list-style-image: url(bullet.gif);
+}
+ol {
+    line-height: 1.5em;
+    margin: .3em 0 0 3.2em;
+    padding: 0;
+    list-style-image: none;
+}
+li {
+    margin-bottom: .1em;
+}
+dt {
+    font-weight: bold;
+    margin-bottom: .1em;
+}
+dl {
+    margin-top: .2em;
+    margin-bottom: .5em;
+}
+dd {
+    line-height: 1.5em;
+    margin-left: 2em;
+    margin-bottom: .1em;
+}
+
+fieldset {
+    border: 1px solid #2f6fab;
+    margin: 1em 0 1em 0;
+    padding: 0 1em 1em;
+    line-height: 1.5em;
+}
+legend {
+    background: white;
+    padding: .5em;
+    font-size: 95%;
+}
+form {
+    border: none;
+    margin: 0;
+}
+
+textarea {
+    width: 100%;
+    padding: .1em;
+}
+
+input.historysubmit {
+    padding: 0 .3em .3em .3em !important;
+    font-size: 94%;
+    cursor: pointer;
+    height: 1.7em !important;
+    margin-left: 1.6em;
+}
+select {
+    vertical-align: top;
+}
+abbr, acronym, .explain {
+    border-bottom: 1px dotted black;
+    color: black;
+    background: none;
+    cursor: help;
+}
+q {
+    font-family: Times, "Times New Roman", serif;
+    font-style: italic;
+}
+/* disabled for now
+blockquote {
+    font-family: Times, "Times New Roman", serif;
+    font-style: italic;
+}*/
+code {
+    background-color: #f9f9f9;
+}
+pre {
+    padding: 1em;
+    border: 1px dashed #2f6fab;
+    color: black;
+    background-color: #f9f9f9;
+    line-height: 1.1em;
+}
+
+/*
+** the main content area
+*/
+
+#siteSub {
+    display: none;
+}
+#contentSub {
+    font-size: 84%;
+    line-height: 1.2em;
+    margin: 0 0 1.4em 1em;
+    color: #7d7d7d;
+    width: auto;
+}
+span.subpages {
+    display: block;
+}
+
+/* Some space under the headers in the content area */
+#bodyContent h1, #bodyContent h2 {
+    margin-bottom: .6em;
+}
+#bodyContent h3, #bodyContent h4, #bodyContent h5 {
+    margin-bottom: .3em;
+}
+.firstHeading {
+    margin-bottom: .1em;
+}
+
+/* user notification thing */
+.usermessage {
+    background-color: #ffce7b;
+    border: 1px solid #ffa500;
+    color: black;
+    font-weight: bold;
+    margin: 2em 0 1em;
+    padding: .5em 1em;
+    vertical-align: middle;
+}
+#siteNotice {
+    text-align: center;
+    font-size: 95%;
+    padding: 0 .9em;
+}
+#siteNotice p {
+    margin: 0;
+    padding: 0;
+}
+.error {
+    color: red;
+    font-size: larger;
+}
+#catlinks {
+    border: 1px solid #aaa;
+    background-color: #f9f9f9;
+    padding: 5px;
+    margin-top: 1em;
+    clear: both;
+}
+/* currently unused, intended to be used by a metadata box
+in the bottom-right corner of the content area */
+.documentDescription {
+    /* The summary text describing the document */
+    font-weight: bold;
+    display: block;
+    margin: 1em 0;
+    line-height: 1.5em;
+}
+.documentByLine {
+    text-align: right;
+    font-size: 90%;
+    clear: both;
+    font-weight: normal;
+    color: #76797c;
+}
+
+/* emulate center */
+.center {
+    width: 100%;
+    text-align: center;
+}
+*.center * {
+    margin-left: auto;
+    margin-right: auto;
+}
+/* small for tables and similar */
+.small, .small * {
+    font-size: 94%;
+}
+table.small {
+    font-size: 100%;
+}
+
+/*
+** content styles
+*/
+
+#toc,
+.toc {
+       border: 1px solid #aaa;
+       background-color: #f9f9f9;
+       padding: 5px;
+       font-size: 95%;
+}
+#toc h2,
+.toc h2 {
+       display: inline;
+       border: none;
+       padding: 0;
+       font-size: 100%;
+       font-weight: bold;
+}
+#toc #toctitle,
+.toc #toctitle,
+#toc .toctitle,
+.toc .toctitle {
+       text-align: center;
+}
+#toc ul,
+.toc ul {
+       list-style-type: none;
+       list-style-image: none;
+       margin-left: 0;
+       padding-left: 0;
+       text-align: left;
+}
+#toc ul ul,
+.toc ul ul {
+       margin: 0 0 0 2em;
+}
+#toc .toctoggle,
+.toc .toctoggle {
+       font-size: 94%;
+}
+
+
+/* images */
+div.floatright, table.floatright {
+    clear: right;
+    float: right;
+    position: relative;
+    margin: 0 0 .5em .5em;
+    border: 0;
+/*
+    border: .5em solid white;
+    border-width: .5em 0 .8em 1.4em;
+*/
+}
+div.floatright p { font-style: italic; }
+div.floatleft, table.floatleft {
+    float: left;
+    position: relative;
+    margin: 0 .5em .5em 0;
+    border: 0;
+/*
+    margin: .3em .5em .5em 0;
+    border: .5em solid white;
+    border-width: .5em 1.4em .8em 0;
+*/
+}
+div.floatleft p { font-style: italic; }
+/* thumbnails */
+div.thumb {
+    margin-bottom: .5em;
+    border-style: solid;
+    border-color: white;
+    width: auto;
+}
+div.thumb div {
+    border: 1px solid #ccc;
+    padding: 3px !important;
+    background-color: #f9f9f9;
+    font-size: 94%;
+    text-align: center;
+    overflow: hidden;
+}
+div.thumb div a img {
+    border: 1px solid #ccc;
+}
+div.thumb div div.thumbcaption {
+    border: none;
+    text-align: left;
+    line-height: 1.4em;
+    padding: .3em 0 .1em 0;
+}
+div.magnify {
+    float: right;
+    border: none !important;
+    background: none !important;
+}
+div.magnify a, div.magnify img {
+    display: block;
+    border: none !important;
+    background: none !important;
+}
+div.tright {
+    clear: right;
+    float: right;
+    border-width: .5em 0 .8em 1.4em;
+}
+div.tleft {
+    float: left;
+    margin-right: .5em;
+    border-width: .5em 1.4em .8em 0;
+}
+
+.hiddenStructure {
+    display: none;
+}
+img.tex {
+    vertical-align: middle;
+}
+span.texhtml {
+    font-family: serif;
+}
+
+/*
+** classes for special content elements like town boxes
+** intended to be referenced directly from the wiki src
+*/
+
+/*
+** User styles
+*/
+/* table standards */
+table.rimage {
+    float: right;
+    position: relative;
+    margin-left: 1em;
+    margin-bottom: 1em;
+    text-align: center;
+}
+.toccolours {
+    border: 1px solid #aaa;
+    background-color: #f9f9f9;
+    padding: 5px;
+    font-size: 95%;
+}
+div.townBox {
+    position: relative;
+    float: right;
+    background: white;
+    margin-left: 1em;
+    border: 1px solid gray;
+    padding: .3em;
+    width: 200px;
+    overflow: hidden;
+    clear: right;
+}
+div.townBox dl {
+    padding: 0;
+    margin: 0 0 .3em;
+    font-size: 96%;
+}
+div.townBox dl dt {
+    background: none;
+    margin: .4em 0 0;
+}
+div.townBox dl dd {
+    margin: .1em 0 0 1.1em;
+    background-color: #f3f3f3;
+}
+
+/*
+** edit views etc
+*/
+.special li {
+    line-height: 1.4em;
+    margin: 0;
+    padding: 0;
+}
+
+/* Page history styling */
+/* the auto-generated edit comments */
+.autocomment {
+    color: gray;
+}
+#pagehistory span.user {
+    margin-left: 1.4em;
+    margin-right: .4em;
+}
+#pagehistory span.minor {
+    font-weight: bold;
+}
+#pagehistory li {
+    border: 1px solid white;
+}
+#pagehistory li.selected {
+    background-color: #f9f9f9;
+    border: 1px dashed #aaa;
+}
+
+/*
+** Diff rendering
+*/
+table.diff, td.diff-otitle, td.diff-ntitle {
+    background-color: white;
+}
+td.diff-addedline {
+    background: #cfc;
+    font-size: smaller;
+}
+td.diff-deletedline {
+    background: #ffa;
+    font-size: smaller;
+}
+td.diff-context {
+    background: #eee;
+    font-size: smaller;
+}
+span.diffchange {
+    color: red;
+    font-weight: bold;
+}
+
+/*
+** keep the whitespace in front of the ^=, hides rule from konqueror
+** this is css3, the validator doesn't like it when validating as css2
+*/
+#bodyContent a[href ^="http://"],
+#bodyContent a[href ^="gopher://"] {
+    background: url(external.png) center right no-repeat;
+    padding-right: 13px;
+}
+#bodyContent a[href ^="https://"],
+.link-https {
+    background: url(lock_icon.gif) center right no-repeat;
+    padding-right: 16px;
+}
+#bodyContent a[href ^="mailto:"],
+.link-mailto {
+    background: url(mail_icon.gif) center right no-repeat;
+    padding-right: 18px;
+}
+#bodyContent a[href ^="news://"] {
+    background: url(news_icon.png) center right no-repeat;
+    padding-right: 18px;
+}
+#bodyContent a[href ^="ftp://"],
+.link-ftp {
+    background: url(file_icon.gif) center right no-repeat;
+    padding-right: 18px;
+}
+#bodyContent a[href ^="irc://"],
+.link-irc {
+    background: url(discussionitem_icon.gif) center right no-repeat;
+    padding-right: 18px;
+}
+/* disable interwiki styling */
+#bodyContent a.extiw,
+#bodyContent a.extiw:active {
+    color: #36b;
+    background: none;
+    padding: 0;
+}
+#bodyContent a.external {
+    color: #36b;
+}
+/* this can be used in the content area to switch off
+special external link styling */
+#bodyContent .plainlinks a {
+    background: none !important;
+    padding: 0;
+}
+/*
+** Structural Elements
+*/
+
+/*
+** general portlet styles (elements in the quickbar)
+*/
+.portlet {
+    border: none;
+    margin: 0 0 .5em;
+    padding: 0;
+    float: none;
+    width: 11.6em;
+    overflow: hidden;
+}
+.portlet h4 {
+    font-size: 95%;
+    font-weight: normal;
+    white-space: nowrap;
+}
+.portlet h5 {
+    background: transparent;
+    padding: 0 1em 0 .5em;
+    display: inline;
+    height: 1em;
+    text-transform: lowercase;
+    font-size: 91%;
+    font-weight: normal;
+    white-space: nowrap;
+}
+.portlet h6 {
+    background: #ffae2e;
+    border: 1px solid #2f6fab;
+    border-style: solid solid none solid;
+    padding: 0 1em 0 1em;
+    text-transform: lowercase;
+    display: block;
+    font-size: 1em;
+    height: 1.2em;
+    font-weight: normal;
+    white-space: nowrap;
+}
+.pBody {
+    font-size: 95%;
+    background-color: white;
+    color: black;
+    border-collapse: collapse;
+    border: 1px solid #aaa;
+    padding: 0 .8em .3em .5em;
+}
+.portlet h1,
+.portlet h2,
+.portlet h3,
+.portlet h4 {
+    margin: 0;
+    padding: 0;
+}
+.portlet ul {
+    line-height: 1.5em;
+    list-style-type: square;
+    list-style-image: url(bullet.gif);
+    font-size: 95%;
+}
+.portlet li {
+    padding: 0;
+    margin: 0;
+}
+
+/*
+** Logo properties
+*/
+
+#p-logo {
+    z-index: 3;
+    position: absolute; /*needed to use z-index */
+    top: 0;
+    left: 0;
+    height: 155px;
+    width: 12em;
+    overflow: visible;
+}
+#p-logo h5 {
+    display: none;
+}
+#p-logo a,
+#p-logo a:hover {
+    display: block;
+    height: 155px;
+    width: 12.2em;
+    background-repeat: no-repeat;
+    background-position: 35% 50% !important;
+    text-decoration: none;
+}
+
+/*
+** the navigation portlet
+*/
+
+#p-navigation {
+    position: relative;
+    z-index: 3;
+}
+
+/*
+** Search portlet
+*/
+#p-search {
+    position: relative;
+    z-index: 3;
+}
+#p-search .pBody {
+    text-align: center;
+}
+input.searchButton {
+    margin-top: 1px;
+    font-size: 95%;
+}
+#searchGoButton {
+    padding-left: .5em;
+    padding-right: .5em;
+    font-weight: bold;
+}
+#searchInput {
+    width: 10.9em;
+    margin: 0;
+    font-size: 95%;
+}
+#p-search .pBody {
+    padding: .5em .4em .4em .4em;
+}
+
+/*
+** the personal toolbar
+*/
+
+#p-personal {
+    width: 100%;
+    white-space: nowrap;
+    padding: 0;
+    margin: 0;
+    position: absolute;
+    left: 0;
+    top: 0;
+    z-index: 0;
+    border: none;
+    background: none;
+    overflow: visible;
+    line-height: 1.2em;
+}
+
+#p-personal h5 {
+    display: none;
+}
+#p-personal .portlet,
+#p-personal .pBody {
+    padding: 0;
+    margin: 0;
+    border: none;
+    z-index: 0;
+    overflow: visible;
+    background: none;
+}
+/* this is the ul contained in the portlet */
+#p-personal ul {
+    border: none;
+    line-height: 1.4em;
+    color: #2f6fab;
+    padding: 0 2em 0 3em;
+    margin: 0;
+    text-align: right;
+    text-transform: lowercase;
+    list-style: none;
+    z-index: 0;
+    background: none;
+}
+#p-personal li {
+    z-index: 0;
+    border: none;
+    padding: 0;
+    display: inline;
+    color: #2f6fab;
+    margin-left: 1em;
+    line-height: 1.2em;
+    background: none;
+}
+#p-personal li a {
+    text-decoration: none;
+    color: #005896;
+    padding-bottom: .2em;
+    background: none;
+}
+#p-personal li a:hover {
+    background-color: white;
+    padding-bottom: .2em;
+    text-decoration: none;
+}
+
+/* the icon in front of the user name, single quotes
+in bg url to hide it from iemac */
+li#pt-userpage,
+li#pt-anonuserpage,
+li#pt-login {
+    background: url(user.gif) top left no-repeat;
+    padding-left: 20px;
+    text-transform: none;
+}
+
+/*
+** the page-related actions- page/talk, edit etc
+*/
+#p-cactions {
+    position: absolute;
+    top: 1.3em;
+    left: 11.5em;
+    margin: 0;
+    white-space: nowrap;
+    width: 76%;
+    line-height: 1.1em;
+    overflow: visible;
+    background: none;
+    border-collapse: collapse;
+    padding-left: 1em;
+    list-style: none;
+    font-size: 95%;
+}
+#p-cactions .hiddenStructure {
+    display: none;
+}
+#p-cactions ul {
+    list-style: none;
+}
+#p-cactions li {
+    display: inline;
+    border: 1px solid #aaa;
+    border-bottom: none;
+    padding: 0 0 .1em 0;
+    margin: 0 .3em 0 0;
+    overflow: visible;
+    background: white;
+}
+#p-cactions li.selected {
+    border-color: #fabd23;
+    padding: 0 0 .2em 0;
+}
+#p-cactions li a {
+    background-color: white;
+    color: #002bb8;
+    border: none;
+    padding: 0 .8em .3em .8em;
+    text-decoration: none;
+    text-transform: lowercase;
+    position: relative;
+    z-index: 0;
+    margin: 0;
+}
+#p-cactions .selected a {
+    z-index: 3;
+}
+#p-cactions .new a {
+    color: #ba0000;
+}
+#p-cactions li a:hover {
+    z-index: 3;
+    text-decoration: none;
+}
+#p-cactions h5 {
+    display: none;
+}
+#p-cactions li.istalk {
+    margin-right: 0;
+}
+#p-cactions li.istalk a {
+    padding-right: .5em;
+}
+#p-cactions #ca-addsection a {
+    padding-left: .4em;
+    padding-right: .4em;
+}
+/* offsets to distinguish the tab groups */
+li#ca-talk {
+    margin-right: 1.6em;
+}
+li#ca-watch, li#ca-unwatch, li#ca-varlang-0, li#ca-print {
+    margin-left: 1.6em;
+}
+
+/*
+** the remaining portlets
+*/
+#p-tbx,
+#p-lang {
+    position: relative;
+    z-index: 3;
+}
+
+/*
+** footer
+*/
+#footer {
+    background-color: white;
+    border-top: 1px solid #fabd23;
+    border-bottom: 1px solid #fabd23;
+    margin: .6em 0 1em 0;
+    padding: .4em 0 1.2em 0;
+    text-align: center;
+    font-size: 90%;
+}
+#footer li {
+    display: inline;
+    margin: 0 1.3em;
+}
+/* hide from incapable browsers */
+head:first-child+body #footer li { white-space: nowrap; }
+#f-poweredbyico, #f-copyrightico {
+    margin: 0 8px;
+    position: relative;
+    top: -2px; /* Bump it up just a tad */
+}
+#f-poweredbyico {
+    float: right;
+    height: 1%;
+}
+#f-copyrightico {
+    float: left;
+    height: 1%;
+}
+
+/* js pref toc */
+#preftoc {
+    float: left;
+    margin: 1em;
+    width: 13em;
+}
+#preftoc li {
+    border: 1px solid white;
+}
+#preftoc li.selected {
+    background-color: #f9f9f9;
+    border: 1px dashed #aaa;
+}
+#preftoc a,
+#preftoc a:active {
+    display: block;
+    color: #0014a6;
+}
+#prefcontrol {
+    clear: both;
+    float: left;
+    margin-top: 1em;
+}
+div.prefsectiontip {
+    font-size: 95%;
+    margin-top: 1em;
+}
+fieldset.operaprefsection {
+    margin-left: 15em;
+}
+
+/*
+** IE/Mac fixes, hope to find a validating way to move this
+** to a separate stylesheet. This would work but doesn't validate:
+** @import("IEMacFixes.css");
+*/
+/* tabs: border on the a, not the div */
+* > html #p-cactions li { border: none; }
+* > html #p-cactions li a {
+    border: 1px solid #aaa;
+    border-bottom: none;
+}
+* > html #p-cactions li.selected a { border-color: #fabd23; }
+/* footer icons need a fixed width */
+* > html #f-poweredbyico,
+* > html #f-copyrightico { width: 88px; }
+* > html #bodyContent,
+* > html #bodyContent pre {
+    overflow-x: auto;
+    width: 100%;
+    padding-bottom: 25px;
+}
+
+/* more IE fixes */
+/* float/negative margin brokenness */
+* html #footer {margin-top: 0;}
+* html #column-content {
+    display: inline;
+    margin-bottom: 0;
+}
+* html div.editsection { font-size: smaller; }
+#pagehistory li.selected { position: relative; }
+
+/* Mac IE 5.0 fix; floated content turns invisible */
+* > html #column-content {
+    float: none;
+}
+* > html #column-one {
+    position: absolute;
+    left: 0;
+    top: 0;
+}
+* > html #footer {
+    margin-left: 13.2em;
+}
+.redirectText {
+    font-size: 150%;
+    margin: 5px;
+}
+
+.printfooter {
+    display: none;
+}
+
+.not-patrolled {
+    background-color: #ffa;
+}
+div.patrollink {
+    font-size: 75%;
+    text-align: right;
+}
+span.newpage, span.minor, span.searchmatch {
+    font-weight: bold;
+}
+span.unpatrolled {
+    font-weight: bold;
+    color: red;
+}
+
+span.searchmatch {
+    color: red;
+}
+.sharedUploadNotice {
+    font-style: italic;
+}
+
+span.updatedmarker {
+    color: black;
+    background-color: #0f0;
+}
+span.newpageletter {
+    font-weight: bold;
+    color: black;
+    background-color: yellow;
+}
+span.minoreditletter {
+    color: black;
+    background-color: #c5ffe6;
+}
+
+table.gallery {
+    border: 1px solid #ccc;
+    margin: 2px;
+    padding: 2px;
+    background-color: white;
+}
+
+table.gallery tr {
+    vertical-align: top;
+}
+
+table.gallery td {
+    vertical-align: top;
+    background-color: #f9f9f9;
+    border: solid 2px white;
+}
+
+div.gallerybox {
+    margin: 2px;
+    width:  150px;
+}
+
+div.gallerybox div.thumb {
+    text-align: center;
+    border: 1px solid #ccc;
+    margin: 2px;
+}
+
+div.gallerytext {
+    font-size: 94%;
+    padding: 2px 4px;
+}
+
+span.comment {
+       font-style: italic;
+}
+
+span.changedby {
+       font-size: 95%;
+}
+
+.previewnote {
+       text-align: center;
+       color: #cc0000;
+}
+.editExternally {
+       border: 1px solid gray;
+       background-color: #ffffff;
+       padding: 3px;
+       margin-top: 0.5em;
+       float: left;
+       font-size: small;
+       text-align: center;
+}
+.editExternallyHelp {
+       font-style: italic;
+       color: gray;
+}
+
+li span.deleted {
+       text-decoration: line-through;
+       color: #888;
+       font-style: italic;
+}
+
+.toggle {
+       margin-left: 2em;
+       text-indent: -2em;
+}
+
+/* Classes for EXIF data display */
+table.metadata {
+       font-size: 0.8em;
+       margin-left: 0.5em;
+       margin-bottom: 0.5em;
+}
+
+table.metadata caption {
+       font-weight: bold;
+}
+
+table.metadata th {
+       font-weight: normal;
+}
+
+table.metadata td {
+       padding: 0.1em;
+}
+
+table.metadata {
+       border: none;
+       border-collapse: collapse;
+}
+
+table.metadata td, table.metadata th {
+       text-align: center;
+       border: 1px solid #aaaaaa;
+       padding-left: 0.1em;
+       padding-right: 0.1em;
+}
+
+table.metadata th {
+       background-color: #f9f9f9;
+}
+
+table.metadata td {
+       background-color: #fcfcfc;
+}
+
+/* filetoc */
+ul#filetoc {
+       text-align: center;
+       border: 1px solid #aaaaaa;
+       background-color: #f9f9f9;
+       padding: 5px;
+       font-size: 95%;
+       margin-bottom: 0.5em;
+       margin-left: 0;
+       margin-right: 0;
+}
+
+#filetoc li {
+       display: inline;
+       list-style-type: none;
+       padding-right: 2em;
+}
+
+/* @bug 1714 */
+input#wpSave, input#wpDiff {
+       margin-right: 0.33em;
+}
+
+
+/* Classes for article validation */
+
+table.revisionform_default {
+       border: 1px solid #000000;
+}
+
+table.revisionform_focus {
+       border: 1px solid #000000;
+       background-color:#00BBFF;
+}
+
+tr.revision_tr_default {
+       background-color:#EEEEEE;
+}
+
+tr.revision_tr_first {
+       background-color:#DDDDDD;
+}
+
+p.revision_saved {
+       color: green;
+       font-weight:bold;
+}
+
+#mw_trackbacks {
+       border: solid 1px #bbbbff;
+       background-color: #eeeeff;
+       padding: 0.2em;
+}
+
+
+/* Allmessages table */
+
+#allmessagestable th {
+       background-color: #b2b2ff;
+}
+
+#allmessagestable tr.orig {
+       background-color: #ffe2e2;
+}
+
+#allmessagestable tr.new {
+       background-color: #e2ffe2;
+}
+
+#allmessagestable tr.def {
+       background-color: #f0f0ff;
+}
+
diff --git a/skins/monobook/news_icon.png b/skins/monobook/news_icon.png
new file mode 100644 (file)
index 0000000..dd1541d
Binary files /dev/null and b/skins/monobook/news_icon.png differ
diff --git a/skins/monobook/required.gif b/skins/monobook/required.gif
new file mode 100644 (file)
index 0000000..bd71976
Binary files /dev/null and b/skins/monobook/required.gif differ
diff --git a/skins/monobook/rtl.css b/skins/monobook/rtl.css
new file mode 100644 (file)
index 0000000..fbd1976
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+Right-to-left fixes for MonoBook.
+Places sidebar on right, tweaks various alignment issues.
+
+Works mostly ok nicely on Safari 1.2.1; fine in Mozilla.
+
+Safari bugs (1.2.1):
+* Tabs are still appearing in left-to-right order. (Try after localizing)
+
+Opera bugs (7.23 linux):
+* Some bits of ltr text (sidebar box titles) have forward and backward versions overlapping each other
+
+IE/mac bugs:
+* The thing barfs on Hebrew and Arabic anyway, so no point testing.
+
+Missing features due to lack of support:
+* external link icons, icon next to user name
+
+To test:
+* Opera6
+* IE 5.0
+* etc
+
+*/
+body {
+    direction: rtl;
+/*    unicode-bidi: bidi-override;*/
+    unicode-bidi: embed;
+}
+#column-content {
+       margin: 0 -12.2em 0 0;
+        float: left;
+}
+#column-content #content{
+       margin-left: 0;
+       margin-right: 12.2em;
+    border-right: 1px solid #aaaaaa;
+    border-left: none;
+}
+html>body .portlet {
+    float: right;
+    clear: right;
+}
+/* recover IEMac (might be fine with the float, but usually it's close to IE */
+*>body .portlet {
+    float: none;
+    clear: none;
+}
+.pBody {
+    padding-right: 0.8em;
+    padding-left: 0.5em;
+}
+
+/* Fix alignment */
+.documentByLine,
+.portletDetails,
+.portletMore,
+#p-personal {
+       text-align: left;
+}
+
+div div.thumbcaption {
+       text-align: right;
+}
+
+div.magnify,
+#div.townBox,
+#p-logo {
+       left: auto;
+       right: 0;
+}
+#p-personal {
+       left: auto;
+       right: 0;
+}
+
+#p-cactions {
+       left: auto;
+       right: 11.5em;
+        padding-left: 0;
+        padding-right: 1em;
+}
+#p-cactions li {
+    margin-left: 0.3em;
+    margin-right: 0;
+    float: right;
+}
+* html #p-cactions li a {
+    display: block;
+    padding-bottom: 0;
+}
+* html #p-cactions li a:hover {
+    padding-bottom: 0.2em;
+}
+/* offsets to distinguish the tab groups */
+li#ca-talk {
+    margin-right: auto;
+    margin-left: 1.6em;
+}
+li#ca-watch,li#ca-unwatch {
+    margin-right: 1.6em !important;
+}
+
+/* Fix margins */
+/* top right bottom left */
+
+ul {
+       margin-left: 0;
+       margin-right: 1.5em;
+}
+ol {
+       margin-left: 0;
+       margin-right: 2.4em;
+}
+dd {
+       margin-left: 0;
+       margin-right: 1.6em;
+}
+#contentSub {
+       margin-right: 1em;
+       margin-left: 0;
+}
+.tocindent {
+       margin-left: 0;
+       margin-right: 2em;
+}
+div.tright {
+    clear: none;
+}
+div.tleft {
+    clear: left;
+}
+div.floatright, table.floatright {
+    clear: none;
+}
+div.floatleft, table.floatleft {
+    clear: left;
+}
+div.townBox {
+       margin-left: 0;
+       margin-right: 1em;
+}
+div.townBox dl dd {
+       margin-left: 0;
+       margin-right: 1.1em;
+}
+#p-personal li {
+       margin-left: 0;
+       margin-right: 1em;
+}
+
+li#ca-talk,
+li#ca-watch {
+       margin-right: auto;
+       margin-left: 1.6em;
+}
+
+#p-personal li {
+    float: left;
+}
+/* Fix link icons */
+li#pt-userpage,
+li#pt-anonuserpage,
+li#pt-login {
+       background: none;
+       padding-left: 0;
+}
+.external {
+    padding: 0 !important;
+    background: none !important;
+}
+#footer {
+    clear: both;
+}
+* html #footer {
+    margin-left: 0;
+    margin-right: 13.6em;
+    border-left: 0;
+    border-right: 1px solid #fabd23;
+} 
+* html #column-content { 
+    float: none;
+    margin-left: 0;
+    margin-right: 0;
+}
+* html #column-content #content {
+    margin-left: 0;
+    margin-top: 3em;
+}
+* html #column-one { right: 0; }
+
+/* js pref toc */
+#preftoc { float: right; }
+/* workaround for moz bug, displayed bullets on left side */
+#preftoc li { list-style: none; }
+#prefcontrol { float: right; }
+fieldset.prefsection,
+fieldset.operaprefsection { 
+    margin-left: 0 !important;
+    margin-right: 15em;
+}
+
+#toc ul {
+    text-align: right;
+}
+
+#toc ul ul {
+    margin: 0 2em 0 0;
+}
+
+input#wpSave, input#wpDiff {
+       margin-right: 0;
+       margin-left: 0.33em;
+}
+
diff --git a/skins/monobook/user.gif b/skins/monobook/user.gif
new file mode 100644 (file)
index 0000000..bc93439
Binary files /dev/null and b/skins/monobook/user.gif differ
diff --git a/skins/monobook/wiki-indexed.png b/skins/monobook/wiki-indexed.png
new file mode 100644 (file)
index 0000000..189a2ae
Binary files /dev/null and b/skins/monobook/wiki-indexed.png differ
diff --git a/skins/monobook/wiki.png b/skins/monobook/wiki.png
new file mode 100644 (file)
index 0000000..69fce98
Binary files /dev/null and b/skins/monobook/wiki.png differ
diff --git a/skins/myskin/main.css b/skins/myskin/main.css
new file mode 100644 (file)
index 0000000..f3ab020
--- /dev/null
@@ -0,0 +1 @@
+/* this file must be empty */
diff --git a/skins/simple/discussionitem_icon.gif b/skins/simple/discussionitem_icon.gif
new file mode 100644 (file)
index 0000000..baec471
Binary files /dev/null and b/skins/simple/discussionitem_icon.gif differ
diff --git a/skins/simple/external.png b/skins/simple/external.png
new file mode 100644 (file)
index 0000000..419c06f
Binary files /dev/null and b/skins/simple/external.png differ
diff --git a/skins/simple/file_icon.gif b/skins/simple/file_icon.gif
new file mode 100644 (file)
index 0000000..847f648
Binary files /dev/null and b/skins/simple/file_icon.gif differ
diff --git a/skins/simple/link_icon.gif b/skins/simple/link_icon.gif
new file mode 100644 (file)
index 0000000..815ccb1
Binary files /dev/null and b/skins/simple/link_icon.gif differ
diff --git a/skins/simple/lock_icon.gif b/skins/simple/lock_icon.gif
new file mode 100644 (file)
index 0000000..8a87e28
Binary files /dev/null and b/skins/simple/lock_icon.gif differ
diff --git a/skins/simple/mail_icon.gif b/skins/simple/mail_icon.gif
new file mode 100644 (file)
index 0000000..50a87a9
Binary files /dev/null and b/skins/simple/mail_icon.gif differ
diff --git a/skins/simple/main.css b/skins/simple/main.css
new file mode 100644 (file)
index 0000000..ff07603
--- /dev/null
@@ -0,0 +1,397 @@
+#toolbar {
+  display: none;
+}
+
+div.center {
+  text-align: center;
+}
+
+#contentSub {
+  padding-left: 2em;
+}
+
+a {
+  text-decoration: none;
+}
+
+a:hover {
+  text-decoration: underline;
+}
+
+#column-content {
+  width: 100%;
+  float: right;
+  margin: 0 0 0.6em -12.2em;
+  padding:0;
+}
+
+#content {
+    margin: 0em 0 0 12.2em;
+    padding: 0em 1em 1.5em 1em;
+    border-left: 1px solid #959595;
+    line-height: 1.5em;
+}
+
+#column-one {
+  position: absolute;
+  top: 0px; left: 0px;
+}
+
+#footer {
+       display: none;
+}
+
+body {
+    margin: 0;
+    padding: 0;
+}
+
+#globalWrapper {
+  width: 100%;
+  height: 100%;
+  margin: 0;
+  padding: 0;
+}
+.visualClear { clear: both; }
+
+img {
+    border: none;
+}
+p {
+    margin: 0.4em 0em 0.5em 0em;
+    line-height: 1.5em;
+}
+p img { margin: 0; }
+
+h1, h2, h3, h4, h5, h6 {
+    margin: 0;
+    padding-top: 0.5em;
+    padding-bottom: 0.17em;
+}
+fieldset {
+    margin: 1em 0em 1em 0em;
+    padding: 0em 1em 1em 1em;
+}
+.usermessage {
+    background-color: #ffce7b;
+    border: 1px solid #ffa500;
+    color: Black;
+    font-weight: bold;
+    margin: 2em 0em 1em 0em;
+    padding: 0.5em 1em;
+    vertical-align: middle;
+}
+.error {
+    color: red;
+    font-size: larger;
+}
+
+table.rimage {
+    float:right;
+    position:relative;
+    margin-left:1em;
+    margin-bottom:1em;
+    text-align:center;
+}
+
+div.townBox {
+    position:relative;
+    float:right;
+    margin-left:1em;
+    padding:0.3em;
+    width: 200px;
+    overflow: hidden;
+    clear: right;
+}
+div.townBox dl {
+    padding: 0;
+    margin: 0 0 0.3em 0;
+}
+div.townBox dl dt {
+    background: none;
+    margin: 0.4em 0 0 0;
+}
+div.townBox dl dd {
+    margin: 0.1em 0 0 1.1em;
+}
+.portlet {
+    border: none;
+    float: none;
+    padding: 0;
+    width: 11.8em;
+    overflow: hidden;
+}
+.portlet h4 {
+    font-weight: normal;
+    white-space: nowrap;
+}
+.portlet h5 {
+  padding: 0em 1em 0em 0.5em;
+  display: inline;
+  height: 1em;
+  font-weight: normal;
+  white-space: nowrap;
+}
+.portlet h6 {
+    padding: 0em 1em 0em 1em;
+    display: block;
+    height: 1.2em;
+    font-weight: normal;
+    white-space: nowrap;
+}
+.pBody {
+    border-collapse: collapse;
+    padding: 0 0.8em 0.3em 0.5em;
+}
+.portlet h1,
+.portlet h2,
+.portlet h3,
+.portlet h4 {
+  margin: 0;
+  padding: 0;
+  font-size: small;
+}
+
+#p-search .pBody {
+    text-align: center;
+}
+
+#searchInput {
+  width: 100%;
+  clear: both;
+  margin: 0 0 0 0;
+}
+
+input.searchButton {
+    margin-top:1px;
+    padding: 0 0.4em;
+    cursor: pointer;
+}
+
+#p-search .pBody {
+    padding: 0.5em 0.4em 0.4em 0.4em;
+}
+
+textarea {
+  width: 100%;
+}
+
+#p-personal li, #p-personal ul,
+#p-tb li, #p-tb ul,
+#p-navigation li, #p-navigation ul,
+#p-cactions li, #p-cactions ul,
+#p-newlinks li, #p-newlinks ul {
+  padding-left: 0em;
+  margin-left: 0.5em;
+}
+
+#p-cactions li, #p-cactions ul {
+  margin-left: 0.7em;
+}
+
+pre {
+  margin: 2em;
+  border: solid 1px black;
+}
+
+h1.firstHeading, h2 {
+  border-bottom: solid 1px black;
+}
+#bodyContent a[href ^="http://"],
+#bodyContent a[href ^="gopher://"] {
+    background: url("external.png") center right no-repeat;
+    padding-right: 13px;
+}
+#bodyContent a[href ^="https://"],
+.link-https {
+    background: url("lock_icon.gif") center right no-repeat;
+    padding-right: 16px;
+}
+#bodyContent a[href ^="mailto:"],
+.link-mailto {
+    background: url("mail_icon.gif") center right no-repeat;
+    padding-right: 18px;
+}
+#bodyContent a[href ^="news://"] {
+    background: url("news_icon.png") center right no-repeat;
+    padding-right: 18px;
+}
+#bodyContent a[href ^="ftp://"],
+.link-ftp {
+    background: url("file_icon.gif") center right no-repeat;
+    padding-right: 18px;
+}
+#bodyContent a[href ^="irc://"],
+.link-irc {
+    background: url("discussionitem_icon.gif")  center right no-repeat;
+    padding-right: 18px;
+}
+
+#bodyContent a.extiw,
+#bodyContent a.extiw:active {
+  color: #5E7CFF;
+  background: none;
+  padding: 0;
+}
+
+td.diff-addedline {
+    background-color: #B9FFB0;
+}
+
+td.diff-deletedline {
+    background-color: #f8ffaa;
+}
+
+span.diffchange { background-color: #FFCDF3; }
+.autocomment { color:  grey; }
+#pagehistory span.user {
+    margin-left: 1.4em;
+    margin-right: 0.4em;
+}
+#pagehistory span.minor { font-weight: bold; }
+#pagehistory li.selected {
+    background-color:#f9f9f9;
+    border:1px dashed #aaaaaa;
+}
+span.urlexpansion {
+  display: none;
+}
+
+div.tocindent {
+  margin-left: 2em;
+}
+#toc {
+  text-align: left;
+  border-top: solid 1px black;
+  border-bottom: solid 1px black;
+}
+
+div.floatright, table.floatright {
+    clear: right;
+    float: right;
+    margin: 0;
+    position: relative;
+    border-width: 0.5em 0 0.8em 1.4em;
+}
+div.floatright p { font-style: italic; }
+div.floatleft, table.floatleft {
+    float: left;
+    margin: 0.3em 0.5em 0.5em 0;
+    position: relative;
+    border-width: 0.5em 1.4em 0.8em 0;
+}
+div.floatleft p { font-style: italic; }
+/* thumbnails */
+div.thumb {
+    margin-bottom: 0.5em;
+    width: auto;
+}
+div.thumb div {
+    padding: 3px !important;
+    text-align: center;
+    overflow: hidden;
+}
+
+div.thumb div div.thumbcaption {
+    border: none;
+    text-align: left;
+    line-height: 1.4;
+    padding: 0.3em 0 0.1em 0;
+}
+div.magnify {
+    float: right;
+    border: none !important;
+    background: none !important;
+}
+div.magnify a, div.magnify img {
+    display: block;
+    border: none !important;
+    background: none !important;
+}
+div.tright {
+    clear: right;
+    float: right;
+    border-width: 0.5em 0 0.8em 1.4em;
+}
+div.tleft {
+    float: left;
+    margin-right:0.5em;
+    border-width: 0.5em 1.4em 0.8em 0;
+}
+
+a.stub { color: #772233; }
+a.new,
+#p-personal a.new {
+       text-decoration: line-through;
+}
+li.new {
+       text-decoration: line-through;
+}
+p.catlinks {
+  text-align: center;
+  width: 80%;
+  margin-left: auto;
+  margin-right: auto;
+  padding: 3px;
+}
+
+#mytabs {
+  background-color: inherit;
+}
+#p-cactions {
+  background-color: inherit;
+}
+div.printfooter {
+  display: none;
+}
+
+
+#ca-addsection a:before {
+  content: "Add section";
+  font-size: 10pt;
+}
+
+#ca-addsection a {
+  font-size: 0px;
+}
+
+#n-portal,
+#n-currentevents,
+#n-help,
+#n-sitesupport {
+  display: none;
+}
+
+span.searchmatch {
+  font-weight: bold;
+}
+
+#preftoc {
+    float: left;
+    margin: 1em;
+    width: 13em;
+}
+#preftoc li {
+}
+#preftoc li.selected {
+    border: 1px dashed #aaa;
+}
+#preftoc a,
+#preftoc a:active {
+    display: block;
+}
+#prefcontrol {
+    clear: both;
+    float: left;
+    margin-top: 1em;
+}
+div.prefsectiontip {
+    font-size: 95%;
+    margin-top: 1em;
+}
+
+#mw_trackbacks {
+       border-style: groove;
+       padding: 0.2em;
+}
+
diff --git a/tests/.cvsignore b/tests/.cvsignore
new file mode 100644 (file)
index 0000000..20cb61e
--- /dev/null
@@ -0,0 +1,6 @@
+LocalTestSettings.php
+*~
+bin
+.classpath
+.project
+project.index
diff --git a/tests/.htaccess b/tests/.htaccess
new file mode 100644 (file)
index 0000000..3a42882
--- /dev/null
@@ -0,0 +1 @@
+Deny from all
diff --git a/tests/ArticleTest.php b/tests/ArticleTest.php
new file mode 100644 (file)
index 0000000..953fd43
--- /dev/null
@@ -0,0 +1,150 @@
+<?php
+
+require_once( 'PHPUnit.php' );
+require_once( '../includes/Defines.php' );
+require_once( '../includes/Article.php' );
+
+class ArticleTest extends PHPUnit_TestCase {
+       var $saveGlobals = array();
+       
+       function ArticleTest( $name ) {
+               $this->PHPUnit_TestCase( $name );
+       }
+       
+       function setUp() {
+               $globalSet = array(
+                       'wgLegacyEncoding' => false,
+                       'wgUseLatin1' => false,
+                       'wgCompressRevisions' => false,
+                       'wgInputEncoding' => 'utf-8',
+                       'wgOutputEncoding' => 'utf-8' );
+               foreach( $globalSet as $var => $data ) {
+                       $this->saveGlobals[$var] = $GLOBALS[$var];
+                       $GLOBALS[$var] = $data;
+               }
+       }
+       
+       function tearDown() {
+               foreach( $this->saveGlobals as $var => $data ) {
+                       $GLOBALS[$var] = $data;
+               }
+       }
+       
+       function testGetRevisionText() {
+               $row = new stdClass;
+               $row->old_flags = '';
+               $row->old_text = 'This is a bunch of revision text.';
+               $this->assertEquals(
+                       'This is a bunch of revision text.',
+                       Revision::getRevisionText( $row ) );
+       }
+       
+       function testGetRevisionTextGzip() {
+               $row = new stdClass;
+               $row->old_flags = 'gzip';
+               $row->old_text = gzdeflate( 'This is a bunch of revision text.' );
+               $this->assertEquals(
+                       'This is a bunch of revision text.',
+                       Revision::getRevisionText( $row ) );
+       }
+       
+       function testGetRevisionTextUtf8Native() {
+               $row = new stdClass;
+               $row->old_flags = 'utf-8';
+               $row->old_text = "Wiki est l'\xc3\xa9cole superieur !";
+               $GLOBALS['wgLegacyEncoding'] = 'iso-8859-1';
+               $this->assertEquals(
+                       "Wiki est l'\xc3\xa9cole superieur !",
+                       Revision::getRevisionText( $row ) );
+       }
+       
+       function testGetRevisionTextUtf8Legacy() {
+               $row = new stdClass;
+               $row->old_flags = '';
+               $row->old_text = "Wiki est l'\xe9cole superieur !";
+               $GLOBALS['wgLegacyEncoding'] = 'iso-8859-1';
+               $this->assertEquals(
+                       "Wiki est l'\xc3\xa9cole superieur !",
+                       Revision::getRevisionText( $row ) );
+       }
+       
+       function testGetRevisionTextUtf8NativeGzip() {
+               $row = new stdClass;
+               $row->old_flags = 'gzip,utf-8';
+               $row->old_text = gzdeflate( "Wiki est l'\xc3\xa9cole superieur !" );
+               $GLOBALS['wgLegacyEncoding'] = 'iso-8859-1';
+               $this->assertEquals(
+                       "Wiki est l'\xc3\xa9cole superieur !",
+                       Revision::getRevisionText( $row ) );
+       }
+       
+       function testGetRevisionTextUtf8LegacyGzip() {
+               $row = new stdClass;
+               $row->old_flags = 'gzip';
+               $row->old_text = gzdeflate( "Wiki est l'\xe9cole superieur !" );
+               $GLOBALS['wgLegacyEncoding'] = 'iso-8859-1';
+               $this->assertEquals(
+                       "Wiki est l'\xc3\xa9cole superieur !",
+                       Revision::getRevisionText( $row ) );
+       }
+       
+       function testCompressRevisionTextUtf8() {
+               $row->old_text = "Wiki est l'\xc3\xa9cole superieur !";
+               $row->old_flags = Revision::compressRevisionText( $row->old_text );
+               $this->assertTrue( false !== strpos( $row->old_flags, 'utf-8' ),
+                       "Flags should contain 'utf-8'" );
+               $this->assertFalse( false !== strpos( $row->old_flags, 'gzip' ),
+                       "Flags should not contain 'gzip'" );
+               $this->assertEquals( "Wiki est l'\xc3\xa9cole superieur !",
+                       $row->old_text, "Direct check" );
+               $this->assertEquals( "Wiki est l'\xc3\xa9cole superieur !",
+                       Revision::getRevisionText( $row ), "getRevisionText" );
+       }
+
+       function testCompressRevisionTextLatin1() {
+               $GLOBALS['wgUseLatin1'] = true;
+               $row->old_text = "Wiki est l'\xe9cole superieur !";
+               $row->old_flags = Revision::compressRevisionText( $row->old_text );
+               $this->assertFalse( false !== strpos( $row->old_flags, 'utf-8' ),
+                       "Flags should not contain 'utf-8'" );
+               $this->assertFalse( false !== strpos( $row->old_flags, 'gzip' ),
+                       "Flags should not contain 'gzip'" );
+               $this->assertEquals( "Wiki est l'\xe9cole superieur !",
+                       $row->old_text, "Direct check" );
+               $this->assertEquals( "Wiki est l'\xe9cole superieur !",
+                       Revision::getRevisionText( $row ), "getRevisionText" );
+       }
+       
+       function testCompressRevisionTextUtf8Gzip() {
+               $GLOBALS['wgCompressRevisions'] = true;
+               $row->old_text = "Wiki est l'\xc3\xa9cole superieur !";
+               $row->old_flags = Revision::compressRevisionText( $row->old_text );
+               $this->assertTrue( false !== strpos( $row->old_flags, 'utf-8' ),
+                       "Flags should contain 'utf-8'" );
+               $this->assertTrue( false !== strpos( $row->old_flags, 'gzip' ),
+                       "Flags should contain 'gzip'" );
+               $this->assertEquals( "Wiki est l'\xc3\xa9cole superieur !",
+                       gzinflate( $row->old_text ), "Direct check" );
+               $this->assertEquals( "Wiki est l'\xc3\xa9cole superieur !",
+                       Revision::getRevisionText( $row ), "getRevisionText" );
+       }
+
+       function testCompressRevisionTextLatin1Gzip() {
+               $GLOBALS['wgCompressRevisions'] = true;
+               $GLOBALS['wgUseLatin1'] = true;
+               $row = new stdClass;
+               $row->old_text = "Wiki est l'\xe9cole superieur !";
+               $row->old_flags = Revision::compressRevisionText( $row->old_text );
+               $this->assertFalse( false !== strpos( $row->old_flags, 'utf-8' ),
+                       "Flags should not contain 'utf-8'" );
+               $this->assertTrue( false !== strpos( $row->old_flags, 'gzip' ),
+                       "Flags should contain 'gzip'" );
+               $this->assertEquals( "Wiki est l'\xe9cole superieur !",
+                       gzinflate( $row->old_text ), "Direct check" );
+               $this->assertEquals( "Wiki est l'\xe9cole superieur !",
+                       Revision::getRevisionText( $row ), "getRevisionText" );
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/tests/DatabaseTest.php b/tests/DatabaseTest.php
new file mode 100644 (file)
index 0000000..8a16cb2
--- /dev/null
@@ -0,0 +1,93 @@
+<?php
+
+require_once( 'PHPUnit.php' );
+require_once( '../includes/Defines.php' );
+require_once( '../includes/Database.php' );
+require_once( '../includes/GlobalFunctions.php' );
+
+class DatabaseTest extends PHPUnit_TestCase {
+       var $db;
+       
+       function DatabaseTest( $name ) {
+               $this->PHPUnit_TestCase( $name );
+       }
+       
+       function setUp() {
+               $this->db =& new Database();
+       }
+       
+       function tearDown() {
+               unset( $this->db );
+       }
+       
+       function testAddQuotesNull() {
+               $this->assertEquals(
+                       'NULL',
+                       $this->db->addQuotes( NULL ) );
+       }
+       
+       function testAddQuotesInt() {
+               # returning just "1234" should be ok too, though...
+               # maybe
+               $this->assertEquals(
+                       "'1234'",
+                       $this->db->addQuotes( 1234 ) );
+       }
+       
+       function testAddQuotesFloat() {
+               # returning just "1234.5678" would be ok too, though
+               $this->assertEquals(
+                       "'1234.5678'",
+                       $this->db->addQuotes( 1234.5678 ) );
+       }
+
+       function testAddQuotesString() {
+               $this->assertEquals(
+                       "'string'",
+                       $this->db->addQuotes( 'string' ) );
+       }
+       
+       function testAddQuotesStringQuote() {
+               $this->assertEquals(
+                       "'string\'s cause trouble'",
+                       $this->db->addQuotes( "string's cause trouble" ) );
+       }
+
+       function testFillPreparedEmpty() {
+               $sql = $this->db->fillPrepared(
+                       'SELECT * FROM interwiki', array() );
+               $this->assertEquals(
+                       "SELECT * FROM interwiki",
+                       $sql);
+       }
+       
+       function testFillPreparedQuestion() {
+               $sql = $this->db->fillPrepared(
+                       'SELECT * FROM cur WHERE cur_namespace=? AND cur_title=?',
+                       array( 4, "Snicker's_paradox" ) );
+               $this->assertEquals(
+                       "SELECT * FROM cur WHERE cur_namespace='4' AND cur_title='Snicker\'s_paradox'",
+                       $sql);
+       }
+       
+       function testFillPreparedBang() {
+               $sql = $this->db->fillPrepared(
+                       'SELECT user_id FROM ! WHERE user_name=?',
+                       array( '"user"', "Slash's Dot" ) );
+               $this->assertEquals(
+                       "SELECT user_id FROM \"user\" WHERE user_name='Slash\'s Dot'",
+                       $sql);
+       }
+
+       function testFillPreparedRaw() {
+               $sql = $this->db->fillPrepared(
+                       "SELECT * FROM cur WHERE cur_title='This_\\&_that,_WTF\\?\\!'",
+                       array( '"user"', "Slash's Dot" ) );
+               $this->assertEquals(
+                       "SELECT * FROM cur WHERE cur_title='This_&_that,_WTF?!'",
+                       $sql);
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/tests/GlobalTest.php b/tests/GlobalTest.php
new file mode 100644 (file)
index 0000000..b0ed0f5
--- /dev/null
@@ -0,0 +1,185 @@
+<?php
+
+require_once( 'PHPUnit.php' );
+require_once( '../includes/Defines.php' );
+require_once( '../includes/Profiling.php' );
+require_once( '../includes/GlobalFunctions.php' );
+
+class GlobalTest extends PHPUnit_TestCase {
+       function GlobalTest( $name ) {
+               $this->PHPUnit_TestCase( $name );
+       }
+       
+       function setUp() {
+               $this->save = array();
+               $saveVars = array( 'wgReadOnlyFile' );
+               foreach( $saveVars as $var ) {
+                       if( isset( $GLOBALS[$var] ) ) {
+                               $this->save[$var] = $GLOBALS[$var];
+                       }
+               }
+               $GLOBALS['wgReadOnlyFile'] = wfTempDir() . '/testReadOnly-' . mt_rand();
+       }
+       
+       function tearDown() {
+               foreach( $this->save as $var => $data ) {
+                       $GLOBALS[$var] = $data;
+               }
+       }
+       
+       function testRandom() {
+               # This could hypothetically fail, but it shouldn't ;)
+               $this->assertFalse(
+                       wfRandom() == wfRandom() );
+       }
+       
+       function testUrlencode() {
+               $this->assertEquals(
+                       "%E7%89%B9%E5%88%A5:Contributions/Foobar",
+                       wfUrlencode( "\xE7\x89\xB9\xE5\x88\xA5:Contributions/Foobar" ) );
+       }
+       
+       function testReadOnlyEmpty() {
+               $this->assertFalse( wfReadOnly() );
+       }
+       
+       function testReadOnlySet() {
+               $f = fopen( $GLOBALS['wgReadOnlyFile'], "wt" );
+               fwrite( $f, 'Message' );
+               fclose( $f );
+               $this->assertTrue( wfReadOnly() );
+               
+               unlink( $GLOBALS['wgReadOnlyFile'] );
+               $this->assertFalse( wfReadOnly() );
+       }
+       
+       function testQuotedPrintable() {
+               $this->assertEquals(
+                       "=?UTF-8?Q?=C4=88u=20legebla=3F?=",
+                       wfQuotedPrintable( "\xc4\x88u legebla?", "UTF-8" ) );
+       }
+       
+       function testTime() {
+               $start = wfTime();
+               $this->assertType( 'double', $start );
+               $end = wfTime();
+               $this->assertTrue( $end > $start, "Time is running backwards!" );
+       }
+       
+       function testArrayToCGI() {
+               $this->assertEquals(
+                       "baz=AT%26T&foo=bar",
+                       wfArrayToCGI(
+                               array( 'baz' => 'AT&T', 'ignore' => '' ),
+                               array( 'foo' => 'bar', 'baz' => 'overridden value' ) ) );
+       }
+       
+       function testMimeTypeMatch() {
+               $this->assertEquals(
+                       'text/html',
+                       mimeTypeMatch( 'text/html',
+                               array( 'application/xhtml+xml' => 1.0,
+                                      'text/html'             => 0.7,
+                                      'text/plain'            => 0.3 ) ) );
+               $this->assertEquals(
+                       'text/*',
+                       mimeTypeMatch( 'text/html',
+                               array( 'image/*' => 1.0,
+                                      'text/*'  => 0.5 ) ) );
+               $this->assertEquals(
+                       '*/*',
+                       mimeTypeMatch( 'text/html',
+                               array( '*/*' => 1.0 ) ) );
+               $this->assertNull(
+                       mimeTypeMatch( 'text/html',
+                               array( 'image/png'     => 1.0,
+                                      'image/svg+xml' => 0.5 ) ) );
+       }
+       
+       function testNegotiateType() {
+               $this->assertEquals(
+                       'text/html',
+                       wfNegotiateType(
+                               array( 'application/xhtml+xml' => 1.0,
+                                      'text/html'             => 0.7,
+                                      'text/plain'            => 0.5,
+                                      'text/*'                => 0.2 ),
+                               array( 'text/html'             => 1.0 ) ) );
+               $this->assertEquals(
+                       'application/xhtml+xml',
+                       wfNegotiateType(
+                               array( 'application/xhtml+xml' => 1.0,
+                                      'text/html'             => 0.7,
+                                      'text/plain'            => 0.5,
+                                      'text/*'                => 0.2 ),
+                               array( 'application/xhtml+xml' => 1.0,
+                                      'text/html'             => 0.5 ) ) );
+               $this->assertEquals(
+                       'text/html',
+                       wfNegotiateType(
+                               array( 'text/html'             => 1.0,
+                                      'text/plain'            => 0.5,
+                                      'text/*'                => 0.5,
+                                      'application/xhtml+xml' => 0.2 ),
+                               array( 'application/xhtml+xml' => 1.0,
+                                      'text/html'             => 0.5 ) ) );
+               $this->assertEquals(
+                       'text/html',
+                       wfNegotiateType(
+                               array( 'text/*'                => 1.0,
+                                      'image/*'               => 0.7,
+                                      '*/*'                   => 0.3 ),
+                               array( 'application/xhtml+xml' => 1.0,
+                                      'text/html'             => 0.5 ) ) );
+               $this->assertNull(
+                       wfNegotiateType(
+                               array( 'text/*'                => 1.0 ),
+                               array( 'application/xhtml+xml' => 1.0 ) ) );
+       }
+       
+       function testTimestamp() {
+               $t = gmmktime( 12, 34, 56, 1, 15, 2001 );
+               $this->assertEquals(
+                       '20010115123456',
+                       wfTimestamp( TS_MW, $t ),
+                       'TS_UNIX to TS_MW' );
+               $this->assertEquals(
+                       979562096,
+                       wfTimestamp( TS_UNIX, $t ),
+                       'TS_UNIX to TS_UNIX' );
+               $this->assertEquals(
+                       '2001-01-15 12:34:56',
+                       wfTimestamp( TS_DB, $t ),
+                       'TS_UNIX to TS_DB' );
+               
+               $this->assertEquals(
+                       '20010115123456',
+                       wfTimestamp( TS_MW, '20010115123456' ),
+                       'TS_MW to TS_MW' );
+               $this->assertEquals(
+                       979562096,
+                       wfTimestamp( TS_UNIX, '20010115123456' ),
+                       'TS_MW to TS_UNIX' );
+               $this->assertEquals(
+                       '2001-01-15 12:34:56',
+                       wfTimestamp( TS_DB, '20010115123456' ),
+                       'TS_MW to TS_DB' );
+               
+               $this->assertEquals(
+                       '20010115123456',
+                       wfTimestamp( TS_MW, '2001-01-15 12:34:56' ),
+                       'TS_DB to TS_MW' );
+               $this->assertEquals(
+                       979562096,
+                       wfTimestamp( TS_UNIX, '2001-01-15 12:34:56' ),
+                       'TS_DB to TS_UNIX' );
+               $this->assertEquals(
+                       '2001-01-15 12:34:56',
+                       wfTimestamp( TS_DB, '2001-01-15 12:34:56' ),
+                       'TS_DB to TS_DB' );
+       }
+       
+       /* TODO: many more! */
+}
+
+?>
\ No newline at end of file
diff --git a/tests/LocalTestSettings.sample b/tests/LocalTestSettings.sample
new file mode 100644 (file)
index 0000000..94adecc
--- /dev/null
@@ -0,0 +1,29 @@
+<?php
+# This contains basic configuration values that are needed
+# for RunTests.php.
+
+# Full path to the mediawiki source code you want to test
+$IP = '/var/www/mediawiki-cvs';
+
+# Now we add that path to the default include_path
+ini_set('include_path',ini_get('include_path').':'.$IP);
+
+# Some options needed for database testing
+$testOptions = array(
+    'mysql3' => array(
+        'server' => null,
+        'user' => null,
+        'password' => null,
+        'database' => null ),
+    'mysql4' => array(
+        'server' => null,
+        'user' => null,
+        'password' => null,
+        'database' => null ),
+    'postgresql' => array(
+        'server' => null,
+        'user' => null,
+        'password' => null,
+        'database' => null ),
+    );
+?>
diff --git a/tests/Makefile b/tests/Makefile
new file mode 100644 (file)
index 0000000..d980c9c
--- /dev/null
@@ -0,0 +1,6 @@
+.PHONY: help test
+help:
+       # Run 'make test' to run the unit tests.
+
+test:
+       php RunTests.php
diff --git a/tests/README b/tests/README
new file mode 100644 (file)
index 0000000..de15318
--- /dev/null
@@ -0,0 +1,8 @@
+Some quickie unit tests done with the PHPUnit testing framework. To run the
+test suite, run 'make test' in this dir or 'php RunTests.php'
+
+You can install PHPUnit via pear like this:
+# pear install PHPUnit
+
+Or fetch and install it manually:
+http://pear.php.net/package/PHPUnit
diff --git a/tests/RunTests.php b/tests/RunTests.php
new file mode 100644 (file)
index 0000000..5291d93
--- /dev/null
@@ -0,0 +1,96 @@
+<?php
+
+if( php_sapi_name() != 'cli' ) {
+       die( 'Must be run from the command line.' );
+}
+
+error_reporting( E_ALL );
+define( "MEDIAWIKI", true );
+
+require_once( 'PHPUnit.php' );
+
+$testOptions = array(
+       'mysql3' => array(
+               'server' => null,
+               'user' => null,
+               'password' => null,
+               'database' => null ),
+       'mysql4' => array(
+               'server' => null,
+               'user' => null,
+               'password' => null,
+               'database' => null ),
+       'postgresql' => array(
+               'server' => null,
+               'user' => null,
+               'password' => null,
+               'database' => null ),
+       );
+
+if( file_exists( 'LocalTestSettings.php' ) ) {
+       include( './LocalTestSettings.php' );
+}
+
+$tests = array(
+       'GlobalTest',
+       'DatabaseTest',
+       'SearchMySQL3Test',
+       'SearchMySQL4Test',
+       'ArticleTest',
+       'SanitizerTest',
+       );
+foreach( $tests as $test ) {
+       require_once( $test . '.php' );
+       $suite = new PHPUnit_TestSuite( $test );
+       $result = PHPUnit::run( $suite );
+       echo $result->toString();
+}
+
+/**
+ * @param string $serverType
+ * @param array $tables
+ */
+function &buildTestDatabase( $serverType, $tables ) {
+       global $testOptions, $wgDBprefix;
+       $wgDBprefix = 'parsertest';
+       $db =& new Database(
+               $testOptions[$serverType]['server'],
+               $testOptions[$serverType]['user'],
+               $testOptions[$serverType]['password'],
+               $testOptions[$serverType]['database'] );
+       if( $db->isOpen() ) {
+               if (!(strcmp($db->getServerVersion(), '4.1') < 0 and stristr($db->getSoftwareLink(), 'MySQL'))) {
+                       # Database that supports CREATE TABLE ... LIKE
+                       foreach ($tables as $tbl) {
+                               $newTableName = $db->tableName( $tbl );
+                               #$tableName = $this->oldTableNames[$tbl];
+                               $tableName = $tbl;
+                               $db->query("CREATE TEMPORARY TABLE $newTableName (LIKE $tableName INCLUDING DEFAULTS)");
+                       }
+               } else {
+                       # Hack for MySQL versions < 4.1, which don't support
+                       # "CREATE TABLE ... LIKE". Note that
+                       # "CREATE TEMPORARY TABLE ... SELECT * FROM ... LIMIT 0"
+                       # would not create the indexes we need....
+                       foreach ($tables as $tbl) {
+                               $res = $db->query("SHOW CREATE TABLE $tbl");
+                               $row = $db->fetchRow($res);
+                               $create = $row[1];
+                               $create_tmp = preg_replace('/CREATE TABLE `(.*?)`/', 'CREATE TEMPORARY TABLE `'
+                                       . $wgDBprefix . '\\1`', $create);
+                               if ($create === $create_tmp) {
+                                       # Couldn't do replacement
+                                       die("could not create temporary table $tbl");
+                               }
+                               $db->query($create_tmp);
+                       }
+
+               }
+               return $db;
+       } else {
+               // Something amiss
+               return null;
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/tests/SanitizerTest.php b/tests/SanitizerTest.php
new file mode 100644 (file)
index 0000000..e9ce295
--- /dev/null
@@ -0,0 +1,65 @@
+<?php
+
+require_once( 'PHPUnit.php' );
+require_once( '../includes/Defines.php' );
+require_once( '../includes/Profiling.php' );
+require_once( '../includes/GlobalFunctions.php' );
+require_once( '../includes/Sanitizer.php' );
+
+class SanitizerTest extends PHPUnit_TestCase {
+       function SanitizerTest( $name ) {
+               $this->PHPUnit_TestCase( $name );
+       }
+       
+       function setUp() {
+       }
+       
+       function tearDown() {
+       }
+
+       function testDecodeNamed() {
+               $this->assertEquals(
+                       "\xc3\xa9cole",
+                       Sanitizer::decodeCharReferences( '&eacute;cole' ) );
+       }
+
+       function testDecodeNumbered() {
+               $this->assertEquals(
+                       "\xc4\x88io bonas dans l'\xc3\xa9cole!",
+                       Sanitizer::decodeCharReferences( "&#x108;io bonas dans l'&#233;cole!" ) );
+       }
+       
+       function testDecodeMixed() {
+               $this->assertEquals(
+                       "\xc4\x88io bonas dans l'\xc3\xa9cole!",
+                       Sanitizer::decodeCharReferences( "&#x108;io bonas dans l'&eacute;cole!" ) );
+       }
+       
+       function testDecodeMixedComplex() {
+               $this->assertEquals(
+                       "\xc4\x88io bonas dans l'\xc3\xa9cole! (mais pas &#x108;io dans l'&eacute;cole)",
+                       Sanitizer::decodeCharReferences( "&#x108;io bonas dans l'&eacute;cole! (mais pas &amp;#x108;io dans l'&#38;eacute;cole)" ) );
+       }
+
+       function testDecodeInvalidAmp() {
+               $this->assertEquals(
+                       "a & b",
+                       Sanitizer::decodeCharReferences( "a & b" ) );
+       }
+       
+       function testDecodeInvalidNamed() {
+               $this->assertEquals(
+                       "&foo;",
+                       Sanitizer::decodeCharReferences( "&foo;" ) );
+       }
+       
+       function testDecodeInvalidNumbered() {
+               $this->assertEquals(
+                       UTF8_REPLACEMENT,
+                       Sanitizer::decodeCharReferences( "&#88888888888888;" ) );
+       }
+       
+       /* TODO: many more! */
+}
+
+?>
\ No newline at end of file
diff --git a/tests/SearchEngineTest.php b/tests/SearchEngineTest.php
new file mode 100644 (file)
index 0000000..cc3df09
--- /dev/null
@@ -0,0 +1,134 @@
+<?php
+
+$IP = '..';
+require_once( 'PHPUnit.php' );
+require_once( '../includes/Defines.php' );
+require_once( '../includes/DefaultSettings.php' );
+require_once( '../includes/Profiling.php' );
+require_once( '../includes/MagicWord.php' );
+require_once( '../languages/Language.php' );
+require_once( '../languages/LanguageUtf8.php' );
+
+require_once( '../includes/SearchEngine.php' );
+
+class SearchEngine_TestCase extends PHPUnit_TestCase {
+       var $db, $search;
+       
+       function insertSearchData() {
+               $this->db->safeQuery( <<<END
+               INSERT INTO ! (page_id,page_namespace,page_title,page_latest)
+               VALUES (1, 0, 'Main_Page', 1),
+                          (2, 1, 'Main_Page', 2),
+                          (3, 0, 'Smithee', 3),
+                          (4, 1, 'Smithee', 4),
+                          (5, 0, 'Unrelated_page', 5),
+                          (6, 0, 'Another_page', 6),
+                          (7, 4, 'Help', 7),
+                          (8, 0, 'Thppt', 8),
+                          (9, 0, 'Alan_Smithee', 9),
+                          (10, 0, 'Pages', 10)
+END
+                       , $this->db->tableName( 'page' ) );
+               $this->db->safeQuery( <<<END
+               INSERT INTO ! (rev_id,rev_page)
+               VALUES (1, 1),
+                      (2, 2),
+                      (3, 3),
+                      (4, 4),
+                      (5, 5),
+                      (6, 6),
+                      (7, 7),
+                      (8, 8),
+                      (9, 9),
+                      (10, 10)
+END
+                       , $this->db->tableName( 'revision' ) );
+               $this->db->safeQuery( <<<END
+               INSERT INTO ! (old_id,old_text)
+               VALUES (1, 'This is a main page'),
+                          (2, 'This is a talk page to the main page, see [[smithee]]'),
+                          (3, 'A smithee is one who smiths. See also [[Alan Smithee]]'),
+                          (4, 'This article sucks.'),
+                          (5, 'Nothing in this page is about the S word.'),
+                          (6, 'This page also is unrelated.'),
+                          (7, 'Help me!'),
+                          (8, 'Blah blah'),
+                          (9, 'yum'),
+                          (10,'are food')
+END
+                       , $this->db->tableName( 'text' ) );
+               $this->db->safeQuery( <<<END
+               INSERT INTO ! (si_page,si_title,si_text)
+               VALUES (1, 'main page', 'this is a main page'),
+                          (2, 'main page', 'this is a talk page to the main page, see smithee'),
+                          (3, 'smithee', 'a smithee is one who smiths see also alan smithee'),
+                          (4, 'smithee', 'this article sucks'),
+                          (5, 'unrelated page', 'nothing in this page is about the s word'),
+                          (6, 'another page', 'this page also is unrelated'),
+                          (7, 'help', 'help me'),
+                          (8, 'thppt', 'blah blah'),
+                          (9, 'alan smithee', 'yum'),
+                          (10, 'pages', 'are food')
+END
+                       , $this->db->tableName( 'searchindex' ) );
+       }
+       
+       function fetchIds( &$results ) {
+               $matches = array();
+               while( $row = $results->fetchObject() ) {
+                       $matches[] = IntVal( $row->page_id );
+               }
+               $results->free();
+               # Search is not guaranteed to return results in a certain order;
+               # sort them numerically so we will compare simply that we received
+               # the expected matches.
+               sort( $matches );
+               return $matches;
+       }
+       
+       function testTextSearch() {
+               $this->assertFalse( is_null( $this->db ), "Can't find a database to test with." );
+               if( !is_null( $this->db ) ) {
+                       $this->assertEquals(
+                               array( 3 ),
+                               $this->fetchIds( $this->search->searchText( 'smithee' ) ),
+                               "Plain search failed" );
+               }
+       }
+       
+       function testTextPowerSearch() {
+               $this->assertFalse( is_null( $this->db ), "Can't find a database to test with." );
+               if( !is_null( $this->db ) ) {
+                       $this->search->setNamespaces( array( 0, 1, 4 ) );
+                       $this->assertEquals(
+                               array( 2, 3 ),
+                               $this->fetchIds( $this->search->searchText( 'smithee' ) ),
+                               "Power search failed" );
+               }
+       }
+       
+       function testTitleSearch() {
+               $this->assertFalse( is_null( $this->db ), "Can't find a database to test with." );
+               if( !is_null( $this->db ) ) {
+                       $this->assertEquals(
+                               array( 3, 9 ),
+                               $this->fetchIds( $this->search->searchTitle( 'smithee' ) ),
+                               "Title search failed" );
+               }
+       }
+       
+       function testTextTitlePowerSearch() {
+               $this->assertFalse( is_null( $this->db ), "Can't find a database to test with." );
+               if( !is_null( $this->db ) ) {
+                       $this->search->setNamespaces( array( 0, 1, 4 ) );
+                       $this->assertEquals(
+                               array( 3, 4, 9 ),
+                               $this->fetchIds( $this->search->searchTitle( 'smithee' ) ),
+                               "Title power search failed" );
+               }
+       }
+       
+}
+
+
+?>
\ No newline at end of file
diff --git a/tests/SearchMySQL3Test.php b/tests/SearchMySQL3Test.php
new file mode 100644 (file)
index 0000000..9767e18
--- /dev/null
@@ -0,0 +1,34 @@
+<?php
+
+require_once( 'SearchEngineTest.php' );
+require_once( '../includes/SearchMySQL3.php' );
+
+class SearchMySQL3Test extends SearchEngine_TestCase {
+       var $db;
+       
+       function SearchMySQL3Test( $name ) {
+               $this->PHPUnit_TestCase( $name );
+       }
+       
+       function setUp() {
+               $GLOBALS['wgContLang'] = new LanguageUtf8;
+               $this->db =& buildTestDatabase(
+                       'mysql3',
+                       array( 'page', 'revision', 'text', 'searchindex' ) );
+               if( $this->db ) {
+                       $this->insertSearchData();
+               }
+               $this->search =& new SearchMySQL3( $this->db );
+       }
+       
+       function tearDown() {
+               if( !is_null( $this->db ) ) {
+                       $this->db->close();
+               }
+               unset( $this->db );
+               unset( $this->search );
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/tests/SearchMySQL4Test.php b/tests/SearchMySQL4Test.php
new file mode 100644 (file)
index 0000000..4038572
--- /dev/null
@@ -0,0 +1,34 @@
+<?php
+
+require_once( 'SearchEngineTest.php' );
+require_once( '../includes/SearchMySQL4.php' );
+
+class SearchMySQL4Test extends SearchEngine_TestCase {
+       var $db;
+       
+       function SearchMySQL4Test( $name ) {
+               $this->PHPUnit_TestCase( $name );
+       }
+       
+       function setUp() {
+               $GLOBALS['wgContLang'] = new LanguageUtf8;
+               $this->db =& buildTestDatabase(
+                       'mysql4',
+                       array( 'page', 'revision', 'text', 'searchindex' ) );
+               if( $this->db ) {
+                       $this->insertSearchData();
+               }
+               $this->search =& new SearchMySQL4( $this->db );
+       }
+       
+       function tearDown() {
+               if( !is_null( $this->db ) ) {
+                       $this->db->close();
+               }
+               unset( $this->db );
+               unset( $this->search );
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/thumb.php b/thumb.php
new file mode 100644 (file)
index 0000000..0c7de0c
--- /dev/null
+++ b/thumb.php
@@ -0,0 +1,79 @@
+<?php
+
+/** 
+ * PHP script to stream out an image thumbnail. 
+ * If the file exists, we make do with abridged MediaWiki initialisation. 
+ */
+
+define( 'MEDIAWIKI', true );
+unset( $IP );
+$wgNoOutputBuffer = true;
+
+require_once( './includes/Defines.php' );
+require_once( './LocalSettings.php' );
+require_once( 'GlobalFunctions.php' );
+
+$wgTrivialMimeDetection = true; //don't use fancy mime detection, just check the file extension for jpg/gif/png.
+
+require_once( 'Image.php' );
+require_once( 'StreamFile.php' );
+
+// Get input parameters
+
+if ( get_magic_quotes_gpc() ) {
+       $fileName = stripslashes( $_REQUEST['f'] );
+       $width = stripslashes( $_REQUEST['w'] );
+} else {
+       $fileName = $_REQUEST['f'];
+       $width = $_REQUEST['w'];
+}
+
+$pre_render= isset($_REQUEST['r']) && $_REQUEST['r']!="0";
+
+// Some basic input validation
+
+$width = intval( $width );
+$fileName = strtr( $fileName, '\\/', '__' );
+
+// Work out paths, carefully avoiding constructing an Image object because that won't work yet
+
+$imagePath = wfImageDir( $fileName ) . '/' . $fileName;
+$thumbName = "{$width}px-$fileName";
+if ( $pre_render ) {
+       $thumbName .= '.png';
+}
+$thumbPath = wfImageThumbDir( $fileName ) . '/' . $thumbName;
+
+if ( is_file( $thumbPath ) && filemtime( $thumbPath ) >= filemtime( $imagePath ) ) {
+       wfStreamFile( $thumbPath );
+       exit;
+}
+
+// OK, no valid thumbnail, time to get out the heavy machinery
+require_once( 'Setup.php' );
+wfProfileIn( 'thumb.php' );
+
+$img = Image::newFromName( $fileName );
+if ( $img ) {
+       $thumb = $img->renderThumb( $width, false );
+} else {
+       $thumb = false;
+}
+
+if ( $thumb && $thumb->path ) {
+       wfStreamFile( $thumb->path );
+} else {
+       $badtitle = wfMsg( 'badtitle' );
+       $badtitletext = wfMsg( 'badtitletext' );
+       echo "<html><head>
+       <title>$badtitle</title>
+       <body>
+<h1>$badtitle</h1>
+<p>$badtitletext</p>
+</body></html>";
+}
+
+wfProfileOut( 'thumb.php' );
+
+
+?>
diff --git a/trackback.php b/trackback.php
new file mode 100644 (file)
index 0000000..a2c9d8d
--- /dev/null
@@ -0,0 +1,75 @@
+<?php
+/**
+ * Provide functions to handle article trackbacks.
+ * @package MediaWiki
+ * @subpackage SpecialPage
+ */
+
+unset($IP);
+define('MEDIAWIKI', true);
+require_once('./includes/Defines.php');
+
+if (!file_exists('LocalSettings.php'))
+       exit;
+
+require_once('./LocalSettings.php');
+require_once('includes/Setup.php');
+
+require_once('Title.php');
+require_once('DatabaseFunctions.php');
+
+/**
+ *
+ */
+function XMLsuccess() {
+       echo "
+<?xml version=\"1.0\" encoding=\"utf-8\"?>
+<response>
+<error>0</error>
+</response>
+       ";
+       exit;
+}
+
+function XMLerror($err = "Invalid request.") {
+       header("HTTP/1.0 400 Bad Request");
+       echo "
+<?xml version=\"1.0\" encoding=\"utf-8\"?>
+<response>
+<error>1</error>
+<message>Invalid request: $err</message>
+</response>
+";
+               exit;
+}
+
+if (!$wgUseTrackbacks)
+       XMLerror("Trackbacks are disabled.");
+
+if (   !isset($_POST['url'])
+    || !isset($_POST['blog_name'])
+    || !isset($_REQUEST['article']))
+       XMLerror("Required field not specified");
+
+$dbw =& wfGetDB(DB_MASTER);
+
+$tbtitle = $_POST['title'];
+$tbex = $_POST['excerpt'];
+$tburl = $_POST['url'];
+$tbname = $_POST['blog_name'];
+$tbarticle = $_REQUEST['article'];
+
+$title = Title::newFromText($tbarticle);
+if (!$title->exists())
+       XMLerror("Specified article does not exist.");
+
+$dbw->insert('trackbacks', array(
+       'tb_page'       => $title->getArticleID(),
+       'tb_title'      => $tbtitle,
+       'tb_url'        => $tburl,
+       'tb_ex'         => $tbex,
+       'tb_name'       => $tbname
+));
+
+XMLsuccess();
+exit;
diff --git a/wiki.phtml b/wiki.phtml
new file mode 100644 (file)
index 0000000..5f6b019
--- /dev/null
@@ -0,0 +1,4 @@
+<?php
+// stub file for compatibility with older versions
+include_once('./index.php');
+?>
\ No newline at end of file