Created
November 13, 2017 21:33
-
-
Save kirchner/ec8eafe01f52633b7f05b546078aef6d to your computer and use it in GitHub Desktop.
internationalization/localization api draft for elm
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[ | |
{ | |
"name": "Message", | |
"comment": " This package lets you create localized texts in a typesafe way.\n\nFor example, create a greeting message in different languages\n\n greeting : Message {}\n greeting =\n [ en |> s \"Hello!\"\n , de |> s \"Moin!\"\n , da |> s \"Heij!\"\n , pl |> s \"Halo!\"\n ]\n |> localize\n\nand pick a localized version according to the user's language settings\n\n view localeCode =\n Html.div []\n [ greeting\n |> choose localeCode\n |> print {}\n |> Html.text\n ]\n\nwhich prints out `\"Heij!\"` when `localeCode == \"da\"`, for example.\n\nYou can add simple placeholders\n\n morePersonalGreeting : Message { name : String }\n morePersonalGreeting =\n [ en\n |> s \"Hello, \"\n |> string .name\n |> s \"!\"\n , de\n |> s \"Moin, \"\n |> string .name\n |> s \"!\"\n , da\n |> s \"Heij, \"\n |> string .name\n |> s \"!\"\n , pl\n |> s \"Halo, \"\n |> string .name\n |> s \"!\"\n ]\n |> localize\n\nwhich are filled at runtime\n\n view localeCode name =\n Html.div []\n [ morePersonalGreeting\n |> choose localeCode\n |> print { name = name }\n |> Html.text\n ]\n\nwhere the user `\"Alice\"` gets the message `\"Moin, Alice!\"` if she has\nselected `\"de\"` as her `localeCode`; or add placeholders for numbers,\ndates, etc. which get formatted according to the rules specified in the\n[CLDR].\n\nOther features are\n\n - formatting of numbers (including percentages and currencies), dates\n and times according to the definitions in the [CLDR],\n - pluralization using `cardinal` and `ordinal` again based on the data\n in the [CLDR],\n - selection of different variants (for example if the locale has\n different genders) using `select`,\n - localized printing of lists\n\n[CLDR]: http://cldr.unicode.org\n\n\n# Types\n\n@docs Message, LocalizedMessage, Top, Case\n\n\n# Print Messages\n\n@docs print, choose\n\n\n# Create Messages\n\n@docs en, de, localize\n\n\n## Basic Message Parts\n\n@docs s, string\n\n\n## Numbers\n\n@docs decimal, DecimalFormat, decimalFormat\n\n\n## Dates and Times\n\nTODO\n\n\n## Pluralization\n\n@docs cardinal, ordinal\n\n@docs one, zero, two, few, many, other\n\n\n## Selects\n\n@docs select, for, forWith\n\n\n## Lists\n\n@docs list, ListFormat\n\n\n## Other Message Parts\n\n@docs ignore, map, mapMessage\n\n\n# Other Functions\n\n@docs localeCode, localeCodes\n\n\n# Custom Locales\n\n@docs Locale, forLocale\n\n", | |
"aliases": [], | |
"types": [ | |
{ | |
"name": "Case", | |
"comment": " ", | |
"args": [], | |
"cases": [] | |
}, | |
{ | |
"name": "DecimalFormat", | |
"comment": " All possible formats for numbers. The actual result depends on the\nCLDR specification for the selected locale.\n", | |
"args": [], | |
"cases": [ | |
[ | |
"DecimalStandard", | |
[] | |
], | |
[ | |
"DecimalLong", | |
[] | |
], | |
[ | |
"DecimalShort", | |
[] | |
] | |
] | |
}, | |
{ | |
"name": "ListFormat", | |
"comment": " ", | |
"args": [], | |
"cases": [ | |
[ | |
"ListStandard", | |
[] | |
], | |
[ | |
"ListStandardShort", | |
[] | |
], | |
[ | |
"ListOr", | |
[] | |
], | |
[ | |
"ListUnit", | |
[] | |
], | |
[ | |
"ListUnitNarrow", | |
[] | |
], | |
[ | |
"ListUnitShort", | |
[] | |
] | |
] | |
}, | |
{ | |
"name": "Locale", | |
"comment": " Opaque type representing a locale like `\"en\"` or `\"fil\"`. This type\nholds all the information provided by [cldr.unicode.org]. This includes\ninformation about how to format numbers, dates and times, pluralization\nrules for ordinal and cardinal numbers and a lot of other localization\ndata.\n\nThis type is usually hidden inside `LocalizedMessage`. At some point,\nthere should be a function to create a custom locale, where you can\nprovide these rules yourself.\n\n[cldr.unicode.org]: http://cldr.unicode.org\n\n", | |
"args": [], | |
"cases": [] | |
}, | |
{ | |
"name": "LocalizedMessage", | |
"comment": " Opaque type representing a message in a specific locale.\n\nEvery `LocalizedMessage` has a `scope` in which it can be used:\n\n - `LocalizedMessage Top args` are top-level messages, created by `en`,\n `de`, `forLocale` etc., and default-messages in messages like `list`,\n - `LocalizedMessage Case args` are sub-messages which can only be used\n inside `ordinal`, `cardinal` or `select` messages.\n\n", | |
"args": [ | |
"scope", | |
"args" | |
], | |
"cases": [] | |
}, | |
{ | |
"name": "Message", | |
"comment": " Opaque type representing a message which is available in several\nlocales, where `args` is a record of arguments, which has to be provided\nwhen `print`ing the message.\n", | |
"args": [ | |
"args" | |
], | |
"cases": [] | |
}, | |
{ | |
"name": "Top", | |
"comment": " ", | |
"args": [], | |
"cases": [] | |
} | |
], | |
"values": [ | |
{ | |
"name": "cardinal", | |
"comment": " Add pluralization according to the CLDR cardinal specifications:\n\n info : LocalizedMessage Top { distance : Float }\n info =\n en\n |> cardinal (decimal DecimalLong .distance)\n [ one\n |> s \"Today you ran 1 mile!\"\n , other\n |> s \"Today you ran \"\n |> count\n |> s \" miles!\"\n ]\n\nThe first argument determines the formatting of the count when it is\ninserted using `count`.\n\n**Note:** The first submessage which matches is taken.\n\n**Important:** If no submessages are provided or no `other` case is\npresent, the resulting `String` when printing may be empty.\n\nYou can also do something like `for 42 |> s \"The answer!\"`, when you\nwant to provide a special version for a certain number. These have to be\nprovided **before** the CLDR submessages so they do not get overwritten.\nAlso note that for example `zero |> s \"...\"` and `for 0 |> s \"...\"` do\nnot necessarily produce the same result! For example, the CLDR\nspecification for the locale `\"en\"` only has the cases `one` and\n`other`, so a `zero` submessage will never be selected.\n\n", | |
"type": "(Message.LocalizedMessage Message.Top args -> Message.LocalizedMessage Message.Top args) -> List (Message.LocalizedMessage Message.Case args) -> Message.LocalizedMessage scope args -> Message.LocalizedMessage scope args" | |
}, | |
{ | |
"name": "choose", | |
"comment": " Helper for choosing a localisation of a message.\n\n message : Message {}\n message =\n [ en |> s \"Good evening!\"\n , de |> s \"Guten Abend!\"\n ]\n |> localize\n\n output : String\n output =\n message\n |> choose \"de\"\n |> print {}\n\nwill result in `\"Guten Abend!\"`.\n\n", | |
"type": "String -> Message.Message args -> Message.LocalizedMessage Message.Top args" | |
}, | |
{ | |
"name": "de", | |
"comment": " ", | |
"type": "Message.LocalizedMessage Message.Top args" | |
}, | |
{ | |
"name": "decimal", | |
"comment": " Add a placeholder for a number which gets formatted according to the\nprovided `DecimalFormat` and the CLDR specifcation for the selected\nlocale.\n\n message : LocalizedMessage Top { metres : Float }\n message =\n en\n |> s \"You have walked \"\n |> decimal DecimalLong .metres\n |> s \" metres.\"\n\n output : String\n output =\n message\n |> print { metres = 4302 }\n\nwill result in `\"You have walked 4 thousand metres.\"`.\n\n", | |
"type": "Message.DecimalFormat -> (args -> Float) -> Message.LocalizedMessage scope args -> Message.LocalizedMessage scope args" | |
}, | |
{ | |
"name": "decimalFormat", | |
"comment": " Create custom decimal formats.\n\n customFormat =\n decimalFormat \"#,##0.##\"\n\n", | |
"type": "String -> Maybe.Maybe Message.DecimalFormat" | |
}, | |
{ | |
"name": "en", | |
"comment": " Start a localized string for the locale `\"en\"`:\n\n message : LocalizedMessage Top {}\n message =\n en\n |> s \"Good evening!\"\n\nThere are functions for every locale contained in the CLDR. If you want\nto use a custom locale you can use `forLocale`.\n\n", | |
"type": "Message.LocalizedMessage Message.Top args" | |
}, | |
{ | |
"name": "few", | |
"comment": " ", | |
"type": "Message.LocalizedMessage Message.Case args" | |
}, | |
{ | |
"name": "for", | |
"comment": " ", | |
"type": "a -> Message.LocalizedMessage Message.Case args -> Message.LocalizedMessage Message.Case args" | |
}, | |
{ | |
"name": "forLocale", | |
"comment": " Start a localized string for a custom locale.\n", | |
"type": "Message.Locale -> Message.LocalizedMessage Message.Top args" | |
}, | |
{ | |
"name": "forWith", | |
"comment": " Provide your own check function for select variants:\n\n message : LocalizedMessage Top { speed : Float }\n message =\n en\n |> select .speed\n [ forWith (\\speed -> speed < 0)\n |> s \"You are going backwards.\"\n , forWith (\\speed -> speed == 0)\n |> s \"You are standing still.\"\n , other\n |> s \"You are moving forward.\"\n ]\n\n", | |
"type": "(a -> Bool) -> Message.LocalizedMessage Message.Case args -> Message.LocalizedMessage Message.Case args" | |
}, | |
{ | |
"name": "ignore", | |
"comment": " The different cases of a `select`, `ordinal` or `cardinal` part need\nto have the same type signature. If only some of them need to contain\na placeholder, you can use `ignore` in the other submessages.\n\n message : LocalizedMessage Top { changes : Float, projectName : String }\n message =\n en\n |> cardinal (decimal DecimalLong .changes)\n [ for 0\n |> ignore .projectName\n |> s \"There are no new changes.\"\n , one\n |> s \"There is one new change in project \"\n |> string .projectName\n |> s \".\"\n , other\n |> s \"There are \"\n |> count\n |> s \" new changes in project \"\n |> string .projectName\n |> s \".\"\n ]\n\nThis can also be used, when some localizations of your message do not\nneed the value of a placeholder.\n\n message : Message { name : String }\n message =\n [ en\n |> \"Good evening \"\n |> string .name\n |> s \"!\"\n , de\n |> \"Guten abend!\"\n |> ignore .name\n ]\n |> localize\n\n", | |
"type": "(args -> a) -> Message.LocalizedMessage scope args -> Message.LocalizedMessage scope args" | |
}, | |
{ | |
"name": "list", | |
"comment": " Use this when enumerating items:\n\n message : LocalizedMessage Top { items : List String }\n message =\n en\n |> s \"You have selected \"\n |> list ListStandard .items (s \"nothing\")\n |> s \".\"\n\n outputA =\n --> == \"You have selected red, green and blue.\"\n message\n |> print { items = [ \"red\", \"green\", \"blue\" ] }\n\n outputB =\n --> == \"You have selected nothing.\"\n message\n |> print { items = [] }\n\n", | |
"type": "Message.ListFormat -> (args -> List String) -> (Message.LocalizedMessage Message.Top args -> Message.LocalizedMessage Message.Top args) -> Message.LocalizedMessage scope args -> Message.LocalizedMessage scope args" | |
}, | |
{ | |
"name": "localeCode", | |
"comment": " Return the locale code of this localized message.\n\n code =\n en\n |> localeCode\n\nequals `\"en\"`.\n\n", | |
"type": "Message.LocalizedMessage Message.Top args -> String" | |
}, | |
{ | |
"name": "localeCodes", | |
"comment": " Return the codes of all locales this message is available in.\n\n codes =\n [ en\n , de\n ]\n |> localize\n |> localeCodes\n\nequals `[ \"en\", \"de\" ]`.\n\n", | |
"type": "Message.Message args -> List String" | |
}, | |
{ | |
"name": "localize", | |
"comment": " Create a message from several localizations:\n\n message : Message {}\n message =\n [ en |> s \"Good evening!\"\n , de |> s \"Guten Abend!\"\n ]\n |> localize\n\n", | |
"type": "List (Message.LocalizedMessage Message.Top args) -> Message.Message args" | |
}, | |
{ | |
"name": "many", | |
"comment": " ", | |
"type": "Message.LocalizedMessage Message.Case args" | |
}, | |
{ | |
"name": "map", | |
"comment": " Apply the given function on the printed result of the localized\nmessage.\n", | |
"type": "(String -> String) -> Message.LocalizedMessage scope args -> Message.LocalizedMessage scope args" | |
}, | |
{ | |
"name": "mapMessage", | |
"comment": " Same as map, but acts on the message, hence on all localizations.\n\n message : Message { name : String }\n message =\n [ en\n |> \"Hello \"\n |> string .name\n |> \"!\"\n , de\n |> \"Hallo \"\n |> string .name\n |> \"!\"\n ]\n |> localize\n |> mapMessage String.toUpper\n\n output =\n message\n |> choose \"en\"\n |> print { name = \"Alice\" }\n\nwill result in `\"HELLO ALICE!\"`.\n\n", | |
"type": "(String -> String) -> Message.Message args -> Message.Message args" | |
}, | |
{ | |
"name": "one", | |
"comment": " Create a sub message within a pluralization which gets choosen when\nthe formatting of the count leads to the `one` case according to the\nCLDR specifications.\n", | |
"type": "Message.LocalizedMessage Message.Case args" | |
}, | |
{ | |
"name": "ordinal", | |
"comment": " Like `cardinal` but uses the CLDR ordinal specifications.\n", | |
"type": "(Message.LocalizedMessage Message.Top args -> Message.LocalizedMessage Message.Top args) -> List (Message.LocalizedMessage Message.Case args) -> Message.LocalizedMessage scope args -> Message.LocalizedMessage scope args" | |
}, | |
{ | |
"name": "other", | |
"comment": " Create a sub message within a pluralization which gets choosen when\nno other case matches.\n", | |
"type": "Message.LocalizedMessage Message.Case args" | |
}, | |
{ | |
"name": "print", | |
"comment": " Convert a localized message to a `String` using the provided\narguments:\n\n message : LocalizedMessage Top {}\n message =\n en\n |> s \"Good evening!\"\n\n output : String\n output =\n message\n |> print {}\n\nwill result in `\"Good evening!\"`.\n\n", | |
"type": "args -> Message.LocalizedMessage Message.Top args -> String" | |
}, | |
{ | |
"name": "s", | |
"comment": " Print the provided `String` verbatim.\n", | |
"type": "String -> Message.LocalizedMessage scope args -> Message.LocalizedMessage scope args" | |
}, | |
{ | |
"name": "select", | |
"comment": " Select between different variants:\n\n type Gender\n = Female\n | Male\n | Other\n\n message : LocalizedMessage Top { gender : Gender }\n message =\n en\n |> select .gender\n [ for Female\n |> s \"She sent you a message.\"\n , for Male\n |> s \"He sent you a message.\"\n , other\n |> s \"They sent you a message.\"\n ]\n\n**Note:** The first submessage which matches is taken.\n\n**Important:** If no submessages are provided or no `other` case is\npresent, the resulting `String` when printing may be empty.\n\n", | |
"type": "(args -> a) -> List (Message.LocalizedMessage Message.Case args) -> Message.LocalizedMessage scope args -> Message.LocalizedMessage scope args" | |
}, | |
{ | |
"name": "string", | |
"comment": " Add a placeholder which gets replace by a `String` which is\nprovided during runtime.\n\n message : LocalizedMessage Top { name : String }\n message =\n en\n |> s \"Good evening \"\n |> string .name\n |> s \"!\"\n\n output : String\n output =\n message\n |> print { name = \"Alice\" }\n\nwill result in `\"Good evening Alice!\"`.\n\n", | |
"type": "(args -> String) -> Message.LocalizedMessage scope args -> Message.LocalizedMessage scope args" | |
}, | |
{ | |
"name": "two", | |
"comment": " ", | |
"type": "Message.LocalizedMessage Message.Case args" | |
}, | |
{ | |
"name": "zero", | |
"comment": " ", | |
"type": "Message.LocalizedMessage Message.Case args" | |
} | |
], | |
"generated-with-elm-version": "0.18.0" | |
} | |
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Message | |
exposing | |
( Case | |
, DecimalFormat | |
( DecimalLong | |
, DecimalShort | |
, DecimalStandard | |
) | |
, ListFormat | |
( ListOr | |
, ListStandard | |
, ListStandardShort | |
, ListUnit | |
, ListUnitNarrow | |
, ListUnitShort | |
) | |
, Locale | |
, LocalizedMessage | |
, Message | |
, Top | |
, cardinal | |
, choose | |
, de | |
, decimal | |
, decimalFormat | |
, en | |
, few | |
, for | |
, forLocale | |
, forWith | |
, ignore | |
, list | |
, localeCode | |
, localeCodes | |
, localize | |
, many | |
, map | |
, mapMessage | |
, one | |
, ordinal | |
, other | |
, s | |
, select | |
, string | |
, two | |
, zero | |
) | |
{-| This package lets you create localized texts in a typesafe way. | |
For example, create a greeting message in different languages | |
greeting : Message {} | |
greeting = | |
[ en |> s "Hello!" | |
, de |> s "Moin!" | |
, da |> s "Heij!" | |
, pl |> s "Halo!" | |
] | |
|> localize | |
and pick a localized version according to the user's language settings | |
view localeCode = | |
Html.div [] | |
[ greeting | |
|> choose localeCode | |
|> print {} | |
|> Html.text | |
] | |
which prints out `"Heij!"` when `localeCode == "da"`, for example. | |
You can add simple placeholders | |
morePersonalGreeting : Message { name : String } | |
morePersonalGreeting = | |
[ en | |
|> s "Hello, " | |
|> string .name | |
|> s "!" | |
, de | |
|> s "Moin, " | |
|> string .name | |
|> s "!" | |
, da | |
|> s "Heij, " | |
|> string .name | |
|> s "!" | |
, pl | |
|> s "Halo, " | |
|> string .name | |
|> s "!" | |
] | |
|> localize | |
which are filled at runtime | |
view localeCode name = | |
Html.div [] | |
[ morePersonalGreeting | |
|> choose localeCode | |
|> print { name = name } | |
|> Html.text | |
] | |
where the user `"Alice"` gets the message `"Moin, Alice!"` if she has | |
selected `"de"` as her `localeCode`; or add placeholders for numbers, | |
dates, etc. which get formatted according to the rules specified in the | |
[CLDR]. | |
Other features are | |
- formatting of numbers (including percentages and currencies), dates | |
and times according to the definitions in the [CLDR], | |
- pluralization using `cardinal` and `ordinal` again based on the data | |
in the [CLDR], | |
- selection of different variants (for example if the locale has | |
different genders) using `select`, | |
- localized printing of lists | |
[CLDR]: http://cldr.unicode.org | |
# Types | |
@docs Message, LocalizedMessage, Top, Case | |
# Print Messages | |
@docs print, choose | |
# Create Messages | |
@docs en, de, localize | |
## Basic Message Parts | |
@docs s, string | |
## Numbers | |
@docs decimal, DecimalFormat, decimalFormat | |
## Dates and Times | |
TODO | |
## Pluralization | |
@docs cardinal, ordinal | |
@docs one, zero, two, few, many, other | |
## Selects | |
@docs select, for, forWith | |
## Lists | |
@docs list, ListFormat | |
## Other Message Parts | |
@docs ignore, map, mapMessage | |
# Other Functions | |
@docs localeCode, localeCodes | |
# Custom Locales | |
@docs Locale, forLocale | |
-} | |
{-| Opaque type representing a message which is available in several | |
locales, where `args` is a record of arguments, which has to be provided | |
when `print`ing the message. | |
-} | |
type Message args | |
= Message (List (LocalizedMessage Top args)) | |
{-| Return the codes of all locales this message is available in. | |
codes = | |
[ en | |
, de | |
] | |
|> localize | |
|> localeCodes | |
equals `[ "en", "de" ]`. | |
-} | |
localeCodes : Message args -> List String | |
localeCodes message = | |
Debug.crash "TODO" | |
{-| Opaque type representing a message in a specific locale. | |
Every `LocalizedMessage` has a `scope` in which it can be used: | |
- `LocalizedMessage Top args` are top-level messages, created by `en`, | |
`de`, `forLocale` etc., and default-messages in messages like `list`, | |
- `LocalizedMessage Case args` are sub-messages which can only be used | |
inside `ordinal`, `cardinal` or `select` messages. | |
-} | |
type LocalizedMessage scope args | |
= LocalizedMessage | |
{ locale : Locale | |
, parts : List (Part args) | |
} | |
{-| Return the locale code of this localized message. | |
code = | |
en | |
|> localeCode | |
equals `"en"`. | |
-} | |
localeCode : LocalizedMessage Top args -> String | |
localeCode localizedMessage = | |
Debug.crash "TODO" | |
type Part args | |
= Verbatim String | |
| String (args -> String) | |
{-| -} | |
type Top | |
= Top | |
{-| -} | |
type Case | |
= Case | |
{-| -} | |
type Default | |
= Default | |
{-| Opaque type representing a locale like `"en"` or `"fil"`. This type | |
holds all the information provided by [cldr.unicode.org]. This includes | |
information about how to format numbers, dates and times, pluralization | |
rules for ordinal and cardinal numbers and a lot of other localization | |
data. | |
This type is usually hidden inside `LocalizedMessage`. At some point, | |
there should be a function to create a custom locale, where you can | |
provide these rules yourself. | |
[cldr.unicode.org]: http://cldr.unicode.org | |
-} | |
type Locale | |
= Locale String | |
| Inherit | |
{-| Start a localized string for the locale `"en"`: | |
message : LocalizedMessage Top {} | |
message = | |
en | |
|> s "Good evening!" | |
There are functions for every locale contained in the CLDR. If you want | |
to use a custom locale you can use `forLocale`. | |
-} | |
en : LocalizedMessage Top args | |
en = | |
LocalizedMessage | |
{ locale = Locale "en" | |
, parts = [] | |
} | |
{-| -} | |
de : LocalizedMessage Top args | |
de = | |
LocalizedMessage | |
{ locale = Locale "de" | |
, parts = [] | |
} | |
{-| Start a localized string for a custom locale. | |
-} | |
forLocale : Locale -> LocalizedMessage Top args | |
forLocale locale = | |
LocalizedMessage | |
{ locale = locale | |
, parts = [] | |
} | |
{-| Create a message from several localizations: | |
message : Message {} | |
message = | |
[ en |> s "Good evening!" | |
, de |> s "Guten Abend!" | |
] | |
|> localize | |
-} | |
localize : List (LocalizedMessage Top args) -> Message args | |
localize localizedMessages = | |
Message localizedMessages | |
{-| Convert a localized message to a `String` using the provided | |
arguments: | |
message : LocalizedMessage Top {} | |
message = | |
en | |
|> s "Good evening!" | |
output : String | |
output = | |
message | |
|> print {} | |
will result in `"Good evening!"`. | |
-} | |
print : args -> LocalizedMessage Top args -> String | |
print args (LocalizedMessage { locale, parts }) = | |
List.foldl (\part sum -> printPart locale args part ++ sum) "" parts | |
printPart : Locale -> args -> Part args -> String | |
printPart locale args part = | |
case part of | |
Verbatim text -> | |
text | |
String accessor -> | |
args |> accessor | |
{-| Helper for choosing a localisation of a message. | |
message : Message {} | |
message = | |
[ en |> s "Good evening!" | |
, de |> s "Guten Abend!" | |
] | |
|> localize | |
output : String | |
output = | |
message | |
|> choose "de" | |
|> print {} | |
will result in `"Guten Abend!"`. | |
-} | |
choose : String -> Message args -> LocalizedMessage Top args | |
choose localeCode (Message localizedMessages) = | |
chooseHelper localeCode localizedMessages | |
chooseHelper : | |
String | |
-> List (LocalizedMessage Top args) | |
-> LocalizedMessage Top args | |
chooseHelper chosenLocaleCode localizedMessages = | |
case localizedMessages of | |
[] -> | |
[ "This message does not have a translation for the locale with the code \"" | |
, chosenLocaleCode | |
, "\"." | |
] | |
|> String.concat | |
|> Debug.crash | |
(LocalizedMessage { locale, parts }) :: rest -> | |
case locale of | |
Locale localeCode -> | |
if localeCode == chosenLocaleCode then | |
LocalizedMessage | |
{ locale = locale | |
, parts = parts | |
} | |
else | |
chooseHelper chosenLocaleCode rest | |
Inherit -> | |
Debug.crash "Top-level messages cannot inherit their locale." | |
{-| Print the provided `String` verbatim. | |
-} | |
s : String -> LocalizedMessage scope args -> LocalizedMessage scope args | |
s text (LocalizedMessage { locale, parts }) = | |
LocalizedMessage | |
{ locale = locale | |
, parts = Verbatim text :: parts | |
} | |
{-| Add a placeholder which gets replace by a `String` which is | |
provided during runtime. | |
message : LocalizedMessage Top { name : String } | |
message = | |
en | |
|> s "Good evening " | |
|> string .name | |
|> s "!" | |
output : String | |
output = | |
message | |
|> print { name = "Alice" } | |
will result in `"Good evening Alice!"`. | |
-} | |
string : | |
(args -> String) | |
-> LocalizedMessage scope args | |
-> LocalizedMessage scope args | |
string accessor (LocalizedMessage { locale, parts }) = | |
LocalizedMessage | |
{ locale = locale | |
, parts = String accessor :: parts | |
} | |
{-| Add a placeholder for a number which gets formatted according to the | |
provided `DecimalFormat` and the CLDR specifcation for the selected | |
locale. | |
message : LocalizedMessage Top { metres : Float } | |
message = | |
en | |
|> s "You have walked " | |
|> decimal DecimalLong .metres | |
|> s " metres." | |
output : String | |
output = | |
message | |
|> print { metres = 4302 } | |
will result in `"You have walked 4 thousand metres."`. | |
-} | |
decimal : | |
DecimalFormat | |
-> (args -> Float) | |
-> LocalizedMessage scope args | |
-> LocalizedMessage scope args | |
decimal format accessor localizedMessage = | |
Debug.crash "TODO" | |
{-| All possible formats for numbers. The actual result depends on the | |
CLDR specification for the selected locale. | |
-} | |
type DecimalFormat | |
= DecimalStandard | |
| DecimalLong | |
| DecimalShort | |
{-| Create custom decimal formats. | |
customFormat = | |
decimalFormat "#,##0.##" | |
-} | |
decimalFormat : String -> Maybe DecimalFormat | |
decimalFormat pattern = | |
Debug.crash "TODO" | |
{-| Add pluralization according to the CLDR cardinal specifications: | |
info : LocalizedMessage Top { distance : Float } | |
info = | |
en | |
|> cardinal (decimal DecimalLong .distance) | |
[ one | |
|> s "Today you ran 1 mile!" | |
, other | |
|> s "Today you ran " | |
|> count | |
|> s " miles!" | |
] | |
The first argument determines the formatting of the count when it is | |
inserted using `count`. | |
**Note:** The first submessage which matches is taken. | |
**Important:** If no submessages are provided or no `other` case is | |
present, the resulting `String` when printing may be empty. | |
You can also do something like `for 42 |> s "The answer!"`, when you | |
want to provide a special version for a certain number. These have to be | |
provided **before** the CLDR submessages so they do not get overwritten. | |
Also note that for example `zero |> s "..."` and `for 0 |> s "..."` do | |
not necessarily produce the same result! For example, the CLDR | |
specification for the locale `"en"` only has the cases `one` and | |
`other`, so a `zero` submessage will never be selected. | |
-} | |
cardinal : | |
(LocalizedMessage Top args -> LocalizedMessage Top args) | |
-> List (LocalizedMessage Case args) | |
-> LocalizedMessage scope args | |
-> LocalizedMessage scope args | |
cardinal count cases localizedMessage = | |
Debug.crash "TODO" | |
{-| Like `cardinal` but uses the CLDR ordinal specifications. | |
-} | |
ordinal : | |
(LocalizedMessage Top args -> LocalizedMessage Top args) | |
-> List (LocalizedMessage Case args) | |
-> LocalizedMessage scope args | |
-> LocalizedMessage scope args | |
ordinal count cases localizedMessage = | |
Debug.crash "TODO" | |
{-| Create a sub message within a pluralization which gets choosen when | |
the formatting of the count leads to the `one` case according to the | |
CLDR specifications. | |
-} | |
one : LocalizedMessage Case args | |
one = | |
LocalizedMessage | |
{ locale = Inherit | |
, parts = [] | |
} | |
{-| -} | |
zero : LocalizedMessage Case args | |
zero = | |
LocalizedMessage | |
{ locale = Inherit | |
, parts = [] | |
} | |
{-| -} | |
two : LocalizedMessage Case args | |
two = | |
LocalizedMessage | |
{ locale = Inherit | |
, parts = [] | |
} | |
{-| -} | |
few : LocalizedMessage Case args | |
few = | |
LocalizedMessage | |
{ locale = Inherit | |
, parts = [] | |
} | |
{-| -} | |
many : LocalizedMessage Case args | |
many = | |
LocalizedMessage | |
{ locale = Inherit | |
, parts = [] | |
} | |
{-| Create a sub message within a pluralization which gets choosen when | |
no other case matches. | |
-} | |
other : LocalizedMessage Case args | |
other = | |
LocalizedMessage | |
{ locale = Inherit | |
, parts = [] | |
} | |
{-| Print the formatted number within a pluralized message. | |
-} | |
count : LocalizedMessage Case args -> LocalizedMessage Case args | |
count localizedMessage = | |
Debug.crash "TODO" | |
{-| Select between different variants: | |
type Gender | |
= Female | |
| Male | |
| Other | |
message : LocalizedMessage Top { gender : Gender } | |
message = | |
en | |
|> select .gender | |
[ for Female | |
|> s "She sent you a message." | |
, for Male | |
|> s "He sent you a message." | |
, other | |
|> s "They sent you a message." | |
] | |
**Note:** The first submessage which matches is taken. | |
**Important:** If no submessages are provided or no `other` case is | |
present, the resulting `String` when printing may be empty. | |
-} | |
select : | |
(args -> a) | |
-> List (LocalizedMessage Case args) | |
-> LocalizedMessage scope args | |
-> LocalizedMessage scope args | |
select accessor cases localizedMessage = | |
Debug.crash "TODO" | |
{-| -} | |
for : a -> LocalizedMessage Case args -> LocalizedMessage Case args | |
for value localizedMessage = | |
Debug.crash "TODO" | |
{-| Provide your own check function for select variants: | |
message : LocalizedMessage Top { speed : Float } | |
message = | |
en | |
|> select .speed | |
[ forWith (\speed -> speed < 0) | |
|> s "You are going backwards." | |
, forWith (\speed -> speed == 0) | |
|> s "You are standing still." | |
, other | |
|> s "You are moving forward." | |
] | |
-} | |
forWith : (a -> Bool) -> LocalizedMessage Case args -> LocalizedMessage Case args | |
forWith check localizedMessage = | |
Debug.crash "TODO" | |
{-| The different cases of a `select`, `ordinal` or `cardinal` part need | |
to have the same type signature. If only some of them need to contain | |
a placeholder, you can use `ignore` in the other submessages. | |
message : LocalizedMessage Top { changes : Float, projectName : String } | |
message = | |
en | |
|> cardinal (decimal DecimalLong .changes) | |
[ for 0 | |
|> ignore .projectName | |
|> s "There are no new changes." | |
, one | |
|> s "There is one new change in project " | |
|> string .projectName | |
|> s "." | |
, other | |
|> s "There are " | |
|> count | |
|> s " new changes in project " | |
|> string .projectName | |
|> s "." | |
] | |
This can also be used, when some localizations of your message do not | |
need the value of a placeholder. | |
message : Message { name : String } | |
message = | |
[ en | |
|> "Good evening " | |
|> string .name | |
|> s "!" | |
, de | |
|> "Guten abend!" | |
|> ignore .name | |
] | |
|> localize | |
-} | |
ignore : (args -> a) -> LocalizedMessage scope args -> LocalizedMessage scope args | |
ignore accessor localizedMessage = | |
localizedMessage | |
{-| Apply the given function on the printed result of the localized | |
message. | |
-} | |
map : (String -> String) -> LocalizedMessage scope args -> LocalizedMessage scope args | |
map f localizedMessage = | |
Debug.crash "TODO" | |
{-| Same as map, but acts on the message, hence on all localizations. | |
message : Message { name : String } | |
message = | |
[ en | |
|> "Hello " | |
|> string .name | |
|> "!" | |
, de | |
|> "Hallo " | |
|> string .name | |
|> "!" | |
] | |
|> localize | |
|> mapMessage String.toUpper | |
output = | |
message | |
|> choose "en" | |
|> print { name = "Alice" } | |
will result in `"HELLO ALICE!"`. | |
-} | |
mapMessage : (String -> String) -> Message args -> Message args | |
mapMessage f message = | |
Debug.crash "TODO" | |
{-| Use this when enumerating items: | |
message : LocalizedMessage Top { items : List String } | |
message = | |
en | |
|> s "You have selected " | |
|> list ListStandard .items (s "nothing") | |
|> s "." | |
outputA = | |
--> == "You have selected red, green and blue." | |
message | |
|> print { items = [ "red", "green", "blue" ] } | |
outputB = | |
--> == "You have selected nothing." | |
message | |
|> print { items = [] } | |
-} | |
list : | |
ListFormat | |
-> (args -> List String) | |
-> (LocalizedMessage Top args -> LocalizedMessage Top args) | |
-> LocalizedMessage scope args | |
-> LocalizedMessage scope args | |
list format accessor default localizedMessage = | |
Debug.crash "TODO" | |
{-| -} | |
type ListFormat | |
= ListStandard | |
| ListStandardShort | |
| ListOr | |
| ListUnit | |
| ListUnitNarrow | |
| ListUnitShort |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment