JSPM

  • Created
  • Published
  • Downloads 82999
  • Score
    100M100P100Q172147F
  • License Apache-2.0

Package Exports

    This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@inlang/paraglide-js) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

    Readme

    Watch the pre-release demo of Paraglide JS

    Attention: The following features are missing and will be added in the upcoming weeks:

    • Support for pluralization

    The i18n library that you can set up within 3 lines of code

    Type in the following command into your terminal to get started immediately:

    npx @inlang/paraglide-js@latest init

    Features

    … and much more

    Getting started

    1. Initialize paraglide-js

    You can initialize paraglide-js by running the following command in your terminal:

    npx @inlang/paraglide-js@latest init

    2. Select an adapter (if required)

    Having an adapter is only required if you want to use paraglide-js with a framework. If you don't use a framework, you can skip this step.

    Alternatively, you can write your own adapter

    3. Add the compile script to your package.json

    If you are using @inlang/paraglide-js-adapter-vite, you can skip this step.

    You can customize the compile script to your needs. For example, you can add a --watch flag to watch for changes, if you have installed a watcher.

    {
      "scripts": {
        "compile": "paraglide-js compile"
      }
    }

    Usage

    Running the compile script will generate a src/paraglide folder. This folder contains all the code that you need to use paraglide-js. Throughout this guide, you will see imports from ./paraglide/*. These are all to this folder.

    Tip: If you are using a bundler, you can set up an alias to ./src/paraglide to make the imports shorter. We recommend $paraglide/*

    Using Messages

    The compiled messages are placed in ./paraglide/messages.js. You can import them all with import * as m from "./paraglide/messages". Don't worry, your bundler will only bundle the messages that you actually use.

    // m is a namespace that contains all messages of your project
    // a bundler like rollup or webpack only bundles
    // the messages that are used
    import * as m from "./paraglide/messages"
    import { setLanguageTag } from "./paraglide/runtime"
    
    // use a message
    m.hello() // Hello world!
    
    // message with parameters
    m.loginHeader({ name: "Samuel" }) // Hello Samuel, please login to continue.
    
    // change the language
    setLanguageTag("de")
    
    m.loginHeader({ name: "Samuel" }) // Hallo Samuel, bitte melde dich an, um fortzufahren.

    Paraglide JS provides five exports in ./paraglide/runtime.js:

    Variable Description
    sourceLanguageTag The source language tag of the project
    availableLanguageTags All language tags of the current project
    languageTag() Returns the language tag of the current user
    setLanguageTag() Sets the language tag of the current user
    onSetLanguageTag() Registers a listener that is called whenever the language tag changes

    Setting the language

    You can set the current language tag by calling setLanguageTag(). Any subsequent calls to either languageTag() or a message function will return the new language tag.

    import { setLanguageTag } from "./paraglide/runtime"
    import * as m from "./paraglide/messages"
    
    setLanguageTag("de")
    m.hello() // Hallo Welt!
    
    setLanguageTag("en")
    m.hello() // Hello world!

    The language tag is global, so you need to be careful with it on the server to make sure multiple requests don't interfere with each other. That's why we recommend using an adapter for your framework. Adapters integrate with the framework's lifecycle and ensure that the language tag is managed correctly.

    Reacting to a language change

    You can react to a language change by calling onSetLanguageTag(). This function is called whenever the language tag changes.

    import { setLanguageTag, onSetLanguageTag } from "./paraglide/runtime"
    import * as m from "./paraglide/messages"
    
    onSetLanguageTag((newLanguageTag) => {
      console.log(`The language changed to ${newLanguageTag}`)
    })
    
    setLanguageTag("de") // The language changed to de
    setLanguageTag("en") // The language changed to en

    There are a few things to know about onSetLanguageTag():

    • You can only register one listener. If you register a second listener it will throw an error.
    • It shouldn't be used on the server.

    The main use case for onSetLanguageTag() is to trigger a rerender of your app's UI when the language changes. Again, if you are using an adapter this is handled for you.

    Forcing a language

    It's common that you need to force a message to be in a certain language, especially on the server. You can do this by passing an options object to the message function as a second parameter.

    import * as m from "./paraglide/messages"
    const msg = m.hello({ name: "Samuel" }, { languageTag: "de" }) // Hallo Samuel!

    Usage with a Bundler

    We provide a few bundler plugins to make it easier to use paraglide-js with a bundler. If you are using one of these bundlers, we recommed using the corresponding plugin.

    These plugins make sure to rerun the compile script whenever you build your project. That way you don't need to modify your build script in package.json. If you are using a bundler with a dev-server, like Vite, the plugins also make sure to rerun the compile script whenever your messages change.

    Playground

    You can find many examples for how to use paraglide on codesandbox:

    Architecture

    Inlang Paraglide JS leverages a compiler to emit vanilla JavaScript functions.

    The emitted functions are often referred to as "message functions". By emitting message functions, inlang Paraglide JS eliminates a class of edge cases while also being simpler, faster, and more reliable than other i18n libraries. The compiled runtime contains less than 50 LOC (lines of code) and is less than 1kb gzipped.

    paraglide JS architecture

    Inlang Paraglide-JS consists of four main parts:

    Part Description
    Compiler Compiles messages into tree-shakable message functions
    Messages The compiled tree-shakable message functions
    Runtime A runtime that resolves the language tag of the current user
    Adapter (if required) An adapter that adjusts the runtime for different frameworks

    Compiler

    The compiler loads an inlang project and compiles the messages into tree-shakable and typesafe message functions.

    Example

    Input

    // messages/en.json
    {
      "hello": "Hello {name}!",
      "loginButton": "Login"
    }

    Output

    // src/paraglide/messages.js
    
    /**
     * @param {object} params
     * @param {string} params.name
     */
    function hello({ name }) {
      return `Hello ${name}!`
    }
    
    function loginButton() {
      return "Login"
    }

    Messages

    The compiled messages are importable as a namespace import (import * as m).

    The namespace import ensures that bundlers like Rollup, Webpack, or Turbopack can tree-shake the messages that are not used.

    Example

    Three compiled message functions exist in an example project.

    // src/paraglide/messages.js
    
    
    export function hello(params) {
      return `Hello ${params.name}!`
    }
    
    export function loginButton() {
      return "Login"
    }
    
    export function loginHeader(params) {
      return `Hello ${params.name}, please login to continue.`
    }

    Only the message hello is used in the source code.

    // source/index.js
    
    import * as m from "./paraglide/messages"
    
    console.log(m.hello({ name: "Samuel" }))

    The bundler tree shakes (removes) loginButton and loginHeader and only includes hello in the output.

    // output/index.js
    
    function hello(params) {
      return `Hello ${params.name}!`
    }
    
    console.log(hello({ name: "Samuel"}))

    Runtime

    View the source of ./paraglide/runtime.js to find the latest runtime API and documentation.

    Adapter

    Paraglide-JS can be adapted to any framework or environment by calling setLanguageTag() and onSetLanguageTag().

    1. setLanguageTag() can be used to set a getter function for the language tag. The getter function can be used to resolve server-side language tags or to resolve the language tag from a global state management library like Redux or Vuex.
    2. onSetLanguageTag() can be used to trigger side-effects such as updating the UI, or requesting the site in the new language from the server.

    Writing an Adapter

    The following example adapts Paraglide-JS to a fictitious metaframework like NextJS, SolidStart, SvelteKit, or Nuxt.

    The goal is to provide a high-level understanding of how to adapt Paraglide-JS to a framework. Besides this example, we recommend viewing the source-code of available adapters. In general, only two functions need to be called to adapt Paraglide-JS to a framework:

    1. setLanguageTag(): to set the language tag
    2. onSetLanguageTag(): to trigger a side-effect when the language changes
    import { setLanguageTag, onSetLanguageTag } from "./paraglide/runtime"
    import { isServer, request, render } from "@example/framework"
    
    
    // On a server, the language tag needs to be resolved on a
    // per-request basis. Hence, we need to pass a getter
    // function () => string to setLanguageTag.
    //
    // Most frameworks offer a way to access the current
    // request. In this example, we assume that the language tag
    // is available in the request object.
    if (isServer){
      setLanguageTag(() => request.languageTag)
    }
    // On a client, the language tag could be resolved from
    // the document's html lang tag.
    //
    // In addition, we also want to trigger a side-effect
    // to request the site if the language changes.
    else {
      setLanguageTag(() => document.documentElement.lang)
    
      //! Make sure to call `onSetLanguageTag` after
      //! the initial language tag has been set to
      //! avoid an infinite loop.
    
      // route to the page in the new language
      onSetLanguageTag((newLanguageTag) => {
         window.location.pathname = `/${newLanguageTag}${window.location.pathname}`
      })
    }
    
    // render the app
    render((page) =>
      <html lang={request.languageTag}>
        <body>
          {page}
        </body>
      </html>
    )

    Community

    We are grateful for all the support we get from the community. Here are just a few of the comments we've received over the last few weeks. Of course we are open to and value criticism as well. If you have any feedback, please let us know directly on GitHub