number_to_human_size doesnt work as expected

362 views
Skip to first unread message

vo.x

unread,
Feb 20, 2009, 1:08:14 PM2/20/09
to rails-i18n
Hello everybody!

Why is "number_to_human_size" method dependent on locales and
translations? Why this method doesnt provide always some reasonable
output? Im using 'de_DE' locale for my application, but Im surprised
that this method actually doesnt work out of the box. I have to search
somewhere for locales etc, thats a shame from my point of view,
especially when size units are quite international. Why are you
leaving poor developer in the dark? Why there is not any note in
documentation etc.

There was also attempts of others to provide some default fallback
(http://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/
1448-add-i18n-for-number_to_human_size-storage-units) but it was
denied. I would say that it is mistake to take defaults from yaml
file. Yaml should be used just for override, even if you want to use
default english.

However, here is my proposal for solution:

def number_to_human_size(number, *args)
return nil if number.nil?

options = args.extract_options!
options.symbolize_keys!

defaults = translate_with_default_fallback
(:'number.format', :locale => options[:locale])
human = translate_with_default_fallback
(:'number.human.format', :locale => options[:locale])
defaults = defaults.merge(human)

unless args.empty?
ActiveSupport::Deprecation.warn('number_to_human_size takes
an option hash ' +
'instead of a separate precision argument.', caller)
precision = args[0] || defaults[:precision]
end

precision ||= (options[:precision] || defaults[:precision])
separator ||= (options[:separator] || defaults[:separator])
delimiter ||= (options[:delimiter] || defaults[:delimiter])

storage_units_format = translate_with_default_fallback
(:'number.human.storage_units.format', :locale => options[:locale])

if number.to_i < 1024
unit = translate_with_default_fallback
(:'number.human.storage_units.units.byte', :locale => options
[:locale], :count => number.to_i)
storage_units_format.gsub(/%n/, number.to_i.to_s).gsub(/%u/,
unit)
else
max_exp = STORAGE_UNITS.size - 1
number = Float(number)
exponent = (Math.log(number) / Math.log(1024)).to_i #
Convert to base 1024
exponent = max_exp if exponent > max_exp # we need this to
avoid overflow for the highest unit
number /= 1024 ** exponent

unit_key = STORAGE_UNITS[exponent]
unit = translate_with_default_fallback
(:"number.human.storage_units.units.#{unit_key}", :locale => options
[:locale], :count => number)

