Issue
Our project implements ngx translate to provide translation functionality for the app.
In this case, I need to use it for some machine configuration data rather than a true "language".
To be more specific, I am converting a slew of XML definitions to yaml, but I ran into a few cases like this (notice the MACHINE_MODEL ISLIKE 470*):
<ENTRY DESC="OG 470">
<CRITERIA>
<CONDGROUP COMBINE="AND">
<CONDITION NAME="MACHINE_VENDOR" OP="EQ">OG</CONDITION>
<CONDITION NAME="MACHINE_TYPE" OP="EQ">OGSERIES</CONDITION>
<CONDITION NAME="MACHINE_MODEL" OP="ISLIKE">470*</CONDITION>
</CONDGROUP>
</CRITERIA>
<PARAMS>
<PARAMLIST NAME="DEVICES">
.
.
.
I am aware of the anchor/alias capability of yaml and suggested using it something like this:
'OG':
'4700': &OG4700Series
config:
.
.
.
'4701': *OG4700Series
'4702': *OG4700Series
'4750': *OG4700Series
However, product management want to implement the wildcard functionality. Is there a good way to do this in .yaml, or should I start trying to roll my own solution by somehow adding another element to the array of keys that gets passed in for the translate service to try?
Solution
The ngx-translate
doesn't support this type of comparison
by default, but it provides a way to customize the default parser
(TranslateDefaultParser) by implementing your own parser
to use it instead of the default one.
If you take a look at the TranslateDefaultParser
, you can notice that getValue function is used to resolve the passed key
/keys
and get the proper value of it from the provided translation:
getValue(target: any, key: string): any {
let keys = typeof key === 'string' ? key.split('.') : [key];
key = '';
do {
key += keys.shift();
if (isDefined(target) && isDefined(target[key]) && (typeof target[key] === 'object' || !keys.length)) {
target = target[key];
key = '';
} else if (!keys.length) {
target = undefined;
} else {
key += '.';
}
} while (keys.length);
return target;
}
So you can create your own parser
class by extending the TranslateDefaultParser
class and overriding the getValue
function to implement the required comparison
:
export class TranslateCustomParser extends TranslateDefaultParser {
/** Gets a value from an object by composed key
* parser.getValue({ key1: { keyA: 'valueI' }}, 'key1.keyA') ==> 'valueI'
* @param target the translation object that contains all the keys and values.
* @param key the passed key from instant/get function or to `translate` pipe.
*/
getValue(target: any, key: string) {
// here you can implement the custom `comparison` you need, then return the proper value.
}
}
Then you can configure the TranslateModule
to use it instead of the default one:
@NgModule({
imports: [
TranslateModule.forChild({
parser: {
provide: TranslateParser,
useClass: TranslateCustomParser,
},
}),
],
})
Now, when you call instant
/get
functions from TranslateService
or use the translate
pipe, to get the translation of a specific key, the value will be returned by the proper key using the new parser's getValue
function.
Answered By - Amer
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.