CINXE.COM

Help:Extension:Translate/Developer guide - MediaWiki

<!DOCTYPE html> <html class="client-nojs vector-feature-language-in-header-disabled vector-feature-language-in-main-page-header-disabled vector-feature-sticky-header-disabled vector-feature-page-tools-pinned-disabled vector-feature-toc-pinned-clientpref-1 vector-feature-main-menu-pinned-disabled vector-feature-limited-width-clientpref-1 vector-feature-limited-width-content-enabled vector-feature-custom-font-size-clientpref-1 vector-feature-appearance-pinned-clientpref-1 vector-feature-night-mode-disabled skin-theme-clientpref-day vector-toc-available" lang="en" dir="ltr"> <head> <meta charset="UTF-8"> <title>Help:Extension:Translate/Developer guide - MediaWiki</title> <script>(function(){var className="client-js vector-feature-language-in-header-disabled vector-feature-language-in-main-page-header-disabled vector-feature-sticky-header-disabled vector-feature-page-tools-pinned-disabled vector-feature-toc-pinned-clientpref-1 vector-feature-main-menu-pinned-disabled vector-feature-limited-width-clientpref-1 vector-feature-limited-width-content-enabled vector-feature-custom-font-size-clientpref-1 vector-feature-appearance-pinned-clientpref-1 vector-feature-night-mode-disabled skin-theme-clientpref-day vector-toc-available";var cookie=document.cookie.match(/(?:^|; )mediawikiwikimwclientpreferences=([^;]+)/);if(cookie){cookie[1].split('%2C').forEach(function(pref){className=className.replace(new RegExp('(^| )'+pref.replace(/-clientpref-\w+$|[^\w-]+/g,'')+'-clientpref-\\w+( |$)'),'$1'+pref+'$2');});}document.documentElement.className=className;}());RLCONF={"wgBreakFrames":false,"wgSeparatorTransformTable":["",""],"wgDigitTransformTable":["",""], "wgDefaultDateFormat":"dmy","wgMonthNames":["","January","February","March","April","May","June","July","August","September","October","November","December"],"wgRequestId":"4d69120d-457f-4371-a3b8-e53055dc2621","wgCanonicalNamespace":"Help","wgCanonicalSpecialPageName":false,"wgNamespaceNumber":12,"wgPageName":"Help:Extension:Translate/Developer_guide","wgTitle":"Extension:Translate/Developer guide","wgCurRevisionId":6685786,"wgRevisionId":6685786,"wgArticleId":1148836,"wgIsArticle":true,"wgIsRedirect":false,"wgAction":"view","wgUserName":null,"wgUserGroups":["*"],"wgCategories":["Extension:Translate"],"wgPageViewLanguage":"en","wgPageContentLanguage":"en","wgPageContentModel":"wikitext","wgRelevantPageName":"Help:Extension:Translate/Developer_guide","wgRelevantArticleId":1148836,"wgIsProbablyEditable":true,"wgRelevantPageIsProbablyEditable":true,"wgRestrictionEdit":[],"wgRestrictionMove":[],"wgNoticeProject":"mediawiki","wgCiteReferencePreviewsActive":true,"wgMediaViewerOnClick":true, "wgMediaViewerEnabledByDefault":true,"wgVisualEditor":{"pageLanguageCode":"en","pageLanguageDir":"ltr","pageVariantFallbacks":"en"},"wgMFDisplayWikibaseDescriptions":{"search":true,"watchlist":true,"tagline":false,"nearby":true},"wgWMESchemaEditAttemptStepOversample":false,"wgWMEPageLength":7000,"wgTranslatePageTranslation":"source","wgCentralAuthMobileDomain":false,"wgEditSubmitButtonLabelPublish":true,"wgDiscussionToolsFeaturesEnabled":{"replytool":true,"newtopictool":true,"sourcemodetoolbar":true,"topicsubscription":false,"autotopicsub":false,"visualenhancements":false,"visualenhancements_reply":false,"visualenhancements_pageframe":false},"wgDiscussionToolsFallbackEditMode":"visual","wgULSPosition":"personal","wgULSisCompactLinksEnabled":true,"wgVector2022LanguageInHeader":false,"wgULSisLanguageSelectorEmpty":false,"wgCheckUserClientHintsHeadersJsApi":["brands","architecture","bitness","fullVersionList","mobile","model","platform","platformVersion"]};RLSTATE={ "ext.globalCssJs.user.styles":"ready","site.styles":"ready","user.styles":"ready","ext.globalCssJs.user":"ready","user":"ready","user.options":"loading","ext.translate.tag.languages":"ready","ext.pygments":"ready","ext.discussionTools.init.styles":"ready","oojs-ui-core.styles":"ready","oojs-ui.styles.indicators":"ready","mediawiki.widgets.styles":"ready","oojs-ui-core.icons":"ready","skins.vector.search.codex.styles":"ready","skins.vector.styles":"ready","skins.vector.icons":"ready","ext.translate.edit.documentation.styles":"ready","ext.translate":"ready","ext.wikimediamessages.styles":"ready","ext.visualEditor.desktopArticleTarget.noscript":"ready","ext.uls.pt":"ready","wikibase.client.init":"ready","ext.wikimediaBadges":"ready"};RLPAGEMODULES=["ext.pygments.view","site","mediawiki.page.ready","mediawiki.toc","skins.vector.js","ext.centralNotice.geoIP","ext.centralNotice.startUp","ext.translate.pagetranslation.uls","ext.urlShortener.toolbar","ext.centralauth.centralautologin", "ext.visualEditor.desktopArticleTarget.init","ext.visualEditor.targetLoader","ext.echo.centralauth","ext.discussionTools.init","ext.eventLogging","ext.wikimediaEvents","ext.navigationTiming","ext.uls.compactlinks","ext.uls.interface","ext.checkUser.clientHints"];</script> <script>(RLQ=window.RLQ||[]).push(function(){mw.loader.impl(function(){return["user.options@12s5i",function($,jQuery,require,module){mw.user.tokens.set({"patrolToken":"+\\","watchToken":"+\\","csrfToken":"+\\"}); }];});});</script> <link rel="stylesheet" href="/w/load.php?lang=en&amp;modules=ext.discussionTools.init.styles%7Cext.pygments%2Ctranslate%2CwikimediaBadges%7Cext.translate.edit.documentation.styles%7Cext.translate.tag.languages%7Cext.uls.pt%7Cext.visualEditor.desktopArticleTarget.noscript%7Cext.wikimediamessages.styles%7Cmediawiki.widgets.styles%7Coojs-ui-core.icons%2Cstyles%7Coojs-ui.styles.indicators%7Cskins.vector.icons%2Cstyles%7Cskins.vector.search.codex.styles%7Cwikibase.client.init&amp;only=styles&amp;skin=vector-2022"> <script async="" src="/w/load.php?lang=en&amp;modules=startup&amp;only=scripts&amp;raw=1&amp;skin=vector-2022"></script> <meta name="ResourceLoaderDynamicStyles" content=""> <link rel="stylesheet" href="/w/load.php?lang=en&amp;modules=site.styles&amp;only=styles&amp;skin=vector-2022"> <meta name="generator" content="MediaWiki 1.44.0-wmf.4"> <meta name="referrer" content="origin"> <meta name="referrer" content="origin-when-cross-origin"> <meta name="robots" content="max-image-preview:standard"> <meta name="format-detection" content="telephone=no"> <meta name="viewport" content="width=1120"> <meta property="og:site_name" content="MediaWiki"> <meta property="og:title" content="Help:Extension:Translate/Developer guide - MediaWiki"> <meta property="og:type" content="website"> <link rel="alternate" media="only screen and (max-width: 640px)" href="//m.mediawiki.org/wiki/Help:Extension:Translate/Developer_guide"> <link rel="alternate" type="application/x-wiki" title="Edit" href="/w/index.php?title=Help:Extension:Translate/Developer_guide&amp;action=edit"> <link rel="apple-touch-icon" href="/static/apple-touch/mediawiki.png"> <link rel="icon" href="/static/favicon/mediawiki.ico"> <link rel="search" type="application/opensearchdescription+xml" href="/w/rest.php/v1/search" title="MediaWiki (en)"> <link rel="EditURI" type="application/rsd+xml" href="//www.mediawiki.org/w/api.php?action=rsd"> <link rel="canonical" href="https://www.mediawiki.org/wiki/Help:Extension:Translate/Developer_guide"> <link rel="license" href="https://creativecommons.org/licenses/by-sa/4.0/"> <link rel="alternate" type="application/atom+xml" title="MediaWiki Atom feed" href="/w/index.php?title=Special:RecentChanges&amp;feed=atom"> <link rel="dns-prefetch" href="//meta.wikimedia.org" /> <link rel="dns-prefetch" href="//login.wikimedia.org"> </head> <body class="ext-discussiontools-replytool-enabled ext-discussiontools-newtopictool-enabled ext-discussiontools-sourcemodetoolbar-enabled skin--responsive skin-vector skin-vector-search-vue mediawiki ltr sitedir-ltr mw-hide-empty-elt ns-12 ns-subject mw-editable page-Help_Extension_Translate_Developer_guide rootpage-Help_Extension_Translate skin-vector-2022 action-view"><a class="mw-jump-link" href="#bodyContent">Jump to content</a> <div class="vector-header-container"> <header class="vector-header mw-header"> <div class="vector-header-start"> <nav class="vector-main-menu-landmark" aria-label="Site"> <div id="vector-main-menu-dropdown" class="vector-dropdown vector-main-menu-dropdown vector-button-flush-left vector-button-flush-right" > <input type="checkbox" id="vector-main-menu-dropdown-checkbox" role="button" aria-haspopup="true" data-event-name="ui.dropdown-vector-main-menu-dropdown" class="vector-dropdown-checkbox " aria-label="Main menu" > <label id="vector-main-menu-dropdown-label" for="vector-main-menu-dropdown-checkbox" class="vector-dropdown-label cdx-button cdx-button--fake-button cdx-button--fake-button--enabled cdx-button--weight-quiet cdx-button--icon-only " aria-hidden="true" ><span class="vector-icon mw-ui-icon-menu mw-ui-icon-wikimedia-menu"></span> <span class="vector-dropdown-label-text">Main menu</span> </label> <div class="vector-dropdown-content"> <div id="vector-main-menu-unpinned-container" class="vector-unpinned-container"> <div id="vector-main-menu" class="vector-main-menu vector-pinnable-element"> <div class="vector-pinnable-header vector-main-menu-pinnable-header vector-pinnable-header-unpinned" data-feature-name="main-menu-pinned" data-pinnable-element-id="vector-main-menu" data-pinned-container-id="vector-main-menu-pinned-container" data-unpinned-container-id="vector-main-menu-unpinned-container" > <div class="vector-pinnable-header-label">Main menu</div> <button class="vector-pinnable-header-toggle-button vector-pinnable-header-pin-button" data-event-name="pinnable-header.vector-main-menu.pin">move to sidebar</button> <button class="vector-pinnable-header-toggle-button vector-pinnable-header-unpin-button" data-event-name="pinnable-header.vector-main-menu.unpin">hide</button> </div> <div id="p-navigation" class="vector-menu mw-portlet mw-portlet-navigation" > <div class="vector-menu-heading"> Navigation </div> <div class="vector-menu-content"> <ul class="vector-menu-content-list"> <li id="n-mainpage-description" class="mw-list-item"><a href="/wiki/MediaWiki" title="Visit the main page [z]" accesskey="z"><span>Main page</span></a></li><li id="n-mw-download" class="mw-list-item"><a href="/wiki/Download"><span>Get MediaWiki</span></a></li><li id="n-mw-extensions" class="mw-list-item"><a href="/wiki/Special:MyLanguage/Category:Extensions"><span>Get extensions</span></a></li><li id="n-blog-text" class="mw-list-item"><a href="https://techblog.wikimedia.org/"><span>Tech blog</span></a></li><li id="n-mw-contribute" class="mw-list-item"><a href="/wiki/Special:MyLanguage/How_to_contribute"><span>Contribute</span></a></li> </ul> </div> </div> <div id="p-support" class="vector-menu mw-portlet mw-portlet-support" > <div class="vector-menu-heading"> Support </div> <div class="vector-menu-content"> <ul class="vector-menu-content-list"> <li id="n-help" class="mw-list-item"><a href="/wiki/Special:MyLanguage/Help:Contents" title="The place to find out"><span>User help</span></a></li><li id="n-mw-faq" class="mw-list-item"><a href="/wiki/Special:MyLanguage/Manual:FAQ"><span>FAQ</span></a></li><li id="n-mw-manual" class="mw-list-item"><a href="/wiki/Special:MyLanguage/Manual:Contents"><span>Technical manual</span></a></li><li id="n-mw-supportdesk" class="mw-list-item"><a href="/wiki/Project:Support_desk"><span>Support desk</span></a></li><li id="n-mw-communication" class="mw-list-item"><a href="/wiki/Special:MyLanguage/Communication"><span>Communication</span></a></li> </ul> </div> </div> <div id="p-development" class="vector-menu mw-portlet mw-portlet-development" > <div class="vector-menu-heading"> Development </div> <div class="vector-menu-content"> <ul class="vector-menu-content-list"> <li id="n-mw-developerportal" class="mw-list-item"><a href="https://developer.wikimedia.org/"><span>Developer portal</span></a></li><li id="n-svn-statistics" class="mw-list-item"><a href="/wiki/Development_statistics"><span>Code statistics</span></a></li> </ul> </div> </div> <div id="p-mediawiki.org" class="vector-menu mw-portlet mw-portlet-mediawiki_org" > <div class="vector-menu-heading"> mediawiki.org </div> <div class="vector-menu-content"> <ul class="vector-menu-content-list"> <li id="n-portal" class="mw-list-item"><a href="/wiki/Project:Help" title="About the project, what you can do, where to find things"><span>Community portal</span></a></li><li id="n-recentchanges" class="mw-list-item"><a href="/wiki/Special:RecentChanges" title="A list of recent changes in the wiki [r]" accesskey="r"><span>Recent changes</span></a></li><li id="n-mw-translate" class="mw-list-item"><a href="/wiki/Special:LanguageStats"><span>Translate content</span></a></li><li id="n-randompage" class="mw-list-item"><a href="/wiki/Special:Random" title="Load a random page [x]" accesskey="x"><span>Random page</span></a></li><li id="n-mw-discussion" class="mw-list-item"><a href="/wiki/Project:Village_Pump"><span>Village pump</span></a></li><li id="n-Sandboxlink-portlet-label" class="mw-list-item"><a href="/wiki/Project:Sandbox"><span>Sandbox</span></a></li> </ul> </div> </div> <div id="p-lang" class="vector-menu mw-portlet mw-portlet-lang" > <div class="vector-menu-heading"> In other languages </div> <div class="vector-menu-content"> <ul class="vector-menu-content-list"> </ul> <div class="after-portlet after-portlet-lang"><span class="wb-langlinks-add wb-langlinks-link"><a href="https://www.wikidata.org/wiki/Special:NewItem?site=mediawikiwiki&amp;page=Help%3AExtension%3ATranslate%2FDeveloper+guide" title="Add interlanguage links" class="wbc-editpage">Add links</a></span></div> </div> </div> </div> </div> </div> </div> </nav> <a href="/wiki/MediaWiki" class="mw-logo"> <img class="mw-logo-icon" src="/static/images/icons/mediawikiwiki.svg" alt="" aria-hidden="true" height="50" width="50"> <span class="mw-logo-container skin-invert"> <img class="mw-logo-wordmark" alt="MediaWiki" src="/static/images/mobile/copyright/mediawikiwiki-wordmark.svg" style="width: 7.5em; height: 1.125em;"> </span> </a> </div> <div class="vector-header-end"> <div id="p-search" role="search" class="vector-search-box-vue vector-search-box-collapses vector-search-box-show-thumbnail vector-search-box-auto-expand-width vector-search-box"> <a href="/wiki/Special:Search" class="cdx-button cdx-button--fake-button cdx-button--fake-button--enabled cdx-button--weight-quiet cdx-button--icon-only search-toggle" title="Search MediaWiki [f]" accesskey="f"><span class="vector-icon mw-ui-icon-search mw-ui-icon-wikimedia-search"></span> <span>Search</span> </a> <div class="vector-typeahead-search-container"> <div class="cdx-typeahead-search cdx-typeahead-search--show-thumbnail cdx-typeahead-search--auto-expand-width"> <form action="/w/index.php" id="searchform" class="cdx-search-input cdx-search-input--has-end-button"> <div id="simpleSearch" class="cdx-search-input__input-wrapper" data-search-loc="header-moved"> <div class="cdx-text-input cdx-text-input--has-start-icon"> <input class="cdx-text-input__input" type="search" name="search" placeholder="Search MediaWiki" aria-label="Search MediaWiki" autocapitalize="sentences" title="Search MediaWiki [f]" accesskey="f" id="searchInput" > <span class="cdx-text-input__icon cdx-text-input__start-icon"></span> </div> <input type="hidden" name="title" value="Special:Search"> </div> <button class="cdx-button cdx-search-input__end-button">Search</button> </form> </div> </div> </div> <nav class="vector-user-links vector-user-links-wide" aria-label="Personal tools"> <div class="vector-user-links-main"> <div id="p-vector-user-menu-preferences" class="vector-menu mw-portlet" > <div class="vector-menu-content"> <ul class="vector-menu-content-list"> <li id="ca-uls" class="mw-list-item active user-links-collapsible-item"><a data-mw="interface" href="#" class="uls-trigger cdx-button cdx-button--fake-button cdx-button--fake-button--enabled cdx-button--weight-quiet"><span class="vector-icon mw-ui-icon-wikimedia-language mw-ui-icon-wikimedia-wikimedia-language"></span> <span>English</span></a> </li> </ul> </div> </div> <div id="p-vector-user-menu-userpage" class="vector-menu mw-portlet emptyPortlet" > <div class="vector-menu-content"> <ul class="vector-menu-content-list"> </ul> </div> </div> <nav class="vector-appearance-landmark" aria-label="Appearance"> <div id="vector-appearance-dropdown" class="vector-dropdown " title="Change the appearance of the page&#039;s font size, width, and color" > <input type="checkbox" id="vector-appearance-dropdown-checkbox" role="button" aria-haspopup="true" data-event-name="ui.dropdown-vector-appearance-dropdown" class="vector-dropdown-checkbox " aria-label="Appearance" > <label id="vector-appearance-dropdown-label" for="vector-appearance-dropdown-checkbox" class="vector-dropdown-label cdx-button cdx-button--fake-button cdx-button--fake-button--enabled cdx-button--weight-quiet cdx-button--icon-only " aria-hidden="true" ><span class="vector-icon mw-ui-icon-appearance mw-ui-icon-wikimedia-appearance"></span> <span class="vector-dropdown-label-text">Appearance</span> </label> <div class="vector-dropdown-content"> <div id="vector-appearance-unpinned-container" class="vector-unpinned-container"> </div> </div> </div> </nav> <div id="p-vector-user-menu-notifications" class="vector-menu mw-portlet emptyPortlet" > <div class="vector-menu-content"> <ul class="vector-menu-content-list"> </ul> </div> </div> <div id="p-vector-user-menu-overflow" class="vector-menu mw-portlet" > <div class="vector-menu-content"> <ul class="vector-menu-content-list"> <li id="pt-sitesupport-2" class="user-links-collapsible-item mw-list-item user-links-collapsible-item"><a data-mw="interface" href="https://donate.wikimedia.org/?utm_source=donate&amp;utm_medium=sidebar&amp;utm_campaign=spontaneous&amp;uselang=en" class=""><span>Donate</span></a> </li> <li id="pt-createaccount-2" class="user-links-collapsible-item mw-list-item user-links-collapsible-item"><a data-mw="interface" href="/w/index.php?title=Special:CreateAccount&amp;returnto=Help%3AExtension%3ATranslate%2FDeveloper+guide" title="You are encouraged to create an account and log in; however, it is not mandatory" class=""><span>Create account</span></a> </li> <li id="pt-login-2" class="user-links-collapsible-item mw-list-item user-links-collapsible-item"><a data-mw="interface" href="/w/index.php?title=Special:UserLogin&amp;returnto=Help%3AExtension%3ATranslate%2FDeveloper+guide" title="You are encouraged to log in; however, it is not mandatory [o]" accesskey="o" class=""><span>Log in</span></a> </li> </ul> </div> </div> </div> <div id="vector-user-links-dropdown" class="vector-dropdown vector-user-menu vector-button-flush-right vector-user-menu-logged-out" title="More options" > <input type="checkbox" id="vector-user-links-dropdown-checkbox" role="button" aria-haspopup="true" data-event-name="ui.dropdown-vector-user-links-dropdown" class="vector-dropdown-checkbox " aria-label="Personal tools" > <label id="vector-user-links-dropdown-label" for="vector-user-links-dropdown-checkbox" class="vector-dropdown-label cdx-button cdx-button--fake-button cdx-button--fake-button--enabled cdx-button--weight-quiet cdx-button--icon-only " aria-hidden="true" ><span class="vector-icon mw-ui-icon-ellipsis mw-ui-icon-wikimedia-ellipsis"></span> <span class="vector-dropdown-label-text">Personal tools</span> </label> <div class="vector-dropdown-content"> <div id="p-personal" class="vector-menu mw-portlet mw-portlet-personal user-links-collapsible-item" title="User menu" > <div class="vector-menu-content"> <ul class="vector-menu-content-list"> <li id="pt-sitesupport" class="user-links-collapsible-item mw-list-item"><a href="https://donate.wikimedia.org/?utm_source=donate&amp;utm_medium=sidebar&amp;utm_campaign=spontaneous&amp;uselang=en"><span>Donate</span></a></li><li id="pt-createaccount" class="user-links-collapsible-item mw-list-item"><a href="/w/index.php?title=Special:CreateAccount&amp;returnto=Help%3AExtension%3ATranslate%2FDeveloper+guide" title="You are encouraged to create an account and log in; however, it is not mandatory"><span class="vector-icon mw-ui-icon-userAdd mw-ui-icon-wikimedia-userAdd"></span> <span>Create account</span></a></li><li id="pt-login" class="user-links-collapsible-item mw-list-item"><a href="/w/index.php?title=Special:UserLogin&amp;returnto=Help%3AExtension%3ATranslate%2FDeveloper+guide" title="You are encouraged to log in; however, it is not mandatory [o]" accesskey="o"><span class="vector-icon mw-ui-icon-logIn mw-ui-icon-wikimedia-logIn"></span> <span>Log in</span></a></li> </ul> </div> </div> <div id="p-user-menu-anon-editor" class="vector-menu mw-portlet mw-portlet-user-menu-anon-editor" > <div class="vector-menu-heading"> Pages for logged out editors <a href="/wiki/Help:Introduction" aria-label="Learn more about editing"><span>learn more</span></a> </div> <div class="vector-menu-content"> <ul class="vector-menu-content-list"> <li id="pt-anoncontribs" class="mw-list-item"><a href="/wiki/Special:MyContributions" title="A list of edits made from this IP address [y]" accesskey="y"><span>Contributions</span></a></li><li id="pt-anontalk" class="mw-list-item"><a href="/wiki/Special:MyTalk" title="Discussion about edits from this IP address [n]" accesskey="n"><span>Talk</span></a></li> </ul> </div> </div> </div> </div> </nav> </div> </header> </div> <div class="mw-page-container"> <div class="mw-page-container-inner"> <div class="vector-sitenotice-container"> <div id="siteNotice"><!-- CentralNotice --></div> </div> <div class="vector-column-start"> <div class="vector-main-menu-container"> <div id="mw-navigation"> <nav id="mw-panel" class="vector-main-menu-landmark" aria-label="Site"> <div id="vector-main-menu-pinned-container" class="vector-pinned-container"> </div> </nav> </div> </div> <div class="vector-sticky-pinned-container"> <nav id="mw-panel-toc" aria-label="Contents" data-event-name="ui.sidebar-toc" class="mw-table-of-contents-container vector-toc-landmark"> <div id="vector-toc-pinned-container" class="vector-pinned-container"> <div id="vector-toc" class="vector-toc vector-pinnable-element"> <div class="vector-pinnable-header vector-toc-pinnable-header vector-pinnable-header-pinned" data-feature-name="toc-pinned" data-pinnable-element-id="vector-toc" > <h2 class="vector-pinnable-header-label">Contents</h2> <button class="vector-pinnable-header-toggle-button vector-pinnable-header-pin-button" data-event-name="pinnable-header.vector-toc.pin">move to sidebar</button> <button class="vector-pinnable-header-toggle-button vector-pinnable-header-unpin-button" data-event-name="pinnable-header.vector-toc.unpin">hide</button> </div> <ul class="vector-toc-contents" id="mw-panel-toc-list"> <li id="toc-mw-content-text" class="vector-toc-list-item vector-toc-level-1"> <a href="#" class="vector-toc-link"> <div class="vector-toc-text">Beginning</div> </a> </li> <li id="toc-Namespace_migration" class="vector-toc-list-item vector-toc-level-1 vector-toc-list-item-expanded"> <a class="vector-toc-link" href="#Namespace_migration"> <div class="vector-toc-text"> <span class="vector-toc-numb">1</span> <span>Namespace migration</span> </div> </a> <ul id="toc-Namespace_migration-sublist" class="vector-toc-list"> </ul> </li> <li id="toc-Splitting_tests_into_integration_and_unit_tests" class="vector-toc-list-item vector-toc-level-1 vector-toc-list-item-expanded"> <a class="vector-toc-link" href="#Splitting_tests_into_integration_and_unit_tests"> <div class="vector-toc-text"> <span class="vector-toc-numb">2</span> <span>Splitting tests into integration and unit tests</span> </div> </a> <ul id="toc-Splitting_tests_into_integration_and_unit_tests-sublist" class="vector-toc-list"> </ul> </li> <li id="toc-Type_declarations_and_comments" class="vector-toc-list-item vector-toc-level-1 vector-toc-list-item-expanded"> <a class="vector-toc-link" href="#Type_declarations_and_comments"> <div class="vector-toc-text"> <span class="vector-toc-numb">3</span> <span>Type declarations and comments</span> </div> </a> <ul id="toc-Type_declarations_and_comments-sublist" class="vector-toc-list"> </ul> </li> <li id="toc-Constructor_dependency_injection" class="vector-toc-list-item vector-toc-level-1 vector-toc-list-item-expanded"> <a class="vector-toc-link" href="#Constructor_dependency_injection"> <div class="vector-toc-text"> <span class="vector-toc-numb">4</span> <span>Constructor dependency injection</span> </div> </a> <ul id="toc-Constructor_dependency_injection-sublist" class="vector-toc-list"> </ul> </li> <li id="toc-File_header" class="vector-toc-list-item vector-toc-level-1 vector-toc-list-item-expanded"> <a class="vector-toc-link" href="#File_header"> <div class="vector-toc-text"> <span class="vector-toc-numb">5</span> <span>File header</span> </div> </a> <ul id="toc-File_header-sublist" class="vector-toc-list"> </ul> </li> <li id="toc-Deprecation_and_version_numbers" class="vector-toc-list-item vector-toc-level-1 vector-toc-list-item-expanded"> <a class="vector-toc-link" href="#Deprecation_and_version_numbers"> <div class="vector-toc-text"> <span class="vector-toc-numb">6</span> <span>Deprecation and version numbers</span> </div> </a> <ul id="toc-Deprecation_and_version_numbers-sublist" class="vector-toc-list"> </ul> </li> </ul> </div> </div> </nav> </div> </div> <div class="mw-content-container"> <main id="content" class="mw-body"> <header class="mw-body-header vector-page-titlebar"> <nav aria-label="Contents" class="vector-toc-landmark"> <div id="vector-page-titlebar-toc" class="vector-dropdown vector-page-titlebar-toc vector-button-flush-left" > <input type="checkbox" id="vector-page-titlebar-toc-checkbox" role="button" aria-haspopup="true" data-event-name="ui.dropdown-vector-page-titlebar-toc" class="vector-dropdown-checkbox " aria-label="Toggle the table of contents" > <label id="vector-page-titlebar-toc-label" for="vector-page-titlebar-toc-checkbox" class="vector-dropdown-label cdx-button cdx-button--fake-button cdx-button--fake-button--enabled cdx-button--weight-quiet cdx-button--icon-only " aria-hidden="true" ><span class="vector-icon mw-ui-icon-listBullet mw-ui-icon-wikimedia-listBullet"></span> <span class="vector-dropdown-label-text">Toggle the table of contents</span> </label> <div class="vector-dropdown-content"> <div id="vector-page-titlebar-toc-unpinned-container" class="vector-unpinned-container"> </div> </div> </div> </nav> <h1 id="firstHeading" class="firstHeading mw-first-heading"><span class="mw-page-title-namespace">Help</span><span class="mw-page-title-separator">:</span><span class="mw-page-title-main">Extension:Translate/Developer guide</span></h1> <div class="mw-indicators"> </div> </header> <div class="vector-page-toolbar"> <div class="vector-page-toolbar-container"> <div id="left-navigation"> <nav aria-label="Namespaces"> <div id="p-associated-pages" class="vector-menu vector-menu-tabs mw-portlet mw-portlet-associated-pages" > <div class="vector-menu-content"> <ul class="vector-menu-content-list"> <li id="ca-nstab-help" class="selected vector-tab-noicon mw-list-item"><a href="/wiki/Help:Extension:Translate/Developer_guide" title="View the help page [c]" accesskey="c"><span>Help</span></a></li><li id="ca-talk" class="vector-tab-noicon mw-list-item"><a href="/wiki/Help_talk:Extension:Translate/Developer_guide" rel="discussion" title="Discussion about the content page [t]" accesskey="t"><span>Discussion</span></a></li> </ul> </div> </div> <div id="vector-variants-dropdown" class="vector-dropdown emptyPortlet" > <input type="checkbox" id="vector-variants-dropdown-checkbox" role="button" aria-haspopup="true" data-event-name="ui.dropdown-vector-variants-dropdown" class="vector-dropdown-checkbox " aria-label="Change language variant" > <label id="vector-variants-dropdown-label" for="vector-variants-dropdown-checkbox" class="vector-dropdown-label cdx-button cdx-button--fake-button cdx-button--fake-button--enabled cdx-button--weight-quiet" aria-hidden="true" ><span class="vector-dropdown-label-text">English</span> </label> <div class="vector-dropdown-content"> <div id="p-variants" class="vector-menu mw-portlet mw-portlet-variants emptyPortlet" > <div class="vector-menu-content"> <ul class="vector-menu-content-list"> </ul> </div> </div> </div> </div> </nav> </div> <div id="right-navigation" class="vector-collapsible"> <nav aria-label="Views"> <div id="p-views" class="vector-menu vector-menu-tabs mw-portlet mw-portlet-views" > <div class="vector-menu-content"> <ul class="vector-menu-content-list"> <li id="ca-view" class="selected vector-tab-noicon mw-list-item"><a href="/wiki/Help:Extension:Translate/Developer_guide"><span>Read</span></a></li><li id="ca-edit" class="vector-tab-noicon mw-list-item"><a href="/w/index.php?title=Help:Extension:Translate/Developer_guide&amp;action=edit" title="Edit the source code of this page [e]" accesskey="e"><span>Edit</span></a></li><li id="ca-history" class="vector-tab-noicon mw-list-item"><a href="/w/index.php?title=Help:Extension:Translate/Developer_guide&amp;action=history" title="Past revisions of this page [h]" accesskey="h"><span>View history</span></a></li> </ul> </div> </div> </nav> <nav class="vector-page-tools-landmark" aria-label="Page tools"> <div id="vector-page-tools-dropdown" class="vector-dropdown vector-page-tools-dropdown" > <input type="checkbox" id="vector-page-tools-dropdown-checkbox" role="button" aria-haspopup="true" data-event-name="ui.dropdown-vector-page-tools-dropdown" class="vector-dropdown-checkbox " aria-label="Tools" > <label id="vector-page-tools-dropdown-label" for="vector-page-tools-dropdown-checkbox" class="vector-dropdown-label cdx-button cdx-button--fake-button cdx-button--fake-button--enabled cdx-button--weight-quiet" aria-hidden="true" ><span class="vector-dropdown-label-text">Tools</span> </label> <div class="vector-dropdown-content"> <div id="vector-page-tools-unpinned-container" class="vector-unpinned-container"> <div id="vector-page-tools" class="vector-page-tools vector-pinnable-element"> <div class="vector-pinnable-header vector-page-tools-pinnable-header vector-pinnable-header-unpinned" data-feature-name="page-tools-pinned" data-pinnable-element-id="vector-page-tools" data-pinned-container-id="vector-page-tools-pinned-container" data-unpinned-container-id="vector-page-tools-unpinned-container" > <div class="vector-pinnable-header-label">Tools</div> <button class="vector-pinnable-header-toggle-button vector-pinnable-header-pin-button" data-event-name="pinnable-header.vector-page-tools.pin">move to sidebar</button> <button class="vector-pinnable-header-toggle-button vector-pinnable-header-unpin-button" data-event-name="pinnable-header.vector-page-tools.unpin">hide</button> </div> <div id="p-cactions" class="vector-menu mw-portlet mw-portlet-cactions emptyPortlet vector-has-collapsible-items" title="More options" > <div class="vector-menu-heading"> Actions </div> <div class="vector-menu-content"> <ul class="vector-menu-content-list"> <li id="ca-more-view" class="selected vector-more-collapsible-item mw-list-item"><a href="/wiki/Help:Extension:Translate/Developer_guide"><span>Read</span></a></li><li id="ca-more-edit" class="vector-more-collapsible-item mw-list-item"><a href="/w/index.php?title=Help:Extension:Translate/Developer_guide&amp;action=edit" title="Edit the source code of this page [e]" accesskey="e"><span>Edit</span></a></li><li id="ca-more-history" class="vector-more-collapsible-item mw-list-item"><a href="/w/index.php?title=Help:Extension:Translate/Developer_guide&amp;action=history"><span>View history</span></a></li> </ul> </div> </div> <div id="p-tb" class="vector-menu mw-portlet mw-portlet-tb" > <div class="vector-menu-heading"> General </div> <div class="vector-menu-content"> <ul class="vector-menu-content-list"> <li id="t-whatlinkshere" class="mw-list-item"><a href="/wiki/Special:WhatLinksHere/Help:Extension:Translate/Developer_guide" title="A list of all wiki pages that link here [j]" accesskey="j"><span>What links here</span></a></li><li id="t-recentchangeslinked" class="mw-list-item"><a href="/wiki/Special:RecentChangesLinked/Help:Extension:Translate/Developer_guide" rel="nofollow" title="Recent changes in pages linked from this page [k]" accesskey="k"><span>Related changes</span></a></li><li id="t-upload" class="mw-list-item"><a href="//commons.wikimedia.org/wiki/Special:UploadWizard" title="Upload files [u]" accesskey="u"><span>Upload file</span></a></li><li id="t-specialpages" class="mw-list-item"><a href="/wiki/Special:SpecialPages" title="A list of all special pages [q]" accesskey="q"><span>Special pages</span></a></li><li id="t-permalink" class="mw-list-item"><a href="/w/index.php?title=Help:Extension:Translate/Developer_guide&amp;oldid=6685786" title="Permanent link to this revision of this page"><span>Permanent link</span></a></li><li id="t-info" class="mw-list-item"><a href="/w/index.php?title=Help:Extension:Translate/Developer_guide&amp;action=info" title="More information about this page"><span>Page information</span></a></li><li id="t-urlshortener" class="mw-list-item"><a href="/w/index.php?title=Special:UrlShortener&amp;url=https%3A%2F%2Fwww.mediawiki.org%2Fwiki%2FHelp%3AExtension%3ATranslate%2FDeveloper_guide"><span>Get shortened URL</span></a></li><li id="t-urlshortener-qrcode" class="mw-list-item"><a href="/w/index.php?title=Special:QrCode&amp;url=https%3A%2F%2Fwww.mediawiki.org%2Fwiki%2FHelp%3AExtension%3ATranslate%2FDeveloper_guide"><span>Download QR code</span></a></li> </ul> </div> </div> <div id="p-coll-print_export" class="vector-menu mw-portlet mw-portlet-coll-print_export" > <div class="vector-menu-heading"> Print/export </div> <div class="vector-menu-content"> <ul class="vector-menu-content-list"> <li id="coll-create_a_book" class="mw-list-item"><a href="/w/index.php?title=Special:Book&amp;bookcmd=book_creator&amp;referer=Help%3AExtension%3ATranslate%2FDeveloper+guide"><span>Create a book</span></a></li><li id="coll-download-as-rl" class="mw-list-item"><a href="/w/index.php?title=Special:DownloadAsPdf&amp;page=Help%3AExtension%3ATranslate%2FDeveloper_guide&amp;action=show-download-screen"><span>Download as PDF</span></a></li><li id="t-print" class="mw-list-item"><a href="/w/index.php?title=Help:Extension:Translate/Developer_guide&amp;printable=yes" title="Printable version of this page [p]" accesskey="p"><span>Printable version</span></a></li> </ul> </div> </div> <div id="p-wikibase-otherprojects" class="vector-menu mw-portlet mw-portlet-wikibase-otherprojects emptyPortlet" > <div class="vector-menu-heading"> In other projects </div> <div class="vector-menu-content"> <ul class="vector-menu-content-list"> </ul> </div> </div> </div> </div> </div> </div> </nav> </div> </div> </div> <div class="vector-column-end"> <div class="vector-sticky-pinned-container"> <nav class="vector-page-tools-landmark" aria-label="Page tools"> <div id="vector-page-tools-pinned-container" class="vector-pinned-container"> </div> </nav> <nav class="vector-appearance-landmark" aria-label="Appearance"> <div id="vector-appearance-pinned-container" class="vector-pinned-container"> <div id="vector-appearance" class="vector-appearance vector-pinnable-element"> <div class="vector-pinnable-header vector-appearance-pinnable-header vector-pinnable-header-pinned" data-feature-name="appearance-pinned" data-pinnable-element-id="vector-appearance" data-pinned-container-id="vector-appearance-pinned-container" data-unpinned-container-id="vector-appearance-unpinned-container" > <div class="vector-pinnable-header-label">Appearance</div> <button class="vector-pinnable-header-toggle-button vector-pinnable-header-pin-button" data-event-name="pinnable-header.vector-appearance.pin">move to sidebar</button> <button class="vector-pinnable-header-toggle-button vector-pinnable-header-unpin-button" data-event-name="pinnable-header.vector-appearance.unpin">hide</button> </div> </div> </div> </nav> </div> </div> <div id="bodyContent" class="vector-body" aria-labelledby="firstHeading" data-mw-ve-target-container> <div class="vector-body-before-content"> <div id="siteSub" class="noprint">From mediawiki.org</div> </div> <div id="contentSub"><div id="mw-content-subtitle"><div class="subpages">&lt; <bdi dir="ltr"><a href="/wiki/Special:MyLanguage/Help:Extension:Translate" title="Special:MyLanguage/Help:Extension:Translate">Help:Extension:Translate</a></bdi></div></div></div> <div id="mw-content-text" class="mw-body-content"><div class="mw-pt-translate-header noprint nomobile" dir="ltr" lang="en"><a href="/w/index.php?title=Special:Translate&amp;group=page-Help%3AExtension%3ATranslate%2FDeveloper+guide&amp;action=page&amp;filter=&amp;action_source=translate_page" title="Special:Translate">Translate this page</a></div><div class="mw-content-ltr mw-parser-output" lang="en" dir="ltr"><div class="mw-pt-languages noprint navigation-not-searchable" lang="en" dir="ltr"><div class="mw-pt-languages-label">Languages:</div><ul class="mw-pt-languages-list"><li><a href="/wiki/Help:Extension:Translate/Developer_guide/de" class="mw-pt-progress mw-pt-progress--low" title="Hilfe:Erweiterung:Übersetzen/Entwicklerleitfaden (4% translated)" lang="de" dir="ltr">Deutsch</a></li> <li><span class="mw-pt-languages-ui mw-pt-languages-selected mw-pt-progress mw-pt-progress--complete" lang="en" dir="ltr">English</span></li> <li><a href="/wiki/Help:Extension:Translate/Developer_guide/nl" class="mw-pt-progress mw-pt-progress--complete" title="Help:Extension:Translate/Developer gids (100% translated)" lang="nl" dir="ltr">Nederlands</a></li> <li><a href="/wiki/Help:Extension:Translate/Developer_guide/fr" class="mw-pt-progress mw-pt-progress--low" title="Help:Extension:Translate/Developer guide/fr (12% translated)" lang="fr" dir="ltr">français</a></li> <li><a href="/wiki/Help:Extension:Translate/Developer_guide/pt" class="mw-pt-progress mw-pt-progress--med" title="Ajuda:Extensão:Translate/Guia do programador (18% translated)" lang="pt" dir="ltr">português</a></li> <li><a href="/wiki/Help:Extension:Translate/Developer_guide/pt-br" class="mw-pt-progress mw-pt-progress--med" title="Ajuda:Extensão:Translate/Guia do programador (18% translated)" lang="pt-BR" dir="ltr">português do Brasil</a></li> <li><a href="/wiki/Help:Extension:Translate/Developer_guide/fi" class="mw-pt-progress mw-pt-progress--low" title="Help:Extension:Translate/Developer guide/fi (2% translated)" lang="fi" dir="ltr">suomi</a></li> <li><a href="/wiki/Help:Extension:Translate/Developer_guide/cs" class="mw-pt-progress mw-pt-progress--high" title="Nápověda:Rozšíření:Translate/Průvodce pro vývojáře (98% translated)" lang="cs" dir="ltr">čeština</a></li> <li><a href="/wiki/Help:Extension:Translate/Developer_guide/fa" class="mw-pt-progress mw-pt-progress--low" title="Help:Extension:Translate/آموزش توسعه‌دهنده (2% translated)" lang="fa" dir="rtl">فارسی</a></li> <li><a href="/wiki/Help:Extension:Translate/Developer_guide/ja" class="mw-pt-progress mw-pt-progress--complete" title="Help:Extension:Translate/開発者向けガイド (100% translated)" lang="ja" dir="ltr">日本語</a></li> <li><a href="/wiki/Help:Extension:Translate/Developer_guide/nan" class="mw-pt-progress mw-pt-progress--low" title="Pang-tsōo:Khok-tián:Huan-i̍k/Khai-huat-tsiá tsí-lâm (14% translated)" lang="nan" dir="ltr">閩南語 / Bân-lâm-gú</a></li></ul></div> <style data-mw-deduplicate="TemplateStyles:r6806430">.mw-parser-output .extension-translate-navcolumn{margin-bottom:.5em;border:1px solid var(--border-color-base,#a2a9b1);padding:5px;background-color:var(--background-color-base,#fff)}@media(min-width:720px){.mw-parser-output .extension-translate-navcolumn{margin-left:.5em;width:21em}.mw-parser-output .extension-translate-navcolumn-align-primary{float:left;clear:left}.mw-parser-output .extension-translate-navcolumn-align-secondary{float:right;clear:right}}.mw-parser-output .extension-translate-navcolumn-title{font-size:larger;font-weight:bold;padding-bottom:.5em;border-bottom:solid 1.5em var(--border-color-success,#2cb491);margin-bottom:1em}</style> <div class="extension-translate-navcolumn plainlinks extension-translate-navcolumn-align-secondary"> <div class="extension-translate-navcolumn-title">Documentation for <a href="/wiki/Special:MyLanguage/Extension:Translate" title="Special:MyLanguage/Extension:Translate">Extension:Translate</a><span style="display:none"><a href="/wiki/Extension:Translate" title="Extension:Translate"> </a></span></div> <p><b>Translators</b> (<a href="/wiki/Special:MyLanguage/Help:Extension:Translate" title="Special:MyLanguage/Help:Extension:Translate">main help page</a><span style="display:none"><a href="/wiki/Help:Extension:Translate" title="Help:Extension:Translate"> </a></span>) </p> <ul><li><a href="/wiki/Special:MyLanguage/Help:Extension:Translate/Translation_example" title="Special:MyLanguage/Help:Extension:Translate/Translation example">How to translate</a><span style="display:none"><a href="/wiki/Help:Extension:Translate/Translation_example" title="Help:Extension:Translate/Translation example"> </a></span></li> <li><a href="/wiki/Special:MyLanguage/Help:Extension:Translate/Translation_best_practices" title="Special:MyLanguage/Help:Extension:Translate/Translation best practices">Best practices</a><span style="display:none"><a href="/wiki/Help:Extension:Translate/Translation_best_practices" title="Help:Extension:Translate/Translation best practices"> </a></span></li> <li><a href="/wiki/Special:MyLanguage/Help:Extension:Translate/Statistics_and_reporting" title="Special:MyLanguage/Help:Extension:Translate/Statistics and reporting">Statistics and reporting</a><span style="display:none"><a href="/wiki/Help:Extension:Translate/Statistics_and_reporting" title="Help:Extension:Translate/Statistics and reporting"> </a></span></li> <li><a href="/wiki/Special:MyLanguage/Help:Extension:Translate/Quality_assurance" title="Special:MyLanguage/Help:Extension:Translate/Quality assurance">Quality assurance</a><span style="display:none"><a href="/wiki/Help:Extension:Translate/Quality_assurance" title="Help:Extension:Translate/Quality assurance"> </a></span></li> <li><a href="/wiki/Special:MyLanguage/Help:Extension:Translate/Message_group_states" title="Special:MyLanguage/Help:Extension:Translate/Message group states">Message group states</a><span style="display:none"><a href="/wiki/Help:Extension:Translate/Message_group_states" title="Help:Extension:Translate/Message group states"> </a></span></li> <li><a href="/wiki/Special:MyLanguage/Help:Extension:Translate/Off-line_translation" title="Special:MyLanguage/Help:Extension:Translate/Off-line translation">Offline translation</a><span style="display:none"><a href="/wiki/Help:Extension:Translate/Off-line_translation" title="Help:Extension:Translate/Off-line translation"> </a></span></li> <li><a href="/wiki/Special:MyLanguage/Help:Extension:Translate/Glossary" title="Special:MyLanguage/Help:Extension:Translate/Glossary">Glossary</a><span style="display:none"><a href="/wiki/Help:Extension:Translate/Glossary" title="Help:Extension:Translate/Glossary"> </a></span></li></ul> <p><b>Translation administrators</b> </p> <ul><li><a href="/wiki/Special:MyLanguage/Help:Extension:Translate/Page_translation_example" title="Special:MyLanguage/Help:Extension:Translate/Page translation example">How to prepare a page for translation</a><span style="display:none"><a href="/wiki/Help:Extension:Translate/Page_translation_example" title="Help:Extension:Translate/Page translation example"> </a></span></li> <li><a href="/wiki/Special:MyLanguage/Help:Extension:Translate/Page_translation_administration" title="Special:MyLanguage/Help:Extension:Translate/Page translation administration">Page translation administration</a><span style="display:none"><a href="/wiki/Help:Extension:Translate/Page_translation_administration" title="Help:Extension:Translate/Page translation administration"> </a></span></li> <li><a href="/wiki/Special:MyLanguage/Help:Extension:Translate/Unstructured_element_translation" title="Special:MyLanguage/Help:Extension:Translate/Unstructured element translation">Unstructured element translation</a><span style="display:none"><a href="/wiki/Help:Extension:Translate/Unstructured_element_translation" title="Help:Extension:Translate/Unstructured element translation"> </a></span></li> <li><a href="/wiki/Special:MyLanguage/Help:Extension:Translate/Group_management" title="Special:MyLanguage/Help:Extension:Translate/Group management">Group management</a><span style="display:none"><a href="/wiki/Help:Extension:Translate/Group_management" title="Help:Extension:Translate/Group management"> </a></span></li> <li><a href="/wiki/Special:MyLanguage/Help:Extension:Translate/Move_translatable_page" title="Special:MyLanguage/Help:Extension:Translate/Move translatable page">Move translatable page</a><span style="display:none"><a href="/wiki/Help:Extension:Translate/Move_translatable_page" title="Help:Extension:Translate/Move translatable page"> </a></span></li> <li><a href="/wiki/Special:MyLanguage/Help:Extension:Translate/Import_Translations_via_CSV" title="Special:MyLanguage/Help:Extension:Translate/Import Translations via CSV">Import translations via CSV</a><span style="display:none"><a href="/wiki/Help:Extension:Translate/Import_Translations_via_CSV" title="Help:Extension:Translate/Import Translations via CSV"> </a></span></li> <li><a href="/wiki/Special:MyLanguage/Help:Extension:Translate/Message_Bundles" title="Special:MyLanguage/Help:Extension:Translate/Message Bundles">Working with message bundles</a><span style="display:none"><a href="/wiki/Help:Extension:Translate/Message_Bundles" title="Help:Extension:Translate/Message Bundles"> </a></span></li></ul> <p><b>Sysadmins and developers</b> </p> <ul><li><a href="/wiki/Special:MyLanguage/Help:Extension:Translate/Installation" title="Special:MyLanguage/Help:Extension:Translate/Installation">Installation</a><span style="display:none"><a href="/wiki/Help:Extension:Translate/Installation" title="Help:Extension:Translate/Installation"> </a></span></li> <li><a href="/wiki/Special:MyLanguage/Help:Extension:Translate/Configuration" title="Special:MyLanguage/Help:Extension:Translate/Configuration">Configuration</a><span style="display:none"><a href="/wiki/Help:Extension:Translate/Configuration" title="Help:Extension:Translate/Configuration"> </a></span></li> <li><a href="/wiki/Special:MyLanguage/Help:Extension:Translate/Getting_started_with_development" title="Special:MyLanguage/Help:Extension:Translate/Getting started with development">Getting started with development</a><span style="display:none"><a href="/wiki/Help:Extension:Translate/Getting_started_with_development" title="Help:Extension:Translate/Getting started with development"> </a></span></li> <li><b><a href="/wiki/Special:MyLanguage/Help:Extension:Translate/Developer_guide" title="Special:MyLanguage/Help:Extension:Translate/Developer guide">Developer guide</a></b><span style="display:none"><a class="mw-selflink selflink"> </a></span></li> <li><a href="/wiki/Special:MyLanguage/Help:Extension:Translate/Components" title="Special:MyLanguage/Help:Extension:Translate/Components">Extending Translate</a><span style="display:none"><a href="/wiki/Help:Extension:Translate/Components" title="Help:Extension:Translate/Components"> </a></span></li> <li><a href="/wiki/Special:MyLanguage/Help:Extension:Translate/Validators" title="Special:MyLanguage/Help:Extension:Translate/Validators">Validators</a><span style="display:none"><a href="/wiki/Help:Extension:Translate/Validators" title="Help:Extension:Translate/Validators"> </a></span></li> <li><a href="/wiki/Special:MyLanguage/Help:Extension:Translate/Insertables" title="Special:MyLanguage/Help:Extension:Translate/Insertables">Insertables</a><span style="display:none"><a href="/wiki/Help:Extension:Translate/Insertables" title="Help:Extension:Translate/Insertables"> </a></span></li> <li><a href="/wiki/Special:MyLanguage/Help:Extension:Translate/Group_configuration" title="Special:MyLanguage/Help:Extension:Translate/Group configuration">Group configuration</a><span style="display:none"><a href="/wiki/Help:Extension:Translate/Group_configuration" title="Help:Extension:Translate/Group configuration"> </a></span></li> <li><a href="/wiki/Special:MyLanguage/Help:Extension:Translate/Group_configuration_example" title="Special:MyLanguage/Help:Extension:Translate/Group configuration example">Group configuration example</a><span style="display:none"><a href="/wiki/Help:Extension:Translate/Group_configuration_example" title="Help:Extension:Translate/Group configuration example"> </a></span></li> <li><a href="/wiki/Special:MyLanguage/Help:Extension:Translate/Translation_memories" title="Special:MyLanguage/Help:Extension:Translate/Translation memories">Translation memories</a><span style="display:none"><a href="/wiki/Help:Extension:Translate/Translation_memories" title="Help:Extension:Translate/Translation memories"> </a></span></li> <li><a href="/wiki/Special:MyLanguage/Help:Extension:Translate/Translation_aids" title="Special:MyLanguage/Help:Extension:Translate/Translation aids">Translation aids</a><span style="display:none"><a href="/wiki/Help:Extension:Translate/Translation_aids" title="Help:Extension:Translate/Translation aids"> </a></span></li> <li><a href="/wiki/Special:MyLanguage/Help:Extension:Translate/Message_Bundles#Enabling_message_bundle_integration" title="Special:MyLanguage/Help:Extension:Translate/Message Bundles">Enabling message bundles</a><span style="display:none"><a href="/wiki/Help:Extension:Translate/Message_Bundles#Enabling_message_bundle_integration" title="Help:Extension:Translate/Message Bundles"> </a></span></li> <li><a class="external text" href="https://doc.wikimedia.org/Translate/master/php/classMediaWiki_1_1Extension_1_1Translate_1_1HookRunner.html">PHP hooks</a></li></ul> <p><small><a class="external text" href="https://www.mediawiki.org/w/index.php?title=Special:Translate&amp;group=page-Template%3AExtension-Translate&amp;language=&amp;action=page&amp;filter=">Translate this template</a></small> </p> </div> <p>Translate extension is a large extension with hundreds of classes. This page provides guidance for developers who want to work on the code. After reading this page and linked documents you will better understand how code in Translate is organized and what special conventions are used. General MediaWiki development policies, coding conventions and how to use tools like Gerrit and Phabricator are out of scope. You are assumed to be familiar with these topics and when they apply to Translate, it will not be repeated here. </p><p>Translate extension is undergoing many large migrations simultaneously. Here we list the major migrations that are on-going, and detail which style is preferred for new code. Generally, when modifying existing code, it is better to keep to current style, and do migrations separately. Some smaller cleanups are okay to do when touching code. </p> <meta property="mw:PageProp/toc"/> <div class="mw-heading mw-heading2 ext-discussiontools-init-section"><h2 id="Namespace_migration" data-mw-thread-id="h-Namespace_migration"><span data-mw-comment-start="" id="h-Namespace_migration"></span>Namespace migration<span data-mw-comment-end="h-Namespace_migration"></span></h2><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Help:Extension:Translate/Developer_guide&amp;action=edit&amp;section=1" title="Edit section: Namespace migration"><span>edit</span></a><span class="mw-editsection-bracket">]</span></span><!--__DTELLIPSISBUTTON__{"threadItem":{"headingLevel":2,"name":"h-","type":"heading","level":0,"id":"h-Namespace_migration","replies":[]}}--></div> <p>We are in process of migrating all Translate code under the namespace <code>\MediaWiki\Extension\Translate</code>. All namespaced code is placed under the <code>src/</code> directory. All new PHP files should be put in an appropriate namespace. See <a href="/wiki/Special:MyLanguage/Extension:Translate/Namespaces" title="Special:MyLanguage/Extension:Translate/Namespaces">Extension:Translate/Namespaces</a><span style="display:none"><a href="/wiki/Extension:Translate/Namespaces" title="Extension:Translate/Namespaces"> </a></span> for guidance which namespaces are going to be available. Namespaces are organized by domain, rather than function. Abbreviations should be avoided in namespaces and class names. Legacy code is in the repository root and various subdirectories. </p> <style data-mw-deduplicate="TemplateStyles:r6651107">.mw-parser-output .note{background-position:left 7px top 50%;padding:0.5em 0.5em 0.5em 40px;margin:0.5em 0;overflow:hidden;background-color:#f8f9fa;color:#333;background-repeat:no-repeat;border:1px solid #ddd}.mw-parser-output .note-inline{display:inline-block;vertical-align:middle}.mw-parser-output .note-info{background-color:#eaf3ff;color:#333;background-image:url("https://upload.wikimedia.org/wikipedia/commons/e/ec/OOjs_UI_icon_information-progressive.svg");background-size:25px;border-color:#a3caff;padding-left:40px;min-height:25px}.mw-parser-output .note-reminder{background-color:#fff9ea;color:#333;background-image:url("https://upload.wikimedia.org/wikipedia/commons/a/a8/OOjs_UI_icon_lightbulb-yellow.svg");background-size:25px;border-color:#fc3;min-height:25px}.mw-parser-output .note-warn{background-color:#fff9ea;color:#333;background-image:url("https://upload.wikimedia.org/wikipedia/commons/3/3b/OOjs_UI_icon_alert-warning.svg");background-size:25px;border-color:#fc3;min-height:25px}.mw-parser-output .note-error{background-color:#fee7e6;color:#333;background-image:url("https://upload.wikimedia.org/wikipedia/commons/b/bf/OOjs_UI_icon_notice-destructive.svg");background-size:25px;border-color:#c33;min-height:25px}@media screen{html.skin-theme-clientpref-night .mw-parser-output .note{background-color:transparent;color:inherit}}@media screen and (prefers-color-scheme:dark){html.skin-theme-clientpref-os .mw-parser-output .note{background-color:transparent;color:inherit}}</style><div role="note" class="note note-info">In Gerrit, SonarCube calculates code review coverage only for code under <code>src/</code> directory.</div> <div class="mw-heading mw-heading2 ext-discussiontools-init-section"><h2 id="Splitting_tests_into_integration_and_unit_tests" data-mw-thread-id="h-Splitting_tests_into_integration_and_unit_tests"><span data-mw-comment-start="" id="h-Splitting_tests_into_integration_and_unit_tests"></span>Splitting tests into integration and unit tests<span data-mw-comment-end="h-Splitting_tests_into_integration_and_unit_tests"></span></h2><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Help:Extension:Translate/Developer_guide&amp;action=edit&amp;section=2" title="Edit section: Splitting tests into integration and unit tests"><span>edit</span></a><span class="mw-editsection-bracket">]</span></span><!--__DTELLIPSISBUTTON__{"threadItem":{"headingLevel":2,"name":"h-","type":"heading","level":0,"id":"h-Splitting_tests_into_integration_and_unit_tests","replies":[]}}--></div> <p>Previously there was no distinction of integration and unit tests. For new code, unit tests should be the main type of tests. Unit tests are placed under <code>tests/phpunit/unit</code> directory matching the namespace layout. There is a Makefile in that directory to easily run all or parts of unit tests while developing. </p> <div class="mw-heading mw-heading2 ext-discussiontools-init-section"><h2 id="Type_declarations_and_comments" data-mw-thread-id="h-Type_declarations_and_comments"><span data-mw-comment-start="" id="h-Type_declarations_and_comments"></span>Type declarations and comments<span data-mw-comment-end="h-Type_declarations_and_comments"></span></h2><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Help:Extension:Translate/Developer_guide&amp;action=edit&amp;section=3" title="Edit section: Type declarations and comments"><span>edit</span></a><span class="mw-editsection-bracket">]</span></span><!--__DTELLIPSISBUTTON__{"threadItem":{"headingLevel":2,"name":"h-","type":"heading","level":0,"id":"h-Type_declarations_and_comments","replies":[]}}--></div> <p>All new code should declare both parameter and return types. In addition strict types should be enabled using <code class="mw-highlight mw-highlight-lang-php mw-content-ltr" dir="ltr"><span class="k">declare</span><span class="p">(</span> <span class="nx">strict_types</span> <span class="o">=</span> <span class="mi">1</span> <span class="p">);</span></code>. </p><p>Thanks to type declarations, most function and method comments are now redundant, as they would only repeat the parameter names and types. Do not add redundant documentation unless it provides additional value. One such example is to provide more accurate type hints for array types, for example: </p> <div class="mw-highlight mw-highlight-lang-php mw-content-ltr" dir="ltr"><pre><span></span><span class="k">class</span> <span class="nc">UserManager</span> <span class="p">{</span> <span class="sd">/** @return User[] */</span> <span class="k">public</span> <span class="k">function</span> <span class="nf">getAllUsers</span><span class="p">()</span><span class="o">:</span> <span class="k">array</span> <span class="p">{</span> <span class="o">...</span> <span class="p">}</span> <span class="p">}</span> </pre></div> <p>As illustrated above, for comments having only one tag or one line description, do use the one line comment syntax as well. </p> <link rel="mw-deduplicated-inline-style" href="mw-data:TemplateStyles:r6651107"><div role="note" class="note note-info">There is no linter about spacing around <code>:</code> in return type declarations. Until such standard comes, please use the illustrated style: no space before, one space after.</div> <div class="mw-heading mw-heading2 ext-discussiontools-init-section"><h2 id="Constructor_dependency_injection" data-mw-thread-id="h-Constructor_dependency_injection"><span data-mw-comment-start="" id="h-Constructor_dependency_injection"></span>Constructor dependency injection<span data-mw-comment-end="h-Constructor_dependency_injection"></span></h2><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Help:Extension:Translate/Developer_guide&amp;action=edit&amp;section=4" title="Edit section: Constructor dependency injection"><span>edit</span></a><span class="mw-editsection-bracket">]</span></span><!--__DTELLIPSISBUTTON__{"threadItem":{"headingLevel":2,"name":"h-","type":"heading","level":0,"id":"h-Constructor_dependency_injection","replies":[]}}--></div> <p>New code should have all its dependencies injected via constructor. In some cases this is not yet possible due to the lack of ObjectFactory support for some types of classes like jobs and maintenance scripts. For such new code, place all dependencies on the class constructor (or main entry point to the class) to easy migration to constructor dependency injection in the future. </p> <link rel="mw-deduplicated-inline-style" href="mw-data:TemplateStyles:r6651107"><div role="note" class="note note-error">Maintenance scripts cannot use any code that requires PHP autoloader, hence all dependencies can only be declared in the <code>execute</code> method, not in the constructor.</div> <p><br/> </p> <div class="mw-heading mw-heading2 ext-discussiontools-init-section"><h2 id="File_header" data-mw-thread-id="h-File_header"><span data-mw-comment-start="" id="h-File_header"></span>File header<span data-mw-comment-end="h-File_header"></span></h2><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Help:Extension:Translate/Developer_guide&amp;action=edit&amp;section=5" title="Edit section: File header"><span>edit</span></a><span class="mw-editsection-bracket">]</span></span><!--__DTELLIPSISBUTTON__{"threadItem":{"headingLevel":2,"name":"h-","type":"heading","level":0,"id":"h-File_header","replies":[]}}--></div> <p>For new code, we have chosen the following minimalistic header: </p> <div class="mw-highlight mw-highlight-lang-php mw-content-ltr" dir="ltr"><pre><span></span><span class="cp">&lt;?php</span> <span class="k">declare</span><span class="p">(</span> <span class="nx">strict_types</span> <span class="o">=</span> <span class="mi">1</span> <span class="p">);</span> <span class="k">namespace</span> <span class="nx">Example</span><span class="p">;</span> <span class="k">use</span> <span class="nx">OtherStuff</span><span class="p">;</span> <span class="sd">/**</span> <span class="sd"> * Class description.</span> <span class="sd"> * @author Your name</span> <span class="sd"> * @license GPL-2.0-or-later</span> <span class="sd"> * @since 2020.06</span> <span class="sd"> */</span> <span class="k">class</span> <span class="nc">ExampleClass</span> <span class="p">{</span> <span class="sd">/** @return User[] */</span> <span class="k">public</span> <span class="k">function</span> <span class="nf">getAllUsers</span><span class="p">()</span><span class="o">:</span> <span class="k">array</span> <span class="p">{</span> <span class="o">...</span> <span class="p">}</span> <span class="p">}</span> </pre></div> <p>If you wish to assert your copyright more explicitly, you can optionally add @copyright tag as well. </p> <div class="mw-heading mw-heading2 ext-discussiontools-init-section"><h2 id="Deprecation_and_version_numbers" data-mw-thread-id="h-Deprecation_and_version_numbers"><span data-mw-comment-start="" id="h-Deprecation_and_version_numbers"></span>Deprecation and version numbers<span data-mw-comment-end="h-Deprecation_and_version_numbers"></span></h2><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Help:Extension:Translate/Developer_guide&amp;action=edit&amp;section=6" title="Edit section: Deprecation and version numbers"><span>edit</span></a><span class="mw-editsection-bracket">]</span></span><!--__DTELLIPSISBUTTON__{"threadItem":{"headingLevel":2,"name":"h-","type":"heading","level":0,"id":"h-Deprecation_and_version_numbers","replies":[]}}--></div> <p>When changing Translate code in backwards incompatible ways, do check <a rel="nofollow" class="external free" href="https://codesearch.wmcloud.org/search/">https://codesearch.wmcloud.org/search/</a> for any users of the code. Known users are TwnMainPage, TranslateSVG, CentralNotice, MassMessage and bunch of stuff in the translatewiki repository. </p><p>You can use the deprecation facilities provided by MediaWiki core, including the @deprecated tag and wfDeprecated() hard deprecation. If there are no known users of the code, it is okay to change it in backwards incompatible way without deprecation, unless it is explicitly marked as stable (See <a href="/wiki/Special:MyLanguage/Stable_interface_policy" title="Special:MyLanguage/Stable interface policy">Stable interface policy</a>). Code marked as stable should be hard-deprecated at least for one <a href="/wiki/Special:MyLanguage/MediaWiki_Language_Extension_Bundle" title="Special:MyLanguage/MediaWiki Language Extension Bundle">MediaWiki Language Extension Bundle</a><span style="display:none"><a href="/wiki/MediaWiki_Language_Extension_Bundle" title="MediaWiki Language Extension Bundle"> </a></span> (MLEB) release. </p><p>MediaWiki core version numbers are meaningless in the context of Translate, as Translate always supports multiple MediaWiki releases. Translate itself uses YYYY.MM style versioning (as part of MLEB). New classes and methods should be annotated with @since YYYY.MM tags. </p> <!-- NewPP limit report Parsed by mw‐web.eqiad.main‐858c7455cb‐8przg Cached time: 20241029103617 Cache expiry: 2592000 Reduced expiry: false Complications: [show‐toc] DiscussionTools time usage: 0.010 seconds CPU time usage: 0.209 seconds Real time usage: 0.280 seconds Preprocessor visited node count: 1676/1000000 Post‐expand include size: 24552/2097152 bytes Template argument size: 10142/2097152 bytes Highest expansion depth: 14/100 Expensive parser function count: 10/500 Unstrip recursion depth: 0/20 Unstrip post‐expand size: 10120/5000000 bytes Lua time usage: 0.029/10.000 seconds Lua memory usage: 1056921/52428800 bytes Number of Wikibase entities loaded: 0/400 --> <!-- Transclusion expansion time report (%,ms,calls,template) 100.00% 117.638 1 -total 75.77% 89.136 1 Template:Extension-Translate 73.97% 87.022 30 Template:Ll 47.19% 55.517 60 Template:Translatable 39.32% 46.253 30 Template:Pagelang 12.93% 15.216 3 Template:Note 5.53% 6.503 2 Template:TNTN 4.13% 4.854 1 Translations:Extension:Translate/Page_display_title/en 2.21% 2.596 1 Translations:MediaWiki_Language_Extension_Bundle/Page_display_title/en --> <!-- Saved in parser cache with key mediawikiwiki:pcache:idhash:1148836-0!canonical and timestamp 20241029103617 and revision id 6685786. Rendering was triggered because: page-view --> </div><!--esi <esi:include src="/esitest-fa8a495983347898/content" /> --><noscript><img src="https://login.wikimedia.org/wiki/Special:CentralAutoLogin/start?type=1x1" alt="" width="1" height="1" style="border: none; position: absolute;"></noscript> <div class="printfooter" data-nosnippet="">Retrieved from "<a dir="ltr" href="https://www.mediawiki.org/w/index.php?title=Help:Extension:Translate/Developer_guide&amp;oldid=6685786">https://www.mediawiki.org/w/index.php?title=Help:Extension:Translate/Developer_guide&amp;oldid=6685786</a>"</div></div> <div id="catlinks" class="catlinks" data-mw="interface"><div id="mw-normal-catlinks" class="mw-normal-catlinks"><a href="/wiki/Special:Categories" title="Special:Categories">Category</a>: <ul><li><a href="/wiki/Category:Extension:Translate" title="Category:Extension:Translate">Extension:Translate</a></li></ul></div></div> </div> </main> </div> <div class="mw-footer-container"> <footer id="footer" class="mw-footer" > <ul id="footer-info"> <li id="footer-info-lastmod"> This page was last edited on 3 August 2024, at 09:51.</li> <li id="footer-info-copyright">Text is available under the <a rel="nofollow" class="external text" href="https://creativecommons.org/licenses/by-sa/4.0/deed.en">Creative Commons Attribution-ShareAlike License</a>; additional terms may apply. Text in <a class="external text" href="https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents">the Help: namespace</a> is available under the <a rel="nofollow" class="external text" href="https://creativecommons.org/publicdomain/zero/1.0/">Creative Commons CC0 License</a>. By using this site, you agree to the <a class="external text" href="https://foundation.wikimedia.org/wiki/Special:MyLanguage/Policy:Terms_of_Use">Terms of Use</a> and <a class="external text" href="https://foundation.wikimedia.org/wiki/Special:MyLanguage/Policy:Privacy_policy">Privacy Policy</a>.</li> </ul> <ul id="footer-places"> <li id="footer-places-privacy"><a href="https://foundation.wikimedia.org/wiki/Special:MyLanguage/Policy:Privacy_policy">Privacy policy</a></li> <li id="footer-places-about"><a href="/wiki/Project:About">About mediawiki.org</a></li> <li id="footer-places-disclaimers"><a href="/wiki/Project:General_disclaimer">Disclaimers</a></li> <li id="footer-places-wm-codeofconduct"><a href="https://www.mediawiki.org/wiki/Special:MyLanguage/Code_of_Conduct">Code of Conduct</a></li> <li id="footer-places-developers"><a href="https://developer.wikimedia.org">Developers</a></li> <li id="footer-places-statslink"><a href="https://stats.wikimedia.org/#/www.mediawiki.org">Statistics</a></li> <li id="footer-places-cookiestatement"><a href="https://foundation.wikimedia.org/wiki/Special:MyLanguage/Policy:Cookie_statement">Cookie statement</a></li> <li id="footer-places-mobileview"><a href="//m.mediawiki.org/w/index.php?title=Help:Extension:Translate/Developer_guide&amp;mobileaction=toggle_view_mobile" class="noprint stopMobileRedirectToggle">Mobile view</a></li> </ul> <ul id="footer-icons" class="noprint"> <li id="footer-copyrightico"><a href="https://wikimediafoundation.org/" class="cdx-button cdx-button--fake-button cdx-button--size-large cdx-button--fake-button--enabled"><img src="/static/images/footer/wikimedia-button.svg" width="84" height="29" alt="Wikimedia Foundation" loading="lazy"></a></li> <li id="footer-poweredbyico"><a href="https://www.mediawiki.org/" class="cdx-button cdx-button--fake-button cdx-button--size-large cdx-button--fake-button--enabled"><img src="/w/resources/assets/poweredby_mediawiki.svg" alt="Powered by MediaWiki" width="88" height="31" loading="lazy"></a></li> </ul> </footer> </div> </div> </div> <div class="vector-settings" id="p-dock-bottom"> <ul></ul> </div><script>(RLQ=window.RLQ||[]).push(function(){mw.config.set({"wgHostname":"mw-web.codfw.main-f69cdc8f6-kmvjg","wgBackendResponseTime":139,"wgDiscussionToolsPageThreads":[{"headingLevel":2,"name":"h-","type":"heading","level":0,"id":"h-Namespace_migration","replies":[]},{"headingLevel":2,"name":"h-","type":"heading","level":0,"id":"h-Splitting_tests_into_integration_and_unit_tests","replies":[]},{"headingLevel":2,"name":"h-","type":"heading","level":0,"id":"h-Type_declarations_and_comments","replies":[]},{"headingLevel":2,"name":"h-","type":"heading","level":0,"id":"h-Constructor_dependency_injection","replies":[]},{"headingLevel":2,"name":"h-","type":"heading","level":0,"id":"h-File_header","replies":[]},{"headingLevel":2,"name":"h-","type":"heading","level":0,"id":"h-Deprecation_and_version_numbers","replies":[]}],"wgPageParseReport":{"discussiontools":{"limitreport-timeusage":"0.010"},"limitreport":{"cputime":"0.209","walltime":"0.280","ppvisitednodes":{"value":1676,"limit":1000000},"postexpandincludesize":{"value":24552,"limit":2097152},"templateargumentsize":{"value":10142,"limit":2097152},"expansiondepth":{"value":14,"limit":100},"expensivefunctioncount":{"value":10,"limit":500},"unstrip-depth":{"value":0,"limit":20},"unstrip-size":{"value":10120,"limit":5000000},"entityaccesscount":{"value":0,"limit":400},"timingprofile":["100.00% 117.638 1 -total"," 75.77% 89.136 1 Template:Extension-Translate"," 73.97% 87.022 30 Template:Ll"," 47.19% 55.517 60 Template:Translatable"," 39.32% 46.253 30 Template:Pagelang"," 12.93% 15.216 3 Template:Note"," 5.53% 6.503 2 Template:TNTN"," 4.13% 4.854 1 Translations:Extension:Translate/Page_display_title/en"," 2.21% 2.596 1 Translations:MediaWiki_Language_Extension_Bundle/Page_display_title/en"]},"scribunto":{"limitreport-timeusage":{"value":"0.029","limit":"10.000"},"limitreport-memusage":{"value":1056921,"limit":52428800}},"cachereport":{"origin":"mw-web.eqiad.main-858c7455cb-8przg","timestamp":"20241029103617","ttl":2592000,"transientcontent":false}}});});</script> </body> </html>

Pages: 1 2 3 4 5 6 7 8 9 10