How to handle nesting and organizing your translation keys using i18next and react-i18next? and other best practices questions
Asked Answered
N

0

8

I have a couple of questions about best practices and the workflow when working with i18n I am currently using react-i18next I am defining the keys directly with default values in the components and then extracting them using babel-plugin-i18next-extract

Example

    <I18nText
        ns="meeting"
        i18nKey="meeting-invitation.videoConferenceLink"
        defaults="You can join the video conference call for {{meeting.name}} when it starts via: <br /> <0>{{meeting.videoConference.link}}</0>"
        components={[
            <a
                href={meeting.videoConference.link}
                target="_blank"
                rel="noopener noreferrer"
            >
                {meeting.videoConference.link}
            </a>,
        ]}
        values={{ meeting }}
    />

Note: I18nText is a custom component wrapping Trans component

Questions:

1️⃣ Should I put keywords that I use a lot across the app into their own key? if so, how do I handle pluralization, formatting and using context at the same time?

let's say that I use the keywords meeting and action across the app and I have a sentence like this

0 meetings, 0 actions         => You have no scheduled meetings and no actions deadlines so far to prepare for.
1 meeting, 1 action           => You have 1 scheduled meeting and 1 action deadline so far to prepare for.
2-inf meetings, 2-inf actions => You have (2-inf) scheduled meetings and (2-inf) action deadlines so far to prepare for.

meetings and actions can have a different count, I am aware that I can use nesting and that I pass count to each nested key like this

"key": "You have $t(glossary:scheduledMeetingWithCount, {\"count\": {{meetingCount}}}) and $t(glossary:actionDeadlinesWithCount, {\"count\": {{actionCount}}}) so far to prepare for."

But won't the translators get confused with all the nesting and passing count? and the scheduledMeetingWithCount and the actionDeadlinesWithCount keys, to what namespace should they be in? glossary? each in their own related namespace as in meeting and action namespaces? and how should there definition look like

"scheduledMeetingWithCount": "1 scheduled meeting",
"scheduledMeetingWithCount_plural": "{{count}} scheduled meeting",
"scheduledMeetingWithCount_0": "no scheduled meetings"  // doesn't i18next not support `_0` for `en`?

and won't that make the keys meeting and action be needed to be translated multiple times? as when it's defined alone meeting , its plural form meetings, when there is a count no meetings, 1 meeting and (2-inf) meeting, and when I need to add scheduled before the meeting name as in 1 scheduled meeting, {{count}} scheduled meetings and no scheduled meetings? Am I going to do this for each keyword I use across the system?

2️⃣ How can I format nested keys?

Let's say I have a key with value Meetings are scheduled for next week and I have a key for meeting_plural wtih the value meetings, but it's lowercase but I have a format function titleCase So I wanted to use something like {{$t(glossary:meeting_plural), titleCase}} are scheduled for next week but that results in meeting_plural), titleCase}} are scheduled for next week I've also tried

t('{{meeting, titleCase}} are scheduled for next week', {meeting: '$t(glossary:meeting_plural)'})

but that results in $T(Glossary:Meeting_Plural) are scheduled for next week so I ended up using

t('{{meeting, titleCase}} are scheduled for next week', { meeting: t('glossary:meeting_plural') })

which worked but is that best practice, should I just leave the translator to translate meetings again? should I add another key for when the "meetings" is title-cased?

3️⃣ How to handle variations in values, should I use context or add a key for every variation? if I use context how do I extract each context that is required?

I have a sentence that changes based on whether the passed action has the property dueDate or not when dueDate exists it shows this

Looks like you have a new action to complete: <strong>{{ action.title }}</strong> assigned by <strong> {{ action.creator.name }} </strong> and to be completed before <strong>{{ action.dueDate, dddd, MMMM Do, YYYY }}</strong>.

if dueDate doesn't exist it shows

Looks like you have a new action to complete: <strong>{{ action.title }}</strong> assigned by <strong> {{ action.creator.name }} </strong>.

how should I handle this case? should they be separated in their own keys? I've tried using context like this

t('action:action-assigned.content', {
  context: action.dueDate && 'dated'
})

and keys to action.json as

"action-assigned.content": "Looks like you have a new action to complete: <strong>{{ action.title }}</strong> assigned by <strong> {{ action.creator.name }} </strong>.",
"action-assigned.content_dated": "Looks like you have a new action to complete: <strong>{{ action.title }}</strong> assigned by <strong> {{ action.creator.name }} </strong> and to be completed before <strong>{{ action.dueDate, dddd, MMMM Do, YYYY }}</strong>."

is that the right use of context? I had to add these keys manually, not by the extraction tool and had to turn off discardOldKeys because it was removing the key with _dated

4️⃣ How do I organize my common keys?

do I throw anything that I'll use across the system in the common namespace and is it okay if I named the key with its value? or would it better to give them a specific key

5️⃣ Should I abstract values that are similar but have different nouns?

I have the values View action, View project, View meeting, ...etc. should I make a key with the value View {{item}} and pass the key for the noun that I want to use or should I just make each value in it's key?

6️⃣ Is there a TMS that support i18next-intervalPlural-postProcessor?

7️⃣ Should I switch to using I18next-icu?

I found ICU to handle pluralization better than i18next default format because in en I can add a specific condition to 0 instead of being limited to key and key_plural and ICU also has select which is like a switch statement which solves some of the issues that I have, Why doesn't i18next have something like select? is context supposed to handle the use-case that select handles?

8️⃣ Does anyone has any personal recommendation for a TMS that they used before and liked?

I want one that supports i18next features well, I've looked into locize but found their pricing hard to predict I would rather have something with a fixed price

9️⃣ Is there is a resource that I can learn best-practices and learn how to scale i18n?

I've searched for i18n resources but found the community to be a little lacking in in-depth guidance or an end-to-end workflow guide, I've mostly been trying things by trial and error but am not sure if I will be facing a roadblock or have growing pains with the current implementation am using

Nut answered 14/8, 2020 at 9:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.