begin
escaped_separator = Regexp.escape(separator)
formatted_number = number_with_precision(number,
:precision => precision,
:separator => separator,
:delimiter => delimiter
).sub(/(\d)(#{escaped_separator}[1-9]*)?0+\z/, '\1\2').sub
(/#{escaped_separator}\z/, '')
storage_units_format.gsub(/%n/, formatted_number).gsub(/
%u/, unit)
rescue
number
end
end
end

private

def translate_with_default_fallback(key, options)
options[:raise] = true
begin
I18n.translate(key, options)
rescue
options[:locale] = :en
I18n.translate(key, options)
end
end

I also created Rails ticket http://rails.lighthouseapp.com/projects/8994/tickets/2029
for this issue

Yaroslav Markin

unread,
Feb 21, 2009, 12:59:49 AM2/21/09
to rails...@googlegroups.com
On Fri, Feb 20, 2009 at 9:08 PM, vo.x <v.on...@gmail.com> wrote:

Hello everybody!

Hey.
 

Why is "number_to_human_size" method dependent on locales and
translations? Why this method doesnt provide always some reasonable
output? 
Im using 'de_DE' locale for my application, but Im surprised
that this method actually doesnt work out of the box. I have to search
somewhere for locales etc, thats a shame from my point of view,
especially when size units are quite international.

Unfortunately, size units are not really that international, see:


The "working out of the box" question is related to how locale fallbacks are handled in Rails I18n — you can handle locale exceptions yourself and try to use :en defaults, or maybe use Globalize2 backend with fallback. Rails has no "default" locale to fallback at the moment.

The reason number_to_human_size does not provide default values when no translations present is that most "translated" helpers don't.

Thanks for the ticket, maybe there will be a change about how fallbacks are handled.


--
Yaroslav Markin

Clemens Kofler

unread,
Feb 21, 2009, 5:55:20 AM2/21/09
to rails-i18n
Yaroslav is right here. I think the current practice (I hesitate to
use the term "best practice" here) for translating the framework is to
copy the contents of all yaml into a single locale file and then
translate them according to your needs. If you do that, there will
hardly ever be a need for fallbacks (at least for the framework).
Another option would be to fetch locales from Sven's repository:
http://github.com/svenfuchs/rails-i18n/tree/e5878d3c661e0b9ad364951c96f1f4f39960a2f1/rails/locale
- however, some of the locales aren't 100% up-to-date (e.g. my German
translation is missing exactly these units). I can guarantee you that
any contribution will be much appreciated if you want to add the
missing keys.

- Clemens

On Feb 21, 6:59 am, Yaroslav Markin <yaroslav.mar...@gmail.com> wrote:
> On Fri, Feb 20, 2009 at 9:08 PM, vo.x <v.ondr...@gmail.com> wrote:
>
> > Hello everybody!
>
> Hey.
>
>
>
> > Why is "number_to_human_size" method dependent on locales and
> > translations? Why this method doesnt provide always some reasonable
> > output?
>
> Im using 'de_DE' locale for my application, but Im surprised
>
> > that this method actually doesnt work out of the box. I have to search
> > somewhere for locales etc, thats a shame from my point of view,
> > especially when size units are quite international.
>
> Unfortunately, size units are not really that international, see:
>
> *http://github.com/svenfuchs/rails-i18n/blob/e5878d3c661e0b9ad364951c9...
> *http://github.com/svenfuchs/rails-i18n/blob/e5878d3c661e0b9ad364951c9...

vo.x

unread,
Feb 22, 2009, 3:23:01 PM2/22/09
to rails-i18n


On 21 Ún, 06:59, Yaroslav Markin <yaroslav.mar...@gmail.com> wrote:
> On Fri, Feb 20, 2009 at 9:08 PM, vo.x <v.ondr...@gmail.com> wrote:
>
> > Hello everybody!
>
> Hey.
>
>
>
> > Why is "number_to_human_size" method dependent on locales and
> > translations? Why this method doesnt provide always some reasonable
> > output?
>
> Im using 'de_DE' locale for my application, but Im surprised
>
> > that this method actually doesnt work out of the box. I have to search
> > somewhere for locales etc, thats a shame from my point of view,
> > especially when size units are quite international.
>
> Unfortunately, size units are not really that international, see:
>
> *http://github.com/svenfuchs/rails-i18n/blob/e5878d3c661e0b9ad364951c9...
> *http://github.com/svenfuchs/rails-i18n/blob/e5878d3c661e0b9ad364951c9...
>
> The "working out of the box" question is related to how locale fallbacks are
> handled in Rails I18n — you can handle locale exceptions yourself and try to
> use :en defaults, or maybe use Globalize2 backend with fallback. Rails has
> no "default" locale to fallback at the moment.

I'm using GetText as a backend. Unfortunately, there is no way how to
know if string was translated or not ....

> The reason number_to_human_size does not provide default values when no
> translations present is that most "translated" helpers don't.

Yes, I'm aware that probably also other helpers are affected by this
and I believe that I will have one day problem also with them ;)

> Thanks for the ticket, maybe there will be a change about how fallbacks are
> handled.
>
> --
> Yaroslav Markin


From what I can say, the easiest solution for now would be adjust
documentation, because I never met any note about helpers and their
language dependency. But may by I'm just bad reader.

Vit

Sven Fuchs

unread,
Jul 8, 2009, 6:11:33 PM7/8/09
to rails...@googlegroups.com
I was just checking my tickets on the Rails Lighthouse and found this
one still open.

https://rails.lighthouseapp.com/projects/8994/tickets/2029-number_to_human_size-with-fallback-to-english

Ok, to summarize the issue is: When one sets I18n.locale to something
else than :en and does not provide any translations for the relevant
keys this helper does not work as people expect. The reason is that
Rails I18n was never built to work with locales other than :en out of
the box. Therefor the same thing applies to all the other helpers, too.

There are two ways to fix this on the client side:

1 - include appropriate translation data to your app (e.g. from http://github.com/svenfuchs/rails-i18n/tree/master)
2 - install some plugin that provides locale fallbacks (e.g. from http://github.com/joshmh/globalize2)

I agree we should document this better. Maybe someone could come up
with a list of helpers that depend on translations? And add a patch to
the I18n guide so it makes clear what translations one has to add
(unless it explains that already)?

I guess I'll close the ticket though.

That said there seem to be quite some request for a simple locale
fallback solution. I'd consider including the locale fallbacks from
Globalize2 or some similar solution to the I18n gem as an optional
module that people can include. Are there any other known locale
fallback solutions out there?
Reply all
Reply to author
Forward
0 new messages