Socket
Socket
Sign inDemoInstall

grunt-banana-checker

Package Overview
Dependencies
Maintainers
14
Versions
18
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

grunt-banana-checker - npm Package Compare versions

Comparing version 0.7.1 to 0.8.0

12

History.md

@@ -0,1 +1,13 @@

v0.8.0 / 2019-08-20
==================
* Allow ignoring missing translations of blank source messages (Roan Kattouw)
* Allow requiring each parameter to be used in translations (James D. Forrester)
* Fix "languageMesages" typo (James D. Forrester)
* Make "lacks documentation" message more specific (Thiemo Kreuz)
* code: Commafy chained consts and fix directories (James D. Forrester)
* build: Upgrade eslint-config-wikimedia to 0.13.1 (James D. Forrester)
* build: Upgrade nyc from 13.3.0 to 14.1.1 (James D. Forrester)
* build: Use template literals (James D. Forrester)
v0.7.0 / 2019-01-08

@@ -2,0 +14,0 @@ ==================

8

package.json
{
"name": "grunt-banana-checker",
"version": "0.7.1",
"version": "0.8.0",
"description": "Checker for the 'Banana' JSON-file format for interface messages, as used by MediaWiki and jQuery.i18n.",

@@ -31,5 +31,5 @@ "repository": {

"devDependencies": {
"eslint-config-wikimedia": "0.10.0",
"nyc": "13.3.0",
"grunt": "1.0.3"
"eslint-config-wikimedia": "0.13.1",
"nyc": "14.1.1",
"grunt": "1.0.4"
},

@@ -36,0 +36,0 @@ "scripts": {

@@ -1,4 +0,4 @@

[![NPM version](https://badge.fury.io/js/grunt-banana-checker.svg)](http://badge.fury.io/js/grunt-banana-checker) [![Build Status](https://travis-ci.org/wikimedia/grunt-banana-checker.svg?branch=master)](https://travis-ci.org/wikimedia/grunt-banana-checker)
[![NPM version](https://badge.fury.io/js/grunt-banana-checker.svg)](http://badge.fury.io/js/grunt-banana-checker) [![Build Status](https://travis-ci.org/wikimedia/banana-checker.svg?branch=master)](https://travis-ci.org/wikimedia/banana-checker)
# grunt-banana-checker
# banana-checker

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

#### requireCompletelyUsedParameters
Type: `boolean`
Default value: `false`
Whether to fail if any translated message fails to use a parameter used in the primary message.
#### requireCompleteTranslationLanguages

@@ -202,1 +208,7 @@ Type: `string[]`

Messages on which to fail if missing in any provided language.
### ignoreMissingBlankTranslations
Type: `boolean`
Default value: `true`
Whether to ignore missing translations whose original string is blank.

@@ -26,2 +26,3 @@ 'use strict';

disallowUnusedTranslations: false,
ignoreMissingBlankTranslations: true,

@@ -59,3 +60,3 @@ requireCompleteMessageDocumentation: true,

} catch ( e ) {
logErr( 'Loading ' + type + ' messages failed: "' + e + '".' );
logErr( `Loading ${type} messages failed: "${e}".` );
ok = false;

@@ -76,3 +77,3 @@ throw e;

if ( options.requireMetadata ) {
logErr( 'No metadata block in the ' + type + ' messages file.' );
logErr( `No metadata block in the ${type} messages file.` );
ok = false;

@@ -103,14 +104,17 @@ }

var language = languageFile.match( jsonFilenameRegex )[ 1 ],
languageMesages = messages( languageFile, language ),
keys = keysNoMetadata( languageMesages, language ),
languageMessages = messages( languageFile, language ),
keys = keysNoMetadata( languageMessages, language ),
blanks = [],
duplicates = [],
unuseds = [],
missing = sourceMessageKeys.slice( 0 );
missing = sourceMessageKeys.slice( 0 ),
unusedParameters = [],
stack, originalParameters;
for ( index in keys ) {
message = keys[ index ];
originalParameters = sourceMessages[ message ].match( /\$\d/g );
if ( missing.indexOf( message ) !== -1 ) {
if ( languageMesages[ message ] === sourceMessages[ message ] ) {
if ( languageMessages[ message ] === sourceMessages[ message ] ) {
duplicates.push( message );

@@ -123,6 +127,17 @@ }

if ( typeof languageMesages[ message ] !== 'string' ) {
if ( originalParameters ) {
// eslint-disable-next-line no-loop-func
stack = originalParameters.filter( function ( originalParameter ) {
return languageMessages[ message ].indexOf( originalParameter ) === -1;
} );
if ( stack.length ) {
unusedParameters.push( { message, stack } );
}
}
if ( typeof languageMessages[ message ] !== 'string' ) {
continue;
}
if ( languageMesages[ message ].trim() === '' ) {
if ( languageMessages[ message ].trim() === '' ) {
blanks.push( message );

@@ -132,4 +147,10 @@ }

if ( options.ignoreMissingBlankTranslations ) {
missing = missing.filter( function ( message ) {
return sourceMessages[ message ] !== '';
} );
}
translatedData[ language ] = {
messages: languageMesages,
messages: languageMessages,
keys: keys,

@@ -139,3 +160,4 @@ blank: blanks,

unused: unuseds,
missing: missing
missing: missing,
unusedParameters: unusedParameters
};

@@ -192,8 +214,6 @@ } );

logErr(
count + ' message' + ( count > 1 ? 's lack' : ' lacks' ) + ' documentation.'
);
logErr( `${count} message${( count > 1 ? 's lack' : ' lacks' )} documentation in qqq.json.` );
sourceMessageMissing.forEach( function ( message ) {
logErr( 'Message "' + message + '" lacks documentation.' );
logErr( `Message "${message}" lacks documentation in qqq.json.` );
} );

@@ -208,8 +228,6 @@ }

logErr(
count + ' documented message' + ( count > 1 ? 's are' : ' is' ) + ' blank.'
);
logErr( `${count} documented message${( count > 1 ? 's are' : ' is' )} blank.` );
documentationMessageBlanks.forEach( function ( message ) {
logErr( 'Message "' + message + '" is documented with a blank string.' );
logErr( `Message "${message}" is documented with a blank string.` );
} );

@@ -224,16 +242,12 @@ }

if ( options.requireLowerCase === 'initial' ) {
logErr(
count + ' message' + ( count > 1 ? 's do' : ' does' ) + ' not start with a lowercase character.'
);
logErr( `${count} message${( count > 1 ? 's do' : ' does' )} not start with a lowercase character.` );
sourceMessageWrongCase.forEach( function ( message ) {
logErr( 'Message "' + message + '" should start with a lowercase character.' );
logErr( `Message "${message}" should start with a lowercase character.` );
} );
} else {
logErr(
count + ' message' + ( count > 1 ? 's are' : ' is' ) + ' not wholly lowercase.'
);
logErr( `${count} message${( count > 1 ? 's are' : ' is' )} not wholly lowercase.` );
sourceMessageWrongCase.forEach( function ( message ) {
logErr( 'Message "' + message + '" should be in lowercase.' );
logErr( `Message "${message}" should be in lowercase.` );
} );

@@ -248,16 +262,12 @@ }

if ( options.requireKeyPrefix.length === 1 ) {
logErr(
count + ' message' + ( count > 1 ? 's do' : ' does' ) + ' not start with the required prefix "' + options.requireKeyPrefix[ 0 ] + '".'
);
logErr( `${count} message${( count > 1 ? 's do' : ' does' )} not start with the required prefix "${options.requireKeyPrefix[ 0 ]}".` );
sourceMessageWrongPrefix.forEach( function ( message ) {
logErr( 'Message "' + message + '" should start with the required prefix "' + options.requireKeyPrefix[ 0 ] + '".' );
logErr( `Message "${message}" should start with the required prefix "${options.requireKeyPrefix[ 0 ]}".` );
} );
} else {
logErr(
count + ' message' + ( count > 1 ? 's do' : ' does' ) + ' not start with any of the required prefices.'
);
logErr( `${count} message${( count > 1 ? 's do' : ' does' )} not start with any of the required prefices.'` );
sourceMessageWrongPrefix.forEach( function ( message ) {
logErr( 'Message "' + message + '" should start with one of the required prefices.' );
logErr( `Message "${message}" should start with one of the required prefices.` );
} );

@@ -272,8 +282,6 @@ }

logErr(
count + ' documented message' + ( count > 1 ? 's are' : ' is' ) + ' undefined.'
);
logErr( `${count} documented message${( count > 1 ? 's are' : ' is' )} undefined.` );
documentationMessageKeys.forEach( function ( message ) {
logErr( 'Message "' + message + '" is documented but undefined.' );
logErr( `Message "${message}" is documented but undefined.` );
} );

@@ -293,8 +301,5 @@ }

ok = false;
logErr(
'The "' + index + '" translation has ' + count + ' blank translation' +
( count > 1 ? 's' : '' ) + ':'
);
logErr( `The "${index}" translation has ${count} blank translation${( count > 1 ? 's' : '' )}:` );
translatedData[ index ].blank.forEach( function ( message ) {
logErr( 'The translation of "' + message + '" is blank.' );
logErr( `The translation of "${message}" is blank.` );
} );

@@ -308,8 +313,5 @@ }

ok = false;
logErr(
'The "' + index + '" translation has ' + count + ' duplicate translation' +
( count > 1 ? 's' : '' ) + ':'
);
logErr( `The "${index}" translation has ${count} duplicate translation${( count > 1 ? 's' : '' )}:` );
translatedData[ index ].duplicate.forEach( function ( message ) {
logErr( 'The translation of "' + message + '" duplicates the primary message.' );
logErr( `The translation of "${message}" duplicates the primary message.` );
} );

@@ -323,9 +325,5 @@ }

ok = false;
logErr(
'The "' + index + '" translation has ' + count + ' unused translation' +
( count > 1 ? 's' : '' ) + ':'
);
logErr( `The "${index}" translation has ${count} unused translation${( count > 1 ? 's' : '' )}:` );
translatedData[ index ].unused.forEach( function ( message ) {
logErr( 'The translation of "' + message + '" is unused.' );
logErr( `The translation of "${message}" is unused.` );
} );

@@ -335,2 +333,22 @@ }

if ( options.requireCompletelyUsedParameters ) {
count = translatedData[ index ].unusedParameters.length;
if ( count > 0 ) {
ok = false;
logErr( `The "${index}" translation has ${count} message${( count > 1 ? 's' : '' )} which fail${( count > 1 ? 's' : '' )} to use all parameters:` );
// eslint-disable-next-line no-loop-func
translatedData[ index ].unusedParameters.forEach( function ( report ) {
switch ( report.stack.length ) {
case 1:
logErr( `The translation of "${report.message}" fails to use the parameter "${report.stack[ 0 ]}".` );
break;
case 2:
logErr( `The translation of "${report.message}" fails to use the parameters "${report.stack[ 0 ]}" and "${report.stack[ 1 ]}" .` );
break;
default:
logErr( `The translation of "${report.message}" fails to use the parameters "${report.stack.join( '", "' )}".` );
}
} );
}
}
}

@@ -351,6 +369,6 @@

ok = false;
logErr( 'The "' + index + '" translation has ' + count + ' missing translation' + ( count > 1 ? 's' : '' ) + ':' );
logErr( `The "${index}" translation has ${count} missing translation${( count > 1 ? 's' : '' )}:` );
translatedData[ index ].missing.forEach( function ( message ) {
logErr( 'The translation of "' + message + '" is missing.' );
logErr( `The translation of "${message}" is missing.` );
} );

@@ -369,8 +387,12 @@ }

for ( message in translatedData[ index ].missing ) {
// eslint-disable-next-line no-prototype-builtins
if ( !translatedData[ index ].missing.hasOwnProperty( sourceMessageKeys[ message ] ) ) {
if (
// eslint-disable-next-line no-prototype-builtins
!translatedData[ index ].missing.hasOwnProperty( sourceMessageKeys[ message ] )
) {
continue;
}
offset = options.requireCompleteTranslationMessages.indexOf( sourceMessageKeys[ message ] );
offset = options.requireCompleteTranslationMessages.indexOf(
sourceMessageKeys[ message ]
);

@@ -385,6 +407,6 @@ if ( offset === -1 ) {

ok = false;
logErr( 'The "' + index + '" translation is missing ' + count + ' required message' + ( count > 1 ? 's' : '' ) + ':' );
logErr( `The "${index}" translation is missing ${count} required message{( count > 1 ? 's' : '' )}:` );
translatedData[ index ].missing.forEach( function ( message ) {
logErr( 'The required message "' + message + '" is missing.' );
logErr( `The required message "${message}" is missing.` );
} );

@@ -391,0 +413,0 @@ }

@@ -28,2 +28,3 @@ #!/usr/bin/env node

case 'disallowUnusedTranslations':
case 'ignoreMissingBlankTranslations':
case 'requireCompleteMessageDocumentation':

@@ -69,2 +70,2 @@ case 'requireLowerCase':

console.log( 'Checked ' + dirs.length + ' message ' + ( dirs.length > 1 ? 'directories' : 'directory' ) + '.' );
console.log( `Checked ${dirs.length} message director${( dirs.length > 1 ? 'ies' : 'y' )}.` );

@@ -25,4 +25,4 @@ const bananaChecker = require( '../src/banana.js' );

grunt.log.ok( messageDirs + ' message ' + ( messageDirs > 1 ? 'directories' : 'directory' ) + ' checked.' );
grunt.log.ok( `${messageDirs} message director${( messageDirs > 1 ? 'ies' : 'y' )} checked.` );
} );
};
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc