From a59fdb2ee36bbe19209e8c6885f6f418763a2151 Mon Sep 17 00:00:00 2001 From: Andrii Bodnar Date: Mon, 4 Nov 2024 10:44:51 +0200 Subject: [PATCH] docs: Resources section improvements (#2064) --- website/docs/misc/community.md | 27 +++--- website/docs/misc/i18next.md | 153 ++++++++++++++++++++++++------- website/docs/misc/react-intl.md | 84 +++++++++-------- website/docs/misc/resources.md | 6 +- website/docs/misc/showroom.md | 56 ++++++----- website/docs/misc/tooling.md | 10 +- website/docusaurus.config.ts | 12 +-- website/src/components/Users.tsx | 4 +- 8 files changed, 218 insertions(+), 134 deletions(-) diff --git a/website/docs/misc/community.md b/website/docs/misc/community.md index 8eb35dc5d..16d1e8966 100644 --- a/website/docs/misc/community.md +++ b/website/docs/misc/community.md @@ -1,33 +1,36 @@ --- title: Community and Contributing +description: Learn how to connect with the Lingui community and contribute to the project --- +For any open-source project, the community is the backbone of success. It's the community that drives growth, provides valuable feedback, and contributes to the project in countless ways. + ## Community Lingui has a significant number of developers as a part of its community. -On this page we've listed some Lingui-related communities that you can be a part of; see the other pages in this section for additional online and in-person learning materials. - -Before participating in Lingui's communities, please read our [Code of Conduct](https://github.com/lingui/js-lingui/blob/main/CODE_OF_CONDUCT.md). We expect that all community members adhere to the guidelines within. +On this page, you'll find links to various Lingui-related communities you can join, as well as additional resources for learning and collaboration. Be sure to explore the other pages in this section for more learning opportunities. -### Stack Overflow - -Stack Overflow is a popular forum to ask code-level questions or if you're stuck with a specific error. Read through the [existing questions](https://stackoverflow.com/questions/tagged/linguijs) tagged with `linguijs` or [ask your own](https://stackoverflow.com/questions/ask?tags=linguijs)! +Before participating, please take a moment to review our [Code of Conduct](https://github.com/lingui/js-lingui/blob/main/CODE_OF_CONDUCT.md). We expect all members to follow these guidelines to ensure a positive and welcoming environment for everyone. -### Discussion forums +### Discussion Forums -The [Lingui Discord server](https://discord.gg/gFWwAYnMtA) is a place where you can learn, share, and collaborate about anything and everything Lingui. +The [Lingui Discord Server](https://discord.gg/gFWwAYnMtA) is a place where you can learn, share, and collaborate about anything and everything Lingui. ![Join the community on Discord](https://img.shields.io/discord/974702239358783608.svg?label=Discord&logo=Discord&colorB=7289da&style=flat-square) -- Connect with users from the community. +- Connect with users in the community. - Get your questions answered and learn cool new tips and tricks. -- Watch for notifications of new content from Lingui and the community. -- Share your knowledge and expertise with others. +- Get notifications about new content from Lingui and the community. +- Share your knowledge and experience with others. + +### Stack Overflow + +Stack Overflow is a popular forum to ask code-level questions or if you're stuck with a specific error. Read through the [existing questions](https://stackoverflow.com/questions/tagged/linguijs) tagged with `linguijs` or [ask your own](https://stackoverflow.com/questions/ask?tags=linguijs)! ### News -For the latest news about Lingui, follow [@LinguiJS](https://twitter.com/LinguiJS) on Twitter. +For the latest news about Lingui, follow [@LinguiJS](https://x.com/LinguiJS) on X. ## Contributing diff --git a/website/docs/misc/i18next.md b/website/docs/misc/i18next.md index bae89491f..7fb38fb63 100644 --- a/website/docs/misc/i18next.md +++ b/website/docs/misc/i18next.md @@ -5,11 +5,13 @@ description: Comparison of Lingui and i18next internationalization libraries # Comparison with i18next -[i18next](https://www.i18next.com/) is an internationalization-framework written in and for JavaScript. i18next and Lingui are two popular internationalization (i18n) libraries used for translating and localizing JS-based applications. Both libraries have their strengths and weaknesses, and which one is best for a particular project depends on the project's specific needs. +[i18next](https://www.i18next.com/) is a widely used internationalization framework designed specifically for JavaScript applications. Both i18next and Lingui are popular libraries for translating and localizing JavaScript-based projects, each offering unique strengths and features. -## Basic comparison +The choice between them ultimately depends on the specific needs of your project. -Here is a basic example of the i18next usage: +## Basic Comparison + +Here's a simple example of how to use i18next: ```js import i18next from "i18next"; @@ -24,11 +26,15 @@ i18next.init({ }, }, }); -// ... +``` + +```js +import i18next from "i18next"; + document.getElementById("output").innerHTML = i18next.t("key"); ``` -Since the Lingui v4 release, there is a core function [i18n.t(...)](/docs/ref/core.md#i18n.t) that allows doing pretty much the same thing. The following example shows how this works with Lingui: +The equivalent example with Lingui looks like this: ```js title="lingui.config.{js,ts}" /** @type {import('@lingui/conf').LinguiConfig} */ @@ -45,48 +51,72 @@ module.exports = { ``` ```js -import { i18n } from "@lingui/core"; +import { t } from "@lingui/core/macro"; -document.getElementById("output").innerHTML = i18n.t({ id: "key", message: "Hello world" }); +document.getElementById("output").innerHTML = t`Hello world`; ``` -:::note -The `message` property can be specified in the case of [Message Extraction](/docs/guides/message-extraction.md) usage flow. You can use the `i18n.t` function only with the `id`, but in this case you'll have to manage your localization catalogs yourself, without advantages of the [message extraction](/docs/guides/message-extraction.md) feature. +:::tip +This example uses a macro for the translation. Macros are a powerful feature of Lingui that allows you to write messages directly in your code. Read more about [Macros](/docs/ref/macro.mdx). ::: +If you prefer to define explicit IDs for your messages, you can follow this approach: + +```js +import { t } from "@lingui/core/macro"; + +document.getElementById("output").innerHTML = t({ id: "msg.greeting", message: `Hello World` }); +``` + +Read more about [Explicit vs Generated Message IDs](/docs/guides/explicit-vs-generated-ids.md). + ## Interpolation -Interpolation is one of the most used functionalities in I18N. It allows integrating dynamic values into your translations. +Interpolation is a key internationalization (i18n) feature that allows you to insert dynamic values into your translations. Both Lingui and i18next support interpolation. i18next sample: ```js +import i18next from "i18next"; + +i18next.t("My name is {name}", { name: "Tom" }); i18next.t("msg.name", { name: "Tom" }); ``` Lingui sample: ```js -i18n._({ id: "msg.name", message: "My name is {name}", values: { name: "Tom" } }); +import { t } from "@lingui/core/macro"; + +const name = "Tom"; + +t`My name is ${name}`; +t({ id: "msg.name", message: `My name is ${name}` }); ``` ## Formatting -Both the Lingui and i18next formatting functions are based on the [Intl API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl). +Both Lingui and i18next formatting functions are based on the [Intl API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl). ### Numbers i18next sample: ```js +import i18next from "i18next"; + i18next.t("intlNumber", { val: 1000 }); // --> Some 1,000 + i18next.t("intlNumber", { val: 1000.1, minimumFractionDigits: 3 }); // --> Some 1,000.100 + i18next.t("intlNumber", { val: 1000.1, formatParams: { val: { minimumFractionDigits: 3 } } }); // --> Some 1,000.100 + i18next.t("intlNumberWithOptions", { val: 2000 }); // --> Some 2,000.00 + i18next.t("intlNumberWithOptions", { val: 2000, minimumFractionDigits: 3 }); // --> Some 2,000.000 ``` @@ -116,8 +146,11 @@ i18n.number(12345.678, { style: "currency", currency: "CZK" }); i18next sample: ```js +import i18next from "i18next"; + i18next.t("intlDateTime", { val: new Date(Date.UTC(2012, 11, 20, 3, 0, 0)) }); // --> On the 12/20/2012 + i18next.t("intlDateTime", { val: new Date(Date.UTC(2012, 11, 20, 3, 0, 0)), formatParams: { @@ -147,7 +180,7 @@ i18n.date(d, { dateStyle: "medium", timeStyle: "medium" }); ## Plurals -Lingui uses the ICU MessageFormat syntax to handle plurals. It provides a simple and translator-friendly approach to plurals localization. +Lingui uses the [ICU MessageFormat](/docs/guides/message-format.md) syntax to handle plurals. It provides a simple and translator-friendly approach to plurals localization. For example: @@ -158,7 +191,7 @@ plural(numBooks, { }); ``` -Under the hood, plural is replaced with low-level `i18n._`. For production, the above example will become: +Under the hood, the [`plural`](/docs/ref/macro.mdx#plural) macro is replaced with a low-level [`i18n._`](/docs/ref/core.md#i18n._) call. In production, the example will look like this: ```js i18n._({ @@ -169,7 +202,7 @@ i18n._({ }); ``` -When we extract messages from source code using Lingui CLI, we get: +When we extract messages from the source code using the [Lingui CLI](/docs/ref/cli.md), we get: ```icu-message-format {numBooks, plural, one {# book} other {# books}} @@ -185,6 +218,8 @@ i18next handles plurals differently. It requires a separate key to be defined fo ``` ```js +import i18next from "i18next"; + i18next.t("key", { count: 0 }); // -> "items" i18next.t("key", { count: 1 }); // -> "item" i18next.t("key", { count: 5 }); // -> "items" @@ -192,30 +227,82 @@ i18next.t("key", { count: 5 }); // -> "items" ## Context -By providing a context you can differ translations. Both i18next and Lingui have the context feature to differentiate messages. +By providing context, you can differentiate translations for the same sentences or provide translators with more details. Both i18next and Lingui have the context feature to differentiate messages. -## Summary +i18next sample: -This is a rather short comparison. Both libraries have quite different concepts, but at the same time the core internationalization approaches are similar and use the same background. +```js +import i18next from "i18next"; + +i18next.t("Right", { context: "direction" }); +``` + +Lingui sample: + +```js +import { msg } from "@lingui/core/macro"; + +msg({ + message: "Right", + context: "direction", +}); +``` + +:::tip +Lingui automatically provides additional context by including in the `.po` file the locations where each message is used, and `msgctxt` if the context is specified. This is useful for translators to understand the context of the message: + +```gettext title="en.po" +#: src/App.js:5 +msgctxt "direction" +msgid "Right" +msgstr "Right" +``` + +i18next can't do this from its plain JSON files. +::: -On top of that, [Lingui](https://github.com/lingui/js-lingui): +## React Integration + +Both libraries provide React components for handling translations in React applications. Lingui provides a set of [React Macros](/docs/ref/macro.mdx#react-macros) that simplify writing messages directly in your code. i18next provides a `Trans` component to handle translations in JSX. + +i18next sample: + +```jsx +import { Trans } from "react-i18next"; + +const HelloWorld = () => { + return Hello World!; +}; +``` + +Lingui sample: + +```jsx +import { Trans } from "@lingui/react/macro"; + +const HelloWorld = () => { + return Hello World!; +}; +``` + +## Summary -- supports rich-text messages -- provides macros to simplify writing messages using MessageFormat syntax -- provides a CLI for extracting and compiling messages -- supports a number of [Catalog formats](/docs/ref/catalog-formats.md), including [Custom Formatters](/docs/guides/custom-formatter.md) -- is very small (**3kb** gzipped), fast, flexible, and stable -- works for vanilla JS, Next.js, Vue.js, Node.js etc. -- is actively maintained. +This is a rather brief comparison. Both libraries have quite different concepts, but at the same time the core internationalization approaches are similar and use the same background. -On the other hand, [i18next](https://www.i18next.com/): +**On top of that, Lingui:** -- mature. Based on how long i18next already is available open source, there is no real i18n case that could not be solved with i18next -- extensible -- has a big ecosystem. +- Supports rich-text messages. +- Provides macros to simplify writing messages using ICU MessageFormat syntax. +- Provides a CLI tool for extracting and compiling messages. +- Supports a number of [Catalog Formats](/docs/ref/catalog-formats.md), including [Custom Formatters](/docs/guides/custom-formatter.md). +- Is very small, fast, flexible, and stable. +- Works with vanilla JS, React (including RSC), Next.js, Node.js, Vue.js etc. +- Is actively maintained. -Lingui is a great choice for projects that require modern and efficient translation approaches, support for popular frameworks, and tools for managing translations. However, whether Lingui is better than i18next or not depends on the specific needs of the project. +**On the other hand, i18next:** -## Discussion +- Is mature. Based on how long i18next has been open source, there is no real i18n case that cannot be solved with i18next. +- Is extensible, with many plugins and tools developed by other contributors, including extractors, locale identifiers, etc. +- Has a big ecosystem. -Do you have any comments or questions? Please join the discussion at [GitHub](https://github.com/lingui/js-lingui/discussions) or raise an [issue](https://github.com/lingui/js-lingui/issues/new). All feedback is welcome! +In conclusion, Lingui is an excellent option for projects that need modern and efficient translation methods, support for popular frameworks, and effective translation management tools. However, the choice between Lingui and i18next ultimately depends on the specific requirements of your project. diff --git a/website/docs/misc/react-intl.md b/website/docs/misc/react-intl.md index ede2994f6..c9afdbfd0 100644 --- a/website/docs/misc/react-intl.md +++ b/website/docs/misc/react-intl.md @@ -5,9 +5,9 @@ description: Comparison of Lingui and react-intl internationalization libraries # Comparison with react-intl -[react-intl](https://github.com/formatjs/formatjs) (Format.js) is popular and widely-used i18n library for React. [Lingui](https://github.com/lingui/js-lingui) is in many ways very similar: both libraries use the same syntax for messages (ICU MessageFormat) and they also have very similar API. +[react-intl](https://github.com/formatjs/formatjs) (Format.js) is a popular and widely used i18n library for React. [Lingui](https://github.com/lingui/js-lingui) is very similar in many ways: both libraries use the same syntax for messages (ICU MessageFormat), and they also have a very similar API. -Here's an example from [react-intl](https://github.com/formatjs/formatjs) docs: +Here's an example from the react-intl docs: ```jsx ``` -Looking at the low-level API of [Lingui](https://github.com/lingui/js-lingui), there isn't much difference: +Looking at the low-level API of Lingui, there isn't much difference: ```jsx ``` -There's really no reason to reinvent the wheel when both libs are build on top of the same message syntax. The story doesn't end here, though. +There's really no reason to reinvent the wheel when both libs are built on top of the same message syntax. The story doesn't end here, though. -## Translations with rich-text markup +## Translations with Rich-Text Markup Suppose we have the following text: @@ -55,19 +55,17 @@ In react-intl, this would be translated as: /> ``` -[Lingui](https://github.com/lingui/js-lingui) extends ICU MessageFormat with tags. The example above would be: +Lingui extends the ICU MessageFormat with tags. The above example would be: ```jsx }} /> ``` -and the translator gets the message in one piece: `Read the documentation`. +The translator gets the message in one piece: `Read the documentation`. -However, let's go yet another level deeper. +## Macros for Component-Based Message Syntax -## Macros for component-based message syntax - -[Lingui](https://github.com/lingui/js-lingui) provides macros [`@lingui/macro`](/docs/ref/macro.mdx) which automatically generates a message syntax. +Lingui provides powerful [Macros](/docs/ref/macro.mdx) that automatically generate a message syntax. Let's go back to the previous example: @@ -83,11 +81,11 @@ All we need to do is to wrap the message in a [`Trans`](/docs/ref/macro.mdx#tran

``` -The macro then parses the [`Trans`](/docs/ref/macro.mdx#trans) macro children and generates `message` and `components` props automatically in the form described in the previous section. +The macro will then parse the [`Trans`](/docs/ref/macro.mdx#trans) macro children and automatically generate `message` and `components` props in the form described in the previous section. -This is extremely useful when adding i18n to an existing project. All we need is to wrap all messages in [`Trans`](/docs/ref/macro.mdx#trans) macro. +This is very useful when adding i18n to an existing project. All we need to do is wrap all messages in the [`Trans`](/docs/ref/macro.mdx#trans) macro. -Let's compare it with react-intl solution to see the difference: +Let's compare it to the react-intl solution to see the difference: ```jsx

@@ -102,7 +100,7 @@ Let's compare it with react-intl solution to see the difference: ``` :::note -It' also worth mentioning that the message IDs are completely optional. [Lingui](https://github.com/lingui/js-lingui) is unopinionated in this way and perfectly works with messages as IDs as well: +It's also worth mentioning that the message IDs are completely optional. Lingui is unopinionated in this way and perfectly works with messages as IDs as well: ```html

@@ -111,6 +109,8 @@ It' also worth mentioning that the message IDs are completely optional. [Lingui] ``` The message ID is `Read the <0>documentation.` instead of `msg.docs`. Both solutions have pros and cons and the library lets you choose the one which works best for you. + +Read more about [Explicit vs Generated Message IDs](/docs/guides/explicit-vs-generated-ids.md). ::: ## Plurals @@ -130,7 +130,7 @@ Let's take a look at the original example from react-intl docs: /> ``` -Using [Lingui](https://github.com/lingui/js-lingui) macros, we could combine [`Trans`](/docs/ref/macro.mdx#trans), [`Plural`](/docs/ref/macro.mdx#plural-1) components and [`i18n.number`](/docs/ref/core.md#i18n.number) macro: +Using Lingui macros, we could combine [`Trans`](/docs/ref/macro.mdx#trans), [`Plural`](/docs/ref/macro.mdx#plural-1) components and [`i18n.number`](/docs/ref/core.md#i18n.number) macro: ```jsx @@ -151,10 +151,10 @@ and the final message would be very similar: /> ``` -The only difference is the `<0>` tag included in the message, as [LinguiJS](https://github.com/lingui/js-lingui) can handle components in both variables and the message itself. +The only difference is the `<0>` tag in the message, since Lingui can handle components in variables as well as in the message itself. :::note -It's good to mention here that this isn't the best example of using plurals. Make your translators happy and move plurals to the top of the message: +It's worth mentioning here that this is not the best example of using plurals. Make your translators happy by moving plurals to the top of the message: ```jsx { ))} -

And many more...

+ And many more...