npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

raven-writer

v1.0.1

Published

raven-writer is a utility to allow for easy translations and interpolations for projects using the popular POEditor localization service

Downloads

6

Readme

raven-writer

raven-writer is a FE utility to allow for easy translations and interpolations for projects using the popular POEditor localization service.

What raven-writer does:

  • GETs and caches localizations for your project
  • Refreshes those localizations at a given interval
  • Transforms simple markdown in your content into HTML strings
  • Allows for dynamic interpolation of string values into your content
  • Easily gets values by term

Docs

Install

npm install raven-writer -S

Quick start example

Given the following POEditor project

In our project we have:

  • A language that is American english, which has a ISO 639-1 language code of en-us
  • A term MY_KEY that has a content value of "My value"
  • A second term GREETING that has a content value of "Hello, **{{name}}!**"
    • Note that the value has {{}} to denote an interpolated value with the key name
    • It also has ** markdown indicating it should be bolded
import { Raven } from "raven-writer";

// make the POE instance
const POE = new Raven();

// load localizations into the instance
await POE.fetchLocalizations({
  id: "<POEDITOR_PROJECT_ID>",
  token: "<YOUR_READ_ONLY_POEDITOR_API_TOKEN>",
  languages: ["en-us"]
});

// make a dictionary
const Translate = POE.makeDictionary("en-us");

// Logs: "My value"
console.log(Translate("MY_KEY"));

// Logs: "Hello, <b>Nate!</b>"
console.log(Translate("GREETING", {name: "Nate"}));

Instantiation

In most cases you'll instantiate the POE instance simply by calling new Raven().

You can optionally pre-load the POE instance with localizations. You'd do this if you wanted access to the POE.makeDictionary(language) functionality without having to make API calls. Refer to the localizations structure if you want to do this.

Props

| Prop | Type | Required? | Description | | ----------------- | :------: | :-------: | ----------- | | localizations | Object | | The preloaded localizations |

Returns

A POE instance that has the following methods:

POE.getLocalizations(localizations);
POE.fetchLocalizations({id, token, languages, keepAlive, url});
POE.makeDictionary(language);
POE.makeText(string, interpolations);
POE.kill();

Usage

Most common case

import { Raven } from "raven-writer";
const POE = new Raven();

Optional preloading

import { Raven } from "raven-writer";

const localizations = {
  "en-us": {
    "GREETING": "Hi!"
  }
};

const PRELOADED = new Raven(localizations);
const Translate = POE.makeDictionary("en-us");
console.log(Translate("GREETING")); // Logs: "Hi!"

POE.fetchLocalizations({...})

Fetches and catches localizations.

Props

| Prop | Type | Required? | Description | | ------------- | :-------: | :---------------------: | ----------- | | token | String | if url is undefined | The readonly api_token found in your POEditor acct | | id | String | if url is undefined | The project id found in your POEditor acct | | languages | Array of ISO 639-1 language codes | if url is undefined | The languages you want to fetch for the given project | | keepAlive | Integer | | If present the localizations will be refreshed per milliseconds defined this value | | url | String | if url, id, and languages are undefined | If present calls will be made to that url instead of hitting the POEditor endpoint |

Returns

A promise that once resolved will populate the POE instance with localizations.

Usage

Most common usage

import { Raven } from "raven-writer";
const tenMins = 1000 * 60 * 10;
const POE = new Raven();
await POE.fetchLocalizations({
  id: "<POEDITOR_PROJECT_ID>",
  token: "<YOUR_READ_ONLY_POEDITOR_API_TOKEN>",
  languages: ["en-us", "sp_mx"],
  keepAlive: tenMins // optional
});

Overwriting the endpoint

import { Raven } from "raven-writer";
const POE = new Raven();
await POE.fetchLocalizations({
  url: "<YOUR_CUSTOM_GET_ENDPOINT>"
});

Note: the response from your endpoint must have the same structure as the localizations structure

POE.makeDictionary(language)

Makes a Dictionary function for a given language that has already been cached in the POE instance

Props

| Prop | Type | Required? | Description | | ------------ | :------: | :-------: | ----------- | | language | String | yes | A ISO 639-1 language code |

Returns

A Dictionary function

Usage

import { Raven } from "raven-writer";
const POE = new Raven();
await POE.fetchLocalizations({..., languages: ["en-us", "sp-mx"]});
const enUsDictionary = POE.makeDictionary("en-us");
const spMxDictionary = POE.makeDictionary("sp-mx");

