jkbrzt / rrule

JavaScript library for working with recurrence rules for calendar dates as defined in the iCalendar RFC and more.
https://jkbrzt.github.io/rrule
Other
3.3k stars 514 forks source link

Documentation for i18n of toText #13

Open Prinzhorn opened 11 years ago

Prinzhorn commented 11 years ago

Please add better documentation about i18n of the toText() method.

  1. What's the meaning of the today parameter?
  2. Which values are passed to gettext?
  3. How do I actually translate stuff? I'm able to change dayNames and monthNames, but that's only part of it.

Thank you for creating this lib!

jkbrzt commented 11 years ago

What's the meaning of the today parameter?

It's not actually used as of now, you can just pass null.

Which values are passed to gettext? How do I actually translate stuff? I'm able to change dayNames and monthNames, but that's only part of it.

The API isn't very nice.

You need to create a language definition with date related stuff. The default English one is here. tokens are only needed for RRule.fromText.

gettext gets the English string (you can see what strings are used here).

A crude example (you need the current master, older versions cached the output of toText):

// Date-related translations
var portuguese = {
    dayNames: [
        "Domingo",
        "Segunda-Feira",
        "Terça-feira",
        "Quarta-feira",
        "Quinta-feira",
        "Sexta-feira",
        "Sábado"
    ],
    monthNames: [
        "Janeiro",
        "Fevereiro",
        // …
    ]
    // `tokens` are only needed for `RRule.fromText`

};

// Strings
var portugueseStrings = {
    'every': 'cada',
    'until': 'até',
    'day': 'dia',
    'days': 'dias',
    'week': 'semana',
    'weeks': 'semanas',
    'on': 'em'
    // …
};

var gettext =  function(id) {
    // Return pt. string, default to english.
    return portugueseStrings[id] || id;
};

var rule = new RRule(RRule.WEEKLY, {
    interval: 5,
    byweekday: [RRule.MO, RRule.FR],
    dtstart: new Date(2012, 1, 1, 10, 30),
    until: new Date(2012, 12, 31)
});

console.log(rule.toText());
// => every 5 weeks on Monday, Friday until January 31, 2013

console.log(rule.toText(null, gettext, portuguese));
// => cada 5 semanas em Segunda-Feira, Sexta-feira até Janeiro 31, 2013

TODO: improve and document the API (perhaps a Language class would be nice).

Prinzhorn commented 11 years ago

The API isn't very nice.

Hm, yeah. There's something missing. Because you can't just translate the words. Depending on the language the order needs to be changed as well, because they have a different grammar. Instead there should be format strings like

singular: 'every week on {{dayNames}}',
plural: 'every {{numWeeks}} weeks on {{dayNames}}'

That's just a rough example. I know that there are a lot edge cases etc. and that it's probably hard to do right.

Prinzhorn commented 11 years ago

Just came across https://github.com/airbnb/polyglot.js , but there are many other solutions for i18n

Some thing that just bit me:

In English it's "every week" and "every month". In German it's "jede Woche" and "jeden Monat". Notice the "n". I can't just translate "every", it won't work.

Similar thing with passing "st" or "rd" to gettext. It doesn't make any sense.

Prinzhorn commented 10 years ago

Any news or plans? Now that I started using DTSTART and UNTIL I can't use the toText method anymore. Before that I was able to hack around the current implementation.

One more thing for the list: Date formats. I want DD.MM.YYYY and not MMMM DD, YYYY.

elecoest commented 10 years ago

I don't understand. In one html file I have this code whith the latests release (2.0).

[code] <!doctype html>

trad tests

[/code] It's doesn't work with the error :

TypeError: is undefined
var defaults =
.clone(RRule.DEFAULT_OPTIONS); in rrule at line 463.

Where I am in wrong ?

sberryman commented 10 years ago

You need another library called underscorejs. I'm on my phone otherwise I would have given you a link.

On Oct 30, 2013, at 11:54 PM, elecoest notifications@github.com wrote:

I don't understand. In one html file I have this code whith the latests release (2.0).

<!doctype html>

trad tests It's doesn't work woth the error :

TypeError: _ is undefined

var defaults = .clone(RRule.DEFAULTOPTIONS); in rrule at line 463.

Where I am in wrong ?

— Reply to this email directly or view it on GitHub.

elecoest commented 10 years ago

ok, i'd placed undesrcore.js in third position... I've place underscore.js in first position. Now i'vva error TypeError: 2 is not an object return result.call(this, func.apply(_, args)); in underscore.js

