DEV Community

Cover image for Don't use i18next ❌😒
Nevo David
Nevo David Subscriber

Posted on

Don't use i18next ❌😒

According to npmjs.com statistics, i18next is the most popular internationalization library for React.

This is probably due to the right choice of the name, which makes many developers think that i18next is some kind of standard library for React and Next.js.

In this article, I will show you why using i18next means shooting yourself in the leg.

Stop using this language


i18next != i18n

A lot of developers are confused about the terms internationalization, i18n and i18next. They believe that i18n = i18next, so when someone mentions i18next, it is some kind of standard.

It is not.

Let me clarify the words internationalization, i18n and i18next.

i18n options

Internationalization is the process of preparing your code to be able to work in different languages and cultures.

It is mostly about rendering different text values to users of different human languages. For this, you may choose any internationalization library out there. It can be i18next.

It can be react-intl. It can be Tolgee JS or Lingui. There are many such libraries, and there is no real standard.

i18n is just an abbreviation for internationalization since there are exactly 18 character omitted between the first "i" and the last "n" letters in the word. So, if you say i18n, it just means the internationalization process described above.

So i18next is just one of the libraries you can use for internationalization, so you can see i18next != i18n. Confusing i18next with "standard for React" is wrong because i18next is far from standard. Let's see why.

Image description


i18next doesn't use the ICU message format

The problem of internationalization is not new.

It's pretty old, and developers have been trying to solve problems like parameter interpolation, pluralization, number formatting or date formatting for decades.

At that time, several projects developed solutions, worked with many platforms and defined what we can call a standard.

One of these standards is Unicode with its ICU Message Format, which solves all the listed problems and already has implementations for many major programming languages, such as JS, PHP, Java, C++, Go, Dart, and many others.

Example of ICU message:

{dogsCount, plural, =0 {No dogs} one {One dog is} other {# dogs are}} here.
Enter fullscreen mode Exit fullscreen mode

Sadly, i18next ignored this standard and decided to implement it themselves. So, they have their own message format, formatting rules, and way of handling pluralization.


Why is this a problem?

In the beginning, you have a small project with a few hundred localization keys. But when your project grows, you have many languages and keys; to manage these, you will need some localization platform like Tolgee, Crowdin or Phrase.

And these platforms will have a hard time managing the strings in the special message format.

In contrast, in the JS world, libraries like Tolgee JS, react-intl or lingui-js follow the ICU message format, so most of the localization platforms can simply manage the data for these libraries.

I18next is over-featured

I18next was created by developers with no localization experience. They created a great tool for developers, but by including features unrelated to localization, and so they've created many problems for translators.

IMHO, the most problematic is the support for returning arrays and objects from localization data.

In i18next, you can do this.

The data:

{
    "array": ['a', 'b', 'c']
}
Enter fullscreen mode Exit fullscreen mode

The code:

i18next.t('array', { returnObjects: true });
Enter fullscreen mode Exit fullscreen mode

The array and object support might seem like an innocent feature enabling you to define different arrays in different languages. However, this is a major issue when you need to manage strings in most localization platforms.

Localization platforms are designed to work on a key-value basis rather than on the basics of structured objects, so they need to be able to convert such data to flat keys like array[0], array[1], or array[2].

But what if the user wants to define arrays of different sizes for different languages? This is unsolvable, and it will generate confusion and mess!

Also, the way the data is used is decided in the code and is not clear from the data.

So the translators don't know if we return the whole array or if we will access the keys separately using this path array.0.

At the same time, I have never encountered a good case for using the arrays' returning feature for localization purposes.

Other features that just cause a mess and can be omitted, like list formatting or selecting by context, are not trivial to support for the platforms.


Check out Tolgee 🀩

It's a good idea to choose a library that uses the ICU message format, such as' linguistorreact-intl`, or an alternative for your framework.

In my projects, I use Tolgee.

The benefit of this combo is that I can always ensure the components are compatible since the same company maintains them.

It also has some pretty neat features like in-context editing, which enables me to delegate the localization from developers and let the product team manage the strings themselves.

Tolgee JS uses the standard ICU message format.

Tolgee is 100% open-source.

Top comments (33)

Collapse
 
masudalimrancasual profile image
Masud Al Imran • Edited

Almost every project I have worked on I implemented internationalization myself, I don't find any significant benefit using i18next that I can't implement myself pretty easily. I think trying to use plugins for every small functions are overkill.
P.S. I also don't like using autocomplete/ search bar plugins. I insist on making one up myself.

Collapse
 
henrywills22 profile image
henrywills22

interesting... do you always get your projects translated just in the json files without any external tool?

Collapse
 
elsyng profile image
Ellis

AgreedπŸ‘

Collapse
 
nevodavid profile image
Nevo David

I think it all comes down to the amount of languages and amount of translations you need

Collapse
 
tswistak profile image
Tomasz Świstak • Edited

How do you handle different pluralization rules across different languages? For me, having it is a main benefit for using i18n libraries. English is pretty simple with just one plural form, but many languages use different forms depending on quantity. Also, as a user of such language, I really dislike seeing that translators couldn't use proper plural form and used all at once or a random one.

Collapse
 
jancizmar profile image
Jan Cizmar

Exactly <3

Collapse
 
claraq profile image
Clara Quintela

Me too.

Collapse
 
martinbaun profile image
Martin Baun

Agreed. Tolgee does it perfectly.

Collapse
 
dane_stevens profile image
Dane Stevens

You can one-click install Tolgee on Railway.app to easily host your own Tolgee instance:
railway.app/template/gpEPyD?referr...

Collapse
 
nevodavid profile image
Nevo David

Awesome!

Collapse
 
nevodavid profile image
Nevo David

Yas!

Collapse
 
keogh profile image
Isaac Zepeda

oh no I already started using it, I gotta say I had some hard time with it

Collapse
 
nevodavid profile image
Nevo David

Oh, what was the problem?

Collapse
 
keogh profile image
Isaac Zepeda

I'm still not able to make it read the spanish translations file in production, I have all the variables set correctly just loading the english file for some reason. Also I add to implement my own middleware for a telegram bot, I mean at the end almost everything I solvable, it just it wasn't as smooth as the documentation says.

Also the documentation was a little overwheelming

Collapse
 
kamran2121 profile image
kamran2121

we exactly got to this issue when storing arrays in i18next data

Collapse
 
nevodavid profile image
Nevo David

Time to move to Tolgee :)

Collapse
 
brooks-123 profile image
Brook

I used i18next for a project at work then we migrated to lingui, but Tolgee looks interesting.

Collapse
 
nevodavid profile image
Nevo David

You should try it out πŸš€

Collapse
 
best_codes profile image
Best Codes

I've tried Tolgee, and it's pretty nice, but I honestly preferred Crowdin translate over it.

Collapse
 
nevodavid profile image
Nevo David

Why?

Collapse
 
best_codes profile image
Best Codes

The Crowdin setup was more intuitive for me. It was easier to integrate with my GitHub account to auto translate my apps and stuff. Plus, you can AI translate in bulk (then review, of course), which helped me translate Codequill all in one day. :D

Thread Thread
 
smithjohn21 profile image
smithjohn21

Tolgee has the batch translation feature now. AFAIK it was added like year ago or something.

Thread Thread
 
best_codes profile image
Best Codes

Does it have OpenAI integration for it?

Thread Thread
 
jancizmar profile image
Jan Cizmar

Hey! Tolgee has something called Tolgee AI translator, which is based on OpenAI. In comparison to legacy translators like Google Translate or DeepL, it uses much more data. tolgee.io/platform/translation_pro...

Thread Thread
 
best_codes profile image
Best Codes

With Crowdin I can already use my own custom AI API endpoints and tokens, or OpenAI, Google, etc. with any custom models I want. :)

Thread Thread
 
jancizmar profile image
Jan Cizmar

This is indeed something, we should think of.

Collapse
 
nenyasha profile image
Melody Mbewe

Great reads @nevodavid. Thanks for the insights

Collapse
 
steven0121 profile image
Steven

Thanks for the insights!

Collapse
 
nevodavid profile image
Nevo David

You are welcome :)

Collapse
 
servicehumorist407 profile image
Andrew

What do you think of: formatjs.io/docs/intl/ ?
We are using it and it works well.

Collapse
 
nevodavid profile image
Nevo David

It's good :)
But it stateless, it means that you can only translate through code

Collapse
 
jancizmar profile image
Jan Cizmar

btw. Tolgee JS uses the ICU MessageFormat implementation provided by FormatJS, which depends on the intl classes.

Collapse
 
romkor profile image
Roman

Sounds like competitors ad