-
-
Notifications
You must be signed in to change notification settings - Fork 210
Description
Is there an existing issue for this?
- I have searched the existing issues
Which Transloco package(s) will this feature affect?
Transloco
Is your feature request related to a problem? Please describe
I am using transloco signal API.
When using transloco API, in general I create a signal attribute (translocoSignal) for each translation key.
When I have a bunch of translations to handle I can use translocoObjectSignal.
But if I need to interpolate the messages using parameters, I need to know the params values (or signals) at signal instantiation time.
What I would like is to create an object Signal but be able to interpolate the parameters at signal evaluation time.
For instance: (if we imagine this kind of feature working on translocoObjectSignal):
private readonly translocoObject = translocoObjectSignal('home.contract');
readonly widget: FilesCheckWidget = {
id: 'contracts',
kind: 'contract',
supportingText: computed(() => this.translocoObject().translate('supportingText', { count: this.items().length })),
buttonLabel: computed(() =>
this.translocoObject().translate('buttonLabel', { remaining: Math.max(0, this.items().length - 2) }),
),
emptyLabels: computed(() => ({
title: this.translocoObject().translate('emptyLabels.title'),
description: this.translocoObject().translate('emptyLabels.description'),
})),
actions: {
mainButton: () => this.router.navigate(['/activities']),
},
};
With this, I could avoid declaring 4 signal attributes that add a bit of noise (imo) in my component code.
Thanks,
Adrian
Describe the solution you'd like
No response
Describe alternatives you've considered
Solution 1
A working sample with classic transloco would be the following.
But it forces us to have one signal per translation and one per parameter in the translation.
It is a lot of boilerplate imo.
private readonly messages = translateObjectSignal('home.contract');
private readonly count = computed(() => this.items().length);
private readonly supportingTextTranslation = translateSignal('home.contract.supportingText', { count: this.count });
private readonly remaining = computed(() => Math.max(0, this.items().length - 2));
private readonly buttonLabelTranslation = translateSignal('home.contract.buttonLabel', { remaining: this.remaining });
readonly widget: FilesCheckWidget = {
id: 'contracts',
kind: 'contract',
supportingText: this.supportingTextTranslation,
buttonLabel: this.buttonLabelTranslation,
emptyLabels: computed(() => ({
title: this.messages()['emptyLabels.title'],
description: this.messages()['emptyLabels.description'],
})),
};Solution 2
Another possibility would be to use lang as a Signal (to force reevaluation) alongside the translate API.
But it feels really awkward, a clear API would be way better.
private readonly lang = toSignal(inject(TranslocoService).langChanges$);
private readonly emptyLabelsSignal = translateObjectSignal('home.contract.emptyLabels');
readonly widget: FilesCheckWidget = {
id: 'contracts',
kind: 'contract',
supportingText: computed(() => translate('home.contract.supportingText', { count: this.items().length }, this.lang())),
buttonLabel: computed(() => translate('home.contract.buttonLabel', { remaining: Math.max(0, this.items().length - 2) }, this.lang())),
emptyLabels: computed(() => ({
title: this.emptyLabelsSignal()['title'],
description: this.emptyLabelsSignal()['description'],
})),
};
Solution 3
Using the previous solution as a base, we can create a utility function like:
export function translateSignalParams(
baseKey: string,
): Signal<(keyOrParams?: string | Record<string, any>, params?: Record<string, any>) => string> {
const transloco = inject(TranslocoService);
const lang = toSignal(transloco.langChanges$);
return computed(() => {
return (keyOrParams?: string | Record<string, any>, params?: Record<string, any>) => {
let key: string | undefined;
let finalParams: Record<string, any> | undefined;
if (typeof keyOrParams === 'string') {
key = keyOrParams;
finalParams = params;
} else {
finalParams = keyOrParams;
key = undefined;
}
const fullKey = baseKey
? key
? `${baseKey}.${key}`
: baseKey
: key;
if (!fullKey) return '';
return transloco.translate(fullKey, finalParams, lang());
};
});
}
And afterwards:
private t = translateSignalParams('home.contract');
/** Widget exposed to component **/
readonly widget: FilesCheckWidget = {
id: 'contracts',
kind: 'contract',
supportingText: computed(() => this.t()('supportingText', { count: this.items().length })),
buttonLabel: computed(() => this.t()('buttonLabel', { remaining: Math.max(0, this.items().length - 2) })),
emptyLabels: computed(() => ({
title: this.t()('emptyLabels.title'),
description: this.t()('emptyLabels.description'),
})),
};
}
Additional context
No response
I would like to make a pull request for this feature
Yes π