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

@kwaeri/i18n

v0.3.1

Published

The internationalization component module of the @kwaeri platform.

Downloads

4

Readme

Patreon kwaeri-i18n PayPal

A Massively Modified Open Source Project by kirvedx

GPG/Keybase Google GitLab GitHub npm

kwaeri/i18n is the internationalization component module for the kwaeri application platform

pipeline status coverage report CII Best Practices

TOC

The Implementation

The i18n component provides internationalization for end users of @kwaeri/cli and the @kwaeri platform in general [kue].

Getting Started

NOTE

@kwaeri/i18n is not ready for production. We've published this module for testing and development purposes. You're free to try out anything that may already be available, but please be aware that there is likely to be many aspects of the platform which are not working and/or are completely broken. As we near completion of the new platform, we'll update documentation and provide complete examples and tutorials for getting started.

Installation

@kwaeri/node-kit wraps the various components under the kwaeri scope, and provides a single entry point to the node-kit platform for easing the process of building a kwaeri application.

@kwaeri/cli wraps the various CLI components under the @kwaeri scope, and provides a single entry point to the user executable framework.

However, if you wish to use @kwaeri/i18n - perform the following steps:

Install @kwaeri/i18n:

npm install @kwaeri/i18n

Usage

The i18n component can be used for internationalization with or without the kwaeri platform.

To leverage the i18n component, you'll first need to include it:

// INCLUDES
import { i18n } from '@kwaeri/i18n';..

Next, you'll need to provide the locales you wish to support through infrastructure:

⇨ MyProject
⇨ ⇨ package.json, *.ts, etc
⇨ ⇨ _locales
⇨ ⇨ ⇨ en
⇨ ⇨ ⇨ ⇨ messages.json
⇨ ⇨ ⇨ en_GB
⇨ ⇨ ⇨ ⇨ messages.json
⇨ ⇨ ⇨ de_DE
⇨ ⇨ ⇨ ⇨ messages.json

The messages.json file is where you provide the content for the locale in question. Only the variable name and content properties and values are required:

{
  "messageName": {
    "content": "This is an example message"
  }
}

You can make a call to i18n.getMessage( messageName: string, ...placeholderValues?: string[] ): string anywhere you need to support internationalization:

console.log( i18n.getMessage( "messageName" ) );

Search Order

Where the translation is taken from is currently determined by the following logic:

  1. A package.json file is read, if available, and a property named default_locale searched for. If found, it's value is configured as the default locale. If default_locale was not provided a fallback value of "en" is substituted.
  2. When new i18n(...) is called, any locales provided are configured as additional locales.
  3. When i18n.init() is called, an attempt to read in all locales configured - as a compliment to, and including, the default - is made. If successful the locales are mapped.

There are two methods which can be used for fetching localised messages:

  • 4(a) getMessage( name: string, ...placeholders: any[] ): string retrieves localised messages according to the configured locale.

    1. The default locale, if available, is searched first.
    2. If the default locale was a derived locale, such as en_US, and the message was not found - the related base locale is then searched (i.e. en ), if available.
    3. If no value is found an empty string is returned.
  • 4(b) getLocalisedMessage( name: string, locale: string, ...placeholders: any[] ): string retrieves a specific localisation.

    1. The specified locale, if available, is searched first.
    2. If the specified locale was a derived locale, such as en_US, and the message was not found - its related base locale is then searched (i.e. en), if available.
    3. If the message is not found in the related base locale, then the default locale is searched, if available.
    4. If the default locale was a derived locale, and the message was not found - the related base locale is then searched, if available.
    5. If no value is found, an empty string is returned.

Placeholders

Template content - or content you want printed within a message as part of a message template, are known as placeholders - and can be passed in as additional arguments to getMessage() or getLocalisedMessage().

The signature of the getMessage methods shows ...placeholders: any[] in their respective argument position(s). Please do not mistake that for an array as the argument type. All arguments in JavaScript are accessible within a function body via the arguments built-in; You can access any passed arguments - including any extra, non-named, arguments that were passed - via arguments[x]; where x is the position of the argument with regards to the order in which it was passed to the functions invocation.

