@intlayer/docs 8.4.4 → 8.4.6
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/dist/cjs/_virtual/_rolldown/runtime.cjs +29 -0
- package/dist/cjs/blog.cjs +21 -1
- package/dist/cjs/blog.cjs.map +1 -1
- package/dist/cjs/common.cjs +81 -1
- package/dist/cjs/common.cjs.map +1 -0
- package/dist/cjs/doc.cjs +21 -1
- package/dist/cjs/doc.cjs.map +1 -1
- package/dist/cjs/frequentQuestions.cjs +21 -1
- package/dist/cjs/frequentQuestions.cjs.map +1 -1
- package/dist/cjs/generated/blog.entry.cjs +572 -1
- package/dist/cjs/generated/blog.entry.cjs.map +1 -1
- package/dist/cjs/generated/docs.entry.cjs +3032 -1
- package/dist/cjs/generated/docs.entry.cjs.map +1 -1
- package/dist/cjs/generated/frequentQuestions.entry.cjs +352 -1
- package/dist/cjs/generated/frequentQuestions.entry.cjs.map +1 -1
- package/dist/cjs/generated/legal.entry.cjs +72 -1
- package/dist/cjs/generated/legal.entry.cjs.map +1 -1
- package/dist/cjs/index.cjs +34 -1
- package/dist/cjs/legal.cjs +21 -1
- package/dist/cjs/legal.cjs.map +1 -1
- package/dist/esm/blog.mjs +14 -1
- package/dist/esm/blog.mjs.map +1 -1
- package/dist/esm/common.mjs +67 -1
- package/dist/esm/common.mjs.map +1 -1
- package/dist/esm/doc.mjs +14 -1
- package/dist/esm/doc.mjs.map +1 -1
- package/dist/esm/frequentQuestions.mjs +14 -1
- package/dist/esm/frequentQuestions.mjs.map +1 -1
- package/dist/esm/generated/blog.entry.mjs +570 -1
- package/dist/esm/generated/blog.entry.mjs.map +1 -1
- package/dist/esm/generated/docs.entry.mjs +3030 -1
- package/dist/esm/generated/docs.entry.mjs.map +1 -1
- package/dist/esm/generated/frequentQuestions.entry.mjs +350 -1
- package/dist/esm/generated/frequentQuestions.entry.mjs.map +1 -1
- package/dist/esm/generated/legal.entry.mjs +70 -1
- package/dist/esm/generated/legal.entry.mjs.map +1 -1
- package/dist/esm/index.mjs +6 -1
- package/dist/esm/legal.mjs +14 -1
- package/dist/esm/legal.mjs.map +1 -1
- package/dist/types/blog.d.ts +2 -2
- package/dist/types/common.d.ts +37 -2
- package/dist/types/common.d.ts.map +1 -0
- package/dist/types/doc.d.ts +2 -2
- package/dist/types/frequentQuestions.d.ts +2 -2
- package/dist/types/generated/blog.entry.d.ts +35 -2
- package/dist/types/generated/blog.entry.d.ts.map +1 -0
- package/dist/types/generated/docs.entry.d.ts +158 -2
- package/dist/types/generated/docs.entry.d.ts.map +1 -0
- package/dist/types/generated/frequentQuestions.entry.d.ts +24 -2
- package/dist/types/generated/frequentQuestions.entry.d.ts.map +1 -0
- package/dist/types/generated/legal.entry.d.ts +10 -2
- package/dist/types/generated/legal.entry.d.ts.map +1 -0
- package/dist/types/legal.d.ts +2 -2
- package/docs/ar/configuration.md +520 -722
- package/docs/ar/intlayer_with_storybook.md +521 -0
- package/docs/bn/configuration.md +922 -0
- package/docs/bn/intlayer_with_hono.md +428 -0
- package/docs/de/configuration.md +369 -743
- package/docs/de/intlayer_with_storybook.md +521 -0
- package/docs/en/configuration.md +181 -507
- package/docs/en/intlayer_with_storybook.md +521 -0
- package/docs/en-GB/configuration.md +456 -657
- package/docs/en-GB/intlayer_with_storybook.md +521 -0
- package/docs/es/configuration.md +379 -754
- package/docs/es/intlayer_with_storybook.md +521 -0
- package/docs/fr/configuration.md +376 -757
- package/docs/fr/intlayer_with_storybook.md +521 -0
- package/docs/hi/configuration.md +532 -728
- package/docs/hi/intlayer_with_storybook.md +521 -0
- package/docs/id/configuration.md +371 -684
- package/docs/id/intlayer_with_storybook.md +521 -0
- package/docs/it/configuration.md +397 -775
- package/docs/it/intlayer_with_storybook.md +521 -0
- package/docs/ja/configuration.md +525 -724
- package/docs/ja/intlayer_with_storybook.md +521 -0
- package/docs/ko/configuration.md +525 -724
- package/docs/ko/intlayer_with_storybook.md +521 -0
- package/docs/pl/configuration.md +430 -734
- package/docs/pl/intlayer_with_storybook.md +521 -0
- package/docs/pt/configuration.md +375 -746
- package/docs/pt/intlayer_with_storybook.md +521 -0
- package/docs/ru/configuration.md +532 -701
- package/docs/ru/intlayer_with_storybook.md +521 -0
- package/docs/tr/configuration.md +527 -719
- package/docs/tr/intlayer_with_storybook.md +521 -0
- package/docs/uk/configuration.md +425 -744
- package/docs/uk/intlayer_with_storybook.md +521 -0
- package/docs/ur/configuration.md +922 -0
- package/docs/ur/intlayer_with_hono.md +428 -0
- package/docs/vi/configuration.md +412 -753
- package/docs/vi/intlayer_with_storybook.md +521 -0
- package/docs/zh/configuration.md +521 -714
- package/docs/zh/intlayer_with_storybook.md +521 -0
- package/package.json +6 -6
- package/src/generated/docs.entry.ts +20 -0
- package/dist/cjs/common-a-l0ULP6.cjs +0 -2
- package/dist/cjs/common-a-l0ULP6.cjs.map +0 -1
- package/dist/types/blog.entry-D5IgxPXY.d.ts +0 -35
- package/dist/types/blog.entry-D5IgxPXY.d.ts.map +0 -1
- package/dist/types/common-B45TZvLQ.d.ts +0 -37
- package/dist/types/common-B45TZvLQ.d.ts.map +0 -1
- package/dist/types/docs.entry-CergjAYt.d.ts +0 -157
- package/dist/types/docs.entry-CergjAYt.d.ts.map +0 -1
- package/dist/types/frequentQuestions.entry-BHglVS-U.d.ts +0 -24
- package/dist/types/frequentQuestions.entry-BHglVS-U.d.ts.map +0 -1
- package/dist/types/legal.entry-B5Lg5eeH.d.ts +0 -10
- package/dist/types/legal.entry-B5Lg5eeH.d.ts.map +0 -1
|
@@ -0,0 +1,521 @@
|
|
|
1
|
+
---
|
|
2
|
+
createdAt: 2026-03-20
|
|
3
|
+
updatedAt: 2026-03-20
|
|
4
|
+
title: Como configurar o Intlayer com o Storybook
|
|
5
|
+
description: Saiba como tornar o seu sistema de design multilíngue usando o Intlayer com o Storybook — compile declarações de conteúdo, adicione um seletor de local e visualize os seus componentes em qualquer idioma.
|
|
6
|
+
keywords:
|
|
7
|
+
- Internacionalização
|
|
8
|
+
- Documentação
|
|
9
|
+
- Intlayer
|
|
10
|
+
- Storybook
|
|
11
|
+
- React
|
|
12
|
+
- i18n
|
|
13
|
+
- TypeScript
|
|
14
|
+
- Vite
|
|
15
|
+
- Webpack
|
|
16
|
+
slugs:
|
|
17
|
+
- doc
|
|
18
|
+
- storybook
|
|
19
|
+
history:
|
|
20
|
+
- version: 8.4.5
|
|
21
|
+
date: 2026-03-20
|
|
22
|
+
changes: Init doc
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
# Intlayer com Storybook
|
|
26
|
+
|
|
27
|
+
## Índice
|
|
28
|
+
|
|
29
|
+
<TOC/>
|
|
30
|
+
|
|
31
|
+
## O que é o Intlayer?
|
|
32
|
+
|
|
33
|
+
**Intlayer** é uma biblioteca de internacionalização (i18n) inovadora e de código aberto, projetada para simplificar o suporte multilíngue em aplicações web modernas. Funciona ao **nível do componente** — cada componente possui as suas próprias declarações de conteúdo — mantendo as traduções localizadas junto ao código que as utiliza.
|
|
34
|
+
|
|
35
|
+
Com o Intlayer pode:
|
|
36
|
+
|
|
37
|
+
- **Gerir traduções de forma declarativa** com ficheiros de conteúdo por componente.
|
|
38
|
+
- **Obter suporte completo para TypeScript** através de tipos gerados automaticamente e autocompletar no IDE.
|
|
39
|
+
- **Alterar locais em tempo de execução** sem recarregar a página.
|
|
40
|
+
- **Traduzir automaticamente** com integrações integradas de fornecedores de IA.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Porquê usar o Intlayer com o Storybook?
|
|
45
|
+
|
|
46
|
+
O Storybook é a ferramenta padrão da indústria para desenvolver e documentar componentes de UI isoladamente. Combiná-lo com o Intlayer permite-lhe:
|
|
47
|
+
|
|
48
|
+
- **Visualizar cada local** diretamente dentro do canvas do Storybook usando um seletor na barra de ferramentas.
|
|
49
|
+
- **Detetar traduções em falta** antes de chegarem à produção.
|
|
50
|
+
- **Documentar componentes multilíngues** com conteúdo real e seguro em termos de tipos, em vez de strings codificadas rigidamente.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Configuração Passo a Passo
|
|
55
|
+
|
|
56
|
+
<Tabs>
|
|
57
|
+
<Tab value="Vite Setup">
|
|
58
|
+
|
|
59
|
+
### Passo 1: Instalar Dependências
|
|
60
|
+
|
|
61
|
+
```bash packageManager="npm"
|
|
62
|
+
npm install intlayer react-intlayer
|
|
63
|
+
npm install vite-intlayer --save-dev
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
```bash packageManager="pnpm"
|
|
67
|
+
pnpm add intlayer react-intlayer
|
|
68
|
+
pnpm add vite-intlayer --save-dev
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
```bash packageManager="yarn"
|
|
72
|
+
yarn add intlayer react-intlayer
|
|
73
|
+
yarn add vite-intlayer --save-dev
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
```bash packageManager="bun"
|
|
77
|
+
bun add intlayer react-intlayer
|
|
78
|
+
bun add vite-intlayer --dev
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
| Pacote | Função |
|
|
82
|
+
| ---------------- | ---------------------------------------------------------------------- |
|
|
83
|
+
| `intlayer` | Core — configuração, compilação de conteúdo, CLI |
|
|
84
|
+
| `react-intlayer` | Bindings React — `IntlayerProvider`, hook `useIntlayer` |
|
|
85
|
+
| `vite-intlayer` | Plugin Vite — monitoriza e compila ficheiros de declaração de conteúdo |
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
### Passo 2: Criar uma Configuração do Intlayer
|
|
90
|
+
|
|
91
|
+
Crie `intlayer.config.ts` na raiz do seu projeto (ou dentro do seu pacote de design system):
|
|
92
|
+
|
|
93
|
+
```typescript fileName="intlayer.config.ts" codeFormat="typescript"
|
|
94
|
+
import { Locales, type IntlayerConfig } from "intlayer";
|
|
95
|
+
|
|
96
|
+
const config: IntlayerConfig = {
|
|
97
|
+
internationalization: {
|
|
98
|
+
locales: [
|
|
99
|
+
Locales.ENGLISH,
|
|
100
|
+
Locales.FRENCH,
|
|
101
|
+
Locales.SPANISH,
|
|
102
|
+
// adicione mais locais conforme necessário
|
|
103
|
+
],
|
|
104
|
+
defaultLocale: Locales.ENGLISH,
|
|
105
|
+
},
|
|
106
|
+
content: {
|
|
107
|
+
contentDir: ["./src"], // onde os seus ficheiros *.content.ts residem
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
export default config;
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
> Para a lista completa de opções, consulte a [referência de configuração](https://github.com/aymericzip/intlayer/blob/main/docs/docs/pt/configuration.md).
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
### Passo 3: Adicionar o Plugin Vite ao Storybook
|
|
119
|
+
|
|
120
|
+
O hook `viteFinal` do Storybook permite-lhe estender a configuração interna do Vite. Importe e adicione o plugin `intlayer()` aqui:
|
|
121
|
+
|
|
122
|
+
```typescript fileName=".storybook/main.ts" codeFormat="typescript"
|
|
123
|
+
import type { StorybookConfig } from "@storybook/react-vite";
|
|
124
|
+
import { defineConfig, mergeConfig } from "vite";
|
|
125
|
+
import { intlayer } from "vite-intlayer";
|
|
126
|
+
|
|
127
|
+
const config: StorybookConfig = {
|
|
128
|
+
stories: ["../src/**/*.stories.@(js|jsx|ts|tsx)"],
|
|
129
|
+
addons: [
|
|
130
|
+
"@storybook/addon-essentials",
|
|
131
|
+
// …outros addons
|
|
132
|
+
],
|
|
133
|
+
framework: {
|
|
134
|
+
name: "@storybook/react-vite",
|
|
135
|
+
options: {},
|
|
136
|
+
},
|
|
137
|
+
|
|
138
|
+
async viteFinal(baseConfig, { configType }) {
|
|
139
|
+
const env = {
|
|
140
|
+
command: configType === "DEVELOPMENT" ? "serve" : "build",
|
|
141
|
+
mode: configType === "DEVELOPMENT" ? "development" : "production",
|
|
142
|
+
} as const;
|
|
143
|
+
|
|
144
|
+
const viteConfig = defineConfig(() => ({
|
|
145
|
+
plugins: [intlayer()],
|
|
146
|
+
}));
|
|
147
|
+
|
|
148
|
+
return mergeConfig(baseConfig, viteConfig(env));
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
export default config;
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
O plugin `intlayer()` monitoriza os seus ficheiros `*.content.ts` e reconstrói os dicionários automaticamente sempre que houver alterações durante o desenvolvimento no Storybook.
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
### Passo 4: Adicionar o Decorador `IntlayerProvider` e uma Barra de Ferramentas de Local
|
|
160
|
+
|
|
161
|
+
O ficheiro `preview` do Storybook é o local ideal para envolver cada story com o `IntlayerProvider` e expor um seletor de local na barra de ferramentas:
|
|
162
|
+
|
|
163
|
+
```tsx fileName=".storybook/preview.tsx" codeFormat="typescript"
|
|
164
|
+
import type { Preview, StoryContext } from "@storybook/react";
|
|
165
|
+
import { IntlayerProvider } from "react-intlayer";
|
|
166
|
+
|
|
167
|
+
const preview: Preview = {
|
|
168
|
+
// Envolver cada story dentro do IntlayerProvider
|
|
169
|
+
decorators: [
|
|
170
|
+
(Story, context: StoryContext) => {
|
|
171
|
+
const locale = context.globals.locale ?? "en";
|
|
172
|
+
return (
|
|
173
|
+
<IntlayerProvider locale={locale}>
|
|
174
|
+
<Story />
|
|
175
|
+
</IntlayerProvider>
|
|
176
|
+
);
|
|
177
|
+
},
|
|
178
|
+
],
|
|
179
|
+
|
|
180
|
+
// Expor um seletor de local na barra de ferramentas do Storybook
|
|
181
|
+
globalTypes: {
|
|
182
|
+
locale: {
|
|
183
|
+
description: "Local ativo",
|
|
184
|
+
defaultValue: "en",
|
|
185
|
+
toolbar: {
|
|
186
|
+
title: "Local",
|
|
187
|
+
icon: "globe",
|
|
188
|
+
items: [
|
|
189
|
+
{ value: "en", title: "English" },
|
|
190
|
+
{ value: "fr", title: "Français" },
|
|
191
|
+
{ value: "es", title: "Español" },
|
|
192
|
+
],
|
|
193
|
+
dynamicTitle: true,
|
|
194
|
+
},
|
|
195
|
+
},
|
|
196
|
+
},
|
|
197
|
+
|
|
198
|
+
parameters: {
|
|
199
|
+
controls: {
|
|
200
|
+
matchers: {
|
|
201
|
+
color: /(background|color)$/i,
|
|
202
|
+
date: /Date$/i,
|
|
203
|
+
},
|
|
204
|
+
},
|
|
205
|
+
},
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
export default preview;
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
> Os valores de `locale` devem coincidir com os locais declarados no seu `intlayer.config.ts`.
|
|
212
|
+
|
|
213
|
+
</Tab>
|
|
214
|
+
<Tab value="Webpack Setup">
|
|
215
|
+
|
|
216
|
+
### Passo 1: Instalar Dependências
|
|
217
|
+
|
|
218
|
+
```bash packageManager="npm"
|
|
219
|
+
npm install intlayer react-intlayer
|
|
220
|
+
npm install @intlayer/webpack --save-dev
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
```bash packageManager="pnpm"
|
|
224
|
+
pnpm add intlayer react-intlayer
|
|
225
|
+
pnpm add @intlayer/webpack --save-dev
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
```bash packageManager="yarn"
|
|
229
|
+
yarn add intlayer react-intlayer
|
|
230
|
+
yarn add @intlayer/webpack --save-dev
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
```bash packageManager="bun"
|
|
234
|
+
bun add intlayer react-intlayer
|
|
235
|
+
bun add @intlayer/webpack --dev
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
### Passo 2: Criar uma Configuração do Intlayer
|
|
241
|
+
|
|
242
|
+
Crie `intlayer.config.ts` na raiz do seu projeto:
|
|
243
|
+
|
|
244
|
+
```typescript fileName="intlayer.config.ts" codeFormat="typescript"
|
|
245
|
+
import { Locales, type IntlayerConfig } from "intlayer";
|
|
246
|
+
|
|
247
|
+
const config: IntlayerConfig = {
|
|
248
|
+
internationalization: {
|
|
249
|
+
locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],
|
|
250
|
+
defaultLocale: Locales.ENGLISH,
|
|
251
|
+
},
|
|
252
|
+
content: {
|
|
253
|
+
contentDir: ["./src"],
|
|
254
|
+
},
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
export default config;
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
### Passo 3: Configurar o Webpack do Storybook
|
|
263
|
+
|
|
264
|
+
Para configurações do Storybook baseadas em Webpack (por exemplo, `@storybook/react-webpack5`), estenda a configuração do webpack através de `webpackFinal` para adicionar os aliases e o loader do Intlayer:
|
|
265
|
+
|
|
266
|
+
```typescript fileName=".storybook/main.ts" codeFormat="typescript"
|
|
267
|
+
import type { StorybookConfig } from "@storybook/react-webpack5";
|
|
268
|
+
import { IntlayerWebpackPlugin } from "@intlayer/webpack";
|
|
269
|
+
|
|
270
|
+
const config: StorybookConfig = {
|
|
271
|
+
stories: ["../src/**/*.stories.@(js|jsx|ts|tsx)"],
|
|
272
|
+
addons: ["@storybook/addon-essentials"],
|
|
273
|
+
framework: {
|
|
274
|
+
name: "@storybook/react-webpack5",
|
|
275
|
+
options: {},
|
|
276
|
+
},
|
|
277
|
+
|
|
278
|
+
webpackFinal: async (baseConfig) => {
|
|
279
|
+
baseConfig.plugins = [
|
|
280
|
+
...(baseConfig.plugins ?? []),
|
|
281
|
+
new IntlayerWebpackPlugin(),
|
|
282
|
+
];
|
|
283
|
+
return baseConfig;
|
|
284
|
+
},
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
export default config;
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
### Passo 4: Adicionar o Decorador `IntlayerProvider` e uma Barra de Ferramentas de Local
|
|
293
|
+
|
|
294
|
+
O mesmo que na configuração Vite — adicione o decorador e o tipo de local global em `.storybook/preview.tsx`:
|
|
295
|
+
|
|
296
|
+
```tsx fileName=".storybook/preview.tsx" codeFormat="typescript"
|
|
297
|
+
import type { Preview, StoryContext } from "@storybook/react";
|
|
298
|
+
import { IntlayerProvider } from "react-intlayer";
|
|
299
|
+
|
|
300
|
+
const preview: Preview = {
|
|
301
|
+
decorators: [
|
|
302
|
+
(Story, context: StoryContext) => {
|
|
303
|
+
const locale = context.globals.locale ?? "en";
|
|
304
|
+
return (
|
|
305
|
+
<IntlayerProvider locale={locale}>
|
|
306
|
+
<Story />
|
|
307
|
+
</IntlayerProvider>
|
|
308
|
+
);
|
|
309
|
+
},
|
|
310
|
+
],
|
|
311
|
+
|
|
312
|
+
globalTypes: {
|
|
313
|
+
locale: {
|
|
314
|
+
description: "Local ativo",
|
|
315
|
+
defaultValue: "en",
|
|
316
|
+
toolbar: {
|
|
317
|
+
title: "Local",
|
|
318
|
+
icon: "globe",
|
|
319
|
+
items: [
|
|
320
|
+
{ value: "en", title: "English" },
|
|
321
|
+
{ value: "fr", title: "Français" },
|
|
322
|
+
{ value: "es", title: "Español" },
|
|
323
|
+
],
|
|
324
|
+
dynamicTitle: true,
|
|
325
|
+
},
|
|
326
|
+
},
|
|
327
|
+
},
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
export default preview;
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
</Tab>
|
|
334
|
+
</Tabs>
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
## Declarar Conteúdo
|
|
339
|
+
|
|
340
|
+
Crie um ficheiro `*.content.ts` ao lado de cada componente. O Intlayer deteta-o automaticamente durante a compilação.
|
|
341
|
+
|
|
342
|
+
```typescript fileName="src/components/CopyButton/CopyButton.content.ts" codeFormat="typescript"
|
|
343
|
+
import { type Dictionary, t } from "intlayer";
|
|
344
|
+
|
|
345
|
+
const copyButtonContent = {
|
|
346
|
+
key: "copy-button",
|
|
347
|
+
content: {
|
|
348
|
+
label: t({
|
|
349
|
+
en: "Copy content",
|
|
350
|
+
fr: "Copier le contenu",
|
|
351
|
+
es: "Copiar contenido",
|
|
352
|
+
}),
|
|
353
|
+
},
|
|
354
|
+
} satisfies Dictionary;
|
|
355
|
+
|
|
356
|
+
export default copyButtonContent;
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
```javascript fileName="src/components/CopyButton/CopyButton.content.mjs" codeFormat="esm"
|
|
360
|
+
import { t } from "intlayer";
|
|
361
|
+
|
|
362
|
+
/** @type {import('intlayer').Dictionary} */
|
|
363
|
+
const copyButtonContent = {
|
|
364
|
+
key: "copy-button",
|
|
365
|
+
content: {
|
|
366
|
+
label: t({
|
|
367
|
+
en: "Copy content",
|
|
368
|
+
fr: "Copier le contenu",
|
|
369
|
+
es: "Copiar contenido",
|
|
370
|
+
}),
|
|
371
|
+
},
|
|
372
|
+
};
|
|
373
|
+
|
|
374
|
+
export default copyButtonContent;
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
```javascript fileName="src/components/CopyButton/CopyButton.content.cjs" codeFormat="commonjs"
|
|
378
|
+
const { t } = require("intlayer");
|
|
379
|
+
|
|
380
|
+
/** @type {import('intlayer').Dictionary} */
|
|
381
|
+
const copyButtonContent = {
|
|
382
|
+
key: "copy-button",
|
|
383
|
+
content: {
|
|
384
|
+
label: t({
|
|
385
|
+
en: "Copy content",
|
|
386
|
+
fr: "Copier le contenu",
|
|
387
|
+
es: "Copiar contenido",
|
|
388
|
+
}),
|
|
389
|
+
},
|
|
390
|
+
};
|
|
391
|
+
|
|
392
|
+
module.exports = copyButtonContent;
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
> Para mais formatos e funcionalidades de declaração de conteúdo, consulte a [documentação de declaração de conteúdo](https://github.com/aymericzip/intlayer/blob/main/docs/docs/pt/dictionary/content_file.md).
|
|
396
|
+
|
|
397
|
+
---
|
|
398
|
+
|
|
399
|
+
## Usar `useIntlayer` num Componente
|
|
400
|
+
|
|
401
|
+
```tsx fileName="src/components/CopyButton/index.tsx" codeFormat="typescript"
|
|
402
|
+
"use client";
|
|
403
|
+
|
|
404
|
+
import { type FC } from "react";
|
|
405
|
+
import { useIntlayer } from "react-intlayer";
|
|
406
|
+
|
|
407
|
+
type CopyButtonProps = {
|
|
408
|
+
content: string;
|
|
409
|
+
};
|
|
410
|
+
|
|
411
|
+
export const CopyButton: FC<CopyButtonProps> = ({ content }) => {
|
|
412
|
+
const { label } = useIntlayer("copy-button");
|
|
413
|
+
|
|
414
|
+
return (
|
|
415
|
+
<button
|
|
416
|
+
onClick={() => navigator.clipboard.writeText(content)}
|
|
417
|
+
aria-label={label.value}
|
|
418
|
+
title={label.value}
|
|
419
|
+
>
|
|
420
|
+
Copiar
|
|
421
|
+
</button>
|
|
422
|
+
);
|
|
423
|
+
};
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
O `useIntlayer` retorna o dicionário compilado para o local atual fornecido pelo `IntlayerProvider` mais próximo. Alterar o local na barra de ferramentas do Storybook volta a renderizar automaticamente a story com as traduzioni atualizadas.
|
|
427
|
+
|
|
428
|
+
---
|
|
429
|
+
|
|
430
|
+
## Escrever Stories para Componentes Internacionalizados
|
|
431
|
+
|
|
432
|
+
Com o decorador `IntlayerProvider` configurado, as suas stories funcionam exatamente como antes. A barra de ferramentas de local controla o local ativo para todo o canvas:
|
|
433
|
+
|
|
434
|
+
```tsx fileName="src/components/CopyButton/CopyButton.stories.tsx" codeFormat="typescript"
|
|
435
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
436
|
+
import { CopyButton } from ".";
|
|
437
|
+
|
|
438
|
+
const meta: Meta<typeof CopyButton> = {
|
|
439
|
+
title: "Components/CopyButton",
|
|
440
|
+
component: CopyButton,
|
|
441
|
+
tags: ["autodocs"],
|
|
442
|
+
argTypes: {
|
|
443
|
+
content: { control: "text" },
|
|
444
|
+
},
|
|
445
|
+
};
|
|
446
|
+
|
|
447
|
+
export default meta;
|
|
448
|
+
type Story = StoryObj<typeof CopyButton>;
|
|
449
|
+
|
|
450
|
+
/** Story padrão — altere o local na barra de ferramentas para visualizar as traduções. */
|
|
451
|
+
export const Default: Story = {
|
|
452
|
+
args: {
|
|
453
|
+
content: "npm install intlayer react-intlayer",
|
|
454
|
+
},
|
|
455
|
+
};
|
|
456
|
+
|
|
457
|
+
/** Renderiza o botão dentro de um bloco de código, um caso de uso comum no mundo real. */
|
|
458
|
+
export const InsideCodeBlock: Story = {
|
|
459
|
+
render: (args) => (
|
|
460
|
+
<div style={{ position: "relative", display: "inline-block" }}>
|
|
461
|
+
<pre style={{ background: "#1e1e1e", color: "#fff", padding: "1rem" }}>
|
|
462
|
+
<code>{args.content}</code>
|
|
463
|
+
</pre>
|
|
464
|
+
<CopyButton
|
|
465
|
+
content={args.content}
|
|
466
|
+
style={{ position: "absolute", top: 8, right: 8 }}
|
|
467
|
+
/>
|
|
468
|
+
</div>
|
|
469
|
+
),
|
|
470
|
+
args: {
|
|
471
|
+
content: "npx intlayer init",
|
|
472
|
+
},
|
|
473
|
+
};
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
> Cada story herda a variável global `locale` da barra de ferramentas, para que possa verificar cada local sem alterar qualquer código da story.
|
|
477
|
+
|
|
478
|
+
---
|
|
479
|
+
|
|
480
|
+
## Testar Traduções em Stories
|
|
481
|
+
|
|
482
|
+
Use as funções `play` do Storybook para garantir que o texto traduzido corretamente é renderizado para um determinado local:
|
|
483
|
+
|
|
484
|
+
```tsx fileName="src/components/CopyButton/CopyButton.stories.tsx" codeFormat="typescript"
|
|
485
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
486
|
+
import { expect, within } from "@storybook/test";
|
|
487
|
+
import { CopyButton } from ".";
|
|
488
|
+
|
|
489
|
+
const meta: Meta<typeof CopyButton> = {
|
|
490
|
+
title: "Components/CopyButton",
|
|
491
|
+
component: CopyButton,
|
|
492
|
+
tags: ["autodocs"],
|
|
493
|
+
};
|
|
494
|
+
|
|
495
|
+
export default meta;
|
|
496
|
+
type Story = StoryObj<typeof CopyButton>;
|
|
497
|
+
|
|
498
|
+
export const AccessibleLabel: Story = {
|
|
499
|
+
args: { content: "Hello World" },
|
|
500
|
+
play: async ({ canvasElement }) => {
|
|
501
|
+
const canvas = within(canvasElement);
|
|
502
|
+
const button = canvas.getByRole("button");
|
|
503
|
+
|
|
504
|
+
// Verificar se o botão tem um nome acessível não vazio
|
|
505
|
+
await expect(button).toHaveAccessibleName();
|
|
506
|
+
// Verificar se o botão não está desativado
|
|
507
|
+
await expect(button).not.toBeDisabled();
|
|
508
|
+
// Verificar a acessibilidade do teclado
|
|
509
|
+
await expect(button).toHaveAttribute("tabindex", "0");
|
|
510
|
+
},
|
|
511
|
+
};
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
---
|
|
515
|
+
|
|
516
|
+
## Recursos Adicionais
|
|
517
|
+
|
|
518
|
+
- [Referência de configuração do Intlayer](https://github.com/aymericzip/intlayer/blob/main/docs/docs/pt/configuration.md)
|
|
519
|
+
- [Documentação de declaração de conteúdo](https://github.com/aymericzip/intlayer/blob/main/docs/docs/pt/dictionary/content_file.md)
|
|
520
|
+
- [Documentação da CLI do Intlayer](https://github.com/aymericzip/intlayer/blob/main/docs/docs/pt/cli/index.md)
|
|
521
|
+
- [Documentação do Storybook](https://storybook.js.org/docs)
|