question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Localisation capabilities of the RelativeTime plugin are insufficient for fusional languages

See original GitHub issue

What do you think about re-working the current locale definition of the RelativeTime plugin to support fusional languages without grammatical mistakes?

Moment.js has more complicated locale definitions, but it allows grammatically correct localisation for Slavic languages, for example. Your Russian localisation suffers from the second problem below and my Czech localisation from both, which makes the localised expressions look so wrong, that they cannot be used in real-world applications.

Problem

  1. Localisation expressions for future (“after %s”) and past (“before %s”) contain the same rest of the expression. However, they contain different prepositions and thus they may need different declension in the rest of the expression.
  2. There is only one localisation expression for multiple seconds (“%d seconds”), minutes (“%d minutes”) etc. However, different numerals may need different declension of the following noun.

For example, Slavic languages do not use just one noun form for singlular (one second) and one for plural (many seconds). Usually there are different forms after numerals 1, 2-4 and 5+. Additionally, the noun changes according to to the grammatical case, which is needed in the particular expression. The grammatical case depends on the preposition, for example.

Examples of English, German Russian and Czech expressions

Years - Past

 a year ago    vor einem Jahr   в прошлом году   vloni (před rokem)
 2 years ago   vor 2 Jahren     2 года назад     před 2 roky
 5 years ago   vor 5 Jahren     5 лет назад      před 5 lety

Years - Future

 in a year     in einem Jahr   через год      za rok
 in 2 years    in 2 Jahren     через 2 года   za 2 roky
 in 5 years    in 5 Jahren     через 5 лет    za 5 let

Days - Past

 yesterday    gestern          вчера          včera
(a day ago    vor einem Tag)   день назад     před jedním dnem)
 2 days ago   vor 2 Tagen      2 дни назад    před 2 dny
 5 days ago   vor 5 Tagen      5 дней назад   před 5 dny

Days - Future

 tomorrow    morgen         завтра         zítra
(in a day    in einem Tag   через день     za den)
 in 2 days   in 2 Tagen     через 2 дни    za 2 dny
 in 5 days   in 5 Tagen     через 5 дней   za 5 dní

Seconds - Past

 a second ago              vor einer Sekonde      секунду назад            před sekundou
 2 seconds ago             vor 2 Sekonden         2 секунды назад          před 2 sekundami
 5 seconds ago             vor 5 Sekonden         5 секунд назад           před 5 sekundami
 a couple of seconds ago   vor wenigen Sekonden   несколько секунд назад   před pár (několika) sekundami

Seconds - Future

 in a second              in einer Sekonde      через секунду            za sekundu
 in 2 seconds             in 2 Sekonden         через 2 секунды          za 2 sekundy
 in 5 seconds             in 5 Sekonden         через 5 секунд           za 5 sekund
 in a couple of seconds   in wenigen Sekonden   через несколько секунд   za pár (několik) sekund

Solution

  1. Duplicate all expressions for future and past instead of combining them with the two prepositions.
  2. Introduce the third expression with the numeral for many (5). Use the current expressions for one (1) and few (2-4).
const locale = {
  name: 'cs',
  weekdays: 'neděle_pondělí_úterý_středa_čtvrtek_pátek_sobota'.split('_'),
  months: 'leden_únor_březen_duben_květen_červen_červenec_srpen_září_říjen_listopad_prosinec'.split('_'),
  ordinal: n => `${n}.`,
  relativeTime: {
    future: {
      s: 'za několik sekund',
      m: 'za minutu',
      mm: 'za %d minuty',
      mmm: 'za %d minut',
      h: 'za hodinu',
      hh: 'za %d hodiny',
      hhh: 'za %d hodin',
      d: 'zítra',
      dd: 'za %d dny',
      ddd: 'za %d dní',
      M: 'za měsíc',
      MM: 'za %d měsíce',
      MMM: 'za %d měsícú',
      y: 'za rok',
      yy: 'za %d roky',
      yyy: 'za %d let'
    },
    past: {
      s: 'před několika sekundami',
      m: 'před minutou',
      mm: 'před %d minutami',
      mmm: 'před %d minutami',
      h: 'před hodinu',
      hh: 'před %d hodinami',
      hhh: 'před %d hodinami',
      d: 'včera',
      dd: 'před %d dny',
      ddd: 'před %d dny',
      M: 'před měsícem',
      MM: 'před %d měsíci',
      MMM: 'před %d měsíci',
      y: 'vloni',
      yy: 'před %d roky',
      yyy: 'před %d lety'
    }
  }
}

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:8
  • Comments:5 (5 by maintainers)

