Skip to content

Commit 8bd3ca6

Browse files
committed
fix: do not namespace data-i10n-id that not exist in any ftl message
ref: #70 (comment)
1 parent 4c9ef62 commit 8bd3ca6

File tree

1 file changed

+55
-36
lines changed

1 file changed

+55
-36
lines changed

src/core/builder.ts

Lines changed: 55 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)