@intlayer/docs 5.5.8 → 5.5.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ar/autoFill.md +1 -2
- package/ar/intlayer_with_create_react_app.md +1 -14
- package/ar/intlayer_with_nextjs_14.md +1 -14
- package/ar/intlayer_with_nextjs_15.md +1 -14
- package/ar/intlayer_with_nextjs_page_router.md +1 -13
- package/ar/intlayer_with_nuxt.md +792 -0
- package/ar/intlayer_with_react_native+expo.md +6 -3
- package/ar/intlayer_with_vite+preact.md +7 -18
- package/ar/intlayer_with_vite+react.md +7 -17
- package/ar/intlayer_with_vite+vue.md +25 -5
- package/ar/packages/nuxt-intlayer/index.md +29 -0
- package/ar/roadmap.md +11 -11
- package/de/autoFill.md +1 -2
- package/de/how_works_intlayer.md +1 -1
- package/de/intlayer_with_create_react_app.md +1 -14
- package/de/intlayer_with_nextjs_14.md +1 -14
- package/de/intlayer_with_nextjs_15.md +1 -14
- package/de/intlayer_with_nextjs_page_router.md +1 -13
- package/de/intlayer_with_nuxt.md +791 -0
- package/de/intlayer_with_react_native+expo.md +6 -3
- package/de/intlayer_with_vite+preact.md +7 -18
- package/de/intlayer_with_vite+react.md +7 -17
- package/de/intlayer_with_vite+vue.md +84 -62
- package/de/packages/nuxt-intlayer/index.md +29 -0
- package/de/roadmap.md +11 -11
- package/en/autoFill.md +1 -2
- package/en/how_works_intlayer.md +17 -3
- package/en/intlayer_with_angular.md +535 -6
- package/en/intlayer_with_create_react_app.md +1 -14
- package/en/intlayer_with_nextjs_14.md +193 -59
- package/en/intlayer_with_nextjs_15.md +192 -61
- package/en/intlayer_with_nextjs_page_router.md +396 -61
- package/en/intlayer_with_nuxt.md +737 -0
- package/en/intlayer_with_react_native+expo.md +6 -3
- package/en/intlayer_with_vite+preact.md +8 -27
- package/en/intlayer_with_vite+react.md +7 -17
- package/en/intlayer_with_vite+solid.md +6 -3
- package/en/intlayer_with_vite+svelte.md +6 -3
- package/en/intlayer_with_vite+vue.md +17 -6
- package/en/packages/nuxt-intlayer/index.md +31 -0
- package/en/roadmap.md +13 -13
- package/en/t.md +5 -5
- package/en-GB/how_works_intlayer.md +16 -4
- package/en-GB/intlayer_with_create_react_app.md +1 -14
- package/en-GB/intlayer_with_nextjs_14.md +1 -14
- package/en-GB/intlayer_with_nextjs_15.md +1 -14
- package/en-GB/intlayer_with_nextjs_page_router.md +1 -13
- package/en-GB/intlayer_with_nuxt.md +795 -0
- package/en-GB/intlayer_with_react_native+expo.md +6 -3
- package/en-GB/intlayer_with_vite+preact.md +7 -18
- package/en-GB/intlayer_with_vite+react.md +6 -9
- package/en-GB/intlayer_with_vite+vue.md +65 -59
- package/en-GB/packages/nuxt-intlayer/index.md +31 -0
- package/en-GB/roadmap.md +11 -11
- package/es/autoFill.md +1 -2
- package/es/how_works_intlayer.md +1 -1
- package/es/intlayer_with_create_react_app.md +1 -14
- package/es/intlayer_with_nextjs_14.md +1 -14
- package/es/intlayer_with_nextjs_15.md +1 -14
- package/es/intlayer_with_nextjs_page_router.md +1 -13
- package/es/intlayer_with_nuxt.md +731 -0
- package/es/intlayer_with_react_native+expo.md +6 -3
- package/es/intlayer_with_vite+preact.md +7 -18
- package/es/intlayer_with_vite+react.md +7 -17
- package/es/intlayer_with_vite+vue.md +64 -51
- package/es/packages/nuxt-intlayer/index.md +29 -0
- package/fr/autoFill.md +1 -2
- package/fr/how_works_intlayer.md +1 -1
- package/fr/intlayer_with_create_react_app.md +1 -14
- package/fr/intlayer_with_nextjs_14.md +1 -14
- package/fr/intlayer_with_nextjs_15.md +1 -14
- package/fr/intlayer_with_nextjs_page_router.md +1 -13
- package/fr/intlayer_with_nuxt.md +731 -0
- package/fr/intlayer_with_react_native+expo.md +6 -3
- package/fr/intlayer_with_vite+preact.md +7 -18
- package/fr/intlayer_with_vite+react.md +7 -17
- package/fr/intlayer_with_vite+vue.md +30 -15
- package/fr/packages/nuxt-intlayer/index.md +29 -0
- package/fr/roadmap.md +11 -11
- package/hi/autoFill.md +1 -2
- package/hi/how_works_intlayer.md +1 -1
- package/hi/intlayer_with_create_react_app.md +1 -14
- package/hi/intlayer_with_nextjs_14.md +1 -14
- package/hi/intlayer_with_nextjs_15.md +1 -14
- package/hi/intlayer_with_nextjs_page_router.md +1 -13
- package/hi/intlayer_with_nuxt.md +784 -0
- package/hi/intlayer_with_react_native+expo.md +6 -3
- package/hi/intlayer_with_vite+preact.md +7 -18
- package/hi/intlayer_with_vite+react.md +7 -17
- package/hi/intlayer_with_vite+vue.md +59 -47
- package/hi/packages/nuxt-intlayer/index.md +29 -0
- package/hi/roadmap.md +11 -11
- package/index.cjs +30 -0
- package/index.d.ts +2 -0
- package/it/autoFill.md +1 -2
- package/it/how_works_intlayer.md +1 -1
- package/it/intlayer_with_create_react_app.md +0 -6
- package/it/intlayer_with_nextjs_14.md +1 -14
- package/it/intlayer_with_nextjs_15.md +1 -14
- package/it/intlayer_with_nextjs_page_router.md +1 -13
- package/it/intlayer_with_nuxt.md +793 -0
- package/it/intlayer_with_react_native+expo.md +6 -3
- package/it/intlayer_with_vite+preact.md +7 -18
- package/it/intlayer_with_vite+react.md +7 -17
- package/it/intlayer_with_vite+vue.md +26 -17
- package/it/packages/nuxt-intlayer/index.md +29 -0
- package/it/roadmap.md +11 -11
- package/ja/autoFill.md +1 -2
- package/ja/how_works_intlayer.md +1 -1
- package/ja/intlayer_with_create_react_app.md +1 -14
- package/ja/intlayer_with_nextjs_14.md +1 -14
- package/ja/intlayer_with_nextjs_15.md +1 -14
- package/ja/intlayer_with_nextjs_page_router.md +1 -13
- package/ja/intlayer_with_nuxt.md +792 -0
- package/ja/intlayer_with_react_native+expo.md +6 -3
- package/ja/intlayer_with_vite+preact.md +7 -18
- package/ja/intlayer_with_vite+react.md +7 -17
- package/ja/intlayer_with_vite+vue.md +68 -63
- package/ja/packages/nuxt-intlayer/index.md +29 -0
- package/ja/roadmap.md +11 -11
- package/ko/autoFill.md +1 -2
- package/ko/how_works_intlayer.md +1 -1
- package/ko/intlayer_with_create_react_app.md +1 -14
- package/ko/intlayer_with_nextjs_14.md +1 -14
- package/ko/intlayer_with_nextjs_15.md +1 -14
- package/ko/intlayer_with_nextjs_page_router.md +1 -13
- package/ko/intlayer_with_nuxt.md +784 -0
- package/ko/intlayer_with_react_native+expo.md +6 -3
- package/ko/intlayer_with_vite+preact.md +7 -18
- package/ko/intlayer_with_vite+react.md +7 -17
- package/ko/intlayer_with_vite+vue.md +69 -59
- package/ko/packages/nuxt-intlayer/index.md +31 -0
- package/ko/roadmap.md +11 -11
- package/package.json +4 -4
- package/pt/autoFill.md +1 -2
- package/pt/how_works_intlayer.md +1 -1
- package/pt/intlayer_with_create_react_app.md +1 -14
- package/pt/intlayer_with_nextjs_14.md +1 -14
- package/pt/intlayer_with_nextjs_15.md +1 -14
- package/pt/intlayer_with_nextjs_page_router.md +1 -13
- package/pt/intlayer_with_nuxt.md +792 -0
- package/pt/intlayer_with_react_native+expo.md +6 -3
- package/pt/intlayer_with_vite+preact.md +7 -18
- package/pt/intlayer_with_vite+react.md +7 -17
- package/pt/intlayer_with_vite+vue.md +23 -19
- package/pt/packages/nuxt-intlayer/index.md +29 -0
- package/pt/roadmap.md +11 -11
- package/ru/autoFill.md +1 -2
- package/ru/how_works_intlayer.md +1 -1
- package/ru/intlayer_with_create_react_app.md +1 -14
- package/ru/intlayer_with_nextjs_14.md +1 -14
- package/ru/intlayer_with_nextjs_15.md +1 -14
- package/ru/intlayer_with_nextjs_page_router.md +1 -13
- package/ru/intlayer_with_nuxt.md +792 -0
- package/ru/intlayer_with_react_native+expo.md +6 -3
- package/ru/intlayer_with_vite+preact.md +7 -18
- package/ru/intlayer_with_vite+react.md +7 -17
- package/ru/intlayer_with_vite+vue.md +25 -17
- package/ru/packages/nuxt-intlayer/index.md +31 -0
- package/ru/roadmap.md +11 -11
- package/zh/autoFill.md +1 -2
- package/zh/intlayer_with_create_react_app.md +1 -14
- package/zh/intlayer_with_nextjs_14.md +1 -14
- package/zh/intlayer_with_nextjs_15.md +1 -14
- package/zh/intlayer_with_nextjs_page_router.md +1 -13
- package/zh/intlayer_with_nuxt.md +784 -0
- package/zh/intlayer_with_react_native+expo.md +6 -3
- package/zh/intlayer_with_vite+preact.md +7 -18
- package/zh/intlayer_with_vite+react.md +7 -17
- package/zh/intlayer_with_vite+vue.md +68 -57
- package/zh/packages/nuxt-intlayer/index.md +31 -0
- package/zh/roadmap.md +11 -11
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Getting Started
|
|
1
|
+
# Getting Started with Internationalization (i18n) in Angular using Intlayer
|
|
2
2
|
|
|
3
3
|
> This package is in development. See the [issue](https://github.com/aymericzip/intlayer/issues/116) for more information. Show your interest in Intlayer for Angular by liking the issue
|
|
4
4
|
|
|
@@ -17,22 +17,22 @@ With Intlayer, you can:
|
|
|
17
17
|
|
|
18
18
|
---
|
|
19
19
|
|
|
20
|
-
## Step-by-Step Guide to Set Up Intlayer in
|
|
20
|
+
## Step-by-Step Guide to Set Up Intlayer in an Angular Application
|
|
21
21
|
|
|
22
22
|
### Step 1: Install Dependencies
|
|
23
23
|
|
|
24
24
|
Install the necessary packages using npm:
|
|
25
25
|
|
|
26
26
|
```bash packageManager="npm"
|
|
27
|
-
npm install intlayer angular-intlayer
|
|
27
|
+
npm install intlayer angular-intlayer @intlayer/webpack
|
|
28
28
|
```
|
|
29
29
|
|
|
30
30
|
```bash packageManager="pnpm"
|
|
31
|
-
pnpm add intlayer angular-intlayer
|
|
31
|
+
pnpm add intlayer angular-intlayer @intlayer/webpack
|
|
32
32
|
```
|
|
33
33
|
|
|
34
34
|
```bash packageManager="yarn"
|
|
35
|
-
yarn add intlayer angular-intlayer
|
|
35
|
+
yarn add intlayer angular-intlayer @intlayer/webpack
|
|
36
36
|
```
|
|
37
37
|
|
|
38
38
|
- **intlayer**
|
|
@@ -42,6 +42,10 @@ yarn add intlayer angular-intlayer vite-intlayer
|
|
|
42
42
|
- **angular-intlayer**
|
|
43
43
|
The package that integrates Intlayer with Angular application. It provides context providers and hooks for Angular internationalization.
|
|
44
44
|
|
|
45
|
+
- **@intlayer/webpack**
|
|
46
|
+
|
|
47
|
+
The package that integrates Intlayer with Webpack. It is used by the Angular CLI to build content declaration files and monitor them in development mode.
|
|
48
|
+
|
|
45
49
|
### Step 2: Configuration of your project
|
|
46
50
|
|
|
47
51
|
Create a config file to configure the languages of your application:
|
|
@@ -104,7 +108,532 @@ module.exports = config;
|
|
|
104
108
|
|
|
105
109
|
> Through this configuration file, you can set up localized URLs, middleware redirection, cookie names, the location and extension of your content declarations, disable Intlayer logs in the console, and more. For a complete list of available parameters, refer to the [configuration documentation](https://github.com/aymericzip/intlayer/blob/main/docs/en/configuration.md).
|
|
106
110
|
|
|
107
|
-
|
|
111
|
+
### Step 3: Integrate Intlayer in Your Angular Configuration
|
|
112
|
+
|
|
113
|
+
To integrate Intlayer with the Angular CLI, you have two options depending on your builder: `esbuild` or `webpack`.
|
|
114
|
+
|
|
115
|
+
#### Option 1: Using esbuild (Recommended)
|
|
116
|
+
|
|
117
|
+
First, modify your `angular.json` to use the custom esbuild builder. Update the `build` configuration:
|
|
118
|
+
|
|
119
|
+
```json fileName="angular.json"
|
|
120
|
+
{
|
|
121
|
+
"projects": {
|
|
122
|
+
"your-app-name": {
|
|
123
|
+
"architect": {
|
|
124
|
+
"build": {
|
|
125
|
+
"builder": "@angular-builders/custom-esbuild:application",
|
|
126
|
+
"options": {
|
|
127
|
+
"plugins": ["./esbuild/intlayer-plugin.ts"]
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
> Make sure to replace `your-app-name` with the actual name of your project in `angular.json`.
|
|
137
|
+
|
|
138
|
+
Next, create an `esbuild/intlayer-plugin.ts` file in your project's root:
|
|
139
|
+
|
|
140
|
+
```typescript fileName="esbuild/intlayer-plugin.ts"
|
|
141
|
+
import { prepareIntlayer, watch } from "@intlayer/chokidar";
|
|
142
|
+
import { getConfiguration, logger } from "@intlayer/config";
|
|
143
|
+
import type { Plugin } from "esbuild";
|
|
144
|
+
|
|
145
|
+
const intlayerPlugin: Plugin = {
|
|
146
|
+
name: "intlayer-esbuild-plugin",
|
|
147
|
+
setup(build) {
|
|
148
|
+
const configuration = getConfiguration();
|
|
149
|
+
let isWatching = false;
|
|
150
|
+
|
|
151
|
+
build.onStart(async () => {
|
|
152
|
+
logger("Intlayer esbuild plugin started", {
|
|
153
|
+
level: "info",
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
if (build.initialOptions.watch && !isWatching) {
|
|
157
|
+
logger("Watch mode enabled. Starting watcher...", {
|
|
158
|
+
level: "info",
|
|
159
|
+
});
|
|
160
|
+
watch(configuration);
|
|
161
|
+
isWatching = true;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
try {
|
|
165
|
+
await prepareIntlayer(configuration);
|
|
166
|
+
} catch (error) {
|
|
167
|
+
logger(`Error in Intlayer esbuild plugin: ${error}`, {
|
|
168
|
+
level: "error",
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
},
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
export default intlayerPlugin;
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
> The `intlayerPlugin` for esbuild ensures that Intlayer is prepared before the build starts and watches for changes in development mode.
|
|
179
|
+
|
|
180
|
+
#### Option 2: Using Webpack
|
|
181
|
+
|
|
182
|
+
First, modify your `angular.json` to use the custom Webpack builder. Update the `build` and `serve` configurations:
|
|
183
|
+
|
|
184
|
+
```json fileName="angular.json"
|
|
185
|
+
{
|
|
186
|
+
"projects": {
|
|
187
|
+
"your-app-name": {
|
|
188
|
+
"architect": {
|
|
189
|
+
"build": {
|
|
190
|
+
"builder": "@angular-builders/custom-webpack:browser",
|
|
191
|
+
"options": {
|
|
192
|
+
"customWebpackConfig": {
|
|
193
|
+
"path": "./webpack.config.js"
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
},
|
|
197
|
+
"serve": {
|
|
198
|
+
"builder": "@angular-builders/custom-webpack:dev-server"
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
> Make sure to replace `your-app-name` with the actual name of your project in `angular.json`.
|
|
207
|
+
|
|
208
|
+
Next, create a `webpack.config.js` file at the root of your project:
|
|
209
|
+
|
|
210
|
+
```javascript fileName="webpack.config.js"
|
|
211
|
+
const { IntlayerWebpackPlugin } = require("@intlayer/webpack");
|
|
212
|
+
|
|
213
|
+
module.exports = {
|
|
214
|
+
plugins: [new IntlayerWebpackPlugin()],
|
|
215
|
+
};
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
> The `IntlayerWebpackPlugin` is used to integrate Intlayer with Webpack. It ensures the building of content declaration files and monitors them in development mode. It defines Intlayer environment variables within the application. Additionally, it provides aliases to optimize performance.
|
|
219
|
+
|
|
220
|
+
### Step 4: Declare Your Content
|
|
221
|
+
|
|
222
|
+
Create and manage your content declarations to store translations:
|
|
223
|
+
|
|
224
|
+
```tsx fileName="src/app/app.content.ts" contentDeclarationFormat="typescript"
|
|
225
|
+
import { t, type Dictionary } from "intlayer";
|
|
226
|
+
|
|
227
|
+
const appContent = {
|
|
228
|
+
key: "app",
|
|
229
|
+
content: {
|
|
230
|
+
title: t({
|
|
231
|
+
en: "Hello",
|
|
232
|
+
fr: "Bonjour",
|
|
233
|
+
es: "Hola",
|
|
234
|
+
}),
|
|
235
|
+
congratulations: t({
|
|
236
|
+
en: "Congratulations! Your app is running. 🎉",
|
|
237
|
+
fr: "Félicitations! Votre application est en cours d'exécution. 🎉",
|
|
238
|
+
es: "¡Felicidades! Tu aplicación está en ejecución. 🎉",
|
|
239
|
+
}),
|
|
240
|
+
exploreDocs: t({
|
|
241
|
+
en: "Explore the Docs",
|
|
242
|
+
fr: "Explorer les Docs",
|
|
243
|
+
es: "Explorar los Docs",
|
|
244
|
+
}),
|
|
245
|
+
learnWithTutorials: t({
|
|
246
|
+
en: "Learn with Tutorials",
|
|
247
|
+
fr: "Apprendre avec les Tutoriels",
|
|
248
|
+
es: "Aprender con los Tutorios",
|
|
249
|
+
}),
|
|
250
|
+
cliDocs: "CLI Docs",
|
|
251
|
+
angularLanguageService: t({
|
|
252
|
+
en: "Angular Language Service",
|
|
253
|
+
fr: "Service de Langage Angular",
|
|
254
|
+
es: "Servicio de Lenguaje Angular",
|
|
255
|
+
}),
|
|
256
|
+
angularDevTools: "Angular DevTools",
|
|
257
|
+
github: "Github",
|
|
258
|
+
twitter: "Twitter",
|
|
259
|
+
youtube: "Youtube",
|
|
260
|
+
},
|
|
261
|
+
} satisfies Dictionary;
|
|
262
|
+
|
|
263
|
+
export default appContent;
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
> Your content declarations can be defined anywhere in your application as soon they are included into the `contentDir` directory (by default, `./src`). And match the content declaration file extension (by default, `.content.{json,ts,tsx,js,jsx,mjs,mjx,cjs,cjx}`).
|
|
267
|
+
|
|
268
|
+
> For more details, refer to the [content declaration documentation](https://github.com/aymericzip/intlayer/blob/main/docs/en/dictionary/get_started.md).
|
|
269
|
+
|
|
270
|
+
### Step 5: Utilize Intlayer in Your Code
|
|
271
|
+
|
|
272
|
+
To utilize Intlayer's internationalization features throughout your Angular application, you need to use the `useIntlayer` function within a component. This function, available from `angular-intlayer`, provides access to your translations as reactive signals.
|
|
273
|
+
|
|
274
|
+
`IntlayerProvider` is registered in the root of the application, so you don't need to add it to your module's providers.
|
|
275
|
+
|
|
276
|
+
Access your content dictionaries in your component class:
|
|
277
|
+
|
|
278
|
+
```typescript fileName="src/app/hello-world.component.ts"
|
|
279
|
+
import { Component, signal } from "@angular/core";
|
|
280
|
+
import { useIntlayer } from "angular-intlayer";
|
|
281
|
+
|
|
282
|
+
@Component({
|
|
283
|
+
selector: "app-hello-world",
|
|
284
|
+
standalone: true,
|
|
285
|
+
template: `
|
|
286
|
+
<h1>{{ content().title }}</h1>
|
|
287
|
+
|
|
288
|
+
<div class="card">
|
|
289
|
+
<button type="button" (click)="increment()">
|
|
290
|
+
{{ content().count }} {{ count() }}
|
|
291
|
+
</button>
|
|
292
|
+
<p [innerHTML]="content().edit"></p>
|
|
293
|
+
</div>
|
|
294
|
+
|
|
295
|
+
<p class="read-the-docs">{{ content().readTheDocs }}</p>
|
|
296
|
+
`,
|
|
297
|
+
})
|
|
298
|
+
export class HelloWorldComponent {
|
|
299
|
+
content = useIntlayer("helloworld");
|
|
300
|
+
count = signal(0);
|
|
301
|
+
|
|
302
|
+
increment() {
|
|
303
|
+
this.count.update((value) => value + 1);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
Intlayer content is returned as a `Signal`, so you access the values by calling the signal in your template: `content().title`.
|
|
309
|
+
|
|
310
|
+
### (Optional) Step 6: Change the language of your content
|
|
311
|
+
|
|
312
|
+
To change the language of your content, you can use the `setLocale` function provided by the `useLocale` function. This allows you to set the locale of the application and update the content accordingly.
|
|
313
|
+
|
|
314
|
+
Create a component to switch between languages:
|
|
315
|
+
|
|
316
|
+
```typescript fileName="src/app/components/locale-switcher.component.ts"
|
|
317
|
+
import { Component } from "@angular/core";
|
|
318
|
+
import { CommonModule } from "@angular/common";
|
|
319
|
+
import { getLocaleName } from "intlayer";
|
|
320
|
+
import { useLocale } from "angular-intlayer";
|
|
321
|
+
import { FormsModule } from "@angular/forms";
|
|
322
|
+
|
|
323
|
+
@Component({
|
|
324
|
+
selector: "app-locale-switcher",
|
|
325
|
+
standalone: true,
|
|
326
|
+
imports: [CommonModule, FormsModule],
|
|
327
|
+
template: `
|
|
328
|
+
<div class="locale-switcher">
|
|
329
|
+
<select [ngModel]="locale()" (ngModelChange)="changeLocale($event)">
|
|
330
|
+
<option *ngFor="let loc of availableLocales" [value]="loc">
|
|
331
|
+
{{ getLocaleName(loc) }}
|
|
332
|
+
</option>
|
|
333
|
+
</select>
|
|
334
|
+
</div>
|
|
335
|
+
`,
|
|
336
|
+
})
|
|
337
|
+
export class LocaleSwitcherComponent {
|
|
338
|
+
localeInfo = useLocale();
|
|
339
|
+
locale = this.localeInfo.locale;
|
|
340
|
+
availableLocales = this.localeInfo.availableLocales;
|
|
341
|
+
|
|
342
|
+
// Expose getLocaleName to the template
|
|
343
|
+
getLocaleName = getLocaleName;
|
|
344
|
+
|
|
345
|
+
changeLocale(newLocale: string) {
|
|
346
|
+
this.localeInfo.setLocale(newLocale);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
Then, use this component in your `app.component.ts`:
|
|
352
|
+
|
|
353
|
+
```typescript fileName="src/app/app.component.ts"
|
|
354
|
+
import { Component } from "@angular/core";
|
|
355
|
+
import { HelloWorldComponent } from "./hello-world.component";
|
|
356
|
+
import { LocaleSwitcherComponent } from "./components/locale-switcher.component";
|
|
357
|
+
|
|
358
|
+
@Component({
|
|
359
|
+
selector: "app-root",
|
|
360
|
+
standalone: true,
|
|
361
|
+
imports: [HelloWorldComponent, LocaleSwitcherComponent],
|
|
362
|
+
template: `
|
|
363
|
+
<div>
|
|
364
|
+
<app-locale-switcher />
|
|
365
|
+
<a href="https://vite.dev" target="_blank">
|
|
366
|
+
<img src="/vite.svg" class="logo" alt="Vite logo" />
|
|
367
|
+
</a>
|
|
368
|
+
<a href="https://angular.dev/" target="_blank">
|
|
369
|
+
<img
|
|
370
|
+
src="/assets/angular.svg"
|
|
371
|
+
class="logo angular"
|
|
372
|
+
alt="Angular logo"
|
|
373
|
+
/>
|
|
374
|
+
</a>
|
|
375
|
+
</div>
|
|
376
|
+
<app-hello-world />
|
|
377
|
+
`,
|
|
378
|
+
})
|
|
379
|
+
export class AppComponent {}
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### (Optional) Step 7: Add localized Routing to your application
|
|
383
|
+
|
|
384
|
+
Adding localized routing in an Angular application involves using the Angular Router with locale prefixes. This creates unique routes for each language, which is useful for SEO.
|
|
385
|
+
|
|
386
|
+
Example:
|
|
387
|
+
|
|
388
|
+
```plaintext
|
|
389
|
+
- https://example.com/about
|
|
390
|
+
- https://example.com/es/about
|
|
391
|
+
- https://example.com/fr/about
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
First, ensure you have `@angular/router` installed.
|
|
395
|
+
|
|
396
|
+
Then, create a router configuration that handles locale-based routing in `app.routes.ts`.
|
|
397
|
+
|
|
398
|
+
```typescript fileName="src/app/app.routes.ts"
|
|
399
|
+
import { Routes } from "@angular/router";
|
|
400
|
+
import { configuration, localeFlatMap } from "intlayer";
|
|
401
|
+
import { HomeComponent } from "./home/home.component";
|
|
402
|
+
import { RootComponent } from "./root/root.component";
|
|
403
|
+
|
|
404
|
+
const { defaultLocale } = configuration.internationalization;
|
|
405
|
+
|
|
406
|
+
export const routes: Routes = [
|
|
407
|
+
localeFlatMap((localizedData) => [
|
|
408
|
+
{
|
|
409
|
+
path: `${localizedData.urlPrefix}`,
|
|
410
|
+
component: RootComponent,
|
|
411
|
+
data: { locale: localizedData.locale },
|
|
412
|
+
},
|
|
413
|
+
{
|
|
414
|
+
path: `${localizedData.urlPrefix}/home`,
|
|
415
|
+
component: HomeComponent,
|
|
416
|
+
data: { locale: localizedData.locale },
|
|
417
|
+
},
|
|
418
|
+
]),
|
|
419
|
+
{ path: "**", redirectTo: `/${defaultLocale}/home` },
|
|
420
|
+
];
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
Then, you need to provide the router in your `app.config.ts`.
|
|
424
|
+
|
|
425
|
+
```typescript fileName="src/app/app.config.ts"
|
|
426
|
+
import { ApplicationConfig } from "@angular/core";
|
|
427
|
+
import { provideRouter } from "@angular/router";
|
|
428
|
+
import { routes } from "./app.routes";
|
|
429
|
+
|
|
430
|
+
export const appConfig: ApplicationConfig = {
|
|
431
|
+
providers: [provideRouter(routes)],
|
|
432
|
+
};
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
### (Optional) Step 8: Change the URL when the locale changes
|
|
436
|
+
|
|
437
|
+
To automatically update the URL when the user changes the language, you can modify the `LocaleSwitcher` component to use Angular's Router:
|
|
438
|
+
|
|
439
|
+
```typescript fileName="src/app/components/locale-switcher.component.ts"
|
|
440
|
+
import { Component, inject } from "@angular/core";
|
|
441
|
+
import { CommonModule } from "@angular/common";
|
|
442
|
+
import { Router } from "@angular/router";
|
|
443
|
+
import { getLocaleName, getLocalizedUrl } from "intlayer";
|
|
444
|
+
import { useLocale } from "angular-intlayer";
|
|
445
|
+
import { FormsModule } from "@angular/forms";
|
|
446
|
+
|
|
447
|
+
@Component({
|
|
448
|
+
selector: "app-locale-switcher",
|
|
449
|
+
standalone: true,
|
|
450
|
+
imports: [CommonModule, FormsModule],
|
|
451
|
+
template: `
|
|
452
|
+
<div class="locale-switcher">
|
|
453
|
+
<select [ngModel]="locale()" (ngModelChange)="changeLocale($event)">
|
|
454
|
+
<option *ngFor="let loc of availableLocales" [value]="loc">
|
|
455
|
+
{{ getLocaleName(loc) }}
|
|
456
|
+
</option>
|
|
457
|
+
</select>
|
|
458
|
+
</div>
|
|
459
|
+
`,
|
|
460
|
+
})
|
|
461
|
+
export class LocaleSwitcherComponent {
|
|
462
|
+
private router = inject(Router);
|
|
463
|
+
|
|
464
|
+
localeInfo = useLocale({
|
|
465
|
+
onLocaleChange: (newLocale) => {
|
|
466
|
+
const currentPath = this.router.url;
|
|
467
|
+
const localizedPath = getLocalizedUrl(currentPath, newLocale);
|
|
468
|
+
this.router.navigateByUrl(localizedPath);
|
|
469
|
+
},
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
locale = this.localeInfo.locale;
|
|
473
|
+
availableLocales = this.localeInfo.availableLocales;
|
|
474
|
+
|
|
475
|
+
getLocaleName = getLocaleName;
|
|
476
|
+
|
|
477
|
+
changeLocale(newLocale: string) {
|
|
478
|
+
this.localeInfo.setLocale(newLocale);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
### (Optional) Step 9: Switch the HTML Language and Direction Attributes
|
|
484
|
+
|
|
485
|
+
When your application supports multiple languages, it's crucial to update the `<html>` tag's `lang` and `dir` attributes to match the current locale.
|
|
486
|
+
|
|
487
|
+
You can create a service to handle this automatically.
|
|
488
|
+
|
|
489
|
+
```typescript fileName="src/app/services/i18n-html-attributes.service.ts"
|
|
490
|
+
import { Injectable, effect } from "@angular/core";
|
|
491
|
+
import { useLocale } from "angular-intlayer";
|
|
492
|
+
import { getHTMLTextDir } from "intlayer";
|
|
493
|
+
|
|
494
|
+
@Injectable({
|
|
495
|
+
providedIn: "root",
|
|
496
|
+
})
|
|
497
|
+
export class I18nHtmlAttributesService {
|
|
498
|
+
private localeInfo = useLocale();
|
|
499
|
+
|
|
500
|
+
constructor() {
|
|
501
|
+
effect(() => {
|
|
502
|
+
const newLocale = this.localeInfo.locale();
|
|
503
|
+
if (newLocale) {
|
|
504
|
+
document.documentElement.lang = newLocale;
|
|
505
|
+
document.documentElement.dir = getHTMLTextDir(newLocale);
|
|
506
|
+
}
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// This method can be called in the app's root component to ensure the service is initialized.
|
|
511
|
+
init() {}
|
|
512
|
+
}
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
Then, inject and initialize this service in your main `AppComponent`:
|
|
516
|
+
|
|
517
|
+
```typescript fileName="src/app/app.component.ts"
|
|
518
|
+
import { Component, inject } from "@angular/core";
|
|
519
|
+
// ... other imports
|
|
520
|
+
import { I18nHtmlAttributesService } from "./services/i18n-html-attributes.service";
|
|
521
|
+
|
|
522
|
+
@Component({
|
|
523
|
+
// ...
|
|
524
|
+
})
|
|
525
|
+
export class AppComponent {
|
|
526
|
+
constructor() {
|
|
527
|
+
inject(I18nHtmlAttributesService).init();
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
### (Optional) Step 10: Creating a Localized Link Directive
|
|
533
|
+
|
|
534
|
+
To ensure that your application's navigation respects the current locale, you can create a custom directive. This directive automatically prefixes internal URLs with the current language.
|
|
535
|
+
|
|
536
|
+
```typescript fileName="src/app/directives/localized-link.directive.ts"
|
|
537
|
+
import { Directive, Input, HostBinding, inject } from "@angular/core";
|
|
538
|
+
import { getLocalizedUrl } from "intlayer";
|
|
539
|
+
import { useLocale } from "angular-intlayer";
|
|
540
|
+
|
|
541
|
+
@Directive({
|
|
542
|
+
selector: "a[appLocalizedLink]",
|
|
543
|
+
standalone: true,
|
|
544
|
+
})
|
|
545
|
+
export class LocalizedLinkDirective {
|
|
546
|
+
@Input("href") originalHref: string = "";
|
|
547
|
+
|
|
548
|
+
private localeInfo = useLocale();
|
|
549
|
+
|
|
550
|
+
@HostBinding("href")
|
|
551
|
+
get localizedHref(): string {
|
|
552
|
+
const locale = this.localeInfo.locale();
|
|
553
|
+
const isExternalLink = /^https?:\/\//.test(this.originalHref);
|
|
554
|
+
|
|
555
|
+
if (isExternalLink || !this.originalHref) {
|
|
556
|
+
return this.originalHref;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
return getLocalizedUrl(this.originalHref, locale);
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
```
|
|
563
|
+
|
|
564
|
+
To use it, add the `appLocalizedLink` directive to your anchor tags and make sure to import it in your component.
|
|
565
|
+
|
|
566
|
+
```typescript fileName="src/app/app.component.ts"
|
|
567
|
+
// ...
|
|
568
|
+
import { LocalizedLinkDirective } from "./directives/localized-link.directive";
|
|
569
|
+
|
|
570
|
+
@Component({
|
|
571
|
+
selector: "app-root",
|
|
572
|
+
standalone: true,
|
|
573
|
+
imports: [/*...,*/ LocalizedLinkDirective],
|
|
574
|
+
template: ` <a href="/home" appLocalizedLink>Home</a> `,
|
|
575
|
+
})
|
|
576
|
+
export class AppComponent {}
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
### (Optional) Step 11: Render Markdown
|
|
580
|
+
|
|
581
|
+
Intlayer supports rendering Markdown content. To convert Markdown into rich HTML, you can integrate [markdown-it](https://github.com/markdown-it/markdown-it).
|
|
582
|
+
|
|
583
|
+
First, install `markdown-it`:
|
|
584
|
+
|
|
585
|
+
```bash
|
|
586
|
+
npm install markdown-it
|
|
587
|
+
# and its types
|
|
588
|
+
npm install -D @types/markdown-it
|
|
589
|
+
```
|
|
590
|
+
|
|
591
|
+
Next, configure the `INTLAYER_MARKDOWN_TOKEN` in your `app.config.ts`.
|
|
592
|
+
|
|
593
|
+
```typescript fileName="src/app/app.config.ts"
|
|
594
|
+
import { ApplicationConfig } from "@angular/core";
|
|
595
|
+
import { provideRouter } from "@angular/router";
|
|
596
|
+
import { routes } from "./app.routes";
|
|
597
|
+
import { createIntlayerMarkdownProvider } from "angular-intlayer/markdown";
|
|
598
|
+
import MarkdownIt from "markdown-it";
|
|
599
|
+
|
|
600
|
+
const md = new MarkdownIt({
|
|
601
|
+
html: true,
|
|
602
|
+
linkify: true,
|
|
603
|
+
typographer: true,
|
|
604
|
+
});
|
|
605
|
+
|
|
606
|
+
export const appConfig: ApplicationConfig = {
|
|
607
|
+
providers: [
|
|
608
|
+
provideRouter(routes),
|
|
609
|
+
createIntlayerMarkdownProvider((markdown) => md.render(markdown)),
|
|
610
|
+
],
|
|
611
|
+
};
|
|
612
|
+
```
|
|
613
|
+
|
|
614
|
+
By default, Intlayer will return the rendered HTML as a string. If you use `[innerHTML]` to bind it, be aware of the security implications (XSS). Always ensure your content is from a trusted source.
|
|
615
|
+
|
|
616
|
+
For more complex scenarios, you can create a pipe to safely render the HTML.
|
|
617
|
+
|
|
618
|
+
### Configure TypeScript
|
|
619
|
+
|
|
620
|
+
Intlayer uses module augmentation to get benefits of TypeScript and make your codebase stronger.
|
|
621
|
+
|
|
622
|
+

|
|
623
|
+
|
|
624
|
+

|
|
625
|
+
|
|
626
|
+
Ensure your TypeScript configuration includes the autogenerated types.
|
|
627
|
+
|
|
628
|
+
```json5 fileName="tsconfig.json"
|
|
629
|
+
{
|
|
630
|
+
// ... Your existing TypeScript configurations
|
|
631
|
+
"include": [
|
|
632
|
+
// ... Your existing TypeScript configurations
|
|
633
|
+
".intlayer/**/*.ts", // Include the auto-generated types
|
|
634
|
+
],
|
|
635
|
+
}
|
|
636
|
+
```
|
|
108
637
|
|
|
109
638
|
### Git Configuration
|
|
110
639
|
|
|
@@ -325,13 +325,7 @@ const App = () => (
|
|
|
325
325
|
> Note: If you want to use your content in a `string` attribute, such as `alt`, `title`, `href`, `aria-label`, etc., you must call the value of the function, like:
|
|
326
326
|
|
|
327
327
|
> ```jsx
|
|
328
|
-
>
|
|
329
|
-
> ```
|
|
330
|
-
|
|
331
328
|
> <img src={content.image.src.value} alt={content.image.value} />
|
|
332
|
-
|
|
333
|
-
> ```
|
|
334
|
-
>
|
|
335
329
|
> ```
|
|
336
330
|
|
|
337
331
|
> To Learn more about the `useIntlayer` hook, refer to the [documentation](https://github.com/aymericzip/intlayer/blob/main/docs/en/packages/react-intlayer/useIntlayer.md).
|
|
@@ -975,21 +969,14 @@ const LocaleSwitcher = () => {
|
|
|
975
969
|
```
|
|
976
970
|
|
|
977
971
|
> Documentation references:
|
|
978
|
-
|
|
972
|
+
>
|
|
979
973
|
> - [`useLocale` hook](https://github.com/aymericzip/intlayer/blob/main/docs/en/packages/react-intlayer/useLocale.md)
|
|
980
|
-
|
|
981
974
|
> - [`getLocaleName` hook](https://github.com/aymericzip/intlayer/blob/main/docs/en/packages/intlayer/getLocaleName.md)
|
|
982
|
-
|
|
983
975
|
> - [`getLocalizedUrl` hook](https://github.com/aymericzip/intlayer/blob/main/docs/en/packages/intlayer/getLocalizedUrl.md)
|
|
984
|
-
|
|
985
976
|
> - [`getHTMLTextDir` hook](https://github.com/aymericzip/intlayer/blob/main/docs/en/packages/intlayer/getHTMLTextDir.md)
|
|
986
|
-
|
|
987
977
|
> - [`hrefLang` attribute](https://developers.google.com/search/docs/specialty/international/localized-versions?hl=fr)
|
|
988
|
-
|
|
989
978
|
> - [`lang` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang)
|
|
990
|
-
|
|
991
979
|
> - [`dir` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/dir)
|
|
992
|
-
|
|
993
980
|
> - [`aria-current` attribute](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-current)
|
|
994
981
|
|
|
995
982
|
### (Optional) Step 9: Switch the HTML Language and Direction Attributes
|