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

lisan-plugin-loader

v0.1.1

Published

Lisan Loader Plugin for dynamic imports

Downloads

66

Readme

Lisan Plugin Loader

Lisan Loader allows you dynamically load your dictionaries and locale configurations.

However, dictionaries must be created compatible with the loader. For that, you can set module option to lisan in Lisan Compiler or provide --module=lisan flag to the Lisan CLI compile command;

Installation

You can install lisan from the sources below, as you see fit.

from npm

npm install lisan-plugin-loader

from CDN

<script src="https://unpkg.com/lisan-plugin-loader/dist/index.umd.js" type="text/javascript"></script>

After adding the script tag above, all public variables will be accessible via window.lisanPluginLoader variables.

Usage

const { lisan } = require('lisan');
const { Loader } = require('lisan-plugin-loader');

lisan.use(
  Loader({
    dictionaryUrlFn: (dictionaryName, localeName) =>
      `https://cdn.mydomain.com/static/${localeName}/dictionaries/${dictionaryName}.js`,
  }),
);

lisan.setLocaleName('tr');

lisan.load('main').then(() => {
  // Loaded https://cdn.mydomain.com/static/tr/dictionaries/main.js
  const translated = lisan.t('hello.person', {
    name: 'John Doe',
  });
  console.log(translated); // Merhaba John Doe
});

Type Signature

type Loader = (urlResolverFunctions: {
  dictionaryUrlFn: string;
  localeUrlFn: string;
}) => TSLisan.Plugin;

Options

dictionaryUrlFn

Type: DictionaryURLResolverFunction Default: undefined

Type Signature

type DictionaryURLResolverFunction = (
  dictionaryName: string;
  localeName: string;
) => string;

localeUrlFn

Type: LocaleURLResolverFunction Default: ({ localeName }) => `https://unpkg.com/lisan-locales/dist/${localeName}.lisan.js`

Warning

localeUrlFn only works if lisan-plugin-l10n is used.

Type Signature

type LocaleURLResolverFunction = (localeName: string) => string;

Methods

For the full list of methods, see Lisan Loader API.

Compatibility

| Platform | IE | Edge | Firefox | Chrome | Nodejs | | -------- | --- | ---- | ------- | ------ | ------ | | Version | 9+ | All | All | All | 8+ |

Guide

Why might you need a dynamic loader?

Lisan takes advantage of doing interpolation on runtime with pure functions. To achieve that it uses Javascript files. However, there is a very important difference loading javascript files dynamically vs synchronously.

Popular Javascript modules (Eg. commonjs, esm, umd) loads modules synchronously. That's why module bundlers like webpack, rollup can statically analyze your code and bundle your source code.

Since i18n preferences are gathered from client-side, it would be a good practice to load dictionaries and/or locales dynamically as chunks (a.k.a lazy loading) especially for Single Page Applications since it would decrease the main bundle size.

Hint

You can also create a separate bundle for each locale and/or dictionaries and include locale/dictionary files to reduce latency. You are completely free to choose how to design your application.

Luckily, Lisan Loader Plugin is here to save you from some pain.

You can use lisan.loadLocale() method to load locales and lisan.load() method to load dictionaries.

Info

lisan compile --module=lisan command will generate dictionaries which are compatible with Lisan Loader.

To learn more about compile command, see: lisan compile.

Loading on Node Environment

When doing server side rendering, Lisan Loader will use require function to load desired file.

It is important to know that the file paths will be added to current working directory path. See: process.cwd()

Example:

Let's assume you are working on a project located in /Users/me/workspace/myproject folder.

// src/index.js
const { lisan } = require('lisan');
const { Loader } = require('lisan-plugin-loader');

lisan.use(
  Loader({
    dictionaryUrlFn: (dictionaryName, localeName) =>
      `/static/${localeName}/dictionaries/${dictionaryName}.js`,
  }),
);

lisan.setLocaleName('en-US');
lisan.load('main').then(() => {
  /*
   * 1. On Node Environment, dictionary will be REQUIRED from:
   * - "/Users/me/workspace/myproject/static/en-US/dictionaries/main.js"
   * 2. On Browser environment,  dictionary will be LOADED from:
   * - "http://<HOSTNAME>/static/en-US/dictionaries/main.js"
   */
  lisan.t('hello.world');
});

Loading on Browser Environment

Lisan Loader will load dictionaries and locales by appending <script> elements before closing body tag </body>.

// src/index.js
const { lisan } = require('lisan');
const { Loader } = require('lisan-plugin-loader');
const { Localization } = require('lisan-plugin-l10n');
const renderHome = require('./pages/home.js');

// Localization is needed to use loadLocale function.
lisan.use(Localization);

lisan.use(
  Loader({
    localeUrlFn: localeName =>
      `https://cdn.mydomain.com/static/locales/${localeName}.js`,
    dictionaryUrlFn: (dictionaryName, localeName) =>
      `https://cdn.mydomain.com/static/${localeName}/dictionaries/${dictionaryName}.js`,
  }),
);

(async () => {
  await lisan.loadLocale('en-US');
  // Loaded https://cdn.mydomain.com/static/locales/en-US.js

  await lisan.load('main');
  // Loaded https://cdn.mydomain.com/static/en-US/dictionaries/main.js

  renderHome();
})().then(() => console.log('rendered'));

Please note that,

lisan.loadLocale("en-US") method will append the script element below:

<script id="Lisan_Locale__en-US" src="https://cdn.mydomain.com/static/locales/en-US.js"></script>

lisan.load("main") method will append the script element below:

<script id="Lisan_Dictionary__en-US__main" src=" https://cdn.mydomain.com/static/en-US/dictionaries/main.js"></script>

Using another dynamic import strategy

There are plenty of ways to dynamically import javascript files like using import() expression, ES Modules in Browsers or a third-party library like requireJS etc.

You are free to use any of them. All you need to do is to provide --module option to lisan compile tool while building your dictionaries.

You can check Dynamic Import Strategies page for more details.

Caching

When you start using javascript files to serve dictionaries, you need to be aware of caching.

Browsers will cache the webpage assets. Thus, if you make a change in your dictionary, clients may not see it.

There are plenty of different strategies to invalidate the cache for javascript files like setting Cache-Control header, or using manifest files, or redirecting static assets' URLs to hashed URLs etc.

However, depending on your use case, one of the simplest solutions could be adding a version tag at the end of your dictionary URLs.

const MY_APP_VERSION = require('package.json').version;

lisan.use(
  Loader({
    localeUrlFn: localeName =>
      `https://cdn.mydomain.com/static/locales/${localeName}.js?v=${MY_APP_VERSION}`,
    dictionaryUrlFn: (dictionaryName, localeName) =>
      `https://cdn.mydomain.com/static/${localeName}/dictionaries/${dictionaryName}.js?v=${MY_APP_VERSION}`,
  }),
);

Or if you'd like to version dictionaries separately, you can add the version name to your dictionary files.

lisan.use(
  Loader({
    dictionaryUrlFn: dictionaryName =>
      `https://cdn.mydomain.com/static/dictionaries/${dictionaryName}.js`,
  }),
);

lisan.load('main-v1.2.3').then(() => {
  // Loaded https://cdn.mydomain.com/static/dictionaries/main-v1.2.3.js
  // All entries can be used by `lisan.t()` and `lisan.c()` methods
});

lisan.load('about-v1.0.0').then(() => {
  // Loaded https://cdn.mydomain.com/static/dictionaries/about-v1.0.0.js
  // All entries can be used by `lisan.t()` and `lisan.c()` methods
});

License

This package is MIT licensed.