{"id":28430985,"url":"https://github.com/elixir-cldr/cldr_units","last_synced_at":"2026-05-09T01:15:03.629Z","repository":{"id":24151410,"uuid":"100649989","full_name":"elixir-cldr/cldr_units","owner":"elixir-cldr","description":"Unit formatting (volume, area, length, ...) functions for the Common Locale Data Repository (CLDR)","archived":false,"fork":false,"pushed_at":"2026-03-17T21:19:25.000Z","size":1349,"stargazers_count":18,"open_issues_count":2,"forks_count":15,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-04-03T08:29:24.967Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/elixir-cldr.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2017-08-17T22:26:29.000Z","updated_at":"2026-03-17T21:19:25.000Z","dependencies_parsed_at":"2022-08-07T11:00:55.876Z","dependency_job_id":"e2b6a540-27a7-4215-bbb1-24f7654d100e","html_url":"https://github.com/elixir-cldr/cldr_units","commit_stats":{"total_commits":406,"total_committers":6,"mean_commits":67.66666666666667,"dds":"0.022167487684729092","last_synced_commit":"429e9055f49d72dbcdfc8bdef64003b38c317308"},"previous_names":[],"tags_count":88,"template":false,"template_full_name":null,"purl":"pkg:github/elixir-cldr/cldr_units","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elixir-cldr%2Fcldr_units","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elixir-cldr%2Fcldr_units/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elixir-cldr%2Fcldr_units/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elixir-cldr%2Fcldr_units/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/elixir-cldr","download_url":"https://codeload.github.com/elixir-cldr/cldr_units/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elixir-cldr%2Fcldr_units/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32803677,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-08T08:22:46.396Z","status":"ssl_error","status_checked_at":"2026-05-08T08:22:45.650Z","response_time":54,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-06-05T14:30:44.866Z","updated_at":"2026-05-09T01:15:03.594Z","avatar_url":"https://github.com/elixir-cldr.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Cldr for Units\n\n[![Hex.pm](https://img.shields.io/hexpm/v/ex_cldr_units.svg)](https://hex.pm/packages/ex_cldr_units)\n[![Hex.pm](https://img.shields.io/hexpm/dw/ex_cldr_units.svg?)](https://hex.pm/packages/ex_cldr_units)\n[![Hex.pm](https://img.shields.io/hexpm/l/ex_cldr_units.svg)](https://hex.pm/packages/ex_cldr_units)\n\n## Installation\n\nNote that `:ex_cldr_units` requires Elixir 1.6 or later.\n\nAdd `ex_cldr_units` as a dependency to your `mix` project:\n\n    defp deps do\n      [\n        {:ex_cldr_units, \"~\u003e 3.0\"}\n      ]\n    end\n\nthen retrieve `ex_cldr_units` from [hex](https://hex.pm/packages/ex_cldr_units):\n\n    mix deps.get\n    mix deps.compile\n\nDocumentation can be found at [https://hexdocs.pm/ex_cldr_units](https://hexdocs.pm/ex_cldr_units).\n\n## Getting Started\n\n`ex_cldr_units` is an add-on library for [ex_cldr](https://hex.pm/packages/ex_cldr) that provides localisation and formatting for units such as weights, lengths, areas, volumes and so on. It also provides unit conversion and simple arithmetic for compatible units.\n\n### Configuration\n\nFrom [ex_cldr](https://hex.pm/packages/ex_cldr) version 2.0, a backend module must be defined into which the public API and the [CLDR](https://cldr.unicode.org) data is compiled.  See the [ex_cldr documentation](https://hexdocs.pm/ex_cldr/readme.html) for further information on configuration.\n\nIn the following examples we assume the presence of a module called `MyApp.Cldr` defined as:\n```elixir\ndefmodule MyApp.Cldr do\n  use Cldr,\n    locales: [\"en\", \"fr\"],\n    default_locale: \"en\",\n    providers: [Cldr.Number, Cldr.Unit, Cldr.List]\nend\n```\n\n### Supporting the String.Chars protocol\n\nThe `String.Chars` protocol underpins `Kernel.to_string/1` and is also used in string interpolation such as `#{my_unit}`.  In order for this to be supported by `Cldr.Unit`, a default backend module must be configured in `config.exs`.  For example:\n```\nconfig :ex_cldr_units,\n  default_backend: MyApp.Cldr\n```\n\n## Public API\n\nThe primary api is defined by three functions:\n\n* `MyApp.Cldr.Unit.to_string/2` for formatting units\n\n* `MyApp.Cldr.Unit.new/2` to create a new `Unit.t` struct that encapsulated a unit and a value that can be used for arithmetic, comparison and conversion\n\n* `MyApp.Cldr.Unit.convert/2` to convert one compatible unit to another\n\n* `MyApp.Cldr.Unit.localize/3` to localize a unit by converting it to units customary for a given territory\n\n### Creating a new unit\n\nA `Cldr.Unit.t()` struct is created with the `Cldr.Unit.new/2` function. The two parameters are a unit name and a number (expressed as a `float`, `integer`, `Decimal` or `Ratio`) in either order.\n\nNaming units is quite flexible combining:\n\n* One or more base unit names. These are the names returned from `Cldr.Unit.known_units/0`\n\n* An optional SI prefix (from `yokto` to `yotta`)\n\n* An optional power prefix of `square` or `cubic`\n\nNames can be expressed as strings with any of `-`, `_` or ` ` as separators between words.\n\nSome examples:\n\n```elixir\niex\u003e Cldr.Unit.new :meter, 1\n{:ok, #Cldr.Unit\u003c:meter, 1\u003e}\n\niex\u003e Cldr.Unit.new \"square meter\", 1\n{:ok, #Cldr.Unit\u003c:square_meter, 1\u003e}\n\niex\u003e Cldr.Unit.new \"square liter\", 1\n{:ok, #Cldr.Unit\u003c\"square_liter\", 1\u003e}\n\niex\u003e Cldr.Unit.new \"square yottaliter\", 1\n{:ok, #Cldr.Unit\u003c\"square_yottaliter\", 1\u003e}\n\niex\u003e Cldr.Unit.new \"cubic light year\", 1\n{:ok, #Cldr.Unit\u003c\"cubic_light_year\", 1\u003e}\n\niex\u003e Cldr.Unit.new \"squre meter\", 1\n{:error,\n {Cldr.UnknownUnitError, \"Unknown unit was detected at \\\"squre_meter\\\"\"}}\n```\n\nYou will note that the unit make not make logical sense (`cubic light-year`?) but they do make mathematical sense.\n\nUnits can also be described as the product of one or more base units. For example:\n\n```elixir\niex\u003e Cldr.Unit.new \"liter ampere\", 1\n{:ok, #Cldr.Unit\u003c\"ampere_liter\", 1\u003e}\n\niex\u003e Cldr.Unit.new \"mile lux\", 1\n{:ok, #Cldr.Unit\u003c\"mile_lux\", 1\u003e}\n```\n\nAgain, this may not have a logical meaning but they do have an arithmetic meaning and they can be formatted as strings:\n\n```elixir\niex\u003e Cldr.Unit.new!(\"liter ampere\", 1) |\u003e Cldr.Unit.to_string\n{:ok, \"1 ampere⋅litre\"}\n\niex\u003e Cldr.Unit.new!(\"mile lux\", 3) |\u003e Cldr.Unit.to_string\n{:ok, \"3 miles⋅lux\"}\n```\n\nLastly, there are units formed by division where are called \"per\" units. For example:\n\n```elixir\niex\u003e Cldr.Unit.new \"mile per hour\", 1\n{:ok, #Cldr.Unit\u003c:mile_per_hour, 1\u003e}\n\niex\u003e Cldr.Unit.new \"liter per second\", 1\n{:ok, #Cldr.Unit\u003c\"liter_per_second\", 1\u003e}\n\niex\u003e Cldr.Unit.new \"cubic gigalux per inch\", 1\n{:ok, #Cldr.Unit\u003c\"cubic_gigalux_per_inch\", 1\u003e}\n```\n\n### Unit formatting and localization\n\n`MyApp.Cldr.Unit.to_string/2` provides localized unit formatting. It supports two arguments:\n\n  * `number` is any number (integer, float or Decimal) or a `Unit.t` struct returned by `Cldr.Unit.new/2`\n\n  * `options` which are:\n\n    * `:unit` is any unit returned by `Cldr.Unit.known_units/0`.  This option is required unless a `Unit.t` is passed as the first argument.\n\n    * `:locale` is any configured locale. See `Cldr.known_locale_names/0`. The default\n      is `locale: Cldr.get_current_locale()`\n\n    * `:style` is one of those returned by `Cldr.Unit.known_styles/0`.\n      The current styles are `:long`, `:short` and `:narrow`.  The default is `style: :long`\n\n    * Any other options are passed to `Cldr.Number.to_string/2` which is used to format the `number`\n\n```elixir\niex\u003e MyApp.Cldr.Unit.to_string 123, unit: :gallon\n{:ok, \"123 gallons\"}\n\niex\u003e MyApp.Cldr.Unit.to_string 1234, unit: :gallon, format: :long\n{:ok, \"1 thousand gallons\"}\n\niex\u003e MyApp.Cldr.Unit.to_string 1234, unit: :gallon, format: :short\n{:ok, \"1K gallons\"}\n\niex\u003e MyApp.Cldr.Unit.to_string 1234, unit: :megahertz\n{:ok, \"1,234 megahertz\"}\n\niex\u003e MyApp.Cldr.Unit.to_string 1234, unit: :foot, locale: \"fr\"\n{:ok, \"1 234 pieds\"}\n\niex\u003e MyApp.Cldr.Unit.to_string Cldr.Unit.new(:ampere, 42), locale: \"fr\"\n{:ok, \"42 ampères\"}\n\niex\u003e Cldr.Unit.to_string 1234, MyApp.Cldr, unit: \"foot_per_second\", style: :narrow, per: :second\n{:ok, \"1,234′/s\"}\n\niex\u003e Cldr.Unit.to_string 1234, MyApp.Cldr, unit: \"foot_per_second\"\n{:ok, \"1,234 feet per second\"}\n\n```\n### Unit decomposition\n\nSometimes its a requirement to decompose a unit into one or more subunits.  For example, if someone is 6.3 feet height we would normally say \"6 feet, 4 inches\".  This can be achieved with `Cldr.Unit.decompose/2`. Using our example:\n\n```elixir\niex\u003e height = Cldr.Unit.new(:foot, 6.3)\n#Cldr.Unit\u003c:foot, 6.3\u003e\niex(2)\u003e Cldr.Unit.decompose height, [:foot, :inch]\n[#Cldr.Unit\u003c:foot, 6.0\u003e, #Cldr.Unit\u003c:inch, 4.0\u003e]\n```\n\nA localised string representing this decomposition can also be produced.  `Cldr.Unit.to_string/3` will process a unit list, using the function `Cldr.List.to_string/2` to perform the list combination.  Again using the example:\n\n```elixir\niex\u003e c = Cldr.Unit.decompose height, [:foot, :inch]\n[#Cldr.Unit\u003c:foot, 6.0\u003e, #Cldr.Unit\u003c:inch, 4.0\u003e]\n\niex\u003e Cldr.Unit.to_string c, MyApp.Cldr\n\"6 feet and 4 inches\"\n\niex\u003e Cldr.Unit.to_string c, MyApp.Cldr, list_options: [format: :unit_short]\n\"6 feet, 4 inches\"\n# And of course full localisation is supported\niex\u003e Cldr.Unit.to_string c, MyApp.Cldr, locale: \"fr\"\n\"6 pieds et 4 pouces\"\n```\n\n### Converting Units\n\n`t:Unit` structs can be converted to other compatible units.  For example, `feet` can be converted to `meters` since they are both of the `length` unit type.\n\n```elixir\n# Test for unit compatibility\niex\u003e Cldr.Unit.compatible? :foot, :meter\ntrue\niex\u003e Cldr.Unit.compatible? :foot, :liter\nfalse\n\n# Convert a unit\niex\u003e Cldr.Unit.convert Cldr.Unit.new!(:foot, 3), :meter\n{:ok, #Cldr.Unit\u003c:meter, 16472365997070327 \u003c|\u003e 18014398509481984\u003e}\n\n```\n\n### Localising units for a given locale or territory\n\nDifferent locales or territories use different measurement systems and sometimes different measurement scales that also vary based upon usage. For example, in the US a person's height is considered in `inches` up to a certain point and `feet and inches` after that. For distances when driving, the length is considered in `yards` for certain distances and `miles` after that. For most other countries the same quantity would be expressed in `centimeters` or `meters` or `kilometers`.\n\n`ex_cldr_units` makes it easy to take a unit and convert it to the units appropriate for a given locale and usage.\n\nConsider this example:\n\n```elixir\niex\u003e height = Cldr.Unit.new!(1.81, :meter)\n#Cldr.Unit\u003c:meter, 1.81\u003e\n\niex\u003e us_height = Cldr.Unit.localize height, usage: :person_height, territory: :US\n[#Cldr.Unit\u003c:foot, 5\u003e,\n #Cldr.Unit\u003c:inch, 1545635392113553812 \u003c|\u003e 137269716642252725\u003e]\n\niex\u003e Cldr.Unit.to_string us_height\n{:ok, \"5 feet and 11.26 inches\"}\n```\n\nNote that conversion is dependent on context. The context above is `:person_height` reflecting that we are referring to the height of a person. For units of `length` category, the other contexts available are `:rainfall`, `:snowfall`, `:vehicle`, `:visibility` and `:road`. Using the above example with the context of `:rainfall` we see\n\n```elixir\niex\u003e length = Cldr.Unit.localize height, usage: :rainfall, territory: :US\n[#Cldr.Unit\u003c:inch, 9781818390648717312 \u003c|\u003e 137269716642252725\u003e]\n\niex\u003e Cldr.Unit.to_string length\n{:ok, \"71.26 inches\"}\n```\n\nSee `Cldr.Unit.preferred_units/3` to see what mappings are available, in particular what context usage is supported for conversion.\n\n### Unit arithmetic\n\nBasic arithmetic is provided by `Cldr.Unit.add/2`, `Cldr.Unit.sub/2`, `Cldr.Unit.trunc/1` and  `Cldr.Unit.round/3`.\n\n```elixir\niex\u003e Cldr.Unit.Math.add(Cldr.Unit.new!(:foot, 1), Cldr.Unit.new!(:foot, 1))\n#Cldr.Unit\u003c:foot, 2\u003e\n\niex\u003e Cldr.Unit.Math.add(Cldr.Unit.new!(:foot, 1), Cldr.Unit.new!(:mile, 1))\n#Cldr.Unit\u003c:foot, 5280.945925937846\u003e\n\niex\u003e Cldr.Unit.Math.add(Cldr.Unit.new!(:foot, 1), Cldr.Unit.new!(:gallon, 1))\n{:error, {Cldr.Unit.IncompatibleUnitError,\n \"Operations can only be performed between units of the same type. Received #Cldr.Unit\u003c:foot, 1\u003e and #Cldr.Unit\u003c:gallon, 1\u003e\"}}\n\niex\u003e Cldr.Unit.round(Cldr.Unit.new!(:yard, 1031.61), 1)\n#Cldr.Unit\u003c:yard, 1031.6\u003e\n\niex\u003e Cldr.Unit.round(Cldr.Unit.new!(:yard, 1031.61), 1, :up)\n#Cldr.Unit\u003c:yard, 1031.7\u003e\n\n```\n\n### Available units\n\nAvailable units are returned by `Cldr.Unit.known_units/0`.\n\n```elixir\niex\u003e Cldr.Unit.known_units\n[:acre, :acre_foot, :ampere, :arc_minute, :arc_second, :astronomical_unit, :bit,\n :bushel, :byte, :calorie, :carat, :celsius, :centiliter, :centimeter, :century,\n :cubic_centimeter, :cubic_foot, :cubic_inch, :cubic_kilometer, :cubic_meter,\n :cubic_mile, :cubic_yard, :cup, :cup_metric, :day, :deciliter, :decimeter,\n :degree, :fahrenheit, :fathom, :fluid_ounce, :foodcalorie, :foot, :furlong,\n :g_force, :gallon, :gallon_imperial, :generic, :gigabit, :gigabyte, :gigahertz,\n :gigawatt, :gram, :hectare, :hectoliter, :hectopascal, :hertz, :horsepower,\n :hour, :inch, ...]\n```\n\n### Unit categories\n\nUnits are grouped by unit category which defines the convertibility of different types.  In general, units of the same category are convertible to each other. The function `Cldr.Unit.known_unit_categories/0` returns the unit categories.\n\n```elixir\niex\u003e Cldr.Unit.known_unit_categories\n[:acceleration, :angle, :area, :concentr, :consumption, :coordinate, :digital,\n :duration, :electric, :energy, :frequency, :length, :light, :mass, :power,\n :pressure, :speed, :temperature, :volume]\n```\n\nSee also `Cldr.Unit.known_units_by_category/0` and `Cldr.Unit.known_units_for_category/1`.\n\n### Measurement systems\n\nUnits generally fall into one of three measurement systems in use around the world. In CLDR these are known as `:metric`, `:ussystem` and `:uksystem`. The following functions allow identifying measurement systems for units, territories and locales.\n\n* The measurement systems are returned with `Cldr.Unit.known_measurement_systems/0`.\n\n* The measurement systems for a given unit are returned by `Cldr.Unit.measurement_systems_for_unit/1`.\n\n* A boolean indicating membership in a given measurement system is returned by `Cldr.Unit.measurement_system?/2`.\n\n* All units belonging to a measurement system are returned by `Cldr.Unit.measurement_system_units/1`.\n\n* The measurement system in use for a given territory is returned by `Cldr.Unit.measurement_system_for_territory/1`.\n\n* The measurement system in use for a given locale is returned by `Cldr.Unit.measurement_system_from_locale/1`.\n\n#### Localisation with measurement systems\n\nKnowledge of the measurement system in place for a given user helps create a better user experience. For example, a user who prefers units of measure in the US system can be shown different but compatible units from a user who prefers metric units.\n\nIn this example, the list of units in the volume category are filtered based upon the users preference as expressed by their locale.\n```elixir\n# For a user preferring US english\niex\u003e system = Cldr.Unit.measurement_system_from_locale \"en\"\n:ussystem\n\niex\u003e {:ok, units} = Cldr.Unit.known_units_for_category(:volume)\niex\u003e Enum.filter(units, \u0026Cldr.Unit.measurement_system?(\u00261, system))\n[:dessert_spoon, :cup, :drop, :dram, :cubic_foot, :teaspoon, :tablespoon,\n :cubic_inch, :bushel, :quart, :pint, :cubic_yard, :cubic_mile, :fluid_ounce,\n :pinch, :barrel, :jigger, :gallon, :acre_foot]\n\n# For a user preferring australian english\niex\u003e system = Cldr.Unit.measurement_system_from_locale \"en-AU\"\n:metric\n\niex\u003e Enum.filter(units, \u0026Cldr.Unit.measurement_system?(\u00261, system))\n[:cubic_centimeter, :centiliter, :cubic_meter, :pint_metric, :megaliter,\n :cubic_kilometer, :hectoliter, :milliliter, :deciliter, :liter, :cup_metric]\n\n# For a user expressing an explicit measurement system\niex\u003e system = Cldr.Unit.measurement_system_from_locale \"en-AU-u-ms-uksystem\"\n:uksystem\n\niex\u003e Enum.filter(units, \u0026Cldr.Unit.measurement_system?(\u00261, system))\n[:quart_imperial, :cubic_foot, :cubic_inch, :dessert_spoon_imperial,\n :cubic_yard, :cubic_mile, :fluid_ounce_imperial, :acre_foot, :gallon_imperial]\n```\n\n## Additional units (custom units)\n\nAdditional domain-specific  units can be defined to suit application requirements. In the context\nof `ex_cldr` there are two parts to configuring additional units.\n\n1. Configure the unit, base unit and conversion in `config.exs`. This is a requirement since units are compiled into code.\n\n2. Configure the localizations for the additional unit in a CLDR backend module. Once configured, additional units act and behave like any of the predefined units of measure defined by CLDR.\n\n### Configuring a unit in config.exs\n\nUnder the application  `:ex_cldr_units`, define a key `:additional_units` with the required unit\ndefinitions.\n\nFor  example:\n```elixir\nconfig :ex_cldr_units,  :additional_units,\n  vehicle: [base_unit: :unit, factor: 1,  offset: 0, sort_before: :all],\n  person: [base_unit: :unit, factor:  1, offset: 0, sort_before: :all]\n```\nThis example defines  two additional units: `:vehicle` and  `:person`.\n\n* The keys `:base_unit`, and  `:factor` are required. The  key `:offset` is optional and  defaults to `0`.\n\n* The key `:sort_before` is optional and defaults to `:none`.\n\n### Configuration keys\n\n* `:base_unit` is the common denominator that is used to support conversion between like units. It can be any atom value. For example `:liter` is the base unit for volume units, `:meter` is the base unit for length units.\n\n*  `:factor` is used to convert a unit to its base unit in order to support conversion. When converting a unit to another compatible unit, the unit is first  multiplied by this units factor then divided by the target units factor.\n\n* `:offset` is added to a unit after applying its base factor in order to convert to another unit.\n\n* `:sort_before` determines where in this *base unit* sorts relative to other base units. Typically this is set to `:all` in which  case this base unit sorts before all other base units or`:none` in which case this base unit sorted after all other base units. The default is `:none`. If in doubt, leave this key to its default.\n\n*  `:systems` is list of measurement systems to which this unit belongs. The known measurement systems are `:metric`, `:uksystem` and `:ussystem`.  The  default is `[:metric,  :ussystem, :uksystem]`.\n\n### Defining localizations\n\nAlthough defining a unit in `config.exs` is enough to create, operate on and serialize an additional unit, it cannot be localised without defining localizations in an `ex_cldr` backend module.  For example:\n\n```elixir\ndefmodule MyApp.Cldr do\n  # Note that this line should come before the `use Cldr` line\n  use Cldr.Unit.Additional\n\n  use Cldr,\n    locales: [\"en\", \"fr\", \"de\", \"bs\", \"af\", \"af-NA\", \"se-SE\"],\n    default_locale: \"en\",\n    providers: [Cldr.Number, Cldr.Unit, Cldr.List]\n\n  unit_localization(:person, \"en\", :long,\n    nominative: %{\n      one: \"{0} person\",\n      other: \"{0} people\"\n    },\n    display_name: \"people\"\n  )\nend\n```\n\nNote the additions to a typical `ex_cldr` backend module:\n\n* `use Cldr.Unit.Additional` is required to define additional units\n\n* use of the `Cldr.Unit.Additional.unit_localization/4` macro in order to define a localization.\n\n* The use templates for the localization. Templates are a string with both a placeholder (for units it is always `{0}`) and some fixed text that reflects the grammatical requirements of the particular locale.\n\n* Not all locales support more than the nominative case. The nominative case is the default and mandatory one. Any configured \"Additional Units\" in a backend module will need to put the localisations into a map with the key `:nominative`.\n\nOne invocation of `Cldr.Unit.Additional.unit_localization/4` should made for each combination of unit, locale and style.\n\n#### Parameters to unit_localization/4\n\n* `unit` is the name of the additional unit as an `atom`.\n\n* `locale` is the locale name for this localization. It should be one of the locale configured in this backend although this cannot currently be confirmed at compile time.\n\n* `style` is one of `:long`, `:short`, or `:narrow`.\n\n* `localizations` is a keyword like of localization strings. Two keys - `:display_name` and `:other` are mandatory. They represent the localizations for a non-count display name and `:other` is the localization for a unit when no other pluralization is defined.\n\n#### Localisation definition\n\nLocalization keyword list defines localizations that match the plural rules for a given locale. Plural rules for a given number in a given locale resolve to one of\nsix keys, and they must be placed under the proper declension to be used:\n\n* `:zero`\n* `:one` (singular)\n* `:two` (dual)\n* `:few` (paucal)\n* `:many` (also used for fractions if they have a separate class)\n* `:other` (required — general plural form. Also used if the language only has a single form)\n\nOnly the `:nominative` key is required, and at minimum, it has to provide the `:other` key. For english, providing keys for `:one` and `:other` is enough. Other languages have different grammatical requirements.\n\nThe key `:display_name` is used by the function `Cldr.Unit.display_name/1` which is primarily used to support UI applications.\n\n### Sorting Units\n\nFrom Elixir 1.10, `Enum.sort/2` supports module-based comparisons to provide a simpler API for sorting structs. `ex_cldr_units` supports Elixir 1.10 as the following example shows:\n```elixir\niex\u003e alias Cldr.Unit\nCldr.Unit\n\niex\u003e unit_list = [Unit.new!(:millimeter, 100), Unit.new!(:centimeter, 100), Unit.new!(:meter, 100), Unit.new!(:kilometer, 100)]\n[#Unit\u003c:millimeter, 100\u003e, #Unit\u003c:centimeter, 100\u003e, #Unit\u003c:meter, 100\u003e,\n #Unit\u003c:kilometer, 100\u003e]\n\niex\u003e Enum.sort unit_list, Cldr.Unit\n[#Unit\u003c:millimeter, 100\u003e, #Unit\u003c:centimeter, 100\u003e, #Unit\u003c:meter, 100\u003e,\n #Unit\u003c:kilometer, 100\u003e]\n\niex\u003e Enum.sort unit_list, {:desc, Cldr.Unit}\n[#Unit\u003c:kilometer, 100\u003e, #Unit\u003c:meter, 100\u003e, #Unit\u003c:centimeter, 100\u003e,\n #Unit\u003c:millimeter, 100\u003e]\n\niex\u003e Enum.sort unit_list, {:asc, Cldr.Unit}\n[#Unit\u003c:millimeter, 100\u003e, #Unit\u003c:centimeter, 100\u003e, #Unit\u003c:meter, 100\u003e,\n #Unit\u003c:kilometer, 100\u003e]\n```\n\nNote that the items being sorted must be all of the same unit category (length, volume, ...). Where units are of the same category but different units, conversion to a common unit will occur before the comparison. If units of different categories are encountered an exception will be raised as the following example shows:\n```elixir\niex\u003e unit_list = [Unit.new!(:millimeter, 100), Unit.new!(:centimeter, 100), Unit.new!(:meter, 100), Unit.new!(:liter, 100)]\n[#Cldr.Unit\u003c:millimeter, 100\u003e, #Cldr.Unit\u003c:centimeter, 100\u003e,\n #Cldr.Unit\u003c:meter, 100\u003e, #Cldr.Unit\u003c:liter, 100\u003e]\n\niex\u003e Enum.sort unit_list, Cldr.Unit\n** (Cldr.Unit.IncompatibleUnitsError) Operations can only be performed between units with the same category and base unit. Received :liter and :meter\n```\n\n### Serializing to a database with Ecto\n\nThe companion package [ex_cldr_units_sql](https://hex.pm/packages/ex_cldr_units_sql) provides functions for the serialization of `Unit` data.  See the [README](https://hexdocs.pm/ex_cldr_units_sql/readme.html) for further information.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felixir-cldr%2Fcldr_units","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Felixir-cldr%2Fcldr_units","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felixir-cldr%2Fcldr_units/lists"}