@intlayer/docs 7.5.11 → 7.5.12
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/blog/ar/intlayer_with_i18next.md +0 -2
- package/blog/ar/intlayer_with_next-i18next.md +0 -2
- package/blog/ar/intlayer_with_react-i18next.md +0 -2
- package/blog/de/intlayer_with_i18next.md +0 -45
- package/blog/de/intlayer_with_next-i18next.md +0 -46
- package/blog/de/intlayer_with_react-i18next.md +0 -2
- package/blog/en/intlayer_with_i18next.md +0 -46
- package/blog/en/intlayer_with_next-i18next.md +0 -48
- package/blog/en/intlayer_with_next-intl.md +0 -44
- package/blog/en/intlayer_with_react-i18next.md +0 -44
- package/blog/en/intlayer_with_react-intl.md +0 -42
- package/blog/en/intlayer_with_vue-i18n.md +0 -44
- package/blog/en-GB/intlayer_with_i18next.md +0 -45
- package/blog/en-GB/intlayer_with_next-i18next.md +0 -47
- package/blog/en-GB/intlayer_with_next-intl.md +0 -42
- package/blog/en-GB/intlayer_with_react-i18next.md +0 -43
- package/blog/en-GB/intlayer_with_react-intl.md +0 -42
- package/blog/en-GB/intlayer_with_vue-i18n.md +0 -46
- package/blog/es/intlayer_with_i18next.md +0 -45
- package/blog/es/intlayer_with_next-i18next.md +0 -47
- package/blog/es/intlayer_with_next-intl.md +0 -42
- package/blog/es/intlayer_with_react-i18next.md +0 -43
- package/blog/es/intlayer_with_react-intl.md +0 -42
- package/blog/es/intlayer_with_vue-i18n.md +0 -46
- package/blog/fr/intlayer_with_i18next.md +0 -45
- package/blog/fr/intlayer_with_next-i18next.md +0 -47
- package/blog/fr/intlayer_with_next-intl.md +0 -42
- package/blog/fr/intlayer_with_react-i18next.md +0 -43
- package/blog/fr/intlayer_with_react-intl.md +0 -42
- package/blog/fr/intlayer_with_vue-i18n.md +0 -46
- package/blog/hi/intlayer_with_i18next.md +0 -2
- package/blog/hi/intlayer_with_next-i18next.md +0 -2
- package/blog/hi/intlayer_with_react-i18next.md +0 -2
- package/blog/id/intlayer_with_i18next.md +0 -2
- package/blog/id/intlayer_with_next-i18next.md +0 -2
- package/blog/id/intlayer_with_react-i18next.md +0 -2
- package/blog/it/intlayer_with_i18next.md +0 -2
- package/blog/it/intlayer_with_next-i18next.md +0 -2
- package/blog/it/intlayer_with_react-i18next.md +0 -2
- package/blog/ja/intlayer_with_i18next.md +0 -45
- package/blog/ja/intlayer_with_next-i18next.md +0 -46
- package/blog/ja/intlayer_with_next-intl.md +0 -42
- package/blog/ja/intlayer_with_react-i18next.md +0 -42
- package/blog/ja/intlayer_with_react-intl.md +0 -42
- package/blog/ja/intlayer_with_vue-i18n.md +0 -46
- package/blog/ko/intlayer_with_i18next.md +0 -2
- package/blog/ko/intlayer_with_next-i18next.md +0 -2
- package/blog/ko/intlayer_with_react-i18next.md +0 -1
- package/blog/pl/intlayer_with_i18next.md +0 -45
- package/blog/pl/intlayer_with_next-i18next.md +0 -46
- package/blog/pl/intlayer_with_next-intl.md +0 -42
- package/blog/pl/intlayer_with_react-i18next.md +0 -43
- package/blog/pl/intlayer_with_react-intl.md +0 -42
- package/blog/pl/intlayer_with_vue-i18n.md +0 -46
- package/blog/pt/intlayer_with_i18next.md +0 -2
- package/blog/pt/intlayer_with_next-i18next.md +0 -2
- package/blog/pt/intlayer_with_react-i18next.md +0 -2
- package/blog/ru/intlayer_with_i18next.md +0 -45
- package/blog/ru/intlayer_with_next-i18next.md +0 -47
- package/blog/ru/intlayer_with_next-intl.md +0 -42
- package/blog/ru/intlayer_with_react-i18next.md +0 -43
- package/blog/ru/intlayer_with_react-intl.md +0 -42
- package/blog/ru/intlayer_with_vue-i18n.md +0 -46
- package/blog/tr/intlayer_with_i18next.md +0 -2
- package/blog/tr/intlayer_with_next-i18next.md +0 -1
- package/blog/tr/intlayer_with_react-i18next.md +0 -2
- package/blog/vi/intlayer_with_i18next.md +0 -2
- package/blog/vi/intlayer_with_next-i18next.md +0 -2
- package/blog/vi/intlayer_with_react-i18next.md +0 -2
- package/blog/zh/intlayer_with_i18next.md +0 -2
- package/blog/zh/intlayer_with_next-i18next.md +0 -2
- package/blog/zh/intlayer_with_react-i18next.md +0 -2
- package/blog/zh/intlayer_with_vue-i18n.md +0 -46
- package/dist/cjs/generated/blog.entry.cjs +58 -29
- package/dist/cjs/generated/blog.entry.cjs.map +1 -1
- package/dist/cjs/generated/docs.entry.cjs +218 -99
- package/dist/cjs/generated/docs.entry.cjs.map +1 -1
- package/dist/cjs/generated/frequentQuestions.entry.cjs +30 -15
- package/dist/cjs/generated/frequentQuestions.entry.cjs.map +1 -1
- package/dist/cjs/generated/legal.entry.cjs +4 -2
- package/dist/cjs/generated/legal.entry.cjs.map +1 -1
- package/dist/esm/generated/blog.entry.mjs +58 -29
- package/dist/esm/generated/blog.entry.mjs.map +1 -1
- package/dist/esm/generated/docs.entry.mjs +218 -99
- package/dist/esm/generated/docs.entry.mjs.map +1 -1
- package/dist/esm/generated/frequentQuestions.entry.mjs +30 -15
- package/dist/esm/generated/frequentQuestions.entry.mjs.map +1 -1
- package/dist/esm/generated/legal.entry.mjs +4 -2
- package/dist/esm/generated/legal.entry.mjs.map +1 -1
- package/dist/types/generated/blog.entry.d.ts.map +1 -1
- package/dist/types/generated/docs.entry.d.ts +1 -0
- package/dist/types/generated/docs.entry.d.ts.map +1 -1
- package/dist/types/generated/frequentQuestions.entry.d.ts.map +1 -1
- package/dist/types/generated/legal.entry.d.ts.map +1 -1
- package/docs/ar/intlayer_with_next-i18next.md +0 -1
- package/docs/ar/intlayer_with_nextjs_14.md +28 -0
- package/docs/ar/intlayer_with_nextjs_15.md +28 -0
- package/docs/ar/intlayer_with_nextjs_16.md +28 -0
- package/docs/ar/intlayer_with_nextjs_no_locale_path.md +1159 -0
- package/docs/ar/plugins/sync-json.md +6 -2
- package/docs/de/intlayer_with_next-i18next.md +0 -1
- package/docs/de/intlayer_with_nextjs_14.md +28 -0
- package/docs/de/intlayer_with_nextjs_15.md +28 -0
- package/docs/de/intlayer_with_nextjs_16.md +28 -0
- package/docs/de/intlayer_with_nextjs_no_locale_path.md +1152 -0
- package/docs/de/plugins/sync-json.md +6 -2
- package/docs/en/intlayer_with_next-i18next.md +0 -1
- package/docs/en/intlayer_with_nextjs_14.md +28 -0
- package/docs/en/intlayer_with_nextjs_15.md +28 -0
- package/docs/en/intlayer_with_nextjs_16.md +31 -1
- package/docs/en/intlayer_with_nextjs_no_locale_path.md +1132 -0
- package/docs/en/plugins/sync-json.md +6 -2
- package/docs/en-GB/intlayer_with_next-i18next.md +0 -1
- package/docs/en-GB/intlayer_with_nextjs_14.md +28 -0
- package/docs/en-GB/intlayer_with_nextjs_15.md +28 -0
- package/docs/en-GB/intlayer_with_nextjs_16.md +28 -0
- package/docs/en-GB/intlayer_with_nextjs_no_locale_path.md +1154 -0
- package/docs/en-GB/plugins/sync-json.md +6 -2
- package/docs/es/intlayer_with_next-i18next.md +0 -1
- package/docs/es/intlayer_with_nextjs_14.md +28 -0
- package/docs/es/intlayer_with_nextjs_15.md +28 -0
- package/docs/es/intlayer_with_nextjs_16.md +28 -0
- package/docs/es/intlayer_with_nextjs_no_locale_path.md +1143 -0
- package/docs/es/plugins/sync-json.md +6 -2
- package/docs/fr/intlayer_with_next-i18next.md +0 -1
- package/docs/fr/intlayer_with_nextjs_14.md +28 -0
- package/docs/fr/intlayer_with_nextjs_15.md +28 -0
- package/docs/fr/intlayer_with_nextjs_16.md +28 -0
- package/docs/fr/intlayer_with_nextjs_no_locale_path.md +1174 -0
- package/docs/fr/plugins/sync-json.md +9 -5
- package/docs/hi/intlayer_with_next-i18next.md +0 -1
- package/docs/hi/intlayer_with_nextjs_14.md +28 -0
- package/docs/hi/intlayer_with_nextjs_15.md +28 -0
- package/docs/hi/intlayer_with_nextjs_16.md +28 -0
- package/docs/hi/intlayer_with_nextjs_no_locale_path.md +1151 -0
- package/docs/hi/plugins/sync-json.md +6 -2
- package/docs/id/intlayer_with_next-i18next.md +0 -1
- package/docs/id/intlayer_with_nextjs_14.md +28 -0
- package/docs/id/intlayer_with_nextjs_15.md +28 -0
- package/docs/id/intlayer_with_nextjs_16.md +28 -0
- package/docs/id/intlayer_with_nextjs_no_locale_path.md +1154 -0
- package/docs/id/plugins/sync-json.md +6 -2
- package/docs/it/intlayer_with_next-i18next.md +0 -1
- package/docs/it/intlayer_with_nextjs_14.md +28 -0
- package/docs/it/intlayer_with_nextjs_15.md +28 -0
- package/docs/it/intlayer_with_nextjs_16.md +28 -0
- package/docs/it/intlayer_with_nextjs_no_locale_path.md +1148 -0
- package/docs/it/plugins/sync-json.md +6 -2
- package/docs/ja/intlayer_with_next-i18next.md +0 -1
- package/docs/ja/intlayer_with_nextjs_14.md +28 -0
- package/docs/ja/intlayer_with_nextjs_15.md +28 -0
- package/docs/ja/intlayer_with_nextjs_16.md +28 -0
- package/docs/ja/intlayer_with_nextjs_no_locale_path.md +1222 -0
- package/docs/ja/plugins/sync-json.md +6 -2
- package/docs/ko/intlayer_with_next-i18next.md +0 -1
- package/docs/ko/intlayer_with_nextjs_14.md +28 -0
- package/docs/ko/intlayer_with_nextjs_15.md +28 -0
- package/docs/ko/intlayer_with_nextjs_16.md +28 -0
- package/docs/ko/intlayer_with_nextjs_no_locale_path.md +1205 -0
- package/docs/ko/plugins/sync-json.md +6 -2
- package/docs/pl/intlayer_with_next-i18next.md +0 -1
- package/docs/pl/intlayer_with_nextjs_14.md +28 -0
- package/docs/pl/intlayer_with_nextjs_15.md +28 -0
- package/docs/pl/intlayer_with_nextjs_16.md +28 -0
- package/docs/pl/intlayer_with_nextjs_no_locale_path.md +1149 -0
- package/docs/pl/plugins/sync-json.md +6 -2
- package/docs/pt/intlayer_with_next-i18next.md +0 -1
- package/docs/pt/intlayer_with_nextjs_14.md +28 -0
- package/docs/pt/intlayer_with_nextjs_15.md +28 -0
- package/docs/pt/intlayer_with_nextjs_16.md +28 -0
- package/docs/pt/intlayer_with_nextjs_no_locale_path.md +1152 -0
- package/docs/pt/plugins/sync-json.md +6 -2
- package/docs/ru/intlayer_with_next-i18next.md +0 -1
- package/docs/ru/intlayer_with_nextjs_14.md +28 -0
- package/docs/ru/intlayer_with_nextjs_15.md +28 -0
- package/docs/ru/intlayer_with_nextjs_16.md +28 -0
- package/docs/ru/intlayer_with_nextjs_no_locale_path.md +1204 -0
- package/docs/ru/plugins/sync-json.md +6 -2
- package/docs/tr/intlayer_with_next-i18next.md +0 -1
- package/docs/tr/intlayer_with_nextjs_14.md +28 -0
- package/docs/tr/intlayer_with_nextjs_15.md +28 -0
- package/docs/tr/intlayer_with_nextjs_16.md +28 -0
- package/docs/tr/intlayer_with_nextjs_no_locale_path.md +1159 -0
- package/docs/tr/plugins/sync-json.md +6 -2
- package/docs/uk/compiler.md +133 -0
- package/docs/uk/component_i18n.md +194 -0
- package/docs/uk/intlayer_with_nextjs_14.md +1646 -0
- package/docs/uk/intlayer_with_nextjs_15.md +1910 -0
- package/docs/uk/intlayer_with_nextjs_16.md +1763 -0
- package/docs/uk/intlayer_with_nextjs_no_locale_path.md +1159 -0
- package/docs/uk/intlayer_with_react_native+expo.md +715 -0
- package/docs/uk/packages/intlayer/getConfiguration.md +145 -0
- package/docs/uk/vs_code_extension.md +133 -0
- package/docs/vi/intlayer_with_next-i18next.md +0 -1
- package/docs/vi/intlayer_with_nextjs_14.md +28 -0
- package/docs/vi/intlayer_with_nextjs_15.md +28 -0
- package/docs/vi/intlayer_with_nextjs_16.md +28 -0
- package/docs/vi/intlayer_with_nextjs_no_locale_path.md +1151 -0
- package/docs/vi/plugins/sync-json.md +6 -2
- package/docs/zh/intlayer_with_next-i18next.md +0 -1
- package/docs/zh/intlayer_with_nextjs_14.md +28 -0
- package/docs/zh/intlayer_with_nextjs_15.md +28 -0
- package/docs/zh/intlayer_with_nextjs_16.md +28 -0
- package/docs/zh/intlayer_with_nextjs_no_locale_path.md +1206 -0
- package/docs/zh/plugins/sync-json.md +9 -5
- package/frequent_questions/ar/SSR_Next_no_[locale].md +1 -1
- package/frequent_questions/de/SSR_Next_no_[locale].md +1 -1
- package/frequent_questions/en/SSR_Next_no_[locale].md +1 -1
- package/frequent_questions/en-GB/SSR_Next_no_[locale].md +1 -1
- package/frequent_questions/es/SSR_Next_no_[locale].md +1 -1
- package/frequent_questions/fr/SSR_Next_no_[locale].md +1 -1
- package/frequent_questions/hi/SSR_Next_no_[locale].md +1 -1
- package/frequent_questions/id/SSR_Next_no_[locale].md +1 -1
- package/frequent_questions/it/SSR_Next_no_[locale].md +1 -1
- package/frequent_questions/ja/SSR_Next_no_[locale].md +1 -1
- package/frequent_questions/ko/SSR_Next_no_[locale].md +1 -1
- package/frequent_questions/pl/SSR_Next_no_[locale].md +1 -1
- package/frequent_questions/pt/SSR_Next_no_[locale].md +1 -1
- package/frequent_questions/ru/SSR_Next_no_[locale].md +1 -1
- package/frequent_questions/tr/SSR_Next_no_[locale].md +1 -1
- package/frequent_questions/vi/SSR_Next_no_[locale].md +1 -1
- package/frequent_questions/zh/SSR_Next_no_[locale].md +1 -1
- package/package.json +6 -6
- package/src/generated/blog.entry.ts +29 -0
- package/src/generated/docs.entry.ts +119 -0
- package/src/generated/frequentQuestions.entry.ts +15 -0
- package/src/generated/legal.entry.ts +2 -0
|
@@ -0,0 +1,1152 @@
|
|
|
1
|
+
---
|
|
2
|
+
createdAt: 2026-01-10
|
|
3
|
+
updatedAt: 2026-01-10
|
|
4
|
+
title: Como traduzir sua aplicação Next.js 16 (sem [locale] no caminho da página) – guia i18n 2026
|
|
5
|
+
description: Descubra como tornar seu site Next.js 16 multilíngue sem [locale] no caminho da página. Siga a documentação para internacionalizar (i18n) e traduzi-lo.
|
|
6
|
+
keywords:
|
|
7
|
+
- Internacionalização
|
|
8
|
+
- Documentação
|
|
9
|
+
- Intlayer
|
|
10
|
+
- Next.js 16
|
|
11
|
+
- JavaScript
|
|
12
|
+
- React
|
|
13
|
+
slugs:
|
|
14
|
+
- doc
|
|
15
|
+
- environment
|
|
16
|
+
- nextjs
|
|
17
|
+
- no-locale-path
|
|
18
|
+
applicationTemplate: https://github.com/aymericzip/intlayer-next-no-lolale-path-template
|
|
19
|
+
youtubeVideo: https://www.youtube.com/watch?v=e_PPG7PTqGU
|
|
20
|
+
history:
|
|
21
|
+
- version: 1.0.0
|
|
22
|
+
date: 2026-01-10
|
|
23
|
+
changes: Lançamento inicial
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
# Traduza seu site Next.js 16 (sem [locale] no caminho da página) usando Intlayer | Internacionalização (i18n)
|
|
27
|
+
|
|
28
|
+
<Tab defaultTab="video">
|
|
29
|
+
<TabItem label="Vídeo" value="video">
|
|
30
|
+
|
|
31
|
+
<iframe title="A melhor solução de i18n para Next.js? Descubra o Intlayer" class="m-auto aspect-16/9 w-full overflow-hidden rounded-lg border-0" allow="autoplay; gyroscope;" loading="lazy" width="1080" height="auto" src="https://www.youtube.com/embed/e_PPG7PTqGU?autoplay=0&origin=http://intlayer.org&controls=0&rel=1"/>
|
|
32
|
+
|
|
33
|
+
</TabItem>
|
|
34
|
+
<TabItem label="Código" value="code">
|
|
35
|
+
|
|
36
|
+
<iframe
|
|
37
|
+
src="https://stackblitz.com/github/aymericzip/intlayer-next-16-no-locale-path-template?embed=1&ctl=1&file=intlayer.config.ts"
|
|
38
|
+
className="m-auto overflow-hidden rounded-lg border-0 max-md:size-full max-md:h-[700px] md:aspect-16/9 md:w-full"
|
|
39
|
+
title="Demo CodeSandbox - Como internacionalizar sua aplicação usando o Intlayer"
|
|
40
|
+
sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"
|
|
41
|
+
loading="lazy"
|
|
42
|
+
/>
|
|
43
|
+
|
|
44
|
+
</TabItem>
|
|
45
|
+
</Tab>
|
|
46
|
+
|
|
47
|
+
Veja o [Modelo de Aplicação](https://github.com/aymericzip/intlayer-next-no-lolale-path-template) no GitHub.
|
|
48
|
+
|
|
49
|
+
## Índice
|
|
50
|
+
|
|
51
|
+
<TOC/>
|
|
52
|
+
|
|
53
|
+
## O que é o Intlayer?
|
|
54
|
+
|
|
55
|
+
**Intlayer** é uma biblioteca inovadora de internacionalização (i18n) open-source concebida para simplificar o suporte multilingue em aplicações web modernas. O **Intlayer** integra-se perfeitamente com o mais recente framework **Next.js 16**, incluindo o seu poderoso **App Router**. Está otimizado para funcionar com **Server Components** para uma renderização eficiente e é totalmente compatível com [**Turbopack**](https://nextjs.org/docs/architecture/turbopack).
|
|
56
|
+
|
|
57
|
+
Com o Intlayer, pode:
|
|
58
|
+
|
|
59
|
+
- **Gerir traduções facilmente** usando dicionários declarativos ao nível do componente.
|
|
60
|
+
- **Localizar dinamicamente metadados**, rotas e conteúdo.
|
|
61
|
+
- **Aceder a traduções tanto em componentes client-side como server-side**.
|
|
62
|
+
- **Garantir suporte a TypeScript** com tipos gerados automaticamente, melhorando a autocompletação e a detecção de erros.
|
|
63
|
+
- **Aproveite recursos avançados**, como detecção e troca dinâmica de locale.
|
|
64
|
+
|
|
65
|
+
> O Intlayer é compatível com Next.js 12, 13, 14 e 16. Se estiver a usar o Page Router do Next.js, pode consultar este [guia](https://github.com/aymericzip/intlayer/blob/main/docs/docs/pt/intlayer_with_nextjs_page_router.md). Para Next.js 12, 13, 14 com App Router, consulte este [guia](https://github.com/aymericzip/intlayer/blob/main/docs/docs/pt/intlayer_with_nextjs_14.md).
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Guia passo a passo para configurar o Intlayer numa aplicação Next.js
|
|
70
|
+
|
|
71
|
+
### Passo 1: Instalar dependências
|
|
72
|
+
|
|
73
|
+
Instale os pacotes necessários usando npm:
|
|
74
|
+
|
|
75
|
+
```bash packageManager="npm"
|
|
76
|
+
npm install intlayer next-intlayer
|
|
77
|
+
npx intlayer init
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
```bash packageManager="pnpm"
|
|
81
|
+
pnpm add intlayer next-intlayer
|
|
82
|
+
pnpm intlayer init
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
```bash packageManager="yarn"
|
|
86
|
+
yarn add intlayer next-intlayer
|
|
87
|
+
yarn intlayer init
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
```bash packageManager="bun"
|
|
91
|
+
bun add intlayer next-intlayer
|
|
92
|
+
bunx intlayer init
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
- **intlayer**
|
|
96
|
+
|
|
97
|
+
O pacote principal que fornece ferramentas de internacionalização para gerenciamento de configuração, tradução, [declaração de conteúdo](https://github.com/aymericzip/intlayer/blob/main/docs/docs/pt/dictionary/content_file.md), transpilação e [comandos CLI](https://github.com/aymericzip/intlayer/blob/main/docs/docs/pt/cli/index.md).
|
|
98
|
+
|
|
99
|
+
- **next-intlayer**
|
|
100
|
+
|
|
101
|
+
O pacote que integra o Intlayer com o Next.js. Fornece providers de contexto e hooks para internacionalização no Next.js. Além disso, inclui o plugin do Next.js para integrar o Intlayer com o [Webpack](https://webpack.js.org/) ou o [Turbopack](https://nextjs.org/docs/app/api-reference/turbopack), bem como um proxy para detectar a locale preferida do utilizador, gerir cookies e tratar redirecionamentos de URL.
|
|
102
|
+
|
|
103
|
+
### Passo 2: Configure o seu projeto
|
|
104
|
+
|
|
105
|
+
Aqui está a estrutura final que iremos criar:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
.
|
|
109
|
+
├── src
|
|
110
|
+
│ ├── app
|
|
111
|
+
│ │ ├── layout.tsx
|
|
112
|
+
│ │ ├── page.content.ts
|
|
113
|
+
│ │ └── page.tsx
|
|
114
|
+
│ ├── components
|
|
115
|
+
│ │ ├── clientComponentExample
|
|
116
|
+
│ │ │ ├── client-component-example.content.ts
|
|
117
|
+
│ │ │ └── ClientComponentExample.tsx
|
|
118
|
+
│ │ ├── localeSwitcher
|
|
119
|
+
│ │ │ ├── localeSwitcher.content.ts
|
|
120
|
+
│ │ │ └── LocaleSwitcher.tsx
|
|
121
|
+
│ │ └── serverComponentExample
|
|
122
|
+
│ │ ├── server-component-example.content.ts
|
|
123
|
+
│ │ └── ServerComponentExample.tsx
|
|
124
|
+
│ └── proxy.ts
|
|
125
|
+
├── intlayer.config.ts
|
|
126
|
+
├── next.config.ts
|
|
127
|
+
├── package.json
|
|
128
|
+
└── tsconfig.json
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
> Se não quiser roteamento por locale, o intlayer pode ser usado apenas como um provider / hook. Veja [este guia](https://github.com/aymericzip/intlayer/blob/main/docs/docs/pt/intlayer_with_nextjs_no_locale_path.md) para mais detalhes.
|
|
132
|
+
|
|
133
|
+
Crie um arquivo de configuração para definir os idiomas da sua aplicação:
|
|
134
|
+
|
|
135
|
+
```typescript fileName="intlayer.config.ts" codeFormat="typescript"
|
|
136
|
+
import { Locales, type IntlayerConfig } from "intlayer";
|
|
137
|
+
|
|
138
|
+
const config: IntlayerConfig = {
|
|
139
|
+
internationalization: {
|
|
140
|
+
locales: [
|
|
141
|
+
Locales.ENGLISH,
|
|
142
|
+
Locales.FRENCH,
|
|
143
|
+
Locales.SPANISH,
|
|
144
|
+
// Outros locales
|
|
145
|
+
],
|
|
146
|
+
defaultLocale: Locales.ENGLISH,
|
|
147
|
+
},
|
|
148
|
+
routing: {
|
|
149
|
+
mode: "search-params", // ou `no-prefix` - Útil para detecção no middleware
|
|
150
|
+
},
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
export default config;
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
```javascript fileName="intlayer.config.mjs" codeFormat="esm"
|
|
157
|
+
import { Locales } from "intlayer";
|
|
158
|
+
|
|
159
|
+
/** @type {import('intlayer').IntlayerConfig} */
|
|
160
|
+
const config = {
|
|
161
|
+
internationalization: {
|
|
162
|
+
locales: [
|
|
163
|
+
Locales.ENGLISH,
|
|
164
|
+
Locales.FRENCH,
|
|
165
|
+
Locales.SPANISH,
|
|
166
|
+
// Outros locales
|
|
167
|
+
],
|
|
168
|
+
defaultLocale: Locales.ENGLISH,
|
|
169
|
+
},
|
|
170
|
+
routing: {
|
|
171
|
+
mode: "search-params", // ou `no-prefix` - Útil para detecção no middleware
|
|
172
|
+
},
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
export default config;
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
```javascript fileName="intlayer.config.cjs" codeFormat="commonjs"
|
|
179
|
+
const { Locales } = require("intlayer");
|
|
180
|
+
|
|
181
|
+
/** @type {import('intlayer').IntlayerConfig} */
|
|
182
|
+
const config = {
|
|
183
|
+
internationalization: {
|
|
184
|
+
locales: [
|
|
185
|
+
Locales.ENGLISH,
|
|
186
|
+
Locales.FRENCH,
|
|
187
|
+
Locales.SPANISH,
|
|
188
|
+
// Seus outros locales
|
|
189
|
+
],
|
|
190
|
+
defaultLocale: Locales.ENGLISH,
|
|
191
|
+
},
|
|
192
|
+
routing: {
|
|
193
|
+
mode: "search-params", // ou `no-prefix` - Útil para detecção no middleware
|
|
194
|
+
},
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
module.exports = config;
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
> Através deste arquivo de configuração, você pode configurar URLs localizadas, redirecionamento por proxy, nomes de cookies, a localização e extensão das suas declarações de conteúdo, desativar os logs do Intlayer no console e muito mais. Para uma lista completa dos parâmetros disponíveis, consulte a [documentação de configuração](https://github.com/aymericzip/intlayer/blob/main/docs/docs/pt/configuration.md).
|
|
201
|
+
|
|
202
|
+
### Passo 3: Integrar o Intlayer na sua configuração do Next.js
|
|
203
|
+
|
|
204
|
+
Configure seu setup do Next.js para usar o Intlayer:
|
|
205
|
+
|
|
206
|
+
```typescript fileName="next.config.ts" codeFormat="typescript"
|
|
207
|
+
import type { NextConfig } from "next";
|
|
208
|
+
import { withIntlayer } from "next-intlayer/server";
|
|
209
|
+
|
|
210
|
+
const nextConfig: NextConfig = {
|
|
211
|
+
/* opções de configuração aqui */
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
export default withIntlayer(nextConfig);
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
```typescript fileName="next.config.mjs" codeFormat="esm"
|
|
218
|
+
import { withIntlayer } from "next-intlayer/server";
|
|
219
|
+
|
|
220
|
+
/** @type {import('next').NextConfig} */
|
|
221
|
+
const nextConfig = {
|
|
222
|
+
/* opções de configuração aqui */
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
export default withIntlayer(nextConfig);
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
```typescript fileName="next.config.cjs" codeFormat="commonjs"
|
|
229
|
+
const { withIntlayer } = require("next-intlayer/server");
|
|
230
|
+
|
|
231
|
+
/** @type {import('next').NextConfig} */
|
|
232
|
+
const nextConfig = {
|
|
233
|
+
/* opções de configuração aqui */
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
module.exports = withIntlayer(nextConfig);
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
> O plugin Next.js `withIntlayer()` é usado para integrar o Intlayer com o Next.js. Ele garante a geração dos ficheiros de declaração de conteúdo e os monitora em modo de desenvolvimento. Define as variáveis de ambiente do Intlayer nos ambientes do [Webpack](https://webpack.js.org/) ou [Turbopack](https://nextjs.org/docs/app/api-reference/turbopack). Além disso, fornece aliases para otimizar o desempenho e assegura compatibilidade com server components.
|
|
240
|
+
|
|
241
|
+
> A função `withIntlayer()` é uma função que retorna uma promise. Permite preparar os dicionários do intlayer antes do início do build. Se quiser utilizá-la com outros plugins, pode fazer await. Exemplo:
|
|
242
|
+
>
|
|
243
|
+
> ```ts
|
|
244
|
+
> const nextConfig = await withIntlayer(nextConfig);
|
|
245
|
+
> const nextConfigWithOtherPlugins = withOtherPlugins(nextConfig);
|
|
246
|
+
>
|
|
247
|
+
> export default nextConfigWithOtherPlugins;
|
|
248
|
+
> ```
|
|
249
|
+
>
|
|
250
|
+
> Se você quiser usá-lo de forma síncrona, pode usar a função `withIntlayerSync()`. Exemplo:
|
|
251
|
+
>
|
|
252
|
+
> ```ts
|
|
253
|
+
> const nextConfig = withIntlayerSync(nextConfig);
|
|
254
|
+
> const nextConfigWithOtherPlugins = withOtherPlugins(nextConfig);
|
|
255
|
+
>
|
|
256
|
+
> export default nextConfigWithOtherPlugins;
|
|
257
|
+
> ```
|
|
258
|
+
>
|
|
259
|
+
> O Intlayer detecta automaticamente se o seu projeto está usando **webpack** ou **Turbopack** com base nas flags de linha de comando `--webpack`, `--turbo`, ou `--turbopack`, assim como na sua **versão do Next.js** atual.
|
|
260
|
+
>
|
|
261
|
+
> Desde `next>=16`, se você estiver usando **Rspack**, deve forçar explicitamente o Intlayer a usar a configuração do webpack desabilitando o Turbopack:
|
|
262
|
+
>
|
|
263
|
+
> ```ts
|
|
264
|
+
> withRspack(withIntlayer(nextConfig, { enableTurbopack: false }));
|
|
265
|
+
> ```
|
|
266
|
+
|
|
267
|
+
### Passo 4: Definir rotas de localidade dinâmicas
|
|
268
|
+
|
|
269
|
+
Remova tudo de `RootLayout` e substitua pelo código a seguir:
|
|
270
|
+
|
|
271
|
+
```tsx {3} fileName="src/app/layout.tsx" codeFormat="typescript"
|
|
272
|
+
import type { Metadata } from "next";
|
|
273
|
+
import type { ReactNode } from "react";
|
|
274
|
+
import "./globals.css";
|
|
275
|
+
import { IntlayerClientProvider, LocalPromiseParams } from "next-intlayer";
|
|
276
|
+
import { getHTMLTextDir, getIntlayer } from "intlayer";
|
|
277
|
+
import { getLocale } from "next-intlayer/server";
|
|
278
|
+
export { generateStaticParams } from "next-intlayer";
|
|
279
|
+
|
|
280
|
+
export const generateMetadata = async ({
|
|
281
|
+
params,
|
|
282
|
+
}: LocalPromiseParams): Promise<Metadata> => {
|
|
283
|
+
const { locale } = await params;
|
|
284
|
+
const { title, description, keywords } = getIntlayer("metadata", locale);
|
|
285
|
+
|
|
286
|
+
return {
|
|
287
|
+
title,
|
|
288
|
+
description,
|
|
289
|
+
keywords,
|
|
290
|
+
};
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
const RootLayout = async ({
|
|
294
|
+
children,
|
|
295
|
+
}: Readonly<{
|
|
296
|
+
children: ReactNode;
|
|
297
|
+
}>) => {
|
|
298
|
+
const locale = await getLocale();
|
|
299
|
+
|
|
300
|
+
return (
|
|
301
|
+
<html lang={locale} dir={getHTMLTextDir(locale)}>
|
|
302
|
+
<IntlayerClientProvider defaultLocale={locale}>
|
|
303
|
+
<body>{children}</body>
|
|
304
|
+
</IntlayerClientProvider>
|
|
305
|
+
</html>
|
|
306
|
+
);
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
export default RootLayout;
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
```jsx {3} fileName="src/app/layout.mjx" codeFormat="esm"
|
|
313
|
+
import "./globals.css";
|
|
314
|
+
import { IntlayerClientProvider } from "next-intlayer";
|
|
315
|
+
import { getHTMLTextDir, getIntlayer } from "intlayer";
|
|
316
|
+
import { getLocale } from "next-intlayer/server";
|
|
317
|
+
export { generateStaticParams } from "next-intlayer";
|
|
318
|
+
|
|
319
|
+
export const generateMetadata = async ({ params }) => {
|
|
320
|
+
const { locale } = await params;
|
|
321
|
+
const { title, description, keywords } = getIntlayer("metadata", locale);
|
|
322
|
+
|
|
323
|
+
return {
|
|
324
|
+
title,
|
|
325
|
+
description,
|
|
326
|
+
keywords,
|
|
327
|
+
};
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
const RootLayout = async ({ children }) => {
|
|
331
|
+
const locale = await getLocale();
|
|
332
|
+
|
|
333
|
+
return (
|
|
334
|
+
<html lang={locale} dir={getHTMLTextDir(locale)}>
|
|
335
|
+
<IntlayerClientProvider defaultLocale={locale}>
|
|
336
|
+
<body>{children}</body>
|
|
337
|
+
</IntlayerClientProvider>
|
|
338
|
+
</html>
|
|
339
|
+
);
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
export default RootLayout;
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
```jsx {1,8} fileName="src/app/layout.csx" codeFormat="commonjs"
|
|
346
|
+
require("./globals.css");
|
|
347
|
+
const { IntlayerClientProvider } = require("next-intlayer");
|
|
348
|
+
const { getHTMLTextDir, getIntlayer } = require("intlayer");
|
|
349
|
+
const { getLocale } = require("next-intlayer/server");
|
|
350
|
+
const { generateStaticParams } = require("next-intlayer");
|
|
351
|
+
|
|
352
|
+
const generateMetadata = async ({ params }) => {
|
|
353
|
+
const { locale } = await params;
|
|
354
|
+
const { title, description, keywords } = getIntlayer("metadata", locale);
|
|
355
|
+
|
|
356
|
+
return {
|
|
357
|
+
title,
|
|
358
|
+
description,
|
|
359
|
+
keywords,
|
|
360
|
+
};
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
const RootLayout = async ({ children }) => {
|
|
364
|
+
const locale = await getLocale();
|
|
365
|
+
|
|
366
|
+
return (
|
|
367
|
+
<html lang={locale} dir={getHTMLTextDir(locale)}>
|
|
368
|
+
<IntlayerClientProvider defaultLocale={locale}>
|
|
369
|
+
<body>{children}</body>
|
|
370
|
+
</IntlayerClientProvider>
|
|
371
|
+
</html>
|
|
372
|
+
);
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
module.exports = {
|
|
376
|
+
default: RootLayout,
|
|
377
|
+
generateStaticParams,
|
|
378
|
+
generateMetadata,
|
|
379
|
+
};
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### Passo 5: Declarar o seu conteúdo
|
|
383
|
+
|
|
384
|
+
Crie e gerencie suas declarações de conteúdo para armazenar traduções:
|
|
385
|
+
|
|
386
|
+
```tsx fileName="src/app/metadata.content.ts" contentDeclarationFormat="typescript"
|
|
387
|
+
import { t, type Dictionary } from "intlayer";
|
|
388
|
+
import { Metadata } from "next";
|
|
389
|
+
|
|
390
|
+
const metadataContent = {
|
|
391
|
+
key: "metadata",
|
|
392
|
+
content: {
|
|
393
|
+
title: t({
|
|
394
|
+
pt: "Meu Título do Projeto",
|
|
395
|
+
en: "My Project Title",
|
|
396
|
+
fr: "Le Titre de mon Projet",
|
|
397
|
+
es: "El Título de mi Proyecto",
|
|
398
|
+
}),
|
|
399
|
+
|
|
400
|
+
description: t({
|
|
401
|
+
pt: "Descubra a nossa plataforma inovadora projetada para simplificar o seu fluxo de trabalho e aumentar a sua produtividade.",
|
|
402
|
+
en: "Discover our innovative platform designed to streamline your workflow and boost productivity.",
|
|
403
|
+
fr: "Découvrez notre plateforme innovante conçue pour simplifier votre flux de travail et booster votre productivité.",
|
|
404
|
+
es: "Descubra nuestra plataforma innovadora diseñada para simplificar su flujo de trabajo y aumentar su productividad.",
|
|
405
|
+
}),
|
|
406
|
+
|
|
407
|
+
keywords: t({
|
|
408
|
+
pt: ["inovação", "produtividade", "fluxo de trabalho", "SaaS"],
|
|
409
|
+
en: ["innovation", "productivity", "workflow", "SaaS"],
|
|
410
|
+
pt: ["inovação", "produtividade", "fluxo de trabalho", "SaaS"],
|
|
411
|
+
fr: ["innovation", "productivité", "flux de travail", "SaaS"],
|
|
412
|
+
es: ["innovación", "productividad", "flujo de trabajo", "SaaS"],
|
|
413
|
+
}),
|
|
414
|
+
},
|
|
415
|
+
} as Dictionary<Metadata>;
|
|
416
|
+
|
|
417
|
+
export default metadataContent;
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
```tsx fileName="src/app/metadata.content.mjs" contentDeclarationFormat="typescript"
|
|
421
|
+
import { t, type Dictionary } from "intlayer";
|
|
422
|
+
|
|
423
|
+
/** @type {import('intlayer').Dictionary<import('next').Metadata>} */
|
|
424
|
+
const metadataContent = {
|
|
425
|
+
key: "metadata",
|
|
426
|
+
content: {
|
|
427
|
+
title: t({
|
|
428
|
+
en: "My Project Title",
|
|
429
|
+
fr: "Le Titre de mon Projet",
|
|
430
|
+
es: "El Título de mi Proyecto",
|
|
431
|
+
}),
|
|
432
|
+
|
|
433
|
+
description: t({
|
|
434
|
+
pt: "Descubra a nossa plataforma inovadora projetada para simplificar o seu fluxo de trabalho e aumentar a produtividade.",
|
|
435
|
+
en: "Discover our innovative platform designed to streamline your workflow and boost productivity.",
|
|
436
|
+
pt: "Descubra a nossa plataforma inovadora projetada para simplificar o seu fluxo de trabalho e aumentar a produtividade.",
|
|
437
|
+
fr: "Découvrez notre plateforme innovante conçue pour simplifier votre flux de travail et booster votre productivité.",
|
|
438
|
+
es: "Descubra su plataforma innovadora diseñada para simplificar su flujo de trabajo y aumentar su productividad.",
|
|
439
|
+
}),
|
|
440
|
+
|
|
441
|
+
keywords: t({
|
|
442
|
+
pt: ["inovação", "produtividade", "fluxo de trabalho", "SaaS"],
|
|
443
|
+
en: ["innovation", "productivity", "workflow", "SaaS"],
|
|
444
|
+
fr: ["innovation", "productivité", "flux de travail", "SaaS"],
|
|
445
|
+
es: ["innovación", "productividad", "flujo de trabajo", "SaaS"],
|
|
446
|
+
}),
|
|
447
|
+
},
|
|
448
|
+
};
|
|
449
|
+
|
|
450
|
+
export default metadataContent;
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
```javascript fileName="src/app/metadata.content.cjs" contentDeclarationFormat="commonjs"
|
|
454
|
+
const { t } = require("intlayer");
|
|
455
|
+
|
|
456
|
+
/** @type {import('intlayer').Dictionary<import('next').Metadata>} */
|
|
457
|
+
const metadataContent = {
|
|
458
|
+
key: "metadata",
|
|
459
|
+
content: {
|
|
460
|
+
title: t({
|
|
461
|
+
pt: "O Título do Meu Projeto",
|
|
462
|
+
en: "My Project Title",
|
|
463
|
+
fr: "Le Titre de mon Projet",
|
|
464
|
+
es: "El Título de mi Proyecto",
|
|
465
|
+
}),
|
|
466
|
+
|
|
467
|
+
description: t({
|
|
468
|
+
pt: "Descubra a nossa plataforma inovadora concebida para simplificar o seu fluxo de trabalho e aumentar a produtividade.",
|
|
469
|
+
en: "Discover our innovative platform designed to streamline your workflow and boost productivity.",
|
|
470
|
+
fr: "Découvrez notre plateforme innovante conçue pour simplifier votre flux de travail et booster votre productivité.",
|
|
471
|
+
es: "Descubra nuestra plataforma innovadora diseñada para simplificar su flujo de trabajo y aumentar su productividad.",
|
|
472
|
+
}),
|
|
473
|
+
|
|
474
|
+
keywords: t({
|
|
475
|
+
pt: ["inovação", "produtividade", "fluxo de trabalho", "SaaS"],
|
|
476
|
+
en: ["innovation", "productivity", "workflow", "SaaS"],
|
|
477
|
+
fr: ["innovation", "productivité", "flux de travail", "SaaS"],
|
|
478
|
+
es: ["innovación", "productividad", "flujo de trabajo", "SaaS"],
|
|
479
|
+
}),
|
|
480
|
+
},
|
|
481
|
+
};
|
|
482
|
+
|
|
483
|
+
module.exports = metadataContent;
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
```json fileName="src/app/metadata.content.json" contentDeclarationFormat="json"
|
|
487
|
+
{
|
|
488
|
+
"key": "metadata",
|
|
489
|
+
"content": {
|
|
490
|
+
"title": {
|
|
491
|
+
"nodeType": "translation",
|
|
492
|
+
"translation": {
|
|
493
|
+
"pt": "O Título do Meu Projeto",
|
|
494
|
+
"en": "My Project Title",
|
|
495
|
+
"fr": "Le Titre de mon Projet",
|
|
496
|
+
"es": "El Título de mi Proyecto"
|
|
497
|
+
}
|
|
498
|
+
},
|
|
499
|
+
"description": {
|
|
500
|
+
"nodeType": "translation",
|
|
501
|
+
"translation": {
|
|
502
|
+
"pt": "Descubra nossa plataforma inovadora projetada para otimizar seu fluxo de trabalho e aumentar sua produtividade.",
|
|
503
|
+
"en": "Discover our innovative platform designed to streamline your workflow and boost productivity.",
|
|
504
|
+
"fr": "Découvrez notre plateforme innovante conçue pour simplifier votre flux de travail et booster votre productivité.",
|
|
505
|
+
"es": "Descubra nuestra plataforma innovadora diseñada para simplificar su flujo de trabajo y aumentar su productividad."
|
|
506
|
+
}
|
|
507
|
+
},
|
|
508
|
+
"keywords": {
|
|
509
|
+
"nodeType": "translation",
|
|
510
|
+
"translation": {
|
|
511
|
+
"pt": ["inovação", "produtividade", "fluxo de trabalho", "SaaS"],
|
|
512
|
+
"en": ["innovation", "productivity", "workflow", "SaaS"],
|
|
513
|
+
"fr": ["innovation", "productivité", "flux de travail", "SaaS"],
|
|
514
|
+
"es": ["innovación", "productividad", "flujo de trabajo", "SaaS"]
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
```tsx fileName="src/app/page.content.ts" contentDeclarationFormat="typescript"
|
|
522
|
+
import { t, type Dictionary } from "intlayer";
|
|
523
|
+
|
|
524
|
+
const pageContent = {
|
|
525
|
+
key: "page",
|
|
526
|
+
content: {
|
|
527
|
+
getStarted: {
|
|
528
|
+
main: t({
|
|
529
|
+
pt: "Comece por editar",
|
|
530
|
+
en: "Get started by editing",
|
|
531
|
+
fr: "Commencez par éditer",
|
|
532
|
+
es: "Comience por editar",
|
|
533
|
+
}),
|
|
534
|
+
pageLink: "src/app/page.tsx",
|
|
535
|
+
},
|
|
536
|
+
},
|
|
537
|
+
} satisfies Dictionary;
|
|
538
|
+
|
|
539
|
+
export default pageContent;
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
```javascript fileName="src/app/page.content.mjs" contentDeclarationFormat="esm"
|
|
543
|
+
import { t } from "intlayer";
|
|
544
|
+
|
|
545
|
+
/** @type {import('intlayer').Dictionary} */
|
|
546
|
+
const pageContent = {
|
|
547
|
+
key: "page",
|
|
548
|
+
content: {
|
|
549
|
+
getStarted: {
|
|
550
|
+
main: t({
|
|
551
|
+
pt: "Comece a editar",
|
|
552
|
+
en: "Get started by editing",
|
|
553
|
+
fr: "Commencez par éditer",
|
|
554
|
+
es: "Comience por editar",
|
|
555
|
+
}),
|
|
556
|
+
pageLink: "src/app/page.tsx",
|
|
557
|
+
},
|
|
558
|
+
},
|
|
559
|
+
};
|
|
560
|
+
|
|
561
|
+
export default pageContent;
|
|
562
|
+
```
|
|
563
|
+
|
|
564
|
+
```javascript fileName="src/app/page.content.cjs" contentDeclarationFormat="commonjs"
|
|
565
|
+
const { t } = require("intlayer");
|
|
566
|
+
|
|
567
|
+
/** @type {import('intlayer').Dictionary} */
|
|
568
|
+
const pageContent = {
|
|
569
|
+
key: "page",
|
|
570
|
+
content: {
|
|
571
|
+
getStarted: {
|
|
572
|
+
main: t({
|
|
573
|
+
pt: "Comece a editar",
|
|
574
|
+
en: "Get started by editing",
|
|
575
|
+
fr: "Commencez par éditer",
|
|
576
|
+
pt: "Comece por editar",
|
|
577
|
+
en: "Get started by editing",
|
|
578
|
+
fr: "Commencez par éditer",
|
|
579
|
+
es: "Comience por editar",
|
|
580
|
+
}),
|
|
581
|
+
pageLink: "src/app/page.tsx",
|
|
582
|
+
},
|
|
583
|
+
},
|
|
584
|
+
};
|
|
585
|
+
|
|
586
|
+
module.exports = pageContent;
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
```json fileName="src/app/page.content.json" contentDeclarationFormat="json"
|
|
590
|
+
{
|
|
591
|
+
"$schema": "https://intlayer.org/schema.json",
|
|
592
|
+
"key": "page",
|
|
593
|
+
"content": {
|
|
594
|
+
"getStarted": {
|
|
595
|
+
"nodeType": "translation",
|
|
596
|
+
"translation": {
|
|
597
|
+
"pt": "Comece por editar",
|
|
598
|
+
"en": "Get started by editing",
|
|
599
|
+
"fr": "Commencez par éditer",
|
|
600
|
+
"es": "Comience por editar"
|
|
601
|
+
}
|
|
602
|
+
},
|
|
603
|
+
"pageLink": "src/app/page.tsx"
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
```
|
|
607
|
+
|
|
608
|
+
> As declarações de conteúdo podem ser definidas em qualquer lugar da sua aplicação desde que sejam incluídas no diretório `contentDir` (por padrão, `./src`). E que correspondam à extensão de ficheiro de declaração de conteúdo (por padrão, `.content.{json,ts,tsx,js,jsx,mjs,mjx,cjs,cjx}`).
|
|
609
|
+
|
|
610
|
+
> Para mais detalhes, consulte a [documentação de declaração de conteúdo](https://github.com/aymericzip/intlayer/blob/main/docs/docs/pt/dictionary/content_file.md).
|
|
611
|
+
|
|
612
|
+
### Passo 6: Utilizar Conteúdo no Seu Código
|
|
613
|
+
|
|
614
|
+
Aceda aos seus dicionários de conteúdo em toda a sua aplicação:
|
|
615
|
+
|
|
616
|
+
```tsx fileName="src/app/page.tsx" codeFormat="typescript"
|
|
617
|
+
import type { FC } from "react";
|
|
618
|
+
import { ClientComponentExample } from "@components/clientComponentExample/ClientComponentExample";
|
|
619
|
+
import { ServerComponentExample } from "@components/serverComponentExample/ServerComponentExample";
|
|
620
|
+
import {
|
|
621
|
+
IntlayerServerProvider,
|
|
622
|
+
useIntlayer,
|
|
623
|
+
getLocale,
|
|
624
|
+
} from "next-intlayer/server";
|
|
625
|
+
import { NextPage } from "next";
|
|
626
|
+
import { headers, cookies } from "next/headers";
|
|
627
|
+
|
|
628
|
+
const PageContent: FC = () => {
|
|
629
|
+
const content = useIntlayer("page");
|
|
630
|
+
|
|
631
|
+
return (
|
|
632
|
+
<>
|
|
633
|
+
<p>{content.getStarted.main}</p>
|
|
634
|
+
<code>{content.getStarted.pageLink}</code>
|
|
635
|
+
</>
|
|
636
|
+
);
|
|
637
|
+
};
|
|
638
|
+
|
|
639
|
+
const Page: NextPage = async () => {
|
|
640
|
+
const locale = await getLocale();
|
|
641
|
+
|
|
642
|
+
return (
|
|
643
|
+
<IntlayerServerProvider locale={locale}>
|
|
644
|
+
<PageContent />
|
|
645
|
+
<ServerComponentExample />
|
|
646
|
+
<ClientComponentExample />
|
|
647
|
+
</IntlayerServerProvider>
|
|
648
|
+
);
|
|
649
|
+
};
|
|
650
|
+
|
|
651
|
+
export default Page;
|
|
652
|
+
```
|
|
653
|
+
|
|
654
|
+
```jsx fileName="src/app/page.mjx" codeFormat="esm"
|
|
655
|
+
import { ClientComponentExample } from "@components/clientComponentExample/ClientComponentExample";
|
|
656
|
+
import { ServerComponentExample } from "@components/serverComponentExample/ServerComponentExample";
|
|
657
|
+
import { IntlayerServerProvider, useIntlayer } from "next-intlayer/server";
|
|
658
|
+
import { getLocale } from "intlayer";
|
|
659
|
+
import { headers, cookies } from "next/headers";
|
|
660
|
+
import { NextPage } from "next";
|
|
661
|
+
|
|
662
|
+
const Page: NextPage = async () => {
|
|
663
|
+
const content = useIntlayer("page");
|
|
664
|
+
|
|
665
|
+
return (
|
|
666
|
+
<>
|
|
667
|
+
<p>{content.getStarted.main}</p>
|
|
668
|
+
<code>{content.getStarted.pageLink}</code>
|
|
669
|
+
</>
|
|
670
|
+
);
|
|
671
|
+
};
|
|
672
|
+
|
|
673
|
+
const Page = async () => {
|
|
674
|
+
|
|
675
|
+
const locale = await getLocale();
|
|
676
|
+
|
|
677
|
+
return (
|
|
678
|
+
<IntlayerServerProvider locale={locale}>
|
|
679
|
+
<PageContent />
|
|
680
|
+
<ServerComponentExample />
|
|
681
|
+
<ClientComponentExample />
|
|
682
|
+
</IntlayerServerProvider>
|
|
683
|
+
);
|
|
684
|
+
};
|
|
685
|
+
|
|
686
|
+
export default Page;
|
|
687
|
+
```
|
|
688
|
+
|
|
689
|
+
```jsx fileName="src/app/page.csx" codeFormat="commonjs"
|
|
690
|
+
import { ClientComponentExample } from "@components/clientComponentExample/ClientComponentExample";
|
|
691
|
+
import { ServerComponentExample } from "@components/serverComponentExample/ServerComponentExample";
|
|
692
|
+
import { IntlayerServerProvider, useIntlayer, getLocale } from "next-intlayer/server";
|
|
693
|
+
import { NextPage } from "next";
|
|
694
|
+
import { headers, cookies } from "next/headers";
|
|
695
|
+
|
|
696
|
+
const Page: NextPage = async () => {
|
|
697
|
+
const content = useIntlayer("page");
|
|
698
|
+
|
|
699
|
+
return (
|
|
700
|
+
<>
|
|
701
|
+
<p>{content.getStarted.main}</p>
|
|
702
|
+
<code>{content.getStarted.pageLink}</code>
|
|
703
|
+
</>
|
|
704
|
+
);
|
|
705
|
+
};
|
|
706
|
+
|
|
707
|
+
const Page: NextPage = async () => {
|
|
708
|
+
const locale = await getLocale();
|
|
709
|
+
|
|
710
|
+
return (
|
|
711
|
+
<IntlayerServerProvider locale={locale}>
|
|
712
|
+
<PageContent />
|
|
713
|
+
<ServerComponentExample />
|
|
714
|
+
<ClientComponentExample />
|
|
715
|
+
</IntlayerServerProvider>
|
|
716
|
+
);
|
|
717
|
+
};
|
|
718
|
+
```
|
|
719
|
+
|
|
720
|
+
- **`IntlayerClientProvider`** é usado para fornecer a locale aos componentes do lado do cliente. Pode ser colocado em qualquer componente pai, incluindo o layout. No entanto, recomenda-se colocá-lo no layout porque o Next.js compartilha o código do layout entre páginas, tornando-o mais eficiente. Ao usar o `IntlayerClientProvider` no layout, você evita reinicializá-lo para cada página, melhorando o desempenho e mantendo um contexto de localização consistente em toda a sua aplicação.
|
|
721
|
+
- **`IntlayerServerProvider`** é usado para fornecer o locale aos filhos do servidor. Não pode ser definido no layout.
|
|
722
|
+
|
|
723
|
+
> Layout e página não podem compartilhar um contexto de servidor comum porque o sistema de contexto de servidor baseia-se num armazenamento de dados por requisição (via [cache do React](https://react.dev/reference/react/cache)), fazendo com que cada "context" seja recriado para diferentes segmentos da aplicação. Colocar o provider num layout partilhado quebraria esse isolamento, impedindo a propagação correta dos valores do contexto de servidor para os seus componentes de servidor.
|
|
724
|
+
|
|
725
|
+
```tsx {4,7} fileName="src/components/clientComponentExample/ClientComponentExample.tsx" codeFormat="typescript"
|
|
726
|
+
"use client";
|
|
727
|
+
|
|
728
|
+
import type { FC } from "react";
|
|
729
|
+
import { useIntlayer } from "next-intlayer";
|
|
730
|
+
|
|
731
|
+
export const ClientComponentExample: FC = () => {
|
|
732
|
+
const content = useIntlayer("client-component-example"); // Cria a declaração de conteúdo relacionada
|
|
733
|
+
|
|
734
|
+
return (
|
|
735
|
+
<div>
|
|
736
|
+
<h2>{content.title}</h2>
|
|
737
|
+
<p>{content.content}</p>
|
|
738
|
+
</div>
|
|
739
|
+
);
|
|
740
|
+
};
|
|
741
|
+
```
|
|
742
|
+
|
|
743
|
+
```jsx {3,6} fileName="src/components/clientComponentExample/ClientComponentExample.mjx" codeFormat="esm"
|
|
744
|
+
"use client";
|
|
745
|
+
|
|
746
|
+
import { useIntlayer } from "next-intlayer";
|
|
747
|
+
|
|
748
|
+
const ClientComponentExample = () => {
|
|
749
|
+
const content = useIntlayer("client-component-example"); // Cria a declaração de conteúdo relacionada
|
|
750
|
+
|
|
751
|
+
return (
|
|
752
|
+
<div>
|
|
753
|
+
<h2>{content.title}</h2>
|
|
754
|
+
<p>{content.content}</p>
|
|
755
|
+
</div>
|
|
756
|
+
);
|
|
757
|
+
};
|
|
758
|
+
```
|
|
759
|
+
|
|
760
|
+
```jsx {3,6} fileName="src/components/clientComponentExample/ClientComponentExample.csx" codeFormat="commonjs"
|
|
761
|
+
"use client";
|
|
762
|
+
|
|
763
|
+
const { useIntlayer } = require("next-intlayer");
|
|
764
|
+
|
|
765
|
+
const ClientComponentExample = () => {
|
|
766
|
+
const content = useIntlayer("client-component-example"); // Criar declaração de conteúdo relacionada
|
|
767
|
+
|
|
768
|
+
return (
|
|
769
|
+
<div>
|
|
770
|
+
<h2>{content.title}</h2>
|
|
771
|
+
<p>{content.content}</p>
|
|
772
|
+
</div>
|
|
773
|
+
);
|
|
774
|
+
};
|
|
775
|
+
```
|
|
776
|
+
|
|
777
|
+
```tsx {2} fileName="src/components/serverComponentExample/ServerComponentExample.tsx" codeFormat="typescript"
|
|
778
|
+
import type { FC } from "react";
|
|
779
|
+
import { useIntlayer } from "next-intlayer/server";
|
|
780
|
+
|
|
781
|
+
export const ServerComponentExample: FC = () => {
|
|
782
|
+
const content = useIntlayer("server-component-example"); // Criar declaração de conteúdo relacionada
|
|
783
|
+
|
|
784
|
+
return (
|
|
785
|
+
<div>
|
|
786
|
+
<h2>{content.title}</h2>
|
|
787
|
+
<p>{content.content}</p>
|
|
788
|
+
</div>
|
|
789
|
+
);
|
|
790
|
+
};
|
|
791
|
+
```
|
|
792
|
+
|
|
793
|
+
```jsx {1} fileName="src/components/serverComponentExample/ServerComponentExample.mjx" codeFormat="esm"
|
|
794
|
+
import { useIntlayer } from "next-intlayer/server";
|
|
795
|
+
|
|
796
|
+
const ServerComponentExample = () => {
|
|
797
|
+
const content = useIntlayer("server-component-example"); // Criar declaração de conteúdo relacionada
|
|
798
|
+
|
|
799
|
+
return (
|
|
800
|
+
<div>
|
|
801
|
+
<h2>{content.title}</h2>
|
|
802
|
+
<p>{content.content}</p>
|
|
803
|
+
</div>
|
|
804
|
+
);
|
|
805
|
+
};
|
|
806
|
+
```
|
|
807
|
+
|
|
808
|
+
```jsx {1} fileName="src/components/serverComponentExample/ServerComponentExample.csx" codeFormat="commonjs"
|
|
809
|
+
const { useIntlayer } = require("next-intlayer/server");
|
|
810
|
+
|
|
811
|
+
const ServerComponentExample = () => {
|
|
812
|
+
const content = useIntlayer("server-component-example"); // Criar declaração de conteúdo relacionada
|
|
813
|
+
|
|
814
|
+
return (
|
|
815
|
+
<div>
|
|
816
|
+
<h2>{content.title}</h2>
|
|
817
|
+
<p>{content.content}</p>
|
|
818
|
+
</div>
|
|
819
|
+
);
|
|
820
|
+
};
|
|
821
|
+
```
|
|
822
|
+
|
|
823
|
+
> Se quiser usar o seu conteúdo num atributo `string`, como `alt`, `title`, `href`, `aria-label`, etc., deve chamar o valor da função, por exemplo:
|
|
824
|
+
|
|
825
|
+
> ```jsx
|
|
826
|
+
> <img src={content.image.src.value} alt={content.image.value} />
|
|
827
|
+
> ```
|
|
828
|
+
|
|
829
|
+
> Para saber mais sobre o hook `useIntlayer`, consulte a [documentação](https://github.com/aymericzip/intlayer/blob/main/docs/docs/pt/packages/next-intlayer/useIntlayer.md).
|
|
830
|
+
|
|
831
|
+
### (Opcional) Passo 7: Configurar Proxy para Detecção de Locale
|
|
832
|
+
|
|
833
|
+
Configure o proxy para detetar a locale preferida do usuário:
|
|
834
|
+
|
|
835
|
+
```typescript fileName="src/proxy.ts" codeFormat="typescript"
|
|
836
|
+
export { intlayerProxy as proxy } from "next-intlayer/proxy";
|
|
837
|
+
|
|
838
|
+
export const config = {
|
|
839
|
+
matcher:
|
|
840
|
+
"/((?!api|static|assets|robots|sitemap|sw|service-worker|manifest|.*\\..*|_next).*)",
|
|
841
|
+
};
|
|
842
|
+
```
|
|
843
|
+
|
|
844
|
+
```javascript fileName="src/proxy.mjs" codeFormat="esm"
|
|
845
|
+
export { intlayerProxy as proxy } from "next-intlayer/proxy";
|
|
846
|
+
|
|
847
|
+
export const config = {
|
|
848
|
+
matcher:
|
|
849
|
+
"/((?!api|static|assets|robots|sitemap|sw|service-worker|manifest|.*\\..*|_next).*)",
|
|
850
|
+
};
|
|
851
|
+
```
|
|
852
|
+
|
|
853
|
+
```javascript fileName="src/proxy.cjs" codeFormat="commonjs"
|
|
854
|
+
const { intlayerProxy } = require("next-intlayer/proxy");
|
|
855
|
+
|
|
856
|
+
const config = {
|
|
857
|
+
matcher:
|
|
858
|
+
"/((?!api|static|assets|robots|sitemap|sw|service-worker|manifest|.*\\..*|_next).*)",
|
|
859
|
+
};
|
|
860
|
+
|
|
861
|
+
module.exports = { proxy: intlayerProxy, config };
|
|
862
|
+
```
|
|
863
|
+
|
|
864
|
+
> O `intlayerProxy` é usado para detectar a localidade preferida do usuário e redirecioná-lo para a URL apropriada conforme especificado na [configuração](https://github.com/aymericzip/intlayer/blob/main/docs/docs/pt/configuration.md). Além disso, permite salvar a localidade preferida do usuário em um cookie.
|
|
865
|
+
|
|
866
|
+
> Se precisar encadear vários proxies juntos (por exemplo, `intlayerProxy` com autenticação ou proxies customizados), o Intlayer agora fornece um helper chamado `multipleProxies`.
|
|
867
|
+
|
|
868
|
+
```ts
|
|
869
|
+
import { multipleProxies, intlayerProxy } from "next-intlayer/proxy";
|
|
870
|
+
import { customProxy } from "@utils/customProxy";
|
|
871
|
+
|
|
872
|
+
export const proxy = multipleProxies([intlayerProxy, customProxy]);
|
|
873
|
+
```
|
|
874
|
+
|
|
875
|
+
### (Opcional) Passo 8: Alterar o idioma do seu conteúdo
|
|
876
|
+
|
|
877
|
+
Para alterar o idioma do seu conteúdo no Next.js, a forma recomendada é usar o componente `Link` para redirecionar os utilizadores para a página localizada apropriada. O componente `Link` permite o prefetch da página, o que ajuda a evitar um recarregamento completo.
|
|
878
|
+
|
|
879
|
+
```tsx fileName="src/components/localeSwitcher/LocaleSwitcher.tsx" codeFormat="typescript"
|
|
880
|
+
"use client";
|
|
881
|
+
|
|
882
|
+
import type { FC } from "react";
|
|
883
|
+
import { Locales, getHTMLTextDir, getLocaleName } from "intlayer";
|
|
884
|
+
import { useLocale } from "next-intlayer";
|
|
885
|
+
|
|
886
|
+
export const LocaleSwitcher: FC = () => {
|
|
887
|
+
const { locale, availableLocales, setLocale } = useLocale({
|
|
888
|
+
onChange: () => window.location.reload(),
|
|
889
|
+
});
|
|
890
|
+
|
|
891
|
+
return (
|
|
892
|
+
<div>
|
|
893
|
+
<button popoverTarget="localePopover">{getLocaleName(locale)}</button>
|
|
894
|
+
<div id="localePopover" popover="auto">
|
|
895
|
+
{availableLocales.map((localeItem) => (
|
|
896
|
+
<button
|
|
897
|
+
key={localeItem}
|
|
898
|
+
aria-current={locale === localeItem ? "page" : undefined}
|
|
899
|
+
onClick={() => setLocale(localeItem)}
|
|
900
|
+
>
|
|
901
|
+
<span>
|
|
902
|
+
{/* Locale — ex.: FR */}
|
|
903
|
+
{localeItem}
|
|
904
|
+
</span>
|
|
905
|
+
<span>
|
|
906
|
+
{/* Idioma em seu próprio locale — ex.: Français */}
|
|
907
|
+
{getLocaleName(localeItem, locale)}
|
|
908
|
+
</span>
|
|
909
|
+
<span dir={getHTMLTextDir(localeItem)} lang={localeItem}>
|
|
910
|
+
{/* Idioma no locale atual — ex.: Francés com o locale atual definido para Locales.SPANISH */}
|
|
911
|
+
{getLocaleName(localeItem)}
|
|
912
|
+
</span>
|
|
913
|
+
<span dir="ltr" lang={Locales.ENGLISH}>
|
|
914
|
+
{/* Idioma em inglês - ex.: Francês */}
|
|
915
|
+
{getLocaleName(localeItem, Locales.ENGLISH)}
|
|
916
|
+
</span>
|
|
917
|
+
</button>
|
|
918
|
+
))}
|
|
919
|
+
</div>
|
|
920
|
+
</div>
|
|
921
|
+
);
|
|
922
|
+
};
|
|
923
|
+
```
|
|
924
|
+
|
|
925
|
+
```jsx fileName="src/components/localeSwitcher/LocaleSwitcher.msx" codeFormat="esm"
|
|
926
|
+
"use client";
|
|
927
|
+
|
|
928
|
+
import { Locales, getHTMLTextDir, getLocaleName } from "intlayer";
|
|
929
|
+
import { useLocale } from "next-intlayer";
|
|
930
|
+
|
|
931
|
+
export const LocaleSwitcher = () => {
|
|
932
|
+
const { locale, availableLocales, setLocale } = useLocale({
|
|
933
|
+
onChange: () => window.location.reload(),
|
|
934
|
+
});
|
|
935
|
+
|
|
936
|
+
return (
|
|
937
|
+
<div>
|
|
938
|
+
<button popoverTarget="localePopover">{getLocaleName(locale)}</button>
|
|
939
|
+
<div id="localePopover" popover="auto">
|
|
940
|
+
{availableLocales.map((localeItem) => (
|
|
941
|
+
<button
|
|
942
|
+
key={localeItem}
|
|
943
|
+
aria-current={locale === localeItem ? "page" : undefined}
|
|
944
|
+
onClick={() => setLocale(localeItem)}
|
|
945
|
+
>
|
|
946
|
+
<span>
|
|
947
|
+
{/* Locale - por exemplo: FR */}
|
|
948
|
+
{localeItem}
|
|
949
|
+
</span>
|
|
950
|
+
<span>
|
|
951
|
+
{/* Language in its own Locale - por exemplo: Français */}
|
|
952
|
+
{getLocaleName(localeItem, locale)}
|
|
953
|
+
</span>
|
|
954
|
+
<span dir={getHTMLTextDir(localeItem)} lang={localeItem}>
|
|
955
|
+
{/* Language in current Locale - por exemplo: Francés com o locale atual definido para Locales.SPANISH */}
|
|
956
|
+
{getLocaleName(localeItem)}
|
|
957
|
+
</span>
|
|
958
|
+
<span dir="ltr" lang={Locales.ENGLISH}>
|
|
959
|
+
{/* Language in English - por exemplo: French */}
|
|
960
|
+
{getLocaleName(localeItem, Locales.ENGLISH)}
|
|
961
|
+
</span>
|
|
962
|
+
</button>
|
|
963
|
+
))}
|
|
964
|
+
</div>
|
|
965
|
+
</div>
|
|
966
|
+
);
|
|
967
|
+
};
|
|
968
|
+
```
|
|
969
|
+
|
|
970
|
+
```jsx fileName="src/components/localeSwitcher/LocaleSwitcher.csx" codeFormat="commonjs"
|
|
971
|
+
"use client";
|
|
972
|
+
|
|
973
|
+
const { Locales, getHTMLTextDir, getLocaleName } = require("intlayer");
|
|
974
|
+
const { useLocale } = require("next-intlayer");
|
|
975
|
+
|
|
976
|
+
export const LocaleSwitcher = () => {
|
|
977
|
+
const path
|
|
978
|
+
const { locale availableLocales, setLocale } = useLocale({
|
|
979
|
+
onChange: ()=> window.location.reload(),
|
|
980
|
+
});
|
|
981
|
+
|
|
982
|
+
return (
|
|
983
|
+
<div>
|
|
984
|
+
<button popoverTarget="localePopover">{getLocaleName(locale)}</button>
|
|
985
|
+
<div id="localePopover" popover="auto">
|
|
986
|
+
{availableLocales.map((localeItem) => (
|
|
987
|
+
<button
|
|
988
|
+
key={localeItem}
|
|
989
|
+
aria-current={locale === localeItem ? "page" : undefined}
|
|
990
|
+
onClick={() => setLocale(localeItem)}
|
|
991
|
+
>
|
|
992
|
+
<span>
|
|
993
|
+
{/* Locale — por exemplo: FR */}
|
|
994
|
+
{localeItem}
|
|
995
|
+
</span>
|
|
996
|
+
<span>
|
|
997
|
+
{/* Idioma no seu próprio locale — por exemplo: Français */}
|
|
998
|
+
{getLocaleName(localeItem, locale)}
|
|
999
|
+
</span>
|
|
1000
|
+
<span dir={getHTMLTextDir(localeItem)} lang={localeItem}>
|
|
1001
|
+
{/* Idioma no locale atual — por exemplo: Francés com o locale atual definido como Locales.SPANISH */}
|
|
1002
|
+
{getLocaleName(localeItem)}
|
|
1003
|
+
</span>
|
|
1004
|
+
<span dir="ltr" lang={Locales.ENGLISH}>
|
|
1005
|
+
{/* Idioma em inglês — por exemplo: French */}
|
|
1006
|
+
{getLocaleName(localeItem, Locales.ENGLISH)}
|
|
1007
|
+
</span>
|
|
1008
|
+
</button>
|
|
1009
|
+
))}
|
|
1010
|
+
</div>
|
|
1011
|
+
</div>
|
|
1012
|
+
);
|
|
1013
|
+
};
|
|
1014
|
+
```
|
|
1015
|
+
|
|
1016
|
+
> Uma forma alternativa é usar a função `setLocale` fornecida pelo hook `useLocale`. Essa função não permitirá o prefetch da página. Consulte a [documentação do hook `useLocale`](https://github.com/aymericzip/intlayer/blob/main/docs/docs/pt/packages/next-intlayer/useLocale.md) para mais detalhes.
|
|
1017
|
+
|
|
1018
|
+
> Referências da documentação:
|
|
1019
|
+
>
|
|
1020
|
+
> - [`useLocale` hook](https://github.com/aymericzip/intlayer/blob/main/docs/docs/pt/packages/next-intlayer/useLocale.md)
|
|
1021
|
+
> - [`getLocaleName` hook](https://github.com/aymericzip/intlayer/blob/main/docs/docs/pt/packages/next-intlayer/getLocaleName.md)
|
|
1022
|
+
> - [`getLocalizedUrl` hook](https://github.com/aymericzip/intlayer/blob/main/docs/docs/pt/packages/next-intlayer/getLocalizedUrl.md)
|
|
1023
|
+
> - [`getHTMLTextDir` hook](https://github.com/aymericzip/intlayer/blob/main/docs/docs/pt/packages/intlayer/getHTMLTextDir.md)
|
|
1024
|
+
> - [`hrefLang` atributo](https://developers.google.com/search/docs/specialty/international/localized-versions?hl=fr)
|
|
1025
|
+
> - [`lang` atributo](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang)
|
|
1026
|
+
> - [`dir` atributo](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/dir)
|
|
1027
|
+
> - [`aria-current` atributo](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-current)
|
|
1028
|
+
|
|
1029
|
+
### (Opcional) Passo 9: Obter a locale atual em Server Actions
|
|
1030
|
+
|
|
1031
|
+
Se precisar da locale ativa dentro de uma Server Action (por exemplo, para localizar e-mails ou executar lógica dependente da locale), chame `getLocale` de `next-intlayer/server`:
|
|
1032
|
+
|
|
1033
|
+
```tsx fileName="src/app/actions/getLocale.ts" codeFormat="typescript"
|
|
1034
|
+
"use server";
|
|
1035
|
+
|
|
1036
|
+
import { getLocale } from "next-intlayer/server";
|
|
1037
|
+
|
|
1038
|
+
export const myServerAction = async () => {
|
|
1039
|
+
const locale = await getLocale();
|
|
1040
|
+
|
|
1041
|
+
// Faça algo com o locale
|
|
1042
|
+
};
|
|
1043
|
+
```
|
|
1044
|
+
|
|
1045
|
+
> A função `getLocale` segue uma estratégia em cascata para determinar a locale do utilizador:
|
|
1046
|
+
>
|
|
1047
|
+
> 1. Primeiro, verifica os cabeçalhos da requisição à procura de um valor de locale que pode ter sido definido pelo proxy
|
|
1048
|
+
> 2. Se nenhum locale for encontrado nos cabeçalhos, procura um locale armazenado em cookies
|
|
1049
|
+
> 3. Se nenhum cookie for encontrado, tenta detetar a língua preferida do utilizador a partir das definições do navegador
|
|
1050
|
+
> 4. Como último recurso, recorre ao locale predefinido configurado na aplicação
|
|
1051
|
+
>
|
|
1052
|
+
> Isso garante que o idioma mais apropriado seja selecionado com base no contexto disponível.
|
|
1053
|
+
|
|
1054
|
+
### (Opcional) Passo 10: Otimize o tamanho do bundle
|
|
1055
|
+
|
|
1056
|
+
Quando usar o `next-intlayer`, os dicionários são incluídos no bundle de cada página por padrão. Para otimizar o tamanho do bundle, o Intlayer fornece um plugin SWC opcional que substitui inteligentemente chamadas a `useIntlayer` usando macros. Isso garante que os dicionários sejam incluídos apenas nos bundles das páginas que realmente os utilizam.
|
|
1057
|
+
|
|
1058
|
+
Para habilitar essa otimização, instale o pacote `@intlayer/swc`. Uma vez instalado, o `next-intlayer` detectará e usará automaticamente o plugin:
|
|
1059
|
+
|
|
1060
|
+
```bash packageManager="npm"
|
|
1061
|
+
npm install @intlayer/swc --save-dev
|
|
1062
|
+
npx intlayer init
|
|
1063
|
+
```
|
|
1064
|
+
|
|
1065
|
+
```bash packageManager="pnpm"
|
|
1066
|
+
pnpm add @intlayer/swc --save-dev
|
|
1067
|
+
pnpm intlayer init
|
|
1068
|
+
```
|
|
1069
|
+
|
|
1070
|
+
```bash packageManager="yarn"
|
|
1071
|
+
yarn add @intlayer/swc --save-dev
|
|
1072
|
+
yarn intlayer init
|
|
1073
|
+
```
|
|
1074
|
+
|
|
1075
|
+
```bash packageManager="bun"
|
|
1076
|
+
bun add @intlayer/swc --dev
|
|
1077
|
+
bunx intlayer init
|
|
1078
|
+
```
|
|
1079
|
+
|
|
1080
|
+
> Observação: Esta otimização está disponível apenas para Next.js 13 e versões superiores.
|
|
1081
|
+
|
|
1082
|
+
> Observação: Este pacote não é instalado por padrão porque plugins SWC ainda são experimentais no Next.js. Isso pode mudar no futuro.
|
|
1083
|
+
|
|
1084
|
+
> Observação: Se você definir a opção como `importMode: 'dynamic'` ou `importMode: 'live'`, ela dependerá de `Suspense`, portanto você terá que envolver suas chamadas `useIntlayer` em um limite `Suspense`. Isso significa que você não poderá usar `useIntlayer` diretamente no nível superior do seu componente Page/Layout.
|
|
1085
|
+
|
|
1086
|
+
### Monitorar mudanças nos dicionários com Turbopack
|
|
1087
|
+
|
|
1088
|
+
Quando estiver a usar o Turbopack como servidor de desenvolvimento com o comando `next dev`, as alterações nos dicionários não serão detetadas automaticamente por padrão.
|
|
1089
|
+
|
|
1090
|
+
Esta limitação ocorre porque o Turbopack não consegue executar plugins do webpack em paralelo para monitorizar alterações nos seus ficheiros de conteúdo. Para contornar isto, terá de usar o comando `intlayer watch` para executar simultaneamente o servidor de desenvolvimento e o watcher de build do Intlayer.
|
|
1091
|
+
|
|
1092
|
+
```json5 fileName="package.json"
|
|
1093
|
+
{
|
|
1094
|
+
// ... As suas configurações existentes do package.json
|
|
1095
|
+
"scripts": {
|
|
1096
|
+
// ... As suas configurações de scripts existentes
|
|
1097
|
+
"dev": "intlayer watch --with 'next dev'",
|
|
1098
|
+
},
|
|
1099
|
+
}
|
|
1100
|
+
```
|
|
1101
|
+
|
|
1102
|
+
> Se você estiver usando next-intlayer@<=6.x.x, é necessário manter a flag `--turbopack` para que a aplicação Next.js 16 funcione corretamente com o Turbopack. Recomendamos usar next-intlayer@>=7.x.x para evitar essa limitação.
|
|
1103
|
+
|
|
1104
|
+
### Configurar TypeScript
|
|
1105
|
+
|
|
1106
|
+
O Intlayer usa module augmentation para tirar proveito do TypeScript e tornar sua codebase mais robusta.
|
|
1107
|
+
|
|
1108
|
+

|
|
1109
|
+
|
|
1110
|
+

|
|
1111
|
+
|
|
1112
|
+
Certifique-se de que sua configuração do TypeScript inclua os tipos autogerados.
|
|
1113
|
+
|
|
1114
|
+
```json5 fileName="tsconfig.json"
|
|
1115
|
+
{
|
|
1116
|
+
// ... Suas configurações existentes do TypeScript
|
|
1117
|
+
"include": [
|
|
1118
|
+
// ... Suas configurações existentes do TypeScript
|
|
1119
|
+
".intlayer/**/*.ts", // Incluir os tipos gerados automaticamente
|
|
1120
|
+
],
|
|
1121
|
+
}
|
|
1122
|
+
```
|
|
1123
|
+
|
|
1124
|
+
### Configuração do Git
|
|
1125
|
+
|
|
1126
|
+
Recomenda-se ignorar os ficheiros gerados pelo Intlayer. Isto permite evitar comitar estes ficheiros no seu repositório Git.
|
|
1127
|
+
|
|
1128
|
+
Para isso, pode adicionar as seguintes instruções ao ficheiro `.gitignore`:
|
|
1129
|
+
|
|
1130
|
+
```plaintext fileName=".gitignore"
|
|
1131
|
+
# Ignorar os ficheiros gerados pelo Intlayer
|
|
1132
|
+
.intlayer
|
|
1133
|
+
```
|
|
1134
|
+
|
|
1135
|
+
### Extensão do VS Code
|
|
1136
|
+
|
|
1137
|
+
Para melhorar a sua experiência de desenvolvimento com o Intlayer, pode instalar a extensão oficial **Intlayer VS Code Extension**.
|
|
1138
|
+
|
|
1139
|
+
[Install from the VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=intlayer.intlayer-vs-code-extension)
|
|
1140
|
+
|
|
1141
|
+
Esta extensão fornece:
|
|
1142
|
+
|
|
1143
|
+
- **Autocompletion** para chaves de tradução.
|
|
1144
|
+
- **Detecção de erros em tempo real** para traduções em falta.
|
|
1145
|
+
- **Visualizações inline** do conteúdo traduzido.
|
|
1146
|
+
- **Ações rápidas** para criar e atualizar traduções facilmente.
|
|
1147
|
+
|
|
1148
|
+
Para mais detalhes sobre como usar a extensão, consulte a [documentação da Extensão Intlayer para VS Code](https://intlayer.org/doc/vs-code-extension).
|
|
1149
|
+
|
|
1150
|
+
### Ir mais longe
|
|
1151
|
+
|
|
1152
|
+
Para ir mais longe, você pode implementar o [editor visual](https://github.com/aymericzip/intlayer/blob/main/docs/docs/pt/intlayer_visual_editor.md) ou externalizar seu conteúdo usando o [CMS](https://github.com/aymericzip/intlayer/blob/main/docs/docs/pt/intlayer_CMS.md).
|