@@ -88,6 +88,148 @@ import { i18n } from './i18n';
8888console .log (i18n .t (' hello' ));
8989```
9090
91+ ## Hooks
92+
93+ ` rsbuild-plugin-i18next-extractor ` now exposes compilation hooks so other build-time plugins can consume extracted translations or customize how the extracted payload is written back to JS assets.
94+
95+ Exported APIs:
96+
97+ - ` getI18nextExtractorWebpackPluginHooks(compilation) `
98+ - ` AfterExtractPayload `
99+ - ` RenderExtractedTranslationsPayload `
100+
101+ ### ` afterExtract `
102+
103+ Called after translation keys have been extracted and locale payloads have been assembled for an entry.
104+
105+ This hook is useful when you want to:
106+
107+ - store extracted translations for a later build step
108+ - inspect extracted keys for debugging or reporting
109+ - feed extracted translations into another plugin
110+
111+ Payload shape:
112+
113+ ``` ts
114+ type AfterExtractPayload = {
115+ entryName: string ;
116+ locales: string [];
117+ files: string [];
118+ extractedKeysByLocale: Record <string , string []>;
119+ extractedTranslationsByLocale: Record <string , Record <string , string >>;
120+ };
121+ ```
122+
123+ ### ` renderExtractedTranslations `
124+
125+ Called before extracted translations are prepended back into JS assets.
126+
127+ The default behavior is still:
128+
129+ ``` ts
130+ const __I18N_EN_EXTRACTED_TRANSLATIONS__ = { ... };
131+ ```
132+
133+ This hook is useful when you want to:
134+
135+ - customize the injected JS code
136+ - skip JS injection for some or all locales
137+ - redirect the extracted payload to another artifact pipeline
138+
139+ Payload shape:
140+
141+ ``` ts
142+ type RenderExtractedTranslationsPayload = {
143+ entryName: string ;
144+ locale: string ;
145+ variableName: string ;
146+ extractedKeys: string [];
147+ extractedTranslations: Record <string , string >;
148+ targetAssetNames: string [];
149+ code: string ;
150+ skip? : boolean ;
151+ };
152+ ```
153+
154+ ### Hook Example
155+
156+ ``` ts
157+ import {
158+ defineConfig ,
159+ type RsbuildPlugin ,
160+ type Rspack ,
161+ } from ' @rsbuild/core' ;
162+ import {
163+ getI18nextExtractorWebpackPluginHooks ,
164+ pluginI18nextExtractor ,
165+ } from ' rsbuild-plugin-i18next-extractor' ;
166+
167+ function pluginObserveI18nExtraction(): RsbuildPlugin {
168+ return {
169+ name: ' example:observe-i18n-extraction' ,
170+ setup(api ) {
171+ api .modifyBundlerChain ((chain ) => {
172+ chain
173+ .plugin (' example:observe-i18n-extraction' )
174+ .use (
175+ class ObserveI18nExtractionPlugin {
176+ apply(compiler : Rspack .Compiler ) {
177+ compiler .hooks .compilation .tap (
178+ ' example:observe-i18n-extraction' ,
179+ (compilation ) => {
180+ const hooks =
181+ getI18nextExtractorWebpackPluginHooks (compilation );
182+
183+ hooks .afterExtract .tapPromise (
184+ ' example:observe-i18n-extraction' ,
185+ async (payload ) => {
186+ console .log (payload .entryName );
187+ console .log (payload .extractedTranslationsByLocale );
188+ return payload ;
189+ },
190+ );
191+
192+ hooks .renderExtractedTranslations .tapPromise (
193+ ' example:observe-i18n-extraction' ,
194+ async (payload ) => {
195+ if (payload .locale === ' zh-CN' ) {
196+ return {
197+ ... payload ,
198+ skip: true ,
199+ code: ' ' ,
200+ };
201+ }
202+
203+ return payload ;
204+ },
205+ );
206+ },
207+ );
208+ }
209+ },
210+ );
211+ });
212+ },
213+ };
214+ }
215+
216+ export default defineConfig ({
217+ plugins: [
218+ pluginI18nextExtractor ({
219+ localesDir: ' ./locales' ,
220+ }),
221+ pluginObserveI18nExtraction (),
222+ ],
223+ });
224+ ```
225+
226+ ### Hook Semantics
227+
228+ - ` afterExtract ` is a waterfall hook and should return the payload it wants later consumers to receive.
229+ - ` renderExtractedTranslations ` is also a waterfall hook and should return the payload it wants the default emitter to use.
230+ - Setting ` skip: true ` or returning an empty ` code ` string prevents that locale payload from being injected into JS assets.
231+ - ` targetAssetNames ` contains all synchronous and async JS assets that would otherwise receive the injected definitions for the current entry.
232+
91233## Options
92234
93235### ` localesDir `
0 commit comments