{"action":"created","comment":{"url":"https://api.github.com/repos/cubing/worldcubeassociation.org/pulls/comments/76529158","id":76529158,"diff_hunk":"@@ -0,0 +1,82 @@\n+require 'i18n/tasks/scanners/file_scanner'\n+class WCAFileScanner < I18n::Tasks::Scanners::FileScanner\n+  include I18n::Tasks::Scanners::RelativeKeys\n+  include I18n::Tasks::Scanners::Results\n+\n+  def active_record?(model)\n+    # FIXME: Find a way to determine this dynamically ?\n+    model != \"contact\"\n+  end\n+\n+  def extract_model_attr(key)\n+    model_key = key.gsub(/^(\\w+)\\..*$/, '\\1').singularize\n+    # Some dirty tricks to assign the detected field to the \"correct\" model\n+    # For most controllers the forms modify a model which has the same name\n+    # as the controller, however for some of them they modified a single different\n+    # model (eg: the `admin` forms modify `person`s, and only that model).\n+    model_name = case model_key\n+                 when \"devise\" then \"user\"\n+                 when \"admin\" then \"person\"\n+                 when \"oauth\" then \"doorkeeper/application\"\n+                 else model_key\n+                 end\n+    attribute = key.gsub(/.*\\.(\\w+)$/, '\\1')\n+    [model_name, attribute]\n+  end\n+\n+  def occurrence_from_line(path, line, line_number, position)\n+    Occurrence.new(\n+      path:     path,\n+      pos:      line_number + position,\n+      line_num: line_number,\n+      line_pos: position,\n+      line:     line,\n+      raw_key: nil)\n+  end\n+\n+  # @return [Array<[absolute key, Results::Occurrence]>]\n+  def scan_file(path)\n+    text = read_file(path)\n+    retval = []\n+    line_number = 0\n+    text.each_line do |line|\n+      line_number += 1\n+      # Scan for possible radio choices\n+      if line =~ /^\\s*<%= f.input :(\\w+), as: :radio_buttons, collection: \\[(.*)\\](.*)%>/\n+        match = Regexp.last_match\n+        abskey = absolute_key(\".#{match[1]}\", path)\n+        occurrence = occurrence_from_line(path, line, line_number, match.offset(0).first)\n+        model, attribute = extract_model_attr(abskey)\n+        # Get all choices from the f.input\n+        options = match[2].gsub(/[: ]/, '').split(',')\n+        options.each do |o|\n+          # Mark every choice as used\n+          retval << [\"simple_form.options.#{model}.#{attribute}.#{o}\", occurrence]\n+        end\n+      end\n+      # We don't use an else here as we want to match radios here too!\n+      # Scan for inputs (or labels for inputs) that are not hidden\n+      next unless line =~ /^\\s*<%= f.(input|label|input_field) :(\\w+)(?!.*hidden)(.*)%>/","path":"WcaOnRails/lib/custom_i18n_scanner.rb","position":null,"original_position":59,"commit_id":"39895a4074e16a05b3fb8f7d3993e0b92d9c2568","original_commit_id":"2c33ea0d46cae1e01fc3a07bda9e4ed33f4bd78e","user":{"login":"viroulep","id":1007485,"avatar_url":"https://avatars.githubusercontent.com/u/1007485?v=3","gravatar_id":"","url":"https://api.github.com/users/viroulep","html_url":"https://github.com/viroulep","followers_url":"https://api.github.com/users/viroulep/followers","following_url":"https://api.github.com/users/viroulep/following{/other_user}","gists_url":"https://api.github.com/users/viroulep/gists{/gist_id}","starred_url":"https://api.github.com/users/viroulep/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/viroulep/subscriptions","organizations_url":"https://api.github.com/users/viroulep/orgs","repos_url":"https://api.github.com/users/viroulep/repos","events_url":"https://api.github.com/users/viroulep/events{/privacy}","received_events_url":"https://api.github.com/users/viroulep/received_events","type":"User","site_admin":false},"body":"Thanks :)","created_at":"2016-08-28T09:51:15Z","updated_at":"2016-08-28T09:51:15Z","html_url":"https://github.com/cubing/worldcubeassociation.org/pull/781#discussion_r76529158","pull_request_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/pulls/781","_links":{"self":{"href":"https://api.github.com/repos/cubing/worldcubeassociation.org/pulls/comments/76529158"},"html":{"href":"https://github.com/cubing/worldcubeassociation.org/pull/781#discussion_r76529158"},"pull_request":{"href":"https://api.github.com/repos/cubing/worldcubeassociation.org/pulls/781"}}},"pull_request":{"url":"https://api.github.com/repos/cubing/worldcubeassociation.org/pulls/781","id":79054112,"html_url":"https://github.com/cubing/worldcubeassociation.org/pull/781","diff_url":"https://github.com/cubing/worldcubeassociation.org/pull/781.diff","patch_url":"https://github.com/cubing/worldcubeassociation.org/pull/781.patch","issue_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/issues/781","number":781,"state":"open","locked":false,"title":"Activate i18n-tasks.","user":{"login":"viroulep","id":1007485,"avatar_url":"https://avatars.githubusercontent.com/u/1007485?v=3","gravatar_id":"","url":"https://api.github.com/users/viroulep","html_url":"https://github.com/viroulep","followers_url":"https://api.github.com/users/viroulep/followers","following_url":"https://api.github.com/users/viroulep/following{/other_user}","gists_url":"https://api.github.com/users/viroulep/gists{/gist_id}","starred_url":"https://api.github.com/users/viroulep/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/viroulep/subscriptions","organizations_url":"https://api.github.com/users/viroulep/orgs","repos_url":"https://api.github.com/users/viroulep/repos","events_url":"https://api.github.com/users/viroulep/events{/privacy}","received_events_url":"https://api.github.com/users/viroulep/received_events","type":"User","site_admin":false},"body":"Fixes #585, #587, #588.\r\n\r\nSome more i18n work :)\r\n\r\nIt's quite a big diff but this is mostly because I had to rework some keys, and add missing keys.\r\n\r\nHere is a summary of the changes:\r\n- I added i18n-tasks to the gems\r\n- I added specs for i18n: I considered that any unused key is an error (should be removed), and that any missing *english* key is an error (should be added).\r\n- I added missing keys, removed unused keys, and reworked/added exceptions for cases where i18n was tricked (I tried to keep the changes to a minimum).\r\n\r\nAbout the gem configuration:\r\nI made i18n-tasks ignores external keys, typically those which are defined in file that would be copy/paste in the repo, such as `devise.views.fr.yml` etc... Which means I had to scope some of the \"extended\" keys we used in these gems views (see [here](https://github.com/viroulep/worldcubeassociation.org/blob/d55b80f6c7e47ce6283000f25128b7df9b97d28b/WcaOnRails/app/views/doorkeeper/authorizations/new.html.erb#L22) or [here](https://github.com/viroulep/worldcubeassociation.org/blob/d55b80f6c7e47ce6283000f25128b7df9b97d28b/WcaOnRails/app/views/devise/registrations/new.html.erb#L18)).\r\n\r\nIn order to detect properly key used by our forms I had to write a custom scanner. Please carefully review this [file](https://github.com/viroulep/worldcubeassociation.org/blob/d55b80f6c7e47ce6283000f25128b7df9b97d28b/WcaOnRails/lib/custom_i18n_scanner.rb) as it does a lot regarding keys detection.\r\nIt should detect every input created, check if a custom hint or label is provided, check if the model is an activerecord, and tag the appropriate keys as used!\r\nI kind of built it incrementally as I was running into false-positives or missing attribute usage.\r\n\r\nOne final note: I couldn't find an easy way to detect whether we want a hint or not for a field, so by default it will tag every field as using a hint, and therefore [this commit](https://github.com/cubing/worldcubeassociation.org/commit/d55b80f6c7e47ce6283000f25128b7df9b97d28b) introduces a lot of empty hints.\r\nI must admit I not quite sure about this, but at least we precisely know what keys our forms are using...\r\n\r\nPlease let me know what you think :)\r\n","created_at":"2016-07-27T16:18:53Z","updated_at":"2016-08-28T09:51:15Z","closed_at":null,"merged_at":null,"merge_commit_sha":"7d48c2b27714f0dd1be434039479c499c3b54f3c","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/pulls/781/commits","review_comments_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/pulls/781/comments","review_comment_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/pulls/comments{/number}","comments_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/issues/781/comments","statuses_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/statuses/39895a4074e16a05b3fb8f7d3993e0b92d9c2568","head":{"label":"viroulep:i18n","ref":"i18n","sha":"39895a4074e16a05b3fb8f7d3993e0b92d9c2568","user":{"login":"viroulep","id":1007485,"avatar_url":"https://avatars.githubusercontent.com/u/1007485?v=3","gravatar_id":"","url":"https://api.github.com/users/viroulep","html_url":"https://github.com/viroulep","followers_url":"https://api.github.com/users/viroulep/followers","following_url":"https://api.github.com/users/viroulep/following{/other_user}","gists_url":"https://api.github.com/users/viroulep/gists{/gist_id}","starred_url":"https://api.github.com/users/viroulep/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/viroulep/subscriptions","organizations_url":"https://api.github.com/users/viroulep/orgs","repos_url":"https://api.github.com/users/viroulep/repos","events_url":"https://api.github.com/users/viroulep/events{/privacy}","received_events_url":"https://api.github.com/users/viroulep/received_events","type":"User","site_admin":false},"repo":{"id":49994335,"name":"worldcubeassociation.org","full_name":"viroulep/worldcubeassociation.org","owner":{"login":"viroulep","id":1007485,"avatar_url":"https://avatars.githubusercontent.com/u/1007485?v=3","gravatar_id":"","url":"https://api.github.com/users/viroulep","html_url":"https://github.com/viroulep","followers_url":"https://api.github.com/users/viroulep/followers","following_url":"https://api.github.com/users/viroulep/following{/other_user}","gists_url":"https://api.github.com/users/viroulep/gists{/gist_id}","starred_url":"https://api.github.com/users/viroulep/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/viroulep/subscriptions","organizations_url":"https://api.github.com/users/viroulep/orgs","repos_url":"https://api.github.com/users/viroulep/repos","events_url":"https://api.github.com/users/viroulep/events{/privacy}","received_events_url":"https://api.github.com/users/viroulep/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/viroulep/worldcubeassociation.org","description":"[WCA Project] All of the code that runs on worldcubeassociation.org","fork":true,"url":"https://api.github.com/repos/viroulep/worldcubeassociation.org","forks_url":"https://api.github.com/repos/viroulep/worldcubeassociation.org/forks","keys_url":"https://api.github.com/repos/viroulep/worldcubeassociation.org/keys{/key_id}","collaborators_url":"https://api.github.com/repos/viroulep/worldcubeassociation.org/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/viroulep/worldcubeassociation.org/teams","hooks_url":"https://api.github.com/repos/viroulep/worldcubeassociation.org/hooks","issue_events_url":"https://api.github.com/repos/viroulep/worldcubeassociation.org/issues/events{/number}","events_url":"https://api.github.com/repos/viroulep/worldcubeassociation.org/events","assignees_url":"https://api.github.com/repos/viroulep/worldcubeassociation.org/assignees{/user}","branches_url":"https://api.github.com/repos/viroulep/worldcubeassociation.org/branches{/branch}","tags_url":"https://api.github.com/repos/viroulep/worldcubeassociation.org/tags","blobs_url":"https://api.github.com/repos/viroulep/worldcubeassociation.org/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/viroulep/worldcubeassociation.org/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/viroulep/worldcubeassociation.org/git/refs{/sha}","trees_url":"https://api.github.com/repos/viroulep/worldcubeassociation.org/git/trees{/sha}","statuses_url":"https://api.github.com/repos/viroulep/worldcubeassociation.org/statuses/{sha}","languages_url":"https://api.github.com/repos/viroulep/worldcubeassociation.org/languages","stargazers_url":"https://api.github.com/repos/viroulep/worldcubeassociation.org/stargazers","contributors_url":"https://api.github.com/repos/viroulep/worldcubeassociation.org/contributors","subscribers_url":"https://api.github.com/repos/viroulep/worldcubeassociation.org/subscribers","subscription_url":"https://api.github.com/repos/viroulep/worldcubeassociation.org/subscription","commits_url":"https://api.github.com/repos/viroulep/worldcubeassociation.org/commits{/sha}","git_commits_url":"https://api.github.com/repos/viroulep/worldcubeassociation.org/git/commits{/sha}","comments_url":"https://api.github.com/repos/viroulep/worldcubeassociation.org/comments{/number}","issue_comment_url":"https://api.github.com/repos/viroulep/worldcubeassociation.org/issues/comments{/number}","contents_url":"https://api.github.com/repos/viroulep/worldcubeassociation.org/contents/{+path}","compare_url":"https://api.github.com/repos/viroulep/worldcubeassociation.org/compare/{base}...{head}","merges_url":"https://api.github.com/repos/viroulep/worldcubeassociation.org/merges","archive_url":"https://api.github.com/repos/viroulep/worldcubeassociation.org/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/viroulep/worldcubeassociation.org/downloads","issues_url":"https://api.github.com/repos/viroulep/worldcubeassociation.org/issues{/number}","pulls_url":"https://api.github.com/repos/viroulep/worldcubeassociation.org/pulls{/number}","milestones_url":"https://api.github.com/repos/viroulep/worldcubeassociation.org/milestones{/number}","notifications_url":"https://api.github.com/repos/viroulep/worldcubeassociation.org/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/viroulep/worldcubeassociation.org/labels{/name}","releases_url":"https://api.github.com/repos/viroulep/worldcubeassociation.org/releases{/id}","deployments_url":"https://api.github.com/repos/viroulep/worldcubeassociation.org/deployments","created_at":"2016-01-20T01:01:37Z","updated_at":"2016-01-20T01:01:44Z","pushed_at":"2016-08-28T09:44:25Z","git_url":"git://github.com/viroulep/worldcubeassociation.org.git","ssh_url":"git@github.com:viroulep/worldcubeassociation.org.git","clone_url":"https://github.com/viroulep/worldcubeassociation.org.git","svn_url":"https://github.com/viroulep/worldcubeassociation.org","homepage":"https://www.worldcubeassociation.org/","size":55719,"stargazers_count":0,"watchers_count":0,"language":"PHP","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"cubing:master","ref":"master","sha":"9abb59e1b3da9a4cfadc06d104eb0e43ead19647","user":{"login":"cubing","id":1092267,"avatar_url":"https://avatars.githubusercontent.com/u/1092267?v=3","gravatar_id":"","url":"https://api.github.com/users/cubing","html_url":"https://github.com/cubing","followers_url":"https://api.github.com/users/cubing/followers","following_url":"https://api.github.com/users/cubing/following{/other_user}","gists_url":"https://api.github.com/users/cubing/gists{/gist_id}","starred_url":"https://api.github.com/users/cubing/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cubing/subscriptions","organizations_url":"https://api.github.com/users/cubing/orgs","repos_url":"https://api.github.com/users/cubing/repos","events_url":"https://api.github.com/users/cubing/events{/privacy}","received_events_url":"https://api.github.com/users/cubing/received_events","type":"Organization","site_admin":false},"repo":{"id":34161579,"name":"worldcubeassociation.org","full_name":"cubing/worldcubeassociation.org","owner":{"login":"cubing","id":1092267,"avatar_url":"https://avatars.githubusercontent.com/u/1092267?v=3","gravatar_id":"","url":"https://api.github.com/users/cubing","html_url":"https://github.com/cubing","followers_url":"https://api.github.com/users/cubing/followers","following_url":"https://api.github.com/users/cubing/following{/other_user}","gists_url":"https://api.github.com/users/cubing/gists{/gist_id}","starred_url":"https://api.github.com/users/cubing/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cubing/subscriptions","organizations_url":"https://api.github.com/users/cubing/orgs","repos_url":"https://api.github.com/users/cubing/repos","events_url":"https://api.github.com/users/cubing/events{/privacy}","received_events_url":"https://api.github.com/users/cubing/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/cubing/worldcubeassociation.org","description":"[WCA Project] All of the code that runs on worldcubeassociation.org","fork":false,"url":"https://api.github.com/repos/cubing/worldcubeassociation.org","forks_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/forks","keys_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/keys{/key_id}","collaborators_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/teams","hooks_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/hooks","issue_events_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/issues/events{/number}","events_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/events","assignees_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/assignees{/user}","branches_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/branches{/branch}","tags_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/tags","blobs_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/git/refs{/sha}","trees_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/git/trees{/sha}","statuses_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/statuses/{sha}","languages_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/languages","stargazers_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/stargazers","contributors_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/contributors","subscribers_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/subscribers","subscription_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/subscription","commits_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/commits{/sha}","git_commits_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/git/commits{/sha}","comments_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/comments{/number}","issue_comment_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/issues/comments{/number}","contents_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/contents/{+path}","compare_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/compare/{base}...{head}","merges_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/merges","archive_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/downloads","issues_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/issues{/number}","pulls_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/pulls{/number}","milestones_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/milestones{/number}","notifications_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/labels{/name}","releases_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/releases{/id}","deployments_url":"https://api.github.com/repos/cubing/worldcubeassociation.org/deployments","created_at":"2015-04-18T10:21:53Z","updated_at":"2016-07-31T18:31:59Z","pushed_at":"2016-08-28T09:44:26Z","git_url":"git://github.com/cubing/worldcubeassociation.org.git","ssh_url":"git@github.com:cubing/worldcubeassociation.org.git","clone_url":"https://github.com/cubing/worldcubeassociation.org.git","svn_url":"https://github.com/cubing/worldcubeassociation.org","homepage":"https://www.worldcubeassociation.org/","size":56077,"stargazers_count":22,"watchers_count":22,"language":"PHP","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":29,"mirror_url":null,"open_issues_count":177,"forks":29,"open_issues":177,"watchers":22,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/cubing/worldcubeassociation.org/pulls/781"},"html":{"href":"https://github.com/cubing/worldcubeassociation.org/pull/781"},"issue":{"href":"https://api.github.com/repos/cubing/worldcubeassociation.org/issues/781"},"comments":{"href":"https://api.github.com/repos/cubing/worldcubeassociation.org/issues/781/comments"},"review_comments":{"href":"https://api.github.com/repos/cubing/worldcubeassociation.org/pulls/781/comments"},"review_comment":{"href":"https://api.github.com/repos/cubing/worldcubeassociation.org/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/cubing/worldcubeassociation.org/pulls/781/commits"},"statuses":{"href":"https://api.github.com/repos/cubing/worldcubeassociation.org/statuses/39895a4074e16a05b3fb8f7d3993e0b92d9c2568"}}}}
{"actor":{"display_login":"viroulep"}}