github_iconTop GitHub Comments

3reactions
prantlfcommented, Oct 14, 2018

My original simplification was not enough. Even the common languages were not covered well with the three plural forms and the single rule for them, as @leovp pointed out.

It would be better to go for the universal solution right away instead of trying something simpler as I did originally. For example, by specifying both the plural rule (a number or a function) and the plural forms as an array of strings, which the plural rule is an index to.

  relativeTime: {
    // Slavic (Slovak, Czech), 3 plural forms for 1, 2-4, 5-
    pluralRule: 8,
    duration: {
      s: 'několik sekund',
      m: 'minuta',
      mm: ['%d minuta', '%d minuty', '%d minut'],
      h: 'hodina',
      hh: ['%d hodina', '%d hodiny', '%d hodin'],
      d: 'den',
      dd: ['%d den', '%d dny', '%d dní'],
      M: 'měsíc',
      MM: ['%d měsíc', '%d měsíce', '%d měsícú'],
      y: 'rok',
      yy: ['%d rok', '%d roky', '%d let']
    },
    future: {
      s: 'za několik sekund',
      m: 'za minutu',
      mm: ['za %d minutu', 'za %d minuty', 'za %d minut'],
      h: 'za hodinu',
      hh: ['za %d hodinu', 'za %d hodiny', 'za %d hodin'],
      d: 'zítra',
      dd: ['za %d den', 'za %d dny', 'za %d dní'],
      M: 'za měsíc',
      MM: ['za %d měsíc', 'za %d měsíce', 'za %d měsícú'],
      y: 'za rok',
      yy: ['za %d rok', 'za %d roky', 'za %d let']
    },
    past: {
      s: 'před několika sekundami',
      m: 'před minutou',
      mm: ['před %d minutou', 'před %d minutami', 'před %d minutami'],
      h: 'před hodinou',
      hh: ['před %d hodinou', 'před %d hodinami', 'před %d hodinami'],
      d: 'včera',
      dd: ['před %d dnem', 'před %d dny', 'před %d dny'],
      M: 'před měsícem',
      MM: ['před %d měsícem', 'před %d měsíci', 'před %d měsíci'],
      y: 'vloni',
      yy: ['před %d rokem', 'před %d roky', 'před %d lety']
    }
  }
  // Plural rule #8
  n => n === 1 ? 0 : n >= 2 && n <= 4 ? 1 : 2

I had to to separate the special singular form from the plural forms. It has usually no number and thus the first plural form (for 1, 21, 31, …) cannot be reused for it.

I updated #304 with this approach.

Eventually, the plural rules should make it out of the relativeTime plugin to the dayjs core utilities. Or may be event out of this module.

1reaction
prantlfcommented, Sep 29, 2018

@limonte, I took care not to break the existing language packs in the suggested fix #304. Czech, Slovak, Russian and Ukrainian language packs are updated. The others are loaded and work as they did before the change. They can be gradually upgraded as the community goes on.

I reused the existing patterns “m” and “mm” for the mnemonic tags “one” and “few”. I added pattern “mmm” for the “many” tag. Tag “zero” is not needed for relative time values. Tag “two” is rare and tag “other” has no common rules. Tags “one”, “few” and “many” hardcoded for 1, 2-4 and 5+ numbers mean a small change and cover many languages. The future step could be implementing the full CLDR rules. See plural rules on CLDR for more information.)

Read more comments on GitHub >

github_iconTop Results From Across the Web

Fusional language - Wikipedia
Fusional languages or inflected languages are a type of synthetic language, distinguished from agglutinative languages by their tendency to use a single ...
Read more >
iamkun/dayjs (Raised $1,326.00) - Issuehunt
Localisation capabilities of the RelativeTime plugin are insufficient for fusional languages. Unfunded#302created byprantlf.
Read more >
Jessica Kantarovich - The University of Chicago
If a language is situated in a multilingual context (which is true of Chukchi, historically and today), it is difficult to demonstrate that...
Read more >
The verb in Nyakyusa - OAPEN Library
ical and structural features with its neighbouring languages, ... become X'; 'to be X') can thus be understood as a result of an...
Read more >
Typology and Historical Linguistics (Chapter 4)
They viewed the fusional type of ancient Indo-Aryan as instantiating the highest ... Indeed, very well-known features of word order in ancient IE...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found