Skip to content

Commit 40c10ad

Browse files
author
Eric Fischer
authored
Add functionality to update comments (#8)
Implements comment pushing mode, with documentation.
1 parent 9fe7349 commit 40c10ad

File tree

6 files changed

+61
-3
lines changed

6 files changed

+61
-3
lines changed

README.md

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,45 @@
11
# reactifex
22

3+
Helper utility designed to make it easy to upload react-intl extracted messages to transifex, with support for ICU plurals and translator comments.
4+
35
[![dependencies](https://img.shields.io/badge/dependencies-none-brightgreen.svg)](reactifex)
46
[![license](https://img.shields.io/npm/l/reactifex.svg)](reactifex)
57
[![npm_version](https://img.shields.io/npm/v/reactifex.svg)](reactifex)
68
[![Build Status](https://travis-ci.org/efischer19/reactifex.svg?branch=master)](https://travis-ci.org/efischer19/reactifex)
79

8-
Helper utility designed to make it easy to upload react-intl extracted messages to transifex, with support for ICU plurals and translator comments.
10+
11+
There are two modes of usage - compilation and comment pushing.
12+
13+
## Compilation mode
14+
15+
In this mode, messages that have been extracted by `babel-plugin-react-intl` (into individual files) are combined. The resulting json is suitable to upload to Transifex and matches their specified `KEYVALUEJSON` format.
916

1017
usage: `$(npm bin)/reactifex <input_folder> <output_file>`
1118
- `input_folder` corresponds to the `messagesDir` option used by `babel-plugin-react-intl`
1219
- note that reactifex assumes folder structure based on this default
1320
- `output_file` will be suitable for upload to transifex
21+
22+
## Comment pushing
23+
24+
This mode is why I wrote this library in the first place - I wanted the ability to use comments as `PO` files do, but none of the tools I found to convert react-intl messages to `PO` files were able to properly handle ICU pluralization. By keeping everything in a js context with `KEYVALUEJSON`, plurals work correctly *and* we now have comment support for translators (by default, Transifex's `KEYVALUEJSON` file format does not allow for comments to be included with strings for translation).
25+
26+
Note that tests for this mode aren't included, as it relies on Transifex's API being up and responsive.
27+
28+
Usage is a little complicated, I'm sorry about that; you're going to be running this server-side as a series of bash commands. Do note that I assume `$SECRET_USER` and `$SECRET_PWD` env vars exist for basic auth purposes. See [Transifex's API Introduction](https://docs.transifex.com/api/introduction) for more details on authentication. Here's an example, written as it would be in the Makefile of a project that makes use of reactifex:
29+
30+
```
31+
tx_url1 = https://www.transifex.com/api/2/project/<project>/resource/<resource>/translation/<default_language_code>/strings/
32+
tx_url2 = https://www.transifex.com/api/2/project/<project>/resource/<resource>/source/
33+
push_translations:
34+
./node_modules/reactifex/bash_scripts/get_hashed_strings.sh $(tx_url1)
35+
$$(npm bin)/reactifex <input_folder> --comments
36+
./node_modules/reactifex/bash_scripts/put_comments.sh $(tx_url2)
37+
```
38+
39+
- [tx_url1](https://docs.transifex.com/api/translation-strings#identifying-strings-using-hashes) and [tx_url2](https://docs.transifex.com/api/resource-strings) are just variables as defined by the Transifex API documentation, extracted for readability.
40+
41+
- First, `bash_scripts/get_hashed_strings.sh` is called with a url argument. This will populate `bash_scripts/hashmap.json` with data about the strings in your resource, including the all-important `string_hash`.
42+
43+
- Next, the main reactifex script (node js) runs with an additional `--comments` flag, and no output file. This has the effect of gathering up all your `babel-plugin-react-intl` extracted messages *with* their comments attached. From there, it's simple enough to match up each message with its `string_hash`, and makes it possible to generate `bash_scripts/put_comments.sh` (a series of curl requests, one per message)
44+
45+
- Finally, `bash_scripts/put_comments.sh` is run with the base PUT url as an argument (we generated the specific `string_hash` portion in the previous step), updating translator comments for each message on Transifex via their API.

bash_scripts/get_hashed_strings.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/bash
2+
3+
curl -L --user $SECRET_USER:$SECRET_PWD -X GET $1 > $(dirname $0)/hashmap.json

bash_scripts/hashmap.json

Whitespace-only changes.

bash_scripts/put_comments.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#!/bin/bash

main.js

100644100755
Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,26 @@ var outData = {};
1919
inData.forEach((message) => {
2020
outData[message["id"]] = message["defaultMessage"];
2121
});
22-
fs.writeFileSync(process.argv[3], JSON.stringify(outData, null, 2));
22+
23+
if (process.argv[3] === "--comments") {
24+
process.stdout.write("generating bash scripts...\n");
25+
var messageInfo = JSON.parse(fs.readFileSync(__dirname + "/bash_scripts/hashmap.json"));
26+
var scriptPath = __dirname + "/bash_scripts/put_comments.sh";
27+
fs.writeFileSync(scriptPath, "#!/bin/bash\n");
28+
fs.writeFileSync(scriptPath, "set -x\n");
29+
inData.forEach((message) => {
30+
var info = messageInfo.find(mi => mi.key == message.id);
31+
if (info) {
32+
var header = " -H \"Content-Type: application/json\"";
33+
var escapedDescription = message.description.replace(/(["])/g, "\\\\\\$1");
34+
var data = " --data \"{\\\"comment\\\": \\\"" + escapedDescription + "\\\"}\"";
35+
var url = " $1" + info.string_hash;
36+
fs.appendFileSync(scriptPath, "curl -L -w \"\\n\" --user $SECRET_USER:$SECRET_PWD -X PUT" + header + data + url + "\n");
37+
} else {
38+
process.stdout.write("string " + message.id + " does not yet exist on transifex!\n");
39+
}
40+
});
41+
fs.writeFileSync(scriptPath, "set +x\n");
42+
} else {
43+
fs.writeFileSync(process.argv[3], JSON.stringify(outData, null, 2));
44+
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "reactifex",
3-
"version": "0.0.2",
3+
"version": "1.0.0",
44
"description": "A helper for moving react-intl messages to transifex and back",
55
"bin": "./main.js",
66
"scripts": {

0 commit comments

Comments
 (0)