# banana-checker

> Checker for the 'Banana' JSON-file format for interface messages, as used by MediaWiki and jQuery.i18n.

By default, Banana checker asserts the following:

* The source and documentation files must exist and contain valid JSON.
* Both files include a `@metadata` object.
* Each defined source message is documented.
* Each defined documentation entry has a matching source message.

For all available options, see the [**Options** section](#options).

You can use Banana checker [standalone](#command-line-interface) or as a [Grunt plugin](#getting-started-grunt-plugin).

## Getting started (Grunt plugin)

To use this plugin, add it as a development dependency to your project:

<pre lang=shell>
npm install grunt-banana-checker --save-dev
</pre>

Ensure your project has a Gruntfile.js file ([example file](http://gruntjs.com/sample-gruntfile)). Then, in Gruntfile.js, add the line:

<pre lang=js>
grunt.loadNpmTasks( 'grunt-banana-checker' );
</pre>

### Configure the Grunt plugin

In Gruntfile.js, add a configuration key for `banana` and set it to an empty object.

We will use this object to declare which directory contains the interface messages. For example, to enable grunt-banana-checker for a single directory only, configure it like so:

<pre lang=js>
grunt.initConfig( {
	banana: {
	    all: 'i18n/'
	}
} );
</pre>

You can also configure multiple directories, like so:

<pre lang=js>
grunt.initConfig( {
	banana: {
	    core: 'languages/i18n/',
	    installer: 'includes/installer/i18n/'
	}
} );
</pre>

You can also use globbing patterns and/or arrays of directories, like so:

<pre lang=js>
grunt.initConfig( {
	banana: {
	    all: 'modules/ve-{mw,wmf}/i18n/'
	}
} );
</pre>

For a full list of supported ways of defining the target directory of a Grunt plugin, see [Configuring tasks](https://gruntjs.com/configuring-tasks) on gruntjs.com.

[See the **Options** sections](#Options) for create a config file.

Config can also be set in Grunt by defining your target directory as an object instead of a string, with `src` and `options` properties, like so:

<pre lang=js>
grunt.initConfig( {
	banana: {
		all: {
			src: 'i18n/',
			options: {
				sourceFile: 'messages.json',
				documentationFile: 'documentation.json'
			}
		}
	}
} );
</pre>

For all available options, see the [**Options** section](#Options).

## Command-line

The Banana checker also offers a command-line interface.

<pre lang=shell>
npm install grunt-banana-checker --save-dev
</pre>

To use Banana checker as part of your test run, refer to the `banana-checker`
program from the `scripts.test` property in your `package.json` file.

<pre lang=js>
{
	"scripts": {
		"test": "banana-checker i18n/"
	}
}
</pre>

Options can be set in the config file, or overridden as `--key=value` pairs. For example:

<pre lang=shell>
npx banana-checker --requireKeyPrefix="x-" i18n/
</pre>

* For boolean options, use the valus `0`, `1`, `true`, or `false`.
* Quotes are allowed, but not required.
* For options that allow multiple values, separate values by comma. Like `--key=one,two`.

## Options

Create a `.bananaconfig.[json|js]` file (or `bananaconfig.[json|js]`):

<pre lang=json>
{
	"sourceFile": "messages.json",
	"documentationFile": "documentation.json"
}
</pre>

Available options are:

#### autofix
Type: `boolean`
Default value: `false`

If enabled, try to automatically fix issues in en/qqq.json detected by some checks.

Note that autofixing will not affect the check result - the checker will fail
even if all errors were automatically fixed.

#### autofixTranslated
Type: `boolean`
Default value: `false`

Same as `autofix` but for translated messages.

#### sourceFile
Type: `string`
Default value: `"en.json"`

The JSON file providing the primary messages.

#### documentationFile
Type: `string`
Default value: `"qqq.json"`

The JSON file providing the documentation messages.

### Rules

Rule options can be set to `"off"`, `"warn"` or `"error"`. When additional options are available an array
tuple should be created, e.g. `[ "error", { "initial: true } ]`.

#### requireMetadata
Default value: `"error"`

Whether to fail if message files don't have a `@metadata` meta-data key.

#### requireCompleteMessageDocumentation
Default value: `"error"`
Additional option: `skip` (type `string[]`) Keys to skip

Whether to fail if any message is in the primary file but not documented.

#### disallowEmptyDocumentation
Default value: `"error"`

Whether to fail if any message is in the primary file but documented as a blank string.

#### requireLowerCase
Default value: `"error"`
Additional option: `initial` (type `boolean`, default `false`)

Whether to fail if any message key is not lower case. If the `"initial"` option is set,
fail only if the first character is not lower case.

#### requireKeyPrefix
Default value: `"off"`
Additional option: `prefix` (type `string` or `string[]`)

Whether to fail if any message key is not prefixed by the given prefix, or if multiple, one of the
given prefixes.

#### disallowUnusedDocumentation
Default value: `"error"`

Whether to fail if any documented message isn't in the primary file.

#### disallowBlankTranslations
Default value: `"warn"`

Whether to warn if any message is translated as a blank string.

#### disallowDuplicateTranslations
Default value: `"off"`

Whether to fail if any message is translated as identical to the original string.

#### disallowUnusedTranslations
Default value: `"off"`

Whether to fail if any translated message isn't in the primary file.

#### requireCompletelyUsedParameters
Default value: `"off"`

Whether to fail if any translated message fails to use a parameter used in the primary message.

#### requireCompleteTranslationLanguages
Default value: `"off"`
Additional option: `langs` (type `string[]`) Languages required
Additional option: `ignoreMissing` (type `boolean`, default `true`) Ignore missing translations whose original string is blank
Example value: `[ "error", { "langs": [ "fr", "es" ], "ignoreMissing": false } ]`

Languages on which to fail if any message in the primary file is missing.

#### requireCompleteTranslationMessages
Default value: `"off"`
Additional option: `keys` (type `string[]`) Message keys to require
Example value: `[ "error", { "keys": [ "first-message-key", "second-message-key" ] } ]`

Messages on which to fail if missing in any provided language.

### disallowLeadingWhitespace
Default value: `"off"`

Whether to ignore leading whitespace in original messages.

### disallowLeadingWhitespaceTranslated
Default value: `"off"`

Whether to ignore leading whitespace in translated messages.

### disallowTrailingWhitespace
Default value: `"error"`

Whether to ignore trailing whitespace in original messages.

### allowTrailingWhitespaceTranslated
Default value: `"warn"`

Whether to ignore trailing whitespace in original messages.
