Skip to content

Commit

Permalink
docs: Guides section improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
andrii-bodnar committed Oct 23, 2024
1 parent 558ba8f commit 333a185
Show file tree
Hide file tree
Showing 7 changed files with 213 additions and 201 deletions.
21 changes: 15 additions & 6 deletions website/docs/guides/dynamic-loading-catalogs.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
---
title: Dynamic Loading of Message Catalogs
description: Learn how to set up dynamic loading of message catalogs in Lingui to reduce bundle size and improve performance
---

# Dynamic Loading of Message Catalogs

[`I18nProvider`](/docs/ref/react.md#i18nprovider) doesn't assume anything about your app and it's the developer responsibility to load messages based on active language.
Internationalization in modern applications requires an efficient way to manage and load localized messages without overwhelming the initial bundle size. With Lingui's flexible approach, the developer is responsible for dynamically loading message catalogs based on the active language.

The [`I18nProvider`](/docs/ref/react.md#i18nprovider) component doesn't make assumptions about your app's structure, giving you the freedom to load only the necessary messages for the currently selected language.

Here's an example of a basic setup with a dynamic load of catalogs.
This guide shows how to set up dynamic loading of message catalogs, ensuring only the needed catalogs are loaded, which reduces bundle size and improves performance.

## Final i18n Loader Helper

Here's the full source of `i18n.ts` logic:
The following code defines the complete logic for dynamically loading and activating message catalogs based on the selected locale. It ensures that only the required catalog is loaded at runtime, optimizing performance:

```tsx title="i18n.ts"
import { i18n } from "@lingui/core";
Expand All @@ -28,7 +35,9 @@ export async function dynamicActivate(locale: string) {
}
```

**How should I use the dynamicActivate in our application?**
### Usage in Your Application

To use the `dynamicActivate` function in your application, you must call it on application startup. The following example shows how to use it in a React application:

```jsx
import React, { useEffect } from "react";
Expand Down Expand Up @@ -62,10 +71,10 @@ i18n-1.f0cf2e3d.chunk.js
main.ab4626ef.js
```

When page is loaded initially, only main bundle and bundle for the first language are loaded:
When the page is first loaded, only the main bundle and the bundle for the first language are loaded:

![Requests during the first render](/img/docs/dynamic-loading-catalogs-1.png)

After changing language in UI, the second language bundle is loaded:
After changing the language in the UI, the second language bundle is loaded:

![Requests during the second render](/img/docs/dynamic-loading-catalogs-2.png)
146 changes: 77 additions & 69 deletions website/docs/guides/explicit-vs-generated-ids.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ description: Learn about the differences between explicit and generated IDs and

When internationalizing your application, you may need to decide whether to use explicit or generated IDs for your messages.

In this guide, we will explore the fundamental concepts of explicit and generated IDs, and then delve into a comprehensive comparison, highlighting the benefits and drawbacks of each approach.
In this guide, we will explore the basic concepts of explicit and generated IDs, and then delve into a comprehensive comparison, highlighting the advantages and disadvantages of each approach.

## What are Explicit IDs and Generated IDs?

### Explicit ID

An explicit ID, often referred to as a user-defined or custom ID, is a manually assigned identifier associated with a specific message. These IDs are typically chosen by developers and are explicitly specified within your code. The typical explicit id may look like `index.header.title` or `modal.buttons.cancel`.
An explicit ID, often referred to as a user-defined or custom ID, is a manually assigned identifier associated with a specific message. These IDs are typically chosen by developers and are explicitly specified within your code.

The typical explicit id may look like `index.header.title` or `modal.buttons.cancel`.

Lingui example:

Expand All @@ -29,7 +31,7 @@ Lingui example:

### Generated IDs

On the other hand, generated IDs are automatically created by the internalization library. In Lingui, such IDs are created based on the source message and [context](#context).
On the other hand, generated IDs are created automatically by the internalization library. In Lingui, such IDs are created based on the source message and [context](#context).

Lingui example:

Expand All @@ -45,23 +47,23 @@ Lingui example:

### Benefits of Generated IDs

1. **Avoiding the "Naming Things" problem:** You don't need to come up with a name for each single phrase in the app. Lingui generates the IDs (in the form of short hashes) from the messages.
2. **Better Developer Experience:** Developers can focus on coding without needing to manually assign IDs, leading to a more streamlined development process. Searching for a user-facing string will lead to the place in code where it's used, as opposed to taking you to a (typically JSON) file full of translations.
3. **Avoiding Duplicates:** Duplicate messages are merged together automatically. Your translators will not have to translate the same phrases again and again. This could lead to cost savings, especially if translators charge by word count.
4. **Smaller bundle:** Lingui generates short IDs such as `uxV9Xq` which are typically shorter than manually crafted IDs like `index.header.title`. This results in a smaller bundle size, optimizing your application's performance.
5. **Preventing ID collisions:** As your application scales, explicit IDs can potentially lead to conflicts. Lingui's generated IDs ensure you steer clear of such collisions.
- **Avoiding the "naming things" problem:** You don't need to come up with a name for each single phrase in the app. Lingui generates the IDs (in the form of short hashes) from the messages.
- **Better developer experience:** Developers can focus on coding without needing to manually assign IDs, leading to a more streamlined development process. Searching for a user-facing string will lead to the place in code where it's used, as opposed to taking you to a (typically JSON) file full of translations.
- **Avoiding duplicates:** Duplicate messages are merged together automatically. Your translators will not have to translate the same phrases again and again. This could lead to cost savings, especially if translators charge by word count.
- **Smaller bundle:** Lingui generates short IDs such as `uxV9Xq` which are typically shorter than manually crafted IDs like `index.header.title`. This results in a smaller bundle size, optimizing your application's performance.
- **Preventing ID collisions:** As your application scales, explicit IDs can potentially lead to conflicts. Lingui's generated IDs ensure you steer clear of such collisions.

### Benefits of Explicit IDs

1. **Control:** Developers have full control over the naming and assignment of explicit IDs. This control allows for precise targeting and easy maintenance of internationalization keys.
2. **Loose Coupling:** Explicit IDs are loosely coupled with the messages (as opposed to when they are generated from the messages). This means that if the message changes, the ID remains the same. When your team uses a TMS (Translation Management System), this makes it easier even for non-technical people to update the strings.
3. **Readability:** Explicit IDs often have meaningful names, making it easier for developers, translators, and content creators to understand their purpose within the codebase.
4. **Predictability:** Since explicit IDs are manually assigned, they remain stable across different versions of your application, reducing the likelihood of breaking changes during updates.
- **Control:** Developers have full control over the naming and assignment of explicit IDs. This control allows for precise targeting and easy maintenance of internationalization keys.
- **Loose coupling:** Explicit IDs are loosely coupled with the messages (as opposed to when they are generated from the messages). This means that if the message changes, the ID remains the same. When your team uses a TMS (Translation Management System), this makes it easier even for non-technical people to update the strings.
- **Readability:** Explicit IDs often have meaningful names, making it easier for developers, translators, and content creators to understand their purpose within the codebase.
- **Predictability:** Since explicit IDs are manually assigned, they remain stable across different versions of your application, reducing the likelihood of breaking changes during updates.

In conclusion, the choice between these two strategies depends on your project requirements and priorities. However, it's important to note that Lingui provides the full range of benefits, especially with generated IDs.

:::note
You don't need to worry about the readability of IDs because you would barely see them. When extracted into a PO file, translators would see source string and its corresponding translation, while the IDs remain behind the scenes.
You don't have to worry about the readability of the IDs because you would hardly see them. When extracted into a PO file, translators would see the source string and its corresponding translation, while the IDs remain behind the scenes:

```gettext
#: src/App.tsx:1
Expand All @@ -71,55 +73,7 @@ msgstr "LinguiJS przyklad"

:::

## Using ID generated from a message

### With [`Trans`](/docs/ref/macro.mdx#trans) macro

```jsx
import { Trans } from "@lingui/react/macro";

function render() {
return (
<>
<h1>
<Trans>LinguiJS example</Trans>
</h1>
<p>
<Trans>
Hello <a href="/profile">{name}</a>.
</Trans>
</p>
</>
);
}
```

In the example code above, the content of [`Trans`](/docs/ref/macro.mdx#trans) is transformed into a message in MessageFormat syntax. By default, this message is used for generating the ID. Considering the example above, the catalog would contain these entries:

```js
const catalog = [
{
id: "uxV9Xq",
message: "LinguiJS example",
},
{
id: "9/omjw",
message: "Hello <0>{name}</0>.",
},
];
```

### With non-JSX macro

In the following example, the message `Hello World` will be extracted and used to create an ID.

```jsx
import { msg } from "@lingui/core/macro";

msg`Hello World`;
```

### Context {#context}
## Context

By default, when using generated IDs, the same text elements are extracted with the same ID, and then translated once. However, this might not always be desirable since the same text can have different meanings and translations. For example, consider the word "right" and its two possible meanings:

Expand All @@ -130,7 +84,7 @@ To distinguish these two cases, you can add `context` to messages. The same text

Regardless of whether you use generated IDs or not, adding context makes the translation process less challenging and helps translators interpret the source accurately. You, in return, get translations of better quality faster and decrease the number of context-related issues you would need to solve.

#### Providing context for a message
Examples:

```jsx
import { Trans } from "@lingui/react/macro";
Expand All @@ -144,7 +98,7 @@ import { Trans } from "@lingui/react";
<Trans id={"16eaSK"} message="right" />;
```

or with non-jsx macro
or with non-JSX macro:

```jsx
import { msg } from "@lingui/core/macro";
Expand All @@ -160,6 +114,7 @@ const ex2 = msg({
});

// ↓ ↓ ↓ ↓ ↓ ↓

const ex1 = {
id: "d1wX4r",
message: `right`,
Expand All @@ -170,11 +125,59 @@ const ex2 = {
};
```

## Using custom ID
## Using Generated IDs

### With [`Trans`](/docs/ref/macro.mdx#trans)
### With JSX Macro

If you're using custom IDs in your project, add `id` prop to i18n components:
```jsx
import { Trans } from "@lingui/react/macro";

function render() {
return (
<>
<h1>
<Trans>LinguiJS example</Trans>
</h1>
<p>
<Trans>
Hello <a href="/profile">{name}</a>.
</Trans>
</p>
</>
);
}
```

In the example code above, the content of [`Trans`](/docs/ref/macro.mdx#trans) is transformed into a message in MessageFormat syntax. By default, this message is used for generating the ID. Considering the example above, the catalog would contain these entries:

```js
const catalog = [
{
id: "uxV9Xq",
message: "LinguiJS example",
},
{
id: "9/omjw",
message: "Hello <0>{name}</0>.",
},
];
```

### With Core Macro

In the following example, the message `Hello World` will be extracted and used to create an ID:

```jsx
import { msg } from "@lingui/core/macro";

msg`Hello World`;
```

## Using Custom IDs

### With JSX Macro

To use custom IDs in JSX macros, pass the ID as a prop to the component:

```jsx
import { Trans } from "@lingui/react/macro";
Expand All @@ -197,9 +200,9 @@ function render() {

The messages with IDs `msg.header` and `msg.hello` will be extracted with their default values as `LinguiJS example` and `Hello <0>{name}</0>.` respectively.

### With non-JSX macro
### With Core Macro

If you're using custom IDs in your project, call the [`msg`](/docs/ref/macro.mdx#definemessage) function with a message descriptor object, passing the ID using the `id` property:
To use custom IDs in non-JSX macros, call the [`msg`](/docs/ref/macro.mdx#definemessage) function with a message descriptor object, passing the ID using the `id` property:

```jsx
import { msg } from "@lingui/core/macro";
Expand All @@ -222,3 +225,8 @@ msg({
}),
});
```

## See Also

- [Message Extraction](/docs/guides/message-extraction.md)
- [Macros Reference](/docs/ref/macro.mdx)
Loading

0 comments on commit 333a185

Please sign in to comment.