# Table of Contents - [devel:syntax_plugins [DokuWiki]](#devel-syntax-plugins-dokuwiki-) - [cs:devel:syntax_plugins [DokuWiki]](#cs-devel-syntax-plugins-dokuwiki-) - [ca:devel:syntax_plugins [DokuWiki]](#ca-devel-syntax-plugins-dokuwiki-) - [da:devel:syntax_plugins [DokuWiki]](#da-devel-syntax-plugins-dokuwiki-) - [es:devel:syntax_plugins [DokuWiki]](#es-devel-syntax-plugins-dokuwiki-) - [eo:devel:syntax_plugins [DokuWiki]](#eo-devel-syntax-plugins-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [devel:syntax_plugins [DokuWiki]](#devel-syntax-plugins-dokuwiki-) - [devel:syntax_plugins - Recent Changes [DokuWiki]](#devel-syntax-plugins-recent-changes-dokuwiki-) - [localization [DokuWiki]](#localization-dokuwiki-) - [install [DokuWiki]](#install-dokuwiki-) - [development [DokuWiki]](#development-dokuwiki-) - [ca:devel:syntax_plugins [DokuWiki]](#ca-devel-syntax-plugins-dokuwiki-) - [da:devel:syntax_plugins [DokuWiki]](#da-devel-syntax-plugins-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [devel:debugging - Old revisions [DokuWiki]](#devel-debugging-old-revisions-dokuwiki-) - [devel:syntax_plugins [DokuWiki]](#devel-syntax-plugins-dokuwiki-) - [✎ ca:devel:syntax_plugins [DokuWiki]](#-ca-devel-syntax-plugins-dokuwiki-) - [cs:devel:syntax_plugins - Old revisions [DokuWiki]](#cs-devel-syntax-plugins-old-revisions-dokuwiki-) - [newsletter [DokuWiki]](#newsletter-dokuwiki-) - [ca:devel:syntax_plugins - Old revisions [DokuWiki]](#ca-devel-syntax-plugins-old-revisions-dokuwiki-) - [da:devel:syntax_plugins - Old revisions [DokuWiki]](#da-devel-syntax-plugins-old-revisions-dokuwiki-) - [it:localization [DokuWiki]](#it-localization-dokuwiki-) - [Sitemap [DokuWiki]](#sitemap-dokuwiki-) - [Sitemap [DokuWiki]](#sitemap-dokuwiki-) - [Sitemap [DokuWiki]](#sitemap-dokuwiki-) - [Sitemap [DokuWiki]](#sitemap-dokuwiki-) - [Sitemap [DokuWiki]](#sitemap-dokuwiki-) - [da:devel:syntax_plugins [DokuWiki]](#da-devel-syntax-plugins-dokuwiki-) - [ca:devel:syntax_plugins [DokuWiki]](#ca-devel-syntax-plugins-dokuwiki-) - [da:devel:syntax_plugins [DokuWiki]](#da-devel-syntax-plugins-dokuwiki-) - [da:devel:syntax_plugins [DokuWiki]](#da-devel-syntax-plugins-dokuwiki-) - [da:devel:syntax_plugins [DokuWiki]](#da-devel-syntax-plugins-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [ca:devel:syntax_plugins [DokuWiki]](#ca-devel-syntax-plugins-dokuwiki-) - [da:devel:syntax_plugins [DokuWiki]](#da-devel-syntax-plugins-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [da:devel:syntax_plugins [DokuWiki]](#da-devel-syntax-plugins-dokuwiki-) - [ca:devel:syntax_plugins [DokuWiki]](#ca-devel-syntax-plugins-dokuwiki-) - [ca:devel:syntax_plugins [DokuWiki]](#ca-devel-syntax-plugins-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [plugin:addnewpage [DokuWiki]](#plugin-addnewpage-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [plugin:addnewpagedeluxe [DokuWiki]](#plugin-addnewpagedeluxe-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [plugin:breadcrumbdeluxe [DokuWiki]](#plugin-breadcrumbdeluxe-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [plugin:authwordpress [DokuWiki]](#plugin-authwordpress-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [plugin:deletepagebutton [DokuWiki]](#plugin-deletepagebutton-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [✎ plugin:authwordpress [DokuWiki]](#-plugin-authwordpress-dokuwiki-) - [Log In [DokuWiki]](#log-in-dokuwiki-) - [plugin:deletepagebutton - Backlinks [DokuWiki]](#plugin-deletepagebutton-backlinks-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [plugin:config [DokuWiki]](#plugin-config-dokuwiki-) - [Unknown](#unknown) - [plugin:iframe [DokuWiki]](#plugin-iframe-dokuwiki-) - [template:vector [DokuWiki]](#template-vector-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [plugin:deletepagebutton [DokuWiki]](#plugin-deletepagebutton-dokuwiki-) - [plugin:config - Old revisions [DokuWiki]](#plugin-config-old-revisions-dokuwiki-) - [plugin:config - Backlinks [DokuWiki]](#plugin-config-backlinks-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [plugin:config [DokuWiki]](#plugin-config-dokuwiki-) - [plugin:config [DokuWiki]](#plugin-config-dokuwiki-) - [plugin:config [DokuWiki]](#plugin-config-dokuwiki-) - [plugin:config [DokuWiki]](#plugin-config-dokuwiki-) - [de:devel:syntax_plugins [DokuWiki]](#de-devel-syntax-plugins-dokuwiki-) - [plugin:config [DokuWiki]](#plugin-config-dokuwiki-) - [plugin:config [DokuWiki]](#plugin-config-dokuwiki-) - [template:wikiweko [DokuWiki]](#template-wikiweko-dokuwiki-) - [it:install:upgrade [DokuWiki]](#it-install-upgrade-dokuwiki-) - [nl:admin_window [DokuWiki]](#nl-admin-window-dokuwiki-) - [mime [DokuWiki]](#mime-dokuwiki-) - [de:config [DokuWiki]](#de-config-dokuwiki-) - [ko:config [DokuWiki]](#ko-config-dokuwiki-) - [devel:plugin_survey:deployment [DokuWiki]](#devel-plugin-survey-deployment-dokuwiki-) - [plugin:config [DokuWiki]](#plugin-config-dokuwiki-) - [Log In [DokuWiki]](#log-in-dokuwiki-) - [de:config [DokuWiki]](#de-config-dokuwiki-) - [nl:admin_window [DokuWiki]](#nl-admin-window-dokuwiki-) - [template:wikiweko [DokuWiki]](#template-wikiweko-dokuwiki-) - [plugin:config [DokuWiki]](#plugin-config-dokuwiki-) - [mime - Recent Changes [DokuWiki]](#mime-recent-changes-dokuwiki-) - [mime [DokuWiki]](#mime-dokuwiki-) - [it:install:upgrade - Old revisions [DokuWiki]](#it-install-upgrade-old-revisions-dokuwiki-) - [template:wikiweko - Backlinks [DokuWiki]](#template-wikiweko-backlinks-dokuwiki-) - [de:config [DokuWiki]](#de-config-dokuwiki-) - [template:wikiweko [DokuWiki]](#template-wikiweko-dokuwiki-) - [template:wikiweko - Old revisions [DokuWiki]](#template-wikiweko-old-revisions-dokuwiki-) - [template:wikiweko [DokuWiki]](#template-wikiweko-dokuwiki-) - [it:install:upgrade - Backlinks [DokuWiki]](#it-install-upgrade-backlinks-dokuwiki-) - [de:config [DokuWiki]](#de-config-dokuwiki-) - [plugin:svgembed [DokuWiki]](#plugin-svgembed-dokuwiki-) - [it:install:upgrade [DokuWiki]](#it-install-upgrade-dokuwiki-) --- # devel:syntax_plugins [DokuWiki] devel:syntax\_plugins ### Table of Contents * [Syntax Plugins](https://www.dokuwiki.org/devel:syntax_plugins#syntax_plugins) * [Synopsis](https://www.dokuwiki.org/devel:syntax_plugins#synopsis) * [Syntax Types](https://www.dokuwiki.org/devel:syntax_plugins#syntax_types) * [Tutorial: Syntax Plugins Explained](https://www.dokuwiki.org/devel:syntax_plugins#tutorialsyntax_plugins_explained) * [Quick Summary](https://www.dokuwiki.org/devel:syntax_plugins#quick_summary) * [Key Concepts](https://www.dokuwiki.org/devel:syntax_plugins#key_concepts) * [modes](https://www.dokuwiki.org/devel:syntax_plugins#modes) * [mode types](https://www.dokuwiki.org/devel:syntax_plugins#mode_types) * [allowed modes](https://www.dokuwiki.org/devel:syntax_plugins#allowed_modes) * [PType](https://www.dokuwiki.org/devel:syntax_plugins#ptype) * [Sort Number](https://www.dokuwiki.org/devel:syntax_plugins#sort_number) * [Patterns](https://www.dokuwiki.org/devel:syntax_plugins#patterns) * [handle() method](https://www.dokuwiki.org/devel:syntax_plugins#handle_method) * [render() method](https://www.dokuwiki.org/devel:syntax_plugins#render_method) * [Safety & Security](https://www.dokuwiki.org/devel:syntax_plugins#safety_security) * [Common plugin functions](https://www.dokuwiki.org/devel:syntax_plugins#common_plugin_functions) * [Adding a Toolbar Button](https://www.dokuwiki.org/devel:syntax_plugins#adding_a_toolbar_button) * [Writing Your Own Plugin](https://www.dokuwiki.org/devel:syntax_plugins#writing_your_own_plugin) * [Read also](https://www.dokuwiki.org/devel:syntax_plugins#read_also) * [Sample Plugin 1 - Now](https://www.dokuwiki.org/devel:syntax_plugins#sample_plugin_1_-_now) * [Sample Plugin 2 - Color](https://www.dokuwiki.org/devel:syntax_plugins#sample_plugin_2_-_color) * [Unit Testing Syntax Plugins](https://www.dokuwiki.org/devel:syntax_plugins#unit_testing_syntax_plugins) Syntax Plugins ============== [Syntax Plugins](http://www.dokuwiki.org/plugins?plugintype=1#extension__table "http://www.dokuwiki.org/plugins?plugintype=1#extension__table") are [plugins](https://www.dokuwiki.org/devel:plugins "devel:plugins") to extend DokuWiki's [syntax](https://www.dokuwiki.org/wiki:syntax "wiki:syntax") . To be able to understand what is needed to register new Syntax within DokuWiki you should read [how the Parser works](https://www.dokuwiki.org/devel:parser "devel:parser") . Edit Synopsis -------- A Syntax Plugin _Example_ needs: * class name `syntax_plugin_example` * which extends [SyntaxPlugin](https://codesearch.dokuwiki.org/search?project=dokuwiki&defs=SyntaxPlugin&path=SyntaxPlugin "view definition for SyntaxPlugin") [1)](https://www.dokuwiki.org/devel:syntax_plugins#fn__1) . * to be stored in a file `lib/plugins/example/syntax.php`. Moreover, a [plugin.info.txt](https://www.dokuwiki.org/devel:plugin_info "devel:plugin_info") file is needed. For full details of plugins and their files and how to create more syntax components refer to [plugin file structure](https://www.dokuwiki.org/devel:plugin_file_structure "devel:plugin_file_structure") . The class needs to implement at least the following functions: * **`getType()`** Should return the type of syntax this plugin defines ([see below](https://www.dokuwiki.org/devel:syntax_plugins#syntax_types "devel:syntax_plugins ↵") ) * **`getSort()`** Returns a number used to determine in which order modes are added, also see [parser, order of adding modes](https://www.dokuwiki.org/devel:parser#order_of_adding_modes_important "devel:parser") and [getSort list](https://www.dokuwiki.org/devel:parser:getsort_list "devel:parser:getsort_list") . * **`connectTo($mode)`** This function is inherited from dokuwiki\\Parsing\\ParserMode\\AbstractMode [2)](https://www.dokuwiki.org/devel:syntax_plugins#fn__2) . Here is the place to register the regular expressions needed to match your syntax. * **`handle($match, $state, $pos, Doku_Handler $handler)`** to prepare the matched syntax for use in the renderer * **`render($format, Doku_Renderer $renderer, $data)`** to render the content The following additional methods can be overridden when required: * **`getPType()`** Defines how this syntax is handled regarding paragraphs[3)](https://www.dokuwiki.org/devel:syntax_plugins#fn__3) . Return: * `normal` — (default value, will be used if the method is not overridden) The plugin output will be inside a paragraph (or another block element), no paragraphs will be inside * `block` — Open paragraphs will be closed before plugin output, the plugin output will not start with a paragraph * `stack` — Open paragraphs will be closed before plugin output, the plugin output wraps other paragraphs * **`getAllowedTypes()`** (default value: `array()`) Should return an array of [mode types](https://www.dokuwiki.org/devel:syntax_plugins#syntax_types "devel:syntax_plugins ↵") that may be nested within the plugin's own markup. * **`accepts($mode)`** This function is used to tell the parser if the plugin accepts syntax mode $mode within its own markup. The default behaviour is to test $mode against the array of modes held by the inherited property `allowedModes`. This array is also filled with modes from the mode types given in `getAllowedTypes()`. Additional functions can be defined as needed. Inherited Properties * **`allowedModes`** — initial value, an empty array, inherited from AbstractMode [4)](https://www.dokuwiki.org/devel:syntax_plugins#fn__4) . Contains a list of other syntax modes which are allowed to occur within the plugin's own syntax mode (ie. the modes which belong to any other DokuWiki markup that can be nested inside the plugin's own markup). Normally, it is automatically populated by the `accepts()` function using the results of `getAllowedTypes()`. Inherited Functions * See [common plugin functions](https://www.dokuwiki.org/devel:common_plugin_functions "devel:common_plugin_functions") for inherited functions available to all plugins. e.g. localisation, configuration and introspection. Edit Syntax Types ------------ DokuWiki uses different syntax types to determine which syntax may be nested. Eg. you can have text formatting inside of tables. To integrate your plugin into this system it needs to specify which type it is and which types can be nested within it. The following types are currently available: | Modetype | Used in mode… | Description | | --- | --- | --- | | container | listblock, table, quote, hr | containers are complex modes that can contain many other modes – hr breaks the principle but they shouldn't be used in tables / lists so they are put here | | baseonly | header | some modes are allowed inside the base mode only | | formatting | strong, emphasis, underline, monospace, subscript, superscript, deleted, footnote | modes for styling text – footnote behaves similar to styling | | substition[5)](https://www.dokuwiki.org/devel:syntax_plugins#fn__5) | 'acronym', 'smiley', 'wordblock', 'entity', 'camelcaselink', 'internallink', 'media', 'externallink', 'linebreak', 'emaillink', 'windowssharelink', 'filelink', 'notoc', 'nocache', 'multiplyentity', 'quotes', 'rss' | modes where the token is simply replaced – they can not contain any other modes | | protected | 'preformatted', 'code', 'file', 'php', 'html' | modes which have a start and end token but inside which no other modes should be applied | | disabled | unformatted | inside this mode no wiki markup should be applied but lineendings and whitespace isn't preserved | | paragraphs | eol[6)](https://www.dokuwiki.org/devel:syntax_plugins#fn__6) | used to mark paragraph boundaries | Edit For a description what each type means and which other formatting classes are registered in them read the comments in `[inc/parser/parser.php](https://codesearch.dokuwiki.org/search?project=dokuwiki&defs=&path=inc%20parser%20parser.php "search definitions for inc/parser/parser.php") `. Edit Tutorial: Syntax Plugins Explained ================================== The goal of this tutorial is to explain the concepts involved in a DokuWiki [syntax plugin](https://www.dokuwiki.org/devel:syntax_plugins "devel:syntax_plugins") and to go through the steps involved in writing your own plugin. For those who are really impatient to get started, grab a copy of the [syntax plugin skeleton](https://www.dokuwiki.org/devel:syntax_plugin_skeleton "devel:syntax_plugin_skeleton") . It's a bare bones plugin which outputs “_Hello World!_” when it encounters “``” on a wiki page. Edit Quick Summary ------------- **modes** * each individual piece of DokuWiki syntax, including your plugin, has its own mode. * similar modes are grouped together into [mode types](https://www.dokuwiki.org/devel:syntax_plugins#mode_types "devel:syntax_plugins ↵") . * a mode's “allowedTypes” govern which other DokuWiki syntax is recognised when nested within the mode's own syntax. All the modes which belong to the allowedTypes will be permitted. * a mode's “type” lets other modes know if they can permit this mode within their syntax. **handle** * the `[handle()](https://www.dokuwiki.org/devel:syntax_plugins#handle_method "devel:syntax_plugins ↵") ` method is called when the parser encounters wiki page content that it decides belongs to your syntax mode. * the `$state` parameter says which type of pattern registered to your mode was triggered. If it's just ordinary text the state parameter will be set to `DOKU_LEXER_UNMATCHED` * do as much processing and decision making as possible here, leaving as little as possible to be carried out in the `[render()](https://www.dokuwiki.org/devel:syntax_plugins#render_method "devel:syntax_plugins ↵") ` method because the output of handle is cached. This also means that you shouldn't do any stuff here that mustn't be cached. **render** * The `[render()](https://www.dokuwiki.org/devel:syntax_plugins#render_method "devel:syntax_plugins ↵") ` method processes the renderer instructions that apply to the plugin's syntax mode - and which were created by the plugin's `[handle()](https://www.dokuwiki.org/devel:syntax_plugins#handle_method "devel:syntax_plugins ↵") ` method. * add content to the output document with `$renderer->doc .= 'content';` * access the return value of handle() using the _$data_ parameter of render($format, Doku\_Renderer $renderer, $data). * ensure any content output by the plugin is **safe** - run raw wiki data through an entity conversion function. * do the minimum possible processing and decision making here, it should all have been done in the `[handle()](https://www.dokuwiki.org/devel:syntax_plugins#handle_method "devel:syntax_plugins ↵") ` method. ![:!:](https://www.dokuwiki.org/lib/images/smileys/exclaim.svg) There is no guarantee the `[render()](https://www.dokuwiki.org/devel:syntax_plugins#render_method "devel:syntax_plugins ↵") ` method will be called at the same time as the `[handle()](https://www.dokuwiki.org/devel:syntax_plugins#handle_method "devel:syntax_plugins ↵") ` method. The instructions generated by the handler are cached and can be used by the renderer at a future time. The only sure way to pass data from `[handle()](https://www.dokuwiki.org/devel:syntax_plugins#handle_method "devel:syntax_plugins ↵") ` to `[render()](https://www.dokuwiki.org/devel:syntax_plugins#render_method "devel:syntax_plugins ↵") ` is using the array it returns - which is passed to `[render()](https://www.dokuwiki.org/devel:syntax_plugins#render_method "devel:syntax_plugins ↵") ` as the `$data` parameter. Edit Key Concepts ------------ Edit ### modes Modes (or more properly syntax modes) are the foundation on which the DokuWiki parser is based. Every different bit of DokuWiki markup has its own syntax mode. E.g. there is a strong mode for handling **strong**, a superscript mode for handling superscript, a table mode for processing tables and many more. When the parser encounters some markup it enters the syntax mode for that markup. The properties and methods of that particular syntax mode govern how the parser behaves while it is within that mode, including: * what other syntax modes are allowed to occur * what instructions to prepare for the renderer Your plugin will add its own syntax mode to the parser - that is automatically handled by DokuWiki when the plugin is first loaded, the name assigned is `plugin_`\+ the name of the plugin's directory (which must also be the plugin's class name without the prefix “`syntax_`”). Then, when the parser encounters the markup used for your plugin, the parser will enter into that syntax mode. While it is in that mode your plugin controls what the parser can do. Edit ### mode types To simplify things, syntax modes which behave in a similar manner have been grouped together into several mode types - a complete list can be found on the [syntax plugin](https://www.dokuwiki.org/devel:syntax_plugins#syntax_types "devel:syntax_plugins") page. Each mode type corresponds to a key in the `$PARSER_MODES` array. The entry for each mode type is itself an array which holds all the syntax modes which belong to that type. e.g. In vanilla DokuWiki with no plugins installed, `$PARSER_MODES['formatting']` holds an array containing: 'strong', 'emphasis', 'underline', 'superscript', 'subscript', 'monospace', 'deleted' & 'footnote'. When each plugin is loaded into the parser it is queried, via `getType()`, to discover which mode type it will belong to. The syntax mode associated with the plugin is then added to the appropriate `$PARSER_MODES` array. ![:!:](https://www.dokuwiki.org/lib/images/smileys/exclaim.svg) The mode type your plugin reports governs where in a DokuWiki page the parser will recognise your plugin's markup. Other DokuWiki (and plugin) syntax modes won't know about your plugin, but they do know about the different mode types. If they allow a particular mode type, they will allow all the modes which belong to that type, including any plugins that have returned that mode type. Select the mode type for your plugin by comparing the behaviour of your plugin to that of the standard DokuWiki syntax modes. Choose the type that the most similar modes belong to. Edit ### allowed modes These are the other modes that can occur nested within the current mode's own markup. Each syntax mode has its own array of allowed modes which tells the parser what other syntax modes will be recognised whilst it is processing the mode. That is, if you want your plugin to be able to occur nested within “\*\*strong\*\*” markup, then the strong mode must include your plugin's mode in its allowedModes array. And if you want to allow strong markup nested within your plugin's markup then your plugin must have `'strong'` in its allowModes array. ![:!:](https://www.dokuwiki.org/lib/images/smileys/exclaim.svg) Your plugin gets in the allowedModes array of other syntax modes through the mode type it reports using the `getType()` method. ![:!:](https://www.dokuwiki.org/lib/images/smileys/exclaim.svg) Your plugin tells the parser which other syntax modes it permits by reporting the mode types it allows via the `getAllowedTypes()` method. Edit ### PType PType governs how the parser handles html

elements when dealing with your syntax mode. Generally, when the parser encounters some markup, there will be a currently open HTML paragraph tag. The parser needs to know if it should close that tag before entering your syntax mode and then open another paragraph when exiting, that is `PType='block'` and `PType='stack'`, or whether it should leave the paragraphs alone, `PType='normal'`. The PType also decides how and if paragraphs are created **inside** the syntax mode. With `PType='normal'` no paragraphs are created at all. `PType='stack'` opens a paragraph when inside the syntax mode (and closes it later, parsing paragraphs like usual). And `PType='block'` starts with no paragraph, but creates them as usual as soon as there are more than two newlines. For those that know CSS, returning `PType='block'` and `PType='stack'` means the html generated by your plugin will be similar to `display:block` and returning `PType='normal'`means the HTML generated will be similar to `display:inline`. #### Example Suppose we have a fairly standard syntax plugin with the ENTRY ⇒ UNMATCHED ⇒ EXIT pattern. Depending on the PType setting, `

` and `

` will be inserted by the renderer automatically at various points outside, or even interspersed, with the plugin text. That means your plugin doesn't need to take care of those tags. | wikisyntax | PType=normal | PType=block | PType=stack | | --- | --- | --- | --- | | foo
text

bar | <[p](http://december.com/html/4/element/p.html)
\>foo
ENTRY("")
UNMATCHED("text")
EXIT("
")
\>
<[p](http://december.com/html/4/element/p.html)
\>bar\> | <[p](http://december.com/html/4/element/p.html)
\>foo\>
ENTRY("")
UNMATCHED("text")
EXIT("
")
<[p](http://december.com/html/4/element/p.html)
\>bar\> | <[p](http://december.com/html/4/element/p.html)
\>foo\>
ENTRY("")
<[p](http://december.com/html/4/element/p.html)
\>
UNMATCHED("text")
\>
EXIT("
")
<[p](http://december.com/html/4/element/p.html)
\>bar\> | Edit Edit ### Sort Number This number is used by the lexer[7)](https://www.dokuwiki.org/devel:syntax_plugins#fn__7) to control the order it tests the syntax mode patterns against raw wiki data. It is only important if the patterns belonging to two or more modes match the same raw data - where the pattern belonging to the mode with the lowest sort number will win out. You can make use of this behaviour to write a plugin which will replace or extend a native DokuWiki handler for the same syntax. An example is the [code](https://www.dokuwiki.org/plugin:code "plugin:code") plugin. Details of existing sort numbers are available for both the [parser](https://www.dokuwiki.org/devel:parser "devel:parser") ([sort list](https://www.dokuwiki.org/devel:parser:getsort_list "devel:parser:getsort_list") ). Edit ### Patterns The parser uses PHP's preg[8)](https://www.dokuwiki.org/devel:syntax_plugins#fn__8) compatible functions. A detailed explanation of regular expressions and their syntax is beyond the scope of this tutorial. There are many good sources on the web. The complete preg syntax is not available for use in constructing syntax plugin patterns. Below is a list of the known differences: * don't surround the pattern with delimiters * to use a pipe “`|`” for multiple alternatives, make them a non-captured group, e.g. “`(?:cat|dog)`” * be very wary of look behind assertions. The parser only attempts to match patterns on the next piece of “not yet matched” data. If you need to look behind to characters that have been involved in a previous pattern match, those characters will never be there. * option flags can only be included as inline options, e.g. `(?i)`, `(?-i)` * back references do not work, e.g. “`(\w)\1\w+`” (finding a word with a doubled first characters), due to the way the lexer functions internally. The parser provides four functions for a plugin to register the patterns it needs. Each function corresponds to a pattern with a different meaning. * **special patterns** — `addSpecialPattern()` — these are the patterns used when one pattern is all that is required. In the parser's terms, these patterns represent entry in the the plugin's syntax mode and exit from that syntax mode all in the one match. Typically these are used by `substition` plugins. * **entry patterns** — `addEntryPattern()` — the pattern which indicates the start of data to be handled by the plugin. Typically these patterns should include a look-ahead to ensure there is also an exit pattern. Any plugin which registers an entry pattern should also register an exit pattern. * **exit patterns** — `addExitPattern()` — the pattern which indicates the end of the data to be handled by the plugin. This pattern can only be matched if text matching the entry pattern has been found. * **internal patterns** — `addPattern()` — these represent special syntax applicable to the plugin that may occur between the entry and exit patterns. Generally these are only required by the more complex structures, e.g. lists and tables. One plugin may add several patterns to the parser, including more than one pattern of the same type. **Tips** * use non-greedy quantifiers, e.g. `+?` or `*?` instead of `+` or `*`. * be wary of using multiple exit patterns. The first exit pattern encountered will most likely trigger the parser to exit your syntax mode - even if that wasn't the pattern the entry pattern looked ahead for. Needing multiple exit patterns probably indicates a need for multiple plugins. * In the [Plugin Survey](https://www.dokuwiki.org/devel:plugin_survey:compatibility#syntax "devel:plugin_survey:compatibility") of 2011 it looks like a majority of special patterns are either `{{…}}` (160 cases) or `~~…~~` (80 cases). A very common entry/exit pattern (231 plugins) is something like an XML tag even if some use upper case letters. * early versions of the DokuWiki lexer had a bug which prevented use of “<” or “>” in look ahead patterns. This bug has been fixed and angle brackets can now be used. Some plugins will still contain the hex codes for angle brackets (“\\x3C”, “\\x3E”) which was the workaround to overcome the effects of this bug. * Use this for a example of correct regular expression: [Use correct regular expressions](https://www.dokuwiki.org/devel:plugin_programming_tips#use_correct_regular_expressions "devel:plugin_programming_tips") Edit ### handle() method This is the part of your plugin which should do all the work. Before DokuWiki renders the wiki page it creates a list of instructions for the renderer. The plugin's `handle()` method generates the render instructions for the plugin's own syntax mode. At some later time, these will be interpreted by the plugin's `render()` method. The instruction list is cached and can be used many times, making it sensible to maximize the work done once by this function and minimize the work done many times by `render()`. The complete signature is: `public function handle($match, $state, $pos, Doku_Handler $handler)` with the arguments: **$match** parameter — The text matched by the patterns, or in the case of **`DOKU_LEXER_UNMATCHED`** the contiguous piece of ordinary text which didn't match any pattern. **$state** parameter — The lexer state for the match, representing the type of pattern which triggered this call to handle(): * **`DOKU_LEXER_ENTER`** — a pattern set by addEntryPattern() * **`DOKU_LEXER_MATCHED`** — a pattern set by addPattern() * **`DOKU_LEXER_EXIT`** — a pattern set by addExitPattern() * **`DOKU_LEXER_SPECIAL`** — a pattern set by addSpecialPattern() * **`DOKU_LEXER_UNMATCHED`** — ordinary text encountered within the plugin's syntax mode which doesn't match any pattern. **$pos** parameter — The character position of the matched text. **$handler** parameter — Object Reference to the [Doku\_Handler](https://www.dokuwiki.org/devel:parser#handler "devel:parser") object. **return** — The instructions for the `render()` method. These instructions are cached. The return value can be everything you require for your needs. Often, it is an array in which the different values are collected that are founded or determined in handle() and which are useful in `render()`. Edit ### render() method The part of the plugin that provides the output for the final web page - or whatever other output format is supported. It is here that the plugin adds its output to that already generated by other parts of the renderer - e.g. by concatenating its output to the renderer's `doc` property. $renderer\->doc .= "some plugin output..."; ![:!:](https://www.dokuwiki.org/lib/images/smileys/exclaim.svg) Any raw wiki data that passes through `render()` should have all special characters converted to HTML entities. You can use DokuWiki's [hsc()](https://codesearch.dokuwiki.org/search?project=dokuwiki&defs=hsc&path= "unknown definition") or the PHP functions, [htmlspecialchars()](https://secure.php.net/htmlspecialchars() "https://secure.php.net/htmlspecialchars()") , [htmlentities()](https://secure.php.net/htmlentities() "https://secure.php.net/htmlentities()") or the renderer's own [\_xmlEntities()](https://codesearch.dokuwiki.org/search?project=dokuwiki&defs=_xmlEntities&path= "unknown definition") method. e.g. $renderer\->doc .= $renderer\->\_xmlEntities($text); The complete signature is: `public function render($format, Doku_Renderer $renderer, $data)` with the arguments: **$format** parameter — Name for the format mode of the final output produced by the renderer. At present DokuWiki only supports one output format `XHTML` and a special (internal) format `metadata` [9)](https://www.dokuwiki.org/devel:syntax_plugins#fn__9) . New modes can be introduced by [renderer plugins](https://www.dokuwiki.org/devel:renderer_plugins "devel:renderer_plugins") . The plugin should only produce output for those formats which it supports - which means this function should be structured … if ($format \== 'xhtml') { // supported mode // code to generate XHTML output from instruction $data } **$renderer** parameter — Give access to the object [Doku\_Renderer](https://codesearch.dokuwiki.org/search?project=dokuwiki&defs=Doku_Renderer&path=inc "unknown definition") , which contains useful functions and values. Above you saw already the usage of `$renderer->doc` for storing the render output. **$data** parameter — An array containing the instructions previously prepared and returned by the plugin's own `handle()` method. The `render()` must interpret the instruction and generate the appropriate output. #### XHTML renderer When your plugin needs to extend the content of a wiki page, you need the output format mode `xhtml`. Because `render()` is called for all the format modes, you need to filter by the desired modes. if ($format \== 'xhtml') { // when the format mode is xhtml /\*\* @var Doku\_Renderer\_xhtml $renderer \*/ // code to generate XHTML output from instruction $data $renderer\->doc .= '
Adds your div
'; } Detail: the variable `$renderer` is now the [Doku\_Renderer\_xhtml](https://codesearch.dokuwiki.org/search?project=dokuwiki&defs=Doku_Renderer_xhtml&path=inc "unknown definition") object. #### Metadata renderer A special render format `metadata` is for rendering metadata. [Metadata](https://www.dokuwiki.org/devel:metadata "devel:metadata") are the extra properties kept for your wiki page, which you can also extend or modify in your plugin. In the metadata rendering format you extracts metadata from the page. This is particularly important if you manually handle certain kinds of links. If you don't register these, they will not show up as backlinks on the pages that they refer to. Here is an example of how to register these backlinks: public function render($format, Doku\_Renderer $renderer, $data) { if($format \== 'xhtml') { /\*\* @var Doku\_Renderer\_xhtml $renderer \*/ // this is where you put all the rendering that will be displayed in the // web browser return true; } if($format \== 'metadata') { /\*\* @var Doku\_Renderer\_metadata $renderer \*/ $renderer\->internallink($data\[0\]); // I am assuming that when processing in handle(), you have stored // the link destination in $data\[0\] return true; } return false; } This example uses the [internallink()](https://codesearch.dokuwiki.org/search?project=dokuwiki&defs=internallink&path= "unknown definition") function from `inc/parser/metadata.php`. You can also access the metadata directly in the renderer with `$renderer->meta` and `$renderer->persistent`, because `$renderer` is now the [Doku\_Renderer\_metadata](https://codesearch.dokuwiki.org/search?project=dokuwiki&defs=Doku_Renderer_metadata&path=inc "unknown definition") object. Here is a snippet from the tag plugin: public function render($format, Doku\_Renderer $renderer, $data) { if ($data \=== false) return false;   // XHTML output if ($format \== 'xhtml') { /\*\* @var Doku\_Renderer\_xhtml $renderer \*/ ...   // for metadata renderer } elseif ($format \== 'metadata') { /\*\* @var Doku\_Renderer\_metadata $renderer \*/ // erase tags on persistent metadata no more used if ([isset](http://www.php.net/isset) ($renderer\->persistent\['subject'\])) { [unset](http://www.php.net/unset) ($renderer\->persistent\['subject'\]); $renderer\->meta\['subject'\] \= \[\]; }   // merge with previous tags and make the values unique if (![isset](http://www.php.net/isset) ($renderer\->meta\['subject'\])) { $renderer\->meta\['subject'\] \= \[\]; } $renderer\->meta\['subject'\] \= [array\_unique](http://www.php.net/array_unique) ([array\_merge](http://www.php.net/array_merge) ($renderer\->meta\['subject'\], $data));   // create raw text summary for the page abstract if ($renderer\->capture) { $renderer\->doc .= [implode](http://www.php.net/implode) (' ', $data); }   ... return true; } return false; } First it handles old persistent metadata no longer used by this plugin. This persistent metadata is always kept, thus when you change your mind and use current metadata instead, you need to remove it explicitly. When handling persistent data in the metadata renderer, take care you update also the current metadata, when you update persistent metadata. The tag plugin stores here 'subject' data by `$renderer->meta['subject'] = …`. Be aware that when you use `p_set_metadata` to set current metadata somewhere, that the next time the metadata is rendered it will overwrite this data. Using [p\_get\_metadata($ID, $key)](https://codesearch.dokuwiki.org/search?project=dokuwiki&defs=p_get_metadata&path= "unknown definition") gives access to stored metadata. For details see [metadata](https://www.dokuwiki.org/devel:metadata "devel:metadata") . When some raw text from your syntax should be included in the abstract you can append it to `$renderer->doc`. When the abstract is long enough, `$renderer->capture` becomes false. The xhtml mode is called when DokuWiki is in need of a new xhtml version of the wikipage. The metadata is a bit different. In general, the metadata of the page is rendered on demand when [p\_get\_metadata()](https://codesearch.dokuwiki.org/search?project=dokuwiki&defs=p_get_metadata&path= "unknown definition") is called somewhere. When someone edit a page and use the preview function, the metadata renderer is not called. So the metadata is not yet updated! This is done when the page is saved. Edit Safety & Security ----------------- Raw wiki page data which reaches your plugin has not been processed at all. No further processing is done on the output after it leaves your plugin. At an absolute minimum the plugin should ensure any raw data output has all HTML special characters converted to HTML entities. Also any wiki data extracted and used internally should be treated with suspicion. See also [security](https://www.dokuwiki.org/devel:security "devel:security") . Edit Common plugin functions ----------------------- Some function are shared between the plugins, refer to next sections for info: * [Plugin configuration settings](https://www.dokuwiki.org/devel:common_plugin_functions#configuration "devel:common_plugin_functions") * [Localization](https://www.dokuwiki.org/devel:common_plugin_functions#localization "devel:common_plugin_functions") * [Using styles and javascript](https://www.dokuwiki.org/devel:common_plugin_functions#styles_and_javascript "devel:common_plugin_functions") Edit ### Adding a Toolbar Button To make it easy on the users of wikis which install your plugin, you should add a button for its syntax to the editor toolbar. * The [toolbar](https://www.dokuwiki.org/devel:toolbar#extending_the_toolbar "devel:toolbar") page explains how you can extend by PHP or javascript. * Another [example](https://www.dokuwiki.org/devel:action_plugins#sample_action_plugin_2 "devel:action_plugins") is available at the Action Plugin page. Edit Writing Your Own Plugin ----------------------- Ok, so you have decided you want to extend DokuWiki's syntax with your own plugin. You have worked out what that syntax will be and how it should be rendered on the user's browser. Now you need to write the plugin. 1. Decide on a name for the plugin. You may want to check the list of [available plugins](https://www.dokuwiki.org/plugins "plugins") to make sure you aren't choosing a name that is already in use. 2. In your own DokuWiki installation, create a new sub directory in the `lib/plugins/` directory. That directory will have the same name as your plugin. 3. Create the file `syntax.php` in the new directory. As a starting point, use a copy of the [skeleton plugin](https://www.dokuwiki.org/devel:syntax_plugin_skeleton "devel:syntax_plugin_skeleton") . 4. Edit that file to make it yours. * change the class name to be `syntax_plugin_`[10)](https://www.dokuwiki.org/devel:syntax_plugins#fn__10) . * change the `getType()` method to report the mode type your plugin will belong to. * add a `getAllowedTypes()` method to report any mode types your plugin will allow to be nested within its own syntax. If your plugin won't allow any other mode then this can be left out. * change the `getPType()` method to report the PType that will apply for your plugin. If its `'normal'` you can remove this method. * change the `getSort()` method to report a unique number after checking the [getsorted list](https://www.dokuwiki.org/devel:parser:getsort_list "devel:parser:getsort_list") and * alter the `connectTo()` method to register the pattern to match your syntax. * add a `postConnect()` method if your syntax has an second pattern to say when the parser is leaving your syntax mode. 5. That's the easy part done, you now have a plugin that will say “Hello World!” when it encounters your syntax pattern. Time to test it and make sure the pattern works as expected - visit your wiki and make up a page with the syntax for your plugin, save it and make sure “Hello World!” shows up. 6. Write your `handle()` & `render()` methods. * if you have entry and exit patterns remember to handle the unmatched data. * treat raw wiki data with suspicion and remember to ensure all special characters go to an entity converter. 7. Add a [plugin.info.txt](https://www.dokuwiki.org/devel:plugin_info "devel:plugin_info") file in your plugin directory (see for example, the sample plugin below) 8. Test and post your completed plugin on the DokuWiki [plugin page](https://www.dokuwiki.org/plugins "plugins") . Edit Read also --------- * The [Plugin Wizard](http://pluginwizard.dokuwiki.org/ "http://pluginwizard.dokuwiki.org/") can create a basic skeleton or with the [dev](https://www.dokuwiki.org/plugin:dev "plugin:dev") plugin. * [Plugin file structure](https://www.dokuwiki.org/devel:plugin_file_structure "devel:plugin_file_structure") * [Common plugin functions](https://www.dokuwiki.org/devel:common_plugin_functions "devel:common_plugin_functions") * [Plugin programming tips](https://www.dokuwiki.org/devel:plugin_programming_tips "devel:plugin_programming_tips") * [Plugin Development](https://www.dokuwiki.org/devel:plugins "devel:plugins") Edit Sample Plugin 1 - Now --------------------- When its syntax, `[NOW]`, is encountered in a wiki page the current date and time will be inserted in [RFC2822](http://www.faqs.org/rfcs/rfc2822 "http://www.faqs.org/rfcs/rfc2822") format. * type is `'substition'`. We are substituting a time stamp for the `[NOW]` token, similar to the way smileys and acronyms are handled. They belong to the mode type `'substition'` so we will too. * allowedTypes are not required, no other DokuWiki syntax can occur within our `[NOW]` syntax. Therefore we don't need the `getAllowedTypes()` method. * PType is `normal`, that's the default value, so we don't need the `getPType()` method. * there is no need for an entry and exit pattern, just a special pattern to detect `[NOW]`. The only thing we need to be careful of is “\[” and “\]” have special meanings in regular expressions, so we will need to _escape_ them, making our pattern - `'\[NOW\]'`. * in this case the `handler()` method doesn't need to do anything. We have no special states to take care of or extra parameters in our syntax. We just return an empty array to ensure a render instruction for our plugin is stored. * all the `render()` method needs to do is add the time stamp to the current wiki page — `$renderer->doc .= date('r');` And that's our plugin finished. [syntax.php](https://www.dokuwiki.org/_export/code/devel:syntax_plugins?codeblock=10 "Download Snippet") \*/   // must be run within DokuWiki if(![defined](http://www.php.net/defined) ('DOKU\_INC')) [die](http://www.php.net/die) ();   /\*\* \* All DokuWiki plugins to extend the parser/rendering mechanism \* need to inherit from this class \*/ class syntax\_plugin\_now extends DokuWiki\_Syntax\_Plugin {   public function [getType](http://www.php.net/gettype) () { return 'substition'; } public function getSort() { return 32; }   public function connectTo($mode) { $this\->Lexer\->addSpecialPattern('\\\[NOW\\\]',$mode,'plugin\_now'); }   public function handle($match, $state, $pos, Doku\_Handler $handler) { return [array](http://www.php.net/array) ($match, $state, $pos); }   public function render($format, Doku\_Renderer $renderer, $data) { // $data is what the function handle return'ed. if($format \== 'xhtml'){ /\*\* @var Doku\_Renderer\_xhtml $renderer \*/ $renderer\->doc .= [date](http://www.php.net/date) ('r'); return true; } return false; } } You also need the plugin.info.txt file: [plugin.info.txt](https://www.dokuwiki.org/_export/code/devel:syntax_plugins?codeblock=11 "Download Snippet") base now author me email me@someplace.com date 2005-07-28 name Now Plugin desc Include the current date and time url https://www.dokuwiki.org/devel:syntax\_plugins Note: due to the way DokuWiki caches pages this plugin will report the date/time at which the cached version was created. You would need to add `~~NOCACHE~~` to the page to ensure the date was current every time the page was requested. Edit Sample Plugin 2 - Color ----------------------- When its syntax, ``, is encountered in a wiki page the text colour will be changed to somecolour, the background will be changed to somebackgroundcolour and both will remain that way until `` is encountered. * what we are doing is similar to the strong mode, its type is 'formatting' so we should use that type too. * allowedTypes should be the inline modes - `substition`, `formatting` & `disabled`. * PType is `normal`, that's the default value, so again we don't need a `getPType()` method. * we need to use an entry and exit pattern. The entry pattern should check to make sure there is an exit pattern, which means `'(?=.*?)'`. The exit pattern is simpler, ``. * the `handle()` method will need to deal with three states matching our entry and exit patterns and unmatched for the text which occurs between them. * `DOKU_LEXER_ENTER` state requires some processing to extract the colour and background colour values, they make up our render instruction. * `DOKU_LEXER_UNMATCHED` state doesn't require any processing, but we have to pass the unmatched text (in `$match`) to `render()` so that goes into our render instruction. * `DOKU_LEXER_EXIT` state doesn't require any processing or have any special data, we simply need to generate an exit instruction for `render()`. * the `render()` method will need to deal with the same three states as `handle()`. * `DOKU_LEXER_ENTER`, open a span with a style using the colour and/or background colour values. * `DOKU_LEXER_UNMATCHED`, add the unmatched text to the output document. * `DOKU_LEXER_EXIT`, close the span Put the file syntax.php from below into a folder named “color” directly below your plugins folder, e.g. /srv/www/htdocs/dokuwiki/lib/plugins. If you do not name this folder “color”, the plugin will not work: [syntax.php](https://www.dokuwiki.org/_export/code/devel:syntax_plugins?codeblock=12 "Download Snippet") \*/   // must be run within Dokuwiki if(![defined](http://www.php.net/defined) ('DOKU\_INC')) [die](http://www.php.net/die) ();   /\*\* \* All DokuWiki plugins to extend the parser/rendering mechanism \* need to inherit from this class \*/ class syntax\_plugin\_color extends DokuWiki\_Syntax\_Plugin {   public function [getType](http://www.php.net/gettype) (){ return 'formatting'; } public function getAllowedTypes() { return [array](http://www.php.net/array) ('formatting', 'substition', 'disabled'); } public function getSort(){ return 158; } public function connectTo($mode) { $this\->Lexer\->addEntryPattern('(?=.\*?)',$mode,'plugin\_color'); } public function postConnect() { $this\->Lexer\->addExitPattern('','plugin\_color'); }     /\*\* \* Handle the match \*/ public function handle($match, $state, $pos, Doku\_Handler $handler){ switch ($state) { case DOKU\_LEXER\_ENTER : [list](http://www.php.net/list) ($color, $background) \= [preg\_split](http://www.php.net/preg_split) ("/\\//u", [substr](http://www.php.net/substr) ($match, 6, \-1), 2); if ($color \= $this\->\_isValid($color)) $color \= "color:$color;"; if ($background \= $this\->\_isValid($background)) $background \= "background-color:$background;"; return [array](http://www.php.net/array) ($state, [array](http://www.php.net/array) ($color, $background));   case DOKU\_LEXER\_UNMATCHED : return [array](http://www.php.net/array) ($state, $match); case DOKU\_LEXER\_EXIT : return [array](http://www.php.net/array) ($state, ''); } return [array](http://www.php.net/array) (); }   /\*\* \* Create output \*/ public function render($format, Doku\_Renderer $renderer, $data) { // $data is what the function handle() return'ed. if($format \== 'xhtml'){ /\*\* @var Doku\_Renderer\_xhtml $renderer \*/ [list](http://www.php.net/list) ($state,$match) \= $data; switch ($state) { case DOKU\_LEXER\_ENTER : [list](http://www.php.net/list) ($color, $background) \= $match; $renderer\->doc .= ""; break;   case DOKU\_LEXER\_UNMATCHED : $renderer\->doc .= $renderer\->\_xmlEntities($match); break; case DOKU\_LEXER\_EXIT : $renderer\->doc .= ""; break; } return true; } return false; }   /\*\* \* Validate color value $c \* this is cut price validation - only to ensure the basic format is correct and there is nothing harmful \* three basic formats "colorname", "#fff\[fff\]", "rgb(255\[%\],255\[%\],255\[%\])" \*/ private function \_isValid($c) { $c \= [trim](http://www.php.net/trim) ($c);   $pattern \= "/^\\s\*( (\[a-zA-z\]+)| #colorname - not verified (\\#(\[0-9a-fA-F\]{3}|\[0-9a-fA-F\]{6}))| #colorvalue (rgb\\((\[0-9\]{1,3}%?,){2}\[0-9\]{1,3}%?\\)) #rgb triplet )\\s\*$/x";   if ([preg\_match](http://www.php.net/preg_match) ($pattern, $c)) return [trim](http://www.php.net/trim) ($c);   return ""; } } Note: No checking is done to ensure colour names are valid or RGB values are within correct ranges. Edit Unit Testing Syntax Plugins --------------------------- For a general introduction about Unit Testing in DokuWiki please see [unittesting](https://www.dokuwiki.org/devel:unittesting "devel:unittesting") . For a syntax plugin a common test goal will be to ensure that a certain wiki code produces the expected XHTML code or other destination language code. The following example function shows a simple way to do this: public function test\_superscript() { $info \= \[\]; $expected \= "\\n

\\nThis is superscripted text.
\\n

\\n";   $instructions \= p\_get\_instructions('This is ^^superscripted^^ text.'); $xhtml \= p\_render('xhtml', $instructions, $info);   $this\->assertEquals($expected, $xhtml); } Here we strongly benefit from DokuWiki's good design. The two function calls to `p_get_instructions()` and `p_render()` are enough to render the example code `//'This is ^^superscripted^^ text.'//` and store the result in the variable **$xhtml**. Finally we only need a simple assert to check if the result is what we **$expected**. Edit [1)](https://www.dokuwiki.org/devel:syntax_plugins#fnt__1) defined in `lib/Extension/SyntaxPlugin.php`, before called `DokuWiki_Syntax_Plugin` which is still available as alias [2)](https://www.dokuwiki.org/devel:syntax_plugins#fnt__2) defined in `inc/Parsing/ParserMode/AbstractMode.php`, inherited via dokuwiki\\Parsing\\ParserMode\\Plugin [3)](https://www.dokuwiki.org/devel:syntax_plugins#fnt__3) See `Doku_Handler_Block` [4)](https://www.dokuwiki.org/devel:syntax_plugins#fnt__4) defined in `inc/Parsing/ParserMode/AbstractMode.php` [5)](https://www.dokuwiki.org/devel:syntax_plugins#fnt__5) Yes this is spelled wrong, but we won't change it to avoid breaking existing plugins. Sometimes a typo becomes a standard - see the HTTP “referer” header for an example [6)](https://www.dokuwiki.org/devel:syntax_plugins#fnt__6) This is actually a class, it does not mean “end of life”, but “end of line”. [7)](https://www.dokuwiki.org/devel:syntax_plugins#fnt__7) the part of the parser which analyses the raw wiki page [8)](https://www.dokuwiki.org/devel:syntax_plugins#fnt__8) perl compatible regular expressions ref: [www.php.net/manual/en/ref.pcre.php](http://www.php.net/manual/en/ref.pcre.php "http://www.php.net/manual/en/ref.pcre.php") [9)](https://www.dokuwiki.org/devel:syntax_plugins#fnt__9) The special mode `metadata` does not output anything but collects metadata for the page. Plugin can add other formats such as the ODT format. Use it to insert values into the metadata array. See the translation plugin for an example. [10)](https://www.dokuwiki.org/devel:syntax_plugins#fnt__10) The name may not contain underscores and needs to match your class name devel/syntax\_plugins.txt · Last modified: 2023-09-01 23:53 by Klap-in * * * ![](https://www.dokuwiki.org/lib/exe/taskrunner.php?id=devel%3Asyntax_plugins&1752069250) --- # cs:devel:syntax_plugins [DokuWiki] cs:devel:syntax\_plugins Stránka s tímto názvem ještě neexistuje ======================================= Odkaz vás zavedl na stránku, která ještě neexistuje. Můžete ji vytvořit stisknutím tlačítka **Vytvořit stránku**. * * * ![](https://www.dokuwiki.org/lib/exe/taskrunner.php?id=cs%3Adevel%3Asyntax_plugins&1752069263) --- # ca:devel:syntax_plugins [DokuWiki] ca:devel:syntax\_plugins Aquest tema encara no existeix ============================== Heu seguit un enllaç a un tema que encara no existeix. Podeu crear-lo per mitjà del botó **Crea aquesta pàgina**. * * * ![](https://www.dokuwiki.org/lib/exe/taskrunner.php?id=ca%3Adevel%3Asyntax_plugins&1752069263) --- # da:devel:syntax_plugins [DokuWiki] da:devel:syntax\_plugins Dette dokument eksisterer ikke (endnu) ====================================== Du har fulgt en henvisning til et dokument der ikke eksisterer (endnu). Du kan oprette dokumentet ved at trykke på knappen **Opret dette dokument**. * * * ![](https://www.dokuwiki.org/lib/exe/taskrunner.php?id=da%3Adevel%3Asyntax_plugins&1752069263) --- # es:devel:syntax_plugins [DokuWiki] es:devel:syntax\_plugins Esta página ya no está disponible ================================= Has seguido un enlace a una página que ya no está disponible. Se puede averiguar el listado de **revisiones antiguas** para comprobar cuando y por qué ha sido borrada, acceder a revisiones antiguas, o restaurarla. * * * ![](https://www.dokuwiki.org/lib/exe/taskrunner.php?id=es%3Adevel%3Asyntax_plugins&1752069263) --- # eo:devel:syntax_plugins [DokuWiki] eo:devel:syntax\_plugins Ĉi tiu paĝo ankoraŭ ne ekzistas =============================== Vi sekvis ligilon, kiu kondukas al artikolo ankoraŭ ne ekzistanta. Se vi rajtas, tiam vi povas krei tiun ĉi paĝon premante la butonon **Krei paĝon**. * * * ![](https://www.dokuwiki.org/lib/exe/taskrunner.php?id=eo%3Adevel%3Asyntax_plugins&1752069263) --- # de:devel:syntax_plugins [DokuWiki] de:devel:syntax\_plugins Dieses Thema existiert noch nicht ================================= Sie sind einem Link zu einer Seite gefolgt, die noch nicht existiert. Sie können die Seite mit dem Knopf **Seite anlegen** selbst anlegen und mit Inhalt füllen. * * * ![](https://www.dokuwiki.org/lib/exe/taskrunner.php?id=de%3Adevel%3Asyntax_plugins&1752069263) --- # devel:syntax_plugins [DokuWiki] devel:syntax\_plugins Media Manager ============= Namespaces ---------- Choose namespace * ![−](https://www.dokuwiki.org/lib/images/minus.gif) [\[root\]](https://www.dokuwiki.org/devel:syntax_plugins?ns=&tab_files=files&do=media) * ![+](https://www.dokuwiki.org/lib/images/plus.gif) [anonymous](https://www.dokuwiki.org/devel:syntax_plugins?ns=anonymous&tab_files=files&do=media) * ![+](https://www.dokuwiki.org/lib/images/plus.gif) [auth](https://www.dokuwiki.org/devel:syntax_plugins?ns=auth&tab_files=files&do=media) * ![+](https://www.dokuwiki.org/lib/images/plus.gif) [config](https://www.dokuwiki.org/devel:syntax_plugins?ns=config&tab_files=files&do=media) * ![−](https://www.dokuwiki.org/lib/images/minus.gif) [devel](https://www.dokuwiki.org/devel:syntax_plugins?ns=devel&tab_files=files&do=media) * ![+](https://www.dokuwiki.org/lib/images/plus.gif) [hackfest](https://www.dokuwiki.org/devel:syntax_plugins?ns=devel%3Ahackfest&tab_files=files&do=media) * ![+](https://www.dokuwiki.org/lib/images/plus.gif) [ideas](https://www.dokuwiki.org/devel:syntax_plugins?ns=devel%3Aideas&tab_files=files&do=media) * ![+](https://www.dokuwiki.org/lib/images/plus.gif) [logouse](https://www.dokuwiki.org/devel:syntax_plugins?ns=devel%3Alogouse&tab_files=files&do=media) * ![+](https://www.dokuwiki.org/lib/images/plus.gif) [plugin\_survey](https://www.dokuwiki.org/devel:syntax_plugins?ns=devel%3Aplugin_survey&tab_files=files&do=media) * ![+](https://www.dokuwiki.org/lib/images/plus.gif) [dokuinstall](https://www.dokuwiki.org/devel:syntax_plugins?ns=dokuinstall&tab_files=files&do=media) * ![+](https://www.dokuwiki.org/lib/images/plus.gif) [example](https://www.dokuwiki.org/devel:syntax_plugins?ns=example&tab_files=files&do=media) * ![+](https://www.dokuwiki.org/lib/images/plus.gif) [hoster](https://www.dokuwiki.org/devel:syntax_plugins?ns=hoster&tab_files=files&do=media) * ![+](https://www.dokuwiki.org/lib/images/plus.gif) [marketing](https://www.dokuwiki.org/devel:syntax_plugins?ns=marketing&tab_files=files&do=media) * ![+](https://www.dokuwiki.org/lib/images/plus.gif) [multi](https://www.dokuwiki.org/devel:syntax_plugins?ns=multi&tab_files=files&do=media) * ![+](https://www.dokuwiki.org/lib/images/plus.gif) [newsletter](https://www.dokuwiki.org/devel:syntax_plugins?ns=newsletter&tab_files=files&do=media) * ![+](https://www.dokuwiki.org/lib/images/plus.gif) [plugin](https://www.dokuwiki.org/devel:syntax_plugins?ns=plugin&tab_files=files&do=media) * ![+](https://www.dokuwiki.org/lib/images/plus.gif) [social](https://www.dokuwiki.org/devel:syntax_plugins?ns=social&tab_files=files&do=media) * ![+](https://www.dokuwiki.org/lib/images/plus.gif) [template](https://www.dokuwiki.org/devel:syntax_plugins?ns=template&tab_files=files&do=media) * ![+](https://www.dokuwiki.org/lib/images/plus.gif) [tips](https://www.dokuwiki.org/devel:syntax_plugins?ns=tips&tab_files=files&do=media) * ![+](https://www.dokuwiki.org/lib/images/plus.gif) [wiki](https://www.dokuwiki.org/devel:syntax_plugins?ns=wiki&tab_files=files&do=media) Media Files ----------- * **Media Files** * [Upload](https://www.dokuwiki.org/devel:syntax_plugins?tab_files=upload&do=media&ns=devel) * [Search](https://www.dokuwiki.org/devel:syntax_plugins?tab_files=search&do=media&ns=devel) ### Files in **devel** * Thumbnails Rows * Name Date * Apply * [![callgraph.png](https://www.dokuwiki.org/_media/devel:callgraph.png?w=90&h=90&tok=92fa18)](https://www.dokuwiki.org/devel:syntax_plugins?image=devel%3Acallgraph.png&ns=devel&tab_details=view&do=media) [callgraph.png](https://www.dokuwiki.org/devel:syntax_plugins?image=devel%3Acallgraph.png&ns=devel&tab_details=view&do=media) 2660×3686 2008-12-16 23:52 268 KB * [![idea-newproject.png](https://www.dokuwiki.org/_media/devel:idea-newproject.png?w=90&h=90&tok=8b41df)](https://www.dokuwiki.org/devel:syntax_plugins?image=devel%3Aidea-newproject.png&ns=devel&tab_details=view&do=media) [idea-newproject.png](https://www.dokuwiki.org/devel:syntax_plugins?image=devel%3Aidea-newproject.png&ns=devel&tab_details=view&do=media) 883×557 2012-06-24 21:13 93.2 KB * [![idea-runconfig.png](https://www.dokuwiki.org/_media/devel:idea-runconfig.png?w=90&h=90&tok=5bb041)](https://www.dokuwiki.org/devel:syntax_plugins?image=devel%3Aidea-runconfig.png&ns=devel&tab_details=view&do=media) [idea-runconfig.png](https://www.dokuwiki.org/devel:syntax_plugins?image=devel%3Aidea-runconfig.png&ns=devel&tab_details=view&do=media) 866×466 2012-06-24 21:16 45.1 KB * [![ideadirectories.png](https://www.dokuwiki.org/_media/devel:ideadirectories.png?w=90&h=90&tok=8c549c)](https://www.dokuwiki.org/devel:syntax_plugins?image=devel%3Aideadirectories.png&ns=devel&tab_details=view&do=media) [ideadirectories.png](https://www.dokuwiki.org/devel:syntax_plugins?image=devel%3Aideadirectories.png&ns=devel&tab_details=view&do=media) 1024×815 2022-10-27 18:56 103.5 KB File ---- devel/syntax\_plugins.txt · Last modified: 2023-09-01 23:53 by Klap-in * * * ![](https://www.dokuwiki.org/lib/exe/taskrunner.php?id=devel%3Asyntax_plugins&1752069263) --- # devel:syntax_plugins - Recent Changes [DokuWiki] devel:syntax\_plugins Recent Changes ============== The following pages were changed recently: You're currently watching the changes inside the **devel** namespace. You can also [view the recent changes of the whole wiki](https://www.dokuwiki.org/start?do=recent) . View changes of PagesMedia filesBoth pages and media files Apply * ![devel:badextensions](https://www.dokuwiki.org/lib/images/fileicons/file.png) 2025-07-09 02:27 [![Show differences to current revisions](https://www.dokuwiki.org/lib/images/diff.png "Show differences to current revisions")](https://www.dokuwiki.org/devel:badextensions?do=diff) [![Old revisions](https://www.dokuwiki.org/lib/images/history.png "Old revisions")](https://www.dokuwiki.org/devel:badextensions?do=revisions) [devel:badextensions](https://www.dokuwiki.org/devel:badextensions) – auto update 0.0.0.0 +187 B * ![devel:svg](https://www.dokuwiki.org/lib/images/fileicons/file.png) 2025-07-07 23:44 [![Show differences to current revisions](https://www.dokuwiki.org/lib/images/diff.png "Show differences to current revisions")](https://www.dokuwiki.org/devel:svg?do=diff) [![Old revisions](https://www.dokuwiki.org/lib/images/history.png "Old revisions")](https://www.dokuwiki.org/devel:svg?do=revisions) [devel:svg](https://www.dokuwiki.org/devel:svg) – \[Embedded SVG\] Spelling correction Restless \-1 B * ![devel:debugging](https://www.dokuwiki.org/lib/images/fileicons/file.png) 2025-07-05 21:50 [![Show differences to current revisions](https://www.dokuwiki.org/lib/images/diff.png "Show differences to current revisions")](https://www.dokuwiki.org/devel:debugging?do=diff) [![Old revisions](https://www.dokuwiki.org/lib/images/history.png "Old revisions")](https://www.dokuwiki.org/devel:debugging?do=revisions) [devel:debugging](https://www.dokuwiki.org/devel:debugging) – Klap-in \-36 B * ![devel:releases:refactor2021](https://www.dokuwiki.org/lib/images/fileicons/file.png) 2025-07-05 21:44 [![Show differences to current revisions](https://www.dokuwiki.org/lib/images/diff.png "Show differences to current revisions")](https://www.dokuwiki.org/devel:releases:refactor2021?do=diff) [![Old revisions](https://www.dokuwiki.org/lib/images/history.png "Old revisions")](https://www.dokuwiki.org/devel:releases:refactor2021?do=revisions) [devel:releases:refactor2021](https://www.dokuwiki.org/devel:releases:refactor2021) – \[Logging\] Klap-in +54 B * ![devel:releases:refactor2024](https://www.dokuwiki.org/lib/images/fileicons/file.png) 2025-07-04 16:35 [![Show differences to current revisions](https://www.dokuwiki.org/lib/images/diff.png "Show differences to current revisions")](https://www.dokuwiki.org/devel:releases:refactor2024?do=diff) [![Old revisions](https://www.dokuwiki.org/lib/images/history.png "Old revisions")](https://www.dokuwiki.org/devel:releases:refactor2024?do=revisions) [devel:releases:refactor2024](https://www.dokuwiki.org/devel:releases:refactor2024) – Klap-in +885 B * ![devel:releases:refactor2023](https://www.dokuwiki.org/lib/images/fileicons/file.png) 2025-07-04 15:19 [![Show differences to current revisions](https://www.dokuwiki.org/lib/images/diff.png "Show differences to current revisions")](https://www.dokuwiki.org/devel:releases:refactor2023?do=diff) [![Old revisions](https://www.dokuwiki.org/lib/images/history.png "Old revisions")](https://www.dokuwiki.org/devel:releases:refactor2023?do=revisions) [devel:releases:refactor2023](https://www.dokuwiki.org/devel:releases:refactor2023) – \[Fixed size logo\] Klap-in ±0 B * ![devel:releases](https://www.dokuwiki.org/lib/images/fileicons/file.png) 2025-07-03 15:46 [![Show differences to current revisions](https://www.dokuwiki.org/lib/images/diff.png "Show differences to current revisions")](https://www.dokuwiki.org/devel:releases?do=diff) [![Old revisions](https://www.dokuwiki.org/lib/images/history.png "Old revisions")](https://www.dokuwiki.org/devel:releases?do=revisions) [devel:releases](https://www.dokuwiki.org/devel:releases) – more about remote api refactor Klap-in +219 B * ![devel:deprecated](https://www.dokuwiki.org/lib/images/fileicons/file.png) 2025-06-30 15:38 [![Show differences to current revisions](https://www.dokuwiki.org/lib/images/diff.png "Show differences to current revisions")](https://www.dokuwiki.org/devel:deprecated?do=diff) [![Old revisions](https://www.dokuwiki.org/lib/images/history.png "Old revisions")](https://www.dokuwiki.org/devel:deprecated?do=revisions) [devel:deprecated](https://www.dokuwiki.org/devel:deprecated) – Klap-in +11 B * ![devel:releases:refactor2022](https://www.dokuwiki.org/lib/images/fileicons/file.png) 2025-06-30 15:03 [![Show differences to current revisions](https://www.dokuwiki.org/lib/images/diff.png "Show differences to current revisions")](https://www.dokuwiki.org/devel:releases:refactor2022?do=diff) [![Old revisions](https://www.dokuwiki.org/lib/images/history.png "Old revisions")](https://www.dokuwiki.org/devel:releases:refactor2022?do=revisions) [devel:releases:refactor2022](https://www.dokuwiki.org/devel:releases:refactor2022) – Klap-in \-36 B * ![devel:css](https://www.dokuwiki.org/lib/images/fileicons/file.png) 2025-06-30 13:46 [![Show differences to current revisions](https://www.dokuwiki.org/lib/images/diff.png "Show differences to current revisions")](https://www.dokuwiki.org/devel:css?do=diff) [![Old revisions](https://www.dokuwiki.org/lib/images/history.png "Old revisions")](https://www.dokuwiki.org/devel:css?do=revisions) [devel:css](https://www.dokuwiki.org/devel:css) – old revision restored (2021-02-03 23:47) Google Fonts information is wrong nfriedli \-479 B * ![devel:releases:refactor2025](https://www.dokuwiki.org/lib/images/fileicons/file.png) 2025-06-27 15:11 ![](https://www.dokuwiki.org/lib/images/blank.gif) [![Old revisions](https://www.dokuwiki.org/lib/images/history.png "Old revisions")](https://www.dokuwiki.org/devel:releases:refactor2025?do=revisions) [devel:releases:refactor2025](https://www.dokuwiki.org/devel:releases:refactor2025) – created Klap-in +1.6 KB * ![devel:releases:refactor_2025](https://www.dokuwiki.org/lib/images/fileicons/file.png) 2025-06-27 15:10 [![Show differences to current revisions](https://www.dokuwiki.org/lib/images/diff.png "Show differences to current revisions")](https://www.dokuwiki.org/devel:releases:refactor_2025?do=diff) [![Old revisions](https://www.dokuwiki.org/lib/images/history.png "Old revisions")](https://www.dokuwiki.org/devel:releases:refactor_2025?do=revisions) [devel:releases:refactor\_2025](https://www.dokuwiki.org/devel:releases:refactor_2025) – removed Klap-in \-1.6 KB * ![devel:releases:refactor_2024](https://www.dokuwiki.org/lib/images/fileicons/file.png) 2025-06-27 15:10 [![Show differences to current revisions](https://www.dokuwiki.org/lib/images/diff.png "Show differences to current revisions")](https://www.dokuwiki.org/devel:releases:refactor_2024?do=diff) [![Old revisions](https://www.dokuwiki.org/lib/images/history.png "Old revisions")](https://www.dokuwiki.org/devel:releases:refactor_2024?do=revisions) [devel:releases:refactor\_2024](https://www.dokuwiki.org/devel:releases:refactor_2024) – removed Klap-in \-1.6 KB * ![devel:patreonblog](https://www.dokuwiki.org/lib/images/fileicons/file.png) 2025-05-21 10:18 [![Show differences to current revisions](https://www.dokuwiki.org/lib/images/diff.png "Show differences to current revisions")](https://www.dokuwiki.org/devel:patreonblog?do=diff) [![Old revisions](https://www.dokuwiki.org/lib/images/history.png "Old revisions")](https://www.dokuwiki.org/devel:patreonblog?do=revisions) [devel:patreonblog](https://www.dokuwiki.org/devel:patreonblog) – \[Part VII\] Michaelsy +15 B * ![devel:javascript](https://www.dokuwiki.org/lib/images/fileicons/file.png) 2025-05-15 11:11 [![Show differences to current revisions](https://www.dokuwiki.org/lib/images/diff.png "Show differences to current revisions")](https://www.dokuwiki.org/devel:javascript?do=diff) [![Old revisions](https://www.dokuwiki.org/lib/images/history.png "Old revisions")](https://www.dokuwiki.org/devel:javascript?do=revisions) [devel:javascript](https://www.dokuwiki.org/devel:javascript) – andi \-22 B * ![devel:authentication](https://www.dokuwiki.org/lib/images/fileicons/file.png) 2025-05-15 11:09 [![Show differences to current revisions](https://www.dokuwiki.org/lib/images/diff.png "Show differences to current revisions")](https://www.dokuwiki.org/devel:authentication?do=diff) [![Old revisions](https://www.dokuwiki.org/lib/images/history.png "Old revisions")](https://www.dokuwiki.org/devel:authentication?do=revisions) [devel:authentication](https://www.dokuwiki.org/devel:authentication) – andi \-17 B devel/syntax\_plugins.txt · Last modified: 2023-09-01 23:53 by Klap-in * * * ![](https://www.dokuwiki.org/lib/exe/taskrunner.php?id=devel%3Asyntax_plugins&1752069263) --- # localization [DokuWiki] localization ### Table of Contents * [Localizing DokuWiki (the Software)](https://www.dokuwiki.org/localization#localizing_dokuwiki_the_software) * [Localizing DokuWiki and its plugins and templates](https://www.dokuwiki.org/localization#localizing_dokuwiki_and_its_plugins_and_templates) * [Howto add a new language](https://www.dokuwiki.org/localization#howto_add_a_new_language) * [Directions for consistent translations](https://www.dokuwiki.org/localization#directions_for_consistent_translations) * [Plugins](https://www.dokuwiki.org/localization#plugins) * [Changing some localized texts and strings in your installation](https://www.dokuwiki.org/localization#changing_some_localized_texts_and_strings_in_your_installation) * [Translating DokuWiki.org (the documentation)](https://www.dokuwiki.org/localization#translating_dokuwikiorg_the_documentation) * [Translation Guidelines](https://www.dokuwiki.org/localization#translation_guidelines) * [Disabling translation feature for certain pages](https://www.dokuwiki.org/localization#disabling_translation_feature_for_certain_pages) * [See also](https://www.dokuwiki.org/localization#see_also) Localizing DokuWiki (the Software) ================================== [DokuWiki](https://www.dokuwiki.org/dokuwiki "dokuwiki") 's user interface can be configured to use any language by setting the appropriate option in the [config](https://www.dokuwiki.org/config:lang "config:lang") . You can help translating DokuWiki to your language by visiting the [DokuWiki Localization Hub](https://translate.dokuwiki.org/ "https://translate.dokuwiki.org/") . We recommend to join the [I18N Mailing List](https://www.dokuwiki.org/mailinglist#i18n_mailing_list "mailinglist") to be informed when new strings are added and need to be translated. Edit Localizing DokuWiki and its plugins and templates ------------------------------------------------- Most of DokuWiki and its plugins and templates only provide localization for English and some other languages. We encourage you to translate them into your native language. Important things to keep in mind when translating: * Please try to **complete your countries main official language** before starting another dialect. * If you do major translation work it is recommended to check your translations in the [development snapshot](https://download.dokuwiki.org/ "https://download.dokuwiki.org/") . This gives you the opportunity to correct errors and verify the layout in your language. * In some languages words and sentences tend to get longer than the original English words. Keep in mind that **your translation needs to work on any screen size** and it often looks better if **words are in line with other items on the page**. * When translating technical descriptions of external origin like the API's delivered by Github, Twitter, Google etc please **read the external manual first**. This is especially important for translating interfaces. Maybe a localized version of the manual or helppages is already at the external source and you can use all or part of these. * As DokuWiki wants to be **standards-compliant**, consider learning about these regarding your language first. You can learn about correct spelling and interpunction from dictionaries or webpages maintained by public institutions. * Always **keep the format strings intact**, i.e. identical. Strings like these `%1$d` and `%s` and `Update:`. The word `Update:` should be translated but the word `` **not**. Edit ### Howto add a new language To prevent spam, [https://translate.dokuwiki.org/](https://translate.dokuwiki.org/ "https://translate.dokuwiki.org/") only has languages which exist in the source code DokuWiki. To initiate a new language you can send a pull request with some translated lines or if you do not program you can open an issue in our Bug tracker. Please use ISO 639-1 (2-letter) and ISO 639-3 (3-letter) language code format, see… When accepted the language becomes available for easier translation via the translation tool. Edit ### Directions for consistent translations At the [consistent translations](https://www.dokuwiki.org/teams:i18n:consistenttranslations "teams:i18n:consistenttranslations") page you can find: * some preferred translations for regularly used words * and how to handle placeholder order in non-english strings. Edit ### Plugins Plugin authors can register their plugin at [https://translate.dokuwiki.org/](https://translate.dokuwiki.org/ "https://translate.dokuwiki.org/") where you can easily help to translate the plugin. If a plugin is not translatable via the translation tool you can do it manually: * Copy the content of `lib/plugins//lang/en/` to `lib/plugins//lang//` * Edit the contained `.php` and `.txt` files in a [UTF-8 capable](https://www.dokuwiki.org/utf-8 "utf-8") text editor * Zip up the new language folder and send it to the author for inclusion in future releases For any further questions or general help you could send a mail to the [I18N-Mailinglist](https://www.dokuwiki.org/mailinglist#i18n_mailing_list "mailinglist") or ask for help in the [IRC-Channel](https://www.dokuwiki.org/irc "irc") . Edit Changing some localized texts and strings in your installation -------------------------------------------------------------- There are many localized texts in DokuWiki like emails that are sent on registration, password forgotten, the text above the edit form, and more. Also the strings used in the buttons and links are translated. You can modify these by creating custom files with your version of the texts. This way your changes aren't overwritten on upgrades. You can change these texts by copying the `.txt` files or copying some strings from `lang.php`: * from `inc/lang/<[ISO 639-1](https://www.loc.gov/standards/iso639-2/php/English_list.php "https://www.loc.gov/standards/iso639-2/php/English_list.php") -lang-code>/` * to `**conf/lang/**/` and editing the copied content. You can do the same thing for plugins and templates by copying `.txt` or some strings from `lang.php`: * from `lib/plugins//lang//` * to `**conf/plugin_lang/**//` * from `lib/tpl/