Skip to content

Commit

Permalink
feat/ support plural forms
Browse files Browse the repository at this point in the history
  • Loading branch information
mrblueblue committed Nov 27, 2015
1 parent 7ab2760 commit f5d12f2
Show file tree
Hide file tree
Showing 8 changed files with 234 additions and 21 deletions.
2 changes: 1 addition & 1 deletion assets/coffee/example.coffee
Expand Up @@ -8,4 +8,4 @@ bar = __('translate me')

__('sdf')
__('e s')
__('sdssdsds')
__('%d sdssdsds')
55 changes: 55 additions & 0 deletions src/utils/buildMessageBlocks.js
@@ -0,0 +1,55 @@
import path from 'path';
import makeRelativePath from './makeRelativePath';
import isPluralForm from './isPluralForm';

import {
join,
concat as cat,
reduce,
last,
takeLast,
compose as cx,
map,
head,
split,
range
} from 'ramda';

const root = process.env.PWD;
const config = require(path.join(root, 'gettext.config.js'));

export const buildMsgtr = map((num) => `msgtr[${num}] ""\n`)
export const buildMsgtrs = (num) => cx(join(''), buildMsgtr)(range(0, num))
export const getNumPlurals = cx(parseInt, last, head, split(';'))

export const formatMessageBlock = (accum, translation) => {
const path = makeRelativePath(translation.path);

const translationBlock = cat(
`#: ${path} ${translation.loc.line}:${translation.loc.column}\n`,
`msgid "${translation.text}"`
)

if (isPluralForm(translation.text)){
const msgstrs = cx(
buildMsgtrs,
getNumPlurals
)(config.header['Plural-Forms'])

return cx(
cat(accum),
cat(translationBlock),
cat('\n'),
cat(msgstrs),
)('\n');
}

return cx(
cat(accum),
cat(translationBlock),
cat('\n'),
cat('msgtr ""\n'),
)('\n');
}

export default reduce(formatMessageBlock, '')
16 changes: 0 additions & 16 deletions src/utils/formatMessageBlock.js

This file was deleted.

4 changes: 2 additions & 2 deletions src/utils/formatWithRequest.js
@@ -1,9 +1,9 @@
import {compose} from 'ramda';
import addFilePath from './addFilePath';
import formatMessageBlock from './formatMessageBlock';
import buildMessageBlocks from './buildMessageBlocks';

const formatWithRequest = (request) => compose(
formatMessageBlock,
buildMessageBlocks,
addFilePath(request)
)

Expand Down
3 changes: 2 additions & 1 deletion src/utils/index.js
@@ -1,9 +1,10 @@
export addFilePath from './addFilePath';
export buildMessageBlocks from './buildMessageBlocks';
export extractTranslations from './extractTranslations';
export formatHeader from './formatHeader';
export formatMessageBlock from './formatMessageBlock';
export formatWithRequest from './formatWithRequest';
export getFilename from './getFilename';
export getFolderPath from './getFolderPath';
export isPluralForm from './isPluralForm';
export makeRelativePath from './makeRelativePath';
export parseECMA from './parseECMA';
6 changes: 6 additions & 0 deletions src/utils/isPluralForm.js
@@ -0,0 +1,6 @@
import {compose, any, equals, split} from 'ramda';

export default compose(
any(equals('%')),
split('')
)
167 changes: 167 additions & 0 deletions test/buildMessageBlocks.spec.js
@@ -0,0 +1,167 @@
import {expect} from 'chai';
import {range} from 'ramda'
import {
buildMsgtr,
buildMsgtrs,
getNumPlurals,
formatMessageBlock,
} from '../src/utils/buildMessageBlocks';

import buildMessageBlocks from '../src/utils/buildMessageBlocks';

describe('buildMessageBlocks', () => {

it('builds a message block for a po file', () => {

let translations = [
{
text: 'hey',
path: '/here',
loc: {
line: 1,
column: 5
}
},
{
text: 'thank you',
path: '/here',
loc: {
line: 1,
column: 5
}
},
{
text: 'how are you',
path: '/here',
loc: {
line: 1,
column: 5
}
}
]

const expected = [
'#: /here 1:5\n',
'msgid "hey"\n',
'msgtr ""\n',
"\n",
'#: /here 1:5\n',
'msgid "thank you"\n',
'msgtr ""\n',
"\n",
'#: /here 1:5\n',
'msgid "how are you"\n',
'msgtr ""\n\n'
]

const formatted = buildMessageBlocks(translations);
expect(formatted).to.be.deep.equal(expected.join(''));
});

it('takes into account plural forms', () => {
let translations = [
{
text: 'hey',
path: '/here',
loc: {
line: 1,
column: 5
}
},
{
text: '%d views',
path: '/here',
loc: {
line: 1,
column: 5
}
}
]

const expected = [
'#: /here 1:5\n',
'msgid "hey"\n',
'msgtr ""\n',
"\n",
'#: /here 1:5\n',
'msgid "%d views"\n',
'msgtr[0] ""\n',
'msgtr[1] ""\n\n'
]

const formatted = buildMessageBlocks(translations);

expect(formatted).to.be.deep.equal(expected.join(''));
});

describe('buildMsgtr', () => {

it('builds a msgstr in a po file', () => {
let ouput = ['msgtr[0] ""\n', 'msgtr[1] ""\n'];
expect(buildMsgtr([0,1])).to.be.deep.equal(ouput);
});
});

describe('buildMsgtrs', () => {
it('builds an array of msgstr\'s given a range', () => {
let ouput = ['msgtr[0] ""\n', 'msgtr[1] ""\n', 'msgtr[2] ""\n', 'msgtr[3] ""\n'];
expect(buildMsgtrs(4)).to.be.deep.equal(ouput.join(''));
});
});

describe('getNumPlurals', () => {
it('determines the number of plural forms given a config', () => {
let config = 'nplurals=2; plural=(n != 1);'
expect(getNumPlurals(config)).to.be.equal(2);
});
});

describe('formatMessageBlock', () => {
it('takes an object, formats it, adds to and returns accumulator', () => {

let translation = {
text: 'hello',
path: '/here',
loc: {
line: 1,
column: 5
}
}

const expected = [
'#: /here 1:5',
'msgid "hello"',
'msgtr ""',
'\n'
]

const formatted = formatMessageBlock('', translation);

expect(formatted).to.be.equal(expected.join('\n'));
});

it('formats plural text properly', () => {

let translation = {
text: '%d views',
path: '/here',
loc: {
line: 1,
column: 5
}
}

const expected = [
'#: /here 1:5',
'msgid "%d views"',
'msgtr[0] ""',
'msgtr[1] ""\n\n'
]

const formatted = formatMessageBlock('', translation);

expect(formatted).to.be.equal(expected.join('\n'));
});
});

});
2 changes: 1 addition & 1 deletion webpack.config.js
Expand Up @@ -12,7 +12,7 @@ module.exports = {
{ test: /\.jst/, loaders: ['gettext-loader','dot-loader'] },
{ test: /\.jsx?$/, loaders: ['babel-loader', 'gettext-loader'] },
{ test: /\.js?$/, loaders: ['gettext-loader'] },
{ test: /\.coffee/, loaders: ['gettext-loader','coffee-loader'] }
{ test: /\.coffee/, loaders: ['gettext-loader', 'coffee-loader'] }
]
},

Expand Down

0 comments on commit f5d12f2

Please sign in to comment.