elecoest commented 10 years ago

Sorry but this way is ak for every body ?

Nobody has this error before ?

Thanks a lot for your help.

creamteam-de commented 5 years ago

What's the meaning of the today parameter?

It's not actually used as of now, you can just pass null.

Which values are passed to gettext? How do I actually translate stuff? I'm able to change dayNames and monthNames, but that's only part of it.

The API isn't very nice.

You need to create a language definition with date related stuff. The default English one is here. tokens are only needed for RRule.fromText.

gettext gets the English string (you can see what strings are used here).

A crude example (you need the current master, older versions cached the output of toText):

// Date-related translations
var portuguese = {
    dayNames: [
        "Domingo",
        "Segunda-Feira",
        "Terça-feira",
        "Quarta-feira",
        "Quinta-feira",
        "Sexta-feira",
        "Sábado"
    ],
    monthNames: [
        "Janeiro",
        "Fevereiro",
        // …
    ]
    // `tokens` are only needed for `RRule.fromText`

};

// Strings
var portugueseStrings = {
    'every': 'cada',
    'until': 'até',
    'day': 'dia',
    'days': 'dias',
    'week': 'semana',
    'weeks': 'semanas',
    'on': 'em'
    // …
};

var gettext =  function(id) {
    // Return pt. string, default to english.
    return portugueseStrings[id] || id;
};

var rule = new RRule(RRule.WEEKLY, {
    interval: 5,
    byweekday: [RRule.MO, RRule.FR],
    dtstart: new Date(2012, 1, 1, 10, 30),
    until: new Date(2012, 12, 31)
});

console.log(rule.toText());
// => every 5 weeks on Monday, Friday until January 31, 2013

console.log(rule.toText(null, gettext, portuguese));
// => cada 5 semanas em Segunda-Feira, Sexta-feira até Janeiro 31, 2013

TODO: improve and document the API (perhaps a Language class would be nice).

Hi, I'm trying to get i18n for german, but I can not find what strings are used in "gettext" since the link is broken. I tried to look on the sources but I could find it anything.

Thanks!

AlexanderKosianchuk commented 5 years ago

What's the meaning of the today parameter?

It's not actually used as of now, you can just pass null.

Which values are passed to gettext? How do I actually translate stuff? I'm able to change dayNames and monthNames, but that's only part of it.

The API isn't very nice. You need to create a language definition with date related stuff. The default English one is here. tokens are only needed for RRule.fromText. gettext gets the English string (you can see what strings are used here). A crude example (you need the current master, older versions cached the output of toText):

// Date-related translations
var portuguese = {
    dayNames: [
        "Domingo",
        "Segunda-Feira",
        "Terça-feira",
        "Quarta-feira",
        "Quinta-feira",
        "Sexta-feira",
        "Sábado"
    ],
    monthNames: [
        "Janeiro",
        "Fevereiro",
        // …
    ]
    // `tokens` are only needed for `RRule.fromText`

};

// Strings
var portugueseStrings = {
    'every': 'cada',
    'until': 'até',
    'day': 'dia',
    'days': 'dias',
    'week': 'semana',
    'weeks': 'semanas',
    'on': 'em'
    // …
};

var gettext =  function(id) {
    // Return pt. string, default to english.
    return portugueseStrings[id] || id;
};

var rule = new RRule(RRule.WEEKLY, {
    interval: 5,
    byweekday: [RRule.MO, RRule.FR],
    dtstart: new Date(2012, 1, 1, 10, 30),
    until: new Date(2012, 12, 31)
});

console.log(rule.toText());
// => every 5 weeks on Monday, Friday until January 31, 2013

console.log(rule.toText(null, gettext, portuguese));
// => cada 5 semanas em Segunda-Feira, Sexta-feira até Janeiro 31, 2013

TODO: improve and document the API (perhaps a Language class would be nice).

Hi, I'm trying to get i18n for german, but I can not find what strings are used in "gettext" since the link is broken. I tried to look on the sources but I could find it anything.

Thanks!

https://github.com/jakubroztocil/rrule/tree/master/src/nlp

ghost commented 5 years ago

Would be nice to have some documentation how to use it. I've translated to german, but it's looks wrong:

const germanStrings = {
    every: 'jedes',
    until: 'bis',
    day: 'Tag',
    days: 'Tage',
    week: 'Woche',
    weeks: 'Wochen',
    on: 'ein',
    in: 'in',
    'on the': 'auf dem',
    for: 'für',
    and: 'und',
    or: 'oder',
    at: 'bei',
    last: 'zuletzt',
    '(~ approximate)': '(~ approximativ)',
    times: 'Zeiten',
    time: 'Zeit',
    minutes: 'Minuten',
    hours: 'Stunden',
    weekdays: 'Wochentage',
    weekday: 'Wochentag',
    months: 'Monate',
    month: 'Monat',
    years: 'Jahre',
    year: 'Jahr'
  };
const RRULE_GERMAN = {
  dayNames: ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'],
  monthNames: [
    'Januar',
    'Februar',
    'März',
    'April',
    'Mai',
    'Juni',
    'Juli',
    'August',
    'September',
    'Oktober',
    'November',
    'Dezember'
  ]
};
const gettext = id => {
    return germanStrings[id] || id;
};

const rruleText = rule.toText(id => {
    gettext(id);
}, RRULE_GERMAN);
ghost commented 4 years ago

Any updates? How to translate text to other language?

gongAll commented 4 years ago

I think the i18n of this library, as of now, is fundamentally flawed. Things like

nth_monthday' => array(
        '1' => 'the 1st',
        '2' => 'the 2nd',
        '3' => 'the 3rd',
        '21' => 'the 21st',
        '22' => 'the 22nd',
        '23' => 'the 23rd',
        '31' => 'the 31st',
        'else' => 'the %{n}th'
    ),

are absolutely necessary for some final user experience usage, in different languages. I'd recommend implementing the logic in this alternative (as mentioned by @wakirin in this post). It would really bring the usage of this library up, since, at this moment, this logic must be done manually, in order to create some usable i18n logic.

UPDATE: after crawling the code, I found a way to do what I wanted, which, for my language, "solved" it. Just for future reference, I'll leave here a list of all the keys you must translate on the getText method you pass on.

 '(~ approximate)'
 'and'
 'at'
 'day'
 'days'
 'every'
 'for'
 'hour'
 'hours'
 'in'
 'last'
 'minutes'
 'month'
 'months'
 'nd'
 'on the'
 'on'
 'or'
 'rd'
 'st'
 'th'
 'the'
 'time'
 'times'
 'until'
 'week'
 'weekday'
 'weekdays'
 'weeks'
 'weeks'
 'year'
 'years'
 'RRule error: Unable to fully convert this rrule to text'
Mistes974 commented 4 years ago

@gongAll Thanks, With your example, I was able to use moment.js and i18n, as below:

export const RRuleToText = ({ strRRule }) => {
  const language = {
    dayNames: moment.weekdays(),
    monthNames: moment.months()
  };

  const getText = id => {
    return i18n.t(`vendor.rrule.${id}`, id);
  };

  const dateFormat = (year, month, day) =>
    moment()
      .date(day)
      .year(year)
      .month(month)
      .format("LL");

  return strRRule
    ? capitalize(
        RRule.fromString(strRRule).toText(getText, language, dateFormat)
      )
    : "";
};
suzumejakku commented 3 years ago

Will there be an update on this matter ? I have to translate into Japanese; the words order is significantly different, so I have no idea how to proceed...

shivakumars commented 3 years ago

I have followed the examples given in the thread, but unfortunately, I'm getting a JS error. Can someone help?

Screenshot 2021-05-07 at 4 57 49 PM

happens when I make a call using below code, console.log(rule.toText(null, gettext, portuguese));

ghost commented 3 years ago

