menu
search
...

i18n issues you may meet

eye-

layout issues

html {
  direction: rtl;
}

If you use a position absolute property, let element on the left, then when you change the direction of the document, the element still stays on the left. You need to adjust the position of the element to the right.

/* before, direction: ltr */
.element {
  position: absolute;
  left: 0;
}

/* after, direction: rtl */
.element {
  position: absolute;
  right: 0;
}
const en = "What's the weather like today?"
const zh = "今天天气怎么样?"
const ar = "ما هو الطقس اليوم ؟"
const ja = "今日の天気はどうですか?"
const ko = "오늘 날씨는 어때요?"
const es = "¿Qué tiempo hace hoy?"
const fr = "Quel temps fait-il aujourd'hui?"
const de = "Wie ist das Wetter heute?"
const it = "Che tempo fa oggi?"
const pt = "Qual a temperatura hoje?"
const nl = "Wat is de weer vandaag?"
const pl = "Jakie jest pogoda dzisiaj?"
const ro = "Ce vreme este azi?"
const tr = "Bugün hava nasıl?"
const vi = "Hôm nay thời tiết thế nào?"

For example, in Brazil (pt-BR), prices use commas as decimal separators instead of periods/points:

// US/UK format
$10.50 (using decimal point)

// Brazil format
R$ 10,50 (using comma as decimal separator)

plural rules

Different languages have different plural rules. For example:

You can use libraries like i18next to handle plural rules:

// English
i18next.t("key", { count: 1 }) // "1 minute"
i18next.t("key", { count: 2 }) // "2 minutes"

// Chinese
i18next.t("key", { count: 1 }) // "1分钟"
i18next.t("key", { count: 2 }) // "2分钟"

// Russian
i18next.t("key", { count: 1 }) // "1 минута"
i18next.t("key", { count: 2 }) // "2 минуты"
i18next.t("key", { count: 5 }) // "5 минут"

The key in i18next is a unique identifier for your translation strings. It's like a variable name that maps to different translations in different languages. Here's how it works:

// translation files
// en.json
{
  "time.minutes": {
    "one": "{{count}} minute",
    "other": "{{count}} minutes"
  }
}

// zh.json
{
  "time.minutes": "{{count}}分钟"
}

// Usage
i18next.t('time.minutes', { count: 1 }); // "1 minute" in English, "1分钟" in Chinese
i18next.t('time.minutes', { count: 2 }); // "2 minutes" in English, "2分钟" in Chinese

The key can be:

The plural forms like one and other are special keys that i18next uses to handle different plural rules:

Some languages have more plural forms. For example, in Russian:

// ru.json
{
  "time.minutes": {
    "one": "{{count}} минута",    // 1
    "few": "{{count}} минуты",    // 2-4
    "many": "{{count}} минут",    // 5-20
    "other": "{{count}} минуты"   // 21, 22, 25-30, etc.
  }
}

The plural rules are based on the CLDR (Common Locale Data Repository) specification, which defines plural rules for different languages. i18next automatically selects the correct form based on the count and the current language's rules.

If your translation files don't support nested structure, you have a simple solution:

minute > 1 ? t("{num} minutes) : t("{num} minute)

But this approach has several problems:

  1. It doesn't work for languages with more than two plural forms (like Russian, Arabic, etc.)
  2. It doesn't handle zero correctly in many languages
  3. It's not maintainable - you need to write this logic everywhere you need plural forms
  4. It doesn't follow the CLDR standards, which means your translations might be incorrect
  5. It makes it harder for translators to work with your translation files

For example, in Russian:

// Wrong approach
minute > 1 ? t("{num} минут") : t("{num} минута")

// This would be wrong for:
// 2-4 minutes (should be "минуты")
// 5-20 minutes (should be "минут")
// 21, 22, 25-30 minutes (should be "минуты")

That's why it's better to use i18next's built-in plural handling:

policy issues

Due to the Turkish government's regulations, we cannot display the strikethrough price on the product page. For example, if you have a product with a original price of 100 TL and a discounted price of 80 TL, you cannot display it as 100 TL → 80 TL. You need to display it as 80 TL.

<!-- this is not allowed in Turkey -->
<span class="current-price">80</span>
<del>
  <span class="original-price">100</span>
  <span class="currency"></span>
</del>
how to create image carouselnextjs intercepting routes