Skip to content

Instantly share code, notes, and snippets.

@kirchner
Created November 13, 2017 21:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kirchner/ec8eafe01f52633b7f05b546078aef6d to your computer and use it in GitHub Desktop.
Save kirchner/ec8eafe01f52633b7f05b546078aef6d to your computer and use it in GitHub Desktop.
internationalization/localization api draft for elm
[
{
"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"
}
]
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
, print
, 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