i18next / i18next-parser

Parse your code to extract translation keys/values and manage your catalog files
MIT License
486 stars 198 forks source link

Support variables in contexts #1018

Open jmlavoier opened 4 months ago

jmlavoier commented 4 months ago

🚀 Feature Proposal

According to this PR. It's considering extracting only hard coded extract values.

The idea is to make it possible the parser recognize the values of the context by specifying the possible values the context might be. This issue is already solved on the i18next-extract library through explicitly specify contexts for a key feature.

Motivation

This feature is very important since most of the time we use dynamic context through a variable unless necessary by implementing conditions within the code to display the required context.

Example

Consider a variable that rely to a frequency like WEEKLY, MONTHLY, YEARLY

Currently the library is working correctly if we hardcoded the values like this:

// code
<>
  {t('frequency', { context: 'WEEKLY' })}
</>

// translation.json
{
  "frequency_WEEKLY": ""
}

But, I need this translation rely to a variable (frequency: 'WEEKLY' | 'MONTHLY' | 'YEARLY' ), and I need to work around using some conditions so make it possible to extract:

// code
const frequency:  'WEEKLY' | 'MONTHLY' | 'YEARLY' = 'WEEKLY'

const translations = {
  WEEKLY: t('frequency', { context: 'WEEKLY' }),
  MONTHLY: t('frequency', { context: 'MONTHLY' }),
  YEARLY: t('frequency', { context: 'YEARLY' }),
}
...
<>
  {translations[frequency]}
</>

// translation.json
{
  "frequency_WEEKLY": ""
  "frequency_MONTHLY": "" 
  "frequency_YEARLY": ""
}

It's wordy and not clean. It increases the complexity by making us get to manage more an unnecessary condition only due to a translation.

Solution

As I linked before, i18next-extract sorted out this challenge by using comments. It would be something like this in this library:

// code
const frequency:  'WEEKLY' | 'MONTHLY' | 'YEARLY' = 'WEEKLY'

<>
  // i18next-parser-mark-context-next-line ['WEEKLY', 'MONTHLY', 'YEARLY']
  {t('frequency', { context:  frequency })}
</>

// translation.json
{
  "frequency_WEEKLY": ""
  "frequency_MONTHLY": "" 
  "frequency_YEARLY": ""
}
jmlavoier commented 4 months ago

I just realized that there is quite a solution for this issue documented in the caveats session. But it's not regarding contexts.

If implement something like this, it works.

// code
const frequency:  'WEEKLY' | 'MONTHLY' | 'YEARLY' = 'WEEKLY'

<>
   /*
   t('frequency_WEEKLY')
   t('frequency_MONTHLY')
   t('frequency_YEARLY')
   */
  {t(`frequency_${frequency}`)}
</>

// translation.json
{
  "frequency_WEEKLY": ""
  "frequency_MONTHLY": "" 
  "frequency_YEARLY": ""
}

But the extract of contexts is still not working.

// code
const frequency:  'WEEKLY' | 'MONTHLY' | 'YEARLY' = 'WEEKLY'

<>
   /*
   t('frequency_WEEKLY')
   t('frequency_MONTHLY')
   t('frequency_YEARLY')
   */
  {t('frequency', { context: frequency } )}
</>

// translation.json
{
  "frequency_WEEKLY": ""
  "frequency_MONTHLY": "" 
  "frequency_YEARLY": ""
  "frequency_frequency": "" // <-- It wrongly extract a new one using the context variable name.
}
karellm commented 4 months ago

The parser does not interpret the code nor do I think it should as it would slow it down. There is not easy solution around that issue.

That said, your last example looks like a bug and if you want to open a PR, that would be very appreciated!

jmlavoier commented 2 months ago

Hey @karellm, how about you add this project to the Hacktoberfest event? You'll encourage more lazy devs like me to contribute to your repo next month. 😅