Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ end

Documentation can be found at [https://hexdocs.pm/language_list](https://hexdocs.pm/language_list).

## Usage:
## Usage

Standard requests will return a list of maps or strings.

Expand Down Expand Up @@ -113,6 +113,6 @@ nil

```

## TODO:
## TODO

[] add native language names to json file.
[ ] add native language names to json file.
16 changes: 9 additions & 7 deletions lib/language_list.ex
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,15 @@ defmodule LanguageList do
def all_data do
file_path = Application.app_dir(:language_list, "priv/languages.json")

decoders = [
object_push: fn key, value, acc -> [{String.to_existing_atom(key), value} | acc] end
]

with {:ok, file} <- File.read(file_path),
{:ok, languages} <- Poison.decode(file, keys: :atoms)
do
languages
else
_ -> raise "Could not read internal languages.json file!"
{languages, :ok, ""} <- JSON.decode(file, :ok, decoders) do
languages
else
_ -> raise "Could not read internal languages.json file!"
end
end

Expand Down Expand Up @@ -51,7 +54,7 @@ defmodule LanguageList do
@doc false
def all_common_data!, do: all_common_data()

@doc"""
@doc """
Returns list of all language names.

## Examples
Expand Down Expand Up @@ -131,5 +134,4 @@ defmodule LanguageList do
{:ok, result}
end
end

end
15 changes: 9 additions & 6 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,18 @@ defmodule LanguageList.MixProject do
def project do
[
app: :language_list,
version: "2.0.0",
elixir: "~> 1.12",
version: "3.0.0",
elixir: "~> 1.18",
start_permanent: Mix.env() == :prod,
description: description(),
package: package(),
deps: deps(),
name: "language_list",
source_url: "https://github.com/GunnarPDX/language_list"
source_url: "https://github.com/GunnarPDX/language_list",
docs: [
main: "readme",
extras: ["README.md"]
]
]
end

Expand All @@ -25,8 +29,7 @@ defmodule LanguageList.MixProject do
# Run "mix help deps" to learn about dependencies.
defp deps do
[
{:poison, "~> 3.1"},
{:ex_doc, ">= 0.0.0", only: :dev, runtime: false}
{:ex_doc, "~> 0.34", only: :dev, runtime: false, warn_if_outdated: true}
]
end

Expand All @@ -43,7 +46,7 @@ defmodule LanguageList.MixProject do
# This option is only needed when you don't want to use the OTP application name
name: "language_list",
# These are the default files included in the package
files: ~w(lib priv .formatter.exs mix.exs README* LICENSE*),
files: ~w(lib priv .formatter.exs mix.exs README* LICENSE* usage-rules.md),
licenses: ["MIT"],
links: %{"GitHub" => "https://github.com/GunnarPDX/language_list"}
]
Expand Down
12 changes: 6 additions & 6 deletions mix.lock
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
%{
"earmark_parser": {:hex, :earmark_parser, "1.4.12", "b245e875ec0a311a342320da0551da407d9d2b65d98f7a9597ae078615af3449", [:mix], [], "hexpm", "711e2cc4d64abb7d566d43f54b78f7dc129308a63bc103fbd88550d2174b3160"},
"ex_doc": {:hex, :ex_doc, "0.24.2", "e4c26603830c1a2286dae45f4412a4d1980e1e89dc779fcd0181ed1d5a05c8d9", [:mix], [{:earmark_parser, "~> 1.4.0", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "e134e1d9e821b8d9e4244687fb2ace58d479b67b282de5158333b0d57c6fb7da"},
"earmark_parser": {:hex, :earmark_parser, "1.4.44", "f20830dd6b5c77afe2b063777ddbbff09f9759396500cdbe7523efd58d7a339c", [:mix], [], "hexpm", "4778ac752b4701a5599215f7030989c989ffdc4f6df457c5f36938cc2d2a2750"},
"ex_doc": {:hex, :ex_doc, "0.39.3", "519c6bc7e84a2918b737aec7ef48b96aa4698342927d080437f61395d361dcee", [:mix], [{:earmark_parser, "~> 1.4.44", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "0590955cf7ad3b625780ee1c1ea627c28a78948c6c0a9b0322bd976a079996e1"},
"jason": {:hex, :jason, "1.2.2", "ba43e3f2709fd1aa1dce90aaabfd039d000469c05c56f0b8e31978e03fa39052", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "18a228f5f0058ee183f29f9eae0805c6e59d61c3b006760668d8d18ff0d12179"},
"makeup": {:hex, :makeup, "1.0.5", "d5a830bc42c9800ce07dd97fa94669dfb93d3bf5fcf6ea7a0c67b2e0e4a7f26c", [:mix], [{:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cfa158c02d3f5c0c665d0af11512fed3fba0144cf1aadee0f2ce17747fba2ca9"},
"makeup_elixir": {:hex, :makeup_elixir, "0.15.1", "b5888c880d17d1cc3e598f05cdb5b5a91b7b17ac4eaf5f297cb697663a1094dd", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.1", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "db68c173234b07ab2a07f645a5acdc117b9f99d69ebf521821d89690ae6c6ec8"},
"makeup_erlang": {:hex, :makeup_erlang, "0.1.1", "3fcb7f09eb9d98dc4d208f49cc955a34218fc41ff6b84df7c75b3e6e533cc65f", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "174d0809e98a4ef0b3309256cbf97101c6ec01c4ab0b23e926a9e17df2077cbb"},
"nimble_parsec": {:hex, :nimble_parsec, "1.1.0", "3a6fca1550363552e54c216debb6a9e95bd8d32348938e13de5eda962c0d7f89", [:mix], [], "hexpm", "08eb32d66b706e913ff748f11694b17981c0b04a33ef470e33e11b3d3ac8f54b"},
"makeup": {:hex, :makeup, "1.2.1", "e90ac1c65589ef354378def3ba19d401e739ee7ee06fb47f94c687016e3713d1", [:mix], [{:nimble_parsec, "~> 1.4", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "d36484867b0bae0fea568d10131197a4c2e47056a6fbe84922bf6ba71c8d17ce"},
"makeup_elixir": {:hex, :makeup_elixir, "1.0.1", "e928a4f984e795e41e3abd27bfc09f51db16ab8ba1aebdba2b3a575437efafc2", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "7284900d412a3e5cfd97fdaed4f5ed389b8f2b4cb49efc0eb3bd10e2febf9507"},
"makeup_erlang": {:hex, :makeup_erlang, "1.0.2", "03e1804074b3aa64d5fad7aa64601ed0fb395337b982d9bcf04029d68d51b6a7", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "af33ff7ef368d5893e4a267933e7744e46ce3cf1f61e2dccf53a111ed3aa3727"},
"nimble_parsec": {:hex, :nimble_parsec, "1.4.2", "8efba0122db06df95bfaa78f791344a89352ba04baedd3849593bfce4d0dc1c6", [:mix], [], "hexpm", "4b21398942dda052b403bbe1da991ccd03a053668d147d53fb8c4e0efe09c973"},
"poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], [], "hexpm", "fec8660eb7733ee4117b85f55799fd3833eb769a6df71ccf8903e8dc5447cfce"},
}
63 changes: 44 additions & 19 deletions test/language_list_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -3,48 +3,48 @@ defmodule LanguageListTest do
# doctest LanguageList

test "get all data" do
assert values = LanguageList.all_data
assert values = LanguageList.all_data()
assert Enum.count(values) > 0
end

test "get all data without :ok/:error" do
assert LanguageList.all_data! |> Enum.count() > 0
assert LanguageList.all_data!() |> Enum.count() > 0
end

test "test get all common data" do
assert values = LanguageList.all_common_data
assert values = LanguageList.all_common_data()
assert Enum.count(values) > 0
end

test "test get all common data without :ok/:error" do
assert LanguageList.all_common_data! |> Enum.count() > 0
assert LanguageList.all_common_data!() |> Enum.count() > 0
end

test "make sure all_common_data returns only common data" do
values = LanguageList.all_common_data
values = LanguageList.all_common_data()
assert Enum.find(values, fn x -> x.common != true end) == nil
end

test "get language names" do
assert values = LanguageList.languages
assert values = LanguageList.languages()
assert Enum.count(values) > 0
end

test "get language names without :ok/:error" do
assert LanguageList.languages! |> Enum.count() > 0
assert LanguageList.languages!() |> Enum.count() > 0
end

test "get common language names" do
assert values = LanguageList.common_languages
assert values = LanguageList.common_languages()
assert Enum.count(values) > 0
end

test "get common language names without :ok/:error" do
assert LanguageList.common_languages! |> Enum.count() > 0
assert LanguageList.common_languages!() |> Enum.count() > 0
end

test "common languages only" do
values = LanguageList.common_languages!
values = LanguageList.common_languages!()
assert Enum.find(values, fn x -> x == "Corsican" end) == nil
assert Enum.find(values, fn x -> x == "Aragonese" end) == nil
assert Enum.find(values, fn x -> x == "Guarani" end) == nil
Expand All @@ -58,33 +58,58 @@ defmodule LanguageListTest do
end

test "find by language name" do
assert LanguageList.find("Icelandic", :name) == {:ok, %{common: true, iso_639_1: "is", iso_639_3: "isl", name: "Icelandic"}}
assert LanguageList.find("Icelandic", :name) ==
{:ok, %{common: true, iso_639_1: "is", iso_639_3: "isl", name: "Icelandic"}}

assert LanguageList.find("name does not exist", :name) == {:error, "No matches found"}
end

test "find by name without :ok/:error" do
assert LanguageList.find!("Icelandic", :name) == %{common: true, iso_639_1: "is", iso_639_3: "isl", name: "Icelandic"}
assert LanguageList.find!("Icelandic", :name) == %{
common: true,
iso_639_1: "is",
iso_639_3: "isl",
name: "Icelandic"
}

assert LanguageList.find!("name does not exist", :name) == nil
end

test "find by iso-1" do
assert LanguageList.find("pt", :iso_639_1) == {:ok, %{common: true, iso_639_1: "pt", iso_639_3: "por", name: "Portuguese"}}
assert LanguageList.find("iso code does not exist", :iso_639_1) == {:error, "No matches found"}
assert LanguageList.find("pt", :iso_639_1) ==
{:ok, %{common: true, iso_639_1: "pt", iso_639_3: "por", name: "Portuguese"}}

assert LanguageList.find("iso code does not exist", :iso_639_1) ==
{:error, "No matches found"}
end

test "find by iso-1 without :ok/:error" do
assert LanguageList.find!("pt", :iso_639_1) == %{common: true, iso_639_1: "pt", iso_639_3: "por", name: "Portuguese"}
assert LanguageList.find!("pt", :iso_639_1) == %{
common: true,
iso_639_1: "pt",
iso_639_3: "por",
name: "Portuguese"
}

assert LanguageList.find!("iso code does not exist", :iso_639_1) == nil
end

test "find by iso-3" do
assert LanguageList.find("pt", :iso_639_1) == {:ok, %{common: true, iso_639_1: "pt", iso_639_3: "por", name: "Portuguese"}}
assert LanguageList.find("iso code does not exist", :iso_639_1) == {:error, "No matches found"}
assert LanguageList.find("pt", :iso_639_1) ==
{:ok, %{common: true, iso_639_1: "pt", iso_639_3: "por", name: "Portuguese"}}

assert LanguageList.find("iso code does not exist", :iso_639_1) ==
{:error, "No matches found"}
end

test "find by iso-3 without :ok/:error" do
assert LanguageList.find!("por", :iso_639_3) == %{common: true, iso_639_1: "pt", iso_639_3: "por", name: "Portuguese"}
assert LanguageList.find!("por", :iso_639_3) == %{
common: true,
iso_639_1: "pt",
iso_639_3: "por",
name: "Portuguese"
}

assert LanguageList.find!("iso code does not exist", :iso_639_3) == nil
end

end
47 changes: 47 additions & 0 deletions usage-rules.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# LanguageList Usage Rules

## Data Structure

Language data is returned as maps with these keys:
- `:name` - Language name (e.g., "Portuguese")
- `:iso_639_1` - Two-letter ISO code (e.g., "pt")
- `:iso_639_3` - Three-letter ISO code (e.g., "por")
- `:common` - Boolean indicating if commonly used

## API Functions

- `all_data/0` - Returns list of all language maps
- `all_common_data/0` - Returns list of common language maps only
- `languages/0` - Returns list of all language names as strings
- `common_languages/0` - Returns list of common language names as strings
- `find/2` - Returns `{:ok, map}` or `{:error, msg}`
- `find!/2` - Returns map or `nil` (no tuple wrapper)

## Search Keys

`find/2` and `find!/2` accept only these keys:
- `:name` - Search by language name
- `:iso_639_1` - Search by 2-letter code
- `:iso_639_3` - Search by 3-letter code

## Common Mistakes

- **Wrong**: `LanguageList.find("en", :iso_639_2)` - Invalid key
- **Right**: `LanguageList.find("en", :iso_639_1)` - Use `:iso_639_1` or `:iso_639_3`

- **Wrong**: Expecting `find!/2` to raise on not found
- **Right**: `find!/2` returns `nil` when not found, not an exception

## Examples

```elixir
# Get Portuguese by ISO code
{:ok, lang} = LanguageList.find("pt", :iso_639_1)
lang.name # => "Portuguese"

# Direct access without tuple
lang = LanguageList.find!("Portuguese", :name)

# Filter common languages
LanguageList.common_languages() # => ["Afrikaans", "Arabic", ...]
```