i18next / i18next-parser

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

Support variables in contexts #1018

Open jmlavoier opened 3 days ago

jmlavoier commented 3 days 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 3 days 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 2 days 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!