@shivakumars t is related to i18n library (https://www.i18next.com/overview/api#t). You need to use your translation library or remove it.

shivakumars commented 3 years ago

@shivakumars t is related to i18n library (https://www.i18next.com/overview/api#t). You need to use your translation library or remove it.

I tried adding the mentioned library as a dependency, still getting the error. Can you help me with an example, please.

ghost commented 3 years ago
const yourStrings = {every: 'jedes',
    until: 'bis',
    day: 'Tag',
    days: 'Tage',
    week: 'Woche',
    weeks: 'Wochen',
    on: 'ein',
    in: 'in',
    'on the': 'auf dem',
    for: 'für',
    and: 'und',
    or: 'oder',
    at: 'bei',
    last: 'zuletzt',
    '(~ approximate)': '(~ approximativ)',
    times: 'Zeiten',
    time: 'Zeit',
    minutes: 'Minuten',
    hours: 'Stunden',
    weekdays: 'Wochentage',
    weekday: 'Wochentag',
    months: 'Monate',
    month: 'Monat',
    years: 'Jahre',
    year: 'Jahr'
};
export const RRuleToText = ({ strRRule }) => {
  const language = {
    dayNames: moment.weekdays(),
    monthNames: moment.months()
  };

  const getText = id => {
    return yourStrings[id];
  };

  const dateFormat = (year, month, day) =>
    moment()
      .date(day)
      .year(year)
      .month(month)
      .format("LL");

  return strRRule
    ? capitalize(
        RRule.fromString(strRRule).toText(getText, language, dateFormat)
      )
    : "";
};
shivakumars commented 3 years ago
const yourStrings = {every: 'jedes',
    until: 'bis',
    day: 'Tag',
    days: 'Tage',
    week: 'Woche',
    weeks: 'Wochen',
    on: 'ein',
    in: 'in',
    'on the': 'auf dem',
    for: 'für',
    and: 'und',
    or: 'oder',
    at: 'bei',
    last: 'zuletzt',
    '(~ approximate)': '(~ approximativ)',
    times: 'Zeiten',
    time: 'Zeit',
    minutes: 'Minuten',
    hours: 'Stunden',
    weekdays: 'Wochentage',
    weekday: 'Wochentag',
    months: 'Monate',
    month: 'Monat',
    years: 'Jahre',
    year: 'Jahr'
};
export const RRuleToText = ({ strRRule }) => {
  const language = {
    dayNames: moment.weekdays(),
    monthNames: moment.months()
  };

  const getText = id => {
    return yourStrings[id];
  };

  const dateFormat = (year, month, day) =>
    moment()
      .date(day)
      .year(year)
      .month(month)
      .format("LL");

  return strRRule
    ? capitalize(
        RRule.fromString(strRRule).toText(getText, language, dateFormat)
      )
    : "";
};

Thank you 🙏 . This worked.

fishdevClassFunc commented 2 years ago
const yourStrings = {every: 'jedes',
    until: 'bis',
    day: 'Tag',
    days: 'Tage',
    week: 'Woche',
    weeks: 'Wochen',
    on: 'ein',
    in: 'in',
    'on the': 'auf dem',
    for: 'für',
    and: 'und',
    or: 'oder',
    at: 'bei',
    last: 'zuletzt',
    '(~ approximate)': '(~ approximativ)',
    times: 'Zeiten',
    time: 'Zeit',
    minutes: 'Minuten',
    hours: 'Stunden',
    weekdays: 'Wochentage',
    weekday: 'Wochentag',
    months: 'Monate',
    month: 'Monat',
    years: 'Jahre',
    year: 'Jahr'
};
export const RRuleToText = ({ strRRule }) => {
  const language = {
    dayNames: moment.weekdays(),
    monthNames: moment.months()
  };

  const getText = id => {
    return yourStrings[id];
  };

  const dateFormat = (year, month, day) =>
    moment()
      .date(day)
      .year(year)
      .month(month)
      .format("LL");

  return strRRule
    ? capitalize(
        RRule.fromString(strRRule).toText(getText, language, dateFormat)
      )
    : "";
};

How to setup this?

cleverfleet commented 2 years ago
const strings = {
  every: 'alle',
  until: 'endet am',
  day: 'Tag',
  days: 'Tage',
  week: 'Wochen',
  weeks: 'Wochen',
  on: 'am',
  in: 'in',
  'on the': 'am',
  for: 'für',
  and: 'und',
  or: 'oder',
  at: 'bei',
  last: 'zuletzt',
  st: '.,',
  nd: '.,',
  rd: '.,',
  th: '.,',
  '(~ approximate)': '(~ ungefähr)',
  times: 'Zeiten',
  time: 'Zeit',
  minutes: 'Minuten',
  hours: 'Stunden',
  weekdays: 'Wochentag',
  weekday: 'Wochentag',
  months: 'Monate',
  month: 'Monate',
  years: 'Jahre',
  year: 'Jahre'
}
export default {
  getText: (id) => strings[id] || id,
  language: {
    dayNames: [
      'Sonntag',
      'Montag',
      'Dienstag',
      'Mittwoch',
      'Donnerstag',
      'Freitag',
      'Samstag'
    ],
    monthNames: [
      'Januar',
      'Februar',
      'März',
      'April',
      'Mai',
      'Juni',
      'Juli',
      'August',
      'September',
      'Oktober',
      'November',
      'Dezember'
    ]
  },
  dateFormat: (year, month, day) => `${day}. ${month} ${year}`
}

// rule.toText(getText, language, dateFormat)

I think these could be better translation options.

I have not tested every possibility as only use daily weekly or yearly stuff. Also noted that things like "every third monday every month ..." is no included at all yet?

marcosandri-dev commented 2 years ago
const yourStrings = {every: 'jedes',
    until: 'bis',
    day: 'Tag',
    days: 'Tage',
    week: 'Woche',
    weeks: 'Wochen',
    on: 'ein',
    in: 'in',
    'on the': 'auf dem',
    for: 'für',
    and: 'und',
    or: 'oder',
    at: 'bei',
    last: 'zuletzt',
    '(~ approximate)': '(~ approximativ)',
    times: 'Zeiten',
    time: 'Zeit',
    minutes: 'Minuten',
    hours: 'Stunden',
    weekdays: 'Wochentage',
    weekday: 'Wochentag',
    months: 'Monate',
    month: 'Monat',
    years: 'Jahre',
    year: 'Jahr'
};
export const RRuleToText = ({ strRRule }) => {
  const language = {
    dayNames: moment.weekdays(),
    monthNames: moment.months()
  };

  const getText = id => {
    return yourStrings[id];
  };

  const dateFormat = (year, month, day) =>
    moment()
      .date(day)
      .year(year)
      .month(month)
      .format("LL");

  return strRRule
    ? capitalize(
        RRule.fromString(strRRule).toText(getText, language, dateFormat)
      )
    : "";
};

Works like magic. For whoever asking, the strRRule is the rule you have created with new Rule, rule.toString(). You can also use dayjs bu adding the LocaleData plugin. Also, if you get an error for the tokens you can pass an empty object: {} or you can find them here: https://github.com/jakubroztocil/rrule/blob/master/src/nlp/i18n.ts

ShacharRatzabi commented 2 years ago

@sberryman @jakubroztocil @Prinzhorn @shivakumars @elecoest did you find any solution for this?

I'm using rrule.toText() to get a human text of a frequency, and I need to support multiple languages

scriptify commented 1 year ago

So the behavior indeed seems a bit odd. I tried copying the dictionary from the i18n.ts file and replicating it in different languages, then passing it to the toText method as the second parameter.

So while the week/month names get correctly translated, the rest doesn't.

The oddity, IMO, starts with the getText function which can be passed as the first parameter.

This function returns translations for different parts of the stringified RRule, e.g. "every" or "for".

The default implementation of this function solely returns id.toString(), while id is the default English word of the expression.

So it turns out, the library itself doesn't even seem to make use of the Regular Expressions inside language.tokens.

To make it work correctly, I created a custom getText implementation which returns the translated version of the id.

So theoretically, we could just translate each ID to our desired language.

So a possible solution would be:

import { RRule } from 'rrule';

interface Language {
  dayNames: string[];
  monthNames: string[];
  tokens: {
    [k: string]: RegExp;
  };
  getTextDict: { [k: string]: string }
}

const GERMAN: Language = {
  dayNames: ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'],
  monthNames: [
    'Januar',
    'Februar',
    'März',
    'April',
    'Mai',
    'Juni',
    'Juli',
    'August',
    'September',
    'Oktober',
    'November',
    'Dezember',
  ],
  tokens: {
    ...
  },
 getTextDict: {
    th: '.',
    every: 'alle',
    days: 'tage',
    weekdays: 'werktage',
    weeks: 'wochen',
    hours: 'stunden',
    minutes: 'minuten',
    months: 'monate',
    years: 'jahre',
    day: 'tag',
    weekday: 'werktag',
    week: 'woche',
    hour: 'stunde',
    minute: 'minute',
    month: 'monat',
    year: 'jahr',
    on: 'am',
    'on the': 'am',
    at: 'um',
    the: 'der',
    first: 'erste',
    second: 'zweite',
    third: 'dritte',
    last: 'letzter',
    for: 'für',
    time: 'mal',
    times: 'mal',
    until: 'bis',
  }
};

export function stringifyRepetition(
  rrule: RRuleConfig,
  language: 'en'  | 'de'
) {
  const rrule = new RRule(rrule);

  if (language === 'en') {
    return rrule.toText();
  }

  const langStrings = GERMAN;

  const getText = (id: any) => {
    return langStrings.tokens[id] || id.toString();
  };

  return rrule.toText(getText, langStrings);
}

Unfortunately, this approach doesn't work well with e.g. German, as words cannot be just replaced with their german equivalent.

The tokens prop of the language objects is quite confusing. This object is not used to stringify values, but to parse strings into RRules.

So I fear the only viable solution is to roll your own implementation. Or did I miss anything?

PierrickP commented 5 months ago

I'm going to add a coin to this issue.

I needed to translate the result of toText(). As other people have pointed out, you can't just translate words individually. Passing a function to toText() would give an imperfect result.

My needs were limited. I've limited myself to freq / until / count / interval options. byweekday / bymonth seem accessible.

I preferred to rely on a true i18n lib, intl-messageformat (which is used in the highest-level lib I use, svelte-i18n). The important thing is that it's based on a standardized format, icu messages (https://unicode-org.github.io/icu/userguide/format_parse/messages/).

I made a small function to correctly pass values (directly based on an instance of RRule)

// $format is the svelte-i18n method to get translation
// $date same for date

export function humanizeRRule(rule) {
  return $format(`humanized rrule`, {
    values: {
      freq: freqEnum[rule.options.freq],
      localizedFreq: $format(freqEnum[rule.options.freq], {
        values: { interval: rule.options.interval },
      }),
      count: $format("{count}", { values: { count: rule.options.count || 0 } }),
      until:
        rule.options.until && $date(rule.options.until, { dateStyle: "long" }),
    },
  });
}

freq is pass as key and translation, count and util as translations

And most important is the translation keys. :warning: It's not prefect, i'm not fluent in any languages.

In English

{
  "humanized rrule": "{freq, select, other {every} } {localizedFreq}{count}{until, select, null {} false {} other { until {until}}}",
  "{count}": "{count, plural, =0 {} =1 { 1 time} other { # times}}",
  "YEARLY": "{interval, plural, =1 {year} other {# years}}",
  "MONTHLY": "{interval, plural, =1 {month} other {# months}}",
  "WEEKLY": "{interval, plural, =1 {week} other {# weeks}}",
  "DAILY": "{interval, plural, =1 {day} other {# days}}",
  "HOURLY": "{interval, plural, =1 {hour} other {# hours}}",
  "MINUTELY": "{interval, plural, =1 {minute} other {# minutes}}",
  "SECONDLY": "{interval, plural, =1 {second} other {# seconds}}"
}

image

French

{
  "humanized rrule": "{freq, select, YEARLY {tous les} MONTHLY {tous les} WEEKLY {toutes les} DAILY {tous les} HOURLY {toutes les} MINUTELY {toutes les} SECONDLY {toutes les} other {} } {localizedFreq}{count}{until, select, null {} false {} other {, jusqu'au {until}}}",
  "{count}": "{count, plural, =0 {} =1 {, 1 fois} other {, # fois}}",
  "YEARLY": "{interval, plural, =1 {ans} other {# ans}}",
  "MONTHLY": "{interval, plural, =1 {mois} other {# mois}}",
  "WEEKLY": "{interval, plural, =1 {semaines} other {# semaines}}",
  "DAILY": "{interval, plural, =1 {jours} other {# jours}}",
  "HOURLY": "{interval, plural, =1 {heures} other {# heures}}",
  "MINUTELY": "{interval, plural, =1 {minutes} other {# minutes}}",
  "SECONDLY": "{interval, plural, =1 {secondes} other {# secondes}}"
}

image

And more exotic, Chinese

(mix between Arabic and Chinese number. It can certainly be improved)

{
  "humanized rrule": "{freq, select, other {每} }{localizedFreq}{count}{until, select, null {} false {} other {直到{until}}}",
  "{count}": "{count, plural, =0 {} =1 {1次} other {一共#次}}",
  "YEARLY": "{interval, plural, =1 {年} other {#年一次}}",
  "MONTHLY": "{interval, plural, =1 {月} other {#月一次}}",
  "WEEKLY": "{interval, plural, =1 {周} other {#周一次}}",
  "DAILY": "{interval, plural, =1 {天} other {#天一次}}",
  "HOURLY": "{interval, plural, =1 {小时} other {#小时一次}}",
  "MINUTELY": "{interval, plural, =1 {分钟} other {#分钟一次}}",
  "SECONDLY": "{interval, plural, =1 {秒} other {#秒一次}}"
}

image

I'm pretty sure we can adapt it to german or other language and continue to implement others options.

dBianchii commented 5 months ago

I need this as well...