POE.getLocalizations(language)

Returns the raw localizations object. see: localizations structure.

Props

| Prop | Type | Required? | Description | | ------------ | :------: | :-------: | ----------- | | language | String | ✅ | A ISO 639-1 language code |

Returns

A localizations object

Usage

Assume the cached localizations are the following:

{
  "en-us": {
    "GREETING": "Hello"
  },
  "sp-mx": {
    "GREETING": "Hola"
  }
}
import { Raven } from "raven-writer";
const POE = new Raven();
await POE.fetchLocalizations({..., languages: ["en-us", "sp_mx"]});
console.log(POE.getLocalizations()) // Logs the preceding full object
console.log(POE.getLocalizations("sp_mx")) // Logs { GREETING: "Hola" }

POE.makeText(str, interolations)

Adds interpolations and/or Markdown transformed into HTML string to a given string. See: Content markdown and interpolation syntax.

Props

| Prop | Type | Required? | Description | | ------------------| :------: | :-------: | ----------- | | str | String | ✅ | Any string value, ie not a POE term | | interolations | Object | | An object with key names that match the dynamic content markers in the str |

Returns

A string with interpolations and Markdown transformed into HTML str (if applicable).

Usage

import { Raven } from "raven-writer";
const POE = new Raven();

// Logs: "Plain text"
console.log(POE.makeText("Plain text"));

// Logs: "Hello, Nate"
console.log(POE.makeText("Hello, {{name}}", { name: "Nate" }));

// Logs: "Some <i>italic text</i>"
console.log(POE.makeText("Some *italic text*"));

// Logs: "Hello, <b>Nate</b>"
console.log(POE.makeText("Hello, **{{name}}**", { name: "Nate" }));

POE.kill()

If you call POE.fetchLocalizations({...}) and set it to refresh localizations via keepAlive, this stops all refreshes on that instance.

Returns

undefined

Usage

import { Raven } from "raven-writer";
const tenMins = 1000 * 1000 * 60 * 10;
const POE = new Raven();
await POE.fetchLocalizations({..., keepAlive: tenMins});
...
POE.kill();

Dictionary(term, interpolations)

The function returns the localized content value of a term, optionally with injected interpolations. Markdown is transformed into HTML strings.

Props

| Prop | Type | Required? | Description | | ------------------| :------: | :-------: | ----------- | | term | String | ✅ | Any string value, ie not a POE term | | interolations | Object | | An object with key names that match the dynamic content markers for the content value associated with the term |

Returns

A string with interpolations and Markdown transformed into HTML str (if applicable) for the language used to create the function.

Usage

import { Raven } from "raven-writer";

const POE = new Raven();
await POE.fetchLocalizations({..., languages: ["en-us", "sp-mx"]});

/*
Assume `POE.fetchLocalizations({...})` caches the following localizations:
{
  "en-us": {
    "GREETING": "*Hello*, {{name}}"
  },
  "sp-mx": {
    "GREETING": "Hola, {{name}}"
  }
}
*/

const EN_US = POE.makeDictionary("en-us");
const SP_MX = POE.makeDictionary("sp-mx");

// Logs: "<i>Hello</i>, Nate"
console.log(EN_US("GREETING", {name: "Nate"}));

// Logs: "Hola, Nate"
console.log(SP_MX("GREETING", {name: "Nate"}));

Content markdown and interpolation syntax

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

Supported Markdown

| Style | Markdown | Output | | ------ | -------- | ------ | | bold | **bold** | <b>world</b> | | italic | *italic* | <i>italic</i>| | bold italic | ***bold italics*** | <b><i>bold italic</i></b> | | link | [link name](https://example.com) | <a href="https://example.com" target="_blank">link name</a> |

Interpolations

Add variables into your content by using interpolations object. The keys in the interpolations object wrapped between {{ and }} can be used to represent dynamic content.

Localizations structure

The localizations are stored as a single nested object. Top level keys are ISO 639-1 language codes, 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 for more details.

Here is an example assuming 3 languages in the project with only one entry in each:

{
  "en-us": {
    "GREETING": "Hello"
  },
  "en-au": {
    "GREETING": "G'day"
  },
  "sp-mx": {
    "GREETING": "Hola"
  }
}