Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: update for v5 #1992

Merged
merged 6 commits into from
Aug 22, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions website/.remarkrc.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export default {
],

// Rules enabled by default by presents above that we don't want
["remark-lint-code-block-style", false],
["remark-lint-file-extension", false],
["remark-lint-heading-style", false],
["remark-lint-list-item-indent", false],
Expand Down
22 changes: 0 additions & 22 deletions website/docs/guides/typescript.md

This file was deleted.

18 changes: 8 additions & 10 deletions website/docs/ref/macro.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,21 @@ import TabItem from "@theme/TabItem";

<Tabs groupId="babel-swc">
<TabItem value="babel" label="Babel" default>
Babel macros require [babel-plugin-macros](https://github.com/kentcdodds/babel-plugin-macros) to work. If you use a framework (for example GatsbyJS, Create React App > 2.0) you might already have macros enabled. Otherwise, install it as any other Babel plugin:
- Install `babel-plugin-macros` as a dev dependency and `@lingui/macro` as dependency:
Lingui macros require `@lingui/babel-plugin-lingui-macro` or [babel-plugin-macros](https://github.com/kentcdodds/babel-plugin-macros) to work.
vonovak marked this conversation as resolved.
Show resolved Hide resolved

Recommended way is to use `@lingui/babel-plugin-lingui-macro` directly, but if you use a framework which is not allowing to change babel configuration (for example GatsbyJS, Create React App > 2.0) that frameworks might support `babel-plugin-macros` out of the box.
timofei-iatsenko marked this conversation as resolved.
Show resolved Hide resolved

- Install `@lingui/babel-plugin-lingui-macro` as a dev dependency:

```bash npm2yarn
npm install --save-dev babel-plugin-macros
npm install --save @lingui/macro
```

- Add `macros` to the top of plugins section in your Babel config:
- Add `@lingui/babel-plugin-lingui-macro` to the top of plugins section in your Babel config:

```json
{
"plugins": ["macros"]
"plugins": ["@lingui/babel-plugin-lingui-macro"]
}
```

Expand All @@ -46,10 +48,6 @@ import TabItem from "@theme/TabItem";
</TabItem>
</Tabs>

:::note
It's recommended to install `@lingui/macro` package as a production dependency rather than development one to avoid `import/no-extraneous-dependencies` errors in ESLint.
:::

:::tip
Don't miss the [Lingui ESLint Plugin](/docs/ref/eslint-plugin.md) which can help you find and prevent common l10n mistakes in your code.
:::
Expand Down Expand Up @@ -1026,7 +1024,7 @@ Use `<Select>` inside `<Trans>` macro if you want to provide `id`, `context` or
### `useLingui`

:::note
`useLingui` is available from `@lingui/[email protected]` and not available yet in the `@lingui/swc-plugin`
`useLingui` is available from lingui v5
timofei-iatsenko marked this conversation as resolved.
Show resolved Hide resolved
:::

Gives access to a [`t`](/docs/ref/macro.mdx#t) macro bound to the local i18n object passed from React context.
Expand Down
2 changes: 1 addition & 1 deletion website/docs/ref/react.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ It's also possible to use `Trans` component directly without macros. In that cas

### Plurals

If you cannot use [@lingui/macro](/docs/ref/macro.mdx) for some reason, you can render plurals using the plain Trans component like this:
If you cannot use [@lingui/react/macro](/docs/ref/macro.mdx) for some reason, you can render plurals using the plain Trans component like this:

```jsx
import React from "react";
Expand Down
185 changes: 96 additions & 89 deletions website/docs/releases/migration-5.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,157 +4,164 @@

TBD

## Split React and JS Macro into separate packages
## React and Js Macros was split to separate packages
timofei-iatsenko marked this conversation as resolved.
Show resolved Hide resolved

The current Lingui macro is tightly coupled with React, which poses problems for developers using vanilla JavaScript or other frameworks such as Vue.
The current Lingui macro is tightly coupled with React, which poses problems for developers using Lingui with vanilla JavaScript or other frameworks such as Vue.
timofei-iatsenko marked this conversation as resolved.
Show resolved Hide resolved

#### Issues

- The existing macro assumes React usage, which isn't ideal for non-React projects.
- Using `@types/react` and `@lingui/react` adds React dependencies to projects that don't use React, which is unnecessary.

#### Benefits of the Split

- Allows the macro to be used with other JSX-based frameworks in the future.
- Removes unwanted React dependencies, making Lingui more versatile.

#### Solution

To address this, the macro package has been split into two separate packages:
The macro package has been split into two separate entrypoints from existing packages:

- `@lingui/react/macro`
- `@lingui/core/macro`

Also, the transformation code has been extracted into a separate Babel plugin `@lingui/babel-plugin-lingui-macro`, which can be used independently of `babel-plugin-macros`.

**Example Usage:**

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

const colors = [msg`Red`, msg`Yellow`, msg`Green`];

function MyComponent() {
<Trans>Hi, my name is {name}</Trans>
<span title={t`Title`} />
<Trans>Hi, my name is {name}</Trans>;
}
```

#### Migration Strategy
### Migration

This is not a breaking change.

Imports from `@lingui/macro` still work, but marked as deprecated. They would be removed in the next major release.
timofei-iatsenko marked this conversation as resolved.
Show resolved Hide resolved

- Users can migrate gradually by starting with `@lingui/macro`, which consolidates macros from both core and React-specific packages.
- Over time, users are encouraged to migrate directly to `@lingui/core/macro` or `@lingui/react/macro` depending on their specific needs.
You can use an automatic [codemod](https://www.npmjs.com/package/@lingui/codemods) to convert your codebase to the new imports:

```bash
npx @lingui/codemods split-macro-imports <path>
```

:::tip
There is a Codemod [@lingui/codemods](https://www.npmjs.com/package/@lingui/codemods) to help you with the migration. Check out the [`split-macro-imports.ts`](https://github.com/lingui/codemods/blob/main/transforms/split-macro-imports.ts) for more details.
:::
After this codemod you can drop `@lingui/macro` from your dependencies.
timofei-iatsenko marked this conversation as resolved.
Show resolved Hide resolved

## Full Vue.js support

TBD ([#1925](https://github.com/lingui/js-lingui/pull/1925))

## Whitespaces handling changes
## Changes in whitespaces handling

The current whitespace handling in Lingui, specifically through `normalizeWhitespace`, has been identified as problematic due to occasional incorrect processing of whitespace normalization. This proposal suggests a revised approach that uses stricter rules based on JSX node types to ensure more accurate and predictable whitespace handling.
### Robust whitespace cleaning in JSX

#### Issues
Whitespace cleaning in JSX expression is unavoidable, otherwise formatting your JSX code, for example with Prettier, will cause changes in extracted message.

- The existing `normalizeWhitespace` function uses regex to manage whitespace, which sometimes leads to unintended normalization results.
- Complex JSX structures and interactions with Babel transformations can further complicate whitespace management.
- The current method merges various JSX node types into a single string before normalization, potentially losing context-specific whitespace information.
```jsx
// prettier-ignore
<Trans>
Hello◦{"◦"}◦world
</Trans>

// should be extracted as
// "Hello◦◦◦world"
// without new lines in start and end of tag
```

Previously Lingui used some regexp based approach to normalize whitespaces in the JSX nodes processed by macro. That approach was not perfect and didn't follow JSX language grammar, that sometimes lead to unexpected results.
timofei-iatsenko marked this conversation as resolved.
Show resolved Hide resolved

#### Solution
With this version lingui use the same set of rules to clean whitespaces as it's done in JSX. This lead to more anticipated results without unwanted cleaning of whitespaces.
timofei-iatsenko marked this conversation as resolved.
Show resolved Hide resolved

- **Utilize JSX Node Information:**
- Instead of treating JSX content as a single string for normalization, use specific JSX node types (e.g., JSXText, JSXExpressionContainer) to apply appropriate whitespace rules.
- Implement a function (cleanJSXElementLiteralChild) that adheres to JSX's intrinsic whitespace handling rules, similar to those defined in Babel's sources.
### No whitespaces cleaning in `t` and other JS macros

**Before:**
We've got a feedback which we agreed on that whitespaces cleaning in the JS macros is redundant and counterintuitive.
timofei-iatsenko marked this conversation as resolved.
Show resolved Hide resolved

```ts
<Trans>Hello◦{"◦"}◦world</Trans>
// -> normalizeWhitespace("Hello◦◦◦world") we lost here information that middle space came from explicit `{"◦"}`
```js
t`Label:◦` + value;
```

**After:**
Note the space after ":", it's expected by developer to be there, but "normalization" will remove it.
timofei-iatsenko marked this conversation as resolved.
Show resolved Hide resolved

Other example would be a markdown, or just a whatever purpose developer want to have an original formatting.
timofei-iatsenko marked this conversation as resolved.
Show resolved Hide resolved

Starting from v5 cleaning whitespaces for JS macros is completely removed.
timofei-iatsenko marked this conversation as resolved.
Show resolved Hide resolved

### Migration

This is a breaking change. Some messages in catalogs might be extracted with different whitespaces and therefore with different ids.

There is no way to automatically convert your catalogs to pick-up existing translation.

If you use TMS (such as Crowdin or Translation.io), migration should be pretty simple. Use Translation Memory feature (or analog).

if you don't use TMS you will need to migrate catalogs manually.
timofei-iatsenko marked this conversation as resolved.
Show resolved Hide resolved

```ts
<Trans>Hello◦{"◦"}◦world</Trans>
## Standalone `babel-plugin-lingui-macro`

// there are strict rules how whitespaces processed in JSXText,
// use `cleanJSXElementLiteralChild` function which follows this rules (taken from babel's sources)
cleanJSXElementLiteralChild("processHello◦") // JSXText
{"◦"} // JSXExpressionContainer - arbitary content, left as is
cleanJSXElementLiteralChild("◦world") // JSXText
Starting with this version there two ways of using Lingui macro with Babel. With `babel-macro-plugin` and with `babel-plugin-lingui-macro`.

```bash npm2yarn
npm install --save-dev @lingui/babel-plugin-lingui-macro
```

This revised approach to whitespace handling in Lingui addresses current limitations and aligns with best practices observed in JSX processing. The processing now mirrors how JSX handles whitespace.
### Migration

If you have access to the babel configuration and don't use any other macro in your code, you can drop `babel-macro-plugin` and add `babel-plugin-lingui-macro` to your babel config.

You will benefit from a slightly faster transpiling time and more configuration options for the plugin which are not available for `babel-macro-plugin` version.

## Introducing `useLingui` Macro for Simplified Localization in React
## Introducing `useLingui` macro

The `useLingui` macro simplifies the handling of non-JSX messages in React components, making internationalization (i18n) integration easy. It replaces direct `t` function calls with cleaner syntax and supports advanced usage within React hooks.
The `useLingui` macro simplify working with non-jsx messages in react components.

**For example:**
Before this macro you have to combine `t` or `msg` macro with an instance returned from `useLingui` hook:
timofei-iatsenko marked this conversation as resolved.
Show resolved Hide resolved

```jsx
import { useLingui } from "@lingui/macro";
import { t, msg } from "@lingui/macro";
import { useLingui } from "@lingui/react";

function MyComponent() {
const { t } = useLingui();
const a = t`Text`;
const { i18n, _ } = useLingui();

const a = t(i18n)`Text`;
// or
const b = _(msg`Text`);
}
```

// ↓ ↓ ↓ ↓ ↓ ↓
With the new macro code above simplifies to:

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

import { useLingui } from "@lingui/react";
function MyComponent() {
const { _: _t } = useLingui();
const a = _t(
/*i18n*/
{
id: "xeiujy",
message: "Text",
}
);
const { t } = useLingui();

const a = t`Text`;
}
```

As a result, it reduces complexity by consolidating i18n handling into a single macro call.
Note that `useLingui()` is imported from `@lingui/react/macro`, because it's a macro and not a runtime function. This will be transpiled to the regular `useLingui` from `@lingui/react` under the hood by Lingui.

## Dependency tree crawling extractor improvements

TBD ([#1958](https://github.com/lingui/js-lingui/pull/1958))

## Improved context

This proposal improves Lingui messages by automatically adding placeholder values as comments in PO files. This improves clarity for translators and AI tools. This feature provides critical **context** to support accurate translations.
## Print placeholder values for better translation context

For example:
If the message contains unnamed placeholders, such as `{0}` Lingui will print theirs values into PO comments, so translators and AI got more context what this placeholder is about.
timofei-iatsenko marked this conversation as resolved.
Show resolved Hide resolved

```js title="Message"
t`from ${myTrip.date}`;
```js
t`Hello ${user.name} ${value}`;
```

```po title="PO file" {1}
#. placeholder {0}: myTrip.date
msgid "from {0}"
```

In case the string is used in multiple places with different values, the context will be more specific:

```js title="Messages"
t`from ${myTrip.date}`;
This will be extracted as

// ...
Before:

t`from ${eventDate}`;
```po
msgid "Hello {0} {value}"
```

```po title="PO file" {1,2}
#. placeholder {0}: myTrip.date
#. placeholder {0}: eventDate
msgid "from {0}"
```
After:

By improving the handling of placeholder contexts, Lingui enhances the **usability for translators and AI**, promoting more accurate and efficient localization processes.
```po
#. placeholder {0}: user.name
msgid "Hello {0} {value}"
```

## Deprecations

Expand Down
8 changes: 4 additions & 4 deletions website/docs/tutorials/javascript.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,22 @@ Let's start with the three major packages:

> The core library responsible for translation and handling of message catalogs

`@lingui/macro`
`@lingui/babel-plugin-lingui-macro`

> Transforms messages wrapped in tagged template literals to ICU MessageFormat and validates them.

1. Install `@lingui/cli`, `@lingui/macro`, `babel-plugin-macros` and Babel core packages as a development dependencies and `@lingui/core` as a runtime dependency:
1. Install `@lingui/cli`, `@lingui/babel-plugin-lingui-macro` and Babel core packages as a development dependencies and `@lingui/core` as a runtime dependency:
timofei-iatsenko marked this conversation as resolved.
Show resolved Hide resolved

```bash npm2yarn
npm install --save-dev @lingui/cli @lingui/macro babel-plugin-macros @babel/core
npm install --save-dev @lingui/cli @lingui/babel-plugin-lingui-macro @babel/core
npm install --save @lingui/core
```

2. Add `macros` plugin to Babel config (e.g: `.babelrc`):

```json
{
"plugins": ["macros"]
"plugins": ["@lingui/babel-plugin-lingui-macro"]
}
```

Expand Down
4 changes: 2 additions & 2 deletions website/docs/tutorials/react-native.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ First, we need to wrap our app with [`I18nProvider`](/docs/ref/react.md#i18nprov

```tsx
import { I18nProvider } from "@lingui/react";
import { Trans } from "@lingui/macro";
import { Trans } from "@lingui/react/macro";
import { i18n } from "@lingui/core";
import { Text } from "react-native";

Expand All @@ -126,7 +126,7 @@ Translating the heading is done. Now, let's translate the `title` prop in the `<
The solution is to use the `t` macro which we can obtain from the `useLingui` hook. We use it like this to get a translated string:

```tsx
import { useLingui } from '@lingui/macro';
import { useLingui } from '@lingui/react/macro';

const { t } = useLingui()
...
Expand Down
2 changes: 1 addition & 1 deletion website/docs/tutorials/react-patterns.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ function MyComponent() {
}
```

Note that we import `useLingui` from `@lingui/macro`. There is also a runtime version of `useLingui` hook exported from `@lingui/react`. In the case above, it doesn't matter what version to choose since we use only `i18n` object which is presented in both.
Note that we import `useLingui` from `@lingui/react/macro`. There is also a runtime version of `useLingui` hook exported from `@lingui/react`. In the case above, it doesn't matter what version to choose since we use only `i18n` object which is presented in both.
timofei-iatsenko marked this conversation as resolved.
Show resolved Hide resolved

:::

Expand Down
Loading
Loading