Santhosh has submitted this change and it was merged.

Change subject: Dict dictionary protocol backend
......................................................................


Dict dictionary protocol backend

* Implements a dict protocol client and a dictionary registry
* Exposes a REST api dictionary/:word/:from/:to

Example: http://localhost:8000/dictionary/pen/en/de
Result:
{
  "definitions": [
    {
      "def": "pen /pen/\r\n (Schreib-) Feder; Füller; Griffel <m>; Stift <m>",
      "db": {
        "name": "fd",
        "desc": "English-German FreeDict Dictionary ver. 0.3.5"
      }
    }
  ],
  "suggestions": []
}

Change-Id: I138b5d457ce46c5bfe4e760d95f29c3adf25abfd
---
M ContentTranslationService.js
A dictionary/dict/Dict.js
A dictionary/dict/DictClient.js
A dictionary/dict/DictRegistry.json
A dictionary/dict/Readme.md
A public/dictionary/css/main.css
A public/dictionary/index.html
A public/dictionary/js/main.js
8 files changed, 958 insertions(+), 0 deletions(-)

Approvals:
  Santhosh: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/ContentTranslationService.js b/ContentTranslationService.js
index 3789500..a36d5e9 100644
--- a/ContentTranslationService.js
+++ b/ContentTranslationService.js
@@ -69,6 +69,17 @@
        } );
 } );
 
+app.get( '/dictionary/:word/:from/:to', function ( req, res ) {
+       var sourceLanguage = req.params.from,
+               word = req.params.word,
+               targetLanguage = req.params.to,
+               dictClient = require( __dirname + '/dictionary/dict/Dict.js' );
+
+       dictClient.getDefinition( word, sourceLanguage, targetLanguage ).then( 
function ( data ) {
+               res.send( data );
+       } );
+} );
+
 app.get( '/version', function ( req, res ) {
        var version = {
                name: pkg.name,
diff --git a/dictionary/dict/Dict.js b/dictionary/dict/Dict.js
new file mode 100644
index 0000000..5c8aef0
--- /dev/null
+++ b/dictionary/dict/Dict.js
@@ -0,0 +1,29 @@
+var dictClient = require( __dirname + '/DictClient.js' ),
+       dictRegistry = require( __dirname + '/DictRegistry.json' ),
+       Q = require( 'q' );
+
+function findDatabase( source, target ) {
+       var dictionaries = dictRegistry[ source ] && dictRegistry[ source ][ 
target ];
+       if ( !dictionaries ) {
+               return null;
+       }
+       return Object.keys( dictionaries );
+}
+
+function getDefinition( word, from, to ) {
+       var deferred = Q.defer();
+       dictClient.lookup( word, {
+               db: findDatabase( from, to ),
+               action: 'def',
+               suggestions: true,
+               error: function ( responseCode, message ) {
+                       deferred.reject( responseCode + ': ' + message );
+               },
+               success: function ( data ) {
+                       deferred.resolve( data );
+               }
+       } );
+       return deferred.promise;
+}
+
+module.exports.getDefinition = getDefinition;
diff --git a/dictionary/dict/DictClient.js b/dictionary/dict/DictClient.js
new file mode 100644
index 0000000..5e11c77
--- /dev/null
+++ b/dictionary/dict/DictClient.js
@@ -0,0 +1,501 @@
+/**
+ * Dict dictionary protocol client as per RFC 2229
+ * Credits:
+ *    Dict client implementation borrowed from: 
https://github.com/ptrm/dict.json
+ *    Copyright (c) 2010 Piotrek Marciniak <piot...@ptrm.eu>, MIT Style License
+ * RFC 2229: http://www.dict.org/rfc2229.txt
+ *@author Santhosh Thottingal <santhosh.thottin...@gmail.com>
+ *@license MIT
+ */
+
+var sys = require( 'sys' ),
+       net = require( 'net' ),
+       logLevel, config;
+
+logLevel = {
+       silent: 0,
+       standard: 1,
+       diagnostic: 2,
+       verbose: 3
+};
+config = {
+       logging: logLevel.silent,
+       dictd: {
+               port: '2628',
+               host: '127.0.0.1',
+               timeout: 700
+       },
+       db: '!' // First match
+};
+
+function firstObj( list ) {
+       var obj = null,
+               idx;
+
+       if ( typeof list !== 'object' ) {
+               return null;
+       }
+       for ( idx in list ) {
+               obj = list[ idx ];
+               break;
+       }
+
+       return obj;
+}
+
+/**
+ * Simple logger, mainly for debugging
+ */
+function log( msg, level ) {
+       if ( !level ) {
+               level = logLevel.standard;
+       }
+       if ( level <= config.logging ) {
+               sys.log( msg );
+       }
+}
+
+/**
+ * Sanitize the words
+ * @param {Object} words
+ */
+function parseWords( words ) {
+       var i, word, db, nDb, dbIdx,
+               res = {},
+               count = 0;
+
+       for ( i in words ) {
+               if ( typeof words[ i ].word !== 'string' ) {
+                       continue;
+               }
+               // cleanup the word by removing traling new line characters
+               word = words[ i ].word.replace( /["\r\n]/g, '' 
).trim().toLowerCase();
+
+               db = [];
+               if ( words[ i ].db ) {
+                       if ( typeof words[ i ].db !== 'object' ) {
+                               words[ i ].db = new Array( words[ i ].db );
+                       }
+                       for ( dbIdx in words[ i ].db ) {
+                               nDb = words[ i ].db[ dbIdx ];
+                               // cleanup the db name by removing traling new 
line characters
+                               db.push( nDb.replace( /["\r\n]/g, '' 
).trim().toLowerCase() );
+                       }
+               }
+
+               if ( !db.length ) {
+                       db.push( config.db );
+               }
+               if ( word ) {
+                       res[ word ] = {
+                               db: db
+                       };
+                       count++;
+               }
+       }
+
+       res.count = count;
+       log( sys.inspect( res ), logLevel.verbose );
+
+       return res;
+}
+
+function getDefs( words, options ) {
+       var dict, defs = {},
+               suggestions = {},
+               reqQueue = [],
+               sentReqs = [],
+               reqOnDrain = false,
+               currentReqIdx = -1,
+               currentReq = {},
+               textBuf = '',
+               textEnded = true,
+               word = '',
+               dbDesc = '',
+               dbName = '',
+               status = '';
+
+       // Create a connection to the dict host and port
+       dict = net.createConnection( config.dictd.port, config.dictd.host );
+       dict.setTimeout( config.dictd.timeout );
+       dict.setEncoding( 'utf8' );
+
+       if ( typeof options !== 'object' ) {
+               options = {};
+       }
+
+       dict.on( 'timeout', function () {
+               log( 'timeout', logLevel.diagnostic );
+               options.error( 'error', 'Timeout' );
+               dict.end();
+       } );
+
+       dict.on( 'end', function () {
+               log( 'end', logLevel.diagnostic );
+               dict.end();
+       } );
+
+       dict.on( 'connect', function () {
+               var dbIdx, req, db, word;
+               log( 'getDefs: connected', logLevel.verbose );
+
+               // put requests to queue
+               for ( word in words ) {
+                       if ( word === 'count' ) {
+                               continue;
+                       }
+                       defs[ word ] = [];
+                       for ( dbIdx in words[ word ].db ) {
+                               db = words[ word ].db[ dbIdx ];
+                               req = 'd ' + db + ' "' + word + '"' + '\r\n';
+                               reqQueue.push( {
+                                       request: req,
+                                       word: word,
+                                       type: 'def',
+                                       db: db
+                               } );
+                       }
+
+               }
+       } );
+
+       function nextRequest() {
+               var req, i;
+               reqOnDrain = false;
+
+               // check whether all responses arrived and if there are 
requests to be sent
+               if ( ( currentReqIdx + 1 < sentReqs.length ) || reqQueue.length 
) {
+                       if ( !dict.writable ) {
+                               reqOnDrain = true;
+                               log( 'nextRequest() postponed till drain', 
logLevel.diagnostic );
+                               return;
+                       }
+
+                       // Send the all pending requests at once. It increases 
performance when
+                       // using remote dict server, and is encouraged by the 
RFC.
+                       req = '';
+                       for ( i in reqQueue ) {
+                               req = req + reqQueue[ i ].request;
+                       }
+
+                       sentReqs = sentReqs.concat( reqQueue );
+                       reqQueue = [];
+                       currentReqIdx++;
+                       currentReq = sentReqs[ currentReqIdx ];
+
+                       if ( req.trim() ) {
+                               dict.write( req );
+                               log( 'getDefs: nextRequest: sent request: "' + 
req + '"', logLevel.verbose );
+                       }
+               } else { // if not, send the quit message
+                       currentReq = {
+                               request: 'q\r\n'
+                       };
+                       dict.end( currentReq.request );
+                       log( 'nextRequest(): Sent "q"', logLevel.diagnostic );
+               }
+       }
+
+       dict.on( 'drain', function () {
+               if ( !reqOnDrain ) {
+                       return;
+               }
+               nextRequest();
+               log( 'called nextRequestuest() on drain', logLevel.diagnostic );
+       } );
+
+       dict.on( 'data', function ( data ) {
+               var idx, definition, header, nextResponsePos = -2,
+                       sug, sugLines, lNum,
+                       response = '';
+
+               if ( typeof data !== 'string' ) {
+                       return;
+               }
+               log( 'Data: ' + JSON.stringify( data ), logLevel.verbose );
+
+               /*
+        To understand the response handling code, an example response is given 
below.
+            C: DEFINE * shortcake
+            -----------------
+            S: 150 2 definitions found: list follows
+            S: 151 "shortcake" wn "WordNet 1.5" : text follows
+            S: shortcake
+            S:   1. n: very short biscuit spread with sweetened fruit and usu.
+            S:      whipped cream
+            S: .
+            S: 151 "Shortcake" web1913 "Webster's Dictionary (1913)" : text 
follows
+            S: Shortcake
+            S:    \Short"cake`\, n.
+            S:    An unsweetened breakfast cake shortened with butter or lard,
+            S:    rolled thin, and baked.
+            S: .
+            S: 250 Command complete
+        */
+               function nextResponse() {
+                       if ( textEnded ) {
+                               nextResponsePos = data.search( /\r\n[0-9]{3}/ );
+                       } else {
+                               nextResponsePos = data.search( /\r\n\.(\r\n|$)/ 
);
+                       }
+
+                       if ( nextResponsePos !== -1 ) {
+                               response = data.substring( 0, nextResponsePos );
+                               // + 2 for \r\n
+                               data = data.slice( nextResponsePos + 2 );
+                       } else {
+                               response = data;
+                       }
+                       if ( textEnded ) {
+                               status = response.substring( 0, 3 );
+                       } else {
+                               textEnded = ( nextResponsePos > -1 );
+                               log( 'nextResponsePos: ' + nextResponsePos, 
logLevel.verbose );
+                       }
+
+                       log( 'Response: "' + response + '", next at ' + 
nextResponsePos, logLevel.verbose );
+                       log( 'Status: ' + status, logLevel.verbose );
+               }
+
+               while ( ( nextResponsePos !== -1 ) && ( nextResponsePos !== 0 ) 
) {
+
+                       if ( textEnded ) {
+                               // reset state variables
+                               textBuf = '';
+                               status = '';
+                               response = '';
+                               nextResponse();
+                       } else {
+                               log( 'Continuing previous data', 
logLevel.verbose );
+                       }
+
+                       switch ( status ) {
+                               //greetings
+                       case '220':
+                               log( 'getDefs: dict.org said hello', 
logLevel.verbose );
+
+                               //we can start the fun now
+                               nextRequest();
+                               break;
+
+                               //bye
+                       case '221':
+                               log( 'getDefs: dict.org says bye', 
logLevel.verbose );
+                               //onEnd event should follow, so no need to do 
anything here
+                               break;
+
+                               //a couple of errors on which we should close
+                               //temorarily unavailable
+                       case '420':
+                               //Server temporarily unavailable
+                       case '421':
+                               //Server shutting down at operator request
+                               options.error( 'error', 'Error code ' + status 
);
+                               return;
+                               //no match
+                       case '552':
+                               //provide suggestions?
+                               // checking request type, because server gives 
the same not found code for suggestions as for words
+                               // also checking whether db isn't on ignore list
+                               if ( ( currentReq.type === 'def' ) && 
options.suggestions ) {
+                                       reqQueue.push( {
+                                               request: 'match ' + 
currentReq.db + ' lev "' + currentReq.word + '"' + '\r\n',
+                                               type: 'sug',
+                                               word: currentReq.word
+                                       } );
+                               }
+                               nextRequest();
+                               break;
+
+                               //a couple of errors on which we might try to 
continue
+                               //syntax error, command not recognized
+                       case '500':
+                               //Syntax error, command not recognized
+                       case '501':
+                               //Syntax error, illegal parameters
+                       case '502':
+                               //Command not implemented
+                       case '503':
+                               // Command parameter not implemented
+                       case '550':
+                               //invalid strategy
+                       case '551':
+                               log( 'Proceeding to next request at status ' + 
status, logLevel.diagnostic );
+                               nextRequest();
+                               break;
+
+                               //suggestions
+                       case '152':
+                               word = currentReq.word;
+
+                               if ( textEnded ) {
+                                       //first line is the status message:
+                                       idx = response.indexOf( '\r\n' );
+                                       if ( idx === -1 ) {
+                                               break;
+                                       }
+                                       header = response.substring( 0, idx );
+                                       response = response.slice( idx + 2 );
+                                       textBuf = response;
+                                       textEnded = response.match( 
/\r\n\.(\r\n|$)/ );
+                                       if ( !textEnded ) {
+                                               log( 'Suggestions didn\'t 
end.', logLevel.verbose );
+                                       }
+                               } else {
+                                       nextResponse();
+                                       textBuf = textBuf.concat( response );
+                               }
+
+                               if ( textEnded ) {
+                                       // Example suggestion response:
+                                       // 152 7 matches found: list follows
+                                       // dbname suggestion1
+                                       // dbname suggestion2
+                                       // Remove the "." ending the text 
message.
+                                       sugLines = textBuf.replace( 
/\r\n\.(\r\n|$)/, '' ).split( '\r\n' );
+                                       // That removed the first line too.
+                                       if ( !suggestions[ word ] ) {
+                                               // initialize the object
+                                               suggestions[ word ] = [];
+                                       }
+
+                                       for ( lNum in sugLines ) {
+                                               if ( !sugLines[ lNum ].trim() ) 
{
+                                                       continue;
+                                               }
+                                               // remove the first word in the 
line because it is db name
+                                               sug = sugLines[ lNum ].replace( 
/^[a-zA-Z0-9]+ "([^"]+)".*/, '$1' );
+                                               log( 'Suggestion: "' + sug + 
'"', logLevel.verbose );
+                                               if ( suggestions[ word 
].indexOf( sug ) === -1 ) {
+                                                       suggestions[ word 
].push( sug );
+                                               }
+                                       }
+
+                                       log( 'Suggestions ended.', 
logLevel.verbose );
+                                       log( 'Parsed suggestions: ' + 
sys.inspect( suggestions[ word ] ), logLevel.verbose );
+                               }
+                               break;
+
+                               //ok
+                       case '250':
+                               nextRequest();
+                               break;
+
+                               //definition
+                       case '151':
+                               //word database name - text follows
+                               //textEnded, so we are free to start anew
+                               if ( textEnded ) {
+                                       //first line is the status message:
+                                       idx = response.indexOf( '\r\n' );
+                                       if ( idx === -1 ) {
+                                               break;
+                                       }
+                                       header = response.substring( 0, idx );
+                                       response = response.slice( idx + 2 );
+
+                                       word = header.replace( /[0-9]{3} 
"([^"]*)".*/, '$1' ).toLowerCase();
+                                       dbName = header.replace( /[0-9]{3} 
"[^"]*" (\w+)\b.*/, '$1' );
+                                       dbDesc = header.replace( /[0-9]{3} 
"[^"]*".*"([^"]*)"/, '$1' );
+
+                                       textBuf = response;
+
+                                       textEnded = response.match( 
/\r\n\.(\r\n|$)/ );
+                                       if ( !textEnded ) {
+                                               log( 'Definition did not end.', 
logLevel.verbose );
+                                       }
+                               } else {
+                                       nextResponse();
+                                       textBuf = textBuf.concat( response );
+                               }
+
+                               if ( textEnded ) {
+                                       // ".." On the beggining of a new line 
means "."
+                                       // We also remove the "." ending the 
text message.
+                                       definition = textBuf.replace( /^\.\./m, 
'.' ).replace( /\r\n\.(\r\n|$)/, '' );
+
+                                       log( 'Definition ended.', 
logLevel.verbose );
+                                       log( 'Parsed defs: ' + sys.inspect( 
definition ), logLevel.verbose );
+
+                                       if ( typeof defs[ currentReq.word ] !== 
'object' ) {
+                                               defs[ currentReq.word ] = [];
+                                       }
+                                       defs[ currentReq.word ].push( {
+                                               def: definition,
+                                               db: {
+                                                       name: dbName,
+                                                       desc: dbDesc
+                                               }
+                                       } );
+
+                                       log( 'Defs: ' + sys.inspect( defs ), 
logLevel.verbose );
+                               }
+                               break;
+                       }
+                       log( '*** End of data event\n', logLevel.verbose );
+               }
+       } );
+
+       dict.on( 'close', function () {
+               var data;
+               if ( options.action === 'def' ) {
+                       defs = firstObj( defs ) || [];
+
+                       if ( options.suggestions ) {
+                               suggestions = firstObj( suggestions ) || [];
+                       }
+               }
+
+               data = {
+                       definitions: defs
+               };
+
+               if ( options.suggestions ) {
+                       data.suggestions = suggestions;
+               }
+               options.success( data );
+               log( 'Connection ended.', logLevel.verbose );
+       } );
+}
+
+/**
+ * Search for the definition of a word
+ * @param {string|Array} word
+ * @param {Object} options
+ */
+function lookup( word, options ) {
+       var defs, words, wordList = [],
+               action = options.action || 'def';
+
+       switch ( action ) {
+       case 'def':
+               wordList = [ {
+                       word: word,
+                       //type: type,
+                       db: options.db || config.db
+                       } ];
+               break;
+
+       case 'multi':
+               wordList = word;
+               break;
+
+       default:
+               options.error( 'error', 'Wrong action given.' );
+               return;
+       }
+
+       // Sanitize the wordList
+       words = parseWords( wordList );
+       if ( words.count ) {
+               log( 'Words ok', logLevel.verbose );
+               defs = getDefs( words, {
+                       action: options.action,
+                       suggestions: !!options.suggestions,
+                       error: options.error,
+                       success: options.success
+               } );
+       }
+}
+
+module.exports.lookup = lookup;
diff --git a/dictionary/dict/DictRegistry.json 
b/dictionary/dict/DictRegistry.json
new file mode 100644
index 0000000..1ac0907
--- /dev/null
+++ b/dictionary/dict/DictRegistry.json
@@ -0,0 +1,316 @@
+{
+       "en": {
+               "af": {
+                       "fd-eng-afr": "English-Afrikaans FreeDict Dictionary 
ver. 0.1.1"
+               },
+               "ar": {
+                       "fd-eng-ara": "English-Arabic FreeDict Dictionary ver. 
0.6.2"
+               },
+               "cs": {
+                       "fd-eng-ces": "English-Czech dicts.info/FreeDict 
Dictionary ver. 0.1.1",
+                       "fd-eng-cze": "English-Czech fdicts/FreeDict Dictionary"
+               },
+               "hr": {
+                       "fd-eng-cro": "English-Croatian Freedict Dictionary"
+               },
+               "cy": {
+                       "fd-eng-cym": "Eurfa Saesneg, English-Welsh 
Eurfa/Freedict dictionary ver. 0.2."
+               },
+               "de": {
+                       "fd-eng-deu": "English-German FreeDict Dictionary ver. 
0.3.5"
+               },
+               "el": {
+                       "fd-eng-ell": "English - Modern Greek XDXF/FreeDict 
dictionary ver. 0.1"
+               },
+               "en": {
+                       "gcide": "The Collaborative International Dictionary of 
English v.0.48"
+               },
+               "fr": {
+                       "fd-eng-fra": "English-French FreeDict Dictionary ver. 
0.1.4"
+               },
+               "ga": {
+                       "fd-eng-gle": "English-Irish FreeDict Dictionary ver. 
0.3.1"
+               },
+               "hi": {
+                       "fd-eng-hin": "English-Hindi FreeDict Dictionary ver. 
1.5.1"
+               },
+               "hr": {
+                       "fd-eng-hrv": "English-Croatian FreeDict Dictionary 
ver. 0.2.1"
+               },
+               "hu": {
+                       "fd-eng-hun": "English-Hungarian FreeDict Dictionary 
ver. 0.1"
+               },
+               "it": {
+                       "fd-eng-ita": "English-Italian FreeDict Dictionary ver. 
0.1.1"
+               },
+               "la": {
+                       "fd-eng-lat": "English-Latin FreeDict Dictionary ver. 
0.1.1"
+               },
+               "lt": {
+                       "fd-eng-lit": "English-Lithuanian FreeDict Dictionary 
ver. 0.7.1"
+               },
+               "nl": {
+                       "fd-eng-nld": "English-Dutch FreeDict Dictionary ver. 
0.1.1"
+               },
+               "pl": {
+                       "fd-eng-pol": "English - Polish 
Piotrowski+Saloni/FreeDict dictionary ver. 0.1"
+               },
+               "pt": {
+                       "fd-eng-por": "English-Portuguese FreeDict Dictionary 
ver. 0.2.2"
+               },
+               "ro": {
+                       "fd-eng-rom": "English-Romanian FreeDict Dictionary 
ver. 0.6.1"
+               },
+               "ru": {
+                       "fd-eng-rus": "English-Russian FreeDict Dictionary ver. 
0.3",
+                       "mueller7": "Mueller English-Russian Dictionary"
+               },
+               "sr": {
+                       "fd-eng-scr": "English-Serbo-Croat Freedict dictionary",
+                       "fd-eng-srp": "English-Serbian FreeDict Dictionary ver. 
0.1.2"
+               },
+               "es": {
+                       "fd-eng-spa": "English-Spanish FreeDict Dictionary ver. 
0.2.1"
+               },
+               "sw": {
+                       "fd-eng-swa": "English-Swahili xFried/FreeDict 
Dictionary"
+               },
+               "sv": {
+                       "fd-eng-swe": "English-Swedish FreeDict Dictionary ver. 
0.1.1"
+               },
+               "tr": {
+                       "fd-eng-tur": "English-Turkish FreeDict Dictionary ver. 
0.2.1"
+               },
+               "cy": {
+                       "fd-eng-wel": "English-Welsh Freedict dictionary"
+               }
+       },
+       "af": {
+               "de": {
+                       "fd-afr-deu": "Afrikaans-German FreeDict Dictionary 
ver. 0.3"
+               },
+               "en": {
+                       "fd-afr-eng": "Afrikaans-English FreeDict Dictionary 
ver. 0.2.1",
+                       "fd-ara-eng": "Arabic-English FreeDict 
DictionaryByarabeyes.org ver. 0.6.2"
+               }
+       },
+       "br": {
+               "fr": {
+                       "fd-bre-fra": "Breton-French FreeDict Dictionary 
(Geriadur Tomaz) ver. 0.3.0"
+               },
+               "en": {
+                       "fd-ces-eng": "Czech-English FreeDict Dictionary ver. 
0.2.1"
+               }
+       },
+       "cr": {
+               "en": {
+                       "fd-cro-eng": "Croatian-English Freedict Dictionary"
+               }
+       },
+       "cy": {
+               "en": {
+                       "fd-cym-eng": "Eurfa Cymraeg, Welsh-English 
Eurfa/Freedict dictionary ver. 0.2.2"
+               }
+       },
+       "cs": {
+               "en": {
+                       "fd-cze-eng": "Czech-English Freedict dictionary"
+               }
+       },
+       "da": {
+               "en": {
+                       "fd-dan-eng": "Danish-English FreeDict Dictionary ver. 
0.2.1"
+               }
+       },
+       "de": {
+               "en": {
+                       "fd-deu-eng": "German-English FreeDict Dictionary ver. 
0.3.3"
+               },
+               "fr": {
+                       "fd-deu-fra": "German-French FreeDict Dictionary ver. 
0.3.1"
+               },
+               "it": {
+                       "fd-deu-ita": "German-Italian FreeDict Dictionary ver. 
0.1.1"
+               },
+               "nl": {
+                       "fd-deu-nld": "German-Dutch FreeDict Dictionary ver. 
0.1.1"
+               },
+               "ku": {
+                       "fd-deu-kur": "German-Kurdish Ferheng/FreeDict 
Dictionary ver. 0.2.1"
+               },
+               "pt": {
+                       "fd-deu-por": "German-Portuguese FreeDict Dictionary 
ver. 0.2.1"
+               },
+               "tr": {
+                       "fd-deu-tur": "German-Turkish Ferheng/FreeDict 
Dictionary ver. 0.2.1"
+               }
+       },
+       "fr": {
+               "br": {
+                       "fd-fra-bre": "French-Breton FreeDict Dictionary 
(Geriadur Tomaz) ver. 0.2.5"
+               },
+               "de": {
+                       "fd-fra-deu": "French-German FreeDict Dictionary ver. 
0.1.1"
+               },
+               "en": {
+                       "fd-fra-eng": "French-English FreeDict Dictionary ver. 
0.3.4"
+               },
+               "nl": {
+                       "fd-fra-nld": "French-Dutch FreeDict Dictionary ver. 
0.1.2"
+               }
+       },
+       "gd": {
+               "de": {
+                       "fd-gla-deu": "Scottish Gaelic-German FreeDict 
Dictionary ver. 0.1.1"
+               }
+       },
+       "ga": {
+               "en": {
+                       "fd-gle-eng": "Irish-English FreeDict Dictionary ver. 
0.1.2"
+               },
+               "pl": {
+                       "fd-gle-pol": "Irish-Polish FreeDict Dictionary ver. 
0.1.1"
+               }
+       },
+       "hi": {
+               "en": {
+                       "fd-hin-eng": "English-Hindi Freedict Dictionary 
[reverse index]"
+               }
+       },
+       "hr": {
+               "en": {
+                       "fd-hrv-eng": "Croatian-English FreeDict Dictionary 
ver. 0.1.1"
+               }
+       },
+       "hu": {
+               "en": {
+                       "fd-hun-eng": "Hungarian-English FreeDict Dictionary 
ver. 0.3"
+               }
+       },
+       "ga": {
+               "en": {
+                       "fd-iri-eng": "Irish-English Freedict dictionary"
+               }
+       },
+       "is": {
+               "en": {
+                       "fd-isl-eng": "íslenska - English FreeDict Dictionary 
ver. 0.1"
+               }
+       },
+       "it": {
+               "de": {
+                       "fd-ita-deu": "Italian-German FreeDict Dictionary ver. 
0.1.1"
+               },
+               "en": {
+                       "fd-ita-eng": "Italian-English FreeDict Dictionary ver. 
0.1.1"
+               }
+       },
+       "ja": {
+               "de": {
+                       "fd-jpn-deu": "Japanese-German FreeDict Dictionary ver. 
0.1.1"
+               }
+       },
+       "ku": {
+               "de": {
+                       "fd-kur-deu": "Kurdish-German Ferheng/FreeDict 
Dictionary ver. 0.1.1"
+               },
+               "en": {
+                       "fd-kur-eng": "Kurdish-English Ferheng/FreeDict 
Dictionary ver. 0.1.1"
+               },
+               "tr": {
+                       "fd-kur-tur": "Kurdish-Turkish Ferheng/FreeDict 
Dictionary ver. 0.1.1"
+               }
+       },
+       "la": {
+               "de": {
+                       "fd-lat-deu": "Latin - German FreeDict dictionary ver. 
0.4"
+               },
+               "en": {
+                       "fd-lat-eng": "Latin-English FreeDict Dictionary ver. 
0.1.1"
+               }
+       },
+       "lt": {
+               "fd-lit-eng": "Lithuanian-English FreeDict Dictionary ver. 
0.7.1"
+       },
+       "mk": {
+               "bg": {
+                       "fd-mkd-bul": "Macedonian - Bulgarian FreeDict 
Dictionary ver. 0.1"
+               }
+       },
+       "nl": {
+               "de": {
+                       "fd-nld-deu": "Dutch-German FreeDict Dictionary ver. 
0.1.1"
+               },
+               "en": {
+                       "fd-nld-eng": "Dutch-English Freedict Dictionary ver. 
0.1.3"
+               },
+               "fr": {
+                       "fd-nld-fra": "Nederlands-French FreeDict Dictionary 
ver. 0.1.1"
+               }
+       },
+       "pl": {
+               "ga": {
+                       "fd-pol-gle": "Polish-Irish FreeDict Dictionary ver. 
0.1.1"
+               }
+       },
+       "pt": {
+               "de": {
+                       "fd-por-deu": "Portuguese-German FreeDict Dictionary 
ver. 0.1.1"
+               },
+               "en": {
+                       "fd-por-eng": "Portuguese-English FreeDict Dictionary 
ver. 0.1.1"
+               }
+       },
+       "sa": {
+               "de": {
+                       "fd-san-deu": "Sanskrit-German FreeDict Dictionary ver. 
0.2.1"
+               }
+       },
+       "sr": {
+               "en": {
+                       "fd-scr-eng": "Serbo-Croat-English Freedict dictionary"
+               }
+       },
+       "sk": {
+               "en": {
+                       "fd-slk-eng": "Slovak-English FreeDict Dictionary ver. 
0.1.1"
+               }
+       },
+       "es": {
+               "en": {
+                       "fd-spa-eng": "Spanish-English FreeDict Dictionary ver. 
0.1.1"
+               }
+       },
+       "sr": {
+               "en": {
+                       "fd-srp-eng": "Serbian - English FreeDict Dictionary 
ver. 0.1.3"
+               }
+       },
+       "sw": {
+               "en": {
+                       "fd-swa-eng": "Swahili-English xFried/FreeDict 
Dictionary",
+                       "fd-swh-eng": "Swahili-English xFried/FreeDict 
Dictionary ver. 0.4.3"
+               },
+               "pl": {
+                       "fd-swh-pol": "Swahili-Polish SSSP/FreeDict Dictionary 
ver. 0.2.2"
+               }
+       },
+       "sv": {
+               "en": {
+                       "fd-swe-eng": "Swedish-English FreeDict Dictionary ver. 
0.1.1"
+               }
+       },
+       "tr": {
+               "de": {
+                       "fd-tur-deu": "Turkish-German FreeDict Dictionary ver. 
0.1.1"
+               },
+               "en": {
+                       "fd-tur-eng": "Turkish-English FreeDict Dictionary ver. 
0.2.1"
+               }
+       },
+       "cy": {
+               "en": {
+                       "fd-wel-eng": "Welsh-English Freedict dictionary"
+               }
+       }
+}
diff --git a/dictionary/dict/Readme.md b/dictionary/dict/Readme.md
new file mode 100644
index 0000000..0445de9
--- /dev/null
+++ b/dictionary/dict/Readme.md
@@ -0,0 +1,16 @@
+Dict client in nodejs
+=====================
+
+This is a Dict dictionary protocol client written in javascript.
+
+It exposes a simple api to check the word definitions in the available 
backends.
+
+```javascript
+getDefinition( 'swim', 'en', 'de' ).then( function (data) {
+     console.log(data)
+} );
+```
+
+The backend dictionaries are listed in DictRegistry.json in the form of a json 
registry.
+It provides a handy translation of ISO 639 two letter language codes to the 
available dictionary
+identifiers.
diff --git a/public/dictionary/css/main.css b/public/dictionary/css/main.css
new file mode 100644
index 0000000..cbb9f57
--- /dev/null
+++ b/public/dictionary/css/main.css
@@ -0,0 +1,40 @@
+ body {
+     width: 80%;
+     margin-left: 10%;
+ }
+ label {
+     width: 20%;
+ }
+ input {
+     width: 40%;
+     padding: 5px;
+ }
+ .lang {
+     width: 5%;
+ }
+ button {
+     width: 10%;
+     padding: 5px;
+ }
+ .status {
+     position: fixed;
+     bottom: 0;
+     left: 0;
+     right: 0;
+     height: 16px;
+     padding: 5px;
+     background: #ccc;
+     color: green;
+     font-size: 0.8em;
+ }
+ .form {
+     border: 1px solid #000;
+     padding: 10px;
+ }
+ .definition {
+     border: 1px solid #000;
+     padding: 10px;
+     font-size: medium;
+     word-wrap: break-word;
+     font-family: sans-serif;
+ }
diff --git a/public/dictionary/index.html b/public/dictionary/index.html
new file mode 100644
index 0000000..46f3e85
--- /dev/null
+++ b/public/dictionary/index.html
@@ -0,0 +1,23 @@
+<html>
+
+<head>
+    <script src="//code.jquery.com/jquery-1.10.2.min.js"></script>
+    <title>DictionaryContent Translation Server</title>
+    <link rel="stylesheet" href="css/main.css" type="text/css" />
+</head>
+
+<body>
+    <h1>Dictionary - Content Translation Server</h1>
+    <div class="form">
+        <label for="word">Define</label>
+        <input name="word" value="Food" />
+        <label for="sourceLanguage">from</label>
+        <input class="lang" name="sourceLanguage" value="en" />
+        <label for="targetLanguage">to</label>
+        <input class="lang" name="targetLanguage" value="de" />
+        <button>Go</button>
+    </div>
+    <pre class="definition"></pre>
+    <script src="js/main.js"></script>
+</body>
+</html>
diff --git a/public/dictionary/js/main.js b/public/dictionary/js/main.js
new file mode 100644
index 0000000..7d80ed8
--- /dev/null
+++ b/public/dictionary/js/main.js
@@ -0,0 +1,22 @@
+/*jshint browser:true, jquery:true */
+( function ( $ ) {
+       'use strict';
+
+       $( document ).ready( function () {
+               $( 'button' ).click( function () {
+                       $( '.definition' ).empty();
+                       var word = $( 'input[name=word]' ).val(),
+                               from = $( 'input[name=sourceLanguage]' ).val(),
+                               to = $( 'input[name=targetLanguage]' ).val();
+                       $.get( word + '/' + from + '/' + to, function ( 
response ) {
+                               $.each( response.definitions, function ( index, 
definition ) {
+                                       $( '.definition' ).append( 
definition.def );
+                                       $( '.definition' ).append( '\n' );
+                                       $( '.definition' ).append( 
definition.db.desc );
+                                       $( '.definition' ).append( '\n\n' );
+                               } );
+                               $( 'progress' ).hide();
+                       } );
+               } );
+       } );
+}( jQuery ) );

-- 
To view, visit https://gerrit.wikimedia.org/r/134074
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I138b5d457ce46c5bfe4e760d95f29c3adf25abfd
Gerrit-PatchSet: 3
Gerrit-Project: mediawiki/services/cxserver
Gerrit-Branch: master
Gerrit-Owner: Santhosh <santhosh.thottin...@gmail.com>
Gerrit-Reviewer: Divec <da...@sheetmusic.org.uk>
Gerrit-Reviewer: KartikMistry <kartik.mis...@gmail.com>
Gerrit-Reviewer: Santhosh <santhosh.thottin...@gmail.com>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to