i18n-polyfill icon indicating copy to clipboard operation
i18n-polyfill copied to clipboard

Why ngx-extractor only works with plainly injected i18N instance?

Open luisfpg opened this issue 5 years ago • 2 comments

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...

luisfpg avatar Dec 04 '18 11:12 luisfpg

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"});

skirilo avatar Dec 20 '18 21:12 skirilo

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...

luisfpg avatar Dec 28 '18 12:12 luisfpg