-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Oleg Klimenko
committed
Jul 28, 2017
1 parent
da4ac0c
commit 9e100cf
Showing
4 changed files
with
206 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
import { I18NEntry, SingleI18NEntry, PluralI18NEntry } from 'i18n-proto'; | ||
|
||
export type Metadata = { | ||
copyrightSubject: string, | ||
bugsEmail: string, | ||
year: number | ||
}; | ||
|
||
export function makeDate(date: Date) { | ||
const timezoneShift = date.getTimezoneOffset() / -60; | ||
let tz = 'Z'; | ||
if (timezoneShift !== 0) { | ||
tz = (timezoneShift > 0 ? '+' : '-') + | ||
(timezoneShift > 9 ? '' : '0') | ||
+ timezoneShift + '00'; | ||
} | ||
|
||
return date.getFullYear() + '-' + | ||
(date.getMonth() > 9 ? '' : '0') + date.getMonth() + '-' + | ||
(date.getDay() > 9 ? '' : '0') + date.getDay() + ' ' + | ||
(date.getHours() > 9 ? '' : '0') + date.getHours() + ':' + | ||
(date.getMinutes() > 9 ? '' : '0') + date.getMinutes() + | ||
tz; | ||
} | ||
|
||
export function convert(json: string, meta: Metadata): string { | ||
const document: I18NEntry[] = JSON.parse(json); | ||
let poEntries: PotEntry[] = []; | ||
|
||
// 1) Make POT header | ||
let poHeader = | ||
`# Translations template for PROJECT. | ||
# Copyright (C) ${meta.year} ${meta.copyrightSubject} | ||
# This file is distributed under the same license as the PROJECT project. | ||
# FIRST AUTHOR <EMAIL@ADDRESS>, ${meta.year}. | ||
# | ||
#, fuzzy | ||
msgid "" | ||
msgstr "" | ||
"Project-Id-Version: PROJECT VERSION\\n" | ||
"Report-Msgid-Bugs-To: ${meta.bugsEmail}\\n" | ||
"POT-Creation-Date: ${makeDate(new Date())}\\n" | ||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\\n" | ||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\\n" | ||
"Language-Team: LANGUAGE <LL@li.org>\\n" | ||
"MIME-Version: 1.0\\n" | ||
"Content-Type: text/plain; charset=utf-8\\n" | ||
"Content-Transfer-Encoding: 8bit\\n" | ||
"Generated-By: i18n-json2po\\n" | ||
`; | ||
|
||
// 2) Make POT entries | ||
for (let item of document) { | ||
let potEntry = new PotEntry(); | ||
if (item.type === 'single') { | ||
potEntry.parseSingleEntry(item); | ||
} | ||
if (item.type === 'plural') { | ||
potEntry.parsePluralEntry(item); | ||
} | ||
poEntries.push(potEntry); | ||
} | ||
|
||
return poHeader + poEntries | ||
.map((entry) => entry.asString()) | ||
.join("\n\n"); | ||
} | ||
|
||
export class PotEntry { | ||
private items: string[] = []; | ||
|
||
protected addComment = (comment: string) => this.items.push('#. ' + comment); | ||
protected addOccurence = (occ: string) => this.items.push('#: ' + occ); | ||
protected addContext = (context: string) => this.items.push('msgctxt ' + JSON.stringify(context)); | ||
protected addMsgid = (id: string) => this.items.push('msgid ' + JSON.stringify(id)); | ||
protected addMsgidPlural = (id: string) => this.items.push('msgid_plural ' + JSON.stringify(id)); | ||
protected addMsgstr = () => this.items.push('msgstr ""'); | ||
protected addMsgstrPlural = (count: number) => { | ||
for (let i = 0; i < count; i++) { | ||
this.items.push('msgstr[' + i + '] ""'); | ||
} | ||
}; | ||
|
||
public asString = () => this.items.join("\n"); | ||
|
||
public parseSingleEntry({ entry, comments, occurences, context, type }: SingleI18NEntry) { | ||
if (comments) { | ||
comments.forEach(this.addComment); | ||
} | ||
|
||
if (occurences) { | ||
occurences.forEach(this.addOccurence); | ||
} | ||
|
||
if (context) { | ||
this.addContext(context); | ||
} | ||
|
||
if (type === 'single') { | ||
this.addMsgid(entry); | ||
this.addMsgstr(); | ||
} | ||
} | ||
|
||
public parsePluralEntry({ entry, comments, occurences, context, type }: PluralI18NEntry) { | ||
if (comments) { | ||
comments.forEach(this.addComment); | ||
} | ||
|
||
if (occurences) { | ||
occurences.forEach(this.addOccurence); | ||
} | ||
|
||
if (context) { | ||
this.addContext(context); | ||
} | ||
|
||
if (type === 'plural') { | ||
this.addMsgid(entry[0]); | ||
this.addMsgidPlural(entry[entry.length - 1]); | ||
this.addMsgstrPlural(entry.length); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import * as cli from 'cli'; | ||
import { readFile, writeFile } from 'fs'; | ||
import { convert } from './convert'; | ||
|
||
const options = cli.parse({ | ||
src: ['s', 'A source JSON file to process', 'string', '__stdin'], | ||
output: ['o', 'Output JSON file', 'string', '__stdout'], | ||
copyrightSubject: ['c', 'Copyright for generated POT file', 'string', ''], | ||
bugsEmail: ['b', 'Email for bugs', 'string', ''], | ||
year: ['y', 'Copyright year', 'number', (new Date()).getFullYear()], | ||
help: ['h', 'Show some help', 'bool', false] | ||
}); | ||
|
||
if (options.help) { | ||
console.log(`i18n JSON -> POT converter | ||
Options: | ||
-h / --help Show this help | ||
-s / --src FILE Define input JSON file name. Defaults | ||
to stdin. | ||
-o / --output FILE Define output POT file name. If a file | ||
already exists, it's contents will be | ||
overwritten. Defaults to stdout. | ||
-c / --copyrightSubject Team name or author name. | ||
-b / --bugsEmail Email for sending bugs | ||
-y / --year Copyright year, defaults to current year. | ||
`); | ||
process.exit(0); | ||
} | ||
|
||
console.warn('Running conversion for file: ', options.src); | ||
|
||
const meta = { | ||
copyrightSubject: options.copyrightSubject, | ||
bugsEmail: options.bugsEmail, | ||
year: options.year, | ||
}; | ||
|
||
if (options.src === '__stdin') { | ||
cli.withStdin((data) => { | ||
try { | ||
makeOutput(convert(data, meta), options.output); | ||
} catch (e) { | ||
console.error(e); | ||
process.exit(1); | ||
} | ||
}); | ||
} else { | ||
readFile(options.src, { encoding: 'utf-8' }, (err, data) => { | ||
if (err) { | ||
console.error(err); | ||
process.exit(1); | ||
} | ||
try { | ||
makeOutput(convert(data, meta), options.output); | ||
} catch (e) { | ||
console.error(e); | ||
process.exit(1); | ||
} | ||
}); | ||
} | ||
|
||
function makeOutput(data: string, output: string) { | ||
if (output === '__stdout') { | ||
console.log(data); | ||
} else { | ||
writeFile(output, data, (e) => { | ||
if (e) { | ||
console.error(e); | ||
process.exit(1); | ||
} | ||
process.exit(0); // success | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters