From b416a68584d20cf4e2958a7467df2c070439877e Mon Sep 17 00:00:00 2001 From: Aymeric PINEAU Date: Thu, 25 Apr 2024 16:48:08 +0200 Subject: [PATCH] docs: update doc --- README.md | 206 ++++++------------ docs/configuration.md | 49 +++++ .../declaration_watching.md | 61 ++++++ docs/content_declaration/enumeration.md | 81 +++++++ docs/content_declaration/function_fetching.md | 76 +++++++ docs/content_declaration/get_started.md | 168 ++++++++++++++ docs/content_declaration/nested_id.md | 102 +++++++++ docs/content_declaration/translation.md | 151 +++++++++++++ docs/interest_of_intlayer.md | 13 ++ docs/intlayer_cli.md | 59 +++++ docs/intlayer_with_create_react_app.md | 127 +++++++++++ docs/intlayer_with_i18n.md | 79 +++++++ docs/intlayer_with_nextjs.md | 182 ++++++++++++++++ examples/cli/package.json | 2 + .../7_translation/custom_content.content.ts | 26 +++ .../7_translation/react_content.content.tsx | 12 + examples/cli/tsconfig.json | 2 +- examples/nextjs-app/intlayer.config.cjs | 4 +- examples/nextjs-app/intlayer.config.js | 5 +- examples/nextjs-app/intlayer.config.json | 4 +- examples/nextjs-app/intlayer.config.mjs | 4 +- packages/@intlayer/config/src/types/config.ts | 4 +- .../enumeration/enumeration.ts | 2 + .../enumeration/getEnumerationContent.ts | 13 +- .../translation/getTranslationContent.ts | 9 +- .../translation/translation.ts | 2 + packages/next-intlayer/README.md | 2 +- .../src/middleware/intlayerMiddleware.ts | 2 + .../next-intlayer/src/server/withIntlayer.ts | 2 + .../src/client/useTraduction.ts | 11 +- packages/react-intlayer/src/getEnumeration.ts | 13 +- packages/react-intlayer/src/getTranslation.ts | 5 +- .../src/server/useTraduction.ts | 7 +- pnpm-lock.yaml | 6 + 34 files changed, 1313 insertions(+), 178 deletions(-) create mode 100644 docs/content_declaration/declaration_watching.md create mode 100644 docs/content_declaration/enumeration.md create mode 100644 docs/content_declaration/function_fetching.md create mode 100644 docs/content_declaration/get_started.md create mode 100644 docs/content_declaration/nested_id.md create mode 100644 docs/content_declaration/translation.md create mode 100644 docs/interest_of_intlayer.md create mode 100644 docs/intlayer_cli.md create mode 100644 docs/intlayer_with_create_react_app.md create mode 100644 docs/intlayer_with_i18n.md create mode 100644 docs/intlayer_with_nextjs.md create mode 100644 examples/cli/src/7_translation/custom_content.content.ts create mode 100644 examples/cli/src/7_translation/react_content.content.tsx diff --git a/README.md b/README.md index 79f18a653..3ec51c1ed 100644 --- a/README.md +++ b/README.md @@ -1,197 +1,113 @@ -# Intlayer: Next-Level Content Management in JavaScript +# Intlayer: A closer way to translate your application -**Intlayer** is an innovative Content Management System (CMS) designed specifically for JavaScript developers. It enables seamless transpilation of JavaScript content into structured dictionaries, making integration into your codebase straightforward and efficient. +Intlayer is an innovative internationalization framework designed to replace i18next for Next.js and React applications. It streamlines the process of internationalization with flexible content declaration and robust configuration options. -## Why Choose Intlayer? +## Why Intlayer? -- **JavaScript-Powered Content Management**: Harness the flexibility of JavaScript to define and manage your content efficiently. -- **Type-Safe Environment**: Leverage TypeScript to ensure all your content definitions are precise and error-free. -- **Integrated Content Files**: Keep your translations close to their respective components, enhancing maintainability and clarity. -- **Simplified Setup**: Get up and running quickly with minimal configuration, especially optimized for Next.js projects. -- **Server Component Support**: Perfectly suited for Next.js server components, ensuring smooth server-side rendering. -- **Enhanced Routing**: Full support for Next.js app routing, adapting seamlessly to complex application structures. +Intlayer offers a more modern approach to internationalization compared to traditional frameworks like i18next. It is designed to fit seamlessly into Next.js and React projects, providing intuitive content declaration, robust configuration options, and a simpler setup process. -## Getting Started with Intlayer +- **Content Declaration**: Declare content dictionaries in the same directory as your components, enhancing maintainability and reducing complexity. [Learn more](https://github.com/aypineau/intlayer/blob/main/docs/content_declaration.md). +- **Customizable Configuration**: Intlayer allows you to customize various aspects of the framework, including internationalization, middleware, and content handling. [Learn how to configure](https://github.com/aypineau/intlayer/blob/main/docs/configuration.md). +- **Integration with Next.js and React**: Intlayer integrates smoothly with Next.js and React applications. It also supports server-side rendering and dynamic routing. [Explore Next.js integration](https://github.com/aypineau/intlayer/blob/main/docs/intlayer_with_nextjs.md) | [Explore React integration](https://github.com/aypineau/intlayer/blob/main/docs/intlayer_with_create_react_app.md). +- **Scalability and Consistency**: With Intlayer, your content dictionaries are structured and consistent, reducing the chances of errors during development. This ensures a more reliable internationalization process. +- **TypeScript Support**: Intlayer provides full support for TypeScript, allowing for more type-safe code. This enhances developer productivity and code quality. -Setting up Intlayer in a Next.js application is straightforward: +## Getting Started -### Step 1: Install Dependencies +To start using Intlayer, follow these steps: -Install the necessary packages using npm: +### Installation + +Install the necessary packages for your project: ```bash -npm install intlayer next-intlayer +npm install intlayer ``` ```bash -yarn install intlayer next-intlayer +yarn add intlayer ``` ```bash -pnpm install intlayer next-intlayer +pnpm add intlayer ``` -### Step 2: Integrate Intlayer in Your Next.js Configuration +### Declaring Your Content -Configure your Next.js setup to use Intlayer: +Intlayer allows you to declare your content in various formats, including TypeScript, ECMAScript modules, CommonJS modules, and JSON. Here's an example of a content declaration using TypeScript: -```javascript -// next.config.mjs -import { withIntlayer } from "next-intlayer/server"; +```typescript +import { t, type ContentModule } from "intlayer"; -const nextConfig = {}; +const exampleContent: ContentModule = { + id: "example", + welcome: t({ + en: "Welcome", + fr: "Bienvenue", + es: "Bienvenido", + }), +}; -export default withIntlayer(nextConfig); +export default exampleContent; ``` -### Step 3: Configure Middleware for Locale Detection +For more examples and information on content declaration, [see the documentation](https://github.com/aypineau/intlayer/blob/main/docs/content_declaration.md). -Set up middleware to detect the user's preferred locale: +### Integrating with Next.js -```typescript -// src/middleware.ts -export { intlayerMiddleware as middleware } from 'next-intlayer/middleware'; +If you're using Next.js, Intlayer is designed to work seamlessly with it. The integration process involves setting up middleware, defining locale routes, and utilizing content dictionaries in your components. -export const config = { - matcher: '/((?!api|static|._\\.._|\_next).*), -}; -``` +Follow this guide to [set up Intlayer with Next.js](https://github.com/aypineau/intlayer/blob/main/docs/intlayer_with_nextjs.md). -### Step 4: Define Dynamic Locale Routes +### Integrating with React -Implement dynamic routing for localized content: +For Create React App users, Intlayer also provides an easy way to integrate internationalization. Learn how to [set up Intlayer with Create React App](https://github.com/aypineau/intlayer/blob/main/docs/intlayer_with_create_react_app.md). -Change `src/app/page.ts` to `src/app/[locale]/page.ts` +### Configuration -### Step 5: Manage Your Content +Intlayer's configuration is highly customizable. You can define internationalization settings, middleware behavior, and more. The configuration file supports various formats like TypeScript, JavaScript, and JSON. -Create and manage your content dictionaries: +Here's an example configuration: ```typescript -// src/app/[locale]/page.content.ts -import { t, type ContentModule } from "intlayer"; +// intlayer.config.ts + +import { Locales, type IntlayerConfig } from "intlayer"; -const pageContent: ContentModule = { - id: "page", - getStarted: { - main: t({ - en: "Get started by editing", - fr: "Commencez par éditer", - es: "Comience por editar", - }), - pageLink: "src/app/page.tsx", +const config: IntlayerConfig = { + internationalization: { + locales: [Locales.ENGLISH], + defaultLocale: Locales.ENGLISH, }, }; -export default pageContent; +export default config; ``` -### Step 6: Utilize Content in Your Code - -Access your content dictionaries throughout your application: - -```tsx -// src/app/[locale]/page.ts - -import { ClientComponentExample } from "@component/components/ClientComponentExample"; -import { LocaleSwitcher } from "@component/components/LangSwitcherDropDown"; -import { NestedServerComponentExample } from "@component/components/NestedServerComponentExample"; -import { ServerComponentExample } from "@component/components/ServerComponentExample"; -import { type NextPageIntlayer, IntlayerClientProvider } from "next-intlayer"; -import { IntlayerServerProvider, useIntlayer } from "next-intlayer/server"; - -const Page: NextPageIntlayer = ({ params: { locale } }) => { - const content = useIntlayer("page", locale); - - return ( - <> -

- {content.getStarted.main} - {content.getStarted.pageLink} -

- {/** - * IntlayerServerProvider is used to provide the locale to the server children - * Don't work if set in the layout - */} - - - - {/** - * IntlayerClientProvider is used to provide the locale to the client children - * Can be set in any parent component, including the layout - */} - - - - - ); -}; - -export default Page; -``` +For more information on configuring Intlayer, [check the configuration documentation](https://github.com/aypineau/intlayer/blob/main/docs/configuration.md). -```tsx -// src/components/ClientComponentExample.tsx +## Using Intlayer with i18next -"use client"; +Intlayer can also export i18next dictionaries for projects that still rely on i18next for certain functionalities. This integration allows you to generate i18next dictionaries while still benefiting from Intlayer's flexible content declaration. [Learn how to configure Intlayer for i18next](https://github.com/aypineau/intlayer/blob/main/docs/intlayer_with_i18n.md). -import { useIntlayer } from "next-intlayer"; +## CLI Commands -export const ClientComponentExample = () => { - const content = useIntlayer("client-component-example"); // Create related content declaration +Intlayer comes with a CLI package that allows you to transpile your content declarations into dictionaries. You can run these commands to build your dictionaries: - return ( -
-

{content.title}

-

{content.content}

-
- ); -}; +```bash +npx intlayer transpile ``` -```tsx -// src/components/ServerComponentExample.tsx +To run in watch mode: -import { useIntlayer } from "next-intlayer/server"; - -export const ServerComponentExample = () => { - const content = useIntlayer("server-component-example"); // Create related content declaration - - return ( -
-

{content.title}

-

{content.content}

-
- ); -}; +```bash +npx intlayer watch ``` -For more detailed usage of intlayer into Client, or Server component, see the [nextJS example here](https://github.com/aypineau/intlayer/blob/main/examples/nextjs-app/src/app/%5Blocale%5D/demo-usage-components/page.tsx). - -## Configuration of your project - -Create a config file to configure the languages of your application: - -```typescript -// intlayer.config.ts - -import { Locales, type IntlayerConfig } from "intlayer"; - -const config: IntlayerConfig = { - internationalization: { - locales: [ - Locales.ENGLISH, - // Your other locales - ], - defaultLocale: Locales.ENGLISH, - }, -}; - -export default config; -``` +For more information on the CLI and its usage, [refer to the CLI documentation](https://github.com/aypineau/intlayer/blob/main/docs/intlayer_cli.md). -To see all available parameters, refer to the [configuration documentation here](https://github.com/aypineau/intlayer/blob/main/docs/configuration.md). +## Conclusion ---- +Intlayer offers a more flexible and modern approach to internationalization. Its seamless integration with Next.js and React, customizable configuration, and support for various content declaration formats make it a powerful choice for internationalization. -This version emphasizes ease of use, practical steps, and the professional application of Intlayer in a Next.js environment. +For additional resources, guides, and examples, explore the [Intlayer documentation](https://github.com/aypineau/intlayer/blob/main/docs/intlayer_with_nextjs.md). diff --git a/docs/configuration.md b/docs/configuration.md index 7cfcab676..8f5c751b8 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -170,30 +170,60 @@ Settings related to content handling within the application, including directory - _Description_: The base directory for the project. - _Example_: `'/path/to/project'` - _Note_: This is used to resolve all Intlayer-related directories. +- **dictionaryOutput**: + - _Type_: `string[]` + - _Default_: `['intlayer']` + - _Description_: The type of dictionary output to use, e.g., `'intlayer'` or `'i18next'`. - **contentDirName**: - _Type_: `string` - _Default_: `'src'` - _Description_: The name of the directory where the content is stored. - _Example_: `'data'`, `'content'`, `'locales'` - _Note_: If not at the base directory level, update the `contentDir`. +- **contentDir**: + + - _Type_: `string` + - _DerivedFrom_: `'baseDir'` / `'contentDirName'` + - _Description_: The directory path where content is stored. + - **resultDirName**: - _Type_: `string` - _Default_: `'.intlayer'` - _Description_: The name of the directory where results are stored. - _Example_: `'outputOFIntlayer'` - _Note_: If this directory is not at the base level, update `resultDir`. +- **resultDir**: + + - _Type_: `string` + - _DerivedFrom_: `'baseDir'` / `'resultDirName'` + - _Description_: The directory path for storing intermediate or output results. + - **moduleAugmentationDirName**: + - _Type_: `string` - _Default_: `'types'` - _Description_: Directory for module augmentation, allowing better IDE suggestions and type checking. - _Example_: `'intlayer-types'` - _Note_: Be sure to include this in `tsconfig.json`. + +- **moduleAugmentationDir**: + + - _Type_: `string` + - _DerivedFrom_: `'baseDir'` / `'moduleAugmentationDirName'` + - _Description_: The path for module augmentation and additional type definitions. + - **dictionariesDirName**: - _Type_: `string` - _Default_: `'dictionary'` - _Description_: Directory for storing dictionaries. - _Example_: `'translations'` - _Note_: If not at the result directory level, update `dictionariesDir`. +- **dictionariesDir**: + + - _Type_: `string` + - _DerivedFrom_: `'resultDir'` / `'dictionariesDirName'` + - _Description_: The directory for storing localization dictionaries. + - **i18nDictionariesDirName**: - _Type_: `string` - _Default_: `'i18_dictionary'` @@ -201,18 +231,37 @@ Settings related to content handling within the application, including directory - _Example_: `'translations'` - _Note_: If not at the result directory level, update `i18nDictionariesDir`. - _Note_: Ensure the i18n dictionaries output includes i18next to build the dictionaries for i18next +- **i18nDictionariesDir**: + + - _Type_: `string` + - _DerivedFrom_: `'resultDir'` / `'i18nDictionariesDirName'` + - _Description_: The directory for storing i18n dictionaries. + - _Note_: Ensure this directory is configured for the i18next output type. + - **typeDirName**: + - _Type_: `string` - _Default_: `'types'` - _Description_: Directory for storing dictionary types. - _Example_: `'intlayer-types'` - _Note_: If not at the result directory level, update `typesDir`. + +- **typesDir**: + + - _Type_: `string` + - _DerivedFrom_: `'resultDir'` / `'typeDirName'` + - _Description_: The directory for storing dictionary types. + - **mainDirName**: - _Type_: `string` - _Default_: `'main'` - _Description_: Directory for storing main files. - _Example_: `'intlayer-main'` - _Note_: If not at the result directory level, update `mainDir`. +- **mainDir**: + - _Type_: `string` + - _DerivedFrom_: `'resultDir'` / `'mainDirName'` + - _Description_: The directory where main application files are stored. - **excludedPath**: - _Type_: `string[]` - _Default_: `['node_modules']` diff --git a/docs/content_declaration/declaration_watching.md b/docs/content_declaration/declaration_watching.md new file mode 100644 index 000000000..c0738e84e --- /dev/null +++ b/docs/content_declaration/declaration_watching.md @@ -0,0 +1,61 @@ +# Intlayer Package Documentation: Content Extension Customization + +## Overview + +The `intlayer` package is a versatile solution designed to structure your content for multi-language applications using JavaScript. This documentation focuses on customizing content file extensions to enhance build efficiency and avoid conflicts in large projects. + +To build dictionaries from your content declarations, you can use [intlayer-cli](https://github.com/aypineau/intlayer/blob/main/packages/intlayer-cli/readme.md). For interpreting these dictionaries, consider [react-intlayer](https://github.com/aypineau/intlayer/blob/main/packages/react-intlayer/readme.md) or [next-intlayer](https://github.com/aypineau/intlayer/blob/main/packages/next-intlayer/readme.md). + +## Content File Extensions + +Intlayer allows you to customize the extensions for your content declaration files. This customization provides flexibility in managing large-scale projects and helps to avoid conflicts with other modules. + +### Default Extensions + +By default, Intlayer watches all files with the following extensions for content declarations: + +- `.content.ts` +- `.content.tsx` +- `.content.js` +- `.content.mjs` +- `.content.cjs` + +These default extensions are suitable for most applications. However, when you have specific needs, you can define custom extensions to streamline the build process and reduce the risk of conflicts with other components. + +### Customizing Content Extensions + +To customize the file extensions Intlayer uses to identify content declaration files, you can specify them in the Intlayer configuration file. This approach is beneficial for large-scale projects where limiting the scope of the watch process improves build performance. + +Here is an example of how to define custom content extensions in your configuration: + +```typescript +import type { IntlayerConfig } from "intlayer"; + +const config: IntlayerConfig = { + content: { + fileExtensions: [".my_content.ts", ".my_content.tsx"], // Your custom extensions + }, +}; + +export default config; +``` + +In this example, the configuration specifies two custom extensions: `.my_content.ts` and `.my_content.tsx`. Intlayer will only watch files with these extensions to build dictionaries. + +### Benefits of Custom Extensions + +- **Build Performance**: Reducing the scope of watched files can significantly improve build performance in large projects. +- **Conflict Avoidance**: Custom extensions help prevent conflicts with other JavaScript or TypeScript files in your project. +- **Organization**: Custom extensions allow you to organize your content declaration files according to your project's needs. + +### Guidelines for Custom Extensions + +When customizing content file extensions, keep the following guidelines in mind: + +- **Uniqueness**: Choose extensions that are unique within your project to avoid conflicts. +- **Consistent Naming**: Use consistent naming conventions for better code readability and maintenance. +- **Avoiding Common Extensions**: Refrain from using common extensions like `.ts` or `.js` to prevent conflicts with other modules or libraries. + +## Conclusion + +Customizing content file extensions in Intlayer is a valuable feature for optimizing performance and avoiding conflicts in large-scale applications. By following the guidelines outlined in this documentation, you can effectively manage your content declarations and ensure smooth integration with other parts of your project. diff --git a/docs/content_declaration/enumeration.md b/docs/content_declaration/enumeration.md new file mode 100644 index 000000000..df18d196a --- /dev/null +++ b/docs/content_declaration/enumeration.md @@ -0,0 +1,81 @@ +# Intlayer Enumeration Documentation + +## Overview + +Enumeration in Intlayer allows developers to define structured content with multiple variations based on specific conditions or thresholds. This is useful for scenarios like pluralization, numeric ranges, or general content-based enumeration. Using enumerations, you can create content that is dynamic and adaptable to varying conditions, such as changing language or different numbers of items. + +## How Enumeration Works + +In Intlayer, enumeration is achieved through the `enu` function, which maps specific keys to their corresponding content. These keys can represent numeric values, ranges, or custom identifiers. When used with React Intlayer or Next Intlayer, the appropriate content is automatically selected based on the application's locale and defined rules. + +## Setting Up Enumeration + +To set up enumeration in your Intlayer project, you need to create a content module that includes enumeration definitions. Here's an example of a simple enumeration for the number of cars: + +```typescript +import { enu, type ContentModule } from "intlayer"; + +const carEnumeration: ContentModule = { + id: "car_count", + numberOfCar: enu({ + "<-1": "Less than minus one car", + "-1": "Minus one car", + "0": "No cars", + "1": "One car", + ">5": "Some cars", + ">19": "Many cars", + }), +}; + +export default carEnumeration; +``` + +In this example, `enu` maps various conditions to specific content. When used in a React component, Intlayer can automatically choose the appropriate content based on the given variable. + +## Using Enumeration with React Intlayer + +To use enumeration in a React component, you can leverage the `useIntlayer` hook from the `react-intlayer` package. This hook retrieves the correct content based on the specified ID. Here's an example of how to use it: + +```javascript +import { useIntlayer } from "react-intlayer"; + +const CarComponent = () => { + const content = useIntlayer("car_count"); + + return ( +
+

{content.numberOfCar(0)}

{/* Output: No cars */} +

{content.numberOfCar(6)}

{/* Output: Some cars */} +

{content.numberOfCar(20)}

{/* Output: Some cars */} +
+ ); +}; + +export default CarComponent; +``` + +In this example, the component dynamically adjusts its output based on the number of cars. The correct content is chosen automatically, depending on the specified range. + +## Important Notes + +- The order of declaration is crucial in Intlayer enumerations. The first valid declaration is the one that will be picked up. +- If multiple conditions apply, ensure they are ordered correctly to avoid unexpected behavior. + +## Best Practices for Enumeration + +To ensure your enumerations work as expected, follow these best practices: + +- **Consistent Naming**: Use clear and consistent IDs for enumeration modules to avoid confusion. +- **Documentation**: Document your enumeration keys and their expected outputs to ensure future maintainability. +- **Error Handling**: Implement error handling to manage cases where no valid enumeration is found. +- **Optimize Performance**: For large applications, reduce the number of watched file extensions to improve performance. + +## Additional Resources + +For more detailed information on configuration and usage, refer to the following resources: + +- [Intlayer CLI Documentation](https://github.com/aypineau/intlayer/blob/main/docs/intlayer_cli.md) +- [React Intlayer Documentation](https://github.com/aypineau/intlayer/blob/main/docs/intlayer_with_create_react_app.md) +- [Next Intlayer Documentation](https://github.com/aypineau/intlayer/blob/main/docs/intlayer_with_nextjs.md) + +These resources provide further insights into the setup and usage of Intlayer in different environments and with various frameworks. diff --git a/docs/content_declaration/function_fetching.md b/docs/content_declaration/function_fetching.md new file mode 100644 index 000000000..d14d5fc8a --- /dev/null +++ b/docs/content_declaration/function_fetching.md @@ -0,0 +1,76 @@ +## Intlayer Function Fetching + +### Overview + +Intlayer is a powerful package for managing structured content in JavaScript applications, allowing developers to create content dictionaries, support multiple languages, and implement enumeration for dynamic content. It offers advanced features such as nested content structures and function declarations for flexible data fetching. + +This guide focuses on the function fetching capabilities of Intlayer, including synchronous and asynchronous functions, to fetch or generate content dynamically. Function fetching is especially useful in scenarios where data needs to be processed, retrieved from external sources, or mocked for testing and development purposes. + +### Function Declarations + +Intlayer allows you to declare content functions in your content modules, which can be either synchronous or asynchronous. When the application builds, Intlayer executes these functions to obtain the function's result. The return value must be a JSON object or a simple value like a string or number. + +Here's an example of a simple synchronous function fetching content: + +```typescript +import type { ContentModule } from "intlayer"; + +const functionContent: ContentModule = { + id: "function_content", + text: () => "This is the content rendered by a function", +}; + +export default functionContent; +``` + +In this example, the `text` key contains a function that returns a string. This content can be rendered in your React components using Intlayer's interpreter packages like `react-intlayer`. + +### Asynchronous Function Fetching + +In addition to synchronous functions, Intlayer supports asynchronous functions, allowing you to fetch data from external sources or simulate data retrieval with mock data. + +Below is an example of an asynchronous function that simulates a server fetch: + +```typescript +import type { ContentModule } from "intlayer"; + +const fakeFetch = async () => { + // Simulate a server fetch with a delay + await new Promise((resolve) => setTimeout(resolve, 200)); + + return "This is the content fetched from the server"; +}; + +const asyncFunctionContent: ContentModule = { + id: "async_function_content", + text: fakeFetch, +}; + +export default asyncFunctionContent; +``` + +In this case, the `fakeFetch` function mimics a delay to simulate server response time. Intlayer executes the asynchronous function and uses the result as the content for the `text` key. + +### Using Function-Based Content in React Components + +To use function-based content in a React component, you need to import `useIntlayer` from `react-intlayer` and call it with the content ID to retrieve the content. Here's an example: + +```javascript +import { useIntlayer } from "react-intlayer"; + +const MyComponent = () => { + const functionContent = useIntlayer("function_content"); + const asyncFunctionContent = useIntlayer("async_function_content"); + + return ( +
+

{functionContent.text}

+ {/* Output: This is the content rendered by a function */} +

{asyncFunctionContent.text}

+ {/* Output: This is the content fetched from the server */} +
+ ); +}; + +export default MyComponent; +``` diff --git a/docs/content_declaration/get_started.md b/docs/content_declaration/get_started.md new file mode 100644 index 000000000..dd7b3b2e8 --- /dev/null +++ b/docs/content_declaration/get_started.md @@ -0,0 +1,168 @@ +# Intlayer Package Documentation + +## intlayer package + +`intlayer` package intend to declare your content in a structured way, using JavaScript. + +To build dictionaries from this declaration, you can use [intlayer-cli](https://github.com/aypineau/intlayer/blob/main/packages/intlayer-cli/readme.md). +And to interpret intlayer dictionaries you can interpreters, such as [react-intlayer](https://github.com/aypineau/intlayer/blob/main/packages/react-intlayer/readme.md), or [next-intlayer](https://github.com/aypineau/intlayer/blob/main/packages/next-intlayer/readme.md) + +## Getting Started with Intlayer + +[See how to use intlayer with NextJS](https://github.com/aypineau/intlayer/blob/main/readme.md) + +### Install Package + +Install the necessary packages using npm: + +```bash +npm install intlayer +``` + +```bash +yarn install intlayer +``` + +```bash +pnpm install intlayer +``` + +### Manage Your Content + +Create and manage your content dictionaries: + +#### Using typescript + +```typescript +// src/app/[locale]/page.content.ts +import { t, enu, type ContentModule } from "intlayer"; + +const pageContent: ContentModule = { + id: "page", + getStarted: { + main: t({ + en: "Get started by editing", + fr: "Commencez par éditer", + es: "Comience por editar", + }), + pageLink: "src/app/page.tsx", + }, + nestedContent: { + id: "enumeration", + numberOfCar: enu({ + "<-1": "Less than minus one car", + "-1": "Minus one car", + "0": "No cars", + "1": "One car", + ">5": "Some cars", + ">19": "Many cars", + }), + }, +}; + +// Content should be exported as default +export default pageContent; +``` + +#### Using ECMAScript modules + +```javascript +// src/app/[locale]/page.content.mjs + +import { t } from "intlayer"; + +/** @type {import('intlayer').ContentModule} */ +const pageContent = { + id: "page", + getStarted: { + main: t({ + en: "Get started by editing", + fr: "Commencez par éditer", + es: "Comience por editar", + }), + pageLink: "src/app/page.tsx", + }, + nestedContent: { + id: "enumeration", + numberOfCar: enu({ + "<-1": "Less than minus one car", + "-1": "Minus one car", + "0": "No cars", + "1": "One car", + ">5": "Some cars", + ">19": "Many cars", + }), + }, +}; + +// Content should be exported as default +export default pageContent; +``` + +#### Using CommonJS modules + +```javascript +// src/app/[locale]/page.content.cjs + +const { t } = require("intlayer"); + +/** @type {import('intlayer').ContentModule} */ +const pageContent = { + id: "page", + getStarted: { + main: t({ + en: "Get started by editing", + fr: "Commencez par éditer", + es: "Comience por editar", + }), + pageLink: "src/app/page.tsx", + }, + nestedContent: { + id: "enumeration", + numberOfCar: enu({ + "<-1": "Less than minus one car", + "-1": "Minus one car", + "0": "No cars", + "1": "One car", + ">5": "Some cars", + ">19": "Many cars", + }), + }, +}; + +// Content should be exported as default +module.exports = pageContent; +``` + +#### Using CommonJS modules + +```json +// src/app/[locale]/page.content.json + +{ + "id": "page", + "getStarted": { + "main": { + "nodeType": "translation", + "en": "Get started by editing", + "fr": "Commencez par éditer", + "es": "Comience por editar", + }, + "pageLink": "src/app/page.tsx", + }, + "nestedContent": { + "id": "enumeration", + "nodeType": "enumeration", + "numberOfCar": { + "<-1": "Less than minus one car", + "-1": "Minus one car", + "0": "No cars", + "1": "One car", + ">5": "Some cars", + ">19": "Many cars", + }, + }, +}; +``` + +This version emphasizes ease of use, practical steps, and the professional application of Intlayer in a Next.js environment. diff --git a/docs/content_declaration/nested_id.md b/docs/content_declaration/nested_id.md new file mode 100644 index 000000000..7065a9881 --- /dev/null +++ b/docs/content_declaration/nested_id.md @@ -0,0 +1,102 @@ +# Intlayer Package Documentation + +## Overview + +The `intlayer` package offers a comprehensive solution to declare your content in a structured way using JavaScript. This guide will explain the concept of nested IDs, a method to manage large declaration files with improved performance, allowing you to efficiently define, manage, and access your content. + +## Intlayer Package + +The `intlayer` package is designed to help you structure and manage content in a multi-lingual environment. It integrates with tools like [intlayer-cli](https://github.com/aypineau/intlayer/blob/main/packages/intlayer-cli/readme.md) to create dictionaries from your declarations, and with interpreters like [react-intlayer](https://github.com/aypineau/intlayer/blob/main/packages/react-intlayer/readme.md) and [next-intlayer](https://github.com/aypineau/intlayer/blob/main/packages/next-intlayer/readme.md) to use these dictionaries in different frameworks. + +## Getting Started with Nested IDs + +Nested IDs in `intlayer` allow you to declare complex content structures efficiently. By introducing nested IDs, you can organize content into a hierarchical structure, leading to better performance and easier management in large-scale applications. + +### Nested ID Declaration + +To declare nested IDs in your content file, you create a structure with inner nodes containing additional content and unique identifiers. This setup is ideal for scenarios where content is vast or highly organized. Here's a typical example of a nested ID structure: + +```typescript +import type { ContentModule } from "intlayer"; + +const nestedContent: ContentModule = { + id: "parent_id", + text: "This is the parent node", + + nestedContent: { + id: "child_id", + text: "This is the child node", + }, +}; + +export default nestedContent; +``` + +In this example, the `parent_id` contains a nested content node with an `id` of `child_id`. This structure allows `intlayer` to create separate dictionaries for each ID, providing flexibility in content management. + +### Using Nested IDs in React + +To utilize nested IDs in a React component, you can employ the `useIntlayer` hook to access the content from a given ID. This approach allows you to extract specific content pieces by referencing their unique IDs. Here's an example of how to retrieve content with nested IDs: + +```javascript +import { useIntlayer } from "react-intlayer"; + +// Display the content in a React component +function MyComponent() { + // Access the parent content + const parentContent = useIntlayer("parent_id"); + + // Access the child content + const childContent = useIntlayer("child_id"); + + return ( +
+

{parentContent.text}

{/* Output: This is the parent node */} +

{childContent.text}

{/* Output: This is the child node */} +
+ ); +} + +export default MyComponent; +``` + +In this example, the `useIntlayer` hook retrieves the content based on the specified IDs. You can then display the content as required, with the flexibility to access both parent and child content independently. + +### Key Benefits of Nested IDs + +Nested IDs offer several benefits: + +- **Improved Performance**: By splitting large content into smaller, organized structures, you reduce the load on your application, leading to improved performance. +- **Flexibility**: The hierarchical structure allows you to access specific parts of the content, providing greater flexibility in application design. +- **Scalability**: As applications grow, nested IDs make it easier to manage complex content structures without losing organization or performance. + +### Advanced Usage of Nested IDs + +To further optimize the performance of nested IDs, you can declare multiple nested levels or use additional unique identifiers within the structure. Here's an example with deeper nesting: + +```typescript +import type { ContentModule } from "intlayer"; + +const deeplyNestedContent: ContentModule = { + id: "level_1", + text: "Level 1 content", + + nestedContent: { + id: "level_2", + text: "Level 2 content", + + nestedContent: { + id: "level_3", + text: "Level 3 content", + }, + }, +}; + +export default deeplyNestedContent; +``` + +In this example, the content structure has three levels of nesting, each with a unique identifier. This design allows you to retrieve content at any level of the hierarchy, providing significant flexibility in content management. + +### Conclusion + +Nested IDs in `intlayer` offer a powerful tool for organizing and managing complex content structures in a way that optimizes performance and scalability. By following the examples and guidelines in this documentation, you can build efficient content declarations that are easy to maintain and expand as your application grows. diff --git a/docs/content_declaration/translation.md b/docs/content_declaration/translation.md new file mode 100644 index 000000000..a216e746c --- /dev/null +++ b/docs/content_declaration/translation.md @@ -0,0 +1,151 @@ +# Intlayer Translation Documentation + +The `intlayer` package offers a robust framework for declaring content in a structured way using JavaScript. It is designed to be versatile, supporting multi-language translations and a variety of use cases for web applications. This guide will focus on how to use `intlayer` for translation in your application. + +## Defining Translations + +The `t` function in `intlayer` allows you to declare content in multiple languages. This function ensures type safety, raising an error if any translations are missing, which is particularly useful in TypeScript environments. + +### Using TypeScript + +Here's an example of how to declare content with translations in a TypeScript file: + +```typescript +import { t, type ContentModule } from "intlayer"; + +const multiLangContent: ContentModule = { + id: "multi_lang", + welcomeMessage: t({ + en: "Welcome to our application", + fr: "Bienvenue dans notre application", + es: "Bienvenido a nuestra aplicación", + }), +}; + +export default multiLangContent; +``` + +### Using ECMAScript Modules + +If you're using ECMAScript modules, the declaration looks like this: + +```javascript +import { t } from "intlayer"; + +const multiLangContent = { + id: "multi_lang", + welcomeMessage: t({ + en: "Welcome to our application", + fr: "Bienvenue dans notre application", + es: "Bienvenido a nuestra aplicación", + }), +}; + +export default multiLangContent; +``` + +### Using CommonJS Modules + +In a CommonJS setup, you can declare translations like this: + +```javascript +const { t } = require("intlayer"); + +const multiLangContent = { + id: "multi_lang", + welcomeMessage: t({ + en: "Welcome to our application", + fr: "Bienvenue dans notre application", + es: "Bienvenido a nuestra aplicación", + }), +}; + +module.exports = multiLangContent; +``` + +### Using JSON + +For JSON-based declarations, you can define translations as follows: + +```json +{ + "id": "multi_lang", + "welcomeMessage": { + "nodeType": "translation", + "en": "Welcome to our application", + "fr": "Bienvenue dans notre application", + "es": "Bienvenido a nuestra aplicación" + } +} +``` + +## Configuration for Locales + +To ensure proper translation handling, you can configure the accepted locales in `intlayer.config.ts`. This configuration allows you to define the languages that your application supports: + +```typescript +import { Locales, type IntlayerConfig } from "intlayer"; + +const config: IntlayerConfig = { + internationalization: { + locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH], + }, +}; + +export default config; +``` + +## Using Translations in React Components + +With `react-intlayer`, you can use translations in React components. Here's an example: + +```jsx +import { useIntlayer } from "react-intlayer"; + +const MyComponent = () => { + const content = useIntlayer("multi_lang"); + + return ( +
+

{content.welcomeMessage}

+
+ ); +}; + +export default MyComponent; +``` + +This component fetches the corresponding translation based on the current locale set in your application. + +## Custom Content Objects + +`intlayer` supports custom content objects for translation, allowing you to define more complex structures while ensuring type safety. Here's an example with a custom object: + +```typescript +import { t, type ContentModule } from "intlayer"; + +interface ICustomContent { + title: string; + content: string; +} + +const customContent: ContentModule = { + id: "custom_content", + profileText: t({ + en: { + title: "Page Title", + content: "Page Content", + }, + fr: { + title: "Titre de la Page", + content: "Contenu de la Page", + }, + es: { + title: "Título de la Página", + content: "Contenido de la Página", + }, + }), +}; + +export default customContent; +``` diff --git a/docs/interest_of_intlayer.md b/docs/interest_of_intlayer.md new file mode 100644 index 000000000..af783aa99 --- /dev/null +++ b/docs/interest_of_intlayer.md @@ -0,0 +1,13 @@ +# Intlayer: A closer way to translate your application + +**Intlayer** is an innovative Content Management System (CMS) designed specifically for JavaScript developers. It converts declaration of multilingual JavaScript content into structured dictionaries, making integration into your codebase straightforward and efficient. + +## Why Choose Intlayer? + +- **JavaScript-Powered Content Management**: Harness the flexibility of JavaScript to define and manage your content efficiently. +- **Type-Safe Environment**: Leverage TypeScript to ensure all your content definitions are precise and error-free. +- **Integrated Content Files**: Keep your translations close to their respective components, enhancing maintainability and clarity. +- **Simplified Setup**: Get up and running quickly with minimal configuration, especially optimized for Next.js projects. +- **Server Component Support**: Perfectly suited for Next.js server components, ensuring smooth server-side rendering. +- **Enhanced Routing**: Full support for Next.js app routing, adapting seamlessly to complex application structures. +- **Interoperability**: Allow i18next interoperability. (beta) diff --git a/docs/intlayer_cli.md b/docs/intlayer_cli.md new file mode 100644 index 000000000..402ac453f --- /dev/null +++ b/docs/intlayer_cli.md @@ -0,0 +1,59 @@ +### Install Package + +Install the necessary packages using npm: + +```bash +npm install intlayer-cli +``` + +```bash +yarn install intlayer-cli +``` + +```bash +pnpm install intlayer-cli +``` + +# intlayer-cli package + +`intlayer-cli` package intend to transpile your [intlayer](https://github.com/aypineau/intlayer/blob/main/packages/intlayer/readme.md) declarations into dictionaries. + +This package will transpile all intlayer files, such as `src/**/*.content.{ts|js|mjs|cjs|json}`. [See how to declare your Intlayer declaration files](https://github.com/aypineau/intlayer/blob/main/packages/intlayer/readme.md). + +To interpret intlayer dictionaries you can interpreters, such as [react-intlayer](https://github.com/aypineau/intlayer/blob/main/packages/react-intlayer/readme.md), or [next-intlayer](https://github.com/aypineau/intlayer/blob/main/packages/next-intlayer/readme.md) + +# Configuration File Support + +Intlayer accepts multiple configuration file formats: + +- `intlayer.config.ts` +- `intlayer.config.js` +- `intlayer.config.json` +- `intlayer.config.cjs` +- `intlayer.config.mjs` +- `.intlayerrc` + +To see how to configure available locales, or other parameters, refer to the [configuration documentation here](https://github.com/aypineau/intlayer/blob/main/docs/configuration.md). + +## Run intlayer commands + +To build your dictionaries, you can run the commands: + +```bash +npx intlayer transpile +``` + +or in watch mode + +```bash +npx intlayer watch +``` + +## Use intlayer commands in your `package.json`: + +```json +"scripts": { + "transpile": "npx intlayer transpile", + "transpile:watch": "npx intlayer watch" +} +``` diff --git a/docs/intlayer_with_create_react_app.md b/docs/intlayer_with_create_react_app.md new file mode 100644 index 000000000..374891188 --- /dev/null +++ b/docs/intlayer_with_create_react_app.md @@ -0,0 +1,127 @@ +# Getting Started with Intlayer + +Setting up Intlayer in a Create React App application is straightforward: + +## Step 1: Install Dependencies + +Install the necessary packages using npm: + +```bash +npm install intlayer react-intlayer +``` + +```bash +yarn install intlayer react-intlayer +``` + +```bash +pnpm install intlayer react-intlayer +``` + +## Step 2: Integrate Intlayer in Your CRA Configuration + +Change your scripts to use react-intlayer + +```json + "scripts": { + "build": "react-intlayer build", + "start": "react-intlayer start", + "transpile": "intlayer transpile" + }, +``` + +Note: react-intlayer scripts are based on craco. You can also implement your own setup based on the intlayer craco plugin. (See example here)[https://github.com/aypineau/intlayer/blob/main/examples/react-app/craco.config.js]. + +## Step 3: Declare Your Content + +Create and manage your content dictionaries: + +```tsx +// src/app/[locale]/page.content.ts +import { t, type ContentModule } from "intlayer"; + +const pageContent: ContentModule = { + id: "page", + getStarted: { + main: t({ + en: "Get started by editing", + fr: "Commencez par éditer", + es: "Comience por editar", + }), + pageLink: "src/app/page.tsx", + }, +}; + +export default pageContent; +``` + +### Step 4: Utilize Intlayer in Your Code + +Access your content dictionaries throughout your application: + +```tsx +import logo from "./logo.svg"; +import "./App.css"; +import { IntlayerClientProvider, useIntlayer } from "react-intlayer"; +import { LocaleSwitcher } from "./components/LangSwitcherDropDown"; + +function AppContent() { + const content = useIntlayer("app"); + + return ( +
+ logo + + {content.getStarted} + + {content.reactLink.content} + +
+ ); +} + +function App() { + return ( + +
+ {/* To use the useIntlayer hook properly, you should access your data in a children component */} + +
+
+ +
+
+ ); +} + +export default App; +``` + +## Configuration of your project + +Create a config file to configure the languages of your application: + +```typescript +// intlayer.config.ts + +import { Locales, type IntlayerConfig } from "intlayer"; + +const config: IntlayerConfig = { + internationalization: { + locales: [ + Locales.ENGLISH, + // Your other locales + ], + defaultLocale: Locales.ENGLISH, + }, +}; + +export default config; +``` + +To see all available parameters, refer to the [configuration documentation here](https://github.com/aypineau/intlayer/blob/main/docs/configuration.md). diff --git a/docs/intlayer_with_i18n.md b/docs/intlayer_with_i18n.md new file mode 100644 index 000000000..09782c473 --- /dev/null +++ b/docs/intlayer_with_i18n.md @@ -0,0 +1,79 @@ +# Internationalization with Intlayer and i18next + +i18next is an open-source internationalization (i18n) framework designed for JavaScript applications. It is widely used for managing translations, localization, and language switching in software projects. However, it has some limitations that can complicate scalability and development. + +Intlayer is another internationalization framework that addresses these limitations, offering a more flexible approach to content declaration and management. Let's explore some key differences between i18next and Intlayer, and how to configure both for optimal internationalization. + +## Intlayer vs. i18next: Key Differences + +### 1. Content Declaration + +With i18next, translation dictionaries must be declared in a specific folder, which can complicate application scalability. In contrast, Intlayer allows content to be declared within the same directory as your component. This has several advantages: + +- **Simplified Content Editing**: Users don't have to search for the correct dictionary to edit, reducing the chance of errors. +- **Automatic Adaptation**: If a component changes location or is removed, Intlayer detects and adapts automatically. + +### 2. Configuration Complexity + +Configuring i18next can be complex, especially when integrating with server-side components or configuring middleware for frameworks like Next.js. Intlayer simplifies this process, offering more straightforward configuration. + +### 3. Consistency of Translation Dictionaries + +Ensuring that translation dictionaries are consistent across different languages can be challenging with i18next. This inconsistency can lead to application crashes if not handled properly. Intlayer addresses this by enforcing constraints on translated content, ensuring no translation is missed and that the translated content is accurate. + +### 4. TypeScript Integration + +Intlayer offers better integration with TypeScript, allowing for auto-suggestions of content in your code, thereby enhancing development efficiency. + +### 5. Sharing Content Across Applications + +Intlayer facilitates the sharing of content declaration files across multiple applications and shared libraries. This feature makes it easier to maintain consistent translations across a larger codebase. + +## How to Generate i18next Dictionaries with Intlayer + +### Configuring Intlayer to Export i18next Dictionaries + +To export i18next dictionaries, you need to configure Intlayer appropriately. Below is an example of how to set up Intlayer to export both Intlayer and i18next dictionaries. + +```typescript +// intlayer.config.ts + +import { Locales, type IntlayerConfig } from "intlayer"; + +const config: IntlayerConfig = { + content: { + // Indicate that Intlayer will export both Intlayer and i18next dictionaries + dictionaryOutput: ["intlayer", "i18next"], + // Relative path from the project root to the directory where i18n dictionaries will be exported + i18nDictionariesDir: "./i18n/dictionaries", + }, +}; + +export default config; +``` + +By including 'i18next' in the configuration, Intlayer generates dedicated i18next dictionaries in addition to the Intlayer dictionaries. Note that removing 'intlayer' from the configuration may break compatibility with React-Intlayer or Next-Intlayer. + +### Importing Dictionaries into Your i18next Configuration + +To import the generated dictionaries into your i18next configuration, you can use 'i18next-resources-to-backend'. Here is an example of how to import your i18next dictionaries: + +```typescript +// i18n/client.ts + +import i18next from "i18next"; +import resourcesToBackend from "i18next-resources-to-backend"; + +i18next + // Your i18next configuration + .use( + resourcesToBackend( + (language: string, namespace: string) => + import(`../i18n-dictionaries/${language}/${namespace}.json`) + ) + ); +``` + +## Important Notes + +The exportation of i18next dictionaries is currently in beta and does not ensure a 1:1 compatibility with other frameworks. It is recommended to stick to a configuration based on Intlayer to minimize issues. diff --git a/docs/intlayer_with_nextjs.md b/docs/intlayer_with_nextjs.md new file mode 100644 index 000000000..0b45e2ec7 --- /dev/null +++ b/docs/intlayer_with_nextjs.md @@ -0,0 +1,182 @@ +# Getting Started with Intlayer + +Setting up Intlayer in a Next.js application is straightforward: + +## Step 1: Install Dependencies + +Install the necessary packages using npm: + +```bash +npm install intlayer next-intlayer +``` + +```bash +yarn install intlayer next-intlayer +``` + +```bash +pnpm install intlayer next-intlayer +``` + +## Step 2: Integrate Intlayer in Your Next.js Configuration + +Configure your Next.js setup to use Intlayer: + +```typescript +// next.config.mjs +import { withIntlayer } from "next-intlayer/server"; + +const nextConfig = {}; + +export default withIntlayer(nextConfig); +``` + +## Step 3: Configure Middleware for Locale Detection + +Set up middleware to detect the user's preferred locale: + +```typescript +// src/middleware.ts +export { intlayerMiddleware as middleware } from 'next-intlayer/middleware'; + +export const config = { + matcher: '/((?!api|static|._\\.._|\_next).*), +}; +``` + +## Step 4: Define Dynamic Locale Routes + +Implement dynamic routing for localized content: + +Change `src/app/page.ts` to `src/app/[locale]/page.ts` + +## Step 5: Declare Your Content + +Create and manage your content dictionaries: + +```tsx +// src/app/[locale]/page.content.ts +import { t, type ContentModule } from "intlayer"; + +const pageContent: ContentModule = { + id: "page", + getStarted: { + main: t({ + en: "Get started by editing", + fr: "Commencez par éditer", + es: "Comience por editar", + }), + pageLink: "src/app/page.tsx", + }, +}; + +export default pageContent; +``` + +[See how to declare your Intlayer declaration files](https://github.com/aypineau/intlayer/blob/main/docs/content_declaration/get_started.md). + +## Step 6: Utilize Content in Your Code + +Access your content dictionaries throughout your application: + +```tsx +// src/app/[locale]/page.ts + +import { ClientComponentExample } from "@component/components/ClientComponentExample"; +import { LocaleSwitcher } from "@component/components/LangSwitcherDropDown"; +import { NestedServerComponentExample } from "@component/components/NestedServerComponentExample"; +import { ServerComponentExample } from "@component/components/ServerComponentExample"; +import { type NextPageIntlayer, IntlayerClientProvider } from "next-intlayer"; +import { IntlayerServerProvider, useIntlayer } from "next-intlayer/server"; + +const Page: NextPageIntlayer = ({ params: { locale } }) => { + const content = useIntlayer("page", locale); + + return ( + <> +

+ {content.getStarted.main} + {content.getStarted.pageLink} +

+ {/** + * IntlayerServerProvider is used to provide the locale to the server children + * Don't work if set in the layout + */} + + + + {/** + * IntlayerClientProvider is used to provide the locale to the client children + * Can be set in any parent component, including the layout + */} + + + + + ); +}; + +export default Page; +``` + +```tsx +// src/components/ClientComponentExample.tsx + +"use client"; + +import { useIntlayer } from "next-intlayer"; + +export const ClientComponentExample = () => { + const content = useIntlayer("client-component-example"); // Create related content declaration + + return ( +
+

{content.title}

+

{content.content}

+
+ ); +}; +``` + +```tsx +// src/components/ServerComponentExample.tsx + +import { useIntlayer } from "next-intlayer/server"; + +export const ServerComponentExample = () => { + const content = useIntlayer("server-component-example"); // Create related content declaration + + return ( +
+

{content.title}

+

{content.content}

+
+ ); +}; +``` + +For more detailed usage of intlayer into Client, or Server component, see the [nextJS example here](https://github.com/aypineau/intlayer/blob/main/examples/nextjs-app/src/app/%5Blocale%5D/demo-usage-components/page.tsx). + +# Configuration of your project + +Create a config file to configure the languages of your application: + +```typescript +// intlayer.config.ts + +import { Locales, type IntlayerConfig } from "intlayer"; + +const config: IntlayerConfig = { + internationalization: { + locales: [ + Locales.ENGLISH, + // Your other locales + ], + defaultLocale: Locales.ENGLISH, + }, +}; + +export default config; +``` + +To see all available parameters, refer to the [configuration documentation here](https://github.com/aypineau/intlayer/blob/main/docs/configuration.md). diff --git a/examples/cli/package.json b/examples/cli/package.json index 8a8c709da..f311c1866 100644 --- a/examples/cli/package.json +++ b/examples/cli/package.json @@ -25,6 +25,8 @@ "intlayer-cli": "workspace:^" }, "devDependencies": { + "@types/react": "^18.2.79", + "@types/react-dom": "^18.2.25", "typescript": "^5.4.5" }, "bug": { diff --git a/examples/cli/src/7_translation/custom_content.content.ts b/examples/cli/src/7_translation/custom_content.content.ts new file mode 100644 index 000000000..b69499932 --- /dev/null +++ b/examples/cli/src/7_translation/custom_content.content.ts @@ -0,0 +1,26 @@ +import { t, type ContentModule } from 'intlayer'; + +interface ICustomContent { + title: string; + content: string; +} + +const customContent: ContentModule = { + id: 'custom_content', + profileText: t({ + en: { + title: 'Title of the page', + content: 'Content of the page', + }, + fr: { + title: 'Titre de la page', + content: 'Contenu de la page', + }, + es: { + title: 'Título de la página', + content: 'Contenido de la página', + }, + }), +}; + +export default customContent; diff --git a/examples/cli/src/7_translation/react_content.content.tsx b/examples/cli/src/7_translation/react_content.content.tsx new file mode 100644 index 000000000..07f31cab9 --- /dev/null +++ b/examples/cli/src/7_translation/react_content.content.tsx @@ -0,0 +1,12 @@ +import { t, type ContentModule } from 'intlayer'; + +const customContent: ContentModule = { + id: 'react_content', + profileText: t({ + en:

Title of the page

, + fr:

Titre de la page

, + es:

Título de la página

, + }), +}; + +export default customContent; diff --git a/examples/cli/tsconfig.json b/examples/cli/tsconfig.json index 60b734cd2..f7c3793b8 100644 --- a/examples/cli/tsconfig.json +++ b/examples/cli/tsconfig.json @@ -14,7 +14,7 @@ /* Language and Environment */ "target": "es2016" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ - // "jsx": "preserve", /* Specify what JSX code is generated. */ + "jsx": "react-jsx" /* Specify what JSX code is generated. */, // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ diff --git a/examples/nextjs-app/intlayer.config.cjs b/examples/nextjs-app/intlayer.config.cjs index 4df1213c4..43381b0ef 100644 --- a/examples/nextjs-app/intlayer.config.cjs +++ b/examples/nextjs-app/intlayer.config.cjs @@ -3,5 +3,7 @@ const { Locales } = require('intlayer'); /** @type {import('intlayer').IntlayerConfig} */ module.exports = { - locales: [Locales.ENGLISH, Locales.FRENCH], + internationalization: { + locales: [Locales.ENGLISH, Locales.FRENCH], + }, }; diff --git a/examples/nextjs-app/intlayer.config.js b/examples/nextjs-app/intlayer.config.js index 4df1213c4..918c4b5b9 100644 --- a/examples/nextjs-app/intlayer.config.js +++ b/examples/nextjs-app/intlayer.config.js @@ -1,7 +1,8 @@ const { Locales } = require('intlayer'); /** @type {import('intlayer').IntlayerConfig} */ - module.exports = { - locales: [Locales.ENGLISH, Locales.FRENCH], + internationalization: { + locales: [Locales.ENGLISH, Locales.FRENCH], + }, }; diff --git a/examples/nextjs-app/intlayer.config.json b/examples/nextjs-app/intlayer.config.json index e90a0fbe9..cf5688deb 100644 --- a/examples/nextjs-app/intlayer.config.json +++ b/examples/nextjs-app/intlayer.config.json @@ -1,3 +1,5 @@ { - "locales": ["en", "fr"] + "internationalization": { + "locales": ["en", "fr"] + } } diff --git a/examples/nextjs-app/intlayer.config.mjs b/examples/nextjs-app/intlayer.config.mjs index 930ed58f3..9cc05d918 100644 --- a/examples/nextjs-app/intlayer.config.mjs +++ b/examples/nextjs-app/intlayer.config.mjs @@ -3,7 +3,9 @@ import { Locales } from 'intlayer'; /** @type {import('intlayer').IntlayerConfig} */ const config = { - locales: [Locales.ENGLISH, Locales.FRENCH], + internationalization: { + locales: [Locales.ENGLISH, Locales.FRENCH], + }, }; export default config; diff --git a/packages/@intlayer/config/src/types/config.ts b/packages/@intlayer/config/src/types/config.ts index bb06b4b3c..0bd5b3c27 100644 --- a/packages/@intlayer/config/src/types/config.ts +++ b/packages/@intlayer/config/src/types/config.ts @@ -1,7 +1,5 @@ import type { Locales } from './locales'; -export type DictionaryOutput = 'intlayer' | 'i18next'; - /** * Configuration for internationalization settings */ @@ -227,6 +225,8 @@ export type BaseContentConfig = { mainDirName: string; }; +export type DictionaryOutput = 'intlayer' | 'i18next'; + /** * Configuration derived based on the base content configuration */ diff --git a/packages/@intlayer/core/src/transpiler/content_transformers/enumeration/enumeration.ts b/packages/@intlayer/core/src/transpiler/content_transformers/enumeration/enumeration.ts index 45a943f72..8495dcbe8 100644 --- a/packages/@intlayer/core/src/transpiler/content_transformers/enumeration/enumeration.ts +++ b/packages/@intlayer/core/src/transpiler/content_transformers/enumeration/enumeration.ts @@ -38,12 +38,14 @@ export type EnumerationContent = Partial> & * * Usage: * + * ```ts * const content = enu({ * '<=-2.3': 'You have less than -2.3', * '<1': 'You have less than one', * '2': 'You have two', * '>=3': 'You have three or more', * }); + * ``` * * The order of the keys will define the priority of the content. * diff --git a/packages/@intlayer/core/src/transpiler/content_transformers/enumeration/getEnumerationContent.ts b/packages/@intlayer/core/src/transpiler/content_transformers/enumeration/getEnumerationContent.ts index 145e185d0..1c3d0414a 100644 --- a/packages/@intlayer/core/src/transpiler/content_transformers/enumeration/getEnumerationContent.ts +++ b/packages/@intlayer/core/src/transpiler/content_transformers/enumeration/getEnumerationContent.ts @@ -7,22 +7,25 @@ type Key = keyof QuantityContent; * * Usage: * + * ```ts * const content = getEnumerationContent({ * '<=-2.3': 'You have less than -2.3', * '<1': 'You have less than one', * '2': 'You have two', * '>=3': 'You have three or more', - * }, - * 2); + * }, 2); * // 'You have two' + * ``` * * The order of the keys will define the priority of the content. * + * ```ts * const content = getEnumerationContent({ - * '<4': 'You have less than four', - * '2': 'You have two', - * }); + * '<4': 'You have less than four', + * '2': 'You have two', + * }, 2); * // 'You have less than four' + * ``` * */ export const getEnumerationContent = ( diff --git a/packages/@intlayer/core/src/transpiler/content_transformers/translation/getTranslationContent.ts b/packages/@intlayer/core/src/transpiler/content_transformers/translation/getTranslationContent.ts index c75cbd5ed..4195381f2 100644 --- a/packages/@intlayer/core/src/transpiler/content_transformers/translation/getTranslationContent.ts +++ b/packages/@intlayer/core/src/transpiler/content_transformers/translation/getTranslationContent.ts @@ -18,12 +18,13 @@ type GetTranslationContent = ( * * Usage: * + * ```ts * const content = getTranslationContent({ - * en: 'Hello', - * fr: 'Bonjour', - * }, - * 'fr'); + * en: 'Hello', + * fr: 'Bonjour', + * }, 'fr'); * // 'Bonjour' + * ``` * * Using TypeScript: * - this function will require each locale to be defined if defined in the project configuration. diff --git a/packages/@intlayer/core/src/transpiler/content_transformers/translation/translation.ts b/packages/@intlayer/core/src/transpiler/content_transformers/translation/translation.ts index e24890283..9333c9ebf 100644 --- a/packages/@intlayer/core/src/transpiler/content_transformers/translation/translation.ts +++ b/packages/@intlayer/core/src/transpiler/content_transformers/translation/translation.ts @@ -13,11 +13,13 @@ const { defaultLocale } = intlayerConfiguration.internationalization; * * Usage: * + * ```ts * translation({ * "en": "Hello", * "fr": "Bonjour", * // ... any other available locale * }) + * ``` * * Using TypeScript: * - this function require each locale to be defined if defined in the project configuration. diff --git a/packages/next-intlayer/README.md b/packages/next-intlayer/README.md index 766c0e8da..604877862 100644 --- a/packages/next-intlayer/README.md +++ b/packages/next-intlayer/README.md @@ -88,7 +88,7 @@ export default pageContent; [See how to declare your Intlayer declaration files](https://github.com/aypineau/intlayer/blob/main/packages/intlayer/readme.md). -### Step 6: Utilize Content in Your Code +### Step 6: Utilize Intlayer in Your Code Access your content dictionaries throughout your application: diff --git a/packages/next-intlayer/src/middleware/intlayerMiddleware.ts b/packages/next-intlayer/src/middleware/intlayerMiddleware.ts index 5a93b01ed..7019b6070 100644 --- a/packages/next-intlayer/src/middleware/intlayerMiddleware.ts +++ b/packages/next-intlayer/src/middleware/intlayerMiddleware.ts @@ -20,12 +20,14 @@ const { * * // ./src/middleware.ts * + * ```ts * export { intlayerMiddleware as middleware } from '@intlayer/next/middleware'; * * // applies this middleware only to files in the app directory * export const config = { * matcher: '/((?!api|static|.*\\..*|_next).*)', * }; + * ``` * */ export const intlayerMiddleware = (request: NextRequest): NextResponse => { diff --git a/packages/next-intlayer/src/server/withIntlayer.ts b/packages/next-intlayer/src/server/withIntlayer.ts index 817caff0b..5c6123af3 100644 --- a/packages/next-intlayer/src/server/withIntlayer.ts +++ b/packages/next-intlayer/src/server/withIntlayer.ts @@ -16,8 +16,10 @@ type WebpackParams = Parameters; * * Usage: * + * ```ts * // next.config.js * export default withIntlayer(nextConfig) + * ``` * */ export const withIntlayer = diff --git a/packages/react-intlayer/src/client/useTraduction.ts b/packages/react-intlayer/src/client/useTraduction.ts index 3c7d9b046..6a7075e3e 100644 --- a/packages/react-intlayer/src/client/useTraduction.ts +++ b/packages/react-intlayer/src/client/useTraduction.ts @@ -12,12 +12,13 @@ import { IntlayerClientContext } from './IntlayerClientProvider'; * * Usage: * - * const content = getTranslation({ - * en: 'Hello', - * fr: 'Bonjour', - * }, - * 'fr'); + * ```tsx + * const content = useTraduction({ + * en: 'Hello', + * fr: 'Bonjour', + * }, 'fr'); * // 'Bonjour' + * ``` * * Using TypeScript: * - this function will require each locale to be defined if defined in the project configuration. diff --git a/packages/react-intlayer/src/getEnumeration.ts b/packages/react-intlayer/src/getEnumeration.ts index efc882f0d..c6f72cb35 100644 --- a/packages/react-intlayer/src/getEnumeration.ts +++ b/packages/react-intlayer/src/getEnumeration.ts @@ -8,22 +8,25 @@ import { contentRender } from './ContentEditor/contentRender'; * * Usage: * + * ```ts * const content = getEnumeration({ * '<=-2.3': 'You have less than -2.3', * '<1': 'You have less than one', * '2': 'You have two', * '>=3': 'You have three or more', - * }, - * 2); + * }, 2); * // 'You have two' + * ``` * * The order of the keys will define the priority of the content. * + * ```ts * const content = getEnumeration({ - * '<4': 'You have less than four', - * '2': 'You have two', - * }); + * '<4': 'You have less than four', + * '2': 'You have two', + * }, 2); * // 'You have less than four' + * ``` * */ export const getEnumeration = ( diff --git a/packages/react-intlayer/src/getTranslation.ts b/packages/react-intlayer/src/getTranslation.ts index d9abd5c21..34b93f264 100644 --- a/packages/react-intlayer/src/getTranslation.ts +++ b/packages/react-intlayer/src/getTranslation.ts @@ -14,12 +14,13 @@ import { contentRender } from './ContentEditor/contentRender'; * * Usage: * + * ```ts * const content = getTranslation({ * en: 'Hello', * fr: 'Bonjour', - * }, - * 'fr'); + * }, 'fr'); * // 'Bonjour' + * ``` * * Using TypeScript: * - this function will require each locale to be defined if defined in the project configuration. diff --git a/packages/react-intlayer/src/server/useTraduction.ts b/packages/react-intlayer/src/server/useTraduction.ts index 8ee2ee482..900c7387f 100644 --- a/packages/react-intlayer/src/server/useTraduction.ts +++ b/packages/react-intlayer/src/server/useTraduction.ts @@ -13,12 +13,13 @@ import { getServerContext } from './serverContext'; * * Usage: * - * const content = getTranslation({ + * ```ts + * const content = useTraduction({ * en: 'Hello', * fr: 'Bonjour', - * }, - * 'fr'); + * }, 'fr'); * // 'Bonjour' + * ``` * * Using TypeScript: * - this function will require each locale to be defined if defined in the project configuration. diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a7dd6ab14..9875d04c0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -50,6 +50,12 @@ importers: specifier: workspace:^ version: link:../../packages/intlayer-cli devDependencies: + '@types/react': + specifier: ^18.2.79 + version: 18.2.79 + '@types/react-dom': + specifier: ^18.2.25 + version: 18.2.25 typescript: specifier: ^5.4.5 version: 5.4.5