Closed ghost closed 4 years ago
Interesting idea - I'll look into it. It's not as straight forward as you might think since the underlying data is actually a series of templates. For example {0} meter
and {0} meters
for English singular and plural. And if it has an SI prefix its actually two templates that have to be merged: milli {0}
and {0} meter
. Its even more complicated when it's a compound unit like cubic milliampere light year
.
A solution may have to be as editing out the numeric value. I'll think on this today.
I'm a little bit curious - what's the use case you're looking to solve?
A solution may have to be as editing out the numeric value. I'll think on this today.
That's roughly what I'm doing right now, it's probably missing some edge-cases but seems to work for de
and en
locales for the time being:
case App.Cldr.Unit.to_string(1, unit: unit) do
{:ok, "1" <> unit} -> String.trim(unit)
_other -> nil
end
I'm a little bit curious - what's the use case you're looking to solve?
I'm using units in table headers like TEMPERATURE (DEGREE CELSIUS)
or ENERGY (KILOWATT HOUR)
or CO2 (PART PER MILLION)
. And I also have a place in the app where I want to style the unit and the numeric value differently so I'm splitting them there as well (not sure if it is the right approach though):
<span class="big bright"><%= value %></span> <!-- 30 -->
<span class="small dimmed"><%= unit %></span> <!-- °C -->
Ahhh, make sense, good use case. What you actually have as headings there isn't the unit though - its the unit category ie Temperature
. I can certainly derived the unit category but I'm not sure there are translations for these in CLDR (I will check).
Would something like this work for you? I think this can be produced reasonably easily (will experiment on the weekend)
Temperature | Energy |
---|---|
23°C | 23h⋅kW |
23°F | 43h⋅kW |
This short form of output comes from Cldr.Unit.to_string unit, style: :narrow
NB: For complex units the formatting can be improved and I'm working on it.
Would something like this work for you?
Oh, I didn't think of moving the unit into the table cells instead of the header. Yes, that would totally work.
Cool, I think that gives me a chance. Even if you have to use Gettext
for translating the headings at least the units can work.
So basically my work this weekend is to find a better way to format complex units like kilowatt hours
.
Anything else that would help this case?
I will also be working on an Ecto
data type to store units with their unit types in Postgres this weekend. Don't know if thats helpful to you or not.
Even if you have to use Gettext for translating the headings at least the units can work.
Sorry, forgot to mention, yes, I'm translating the unit categories via gettext, and only use Cldr to get the units.
Anything else that would help this case?
Not directly related, but maybe having a way to get the "splitted" unit would help with my second use-case where I want to style the value and the unit differently:
{:ok, {value, unit}} = App.Cldr.Unit.to_string(value, unit: unit, split: true)
so that then I can put them in separate <span>
tags.
Interesting challenge - I'll see what I can do :-)
I've push a couple of commits to master. Here's the changelog:
Cldr.Unit.to_iolist/3
and Cldr.Unit.to_iolist!/3
to return the formatted unit as an iolist rather than a string. This allows for formatting the number and the unit name differently. It also allows some efficiency in inserting formatted content into a Phoenix workflow since it handles iolists efficiently.Fix resolving translatable unit names from strings
Fix converting translatable units that have a "per" conversion
Now you can say:
iex> Cldr.Unit.to_iolist Cldr.Unit.new!(:kilowatt_hour, 123), MyApp.Cldr
{:ok, ["123", " kilowatt-hours"]}
Note that there is no guarantee that the number element is first. And there is no guarantee that there are only two elements in the list. But if you are sure of what the shape of the result will be you can:
iex> [number, unit_name] = Cldr.Unit.to_iolist! Cldr.Unit.new!(:kilowatt_hour, 123), MyApp.Cldr
["123", " kilowatt-hours"]
iex> number
"123"
iex> unit_name
" kilowatt-hours"
{:ex_cldr_units, github: "elixir-cldr/cldr_units"}
mix deps.get
And you should be good to go .....
Let me know if everything is ok on your end and I'll plan a release to hex.
@kipcole9 thank you!
Let me know if everything is ok on your end and I'll plan a release to hex.
Sure! I'm sorry I won't be able to test it today, but I will definitely do it tomorrow.
Let me know if everything is ok on your end and I'll plan a release to hex.
@kipcole9 thank you! Works great!
I've published ex_cldr_units version 3.1.0. Was a good exercise and the refactoring helps separate concerns too. Let me know if there is anything that would help you use case?
Closing now, thanks for the collaboration.
👋
Is there a way to get only the unit like
App.Cldr.Unit.to_string(:meter) # => "Meter"
?