@@ -147,73 +147,92 @@ export default class Build extends Base {
147147 const FTL_MESSAGE_PATTERN = / ^ (?< message > [ a - z ] \S * ) ( * = * ) (?< pattern > .* ) $ / gim;
148148 const HTML_DATAI10NID_PATTERN = new RegExp ( `(data-l10n-id)="((?!${ namespace } )\\S*)"` , "g" ) ;
149149
150- // Walk the sub folders of `build/addon/locale`
151- const localeNames = ( await glob ( `${ dist } /addon/locale/*` , { onlyDirectories : true } ) )
152- . map ( locale => basename ( locale ) ) ;
153- this . logger . debug ( "locale names: " , localeNames ) ;
150+ // Get locale names
151+ const localePaths = await glob ( `${ dist } /addon/locale/*` , { onlyDirectories : true } ) ;
152+ const localeNames = localePaths . map ( locale => basename ( locale ) ) ;
153+ this . logger . debug ( "Locale names:" , localeNames ) ;
154+
155+ const allMessages = new Set < string > ( ) ;
156+ const messagesByLocale = new Map < string , Set < string > > ( ) ;
154157
155- const Messages = new Map < string , Set < string > > ( ) ;
156158 for ( const localeName of localeNames ) {
157159 // Prefix Fluent messages in each ftl, add message to set.
158- const MessageInThisLang = new Set < string > ( ) ;
160+ const localeMessages = new Set < string > ( ) ;
159161 const ftlPaths = await glob ( `${ dist } /addon/locale/${ localeName } /**/*.ftl` ) ;
162+
160163 await Promise . all ( ftlPaths . map ( async ( ftlPath : string ) => {
161- const ftlContent = await readFile ( ftlPath , "utf-8" ) ;
162- const matchs = [ ...ftlContent . matchAll ( FTL_MESSAGE_PATTERN ) ] ;
163- const newFtlContent = matchs . reduce ( ( content , match ) => {
164- if ( ! match . groups ?. message )
165- return content ;
166- MessageInThisLang . add ( match . groups . message ) ;
167- return content . replace ( match . groups . message , `${ namespace } -${ match . groups . message } ` ) ;
168- } , ftlContent ) ;
164+ let ftlContent = await readFile ( ftlPath , "utf-8" ) ;
165+ const matches = [ ...ftlContent . matchAll ( FTL_MESSAGE_PATTERN ) ] ;
166+
167+ for ( const match of matches ) {
168+ const message = match . groups ?. message ;
169+ if ( message ) {
170+ const namespacedMessage = `${ namespace } -${ message } ` ;
171+ localeMessages . add ( message ) ;
172+ allMessages . add ( message ) ;
173+ ftlContent = ftlContent . replace ( message , namespacedMessage ) ;
174+ }
175+ }
169176
170177 // If prefixFluentMessages===true, we save the changed ftl file,
171178 // otherwise discard the changes
172179 if ( build . fluent . prefixFluentMessages )
173- await writeFile ( ftlPath , newFtlContent ) ;
180+ await writeFile ( ftlPath , ftlContent ) ;
174181
175182 // rename *.ftl to addonRef-*.ftl
176183 if ( build . fluent . prefixLocaleFiles === true ) {
177184 await move ( ftlPath , `${ dirname ( ftlPath ) } /${ namespace } -${ basename ( ftlPath ) } ` ) ;
178185 this . logger . debug ( `Prefix filename: ${ ftlPath } ` ) ;
179186 }
180187 } ) ) ;
181- Messages . set ( localeName , MessageInThisLang ) ;
188+
189+ messagesByLocale . set ( localeName , localeMessages ) ;
182190 }
183191
184192 // Prefix Fluent messages in xhtml
185- const MessagesInHTML = new Set < string > ( ) ;
193+ const messagesInHTML = new Set < string > ( ) ;
186194 const htmlPaths = await glob ( [
187195 `${ dist } /addon/**/*.xhtml` ,
188196 `${ dist } /addon/**/*.html` ,
189197 ] ) ;
190198 await Promise . all ( htmlPaths . map ( async ( htmlPath ) => {
191- const content = await readFile ( htmlPath , "utf-8" ) ;
192- const matches = [ ...content . matchAll ( HTML_DATAI10NID_PATTERN ) ] ;
193- const newHtmlContent = matches . reduce ( ( result , match ) => {
199+ let htmlContent = await readFile ( htmlPath , "utf-8" ) ;
200+ const matches = [ ...htmlContent . matchAll ( HTML_DATAI10NID_PATTERN ) ] ;
201+
202+ for ( const match of matches ) {
194203 const [ matched , attrKey , attrVal ] = match ;
195- MessagesInHTML . add ( attrVal ) ;
196- return result . replace (
197- matched ,
198- `${ attrKey } ="${ namespace } -${ attrVal } "` ,
199- ) ;
200- } , content ) ;
204+
205+ if ( ! allMessages . has ( attrVal ) ) {
206+ this . logger . debug ( `HTML data-i10n-id ${ attrVal } do not exist in any FTL message, skip to namespace` ) ;
207+ continue ;
208+ }
209+
210+ messagesInHTML . add ( attrVal ) ;
211+ const namespacedAttr = `${ namespace } -${ attrVal } ` ;
212+ htmlContent = htmlContent . replace ( matched , `${ attrKey } ="${ namespacedAttr } "` ) ;
213+ }
201214
202215 if ( build . fluent . prefixFluentMessages )
203- await writeFile ( htmlPath , newHtmlContent ) ;
216+ await writeFile ( htmlPath , htmlContent ) ;
204217 } ) ) ;
205218
206- // Check miss 1: Cross check in diff locale
219+ // Check miss 1: Cross check in diff locale - seems no need
220+ // messagesMap.forEach((messageInThisLang, lang) => {
221+ // // Needs Nodejs 22
222+ // const diff = allMessages.difference(messageInThisLang);
223+ // if (diff.size)
224+ // this.logger.warn(`FTL messages "${Array.from(diff).join(", ")} don't exist the locale ${lang}"`);
225+ // });
207226
208227 // Check miss 2: Check ids in HTML but not in ftl
209- MessagesInHTML . forEach ( ( messageInHTML ) => {
210- const miss = new Set ( ) ;
211- Messages . forEach ( ( messagesInThisLang , lang ) => {
212- if ( ! messagesInThisLang . has ( messageInHTML ) )
213- miss . add ( lang ) ;
214- } ) ;
215- if ( miss . size !== 0 )
216- this . logger . warn ( `FTL message " ${ messageInHTML } " don't exist in " ${ [ ... miss ] . join ( ", " ) } "` ) ;
228+ messagesInHTML . forEach ( ( messageInHTML ) => {
229+ const missingLocales = [ ... messagesByLocale . entries ( ) ]
230+ . filter ( ( [ _ , messages ] ) => ! messages . has ( messageInHTML ) )
231+ . map ( ( [ locale ] ) => locale ) ;
232+
233+ if ( missingLocales . length > 0 ) {
234+ this . logger . warn ( `HTML data-l10n-id " ${ messageInHTML } " is missing in locales: ${ missingLocales . join ( ", " ) } ` ) ;
235+ }
217236 } ) ;
218237 }
219238
0 commit comments