i18n icon indicating copy to clipboard operation
i18n copied to clipboard

ICU support

Open sandstrom opened this issue 4 months ago • 3 comments

Following up on this one.

We're running into some limitations with the current pluralization handling in this gem. In short, it's hard to do strings with multiple plural words.

Would you be open to me exploring/suggestion what a hook that could integrate with an external message format library (e.g. https://github.com/format-message/message-format-rb) could look like?

I'd try to come up with something minimal. Hook would be in library, the rest would be 'user space' (not inside this gem).

You 
  {reportCount, plural,
    =0 {have no projects}
    one {have # project}
    other {have # projects}
  }
  pending approval and 
  {unreadCount, plural,
    =0 {have no unread notifications}
    one {have # unread notifications}
    other {have # unread notifications}
  }
today.

Related: https://github.com/ruby-i18n/i18n/issues/522

sandstrom avatar Oct 07 '25 12:10 sandstrom

I’d support this effort! I’ve ran into the same problem myself previously.

radar avatar Oct 07 '25 19:10 radar

Alright, I'll have a look and get back to you with a suggestion!

sandstrom avatar Oct 08 '25 11:10 sandstrom

The recommended way of extending the backend per the wiki seems to be this pattern:

module I18n::Backend::IcuPluralization
  def translate(locale, key, options = {})
    # need to put in the magic option `:count` into options,
    # to trigger the pluralization logic (otherwise pluralize isn't called)
    value = lookup(locale, key, options[:scope], options)
    options[:count] = 999 if icu_format_detected?(value)
    super
  end

  def pluralize(locale, entry, count)
    # call custom pluralization logic
  end
end

I18n::Backend::Simple.send(:include, I18n::Backend::IcuPluralization)

I haven't tested yet myself, but I think there may be sufficient facilities in this lib to support this.


Having looked through the code a bit, it's pretty complicated and I think a larger refactor could simplify things.

I guess the first step might be to draw up a list of functionality that should be deprecated.

Some thoughts:

  • The current backend structure (it's very confusing). In my mind, backends are where translations are stored, and shouldn't be concerned with caching, cascade lookups, memoization, chaining, fallbacks or many other things. Not saying all this behavior should go, but e.g. 'fallback to english' should be a few lines lines of code, not a full backend.
    • We could probably reduce the backends to 2-3 (YAML, gettext and something else).
  • Break out trivial things that could live in user-land, for example cascade lookup logic (just catch the missing translation exception, modify key and redo)
  • Current pluralization config is very confusing (https://guides.rubyonrails.org/i18n.html#locale-specific-rules).

Should I open a separate issue where we can track suggestions on things to deprecate? Or does that not seem like a relevant thing to do?

sandstrom avatar Nov 04 '25 13:11 sandstrom