{"id":46405120,"url":"https://github.com/64bit-polygon/raven-writer","last_synced_at":"2026-03-05T12:01:28.175Z","repository":{"id":228105446,"uuid":"773135911","full_name":"64bit-polygon/raven-writer","owner":"64bit-polygon","description":"raven-writer is a utility to allow for easy translations and interpolations for projects using the popular POEditor localization service.","archived":false,"fork":false,"pushed_at":"2024-03-22T19:11:20.000Z","size":6395,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-31T13:05:50.810Z","etag":null,"topics":["localization","poeditor","translation"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/raven-writer","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/64bit-polygon.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2024-03-16T21:06:24.000Z","updated_at":"2024-03-22T21:39:07.000Z","dependencies_parsed_at":"2024-03-22T19:40:37.910Z","dependency_job_id":null,"html_url":"https://github.com/64bit-polygon/raven-writer","commit_stats":{"total_commits":8,"total_committers":1,"mean_commits":8.0,"dds":0.0,"last_synced_commit":"79f2d616d5fde0d9a5a97f2241493a15b0714091"},"previous_names":["64bit-polygon/raven-writer"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/64bit-polygon/raven-writer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/64bit-polygon%2Fraven-writer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/64bit-polygon%2Fraven-writer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/64bit-polygon%2Fraven-writer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/64bit-polygon%2Fraven-writer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/64bit-polygon","download_url":"https://codeload.github.com/64bit-polygon/raven-writer/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/64bit-polygon%2Fraven-writer/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30123709,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-05T11:11:57.947Z","status":"ssl_error","status_checked_at":"2026-03-05T11:11:29.001Z","response_time":93,"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":["localization","poeditor","translation"],"created_at":"2026-03-05T12:00:57.672Z","updated_at":"2026-03-05T12:01:28.160Z","avatar_url":"https://github.com/64bit-polygon.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# `raven-writer`\n \n`raven-writer` is a FE utility to allow for easy translations and interpolations for projects using the popular [POEditor](https://poeditor.com/) localization service.\n\nWhat `raven-writer` does:\n\n- GETs and caches localizations for your project\n- Refreshes those localizations at a given interval\n- Transforms simple markdown in your content into HTML strings\n- Allows for dynamic interpolation of string values into your content\n- Easily gets values by term\n\n---\n\n## Docs\n\n- [`Installation`](#install)\n- [`Quick start example`](#basic)\n- [`Instantiation`](#instantiation) - Creates the `POE instance`\n  - [`POE.fetchLocalizations({...})`](#fetchLocalizations) - Fetches and caches localizations\n  - [`POE.makeDictionary(language)`](#makeDictionary) - returns a dictionary function\n  - [`POE.localizations(language)`](#localizations) - returns the raw localizations\n  - [`POE.makeText(str, interpolations)`](#makeText) - helper method to add interpolations to any string value and transform simple markdown into an HTML string\n  - [`POE.kill()`](#kill) - Kills all refreshing of localizations on a `POE instance`\n- [`Dictionary(term, interpolations)`](#dictionary) - function that returns the value from a cached language\n- [`Content markdown and interpolation syntax`](#contentSyntax) - How your POEditor content should be written for MD and interpolations\n- [`Localizations structure`](#localizationsStructure)\n\n## \u003ca id=\"install\"\u003e\u003c/a\u003eInstall\n\n```\nnpm install raven-writer -S\n```\n\n## \u003ca id=\"basic\"\u003e\u003c/a\u003eQuick start example\n\nGiven the following POEditor project\n\n\u003cimg src=\"https://firebasestorage.googleapis.com/v0/b/react-portfolio-944de.appspot.com/o/raven-writer-POEditor.png?alt=media\u0026token=0fbac1cc-f3f2-4db5-a455-dfb38c94a66f\" /\u003e\n\nIn our project we have:\n- A language that is American english, which has a ISO 639-1 language code of `en-us`\n- A term `MY_KEY` that has a content value of `\"My value\"`\n- A second term `GREETING` that has a content value of `\"Hello, **{{name}}!**\"`\n  - Note that the value has `{{}}` to denote an interpolated value with the key `name`\n  - It also has `**` markdown indicating it should be bolded\n\n```js\nimport { Raven } from \"raven-writer\";\n\n// make the POE instance\nconst POE = new Raven();\n\n// load localizations into the instance\nawait POE.fetchLocalizations({\n  id: \"\u003cPOEDITOR_PROJECT_ID\u003e\",\n  token: \"\u003cYOUR_READ_ONLY_POEDITOR_API_TOKEN\u003e\",\n  languages: [\"en-us\"]\n});\n\n// make a dictionary\nconst Translate = POE.makeDictionary(\"en-us\");\n\n// Logs: \"My value\"\nconsole.log(Translate(\"MY_KEY\"));\n\n// Logs: \"Hello, \u003cb\u003eNate!\u003c/b\u003e\"\nconsole.log(Translate(\"GREETING\", {name: \"Nate\"}));\n```\n\n## \u003ca id=\"instantiation\"\u003e\u003c/a\u003eInstantiation\n\nIn most cases you'll instantiate the `POE instance` simply by calling `new Raven()`.\n\nYou can optionally pre-load the `POE instance` with localizations. You'd do this if you wanted\naccess to the `POE.makeDictionary(language)` functionality without having to make API calls.\nRefer to the [`localizations structure`](#localizationsStructure) if you want to do this.\n\n#### Props\n\n| Prop              | Type     | Required? | Description |\n| ----------------- | :------: | :-------: | ----------- |\n| **localizations** | `Object` |           | The preloaded [`localizations`](#localizationsStructure) |\n\n#### Returns\n\nA `POE instance` that has the following methods:\n\n```js\nPOE.getLocalizations(localizations);\nPOE.fetchLocalizations({id, token, languages, keepAlive, url});\nPOE.makeDictionary(language);\nPOE.makeText(string, interpolations);\nPOE.kill();\n```\n\n#### Usage\n\nMost common case\n\n```js\nimport { Raven } from \"raven-writer\";\nconst POE = new Raven();\n```\n\nOptional preloading\n\n```js\nimport { Raven } from \"raven-writer\";\n\nconst localizations = {\n  \"en-us\": {\n    \"GREETING\": \"Hi!\"\n  }\n};\n\nconst PRELOADED = new Raven(localizations);\nconst Translate = POE.makeDictionary(\"en-us\");\nconsole.log(Translate(\"GREETING\")); // Logs: \"Hi!\"\n```\n\n## \u003ca id=\"fetchLocalizations\"\u003e\u003c/a\u003e`POE.fetchLocalizations({...})`\n\nFetches and catches localizations.\n\n#### Props\n\n| Prop          | Type      | Required?               | Description |\n| ------------- | :-------: | :---------------------: | ----------- |\n| **token**     | `String`  | if `url` is `undefined` | The readonly `api_token` found in your [POEditor acct](https://poeditor.com/account/api) |\n| **id**        | `String`  | if `url` is `undefined` | The project `id` found in your [POEditor acct](https://poeditor.com/account/api) |\n| **languages** | `Array` of ISO 639-1 language codes | if `url` is `undefined` | The languages you want to fetch for the given project |\n| **keepAlive** | `Integer` |                         | If present the localizations will be refreshed per milliseconds defined this value |\n| **url**       | `String`  | if `url`, `id`, and `languages` are `undefined` | If present calls will be made to that url instead of hitting the POEditor endpoint |\n\n#### Returns\n\nA `promise` that once resolved will populate the `POE instance` with localizations.\n\n#### Usage\n\nMost common usage\n\n```js\nimport { Raven } from \"raven-writer\";\nconst tenMins = 1000 * 60 * 10;\nconst POE = new Raven();\nawait POE.fetchLocalizations({\n  id: \"\u003cPOEDITOR_PROJECT_ID\u003e\",\n  token: \"\u003cYOUR_READ_ONLY_POEDITOR_API_TOKEN\u003e\",\n  languages: [\"en-us\", \"sp_mx\"],\n  keepAlive: tenMins // optional\n});\n```\n\nOverwriting the endpoint\n\n```js\nimport { Raven } from \"raven-writer\";\nconst POE = new Raven();\nawait POE.fetchLocalizations({\n  url: \"\u003cYOUR_CUSTOM_GET_ENDPOINT\u003e\"\n});\n``` \n\n\u003cu\u003eNote\u003c/u\u003e: *the response from your endpoint **must** have the same structure as the [`localizations structure`](#localizationsStructure)*\n\n## \u003ca id=\"makeDictionary\"\u003e\u003c/a\u003e`POE.makeDictionary(language)`\n\nMakes a [`Dictionary function`](#dictionary) for a given language that has already been cached in the `POE instance`\n\n#### Props\n\n| Prop         | Type     | Required? | Description |\n| ------------ | :------: | :-------: | ----------- |\n| **language** | `String` |  yes      | A ISO 639-1 language code |\n\n#### Returns\n\nA [`Dictionary function`](#dictionary)\n\n#### Usage\n\n```js\nimport { Raven } from \"raven-writer\";\nconst POE = new Raven();\nawait POE.fetchLocalizations({..., languages: [\"en-us\", \"sp-mx\"]});\nconst enUsDictionary = POE.makeDictionary(\"en-us\");\nconst spMxDictionary = POE.makeDictionary(\"sp-mx\");\n```\n\n## \u003ca id=\"localizations\"\u003e\u003c/a\u003e`POE.getLocalizations(language)`\n\nReturns the raw localizations object. see: [`localizations structure`](#localizationsStructure).\n\n#### Props\n\n| Prop         | Type     | Required? | Description |\n| ------------ | :------: | :-------: | ----------- |\n| **language** | `String` | ✅        | A ISO 639-1 language code |\n\n#### Returns\n\nA [`localizations object`](#localizationsStructure)\n\n#### Usage\n\nAssume the cached localizations are the following:\n\n```json\n{\n  \"en-us\": {\n    \"GREETING\": \"Hello\"\n  },\n  \"sp-mx\": {\n    \"GREETING\": \"Hola\"\n  }\n}\n```\n\n```js\nimport { Raven } from \"raven-writer\";\nconst POE = new Raven();\nawait POE.fetchLocalizations({..., languages: [\"en-us\", \"sp_mx\"]});\nconsole.log(POE.getLocalizations()) // Logs the preceding full object\nconsole.log(POE.getLocalizations(\"sp_mx\")) // Logs { GREETING: \"Hola\" }\n```\n\n## \u003ca id=\"makeText\"\u003e\u003c/a\u003e`POE.makeText(str, interolations)`\n\nAdds interpolations and/or Markdown transformed into HTML string to a given string. See: [`Content markdown and interpolation syntax`](#contentSyntax).\n\n#### Props\n\n| Prop              | Type     | Required? | Description |\n| ------------------| :------: | :-------: | ----------- |\n| **str**           | `String` | ✅        | Any string value, ie not a POE term |\n| **interolations** | `Object` |           | An object with key names that match the dynamic content markers in the `str` |\n\n#### Returns\n\nA string with interpolations and Markdown transformed into HTML str (if applicable).\n\n#### Usage\n\n```js\nimport { Raven } from \"raven-writer\";\nconst POE = new Raven();\n\n// Logs: \"Plain text\"\nconsole.log(POE.makeText(\"Plain text\"));\n\n// Logs: \"Hello, Nate\"\nconsole.log(POE.makeText(\"Hello, {{name}}\", { name: \"Nate\" }));\n\n// Logs: \"Some \u003ci\u003eitalic text\u003c/i\u003e\"\nconsole.log(POE.makeText(\"Some *italic text*\"));\n\n// Logs: \"Hello, \u003cb\u003eNate\u003c/b\u003e\"\nconsole.log(POE.makeText(\"Hello, **{{name}}**\", { name: \"Nate\" }));\n```\n\n## \u003ca id=\"kill\"\u003e\u003c/a\u003e`POE.kill()`\n\nIf you call `POE.fetchLocalizations({...})` and set it to refresh localizations via `keepAlive`, this stops all refreshes on that instance.\n\n#### Returns\n\n`undefined`\n\n#### Usage\n\n```js\nimport { Raven } from \"raven-writer\";\nconst tenMins = 1000 * 1000 * 60 * 10;\nconst POE = new Raven();\nawait POE.fetchLocalizations({..., keepAlive: tenMins});\n...\nPOE.kill();\n```\n\n## \u003ca id=\"dictionary\"\u003e\u003c/a\u003e`Dictionary(term, interpolations)`\n\nThe function returns the localized content value of a term, optionally with injected interpolations. Markdown is transformed into HTML strings.\n\n#### Props\n\n| Prop              | Type     | Required? | Description |\n| ------------------| :------: | :-------: | ----------- |\n| **term**          | `String` | ✅        | Any string value, ie not a POE term |\n| **interolations** | `Object` |           | An object with key names that match the dynamic content markers for the content value associated with the term |\n\n#### Returns\n\nA string with interpolations and Markdown transformed into HTML str (if applicable) for the language used to create the function.\n\n#### Usage\n\n```js\nimport { Raven } from \"raven-writer\";\n\nconst POE = new Raven();\nawait POE.fetchLocalizations({..., languages: [\"en-us\", \"sp-mx\"]});\n\n/*\nAssume `POE.fetchLocalizations({...})` caches the following localizations:\n{\n  \"en-us\": {\n    \"GREETING\": \"*Hello*, {{name}}\"\n  },\n  \"sp-mx\": {\n    \"GREETING\": \"Hola, {{name}}\"\n  }\n}\n*/\n\nconst EN_US = POE.makeDictionary(\"en-us\");\nconst SP_MX = POE.makeDictionary(\"sp-mx\");\n\n// Logs: \"\u003ci\u003eHello\u003c/i\u003e, Nate\"\nconsole.log(EN_US(\"GREETING\", {name: \"Nate\"}));\n\n// Logs: \"Hola, Nate\"\nconsole.log(SP_MX(\"GREETING\", {name: \"Nate\"}));\n```\n\n## \u003ca id=\"contentSyntax\"\u003e\u003c/a\u003eContent markdown and interpolation syntax\n\n`raven-writer` supports a limited subset of markdown and a simple way of adding interpolations to your content. Use this as a guide when adding content values on the POEditor dashboard\n\n#### Supported Markdown\n\n| Style  | Markdown | Output |\n| ------ | -------- | ------ |\n| **bold** | `**bold**` | `\u003cb\u003eworld\u003c/b\u003e` |\n| *italic* | `*italic*` | `\u003ci\u003eitalic\u003c/i\u003e`|\n| ***bold italic*** | `***bold italics***` | `\u003cb\u003e\u003ci\u003ebold italic\u003c/i\u003e\u003c/b\u003e` |\n| [link](#url) | `[link name](https://example.com)` | `\u003ca href=\"https://example.com\" target=\"_blank\"\u003elink name\u003c/a\u003e` |\n\n#### Interpolations\n\nAdd variables into your content by using `interpolations` object.\nThe keys in the `interpolations` object wrapped between `{{` and `}}` can be used to represent dynamic content.\n\n## \u003ca id=\"localizationsStructure\"\u003e\u003c/a\u003eLocalizations structure\n\nThe localizations are stored as a single nested object. Top level keys are [ISO 639-1 language codes](https://en.wikipedia.org/wiki/ISO_639-1), each holding that language's localizations in key/value pairs where the key is what POEditor refers to as the `term` and value is what POEditor refers to as the `content`. See the [POEditor API](https://poeditor.com/docs/api#terms) for more details.\n\nHere is an example assuming 3 languages in the project with only one entry in each:\n\n```json\n{\n  \"en-us\": {\n    \"GREETING\": \"Hello\"\n  },\n  \"en-au\": {\n    \"GREETING\": \"G'day\"\n  },\n  \"sp-mx\": {\n    \"GREETING\": \"Hola\"\n  }\n}\n```\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F64bit-polygon%2Fraven-writer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F64bit-polygon%2Fraven-writer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F64bit-polygon%2Fraven-writer/lists"}