Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@inlang/paraglide-js

Package Overview
Dependencies
Maintainers
2
Versions
67
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@inlang/paraglide-js

[ Watch the demo of Paraglide JS](https://www.youtube.com/watch?v=-YES3CCAG90)

  • 1.3.3
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
20K
increased by6.33%
Maintainers
2
Weekly downloads
 
Created
Source

Watch the demo of Paraglide JS

Simple, adaptable, and tiny i18n library for JS

Get started with:

npx @inlang/paraglide-js@latest init

Features

Treeshaking

Treeshaking gives us superpowers. With it, each page of your app only loads the messages that it actually uses. Incremental loading like this would usually take hours of manual tweaking to get right. With Paraglide-JS you get it for free. Say goodbye to huge bundles.

Getting started

1. Initialize paraglide-js

Initialize paraglide-js whith:

npx @inlang/paraglide-js@latest init

This will:

  1. Install necessary dependencies
  2. Add the Paraglide compiler to your build script
  3. Set up configuration files

2. Set up an adapter (optional)

Adapters are framework-integrations for Paraglide. If you are using a framework, using an adapter is recommended , but not required.

Alternatively, you can write your own adapter

Usage

Running your build script will generate a src/paraglide folder. This folder contains all the code that you need to use paraglide-js.

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

Adding Messages

By default, paraglide expects your messages to be in messages/{lang}.json.

{
	"hello": "Hello world!"
	"loginHeader": "Hello {name}, please login to continue."
}

Using Messages

You can import messages with import * as m from "./paraglide/messages". Don't worry, your bundler will only include the messages that you actually use.

import * as m from "./paraglide/messages.js"
import { setLanguageTag } from "./paraglide/runtime.js"

m.hello() // Hello world!
m.loginHeader({ name: "Samuel" }) // Hello Samuel, please login to continue.

If you want to choose between messages at runtime, you can create a record of messages and index into it.

import * as m from "./paraglide/messages.js"

const season = {
	spring: m.spring,
	summer: m.summer,
	autumn: m.autumn,
	winter: m.winter,
} as const;

const msg = season["spring"]() // Hello spring!

(optional) Using the Sherlock IDE Extension

Sherlock integrates with paraglide to give you the optimal dev-experience.

VsCode screenshot showing Sherlock adding inlay hints next to messages and making an "extract message" code action available for hardcoded text

Adding Languages

You can declare which languages you support in ./project.inlang/settings.json in the languageTags array.

// project.inlang/settings.json
{
	"languageTags": ["en", "de"]
}

Then create another messages/{lang}.json file and get translating!

Setting the language

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

import { setLanguageTag } from "./paraglide/runtime.js"
import * as m from "./paraglide/messages.js"

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.

You will need to call setLanguageTag on both the server and the client, since they run in separate processes.

Reacting to language changes

Messages aren't reactive, so you will need to trigger a re-render when the language changes. You can register a callback using onSetLanguageTag(). It is called whenever the language tag changes.

If you are using an adapter this is likely done for you.

import { setLanguageTag, onSetLanguageTag } from "./paraglide/runtime.js"
import * as m from "./paraglide/messages.js"

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.
  • setLanguageTag shouldn't be used on the server.

Getting a message in a specific language

You can import a message in a specific language from paraglide/messages/{lang}.js. This is great if you always need the same language in a given file.

import * as m from "./paraglide/messages/de.js"
m.hello() // Hallo Welt

If you want to force a language, but don't know ahead of time which language you can pass the languageTag option as the second parameter to a message function. This is often needed on the server.

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

## Lazy-Loading

Paraglide consciously discourages lazy-loading translations since it seriously hurts your web-vitals. Learn more about why lazy-loading is bad & what to do instead in this blog post.

If you really want to do it anway, you can lazily import the language-specific message files. Be careful with this, as it's easy to accidenally break tree-shaking.

const lazyGerman = await import("./paraglide/messages/de.js")

Usage with a Bundler

We provide bundler plugins to make it easier to use Paraglide with a bundler. If you are using one we recommed using the corresponding plugin.

These plugins make sure to compile your messages whenever you build your project. If your bundler has a dev-server, like Vite, the plugin also makes sure to recompile whenever your messages change.

Playground

You can find many examples for how to use paraglide on codesandbox, or in our GitHub repository.

Architecture

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

The emitted functions are referred to as "message functions". By emitting message functions, inlang Paraglide JS eliminates a whole 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 300 bytes minified & gzipped.

paraglide JS architecture

Inlang Paraglide-JS consists of four main parts:

PartDescription
CompilerCompiles messages into tree-shakable message functions
MessagesThe compiled tree-shakable message functions
RuntimeA runtime that resolves the language tag of the current user
Adapter(optional) 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/en.js

/**
 * @param {object} params
 * @param {string} params.name
 */
export const hello = (params) => `Hello ${params.name}!`

/** ... */
export const loginButton = () => "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 const hello = (params) => `Hello ${params.name}!`

/** ... */
export const loginButton = () => "Login"

/** ... */
export const loginHeader = (params) => `Hello ${params.name}, please login to continue.`

Only the message hello is used in the source code.

// src/my-code.js
import * as m from "../paraglide/messages.js"

console.log(m.hello({ name: "Samuel" }))

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

// dist/my-code.js
const hello = (params) => `Hello ${params.name}!`

console.log(hello({ name: "Samuel" }))

Writing an Adapter

An "adapter" is a library that integrates with a framework's liefcycle and does two main things:

  • Calls setLanguageTag() at appropriate times to set the language
  • Reacts to onSetLanguageTag(), usually by navigating or relading the page.

Here is an example that adapts Paraglide-JS to a fictitious metaframework like NextJS or SvelteKit.

import { setLanguageTag, onSetLanguageTag } from "../paraglide/runtime.js"
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}`
	})
}

// make sure the app renders _after_ you've done your setup
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 a few comments we've received recently.

If you have any feedback / problems, please let us know on GitHub

Roadmap

Of course, we're not done yet! We plan on adding the following features to Paraglide JS soon:

Talks

Working with Translators

Paraglide JS is part of the inlang ecosystem, so it integrates nicely with all the other inlang compatible tools. If you are working with translators and/or designers you will find the following tools useful:

  • Fink - An Online UI for editing translations. Changes made in Fink are committed to a translation branch or submitted via pull request.
  • Parrot - A Figma Plugin for previewing translations right in your Figma designs. This avoids any layout issues that might occur due to different text lengths in different languages.

Pricing

Keywords

FAQs

Package last updated on 18 Mar 2024

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc