Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sending translocoService into the missing handler #555

Closed
1 task done
AbdealiLoKo opened this issue Apr 1, 2022 · 5 comments
Closed
1 task done

Sending translocoService into the missing handler #555

AbdealiLoKo opened this issue Apr 1, 2022 · 5 comments

Comments

@AbdealiLoKo
Copy link

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 trying to write a missing key handler which uses my key as the value.
The default behavior currently does not transpile() my variables though.

So, I tried writing a custom missing handler needs to use the translations and transpiler.

This is what I tried:

class TranspileKeyHandler implements TranslocoMissingHandler {
    constructor(
        @Inject(TRANSLOCO_TRANSPILER) private parser: TranslocoTranspiler,
        private translate: TranslocoService) {}

    handle(key: string, config: TranslocoMissingHandlerData, params?: HashMap) {
        const translation = this.translate.getTranslation(config.activeLang);
        return this.parser.transpile(key, params, translation);
    }
}

This gives me a circular DI issue because the missing handler is being used in the TranslocoService.

Describe the solution you'd like

In ngx-translate I could do:

class InterpolateKeyHandler implements MissingTranslationHandler {
    handle({ key, translateService, interpolateParams }: MissingTranslationHandlerParams) {
        return translateService.parser.interpolate(key, interpolateParams);
    }
}

Similarly, It would be nice to get the translateService as a argument into the handle function so we can use it easily.
This way I could do getTranslation() from the provided translateService

Describe alternatives you've considered

- I could try to dynamically inject the `TranslationService`
 - I could call the `TranslocoLoader` myself and make a second copy of the `translations`
Both are not ideal.

Additional context

No response

I would like to make a pull request for this feature

Yes 🚀

@shaharkazaz
Copy link
Collaborator

@AbdealiJK, I now understand why you are using the syntax with the double curly braces jsverse/transloco-keys-manager#130 🙂
That's an interesting idea. Can you share the motivation and the pros and cons of using this approach?

@AbdealiLoKo
Copy link
Author

Hi @shaharkazaz thanks a lot for going through all the 3 issues i raised and understanding them :)

The way I generally prefer to use translations is to do:

'Email is required - please enter it' | translate
Or
'User "{{name}}" cannot be deleted as this user is the only admin' | translate

This is a very simple approach where developers who normally know English can just write the English they expect to be shown.
And that English sentence becomes the key for the translation.

Pros:

  • When developers write the code. They focus on English and just call translate for what needs translation
  • Deduping becomes simpler for translators. When translators work on a .json or .po - we can very easily find keys which are similar. Like Can't delete this user and Can not delete this user and dedupe them.
  • When many developers work on a code base, there are tonnes of duplicated keys which are not known by all developers. So, using this approach developers don't need to think more about it. And just wrote code as though i18n is not present.
  • When developers search for error messages they directly get the code where it is constructed which makes debugging easier
  • When developers are writing code. They can immediately see the messages and don't have to keep mapping it to the key/value. Happens sometimes with cryptic keys. For example, Earlier I called something 'User Role' now I call it 'User Group'. Sometimes we don't change the key but change the value of the translation ...
  • The fallback translation for English I can use is an Empty translation, so no extra file I need to load (I guess this is not as important)

Overall. I have found in all my projects using this approach has made a developer's life much much easier.
And I can isolate my development work and translation work completely

My workflow today is:

  1. Developers write their code as they need
  2. Before a release some translators translate the .po/.json files
  3. If a translator finds some phrases are repeated or can be simplified - they just dedupe it in the code

The nested keys approach has always given us issues like if I have the same string in 2 places we have duplicated values. Like 'UserEdit.Name' and 'UserLogin.Name' both having the value 'User name'. These are not as easy to track because they will be in different parts of my en.json and developers won't always know they have to make a 'UserCommon.Name'.

Bottom line: The approach I described reduces the maintenance work needed to keep translations in projects.

I haven't seen any major cons for this approach.
Except that as I see here - some libraries don't consider this popular and haven't handled it :)

@shaharkazaz
Copy link
Collaborator

shaharkazaz commented Apr 11, 2022

@AbdealiJK Here is a working example, use the injector since you know that the Transloco service is injected already.

@AbdealiLoKo
Copy link
Author

That's fair - I can dynamically inject it.
Will close the ticket as that makes sense and should work for me
Thanks !

@MikeDabrowski
Copy link

I had the same original issue and used the workaround with dynamic inject. Thanks @AbdealiLoKo and @shaharkazaz for this idea.

However, while I was digging in the transloco code, I noticed that the translation object could easily be passed to the missing handler, the same way it is passed to the transpiler here:

https://github.com/ngneat/transloco/blob/27895f4af1236eece362529f1b422910c14fec24/libs/transloco/src/lib/transloco.service.ts#L290-L298

Having access to translations object, I could just pick the translation using fallback key or fallback second time to an empty string.

Note: In my case, we use custom transpiler and UPPER_CASE keys but the fallback keys do not require transpilation nor additional params (maybe yet).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants