{"action":"created","comment":{"url":"https://api.github.com/repos/change/linguist/pulls/comments/183822069","pull_request_review_id":114894050,"id":183822069,"diff_hunk":"@@ -0,0 +1,170 @@\n+defmodule Linguist.MemorizedVocabulary do\n+  alias Linguist.Compiler\n+  alias Linguist.NoTranslationError\n+  alias Cldr.Number.Cardinal\n+\n+  @moduledoc \"\"\"\n+  Defines lookup functions for given translation locales, binding interopolation\n+\n+  Locales are defined with the `locale/2` function, accepting a locale name and\n+  a String path to evaluate for the translations list.\n+\n+  For example, given the following translations :\n+\n+  locale \"en\", [\n+    flash: [\n+      notice: [\n+        hello: \"hello %{first} %{last}\",\n+      ]\n+    ],\n+    users: [\n+      title: \"Users\",\n+    ]\n+  ]\n+\n+  locale \"fr\", Path.join([__DIR__, \"fr.exs\"])\n+\n+  this module will respond to these functions :\n+\n+  t(\"en\", \"flash.notice.hello\", bindings \\\\ []), do: # ...\n+  t(\"en\", \"users.title\", bindings \\\\ []), do: # ...\n+  t(\"fr\", \"flash.notice.hello\", bindings \\\\ []), do: # ...\n+  \"\"\"\n+\n+  def t(locale, path, bindings \\\\ []) do\n+    pluralization_key = Application.fetch_env!(:linguist, :pluralization_key)\n+    if Keyword.has_key?(bindings, pluralization_key) do\n+      plural_atom =\n+        Cardinal.plural_rule(\n+          Keyword.get(bindings, pluralization_key),\n+          locale\n+        )\n+\n+      new_path = \"#{path}.#{plural_atom}\"\n+      do_t(locale, new_path, bindings)\n+    else\n+      do_t(locale, path, bindings)\n+    end\n+  end\n+\n+  def t!(locale, path, bindings \\\\ []) do\n+    case t(locale, path, bindings) do\n+      {:ok, translation} -> translation\n+      {:error, :no_translation} ->\n+        raise %NoTranslationError{message: \"#{locale}: #{path}\"}\n+    end\n+  end\n+\n+  defp do_t(locale, translation_key, bindings \\\\ []) do\n+    case :ets.lookup(:translations_registry, \"#{locale}.#{translation_key}\") do\n+      [] -> {:error, :no_translation}\n+      [{_, string}] ->\n+        translation =\n+          Compiler.interpol_rgx()\n+          |> Regex.split(string, on: [:head, :tail])\n+          |> Enum.reduce(\"\", fn\n+            <<\"%{\" <> rest>>, acc ->\n+              key = String.to_atom(String.rstrip(rest, ?}))","path":"lib/linguist/memorized_vocabulary.ex","position":67,"original_position":67,"commit_id":"890d93b1158ddcedb6c2e98adadd8470afc7b774","original_commit_id":"890d93b1158ddcedb6c2e98adadd8470afc7b774","user":{"login":"willbarrett","id":1779034,"avatar_url":"https://avatars2.githubusercontent.com/u/1779034?v=4","gravatar_id":"","url":"https://api.github.com/users/willbarrett","html_url":"https://github.com/willbarrett","followers_url":"https://api.github.com/users/willbarrett/followers","following_url":"https://api.github.com/users/willbarrett/following{/other_user}","gists_url":"https://api.github.com/users/willbarrett/gists{/gist_id}","starred_url":"https://api.github.com/users/willbarrett/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/willbarrett/subscriptions","organizations_url":"https://api.github.com/users/willbarrett/orgs","repos_url":"https://api.github.com/users/willbarrett/repos","events_url":"https://api.github.com/users/willbarrett/events{/privacy}","received_events_url":"https://api.github.com/users/willbarrett/received_events","type":"User","site_admin":false},"body":"Workin' on it ;)","created_at":"2018-04-24T17:44:23Z","updated_at":"2018-04-24T17:44:24Z","html_url":"https://github.com/change/linguist/pull/4#discussion_r183822069","pull_request_url":"https://api.github.com/repos/change/linguist/pulls/4","author_association":"NONE","_links":{"self":{"href":"https://api.github.com/repos/change/linguist/pulls/comments/183822069"},"html":{"href":"https://github.com/change/linguist/pull/4#discussion_r183822069"},"pull_request":{"href":"https://api.github.com/repos/change/linguist/pulls/4"}},"in_reply_to_id":183570600},"pull_request":{"url":"https://api.github.com/repos/change/linguist/pulls/4","id":182915588,"html_url":"https://github.com/change/linguist/pull/4","diff_url":"https://github.com/change/linguist/pull/4.diff","patch_url":"https://github.com/change/linguist/pull/4.patch","issue_url":"https://api.github.com/repos/change/linguist/issues/4","number":4,"state":"open","locked":false,"title":"Add Linguist.MemorizedVocabulary module","user":{"login":"willbarrett","id":1779034,"avatar_url":"https://avatars2.githubusercontent.com/u/1779034?v=4","gravatar_id":"","url":"https://api.github.com/users/willbarrett","html_url":"https://github.com/willbarrett","followers_url":"https://api.github.com/users/willbarrett/followers","following_url":"https://api.github.com/users/willbarrett/following{/other_user}","gists_url":"https://api.github.com/users/willbarrett/gists{/gist_id}","starred_url":"https://api.github.com/users/willbarrett/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/willbarrett/subscriptions","organizations_url":"https://api.github.com/users/willbarrett/orgs","repos_url":"https://api.github.com/users/willbarrett/repos","events_url":"https://api.github.com/users/willbarrett/events{/privacy}","received_events_url":"https://api.github.com/users/willbarrett/received_events","type":"User","site_admin":false},"body":"This module holds translations in an ets table and loads the translations from yaml files at runtime. There are a few tweaks I'll probably be making to make the string handling align a bit better with what's expected by our systems, but this works well. When loading all our comms translations, this takes about half a second to return.\r\n\r\n@change/octopus ","created_at":"2018-04-19T22:28:58Z","updated_at":"2018-04-24T17:44:24Z","closed_at":null,"merged_at":null,"merge_commit_sha":"7f77f2032e3d38246a61c7eea198c658ff51e92a","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/change/linguist/pulls/4/commits","review_comments_url":"https://api.github.com/repos/change/linguist/pulls/4/comments","review_comment_url":"https://api.github.com/repos/change/linguist/pulls/comments{/number}","comments_url":"https://api.github.com/repos/change/linguist/issues/4/comments","statuses_url":"https://api.github.com/repos/change/linguist/statuses/890d93b1158ddcedb6c2e98adadd8470afc7b774","head":{"label":"change:wbarrett/plan-dies-due-to-contact-with-reality","ref":"wbarrett/plan-dies-due-to-contact-with-reality","sha":"890d93b1158ddcedb6c2e98adadd8470afc7b774","user":{"login":"change","id":121582,"avatar_url":"https://avatars3.githubusercontent.com/u/121582?v=4","gravatar_id":"","url":"https://api.github.com/users/change","html_url":"https://github.com/change","followers_url":"https://api.github.com/users/change/followers","following_url":"https://api.github.com/users/change/following{/other_user}","gists_url":"https://api.github.com/users/change/gists{/gist_id}","starred_url":"https://api.github.com/users/change/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/change/subscriptions","organizations_url":"https://api.github.com/users/change/orgs","repos_url":"https://api.github.com/users/change/repos","events_url":"https://api.github.com/users/change/events{/privacy}","received_events_url":"https://api.github.com/users/change/received_events","type":"Organization","site_admin":false},"repo":{"id":129455085,"name":"linguist","full_name":"change/linguist","owner":{"login":"change","id":121582,"avatar_url":"https://avatars3.githubusercontent.com/u/121582?v=4","gravatar_id":"","url":"https://api.github.com/users/change","html_url":"https://github.com/change","followers_url":"https://api.github.com/users/change/followers","following_url":"https://api.github.com/users/change/following{/other_user}","gists_url":"https://api.github.com/users/change/gists{/gist_id}","starred_url":"https://api.github.com/users/change/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/change/subscriptions","organizations_url":"https://api.github.com/users/change/orgs","repos_url":"https://api.github.com/users/change/repos","events_url":"https://api.github.com/users/change/events{/privacy}","received_events_url":"https://api.github.com/users/change/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/change/linguist","description":"Elixir Internationalization library","fork":true,"url":"https://api.github.com/repos/change/linguist","forks_url":"https://api.github.com/repos/change/linguist/forks","keys_url":"https://api.github.com/repos/change/linguist/keys{/key_id}","collaborators_url":"https://api.github.com/repos/change/linguist/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/change/linguist/teams","hooks_url":"https://api.github.com/repos/change/linguist/hooks","issue_events_url":"https://api.github.com/repos/change/linguist/issues/events{/number}","events_url":"https://api.github.com/repos/change/linguist/events","assignees_url":"https://api.github.com/repos/change/linguist/assignees{/user}","branches_url":"https://api.github.com/repos/change/linguist/branches{/branch}","tags_url":"https://api.github.com/repos/change/linguist/tags","blobs_url":"https://api.github.com/repos/change/linguist/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/change/linguist/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/change/linguist/git/refs{/sha}","trees_url":"https://api.github.com/repos/change/linguist/git/trees{/sha}","statuses_url":"https://api.github.com/repos/change/linguist/statuses/{sha}","languages_url":"https://api.github.com/repos/change/linguist/languages","stargazers_url":"https://api.github.com/repos/change/linguist/stargazers","contributors_url":"https://api.github.com/repos/change/linguist/contributors","subscribers_url":"https://api.github.com/repos/change/linguist/subscribers","subscription_url":"https://api.github.com/repos/change/linguist/subscription","commits_url":"https://api.github.com/repos/change/linguist/commits{/sha}","git_commits_url":"https://api.github.com/repos/change/linguist/git/commits{/sha}","comments_url":"https://api.github.com/repos/change/linguist/comments{/number}","issue_comment_url":"https://api.github.com/repos/change/linguist/issues/comments{/number}","contents_url":"https://api.github.com/repos/change/linguist/contents/{+path}","compare_url":"https://api.github.com/repos/change/linguist/compare/{base}...{head}","merges_url":"https://api.github.com/repos/change/linguist/merges","archive_url":"https://api.github.com/repos/change/linguist/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/change/linguist/downloads","issues_url":"https://api.github.com/repos/change/linguist/issues{/number}","pulls_url":"https://api.github.com/repos/change/linguist/pulls{/number}","milestones_url":"https://api.github.com/repos/change/linguist/milestones{/number}","notifications_url":"https://api.github.com/repos/change/linguist/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/change/linguist/labels{/name}","releases_url":"https://api.github.com/repos/change/linguist/releases{/id}","deployments_url":"https://api.github.com/repos/change/linguist/deployments","created_at":"2018-04-13T21:26:58Z","updated_at":"2018-04-17T21:30:51Z","pushed_at":"2018-04-23T21:16:18Z","git_url":"git://github.com/change/linguist.git","ssh_url":"git@github.com:change/linguist.git","clone_url":"https://github.com/change/linguist.git","svn_url":"https://github.com/change/linguist","homepage":"","size":54,"stargazers_count":0,"watchers_count":0,"language":"Elixir","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":1,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit"},"forks":0,"open_issues":1,"watchers":0,"default_branch":"master"}},"base":{"label":"change:master","ref":"master","sha":"e642a5197c14b456fb231c377881dae50947cbaf","user":{"login":"change","id":121582,"avatar_url":"https://avatars3.githubusercontent.com/u/121582?v=4","gravatar_id":"","url":"https://api.github.com/users/change","html_url":"https://github.com/change","followers_url":"https://api.github.com/users/change/followers","following_url":"https://api.github.com/users/change/following{/other_user}","gists_url":"https://api.github.com/users/change/gists{/gist_id}","starred_url":"https://api.github.com/users/change/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/change/subscriptions","organizations_url":"https://api.github.com/users/change/orgs","repos_url":"https://api.github.com/users/change/repos","events_url":"https://api.github.com/users/change/events{/privacy}","received_events_url":"https://api.github.com/users/change/received_events","type":"Organization","site_admin":false},"repo":{"id":129455085,"name":"linguist","full_name":"change/linguist","owner":{"login":"change","id":121582,"avatar_url":"https://avatars3.githubusercontent.com/u/121582?v=4","gravatar_id":"","url":"https://api.github.com/users/change","html_url":"https://github.com/change","followers_url":"https://api.github.com/users/change/followers","following_url":"https://api.github.com/users/change/following{/other_user}","gists_url":"https://api.github.com/users/change/gists{/gist_id}","starred_url":"https://api.github.com/users/change/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/change/subscriptions","organizations_url":"https://api.github.com/users/change/orgs","repos_url":"https://api.github.com/users/change/repos","events_url":"https://api.github.com/users/change/events{/privacy}","received_events_url":"https://api.github.com/users/change/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/change/linguist","description":"Elixir Internationalization library","fork":true,"url":"https://api.github.com/repos/change/linguist","forks_url":"https://api.github.com/repos/change/linguist/forks","keys_url":"https://api.github.com/repos/change/linguist/keys{/key_id}","collaborators_url":"https://api.github.com/repos/change/linguist/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/change/linguist/teams","hooks_url":"https://api.github.com/repos/change/linguist/hooks","issue_events_url":"https://api.github.com/repos/change/linguist/issues/events{/number}","events_url":"https://api.github.com/repos/change/linguist/events","assignees_url":"https://api.github.com/repos/change/linguist/assignees{/user}","branches_url":"https://api.github.com/repos/change/linguist/branches{/branch}","tags_url":"https://api.github.com/repos/change/linguist/tags","blobs_url":"https://api.github.com/repos/change/linguist/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/change/linguist/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/change/linguist/git/refs{/sha}","trees_url":"https://api.github.com/repos/change/linguist/git/trees{/sha}","statuses_url":"https://api.github.com/repos/change/linguist/statuses/{sha}","languages_url":"https://api.github.com/repos/change/linguist/languages","stargazers_url":"https://api.github.com/repos/change/linguist/stargazers","contributors_url":"https://api.github.com/repos/change/linguist/contributors","subscribers_url":"https://api.github.com/repos/change/linguist/subscribers","subscription_url":"https://api.github.com/repos/change/linguist/subscription","commits_url":"https://api.github.com/repos/change/linguist/commits{/sha}","git_commits_url":"https://api.github.com/repos/change/linguist/git/commits{/sha}","comments_url":"https://api.github.com/repos/change/linguist/comments{/number}","issue_comment_url":"https://api.github.com/repos/change/linguist/issues/comments{/number}","contents_url":"https://api.github.com/repos/change/linguist/contents/{+path}","compare_url":"https://api.github.com/repos/change/linguist/compare/{base}...{head}","merges_url":"https://api.github.com/repos/change/linguist/merges","archive_url":"https://api.github.com/repos/change/linguist/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/change/linguist/downloads","issues_url":"https://api.github.com/repos/change/linguist/issues{/number}","pulls_url":"https://api.github.com/repos/change/linguist/pulls{/number}","milestones_url":"https://api.github.com/repos/change/linguist/milestones{/number}","notifications_url":"https://api.github.com/repos/change/linguist/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/change/linguist/labels{/name}","releases_url":"https://api.github.com/repos/change/linguist/releases{/id}","deployments_url":"https://api.github.com/repos/change/linguist/deployments","created_at":"2018-04-13T21:26:58Z","updated_at":"2018-04-17T21:30:51Z","pushed_at":"2018-04-23T21:16:18Z","git_url":"git://github.com/change/linguist.git","ssh_url":"git@github.com:change/linguist.git","clone_url":"https://github.com/change/linguist.git","svn_url":"https://github.com/change/linguist","homepage":"","size":54,"stargazers_count":0,"watchers_count":0,"language":"Elixir","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":1,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit"},"forks":0,"open_issues":1,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/change/linguist/pulls/4"},"html":{"href":"https://github.com/change/linguist/pull/4"},"issue":{"href":"https://api.github.com/repos/change/linguist/issues/4"},"comments":{"href":"https://api.github.com/repos/change/linguist/issues/4/comments"},"review_comments":{"href":"https://api.github.com/repos/change/linguist/pulls/4/comments"},"review_comment":{"href":"https://api.github.com/repos/change/linguist/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/change/linguist/pulls/4/commits"},"statuses":{"href":"https://api.github.com/repos/change/linguist/statuses/890d93b1158ddcedb6c2e98adadd8470afc7b774"}},"author_association":"NONE"}}
{"actor":{"display_login":"willbarrett"}}