Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
zakkudo committed Feb 19, 2019
1 parent 03c6777 commit 6839627
Show file tree
Hide file tree
Showing 16 changed files with 837 additions and 85 deletions.
50 changes: 50 additions & 0 deletions src/LocaleDirectory.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
const fs = require('fs');
const path = require('path');
const PO = require('./PO');
const JSON = require('./JSON');
const JSON5 = require('./JSON5');
const CSV = require('./CSV');

const formatHandler = new Map([
['po', PO],
['json', JSON],
['json5', JSON5],
['csv', CSV],
]);

class LocaleDirectory {
constructor(directoryPath) {
this.directoryPath = directoryPath;
}

buildFilename(locale, format) {
const basename = [locale, format].filter(p => p).join('.');

return path.resolve(this.directoryPath, `${basename}`);
}

writeFile(locale, localization, format) {
const filename = this.buildFilename(locale, format);
const handler = formatHandler.get(format);
const data = handler.stringify(localization);

fs.writeSync(filename, data);
}

readFile(locale, format) {
const filename = this.buildFilename(locale, format);
const handler = formatHandler.get(format);
const data = fs.readSync(filename);

return handler.parse(data);
}

normalizeTo(format) {
formatHandler.entries().forEach(([extension, handler]) => {
if (extension !== format) {
}
});
}
}

module.exports = LocaleDirectory;
4 changes: 4 additions & 0 deletions src/formats/CSV.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
class CSV {
}

module.exports = CSV;
4 changes: 4 additions & 0 deletions src/formats/JSON.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
class JSON {
}

module.exports = JSON;
4 changes: 4 additions & 0 deletions src/formats/JSON5.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
class JSON5 {
}

module.exports = JSON5;
56 changes: 56 additions & 0 deletions src/formats/PO.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
TODO Need to parse comments like /**/ and //
class PO {
static read(locale, string) {
}

static write(locale, string) {
}
}
/*
///* This is the first comment. */
//gettext ("foo");
//
///* This is the second comment: not extracted */
//gettext (
//"bar");
//
//gettext (
///* This is the third comment. */
//"baz");
/*
*
*
*
white-space
# translator-comments
#. extracted-comments
#: reference…
#, flag…
#| msgid previous-untranslated-string
msgid untranslated-string
msgstr translated-string
#. NEW
#: lib/error.c:116
msgctxt "Context"
msgid "Unknown system error"
msgstr ""
"<b>Tip</b><br/>Some non-Meade telescopes support a subset of the LX200 "
"command set. Select <tt>LX200 Basic</tt> to control such devices."
msgstr ""
#: ../src/waei/application.c:140 ../src/gwaei/application.c:234
#, kde-format
msgid "Time: %1 second"
msgid_plural "Time: %1 seconds"
msgstr[0] ""
msgstr[1] ""
#~ msgid "Set the telescope longitude and latitude."
#~ msgstr "Postavi geo. dužinu i širinu teleskopa."
*/

module.exports = PO;
15 changes: 15 additions & 0 deletions src/isCommentCharacter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const commentCharacters = new Set([
"/*",
"//"
]);

/**
* Conveneince function to check for comment character patterns
* @param {String} character - A character to check in the comment list
* @return {Boolean} true if the character will cause characters after it to
* not execute their usual meaning.
* @private
*/
module.exports = function isCommentCharacter(character) {
return commentCharacters.has(character);
}
14 changes: 14 additions & 0 deletions src/isCommentStartCharacter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const commentCharacters = new Set([
"//",
'/*'
]);

/**
* Convenience method for checking for comment characters.
* @param {String} character - A character pattern to check if is a comment
* @return {Boolean} True if it is a comment character for javascript
* @private
*/
module.exports = function isCommentStartCharacter(character) {
return commentCharacters.has(character);
}
7 changes: 2 additions & 5 deletions src/isWhiteSpaceCharacter.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
const whiteSpaceCharacters = new Set([
' ',
' ',
]);
const pattern = new RegExp(/^\s$/);

/**
* Checks for coding whitespace characters
Expand All @@ -11,5 +8,5 @@ const whiteSpaceCharacters = new Set([
* @private
*/
module.exports = function isWhiteSpaceCharacter(character) {
return whiteSpaceCharacters.has(character);
return pattern.test(character);
}
143 changes: 107 additions & 36 deletions src/parseLocalizationFunction.js
Original file line number Diff line number Diff line change
@@ -1,40 +1,79 @@
const isQuoteCharacter = require('./isQuoteCharacter');
const isWhiteSpaceCharacter = require('./isWhiteSpaceCharacter');
const isCommentStartCharacter = require('./isCommentStartCharacter');
const peek = require('./peek');
const peekUntil = require('./peekUntil');

function isComment(currentIterator, nextIterator) {
const {stack, character} = nextIterator;
const head = stack[0];

return isCommentStartCharacter(head) || (currentIterator.stack[0] === '/*' && character === '*/');
}

