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

oxford

v3.0.3

Published

Localization/String library module

Downloads

19

Readme

Oxford Localization/String Library

Build Status

This l10n module is used to localize applications. It is based on the principle of overrides/fallbacks, where injected string libraries are deeply merged from right to left.

  const lib1 = { a: 1, b: 2, c: 3 };
  const lib2 = { b: 'foo', x: 7, y: 8, z: 9 };
  const lib3 = { b: 'baz', z: 'bar' };

  const oxford = require('oxford');
  const ox = oxford([lib1, lib2, lib3]);
  // lib1 is the base and each subsequent library is
  // merged in and overrides any values

  // Results in
  {
    a: '1',
    b: 'baz',
    c: '3',
    x: '7',
    y: '8',
    z: 'bar'
  }

It was heavily inspired by Mozilla's L20n framework, which I recommend you checkout and see if it fits as your project's localization solution.

%printf based dynamic placeholders that expect an input

{
  "congratsMessage": "Congrats %s!"
}

It's also possible to use indexed placeholders for custom ordering, to account for things like grammatical conjugations.

{
  "message": "Using Oxford is %s1 %s2"
}
{
  "message": "El uso de Oxford es %s2 %s1"
}

ox.get('message', 'dead', 'simple'); // Using Oxford is dead simple
ox.get('message', 'muertos', 'simple'); // El uso de Oxford es simple muertos

{{mustache}} references to internal sibling props

{
  "name": "Bob",
  "welcomeMessage": "Howdy {{name}}!" // 'Howdy Bob!'
}

[[references]] used to inject prop into scope

  {
    "oneScope": {
      "messages": "[[globalMessages]]" // resolves to "oneScope": { "messages": { "greeting": "Hello World" } }
    },
    "twoScope": {
      "messages": "[[globalMessages]]" // resolves to "twoScope": { "messages": { "greeting": "Hello World" } }
    },
    "redScope": {
      "messages": "[[globalMessages]]" // resolves to "redScope": { "messages": { "greeting": "Hello World" } }
    },
    "blueScope": {
      "messages": "[[globalMessages]]" // resolves to "blueScope": { "messages": { "greeting": "Hello World" } }
    },
    "globalMessages": {
      "greeting": "Hello World"
    }
  }

#(mixins) used to perform simple mods on values

function capitalize(text) {
  text = text.trim();
  return text.slice(0, 1).toUpperCase() + text.slice(1);
}

{
  "world": "world",
  "hello": "Hello #capitalize({{world}})!" // 'Hello World!'
}

String lookup method get()

const oxford = require('oxford');
const ox = oxford([
  {
    "prop": "the quick %s"
  },
  {
    "nested": {
      "prop": "%s jumps over"
    }
  },
  {
    "defaultVariant": {
      "$default": "normal",
      "normal": "normal text",
      "alternate": "alternate text"
    }
  }
]);

// Get a value from prop
ox.get('prop', 'brown'); // => 'the quick brown'

// Get a value from a nested.prop
ox.get('nested.prop', 'fox'); // => 'fox jumps over'

// Get a value from a prop with variants
ox.get('defaultVariant'); // => 'normal text'
ox.get('defaultVariant.normal'); // => 'normal text'
ox.get('defaultVariant.alternate'); // => 'alternate text'

Parameterized string lookup

Oxford was designed to make it possible to handle complex languages without needing to modify your code. The approach gives translators significant control and the ability to improve translations over time.

const oxford = require('oxford');

// the translations could start basic
const ox = oxford({
  body: 'He took %d1 week(s) and %d2 day(s)'
});

// or they can evolve to support the nuances of various languages
const ox = oxford({
  body: {
    "$key": "#pluralize(%d1) #pluralize(%d2)",
    "singular singular": "He took a week and one day.",
    "singular plural": "He took a week and %d2 days.",
    "plural singular": "He took %d1 weeks and one day.",
    "plural plural": "He took %d1 weeks and %d2 days."
  }
});

ox.get('body', 1, 1); // He took a week and one day.
ox.get('body', 1, 3); // He took a week and 3 days.
ox.get('body', 3, 1); // He took 3 weeks and one day.
ox.get('body', 3, 3); // He took 3 weeks and 3 days.

Child (sub-trees) oxford instances

Sometimes you may only want a portion of the string library for a particular view. Using the child method, it extracts an immutable version of the desired library.

const oxford = require('oxford');

const ox = oxford([{
  a: {
    b : {
      c: 'foo',
      d: 'bar'
    }
  }
}]);

ox.get('a.b.c'); // 'foo'

const oxChild = ox.child('a.b');

oxChild.get('c') // "foo"
oxChild.get('d') // "bar"
oxChild.get('a.b.c') // throws ReferenceError

Exposed internal dictionary object

This may be useful when using the dictionary on both the server and the client.

In the future this will be deprecated in favour of a deserialization method as it opens risk to state mutation.

const ox = oxford([dictionaryData]);

// This is the internal compiled dictionary, be careful not to mutate
const dictionary = ox.dictionary;

//wont lose data when stringified
const dictionaryString = JSON.stringify(dictionary);
const oxNew = oxford([JSON.parse(dictionaryString)]); //ox will be the same as oxNew

Oxford Plugin System

Oxford exposes seams that you may register external plugins into the processing/query chain.

You can register a plugin by referencing an installed package. The convention is oxford-plugin-<name> and you can reference it just by <name> and oxford will automatically try registering oxford-plugin-<name> first and then the plain <name> if it fails

Example

//installed package 'oxford-plugin-markdown'
// oxford-plugin-markdown/index.js
'use strict';

const parseMarkdown = require('marked');

module.exports = {
  hook: 'post-get',
  name: 'markdownPlugin',
  method: function (string) {
    return parseMarkdown(string);
};

// example.js
const oxford = require('oxford');
oxford.registerPlugin('markdown');
//or oxford.registerPlugin('oxford-plugin-markdown');
//or oxford.registerPlugin(require('oxford-plugin-markdown'));

const ox = oxford({ hello: '#Hello %s!' });

ox.get('hello', 'Brett'); // returns <h1>Hello Brett!</h1>

Current available hooks include:

  • prebuild
  • postbuild
  • preget
  • postget
  • static

All hooks are normalized upon registering involving lowercasing and removing underscores(_), hyphens(-) and white spaces(" ").

This means that the following hook definitions are synonomous:

  • 'preget'
  • 'post-get'
  • 'pre_build'
  • 'post build'
  • 'Preget'
  • 'Pre-get'
  • etc.

Pre-get hook

This hook is invoked before any processing occurs when calling the .get() method. It is triggered before any additional traversals(i.e. mustaches/references) or decoding (i.e. HTML entity decoding).

Post-get hook

This hook is invoked after any processing occurs when calling the .get() method. It is triggered after any additional traversals(i.e. mustaches/references) or decoding (i.e. HTML entity decoding).

Pre-build hook

This hook is invoked immediately before the string libray is built/comibined, so it can be used for any sort of custom preprocessing of the string library data before being handed off to Oxford.

Post-build hook

This hook is invoked immediately after the string libray is built/combined, so it can be used for any sort of custom post-processing of the string library data before being handed off to Oxford.

Static hook

This hook attaches a public static method onto the Oxford instance. It can be useful for things like parsing a custom data type or importing from a URL.

# lib/text.yml
---
hello: Hello %s!

//installed package 'oxford-plugin-yaml'
//oxford-plugin-yaml/index.js
'use strict';

const yaml = require('js-yaml');

module.exports = {
  hook: 'static',
  name: 'importYAML',
  method: function (url) {
    return this(yaml.safeLoad(fs.readFileSync(url, 'utf8')))
  }
};


// example.js
const oxford = require('oxford');
oxford.registerPlugin('yaml');

const ox = oxford.importYAML('./lib/text.yml');

ox.get('hello', 'Brett'); // returns Hello Brett!