├── .eslintrc.json ├── .gitignore ├── .gitreview ├── .mailmap ├── .phpcs.xml ├── .puppet-lint.rc ├── COPYING ├── Gemfile ├── Gruntfile.js ├── README.md ├── Rakefile ├── bin ├── autobackport-mediawiki ├── autoexport ├── autoexport-mediawiki ├── autoimport ├── autoimport-mediawiki ├── clupdate-bzr-repo ├── clupdate-git-repo ├── clupdate-svn-repo ├── createmi ├── data │ ├── known_hosts │ └── ssh_config ├── execute-and-notify ├── export-translation-dump ├── findexportroot ├── fuzzy ├── fuzzyr ├── git-ssh-wrapper ├── l10n-bot ├── manualexport ├── merge-wmgerrit-patches ├── oregano ├── repo ├── repocommit ├── repoexport ├── repomulti ├── repong-cleanups ├── repoupdate ├── scripts │ ├── LICENSE │ ├── mlebstats.php │ └── snedUdpMessage.php ├── search-reindex ├── stats-newcorelangs ├── synclock ├── twn-update-all ├── twn-update-config ├── twn-update-database ├── twn-update-maintained ├── udpcast ├── version ├── wikiupdate └── wikiupdate-repo ├── composer.json ├── composer.lock ├── generate-language-rename-commands.php ├── groups ├── Ajapaik │ └── Ajapaik.yaml ├── Blockly │ └── Blockly.yaml ├── EOL │ └── EOL.yaml ├── EtherpadLite │ ├── EtherpadLite.yaml │ └── Plugins.yaml ├── FUDforum │ └── FUDforum.yaml ├── FreeCol │ └── FreeCol.yaml ├── Huggle │ └── Huggle.yaml ├── Intuition │ ├── IntuitionAgg.yaml │ ├── commtech-commons.yaml │ ├── dcatap.yaml │ ├── intuition-textdomains.txt │ ├── orphantalk.yaml │ ├── raun.yaml │ ├── refill.yaml │ └── web.yaml ├── Kiwix │ ├── KiwixAgg.yaml │ ├── KiwixAndroid.yaml │ ├── KiwixApple.yaml │ ├── KiwixDesktop.yaml │ ├── KiwixMWoffliner.yaml │ ├── KiwixPhET.yaml │ ├── KiwixServe.yaml │ └── KiwixZimitFrontend.yaml ├── MantisBT │ ├── CodevTT.yaml │ └── MantisBT.yaml ├── MathJax │ └── MathJax.yaml ├── MediaWiki │ ├── ExtensionsAgg.yaml │ ├── MediaWiki.yaml │ ├── MirahezeAgg.yaml │ ├── SkinsAgg.yaml │ ├── SocialProfileAgg.yaml │ ├── SocialToolsAgg.yaml │ ├── WikimediaAdvancedAgg.yaml │ ├── WikimediaAgg.yaml │ ├── WikimediaFundraisingAgg.yaml │ ├── WikimediaLegacyAgg.yaml │ ├── WikimediaMainAgg.yaml │ ├── WikimediaMediaAgg.yaml │ ├── WikimediaTechnicalAgg.yaml │ ├── WikimediaUpcomingAgg.yaml │ ├── WikimediaWikivoyageAgg.yaml │ ├── mediawiki-extensions.txt │ ├── mediawiki-skins.txt │ ├── mwbitbucket.yaml │ ├── mwgerrit.yaml │ ├── mwgithub.yaml │ ├── mwgitlab.yaml │ ├── repong-generator.php │ ├── wikimedia-mostused-2011.txt │ └── wikimedia-mostused-2015.txt ├── NFCRingControl │ └── NFCRingControl.yaml ├── Nocc │ └── Nocc.yaml ├── OpenStreetMap │ ├── OpenStreetMap.yaml │ └── WaymarkedTrails.yaml ├── Oppia │ ├── Oppia.yaml │ └── OppiaAndroid.yaml ├── PageTranslationAgg.yaml ├── Phabricator │ ├── Phabricator.yaml │ ├── PhabricatorAgg.yaml │ └── generate-yaml.php ├── Projects │ └── OpenHistoricalMap.yaml ├── Pywikibot │ └── Pywikibot.yaml ├── Vicuna │ └── Vicuna.yaml ├── Wikidocumentaries │ └── Wikidocumentaries.yaml ├── Wikimedia │ ├── Adiutor.yaml │ ├── Anvesha.yaml │ ├── CapacityExchange.yaml │ ├── CeJS.yaml │ ├── Cita.yaml │ ├── CitationHunt.yaml │ ├── CommonsAndroid.yaml │ ├── ConvenientDiscussions.yaml │ ├── CopyPatrol.yaml │ ├── DiscordWikiBot.yaml │ ├── GrantMetrics.yaml │ ├── InteractionTimeline.yaml │ ├── InternetArchiveBot.yaml │ ├── JankClient.yaml │ ├── MiniEdit.yaml │ ├── PageContentService.yaml │ ├── Pageviews.yaml │ ├── ProveIt.yaml │ ├── QRmedia.yaml │ ├── QuickStatements3.yaml │ ├── Ranker.yaml │ ├── SWViewer.yaml │ ├── SignIt.yaml │ ├── Toolhub.yaml │ ├── Twinkle.yaml │ ├── WPCleaner.yaml │ ├── WSExport.yaml │ ├── WhoWroteThat.yaml │ ├── WikiBlame.yaml │ ├── WikiEduDashboard.yaml │ ├── WikiLearn.yaml │ ├── WikiScore.yaml │ ├── WikidataImagePositions.yaml │ ├── WikidataLexemeForms.yaml │ ├── WikidataMismatchFinder.yaml │ ├── WikimediaDeveloperPortal.yaml │ ├── WikimediaMailmanTemplates.yaml │ ├── WikimediaMobile-android.yaml │ ├── WikimediaMobile-ios.yaml │ ├── WikimediaMobile-kaios.yaml │ ├── WikimediaMobile.yaml │ ├── WikimediaOCR.yaml │ ├── WikimediaPortals.yaml │ ├── WikimediaTools.yaml │ ├── WikipediaLibrary.yaml │ ├── WikipediaPreview.yaml │ ├── WikipediaYearInReview.yaml │ ├── Wikistats.yaml │ ├── WmczTracker.yaml │ ├── WmczWeb.yaml │ ├── Wscd.yaml │ ├── XTools.yaml │ ├── global-search.yaml │ ├── ia-upload.yaml │ ├── jquery.uls.yaml │ ├── svgtranslate.yaml │ ├── video2commons.yaml │ ├── wiki-ai.yaml │ └── wscontest.yaml ├── lib.reviews │ └── lib.reviews.yaml └── wikidata │ └── wikidata.yaml ├── melange ├── .gitignore ├── BundleCreater.php ├── README.md ├── config.ini └── melange.php ├── mw-config ├── DevelopmentSettings.php ├── ExtensionSettings.php ├── FallbackSettings.php ├── LanguageSettings.php ├── NewUserMessageJob.php ├── PermissionSettings.php ├── TranslateSettings.php ├── TranslatewikiSettings.php └── validation-exclusion-list.php ├── package-lock.json ├── package.json ├── puppet ├── .gitignore ├── .puppet-lint.rc ├── Makefile ├── Puppetfile ├── Puppetfile.lock ├── README ├── data │ ├── .gitignore │ ├── common.yaml │ ├── developer.yaml.example │ └── nodes │ │ ├── dev.yaml │ │ ├── web2.eyaml │ │ └── web2.yaml ├── hiera.yaml ├── modules │ ├── awstats │ │ ├── files │ │ │ ├── awstats.conf.local │ │ │ └── stats.translatewiki.net │ │ ├── manifests │ │ │ └── init.pp │ │ └── templates │ │ │ ├── awstats.service.erb │ │ │ ├── awstats.timer.erb │ │ │ ├── mlebstats.service.erb │ │ │ └── mlebstats.timer.erb │ ├── base │ │ ├── manifests │ │ │ ├── firewall │ │ │ │ ├── post.pp │ │ │ │ └── pre.pp │ │ │ ├── init.pp │ │ │ ├── mediawiki.pp │ │ │ └── vcs.pp │ │ └── templates │ │ │ └── translatewiki.sh.erb │ ├── fcgiwrap │ │ └── manifests │ │ │ └── init.pp │ ├── hostname │ │ └── manifests │ │ │ └── init.pp │ ├── keyholder │ │ ├── README │ │ ├── files │ │ │ ├── keyholder │ │ │ └── ssh-agent-proxy │ │ ├── manifests │ │ │ ├── agent.pp │ │ │ └── init.pp │ │ └── templates │ │ │ └── initscripts │ │ │ ├── keyholder-agent.systemd.erb │ │ │ └── keyholder-proxy.systemd.erb │ ├── kitanonl │ │ ├── files │ │ │ ├── index.html │ │ │ └── kitano.nl │ │ └── manifests │ │ │ └── init.pp │ ├── mailer │ │ └── manifests │ │ │ └── init.pp │ ├── mariadb │ │ └── manifests │ │ │ └── init.pp │ ├── memcached │ │ ├── files │ │ │ └── memcached.conf │ │ └── manifests │ │ │ └── init.pp │ ├── nginx │ │ ├── files │ │ │ ├── error.html │ │ │ ├── ffdhe2048.txt │ │ │ ├── logrotate │ │ │ ├── nginx.conf │ │ │ ├── offline │ │ │ ├── ssl-certbot.conf │ │ │ ├── ssl.conf │ │ │ ├── translatewiki.net │ │ │ └── translatewiki.org │ │ ├── manifests │ │ │ ├── devsite.pp │ │ │ ├── init.pp │ │ │ ├── sites.pp │ │ │ └── ssl.pp │ │ └── templates │ │ │ ├── devsite.conf.erb │ │ │ └── ssl-selfsigned.conf.erb │ ├── php │ │ ├── files │ │ │ ├── wmerrors.ini │ │ │ └── www.conf │ │ └── manifests │ │ │ └── init.pp │ ├── profile │ │ └── manifests │ │ │ └── mwelasticsearch.pp │ ├── repong │ │ ├── manifests │ │ │ ├── autobackport.pp │ │ │ ├── autobackport_mediawiki_timer.pp │ │ │ ├── autoexport.pp │ │ │ ├── autoexport_timer.pp │ │ │ ├── autoimport.pp │ │ │ ├── autoimport_timer.pp │ │ │ └── init.pp │ │ └── templates │ │ │ ├── autobackport-mediawiki.timer.erb │ │ │ ├── autobackport-mediawiki@.service.erb │ │ │ ├── autoexport.service.erb │ │ │ ├── autoexport.timer.erb │ │ │ ├── autoimport.service.erb │ │ │ ├── autoimport.timer.erb │ │ │ ├── repong-cleanups.service.erb │ │ │ └── repong-cleanups.timer.erb │ ├── sshd │ │ ├── files │ │ │ └── sshd_config │ │ └── manifests │ │ │ └── init.pp │ ├── users │ │ ├── files │ │ │ └── aliases │ │ ├── manifests │ │ │ ├── aliases.pp │ │ │ └── init.pp │ │ └── templates │ │ │ └── sudo.erb │ └── wiki │ │ ├── files │ │ └── phplog2irc.service │ │ ├── manifests │ │ ├── docroot.pp │ │ ├── init.pp │ │ ├── irc.pp │ │ ├── slack.pp │ │ ├── stats.pp │ │ └── workdir.pp │ │ └── templates │ │ ├── LocalSettings.php.erb │ │ ├── irc-log-relay.env.erb │ │ ├── irc-log-relay.service.erb │ │ ├── irc-rc-relay.env.erb │ │ ├── irc-rc-relay.service.erb │ │ ├── mw-completeexternaltranslation.service.erb │ │ ├── mw-completeexternaltranslation.timer.erb │ │ ├── mw-jobrunner.service.erb │ │ ├── mw-logrotate.erb │ │ ├── mw-newcorelangs.service.erb │ │ ├── mw-newcorelangs.timer.erb │ │ ├── mw-sitemap.service.erb │ │ ├── mw-sitemap.timer.erb │ │ ├── mw-specialpages.service.erb │ │ ├── mw-specialpages.timer.erb │ │ ├── mw-supportedlanguages.service.erb │ │ ├── mw-supportedlanguages.timer.erb │ │ ├── mw-translationexports.service.erb │ │ ├── mw-translationexports.timer.erb │ │ ├── slack-log-relay.service.erb │ │ └── wikisettings.erb ├── setup-environment.sh └── site.pp ├── relays ├── irc │ ├── COPYING │ ├── README │ ├── rakkauspipe.sh │ └── relay.pl ├── logfilter.php └── slack │ ├── slack-logger.php │ └── slackpipe.sh ├── repoconfig.yaml ├── repong ├── .gitignore ├── LICENSE ├── composer.json ├── composer.lock ├── repoconfig.schema.yaml ├── repong.php └── src │ ├── App │ ├── BackportCommand.php │ ├── Command.php │ ├── CommitCommand.php │ ├── DiffCommand.php │ ├── ExportCommand.php │ ├── ListCommand.php │ ├── PurgeCommand.php │ ├── StatusCommand.php │ └── UpdateCommand.php │ └── Forge │ ├── ForgeClient.php │ ├── ForgeFactory.php │ ├── GithubClient.php │ ├── GithubPullRequestResponse.php │ ├── GitlabClient.php │ ├── GitlabPullRequestResponse.php │ ├── PullRequestResponse.php │ └── PullRequestSpecifier.php ├── translatewiki-composer.json ├── validate-bash.php ├── validate-repoconfig.php ├── validate-yaml.php └── webfiles ├── jserror.php └── twn.jserrorlog.js /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "extends": [ 4 | "wikimedia/client", 5 | "wikimedia/jquery" 6 | ], 7 | "globals": { 8 | "ve": "readonly", 9 | "VisualEditorSupportCheck": "readonly", 10 | "OO": "readonly", 11 | "unicodeJS": "readonly", 12 | "RangeFix": "readonly", 13 | "Papa": "readonly", 14 | "mw": "readonly", 15 | "require": "readonly" 16 | }, 17 | "rules": { 18 | "no-jquery/no-hide": "error", 19 | "no-jquery/no-show": "error", 20 | "no-jquery/no-toggle": "error", 21 | "max-len": "off", 22 | "no-jquery/no-done-fail": "warn" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .svn 2 | *~ 3 | *.kate-swp 4 | .*.swp 5 | .idea 6 | extensions/ 7 | node_modules/ 8 | vendor/ 9 | Gemfile.lock 10 | known_hosts.old 11 | .eslintcache 12 | -------------------------------------------------------------------------------- /.gitreview: -------------------------------------------------------------------------------- 1 | [gerrit] 2 | host=gerrit.wikimedia.org 3 | port=29418 4 | project=translatewiki 5 | defaultbranch=master 6 | defaultrebase=0 7 | -------------------------------------------------------------------------------- /.puppet-lint.rc: -------------------------------------------------------------------------------- 1 | --fail-on-warnings 2 | --log-format='%{path}:%{line} %{KIND} %{message} (%{check})' 3 | 4 | # Long lines are fine... 5 | --no-80chars-check 6 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'sync' 4 | gem 'rake' 5 | gem 'xmlrpc' 6 | gem 'puppet', ENV['PUPPET_GEM_VERSION'] || '~> 4.10.9' 7 | gem 'puppetlabs_spec_helper' 8 | 9 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node, es6 */ 2 | module.exports = function ( grunt ) { 3 | 'use strict'; 4 | 5 | grunt.loadNpmTasks( 'grunt-eslint' ); 6 | 7 | grunt.initConfig( { 8 | eslint: { 9 | options: { 10 | cache: true 11 | }, 12 | all: [ 13 | '**/*.{js,json}', 14 | '!{node_modules,vendor}/**/*.{js,json}' 15 | ] 16 | } 17 | } ); 18 | 19 | grunt.registerTask( 'test', [ 'eslint' ] ); 20 | grunt.registerTask( 'default', 'test' ); 21 | }; 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # translatewiki.net configuration 2 | 3 | This repository contains code to install and operate [translatewiki.net](https://translatewiki.net). A few files with secrets are omitted. 4 | 5 | If you are looking to have your project added to translatewiki.net for translation, please see [Setup of a new project](https://translatewiki.net/wiki/Setup_of_a_new_project). 6 | 7 | ## Directories 8 | 9 | * bin/ Shell commands. 10 | * groups/ Configuration files for translation groups for the MediaWiki extension Translate. 11 | * relays/ IRC/Slack recent changes bot code. 12 | * melange/ MediaWiki Language Extension Bundle (MLEB) release tooling. 13 | * puppet/ translatewiki.net puppet code. 14 | * repong/ Repository management tooling for supported projects of the MediaWiki extension Translate. 15 | * webfiles/ Static web files for translatewiki.net operation. 16 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # This Rakefile is meant to run linters and tests. 2 | # 3 | # You will need 'bundler' to install dependencies: 4 | # 5 | # $ apt-get install bundler 6 | # $ bundle install 7 | # 8 | # Then run rake in using bundler environment: 9 | # 10 | # $ bundle exec rake test 11 | # 12 | # To see all available tasks: 13 | # 14 | # $ bundle exec rake 15 | # 16 | 17 | require 'puppet-lint/tasks/puppet-lint' 18 | require 'puppet-syntax/tasks/puppet-syntax' 19 | 20 | PuppetSyntax.exclude_paths = ["puppet/vendor/**/*"] 21 | PuppetLint.configuration.pattern = "puppet/modules/**/*.pp" 22 | 23 | task :default => [:help] 24 | 25 | desc 'Show the help' 26 | task :help do 27 | system 'rake -T' 28 | end 29 | 30 | desc 'Run all build/tests commands (CI entry point)' 31 | task test: [:syntax, :lint] 32 | -------------------------------------------------------------------------------- /bin/autobackport-mediawiki: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o nounset -o pipefail -o errexit 3 | 4 | DIRSCRIPT=$(dirname "$(readlink -f "$0")") 5 | . /etc/wikisettings 6 | # shellcheck source=bin/synclock 7 | . "$DIRSCRIPT/synclock" 8 | 9 | cd "$AUTOEXPORT_DIR" 10 | 11 | BRANCH=$1 12 | PROJECTS=$(php "$DIRSCRIPT/../repong/repong.php" list-projects | grep ^mediawiki) 13 | 14 | _b=$(tput bold) 15 | b_=$(tput sgr0) 16 | 17 | for i in $PROJECTS; do 18 | echo "${_b}$i${b_}" 19 | { 20 | sudo -u "$L10NBOTUSER" "$DIRSCRIPT/repomulti" backport "$i" "$BRANCH" && 21 | sudo -u "$L10NBOTUSER" "$DIRSCRIPT/repomulti" commit "$i" --backport-branch "$BRANCH" 22 | } || : 23 | done 24 | 25 | echo "Check https://gerrit.wikimedia.org/r/q/owner:L10n-bot+status:open for patches needing manual review" 26 | -------------------------------------------------------------------------------- /bin/autoexport: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o nounset -o pipefail -o errexit 3 | 4 | DIRSCRIPT=$(dirname "$(readlink -f "$0")") 5 | . /etc/wikisettings 6 | # shellcheck source=bin/synclock 7 | . "$DIRSCRIPT/synclock" 8 | 9 | cd "$AUTOEXPORT_DIR" 10 | 11 | case "$(basename -- "$0")" in 12 | autoexport) 13 | PROJECTS=$(php "$DIRSCRIPT/../repong/repong.php" list-projects | grep -v ^mediawiki) 14 | ;; 15 | autoexport-mediawiki) 16 | PROJECTS=$(php "$DIRSCRIPT/../repong/repong.php" list-projects | grep ^mediawiki) 17 | ;; 18 | *) 19 | echo "I don't know what to export" 20 | exit 1 21 | ;; 22 | esac 23 | 24 | _b=$(tput bold) 25 | b_=$(tput sgr0) 26 | 27 | for i in $PROJECTS; do 28 | echo "${_b}$i${b_}" 29 | { 30 | sudo -u "$L10NBOTUSER" "$DIRSCRIPT/repomulti" update "$i" && 31 | sudo -u "$L10NBOTUSER" "$DIRSCRIPT/repomulti" export "$i" && 32 | sudo -u "$L10NBOTUSER" "$DIRSCRIPT/repomulti" commit "$i" 33 | } || : 34 | done 35 | 36 | echo "Check https://gerrit.wikimedia.org/r/q/owner:L10n-bot+status:open for patches needing manual review" 37 | -------------------------------------------------------------------------------- /bin/autoexport-mediawiki: -------------------------------------------------------------------------------- 1 | autoexport -------------------------------------------------------------------------------- /bin/autoimport: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o nounset -o pipefail -o errexit 3 | 4 | DIRSCRIPT=$(dirname "$(readlink -f "$0")") 5 | . /etc/wikisettings 6 | # shellcheck source=bin/synclock 7 | . "$DIRSCRIPT/synclock" 8 | 9 | SCRIPT="$WIKIDIR/extensions/Translate/scripts/importExternalTranslations.php" 10 | NAME="non-mediawiki" 11 | 12 | # Needed for list-projects to know which repoconfig.yaml to read 13 | cd "$AUTOIMPORT_DIR" 14 | 15 | php "$DIRSCRIPT/../repong/repong.php" list-projects | grep -v ^mediawiki | xargs -n1 -P4 "$DIRSCRIPT/repo" update || : 16 | 17 | if OUTPUT=$(php "$WIKISCRIPT" "$SCRIPT" --name "$NAME" --safe-import --group=* --skipgroup=ext-*,core,mediawiki*) 18 | then 19 | if [[ ! -z "$OUTPUT" ]] 20 | then 21 | echo "$OUTPUT" | xargs -l "$DIRSCRIPT/udpcast" 22 | fi 23 | else 24 | CODE=$? 25 | echo "$OUTPUT" 26 | "$DIRSCRIPT/udpcast" "Fatal error in autoimport! Please check the logs." 27 | exit "$CODE" 28 | fi 29 | -------------------------------------------------------------------------------- /bin/autoimport-mediawiki: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o nounset -o pipefail -o errexit 3 | 4 | DIRSCRIPT=$(dirname "$(readlink -f "$0")") 5 | . /etc/wikisettings 6 | # shellcheck source=bin/synclock 7 | . "$DIRSCRIPT/synclock" 8 | 9 | SCRIPT="$WIKIDIR/extensions/Translate/scripts/importExternalTranslations.php" 10 | NAME=mediawiki 11 | 12 | # Needed for list-projects to know which repoconfig.yaml to read 13 | cd "$AUTOIMPORT_DIR" 14 | 15 | php "$DIRSCRIPT/../repong/repong.php" list-projects | grep ^mediawiki | xargs -n1 -P4 "$DIRSCRIPT/repo" update || : 16 | 17 | if OUTPUT=$(php "$WIKISCRIPT" "$SCRIPT" --name "$NAME" --group=core,ext-*,mediawiki*) 18 | then 19 | if [[ ! -z "$OUTPUT" ]] 20 | then 21 | echo "$OUTPUT" | xargs -l "$DIRSCRIPT/udpcast" 22 | fi 23 | else 24 | CODE=$? 25 | echo "$OUTPUT" 26 | "$DIRSCRIPT/udpcast" "Fatal error in autoimport-mediawiki! Please check the logs." 27 | exit "$CODE" 28 | fi 29 | -------------------------------------------------------------------------------- /bin/clupdate-bzr-repo: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o nounset -o pipefail -o errexit 3 | 4 | URL=$1 5 | DIR=$2 6 | BRANCH=${3:-master} 7 | 8 | if [ -d "$DIR/.bzr" ] 9 | then 10 | cd "$DIR" 11 | bzr revert --quiet 12 | bzr pull "$BRANCH" --quiet --overwrite 13 | else 14 | bzr checkout "${URL}/${BRANCH}" "$DIR" 15 | fi 16 | -------------------------------------------------------------------------------- /bin/clupdate-git-repo: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o nounset -o pipefail -o errexit 3 | 4 | URL=$1 5 | DIR=$2 6 | BRANCH=${3:-master} 7 | COMMIT=${4:-origin/$BRANCH} 8 | FORGE=${5:-none} 9 | 10 | # Avoid getting stuck waiting for user input 11 | export GIT_TERMINAL_PROMPT=0 12 | 13 | # On URL change, start from scratch 14 | if [ -d "$DIR/.git" ] 15 | then ( 16 | ACTUALURL="$(git -C "$DIR" config --get remote.origin.url)" 17 | if [ "$URL" != "$ACTUALURL" ] 18 | then 19 | echo "Re-cloning $DIR to update from $ACTUALURL to $URL"; 20 | rm -rf "$DIR" 21 | fi 22 | ) fi 23 | 24 | if [ -d "$DIR/.git" ] 25 | then ( 26 | cd "$DIR" 27 | git rebase --abort &>/dev/null || : 28 | git fetch -q --prune 29 | git checkout -qf "$BRANCH" 30 | git reset -q --hard "$COMMIT" 31 | git clean -q -f -d &>/dev/null 32 | ) else ( 33 | git clone "$URL" "$DIR" -b "$BRANCH" 34 | ) fi 35 | 36 | # This configuration part is cheap, so run it every time to ensure it's up to date 37 | cd "$DIR" 38 | if [ "$FORGE" = 'wikimedia-gerrit' ] 39 | then 40 | git config user.name 'Translation updater bot' 41 | git config user.email 'l10n-bot@translatewiki.net' 42 | git config gitreview.username 'l10n-bot' 43 | git config gitreview.remote origin 44 | git config gpg.format 'ssh' 45 | git config commit.gpgsign 'true' 46 | git config user.signingkey 'key::ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG/B9tTMv3xBeENcfU48os66O+W1w9puNIB8nEz3TJ7Q' 47 | 48 | # Avoid using git review --setup because it uses SCP which does not honor GIT_SSH 49 | if [[ ! -e .git/hooks/commit-msg ]]; 50 | then 51 | mkdir -p .git/hooks 52 | curl -Lo .git/hooks/commit-msg https://gerrit.wikimedia.org/r/tools/hooks/commit-msg 53 | chmod +x .git/hooks/commit-msg 54 | fi 55 | else 56 | git config user.name 'translatewiki.net' 57 | git config user.email 'l10n-bot@translatewiki.net' 58 | git config gpg.format 'ssh' 59 | git config commit.gpgsign 'true' 60 | git config user.signingkey 'key::ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG/B9tTMv3xBeENcfU48os66O+W1w9puNIB8nEz3TJ7Q' 61 | fi 62 | -------------------------------------------------------------------------------- /bin/clupdate-svn-repo: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o nounset -o pipefail -o errexit 3 | 4 | URL=$1 5 | DIR=$2 6 | 7 | if [ -d "$DIR/.svn" ] 8 | then ( 9 | cd "$DIR" 10 | svn up -q "$DIR" 11 | ) else 12 | svn checkout -q "$URL" "$DIR" 13 | fi 14 | -------------------------------------------------------------------------------- /bin/createmi: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o nounset -o pipefail -o errexit 3 | 4 | . /etc/wikisettings 5 | 6 | php "$WIKISCRIPT" "$WIKIDIR/extensions/Translate/scripts/createMessageIndex.php" --quiet 7 | echo "Done." 8 | -------------------------------------------------------------------------------- /bin/data/known_hosts: -------------------------------------------------------------------------------- 1 | # Don't add IPs here 2 | git.code.sf.net ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPAa5MFfMaXyT3Trf/Av/laAvIhUzZJUnvPZAd9AC6bKWAhVl+A3s2+M6SlhF/Tn/W0akN03GyNviBtqJKtx0RU= 3 | svn.code.sf.net ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPAa5MFfMaXyT3Trf/Av/laAvIhUzZJUnvPZAd9AC6bKWAhVl+A3s2+M6SlhF/Tn/W0akN03GyNviBtqJKtx0RU= 4 | git-ssh.wikimedia.org ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBJJQs/ByE2oE32pdGxLmPfwUGGfCkGNMtt2BbabYCCyquLI1woLE4apVno5GSvNotKRpcMN6VbRdwatvT/yFUIw= 5 | [gerrit.wikimedia.org]:29418 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCF8pwFLehzCXhbF1jfHWtd9d1LFq2NirplEBQYs7AOrGwQ/6ZZI0gvZFYiEiaw1o+F1CMfoHdny1VfWOJF3mJ1y9QMKAacc8/Z3tG39jBKRQCuxmYLO1SWymv7/Uvx9WQlkNRoTdTTa9OJFy6UqvLQEXKYaokfMIUHZ+oVFf1CgQ== 6 | github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl 7 | github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg= 8 | gitlab.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAfuCHKVTjquxvt6CM6tdG4SLp1Btn/nOeHHE5UOzRdf 9 | bitbucket.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIazEu89wgQZ4bqs3d63QSMzYVa0MuJ2e2gKTKqu+UUO 10 | gitlab.wikimedia.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG5c7aJKGboKUMkoxxcpMhNw5PkRxWVN2RRzN0Bb9ZN2 -------------------------------------------------------------------------------- /bin/data/ssh_config: -------------------------------------------------------------------------------- 1 | Host * 2 | BatchMode yes 3 | CheckHostIP no 4 | ControlMaster auto 5 | ControlPath /tmp/l10n-bot-%C 6 | ControlPersist 60 7 | HashKnownHosts no 8 | IdentitiesOnly yes 9 | IdentityFile /etc/keyholder.d/l10n_bot.pub 10 | IdentityFile /etc/keyholder.d/l10n_bot_2023.pub 11 | -------------------------------------------------------------------------------- /bin/execute-and-notify: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o nounset -o pipefail -o errexit 3 | 4 | DIRSCRIPT=$(dirname "$(readlink -f "$0")") 5 | COMMAND="${*}" 6 | PRETTYCOMMAND="$(basename -- "$1") ${*:2}" 7 | 8 | if ANSIOUTPUT=$(export TERM=ansi; pipetty $COMMAND) 9 | then 10 | SUBJECT="$PRETTYCOMMAND completed" 11 | else 12 | SUBJECT="$PRETTYCOMMAND failed" 13 | fi 14 | 15 | HTMLOUTPUT=$(echo "$ANSIOUTPUT" | ansi2html -wlc) 16 | PLAINOUTPUT=$(echo "$ANSIOUTPUT" | ansi2txt) 17 | 18 | # Part 1 - send email 19 | cat < $INFOFILE 45 | echo "Export completed successfully." 46 | -------------------------------------------------------------------------------- /bin/findexportroot: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -o nounset -o errexit 3 | 4 | # Used by repo* scripts to find the repository root 5 | # similar to how like git tries to find .git 6 | DIR=${DIR:-$(pwd)} 7 | 8 | while true 9 | do 10 | if [ ! -f "$DIR/repoconfig.yaml" ] 11 | then 12 | DIR=$(dirname "$DIR") 13 | else 14 | break 15 | fi 16 | 17 | if [ "$DIR" = "/" ] 18 | then 19 | echo "Fatal: Could not find repoconfig.yaml" 20 | exit 1 21 | fi 22 | done 23 | -------------------------------------------------------------------------------- /bin/fuzzy: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o nounset -o pipefail -o errexit 3 | 4 | . /etc/wikisettings 5 | 6 | if [ "$#" -gt "2" ]; then 7 | echo "Only two parameters allowed for fuzzy dry run:" 8 | echo "\$1 is the message key (replace spaces by underscores; use a trailing /)" 9 | echo "\$2 is the edit summary" 10 | exit 11 | fi 12 | 13 | php "$WIKISCRIPT" "$WIKIDIR/extensions/Translate/scripts/fuzzy.php" --skiplanguages=en,test,qqq "$1" --comment="$2" 14 | -------------------------------------------------------------------------------- /bin/fuzzyr: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o nounset -o pipefail -o errexit 3 | 4 | . /etc/wikisettings 5 | 6 | if [ "$#" -gt "2" ]; then 7 | echo "Only two parameters allowed for fuzzy:" 8 | echo "\$1 is the message key (replace spaces by underscores; use a trailing /)" 9 | echo "\$2 is the edit summary" 10 | exit 11 | fi 12 | 13 | php "$WIKISCRIPT" "$WIKIDIR/extensions/Translate/scripts/fuzzy.php" --skiplanguages=en,test,qqq "$1" --really --comment="$2" 14 | -------------------------------------------------------------------------------- /bin/git-ssh-wrapper: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | DIRSCRIPT=$(dirname "$(readlink -f "$0")") 3 | 4 | exec ssh -F "$DIRSCRIPT/data/ssh_config" -oUserKnownHostsFile="$DIRSCRIPT/data/known_hosts" "$@" 5 | -------------------------------------------------------------------------------- /bin/l10n-bot: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -o nounset -o errexit 3 | 4 | . /etc/l10n-bot/env 5 | SSH_AUTH_SOCK=/run/keyholder/proxy.sock $@ 6 | -------------------------------------------------------------------------------- /bin/manualexport: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o nounset -o pipefail -o errexit 3 | 4 | DIRSCRIPT=$(dirname "$(readlink -f "$0")") 5 | . /etc/wikisettings 6 | # shellcheck source=bin/synclock 7 | . "$DIRSCRIPT/synclock" 8 | 9 | PROJECT=${1} 10 | FILTER=${2:-*} 11 | 12 | cd "$AUTOEXPORT_DIR" 13 | sudo -u "$L10NBOTUSER" "$DIRSCRIPT/repomulti" update "$PROJECT" --filter "$FILTER" && 14 | sudo -u "$L10NBOTUSER" "$DIRSCRIPT/repomulti" export "$PROJECT" --filter "$FILTER" && 15 | sudo -u "$L10NBOTUSER" "$DIRSCRIPT/repomulti" commit "$PROJECT" --filter "$FILTER" 16 | -------------------------------------------------------------------------------- /bin/merge-wmgerrit-patches: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o nounset -o pipefail -o errexit 3 | DIRSCRIPT=$(dirname "$(readlink -f "$0")") 4 | 5 | U="L10n-bot " 6 | GERRIT=("l10n-bot@gerrit.wikimedia.org" -p 29418) 7 | 8 | "$DIRSCRIPT/git-ssh-wrapper" "${GERRIT[@]}" gerrit query --format=TEXT "owner:$U" "project:$1" status:open | 9 | (grep -Po '(?<=^ number: )[0-9]+$' || true) | # Handle pipefail from grep 10 | sort | 11 | xargs -I ____ "$DIRSCRIPT/git-ssh-wrapper" "${GERRIT[@]}" gerrit review ____,1 --code-review 2 12 | -------------------------------------------------------------------------------- /bin/repo: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o errexit -o nounset -o pipefail 3 | 4 | . /etc/wikisettings 5 | 6 | umask 0002 7 | 8 | DIRSCRIPT=$(dirname "$(readlink -f "$0")") 9 | COMMAND=$1 10 | PROJECT=$2 11 | 12 | cd "$AUTOIMPORT_DIR" 13 | sudo -u "$L10NBOTUSER" "$DIRSCRIPT/repo$COMMAND" "$PROJECT" 14 | -------------------------------------------------------------------------------- /bin/repocommit: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o errexit -o nounset -o pipefail 3 | 4 | DIRSCRIPT=$(dirname "$(readlink -f "$0")") 5 | # shellcheck source=bin/findexportroot 6 | . "$DIRSCRIPT/findexportroot" 7 | 8 | export GIT_SSH="$DIRSCRIPT/git-ssh-wrapper" 9 | export SVN_SSH="$DIRSCRIPT/git-ssh-wrapper" 10 | 11 | ME=$(basename -- "$0") 12 | COMMAND=${ME:4} 13 | PROJECT=$1 14 | 15 | php "$DIRSCRIPT/../repong/repong.php" "$COMMAND" "$PROJECT" 16 | -------------------------------------------------------------------------------- /bin/repoexport: -------------------------------------------------------------------------------- 1 | repocommit -------------------------------------------------------------------------------- /bin/repomulti: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Example: repomulti update 3 | # Example: repomulti status 'mediawiki|mwgithub|mwgerrit' 4 | set -o nounset -o pipefail -o errexit 5 | 6 | DIRSCRIPT=$(dirname "$(readlink -f "$0")") 7 | 8 | COMMAND=${1:-status} 9 | 10 | case "$COMMAND" in 11 | purge|list-projects) 12 | php "$DIRSCRIPT/../repong/repong.php" "$COMMAND" "${@:2}" 13 | exit 14 | ;; 15 | update|commit|backport) 16 | WRAPPER="$DIRSCRIPT/l10n-bot" 17 | export GIT_SSH="$DIRSCRIPT/git-ssh-wrapper" 18 | export SVN_SSH="$DIRSCRIPT/git-ssh-wrapper" 19 | ;; 20 | *) 21 | WRAPPER="" 22 | ;; 23 | esac 24 | 25 | # Second parameter can be a pattern to restrict groups 26 | PATTERN="${2:-.*}" 27 | PROJECTS=$(php "$DIRSCRIPT/../repong/repong.php" list-projects | grep -P "^$PATTERN$") || 28 | echo "Pattern '$PATTERN' did not match any projects" 29 | 30 | _b=$(tput bold) 31 | b_=$(tput sgr0) 32 | 33 | for i in $PROJECTS; do 34 | if [ "$i" != "$PATTERN" ] 35 | then 36 | echo "${_b}$i${b_}" 37 | fi 38 | $WRAPPER php "$DIRSCRIPT/../repong/repong.php" "$COMMAND" "$i" "${@:3}" 39 | done 40 | -------------------------------------------------------------------------------- /bin/repong-cleanups: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o nounset -o pipefail -o errexit 3 | 4 | . /etc/wikisettings 5 | DIRSCRIPT=$(dirname "$(readlink -f "$0")") 6 | 7 | # shellcheck source=bin/synclock 8 | . "$DIRSCRIPT/synclock" 9 | 10 | find /resources/caches/$WIKINAME/ -maxdepth 1 -ctime +365 -type f -delete 11 | 12 | cd "$AUTOIMPORT_DIR" 13 | php "$DIRSCRIPT/../repong/repong.php" purge --really 14 | 15 | cd "$AUTOEXPORT_DIR" 16 | php "$DIRSCRIPT/../repong/repong.php" purge --really 17 | -------------------------------------------------------------------------------- /bin/repoupdate: -------------------------------------------------------------------------------- 1 | repocommit -------------------------------------------------------------------------------- /bin/search-reindex: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o nounset -o pipefail -o errexit 3 | 4 | . /etc/wikisettings 5 | 6 | CURRENTTIME=$(date +"%T") 7 | echo "*** $CURRENTTIME: Starting reindex ***" 8 | php "$WIKISCRIPT" "$WORKDIR/extensions/CirrusSearch/maintenance/Metastore.php" --upgrade 9 | php "$WIKISCRIPT" "$WORKDIR/extensions/CirrusSearch/maintenance/UpdateSearchIndexConfig.php" --startOver 10 | php "$WIKISCRIPT" "$WORKDIR/extensions/CirrusSearch/maintenance/ForceSearchIndex.php" --skipLinks --indexOnSkip --buildChunks 500 --batch-size=50 | parallel --eta --nice 20 --joblog reindex.log --no-notice 11 | php "$WIKISCRIPT" "$WORKDIR/extensions/CirrusSearch/maintenance/ForceSearchIndex.php" --skipParse --buildChunks 500 --batch-size=50 | parallel --eta --nice 20 --joblog reindex-2.log --no-notice 12 | 13 | CURRENTTIME=$(date +"%T") 14 | echo "*** $CURRENTTIME: Reindex complete ***" 15 | -------------------------------------------------------------------------------- /bin/stats-newcorelangs: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o errexit -o nounset -o pipefail 3 | 4 | . /etc/wikisettings 5 | 6 | cd "$AUTOIMPORT_DIR/mediawiki/master" 7 | { 8 | echo "{{/Header1}}
"
 9 | 	git log --format="format:%ci" --name-only --diff-filter=A languages/i18n/*.json
10 | 	echo "
" 11 | } | php "$WIKISCRIPT" edit --user=MaintenanceBot --summary="Updating statistics" Translating:MediaWiki/New_languages 12 | -------------------------------------------------------------------------------- /bin/synclock: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o nounset -o pipefail -o errexit 3 | 4 | . /etc/wikisettings 5 | 6 | LOCKFILE="${LOCKFILE-/tmp/sync.lock}" 7 | TIMEOUT=1800 8 | 9 | touch "$LOCKFILE" 10 | # This only needs to succeed once 11 | chmod 777 "$LOCKFILE" >/dev/null 2>&1 || : 12 | 13 | # Create a file descriptor over the given lockfile. 14 | exec {FD}<>"$LOCKFILE" 15 | 16 | # Check if another process is running and show what it is 17 | if ! flock --nonblock $FD 18 | then 19 | echo "Another process is currently holding a lock:" 20 | cat "$LOCKFILE" 21 | echo "Waiting at most $TIMEOUT seconds for the lock to be released" 22 | fi 23 | 24 | # Note: This is a special bash variable 25 | SECONDS=0 26 | if flock --wait $TIMEOUT $FD; then 27 | echo "Waited $SECONDS seconds to acquire the lock" 28 | echo "${USER-unknown} started running $(basename -- "$0") at $(date -uIseconds)" > "$LOCKFILE" 29 | else 30 | echo "Failed to obtain a lock within $SECONDS seconds" 31 | exit 1 32 | fi 33 | -------------------------------------------------------------------------------- /bin/twn-update-all: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o nounset -o pipefail -o errexit 3 | 4 | . /etc/wikisettings 5 | 6 | DIRSCRIPT=$(dirname "$(readlink -f "$0")") 7 | 8 | cd "$WORKDIR" 9 | REV=$(git log --pretty="%h %ci (%cr)" -n 1) 10 | "$DIRSCRIPT/udpcast" "updating $WIKINAME from $REV..." 11 | 12 | CURRENTTIME=$(date +"%T") 13 | echo "*** $CURRENTTIME: Updating config ***" 14 | "$DIRSCRIPT/twn-update-config" 15 | 16 | "$DIRSCRIPT/wikiupdate" "$WORKDIR" "$WORKDIR"/extensions/* "$WORKDIR"/skins/* 17 | 18 | REV=$(git log --pretty="%h %ci (%cr)" -n 1) 19 | "$DIRSCRIPT/udpcast" "updated $WIKINAME to $REV" 20 | -------------------------------------------------------------------------------- /bin/twn-update-config: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o nounset -o pipefail -o errexit 3 | 4 | . /etc/wikisettings 5 | 6 | DIRSCRIPT=$(dirname "$(readlink -f "$0")") 7 | sudo -u "$REPOUSER" "$DIRSCRIPT/wikiupdate-repo" "$CONFDIR" 8 | sudo -u "$REPOUSER" rsync -r "$CONFDIR/mw-config/" "$WORKDIR/config" 9 | sudo -u "$REPOUSER" rsync -r "$CONFDIR/webfiles/" "$WORKDIR/webfiles" 10 | sudo -u "$MAINTUSER" sudo /usr/sbin/service mw-jobrunner restart 11 | -------------------------------------------------------------------------------- /bin/twn-update-database: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o nounset -o pipefail -o errexit 3 | 4 | . /etc/wikisettings 5 | 6 | sudo -u "$REPOUSER" php "$WORKDIR/maintenance/run.php" update --quick 7 | 8 | CURRENTTIME=$(date +"%T") 9 | echo "*** $CURRENTTIME: Updating translator activity ***" 10 | sudo -u "$MAINTUSER" php "$WIKISCRIPT" "$WIKIDIR/extensions/Translate/scripts/updateTranslatorActivity.php" 11 | -------------------------------------------------------------------------------- /bin/twn-update-maintained: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o nounset -o pipefail -o errexit 3 | 4 | . /etc/wikisettings 5 | 6 | DIRSCRIPT=$(dirname "$(readlink -f "$0")") 7 | "$DIRSCRIPT/wikiupdate" "$WORKDIR"/extensions/{Translate,UniversalLanguageSelector,CleanChanges,TwnMainPage,Babel} 8 | "$DIRSCRIPT/udpcast" "updated $WIKINAME (self-maintained extensions)" 9 | -------------------------------------------------------------------------------- /bin/udpcast: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -o nounset -o errexit 3 | 4 | DIRSCRIPT=$(dirname "$(readlink -f "$0")") 5 | WHO=${SUDO_USER-${USER-}} 6 | 7 | php "${DIRSCRIPT}/scripts/snedUdpMessage.php" --host=127.0.0.1 --port=8966 --quiet=1 "[$WHO]" "$@" 8 | -------------------------------------------------------------------------------- /bin/version: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o nounset -o pipefail -o errexit 3 | 4 | . /etc/wikisettings 5 | 6 | cd "$WORKDIR" 7 | 8 | sudo -u "$REPOUSER" git log -1 $(sudo -u "$REPOUSER" git merge-base origin/master HEAD) 9 | -------------------------------------------------------------------------------- /bin/wikiupdate: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o nounset -o pipefail -o errexit 3 | 4 | . /etc/wikisettings 5 | 6 | DIRSCRIPT=$(dirname "$(readlink -f "$0")") 7 | 8 | CURRENTTIME=$(date +"%T") 9 | echo "*** $CURRENTTIME: Updating repositories ***" 10 | find "$@" -maxdepth 1 -type d -name .git -print0 | 11 | xargs -0 -n1 dirname | 12 | xargs -n1 -P4 sudo -H -u "$REPOUSER" "$DIRSCRIPT/wikiupdate-repo" 13 | 14 | CURRENTTIME=$(date +"%T") 15 | echo "*** $CURRENTTIME: Updating composer dependencies ***" 16 | sudo -u "$REPOUSER" composer -n -d"$WORKDIR" update 17 | 18 | CURRENTTIME=$(date +"%T") 19 | echo "*** $CURRENTTIME: Rebuilding caches ***" 20 | sudo -u "$MAINTUSER" nice php "$WORKDIR/maintenance/run.php" rebuildLocalisationCache --threads 6 --quiet 21 | 22 | CURRENTTIME=$(date +"%T") 23 | echo "*** $CURRENTTIME: All done ***" 24 | -------------------------------------------------------------------------------- /bin/wikiupdate-repo: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o nounset -o pipefail -o errexit 3 | 4 | # Avoid getting stuck waiting for user input 5 | export GIT_TERMINAL_PROMPT=0 6 | 7 | cd "$1" 8 | if ! OUTPUT=$(git fetch --quiet 2>&1 >&-); then 9 | CODE=$? 10 | printf "\\033[31m%s failed to update\\033[0m\\n" "$1" 11 | echo "$OUTPUT" 12 | exit "$CODE" 13 | fi 14 | 15 | # NB: grep returns with failure code with empty input 16 | OUTPUT=$(git log --oneline --no-decorate HEAD..FETCH_HEAD | grep -v "Localisation updates from" || :) 17 | if [ -n "$OUTPUT" ]; then 18 | echo "== $1 ==" 19 | echo "$OUTPUT"; 20 | echo 21 | fi 22 | 23 | if ! OUTPUT=$(git pull --quiet --rebase 2>&1 >&- && git submodule update --init); then 24 | CODE=$? 25 | printf "\\033[31m%s failed to update\\033[0m\\n" "$1" 26 | echo "$OUTPUT" 27 | exit "$CODE" 28 | fi 29 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require-dev": { 3 | "justinrainbow/json-schema": "^5.2", 4 | "mediawiki/mediawiki-codesniffer": "47.0.0", 5 | "php-parallel-lint/php-parallel-lint": "1.4.0", 6 | "symfony/yaml": "^5.1" 7 | }, 8 | "scripts": { 9 | "fix": "phpcbf", 10 | "test": [ 11 | "parallel-lint . --exclude vendor --exclude repong/vendor --exclude node_modules --exclude puppet --exclude melange/extensions", 12 | "@php validate-bash.php", 13 | "@phpcs", 14 | "@php validate-yaml.php groups puppet/hiera.yaml puppet/data", 15 | "@php validate-repoconfig.php" 16 | ], 17 | "phpcs": "phpcs -sp --cache" 18 | }, 19 | "require": { 20 | "ext-yaml": "*" 21 | }, 22 | "config": { 23 | "allow-plugins": { 24 | "dealerdirect/phpcodesniffer-composer-installer": true 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /generate-language-rename-commands.php: -------------------------------------------------------------------------------- 1 | \n"; 9 | exit( 1 ); 10 | } 11 | 12 | $sourceLanguage = $argv[1]; 13 | $targetLanguage = $argv[2]; 14 | 15 | $config = Yaml::parseFile( 'repoconfig.yaml' ); 16 | 17 | foreach ( $config as $key => $value ) { 18 | if ( $key === '@meta' ) { 19 | continue; 20 | } 21 | 22 | echo "sudo -u l10n-bot repomulti update {$key}\n"; 23 | 24 | $group = $value['group']; 25 | echo "sudo -u l10n-bot php /srv/mediawiki/targets/production/extensions/Translate/scripts/export-rename-language.php --group='{$group}' --target=. --source-language {$sourceLanguage} --target-language {$targetLanguage}\n"; 26 | 27 | echo "sudo -u l10n-bot repomulti status {$key}\n"; 28 | echo "sudo -u l10n-bot repomulti commit {$key}\n"; 29 | echo "\n"; 30 | } 31 | -------------------------------------------------------------------------------- /groups/EOL/EOL.yaml: -------------------------------------------------------------------------------- 1 | TEMPLATE: 2 | BASIC: 3 | icon: wiki://EOL_logo.svg 4 | namespace: NS_EOL 5 | class: FileBasedMessageGroup 6 | description: "{{Special:MyLanguage/Translations:Group descriptions/eol/en}}" 7 | 8 | FILES: 9 | format: Yaml 10 | parseCLDRPlurals: true 11 | codeAsRoot: true 12 | codeMap: 13 | be-tarask: be-Tarask 14 | en-gb: en-GB 15 | es-mx: es-MX 16 | ku-latn: ku-Latn 17 | pt-br: pt-BR 18 | pt: pt-PT 19 | sh-cyrl: sh-Cyrl 20 | sh-latn: sh 21 | sr-ec: sr 22 | sr-el: sr-Latn 23 | tt-cyrl: tt 24 | zh-hans: zh-CN 25 | zh-hant: zh-TW 26 | 27 | VALIDATORS: 28 | - id: InsertableRegex 29 | enforce: true 30 | insertable: true 31 | params: /%{[a-z0-9_]+}/ 32 | 33 | --- 34 | BASIC: 35 | id: eol 36 | label: Encyclopedia of Life 37 | meta: yes 38 | class: AggregateMessageGroup 39 | 40 | GROUPS: 41 | - eol-* 42 | 43 | --- 44 | BASIC: 45 | id: eol-website 46 | label: Encyclopedia of Life - Website 47 | 48 | FILES: 49 | sourcePattern: "%GROUPROOT%/eol-website/config/locales/%CODE%.yml" 50 | 51 | MANGLER: 52 | class: StringMatcher 53 | patterns: 54 | - "*" 55 | prefix: website- 56 | 57 | TAGS: 58 | ignored: 59 | - website-license_group.labels.* 60 | - website-locale_codes.* 61 | - website-simple_form.required.mark 62 | optional: 63 | - website-about.trait_bank.title 64 | - website-nav.trait_bank 65 | --- 66 | BASIC: 67 | id: eol-devise 68 | label: Encyclopedia of Life - Devise (Authentication) 69 | 70 | FILES: 71 | sourcePattern: "%GROUPROOT%/eol-website/config/locales/devise.%CODE%.yml" 72 | 73 | MANGLER: 74 | class: StringMatcher 75 | patterns: 76 | - "*" 77 | prefix: devise- 78 | -------------------------------------------------------------------------------- /groups/EtherpadLite/EtherpadLite.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | BASIC: 3 | id: etherpad-lite 4 | label: Etherpad lite 5 | icon: wiki://Etherpad_lite.svg 6 | description: "{{Special:MyLanguage/Translations:Group descriptions/etherpad-lite/en}}" 7 | namespace: NS_ETHERPADLITE 8 | meta: yes 9 | class: AggregateMessageGroup 10 | 11 | GROUPS: 12 | - etherpad-lite-core 13 | - etherpad-lite-plugin-* 14 | 15 | --- 16 | BASIC: 17 | id: etherpad-lite-core 18 | label: Etherpad lite core 19 | icon: wiki://Etherpad_lite.svg 20 | description: "{{Special:MyLanguage/Translations:Group descriptions/etherpad-lite/en}}" 21 | namespace: NS_ETHERPADLITE 22 | class: FileBasedMessageGroup 23 | 24 | FILES: 25 | format: Json 26 | sourcePattern: "%GROUPROOT%/etherpad-lite/src/locales/%CODE%.json" 27 | 28 | VALIDATORS: 29 | - id: InsertableRegex 30 | insertable: true 31 | enforce: false 32 | params: /{{[a-zA-Z_]+}}/ 33 | 34 | TAGS: 35 | optional: 36 | - pad.settings.fontType.* 37 | 38 | -------------------------------------------------------------------------------- /groups/FUDforum/FUDforum.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | BASIC: 3 | id: out-fudforum 4 | label: FUDforum 5 | icon: wiki://Fudforum.png 6 | description: "{{Special:MyLanguage/Translations:Group descriptions/fudforum/en}}" 7 | namespace: NS_FUDFORUM 8 | class: FileBasedMessageGroup 9 | 10 | FILES: 11 | format: Java 12 | keySeparator: ":" 13 | sourcePattern: "%GROUPROOT%/fudforum/install/forum_data/thm/default/i18n/%CODE%/msg" 14 | 15 | VALIDATORS: 16 | - id: InsertableRegex 17 | enforce: true 18 | insertable: true 19 | params: /\$[1-9]/ 20 | - id: InsertableRegex 21 | enforce: true 22 | insertable: true 23 | params: '/{(?:VAR|GVAR|TEMPLATE|VAR-HTML|FUNC): [^}]+}/' 24 | - id: Replacement 25 | enforce: true 26 | params: 27 | search: '{{PLURAL:' 28 | replace: '{PLURAL:' 29 | 30 | INSERTABLES: 31 | # HTML entities 32 | - class: RegexInsertablesSuggester 33 | params: '/&#?\w+;/' 34 | 35 | TAGS: 36 | optional: 37 | - msg_title 38 | - thread_title 39 | - tree_title 40 | -------------------------------------------------------------------------------- /groups/Huggle/Huggle.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | BASIC: 3 | id: huggle 4 | label: Huggle 5 | icon: wiki://Huggle_icon_mini.svg 6 | description: "{{Special:MyLanguage/Translations:Group descriptions/huggle/en}}" 7 | namespace: NS_HUGGLE 8 | class: FileBasedMessageGroup 9 | 10 | FILES: 11 | format: AndroidXml 12 | sourcePattern: "%GROUPROOT%/huggle/huggle/Localization/%CODE%.xml" 13 | codeMap: 14 | nb: "no" 15 | pt-br: pt-BR 16 | zh-hans: zh 17 | cs: cz 18 | 19 | VALIDATORS: 20 | - id: MediaWikiParameter 21 | insertable: true 22 | enforce: false 23 | -------------------------------------------------------------------------------- /groups/Intuition/IntuitionAgg.yaml: -------------------------------------------------------------------------------- 1 | BASIC: 2 | id: tsint-0-all 3 | label: Intuition 4 | icon: wiki://Collaboration_logo_V2.svg 5 | description: "{{Special:MyLanguage/Translations:Group descriptions/tsint/en}}" 6 | meta: yes 7 | class: AggregateMessageGroup 8 | namespace: NS_INTUITION 9 | 10 | GROUPS: 11 | - tsint-* 12 | - int-* 13 | 14 | VALIDATORS: 15 | - id: NumericalParameter 16 | insertable: true 17 | -------------------------------------------------------------------------------- /groups/Intuition/commtech-commons.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | BASIC: 3 | id: int-commtech-commons 4 | label: CommunityTechBot 5 | namespace: NS_INTUITION 6 | class: FileBasedMessageGroup 7 | 8 | MANGLER: 9 | class: StringMatcher 10 | prefix: commtech-commons- 11 | patterns: 12 | - "*" 13 | 14 | FILES: 15 | format: Json 16 | sourcePattern: "%GROUPROOT%/int-commtech-commons/i18n/%CODE%.json" 17 | 18 | VALIDATORS: 19 | - id: NumericalParameter 20 | insertable: true 21 | -------------------------------------------------------------------------------- /groups/Intuition/dcatap.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | BASIC: 3 | id: int-dcatap 4 | label: DCAT-AP 5 | namespace: NS_INTUITION 6 | class: FileBasedMessageGroup 7 | 8 | MANGLER: 9 | class: StringMatcher 10 | prefix: dcatap- 11 | patterns: 12 | - "*" 13 | 14 | FILES: 15 | format: Json 16 | sourcePattern: "%GROUPROOT%/int-dcatap/i18n/%CODE%.json" 17 | 18 | VALIDATORS: 19 | - id: NumericalParameter 20 | insertable: true 21 | -------------------------------------------------------------------------------- /groups/Intuition/intuition-textdomains.txt: -------------------------------------------------------------------------------- 1 | Catdown 2 | optional = script-filename, readme-filename 3 | ignored = scaling-none 4 | 5 | CommonsHelper 2 6 | ignored = title, tusc 7 | optional = commonshelper2, standard_project, checkusage 8 | 9 | Cvn Overlay 10 | 11 | General 12 | optional = colon-separator, dateformat, parentheses, comma-separator, word-separator 13 | 14 | GetWikiAPI 15 | ignored = title 16 | 17 | Grep 18 | 19 | Intuition - Core 20 | id = tsint-core 21 | prefix = tsintuition- | 22 | file = tsintuition/%CODE%.json 23 | ignored = title 24 | 25 | Jarry 26 | ignored = title 27 | 28 | Krinkle 29 | 30 | # Unused 31 | #Pb 32 | #optional = labs-name 33 | 34 | Rtrc 35 | ignored = rtrc-months 36 | 37 | Templatecount 38 | optional = title 39 | 40 | Template transclusion check 41 | 42 | Toolserver status 43 | 44 | Ts Reports 45 | optional = base_links, report_variable, report_changelinks 46 | 47 | Voiceintro 48 | ignored = voiceintro-title 49 | 50 | What leaves here 51 | 52 | Wikiviewstats 53 | -------------------------------------------------------------------------------- /groups/Intuition/orphantalk.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | BASIC: 3 | id: int-orphantalk 4 | label: OrphanTalk 5 | namespace: NS_INTUITION 6 | class: FileBasedMessageGroup 7 | 8 | MANGLER: 9 | class: StringMatcher 10 | prefix: orphantalk2- 11 | patterns: 12 | - "*" 13 | 14 | FILES: 15 | format: Json 16 | sourcePattern: "%GROUPROOT%/int-orphantalk/messages/%CODE%.json" 17 | 18 | VALIDATORS: 19 | - id: NumericalParameter 20 | insertable: true -------------------------------------------------------------------------------- /groups/Intuition/raun.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | BASIC: 3 | id: int-raun 4 | label: Raun 5 | namespace: NS_INTUITION 6 | class: FileBasedMessageGroup 7 | 8 | MANGLER: 9 | class: StringMatcher 10 | prefix: raun- 11 | patterns: 12 | - "*" 13 | 14 | FILES: 15 | format: Json 16 | sourcePattern: "%GROUPROOT%/int-raun/messages/%CODE%.json" 17 | 18 | TAGS: 19 | ignored: 20 | - raun-ns* 21 | 22 | VALIDATORS: 23 | - id: NumericalParameter 24 | insertable: true -------------------------------------------------------------------------------- /groups/Intuition/refill.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | BASIC: 3 | id: int-refill 4 | label: reFill 5 | description: "{{Special:MyLanguage/Translations:Group descriptions/Refill/en}}" 6 | namespace: NS_INTUITION 7 | class: FileBasedMessageGroup 8 | 9 | MANGLER: 10 | class: StringMatcher 11 | prefix: refill- 12 | patterns: 13 | - "*" 14 | 15 | FILES: 16 | format: Json 17 | sourcePattern: "%GROUPROOT%/int-refill/messages/%CODE%.json" 18 | 19 | TAGS: 20 | optional: 21 | - refill-appname 22 | - refill-wikitext-support-parameter-* 23 | - refill-wikitext-parameter-* 24 | - refill-wikitext-template-* 25 | 26 | VALIDATORS: 27 | - id: NumericalParameter 28 | insertable: true -------------------------------------------------------------------------------- /groups/Intuition/web.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | BASIC: 3 | id: int-web 4 | label: Intuition - User Dashboard 5 | namespace: NS_INTUITION 6 | class: FileBasedMessageGroup 7 | 8 | MANGLER: 9 | class: StringMatcher 10 | prefix: web- 11 | patterns: 12 | - "*" 13 | 14 | FILES: 15 | format: Json 16 | sourcePattern: "%GROUPROOT%/int-web/messages/%CODE%.json" 17 | 18 | TAGS: 19 | optional: 20 | - web-title 21 | 22 | VALIDATORS: 23 | - id: NumericalParameter 24 | insertable: true -------------------------------------------------------------------------------- /groups/Kiwix/KiwixAgg.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | BASIC: 3 | id: kiwix 4 | label: Kiwix 5 | icon: wiki://Kiwix_icon.svg 6 | description: "{{Special:MyLanguage/Translations:Group descriptions/kiwix/en}}" 7 | namespace: NS_KIWIX 8 | meta: yes 9 | class: AggregateMessageGroup 10 | 11 | 12 | GROUPS: 13 | - kiwix-* 14 | -------------------------------------------------------------------------------- /groups/Kiwix/KiwixApple.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | BASIC: 3 | id: kiwix-apple 4 | label: Kiwix Apple 5 | icon: wiki://Kiwix_icon.svg 6 | description: "{{Special:MyLanguage/Translations:Group descriptions/kiwix-apple/en}}" 7 | namespace: NS_KIWIX 8 | class: FileBasedMessageGroup 9 | support: 10 | url: https://github.com/kiwix/apple/issues/new 11 | params: 12 | title: Translation issue with message %MESSAGE% 13 | body: "\nMessage URL: %MESSAGE_URL%" 14 | 15 | MANGLER: 16 | class: StringMatcher 17 | prefix: apple- 18 | patterns: 19 | - "*" 20 | 21 | FILES: 22 | format: Apple 23 | sourcePattern: "%GROUPROOT%/kiwix-apple/Support/%CODE%.lproj/Localizable.strings" 24 | 25 | VALIDATORS: 26 | - id: IosVariable 27 | insertable: true 28 | enforce: true 29 | 30 | TAGS: 31 | optional: 32 | - apple-enum.category.ted 33 | - apple-enum.category.stackexchange 34 | -------------------------------------------------------------------------------- /groups/Kiwix/KiwixDesktop.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | BASIC: 3 | id: kiwix-desktop 4 | label: Kiwix Desktop 5 | icon: wiki://Kiwix_icon.svg 6 | description: "{{Special:MyLanguage/Translations:Group descriptions/kiwix/en}}" 7 | namespace: NS_KIWIX 8 | class: FileBasedMessageGroup 9 | 10 | FILES: 11 | format: Json 12 | sourcePattern: "%GROUPROOT%/kiwix-desktop/resources/i18n/%CODE%.json" 13 | 14 | VALIDATORS: 15 | - id: InsertableRegex 16 | enforce: true 17 | insertable: true 18 | params: /{{[a-zA-Z_0-9]+}}/ 19 | 20 | INSERTABLES: 21 | - class: HtmlTagInsertablesSuggester -------------------------------------------------------------------------------- /groups/Kiwix/KiwixMWoffliner.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | BASIC: 3 | id: kiwix-mwoffliner 4 | label: MWoffliner MediaWiki scraper 5 | icon: wiki://Kiwix_icon.svg 6 | description: "{{Special:MyLanguage/Translations:Group descriptions/mwoffliner/en}}" 7 | namespace: NS_KIWIX 8 | class: FileBasedMessageGroup 9 | support: 10 | url: https://github.com/openzim/mwoffliner/issues/new 11 | params: 12 | title: Translation issue with message %MESSAGE% 13 | body: "\n\nURL: %MESSAGE_URL%" 14 | 15 | FILES: 16 | format: Json 17 | sourcePattern: "%GROUPROOT%/kiwix-mwoffliner/translation/%CODE%.json" 18 | 19 | MANGLER: 20 | class: StringMatcher 21 | prefix: mwoffliner- 22 | patterns: 23 | - "*" 24 | 25 | VALIDATORS: 26 | - id: InsertableRegex 27 | enforce: true 28 | insertable: true 29 | params: /\${[a-zA-Z0-9]+}/ 30 | - id: MatchSet 31 | enforce: true 32 | include: 33 | - mwoffliner-=5F=5Fdirection 34 | params: 35 | values: 36 | - ltr 37 | - rtl 38 | 39 | TAGS: 40 | optional: 41 | - mwoffliner-=5F=5Fdirection 42 | -------------------------------------------------------------------------------- /groups/Kiwix/KiwixPhET.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | BASIC: 3 | id: kiwix-phet 4 | label: PhET Interactive Simulations 5 | icon: wiki://Kiwix_icon.svg 6 | description: "{{Special:MyLanguage/Kiwix:phet-zim-description/en}}" 7 | namespace: NS_KIWIX 8 | class: FileBasedMessageGroup 9 | support: 10 | url: https://github.com/openzim/phet/issues/new 11 | params: 12 | title: Translation issue with message %MESSAGE% 13 | body: "\n\nURL: %MESSAGE_URL%" 14 | 15 | FILES: 16 | format: Json 17 | sourcePattern: "%GROUPROOT%/kiwix-phet/res/js/i18n/%CODE%.json" 18 | 19 | MANGLER: 20 | class: StringMatcher 21 | prefix: phet- 22 | patterns: 23 | - "*" 24 | -------------------------------------------------------------------------------- /groups/Kiwix/KiwixServe.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | BASIC: 3 | id: kiwix-serve 4 | label: Kiwix Serve 5 | icon: wiki://Kiwix_icon.svg 6 | description: "{{Special:MyLanguage/Translations:Group descriptions/kiwix/en}}" 7 | namespace: NS_KIWIX 8 | class: FileBasedMessageGroup 9 | 10 | FILES: 11 | format: Json 12 | sourcePattern: "%GROUPROOT%/kiwix-serve/static/skin/i18n/%CODE%.json" 13 | 14 | MANGLER: 15 | class: StringMatcher 16 | prefix: serve- 17 | patterns: 18 | - "*" 19 | 20 | VALIDATORS: 21 | - id: InsertableRegex 22 | enforce: true 23 | insertable: true 24 | params: /{{{?[a-zA-Z_0-9]+}?}}/ 25 | 26 | INSERTABLES: 27 | - class: HtmlTagInsertablesSuggester 28 | 29 | TAGS: 30 | ignored: 31 | - serve-non-translated-text 32 | optional: 33 | - serve-book-category.gutenberg 34 | - serve-book-category.iFixit 35 | - serve-book-category.mooc 36 | - serve-book-category.phet 37 | - serve-book-category.stack_exchange 38 | - serve-book-category.ted 39 | - serve-book-category.vikidia 40 | - serve-book-category.wikihow 41 | -------------------------------------------------------------------------------- /groups/Kiwix/KiwixZimitFrontend.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | BASIC: 3 | id: kiwix-zimit-frontend 4 | label: Kiwix Zimit Frontend 5 | icon: wiki://Kiwix_icon.svg 6 | description: "{{Special:MyLanguage/Translations:Group descriptions/kiwix-zimit-frontend/en}}" 7 | namespace: NS_KIWIX 8 | class: FileBasedMessageGroup 9 | support: 10 | url: https://github.com/openzim/zimit-frontend/issues 11 | params: 12 | title: Translation issue with message %MESSAGE% 13 | body: "\n\nURL: %MESSAGE_URL%" 14 | 15 | FILES: 16 | format: Json 17 | sourcePattern: "%GROUPROOT%/kiwix-zimit-frontend/locales/%CODE%.json" 18 | nestingSeparator: . 19 | 20 | MANGLER: 21 | class: StringMatcher 22 | prefix: zimit-ui- 23 | patterns: 24 | - "*" 25 | 26 | VALIDATORS: 27 | - id: InsertableRegex 28 | enforce: true 29 | insertable: true 30 | params: /\%*{[a-zA-Z0-9_]+\}/ 31 | 32 | TAGS: 33 | optional: 34 | - zimit-ui-requestStatus.progressMessage 35 | 36 | -------------------------------------------------------------------------------- /groups/MantisBT/CodevTT.yaml: -------------------------------------------------------------------------------- 1 | BASIC: 2 | id: codev 3 | label: CodevTT 4 | icon: wiki://CodevTT_logo.png 5 | description: "{{Special:MyLanguage/Translations:Group descriptions/codev/en}}" 6 | namespace: NS_MANTIS 7 | class: FileBasedMessageGroup 8 | codeBrowser: "https://github.com/mantisbt-plugins/codev/blob/master/%FILE%#L%LINE%" 9 | 10 | FILES: 11 | format: Gettext 12 | sourcePattern: "%GROUPROOT%/codev/i18n/locale/%CODE%/LC_MESSAGES/codev.po" 13 | definitionFile: "%GROUPROOT%/codev/i18n/locale/codevtt.pot" 14 | codeMap: 15 | cs: cs_CZ 16 | de: de_DE 17 | en-gb: en_GB 18 | es: es_ES 19 | fr: fr_FR 20 | it: it_IT 21 | ja: ja_JP 22 | nb: nb_NO 23 | nl: nl_NL 24 | nn: nn_NO 25 | pl: pl_PL 26 | pt-br: pt_BR 27 | pt: pt_PT 28 | sv: sv_SE 29 | vi: vi_VN 30 | zh-hans: zh_CN 31 | zh-hant: zh_TW 32 | 33 | MANGLER: 34 | class: StringMatcher 35 | prefix: codev- 36 | patterns: 37 | - "*" 38 | -------------------------------------------------------------------------------- /groups/MediaWiki/MirahezeAgg.yaml: -------------------------------------------------------------------------------- 1 | BASIC: 2 | id: miraheze 3 | label: Miraheze 4 | icon: wiki://Miraheze-Logo.svg 5 | meta: yes 6 | class: AggregateMessageGroup 7 | description: "{{Special:MyLanguage/Translations:Group descriptions/miraheze/en}}" 8 | namespace: NS_MEDIAWIKI 9 | 10 | GROUPS: 11 | - mwgithub-createwiki 12 | - mwgithub-datadump 13 | - mwgithub-globalnewfiles 14 | - mwgithub-importdump 15 | - mwgithub-incidentreporting 16 | - mwgithub-managewiki 17 | - mwgithub-matomoanalytics 18 | - mwgithub-miraheze-discordnotifications 19 | - mwgithub-mirahezeerrorpages 20 | - mwgithub-mirahezelanding 21 | - mwgithub-mirahezemagic-custom 22 | - mwgithub-mirahezemagic-managewiki 23 | - mwgithub-mirahezemagic-override 24 | - mwgithub-pdfembed 25 | - mwgithub-removepii 26 | - mwgithub-requestssl 27 | - mwgithub-rottenlinks 28 | - mwgithub-wikidiscover 29 | - mwgithub-youtube 30 | -------------------------------------------------------------------------------- /groups/MediaWiki/SkinsAgg.yaml: -------------------------------------------------------------------------------- 1 | TEMPLATE: 2 | BASIC: 3 | icon: wiki://MediaWiki-2020-icon.svg 4 | meta: yes 5 | namespace: NS_MEDIAWIKI 6 | class: AggregateMessageGroup 7 | 8 | --- 9 | BASIC: 10 | id: mediawiki-skin-0-all 11 | label: MediaWiki skins 12 | description: '{{Special:MyLanguage/Translations:Group descriptions/mediawikiskins/en}}' 13 | 14 | GROUPS: 15 | - mediawiki-skin-* 16 | - mwbitbucketskin-* 17 | - mwgithubskin-* 18 | - mwgitlabskin-* 19 | -------------------------------------------------------------------------------- /groups/MediaWiki/SocialProfileAgg.yaml: -------------------------------------------------------------------------------- 1 | BASIC: 2 | id: ext-socialprofile-0-all 3 | label: All SocialProfile messages 4 | icon: wiki://MediaWiki-2020-icon.svg 5 | meta: yes 6 | class: AggregateMessageGroup 7 | description: '{{int:translate-group-desc-socialprofile}}' 8 | namespace: NS_MEDIAWIKI 9 | 10 | GROUPS: 11 | - ext-socialprofile-systemgifts 12 | - ext-socialprofile-useractivity 13 | - ext-socialprofile-userboard 14 | - ext-socialprofile-usergifts 15 | - ext-socialprofile-userprofile 16 | - ext-socialprofile-userrelationship 17 | - ext-socialprofile-userstats 18 | - ext-socialprofile-userwelcome 19 | -------------------------------------------------------------------------------- /groups/MediaWiki/SocialToolsAgg.yaml: -------------------------------------------------------------------------------- 1 | BASIC: 2 | id: ext-socialtools 3 | label: All i18n messages for all social tools 4 | icon: wiki://MediaWiki-2020-icon.svg 5 | meta: yes 6 | class: AggregateMessageGroup 7 | description: '{{Special:MyLanguage/Translations:Group descriptions/socialtools/en}}' 8 | namespace: NS_MEDIAWIKI 9 | 10 | GROUPS: 11 | - ext-socialprofile-0-all 12 | - ext-ajaxpoll 13 | - ext-blogpage 14 | - ext-challenge 15 | - ext-fanboxes 16 | - ext-imagerating 17 | - ext-linkfilter 18 | - ext-miniinvite 19 | - ext-newsignuppage 20 | - ext-picturegame 21 | - ext-pollny 22 | - ext-quizgame 23 | - ext-randomgameunit 24 | - ext-sitemetrics 25 | - ext-sportsteams 26 | - ext-userstatus-* 27 | - ext-voteny 28 | - ext-video 29 | - ext-wikiforum 30 | - ext-wikitextloggedinout 31 | -------------------------------------------------------------------------------- /groups/MediaWiki/WikimediaAgg.yaml: -------------------------------------------------------------------------------- 1 | BASIC: 2 | id: ext-0-wikimedia 3 | label: Extensions used by Wikimedia 4 | icon: wiki://MediaWiki-2020-icon.svg 5 | meta: yes 6 | class: AggregateMessageGroup 7 | description: '{{Special:MyLanguage/Translations:Group descriptions/wikimediaextensions/en}}' 8 | namespace: NS_MEDIAWIKI 9 | 10 | GROUPS: # See Wikimedia*Agg.yaml. Do not duplicate group names! 11 | - wikimedia-main 12 | - wikimedia-advanced 13 | - wikimedia-fundraising 14 | - wikimedia-legacy 15 | - wikimedia-media 16 | - wikimedia-upcoming 17 | - wikimedia-wikivoyage 18 | - wikimedia-technical 19 | -------------------------------------------------------------------------------- /groups/MediaWiki/WikimediaFundraisingAgg.yaml: -------------------------------------------------------------------------------- 1 | BASIC: 2 | id: wikimedia-fundraising 3 | label: Extensions used by Wikimedia - Fundraising 4 | icon: wiki://MediaWiki-2020-icon.svg 5 | meta: yes 6 | class: AggregateMessageGroup 7 | description: '{{Special:MyLanguage/Translations:Group descriptions/wikimediaextensions-fundraising/en}}' 8 | namespace: NS_MEDIAWIKI 9 | 10 | GROUPS: 11 | - ext-di-epf 12 | - ext-di-gc 13 | - ext-fundraiserlandingpage # r101409 for donatewiki 14 | - ext-fundraisingemailunsubscribe 15 | - ext-fundraisingtranslateworkflow # 2014-07-14 for Meta 16 | - ext-landingcheck 17 | -------------------------------------------------------------------------------- /groups/MediaWiki/WikimediaLegacyAgg.yaml: -------------------------------------------------------------------------------- 1 | BASIC: 2 | id: wikimedia-legacy 3 | label: Extensions used by Wikimedia - Legacy 4 | icon: wiki://MediaWiki-2020-icon.svg 5 | meta: yes 6 | class: AggregateMessageGroup 7 | description: '{{Special:MyLanguage/Translations:Group descriptions/wikimediaextensions-legacy/en}}' 8 | namespace: NS_MEDIAWIKI 9 | 10 | GROUPS: 11 | # FlaggedRevs is no longer installed on new Wikimedia wikis 12 | - ext-flaggedrevs-flaggedrevs 13 | - ext-flaggedrevs-configuredpages 14 | - ext-flaggedrevs-pendingchanges 15 | - ext-flaggedrevs-qualityoversight 16 | - ext-flaggedrevs-revisionreview 17 | - ext-flaggedrevs-stabilization 18 | - ext-flaggedrevs-stablepages 19 | - ext-flaggedrevs-unreviewedpages 20 | - ext-flaggedrevs-validationstatistics 21 | - ext-flow-user 22 | - ext-liquidthreads # Installed on very few wikis and no longer installed on new ones 23 | - ext-listings # T253216 24 | - ext-ores # https://www.mediawiki.org/wiki/Topic:Wx1wkmwnerl0pwmj - no longer installed on new wikis 25 | - ext-shorturl # No longer installed on new wikis, replaced with UrlShortener 26 | - ext-wikimediaundeployedplaceholders # https://gerrit.wikimedia.org/r/c/mediawiki/extensions/WikimediaMessages/+/752150 27 | - mediawiki-skin-cologneblue # Installed, but not updated and used by very few people 28 | - mediawiki-skin-modern # Installed, but not updated and used by very few people 29 | -------------------------------------------------------------------------------- /groups/MediaWiki/WikimediaMediaAgg.yaml: -------------------------------------------------------------------------------- 1 | BASIC: 2 | id: wikimedia-media 3 | label: Extensions used by Wikimedia - Media 4 | icon: wiki://MediaWiki-2020-icon.svg 5 | meta: yes 6 | class: AggregateMessageGroup 7 | description: '{{Special:MyLanguage/Translations:Group descriptions/wikimediaextensions-media/en}}' 8 | namespace: NS_MEDIAWIKI 9 | 10 | GROUPS: 11 | - ext-3D 12 | - ext-commonsmetadata # Change id ecfa294d4b158aa5c44c166fa883d8ceef7d357d 13 | - ext-fileexporter # https://phabricator.wikimedia.org/rOMWCed0953cf03e16621029ba7b21b716d448e387de0 14 | - ext-fileimporter # https://phabricator.wikimedia.org/rOMWCed0953cf03e16621029ba7b21b716d448e387de0 15 | - ext-imagemap 16 | - ext-mediasearch 17 | - ext-pdfhandler 18 | - ext-phonos # https://phabricator.wikimedia.org/rOMWC8a38488adb7a140238ae198c269847f3f94b5e8f 19 | - ext-uploadslink # 2016-05-04: Commons, 7e1cd07dba434c0a433672a2da97b5224d3aaecd 20 | - ext-wikibasemediainfo # https://phabricator.wikimedia.org/rOMWCef62d89def2ab616c2ca47d3165b65116c4a45ea 21 | - ext-wikimediacreativecommonslicensetexts # commons.wikimedia.org 22 | - mediawiki-exif 23 | -------------------------------------------------------------------------------- /groups/MediaWiki/WikimediaUpcomingAgg.yaml: -------------------------------------------------------------------------------- 1 | BASIC: 2 | id: wikimedia-upcoming 3 | label: Extensions used by Wikimedia - Upcoming 4 | icon: wiki://MediaWiki-2020-icon.svg 5 | meta: yes 6 | class: AggregateMessageGroup 7 | description: '{{Special:MyLanguage/Translations:Group descriptions/wikimediaextensions-upcoming/en}}' 8 | namespace: NS_MEDIAWIKI 9 | 10 | GROUPS: 11 | - ext-articlesummaries # https://phabricator.wikimedia.org/rOMWCe262ae3da8b76dd7f79a2ca9c72b5c9c5164daa6 12 | - ext-capiunto # wikidataclient-test 13 | - ext-chart # https://phabricator.wikimedia.org/rOMWC87d69e644b112a71bedc948c824400172d2f586c 14 | - ext-chessbrowser # https://phabricator.wikimedia.org/rOMWCba8b786c7f3a290f0747a6859fd07502eb83108f 15 | - ext-pagenotice # https://phabricator.wikimedia.org/rOMWCd3b399694f2b03af6ee029fb0cf1e3e9939e7a5b: 16 | - ext-reportincident # https://phabricator.wikimedia.org/rOMWCf594ec5484fac1b992138e573369ffae8bdeba36 17 | - ext-stopforumspam # Deployed experimentally on several wikis. Move to Advanced when the deployment becomes wider. https://phabricator.wikimedia.org/rOMWCf3de027936c615d7a310793d85a836350fcdc1df 18 | - ext-wikilambda-ve # Planned to be enabled on client wikis. Move to Advanced or Main when the deployment becomes wider. 19 | - ext-wikistories # Deployed only on one wiki in beta. Move to Advanced when the deployment becomes wider. https://phabricator.wikimedia.org/rOMWC88ac6b94ff5acfbcd6a539e21b7454b6a38eaaba 20 | -------------------------------------------------------------------------------- /groups/MediaWiki/WikimediaWikivoyageAgg.yaml: -------------------------------------------------------------------------------- 1 | BASIC: 2 | id: wikimedia-wikivoyage 3 | label: Extensions used by Wikimedia - Wikivoyage 4 | icon: wiki://MediaWiki-2020-icon.svg 5 | meta: yes 6 | class: AggregateMessageGroup 7 | description: '{{Special:MyLanguage/Translations:Group descriptions/wikimediaextensions-wikivoyage/en}}' 8 | namespace: NS_MEDIAWIKI 9 | 10 | GROUPS: 11 | - ext-calendar # Change id bc3616c74aab74b74f78bbb2ce3241e5a564b4f9 for Wikivoyage 12 | - ext-creditssource # Change id bc3616c74aab74b74f78bbb2ce3241e5a564b4f9 for Wikivoyage 13 | - ext-geocrumbs # Change id bc3616c74aab74b74f78bbb2ce3241e5a564b4f9 for Wikivoyage 14 | - ext-insider # Change id bc3616c74aab74b74f78bbb2ce3241e5a564b4f9 for Wikivoyage 15 | - ext-kartographer-wv 16 | - ext-mapsources # wikivoyage 17 | - ext-relatedarticles # Change id bc3616c74aab74b74f78bbb2ce3241e5a564b4f9 for Wikivoyage 18 | - ext-toctree # Change id bc3616c74aab74b74f78bbb2ce3241e5a564b4f9 for Wikivoyage 19 | -------------------------------------------------------------------------------- /groups/MediaWiki/mwbitbucket.yaml: -------------------------------------------------------------------------------- 1 | TEMPLATE: 2 | BASIC: 3 | icon: wiki://MediaWiki-2020-icon.svg 4 | class: FileBasedMessageGroup 5 | namespace: NS_MEDIAWIKI 6 | 7 | FILES: 8 | format: Json 9 | 10 | VALIDATORS: 11 | - id: BraceBalance 12 | - id: MediaWikiLink 13 | - id: MediaWikiPageName 14 | - id: MediaWikiParameter 15 | - id: MediaWikiPlural 16 | 17 | INSERTABLES: 18 | - class: MediaWikiInsertablesSuggester 19 | 20 | --- 21 | BASIC: 22 | id: mwbitbucketskin-medik 23 | label: Medik 24 | description: "{{Special:MyLanguage/MediaWiki:Medik-desc/en}}" 25 | 26 | FILES: 27 | format: Json 28 | sourcePattern: "%GROUPROOT%/mwbitbucket/wikiskripta/medik/i18n/%CODE%.json" 29 | -------------------------------------------------------------------------------- /groups/MediaWiki/mwgitlab.yaml: -------------------------------------------------------------------------------- 1 | TEMPLATE: 2 | BASIC: 3 | icon: wiki://MediaWiki-2020-icon.svg 4 | class: FileBasedMessageGroup 5 | namespace: NS_MEDIAWIKI 6 | 7 | FILES: 8 | format: Json 9 | 10 | VALIDATORS: 11 | - id: BraceBalance 12 | - id: MediaWikiLink 13 | - id: MediaWikiPageName 14 | - id: MediaWikiParameter 15 | - id: MediaWikiPlural 16 | 17 | INSERTABLES: 18 | - class: MediaWikiInsertablesSuggester 19 | 20 | --- 21 | BASIC: 22 | id: mwgitlab-ratepage-user 23 | label: RatePage - User interface 24 | description: "{{Special:MyLanguage/MediaWiki:RatePage-desc/en}}" 25 | 26 | FILES: 27 | format: Json 28 | sourcePattern: "%GROUPROOT%/mwgitlab/nonsensopedia/ratepage/i18n/%CODE%.json" 29 | 30 | TAGS: 31 | optional: 32 | - ratePage 33 | --- 34 | BASIC: 35 | id: mwgitlab-ratepage-api 36 | label: RatePage - API 37 | description: "{{Special:MyLanguage/MediaWiki:RatePage-desc/en}}" 38 | 39 | FILES: 40 | format: Json 41 | sourcePattern: "%GROUPROOT%/mwgitlab/nonsensopedia/ratepage/i18n/api/%CODE%.json" 42 | --- 43 | BASIC: 44 | id: mwgitlab-userprofilev2 45 | label: UserProfileV2 46 | description: "{{Special:MyLanguage/MediaWiki:UserProfileV2-desc/en}}" 47 | support: 48 | url: https://telepedia.atlassian.net/servicedesk/customer/portal/1/group/1/create/6 49 | params: 50 | description: "%MESSAGE_URL%" 51 | summary: Translation issue with message %MESSAGE% 52 | 53 | FILES: 54 | format: Json 55 | sourcePattern: "%GROUPROOT%/mwgitlab/telepedia/userprofilev2/i18n/%CODE%.json" 56 | 57 | TAGS: 58 | optional: 59 | - UserProfileV2 60 | - prefs-profile 61 | ignored: 62 | - userprofilev2-discord-placeholder 63 | - userprofilev2-twitter-placeholder 64 | - userprofilev2-mastodon-placeholder 65 | -------------------------------------------------------------------------------- /groups/MediaWiki/repong-generator.php: -------------------------------------------------------------------------------- 1 | 'wmgerrit', 32 | 'url' => "https://gerrit.wikimedia.org/r/mediawiki/$type/$name", 33 | 'url|export' => "ssh://l10n-bot@gerrit.wikimedia.org:29418/mediawiki/$type/$name", 34 | ]; 35 | } 36 | 37 | return $config; 38 | } 39 | 40 | $type = $argv[ 1 ]; 41 | if ( $type === 'extensions' || $type === 'skins' ) { 42 | $config = makeRepoConfig( $type ); 43 | echo json_encode( $config, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES ); 44 | } else { 45 | echo "Invalid type: $type\n"; 46 | exit( 1 ); 47 | } 48 | -------------------------------------------------------------------------------- /groups/NFCRingControl/NFCRingControl.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | BASIC: 3 | id: nfcring-control 4 | label: NFC Ring Control 5 | icon: wiki://McLear_Crest_Cropped.svg 6 | description: "{{Special:MyLanguage/Translations:Group descriptions/nfcring-control/en}}" 7 | namespace: NS_NFCRINGCONTROL 8 | class: FileBasedMessageGroup 9 | 10 | FILES: 11 | format: Json 12 | sourcePattern: "%GROUPROOT%/nfcring-control/www/locales/%CODE%.json" 13 | -------------------------------------------------------------------------------- /groups/OpenStreetMap/WaymarkedTrails.yaml: -------------------------------------------------------------------------------- 1 | BASIC: 2 | id: out-waymarked-trails-0-all 3 | label: Waymarked Trails 4 | icon: wiki://Waymarked_Trails_logo.svg 5 | description: "{{Special:MyLanguage/Translations:Group descriptions/waymarked-trails/en}}" 6 | namespace: NS_OSM 7 | meta: yes 8 | class: AggregateMessageGroup 9 | 10 | GROUPS: 11 | - out-waymarked-trails 12 | - out-waymarked-trails-help 13 | 14 | --- 15 | BASIC: 16 | id: out-waymarked-trails 17 | label: Waymarked Trails Website 18 | icon: wiki://Waymarked_Trails_logo.svg 19 | description: "{{Special:MyLanguage/Translations:Group descriptions/waymarked-trails/en}}" 20 | namespace: NS_OSM 21 | class: FileBasedMessageGroup 22 | 23 | MANGLER: 24 | class: StringMatcher 25 | prefix: wmt- 26 | patterns: 27 | - "*" 28 | 29 | FILES: 30 | format: Yaml 31 | sourcePattern: "%GROUPROOT%/waymarkedtrails-website/src/i18n/%CODE%/messages.yaml" 32 | definitionFile: "%GROUPROOT%/waymarkedtrails-website/src/i18n/qot/messages.yaml" 33 | codeMap: 34 | # This is needed because they have symlinked no to nb to avoid import 35 | "no": x-invalidLanguageCode 36 | 37 | TAGS: 38 | optional: 39 | - wmt-details.Wikipedia 40 | 41 | --- 42 | BASIC: 43 | id: out-waymarked-trails-help 44 | label: Waymarked Trails Help 45 | icon: wiki://Waymarked_Trails_logo.svg 46 | description: "{{Special:MyLanguage/Translations:Group descriptions/waymarked-trails-help/en}}" 47 | namespace: NS_OSM 48 | class: FileBasedMessageGroup 49 | 50 | MANGLER: 51 | class: StringMatcher 52 | prefix: wmthelp- 53 | patterns: 54 | - "*" 55 | 56 | FILES: 57 | format: Yaml 58 | sourcePattern: "%GROUPROOT%/waymarkedtrails-website/src/i18n/%CODE%/helppages.yaml" 59 | definitionFile: "%GROUPROOT%/waymarkedtrails-website/src/i18n/qot/helppages.yaml" 60 | -------------------------------------------------------------------------------- /groups/Oppia/Oppia.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | BASIC: 3 | id: oppia 4 | label: Oppia 5 | icon: wiki://Oppia_logo.png 6 | description: "{{Special:MyLanguage/Translations:Group descriptions/oppia/en}}" 7 | namespace: NS_OPPIA 8 | class: FileBasedMessageGroup 9 | 10 | FILES: 11 | format: Json 12 | sourcePattern: "%GROUPROOT%/oppia/assets/i18n/%CODE%.json" 13 | definitionFile: "%GROUPROOT%/oppia/assets/i18n/en.json" 14 | includeMetadata: false 15 | 16 | VALIDATORS: 17 | # Variables: <[listOfNames]>, <[sectionNameI18nId | translate]> 18 | - id: InsertableRegex 19 | insertable: true 20 | enforce: true 21 | params: /<\[[a-zA-Z_\ |1-9]+\]>/ 22 | 23 | INSERTABLES: 24 | - class: HtmlTagInsertablesSuggester 25 | # For HTML entities 26 | - class: RegexInsertablesSuggester 27 | params: '/&#?\w+;/' 28 | -------------------------------------------------------------------------------- /groups/PageTranslationAgg.yaml: -------------------------------------------------------------------------------- 1 | BASIC: 2 | id: page-0-all 3 | label: Translatable pages 4 | meta: yes 5 | class: AggregateMessageGroup 6 | description: "{{Special:MyLanguage/Translations:Group descriptions/translatablepages/en}}" 7 | namespace: NS_TRANSLATIONS 8 | 9 | GROUPS: 10 | - page-* 11 | -------------------------------------------------------------------------------- /groups/Phabricator/PhabricatorAgg.yaml: -------------------------------------------------------------------------------- 1 | BASIC: 2 | id: phabricator 3 | label: Phabricator 4 | icon: wiki://Phacility_phabricator_logo.svg 5 | meta: yes 6 | namespace: NS_PHABRICATOR 7 | class: AggregateMessageGroup 8 | description: > 9 | [[Translating:Phabricator|Phabricator]] is a suite of web-based development collaboration tools. 10 | For now these translations are only applied to the Wikimedia installation of Phabricator. 11 | The goal is to promote these translations to be the "official" ones for Phabricator. 12 | 13 | GROUPS: 14 | - phabricator-* 15 | -------------------------------------------------------------------------------- /groups/Phabricator/generate-yaml.php: -------------------------------------------------------------------------------- 1 | [ 12 | 'id' => "phabricator-$project-$component", 13 | 'label' => "Phabricator ($project > $component)", 14 | ], 15 | 'FILES' => [ 16 | 'sourcePattern' => "%GROUPROOT%/phabricator/projects/$project/$component/%CODE%.json" 17 | ], 18 | 'MANGLER' => [ 19 | 'prefix' => "$project-$component-", 20 | ], 21 | ]; 22 | 23 | $specification .= yaml_emit( $stuff ) . "\n"; 24 | } 25 | 26 | echo str_replace( "...\n", '', $specification ); 27 | -------------------------------------------------------------------------------- /groups/Vicuna/Vicuna.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | BASIC: 3 | id: out-vicuna 4 | label: VicuñaUploader 5 | icon: wiki://VicunaUploader_logo.png 6 | description: "{{Special:MyLanguage/Translations:Group descriptions/vicuna/en}}" 7 | namespace: NS_VICUNA 8 | class: FileBasedMessageGroup 9 | 10 | FILES: 11 | format: Java 12 | sourcePattern: "%GROUPROOT%/vicuna/src/main/resources/cuploader/text_utf8/messages_%CODE%.properties" 13 | definitionFile: "%GROUPROOT%/vicuna/src/main/resources/cuploader/text_utf8/messages.properties" 14 | codeMap: 15 | cs: cs_CZ 16 | es: es_ES 17 | it: it_IT 18 | nb: nb_NO 19 | pl: pl_PL 20 | sv: sv_SE 21 | en-gb: en_GB 22 | pt: pt_PT 23 | pt-br: pt_BR 24 | zh-hans: zh_CN 25 | -------------------------------------------------------------------------------- /groups/Wikidocumentaries/Wikidocumentaries.yaml: -------------------------------------------------------------------------------- 1 | BASIC: 2 | id: wikidocumentaries 3 | label: Wikidocumentaries 4 | description: "{{Special:MyLanguage/Translations:Group descriptions/wikidocumentaries/en}}" 5 | class: FileBasedMessageGroup 6 | namespace: NS_WIKIDOCUMENTARIES 7 | 8 | MANGLER: 9 | class: StringMatcher 10 | prefix: ui- 11 | patterns: 12 | - "*" 13 | 14 | FILES: 15 | format: Json 16 | sourcePattern: "%GROUPROOT%/Wikidocumentaries/wikidocumentaries-ui/src/store/translation/%CODE%.json" 17 | nestingSeparator: . 18 | -------------------------------------------------------------------------------- /groups/Wikimedia/Adiutor.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | BASIC: 3 | id: adiutor 4 | label: Adiutor 5 | icon: wiki://Adiutor_icon.svg 6 | description: "{{Special:MyLanguage/Translations:Group descriptions/adiutor/en}}" 7 | namespace: NS_WIKIMEDIA 8 | class: FileBasedMessageGroup 9 | support: 10 | url: https://meta.wikimedia.org/wiki/Talk:Adiutor 11 | params: 12 | action: edit 13 | section: new 14 | preloadtitle: Translation issue with message %MESSAGE% 15 | preloadparams: "%MESSAGE_URL%" 16 | preload: Translatewiki.net/New_issue_template 17 | 18 | MANGLER: 19 | class: StringMatcher 20 | prefix: adiutor- 21 | patterns: 22 | - "*" 23 | 24 | FILES: 25 | format: Json 26 | sourcePattern: "%GROUPROOT%/adiutor/i18n/%CODE%.json" 27 | 28 | VALIDATORS: 29 | - id: MediaWikiParameter 30 | insertable: true 31 | enforce: false 32 | - id: MediaWikiPlural 33 | - id: BraceBalance 34 | 35 | INSERTABLES: 36 | - class: MediaWikiInsertablesSuggester 37 | - class: UrlInsertablesSuggester 38 | -------------------------------------------------------------------------------- /groups/Wikimedia/Anvesha.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | BASIC: 3 | id: anvesha 4 | label: Anvesha 5 | description: "{{Special:MyLanguage/Translations:Group descriptions/anvesha/en}}" 6 | namespace: NS_WIKIMEDIA 7 | class: FileBasedMessageGroup 8 | 9 | MANGLER: 10 | class: StringMatcher 11 | prefix: anvesha- 12 | patterns: 13 | - "*" 14 | 15 | FILES: 16 | format: Json 17 | sourcePattern: "%GROUPROOT%/anvesha/languages/%CODE%.json" 18 | 19 | VALIDATORS: 20 | - id: MediaWikiParameter 21 | insertable: true 22 | enforce: false 23 | - id: MediaWikiPlural 24 | - id: BraceBalance -------------------------------------------------------------------------------- /groups/Wikimedia/CapacityExchange.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | BASIC: 3 | id: capacity-exchange 4 | label: Capacity Exchange 5 | description: "{{Special:MyLanguage/Translations:Group descriptions/capacity-exchange/en}}" 6 | namespace: NS_WIKIMEDIA 7 | class: FileBasedMessageGroup 8 | support: 9 | url: https://github.com/wikimediabrasil/capx-frontend/issues/new 10 | params: 11 | title: Translation issue with message %MESSAGE% 12 | body: "\n\nURL: %MESSAGE_URL%" 13 | 14 | MANGLER: 15 | class: StringMatcher 16 | prefix: capex- 17 | patterns: 18 | - "*" 19 | 20 | FILES: 21 | format: Json 22 | sourcePattern: "%GROUPROOT%/capacity-exchange/locales/%CODE%.json" 23 | 24 | TAGS: 25 | optional: 26 | - capex-footer-link-github 27 | -------------------------------------------------------------------------------- /groups/Wikimedia/CeJS.yaml: -------------------------------------------------------------------------------- 1 | BASIC: 2 | id: cejs 3 | label: Colorless echo JavaScript kit 4 | description: "{{Special:MyLanguage/Translations:Group descriptions/cejs/en}}" 5 | namespace: NS_WIKIMEDIA 6 | class: FileBasedMessageGroup 7 | support: 8 | url: https://github.com/kanasimi/CeJS/issues/new 9 | params: 10 | title: Translation issue with message %MESSAGE% 11 | body: "\n\nURL: %MESSAGE_URL%" 12 | 13 | FILES: 14 | format: Json 15 | sourcePattern: "%GROUPROOT%/cejs/application/locale/resources/i18n/%CODE%.json" 16 | 17 | MANGLER: 18 | class: StringMatcher 19 | prefix: cejs- 20 | patterns: 21 | - "*" 22 | 23 | TAGS: 24 | ignored: 25 | - cejs-untranslated-message-count 26 | 27 | VALIDATORS: 28 | - id: InsertableRegex 29 | insertable: true 30 | enforce: true 31 | params: /%[A-Za-z1-9]%?/ 32 | - id: MediaWikiPlural 33 | -------------------------------------------------------------------------------- /groups/Wikimedia/Cita.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | BASIC: 3 | id: cita 4 | label: Cita 5 | description: "{{Special:MyLanguage/Translations:Group descriptions/cita/en}}" 6 | icon: wiki://Cita_addon_logo.svg 7 | namespace: NS_WIKIMEDIA 8 | class: FileBasedMessageGroup 9 | 10 | MANGLER: 11 | class: StringMatcher 12 | prefix: cita- 13 | patterns: 14 | - "*" 15 | 16 | FILES: 17 | format: Java 18 | sourcePattern: "%GROUPROOT%/cita/static/chrome/locale/%CODE%/wikicite.properties" 19 | codeMap: 20 | en: en-US 21 | 22 | VALIDATORS: 23 | - id: Printf 24 | insertable: true 25 | - id: BraceBalance 26 | 27 | TAGS: 28 | optional: 29 | - cita-wikicite.global.name 30 | - cita-wikicite.item.doi 31 | - cita-wikicite.item.occ 32 | - cita-wikicite.item.qid 33 | - cita-wikicite.submenu.label 34 | -------------------------------------------------------------------------------- /groups/Wikimedia/CitationHunt.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | BASIC: 3 | id: citationhunt 4 | label: CitationHunt 5 | description: "{{Special:MyLanguage/Translations:Group descriptions/citationhunt/en}}" 6 | namespace: NS_WIKIMEDIA 7 | class: FileBasedMessageGroup 8 | 9 | MANGLER: 10 | class: StringMatcher 11 | prefix: citationhunt- 12 | patterns: 13 | - "*" 14 | 15 | FILES: 16 | format: Json 17 | sourcePattern: "%GROUPROOT%/citationhunt/chstrings/%CODE%.json" 18 | 19 | VALIDATORS: 20 | - id: Printf 21 | insertable: true 22 | # {link_end} 23 | - id: InsertableRegex 24 | insertable: true 25 | params: /{[a-zA-Z_]+}/ 26 | - id: MediaWikiPlural 27 | 28 | INSERTABLES: 29 | # HTML entities 30 | - class: RegexInsertablesSuggester 31 | params: '/&#?\w+;/' 32 | 33 | TAGS: 34 | optional: 35 | - citationhunt-tooltitle -------------------------------------------------------------------------------- /groups/Wikimedia/ConvenientDiscussions.yaml: -------------------------------------------------------------------------------- 1 | BASIC: 2 | id: convenient-discussions 3 | label: Convenient Discussions 4 | icon: wiki://Convenient_Discussions_logo_color.svg 5 | description: "{{Special:MyLanguage/Translations:Group descriptions/convenient-discussions/en}}" 6 | class: FileBasedMessageGroup 7 | namespace: NS_WIKIMEDIA 8 | 9 | MANGLER: 10 | class: StringMatcher 11 | prefix: convenient-discussions- 12 | patterns: 13 | - "*" 14 | 15 | FILES: 16 | format: Json 17 | sourcePattern: "%GROUPROOT%/jwbth/convenient-discussions/i18n/%CODE%.json" 18 | 19 | TAGS: 20 | optional: 21 | - convenient-discussions-cm-gotoparent 22 | - convenient-discussions-cm-gotochild 23 | - convenient-discussions-cf-autocomplete-commentlinks-text 24 | - convenient-discussions-cf-help 25 | - convenient-discussions-cf-help-short 26 | - convenient-discussions-cm-copylink 27 | - convenient-discussions-dot-separator 28 | - convenient-discussions-ellipsis 29 | - convenient-discussions-script-name-short 30 | - convenient-discussions-sm-copylink 31 | - convenient-discussions-toc-commentcount-new 32 | - convenient-discussions-user-male-dative 33 | - convenient-discussions-user-female-dative 34 | - convenient-discussions-user-unknown-dative 35 | - convenient-discussions-user-male-genitive 36 | - convenient-discussions-user-female-genitive 37 | - convenient-discussions-user-unknown-genitive 38 | - convenient-discussions-navpanel-newcomments-names 39 | - convenient-discussions-bullet 40 | 41 | VALIDATORS: 42 | - id: BraceBalance 43 | - id: MediaWikiParameter 44 | insertable: true 45 | - id: MediaWikiPlural 46 | 47 | INSERTABLES: 48 | - class: HtmlTagInsertablesSuggester 49 | # HTML entities 50 | - class: RegexInsertablesSuggester 51 | params: '/&#?\w+;/' 52 | -------------------------------------------------------------------------------- /groups/Wikimedia/CopyPatrol.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | BASIC: 3 | id: copypatrol 4 | label: CopyPatrol 5 | icon: wiki://Dialog-error-copyright.svg 6 | description: "{{Special:MyLanguage/Translations:Group descriptions/copypatrol/en}}" 7 | class: FileBasedMessageGroup 8 | namespace: NS_WIKIMEDIA 9 | 10 | MANGLER: 11 | class: StringMatcher 12 | prefix: copypatrol- 13 | patterns: 14 | - "*" 15 | 16 | FILES: 17 | format: Json 18 | sourcePattern: "%GROUPROOT%/copypatrol/i18n/%CODE%.json" 19 | 20 | VALIDATORS: 21 | - id: NumericalParameter 22 | insertable: true 23 | 24 | TAGS: 25 | optional: 26 | - copypatrol-name 27 | - copypatrol-footer-commtech 28 | - copypatrol-phabricator 29 | -------------------------------------------------------------------------------- /groups/Wikimedia/DiscordWikiBot.yaml: -------------------------------------------------------------------------------- 1 | BASIC: 2 | id: discordwikibot 3 | label: DiscordWikiBot 4 | namespace: NS_WIKIMEDIA 5 | class: FileBasedMessageGroup 6 | description: "{{Special:MyLanguage/Translations:Group descriptions/discordwikibot/en}}" 7 | 8 | FILES: 9 | format: Json 10 | sourcePattern: "%GROUPROOT%/stjohann/DiscordWikiBot/DiscordWikiBot/i18n/%CODE%.json" 11 | 12 | MANGLER: 13 | class: StringMatcher 14 | prefix: discordwikibot- 15 | patterns: 16 | - "*" 17 | 18 | TAGS: 19 | optional: 20 | - discordwikibot-bullet 21 | - discordwikibot-comma 22 | - discordwikibot-separator 23 | 24 | VALIDATORS: 25 | - id: InsertableRegex 26 | insertable: true 27 | enforce: true 28 | params: /\{[0-9]+\}/ 29 | - id: InsertableRegex 30 | insertable: true 31 | params: /\{msg:[^}]+\}/ 32 | - id: SmartFormatPlural 33 | insertable: true 34 | enforce: true 35 | 36 | LANGUAGES: 37 | exclude: 38 | - en-gb 39 | -------------------------------------------------------------------------------- /groups/Wikimedia/GrantMetrics.yaml: -------------------------------------------------------------------------------- 1 | BASIC: 2 | id: grant-metrics 3 | label: Grant Metrics 4 | icon: wiki://Grant metrics logo.svg 5 | description: "{{Special:MyLanguage/Translations:Group descriptions/grantmetrics/en}}" 6 | class: FileBasedMessageGroup 7 | namespace: NS_WIKIMEDIA 8 | 9 | MANGLER: 10 | class: StringMatcher 11 | prefix: grant-metrics- 12 | patterns: 13 | - "*" 14 | 15 | FILES: 16 | format: Json 17 | sourcePattern: "%GROUPROOT%/grant-metrics/i18n/%CODE%.json" 18 | 19 | TAGS: 20 | optional: 21 | - grant-metrics-num-abbrev-billion 22 | - grant-metrics-num-abbrev-million 23 | - grant-metrics-num-abbrev-thousand 24 | 25 | VALIDATORS: 26 | - id: BraceBalance 27 | - id: MediaWikiParameter 28 | - id: MediaWikiPlural 29 | 30 | INSERTABLES: 31 | - class: MediaWikiInsertablesSuggester 32 | -------------------------------------------------------------------------------- /groups/Wikimedia/InteractionTimeline.yaml: -------------------------------------------------------------------------------- 1 | BASIC: 2 | id: interaction-timeline 3 | label: Interaction Timeline 4 | icon: wiki://Interaction Timeline Logo.svg 5 | description: "{{Special:MyLanguage/Translations:Group descriptions/interaction-timeline/en}}" 6 | class: FileBasedMessageGroup 7 | namespace: NS_WIKIMEDIA 8 | 9 | MANGLER: 10 | class: StringMatcher 11 | prefix: interaction-timeline- 12 | patterns: 13 | - "*" 14 | 15 | FILES: 16 | format: Json 17 | sourcePattern: "%GROUPROOT%/interaction-timeline/i18n/%CODE%.json" 18 | 19 | VALIDATORS: 20 | - id: BraceBalance 21 | - id: MediaWikiParameter 22 | 23 | INSERTABLES: 24 | - class: MediaWikiInsertablesSuggester 25 | -------------------------------------------------------------------------------- /groups/Wikimedia/InternetArchiveBot.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | BASIC: 3 | id: internetarchivebot 4 | label: Internet Archive Bot 5 | icon: wiki://Internet_Archive_logo_and_wordmark.svg 6 | description: "{{Special:MyLanguage/Translations:Group descriptions/internetarchivebot/en}}" 7 | class: FileBasedMessageGroup 8 | namespace: NS_WIKIMEDIA 9 | 10 | MANGLER: 11 | class: StringMatcher 12 | prefix: iabot- 13 | patterns: 14 | - "*" 15 | 16 | FILES: 17 | format: Json 18 | sourcePattern: "%GROUPROOT%/internetarchivebot/app/src/html/i18n/%CODE%.json" 19 | 20 | VALIDATORS: 21 | - id: InsertableRegex 22 | enforce: true 23 | insertable: true 24 | params: /{{[a-zA-Z_]+}}/ 25 | 26 | INSERTABLES: 27 | - class: HtmlTagInsertablesSuggester 28 | 29 | TAGS: 30 | ignored: 31 | - iabot-languageunavailableheader 32 | - iabot-languageunavailablemessage 33 | -------------------------------------------------------------------------------- /groups/Wikimedia/JankClient.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | BASIC: 3 | id: jank-client 4 | label: Jank Client 5 | icon: wiki://Jank-client-logo.png 6 | description: "{{Special:MyLanguage/Translations:Group descriptions/jank-client/en}}" 7 | namespace: NS_WIKIMEDIA 8 | class: FileBasedMessageGroup 9 | support: 10 | url: https://github.com/MathMan05/JankClient/issues/new 11 | params: 12 | title: Translation issue with message %MESSAGE% 13 | body: "\n\nURL: %MESSAGE_URL%" 14 | 15 | FILES: 16 | format: Json 17 | sourcePattern: "%GROUPROOT%/jank-client/translations/%CODE%.json" 18 | nestingSeparator: . 19 | 20 | MANGLER: 21 | class: StringMatcher 22 | prefix: jank-client- 23 | patterns: 24 | - "*" 25 | 26 | VALIDATORS: 27 | - id: MediaWikiParameter 28 | insertable: true 29 | enforce: true 30 | - id: MediaWikiPlural 31 | enforce: true 32 | - id: BraceBalance 33 | enforce: true 34 | -------------------------------------------------------------------------------- /groups/Wikimedia/MiniEdit.yaml: -------------------------------------------------------------------------------- 1 | BASIC: 2 | id: miniedit 3 | label: MiniEdit 4 | description: "{{Special:MyLanguage/Translations:Group descriptions/miniedit/en}}" 5 | class: FileBasedMessageGroup 6 | namespace: NS_WIKIMEDIA 7 | support: 8 | url: https://www.mediawiki.org/wiki/Talk:MiniEdit 9 | params: 10 | action: edit 11 | section: new 12 | preloadtitle: Translation issue with message %MESSAGE% 13 | preloadparams: "%MESSAGE_URL%" 14 | preload: Translatewiki.net/New_issue_template 15 | 16 | FILES: 17 | format: Json 18 | sourcePattern: "%GROUPROOT%/miniedit/i18n/%CODE%.json" 19 | 20 | VALIDATORS: 21 | - id: MediaWikiLink -------------------------------------------------------------------------------- /groups/Wikimedia/PageContentService.yaml: -------------------------------------------------------------------------------- 1 | BASIC: 2 | id: pagecontentservice 3 | label: Page Content Service 4 | namespace: NS_WIKIMEDIA 5 | class: FileBasedMessageGroup 6 | description: "{{Special:MyLanguage/Translations:Group descriptions/pagecontentservice/en}}" 7 | 8 | FILES: 9 | format: Json 10 | sourcePattern: "%GROUPROOT%/pagecontentservice/i18n/%CODE%.json" 11 | 12 | TAGS: 13 | optional: 14 | - pagecontentservice-license-footer-name 15 | - pagecontentservice-license-footer-name-cc4 16 | 17 | VALIDATORS: 18 | - id: BraceBalance 19 | - id: MediaWikiParameter 20 | insertable: true 21 | - id: MediaWikiPlural 22 | 23 | MANGLER: 24 | class: StringMatcher 25 | prefix: pagecontentservice- 26 | patterns: 27 | - "*" 28 | -------------------------------------------------------------------------------- /groups/Wikimedia/Pageviews.yaml: -------------------------------------------------------------------------------- 1 | BASIC: 2 | id: pageviews 3 | label: Pageviews Analysis 4 | icon: wiki://Pageviews Analysis.svg 5 | description: "{{Special:MyLanguage/Translations:Group descriptions/pageviews/en}}" 6 | class: FileBasedMessageGroup 7 | namespace: NS_WIKIMEDIA 8 | 9 | MANGLER: 10 | class: StringMatcher 11 | prefix: pageviews- 12 | patterns: 13 | - "*" 14 | 15 | FILES: 16 | format: Json 17 | sourcePattern: "%GROUPROOT%/pageviews/messages/%CODE%.json" 18 | 19 | TAGS: 20 | optional: 21 | - pageviews-csv 22 | - pageviews-json 23 | - pageviews-png 24 | - pageviews-comma-character 25 | 26 | VALIDATORS: 27 | - id: BraceBalance 28 | - id: MediaWikiParameter 29 | - id: MediaWikiPlural 30 | 31 | INSERTABLES: 32 | - class: MediaWikiInsertablesSuggester 33 | -------------------------------------------------------------------------------- /groups/Wikimedia/ProveIt.yaml: -------------------------------------------------------------------------------- 1 | BASIC: 2 | id: proveit 3 | label: ProveIt 4 | icon: wiki://ProveIt logo for user boxes.svg 5 | description: "{{Special:MyLanguage/Translations:Group descriptions/proveit/en}}" 6 | class: FileBasedMessageGroup 7 | namespace: NS_WIKIMEDIA 8 | 9 | MANGLER: 10 | class: StringMatcher 11 | prefix: proveit- 12 | patterns: 13 | - "*" 14 | 15 | FILES: 16 | format: Json 17 | sourcePattern: "%GROUPROOT%/proveit/i18n/%CODE%.json" -------------------------------------------------------------------------------- /groups/Wikimedia/QRmedia.yaml: -------------------------------------------------------------------------------- 1 | BASIC: 2 | id: qrmedia 3 | label: QRmedia 4 | icon: wiki://QRmedia.png 5 | description: "{{Special:MyLanguage/Translations:Group descriptions/qrmedia/en}}" 6 | class: FileBasedMessageGroup 7 | namespace: NS_WIKIMEDIA 8 | 9 | FILES: 10 | format: Gettext 11 | sourcePattern: "%GROUPROOT%/qrmedia/qrmedia/locale/%CODE%/LC_MESSAGES/django.po" 12 | definitionFile: "%GROUPROOT%/qrmedia/qrmedia/locale/django.pot" 13 | header: | 14 | # Localization strings for QRMedia 15 | # Copyright (C) 2020 Wikimédia France 16 | # This file is distributed under the same license as the QRMedia package. 17 | # Sylvain Boissel , 2020. 18 | # 19 | 20 | MANGLER: 21 | class: StringMatcher 22 | prefix: qrmedia- 23 | patterns: 24 | - "*" 25 | 26 | VALIDATORS: 27 | - id: GettextNewline 28 | enforce: true 29 | - id: BraceBalance -------------------------------------------------------------------------------- /groups/Wikimedia/QuickStatements3.yaml: -------------------------------------------------------------------------------- 1 | BASIC: 2 | id: quickstatements3 3 | label: "QuickStatements 3.0" 4 | icon: wiki://QS3.0_-_Icon.svg 5 | namespace: NS_WIKIMEDIA 6 | class: FileBasedMessageGroup 7 | description: "{{Special:MyLanguage/Translations:Group descriptions/quickstatements3/en}}" 8 | support: 9 | url: https://github.com/wikimediabrasil/quickstatements3/issues/new 10 | params: 11 | title: Translation issue with message %MESSAGE% 12 | body: "\n\nURL: %MESSAGE_URL%" 13 | 14 | FILES: 15 | format: Json 16 | sourcePattern: "%GROUPROOT%/quickstatements3/translations/%CODE%.json" 17 | 18 | MANGLER: 19 | class: StringMatcher 20 | prefix: quickstatements3- 21 | patterns: 22 | - "*" 23 | 24 | VALIDATORS: 25 | - id: MediaWikiParameter 26 | 27 | INSERTABLES: 28 | - class: HtmlTagInsertablesSuggester -------------------------------------------------------------------------------- /groups/Wikimedia/Ranker.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | BASIC: 3 | id: ranker 4 | label: Ranker 5 | description: "{{Special:MyLanguage/Translations:Group descriptions/ranker/en}}" 6 | namespace: NS_WIKIMEDIA 7 | class: FileBasedMessageGroup 8 | support: 9 | url: https://phabricator.wikimedia.org/maniphest/task/edit/form/1/ 10 | params: 11 | projects: Tool-ranker, i18n 12 | title: Translation issue about message %MESSAGE% 13 | description: "\n\n----\n\nMessage URL: %MESSAGE_URL%" 14 | 15 | MANGLER: 16 | class: StringMatcher 17 | prefix: ranker- 18 | patterns: 19 | - "*" 20 | 21 | FILES: 22 | format: Json 23 | sourcePattern: "%GROUPROOT%/ranker/i18n/%CODE%.json" 24 | 25 | VALIDATORS: 26 | - id: MediaWikiParameter 27 | insertable: true 28 | enforce: false 29 | - id: MediaWikiPlural 30 | - id: BraceBalance 31 | 32 | INSERTABLES: 33 | - class: MediaWikiInsertablesSuggester 34 | -------------------------------------------------------------------------------- /groups/Wikimedia/SWViewer.yaml: -------------------------------------------------------------------------------- 1 | BASIC: 2 | id: swviewer 3 | label: SWViewer 4 | icon: wiki://Swviewer-logo.svg 5 | description: "{{Special:MyLanguage/Translations:Group descriptions/swviewer/en}}" 6 | class: FileBasedMessageGroup 7 | namespace: NS_WIKIMEDIA 8 | 9 | MANGLER: 10 | class: StringMatcher 11 | prefix: swviewer- 12 | patterns: 13 | - "*" 14 | 15 | FILES: 16 | format: Json 17 | sourcePattern: "%GROUPROOT%/SWViewer/tool-swviewer/i18n/%CODE%.json" 18 | 19 | VALIDATORS: 20 | - id: BraceBalance 21 | enforce: true 22 | - id: MediaWikiParameter 23 | insertable: true 24 | enforce: true 25 | 26 | INSERTABLES: 27 | # [$1|some page] 28 | - class: RegexInsertablesSuggester 29 | params: 30 | regex: /(?
\[[^]|]+\|)[^]]+(?\])/
31 |       display: $pre $post
32 |       pre: $pre
33 |       post: $post
34 | 
35 | 


--------------------------------------------------------------------------------
/groups/Wikimedia/SignIt.yaml:
--------------------------------------------------------------------------------
 1 | ---
 2 | BASIC:
 3 |   id: signit
 4 |   label: Lingua Libre SignIt
 5 |   description: "{{Special:MyLanguage/Translations:Group descriptions/signit/en}}"
 6 |   icon: wiki://Signit-64.png
 7 |   namespace: NS_WIKIMEDIA
 8 |   class: FileBasedMessageGroup
 9 |   support:
10 |     url: https://github.com/lingua-libre/SignIt/issues/new
11 |     params:
12 |       title: Translation issue with message %MESSAGE%
13 |       body: "\n\nURL: %MESSAGE_URL%"
14 | 
15 | MANGLER:
16 |   class: StringMatcher
17 |   prefix: signit-
18 |   patterns:
19 |     - "*"
20 | 
21 | FILES:
22 |   format: Json
23 |   sourcePattern: "%GROUPROOT%/signit/i18n/%CODE%.json"
24 | 
25 | VALIDATORS:
26 |   - id: NumericalParameter
27 |     insertable: true
28 |     enforce: true
29 |   - id: BraceBalance
30 | 
31 | INSERTABLES:
32 |   - class: HtmlTagInsertablesSuggester
33 | 
34 | TAGS:
35 |   optional:
36 |     - signit-si-overlay-coreContent-right-wikt-iso
37 |     - signit-si-overlay-coreContent-right-wikt-section-id
38 | 


--------------------------------------------------------------------------------
/groups/Wikimedia/Twinkle.yaml:
--------------------------------------------------------------------------------
 1 | ---
 2 | BASIC:
 3 |   id: twinkle-core
 4 |   label: Twinkle
 5 |   description: "{{Special:MyLanguage/Translations:Group descriptions/twinkle/en}}"
 6 |   icon: wiki://Police_man_Twinkle_Head.svg
 7 |   namespace: NS_WIKIMEDIA
 8 |   class: FileBasedMessageGroup
 9 | 
10 | MANGLER:
11 |   class: StringMatcher
12 |   prefix: twinkle-
13 |   patterns:
14 |     - "*"
15 | 
16 | FILES:
17 |   format: Json
18 |   sourcePattern: "%GROUPROOT%/wikimedia-gadgets/twinkle-core/i18n/%CODE%.json"
19 | 
20 | VALIDATORS:
21 |   - id: MediaWikiParameter
22 |     insertable: true
23 |     enforce: false
24 |   - id: MediaWikiPlural
25 |   - id: BraceBalance
26 | 
27 | INSERTABLES:
28 |   - class: HtmlTagInsertablesSuggester
29 | 
30 | TAGS:
31 |   optional:
32 |     - twinkle-bullet-separator
33 |   ignored:
34 |     - twinkle-pref-xfdwatchpage-tooltip
35 |     - twinkle-pref-xfdwatchuser-tooltip
36 | 


--------------------------------------------------------------------------------
/groups/Wikimedia/WPCleaner.yaml:
--------------------------------------------------------------------------------
 1 | BASIC:
 2 |   id: wpcleaner
 3 |   label: WPCleaner
 4 |   description: "{{Special:MyLanguage/Translations:Group descriptions/wpcleaner/en}}"
 5 |   icon: wiki://Nuvola_web_broom.svg
 6 |   namespace: NS_WIKIMEDIA
 7 |   class: FileBasedMessageGroup
 8 |   codeBrowser: "https://github.com/WPCleaner/wpcleaner/blob/master/WikipediaCleaner/src/%FILE%#L%LINE%"
 9 | 
10 | FILES:
11 |   format: Gettext
12 |   definitionFile: "%GROUPROOT%/wpcleaner/WikipediaCleaner/src/org/wikipediacleaner/translation/WikiCleaner.pot"
13 |   sourcePattern: "%GROUPROOT%/wpcleaner/WikipediaCleaner/src/org/wikipediacleaner/translation/%CODE%.po"
14 |   codeMap:
15 |     en-gb: en_GB
16 |     pt-br: pt_BR
17 |     zh-hans: zh_CN
18 |     zh-hant: zh_TW
19 |   header: |
20 |     # This file is distributed under the same license as the wikicleaner package.
21 |     #
22 | 
23 | MANGLER:
24 |   class: StringMatcher
25 |   prefix: wpcleaner-
26 |   patterns:
27 |     - "*"
28 | 
29 | VALIDATORS:
30 |   - id: GettextPlural
31 |     enforce: true
32 |   - id: GettextNewline
33 |     enforce: true
34 |   - id: InsertableRegex
35 |     insertable: true
36 |     enforce: true
37 |     params: /{[0-9]+}/
38 | 


--------------------------------------------------------------------------------
/groups/Wikimedia/WSExport.yaml:
--------------------------------------------------------------------------------
 1 | BASIC:
 2 |   id: wsexport
 3 |   label: Wikisource Export
 4 |   description: "{{Special:MyLanguage/Translations:Group descriptions/wsexport/en}}"
 5 |   icon: wiki://Ws-export_logo.svg
 6 |   namespace: NS_WIKIMEDIA
 7 |   class: FileBasedMessageGroup
 8 | 
 9 | FILES:
10 |   format: Json
11 |   sourcePattern: "%GROUPROOT%/wsexport/i18n/%CODE%.json"
12 | 
13 | MANGLER:
14 |   class: StringMatcher
15 |   prefix: wsexport-
16 |   patterns:
17 |     - "*"
18 | 
19 | VALIDATORS:
20 |   - id: MediaWikiParameter
21 |     insertable: true
22 |     enforce: false
23 |   - id: BraceBalance
24 | 
25 | TAGS:
26 |   optional:
27 |     - wsexport-lang-field-value
28 |     - wsexport-app-title-wikisource
29 |     - wsexport-format-field-help
30 | 


--------------------------------------------------------------------------------
/groups/Wikimedia/WhoWroteThat.yaml:
--------------------------------------------------------------------------------
 1 | BASIC:
 2 |   id: whowrotethat
 3 |   label: WhoWroteThat?
 4 |   description: "{{Special:MyLanguage/Translations:Group descriptions/whowrotethat/en}}"
 5 |   class: FileBasedMessageGroup
 6 |   namespace: NS_WIKIMEDIA
 7 | 
 8 | FILES:
 9 |   format: Json
10 |   sourcePattern: "%GROUPROOT%/whowrotethat/i18n/%CODE%.json"
11 | 
12 | VALIDATORS:
13 |   - id: BraceBalance
14 |     insertable: false
15 |     enforce: false
16 |   # Match variables $1, $2 etc
17 |   - id: InsertableRegex
18 |     params: /\$[1-9]/
19 |     insertable: true
20 |     enforce: false
21 |   # Match HTML tags
22 |   - id: InsertableRegex
23 |     params: /<\/?[a-z]+>/
24 |     insertable: true
25 |     enforce: false


--------------------------------------------------------------------------------
/groups/Wikimedia/WikiBlame.yaml:
--------------------------------------------------------------------------------
 1 | BASIC:
 2 |   id: wikiblame
 3 |   label: WikiBlame
 4 |   icon: wiki://WikiBlame.png
 5 |   description: "{{Special:MyLanguage/Translations:Group descriptions/wikiblame/en}}"
 6 |   namespace: NS_WIKIMEDIA
 7 |   class: FileBasedMessageGroup
 8 | 
 9 | FILES:
10 |   format: FlatPhp
11 |   sourcePattern: "%GROUPROOT%/wikiblame/wikiblame_inc/%CODE%.php"
12 | 
13 | VALIDATORS:
14 |   - id: InsertableRegex
15 |     enforce: true
16 |     insertable: true
17 |     params: /_[\p{Lu}_]+_/u
18 |   - id: InsertableRegex
19 |     enforce: true
20 |     insertable: true
21 |     include:
22 |       - messages\x5b'date_format'\x5d
23 |     params: /YYYY|MM|DD/
24 | 
25 | TAGS:
26 |   optional:
27 |     - text_dir
28 |     - messages\x5b'manual_link'\x5d
29 |     - messages\x5b'contact_link'\x5d
30 |     - messages\x5b'lang_example'\x5d
31 |     - messages\x5b'project_example'\x5d
32 |     - messages\x5b'binary_in_wp'\x5d
33 | 


--------------------------------------------------------------------------------
/groups/Wikimedia/WikiEduDashboard.yaml:
--------------------------------------------------------------------------------
 1 | BASIC:
 2 |   id: wikiedudashboard
 3 |   label: Wiki Ed Dashboard
 4 |   icon: wiki://Wikipedia_Education_Program_logo_square.png
 5 |   description: "{{Special:MyLanguage/Translations:Group descriptions/wikiedudashboard/en}}"
 6 |   namespace: NS_WIKIMEDIA
 7 |   class: FileBasedMessageGroup
 8 | 
 9 | FILES:
10 |   format: Yaml
11 |   parseCLDRPlurals: true
12 |   sourcePattern: "%GROUPROOT%/wikiedudashboard/config/locales/%CODE%.yml"
13 |   codeAsRoot: true
14 |   codeMap:
15 |     zh-hans: zh-CN
16 |     zh-hant: zh-TW
17 | 
18 | MANGLER:
19 |   class: StringMatcher
20 |   prefix: wikiedudashboard-
21 |   patterns:
22 |     - "*"
23 | 
24 | VALIDATORS:
25 |   - id: InsertableRubyVariable
26 |     insertable: true
27 |     enforce: false
28 | 
29 | INSERTABLES:
30 |   - class: RegexInsertablesSuggester
31 |     params: /\%{[^}]+}|%s/
32 |   - class: RegexInsertablesSuggester
33 |     params: /&(?:[a-z]+|#\d+);/
34 | 
35 | TAGS:
36 |   ignored:
37 |     - wikiedudashboard-number.human.decimal_units.units.unit
38 |     - wikiedudashboard-article.views_added
39 |     - wikiedudasbhoard-tasks.*
40 |     - wikiedudashboard-timeout
41 |   optional:
42 |     - wikiedudashboard-courses.creator.assignment_start_placeholder
43 |     - wikiedudashboard-courses.creator.assignment_end_placeholder
44 |     - wikiedudashboard-courses.creator.start_date_placeholder
45 |     - wikiedudashboard-courses.creator.end_date_placeholder
46 |     - wikiedudashboard-settings.categories.salesforce
47 | 


--------------------------------------------------------------------------------
/groups/Wikimedia/WikiScore.yaml:
--------------------------------------------------------------------------------
 1 | ---
 2 | BASIC:
 3 |   id: wikiscore
 4 |   label: WikiScore
 5 |   description: " {{Special:MyLanguage/Wikimedia:wikiscore-index-about-intro/en}}"
 6 |   namespace: NS_WIKIMEDIA
 7 |   class: FileBasedMessageGroup
 8 |   support:
 9 |     url:  https://github.com/WikiMovimentoBrasil/wikiscore/issues/new
10 |     params:
11 |       title: Translation issue with message %MESSAGE%
12 |       body: "\n\nURL: %MESSAGE_URL%"
13 | 
14 | MANGLER:
15 |   class: StringMatcher
16 |   prefix: wikiscore-
17 |   patterns:
18 |     - "*"
19 | 
20 | FILES:
21 |   format: Json
22 |   sourcePattern: "%GROUPROOT%/wikiscore/translations/%CODE%.json"
23 | 
24 | VALIDATORS:
25 |   - id: MediaWikiParameter
26 |     insertable: true
27 |     enforce: false
28 | 


--------------------------------------------------------------------------------
/groups/Wikimedia/WikidataImagePositions.yaml:
--------------------------------------------------------------------------------
 1 | BASIC:
 2 |   id: wikidata-image-positions
 3 |   label: Wikidata Image Positions
 4 |   namespace: NS_WIKIMEDIA
 5 |   class: FileBasedMessageGroup
 6 |   description: "{{Special:MyLanguage/Translations:Group descriptions/wikidata-image-positions/en}}"
 7 |   support:
 8 |     url: https://phabricator.wikimedia.org/maniphest/task/edit/form/1/
 9 |     params:
10 |       title: Translation issue with message %MESSAGE%
11 |       description: "\n\nURL: %MESSAGE_URL%"
12 |       projects: wikidata-image-positions,i18n
13 | 
14 | MANGLER:
15 |   class: StringMatcher
16 |   prefix: wikidata-image-positions-
17 |   patterns:
18 |     - "*"
19 | 
20 | FILES:
21 |   format: Json
22 |   sourcePattern: "%GROUPROOT%/wikidata-image-positions/i18n/%CODE%.json"
23 | 
24 | VALIDATORS:
25 |   - id: MediaWikiParameter
26 |     insertable: true
27 |     enforce: true
28 | 
29 | INSERTABLES:
30 |   - class: HtmlTagInsertablesSuggester
31 | 


--------------------------------------------------------------------------------
/groups/Wikimedia/WikidataLexemeForms.yaml:
--------------------------------------------------------------------------------
 1 | BASIC:
 2 |   id: wikidata-lexeme-forms
 3 |   label: Wikidata Lexeme Forms
 4 |   namespace: NS_WIKIMEDIA
 5 |   class: FileBasedMessageGroup
 6 |   description: "{{Special:MyLanguage/Translations:Group descriptions/wikidata-lexeme-forms/en}}"
 7 | 
 8 | MANGLER:
 9 |   class: StringMatcher
10 |   prefix: wikidata-lexeme-forms-
11 |   patterns:
12 |     - "*"
13 | 
14 | FILES:
15 |   format: Json
16 |   sourcePattern: "%GROUPROOT%/wikidata-lexeme-forms/i18n/%CODE%.json"
17 |   codeMap:
18 |     aeb-latn: aeb
19 |     bbc-latn: bbc
20 |     gan-hant: gan
21 |     gom-latn: gom
22 |     hif-latn: hif
23 |     ike-cans: iu
24 |     kbd-cyrl: kbd
25 |     kk-cyrl: kk
26 |     ku-latn: ku
27 |     ruq-latn: ruq
28 |     sr-ec: sr
29 |     tg-cyrl: tg
30 |     ug-arab: ug
31 | 
32 | VALIDATORS:
33 |   - id: MediaWikiParameter
34 |     insertable: true
35 |     enforce: false
36 |   - id: MediaWikiPlural
37 | 
38 | INSERTABLES:
39 |   - class: HtmlTagInsertablesSuggester
40 | 


--------------------------------------------------------------------------------
/groups/Wikimedia/WikidataMismatchFinder.yaml:
--------------------------------------------------------------------------------
 1 | BASIC:
 2 |   id: wikidata-mismatch-finder
 3 |   label: Wikidata Mismatch Finder
 4 |   namespace: NS_WIKIMEDIA
 5 |   class: FileBasedMessageGroup
 6 |   description: "{{Special:MyLanguage/Translations:Group descriptions/wikidata-mismatch-finder/en}}"
 7 |   support:
 8 |     url: https://phabricator.wikimedia.org/maniphest/task/edit/form/1/
 9 |     params:
10 |       title: Translation issue with message %MESSAGE%
11 |       description: "\n\nURL: %MESSAGE_URL%"
12 |       projects: mismatch_finder,i18n
13 | 
14 | MANGLER:
15 |   class: StringMatcher
16 |   prefix: wikidata-mismatch-finder-
17 |   patterns:
18 |     - "*"
19 | 
20 | FILES:
21 |   format: Json
22 |   sourcePattern: "%GROUPROOT%/wikidata-mismatch-finder/public/i18n/%CODE%.json"
23 | 
24 | VALIDATORS:
25 |   - id: MediaWikiParameter
26 |     insertable: true
27 |     enforce: true
28 | 
29 | INSERTABLES:
30 |   - class: HtmlTagInsertablesSuggester
31 | 


--------------------------------------------------------------------------------
/groups/Wikimedia/WikimediaMailmanTemplates.yaml:
--------------------------------------------------------------------------------
 1 | ---
 2 | BASIC:
 3 |   id: wikimedia-mailman-templates
 4 |   label: Wikimedia Mailman Templates
 5 |   description: "{{Special:MyLanguage/Translations:Group descriptions/wikimedia-mailman-templates/en}}"
 6 |   namespace: NS_WIKIMEDIA
 7 |   class: FileBasedMessageGroup
 8 |   support:
 9 |     url: https://phabricator.wikimedia.org/maniphest/task/edit/form/1/
10 |     params:
11 |       projects: i18n,Wikimedia-Mailing-lists
12 |       title: Translation issue about message %MESSAGE%
13 |       description: "\n\n----\n\nMessage URL: %MESSAGE_URL%"
14 | 
15 | FILES:
16 |   format: Json
17 |   sourcePattern: "%GROUPROOT%/wikimedia-mailman-templates/i18n/%CODE%.json"
18 |   codeMap:
19 |     pt-br: pt_BR
20 |     zh-hans: zh_CN
21 |     zh-hant: zh_TW
22 |     sr-cyrl: sr
23 |     nb: "no"
24 | 
25 | MANGLER:
26 |   class: StringMatcher
27 |   prefix: wikimedia-mailman-templates-
28 |   patterns:
29 |     - "*"
30 | 
31 | VALIDATORS:
32 |   - id: InsertableRegex
33 |     enforce: true
34 |     insertable: true
35 |     params: /\${[a-zA-Z_]+}/
36 | 
37 | LANGUAGES:
38 |   include:
39 |     - ar
40 |     - ast
41 |     - ca
42 |     - cs
43 |     - da
44 |     - de
45 |     - el
46 |     - es
47 |     - et
48 |     - eu
49 |     - fi
50 |     - fr
51 |     - gl
52 |     - he
53 |     - hr
54 |     - hu
55 |     - ia
56 |     - it
57 |     - ja
58 |     - ko
59 |     - lt
60 |     - nl
61 |     - nb
62 |     - pl
63 |     - pt
64 |     - pt-br
65 |     - ro
66 |     - ru
67 |     - sk
68 |     - sl
69 |     - sr-cyrl
70 |     - sv
71 |     - tr
72 |     - uk
73 |     - vi
74 |     - zh-hans
75 |     - zh-hant


--------------------------------------------------------------------------------
/groups/Wikimedia/WikimediaMobile-kaios.yaml:
--------------------------------------------------------------------------------
 1 | TEMPLATE:
 2 |   BASIC:
 3 |     description: "{{Special:MyLanguage/Wikimedia:wikipedia-kaios-app-description/en}}"
 4 |     icon: wiki://Wikimedia-logo.svg
 5 |     namespace: NS_WIKIMEDIA
 6 |     class: FileBasedMessageGroup
 7 | 
 8 |   MANGLER:
 9 |     class: StringMatcher
10 |     patterns:
11 |       - "*"
12 | 
13 |   VALIDATORS:
14 |   - id: BraceBalance
15 |     enforce: false
16 |   # Match variables $1, $2 etc
17 |   - id: InsertableRegex
18 |     params: /\$[1-9]/
19 |     insertable: true
20 |     enforce: false
21 |   # Match HTML tags
22 |   - id: InsertableRegex
23 |     params: /<\/?[a-z]+>/
24 |     insertable: true
25 |     enforce: false
26 |   # Plural validator
27 |   - id: MediaWikiPlural
28 | 
29 | ---
30 | BASIC:
31 |   icon: wiki://Wikipedia-logo-v2.svg
32 |   id: wikimedia-mobile-wikipedia-kaios-strings
33 |   label: Wikipedia KaiOS Mobile
34 | 
35 | MANGLER:
36 |   prefix: wikipedia-kaios-
37 | 
38 | FILES:
39 |   format: Json
40 |   sourcePattern: "%GROUPROOT%/wikipedia-kaios/i18n/%CODE%.json"
41 | 


--------------------------------------------------------------------------------
/groups/Wikimedia/WikimediaMobile.yaml:
--------------------------------------------------------------------------------
 1 | TEMPLATE:
 2 |   BASIC:
 3 |     description: "{{Special:MyLanguage/Translations:Group descriptions/wikimedia-mobile/en}}"
 4 |     icon: wiki://Wikimedia-logo.svg
 5 |     namespace: NS_WIKIMEDIA
 6 |     class: FileBasedMessageGroup
 7 | 
 8 |   FILES:
 9 |     format: Java
10 |     codeMap:
11 |       nb: "no"
12 | 
13 | ---
14 | BASIC:
15 |   id: out-wikimedia-mobile-0-all
16 |   label: Wikimedia Mobile Apps
17 |   meta: yes
18 |   class: AggregateMessageGroup
19 | 
20 | GROUPS:
21 |   - out-wikimedia-mobile-wikipedia-android-strings
22 |   - out-wikimedia-mobile-wikipedia-ios-0-all
23 |   - wikimedia-mobile-wikipedia-kaios-strings
24 | 


--------------------------------------------------------------------------------
/groups/Wikimedia/WikimediaOCR.yaml:
--------------------------------------------------------------------------------
 1 | BASIC:
 2 |   id: wikimedia-ocr
 3 |   label: Wikimedia OCR
 4 |   icon: wiki://WikimediaOCR-logo.svg
 5 |   namespace: NS_WIKIMEDIA
 6 |   class: FileBasedMessageGroup
 7 |   description: "{{Special:MyLanguage/Translations:Group descriptions/wikimedia-ocr/en}}"
 8 |   support:
 9 |     url: https://phabricator.wikimedia.org/maniphest/task/edit/form/1/
10 |     params:
11 |       projects: i18n,wikimedia_ocr
12 |       title: Translation issue about message %MESSAGE%
13 |       description: "\n\n----\n\nMessage URL: %MESSAGE_URL%"
14 | 
15 | FILES:
16 |   format: Json
17 |   sourcePattern: "%GROUPROOT%/WikimediaOCR/i18n/%CODE%.json"
18 | 
19 | MANGLER:
20 |   class: StringMatcher
21 |   prefix: wikimedia-ocr-
22 |   patterns:
23 |     - "*"
24 | 
25 | VALIDATORS:
26 |   - id: BraceBalance
27 |   - id: MediaWikiPlural
28 |     enforce: true
29 |   - id: NumericalParameter
30 |     enforce: true
31 |     insertable: true
32 | 
33 | TAGS:
34 |   optional:
35 |     - wikimedia-ocr-api
36 |     - wikimedia-ocr-engine-name-google
37 |     - wikimedia-ocr-engine-name-tesseract
38 | 


--------------------------------------------------------------------------------
/groups/Wikimedia/WikimediaPortals.yaml:
--------------------------------------------------------------------------------
 1 | ---
 2 | BASIC:
 3 |   id: wikimedia-portals
 4 |   label: Wikimedia Portals
 5 |   description: "{{Special:MyLanguage/Translations:Group descriptions/wikimedia-portals/en}}"
 6 |   class: FileBasedMessageGroup
 7 |   namespace: NS_WIKIMEDIA
 8 | 
 9 | MANGLER:
10 |   class: StringMatcher
11 |   prefix: portals-
12 |   patterns:
13 |     - "*"
14 | 
15 | FILES:
16 |   format: Json
17 |   nestingSeparator: .
18 |   sourcePattern: "%GROUPROOT%/wikimedia-portals/l10n/%CODE%.json"
19 | 
20 | TAGS:
21 |   optional:
22 |     - portals-app-links.url
23 |     - portals-language-name
24 |     - portals-language-name-romanized
25 |     - portals-language-name-romanized-sorted
26 |     - portals-terms-link
27 |     - portals-privacy-policy-link
28 | 


--------------------------------------------------------------------------------
/groups/Wikimedia/WikipediaPreview.yaml:
--------------------------------------------------------------------------------
 1 | BASIC:
 2 |   id: wikipedia-preview
 3 |   label: Wikipedia Preview
 4 |   icon: wiki://Wikimedia-logo.svg
 5 |   description: "{{Special:MyLanguage/Translations:Group descriptions/wikipedia-preview/en}}"
 6 |   namespace: NS_WIKIMEDIA
 7 |   class: FileBasedMessageGroup
 8 | 
 9 | MANGLER:
10 |   prefix: wikipedia-preview-
11 |   class: StringMatcher
12 |   patterns:
13 |     - "*"
14 | 
15 | FILES:
16 |   format: Json
17 |   sourcePattern: "%GROUPROOT%/wikipedia-preview/i18n/%CODE%.json"
18 | 


--------------------------------------------------------------------------------
/groups/Wikimedia/WikipediaYearInReview.yaml:
--------------------------------------------------------------------------------
 1 | BASIC:
 2 |   id: wikipedia-year-in-review
 3 |   label: Wikipedia Year in Review
 4 |   description: "{{Special:MyLanguage/Translations:Group descriptions/wikipedia-year-in-review/en}}"
 5 |   namespace: NS_WIKIMEDIA
 6 |   class: FileBasedMessageGroup
 7 |   support:
 8 |     url: https://github.com/jdlrobson/wikipedia-year-in-review/issues
 9 |     params:
10 |       title: Translation issue with message %MESSAGE%
11 |       body: "\n\nURL: %MESSAGE_URL%"
12 | 
13 | MANGLER:
14 |   class: StringMatcher
15 |   prefix: wp-year-in-review-
16 |   patterns:
17 |     - "*"
18 | 
19 | FILES:
20 |   format: Json
21 |   sourcePattern: "%GROUPROOT%/wikipedia-year-in-review/i18n/%CODE%.json"
22 | 
23 | VALIDATORS:
24 |   - id: MediaWikiParameter
25 |     insertable: true
26 |     enforce: false
27 |   - id: BraceBalance


--------------------------------------------------------------------------------
/groups/Wikimedia/Wikistats.yaml:
--------------------------------------------------------------------------------
 1 | BASIC:
 2 |   id: wikistats
 3 |   label: Wikistats 2.0
 4 |   icon: wiki://WMF_Analytics_-_Ring_Logo.svg
 5 |   namespace: NS_WIKIMEDIA
 6 |   class: FileBasedMessageGroup
 7 |   description: "{{Special:MyLanguage/Translations:Group descriptions/wikistats/en}}"
 8 | 
 9 | MANGLER:
10 |   class: StringMatcher
11 |   prefix: wikistats-
12 |   patterns:
13 |     - "*"
14 | 
15 | FILES:
16 |   format: Json
17 |   sourcePattern: "%GROUPROOT%/wikistats/src/i18n/%CODE%.json"
18 | 
19 | VALIDATORS:
20 |   # Variables: {fooBar}
21 |   - id: InsertableRegex
22 |     insertable: true
23 |     params: /\{[^|} ]+\}/
24 |   - id: BraceBalance
25 | 


--------------------------------------------------------------------------------
/groups/Wikimedia/WmczTracker.yaml:
--------------------------------------------------------------------------------
 1 | BASIC:
 2 |   id: wmcz-tracker
 3 |   label: Tracker
 4 |   meta: yes
 5 |   description: "{{Special:MyLanguage/Translations:Group descriptions/tracker/en}}"
 6 |   class: AggregateMessageGroup
 7 |   namespace: NS_WIKIMEDIA
 8 | 
 9 | GROUPS:
10 |   - wmcz-tracker-*
11 | 
12 | ---
13 | BASIC:
14 |   id: wmcz-tracker-django
15 |   label: Tracker - main
16 |   class: FileBasedMessageGroup
17 |   namespace: NS_WIKIMEDIA
18 | 
19 | FILES:
20 |   format: Gettext
21 |   sourcePattern: "%GROUPROOT%/wmcz-tracker/trackersite/locale/%CODE%/LC_MESSAGES/django.po"
22 |   definitionFile: "%GROUPROOT%/wmcz-tracker/trackersite/locale/django.pot"
23 | 
24 | MANGLER:
25 |   class: StringMatcher
26 |   prefix: tracker-
27 |   patterns:
28 |     - "*"
29 | 
30 | VALIDATORS:
31 |   - id: InsertableRegex
32 |     insertable: true
33 |     enforce: true
34 |     params: /%\([a-z0-9_]+\)[sd]/
35 |   - id: InsertableRegex
36 |     insertable: true
37 |     enforce: true
38 |     params: /%[sd]/
39 |   - id: GettextNewline
40 |     enforce: true
41 |   - id: GettextPlural
42 |     enforce: true
43 | 
44 | ---
45 | BASIC:
46 |   id: wmcz-tracker-djangojs
47 |   label: Tracker - JavaScript
48 |   class: FileBasedMessageGroup
49 |   namespace: NS_WIKIMEDIA
50 | 
51 | FILES:
52 |   format: Gettext
53 |   sourcePattern: "%GROUPROOT%/wmcz-tracker/trackersite/locale/%CODE%/LC_MESSAGES/djangojs.po"
54 |   definitionFile: "%GROUPROOT%/wmcz-tracker/trackersite/locale/djangojs.pot"
55 | 
56 | MANGLER:
57 |   class: StringMatcher
58 |   prefix: tracker-js-
59 |   patterns:
60 |     - "*"
61 | 
62 | VALIDATORS:
63 |   - id: InsertableRegex
64 |     insertable: true
65 |     enforce: true
66 |     params: /%\([a-z0-9_]+\)[sd]/
67 |   - id: InsertableRegex
68 |     insertable: true
69 |     enforce: true
70 |     params: /%[sd]/
71 |   - id: GettextNewline
72 |     enforce: true
73 |   - id: GettextPlural
74 |     enforce: true
75 | 


--------------------------------------------------------------------------------
/groups/Wikimedia/Wscd.yaml:
--------------------------------------------------------------------------------
 1 | ---
 2 | BASIC:
 3 |   id: wscd
 4 |   label: Wikimedia Server Connectivity Dashboard
 5 |   description: "{{Special:MyLanguage/Translations:Group descriptions/wscd/en}}"
 6 |   namespace: NS_WIKIMEDIA
 7 |   class: FileBasedMessageGroup
 8 |   support:
 9 |     url: https://github.com/diskdance/wscd/issues/new
10 |     params:
11 |       title: Translation issue with message %MESSAGE%
12 |       body: "\n\nURL: %MESSAGE_URL%"
13 | 
14 | MANGLER:
15 |   class: StringMatcher
16 |   prefix: wscd-
17 |   patterns:
18 |     - "*"
19 | 
20 | FILES:
21 |   format: Json
22 |   sourcePattern: "%GROUPROOT%/wscd/i18n/%CODE%.json"
23 | 
24 | TAGS:
25 |   optional:
26 |     - wscd-tbl-page-info
27 | 
28 | VALIDATORS:
29 |   - id: MediaWikiParameter
30 |     insertable: true
31 |     enforce: true
32 | 
33 | INSERTABLES:
34 |   - class: HtmlTagInsertablesSuggester
35 | 


--------------------------------------------------------------------------------
/groups/Wikimedia/XTools.yaml:
--------------------------------------------------------------------------------
 1 | BASIC:
 2 |   id: xtools
 3 |   label: XTools
 4 |   icon: wiki://XTools logo.svg
 5 |   description: "{{Special:MyLanguage/Translations:Group descriptions/xtools/en}}"
 6 |   class: FileBasedMessageGroup
 7 |   namespace: NS_WIKIMEDIA
 8 | 
 9 | MANGLER:
10 |   class: StringMatcher
11 |   prefix: xtools-
12 |   patterns:
13 |     - "*"
14 | 
15 | FILES:
16 |   format: Json
17 |   sourcePattern: "%GROUPROOT%/xtools/i18n/%CODE%.json"
18 | 
19 | TAGS:
20 |   optional:
21 |     - xtools-comma-character
22 |     - xtools-whois
23 |     - xtools-size-gigabytes
24 |     - xtools-size-kilobytes
25 |     - xtools-size-megabytes
26 |     - xtools-size-terabytes
27 | 
28 | VALIDATORS:
29 |   - id: BraceBalance
30 |   - id: MediaWikiParameter
31 |   - id: MediaWikiPlural
32 | 
33 | INSERTABLES:
34 |   - class: MediaWikiInsertablesSuggester
35 | 


--------------------------------------------------------------------------------
/groups/Wikimedia/global-search.yaml:
--------------------------------------------------------------------------------
 1 | BASIC:
 2 |   id: global-search
 3 |   label: Global Search
 4 |   icon: wiki://Meta Checkuser.svg
 5 |   description: "{{Special:MyLanguage/Translations:Group descriptions/global-search/en}}"
 6 |   class: FileBasedMessageGroup
 7 |   namespace: NS_WIKIMEDIA
 8 | 
 9 | MANGLER:
10 |   class: StringMatcher
11 |   prefix: global-search-
12 |   patterns:
13 |     - "*"
14 | 
15 | FILES:
16 |   format: Json
17 |   sourcePattern: "%GROUPROOT%/global-search/i18n/%CODE%.json"
18 | 
19 | TAGS:
20 |   optional:
21 |     - global-search-csv
22 |     - global-search-json
23 |     - global-search-tsv
24 |     - global-search-markdown
25 | 
26 | VALIDATORS:
27 |   - id: BraceBalance
28 |   - id: MediaWikiParameter
29 |   - id: MediaWikiPlural
30 | 
31 | 
32 | INSERTABLES:
33 |   - class: MediaWikiInsertablesSuggester
34 | 


--------------------------------------------------------------------------------
/groups/Wikimedia/ia-upload.yaml:
--------------------------------------------------------------------------------
 1 | ---
 2 | BASIC:
 3 |   id: ia-upload
 4 |   label: ia-upload
 5 |   description: "{{Special:MyLanguage/Translations:Group descriptions/ia-upload/en}}"
 6 |   class: FileBasedMessageGroup
 7 |   namespace: NS_WIKIMEDIA
 8 | 
 9 | MANGLER:
10 |   class: StringMatcher
11 |   prefix: ia-upload-
12 |   patterns:
13 |     - "*"
14 | 
15 | FILES:
16 |   format: Json
17 |   sourcePattern: "%GROUPROOT%/ia-upload/i18n/%CODE%.json"
18 | 
19 | INSERTABLES:
20 |   - class: MediaWikiInsertablesSuggester
21 | 


--------------------------------------------------------------------------------
/groups/Wikimedia/jquery.uls.yaml:
--------------------------------------------------------------------------------
 1 | ---
 2 | BASIC:
 3 |   description: "{{Special:MyLanguage/Translations:Group descriptions/universallanguageselectorlib/en}}"
 4 |   namespace: NS_WIKIMEDIA
 5 |   id: jquery-uls
 6 |   label: jQuery.ULS
 7 |   icon: wiki://JQuery-logo-square.svg
 8 |   class: FileBasedMessageGroup
 9 | 
10 | MANGLER:
11 |   class: StringMatcher
12 |   prefix: uls-
13 |   patterns:
14 |     - "*"
15 | 
16 | FILES:
17 |   format: Json
18 |   sourcePattern: "%GROUPROOT%/jquery.uls/i18n/%CODE%.json"
19 | 


--------------------------------------------------------------------------------
/groups/Wikimedia/svgtranslate.yaml:
--------------------------------------------------------------------------------
 1 | BASIC:
 2 |   id: svgtranslate
 3 |   label: SVG Translate
 4 |   description: "{{Special:MyLanguage/Translations:Group descriptions/svgtranslate/en}}"
 5 |   class: FileBasedMessageGroup
 6 |   namespace: NS_WIKIMEDIA
 7 | 
 8 | MANGLER:
 9 |   class: StringMatcher
10 |   prefix: svgtranslate-
11 |   patterns:
12 |     - "*"
13 | 
14 | FILES:
15 |   format: Json
16 |   sourcePattern: "%GROUPROOT%/svgtranslate/i18n/%CODE%.json"
17 | 
18 | VALIDATORS:
19 |   - id: BraceBalance
20 |   - id: MediaWikiParameter
21 | 
22 | INSERTABLES:
23 |   - class: MediaWikiInsertablesSuggester
24 | 


--------------------------------------------------------------------------------
/groups/Wikimedia/video2commons.yaml:
--------------------------------------------------------------------------------
 1 | ---
 2 | BASIC:
 3 |   id: video2commons
 4 |   label: video2commons
 5 |   description: "{{Special:MyLanguage/Translations:Group descriptions/video2commons/en}}"
 6 |   namespace: NS_WIKIMEDIA
 7 |   class: FileBasedMessageGroup
 8 | 
 9 | MANGLER:
10 |   class: StringMatcher
11 |   prefix: video2commons-
12 |   patterns:
13 |     - "*"
14 | 
15 | FILES:
16 |   format: Json
17 |   sourcePattern: "%GROUPROOT%/video2commons/video2commons/frontend/i18n/%CODE%.json"
18 | 
19 | VALIDATORS:
20 |   - id: InsertableRegex
21 |     insertable: true
22 |     enforce: true
23 |     params: /\{\{[\/#]a\}\}/
24 | 


--------------------------------------------------------------------------------
/groups/Wikimedia/wscontest.yaml:
--------------------------------------------------------------------------------
 1 | BASIC:
 2 |   id: wscontest
 3 |   label: Wikisource Contest Tool
 4 |   description: "{{Special:MyLanguage/Translations:Group descriptions/wscontest/en}}"
 5 |   class: FileBasedMessageGroup
 6 |   namespace: NS_WIKIMEDIA
 7 | 
 8 | MANGLER:
 9 |   class: StringMatcher
10 |   prefix: wscontest-
11 |   patterns:
12 |     - "*"
13 | 
14 | FILES:
15 |   format: Json
16 |   sourcePattern: "%GROUPROOT%/wscontest/lang/%CODE%.json"
17 | 
18 | VALIDATORS:
19 |   - id: BraceBalance
20 |   - id: MediaWikiParameter
21 |   - id: MediaWikiPlural
22 | 
23 | INSERTABLES:
24 |   - class: MediaWikiInsertablesSuggester
25 | 


--------------------------------------------------------------------------------
/groups/lib.reviews/lib.reviews.yaml:
--------------------------------------------------------------------------------
 1 | ---
 2 | BASIC:
 3 |   id: lib.reviews
 4 |   label: lib.reviews
 5 |   description: "{{Special:MyLanguage/Translations:Group descriptions/lib.reviews/en}}"
 6 |   class: FileBasedMessageGroup
 7 |   namespace: NS_LIBREVIEWS
 8 | 
 9 | FILES:
10 |   format: Json
11 |   nestingSeparator: /
12 |   parseCLDRPlurals: yes
13 |   sourcePattern: "%GROUPROOT%/lib.reviews/locales/%CODE%.json"
14 |   codeMap:
15 |     pt: pt-PT
16 |     pt-br: pt
17 |     zh-hans: zh
18 |     zh-hant: zh-Hant
19 | 
20 | VALIDATORS:
21 |   - id: Printf
22 |     insertable: true
23 |   - id: UnicodePlural
24 | 
25 | INSERTABLES:
26 |   - class: HtmlTagInsertablesSuggester
27 |   # HTML entities
28 |   - class: RegexInsertablesSuggester
29 |     params: '/&#?\w+;/'
30 | 


--------------------------------------------------------------------------------
/groups/wikidata/wikidata.yaml:
--------------------------------------------------------------------------------
 1 | TEMPLATE:
 2 |   BASIC:
 3 |     icon: wiki://Wikidata-logo.svg
 4 |     namespace: NS_WIKIMEDIA
 5 |     class: FileBasedMessageGroup
 6 |     description: "{{Special:MyLanguage/Translations:Group descriptions/wikidata/en}}"
 7 | 
 8 |   FILES:
 9 |     format: Json
10 | 
11 | ---
12 | BASIC:
13 |   id: wikidata-0-all
14 |   label: Wikidata
15 |   meta: yes
16 |   class: AggregateMessageGroup
17 | 
18 | GROUPS:
19 |   - wikidata-*
20 | 
21 | ---
22 | BASIC:
23 |   id: wikidata-query-gui
24 |   label: Wikidata Query GUI
25 |   description: "{{Special:MyLanguage/Translations:Group descriptions/wikidata-query-gui/en}}"
26 | 
27 | FILES:
28 |   sourcePattern: "%GROUPROOT%/wikidata-query-gui/i18n/%CODE%.json"
29 | 
30 | VALIDATORS:
31 |   - id: NumericalParameter
32 |     insertable: true
33 | 
34 | ---
35 | BASIC:
36 |   id: wikidata-query-builder
37 |   label: Wikidata Query Builder
38 |   description: "{{Special:MyLanguage/Translations:Group descriptions/wikidata-query-builder/en}}"
39 | 
40 | FILES:
41 |   sourcePattern: "%GROUPROOT%/wikidata-query-builder/public/i18n/%CODE%.json"
42 | 
43 | VALIDATORS:
44 |   - id: NumericalParameter
45 |     insertable: true
46 | 


--------------------------------------------------------------------------------
/melange/.gitignore:
--------------------------------------------------------------------------------
1 | extensions/
2 | notes/
3 | releases/
4 | 


--------------------------------------------------------------------------------
/melange/config.ini:
--------------------------------------------------------------------------------
 1 | [common]
 2 | extensionrepo=ssh://kartik@gerrit.wikimedia.org:29418/mediawiki/extensions/
 3 | releasever=2025.03
 4 | releasever-prev=2024.07
 5 | bundlename=MediaWiki language extension bundle
 6 | downloadurl=https://translatewiki.net/mleb
 7 | hasher=sha256sum
 8 | branchname=mleb/$1
 9 | tagname=$1
10 | versionextra=[https://www.mediawiki.org/wiki/MLEB MLEB $1]
11 | piggyurl="https://www.mediawiki.org/w/api.php?action=query&titles=MediaWiki%20Language%20Extension%20Bundle/installation&prop=revisions&rvprop=content&format=json&formatversion=2"
12 | piggyfile=INSTALL.MediaWikiLanguageExtensionBundle
13 | 
14 | [extensions]
15 | Babel=master
16 | cldr=master
17 | CleanChanges=master
18 | # MLEB 2025.03 branch
19 | Translate=acc2f7b468e0f95c3d39740f9c9351e4ba30b78c
20 | UniversalLanguageSelector=master
21 | 


--------------------------------------------------------------------------------
/melange/melange.php:
--------------------------------------------------------------------------------
 1 | $cmd();
15 | } else {
16 | 	echo "Available actions are:\n";
17 | 	$rObj = new ReflectionObject( $bundler );
18 | 	$rMethods = $rObj->getMethods( ReflectionMethod::IS_PUBLIC );
19 | 	foreach ( $rMethods as $rMethod ) {
20 | 		$name = str_replace( '_', '-', $rMethod->getName() );
21 | 		if ( $name === '--construct' ) {
22 | 			continue;
23 | 		}
24 | 		echo "- " . $name . "\n";
25 | 	}
26 | }
27 | 


--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
 1 | {
 2 | 	"private": true,
 3 | 	"scripts": {
 4 | 		"test": "grunt test"
 5 | 	},
 6 | 	"devDependencies": {
 7 | 		"eslint-config-wikimedia": "0.30.0",
 8 | 		"grunt": "1.6.1",
 9 | 		"grunt-eslint": "24.3.0"
10 | 	}
11 | }
12 | 


--------------------------------------------------------------------------------
/puppet/.gitignore:
--------------------------------------------------------------------------------
1 | .tmp
2 | .librarian
3 | 


--------------------------------------------------------------------------------
/puppet/.puppet-lint.rc:
--------------------------------------------------------------------------------
1 | --no-80chars-check
2 | 


--------------------------------------------------------------------------------
/puppet/Makefile:
--------------------------------------------------------------------------------
 1 | .PHONY: test testpp checkheaders apply
 2 | PUPPET=/opt/puppetlabs/bin/puppet
 3 | 
 4 | test: testpp checkheaders lint
 5 | 
 6 | checkheaders:
 7 | 	for files in modules/*/files; do find $$files -type f |xargs -r grep -L 'managed by puppet'; done
 8 | 
 9 | testpp:
10 | 	git ls-files | grep "\.pp$$" | xargs -r $(PUPPET) parser validate
11 | 
12 | lint:
13 | 	sudo apt install -y -qqq puppet-lint
14 | 	puppet-lint modules
15 | 
16 | noop:
17 | 	librarian-puppet install --path ./vendor
18 | 	sudo $(PUPPET) apply --hiera_config hiera.yaml --modulepath 'modules:vendor:$$basemodulepath' --noop --test site.pp
19 | 
20 | apply: site.pp
21 | 	librarian-puppet install --path ./vendor
22 | 	sudo $(PUPPET) apply --hiera_config hiera.yaml --modulepath 'modules:vendor:$$basemodulepath' site.pp
23 | 


--------------------------------------------------------------------------------
/puppet/Puppetfile:
--------------------------------------------------------------------------------
 1 | forge "https://forgeapi.puppetlabs.com"
 2 | 
 3 | mod 'lvicainne/opendkim',
 4 |     :git => 'https://github.com/lvicainne/puppet-opendkim.git',
 5 |     :tag => 'v0.4.0'
 6 | #mod 'puppet-elasticsearch', '9.0.0'
 7 | #mod 'puppet-elastic_stack', '9.0.0'
 8 | #mod 'puppet-kibana', '8.0.0'
 9 | mod 'puppet-letsencrypt', '11.0.0'
10 | mod 'puppet-postfix', '4.4.0'
11 | mod 'puppet-systemd', '6.6.0'
12 | mod 'puppetlabs-firewall', '8.0.1'
13 | mod 'puppetlabs-java', '11.0.0'
14 | mod 'puppetlabs-mount_core', '1.2.0'
15 | mod 'puppetlabs-mysql', '15.0.0'
16 | mod 'syseleven-restic', '2.6.1'
17 | mod 'thias-sysctl', '1.0.7'
18 | 


--------------------------------------------------------------------------------
/puppet/Puppetfile.lock:
--------------------------------------------------------------------------------
 1 | FORGE
 2 |   remote: https://forgeapi.puppetlabs.com
 3 |   specs:
 4 |     puppet-alternatives (5.1.0)
 5 |     puppet-archive (7.1.0)
 6 |       puppetlabs-stdlib (>= 4.18.0, < 10.0.0)
 7 |     puppet-epel (5.0.0)
 8 |     puppet-letsencrypt (11.0.0)
 9 |       puppet-epel (>= 3.0.1, < 6.0.0)
10 |       puppetlabs-inifile (>= 2.5.0, < 7.0.0)
11 |       puppetlabs-stdlib (>= 4.13.1, < 10.0.0)
12 |     puppet-postfix (4.4.0)
13 |       puppet-alternatives (>= 2.0.0, < 6.0.0)
14 |       puppetlabs-mailalias_core (>= 1.0.5, < 2.0.0)
15 |       puppetlabs-stdlib (>= 4.13.0, < 10.0.0)
16 |     puppet-systemd (6.6.0)
17 |       puppetlabs-inifile (>= 1.6.0, < 7.0.0)
18 |       puppetlabs-stdlib (>= 4.13.1, < 10.0.0)
19 |     puppetlabs-concat (9.0.2)
20 |       puppetlabs-stdlib (>= 9.0.0, < 10.0.0)
21 |     puppetlabs-firewall (8.0.1)
22 |       puppetlabs-stdlib (>= 9.0.0, < 10.0.0)
23 |     puppetlabs-inifile (6.1.1)
24 |       puppetlabs-stdlib (>= 4.13.0, < 10.0.0)
25 |     puppetlabs-java (11.0.0)
26 |       puppet-archive (>= 1.1.0, < 8.0.0)
27 |       puppetlabs-stdlib (>= 4.13.1, < 10.0.0)
28 |     puppetlabs-mailalias_core (1.2.0)
29 |     puppetlabs-mount_core (1.2.0)
30 |     puppetlabs-mysql (15.0.0)
31 |       puppetlabs-stdlib (>= 9.0.0, < 10.0.0)
32 |     puppetlabs-stdlib (9.6.0)
33 |     syseleven-restic (2.6.1)
34 |       puppet-systemd (>= 3.10.0)
35 |       puppetlabs-concat (>= 7.4.0)
36 |       puppetlabs-stdlib (>= 8.2.0)
37 |     thias-sysctl (1.0.7)
38 | 
39 | GIT
40 |   remote: https://github.com/lvicainne/puppet-opendkim.git
41 |   ref: v0.4.0
42 |   sha: 5f34642760dd99bb2ef671ff551f87471e308db7
43 |   specs:
44 |     lvicainne-opendkim (0.3.0)
45 |       puppetlabs-stdlib (>= 4.13.0, < 10.0.0)
46 | 
47 | DEPENDENCIES
48 |   lvicainne-opendkim (>= 0)
49 |   puppet-letsencrypt (= 11.0.0)
50 |   puppet-postfix (= 4.4.0)
51 |   puppet-systemd (= 6.6.0)
52 |   puppetlabs-firewall (= 8.0.1)
53 |   puppetlabs-java (= 11.0.0)
54 |   puppetlabs-mount_core (= 1.2.0)
55 |   puppetlabs-mysql (= 15.0.0)
56 |   syseleven-restic (= 2.6.1)
57 |   thias-sysctl (= 1.0.7)
58 | 
59 | 


--------------------------------------------------------------------------------
/puppet/README:
--------------------------------------------------------------------------------
 1 | == Bootstrap process ==
 2 | 
 3 | Start with a feshly installed, minimal Debian 10 (Buster):
 4 | 
 5 |   apt update
 6 |   apt upgrade
 7 |   apt dist-upgrade
 8 |   apt autoremove
 9 |   shutdown -r now
10 | 
11 | Then copy setup-environment.sh to the server and run it:
12 |   chmod +x setup-environment.sh
13 |   # For development
14 |   ./setup-environment.sh dev.translatewiki.net
15 |   # For production
16 |   ./setup-environment.sh web2.translatewiki.net
17 | 
18 | 
19 | == Manual configuration required for production ==
20 | * Copy/create the following files for keyholder:
21 |   /root/keyholder/l10n-bot
22 |   /root/keyholder/l10n-bot.pub
23 | * Add accounts for stats.translatewiki.net to /etc/webauth
24 | * Put backup keys in /root/.ssh/
25 | 


--------------------------------------------------------------------------------
/puppet/data/.gitignore:
--------------------------------------------------------------------------------
1 | developer.yaml
2 | 


--------------------------------------------------------------------------------
/puppet/data/developer.yaml.example:
--------------------------------------------------------------------------------
 1 | # Add your ssh key here. Then you can login as developer@host.
 2 | 
 3 | users::ssh_keys:
 4 |   developer@localhost:
 5 |     user: developer
 6 |     type: ssh-..
 7 |     key: AAAA...
 8 | 
 9 | # You can add extra repositories here later
10 | #lookup_options:
11 | #  wiki::workdir::repos:
12 | #    merge: hash
13 | #
14 | #wiki::workdir::repos:
15 | #  workdir/extensions/ContentTranslation:
16 | #    source: https://gerrit.wikimedia.org/r/mediawiki/extensions/ContentTranslation
17 | 


--------------------------------------------------------------------------------
/puppet/data/nodes/dev.yaml:
--------------------------------------------------------------------------------
 1 | classes:
 2 |   - '::nginx::devsite'
 3 |   - '::wiki::workdir'
 4 | 
 5 | users::users:
 6 |   developer:
 7 |     uid: 1000
 8 |     groups: [ betawiki, www-shared, l10n-bot, sysadmin ]
 9 |     comment: Almighty Developer
10 |   betawiki:
11 |     uid: 1001
12 |     groups: [ betawiki, www-shared ]
13 |     comment: Maintenance Account
14 |   l10n-bot:
15 |     # To match gid of l10n-bot
16 |     uid: 1021
17 |     system: true
18 |     groups: [ l10n-bot ]
19 |     managehome: false
20 |     shell: /bin/false
21 |     comment: Maintenance Account
22 | 
23 | wiki::config_dir: /home/developer/translatewiki
24 | wiki::domain: dev.translatewiki.net
25 | wiki::repo_user: developer
26 | wiki::production_dir: /home/developer/mediawiki/workdir
27 | wiki::work_dir: /home/developer/mediawiki/workdir
28 | wiki::workdir::deployment_dir: /home/developer/mediawiki
29 | wiki::workdir::mediawiki_config: DevelopmentSettings.php
30 | 


--------------------------------------------------------------------------------
/puppet/hiera.yaml:
--------------------------------------------------------------------------------
 1 | ---
 2 | version: 5
 3 | 
 4 | defaults:
 5 |   datadir: data
 6 |   data_hash: 'yaml_data'
 7 | hierarchy:
 8 |   - name: 'Developer specific settings for development environment'
 9 |     path: 'developer.yaml'
10 |   - name: 'secrets by name yaml'
11 |     path: "nodes/%{::hostname}.eyaml"
12 |     lookup_key: eyaml_lookup_key
13 |     options:
14 |       pkcs7_private_key: /root/secrets/puppet-hiera-eyaml/private_key.pkcs7.pem
15 |       pkcs7_public_key: /root/secrets/puppet-hiera-eyaml/public_key.pkcs7.pem
16 |   - name: 'nodes by name yaml'
17 |     path: "nodes/%{::hostname}.yaml"
18 |   - name: 'Default values'
19 |     path: 'common.yaml'
20 | 


--------------------------------------------------------------------------------
/puppet/modules/awstats/files/awstats.conf.local:
--------------------------------------------------------------------------------
 1 | # file managed by puppet
 2 | 
 3 | # You can overrides config directives here.
 4 | # This is particularly useful for users with several configs for
 5 | # different virtual servers, who want to reuse common parameters.
 6 | # Also, this file is not updated with each new upstream release.
 7 | 
 8 | LogFile="/usr/share/awstats/tools/logresolvemerge.pl /var/log/nginx/access.log /var/log/nginx/access.log.1 |"
 9 | LogFormat=1
10 | SiteDomain="translatewiki.net"
11 | DirCgi="/awstats"
12 | DirIcons="/awstatsicons"
13 | 
14 | AllowFullYearView=3
15 | DNSLookup=0
16 | LoadPlugin=“geoip6 GEOIP_STANDARD /usr/share/GeoIP/GeoIPv6.dat”
17 | 


--------------------------------------------------------------------------------
/puppet/modules/awstats/files/stats.translatewiki.net:
--------------------------------------------------------------------------------
 1 | # file managed by puppet
 2 | 
 3 | server {
 4 | 	listen 80;
 5 | 	listen [2a03:4000:39:55d:5400:a2ff:fe21:b3ea]:80;
 6 | 	server_name stats.translatewiki.net;
 7 | 	return 301 https://$host$request_uri;
 8 | }
 9 | 
10 | server {
11 | 	listen 443 ssl http2;
12 | 	listen [2a03:4000:39:55d:5400:a2ff:fe21:b3ea]:443 ssl http2;
13 | 
14 | 	include includes/ssl-certbot.conf;
15 | 
16 | 	server_name stats.translatewiki.net;
17 | 	root /www/stats.translatewiki.net;
18 | 
19 | 	auth_basic            "Restricted";
20 | 	auth_basic_user_file  /etc/webauth;
21 | 
22 | 	location / {
23 | 		rewrite ^ /awstats.pl;
24 | 	}
25 | 
26 | 	location = /awstats.pl {
27 | 		gzip off;
28 | 		root /usr/lib/cgi-bin;
29 | 		include /etc/nginx/fastcgi_params;
30 | 		fastcgi_param SCRIPT_FILENAME /usr/lib/cgi-bin/awstats.pl;
31 | 		fastcgi_pass unix:/var/run/fcgiwrap.socket;
32 | 	}
33 | 
34 | 	location ~ ^/awstatsicons/(.*)$ {
35 | 		alias /usr/share/awstats/icon/$1;
36 | 	}
37 | 
38 | 	# Exclude let's encrypt
39 | 	location /.well-known {
40 | 		auth_basic off;
41 | 	}
42 | }
43 | 


--------------------------------------------------------------------------------
/puppet/modules/awstats/manifests/init.pp:
--------------------------------------------------------------------------------
 1 | # = Class: awstats
 2 | #
 3 | # Provides some stats for us.
 4 | #
 5 | class awstats {
 6 |   include fcgiwrap
 7 | 
 8 |   package { 'awstats':
 9 |     ensure => present,
10 |   }
11 | 
12 |   package { [
13 |     'geoip-database',
14 |     'libgeo-ip-perl',
15 |   ]:
16 |     ensure => present,
17 |   }
18 | 
19 |   File {
20 |     require => Package['awstats']
21 |   }
22 | 
23 |   file { '/etc/awstats/awstats.conf.local':
24 |     source => 'puppet:///modules/awstats/awstats.conf.local',
25 |   }
26 | 
27 |   file { '/etc/nginx/sites/stats.translatewiki.net':
28 |     source  => 'puppet:///modules/awstats/stats.translatewiki.net',
29 |     require => [Package['nginx'], Service['fcgiwrap']],
30 |     notify  => Service['nginx'],
31 |   }
32 | 
33 |   systemd::timer { 'awstats.timer':
34 |     timer_content   => template('awstats/awstats.timer.erb'),
35 |     service_content => template('awstats/awstats.service.erb'),
36 |     active          => true,
37 |     enable          => true,
38 |   }
39 | 
40 |   systemd::timer { 'mlebstats.timer':
41 |     timer_content   => template('awstats/mlebstats.timer.erb'),
42 |     service_content => template('awstats/mlebstats.service.erb'),
43 |     active          => true,
44 |     enable          => true,
45 |   }
46 | }
47 | 


--------------------------------------------------------------------------------
/puppet/modules/awstats/templates/awstats.service.erb:
--------------------------------------------------------------------------------
 1 | # This file is managed by puppet
 2 | [Unit]
 3 | Description=Process logs for awstats
 4 | 
 5 | [Service]
 6 | ExecStart=/usr/lib/cgi-bin/awstats.pl -update -config=translatewiki.net
 7 | ProtectHome=read-only
 8 | ProtectSystem=full
 9 | Nice=10
10 | 


--------------------------------------------------------------------------------
/puppet/modules/awstats/templates/awstats.timer.erb:
--------------------------------------------------------------------------------
 1 | # This file is managed by puppet
 2 | [Unit]
 3 | Description=Run awstats processing regularly
 4 | 
 5 | [Timer]
 6 | AccuracySec=1m
 7 | OnBootSec=10m
 8 | OnUnitActiveSec=10m
 9 | 
10 | [Install]
11 | WantedBy=timers.target
12 | 


--------------------------------------------------------------------------------
/puppet/modules/awstats/templates/mlebstats.service.erb:
--------------------------------------------------------------------------------
 1 | # This file is managed by puppet
 2 | [Unit]
 3 | Description=Emails MLEB download statistics
 4 | 
 5 | [Service]
 6 | ExecStart=/usr/bin/php /home/betawiki/config/bin/scripts/mlebstats.php /var/lib/awstats nlaxstrom@wikimedia.org,federico@translatewiki.net
 7 | ProtectHome=read-only
 8 | ProtectSystem=full
 9 | Nice=10
10 | 


--------------------------------------------------------------------------------
/puppet/modules/awstats/templates/mlebstats.timer.erb:
--------------------------------------------------------------------------------
 1 | # This file is managed by puppet
 2 | [Unit]
 3 | Description=Run mlebstats on first day of the month
 4 | 
 5 | [Timer]
 6 | OnCalendar=*-*-01 06:00:00
 7 | Persistent=true
 8 | 
 9 | [Install]
10 | WantedBy=timers.target
11 | 


--------------------------------------------------------------------------------
/puppet/modules/base/manifests/firewall/post.pp:
--------------------------------------------------------------------------------
 1 | # = Class: base::firewall::post
 2 | #
 3 | # Provides installation and configuration for translatewiki.net firewall
 4 | #
 5 | class base::firewall::post {
 6 |   firewall { '999 drop all':
 7 |     proto  => 'all',
 8 |     jump   => 'drop',
 9 |     before => undef,
10 |   }
11 | }
12 | 


--------------------------------------------------------------------------------
/puppet/modules/base/manifests/firewall/pre.pp:
--------------------------------------------------------------------------------
 1 | # = Class: base::firewall::pre
 2 | #
 3 | # Provides installation and configuration for translatewiki.net firewall
 4 | #
 5 | class base::firewall::pre {
 6 |   Firewall {
 7 |     require => undef,
 8 |   }
 9 | 
10 |   # Default firewall rules
11 |   firewall { '000 accept all icmp':
12 |     proto => 'icmp',
13 |     jump  => 'accept',
14 |   }
15 |   -> firewall { '000 accept all icmpv6':
16 |     proto => 'ipv6-icmp',
17 |     jump  => 'accept',
18 |   }
19 |   -> firewall { '001 accept all to lo interface':
20 |     proto   => 'all',
21 |     iniface => 'lo',
22 |     jump    => 'accept',
23 |   }
24 |   -> firewall { '002 reject local traffic not on loopback interface':
25 |     iniface     => '! lo',
26 |     proto       => 'all',
27 |     destination => '127.0.0.1/8',
28 |     jump        => 'reject',
29 |   }
30 |   -> firewall { '003 accept related established rules':
31 |     proto => 'all',
32 |     state => ['RELATED', 'ESTABLISHED'],
33 |     jump  => 'accept',
34 |   }
35 |   -> firewall { '006 Allow inbound SSH (v4)':
36 |     dport    => 22,
37 |     proto    => tcp,
38 |     jump     => accept,
39 |     protocol => 'IPv4',
40 |   }
41 |   -> firewall { '006 Allow inbound SSH (v6)':
42 |     dport    => 22,
43 |     proto    => tcp,
44 |     jump     => accept,
45 |     protocol => 'IPv6',
46 |   }
47 | }
48 | 


--------------------------------------------------------------------------------
/puppet/modules/base/manifests/init.pp:
--------------------------------------------------------------------------------
 1 | # = Class: base
 2 | #
 3 | # Provides base configuration for servers.
 4 | #
 5 | class base (
 6 |   String $maintenance_user,
 7 |   String $bin_dir,
 8 |   Optional[String] $mount_device = undef,
 9 | ) {
10 |   $packages = [
11 |     # Basic packages
12 |     'ack',
13 |     'acl',
14 |     'apticron', # Daily message about available updates to root
15 |     'bash-completion',
16 |     'colorized-logs', # For execute-and-notify script
17 |     'curl',
18 |     'git',
19 |     'git-review',
20 |     'htop',
21 |     'iftop',
22 |     'iotop', # IO view
23 |     'iperf', # Network performance
24 |     'jnettop', # Network view
25 |     'make',
26 |     'mlocate',
27 |     'mydumper',
28 |     'nano',
29 |     'netcat-openbsd',
30 |     'nfs-common',
31 |     'parallel', # Used for e.g. forceSearchIndex.php
32 |     'screen',
33 |     'unattended-upgrades',
34 |     'unzip',
35 |     'wget',
36 |   ]
37 |   stdlib::ensure_packages($packages, {
38 |     ensure => 'present',
39 |   })
40 | 
41 |   file { '/etc/profile.d/translatewiki.sh':
42 |     content => template('base/translatewiki.sh.erb'),
43 |   }
44 | 
45 |   file { '/scratch':
46 |     ensure => directory,
47 |   }
48 | 
49 |   if $mount_device {
50 |     mount { '/scratch':
51 |       ensure  => 'mounted',
52 |       device  => $mount_device,
53 |       fstype  => 'nfs',
54 |       options => 'rw',
55 |       require => File['/scratch'],
56 |     }
57 |   }
58 | 
59 |   file { '/etc/default/locale':
60 |     content => 'LANG="en_US.UTF-8"',
61 |   }
62 | 
63 |   file { '/etc/systemd/journald.conf.d/':
64 |     ensure => 'directory',
65 |   }
66 | 
67 |   file { '/etc/systemd/journald.conf.d/50-override.conf':
68 |     content => "[Journal]\nStorage=persistent\n",
69 |   }
70 | }
71 | 


--------------------------------------------------------------------------------
/puppet/modules/base/manifests/mediawiki.pp:
--------------------------------------------------------------------------------
 1 | # = Class: base::mediawiki
 2 | #
 3 | # Provides base configuration for MediaWiki.
 4 | #
 5 | class base::mediawiki {
 6 |   $packages = [
 7 |     'doxygen',
 8 |     'fontconfig',
 9 |     # Development extras
10 |     'jpegoptim',
11 |     'optipng',
12 |     # Dependencies for compiling wikidiff2
13 |     'g++',
14 |     'pkg-config',
15 |     'libthai-dev',
16 |     # fonts for phplot
17 |     'fonts-dejavu',
18 |   ]
19 |   stdlib::ensure_packages($packages, {
20 |     ensure => 'present',
21 |   })
22 | }
23 | 


--------------------------------------------------------------------------------
/puppet/modules/base/manifests/vcs.pp:
--------------------------------------------------------------------------------
 1 | # = Class: base::vcs
 2 | #
 3 | # Provides installation and configuration for translatewiki.net supported
 4 | # version control systems.
 5 | #
 6 | class base::vcs {
 7 |   $packages = [
 8 |     'bzr',
 9 |     'cvs',
10 |     'gettext',
11 |     'mercurial',
12 |     'subversion',
13 |   ]
14 |   stdlib::ensure_packages($packages, {
15 |     ensure => 'present',
16 |   })
17 | }
18 | 


--------------------------------------------------------------------------------
/puppet/modules/base/templates/translatewiki.sh.erb:
--------------------------------------------------------------------------------
1 | # This file is managed by puppet
2 | if [ -z ${PATH-} ] ; then
3 |   export PATH=<%= @bin_dir %>
4 | elif ! echo ${PATH} | grep -q <%= @bin_dir %> ; then
5 |   export PATH=${PATH}:<%= @bin_dir %>
6 | fi
7 | 
8 | alias b='sudo -E -u <%= @maintenance_user %>'
9 | 


--------------------------------------------------------------------------------
/puppet/modules/fcgiwrap/manifests/init.pp:
--------------------------------------------------------------------------------
 1 | # = Class: fcgiwrap
 2 | #
 3 | # Provides installation and configuration for the fcgiwrap package.
 4 | #
 5 | class fcgiwrap {
 6 |   package { 'fcgiwrap':
 7 |     ensure => present,
 8 |   }
 9 | 
10 |   service { 'fcgiwrap':
11 |     ensure  => running,
12 |     require => Package['fcgiwrap'],
13 |   }
14 | }
15 | 


--------------------------------------------------------------------------------
/puppet/modules/hostname/manifests/init.pp:
--------------------------------------------------------------------------------
 1 | # = Class: hostname
 2 | #
 3 | # Provides hostname
 4 | #
 5 | class hostname {
 6 |   $packages = [
 7 |     'libnss-myhostname',
 8 |   ]
 9 |   stdlib::ensure_packages($packages, {
10 |     ensure => 'present',
11 |   })
12 | 
13 |   $hostname = $::ipaddress ? {
14 |     '152.89.106.205' => 'web2.translatewiki.net',
15 |     default          => 'unknown.tranlatewiki.net',
16 |   }
17 | 
18 |   file { '/etc/hostname':
19 |     ensure  => file,
20 |     content => $hostname,
21 |   }
22 | }
23 | 


--------------------------------------------------------------------------------
/puppet/modules/keyholder/README:
--------------------------------------------------------------------------------
1 | This module has been copied from the URL below, with small modifications to make it
2 | work independently and on Ubuntu.
3 | https://github.com/wikimedia/puppet/tree/f51428239f80288c3a37bdef88665c941238f926/modules/keyholder
4 | 


--------------------------------------------------------------------------------
/puppet/modules/keyholder/templates/initscripts/keyholder-agent.systemd.erb:
--------------------------------------------------------------------------------
 1 | [Unit]
 2 | Description=Shared keyholder SSH agent which holds shared identities
 3 | 
 4 | [Install]
 5 | WantedBy=multi-user.target
 6 | 
 7 | [Service]
 8 | User=keyholder
 9 | Group=keyholder
10 | ExecStart=/usr/bin/ssh-agent -d -a /run/keyholder/agent.sock
11 | ExecStop=/bin/rm -f /run/keyholder/agent.sock
12 | RuntimeDirectory=keyholder
13 | 


--------------------------------------------------------------------------------
/puppet/modules/keyholder/templates/initscripts/keyholder-proxy.systemd.erb:
--------------------------------------------------------------------------------
 1 | [Unit]
 2 | Description=keyholder-proxy - Filtering proxy for keyholder SSH agent
 3 | Requires=keyholder-agent.service
 4 | 
 5 | [Install]
 6 | WantedBy=multi-user.target
 7 | 
 8 | [Service]
 9 | User=keyholder
10 | Group=keyholder
11 | UMask=111
12 | ExecStartPre=/bin/rm -f /run/keyholder/proxy.sock
13 | ExecStart=/usr/local/bin/ssh-agent-proxy --bind /run/keyholder/proxy.sock --connect /run/keyholder/agent.sock
14 | ExecStop=/bin/rm -f /run/keyholder/proxy.sock
15 | RuntimeDirectory=keyholder
16 | 


--------------------------------------------------------------------------------
/puppet/modules/kitanonl/files/index.html:
--------------------------------------------------------------------------------
 1 | 
 2 | 
 3 | 
 4 |     Kitano ICT
 5 | 
 6 | 
 7 |     



8 |
Hier komt (n)ooit de website van Kitano ICT
9 |
10 | Overige handelsnamen:
11 | Utrecht Beer Buyers Club (UBBC)
12 |
13 | Adresgegevens
14 | Weerschijnvlinder 16
15 | 3544 DV Utrecht
16 | Nederland

17 | T: +31 6 50691239
18 | info@kitano.nl
19 |
20 | KVK: 30197597
21 | VAT: NL001879397B69
22 | Bank: NL93KNAB0255648812
23 | BIC: KNABNL2H
24 |
25 |



26 |



27 |



28 |



29 | This website does track visits or use any cookies. 30 |
31 | 32 | 33 | -------------------------------------------------------------------------------- /puppet/modules/kitanonl/files/kitano.nl: -------------------------------------------------------------------------------- 1 | # file managed by puppet 2 | 3 | server { 4 | listen 80; 5 | listen [2a03:4000:39:55d:5400:a2ff:fe21:b3ea]:80; 6 | server_name .kitano.nl; 7 | return 301 https://$host$request_uri; 8 | } 9 | 10 | server { 11 | listen 443; 12 | listen [2a03:4000:39:55d:5400:a2ff:fe21:b3ea]:443 ssl http2; 13 | 14 | server_name .kitano.nl; 15 | root /www/kitano.nl; 16 | index index.html; 17 | } 18 | -------------------------------------------------------------------------------- /puppet/modules/kitanonl/manifests/init.pp: -------------------------------------------------------------------------------- 1 | # = Class: kitanonl 2 | # 3 | # Provides kitano.nl website 4 | # 5 | class kitanonl { 6 | $directories = [ 7 | '/www', 8 | '/www/kitano.nl', 9 | ] 10 | ensure_resource('file', $directories, { 11 | 'ensure' => 'directory', 12 | 'owner' => 'betawiki', 13 | 'group' => 'users' 14 | }) 15 | 16 | file { '/www/kitano.nl/index.html': 17 | source => 'puppet:///modules/kitanonl/index.html', 18 | require => File['/www/kitano.nl'], 19 | } 20 | 21 | file { '/etc/nginx/sites/kitano.nl': 22 | source => 'puppet:///modules/kitanonl/kitano.nl', 23 | require => [ 24 | Package['nginx'], 25 | Service['fcgiwrap'] 26 | ], 27 | notify => Service['nginx'], 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /puppet/modules/mariadb/manifests/init.pp: -------------------------------------------------------------------------------- 1 | # = Class: mariadb 2 | # 3 | # Provides mariadb installation and configuration for translatewiki.net. 4 | # 5 | class mariadb { 6 | class { '::mysql::server': 7 | package_name => 'mariadb-server', 8 | service_name => 'mariadb', 9 | restart => false, 10 | override_options => { 11 | mysqld => { 12 | character-set-server => 'utf8', 13 | innodb_buffer_pool_instances => '12', 14 | innodb_buffer_pool_size => '20G', 15 | innodb_file_per_table => '1', 16 | innodb_log_file_size => '2G', 17 | thread_pool_size => '16', 18 | key_buffer_size => '16M', 19 | query_cache_size => '0', 20 | query_cache_type => '0', 21 | ssl => '0', 22 | table_cache => '1500', 23 | log-error => undef, 24 | # temporary fix for https://github.com/puppetlabs/puppetlabs-mysql/issues/1509 25 | ssl-ca => undef, 26 | ssl-cert => undef, 27 | ssl-key => undef, 28 | }, 29 | mysqld_safe => { 30 | log-error => undef 31 | }, 32 | client => { 33 | default-character-set => 'utf8' 34 | } 35 | } 36 | } 37 | 38 | class { '::mysql::client': 39 | package_name => 'mariadb-client', 40 | } 41 | 42 | $packages = [ 43 | 'mysqltuner', 44 | ] 45 | stdlib::ensure_packages($packages, { 46 | ensure => 'present', 47 | }) 48 | } 49 | -------------------------------------------------------------------------------- /puppet/modules/memcached/files/memcached.conf: -------------------------------------------------------------------------------- 1 | # file managed by puppet 2 | 3 | # memcached default config file 4 | # 2003 - Jay Bonci 5 | # This configuration file is read by the start-memcached script provided as 6 | # part of the Debian GNU/Linux distribution. 7 | 8 | # Run memcached as a daemon. This command is implied, and is not needed for the 9 | # daemon to run. See the README.Debian that comes with this package for more 10 | # information. 11 | -d 12 | 13 | # Log memcached's output to /var/log/memcached 14 | logfile /var/log/memcached.log 15 | 16 | # Be verbose 17 | # -v 18 | 19 | # Be even more verbose (print client commands as well) 20 | # -vv 21 | 22 | # Start with a cap of 64 megs of memory. It's reasonable, and the daemon default 23 | # Note that the daemon will grow to this size, but does not start out holding this much 24 | # memory 25 | -m 4096 26 | 27 | # Default connection port is 11211 28 | -p 11211 29 | 30 | # Run the daemon as root. The start-memcached will default to running as root if no 31 | # -u command is present in this config file 32 | -u nobody 33 | 34 | # Specify which IP address to listen on. The default is to listen on all IP addresses 35 | # This parameter is one of the only security measures that memcached has, so make sure 36 | # it's listening on a firewalled interface. 37 | -l 127.0.0.1 38 | 39 | # Limit the number of simultaneous incoming connections. The daemon default is 1024 40 | # -c 1024 41 | 42 | # Lock down all paged memory. Consult with the README and homepage before you do this 43 | # -k 44 | 45 | # Return error when memory is exhausted (rather than removing items) 46 | # -M 47 | 48 | # Maximize core file limit 49 | # -r 50 | -------------------------------------------------------------------------------- /puppet/modules/memcached/manifests/init.pp: -------------------------------------------------------------------------------- 1 | # = Class: memcached 2 | # 3 | # Provides memcached installation and configuration. 4 | # 5 | class memcached { 6 | $packages = [ 7 | 'memcached', 8 | ] 9 | stdlib::ensure_packages($packages, { 10 | ensure => 'present', 11 | }) 12 | 13 | service { 'memcached': 14 | ensure => running, 15 | enable => true, 16 | hasstatus => true, 17 | hasrestart => true, 18 | require => Package['memcached'], 19 | } 20 | 21 | file { '/etc/memcached.conf': 22 | source => 'puppet:///modules/memcached/memcached.conf', 23 | backup => '.puppet.bak', 24 | require => Package['memcached'], 25 | notify => Service['memcached']; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /puppet/modules/nginx/files/error.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | An error? Don't worry! 7 | 8 | 9 |

Oops

10 |

It looks like our backend is currently unable to process your request. Please try again later.

11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /puppet/modules/nginx/files/ffdhe2048.txt: -------------------------------------------------------------------------------- 1 | -----BEGIN DH PARAMETERS----- 2 | MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz 3 | +8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a 4 | 87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7 5 | YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi 6 | 7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD 7 | ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg== 8 | -----END DH PARAMETERS----- -------------------------------------------------------------------------------- /puppet/modules/nginx/files/logrotate: -------------------------------------------------------------------------------- 1 | # This file is managed by puppet 2 | /var/log/nginx/*.log { 3 | daily 4 | missingok 5 | rotate 30 6 | compress 7 | delaycompress 8 | notifempty 9 | create 0640 www-data adm 10 | sharedscripts 11 | prerotate 12 | if [ -d /etc/logrotate.d/httpd-prerotate ]; then \ 13 | run-parts /etc/logrotate.d/httpd-prerotate; \ 14 | fi \ 15 | endscript 16 | postrotate 17 | [ -f /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid` 18 | endscript 19 | } 20 | -------------------------------------------------------------------------------- /puppet/modules/nginx/files/nginx.conf: -------------------------------------------------------------------------------- 1 | # file managed by puppet 2 | 3 | user www-data; 4 | worker_processes auto; 5 | pid /run/nginx.pid; 6 | 7 | events { 8 | worker_connections 2048; 9 | } 10 | 11 | http { 12 | 13 | ## 14 | # Basic Settings 15 | ## 16 | 17 | sendfile on; 18 | tcp_nopush on; 19 | tcp_nodelay on; 20 | keepalive_timeout 300 300; 21 | types_hash_max_size 2048; 22 | server_tokens off; 23 | 24 | include /etc/nginx/mime.types; 25 | default_type application/octet-stream; 26 | 27 | client_max_body_size 5M; 28 | 29 | ## 30 | # Logging Settings 31 | ## 32 | 33 | log_format main '$remote_addr $host $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $ssl_cipher $request_time'; 34 | access_log /var/log/nginx/access.log main; 35 | error_log /var/log/nginx/error.log; 36 | 37 | ## 38 | # Gzip Settings 39 | ## 40 | 41 | gzip on; 42 | gzip_comp_level 8; 43 | gzip_buffers 16 8k; 44 | gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml image/x-icon; 45 | 46 | ## 47 | # Virtual Host Configs 48 | ## 49 | 50 | upstream php { 51 | server unix:/run/php/php-fpm.sock; 52 | } 53 | 54 | limit_req_zone $binary_remote_addr zone=perip:1m rate=3r/s; 55 | 56 | include /etc/nginx/sites/*; 57 | } 58 | -------------------------------------------------------------------------------- /puppet/modules/nginx/files/offline: -------------------------------------------------------------------------------- 1 | # file managed by puppet 2 | 3 | server { 4 | listen 80 default_server; 5 | listen [2a03:4000:39:55d:5400:a2ff:fe21:b3ea]:80; 6 | listen 443 ssl default_server http2; 7 | listen [2a03:4000:39:55d:5400:a2ff:fe21:b3ea]:443 ssl http2; 8 | 9 | ssl_certificate /etc/ssl/private/translatewiki.net.pem; 10 | ssl_certificate_key /etc/ssl/private/translatewiki.net.key; 11 | 12 | ssl_session_cache shared:SSL:1m; 13 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2; 14 | ssl_prefer_server_ciphers on; 15 | ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS"; 16 | 17 | add_header Strict-Transport-Security "max-age=31536000"; 18 | 19 | server_name translatewiki.net; 20 | root /www/offline; 21 | 22 | location /index.php { 23 | set $fastcgi_pass_value unix:/var/run/php-fpm.sock; 24 | 25 | fastcgi_pass $fastcgi_pass_value; 26 | fastcgi_buffers 16 4k; 27 | include fastcgi.conf; 28 | } 29 | 30 | # there is probably better way to do this 31 | rewrite ^(/|/[^i].+)$ /index.php last; 32 | } 33 | -------------------------------------------------------------------------------- /puppet/modules/nginx/files/ssl-certbot.conf: -------------------------------------------------------------------------------- 1 | # file managed by puppet 2 | 3 | include includes/ssl.conf; 4 | 5 | ssl_certificate /etc/letsencrypt/live/translatewiki.net/fullchain.pem; 6 | ssl_certificate_key /etc/letsencrypt/live/translatewiki.net/privkey.pem; 7 | ssl_trusted_certificate /etc/letsencrypt/live/translatewiki.net/cert.pem; 8 | ssl_stapling on; 9 | ssl_stapling_verify on; 10 | resolver 8.8.8.8 8.8.4.4; 11 | -------------------------------------------------------------------------------- /puppet/modules/nginx/files/ssl.conf: -------------------------------------------------------------------------------- 1 | # file managed by puppet 2 | 3 | # https://ssl-config.mozilla.org/#server=nginx&server-version=1.14.2&config=intermediate&openssl-version=1.1.1d 4 | ssl_session_timeout 1d; 5 | ssl_session_cache shared:MozSSL:20m; # about 80000 sessions 6 | ssl_session_tickets off; 7 | 8 | ssl_dhparam /etc/ssl/certs/dhparam.pem; 9 | 10 | # intermediate configuration 11 | ssl_protocols TLSv1.2 TLSv1.3; 12 | ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; 13 | ssl_prefer_server_ciphers off; 14 | 15 | add_header Strict-Transport-Security "max-age=31536000; includeSubDomains"; 16 | 17 | ssl_buffer_size 4k; 18 | -------------------------------------------------------------------------------- /puppet/modules/nginx/files/translatewiki.org: -------------------------------------------------------------------------------- 1 | # file managed by puppet 2 | 3 | server { 4 | listen 80; 5 | listen [2a03:4000:39:55d:5400:a2ff:fe21:b3ea]:80; 6 | server_name translatewiki.org; 7 | 8 | return 301 https://translatewiki.net$request_uri; 9 | } 10 | 11 | server { 12 | listen 443 ssl http2; 13 | listen [2a03:4000:39:55d:5400:a2ff:fe21:b3ea]:443 ssl http2; 14 | server_name translatewiki.org; 15 | include includes/ssl-certbot.conf; 16 | 17 | return 301 https://translatewiki.net$request_uri; 18 | } 19 | -------------------------------------------------------------------------------- /puppet/modules/nginx/manifests/devsite.pp: -------------------------------------------------------------------------------- 1 | # = Class: nginx::ssl 2 | # 3 | # Provides SSL configuration for nginx sites. 4 | # 5 | class nginx::devsite ( 6 | String $domain, 7 | ) { 8 | $certdir = '/etc/ssl/localcerts'; 9 | 10 | File { 11 | require => File['/etc/nginx/nginx.conf'] 12 | } 13 | 14 | file { $certdir: 15 | ensure => 'directory', 16 | } 17 | 18 | file { '/etc/ssl/certs/dhparam.pem': 19 | source => 'puppet:///modules/nginx/ffdhe2048.txt', 20 | notify => Service[ 'nginx' ], 21 | } 22 | 23 | $dirs = [ 24 | '/etc/nginx', 25 | '/etc/nginx/sites', 26 | '/etc/nginx/includes', 27 | ] 28 | ensure_resource('file', $dirs, { 29 | ensure => 'directory', 30 | }) 31 | 32 | file { '/etc/nginx/includes/ssl.conf': 33 | source => 'puppet:///modules/nginx/ssl.conf', 34 | notify => Service[ 'nginx' ], 35 | } 36 | 37 | file { '/etc/nginx/includes/ssl-selfsigned.conf': 38 | content => template('nginx/ssl-selfsigned.conf.erb'), 39 | notify => Service[ 'nginx' ], 40 | } 41 | 42 | file { "/etc/nginx/sites/${domain}": 43 | content => template('nginx/devsite.conf.erb'), 44 | notify => Service[ 'nginx' ], 45 | } 46 | 47 | $command = @("COMMAND"/L) 48 | openssl req -newkey rsa:2048 -nodes -x509 -days 365 \ 49 | -keyout ${domain}.key -out ${domain}.crt -subj '/CN=${domain}' 50 | |-COMMAND 51 | 52 | exec { 'Create self-signed cert': 53 | command => $command, 54 | cwd => $certdir, 55 | creates => [ "${certdir}/${domain}.key", "${certdir}/${domain}.crt", ], 56 | path => $::path, 57 | notify => Service[ 'nginx' ], 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /puppet/modules/nginx/manifests/init.pp: -------------------------------------------------------------------------------- 1 | # = Class: nginx 2 | # 3 | # Provides installation and configuration information for the nginx package. 4 | # 5 | class nginx { 6 | $packages = [ 7 | 'nginx', 8 | ] 9 | stdlib::ensure_packages($packages, { 10 | ensure => 'present', 11 | }) 12 | 13 | service { 'nginx': 14 | ensure => running, 15 | enable => true, 16 | require => Package['nginx'], 17 | } 18 | 19 | File { 20 | require => Package['nginx'], 21 | notify => Service['nginx'], 22 | } 23 | 24 | file { '/etc/nginx/nginx.conf': 25 | source => 'puppet:///modules/nginx/nginx.conf', 26 | } 27 | 28 | file { '/etc/logrotate.d/nginx': 29 | source => 'puppet:///modules/nginx/logrotate' 30 | } 31 | 32 | file { '/www/error/': 33 | ensure => 'directory'; 34 | } 35 | 36 | file { '/www/error/error.html': 37 | source => 'puppet:///modules/nginx/error.html'; 38 | } 39 | 40 | # set up the default parameters for all firewall rules 41 | Firewall { 42 | before => Class['base::firewall::post'], 43 | require => Class['base::firewall::pre'], 44 | } 45 | 46 | firewall { '020 Allow inbound HTTP (v4)': 47 | dport => 80, 48 | proto => tcp, 49 | jump => accept, 50 | protocol => 'IPv4', 51 | } 52 | 53 | firewall { '020 Allow inbound HTTP (v6)': 54 | dport => 80, 55 | proto => tcp, 56 | jump => accept, 57 | protocol => 'IPv6', 58 | } 59 | 60 | firewall { '021 Allow inbound HTTPS (v4)': 61 | dport => 443, 62 | proto => tcp, 63 | jump => accept, 64 | protocol => 'IPv4', 65 | } 66 | 67 | firewall { '021 Allow inbound HTTPS (v6)': 68 | dport => 443, 69 | proto => tcp, 70 | jump => accept, 71 | protocol => 'IPv6', 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /puppet/modules/nginx/manifests/sites.pp: -------------------------------------------------------------------------------- 1 | # = Class: nginx::sites 2 | # 3 | # Provides configuration information for nginx sites. 4 | # 5 | class nginx::sites { 6 | include nginx::ssl 7 | 8 | File { 9 | require => File['/etc/nginx/nginx.conf'] 10 | } 11 | 12 | $directories = [ 13 | '/www', 14 | '/www/stats.translatewiki.net', 15 | '/www/translatewiki.net', 16 | '/www/translatewiki.net/docroot', 17 | '/www/translatewiki.net/error', 18 | ] 19 | ensure_resource('file', $directories, { 20 | 'ensure' => 'directory', 21 | 'owner' => 'betawiki', 22 | 'group' => 'users' 23 | }) 24 | 25 | file { '/etc/nginx/sites/translatewiki.net': 26 | source => 'puppet:///modules/nginx/translatewiki.net', 27 | } 28 | 29 | file { '/etc/nginx/sites/translatewiki.org': 30 | source => 'puppet:///modules/nginx/translatewiki.org', 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /puppet/modules/nginx/manifests/ssl.pp: -------------------------------------------------------------------------------- 1 | # = Class: nginx::ssl 2 | # 3 | # Provides SSL configuration for nginx sites. 4 | # 5 | class nginx::ssl { 6 | include nginx 7 | 8 | file { '/etc/ssl/certs/dhparam.pem': 9 | source => 'puppet:///modules/nginx/ffdhe2048.txt', 10 | notify => Service[ 'nginx' ], 11 | } 12 | 13 | file { '/etc/nginx/includes': 14 | ensure => 'directory', 15 | } 16 | 17 | file { '/etc/nginx/includes/ssl.conf': 18 | source => 'puppet:///modules/nginx/ssl.conf', 19 | } 20 | 21 | file { '/etc/nginx/includes/ssl-certbot.conf': 22 | source => 'puppet:///modules/nginx/ssl-certbot.conf', 23 | } 24 | 25 | class { '::letsencrypt': 26 | email => 'root@translatewiki.net', 27 | } 28 | 29 | letsencrypt::certonly { 'translatewiki.net': 30 | plugin => 'webroot', 31 | manage_cron => true, 32 | cron_success_command => 'systemctl reload nginx.service', 33 | cron_output => 'suppress', 34 | domains => [ 35 | 'translatewiki.net', 36 | 'translatewiki.org', 37 | 'stats.translatewiki.net', 38 | 'kitano.nl', 39 | ], 40 | webroot_paths => [ 41 | '/www/translatewiki.net/docroot', 42 | '/www/translatewiki.net/docroot', 43 | '/www/stats.translatewiki.net', 44 | '/www/kitano.nl', 45 | ], 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /puppet/modules/nginx/templates/devsite.conf.erb: -------------------------------------------------------------------------------- 1 | # file managed by puppet 2 | 3 | server { 4 | listen 80 default_server; 5 | server_name <%= @domain %>; 6 | return 301 https://$host$request_uri; 7 | } 8 | 9 | server { 10 | listen 443 ssl default_server deferred http2; 11 | server_name <%= @domain %>; 12 | root /www/$host/docroot; 13 | 14 | include includes/ssl-selfsigned.conf; 15 | 16 | location = / { 17 | rewrite ^ /w/index.php; 18 | } 19 | 20 | location ~ ^/wiki { 21 | rewrite ^ /w/index.php; 22 | } 23 | 24 | location = /sitemap { 25 | rewrite ^ "/w/index.php?title=Special:RecentChanges&translations=&feed=atom"; 26 | } 27 | 28 | location ~ ^/w/(cache|config|docs|includes|languages|maintenance|mw-config|tests|vendor)/ { 29 | deny all; 30 | } 31 | 32 | # Allowed php files, case sensitive 33 | location ~ ^/w/(index|load|api|opensearch_desc|rest|webfiles/jserror)\.php { 34 | limit_req zone=perip burst=30 delay=20; 35 | 36 | fastcgi_pass php; 37 | fastcgi_buffering off; 38 | fastcgi_buffers 16 16k; 39 | fastcgi_connect_timeout 1s; 40 | fastcgi_send_timeout 2s; 41 | fastcgi_read_timeout 15s; 42 | include fastcgi.conf; 43 | } 44 | 45 | # Deny access to all php files except those above 46 | location ~* \.php$ { 47 | deny all; 48 | } 49 | 50 | location ~* \.(png|jpg|jpeg|gif|ico|svg|woff|woff2|eot|ttf|webp)$ { 51 | expires 2M; 52 | } 53 | 54 | error_page 500 502 503 504 /error.html; 55 | location = /error.html { 56 | root /www/error; 57 | internal; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /puppet/modules/nginx/templates/ssl-selfsigned.conf.erb: -------------------------------------------------------------------------------- 1 | # file managed by puppet 2 | 3 | include includes/ssl.conf; 4 | ssl_certificate <%= @certdir %>/<%= @domain %>.crt; 5 | ssl_certificate_key <%= @certdir %>/<%= @domain %>.key; 6 | -------------------------------------------------------------------------------- /puppet/modules/php/files/wmerrors.ini: -------------------------------------------------------------------------------- 1 | wmerrors.enabled=On 2 | wmerrors.backtrace_in_php_error_message=On 3 | wmerrors.error_script_file=/www/error/error.html 4 | -------------------------------------------------------------------------------- /puppet/modules/php/files/www.conf: -------------------------------------------------------------------------------- 1 | ; managed by puppet 2 | 3 | [www] 4 | listen = /run/php/php-fpm.sock 5 | listen.owner = www-data 6 | listen.group = www-data 7 | user = www-data 8 | group = www-data 9 | 10 | pm = dynamic 11 | pm.max_children = 30 12 | pm.start_servers = 2 13 | pm.min_spare_servers = 2 14 | pm.max_spare_servers = 5 15 | pm.max_requests = 500 16 | 17 | request_terminate_timeout = 2m 18 | -------------------------------------------------------------------------------- /puppet/modules/php/manifests/init.pp: -------------------------------------------------------------------------------- 1 | # == Class: php 2 | # 3 | # Configures php for MediaWiki to run in cli and fpm modes. 4 | # 5 | class php { 6 | $packages = [ 7 | 'php-luasandbox', 8 | 'php-memcached', 9 | 'php-wikidiff2', 10 | 'php-wmerrors', 11 | 'php-yaml', 12 | 'php8.2-cli', 13 | 'php8.2-curl', 14 | 'php8.2-dba', 15 | 'php8.2-fpm', 16 | 'php8.2-gd', 17 | 'php8.2-gmp', # For WebAuthn 18 | 'php8.2-intl', 19 | 'php8.2-mbstring', 20 | 'php8.2-mysql', 21 | 'php8.2-opcache', 22 | 'php8.2-xml', 23 | ] 24 | stdlib::ensure_packages($packages, { 25 | ensure => 'present', 26 | }) 27 | 28 | file { '/etc/php/8.2/fpm/pool.d/www.conf': 29 | source => 'puppet:///modules/php/www.conf', 30 | require => Package['php8.2-fpm'], 31 | notify => Service['php-fpm'], 32 | } 33 | 34 | service { 'php-fpm': 35 | ensure => running, 36 | enable => true, 37 | name => 'php8.2-fpm.service', 38 | } 39 | 40 | file { '/etc/php/8.2/fpm/conf.d/50-wmerrors.ini': 41 | source => 'puppet:///modules/php/wmerrors.ini', 42 | require => Package['php8.2-fpm'], 43 | notify => Service['php-fpm'], 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /puppet/modules/profile/manifests/mwelasticsearch.pp: -------------------------------------------------------------------------------- 1 | # = Class: mwelasticsearch 2 | # 3 | # Provides elasticsearch configuration for MediaWiki. 4 | # 5 | class profile::mwelasticsearch ( 6 | String $memory_limit = '1g', 7 | ) { 8 | include ::apt 9 | 10 | # Do not automatically upgrade these packages 11 | apt::pin { 'elasticsearch': 12 | packages => [ 'elasticsearch-oss', 'kibana-oss' ], 13 | priority => 1000, 14 | version => '7.10.2', 15 | } 16 | 17 | class { 'java': distribution => 'jre' } 18 | 19 | class { 'elastic_stack::repo': 20 | version => 7, 21 | oss => true, 22 | } 23 | 24 | class { 'elasticsearch': 25 | restart_on_change => true, 26 | version => '7.10.2', 27 | oss => true, 28 | jvm_options => [ 29 | "-Xms${memory_limit}", 30 | "-Xmx${memory_limit}", 31 | ], 32 | } 33 | 34 | elasticsearch::plugin { 'org.wikimedia.search:extra:7.10.2-wmf1': 35 | } 36 | 37 | elasticsearch::plugin { 'org.wikimedia.search.highlighter:experimental-highlighter-elasticsearch-plugin:7.10.2': 38 | module_dir => 'experimental-highlighter' 39 | } 40 | 41 | class { 'kibana': 42 | ensure => '7.10.2', 43 | oss => true, 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /puppet/modules/repong/manifests/autobackport.pp: -------------------------------------------------------------------------------- 1 | # = Class: repong::autobackport 2 | # 3 | # Sets up automated backports using systemd timers 4 | # 5 | class repong::autobackport ( 6 | String $l10nbot_user = lookup('repong::l10nbot_user'), 7 | String $bin_dir = lookup('repong::bin_dir'), 8 | ) { 9 | systemd::unit_file { 'autobackport-mediawiki@.service': 10 | content => template('repong/autobackport-mediawiki@.service.erb'), 11 | } 12 | 13 | Repong::Autobackport_mediawiki_timer { 14 | require => User[ $l10nbot_user ], 15 | } 16 | 17 | # Using early European mornings when CI has low use 18 | # LTS; supported till November 2025 19 | repong::autobackport_mediawiki_timer { 'REL1_39': 20 | branch => 'REL1_39', 21 | when => 'Mon 05:30:00 UTC', 22 | } 23 | 24 | # supported till June 2025 25 | repong::autobackport_mediawiki_timer { 'REL1_42': 26 | branch => 'REL1_42', 27 | when => 'Thu 05:30:00 UTC', 28 | } 29 | 30 | # LTS; supported till December 2027 31 | repong::autobackport_mediawiki_timer { 'REL1_43': 32 | branch => 'REL1_43', 33 | when => 'Tue 05:30:00 UTC', 34 | } 35 | 36 | # supported till June 2026 37 | repong::autobackport_mediawiki_timer { 'REL1_44': 38 | branch => 'REL1_44', 39 | when => 'Wed 05:30:00 UTC', 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /puppet/modules/repong/manifests/autobackport_mediawiki_timer.pp: -------------------------------------------------------------------------------- 1 | # = Type: repong::autobackport_mediawiki_timer 2 | define repong::autobackport_mediawiki_timer ( 3 | String $branch, 4 | String $when, 5 | Boolean $active = true, 6 | ) { 7 | $ensure = $active ? { 8 | true => 'present', 9 | default => 'absent' 10 | }; 11 | systemd::timer { "autobackport-mediawiki-${branch}.timer": 12 | ensure => $ensure, 13 | timer_content => template('repong/autobackport-mediawiki.timer.erb'), 14 | active => $active, 15 | enable => $active, 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /puppet/modules/repong/manifests/autoexport.pp: -------------------------------------------------------------------------------- 1 | # = Class: repong::autoexport 2 | # 3 | # Sets up automated exports using systemd timers 4 | # 5 | class repong::autoexport ( 6 | String $l10nbot_user = lookup('repong::l10nbot_user'), 7 | ) { 8 | Repong::Autoexport_timer { 9 | require => User[ $l10nbot_user ], 10 | } 11 | 12 | repong::autoexport_timer { 'autoexport': 13 | when => 'Mon,Thu 12:00:00 UTC', 14 | } 15 | 16 | repong::autoexport_timer { 'autoexport-mediawiki': 17 | command => 'autoexport-mediawiki', 18 | when => 'Mon-Fri 7:00:00 UTC', 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /puppet/modules/repong/manifests/autoexport_timer.pp: -------------------------------------------------------------------------------- 1 | # = Type: repong::autoexport_timer 2 | define repong::autoexport_timer ( 3 | String $when, 4 | String $command = 'autoexport', 5 | String $l10nbot_user = lookup('repong::l10nbot_user'), 6 | String $bin_dir = lookup('repong::bin_dir'), 7 | Boolean $active = true, 8 | ) { 9 | $ensure = $active ? { 10 | true => 'present', 11 | default => 'absent' 12 | }; 13 | systemd::timer { "${name}.timer": 14 | ensure => $ensure, 15 | timer_content => template('repong/autoexport.timer.erb'), 16 | service_content => template('repong/autoexport.service.erb'), 17 | active => $active, 18 | enable => $active, 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /puppet/modules/repong/manifests/autoimport.pp: -------------------------------------------------------------------------------- 1 | # = Class: repong::autoimport 2 | # 3 | # Sets up automated imports using systemd timers 4 | # 5 | class repong::autoimport ( 6 | String $l10nbot_user = lookup('repong::l10nbot_user'), 7 | String $bin_dir = lookup('repong::bin_dir'), 8 | ) { 9 | Repong::Autoimport_timer { 10 | require => User[ $l10nbot_user ], 11 | } 12 | 13 | repong::autoimport_timer { 'autoimport': 14 | when => '*-*-* 0/2:30:00 UTC', 15 | } 16 | 17 | repong::autoimport_timer { 'autoimport-mediawiki': 18 | command => 'autoimport-mediawiki', 19 | when => '*-*-* 6,12,20:48:00 UTC', 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /puppet/modules/repong/manifests/autoimport_timer.pp: -------------------------------------------------------------------------------- 1 | # = Type: repong::autoimport_timer 2 | define repong::autoimport_timer ( 3 | String $when, 4 | String $command = 'autoimport', 5 | String $l10nbot_user = lookup('repong::l10nbot_user'), 6 | String $bin_dir = lookup('repong::bin_dir'), 7 | Boolean $active = true, 8 | ) { 9 | $ensure = $active ? { 10 | true => 'present', 11 | default => 'absent' 12 | }; 13 | systemd::timer { "${name}.timer": 14 | ensure => $ensure, 15 | timer_content => template('repong/autoimport.timer.erb'), 16 | service_content => template('repong/autoimport.service.erb'), 17 | active => $active, 18 | enable => $active, 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /puppet/modules/repong/manifests/init.pp: -------------------------------------------------------------------------------- 1 | # = Class: repong 2 | # 3 | # Sets up central directories for autoimports and autoexports 4 | # 5 | class repong ( 6 | String $config_dir, 7 | String $l10nbot_user, 8 | String $import_dir, 9 | String $export_dir, 10 | String $bin_dir, 11 | ) { 12 | Exec { 13 | require => User[ $l10nbot_user ], 14 | } 15 | 16 | exec { "Create import directory ${import_dir}": 17 | creates => $import_dir, 18 | command => "mkdir -p ${import_dir}", 19 | path => $::path, 20 | } -> file { $import_dir: 21 | ensure => 'directory', 22 | owner => $l10nbot_user, 23 | } 24 | 25 | file { "${import_dir}/repoconfig.yaml": 26 | ensure => 'link', 27 | target => "${config_dir}/repoconfig.yaml", 28 | owner => $l10nbot_user, 29 | } 30 | 31 | file { "${import_dir}/sync.lock": 32 | ensure => 'file', 33 | content => '', 34 | replace => 'no', 35 | owner => $l10nbot_user, 36 | mode => 'ugo+rw', 37 | } 38 | 39 | exec { "Create export directory ${export_dir}": 40 | creates => $export_dir, 41 | command => "mkdir -p ${export_dir}", 42 | path => $::path, 43 | } -> file { $export_dir: 44 | ensure => 'directory', 45 | owner => $l10nbot_user, 46 | } 47 | 48 | file { "${export_dir}/repoconfig.yaml": 49 | ensure => 'link', 50 | target => "${config_dir}/repoconfig.yaml", 51 | owner => $l10nbot_user, 52 | } 53 | 54 | file { "${export_dir}/REPONG-VARIANT": 55 | ensure => 'file', 56 | content => 'export', 57 | owner => $l10nbot_user, 58 | } 59 | 60 | systemd::timer { 'repong-cleanups.timer': 61 | timer_content => template('repong/repong-cleanups.timer.erb'), 62 | service_content => template('repong/repong-cleanups.service.erb'), 63 | active => true, 64 | enable => true, 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /puppet/modules/repong/templates/autobackport-mediawiki.timer.erb: -------------------------------------------------------------------------------- 1 | # This file is managed by puppet 2 | [Unit] 3 | Description=Run autobackport-mediawiki for a given branch on a defined schedule 4 | 5 | [Timer] 6 | OnCalendar=<%= @when %> 7 | Unit=autobackport-mediawiki@<%= @branch %>.service 8 | 9 | [Install] 10 | WantedBy=timers.target 11 | -------------------------------------------------------------------------------- /puppet/modules/repong/templates/autobackport-mediawiki@.service.erb: -------------------------------------------------------------------------------- 1 | # This file is managed by puppet 2 | [Unit] 3 | Description=Backport translations for MediaWiki translations for branch %I 4 | Requisite=mysql.service 5 | After=mysql.service 6 | 7 | [Service] 8 | User=<%= @l10nbot_user %> 9 | ExecStart=<%= @bin_dir %>/execute-and-notify <%= @bin_dir %>/autobackport-mediawiki "%i" 10 | ProtectHome=read-only 11 | ProtectSystem=full 12 | Nice=5 13 | -------------------------------------------------------------------------------- /puppet/modules/repong/templates/autoexport.service.erb: -------------------------------------------------------------------------------- 1 | # This file is managed by puppet 2 | [Unit] 3 | Description=Export translations 4 | Requisite=mysql.service 5 | After=mysql.service 6 | 7 | [Service] 8 | User=<%= @l10nbot_user %> 9 | ExecStart=<%= @bin_dir %>/execute-and-notify <%= @bin_dir %>/<%= @command %> 10 | ProtectHome=read-only 11 | ProtectSystem=full 12 | Nice=5 13 | -------------------------------------------------------------------------------- /puppet/modules/repong/templates/autoexport.timer.erb: -------------------------------------------------------------------------------- 1 | # This file is managed by puppet 2 | [Unit] 3 | Description=Run autoexport on a defined schedule 4 | 5 | [Timer] 6 | OnCalendar=<%= @when %> 7 | 8 | [Install] 9 | WantedBy=timers.target 10 | -------------------------------------------------------------------------------- /puppet/modules/repong/templates/autoimport.service.erb: -------------------------------------------------------------------------------- 1 | # This file is managed by puppet 2 | [Unit] 3 | Description=Automatically imports translations 4 | Requisite=mysql.service 5 | After=mysql.service 6 | 7 | [Service] 8 | User=<%= @l10nbot_user %> 9 | ExecStart=<%= @bin_dir %>/<%= @command %> 10 | ProtectHome=read-only 11 | ProtectSystem=full 12 | Nice=5 13 | -------------------------------------------------------------------------------- /puppet/modules/repong/templates/autoimport.timer.erb: -------------------------------------------------------------------------------- 1 | # This file is managed by puppet 2 | [Unit] 3 | Description=Run autoimport on a defined schedule 4 | 5 | [Timer] 6 | OnCalendar=<%= @when %> 7 | 8 | [Install] 9 | WantedBy=timers.target 10 | -------------------------------------------------------------------------------- /puppet/modules/repong/templates/repong-cleanups.service.erb: -------------------------------------------------------------------------------- 1 | # This file is managed by puppet 2 | [Unit] 3 | Description=Cleanups stale files related to repository handling 4 | 5 | [Service] 6 | ExecStart=<%= @bin_dir %>/repong-cleanups 7 | ProtectHome=read-only 8 | ProtectSystem=full 9 | Nice=10 10 | -------------------------------------------------------------------------------- /puppet/modules/repong/templates/repong-cleanups.timer.erb: -------------------------------------------------------------------------------- 1 | # This file is managed by puppet 2 | [Unit] 3 | Description=Run repong-cleanups on a defined schedule 4 | 5 | [Timer] 6 | OnCalendar=weekly 7 | AccuracySec=12h 8 | Persistent=true 9 | 10 | [Install] 11 | WantedBy=timers.target 12 | -------------------------------------------------------------------------------- /puppet/modules/sshd/files/sshd_config: -------------------------------------------------------------------------------- 1 | # This file is managed by puppet 2 | Protocol 2 3 | PermitRootLogin no 4 | PasswordAuthentication no 5 | KbdInteractiveAuthentication no 6 | PrintMotd no 7 | UsePAM yes 8 | AcceptEnv LANG LC_* 9 | Subsystem sftp /usr/lib/openssh/sftp-server 10 | -------------------------------------------------------------------------------- /puppet/modules/sshd/manifests/init.pp: -------------------------------------------------------------------------------- 1 | # = Class: ssh 2 | # 3 | # Provides sshd configuration for servers. 4 | # 5 | class sshd { 6 | $packages = [ 7 | 'mosh', # ssh for bad connections 8 | ] 9 | stdlib::ensure_packages($packages, { 10 | ensure => 'present', 11 | }) 12 | 13 | file { '/etc/ssh/sshd_config': 14 | source => 'puppet:///modules/sshd/sshd_config', 15 | notify => Service['sshd'], 16 | } 17 | 18 | service { 'sshd': 19 | ensure => running, 20 | enable => true, 21 | } 22 | 23 | # set up the default parameters for all firewall rules 24 | Firewall { 25 | before => Class['base::firewall::post'], 26 | require => Class['base::firewall::pre'], 27 | } 28 | 29 | firewall { '009 Allow inbound mosh (v4)': 30 | dport => '60000:61000', 31 | proto => udp, 32 | jump => accept, 33 | protocol => 'IPv4', 34 | } 35 | 36 | firewall { '009 Allow inbound mosh (v6)': 37 | dport => '60000:61000', 38 | proto => udp, 39 | jump => accept, 40 | protocol => 'IPv6', 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /puppet/modules/users/files/aliases: -------------------------------------------------------------------------------- 1 | # file managed by puppet 2 | 3 | mailer-daemon: postmaster 4 | postmaster: root 5 | nobody: root 6 | hostmaster: root 7 | usenet: root 8 | news: root 9 | webmaster: root 10 | www: root 11 | www-data: root 12 | ftp: root 13 | abuse: root 14 | noc: root 15 | security: root 16 | l10n-bot: root 17 | 18 | # Who gets all the junk email :) 19 | root: siebrand@kitano.nl, niklas.laxstrom@gmail.com, apatro@wikimedia.org 20 | 21 | # Personal email aliases 22 | amir: amir.aharoni@mail.huji.ac.il 23 | nike: niklas.laxstrom@gmail.com 24 | raymond: raimond.spekking@gmail.com 25 | siebrand: siebrand@kitano.nl 26 | federico: federicoleva@tiscali.it 27 | 28 | # Main contact address for translation admins 29 | translatewiki: siebrand@kitano.nl, niklas.laxstrom@gmail.com, apatro@wikimedia.org 30 | 31 | # Legacy? 32 | blockly: siebrand@kitano.nl 33 | 34 | # BounceHandler 35 | bouncehandler: "|curl --interface 127.0.0.1 -d action=bouncehandler -d format=json --data-urlencode email@- https://translatewiki.net/w/api.php" 36 | -------------------------------------------------------------------------------- /puppet/modules/users/manifests/aliases.pp: -------------------------------------------------------------------------------- 1 | # = Class: users 2 | # 3 | # Provides /etc/aliases 4 | # 5 | class users::aliases { 6 | # Pull down the main aliases file 7 | file { '/etc/aliases': 8 | source => 'puppet:///modules/users/aliases' 9 | } 10 | 11 | # Rebuild the database, but only when the file changes 12 | exec { 'newaliases': 13 | path => ['/usr/bin', '/usr/sbin'], 14 | subscribe => File['/etc/aliases'], 15 | refreshonly => true 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /puppet/modules/users/templates/sudo.erb: -------------------------------------------------------------------------------- 1 | # file managed by puppet 2 | Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:<%= @bin_dir %>" 3 | %sysadmin ALL = NOPASSWD: ALL 4 | %betawiki ALL = (<%= @maintenance_user %>) NOPASSWD: ALL 5 | %betawiki ALL = (<%= @repo_user %>) NOPASSWD: ALL 6 | %betawiki ALL = NOPASSWD: /usr/sbin/service mw-jobrunner restart 7 | %betawiki ALL = NOPASSWD: /usr/sbin/service php8.2-fpm reload 8 | %<%= @l10nbot_group %> ALL = (<%= @l10nbot_user %>) NOPASSWD: ALL 9 | -------------------------------------------------------------------------------- /puppet/modules/wiki/files/phplog2irc.service: -------------------------------------------------------------------------------- 1 | # This file is managed by puppet 2 | [Unit] 3 | Description=Process and relay error messages to irc-log-relay 4 | After=network.target 5 | 6 | [Service] 7 | User=betawiki 8 | Group=betawiki 9 | ExecStart=/bin/sh /home/betawiki/config/relays/irc/rakkauspipe.sh 10 | Restart=always 11 | RestartSec=60 12 | PrivateDevices=true 13 | PrivateTmp=true 14 | ProtectHome=read-only 15 | ProtectSystem=full 16 | 17 | [Install] 18 | WantedBy=multi-user.target 19 | -------------------------------------------------------------------------------- /puppet/modules/wiki/manifests/docroot.pp: -------------------------------------------------------------------------------- 1 | # = Class: wiki::docroot 2 | # 3 | # Creates directories for wiki deployment 4 | # 5 | class wiki::docroot ( 6 | String $maintenance_user, 7 | String $domain, 8 | String $production_dir, 9 | ) { 10 | $directories = [ 11 | '/www', 12 | "/www/${domain}", 13 | "/www/${domain}/docroot", 14 | ] 15 | ensure_resource('file', $directories, { 16 | ensure => 'directory', 17 | }) 18 | 19 | file { "/www/${domain}/docroot/w": 20 | ensure => 'symlink', 21 | target => $production_dir, 22 | require => File[ "/www/${domain}/docroot" ], 23 | } 24 | 25 | $shared_directories = [ 26 | "/www/${domain}/logs", 27 | "/www/${domain}/docroot/images", 28 | "/www/${domain}/docroot/sitemap", 29 | ] 30 | file { $shared_directories: 31 | ensure => 'directory', 32 | group => 'www-shared', 33 | mode => '2664', 34 | require => Group[ 'www-shared' ], 35 | } 36 | 37 | # It seems that php ignores umask for error_log file. Hence default setfacl permissions 38 | # are not sufficient here. Instead create the files pre-emptively, which has the added 39 | # benefit that also log rotation can use the same list. 40 | $log_files = [ 41 | "/www/${domain}/logs/access_cli", 42 | "/www/${domain}/logs/auth", 43 | "/www/${domain}/logs/debug", 44 | "/www/${domain}/logs/error_js", 45 | "/www/${domain}/logs/error_php", 46 | "/www/${domain}/logs/group_sync", 47 | ] 48 | 49 | file { $log_files: 50 | ensure => 'file', 51 | owner => $maintenance_user, 52 | group => 'www-shared', 53 | mode => 'ug=rw,o=r', 54 | require => [ 55 | Group[ 'www-shared' ], 56 | User[ $maintenance_user ], 57 | File[ "/www/${domain}/logs/" ], 58 | ], 59 | } 60 | 61 | file { '/etc/logrotate.d/mediawiki': 62 | content => template('wiki/mw-logrotate.erb'), 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /puppet/modules/wiki/manifests/irc.pp: -------------------------------------------------------------------------------- 1 | # = Class: wiki::irc 2 | # 3 | # Configures various IRC related wiki stuff 4 | # 5 | class wiki::irc ( 6 | String $config_dir, 7 | String $maintenance_user, 8 | ) { 9 | $packages = [ 10 | # irc bots 11 | 'libpoe-component-irc-perl', 12 | ] 13 | stdlib::ensure_packages($packages, { 14 | ensure => 'present', 15 | }) 16 | 17 | file { '/etc/irc-relay': 18 | ensure => 'directory', 19 | } 20 | 21 | file { '/etc/irc-relay/irc-log-relay.env': 22 | content => template('wiki/irc-log-relay.env.erb'), 23 | } 24 | 25 | file { '/etc/systemd/system/irc-log-relay.service': 26 | content => template('wiki/irc-log-relay.service.erb'), 27 | } 28 | 29 | service { 'irc-log-relay': 30 | ensure => running, 31 | enable => true, 32 | require => [ 33 | File['/etc/systemd/system/irc-log-relay.service'], 34 | File['/etc/irc-relay/irc-log-relay.env'] 35 | ], 36 | } 37 | 38 | file { '/etc/irc-relay/irc-rc-relay.env': 39 | content => template('wiki/irc-rc-relay.env.erb'), 40 | } 41 | 42 | file { '/etc/systemd/system/irc-rc-relay.service': 43 | content => template('wiki/irc-rc-relay.service.erb'), 44 | } 45 | 46 | service { 'irc-rc-relay': 47 | ensure => running, 48 | enable => true, 49 | require => [ 50 | File['/etc/systemd/system/irc-rc-relay.service'], 51 | File['/etc/irc-relay/irc-rc-relay.env'] 52 | ], 53 | } 54 | 55 | file { '/etc/systemd/system/phplog2irc.service': 56 | source => 'puppet:///modules/wiki/phplog2irc.service', 57 | } 58 | 59 | service { 'phplog2irc': 60 | ensure => running, 61 | enable => true, 62 | require => File['/etc/systemd/system/phplog2irc.service'], 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /puppet/modules/wiki/manifests/slack.pp: -------------------------------------------------------------------------------- 1 | # = Class: wiki::slack 2 | # 3 | # Configures various Slack related requirements. 4 | # 5 | class wiki::slack ( 6 | String $config_dir, 7 | String $maintenance_user, 8 | String $slack_webhook_url = lookup('slack_webhook_url') 9 | ) { 10 | 11 | file { '/etc/systemd/system/slack-log-relay.service': 12 | content => template('wiki/slack-log-relay.service.erb'), 13 | notify => [ 14 | Service['slack-log-relay'] 15 | ] 16 | } 17 | 18 | service { 'slack-log-relay': 19 | ensure => running, 20 | enable => true, 21 | require => [ 22 | File['/etc/systemd/system/slack-log-relay.service'], 23 | ] 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /puppet/modules/wiki/manifests/stats.pp: -------------------------------------------------------------------------------- 1 | # = Class: wiki 2 | # 3 | # Enables daily stat scripts 4 | class wiki::stats ( 5 | String $config_dir, 6 | String $l10nbot_user, 7 | ) { 8 | systemd::timer { 'mw-newcorelangs.timer': 9 | timer_content => template('wiki/mw-newcorelangs.timer.erb'), 10 | service_content => template('wiki/mw-newcorelangs.service.erb'), 11 | active => true, 12 | enable => true, 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /puppet/modules/wiki/templates/LocalSettings.php.erb: -------------------------------------------------------------------------------- 1 | '; 4 | $CONF = '<%= @config_dir %>'; 5 | $IP = __DIR__; 6 | 7 | $wgSecretKey = file_get_contents( "$IP/../secretkey" ); 8 | require_once "$CONF/mw-config/<%= @mediawiki_config %>"; 9 | require_once "$IP/../CustomSettings.php"; 10 | -------------------------------------------------------------------------------- /puppet/modules/wiki/templates/irc-log-relay.env.erb: -------------------------------------------------------------------------------- 1 | # This file is managed by puppet 2 | IRC_NICK=rakkaus 3 | IRC_NAME=translatewiki.net utility bot 4 | IRC_RELAY_PORT=8966 5 | IRC_HOST=irc.libera.chat 6 | IRC_PORT=6667 7 | IRC_CHANNEL=#translatewiki 8 | IRC_MESSAGE_TYPE=notice 9 | -------------------------------------------------------------------------------- /puppet/modules/wiki/templates/irc-log-relay.service.erb: -------------------------------------------------------------------------------- 1 | # This file is managed by puppet 2 | [Unit] 3 | Description=IRC relay for PHP error log 4 | After=network.target 5 | 6 | [Service] 7 | User=<%= @maintenance_user %> 8 | ExecStart=/usr/bin/perl <%= @config_dir %>/relays/irc/relay.pl 9 | Restart=always 10 | RestartSec=60 11 | PrivateDevices=true 12 | PrivateTmp=true 13 | ProtectHome=read-only 14 | ProtectSystem=full 15 | EnvironmentFile=/etc/irc-relay/irc-log-relay.env 16 | 17 | [Install] 18 | WantedBy=multi-user.target 19 | -------------------------------------------------------------------------------- /puppet/modules/wiki/templates/irc-rc-relay.env.erb: -------------------------------------------------------------------------------- 1 | # This file is managed by puppet 2 | IRC_NICK=rakkaudella 3 | IRC_NAME=translatewiki.net recent changes relay 4 | IRC_RELAY_PORT=8967 5 | IRC_HOST=irc.libera.chat 6 | IRC_PORT=6667 7 | IRC_CHANNEL=#translatewiki-rc 8 | IRC_MESSAGE_TYPE=privmsg 9 | -------------------------------------------------------------------------------- /puppet/modules/wiki/templates/irc-rc-relay.service.erb: -------------------------------------------------------------------------------- 1 | # This file is managed by puppet 2 | [Unit] 3 | Description=IRC relay for MediaWiki recent changes 4 | After=network.target 5 | 6 | [Service] 7 | User=<%= @maintenance_user %> 8 | ExecStart=/usr/bin/perl <%= @config_dir %>/relays/irc/relay.pl 9 | Restart=always 10 | RestartSec=60 11 | PrivateDevices=true 12 | PrivateTmp=true 13 | ProtectHome=read-only 14 | ProtectSystem=full 15 | EnvironmentFile=/etc/irc-relay/irc-rc-relay.env 16 | 17 | [Install] 18 | WantedBy=multi-user.target 19 | -------------------------------------------------------------------------------- /puppet/modules/wiki/templates/mw-completeexternaltranslation.service.erb: -------------------------------------------------------------------------------- 1 | # This file is managed by puppet 2 | [Unit] 3 | Description=Complete external translation synchronization 4 | Requisite=mysql.service 5 | After=mysql.service 6 | 7 | [Service] 8 | User=<%= @maintenance_user %> 9 | ExecStart=/usr/bin/php <%= @production_dir %>/maintenance/run.php <%= @production_dir %>/extensions/Translate/scripts/completeExternalTranslation.php 10 | ProtectHome=read-only 11 | ProtectSystem=full 12 | Nice=5 13 | -------------------------------------------------------------------------------- /puppet/modules/wiki/templates/mw-completeexternaltranslation.timer.erb: -------------------------------------------------------------------------------- 1 | # This file is managed by puppet 2 | [Unit] 3 | Description=Run mw-completeexternaltranslation every 15m 4 | 5 | [Timer] 6 | AccuracySec=1m 7 | OnBootSec=15m 8 | OnUnitActiveSec=15m 9 | 10 | [Install] 11 | WantedBy=timers.target 12 | -------------------------------------------------------------------------------- /puppet/modules/wiki/templates/mw-jobrunner.service.erb: -------------------------------------------------------------------------------- 1 | # This file is managed by puppet 2 | [Unit] 3 | Description=Process MediaWiki jobs 4 | After=mysql.service network.target 5 | 6 | [Service] 7 | User=www-data 8 | Group=www-data 9 | ExecStart=/usr/bin/php <%= @production_dir %>/maintenance/run.php runJobs --wait --maxjobs=1000 --memory-limit=1G --procs=4 10 | Restart=always 11 | RestartSec=1 12 | ProtectHome=read-only 13 | ProtectSystem=full 14 | Nice=5 15 | 16 | [Install] 17 | WantedBy=multi-user.target 18 | -------------------------------------------------------------------------------- /puppet/modules/wiki/templates/mw-logrotate.erb: -------------------------------------------------------------------------------- 1 | # file managed by puppet 2 | 3 | <% @log_files.each do |file| -%> 4 | <%= file %> 5 | <% end -%> 6 | { 7 | su <%= @maintenance_user %> www-shared 8 | copytruncate 9 | weekly 10 | rotate 4 11 | maxage 30 12 | nocompress 13 | dateext 14 | } 15 | -------------------------------------------------------------------------------- /puppet/modules/wiki/templates/mw-newcorelangs.service.erb: -------------------------------------------------------------------------------- 1 | # This file is managed by puppet 2 | [Unit] 3 | Description=Update Translating:MediaWiki/New_languages wiki page 4 | Requisite=mysql.service 5 | After=mysql.service 6 | 7 | [Service] 8 | User=<%= @l10nbot_user %> 9 | ExecStart=/bin/bash <%= @config_dir %>/bin/stats-newcorelangs 10 | ProtectHome=read-only 11 | ProtectSystem=full 12 | Nice=10 13 | -------------------------------------------------------------------------------- /puppet/modules/wiki/templates/mw-newcorelangs.timer.erb: -------------------------------------------------------------------------------- 1 | # This file is managed by puppet 2 | [Unit] 3 | Description=Run mw-newcorelangs 4 | 5 | [Timer] 6 | AccuracySec=1h 7 | OnBootSec=2h 8 | OnUnitActiveSec=12h 9 | 10 | [Install] 11 | WantedBy=timers.target 12 | -------------------------------------------------------------------------------- /puppet/modules/wiki/templates/mw-sitemap.service.erb: -------------------------------------------------------------------------------- 1 | # This file is managed by puppet 2 | [Unit] 3 | Description=Generate sitemap for MediaWiki 4 | Requisite=mysql.service 5 | After=mysql.service 6 | 7 | [Service] 8 | User=<%= @maintenance_user %> 9 | ExecStart=/usr/bin/php <%= @production_dir %>/maintenance/run.php generateSitemap --fspath /www/<%= @domain %>/docroot/sitemap/ --skip-redirects --urlpath sitemap/ 10 | ProtectHome=read-only 11 | ProtectSystem=full 12 | Nice=10 13 | -------------------------------------------------------------------------------- /puppet/modules/wiki/templates/mw-sitemap.timer.erb: -------------------------------------------------------------------------------- 1 | # This file is managed by puppet 2 | [Unit] 3 | Description=Run mw-sitemap 4 | 5 | [Timer] 6 | OnCalendar=weekly 7 | AccuracySec=12h 8 | Persistent=true 9 | 10 | [Install] 11 | WantedBy=timers.target 12 | -------------------------------------------------------------------------------- /puppet/modules/wiki/templates/mw-specialpages.service.erb: -------------------------------------------------------------------------------- 1 | # This file is managed by puppet 2 | [Unit] 3 | Description=Update cached MediaWiki special pages 4 | Requisite=mysql.service 5 | After=mysql.service 6 | 7 | [Service] 8 | User=<%= @maintenance_user %> 9 | ExecStart=/usr/bin/php <%= @production_dir %>/maintenance/run.php updateSpecialPages 10 | ProtectHome=read-only 11 | ProtectSystem=full 12 | Nice=10 13 | -------------------------------------------------------------------------------- /puppet/modules/wiki/templates/mw-specialpages.timer.erb: -------------------------------------------------------------------------------- 1 | # This file is managed by puppet 2 | [Unit] 3 | Description=Run mw-specialpages 4 | 5 | [Timer] 6 | OnCalendar=weekly 7 | AccuracySec=12h 8 | Persistent=true 9 | 10 | [Install] 11 | WantedBy=timers.target 12 | -------------------------------------------------------------------------------- /puppet/modules/wiki/templates/mw-supportedlanguages.service.erb: -------------------------------------------------------------------------------- 1 | # This file is managed by puppet 2 | [Unit] 3 | Description=Update Special:SupportedLanguages caches 4 | Requisite=mysql.service 5 | After=mysql.service 6 | 7 | [Service] 8 | User=<%= @maintenance_user %> 9 | ExecStart=/usr/bin/php <%= @production_dir %>/maintenance/run.php <%= @production_dir %>/extensions/Translate/scripts/updateTranslatorActivity.php 10 | ProtectHome=read-only 11 | ProtectSystem=full 12 | Nice=10 13 | -------------------------------------------------------------------------------- /puppet/modules/wiki/templates/mw-supportedlanguages.timer.erb: -------------------------------------------------------------------------------- 1 | # This file is managed by puppet 2 | [Unit] 3 | Description=Run wiki-supportedlanguages daily 4 | 5 | [Timer] 6 | AccuracySec=10m 7 | OnBootSec=2h 8 | OnUnitActiveSec=1d 9 | 10 | [Install] 11 | WantedBy=timers.target 12 | -------------------------------------------------------------------------------- /puppet/modules/wiki/templates/mw-translationexports.service.erb: -------------------------------------------------------------------------------- 1 | # This file is managed by puppet 2 | [Unit] 3 | Description=Export translations in a dump file 4 | After=network.target 5 | 6 | [Service] 7 | User=<%= @maintenance_user %> 8 | ExecStart=/bin/bash <%= @bin_dir %>/export-translation-dump 9 | ProtectHome=read-only 10 | ProtectSystem=full 11 | Nice=10 12 | -------------------------------------------------------------------------------- /puppet/modules/wiki/templates/mw-translationexports.timer.erb: -------------------------------------------------------------------------------- 1 | # This file is managed by puppet 2 | [Unit] 3 | Description=Run mw-translationexports 4 | 5 | [Timer] 6 | OnCalendar=bi-annually 7 | AccuracySec=24h 8 | Persistent=true 9 | 10 | [Install] 11 | WantedBy=timers.target 12 | -------------------------------------------------------------------------------- /puppet/modules/wiki/templates/slack-log-relay.service.erb: -------------------------------------------------------------------------------- 1 | # This file is managed by puppet 2 | [Unit] 3 | Description=Slack relay for PHP error log 4 | After=network.target 5 | 6 | [Service] 7 | User=<%= @maintenance_user %> 8 | ExecStart=/bin/sh <%= @config_dir %>/relays/slack/slackpipe.sh 9 | Restart=always 10 | RestartSec=60 11 | PrivateDevices=true 12 | PrivateTmp=true 13 | ProtectHome=read-only 14 | ProtectSystem=full 15 | Environment="SLACK_LOG_WEBHOOK=<%= @slack_webhook_url %>" 16 | 17 | [Install] 18 | WantedBy=multi-user.target 19 | -------------------------------------------------------------------------------- /puppet/modules/wiki/templates/wikisettings.erb: -------------------------------------------------------------------------------- 1 | # Variables required by scripts 2 | 3 | WIKIDIR=<%= @production_dir %> 4 | WIKISCRIPT=<%= @production_dir %>/maintenance/run.php 5 | WORKDIR=<%= @work_dir %> 6 | CONFDIR=<%= @config_dir %> 7 | MAINTUSER=<%= @maintenance_user %> 8 | WIKINAME=<%= @domain %> 9 | REPOUSER=<%= @repo_user %> 10 | L10NBOTUSER=<%= @l10nbot_user %> 11 | AUTOIMPORT_DIR=<%= @autoimport_dir %> 12 | AUTOEXPORT_DIR=<%= @autoexport_dir %> 13 | LOCKFILE=<%= @lockfile %> 14 | -------------------------------------------------------------------------------- /puppet/setup-environment.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o nounset -o pipefail -o errexit 3 | 4 | HOSTNAME=${1:-dev.translatewiki.net} 5 | DEB=puppet7-release-bullseye.deb 6 | 7 | echo -e "\n\n\nInstalling puppet..." 8 | cd /root 9 | wget "https://apt.puppetlabs.com/$DEB" -O "$DEB" 10 | dpkg -i "$DEB" 11 | apt update 12 | apt install -y git puppet-agent make librarian-puppet 13 | 14 | # Update PATHs 15 | . /etc/profile 16 | echo -e "\n\n\nDownloading configuration..." 17 | git clone https://gerrit.wikimedia.org/r/translatewiki 18 | cd translatewiki/puppet 19 | 20 | hostnamectl set-hostname "$HOSTNAME" 21 | cp data/developer.yaml.example data/developer.yaml 22 | nano data/developer.yaml 23 | 24 | echo -e "\n\n\nRunning puppet..." 25 | make apply 26 | 27 | # Update PATHs 28 | . /etc/profile 29 | echo -e "\n\n\nUpdating wiki..." 30 | cd /home/developer/translatewiki 31 | twn-update-all 32 | # Fails halfway the first time due to checkuser 33 | twn-update-database || twn-update-database 34 | 35 | echo -e "\n\n\nConfiguring elastic search..." 36 | cd /home/developer/mediawiki/workdir 37 | php maintenance/run.php ./extensions/Translate/scripts/ttmserver-export.php 38 | 39 | cd /root 40 | rm -r "$DEB" translatewiki 41 | 42 | echo "\n\n\nTo access developer account on the wiki, you need to reset the password with" 43 | echo " php /home/developer/mediawiki/workdir/maintenance/run.php changePassword --user Developer --password '...'" 44 | echo "\n\n\nReboot the machine to ensure all config changes are enabled" 45 | -------------------------------------------------------------------------------- /puppet/site.pp: -------------------------------------------------------------------------------- 1 | lookup('classes', {merge => unique}).include 2 | 3 | # It is not possible to create resources directly in hiera data 4 | lookup('keyholder::agent').each |$name, $cfg| { 5 | ::keyholder::agent { 6 | "${name}": * => $cfg, 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /relays/irc/README: -------------------------------------------------------------------------------- 1 | The bot code needs the following packages: libpoe-perl libpoe-component-irc-perl 2 | Originally written by OverlordQ: http://en.wikipedia.org/wiki/User:OverlordQ/IRCRCBot 3 | 4 | Feature requests: 5 | * Authentication against nickserv 6 | -------------------------------------------------------------------------------- /relays/irc/rakkauspipe.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | php /home/betawiki/config/relays/logfilter.php /www/translatewiki.net/logs/error_php | nc -u 127.0.0.1 8966 5 | -------------------------------------------------------------------------------- /relays/logfilter.php: -------------------------------------------------------------------------------- 1 | 2 ) { 41 | $count -= 2; 42 | $note = "($count lines skipped) "; 43 | } 44 | if ( mb_strlen( $line ) > 400 ) { 45 | $line = mb_substr( $line, 0, 400 ) . '...'; 46 | } 47 | echo "$line $note\n"; 48 | } 49 | 50 | sleep( $count ? 30 : 1 ); 51 | } 52 | -------------------------------------------------------------------------------- /relays/slack/slack-logger.php: -------------------------------------------------------------------------------- 1 | 0 ) { 24 | // There is data to read from STDIN 25 | $data = fgets( STDIN ); 26 | 27 | if ( $data !== false ) { 28 | sendSlackMessage( $webhook, generateSlackMessage( $data ) ); 29 | } 30 | } 31 | $read = [ STDIN ]; 32 | 33 | } 34 | } catch ( Exception $e ) { 35 | exit( "$e" ); 36 | } 37 | 38 | /** 39 | * Generate a Slack message 40 | */ 41 | function generateSlackMessage( string $data ): string { 42 | $slackMessage = [ 43 | 'text' => "```$data```", 44 | 'username' => 'Translatewiki Logger', 45 | ]; 46 | return json_encode( $slackMessage ); 47 | } 48 | 49 | /** 50 | * Send a Slack message via curl 51 | */ 52 | function sendSlackMessage( string $webhookUrl, string $payload ): void { 53 | $c = curl_init( $webhookUrl ); 54 | curl_setopt( $c, CURLOPT_RETURNTRANSFER, true ); 55 | curl_setopt( $c, CURLOPT_SSL_VERIFYPEER, true ); 56 | curl_setopt( $c, CURLOPT_POST, true ); 57 | curl_setopt( $c, CURLOPT_FAILONERROR, true ); 58 | curl_setopt( $c, CURLOPT_POSTFIELDS, [ 'payload' => $payload ] ); 59 | curl_exec( $c ); 60 | 61 | if ( curl_errno( $c ) ) { 62 | $errorMessage = curl_error( $c ); 63 | } 64 | curl_close( $c ); 65 | 66 | if ( isset( $errorMessage ) ) { 67 | throw new Exception( $errorMessage ); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /relays/slack/slackpipe.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | DIRSCRIPT=$(dirname "$(readlink -f "$0")") 5 | 6 | php $DIRSCRIPT/../logfilter.php /www/translatewiki.net/logs/error_php | php $DIRSCRIPT/slack-logger.php 7 | -------------------------------------------------------------------------------- /repong/.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | -------------------------------------------------------------------------------- /repong/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "translatewiki/repong", 3 | "description": "Command line VCS repository management tool", 4 | "license": "GPL-2.0-or-later", 5 | "autoload": { 6 | "psr-4": { "Translatewiki\\RepoNg\\": "src/" } 7 | }, 8 | "require": { 9 | "symfony/console": "^7.0", 10 | "symfony/process": "^7.0", 11 | "knplabs/github-api": "^3.14", 12 | "m4tthumphrey/php-gitlab-api": "^11.0", 13 | "guzzlehttp/guzzle": "^7.0.1", 14 | "http-interop/http-factory-guzzle": "^1.0", 15 | "ext-yaml": "*", 16 | "ext-json": "*" 17 | }, 18 | "require-dev": { 19 | "php-parallel-lint/php-console-highlighter": "1.0.0", 20 | "php-parallel-lint/php-parallel-lint": "1.4.0" 21 | }, 22 | "scripts": { 23 | "test": [ 24 | "parallel-lint . --exclude vendor" 25 | ] 26 | }, 27 | "config": { 28 | "allow-plugins": { 29 | "php-http/discovery": false 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /repong/repong.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | BackportCommand::class, 19 | 'commit' => CommitCommand::class, 20 | 'diff' => DiffCommand::class, 21 | 'export' => ExportCommand::class, 22 | 'list-projects' => ListCommand::class, 23 | 'purge' => PurgeCommand::class, 24 | 'status' => StatusCommand::class, 25 | 'update' => UpdateCommand::class, 26 | ]; 27 | 28 | $commandFactory = static function ( $className ) { 29 | return static function () use ( $className ) { 30 | return new $className(); 31 | }; 32 | }; 33 | 34 | $commandLoader = new FactoryCommandLoader( 35 | array_map( $commandFactory, $commandList ) 36 | ); 37 | 38 | $application = new Application(); 39 | $application->setCommandLoader( $commandLoader ); 40 | $application->run(); 41 | -------------------------------------------------------------------------------- /repong/src/App/DiffCommand.php: -------------------------------------------------------------------------------- 1 | setName( 'diff' ); 17 | $this->setDescription( 'Shows uncommitted changes' ); 18 | $this->addArgument( 'project', InputArgument::REQUIRED ); 19 | $this->addOption( 'variant', null, InputOption::VALUE_REQUIRED ); 20 | $this->addOption( 'filter', null, InputOption::VALUE_REQUIRED ); 21 | } 22 | 23 | protected function execute( InputInterface $input, OutputInterface $output ): int { 24 | $project = $input->getArgument( 'project' ); 25 | $variant = $input->getOption( 'variant' ) ?: $this->defaultVariant; 26 | $filter = $input->getOption( 'filter' ); 27 | $config = $this->getConfig( $project, $variant ); 28 | $base = $this->getBase(); 29 | 30 | $processes = new SplObjectStorage(); 31 | 32 | foreach ( $config['repos'] as $name => $repo ) { 33 | if ( $filter !== null && !fnmatch( $filter, $name ) ) { 34 | continue; 35 | } 36 | 37 | $type = $repo['type']; 38 | $genericType = $this->getGenericRepositoryType( $repo['type'] ); 39 | 40 | $command = "cd '$name' && "; 41 | if ( $genericType === 'git' ) { 42 | $command .= "git diff"; 43 | } elseif ( $type === 'svn' ) { 44 | $command .= "svn diff"; 45 | } elseif ( $type === 'bzr' ) { 46 | $command .= "bzr diff"; 47 | } else { 48 | throw new RuntimeException( "Unknown repo type '$type' for repository: $name" ); 49 | } 50 | 51 | $process = Process::fromShellCommandline( $command ); 52 | $process->setTimeout( 10 ); 53 | $process->setWorkingDirectory( $base ); 54 | $processes->attach( $process ); 55 | } 56 | 57 | $this->runParallelWithOutput( $processes, $output ); 58 | 59 | return 0; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /repong/src/App/ListCommand.php: -------------------------------------------------------------------------------- 1 | setName( 'list-projects' ); 12 | $this->setDescription( 'Lists all projects defined in repoconfig.yaml' ); 13 | } 14 | 15 | protected function execute( InputInterface $input, OutputInterface $output ): int { 16 | unset( $this->config[ '@meta' ] ); 17 | echo implode( "\n", array_keys( $this->config ) ) . "\n"; 18 | 19 | return 0; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /repong/src/Forge/ForgeClient.php: -------------------------------------------------------------------------------- 1 | cache[$domain] ) ) { 14 | $this->cache[$domain] = $this->constructForgeClient( $type, $domain ); 15 | } 16 | 17 | return $this->cache[$domain]; 18 | } 19 | 20 | private function constructForgeClient( string $type, string $domain ): ForgeClient { 21 | // In the future, there may be other authentication methods 22 | $token = $this->getToken( $domain ); 23 | if ( $type === 'github' ) { 24 | $client = new GithubClient( $token ); 25 | } elseif ( $type === 'gitlab' ) { 26 | $client = new GitlabClient( $token, "https://$domain" ); 27 | } else { 28 | throw new RuntimeException( "No forge client for repository type $type" ); 29 | } 30 | 31 | return $client; 32 | } 33 | 34 | private function getToken( $domain ): string { 35 | $domainForToken = preg_replace( '~[^a-zA-Z0-9_]~', '_', $domain ); 36 | $environmentVariableName = 'L10NBOT_TOKEN_' . $domainForToken; 37 | $token = getenv( $environmentVariableName ); 38 | 39 | if ( $token === false && $environmentVariableName === 'L10NBOT_TOKEN_github_com' ) { 40 | // Backwards compatibility 41 | $token = getenv( 'L10NBOT_GITHUB_TOKEN' ); 42 | } 43 | 44 | if ( $token === false ) { 45 | throw new RuntimeException( 46 | "Environment variable $environmentVariableName is not defined" 47 | ); 48 | } 49 | 50 | return $token; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /repong/src/Forge/GithubPullRequestResponse.php: -------------------------------------------------------------------------------- 1 | pr = $pr; 18 | $this->client = $client; 19 | $this->isNew = $isNew; 20 | } 21 | 22 | public function isNew(): bool { 23 | return $this->isNew; 24 | } 25 | 26 | public function getCreationTime(): DateTime { 27 | return $this->client->getPullRequestCreationTime( $this->pr ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /repong/src/Forge/GitlabClient.php: -------------------------------------------------------------------------------- 1 | client = new Client(); 18 | if ( $url ) { 19 | $this->client->setUrl( $url ); 20 | } 21 | $this->client->authenticate( $token, Client::AUTH_HTTP_TOKEN ); 22 | } 23 | 24 | public function createPullRequest( 25 | PullRequestSpecifier $pr, 26 | string $title, 27 | ?string $body = null 28 | ): PullRequestResponse { 29 | $isNew = true; 30 | $mergeRequestId = null; 31 | 32 | try { 33 | $response = $this->client->mergeRequests()->create( 34 | $pr->getRepositoryOwner() . '/' . $pr->getRepositoryName(), 35 | $pr->getHead(), 36 | $pr->getBase(), 37 | $title, 38 | [ 39 | 'description' => $body, 40 | ] 41 | ); 42 | $mergeRequestId = (int)$response['iid']; 43 | } catch ( RuntimeException $e ) { 44 | if ( 45 | $e->getCode() === 409 && 46 | strpos( $e->getMessage(), 'merge request already exists' ) !== false 47 | ) { 48 | $isNew = false; 49 | if ( preg_match( '~!([0-9]+)$~', $e->getMessage(), $matches ) ) { 50 | $mergeRequestId = (int)$matches[1]; 51 | } 52 | } else { 53 | throw $e; 54 | } 55 | } 56 | 57 | return new GitlabPullRequestResponse( $pr, $this, $isNew, $mergeRequestId ); 58 | } 59 | 60 | public function getPullRequestCreationTime( 61 | PullRequestSpecifier $pr, 62 | int $mergeRequestId 63 | ): DateTime { 64 | $response = $this->client->mergeRequests()->show( 65 | $pr->getRepositoryOwner() . '/' . $pr->getRepositoryName(), 66 | $mergeRequestId 67 | ); 68 | 69 | try { 70 | return new DateTime( $response['created_at'] ); 71 | } catch ( Exception $e ) { 72 | throw new RangeException( 73 | "Unable to create a DateTime from '{$response['created_at']}'" 74 | ); 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /repong/src/Forge/GitlabPullRequestResponse.php: -------------------------------------------------------------------------------- 1 | pr = $pr; 26 | $this->client = $client; 27 | $this->isNew = $isNew; 28 | $this->mergeRequestId = $mergeRequestId; 29 | } 30 | 31 | public function isNew(): bool { 32 | return $this->isNew; 33 | } 34 | 35 | public function getCreationTime(): DateTime { 36 | if ( $this->mergeRequestId === null ) { 37 | throw new RuntimeException( 'Merge request id is missing' ); 38 | } 39 | 40 | return $this->client->getPullRequestCreationTime( $this->pr, $this->mergeRequestId ); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /repong/src/Forge/PullRequestResponse.php: -------------------------------------------------------------------------------- 1 | repositoryOwner = $repositoryOwner; 20 | $this->repositoryName = $repositoryName; 21 | $this->base = $base; 22 | $this->head = $head; 23 | } 24 | 25 | public function getRepositoryOwner(): string { 26 | return $this->repositoryOwner; 27 | } 28 | 29 | public function getRepositoryName(): string { 30 | return $this->repositoryName; 31 | } 32 | 33 | /** Source branch */ 34 | public function getBase(): string { 35 | return $this->base; 36 | } 37 | 38 | /** Target branch */ 39 | public function getHead(): string { 40 | return $this->head; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /translatewiki-composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require": { 3 | "romaricdrigon/metayaml": "dev-master#1481b99679b29cbb50c88f3e10e4951ac64b8ad3" 4 | }, 5 | "extra": { 6 | "merge-plugin": { 7 | "include": [ 8 | "extensions/AbuseFilter/composer.json", 9 | "extensions/CheckUser/composer.json", 10 | "extensions/OATHAuth/composer.json", 11 | "extensions/Elastica/composer.json", 12 | "extensions/Maps/composer.json", 13 | "extensions/SyntaxHighlight_GeSHi/composer.json", 14 | "extensions/TemplateStyles/composer.json", 15 | "extensions/Translate/composer.json", 16 | "extensions/WebAuthn/composer.json" 17 | ] 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /validate-bash.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | validate( $data, $schema, Constraint::CHECK_MODE_TYPE_CAST ); 15 | 16 | if ( $validator->isValid() ) { 17 | echo "repoconfig.yaml validates against the schema.\n"; 18 | exit( 0 ); 19 | } else { 20 | echo "repoconfig.yaml does not validate. Violations:\n"; 21 | foreach ( $validator->getErrors() as $error ) { 22 | printf( "[%s] %s\n", $error['property'], $error['message'] ); 23 | } 24 | exit( 1 ); 25 | } 26 | -------------------------------------------------------------------------------- /validate-yaml.php: -------------------------------------------------------------------------------- 1 | $v ) { 30 | yield $k; 31 | } 32 | } else { 33 | echo "$p is not a file or directory\n"; 34 | exit( 2 ); 35 | } 36 | } 37 | } 38 | 39 | exit( $exit ); 40 | -------------------------------------------------------------------------------- /webfiles/jserror.php: -------------------------------------------------------------------------------- 1 | $ip\t$agent\n>URL: $url\n>STACK: $stack\n" ); 19 | fclose( $file ); 20 | echo "Thank you sir obvious.\n"; 21 | } else { 22 | echo "Bunny is sad.\n"; 23 | } 24 | -------------------------------------------------------------------------------- /webfiles/twn.jserrorlog.js: -------------------------------------------------------------------------------- 1 | window.onerror = function ( errorMsg, fileUrl, lineNumber ) { 2 | $.ajax( { 3 | url: mw.config.get( 'wgScriptPath' ) + '/webfiles/jserror.php', 4 | type: 'POST', 5 | data: { 6 | errorMsg: errorMsg, 7 | fileUrl: fileUrl, 8 | lineNumber: lineNumber, 9 | windowLocation: location.href, 10 | errorStackTrace: new Error().stack // non-standard property, not in all browsers 11 | } 12 | } ).done( function () { 13 | mw.log( 'window.onerror> Logged error successfully', arguments ); 14 | } ).fail( function () { 15 | mw.log( 'window.onerror> Logging error failed', arguments ); 16 | } ); 17 | }; 18 | --------------------------------------------------------------------------------