In Typescript, we can denote that all extra arguments will be received under a specific name by using the rest spread syntax (i.e. ...placeholders: any[]). This, in fact, names the remaining arguments, and packs them into a nested array in its respective position - but it's nifty for minimizing syntax for the callers of our methods.

With that said, you can pass the placeholders values in the order they should appear within the message template as individual arguments:

// We can get intricate if we want:
try {
  // Some error creating code:
  throw new Error( `ASSERTION_ERROR: ${i18n.getMessage( "assertionError", "Some untranslated text", `${new Error().lineNumber}` )}` );
}
catch( exception ) {
  DEBUG( ( exception as Error ).message );
}

To leverage placeholders - or template parameters, follow a two-part process for defining them:

  1. Template them by name in a message's content by surrounding their name with the dollar sign $ character at their position within the message.
  2. Define their value within the placeholders object for any message, by creating a sub-property that's named respectively whos value is of object type. Within that specific placeholder's object define a content sub-property that indicates its position within the message template and which placeholder argument - when provided in a getMessage() or getLocalisedMessage() invocation - is the argument that should replace it, by specifying a positional template parameter (i.e. $1) as its value.

Things to note:

  • Placeholders are not defined in order, but are supplied in order; Logic exists to break the placeholder processing loop when as many placeholders have been replaced as values for placeholders have been provided.
  • Any placeholder that is not provided a value in a getMessage() or geLocalisedMessage() invocation is left as-is within the message template.
  • Additional placeholders are ignored.
  • A maximum of 8 placeholders are supported per message.

This behavior is intended to keep things consistent with other implementations - such as Chrome's i18n implementation.

{
  "assertionError": {
    "content": "ASSERTION_ERROR: $details$",
    "description": "A description to help translators understand the purpose and use of the translatable message",
    "placeholders": {
      "details": {
        "content": "$1",
        "example": "A string and number cannot be loosely asserted as equal in value without first being converted to the same type."
      }
    }
  }
}

To be continued...

How to Contribute Code

Our Open Source projects are always open to contribution. If you'd like to cocntribute, all we ask is that you follow the guidelines for contributions, which can be found at the Massively Modified Wiki

There you'll find topics such as the guidelines for contributions; step-by-step walk-throughs for getting set up, Coding Standards, CSS Naming Conventions, and more.

Other Ways to Contribute

There are other ways to contribute to the project other than with code. Consider testing the software, or in case you've found an Bug - please report it. You can also support the project monetarly through donations via PayPal.

Regardless of how you'd like to contribute, you can also find in-depth information for how to do so at the Massively Modified Wiki

Bug Reports

To submit bug reports, request enhancements, and/or new features - please make use of the issues system baked-in to our source control project space at Gitlab

You may optionally start an issue, track, and manage it via email by sending an email to our project's Service Desk.

For more in-depth documentation on the process of submitting bug reports, please visit the Massively Modified Wiki on Bug Reports

Vulnerability Reports

Our Vulnerability Reporting process is very similar to Gitlab's. In fact, you could say its a fork.

To submit vulnerability reports, please email our Security Group. We will try to acknowledge receipt of said vulnerability by the next business day, and to also provide regular updates about our progress. If you are curious about the status of your report feel free to email us again. If you wish to encrypt your disclosure email, like with gitlab - please email us to ask for our GPG Key.

Please refrain from requesting compensation for reporting vulnerabilities. We will publicly acknowledge your responsible disclosure, if you request us to do so. We will also try to make the confidential issue public after the vulnerability is announced.

You are not allowed, and will not be able, to search for vulnerabilities on Gitlab.com. As our software is open source, you may download a copy of the source and test against that.

Confidential Issues

When a vulnerability is discovered, we create a [confidential issue] to track it internally. Security patches will be pushed to private branches and eventually merged into a security branch. Security issues that are not vulnerabilites can be seen on our public issue tracker.

For more in-depth information regarding vulnerability reports, confidentiality, and our practices; Please visit the Massively Modified Wiki on Vulnerability

Donations

If you cannot contribute time or energy to neither the code base, documentation, nor community support; please consider making a monetary contribution which is extremely useful for maintaining the Massively Modified network and all the goodies offered free to the public.

Patreon Donate via PayPal.com PayPal