/**
* @private
*/
function continueToQuoteStart(text, state) {
const readCharacter = require('./readCharacter');

while ((state = readCharacter(text, state)) !== null) {
const character = text.charAt(state.index);
function continueToQuoteStart(text, iterator) {
iterator = peekUntil(text, iterator, (currentIterator, nextIterator) => {
const {stack, character} = nextIterator;
const head = stack[0];

if (isQuoteCharacter(state.stack[0])) {
break;
if (isQuoteCharacter(currentIterator.stack[0])) {
return false;
}

if (!isQuoteCharacter(character) && !isWhiteSpaceCharacter(character)) {
if (!isQuoteCharacter(head) && !isComment(currentIterator, nextIterator) && !isWhiteSpaceCharacter(character)) {
throw new SyntaxError('localization key must be a literal');
}
}

return state;
return true;
});

return iterator;
}

/**
* @private
*/
function continueUntilStackLengthIs(text, state, length) {
function continueUntilStackLengthIs(text, iterator, length) {
const readCharacter = require('./readCharacter');

while ((state = readCharacter(text, state)) !== null) {
if (state.stack.length <= length) {
while ((iterator = readCharacter(text, iterator)) !== null) {
if (iterator.stack.length <= length) {
break;
}
}

return state;
return iterator;
}

function readPossibleComment(text, iterator) {
const initialState = iterator;
const initialStackSize = initialState.stack.length;
let comment = [];

iterator = peekUntil(text, iterator, (currentIterator, nextIterator) => {
if (isCommentStartCharacter(nextIterator.character)) {
comment.unshift('');
}

if (nextIterator.comment) {
comment[0] = nextIterator.comment;
}

if (nextIterator.stack.length < initialStackSize) {
return false;
}

return true;
});

if (comment.length) {
return comment.filter(c => c).reverse().join('\n');
}

return null;
}

function readStringArgument(text, {index, stack, lineNumber}, name) {
Expand All @@ -49,6 +88,15 @@ function readStringArgument(text, {index, stack, lineNumber}, name) {
return [end, stringArgument];
}

function forceIncrement(text, iterator, count = 1) {
const nextIndex = iterator.index + count;

return Object.assign({}, iterator, {
index: nextIndex,
character: text.charAt(nextIndex - 1),
});
}

/**
* Parses the information from a localization function, include the function string,
* the key, the line number. Parses __, __n, __p, __np.
Expand All @@ -60,44 +108,67 @@ function readStringArgument(text, {index, stack, lineNumber}, name) {
* as the new index after the translation function
* @private
*/
module.exports = function parseLocalizationFunction(text, {index, stack, lineNumber}) {
const functionStart = {index, stack, lineNumber};
module.exports = function parseLocalizationFunction(text, iterator) {
const functionStart = iterator;
const initialStackSize = iterator.stack.length;
let plural = false;
let particular = false;
let fn = '__';

index += 1;
iterator = forceIncrement(text, iterator, 2);

if (text.charAt(index + 1) === 'n') {
plural = true;
index += 1;
}
iterator = peek(text, iterator, (nextIterator) => {
if (nextIterator.character === 'n') {
fn += 'n';
plural = true;
return true;
}
});

if (text.charAt(index + 1) === 'p') {
particular = true;
index += 1;
}
iterator = peek(text, iterator, (nextIterator) => {
if (nextIterator.character === 'p') {
fn += 'p';
particular = true;
return true;
}
});

if (text.charAt(index + 1) === '(') {
index += 1;
}
iterator = peek(text, iterator, (nextIterator) => {
return nextIterator.character === '(';
});

const metadata = {plural, particular};
let state = {index, stack, lineNumber};
const comment = readPossibleComment(text, iterator);

if (particular) {
let context;
[state, context] = readStringArgument(text, state, 'context');

[iterator, context] = readStringArgument(text, iterator, 'context');
metadata.context = context;

iterator = peekUntil(text, iterator, (currentIterator, nextIterator) => {
return isWhiteSpaceCharacter(nextIterator.character);
});

iterator = peek(text, iterator, (nextIterator) => {
return nextIterator.character === ',';
});
}

let key;
[state, key] = readStringArgument(text, state, 'key');
[iterator, key] = readStringArgument(text, iterator, 'key');
metadata.key = key;

const functionEnd = (state.stack[0] === '(') ?
continueUntilStackLengthIs(text, {...state}, state.stack.length - 1) : state;
const fn = text.substring(functionStart.index, functionEnd.index);
metadata.fn = fn;
const functionEnd = (iterator.stack[0] === '(') ?
continueUntilStackLengthIs(text, {...iterator}, initialStackSize) : iterator;
const character = text.substring(functionStart.index, functionEnd.index);
fn += `(${[metadata.context, key].filter(a => a).map(a => JSON.stringify(a)).join(',')})`;

const output = Object.assign({}, functionEnd, metadata, {character, fn});

if (comment) {
output.comment = comment;
}

return Object.assign({}, functionEnd, metadata);
return output;
}
5 changes: 5 additions & 0 deletions src/parseLocalizationFunction.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const parseLocalizationFunction = require('./parseLocalizationFunction');

describe('parseLocalizationFunction', () => {
});

13 changes: 13 additions & 0 deletions src/peek.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

function peek(text, iterator, fn) {
const readCharacter = require('./readCharacter');
const nextIterator = readCharacter(text, iterator);

if (fn(nextIterator)) {
return nextIterator;
}

return iterator;
}

module.exports = peek;

0 comments on commit 6839627

Please sign in to comment.