Skip to content

Commit c696d96

Browse files
committed
update missing keys which depends on changed modules
it makes working right while watching.
1 parent 1bb4e27 commit c696d96

File tree

1 file changed

+48
-15
lines changed

1 file changed

+48
-15
lines changed

index.ts

Lines changed: 48 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,25 @@ function getPath(template: string, language?: string, namespace?: string) {
8888
return template;
8989
}
9090

91+
export type CollectedKeys = {[language: string]: {[namespace: string]: {[key: string]: string[]}}};
92+
93+
function removeMap<T>(obj: _.Dictionary<T>, keys: (string | undefined)[]) {
94+
for (const emptyKey of keys) {
95+
if (emptyKey !== undefined) {
96+
delete obj[emptyKey];
97+
}
98+
}
99+
100+
return obj;
101+
}
102+
91103
export default class I18nextPlugin {
92104
protected compilation: wp.Compilation;
93105
protected option: InternalOption;
94106
protected context: string;
95-
protected missingKeys: {[language: string]: {[namespace: string]: string[]}};
107+
protected missingKeys: CollectedKeys = {};
108+
protected startTime = Date.now();
109+
protected prevTimestamps: {[file: string]: number} = {};
96110

97111
public constructor(option: Option) {
98112
this.option = _.defaults(option, {
@@ -132,14 +146,29 @@ export default class I18nextPlugin {
132146

133147
compiler.plugin("compilation", (compilation, data) => {
134148
// reset for new compliation
135-
this.missingKeys = {};
136-
137149
i18next.reloadResources(this.option.languages);
138150
this.compilation = compilation;
151+
const changedFiles = _.keys(compilation.fileTimestamps).filter(
152+
watchfile => (this.prevTimestamps[watchfile] || this.startTime) < (compilation.fileTimestamps[watchfile] || Infinity)
153+
);
154+
155+
removeMap(this.missingKeys, _.map(this.missingKeys, (namespaces, lng) =>
156+
_.size(removeMap(namespaces, _.map(namespaces, (values, ns) =>
157+
_.size(removeMap(values, _.map(values, (deps, key) => {
158+
_.remove(deps, dep => _.includes(changedFiles, dep));
159+
160+
return deps.length === 0 ? key : undefined;
161+
}))) === 0 ? ns : undefined
162+
))) === 0 ? lng : undefined
163+
));
164+
139165
data.normalModuleFactory.plugin(
140166
"parser",
141167
(parser: any) => {
142-
parser.plugin(`call ${this.option.functionName}`, this.onTranslateFunctionCall.bind(this));
168+
const that = this;
169+
parser.plugin(`call ${this.option.functionName}`, function(this: wp.Parser, arg: wp.Expression) {
170+
return I18nextPlugin.onTranslateFunctionCall.call(this, that, arg);
171+
});
143172
}
144173
);
145174
});
@@ -149,6 +178,8 @@ export default class I18nextPlugin {
149178

150179
protected async onEmit(compilation: wp.Compilation, callback: (err?: Error) => void) {
151180
// emit translation files
181+
this.prevTimestamps = compilation.fileTimestamps;
182+
152183
try {
153184
await Promise.all(_.map(this.option.languages, lng => {
154185
const resourceTemplate = path.join(this.context, getPath(this.option.resourcePath, lng));
@@ -204,20 +235,20 @@ export default class I18nextPlugin {
204235
}
205236
}
206237

207-
return _.map(namespaces, async (keys, ns) => new Promise<void>(resolve => {
238+
return _.map(namespaces, async (values, ns) => new Promise<void>(resolve => {
208239
delete remains[lng][ns];
209240
const missingPath = getPath(resourceTemplate, undefined, ns);
210241
const stream = fs.createWriteStream(missingPath, {
211242
defaultEncoding: "utf-8"
212243
});
213-
keys = _.sortedUniq(_.sortBy(keys));
244+
const keys = _.sortedUniq(_.sortBy(_.keys(values)));
214245
stream.write("{\n");
215246
stream.write(_.map(keys, key => `\t"${key}": "${key}"`).join(",\n"));
216247
stream.write("\n}");
217248

218249
stream.on("close", () => resolve());
219250

220-
compilation.warnings.push(`missing translation ${keys.length} keys in ${lng}/${ns}`);
251+
compilation.warnings.push(`missing translation ${_.size(values)} keys in ${lng}/${ns}`);
221252
}));
222253
}));
223254
// remove previous missings
@@ -235,27 +266,29 @@ export default class I18nextPlugin {
235266
}
236267
}
237268

238-
protected onTranslateFunctionCall(expr: any) {
239-
const args = expr.arguments.map((arg: any) => extractArgs(arg, this.warningOnCompilation.bind(this)));
269+
protected static onTranslateFunctionCall(this: wp.Parser, plugin: I18nextPlugin, expr: wp.Expression) {
270+
const args = expr.arguments.map((arg: any) => extractArgs(arg, plugin.warningOnCompilation.bind(plugin)));
240271

241-
for (const lng of this.option.languages) {
272+
for (const lng of plugin.option.languages) {
242273
const keyOrKeys: string | string[] = args[0];
243274
const option: i18next.TranslationOptionsBase = Object.assign(_.defaults(args[1], {}), {
244275
lng,
245-
defaultValue: null
246-
});
276+
defaultValue: this.state.current.resource
277+
} as i18next.TranslationOptionsBase);
247278
i18next.t(keyOrKeys, option);
248279
}
249280
}
250281

251-
protected onKeyMissing(lng: string, ns: string, key: string, __: string) {
252-
const p = [lng, ns];
282+
protected onKeyMissing(lng: string, ns: string, key: string, moduleName: string) {
283+
const p = [lng, ns, key];
253284
let arr: string[] = _.get(this.missingKeys, p);
254285
if (arr === undefined) {
255286
_.set(this.missingKeys, p, []);
256287
arr = _.get(this.missingKeys, p);
257288
}
258-
arr.push(key);
289+
if (arr.indexOf(moduleName) === -1) {
290+
arr.push(moduleName);
291+
}
259292
}
260293

261294
protected warningOnCompilation(msg: string) {

0 commit comments

Comments
 (0)