{"id":36796001,"url":"https://github.com/efischer19/reactifex","last_synced_at":"2026-01-12T13:30:00.795Z","repository":{"id":57348124,"uuid":"124269907","full_name":"efischer19/reactifex","owner":"efischer19","description":"Helper utility designed to make it easy to upload react-intl extracted messages to transifex, with support for ICU plurals and translator comments.","archived":false,"fork":false,"pushed_at":"2023-08-28T10:19:39.000Z","size":18,"stargazers_count":1,"open_issues_count":1,"forks_count":4,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-11-27T10:05:12.722Z","etag":null,"topics":["icu-plurals","react-intl","transifex","transifex-api","translator-comments"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/efischer19.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-03-07T17:20:45.000Z","updated_at":"2019-06-25T19:43:31.000Z","dependencies_parsed_at":"2024-06-18T20:12:55.175Z","dependency_job_id":"b728163f-f96b-492f-9c9a-5340771fae97","html_url":"https://github.com/efischer19/reactifex","commit_stats":{"total_commits":12,"total_committers":1,"mean_commits":12.0,"dds":0.0,"last_synced_commit":"42ff3cc97c6fe8562f9bb403c0687b03cd8c4b13"},"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/efischer19/reactifex","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/efischer19%2Freactifex","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/efischer19%2Freactifex/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/efischer19%2Freactifex/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/efischer19%2Freactifex/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/efischer19","download_url":"https://codeload.github.com/efischer19/reactifex/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/efischer19%2Freactifex/sbom","scorecard":{"id":368368,"data":{"date":"2025-08-11","repo":{"name":"github.com/efischer19/reactifex","commit":"42ff3cc97c6fe8562f9bb403c0687b03cd8c4b13"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.5,"checks":[{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":0,"reason":"Found 0/12 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 8 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-18T12:24:44.660Z","repository_id":57348124,"created_at":"2025-08-18T12:24:44.660Z","updated_at":"2025-08-18T12:24:44.660Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28339118,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-12T12:22:26.515Z","status":"ssl_error","status_checked_at":"2026-01-12T12:22:10.856Z","response_time":98,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["icu-plurals","react-intl","transifex","transifex-api","translator-comments"],"created_at":"2026-01-12T13:30:00.090Z","updated_at":"2026-01-12T13:30:00.776Z","avatar_url":"https://github.com/efischer19.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# reactifex\n\nHelper utility designed to make it easy to upload react-intl extracted messages to transifex, with support for ICU plurals and translator comments.\n\n[![dependencies](https://img.shields.io/badge/dependencies-none-brightgreen.svg)](reactifex)\n[![license](https://img.shields.io/npm/l/reactifex.svg)](reactifex)\n[![npm_version](https://img.shields.io/npm/v/reactifex.svg)](reactifex)\n[![Build Status](https://travis-ci.org/efischer19/reactifex.svg?branch=master)](https://travis-ci.org/efischer19/reactifex)\n\n\nThere are two modes of usage - compilation and comment pushing.\n\n## Compilation mode\n\nIn 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.\n\nusage: `$(npm bin)/reactifex \u003cinput_folder\u003e \u003coutput_file\u003e`\n  - `input_folder` corresponds to the `messagesDir` option used by `babel-plugin-react-intl`\n    - note that reactifex assumes folder structure based on this default\n  - `output_file` will be suitable for upload to transifex\n\n## Comment pushing\n\nThis 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).\n\nUsage 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:\n\n```\ntx_url1 = https://www.transifex.com/api/2/project/\u003cproject\u003e/resource/\u003cresource\u003e/translation/\u003cdefault_language_code\u003e/strings/\ntx_url2 = https://www.transifex.com/api/2/project/\u003cproject\u003e/resource/\u003cresource\u003e/source/\npush_translations:\n    ./node_modules/reactifex/bash_scripts/get_hashed_strings.sh $(tx_url1)\n    $$(npm bin)/reactifex \u003cinput_folder\u003e --comments\n    ./node_modules/reactifex/bash_scripts/put_comments.sh $(tx_url2)\n```\n\n  - [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.\n\n  - 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`.\n\n  - 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 save these pairs in a '|'-delimited list, for later consumption.\n\n  - Finally, `bash_scripts/put_comments.sh` is run with the base PUT url as an argument (also reads the data file we created in the previous step), updating translator comments for each message on Transifex via their API.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fefischer19%2Freactifex","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fefischer19%2Freactifex","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fefischer19%2Freactifex/lists"}