i18n-polyfill
i18n-polyfill copied to clipboard
Why ngx-extractor only works with plainly injected i18N instance?
I'm building a fairly complex software, https://github.com/cyclosproject/cyclos4-ui.
Initially we had thought in our own i18n solution, because we need translations in services / components. But then we found i18n-polyfill and started using it.
We were happy, and did a lot of restructuring of the code.
As components have a lot of common dependencies, we've created a base class which receives the Injector instance and gets all the services it needs. We started doing the same with i18n
.
Then I suddenly realized none of the keys in components were being catched by ngx-extractor
, because the i18n instance was not injected directly, but obtained from the Injector.
The point is: why can't the i18n instance be passed around? I guess it would work if the string is set in the xlf file, but ngx-extractor ignores them.
To my surprise, when trying to find what happened, I found this answer: https://github.com/ngx-translate/i18n-polyfill/issues/37#issuecomment-437732146
The point is: why does the processor needs to work on directly injected references of i18n? Couldn't it just parse all the usages of I18N, and that's it?
The requirement that i18n MUST be injected is not documented anywhere, and is something fundamental for the extractor to work. And without the extractor working, there's no point in using i18n-polyfill...
Can we add the following code into extractor.ts ` protected _findI18nVariables(node: ts.Node): ts.VariableDeclaration[] { let variableNodes = this._findNodes(node, ts.SyntaxKind.VariableDeclaration) as ts.VariableDeclaration[]; variableNodes = variableNodes.filter(varNode => { if(varNode && varNode.type) { if (varNode.type["typeName"] && varNode.type["typeName"]["escapedText"]) return varNode.type["typeName"]["escapedText"] === "I18n"; } return false; });
return variableNodes;
} } `
And this piece of code to the end of the extract method: ` const variableNodes = this._findI18nVariables(this._sourceFile); variableNodes.forEach(i18nVariable => { var name = i18nVariable.name['escapedText']; }); variableNodes.forEach(varNode => { const callNodes = this._findCallNodes(varNode.parent ? varNode.parent : this._sourceFile, varNode.name['escapedText']); callNodes.forEach(callNode => { entries.push(...this._getCallArgStrings(callNode)); }); });
`
This will cover the code like this:
When I18n service retrieved using a factory function
const i18n: I18n = getTranslationService(); let textMsg = i18n({value: "Text message", id:"msgId"});
Nice. Is there a planned release shortly to include this fix? If not we'll have to do a heavy refactoring on the code to inject the I18n instances in all usages...